def test_displayed_in_start_time_desc(self): from datetime import datetime, timedelta t = datetime.now() first = dict(duration_ms=1, return_code=200, start_time=t, function='begin/session') second = dict(duration_ms=1, return_code=200, start_time=t - timedelta(seconds=1), function='delete/stubs') # inserted out of start_time order but sorted by start_time desc self.db.tracker.insert(first) self.db.tracker.insert(second) from stubo.model.db import Tracker tracker = Tracker(self.db) tracks = list(tracker.find_tracker_data({}, 0, 5)) self.assertEqual(tracks[0].get('function'), 'begin/session') self.assertEqual(tracks[1].get('function'), 'delete/stubs') self.http_client.fetch(self.get_url('/tracker?all_hosts=true'), self.stop) response = self.wait() self.assertEqual(response.code, 200) html = response.body first_index = html.find('begin/session</a>') second_index = html.find('delete/stubs</a>') self.assertTrue(first_index < second_index)
def test_displayed_in_start_time_desc(self): from datetime import datetime, timedelta t = datetime.now() first = dict(duration_ms=1, return_code=200, start_time=t, function='begin/session') second = dict(duration_ms=1, return_code=200, start_time=t-timedelta(seconds=1), function='delete/stubs') # inserted out of start_time order but sorted by start_time desc self.db.tracker.insert(first) self.db.tracker.insert(second) from stubo.model.db import Tracker tracker = Tracker(self.db) tracks = list(tracker.find_tracker_data({}, 0, 5)) self.assertEqual(tracks[0].get('function'), 'begin/session') self.assertEqual(tracks[1].get('function'), 'delete/stubs') self.http_client.fetch(self.get_url('/tracker?all_hosts=true'), self.stop) response = self.wait() self.assertEqual(response.code, 200) html = response.body first_index = html.find('begin/session</a>') second_index = html.find('delete/stubs</a>') self.assertTrue(first_index < second_index)
def store_source_recording(scenario_name_key, record_session): host, scenario_name = scenario_name_key.split(':') # use original put/stub payload logged in tracker tracker = Tracker() last_used = tracker.session_last_used(scenario_name_key, record_session, 'record') if not last_used: # empty recordings are currently supported! log.debug('Unable to find a recording for session={0}, scenario={1}'.format(record_session, scenario_name_key)) return recording = tracker.get_last_recording(scenario_name, record_session, last_used['start_time']) recording = list(recording) if not recording: raise exception_response(400, title="Unable to find a recording for scenario='{0}', record_session='{1}'".format(scenario_name, record_session)) number_of_requests = len(recording) scenario_db = Scenario() for nrequest in range(number_of_requests): track = recording[nrequest] request_text = track.get('request_text') if not request_text: raise exception_response(400, title='Unable to obtain recording details, was full tracking enabled?') priority = int(track['request_params'].get('priority', nrequest+1)) stub = parse_stub(request_text, scenario_name_key, track['request_params']) stub.set_priority(priority) scenario_db.insert_pre_stub(scenario_name_key, stub)
def store_source_recording(scenario_name_key, record_session): host, scenario_name = scenario_name_key.split(':') # use original put/stub payload logged in tracker tracker = Tracker() last_used = tracker.session_last_used(scenario_name_key, record_session, 'record') if not last_used: # empty recordings are currently supported! log.debug('Unable to find a recording for session={0}, scenario={1}'.format(record_session, scenario_name_key)) return recording = tracker.get_last_recording(scenario_name, record_session, last_used['start_time']) recording = list(recording) if not recording: raise exception_response(400, title="Unable to find a recording for scenario='{0}', record_session='{1}'".format( scenario_name, record_session)) number_of_requests = len(recording) scenario_db = Scenario() for nrequest in range(number_of_requests): track = recording[nrequest] request_text = track.get('request_text') if not request_text: raise exception_response(400, title='Unable to obtain recording details, was full tracking enabled?') priority = int(track['request_params'].get('priority', nrequest + 1)) stub = parse_stub(request_text, scenario_name_key, track['request_params']) stub.set_priority(priority) scenario_db.insert_pre_stub(scenario_name_key, stub)
def on_finish(self): elapsed_ms = int(1000.0 * self.request.request_time()) tracker = Tracker() # handle fail early cases that don't have a response if not hasattr(self.track, 'stubo_response'): self.track.stubo_response = '' return_code = self.get_status() record = dict(duration_ms=elapsed_ms, return_code=return_code) if self._headers_written: record['response_headers'] = self._headers record['response_size'] = int( self._headers.get('Content-Length', len(self.track.stubo_response))) self.track.update(record) if self.track.function == 'get/response' \ and return_code > 399: self.track.request_text = self.request.body if self.track.tracking_level != 'full' and \ self.track.response_size > self.max_response_size: try: # response will typically be json dict so convert to str to chop self.track.stubo_response = str( self.track.stubo_response)[:self.max_response_size] except Exception, e: log.error( "unable to trim tracked stubo response: {0}".format(e))
def get_tracks(handler, session_filter, show_only_errors, skip, limit, start_time, latency, all_hosts, function): tracker = Tracker() tracker_filter = {} if start_time: try: start = datetime.datetime.strptime(start_time, '%Y-%m-%d %H:%M:%S') tracker_filter['start_time'] = {"$lt": start} except ValueError, e: raise exception_response( 400, title='start_time format error: {0}'.format(e))
def get(self, record_id): tracker = Tracker(self.db) # getting tracker obj obj = yield tracker.find_tracker_data_full(record_id) if obj is not None: obj['start_time'] = obj['start_time'].strftime('%Y-%m-%d %H:%M:%S') # converting document ID to string obj_id = str(ObjectId(obj['_id'])) obj['id'] = obj_id # removing BSON object obj.pop('_id') result = { 'data': obj } self.write(result) else: self.set_status(404) self.write("Record with ID: %s not found." % record_id)
def test_multidate(self): # import from commands file self._import_module() self.http_client.fetch(self.get_url('/api/v2/tracker/records'), self.stop) response = self.wait() self.assertEqual(response.code, 200) json_body = json.loads(response.body) tracker_items = json_body['data'] tracker = Tracker(self.db) for item in tracker_items: if item['function'] == 'get/response': record_id = item['id'] obj = tracker.find_tracker_data_full(record_id) print obj['stubo_response'] self.assertTrue('2014-11-06' in obj['stubo_response']) self.assertTrue('2014-10-06' in obj['stubo_response']) self.assertTrue('2014-08-06' in obj['stubo_response'])
def get_track(request, tracker_id): tracker = Tracker() return tracker.find_tracker_data_full(tracker_id)
def get(self): # getting pagination info skip = int(self.get_argument('skip', 0)) limit = int(self.get_argument('limit', 100)) tracker = Tracker(self.db) # getting total items total_items = yield tracker.item_count() # TODO: add filtering tracker_filter = {} cursor = tracker.find_tracker_data(tracker_filter, skip, limit) tracker_objects = [] while (yield cursor.fetch_next): try: document = cursor.next_object() # converting datetime object to string document['start_time'] = document['start_time'].strftime('%Y-%m-%d %H:%M:%S') # converting document ID to string obj_id = str(ObjectId(document['_id'])) document['id'] = obj_id # adding object ref ID document['href'] = "/stubo/api/v2/tracker/records/objects/%s" % obj_id # removing BSON object document.pop('_id') tracker_objects.append(document) except Exception as ex: log.warn('Failed to fetch document: %s' % ex) # --- Pagination --- # skip forward skip_forward = skip skip_forward += limit # skip backwards skip_backwards = skip - limit if skip_backwards < 0: skip_backwards = 0 # previous, removing link if there are no pages if skip != 0: previous_page = "/stubo/api/v2/tracker/records?skip=" + str(skip_backwards) + "&limit=" + str(limit) else: previous_page = None # next page, removing link if there are no records ahead if skip_forward + limit >= total_items: next_page = None else: next_page = "/stubo/api/v2/tracker/records?skip=" + str(skip_forward) + "&limit=" + str(limit) result = {'data': tracker_objects, 'paging': { 'previous': previous_page, 'next': next_page, 'first': "/stubo/api/v2/tracker/records?skip=" + str(0) + "&limit=" + str(limit), 'last': "/stubo/api/v2/tracker/records?skip=" + str(total_items-limit) + "&limit=" + str(limit), 'currentLimit': limit, 'totalItems': total_items }} self.write(result)
def export_stubs_to_commands_format(handler, scenario_name): """ Exports scenario to .commands file format. :param handler: :param scenario_name: <string> Scenario name :return: :raise exception_response: """ cache = Cache(get_hostname(handler.request)) scenario_name_key = cache.scenario_key_name(scenario_name) # use user arg or epoch time session_id = handler.get_argument('session_id', int(time.time())) session = u'{0}_{1}'.format(scenario_name, session_id) cmds = [ 'delete/stubs?scenario={0}'.format(scenario_name), 'begin/session?scenario={0}&session={1}&mode=record'.format( scenario_name, session) ] files = [] scenario = Scenario() # get scenario pre stubs for specified scenario stubs = list(scenario.get_pre_stubs(scenario_name_key)) if stubs: for i in range(len(stubs)): entry = stubs[i] stub = Stub(entry['stub'], scenario_name_key) # if stub is rest - matcher may be None, checking that if stub.contains_matchers() is None: cmds.append('# Stub skipped since no matchers were found. Consider using .yaml format for additional ' 'capabilities') # skipping to next stub, this stub is not compatible with .commands format continue matchers = [('{0}_{1}_{2}.textMatcher'.format(session, i, x), stub.contains_matchers()[x]) for x in range(len(stub.contains_matchers()))] matchers_str = ",".join(x[0] for x in matchers) url_args = stub.args() url_args['session'] = session module_info = stub.module() if module_info: # Note: not including put/module in the export, modules are shared # by multiple scenarios. url_args['ext_module'] = module_info['name'] url_args['stub_created_date'] = stub.recorded() url_args['stubbedSystemDate'] = module_info.get('recorded_system_date') url_args['system_date'] = module_info.get('system_date') url_args = urlencode(url_args) responses = stub.response_body() assert(len(responses) == 1) response = responses[0] response = ('{0}_{1}.response'.format(session, i), response) cmds.append('put/stub?{0},{1},{2}'.format(url_args, matchers_str, response[0])) files.append(response) files.extend(matchers) else: cmds.append('put/stub?session={0},text=a_dummy_matcher,text=a_dummy_response'.format(session)) cmds.append('end/session?session={0}'.format(session)) runnable = asbool(handler.get_argument('runnable', False)) runnable_info = dict() if runnable: playback_session = handler.get_argument('playback_session', None) if not playback_session: raise exception_response(400, title="'playback_session' argument required with 'runnable") runnable_info['playback_session'] = playback_session tracker = Tracker() last_used = tracker.session_last_used(scenario_name_key, playback_session, 'playback') if not last_used: raise exception_response(400, title="Unable to find playback session") runnable_info['last_used'] = dict(remote_ip=last_used['remote_ip'], start_time=str(last_used['start_time'])) playback = tracker.get_last_playback(scenario_name, playback_session, last_used['start_time']) playback = list(playback) if not playback: raise exception_response(400, title="Unable to find a playback for scenario='{0}', playback_session='{1}'".format(scenario_name, playback_session)) cmds.append('begin/session?scenario={0}&session={1}&mode=playback'.format( scenario_name, session)) number_of_requests = len(playback) runnable_info['number_of_playback_requests'] = number_of_requests for nrequest in range(number_of_requests): track = playback[nrequest] request_text = track.get('request_text') if not request_text: raise exception_response(400, title='Unable to obtain playback details, was full tracking enabled?') request_file_name = '{0}_{1}.request'.format(session, nrequest) files.append((request_file_name, request_text)) stubo_response_text = track['stubo_response'] if not isinstance(stubo_response_text, basestring): stubo_response_text = unicode(stubo_response_text) stubo_response_file_name = '{0}_{1}.stubo_response'.format(session, nrequest) files.append((stubo_response_file_name, stubo_response_text)) url_args = track['request_params'] url_args['session'] = session url_args = urlencode(url_args) cmds.append(u'get/response?{0},{1}'.format(url_args, request_file_name)) cmds.append('end/session?session={0}'.format(session)) try: bookmarks = cache.get_all_saved_request_index_data() if bookmarks: cmds.append('import/bookmarks?location=bookmarks') files.append(('bookmarks', json.dumps(bookmarks))) except Exception as ex: log.warn("failed to export bookmarks, error: %s" % ex) pass files.append(('{0}.commands'.format(scenario_name), b"\r\n".join(cmds))) static_dir = handler.settings['static_path'] export_dir = handler.get_argument('export_dir', scenario_name_key).replace(':', '_') export_dir_path = os.path.join(static_dir, 'exports', export_dir) if os.path.exists(export_dir_path): shutil.rmtree(export_dir_path) os.makedirs(export_dir_path) archive_name = os.path.join(export_dir_path, scenario_name) zout = zipfile.ZipFile(archive_name+'.zip', "w") tar = tarfile.open(archive_name+".tar.gz", "w:gz") for finfo in files: fname, contents = finfo file_path = os.path.join(export_dir_path, fname) with codecs.open(file_path, mode='wb', encoding='utf-8') as f: f.write(contents) f.close() tar.add(file_path, fname) zout.write(file_path, fname) tar.close() zout.close() shutil.copy(archive_name+'.zip', archive_name+'.jar') files.extend([(scenario_name+'.zip',), (scenario_name+'.tar.gz',), (scenario_name+'.jar',)]) # getting links links = get_export_links(handler, scenario_name_key, files) return links
def export_stubs_to_commands_format(handler, scenario_name): """ Exports scenario to .commands file format. :param handler: :param scenario_name: <string> Scenario name :return: :raise exception_response: """ cache = Cache(get_hostname(handler.request)) scenario_name_key = cache.scenario_key_name(scenario_name) # use user arg or epoch time session_id = handler.get_argument('session_id', int(time.time())) session = u'{0}_{1}'.format(scenario_name, session_id) cmds = [ 'delete/stubs?scenario={0}'.format(scenario_name), 'begin/session?scenario={0}&session={1}&mode=record'.format( scenario_name, session) ] files = [] scenario = Scenario() # get scenario pre stubs for specified scenario stubs = list(scenario.get_pre_stubs(scenario_name_key)) if stubs: for i in range(len(stubs)): entry = stubs[i] stub = Stub(entry['stub'], scenario_name_key) # if stub is rest - matcher may be None, checking that if stub.contains_matchers() is None: cmds.append( '# Stub skipped since no matchers were found. Consider using .yaml format for additional ' 'capabilities') # skipping to next stub, this stub is not compatible with .commands format continue matchers = [('{0}_{1}_{2}.textMatcher'.format(session, i, x), stub.contains_matchers()[x]) for x in range(len(stub.contains_matchers()))] matchers_str = ",".join(x[0] for x in matchers) url_args = stub.args() url_args['session'] = session module_info = stub.module() if module_info: # Note: not including put/module in the export, modules are shared # by multiple scenarios. url_args['ext_module'] = module_info['name'] url_args['stub_created_date'] = stub.recorded() url_args['stubbedSystemDate'] = module_info.get( 'recorded_system_date') url_args['system_date'] = module_info.get('system_date') url_args = urlencode(url_args) responses = stub.response_body() assert (len(responses) == 1) response = responses[0] response = ('{0}_{1}.response'.format(session, i), response) cmds.append('put/stub?{0},{1},{2}'.format(url_args, matchers_str, response[0])) files.append(response) files.extend(matchers) else: cmds.append( 'put/stub?session={0},text=a_dummy_matcher,text=a_dummy_response'. format(session)) cmds.append('end/session?session={0}'.format(session)) runnable = asbool(handler.get_argument('runnable', False)) runnable_info = dict() if runnable: playback_session = handler.get_argument('playback_session', None) if not playback_session: raise exception_response( 400, title="'playback_session' argument required with 'runnable") runnable_info['playback_session'] = playback_session tracker = Tracker() last_used = tracker.session_last_used(scenario_name_key, playback_session, 'playback') if not last_used: raise exception_response(400, title="Unable to find playback session") runnable_info['last_used'] = dict(remote_ip=last_used['remote_ip'], start_time=str( last_used['start_time'])) playback = tracker.get_last_playback(scenario_name, playback_session, last_used['start_time']) playback = list(playback) if not playback: raise exception_response( 400, title= "Unable to find a playback for scenario='{0}', playback_session='{1}'" .format(scenario_name, playback_session)) cmds.append( 'begin/session?scenario={0}&session={1}&mode=playback'.format( scenario_name, session)) number_of_requests = len(playback) runnable_info['number_of_playback_requests'] = number_of_requests for nrequest in range(number_of_requests): track = playback[nrequest] request_text = track.get('request_text') if not request_text: raise exception_response( 400, title= 'Unable to obtain playback details, was full tracking enabled?' ) request_file_name = '{0}_{1}.request'.format(session, nrequest) files.append((request_file_name, request_text)) stubo_response_text = track['stubo_response'] if not isinstance(stubo_response_text, basestring): stubo_response_text = unicode(stubo_response_text) stubo_response_file_name = '{0}_{1}.stubo_response'.format( session, nrequest) files.append((stubo_response_file_name, stubo_response_text)) url_args = track['request_params'] url_args['session'] = session url_args = urlencode(url_args) cmds.append(u'get/response?{0},{1}'.format(url_args, request_file_name)) cmds.append('end/session?session={0}'.format(session)) files.append(('{0}.commands'.format(scenario_name), b"\r\n".join(cmds))) static_dir = handler.settings['static_path'] export_dir = handler.get_argument('export_dir', scenario_name_key).replace(':', '_') export_dir_path = os.path.join(static_dir, 'exports', export_dir) if os.path.exists(export_dir_path): shutil.rmtree(export_dir_path) os.makedirs(export_dir_path) archive_name = os.path.join(export_dir_path, scenario_name) zout = zipfile.ZipFile(archive_name + '.zip', "w") tar = tarfile.open(archive_name + ".tar.gz", "w:gz") for finfo in files: fname, contents = finfo file_path = os.path.join(export_dir_path, fname) with codecs.open(file_path, mode='wb', encoding='utf-8') as f: f.write(contents) f.close() tar.add(file_path, fname) zout.write(file_path, fname) tar.close() zout.close() shutil.copy(archive_name + '.zip', archive_name + '.jar') files.extend([(scenario_name + '.zip', ), (scenario_name + '.tar.gz', ), (scenario_name + '.jar', )]) # getting links links = get_export_links(handler, scenario_name_key, files) return links