import io from contextlib import redirect_stdout from pathlib import Path import tempfile from unittest import TestCase from sohstationviewer.view.util.functions import ( get_soh_messages_for_view, log_str, is_doc_file, create_search_results_file, create_table_of_content_file, check_chan_wildcards_format, check_masspos ) from sohstationviewer.view.util.enums import LogType from sohstationviewer.conf import constants as const from sohstationviewer.conf.constants import (WF_1ST, WF_2ND, WF_3RD) class TestGetSOHMessageForView(TestCase): def test_no_or_empty_textlog(self): soh_msg_channels = {"ACE": ["test1\ntest2", "test3"], "LOG": ["test4"]} soh_msg_for_view = {'ACE': ['test1', 'test2', 'test3'], 'LOG': ['test4']} with self.subTest('test_no_TEXT_str_dataset_key'): soh_messages = {"key1": soh_msg_channels} ret = get_soh_messages_for_view("key1", soh_messages) self.assertNotIn('TEXT', list(ret.keys())) self.assertEqual(ret, soh_msg_for_view) with self.subTest('test_empty_TEXT_tupple_dataset_key'): soh_messages = {"TEXT": [], ("key1", "key2"): soh_msg_channels} ret = get_soh_messages_for_view(("key1", "key2"), soh_messages) self.assertNotIn('TEXT', list(ret.keys())) self.assertEqual(ret, soh_msg_for_view) # no key "TEXT", dataset has no channels with self.subTest('test_no_TEXT_no_SOH_channels_for_dataset'): soh_messages = {"key1": {}} ret = get_soh_messages_for_view("key1", soh_messages) self.assertEqual(ret, {}) def test_some_empty_soh_message(self): soh_messages = {"TEXT": ['text1', 'text2\ntext3'], "key1": {"ACE": ["test1\ntest2", "test3"], "LOG": []}} # channel LOG is empty ret = get_soh_messages_for_view("key1", soh_messages) self.assertEqual(ret, {'TEXT': ['text1', 'text2', 'text3'], 'ACE': ['test1', 'test2', 'test3'], 'LOG': []}) class TestLogStr(TestCase): def test_log_str(self): log = ('info line 1', LogType.INFO) ret = log_str(log) self.assertEqual(ret, 'INFO: info line 1') class TestIsDocFile(TestCase): @classmethod def setUpClass(cls) -> None: cls.temp_dir = tempfile.TemporaryDirectory() def _run_is_doc_file(self, filename, include_table_of_contents=False): test_file = Path(self.temp_dir.name).joinpath(filename) with open(test_file, 'w'): pass return is_doc_file( test_file, include_table_of_contents=include_table_of_contents) def test_not_md_file(self): self.assertFalse(self._run_is_doc_file("doc.md")) def test_table_of_contents_file(self): self.assertFalse(self._run_is_doc_file( "./" + const.TABLE_CONTENTS, include_table_of_contents=False)) self.assertTrue(self._run_is_doc_file( "./" + const.TABLE_CONTENTS, include_table_of_contents=True)) def test_doc_file(self): self.assertTrue(self._run_is_doc_file('doc.help.md')) class TestCreateSearchResultFile(TestCase): @classmethod def setUpClass(cls) -> None: cls.temp_dir = tempfile.TemporaryDirectory() cls.temp_dir_path = Path(cls.temp_dir.name) with open(cls.temp_dir_path.joinpath('file1.help.md'), 'w') as file1: file1.write('exist1') with open(cls.temp_dir_path.joinpath( '01 _ file2.help.md'), 'w') as file2: file2.write('exist2') with open(cls.temp_dir_path.joinpath('file3.md'), 'w') as file3: file3.write('exist') with open(cls.temp_dir_path.joinpath(const.SEARCH_RESULTS), 'w'): pass with open(cls.temp_dir_path.joinpath(const.TABLE_CONTENTS), 'w'): pass def test_search_text_in_no_files(self): search_result_filename = create_search_results_file( self.temp_dir_path, 'non_exist') self.assertEqual(search_result_filename.name, const.SEARCH_RESULTS) with open(search_result_filename, 'r') as file: content = file.read() self.assertEqual( content, "# Search results\n\nText 'non_exist' not found.") def test_search_text_in_one_file(self): search_result_filename = create_search_results_file( self.temp_dir_path, 'exist1') self.assertEqual(search_result_filename.name, const.SEARCH_RESULTS) with open(search_result_filename, 'r') as file: content = file.read() self.assertEqual( content, "# Search results\n\n" "Text 'exist1' found in the following files:\n\n" "---------------------------\n\n" "+ [file1](file1.help.md)\n\n") def test_search_text_in_all_files(self): search_result_filename = create_search_results_file( self.temp_dir_path, 'exist') self.assertEqual(search_result_filename.name, const.SEARCH_RESULTS) with open(search_result_filename, 'r') as file: content = file.read() self.assertEqual( content, "# Search results\n\n" "Text 'exist' found in the following files:\n\n" "---------------------------\n\n" "+ [file2](01%20_%20file2.help.md)\n\n" "+ [file1](file1.help.md)\n\n") def test_empty_search_text(self): # This case is excluded in help_view search_result_filename = create_search_results_file( self.temp_dir_path, '') self.assertEqual(search_result_filename.name, const.SEARCH_RESULTS) with open(search_result_filename, 'r') as file: content = file.read() self.assertEqual( content, "# Search results\n\n" "Text '' found in the following files:\n\n" "---------------------------\n\n" "+ [file2](01%20_%20file2.help.md)\n\n" "+ [file1](file1.help.md)\n\n") def test_no_search_result_file_exist(self): search_result_file_path = self.temp_dir_path.joinpath( const.SEARCH_RESULTS) search_result_file_path.unlink() # remove file search_result_filename = create_search_results_file( self.temp_dir_path, 'exist2') self.assertEqual(search_result_filename.name, const.SEARCH_RESULTS) with open(search_result_filename, 'r') as file: content = file.read() self.assertEqual( content, "# Search results\n\n" "Text 'exist2' found in the following files:\n\n" "---------------------------\n\n" "+ [file2](01%20_%20file2.help.md)\n\n") class TestCreateTableOfContentFile(TestCase): @classmethod def setUpClass(cls) -> None: cls.temp_dir = tempfile.TemporaryDirectory() cls.temp_dir_path = Path(cls.temp_dir.name) with open(cls.temp_dir_path.joinpath('file1.help.md'), 'w') as file1: file1.write('exist1') with open(cls.temp_dir_path.joinpath( '01 _ file2.help.md'), 'w') as file2: file2.write('exist2') with open(cls.temp_dir_path.joinpath('file3.md'), 'w') as file3: file3.write('exist') with open(cls.temp_dir_path.joinpath(const.SEARCH_RESULTS), 'w'): pass with open(cls.temp_dir_path.joinpath(const.TABLE_CONTENTS), 'w'): pass def test_create_table_of_contents_file(self): table_contents_path = self.temp_dir_path.joinpath(const.TABLE_CONTENTS) f = io.StringIO() with redirect_stdout(f): create_table_of_content_file(self.temp_dir_path) output = f.getvalue() self.assertEqual( f"{table_contents_path.as_posix()} has been created.", output.strip()) self.assertIn(table_contents_path, list(self.temp_dir_path.iterdir())) with open(table_contents_path, 'r') as file: content = file.read() self.assertTrue(content.endswith( "# Table of Contents\n\n" "+ [Table of Contents](01%20_%20Table%20of%20Contents.help.md)" "\n\n" "+ [file2](01%20_%20file2.help.md)\n\n" "+ [file1](file1.help.md)\n\n", ) ) class TestCheckChanWildcardsFormat(TestCase): def test_len1(self): with self.subTest("Wildcard is *"): wc = '*' try: check_chan_wildcards_format(wc) except Exception: self.fail(f"Wildcard '{wc}' raise Exception unexpectedly") with self.subTest("Wildcard isn't *"): wc = 'L' with self.assertRaises(Exception) as context: check_chan_wildcards_format(wc) self.assertEqual( str(context.exception), f"Request '{wc}' has length=1 which must be '*'." ) def test_len2(self): with self.subTest("Wildcard with first char matched"): wc = 'L*' try: check_chan_wildcards_format(wc) except Exception: self.fail(f"Wildcard '{wc}' raise Exception unexpectedly") with self.subTest("Wildcard with first char not matched"): wc = 'W*' pattern = f"[{WF_1ST}*]" with self.assertRaises(Exception) as context: check_chan_wildcards_format(wc) self.assertEqual( str(context.exception), f"Request '{wc}' has first character not match {pattern}." ) with self.subTest("Wildcard with last char matched"): wc = '*N' try: check_chan_wildcards_format(wc) except Exception: self.fail(f"Wildcard '{wc}' raise Exception unexpectedly") with self.subTest("Wildcard with last char not matched"): wc = '*L' pattern = f"[{WF_3RD}*]" with self.assertRaises(Exception) as context: check_chan_wildcards_format(wc) self.assertEqual( str(context.exception), f"Request '{wc}' has last character not match {pattern}." ) with self.subTest("Wildcard is **"): wc = '**' with self.assertRaises(Exception) as context: check_chan_wildcards_format(wc) self.assertEqual( str(context.exception), f"Request '{wc}' includes '**' which isn't allowed." ) def test_len3(self): with self.subTest("Wildcard with first char matched"): wc = 'HL*' try: check_chan_wildcards_format(wc) except Exception: self.fail(f"Wildcard '{wc}' raise Exception unexpectedly") with self.subTest("Wildcard with first char is a '*'"): wc = '*L*' try: check_chan_wildcards_format(wc) except Exception: self.fail(f"Wildcard '{wc}' raise Exception unexpectedly") with self.subTest("Wildcard with first char not matched"): wc = 'WL*' pattern = f"[{WF_1ST}*]" with self.assertRaises(Exception) as context: check_chan_wildcards_format(wc) self.assertEqual( str(context.exception), f"Request '{wc}' has first character not match {pattern}." ) with self.subTest("Wildcard with last char matched"): wc = '*LN' try: check_chan_wildcards_format(wc) except Exception: self.fail(f"Wildcard '{wc}' raise Exception unexpectedly") with self.subTest("Wildcard with last char is a '*'"): wc = 'HL*' try: check_chan_wildcards_format(wc) except Exception: self.fail(f"Wildcard '{wc}' raise Exception unexpectedly") with self.subTest("Wildcard with last char not matched"): wc = '*LL' pattern = f"[{WF_3RD}*]" with self.assertRaises(Exception) as context: check_chan_wildcards_format(wc) self.assertEqual( str(context.exception), f"Request '{wc}' has last character not match {pattern}." ) with self.subTest("Wildcard with second char matched"): wc = 'HHN' try: check_chan_wildcards_format(wc) except Exception: self.fail(f"Wildcard '{wc}' raise Exception unexpectedly") with self.subTest("Wildcard with second char is a star"): wc = 'H*N' try: check_chan_wildcards_format(wc) except Exception: self.fail(f"Wildcard '{wc}' raise Exception unexpectedly") with self.subTest("Wildcard with second char not matched"): wc = 'HWE' pattern = f"[{WF_2ND}*]" with self.assertRaises(Exception) as context: check_chan_wildcards_format(wc) self.assertEqual( str(context.exception), f"Request '{wc}' has second character not match {pattern}." ) with self.subTest("Wildcard start with '**'"): wc = '**E' with self.assertRaises(Exception) as context: check_chan_wildcards_format(wc) self.assertEqual( str(context.exception), f"Request '{wc}' includes '**' which isn't allowed." ) with self.subTest("Wildcard end with '**'"): wc = 'H**' with self.assertRaises(Exception) as context: check_chan_wildcards_format(wc) self.assertEqual( str(context.exception), f"Request '{wc}' includes '**' which isn't allowed." ) def test_len_gt_3(self): wc = 'HHLL' with self.assertRaises(Exception) as context: check_chan_wildcards_format(wc) self.assertEqual( str(context.exception), f"Request '{wc}' has length={len(wc)} > 3 which isn't allowed." ) class TestCheckMassPos(TestCase): @classmethod def setUpClass(cls) -> None: cls.mp_data = {'MP1': {'chan_id': 'MP1', 'samplerate': 1}, 'MP3': {'chan_id': 'MP3', 'samplerate': 1}, 'MP4': {'chan_id': 'MP4', 'samplerate': 1}} cls.sel_key = '1378' def test_include_mp123(self): with self.assertRaises(Exception) as context: check_masspos(self.mp_data, self.sel_key, include_mp123=True, include_mp456=False) self.assertEqual( str(context.exception), f"Data set {self.sel_key} doesn't include mass position 2") def test_include_mp456(self): with self.assertRaises(Exception) as context: check_masspos(self.mp_data, self.sel_key, include_mp123=False, include_mp456=True) self.assertEqual( str(context.exception), f"Data set {self.sel_key} doesn't include mass position 5,6") def test_include_mp123456(self): with self.assertRaises(Exception) as context: check_masspos(self.mp_data, self.sel_key, include_mp123=True, include_mp456=True) self.assertEqual( str(context.exception), f"Data set {self.sel_key} doesn't include mass position 2,5,6") def test_not_include_mp(self): try: check_masspos(self.mp_data, self.sel_key, include_mp123=False, include_mp456=False) except Exception: self.fail("check_masspos() raise Exception unexpectedly")