def file_sync_setup(request): """ Setup and teardown for testing the file_sync demo. """ # Create two temporary directories. master_dir = tempfile.mkdtemp() slave_dir = tempfile.mkdtemp() # Collect constants from the file_sync test module. master_service = getattr(request.module, 'MASTER_SERVICE') slave_service = getattr(request.module, 'SLAVE_SERVICE') path_to_modules = getattr(request.module, 'PATH_TO_MIX_DIR') # Start the master and slave watchdogs. start_service_in(master_service, 'master', master_dir, alias=ALIAS, path=path_to_modules) start_service_in(slave_service, 'slave', slave_dir, alias=ALIAS, path=path_to_modules) yield master_dir, slave_dir # Stop the services and remove the temp dirs. sparkl('stop', master_service, alias=ALIAS) sparkl('stop', slave_service, alias=ALIAS) subprocess.check_call(['rm', '-rf', master_dir]) subprocess.check_call(['rm', '-rf', slave_dir])
def login_to_sparkl(self): """ Creates a connection to SPARKL. """ sparkl('connect', 'http://localhost:8000', alias=ALIAS) self.is_connected = True print('Connected to SPARKL.')
def logout_close(alias='default'): """ Logs out user and closes connection linked to specified alias (default is "default") """ sparkl('logout', alias=alias) print('Logging out of SPARKL...') sparkl('close', alias=alias) print('Connection associated with alias %s is closed' % (alias))
def lib_create(name, names, alias): """ Creates a folder in the user tree if it does not exist already. """ if not any(x['attr']['name'] == name for x in names): sparkl('mkdir', name, alias=alias) print('Creating %s folder...' % (name)) return print('Folder %s already exists.' % (name))
def logout_from_sparkl(self): """ Closes connection to SPARKL. """ # Gets only called if login was successful. if self.is_connected: sparkl('close', alias=ALIAS) self.is_connected = False print('Closed connection.')
def main(user, filters, alias='default'): """ Logs in the specified user, starts the event logging and hands down the events generator and the specified filters to the logging framework. Also specifies an on-event and on-exit function for this framework. The on-event function uses a queue to communicate with the main function. """ # Try to login success, result = login(user, alias) # Log out on failure (e.g. wrong username/password/not running instance) if not success: try: sparkl('close', alias=alias) print(result) except CliException as error: print(error) return # If login was successful, evens generator is returned by login events = result # Create a queue shared between the main process and the on-event function event_queue = queue_mod.Queue() # Cleanup function to call when exiting from logging. on_exit = (logout, (), {'alias': alias}) # Function to call on successful matching of event. The log framework # will insert 'event' as the first parameter on_event = (stop_services, (TARGET_FOR_STOP, events, event_queue), { 'alias': alias }) try: # Start logging using filters, on_event and on_exit functions log_frame(events, filters, on_exit=on_exit, on_event=on_event) except LogException as error: print(error.message) sparkl('close', alias=alias) raise # Go through queue after logging stopped read_queue(event_queue)
def stop_services(event, path, events, event_queue, alias='default'): """ Called on on_event of logger frame. Prints the specified event, stops all running SPARKL services in path and closes the event generator. NOTE: The 'event' argument is inserted by the log framework. The function is sent to the framework thus: - ( stop_services, ( path, events, event_queue ), { 'alias': alias } ) """ print('Received stop event.') event_queue.put(event) sparkl('stop', path, alias=alias) events.close()
def module_setup(request): """ Setup method used by tests. Called once per test modules. It collects the path to one or more SPARKL configurations specified in the test module (kept in the FILE_PATHS constant) and imports them into the test directory. This method collects the alias from the base_setup and hands down this alias to all the tests. The tests use the base_setup method only through setup_method. """ path_to_files = getattr(request.module, 'FILE_PATHS') for file_path in path_to_files: sparkl('put', file_path, IMPORT_DIR, alias=ALIAS) yield ALIAS sparkl('stop', IMPORT_DIR, alias=ALIAS)
def trigger_operation(fields, operation): """ Function runs a SPARKL operation. It also sets the fields needed to do so. """ # Generate random alias alias = uuid.uuid4().hex # Try to connect and log into SPARKL (login_tag, login_data) = connect_login(alias) # If either fails, return and print error if login_tag == 'error': print(login_data) return 'error', login_data # Set vars and call operation try: sparkl('vars', alias=alias, literal=fields) result_data = sparkl('call', operation, alias=alias) # Return from fun if operation not found or other SPARKL error except CliException as error: print(error) return 'error', error # Log out and close connection logout_close(alias) # Get response and fields try: response = result_data['attr']['name'] fields = result_data['content'] # If SPARKL operation fails, return data is not as expected except KeyError as error: print(result_data) return 'error', error # Return object with response and fields return_object = {'response': response, 'fields': fields} return 'ok', return_object
def get_sparkl_result(operation, alias, fields=None): """ Generic function used by tests. It sets the expected input fields, and calls the specified operation. It returns the response and the output fields. """ # In case of FLAGS, no field values are needed. if fields: sparkl('vars', literal=fields, alias=alias) result = format_response_data(sparkl('call', operation, alias=alias)) try: response = result['response'] fields = result['fields'] return response, fields except KeyError: error_msg = 'SPARKL error: {}'.format(json.dumps(result)) assert False, error_msg
def login(user, alias): """ Logs in specified user and starts the event logging. Returns either: - True, the events generator - False, an error message """ try: sparkl('connect', 'http://localhost:8000', alias=alias) sparkl('login', user, alias=alias) # Specify a path to any configuration object to # narrow down the events you will be receiving. # E.g. sparkl listen Scratch/Primes/CheckPrime events = sparkl('listen', alias=alias) return True, events except CliException as error: return False, error
def run_tests(alias, event_queue, log_writer, test_data): """ Run once per test. - alias: The SPARKL alias used by the session - test_data: A dict containing the test data. It comprises: - OPERATION: The name of the operation to call - INPUT_FIELDS (optional): The input fields and their values - EXP_RESPONSE: The expected response/reply - OUTPUT_FIELDS (optional): One or more output fields with their expected value - CHECK_FUN (optional): A function that makes extra assertions on the output values - STOP_OR_NOT (optional): A flag to indicate all running services must be stopped before the test is run """ # Stop all services in test directory if test requires so. if STOP_OR_NOT in test_data: sparkl('stop', IMPORT_DIR, alias=alias) # Set field values if the test specifies input data for the operation. if INPUT_FIELDS in test_data: sparkl('vars', literal=test_data[INPUT_FIELDS], alias=alias) # Call SPARKL operation and gather results. result = sparkl('call', test_data[OPERATION], alias=alias) # Check whether the expected events are received. assert_events(event_queue, log_writer, test_data[TEST_NAME], miners=test_data.get(MINERS, None)) # Check whether the tested operation returned the expected response. assert_result(result, **test_data)
def connect_login(alias='default'): """ Connects to a SPARKL instance and logs into a user account The function returns the specified alias (default is "default") for other funs to use """ # Prompt for SPARKL instance URL instance = input('Enter your SPARKL instance URL: ') # Get live connections connection_data = sparkl('connect') connections = connection_data['content'] # If alias in use, prompt for new alias while any(x['attr']['alias'] == alias for x in connections): alias = input('Alias %s in use. Type in another (e.g. foo or bar):' % (alias)) try: # Connect to SPARKL instance sparkl('connect', url=instance, alias=alias) print('Connected to %s using alias %s' % (instance, alias)) # Prompt for username user = input('Enter your username: '******'login', user=user, alias=alias) print('Logging in as %s...' % (user)) except CliException as error: print(error) return 'error', error # Return used alias return 'ok', alias
def start_service_in(sparkl_path, module_name, watchdog_path, **kwargs): """ Maps a SPARKL service to its implementation using `sparkl service`. - sparkl_path: The path to the SPARKL service in the user tree - module_name: The name of the implementation module (without the suffix) - watchdog_path: The directory in which the `sparkl service` command is executed (and the Python watchdog is started) """ # Filter kwargs for `sparkl service` service_kwargs = dict() for key, value in kwargs.items(): if key in ['path', 'alias']: service_kwargs[key] = value # Start the SPARKL service in the specified directory. with ChDir(watchdog_path): sparkl('service', sparkl_path, module_name, **service_kwargs) # Give the watchdog time to start. sleep(kwargs.get('wait', 3))
def unit_import(config_files, folder, alias): """ Iterates through a list of files and offers them for importing. """ for config in config_files: # Prompt for user input answer = user_confirm('Import %s? y/n: ' % config) # If answer is yes, tries to import file if answer == 'Y': change_message = sparkl('put', config, folder, alias=alias) # Fun prints message based on success/failure is_import_successful(change_message, config, folder)
def event_to_queue(alias, listen_path, event_queue): """ Starts a listener process and puts each event in the supplied event queue. - alias: The SPARKL CLI alias used by the test suite. - listen_path: The path to the SPARKL resource targeted by the listener (e.g. a service or an operation). - event_queue: A queue used by the listener process to communicate with the main test process. """ events = sparkl('listen', listen_path, alias=alias) for event in events: event_queue.put(event)
def open_socket(service_path): """ Tries to open a websocket using the specified path. The path must be the full path to the service in the SPARKL user tree prepended by the user name. E.g.: [email protected]/Scratch/lib_bitcoin_python/Bitcoin. """ try: service = sparkl('service', service_path, IMPL_MODULE, alias=ALIAS) return True, service except WebSocketBadStatusException as error: return False, ', '.join(error.args) except WebSocketConnectionClosedException as error: return False, ', '.join(error.args)
def multi_import(): """ Imports all or only the selected SPARKL configs into the user's configuration tree. """ # Logs you in using random alias alias = uuid.uuid4().hex (tag, info) = connect_login(alias) # If fails to log in or connect, return from function if tag == 'error': print(info) return # Gets the folders available in the user tree folders = sparkl('ls', alias=alias) folder_names = folders['content'] # Creates Scratch and/or Lib folder if it does not exist in the user tree xmp_dir = 'Scratch' lib_dir = 'Lib' lib_create(xmp_dir, folder_names, alias) lib_create(lib_dir, folder_names, alias) # Gets the SPARKL config files from the Examples and Library folders # in the examples repo examples = glob.glob('../Examples/*/*.xml') libs = glob.glob('../Library/*/*.xml') # Prompts user to import all config files answer_all = user_confirm('Import all examples? y/n ') # If user chooses yes, tries to import if answer_all == 'Y': # All files from the Examples folder for config in examples: change_message = sparkl('put', config, xmp_dir, alias=alias) # Fun prints message based on success/failure is_import_successful(change_message, config, xmp_dir) # All files from the Library folder for config in libs: change_message = sparkl('put', config, lib_dir, alias=alias) # Fun prints message based on success/failure is_import_successful(change_message, config, lib_dir) # Logs you out and closes connection logout_close(alias) return # If not all files are chosen for importing, offers them one by one unit_import(examples, xmp_dir, alias) unit_import(libs, lib_dir, alias) # Logs you out and closes connection logout_close(alias) return
def session_setup(): """ Sets the test environment for all test modules. """ # Collect login details from test settings. sse_url = read_from_config('sse_url') sse_user = read_from_config('sse_user') sse_pwd = read_from_config('sse_pass') # Set test environment, connect, login, create test folder sparkl('connect', sse_url, alias=ALIAS) sparkl('login', sse_user, sse_pwd, alias=ALIAS) sparkl('mkdir', IMPORT_DIR, alias=ALIAS) # Start test log writer. log_writer, log_handle = start_test_log() # Each test can access it. yield log_writer # Clean up after all tests have run. sparkl('rm', IMPORT_DIR, alias=ALIAS) sparkl('logout', alias=ALIAS) sparkl('close', alias=ALIAS) # Close log file and writer co-routine. stop_test_log(log_writer, log_handle)
def logout(alias='default'): """ Called on on_exit of logger frame. Closes the connection to SPARKL. """ sparkl('close', alias=alias)