From 9ca26fc9eec4a57601032e538fd51d2b143c6896 Mon Sep 17 00:00:00 2001 From: Dyrell Chapman Date: Tue, 2 Oct 2018 13:10:00 -0600 Subject: [PATCH] Include Additional API Tests (#45) * Update gitignore, fix key order for gtta * added getInclusionStates test * Added getBalances test * Added wereAddressesSpentFrom test * Replaced add/remove neighbor test * Improve dynamic api call step * Remove unused test steps * Restructure api call args and features * Refactor inclusion state test * Moved argument preparation to util functions * Added attach/store/find transaction api test * Refactored with new type for api args * Added checkConsistency test * Added interruptAttachToTangle test * Changed static values, removed unnecessary logging * Changed static value for inclusion test * Change host and port pull for neighboring * Remove machine2 duplicate api tests * Fix indentation in machine1 feature * Changed api utility input name * Replaced non behavioural steps for interrupt test * Added comparison utility for api test calls * Added expected response for inclusion test * Added expected balance for getBalance test * Added docstring for check neighbors method * Add bool argument type for test arg lists * Replaced step syntax for threading with parallel * Add description for inconsistent transaction --- .gitignore | 3 + .../features/machine1/1_api_tests.feature | 259 ++++++++++++---- .../features/machine2/2_api_tests.feature | 64 ---- .../tests/features/machine2/__init__.py | 0 .../tests/features/machine2/config.yml | 14 - .../tests/features/steps/api_test_steps.py | 282 ++++++++++++------ PythonRegression/util/static_vals.py | 76 +++-- .../util/test_logic/api_test_logic.py | 62 +++- 8 files changed, 513 insertions(+), 247 deletions(-) delete mode 100644 PythonRegression/tests/features/machine2/2_api_tests.feature delete mode 100644 PythonRegression/tests/features/machine2/__init__.py delete mode 100644 PythonRegression/tests/features/machine2/config.yml diff --git a/.gitignore b/.gitignore index 33995c200e..f803515de1 100644 --- a/.gitignore +++ b/.gitignore @@ -105,3 +105,6 @@ venv.bak/ # pyc files *.pyc + +#Metafiles +.metadata/ diff --git a/PythonRegression/tests/features/machine1/1_api_tests.feature b/PythonRegression/tests/features/machine1/1_api_tests.feature index 16d9ccfd81..2e2609ae34 100644 --- a/PythonRegression/tests/features/machine1/1_api_tests.feature +++ b/PythonRegression/tests/features/machine1/1_api_tests.feature @@ -1,93 +1,228 @@ Feature: Test API calls on Machine 1 Test various api calls to make sure they are responding - correctly - + correctly. + Scenario: GetNodeInfo is called - Given "getNodeInfo" is called on "nodeA" + + #All api calls will be formatted as following, any arguments should be + #listed below the call in table format + #Example: + # "" is called on "" with: + #|keys |values |type | + #| | | | + # + #See tests/features/steps/api_test_steps.py for further details + # + + Given "getNodeInfo" is called on "nodeA" with: + |keys |values |type | + Then a response with the following is returned: - |keys | - |appName | - |appVersion | - |duration | + |keys | + |appName | + |appVersion | + |duration | |jreAvailableProcessors | - |jreFreeMemory | - |jreMaxMemory | - |jreTotalMemory | - |jreVersion | - |latestMilestone | + |jreFreeMemory | + |jreMaxMemory | + |jreTotalMemory | + |jreVersion | + |latestMilestone | |latestMilestoneIndex | - |latestSolidSubtangleMilestone | - |latestSolidSubtangleMilestoneIndex | + |latestSolidSubtangleMilestone | + |latestSolidSubtangleMilestoneIndex | |milestoneStartIndex | - |neighbors | - |packetsQueueSize | - |time | - |tips | + |neighbors | + |packetsQueueSize | + |time | + |tips | |transactionsToRequest | - + Scenario: GetNeighbors is called - Given "getNeighbors" is called on "nodeA" + Given "getNeighbors" is called on "nodeA" with: + |keys |values |type | + Then a response with the following is returned: - |keys | - |address | + |keys | + |address | |numberOfAllTransactions | - |numberOfAllTransactionRequests | + |numberOfAllTransactionRequests | |numberOfNewTransactions | - |numberOfInvalidTransactions | + |numberOfInvalidTransactions | |numberOfSentTransactions | - |connectionType | - - + |connectionType | + + + Scenario: Add and Remove Neighbors + Adds nodeB as a neighbor to nodeA, and then removes it. + + Given "addNeighbors" is called on "nodeA" with: + |keys |values |type | + |uris |nodeB |nodeAddress | + + Then a response with the following is returned: + |keys | + |addedNeighbors | + |duration | + + + When "removeNeighbors" is called on "nodeA" with: + |keys |values |type | + |uris |nodeB |nodeAddress | + + + Then a response with the following is returned: + |keys | + |duration | + |removedNeighbors | + + Scenario: GetTips is called - Given "getTips" is called on "nodeA" + Given "getTips" is called on "nodeA" with: + |keys |values |type | + Then a response with the following is returned: - |keys | - |hashes | - |duration | + |keys | + |hashes | + |duration | - - Scenario Outline: GetTrytes is called + + + #Values can be found in util/static_vals.py + Scenario Outline: GetTrytes is called Given getTrytes is called with the hash Then the response should be equal to Examples: - |hash | trytes | - |TEST_HASH | TEST_TRYTES | - - + |hash |trytes | + |TEST_HASH |TEST_TRYTES | + + + Scenario: GetTransactionsToApprove is called - Given "getTransactionsToApprove" is called on "nodeA" + Given "getTransactionsToApprove" is called on "nodeA" with: + |keys |values |type | + |depth |3 |int | + Then a response with the following is returned: - |keys | - |trunkTransaction | - |branchTransaction | - |duration | - + |keys | + |branchTransaction | + |duration | + |trunkTransaction | + -### -# To be replaced with a new neighbor test linking nodes within a given topology together -### -# @neighbors -# Scenario: Add and remove Neighbors -# Given 2 neighbors are added with "addNeighbors" on "nodeA" -# When "getNeighbors" is called, it should return the following neighbors: -# |neighbors | -# |178.128.236.6:14600 | -# |167.99.178.3:14600 | -# Then "removeNeighbors" will be called to remove the same neighbors -# And "getNeighbors" should not return the following neighbors: -# |neighbors | -# |178.128.236.6:14600 | -# |167.99.178.3:14600 | + Scenario: CheckConsistency is called + Given "checkConsistency" is called on "nodeA" with: + |keys |values |type | + |tails |TEST_HASH |staticList | + + Then the response for "checkConsistency" should return with: + |keys |values |type | + |state |True |bool | + + When an inconsistent transaction is generated on "nodeA" + + And "checkConsistency" is called on "nodeA" with: + |keys |values |type | + |tails |inconsistentTransactions |responseList | + + Then the response for "checkConsistency" should return with: + |keys |values |type | + |state |False |bool | + + + + #Values can be found in util/static_vals.py + Scenario: GetInclusionStates is called + Given "getInclusionStates" is called on "nodeA" with: + |keys |values |type | + |transactions |TEST_HASH |staticList | + |tips |TEST_TIP_LIST |staticValue | + + Then the response for "getInclusionStates" should return with: + |keys |values |type | + |states |False |bool | + #Address can be found in util/static_vals.py + Scenario: GetBalances is called + Given "getBalances" is called on "nodeA" with: + |keys |values |type | + |addresses |TEST_EMPTY_ADDRESS |staticList | + |threshold |100 |int | + + Then the response for "getBalances" should return with: + |keys |values |type | + |balances |0 |int | + + + Scenario: Interrupt attach to tangle + Begins attaching a transaction to the tangle with a high MWM, then issues an interrupt to the node + If the interrupt is successful, the attachToTangle response will return a null tryte list + + Given "attachToTangle" is called in parallel on "nodeA" with: + |keys |values |type | + |trytes |EMPTY_TRANSACTION_TRYTES|staticList | + |trunk_transaction |TEST_HASH |staticValue | + |branch_transaction |TEST_HASH |staticValue | + |min_weight_magnitude |50 |int | + + And "interruptAttachingToTangle" is called in parallel on "nodeA" with: + |keys |values |type | + + # Do not include duration in the return expectations as it will always return a variable amount + Then the "attachToTangle" parallel call should return with: + |keys |values |type | + |trytes |NULL_LIST |staticValue | + + + + Scenario: WereAddressesSpentFrom is called + Given "wereAddressesSpentFrom" is called on "nodeA" with: + |keys |values |type | + |addresses |TEST_EMPTY_ADDRESS |staticList | + + Then a response with the following is returned: + |keys | + |duration | + |states | + + + + Scenario: Create, attach, store and find a transaction + Generate a transaction, attach it to the tangle, and store it locally. Then find + that transaction via its address. + + Given a transaction is generated and attached on "nodeA" with: + |keys |values |type | + |address |TEST_STORE_ADDRESS |staticValue | + |value |0 |int | + + Then a response with the following is returned: + |keys | + |trytes | + + When "storeTransactions" is called on "nodeA" with: + |keys |values |type | + |trytes |TEST_STORE_TRANSACTION |staticValue | + + And "findTransactions" is called on "nodeA" with: + |keys |values |type | + |addresses |TEST_STORE_ADDRESS |staticList | + + Then a response with the following is returned: + |keys | + |hashes | + + + Scenario: Broadcast a test transacion - Send a test transaction from one node in a machine, and find that transaction + Send a test transaction from one node in a machine with a unique tag, and find that transaction through a different node in the same machine - Given "nodeA" and "nodeB" are neighbors - When a transaction with the tag "TEST9TRANSACTION" is sent from "nodeA" + Given "nodeA" and "nodeB" are neighbors + When a transaction with the tag "TEST9TAG9ONE" is sent from "nodeA" And findTransaction is called with the same tag on "nodeB" Then the transaction should be found - \ No newline at end of file + diff --git a/PythonRegression/tests/features/machine2/2_api_tests.feature b/PythonRegression/tests/features/machine2/2_api_tests.feature deleted file mode 100644 index a7b142a787..0000000000 --- a/PythonRegression/tests/features/machine2/2_api_tests.feature +++ /dev/null @@ -1,64 +0,0 @@ -Feature: Test API calls on Machine 2 - Test various api calls to make sure they are responding - correctly - - Scenario: GetNodeInfo is called - Given "getNodeInfo" is called on "nodeA" - Then a response with the following is returned: - |keys | - |appName | - |appVersion | - |duration | - |jreAvailableProcessors | - |jreFreeMemory | - |jreMaxMemory | - |jreTotalMemory | - |jreVersion | - |latestMilestone | - |latestMilestoneIndex | - |latestSolidSubtangleMilestone | - |latestSolidSubtangleMilestoneIndex | - |milestoneStartIndex | - |neighbors | - |packetsQueueSize | - |time | - |tips | - |transactionsToRequest | - - - Scenario: GetNeighbors is called - Given "getNeighbors" is called on "nodeA" - Then a response with the following is returned: - |keys | - |address | - |numberOfAllTransactions | - |numberOfAllTransactionRequests | - |numberOfNewTransactions | - |numberOfInvalidTransactions | - |numberOfSentTransactions | - |connectionType | - - - Scenario: GetTips is called - Given "getTips" is called on "nodeA" - Then a response with the following is returned: - |keys | - |hashes | - |duration | - - - Scenario Outline: GetTrytes is called - Given getTrytes is called with the hash - Then the response should be equal to - - Examples: - |hash | trytes | - |static_vals.TEST_HASH | static_vals.TEST_TRYTES | - - Scenario: GetTransactionsToApprove is called - Given "getTransactionsToApprove" is called on "nodeA" - Then a response with the following is returned: - |keys | - |trunkTransaction | - |branchTransaction | - |duration | diff --git a/PythonRegression/tests/features/machine2/__init__.py b/PythonRegression/tests/features/machine2/__init__.py deleted file mode 100644 index e69de29bb2..0000000000 diff --git a/PythonRegression/tests/features/machine2/config.yml b/PythonRegression/tests/features/machine2/config.yml deleted file mode 100644 index 056ff6dc99..0000000000 --- a/PythonRegression/tests/features/machine2/config.yml +++ /dev/null @@ -1,14 +0,0 @@ -defaults: &db_2 - db: https://s3.eu-central-1.amazonaws.com/iotaledger-dbfiles/dev/testnet_files.tgz - db_checksum: 6eaa06d5442416b7b8139e337a1598d2bae6a7f55c2d9d01f8c5dac69c004f75 - -seeds: # For internal use by the regression system. - - SEED - - SIID - -nodes: - nodeA: #name - <<: *db_2 - - nodeB: - <<: *db_2 diff --git a/PythonRegression/tests/features/steps/api_test_steps.py b/PythonRegression/tests/features/steps/api_test_steps.py index 0731e5a443..3dcc06919f 100644 --- a/PythonRegression/tests/features/steps/api_test_steps.py +++ b/PythonRegression/tests/features/steps/api_test_steps.py @@ -1,64 +1,119 @@ from aloe import * -from iota import Iota,ProposedTransaction,Address,Tag,TryteString,BundleHash +from iota import ProposedTransaction,Address,Tag,TryteString,ProposedBundle,Transaction from util import static_vals -from util.test_logic import api_test_logic as tests +from util.test_logic import api_test_logic as api_utils from time import sleep -import importlib +import threading import logging logging.basicConfig(level=logging.INFO) logger = logging.getLogger(__name__) -neighbors = static_vals.TEST_NEIGHBORS testAddress = static_vals.TEST_ADDRESS config = {} responses = {'getNodeInfo':{},'getNeighbors':{},'getTips':{},'getTransactionsToApprove': {},'getTrytes':{}} -### -#Register API call -@step(r'"([^"]*)" is called on "([^"]*)"') + +''' +This is the general api calling function. There are 3 inputs + +@param apiCAll: The api call that will be requested +@param nodeName: The name identifying the node you would like to make this request on +@param table: A gherkin table outlining any arguments needed for the call + (See tests/features/machine1/1_api+tests.feature for examples) + + The table parameter is unique in that there are several input types available depending on the call + being made. + Types: + string: Basic string argument, will be taken as is + int: Basic integer argument, will be converted to int before call is made + nodeAddress: Node name identifier, will create address from node configuration + staticValue: Static name identifier, will fetch value from util/static_vals.py + staticList: Same as staticValue, except it places the results into a list + responseValue: Identifier for api call response value + responseList: Same as responseValue, ecept it places the results into a list + bool: Bool argument, returns True or False + +''' +@step(r'"([^"]*)" is called on "([^"]*)" with:') def api_method_is_called(step,apiCall,nodeName): logger.info('%s is called on %s',apiCall,nodeName) config['apiCall'] = apiCall config['nodeId'] = nodeName + arg_list = step.hashes + + options = {} + api_utils.prepare_options(arg_list, options) responses[apiCall] = {} - - - api = tests.prepare_api_call(nodeName) - - logger.debug('Assigning call list...') - - callList = { - 'getNodeInfo': api.get_node_info, - 'getNeighbors': api.get_neighbors, - 'getTips': api.get_tips, - 'getTransactionsToApprove': api.get_transactions_to_approve - } - - if apiCall == 'getNodeInfo': - response = api.get_node_info() - logger.debug('Node Info Response: %s',response) - elif apiCall == 'getNeighbors': - response = api.get_neighbors() - logger.debug('Neighbor Response: %s',response) - elif apiCall == 'getTips': - response = api.get_tips() - logger.debug('Get Tips Response Error') - elif apiCall == 'getTransactionsToApprove': - response = api.get_transactions_to_approve(3) - logger.debug('Get Transactions To Approve Error') - else: - response = "Incorrect API call definition" - - - assert type(response) is dict, response + + api = api_utils.prepare_api_call(nodeName) + response = api_utils.fetch_call(apiCall, api, options) + + assert type(response) is dict, 'There may be something wrong with the response format: {}'.format(response) responses[apiCall] = {} responses[apiCall][nodeName] = response +#This method is identical to the method above, but creates a new thread +#TODO: Find a way to pass aloe.world variable between threads to eliminate need for duplicate code +@step(r'"([^"]*)" is called in parallel on "([^"]*)" with:') +def threaded_call(step,apiCall,node): + logger.info("Creating thread for {}".format(apiCall)) + config['apiCall'] = apiCall + config['nodeId'] = node + arg_list = step.hashes + + options = {} + api_utils.prepare_options(arg_list, options) + api = api_utils.prepare_api_call(node) + + def make_call(api,options): + response = api_utils.fetch_call(apiCall, api, options) + responses[apiCall] = {} + responses[apiCall][node] = response + return response + + new_thread = threading.Thread(target=make_call, args=(api,options)) + new_thread.setDaemon(True) + new_thread.start() + + if 'threads' not in config: + config['threads'] = {} + config['threads'][apiCall] = new_thread + #Wait 3 seconds to give node time to respond + sleep(3) + + +@step(r'the "([^"]*)" parallel call should return with:') +def compare_thread_return(step,apiCall): + #Prepare response list for comparison + response_list = responses[apiCall][config['nodeId']] + #Exclude duration from response list + if 'duration' in response_list: + del response_list['duration'] + response_keys = response_list.keys() + + #Prepare expected values list for comparison + expected_values = {} + args = step.hashes + api_utils.prepare_options(args,expected_values) + keys = expected_values.keys() + + #Confirm that the lists are of equal length before comparing + assert len(keys) == len(response_keys), 'Response: {} does not contain the same number of arguments: {}'.format(keys,response_keys) + + for count in range(len(keys)): + response_key = response_keys[count] + response_value = response_list[response_key] + expected_value = expected_values[response_key] + + assert response_value == expected_value, \ + 'Returned: {} does not match the expected value: {}'.format(response_value,expected_value) + + logger.info('Responses match') @step(r'GTTA is called (\d+) times on "([^"]*)"') @@ -67,7 +122,7 @@ def spam_call_gtta(step,numTests,node): config['apiCall'] = apiCall config['nodeId'] = node - api = tests.prepare_api_call(node) + api = api_utils.prepare_api_call(node) logging.info('Calls being made to %s',node) responseVal = [] for i in range(int(numTests)): @@ -78,6 +133,61 @@ def spam_call_gtta(step,numTests,node): responses[apiCall] = {} responses[apiCall][node] = responseVal + +### +#Transaction Generator +#TODO: Merge Transaction Logic commit to modularise bundle generation +@step(r'a transaction is generated and attached on "([^"]*)" with:') +def generate_transaction_and_attach(step,node): + arg_list = step.hashes + config['nodeId'] = node + config['apiCall'] = 'attachToTangle' + options = {} + api = api_utils.prepare_api_call(node) + + api_utils.prepare_options(arg_list, options) + addresses = options.get('address') + value = options.get('value') + + transaction = ProposedTransaction(address=Address(addresses[0]), value = value) + + bundle = ProposedBundle() + bundle.add_transaction(transaction) + bundle.finalize() + trytes = str(bundle[0].as_tryte_string()) + + gtta = api.get_transactions_to_approve(depth=3) + branch = str(gtta['branchTransaction']) + trunk = str(gtta['trunkTransaction']) + + sent = api.attach_to_tangle(trunk,branch,[trytes],9) + logger.info('Transaction Sent') + + setattr(static_vals, "TEST_STORE_TRANSACTION", sent.get('trytes')) + + +@step(r'the response for "([^"]*)" should return with:') +def check_response_for_value(step,apiCall): + response_values = responses[apiCall][config['nodeId']] + + expected_values = {} + args = step.hashes + api_utils.prepare_options(args,expected_values) + + + for expected_value_key in expected_values: + if expected_value_key in response_values: + expected_value = expected_values[expected_value_key] + response_value = response_values[expected_value_key] + if type(response_value) is list: + response_value = response_value[0] + assert expected_value == response_value, \ + "The expected value {} does not match the response value: {}".format(expected_value,response_value) + + logger.info('Response contained expected values') + + + ### #Response testing @step(r'a response with the following is returned:') @@ -107,14 +217,41 @@ def compare_response(step): assert str(responseKeys[responseKeyVal]) == str(keys[responseKeyVal]) except: logger.debug("No values to verify response with") - + +''' +Creates an inconsistent transaction by generating a zero value transaction that references +a non-existent transaction as its branch and trunk, thus not connecting with any other part +of the tangle. +''' +#TODO: Merge Transaction Logic commit to modularise bundle generation +@step(r'an inconsistent transaction is generated on "([^"]*)"') +def create_inconsistent_transaction(step,node): + config['nodeId'] = node + api = api_utils.prepare_api_call(node) + branch = getattr(static_vals,"NULL_HASH") + trunk = branch + trytes = getattr(static_vals,"EMPTY_TRANSACTION_TRYTES") + + transaction = api.attach_to_tangle(trunk,branch,[trytes],14) + transaction_trytes = transaction.get('trytes') + api.store_transactions(transaction_trytes) + transaction_hash = Transaction.from_tryte_string(transaction_trytes[0]) + logger.info(transaction_hash.hash) + + if 'inconsistentTransactions' not in responses: + responses['inconsistentTransactions'] = {} + + responses['inconsistentTransactions'][node] = transaction_hash.hash + + + ### #Test GetTrytes @step(r'getTrytes is called with the hash ([^"]+)') def call_getTrytes(step,hash): - api = tests.prepare_api_call(config['nodeId']) + api = api_utils.prepare_api_call(config['nodeId']) testHash = getattr(static_vals, hash) - response = api.get_trytes(testHash) + response = api.get_trytes([testHash]) logger.debug("Call may not have responded correctly: \n%s",response) assert type(response) is dict responses['getTrytes'][config['nodeId']] = response @@ -128,53 +265,20 @@ def check_trytes(step,trytes): assert response['trytes'][0] == testTrytes, "Trytes do not match" - -### -#Test Add and Remove Neighbors -@step(r'2 neighbors are added with "([^"]*)" on "([^"]*)"') -def add_neighbors(step,apiCall,nodeName): - config['nodeId'] = nodeName - api = tests.prepare_api_call(nodeName) - response = api.add_neighbors(neighbors) - logger.debug('Response: %s',response) - - -@step(r'"getNeighbors" is called, it should return the following neighbors:') -def check_neighbors_post_addition(step): - logger.info('Ensuring Neighbors were added correctly') - containsNeighbor = check_neighbors(step) - assert containsNeighbor[1] is True - assert containsNeighbor[0] is True - - -@step(r'"removeNeighbors" will be called to remove the same neighbors') -def remove_neighbors(step): - api = tests.prepare_api_call(config['nodeId']) - response = api.remove_neighbors(neighbors) - logger.debug('Response: %s',response) - -@step(r'"getNeighbors" should not return the following neighbors:') -def check_neighbors_post_removal(step): - logger.info('Ensuring Neighbors were removed correctly') - containsNeighbor = check_neighbors(step) - assert containsNeighbor[1] is False - assert containsNeighbor[0] is False - - ### #Test transactions @step(r'"([^"]*)" and "([^"]*)" are neighbors') def make_neighbors(step,node1,node2): - host1 = world.machine['nodes'][node1]['host'] - port1 = world.machine['nodes'][node1]['ports']['gossip-udp'] - host2 = world.machine['nodes'][node2]['host'] - port2 = world.machine['nodes'][node2]['ports']['gossip-udp'] + host1 = world.machine['nodes'][node1]['podip'] + port1 = world.machine['nodes'][node1]['clusterip_ports']['gossip-udp'] + host2 = world.machine['nodes'][node2]['podip'] + port2 = world.machine['nodes'][node2]['clusterip_ports']['gossip-udp'] hosts = [host1,host2] ports = [port1,port2] - api1 = tests.prepare_api_call(node1) - api2 = tests.prepare_api_call(node2) + api1 = api_utils.prepare_api_call(node1) + api2 = api_utils.prepare_api_call(node2) response1 = api1.get_neighbors() response2 = api2.get_neighbors() @@ -225,7 +329,7 @@ def send_transaction(step,tag,nodeName): logger.debug('Preparing Transaction...') logger.debug('Node: %s',nodeName) config['tag'] = tag - api = tests.prepare_api_call(nodeName) + api = api_utils.prepare_api_call(nodeName) txn = \ ProposedTransaction( address = @@ -244,7 +348,7 @@ def send_transaction(step,tag,nodeName): @step(r'findTransaction is called with the same tag on "([^"]*)"') def find_transaction_is_called(step,nodeName): logger.debug(nodeName) - api = tests.prepare_api_call(nodeName) + api = api_utils.prepare_api_call(nodeName) logger.info("Searching for Transaction with the tag: {} on {}".format(config['tag'],nodeName)) response = api.find_transactions(tags=[config['tag']]) config['findTransactionResponse'] = response @@ -260,9 +364,9 @@ def check_transaction_response(step): @step(r'find transaction is called with the address:') def find_transactions_from_address(step): logger.info('Finding milestones') - node = config('nodeId') + node = config['nodeId'] - api = tests.prepare_api_call(node) + api = api_utils.prepare_api_call(node) transactions = api.find_transactions(addresses = [step.multiline]) responses['findTransactions'] = transactions @@ -286,9 +390,17 @@ def fetch_config(key): def fetch_response(apiCall): return responses[apiCall] +''' +This method is used to determine if a node contains the neighbors specified in the steps feature list + +@returns a list of two bools +If the return contains a False response, then the neighbor associated with that bool will be added in the remaining +methods in the step. +''' +#TODO: Move this function to a utility file along with all other functionality involving neighbors def check_neighbors(step): - api = prepare_api_call(config['nodeId']) + api = api_utils.prepare_api_call(config['nodeId']) response = api.getNeighbors() containsNeighbor = [False,False] diff --git a/PythonRegression/util/static_vals.py b/PythonRegression/util/static_vals.py index 081038a4ed..1270dc71ad 100644 --- a/PythonRegression/util/static_vals.py +++ b/PythonRegression/util/static_vals.py @@ -1,31 +1,65 @@ +NULL_LIST = [] + TEST_TRANSACTION_HASH = "BNKODGPOSCN9ENBCFYXPIJZMSACAFTZIAGSWOCZFG9BYECELVD9JLBDSFIDKNXOQIRPTGNWZDMSYZ9999" TEST_TRANSACTION_HASHES = ["BNKODGPOSCN9ENBCFYXPIJZMSACAFTZIAGSWOCZFG9BYECELVD9JLBDSFIDKNXOQIRPTGNWZDMSYZ9999","ZPZKTOXRHKRPGNJKOCMHBQWGSMTMSDTVSYHVNZN9MMMPAZHOJYHOESCXGIDLTMXPFWDFKRNHAILRZ9999"] - TEST_NEIGHBORS = [u'udp://178.128.236.6:14600',u'udp://167.99.178.3:14600'] -TEST_HASH = ["KEHXTIVIBJHIQOWXQ9BSDMIDXLNO9WJQUGOSKVTMFMAHNSAYDSFWGOYQWINLCAMBASPUATDNVCFT99999"] +TEST_HASH = "NMPXODIWSCTMWRTQ9AI9VROYNFACWCQDXDSJLNC9HKCECBCGQTBUBKVROXZLQWAZRQUGIJTLTMAMSH999" +NULL_HASH = "999999999999999999999999999999999999999999999999999999999999999999999999999999999" + +TEST_TIP_LIST = ["SBKWTQWCFTF9DBZHJKQJKU9LXMZD9BMWJIJLZCCZYJFWIBGYYQBJOWWFWIHDEDTIHUB9PMOWZVCPKV999"] TEST_ADDRESS = "TEST9TRANSACTION9TEST9TRANSACTION9TEST9TRANSACTION9TEST9TRANSACTION9TEST999999999" +TEST_EMPTY_ADDRESS = "EMPTY9BALANCE9TEST999999999999999999999999999999999999999999999999999999999999999" +TEST_STORE_ADDRESS = "STORE9AND9FIND9999999999999999999999999999999999999999999999999999999999999999999" +TEST_CONSISTENCY_ADDRESS = "THIS9TRANSACTION9IS9NOT9CONSISTENT99999999999999999999999999999999999999999999999" -TEST_TRYTES = "CCWCXCGDEAGDDDPCADEAKDPCGDEARCFDTCPCHDTCSCEAIDGDXCBDVCEAHDWCTCEAXCCDHDPCGDDDPCADSARCCDADEAGDDDPCADADTCFDEAXCBDEACDUCUC9DXCBDTCEAAD\ -CDSCTCQAEAHDWCTCFDTCUCCDFDTCEASBEAPCADEABDCDHDEAFDTCRCTCXCJDXCBDVCEAFDTCKDPCFDSCGDEAUCCDFDEAHDWCXCGDEAGDDDPCADSA999999999999999999999999999999999\ -9999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999\ -9999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999\ -9999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999\ -9999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999\ -9999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999\ -9999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999\ -9999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999\ -9999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999\ -9999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999\ -9999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999\ -9999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999\ -9999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999\ -9999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999\ -999999999999999999999999999IHOP9DM9ME9IF9I9SHOULD9STOP9SPAMMING99THE9TANGLE9ROCKS999999999999999999999999999999999999999999999999999999VMPP9DM9ME\ -9TO9STOP999999999ZLOMTZD99999999999999999999XKPFGCXPWHTOYUFJWKWLOVZLLSPRKFRWSWOIOYRQVWUZLJZGJDFELHBMPTTKVWFGYFJGWAIHSWGFCBLYXXRNUWXUDQPACLIUQ9ZUQ\ -9KULYUANXDYVFWLDMJVCFNWTRWEDPJSNTVCKZRBKQUCKTY9ADVCKXSZBA9999MPGLLWKQDCUNCTYNMKXSMCQNSLTSNRWIYBTUYYKEMLCSOFVNXUG9CG9IFASNZLFMJOOADXCSTYBK99999IHO\ -P9DM9ME9TO9STOP999999999PN9Q99LKE999999999MMMMMMMMMHEA999999999E99999999999999" +TEST_TRYTES = "99999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999\ +99999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999\ +99999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999\ +99999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999\ +99999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999\ +99999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999\ +99999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999\ +99999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999\ +99999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999\ +99999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999\ +99999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999\ +99999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999\ +99999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999\ +99999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999\ +99999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999\ +99999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999\ +99999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999\ +99999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999\ +999999999999999999999999999999999999999999999999999999999999BTCAAFIH9CJIVIMWFMIHKFNWRTLJRKSTMRCVRE9CIP9AEDTOULVFRHQZT9Q\ +AQBZXXAZGBNMVOOKTKAXTB999999999999999999999999999OOL999999999999999999999999PZOOHYD99999999999A99999999COGFFWFFHESWQEXJ\ +PRMXRAXDWZKJKNKEWTRZRZTFCCDXYSOBOLYEEKMHVIBEBTXHNEHLRFFTPZNPPKZTZDBNUFRSPIATLJAIPFAOPHQYUIL9HCCZCPCYMARJRLGCHRER9DPZQZK\ +WTFMS9VNCQNU9MREAWURCRFP999RY9WPBQNZJQVWPEA9PLGEYFKO9KDLHUIKBLHAWFMJQHVBADMAECNWOOMJSOSQDXCASDUITIOQTCAFR999OOL99999999\ +9999999999999999OCRAFGUKE999999999L99999999IPEHQKQXYFIYKCAATJXKXYLICFF" +EMPTY_TRANSACTION_TRYTES = "99999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999\ +99999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999\ +99999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999\ +99999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999\ +99999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999\ +99999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999\ +99999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999\ +99999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999\ +99999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999\ +99999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999\ +99999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999\ +99999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999\ +99999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999\ +99999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999\ +99999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999\ +99999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999\ +99999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999\ +99999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999\ +999999999999999999999999999999999999999999999999999999999999999999TEST9TRANSACTION9TEST9TRANSACTION9TEST9TRANSACTION9TE\ +ST9TRANSACTION9TEST999999999999999999999999999999999999LA9999999999999999999999999PENPEZD99999999999999999999ZKJDCAXDVI\ +LDLFAPDQZCKROIQRDKHZZIX9QQ9RQICWYLH9EUCFZUBKWAAREIXSIPLNQBGXAACBZAKCWLC999999999999999999999999999999999999999999999999\ +99999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999\ +9999999999999999999999999999999999999999999999999999999999999999999999999999" \ No newline at end of file diff --git a/PythonRegression/util/test_logic/api_test_logic.py b/PythonRegression/util/test_logic/api_test_logic.py index 7d1f0868e3..a21e8789c9 100644 --- a/PythonRegression/util/test_logic/api_test_logic.py +++ b/PythonRegression/util/test_logic/api_test_logic.py @@ -1,5 +1,6 @@ from aloe import world from iota import Iota +from util import static_vals import logging logging.basicConfig(level=logging.INFO) @@ -55,4 +56,63 @@ def check_neighbors(step,node): def import_steps(): import tests.features.steps.api_test_steps as steps return steps - + + +def prepare_options(args,optionList): + for x in range(len(args)): + if len(args) != 0: + key = args[x]['keys'] + value = args[x]['values'] + arg_type = args[x]['type'] + + if arg_type == "int": + value = int(value) + elif arg_type == "nodeAddress": + host = world.machine['nodes'][value]['host'] + port = world.machine['nodes'][value]['ports']['gossip-udp'] + address = "udp://" + host + ":" + str(port) + value = [address.decode()] + elif arg_type == "staticValue": + value = getattr(static_vals,value) + elif arg_type == "staticList": + address = getattr(static_vals,value) + value = [address] + elif arg_type == "bool": + if value == "False": + value = False + else: + value = True + elif arg_type == "responseValue": + config = fetch_config('nodeId') + response = fetch_response(value) + value = response[config] + elif arg_type == "responseList": + config = fetch_config('nodeId') + response = fetch_response(value) + value = [response[config]] + + optionList[key] = value + +def fetch_call(apiCall,api,options): + callList = { + 'getNodeInfo': api.get_node_info, + 'getNeighbors': api.get_neighbors, + 'getTips': api.get_tips, + 'getTransactionsToApprove': api.get_transactions_to_approve, + 'getBalances': api.get_balances, + 'addNeighbors': api.add_neighbors, + 'removeNeighbors': api.remove_neighbors, + 'wereAddressesSpentFrom': api.were_addresses_spent_from, + 'getInclusionStates': api.get_inclusion_states, + 'storeTransactions': api.store_transactions, + 'broadcastTransactions': api.broadcast_transactions, + 'findTransactions': api.find_transactions, + 'attachToTangle': api.attach_to_tangle, + 'checkConsistency': api.check_consistency, + 'interruptAttachingToTangle': api.interrupt_attaching_to_tangle, + } + + response = callList[apiCall](**options) + + return response +