def __init__(self, feedback_queue, file_name): self._feedback_queue = feedback_queue with open(file_name, 'r') as f: config_string = f.read() new_config = config.string_to_python(config_string) available_tasks = api.get_tasks(False) for task in new_config: if task['type'] not in available_tasks: self._feedback_queue.put( (common.api_exception_status, 'task ' + task['type'] + ' does not exist in ' 'this build')) continue try: api.new_task(task) except KeyError as e: self._feedback_queue.put( (common.api_exception_status, 'task ' + task['type'] + ' missing required key ' '%s from its configuration' % str(e))) except ValueError as e: self._feedback_queue.put( (common.api_exception_status, 'task ' + task['type'] + ' has at least one ' 'bad value for a config option:\n%s' % str(e))) thread = threading.Thread(target=self._handle_communication) thread.daemon = True thread.start()
def __call__(self): now = time.time() slept = now - self._last_check self._last_check = now trigger_probability = slept / self._time_per_trigger if random.random() < trigger_probability: self._triggered += 1 api.new_task(self._task)
def _check_regexes(self, body): """ Check if any of the configured regexes match against an email. Args: body (str): The string of an email body. """ for regex in self._regexes: if regex.search(body): api.new_task(self._regexes[regex])
def test_good_cases(task, good_cases): """ Used to test properly formatted configs. Prints feedback from the task. Args: task: A task dictionary mapping 'type' to the task name (e.g. 'ssh') good_cases: A list of tuples of the form ('config_name', config). config should be properly formatted. """ sim = usersim.UserSim(True) for config_name, config in good_cases: task['config'] = config api.new_task(task) print('Correctly accepted %s' % config_name)
def _check_links(self, body): """ Check if a link exists in an email, and if so checks if we should open it. Args: body (str): The string of an email body. """ # As useful as they are, regular expressions are ugly. If the name doesn't give it away, this matches a URL. url_regex = '([0-9]{1,3}\\.[0-9]{1,3}\\.[0-9]{1,3}\\.[0-9]{1,3}|(((news|telnet|nttp|file|http|ftp|https)://)' \ '|(www|ftp)[-A-Za-z0-9]*\\.)[-A-Za-z0-9/\\.]+)(:[0-9]*)?' match = re.search(url_regex, body) if match and random.randint(1, 100) <= self._config['open_links']: # There was a link in the email and we chose to click it. link_config = {'type': 'firefox', 'config': {'sites': [match.group()]}} api.new_task(link_config)
def run_test(): test_1 = {'type': 'test', 'config': {}} test_2 = {'type': 'testfeedback', 'config': {}} config = {'type': 'sequence', 'config': {'tasks': [test_1, test_2]}} sim = usersim.UserSim(True) task_id = api.new_task(config) print('Cycle 1') sim.cycle() print(api.status_task(task_id)) print('Cycle 2') sim.cycle() print(api.status_task(task_id)) print('Cycle 3') sim.cycle() # The sequence task may be stopped here, if it goes after the testfeedback task. print(api.status_task(task_id)) print('Cycle 4') sim.cycle() # Otherwise it would be stopped here. print(api.status_task(task_id))
def test_bad_value_cases(task, bad_value_cases): """ Test configs with invalid values. Args: task (dict): A task config dict. task['config'] will be overwritten. bad_value_cases (list(tuple)): List of tuples of the form ('config_name', config), where config contains a key:value pair with an invalid value. """ for config_name, config in bad_value_cases: task['config'] = config try: api.new_task(task) except ValueError: print('Correctly rejected %s' % config_name) else: raise AssertionError('Incorrectly accepted %s' % config_name)
def run_test(): # Calculate the trigger time to be 10 seconds from now. trigger_time = datetime.datetime.now() + datetime.timedelta(seconds=5) trigger_time = trigger_time.time() time = '{}{}'.format(str(trigger_time.hour), str(trigger_time.minute)) seconds = float(trigger_time.second) print('Trigger time is {}'.format(str(trigger_time))) config = {'type': 'attime', 'config': {'time': str(time), 'seconds': seconds, 'task': {'type': 'test', 'config': {}}}} sim = usersim.UserSim(True) task_id = api.new_task(config) result = sim.cycle() print(sim.status_task(task_id)['status']) while True: result = sim.cycle() if len(result) > 1: print(result) # Only break once we see the nested task has been stopped. if api.status_task(2)['state'] == api.States.STOPPED: break
def run_test(): test_1 = {'type': 'test', 'config': {}} test_2 = {'type': 'testfeedback', 'config': {}} config = {'type': 'all', 'config': {'tasks': [test_1, test_2]}} sim = usersim.UserSim(True) task_id = api.new_task(config) print('Cycle 1') sim.cycle() print(api.status_task(task_id)) print('Cycle 2') sim.cycle() # If both tasks go before the all task, it will be stopped here. print(api.status_task(task_id)) print('Cycle 3') sim.cycle() # Otherwise, it will be stopped here. print(api.status_task(task_id))
def run_test(): reps = 10 config = { 'type': 'frequency', 'config': { 'frequency': 2000, 'repetitions': reps, 'task': { 'type': 'test', 'config': {} } } } sim = usersim.UserSim(True) task_id = api.new_task(config) while True: result = sim.cycle() if len(result) > 1: print(result) # Break once the final task has been stopped. if api.status_task(task_id + reps)['state'] == api.States.STOPPED: break
def test_good_cases(task, good_cases): """ Test properly formatted configs. Args: task (dict): A task config dict. task['config'] will be overwritten. good_cases (list(tuple)): List of tuples of the form ('config_name', config), where config is a valid config for the task. """ for config_name, config in good_cases: task['config'] = config sim = usersim.UserSim(True) api.new_task(task) # Running this one is way too annoying. #result = sim.cycle() #for item in result: # print(item) print('Correctly accepted %s' % config_name)
def __call__(self): if not self._waiting and self._index < len(self._tasks): # Start the next task and wait for it. self._current = api.new_task(self._tasks[self._index]) self._waiting = True self._index += 1 if api.status_task(self._current)['state'] == api.States.STOPPED: self._waiting = False
def test_bad_key_cases(task, bad_key_cases): """ Used to test configs with missing keys. This function will raise an assertion error if validate incorrectly accepts a bad config dictionary. Args: task: A task dictionary mapping 'type' to the task name (e.g. 'ssh') bad_key_cases: A list of tuples of the form ('config_name', config). config should be missing at least one key. Raises: AssertionError: If api.new_task does not raise a KeyError """ for config_name, config in bad_key_cases: task['config'] = config try: api.new_task(task) raise AssertionError('Incorrectly accepted %s' % config_name) except KeyError: print('Correctly rejected %s' % config_name)
def _handle_communication(self): """ Periodically check if there are any new config files available or if there is any feedback that should be forwarded. """ while True: new_config = self._receive() if new_config: available_tasks = api.get_tasks(False) for task in new_config: # As in the _receive method, it's okay for the feedback messages in here to stay in case feedback is # used with boost in later versions. if task['type'] not in available_tasks: self._feedback_queue.put( (common.api_exception_status, 'task ' + task['type'] + ' does not ' 'exist in the current build')) continue try: api.new_task(task) except KeyError as e: self._feedback_queue.put( (common.api_exception_status, 'task ' + task['type'] + ' missing ' 'required key %s from its configuration' % e.message)) except ValueError as e: self._feedback_queue.put( (common.api_exception_status, 'task ' + task['type'] + ' has at least ' 'one bad value for a config option:\n%s' % e.message)) self._send() # So the CPU isn't running at 100%. time.sleep(5)
def run_test(): seconds = 10 task = {'type': 'test', 'config': {}} config = {'type': 'delay', 'config': {'task': task, 'seconds': seconds}} sim = usersim.UserSim(True) task_id = api.new_task(config) while True: sim.cycle() if api.status_task(2)['state'] == api.States.STOPPED: print('Nested delay task complete.') break
def __call__(self): if not self._started: for task in self._tasks: task_id = api.new_task(task) self._task_ids.add(task_id) self._started = True self._stopped_task_ids = set() for task_id in self._task_ids: # Check that all nested tasks have stopped. if api.status_task(task_id)['state'] == api.States.STOPPED: # Would do self._task_ids.remove here, but we can't modify the data structure while iterating over it. self._stopped_task_ids.add(task_id) else: break else: # Since they are uncommon, the else part of a for-else executes when the for loop completes without a break. self._done = True # No point repeating work that's already been completed. self._task_ids = self._task_ids - self._stopped_task_ids
def test_new_task(): task = {'type': 'test', 'config': {}} assert api.new_task(task, reset=True) == 1
def __call__(self): if datetime.datetime.now() >= self._trigger_time: self._triggered = True api.new_task(self._task)