def test_TLDR_search_with_simulated_manual_input(self): """ note: without "thread.has_been_stopped()" check -> >= 3 seconds with "thread.has_been_stopped()" check at fnames level -> 0.9 seconds with "thread.has_been_stopped()" check at line level -> 0.85 seconds :return: """ test_strings = [ "open port listen", "a fi le file ile" ] for test in test_strings: start_time = time.time() fake_manual_input = "" tldr_parser_thread = None tldr_parser = TLDRParser() for c in test: fake_manual_input += c input_data = InputParser.parse_input(test, is_search_mode=True) if tldr_parser_thread: tldr_parser_thread.stop() tldr_parser_thread = TLDRParseThread(tldr_parser, input_data) tldr_parser_thread.start() time.sleep(0.05) while tldr_parser_thread.is_alive(): time.sleep(0.01) execution_time = (time.time() - start_time) logging.info("execution_time: %s -> %s seconds" % (test, execution_time)) self.assertTrue(execution_time < 3.0, msg="execution takes too long: %s sec" % execution_time)
def test_TLDR_parser(self): searcher = TLDRParser() test_strings = [ # input: [ Input object, excepted first example cmd, expected url, number of example for the specific command] # NOTE: this values may change with new TLDR version ["process ps", "ps aux", "https://manned.org/ps", 7], ["gunzip archive", "gunzip {{archive.tar.gz}}", "https://manned.org/gunzip", 3], ["list directory permission gnu", "ls -1", "https://www.gnu.org/software/coreutils/ls", 7], ["apk update", "apk update", "https://wiki.alpinelinux.org/wiki/Alpine_Linux_package_management", 6] ] for test in test_strings: logging.debug("input test: %s" % test) input_array = test[0].split(" ") input_data = InputData(False, test[0], input_array) results = searcher.find_match_command(input_data) self.assertTrue(len(results) > 0, msg="no results, check if the 'pages' folder exist") first_result = results[0] parsed_tldr_example = searcher.get_tldr_cmd_examples(first_result) example_count = 0 for row in parsed_tldr_example.get_rows(): if row[ParsedTLDRExample.INDEX_EXAMPLE_TYPE] == ParsedTLDRExample.Type.EXAMPLE: example_count += 1 if example_count == 0: self.assertEqual(test[1], row[ParsedTLDRExample.INDEX_EXAMPLE_VALUE], msg="wrong command found: %s -> %s" % (test, row)) # this should get the same result as the previous assert self.assertTrue(example_count, parsed_tldr_example.get_first_example_index()) self.assertEqual(test[1], parsed_tldr_example.get_current_selected_example(row_index=example_count), msg="wrong command found: %s -> %s" % (test, row)) # there are 2 rows until the next example self.assertEqual(2, parsed_tldr_example.get_delta_next_example_index(example_count)) # because this is the first, the delta is 0 self.assertEqual(0, parsed_tldr_example.get_delta_previous_example_index(example_count)) if test[2]: self.assertTrue(parsed_tldr_example.has_url_more_info(), msg="no url found: %s" % test) self.assertEqual(test[2], parsed_tldr_example.get_url_more_info(), msg="wrong url: %s" % test) self.assertLessEqual(test[3], example_count, msg="wrong number of command found: %s" % test)
def test_TLDR_search_time(self): """ the first call load read from disk (excepted time ~0,08) the second and third use the cached memory (expected time ~0,01) # :return: """ searcher = TLDRParser() test_strings = [ # input, excepted cmd, max index of expected cmd ["", 0.5], # disk ["randomstringwithnomatch", 0.05], # memory ["open port listen", 0.05], # memory ] for test in test_strings: input_array = test[0].split(" ") input_data = InputData(False, test[0], input_array) start_time = time.time() results = searcher.find_match_command(input_data) execution_time = (time.time() - start_time) logging.info("execution_time: %s seconds" % execution_time) self.assertTrue(execution_time < 0.5, msg="execution takes too long: %s sec" % execution_time)
def test_TLDR_empty_input(self): searcher = TLDRParser() empty_input = InputData(False, "", []) results = searcher.find_match_command(empty_input) count_results = len(results) self.assertTrue(count_results > 100, msg="results are less then 100: %s" % count_results)
def test_TLDR_search(self): """ get the meaning ('name' field) from the man page input [<array_search_words>,<expected_command_result>,<worst_expected_command_result_index>] :return: """ searcher = TLDRParser() #test_strings = [["list file permission", "ls", 4]] test_strings = [ # input, excepted cmd, max index of expected cmd ["randomstringwithnomatch", "", 0], ["list file permission", "ls", 2], ["process", "ps", 2], ["process list", "ps", 2], ["merge pdf page", "pdftk", 4], ["locate program", "which", 1], ["git diff", "git-diff", 2], ["hex", "hexdump", 3], ["srm", "srm", 1], ["open port listen", "netstat", 2], ["time boot", "uptime", 1], ["time boot", "systemd-analyze", 4], ["tar", "tar", 1], # tar is also a substring of many other cmds ["extract file gz", "tar", 2], # "e[x]tract" string special case ["bios info", "dmidecode", 1], ["dns reverse", "drill", 2], ["open default", "xdg-open", 1], ["download file", "wget", 1], ["download file", "curl", 6], ["post request", "curl", 6], ["download package", "apt-get", 2], ["keyboard layout", "setxkbmap", 1], # single result # security ["extract from binary", "binwalk", 1], ["secure disk overwrite", "sfill", 1], ["scan network", "arp-scan", 1], ["scan network", "nmap", 5], ["scan port script", "nmap", 5], ] total_index_result = 0 for test in test_strings: input_array = test[0].split(" ") input_data = InputData(False, test[0], input_array) logging.debug("#input: %s" % test) results = searcher.find_match_command(input_data) # check if the expected cmd is within the first x results found = False i = 0 for i in range(len(results)): item = results[i] logging.debug("%s" % results[i]) if item[TLDRParser.INDEX_TLDR_MATCH_CMD].endswith(test[1]): found = True break total_index_result += i if test[2] > 0: self.assertTrue(len(results) > 0, msg="no results, check if the 'pages' folder exist") self.assertTrue(found, msg="expected cmd is not in the results: %s" % test) self.assertTrue(i <= test[2], msg="the cmd index is %s, expected: %s" % (i, test)) else: self.assertTrue(len(results) == 0, msg="no result expected, more than one or more found instead") # this is use to mesure how well the function behave avg_index_result = total_index_result / len(test_strings) logging.debug("total index result: %s " % total_index_result) logging.debug("avg index result: %s " % avg_index_result) self.assertTrue(avg_index_result <= 5, msg="the overall behavior of the function is not good enough")
def test_format_tldr_pages(self): searcher = TLDRParser() self.assertRegex(searcher.format_tldr_pages(), "\d pages have been correctly formatted", msg="something wrong with TLDR pages, maybe the format has changed with a TLDR update")
def run_loop_tldr(self, cached_in_memory_pages): """ :return: """ tldr_parser = TLDRParser(cached_in_memory_pages) tldr_parser_thread = None input_data = InputData(False, "", []) tldr_options_reload_needed = True tldr_options_waiting = True tldr_examples_reload_needed = True tldr_ui_reload = True msg_to_show = None page_tldr_search = PageSelectTLDR(self.drawer) while True: # TODO fix "alt+d" crash if tldr_options_reload_needed: tldr_options_reload_needed = False input_data = InputParser.parse_input( self.search_field.get_text_lower(), is_search_mode=True) if tldr_parser_thread: tldr_parser_thread.stop() tldr_parser_thread = TLDRParseThread(tldr_parser, input_data) tldr_parser_thread.start() tldr_options_waiting = True if tldr_options_waiting and not tldr_parser_thread.is_alive(): tldr_options_waiting = False self.tldr_options = tldr_parser_thread.get_result_tldr_options( ) self.update_tldr_options_to_draw() tldr_examples_reload_needed = True tldr_ui_reload = True if tldr_examples_reload_needed: tldr_examples_reload_needed = False if len(self.tldr_options_draw) > 0: tldr_page_match = self.tldr_options_draw[ self.tldr_options_draw_index] self.tldr_examples = tldr_parser.get_tldr_cmd_examples( tldr_page_match) self.update_tldr_example_to_draw() self.update_tldr_options_to_draw_cmd_availability() # reset example index self.tldr_examples_index = self.tldr_examples.get_first_example_index( ) self.tldr_examples_draw_index = self.tldr_examples_index else: self.tldr_examples = ParsedTLDRExample() self.tldr_examples_index = 0 self.tldr_examples_draw = [] if page_tldr_search.has_minimum_size(): page_tldr_search.draw_page( search_filters=self.search_field, input_data=input_data, tldr_options_draw=self.tldr_options_draw, tldr_options_draw_index=self.tldr_options_draw_index, tldr_examples_draw=self.tldr_examples_draw, example_draw_index=self.tldr_examples_draw_index, example_content_shift=self.example_content_shift, focus_area=self.focus, has_url_more_info=self.tldr_examples.has_url_more_info(), is_waiting=tldr_options_waiting, msg_to_show=msg_to_show) if msg_to_show: msg_to_show = None # wait for char c = self.drawer.wait_next_char( multi_threading_mode=tldr_parser_thread.is_alive()) logging.debug("pressed key: %s" % repr(c)) tldr_ui_reload = True if c == Keys.KEY_TIMEOUT: tldr_ui_reload = False continue elif c in Keys.KEYS_ENTER: selected_example = self.get_selected_example( search_input=input_data) if selected_example: return [True, [True, selected_example]] elif c == Keys.KEY_CTRL_SPACE: example_to_copy = self.get_selected_example( search_input=input_data, copied=True) if example_to_copy: msg_to_show = ConsoleUtils.copy_to_clipboard( example_to_copy, show_data_in_msg=False)[1] elif c == Keys.KEY_CTRL_L: if self.tldr_examples.has_url_more_info(): msg_to_show = ConsoleUtils.copy_to_clipboard( self.tldr_examples.get_url_more_info())[1] elif c == Keys.KEY_CTRL_E: res = ConsoleUtils.copy_to_clipboard( self.tldr_examples.get_tldr_github_page()) msg_to_show = res[1] elif c == Keys.KEY_TAB: self.flip_focus() # go back to main page elif c == Keys.KEY_CTRL_F or c == Keys.KEY_CTRL_D or c == Keys.KEY_ESC: return [False, 0] elif c == Keys.KEY_UP: if self.move_up(): tldr_examples_reload_needed = True elif c == Keys.KEY_DOWN: if self.move_down(): tldr_examples_reload_needed = True # -> command elif c == Keys.KEY_RIGHT: self.move_right() # <- command elif c == Keys.KEY_LEFT: self.move_left() # this occurs when the console size changes elif c == Keys.KEY_RESIZE: self.drawer.reset() self.search_field.set_max_x(self.drawer.get_max_x(), with_margin_x=True) self.update_tldr_options_to_draw() # move cursor to the beginning elif c == Keys.KEY_START or c == Keys.KEY_CTRL_A: self.search_field.move_cursor_to_start() self.example_content_shift.reset_context_shifted() self.focus = PageSelectTLDR.Focus.AREA_FILES # move cursor to the end elif c == Keys.KEY_CTRL_E: self.search_field.move_cursor_to_end() self.example_content_shift.reset_context_shifted() self.focus = PageSelectTLDR.Focus.AREA_FILES elif c == Keys.KEY_CTRL_U: if self.search_field.set_text(""): tldr_options_reload_needed = True # delete a char of the search elif c in Keys.KEYS_DELETE: if self.delete_char(): tldr_options_reload_needed = True # normal search char elif type(c) is str: if self.add_str(c): tldr_options_reload_needed = True else: logging.error("input not handled: %s" % repr(c))