def test_sqlite_1(self, mock_spath, mock_path, mock_sys): mock_path.return_value = os.path.join(os.path.dirname(__file__), 'configs') mock_spath.return_value = os.path.join(os.path.dirname(__file__), 'configs') js = JsnapSqlite("10.216.193.114", self.db) js.insert_data(self.db_dict2) def fun(): raise BaseException with patch('logging.Logger.error') as mock_log: extr = SqliteExtractXml(self.db) data, formt = extr.get_xml_using_snapname( "10.216.193.114", self.db_dict2['cli_command'], self.db_dict2['snap_name']) self.assertEqual(data, "mock_data") self.assertEqual(formt, "text") try: data, format = extr.get_xml_using_snapname( "10.216.193.114", self.db_dict2['cli_command'], "mock_ssssnap") except BaseException: err = [ "No previous snapshots exists with name = mock_ssssnap for command = show version" ] c_list = mock_log.call_args_list[0] self.assertNotEqual(c_list[0][0].find(err[0]), -1)
def test_sqlite_extractxml_db_absent(self, mock_isfile, mock_path): mock_path.return_value = os.path.join(os.path.dirname(__file__), 'configs') mock_isfile.return_value = False with patch('sys.exit') as mock_exit: extr = SqliteExtractXml(self.db) mock_exit.assert_called_with(1)
def test_sqlite_2(self, mock_spath, mock_path, mock_sys): mock_path.return_value = os.path.join(os.path.dirname(__file__), 'configs') mock_spath.return_value = os.path.join(os.path.dirname(__file__), 'configs') def fun(): raise BaseException mock_sys.return_value = fun js = JsnapSqlite("1.1.1.1", self.db) js.insert_data(self.db_dict2) with patch('logging.Logger.error') as mock_log: extr = SqliteExtractXml(self.db) extr.get_xml_using_snapname( "10.216.193.11", self.db_dict2['cli_command'], self.db_dict2['snap_name']) err = "ERROR!! Complete message is no such table: table_10__216__193__11" c_list = mock_log.call_args_list[0] self.assertNotEqual(c_list[0][0].find(err), -1)
def test_sqlite_3(self, mock_spath, mock_path, mock_sys): mock_path.return_value = os.path.join(os.path.dirname(__file__), 'configs') mock_spath.return_value = os.path.join(os.path.dirname(__file__), 'configs') js = JsnapSqlite("1.1.1.1", self.db) js.insert_data(self.db_dict2) with patch('logging.Logger.error') as mock_log: extr = SqliteExtractXml(self.db) data, formt = extr.get_xml_using_snap_id( "1.1.1.1", self.db_dict2['cli_command'], 0) self.assertEqual(data, "mock_data") self.assertEqual(formt, "text") extr.get_xml_using_snap_id("1.1.1.1", "show vers", 0) err = [ "ERROR!! Complete message is: 'NoneType' object is not iterable"] c_list = mock_log.call_args_list[0] self.assertNotEqual(c_list[0][0].find(err[0]), -1)
def test_sqlite_2(self, mock_spath, mock_path, mock_sys): mock_path.return_value = os.path.join(os.path.dirname(__file__), 'configs') mock_spath.return_value = os.path.join(os.path.dirname(__file__), 'configs') def fun(): raise BaseException mock_sys.return_value = fun js = JsnapSqlite("1.1.1.1", self.db) js.insert_data(self.db_dict2) with patch('logging.Logger.error') as mock_log: extr = SqliteExtractXml(self.db) extr.get_xml_using_snapname( "10.216.193.11", self.db_dict2['cli_command'], self.db_dict2['snap_name']) err = "ERROR!! Complete message is no such table: table_10__216__193__11" c_list = mock_log.call_args_list[0] self.assertNotEqual(c_list[0][0].find(err), -1)
def test_sqlite_3(self, mock_spath, mock_path, mock_sys): mock_path.return_value = os.path.join(os.path.dirname(__file__), 'configs') mock_spath.return_value = os.path.join(os.path.dirname(__file__), 'configs') js = JsnapSqlite("1.1.1.1", self.db) js.insert_data(self.db_dict2) with patch('logging.Logger.error') as mock_log: extr = SqliteExtractXml(self.db) data, formt = extr.get_xml_using_snap_id( "1.1.1.1", self.db_dict2['cli_command'], 0) self.assertEqual(data, "mock_data") self.assertEqual(formt, "text") extr.get_xml_using_snap_id("1.1.1.1", "show vers", 0) if sys.version_info[0] == 2 or (sys.version_info[0] == 3 and sys.version_info[1] <= 6): err = ["ERROR!! Complete message is: 'NoneType' object is not iterable"] else : err = ["ERROR!! Complete message is: cannot unpack non-iterable NoneType object"] c_list = mock_log.call_args_list[0] self.assertNotEqual(c_list[0][0].find(err[0]), -1)
def test_sqlite_1(self, mock_spath, mock_path, mock_sys): mock_path.return_value = os.path.join(os.path.dirname(__file__), 'configs') mock_spath.return_value = os.path.join(os.path.dirname(__file__), 'configs') js = JsnapSqlite("1.1.1.1", self.db) js.insert_data(self.db_dict2) def fun(): raise BaseException with patch('logging.Logger.error') as mock_log: extr = SqliteExtractXml(self.db) data, formt = extr.get_xml_using_snapname( "1.1.1.1", self.db_dict2['cli_command'], self.db_dict2['snap_name']) self.assertEqual(data, "mock_data") self.assertEqual(formt, "text") try: data, format= extr.get_xml_using_snapname( "1.1.1.1", self.db_dict2['cli_command'], "mock_ssssnap") except BaseException: err = [ "No previous snapshots exists with name = mock_ssssnap for command = show version"] c_list = mock_log.call_args_list[0] self.assertNotEqual(c_list[0][0].find(err[0]), -1)
def generate_test_files(self, main_file, device, check, diff, db, snap_del, pre=None, action=None, post=None): """ generate names of snap files from hostname and out files given by user, tests are performed on values stored in these snap files, in which test is to be performed :param main_file: main config file, to extract test files user wants to run :param device: device name :param check: variable to check if --check option is given or not :param diff: variable to check if --diff option is given or not :param db: database object :param snap_del: if --snapcheck operator is used without any test file name it will create temprory file and then will delete it at the end :param pre: file name of pre snapshot :param post: file name of post snapshot :param action: given by module version, either snap, snapcheck or check :return: object of operator.Operator containing test details """ op = Operator() op.device = device tests_files = [] self.log_detail['hostname'] = device # pre_user and post_user are the names of the snapshot files # that the user wants to keep and store the snapfiles # with these names pre_user = pre post_user = post # get the test files from config.yml if main_file.get('tests') is None: self.logger_check.error( colorama.Fore.RED + "\nERROR!! No test file found, Please mention test files !!", extra=self.log_detail) else: # extract test files, first search in path given in jsnapy.cfg for tfile in main_file.get('tests'): if not os.path.isfile(tfile): tfile = os.path.join( expanduser(get_path('DEFAULT', 'test_file_path')), tfile) if os.path.isfile(tfile): test_file = open(tfile, 'r') tests_files.append( yaml.load(test_file, Loader=yaml.FullLoader)) else: self.logger_check.error( colorama.Fore.RED + "ERROR!! File %s not found for testing" % tfile, extra=self.log_detail) # check what all test cases need to be included, if nothing given # then include all test cases #### for tests in tests_files: tests_included = [] if 'tests_include' in tests: tests_included = tests.get('tests_include') else: for t in tests: tests_included.append(t) message = self._print_testmssg("Device: " + device, "*") self.logger_check.info(colorama.Fore.BLUE + message, extra=self.log_detail) for val in tests_included: self.logger_check.info("Tests Included: %s " % (val), extra=self.log_detail) # This is Where we are going to print the description mentioned by the user for the testcase # Enumerate generate a tuple of index and corresponding element in the list # index[0] is index and index[1] is the dictionary in which it will search. description_index = [ index[0] for index in enumerate(tests[val]) if 'description' in index[1] ] if len(description_index) > 0: description_index = description_index[0] description = tests[val][description_index][ 'description'] if description is not None: self.logger_check.info("Description: %s " % (description), extra=self.log_detail) try: if any('command' in d for d in tests[val]): index = next((i for i, x in enumerate(tests[val]) if 'command' in x), 0) command = tests[val][index].get('command').split( '|')[0].strip() reply_format = tests[val][0].get('format', 'xml') message = self._print_testmssg( "Command: " + command, "*") self.logger_check.info(colorama.Fore.BLUE + message, extra=self.log_detail) name = '_'.join(command.split()) teston = command # this is necessary for the pre and post to be the same that user specified # In a case when there are multiple rpc's with kwargs and a rpc with no kwargs pre = pre_user post = post_user else: index = next((i for i, x in enumerate(tests[val]) if 'rpc' in x), 0) index_kwargs = next( (i for i, x in enumerate(tests[val]) if 'kwargs' in x or 'args' in x), 1) rpc = tests[val][index]['rpc'] reply_format = tests[val][index].get( 'format', 'xml') self.logger_check.info(colorama.Fore.BLUE + (25) * "*" + "RPC is " + rpc + (25) * '*', extra=self.log_detail) name = rpc teston = rpc # this is necessary for the pre and post to be the same that user specified # In a case when there are multiple rpc's with kwargs and a rpc with no kwargs pre = pre_user post = post_user # here the user specified name is being used and the hash value generated for # kwargs part is appended to the name if 'kwargs' in tests[val][index_kwargs] and tests[ val][index_kwargs].get('kwargs') is None: del tests[val][index_kwargs]['kwargs'] if 'args' in tests[val][index_kwargs] and tests[ val][index_kwargs].get('args') is None: del tests[val][index_kwargs]['args'] if 'kwargs' in tests[val][ index_kwargs] or 'args' in tests[val][ index_kwargs]: if tests[val][index_kwargs].get('kwargs'): data = tests[val][index_kwargs].get( 'kwargs') elif tests[val][index_kwargs].get('args'): data = tests[val][index_kwargs].get('args') hash_kwargs = hashlib.md5( json.dumps(data, sort_keys=True).encode( 'utf-8')).digest() hash_kwargs = base64.urlsafe_b64encode( hash_kwargs).strip() if action == 'check' and pre_user is not None and post_user is not None: pre = pre_user + '_' + hash_kwargs.decode( 'utf-8') post = post_user + '_' + hash_kwargs.decode( 'utf-8') elif action == 'snapcheck' and pre_user is not None and post_user is None: pre = pre_user + '_' + hash_kwargs.decode( 'utf-8') elif diff is True and pre_user is not None and post_user is not None: pre = pre_user + '_' + hash_kwargs.decode( 'utf-8') post = post_user + '_' + hash_kwargs.decode( 'utf-8') except KeyError: self.logger_check.error( colorama.Fore.RED + "ERROR occurred, test keys 'command' or 'rpc' not defined properly", extra=self.log_detail) except Exception as ex: self.logger_check.error(colorama.Fore.RED + "ERROR Occurred: %s" % str(ex), extra=self.log_detail) else: # extract snap files, if check from sqlite is true t if db.get('check_from_sqlite') is True and ( check is True or diff is True or action in ["check", "diff"]): a = SqliteExtractXml(db.get('db_name')) # while checking from database, preference is given # to id and then snap name if (db['first_snap_id'] is not None) and (db['second_snap_id'] is not None): snapfile1, data_format1 = a.get_xml_using_snap_id( str(device), name, db['first_snap_id']) snapfile2, data_format2 = a.get_xml_using_snap_id( str(device), name, db['second_snap_id']) else: snapfile1, data_format1 = a.get_xml_using_snapname( str(device), name, pre) snapfile2, data_format2 = a.get_xml_using_snapname( str(device), name, post) if reply_format != data_format1 or reply_format != data_format2: self.logger_check.error( colorama.Fore.RED + "ERROR!! Data stored in database is not in %s format." % reply_format, extra=self.log_detail) pass # sys.exit(1) ###### taking snapshot for --snapcheck operation #### elif db.get('check_from_sqlite') is True: a = SqliteExtractXml(db.get('db_name')) snapfile1, data_format1 = a.get_xml_using_snapname( str(device), name, pre) if reply_format != data_format1: self.logger_check.error( colorama.Fore.RED + "ERROR!! Data stored in database is not in %s format." % reply_format, extra=self.log_detail) pass # sys.exit(1) else: snapfile1 = self.generate_snap_file( device, pre, name, reply_format) # if check is true then call function to compare two # snapshots #### if (check is True or action == "check") and reply_format == 'xml': if db.get('check_from_sqlite') is False: snapfile2 = self.generate_snap_file( device, post, name, reply_format) self.compare_reply(op, tests[val], val, teston, check, db, snapfile1, snapfile2, action) # if --diff is true then call compare_diff to compare # two snapshots word by word #### elif (diff is True): if db.get('check_from_sqlite') is False: snapfile2 = self.generate_snap_file( device, post, name, reply_format) self.compare_diff(snapfile1, snapfile2, db.get('check_from_sqlite')) # else call --snapcheck test operation, it works only # for xml reply format #### elif (reply_format == 'xml'): self.compare_reply(op, tests[val], val, teston, check, db, snapfile1, action) ######## bug here ############ # multiple testcases for single command and same device, its deleting that file #################### """ if snap_del is True: snapfile1 = snapfile1 if os.path.isfile(snapfile1) else self.generate_snap_file(device, pre, name, reply_format) os.remove(snapfile1) """ else: # give error message if snapshot in text format is # used with operations other than --diff #### self.logger_check.error( colorama.Fore.RED + "ERROR!! for checking snapshots in text format use '--diff' option ", extra=self.log_detail) # print final result, if operation is --diff then message gets # printed compare_diff function only #### if (diff is not True): op.final_result(self.log_detail) return op
def generate_test_files( self, main_file, device, check, diff, db, snap_del, pre=None, action=None, post=None): """ generate names of snap files from hostname and out files given by user, tests are performed on values stored in these snap files, in which test is to be performed :param main_file: main config file, to extract test files user wants to run :param device: device name :param check: variable to check if --check option is given or not :param diff: variable to check if --diff option is given or not :param db: database object :param snap_del: if --snapcheck operator is used without any test file name it will create temprory file and then will delete it at the end :param pre: file name of pre snapshot :param post: file name of post snapshot :param action: given by module version, either snap, snapcheck or check :return: object of testop.Operator containing test details """ op = Operator() op.device = device tests_files = [] self.log_detail['hostname'] = device # get the test files from config.yml if main_file.get('tests') is None: self.logger_check.error( colorama.Fore.RED + "\nERROR!! No test file found, Please mention test files !!", extra=self.log_detail) else: # extract test files, first search in path given in jsnapy.cfg for tfile in main_file.get('tests'): if not os.path.isfile(tfile): tfile = os.path.join( get_path( 'DEFAULT', 'test_file_path'), tfile) if os.path.isfile(tfile): test_file = open(tfile, 'r') tests_files.append(yaml.load(test_file)) else: self.logger_check.error( colorama.Fore.RED + "ERROR!! File %s not found for testing" % tfile, extra=self.log_detail) # check what all test cases need to be included, if nothing given # then include all test cases #### for tests in tests_files: tests_included = [] if 'tests_include' in tests: tests_included = tests.get('tests_include') else: for t in tests: tests_included.append(t) message= self._print_testmssg("Device: "+device, "*") self.logger_check.info(colorama.Fore.BLUE + message, extra=self.log_detail) for val in tests_included: self.logger_check.info( "Tests Included: %s " % (val), extra=self.log_detail) try: if tests[val][0].keys()[0] == 'command': command = tests[val][0].get('command').split('|')[0].strip() reply_format = tests[val][0].get('format', 'xml') message = self._print_testmssg("Command: "+command, "*") self.logger_check.info( colorama.Fore.BLUE + message, extra=self.log_detail) name = '_'.join(command.split()) teston = command else: rpc = tests[val][0]['rpc'] reply_format = tests[val][0].get('format', 'xml') self.logger_check.info(colorama.Fore.BLUE + (25) * "*" + "RPC is " + rpc + (25) * '*', extra=self.log_detail) name = rpc teston = rpc except KeyError: self.logger_check.error( colorama.Fore.RED + "ERROR occurred, test keys 'command' or 'rpc' not defined properly", extra=self.log_detail) except Exception as ex: self.logger_check.error( colorama.Fore.RED + "ERROR Occurred: %s" % str(ex), extra=self.log_detail) else: # extract snap files, if check from sqlite is true t if db.get( 'check_from_sqlite') is True and (check is True or diff is True or action in ["check", "diff"]): a = SqliteExtractXml(db.get('db_name')) # while checking from database, preference is given # to id and then snap name if (db['first_snap_id'] is not None) and ( db['second_snap_id'] is not None): snapfile1, data_format1 = a.get_xml_using_snap_id( str(device), name, db['first_snap_id']) snapfile2, data_format2 = a.get_xml_using_snap_id( str(device), name, db['second_snap_id']) else: snapfile1, data_format1 = a.get_xml_using_snapname( str(device), name, pre) snapfile2, data_format2 = a.get_xml_using_snapname( str(device), name, post) if reply_format != data_format1 or reply_format != data_format2: self.logger_check.error(colorama.Fore.RED + "ERROR!! Data stored in database is not in %s format." % reply_format, extra=self.log_detail) pass # sys.exit(1) ###### taking snapshot for --snapcheck operation #### elif db.get('check_from_sqlite') is True: a = SqliteExtractXml(db.get('db_name')) snapfile1, data_format1 = a.get_xml_using_snapname( str(device), name, pre) if reply_format != data_format1: self.logger_check.error( colorama.Fore.RED + "ERROR!! Data stored in database is not in %s format." % reply_format, extra=self.log_detail) pass # sys.exit(1) else: snapfile1 = self.generate_snap_file( device, pre, name, reply_format) # if check is true then call function to compare two # snapshots #### if (check is True or action is "check") and reply_format == 'xml': if db.get('check_from_sqlite') is False: snapfile2 = self.generate_snap_file( device, post, name, reply_format) self.compare_reply( op, tests[val], teston, check, db, snapfile1, snapfile2, action) # if --diff is true then call compare_diff to compare # two snapshots word by word #### elif(diff is True): if db.get('check_from_sqlite') is False: snapfile2 = self.generate_snap_file( device, post, name, reply_format) self.compare_diff( snapfile1, snapfile2, db.get('check_from_sqlite')) # else call --snapcheck test operation, it works only # for xml reply format #### elif (reply_format == 'xml'): self.compare_reply( op, tests[val], teston, check, db, snapfile1, action) ######## bug here ############ # multiple testcases for single command and same device, its deleting that file #################### """ if snap_del is True: snapfile1 = snapfile1 if os.path.isfile(snapfile1) else self.generate_snap_file(device, pre, name, reply_format) os.remove(snapfile1) """ else: # give error message if snapshot in text format is # used with operations other than --diff #### self.logger_check.error( colorama.Fore.RED + "ERROR!! for checking snapshots in text format use '--diff' option ", extra=self.log_detail) # print final result, if operation is --diff then message gets # printed compare_diff function only #### if (diff is not True): op.final_result(self.log_detail) return op