def insert_stub(self, doc, stateful): from stubo.model.stub import Stub matchers = doc['stub'].contains_matchers() scenario = doc['scenario'] stubs_cursor = self.get_stubs(scenario) if stubs_cursor.count(): for stub in stubs_cursor: the_stub = Stub(stub['stub'], scenario) if matchers == the_stub.contains_matchers(): if not stateful and \ doc['stub'].response_body() == the_stub.response_body(): msg = 'duplicate stub found, not inserting.' log.warn(msg) return msg log.debug('In scenario: {0} found exact match for matchers:' ' {1}. Perform stateful update of stub.'.format(scenario, matchers)) response = the_stub.response_body() response.extend(doc['stub'].response_body()) the_stub.set_response_body(response) self.db.scenario_stub.update( {'_id': ObjectId(stub['_id'])}, {'$set' : {'stub' : the_stub.payload}}) return 'updated with stateful response' doc['stub'] = doc['stub'].payload status = self.db.scenario_stub.insert(doc) return 'put {0} stub'.format(status)
def insert_stub(self, doc, stateful): from stubo.model.stub import Stub matchers = doc['stub'].contains_matchers() scenario = doc['scenario'] stubs_cursor = self.get_stubs(scenario) if stubs_cursor.count(): for stub in stubs_cursor: the_stub = Stub(stub['stub'], scenario) if matchers and matchers == the_stub.contains_matchers(): if not stateful and \ doc['stub'].response_body() == the_stub.response_body(): msg = 'duplicate stub found, not inserting.' log.warn(msg) return msg log.debug('In scenario: {0} found exact match for matchers:' ' {1}. Perform stateful update of stub.'.format(scenario, matchers)) response = the_stub.response_body() response.extend(doc['stub'].response_body()) the_stub.set_response_body(response) self.db.scenario_stub.update( {'_id': ObjectId(stub['_id'])}, {'$set' : {'stub' : the_stub.payload}}) return 'updated with stateful response' doc['stub'] = doc['stub'].payload status = self.db.scenario_stub.insert(doc) return 'inserted scenario_stub: {0}'.format(status)
def insert_stub(self, doc, stateful): """ Insert stub into DB. Performs a check whether this stub already exists in database or not. If it exists and stateful is True - new response is appended to the response list, else - reports that duplicate stub found and it will not be inserted. :param doc: Stub class with Stub that will be inserted :param stateful: <boolean> specify whether stub insertion should be stateful or not :return: <string> message with insertion status: ignored - if not stateful and stub was already present updated - if stateful and stub was already present created - if stub was not present in database """ # getting initial values - stub matchers, scenario name matchers = doc["stub"].contains_matchers() scenario = doc["scenario"] matchers_hash = self._create_hash(matchers) # check if we have matchers - should be None for REST calls if matchers is not None: # additional helper value for indexing doc["matchers_hash"] = matchers_hash matched_stub = self.get_matched_stub(name=scenario, matchers_hash=matchers_hash) # checking if stub already exists if matched_stub: # creating stub object from found document the_stub = Stub(matched_stub["stub"], scenario) if not stateful and doc["stub"].response_body() == the_stub.response_body(): msg = "duplicate stub found, not inserting." log.warn(msg) result = {"status": "ignored", "msg": msg, "key": str(matched_stub["_id"])} return result # since stateful is true - updating stub body by extending the list log.debug( "In scenario: {0} found exact match for matchers:" " {1}. Perform stateful update of stub.".format(scenario, matchers) ) response = the_stub.response_body() response.extend(doc["stub"].response_body()) the_stub.set_response_body(response) # updating Stub body and size, writing to database self.db.scenario_stub.update( {"_id": matched_stub["_id"]}, {"$set": {"stub": the_stub.payload, "space_used": len(unicode(the_stub.payload))}}, ) result = {"status": "updated", "msg": "Updated with stateful response", "key": str(matched_stub["_id"])} return result # inserting stub into DB status = self.db.scenario_stub.insert(self.get_stub_document(doc)) result = {"status": "created", "msg": "Inserted scenario_stub", "key": str(status)} return result
def test_put_stub(self): self.http_client.fetch(self.get_url('/stubo/api/begin/session?scenario=xslt&session=s1&mode=record'), self.stop) response = self.wait() self.assertEqual(response.code, 200) self.http_client.fetch(self.get_url('/stubo/api/put/module?name=/static/cmds/tests/ext/xslt/mangler.py'), self.stop) response = self.wait() self.assertEqual(response.code, 200) self.http_client.fetch(self.get_url('/stubo/api/put/stub?session=s1&ext_module=mangler'), callback=self.stop, method="POST", body="""||textMatcher||<request><a>ba</a><trans_id>1234</trans_id><b>ba</b><user uuid="xxx">joe</user><dt>2013-11-25</dt></request>||response||<response><a>ba</a><trans_id>1234</trans_id><b>ba</b><user uuid="xxx">joe</user><dt>2013-11-25</dt></response>""") response = self.wait() self.assertEqual(response.code, 200) from stubo.model.db import Scenario scenario_db = Scenario(db=self.db) stubs = list(scenario_db.get_stubs('localhost:xslt')) self.assertEqual(len(stubs), 1) from stubo.model.stub import Stub stub = Stub(stubs[0]['stub'], 'localhost:xslt') self.assertEqual(stub.contains_matchers()[0], u'<request><a>ba</a><trans_id>***</trans_id><b>ba</b><user uuid="***">***</user><dt>***</dt></request>\n') self.assertEqual(stub.response_body()[0], u'<response><a>ba</a><trans_id>***</trans_id><b>ba</b><user uuid="***">***</user><dt>***</dt></response>\n') from datetime import date self.assertEqual(stub.module(), { u'system_date': str(date.today()), u'recorded_system_date': str(date.today()), u'name': u'mangler'})
def test_put_stub(self): self.http_client.fetch(self.get_url('/stubo/api/put/module?name=/static/cmds/tests/ext/split/splitter.py'), self.stop) response = self.wait() self.assertEqual(response.code, 200) self.http_client.fetch(self.get_url('/stubo/api/begin/session?scenario=split&session=split_1&mode=record'), self.stop) response = self.wait() self.assertEqual(response.code, 200) self.http_client.fetch(self.get_url('/stubo/api/put/stub?session=split_1&ext_module=splitter'), callback=self.stop, method="POST", body="""||textMatcher||<a> <pre>hello</pre> <id>xxx</id> <post>goodbye</post> </a>||response||Hello {{1+1}} World""") response = self.wait() self.assertEqual(response.code, 200) from stubo.model.db import Scenario scenario_db = Scenario(db=self.db) stubs = list(scenario_db.get_stubs('localhost:split')) self.assertEqual(len(stubs), 1) from stubo.model.stub import Stub stub = Stub(stubs[0]['stub'], 'localhost:split') self.assertEqual(stub.contains_matchers(), [u'<a>\n<pre>hello</pre>\n', '\n<post>goodbye</post>\n</a>']) self.assertEqual(stub.response_body()[0], u'Hello {{1+1}} World') from datetime import date self.assertEqual(stub.module(), { u'system_date': str(date.today()), u'recorded_system_date': str(date.today()), u'name': u'splitter'})
def test_put_stub(self): self.http_client.fetch(self.get_url('/stubo/api/put/module?name=/static/cmds/tests/ext/cache/text/example.py'), self.stop) response = self.wait() self.assertEqual(response.code, 200) self.http_client.fetch(self.get_url('/stubo/api/begin/session?scenario=cache&session=cache_1&mode=record'), self.stop) response = self.wait() self.assertEqual(response.code, 200) self.http_client.fetch(self.get_url('/stubo/api/put/stub?session=cache_1&ext_module=example'), callback=self.stop, method="POST", body="""||textMatcher||<request>hello</request>||response||<response>0</response>""") response = self.wait() self.assertEqual(response.code, 200) from stubo.model.db import Scenario scenario_db = Scenario(db=self.db) stubs = list(scenario_db.get_stubs('localhost:cache')) self.assertEqual(len(stubs), 1) from stubo.model.stub import Stub stub = Stub(stubs[0]['stub'], 'localhost:cache') self.assertEqual(stub.contains_matchers(), ['<request>hello</request>']) self.assertEqual(stub.response_body()[0], u'<response>0</response>') from datetime import date self.assertEqual(stub.module(), {u'system_date': str(date.today()), u'recorded_system_date': str(date.today()), u'name': u'example'})
def test_put_stub(self): self.http_client.fetch( self.get_url( '/stubo/api/put/module?name=/static/cmds/tests/ext/cache/text/example.py' ), self.stop) response = self.wait() self.assertEqual(response.code, 200) self.http_client.fetch( self.get_url( '/stubo/api/begin/session?scenario=cache&session=cache_1&mode=record' ), self.stop) response = self.wait() self.assertEqual(response.code, 200) stub = { "priority": 1, "args": { "priority": "1", "ext_module": "example" }, "request": { "bodyPatterns": { "contains": ["<request>hello</request>\n"] }, "method": "POST" }, "response": { "body": "<response>0</response>\n", "status": 200 } } import json self.http_client.fetch(self.get_url( '/stubo/api/put/stub?session=cache_1&ext_module=example'), callback=self.stop, method="POST", body=json.dumps(stub), headers={'Content-Type': 'application/json'}) response = self.wait() self.assertEqual(response.code, 200) from stubo.model.db import Scenario scenario_db = Scenario(db=self.db) stubs = list(scenario_db.get_stubs('localhost:cache')) self.assertEqual(len(stubs), 1) from stubo.model.stub import Stub stub = Stub(stubs[0]['stub'], 'localhost:cache') self.assertEqual(stub.contains_matchers(), ['<request>hello</request>\n']) self.assertEqual(stub.response_body()[0], u'<response>0</response>\n') from datetime import date self.assertEqual( stub.module(), { u'system_date': str(date.today()), u'recorded_system_date': str(date.today()), u'name': u'example' })
def insert_stub(self, doc, stateful): """ Insert stub into DB. Performs a check whether this stub already exists in database or not. If it exists and stateful is True - new response is appended to the response list, else - reports that duplicate stub found and it will not be inserted. :param doc: Stub class with Stub that will be inserted :param stateful: <boolean> specify whether stub insertion should be stateful or not :return: <string> message with insertion status """ matchers = doc['stub'].contains_matchers() scenario = doc['scenario'] stubs_cursor = self.get_stubs(scenario) if stubs_cursor.count(): for stub in stubs_cursor: the_stub = Stub(stub['stub'], scenario) if matchers and matchers == the_stub.contains_matchers(): if not stateful and \ doc['stub'].response_body() == the_stub.response_body(): msg = 'duplicate stub found, not inserting.' log.warn(msg) return msg log.debug( 'In scenario: {0} found exact match for matchers:' ' {1}. Perform stateful update of stub.'.format( scenario, matchers)) response = the_stub.response_body() response.extend(doc['stub'].response_body()) the_stub.set_response_body(response) self.db.scenario_stub.update( {'_id': ObjectId(stub['_id'])}, {'$set': { 'stub': the_stub.payload }}) return 'updated with stateful response' doc['stub'] = doc['stub'].payload status = self.db.scenario_stub.insert(doc) self.db.scenario_stub.create_index([("stub.priority", ASCENDING), ("scenario", ASCENDING)]) return 'inserted scenario_stub: {0}'.format(status)
def insert_stub(self, doc, stateful): """ Insert stub into DB. Performs a check whether this stub already exists in database or not. If it exists and stateful is True - new response is appended to the response list, else - reports that duplicate stub found and it will not be inserted. :param doc: Stub class with Stub that will be inserted :param stateful: <boolean> specify whether stub insertion should be stateful or not :return: <string> message with insertion status """ matchers = doc['stub'].contains_matchers() scenario = doc['scenario'] stubs_cursor = self.get_stubs(scenario) if stubs_cursor.count(): for stub in stubs_cursor: the_stub = Stub(stub['stub'], scenario) if matchers and matchers == the_stub.contains_matchers(): if not stateful and \ doc['stub'].response_body() == the_stub.response_body(): msg = 'duplicate stub found, not inserting.' log.warn(msg) return msg log.debug('In scenario: {0} found exact match for matchers:' ' {1}. Perform stateful update of stub.'.format(scenario, matchers)) response = the_stub.response_body() response.extend(doc['stub'].response_body()) the_stub.set_response_body(response) self.db.scenario_stub.update( {'_id': ObjectId(stub['_id'])}, {'$set' : {'stub' : the_stub.payload}}) return 'updated with stateful response' doc['stub'] = doc['stub'].payload status = self.db.scenario_stub.insert(doc) self.db.scenario_stub.create_index([("stub.priority", ASCENDING), ("scenario", ASCENDING)]) return 'inserted scenario_stub: {0}'.format(status)
def test_put_stub(self): self.http_client.fetch(self.get_url('/stubo/api/put/module?name=/static/cmds/tests/ext/cache/text/example.py'), self.stop) response = self.wait() self.assertEqual(response.code, 200) self.http_client.fetch(self.get_url('/stubo/api/begin/session?scenario=cache&session=cache_1&mode=record'), self.stop) response = self.wait() self.assertEqual(response.code, 200) stub = { "priority": 1, "args": { "priority": "1", "ext_module": "example" }, "request": { "bodyPatterns": { "contains": [ "<request>hello</request>\n" ] }, "method": "POST" }, "response": { "body": "<response>0</response>\n", "status": 200 } } import json self.http_client.fetch(self.get_url('/stubo/api/put/stub?session=cache_1&ext_module=example'), callback=self.stop, method="POST", body=json.dumps(stub), headers={'Content-Type': 'application/json'}) response = self.wait() self.assertEqual(response.code, 200) from stubo.model.db import Scenario scenario_db = Scenario(db=self.db) stubs = list(scenario_db.get_stubs('localhost:cache')) self.assertEqual(len(stubs), 1) from stubo.model.stub import Stub stub = Stub(stubs[0]['stub'], 'localhost:cache') self.assertEqual(stub.contains_matchers(), ['<request>hello</request>\n']) self.assertEqual(stub.response_body()[0], u'<response>0</response>\n') from datetime import date self.assertEqual(stub.module(), {u'system_date': str(date.today()), u'recorded_system_date': str(date.today()), u'name': u'example'})
def test_put_stub(self): self.http_client.fetch( self.get_url( '/stubo/api/begin/session?scenario=xslt&session=s1&mode=record' ), self.stop) response = self.wait() self.assertEqual(response.code, 200) self.http_client.fetch( self.get_url( '/stubo/api/put/module?name=/static/cmds/tests/ext/xslt/mangler.py' ), self.stop) response = self.wait() self.assertEqual(response.code, 200) self.http_client.fetch( self.get_url('/stubo/api/put/stub?session=s1&ext_module=mangler'), callback=self.stop, method="POST", body= """||textMatcher||<request><a>ba</a><trans_id>1234</trans_id><b>ba</b><user uuid="xxx">joe</user><dt>2013-11-25</dt></request>||response||<response><a>ba</a><trans_id>1234</trans_id><b>ba</b><user uuid="xxx">joe</user><dt>2013-11-25</dt></response>""" ) response = self.wait() self.assertEqual(response.code, 200) from stubo.model.db import Scenario scenario_db = Scenario(db=self.db) stubs = list(scenario_db.get_stubs('localhost:xslt')) self.assertEqual(len(stubs), 1) from stubo.model.stub import Stub stub = Stub(stubs[0]['stub'], 'localhost:xslt') self.assertEqual( stub.contains_matchers()[0], u'<request><a>ba</a><trans_id>***</trans_id><b>ba</b><user uuid="***">***</user><dt>***</dt></request>\n' ) self.assertEqual( stub.response_body()[0], u'<response><a>ba</a><trans_id>***</trans_id><b>ba</b><user uuid="***">***</user><dt>***</dt></response>\n' ) from datetime import date self.assertEqual( stub.module(), { u'system_date': str(date.today()), u'recorded_system_date': str(date.today()), u'name': u'mangler' })
def test_put_stub(self): self.http_client.fetch( self.get_url( '/stubo/api/put/module?name=/static/cmds/tests/ext/split/splitter.py' ), self.stop) response = self.wait() self.assertEqual(response.code, 200) self.http_client.fetch( self.get_url( '/stubo/api/begin/session?scenario=split&session=split_1&mode=record' ), self.stop) response = self.wait() self.assertEqual(response.code, 200) self.http_client.fetch(self.get_url( '/stubo/api/put/stub?session=split_1&ext_module=splitter'), callback=self.stop, method="POST", body="""||textMatcher||<a> <pre>hello</pre> <id>xxx</id> <post>goodbye</post> </a>||response||Hello {{1+1}} World""") response = self.wait() self.assertEqual(response.code, 200) from stubo.model.db import Scenario scenario_db = Scenario(db=self.db) stubs = list(scenario_db.get_stubs('localhost:split')) self.assertEqual(len(stubs), 1) from stubo.model.stub import Stub stub = Stub(stubs[0]['stub'], 'localhost:split') self.assertEqual( stub.contains_matchers(), [u'<a>\n<pre>hello</pre>\n', '\n<post>goodbye</post>\n</a>']) self.assertEqual(stub.response_body()[0], u'Hello {{1+1}} World') from datetime import date self.assertEqual( stub.module(), { u'system_date': str(date.today()), u'recorded_system_date': str(date.today()), u'name': u'splitter' })
def test_put_stub(self): self.http_client.fetch( self.get_url( '/stubo/api/put/module?name=/static/cmds/tests/ext/cache/text/example.py' ), self.stop) response = self.wait() self.assertEqual(response.code, 200) self.http_client.fetch( self.get_url( '/stubo/api/begin/session?scenario=cache&session=cache_1&mode=record' ), self.stop) response = self.wait() self.assertEqual(response.code, 200) self.http_client.fetch( self.get_url( '/stubo/api/put/stub?session=cache_1&ext_module=example'), callback=self.stop, method="POST", body= """||textMatcher||<request>hello</request>||response||<response>0</response>""" ) response = self.wait() self.assertEqual(response.code, 200) from stubo.model.db import Scenario scenario_db = Scenario(db=self.db) stubs = list(scenario_db.get_stubs('localhost:cache')) self.assertEqual(len(stubs), 1) from stubo.model.stub import Stub stub = Stub(stubs[0]['stub'], 'localhost:cache') self.assertEqual(stub.contains_matchers(), ['<request>hello</request>']) self.assertEqual(stub.response_body()[0], u'<response>0</response>') from datetime import date self.assertEqual( stub.module(), { u'system_date': str(date.today()), u'recorded_system_date': str(date.today()), u'name': u'example' })
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
def create_session_cache(self, scenario_name, session_name, system_date=None): scenario_key = self.scenario_key_name(scenario_name) log.debug("create_session_cache: scenario_key={0}, session_name={1}".format( scenario_key, session_name)) session = self.get(scenario_key, session_name) if not session: # must be using a different session name for playback than record session = { 'session' : session_name, 'scenario' : scenario_key } # add to sessions map self.set_raw('{0}:sessions'.format(self.host), session_name, scenario_name) session['status'] = 'playback' session['system_date'] = system_date or datetime.date.today().strftime( '%Y-%m-%d') session['last_used'] = datetime.datetime.utcnow().strftime('%Y-%m-%d %H:%M:%S') cache_info = [] # copy mongo scenario stubs to redis cache scenario_col = Scenario() stubs_cursor = scenario_col.get_stubs(scenario_key) stubs = list(stubs_cursor) if not stubs: raise exception_response(500, title="found no stubs in mongo for {0}".format(scenario_key)) from stubo.ext.module import Module for scenario_stub in stubs: stub = Stub(scenario_stub['stub'], scenario_stub['scenario']) if stub.module(): module_name = stub.module()['name'] # tag this stub with the latest version of the module module = Module(self.host) version = module.latest_version(module_name) if not version: raise exception_response(500, title="module '{0}' not found in cache".format( module.key(module_name))) stub.module()['version'] = version response_pairs = [(compute_hash(x), x) for x in stub.response_body()] # cache each response id -> text for response in response_pairs: response_id, response_text = response self.set_response_text(scenario_name, session_name, response_id, response_text) # replace response text with response hash ids for session cache # stub.pop('response', None) stub.response().pop('body', None) stub.response()['ids'] = [x[0] for x in response_pairs] delay_policy_name = stub.delay_policy() if delay_policy_name: # Note: the delay policy is not really cached with the session. # The get/response call will just use the name to get the latest # delay value from the 'delay_policy' key in redis. delay_policy_key = '{0}:delay_policy'.format(self.host) delay_policy = self.get(delay_policy_key, delay_policy_name) if not delay_policy: log.warn('unable to find delay_policy: {0}'.format( delay_policy_name)) stub.set_delay_policy(delay_policy) #_id = ObjectId(scenario_stub['_id']) #stub['recorded'] = str(_id.generation_time.date()) cache_info.append(stub.payload) session['stubs'] = cache_info #log.debug('stubs: {0}'.format(session['stubs'])) self.set(scenario_key, session_name, session) log.debug('created session cache: {0}:{1}'.format(session['scenario'], session['session']))
def insert_stub(self, doc, stateful): """ Insert stub into DB. Performs a check whether this stub already exists in database or not. If it exists and stateful is True - new response is appended to the response list, else - reports that duplicate stub found and it will not be inserted. :param doc: Stub class with Stub that will be inserted :param stateful: <boolean> specify whether stub insertion should be stateful or not :return: <string> message with insertion status """ # getting initial values - stub matchers, scenario name matchers = doc['stub'].contains_matchers() scenario = doc['scenario'] matchers_hash = self._create_hash(matchers) # check if we have matchers - should be None for REST calls if matchers is not None: # additional helper value for indexing doc['matchers_hash'] = matchers_hash matched_stub = self.get_matched_stub(name=scenario, matchers_hash=matchers_hash) # checking if stub already exists if matched_stub: # creating stub object from found document the_stub = Stub(matched_stub['stub'], scenario) if not stateful and doc['stub'].response_body() == the_stub.response_body(): msg = 'duplicate stub found, not inserting.' log.warn(msg) return msg # since stateful is true - updating stub body by extending the list log.debug('In scenario: {0} found exact match for matchers:' ' {1}. Perform stateful update of stub.'.format(scenario, matchers)) response = the_stub.response_body() response.extend(doc['stub'].response_body()) the_stub.set_response_body(response) # updating Stub body and size, writing to database self.db.scenario_stub.update( {'_id': matched_stub['_id']}, {'$set': {'stub': the_stub.payload, 'space_used': len(unicode(the_stub.payload))}}) return 'updated with stateful response' # Stub doesn't exist in DB - preparing new object doc['stub'] = doc['stub'].payload # additional helper for aggregation framework try: doc['recorded'] = doc['stub']['recorded'] except KeyError: # during tests "recorded" value is not supplied pass # calculating stub size doc['space_used'] = len(unicode(doc['stub'])) # inserting stub into DB status = self.db.scenario_stub.insert(doc) # create indexes if matchers_hash: self._create_index(key="matchers_hash") # creating index for scenario and priority self._create_index(key="scenario") if 'priority' in doc['stub']: # creating index for priority self._create_index("stub.priority") return 'inserted scenario_stub: {0}'.format(status)
def insert_stub(self, doc, stateful): """ Insert stub into DB. Performs a check whether this stub already exists in database or not. If it exists and stateful is True - new response is appended to the response list, else - reports that duplicate stub found and it will not be inserted. :param doc: Stub class with Stub that will be inserted :param stateful: <boolean> specify whether stub insertion should be stateful or not :return: <string> message with insertion status: ignored - if not stateful and stub was already present updated - if stateful and stub was already present created - if stub was not present in database """ # getting initial values - stub matchers, scenario name matchers = doc['stub'].contains_matchers() scenario = doc['scenario'] matchers_hash = self._create_hash(matchers) # check if we have matchers - should be None for REST calls if matchers is not None: # additional helper value for indexing doc['matchers_hash'] = matchers_hash matched_stub = self.get_matched_stub(name=scenario, matchers_hash=matchers_hash) # checking if stub already exists if matched_stub: # creating stub object from found document the_stub = Stub(matched_stub['stub'], scenario) if not stateful and doc['stub'].response_body( ) == the_stub.response_body(): msg = 'duplicate stub found, not inserting.' log.warn(msg) result = { 'status': 'ignored', 'msg': msg, 'key': str(matched_stub['_id']) } return result # since stateful is true - updating stub body by extending the list log.debug('In scenario: {0} found exact match for matchers:' ' {1}. Perform stateful update of stub.'.format( scenario, matchers)) response = the_stub.response_body() response.extend(doc['stub'].response_body()) the_stub.set_response_body(response) # updating Stub body and size, writing to database self.db.scenario_stub.update({'_id': matched_stub['_id']}, { '$set': { 'stub': the_stub.payload, 'space_used': len(unicode(the_stub.payload)) } }) result = { 'status': 'updated', 'msg': 'Updated with stateful response', 'key': str(matched_stub['_id']) } return result # inserting stub into DB status = self.db.scenario_stub.insert(self.get_stub_document(doc)) result = { 'status': 'created', 'msg': 'Inserted scenario_stub', 'key': str(status) } return result
def export_stubs(handler, scenario_name): cache = Cache(get_hostname(handler.request)) scenario_name_key = cache.scenario_key_name(scenario_name) scenario = Scenario() stubs = list(scenario.get_stubs(scenario_name_key)) """ [{ u'_id': ObjectId('537c8f1cac5f7303ad704d85'), u'scenario': u'localhost:first', u'stub': { u'recorded': u'2014-05-21', u'request': { u'bodyPatterns': [ { u'contains': [ u'get my stub\n']}], u'method': u'POST'}, u'response': { u'body': u'Hello {{1+1}} World\n', u'delayPolicy': u'slow', u'status': 200}}}] """ # 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 = [] if len(stubs) > 0: for i in range(len(stubs)): entry = stubs[i] stub = Stub(entry['stub'], scenario_name_key) 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 = 'session={0}'.format(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={0}&stub_created_date={1}&stubbedSystem'\ 'Date={2}&system_date={3}'.format(module_info['name'], stub.recorded(), module_info.get('recorded_system_date'), module_info.get('system_date')) responses = stub.response_body() for ii in range(len(responses)): response = responses[ii] response = ('{0}_{1}.response.{2}'.format(session, i, ii), responses[ii]) 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)) bookmarks = cache.get_all_saved_request_index_data() if bookmarks: cmds.append('import/bookmarks?location=bookmarks') files.append(('bookmarks', json.dumps(bookmarks))) files.append(('{0}.commands'.format(scenario_name), b"\r\n".join(cmds))) static_dir = handler.settings['static_path'] scenario_dir = os.path.join(static_dir, 'exports', scenario_name_key.replace(':', '_')) if os.path.exists(scenario_dir): shutil.rmtree(scenario_dir) os.makedirs(scenario_dir) archive_name = os.path.join(scenario_dir, 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(scenario_dir, fname) with codecs.open(file_path, mode='wb', encoding='utf-8') as f: f.write(contents) 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', )]) links = get_export_links(handler, scenario_name_key, files) payload = dict(scenario=scenario_name, scenario_dir=scenario_dir, links=links) return dict(version=version, data=payload)
def create_session_cache(self, scenario_name, session_name, system_date=None): scenario_key = self.scenario_key_name(scenario_name) log.debug("create_session_cache: scenario_key={0}, session_name={1}".format( scenario_key, session_name)) session = self.get(scenario_key, session_name) if not session: # must be using a different session name for playback than record session = { 'session' : session_name, 'scenario' : scenario_key } # add to sessions map self.set_raw('{0}:sessions'.format(self.host), session_name, scenario_name) session['status'] = 'playback' session['system_date'] = system_date or datetime.date.today().strftime( '%Y-%m-%d') session['last_used'] = datetime.datetime.utcnow().strftime('%Y-%m-%d %H:%M:%S') cache_info = [] # copy mongo scenario stubs to redis cache scenario_col = Scenario() stubs_cursor = scenario_col.get_stubs(scenario_key) stubs = list(stubs_cursor) if not stubs: raise exception_response(500, title="found no stubs in mongo for {0}".format(scenario_key)) from stubo.ext.module import Module for scenario_stub in stubs: stub = Stub(scenario_stub['stub'], scenario_stub['scenario']) if stub.module(): module_name = stub.module()['name'] # tag this stub with the latest version of the module module = Module(self.host) version = module.latest_version(module_name) if not version: raise exception_response(500, title="module '{0}' not found in cache".format( module.key(module_name))) stub.module()['version'] = version response_ids = [] response_bodys = stub.response_body() # cache each response id -> response (text, status) etc for response_text in response_bodys: stub.set_response_body(response_text) response_id = response_hash(response_text, stub) self.set_response(scenario_name, session_name, response_id, stub.response()) response_ids.append(response_id) # replace response text with response hash ids for session cache stub.response().pop('body', None) stub.response()['ids'] = response_ids delay_policy_name = stub.delay_policy() if delay_policy_name: # Note: the delay policy is not really cached with the session. # The get/response call will just use the name to get the latest # delay value from the 'delay_policy' key in redis. delay_policy_key = '{0}:delay_policy'.format(self.host) delay_policy = self.get(delay_policy_key, delay_policy_name) if not delay_policy: log.warn('unable to find delay_policy: {0}'.format( delay_policy_name)) stub.set_delay_policy(delay_policy) #_id = ObjectId(scenario_stub['_id']) #stub['recorded'] = str(_id.generation_time.date()) cache_info.append(stub.payload) session['stubs'] = cache_info #log.debug('stubs: {0}'.format(session['stubs'])) self.set(scenario_key, session_name, session) log.debug('created session cache: {0}:{1}'.format(session['scenario'], session['session'])) return session