import unittest from os import path, remove, environ from typing_extensions import List from stringlist import * class StringListTests(unittest.TestCase): def setUp(self): pass def test_can_construct(self): list = StringList() self.assertIsNotNone(list) self.assertIs(list.count(), 0) def test_count_works(self): list = StringList() expected = 0 actual = list.count() self.assertEqual(expected, actual) list.values.extend([1, 2, 3]) expected = 3 actual = list.count() self.assertEqual(expected, actual) def test_clear_works(self): list = StringList() list.values.extend([1, 2, 3]) self.assertNotEqual(len(list.values), 0) list.clear() self.assertEqual(len(list.values), 0) def test_add_works(self): list: StringList = StringList() expected: List[str] = ["abc", "123"] list.add(expected[0]) list.add(expected[1]) actual: List[str] = ["abc", "123"] self.assertIsNotNone(list.values) self.assertListEqual(expected, actual) def test_save_and_load_from_file(self): userprofile_path = environ.get("userprofile") if not path.exists(userprofile_path): raise Exception(f"Cannot find path ({userprofile_path})") filename: str = path.abspath(path.join(userprofile_path, "testfile.txt")) if path.exists(filename): raise Exception(f"Test file already exists: ({filename})") expected_lines: str = ["There once", "was a man", "from Kantuckeh"] list1: StringList = StringList().add_strings(expected_lines) list1.save_to_file(filename) try: list2: StringList = StringList() list2.load_from_file(filename) finally: remove(filename) #self.assertListEqual(list1.values, list2.values) self.assertEqual(list2.count(), len(expected_lines)) self.assertEqual(list2.count(), 3) self.assertEqual(list2.values[0], expected_lines[0]+"\n") self.assertEqual(list2.values[1], expected_lines[1]+"\n") self.assertEqual(list2.values[2], expected_lines[2]+"\n") def test_strip_line_endings_after_load_from_file(self): userprofile_path = environ.get("userprofile") if not path.exists(userprofile_path): raise Exception(f"Cannot find path ({userprofile_path})") filename: str = path.abspath(path.join(userprofile_path, "testfile.txt")) if path.exists(filename): raise Exception(f"Test file already exists: ({filename})") expected_lines: str = ["There once", "was a man", "from Kantuckeh"] list1: StringList = StringList().add_strings(expected_lines) list1.save_to_file(filename) try: list2: StringList = StringList() list2.load_from_file(filename) finally: remove(filename) list2.strip_line_endings() self.assertListEqual(list1.values, list2.values) def test_remove_with_single_item(self): before = list(range(0, 10)) list1: StringList = StringList() \ .add_strings(before) \ .remove(4) expected = [0, 1, 2, 3, 5, 6, 7, 8, 9] actual = list1.values self.assertEqual(expected, actual) def test_remove_first_item(self): before = list(range(0, 10)) list1: StringList = StringList() \ .add_strings(before) \ .remove(0) expected = [1, 2, 3, 4, 5, 6, 7, 8, 9] actual = list1.values self.assertEqual(expected, actual) def test_remove_last_item(self): before = list(range(0, 10)) list1: StringList = StringList() \ .add_strings(before) \ .remove(9) expected = [0, 1, 2, 3, 4, 5, 6, 7, 8] actual = list1.values self.assertEqual(expected, actual) def test_remove_first_three_items(self): before = list(range(0, 10)) list1: StringList = StringList() \ .add_strings(before) \ .remove(0, 3) expected = [3, 4, 5, 6, 7, 8, 9] actual = list1.values self.assertEqual(expected, actual) def test_remove_last_three_items(self): before = list(range(0, 10)) list1: StringList = StringList() \ .add_strings(before) \ .remove(7, 3) expected = [0, 1, 2, 3, 4, 5, 6] actual = list1.values self.assertEqual(expected, actual) def test_remove_middle_three_items(self): before = list(range(0, 10)) list1: StringList = StringList() \ .add_strings(before) \ .remove(4, 3) expected = [0, 1, 2, 3, 7, 8, 9] actual = list1.values self.assertEqual(expected, actual) def test_remove_before_first_item(self): before = list(range(0, 10)) list1: StringList = StringList() \ .add_strings(before) \ .remove(-1, 3) # This is what actually happens. expected = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9] # This is what I REALLY wanted to happen. :/ #expected = [2, 3, 4, 5, 6, 7, 8, 9] actual = list1.values self.assertEqual(expected, actual) def test_remove_beyond_last_item(self): before = list(range(0, 10)) list1: StringList = StringList() \ .add_strings(before) \ .remove(9, 3) #expected = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9] expected = [0, 1, 2, 3, 4, 5, 6, 7, 8] actual = list1.values self.assertEqual(expected, actual) def test_parse_empty(self): list1: StringList = StringList() list1.parse("") self.assertEqual(1, list1.count()) def test_parse_single_token(self): list1: StringList = StringList() input = "A monkey's your uncle." expected = [input] list1.parse(input, ",") actual = list1.values self.assertEqual(len(actual), 1) self.assertEqual(expected, actual) def test_parse_multiple_tokens(self): list1: StringList = StringList() input = "A monkey's your uncle." expected = ["A", "monkey's", "your", "uncle."] list1.parse(input, " ") actual = list1.values self.assertListEqual(expected, actual) self.assertEqual(4, len(actual)) def test_text_empty(self): list1: StringList = StringList() list1.clear() expected = "" actual = list1.text() self.assertEqual(expected, actual) self.assertEqual(0, len(actual)) def test_text_single_value(self): list1: StringList = StringList() input = "A monkey's your uncle." list1.add(input) expected = input actual = list1.text() self.assertEqual(expected, actual) def test_text_multiple_values(self): list1: StringList = StringList() input = ["A", "monkey's", "your", "uncle."] list1.add_strings(input) expected = "A monkey's your uncle." actual = list1.text(" ") self.assertEqual(expected, actual) def test_value_of_missing_key_is_handled(self): list1: StringList = StringList() list1.add("key=value") encountered_expected_exception: bool = False try: list1.value_of_key("missing_key") except KeyNotFoundException as e: encountered_expected_exception = True self.assertTrue(encountered_expected_exception) def test_contains_key_missing_on_list_size_of_1(self): list1: StringList = StringList() list1.add("key=value") actual: bool = list1.contains_key("missing") self.assertFalse(actual) def test_contains_key_missing_on_list_size_of_10(self): list1: StringList = StringList() list1.add_strings([f"key{i}=value{i}" for i in range(0, 10)]) actual: bool = list1.contains_key("missing") self.assertFalse(actual) def test_contains_key_missing_on_empty_list(self): list1: StringList = StringList() actual: bool = list1.contains_key("missing") self.assertFalse(actual) def test_contains_key_present_on_list_size_of_1(self): list1: StringList = StringList() list1.add("key=value") actual: bool = list1.contains_key("key") self.assertTrue(actual) def test_contains_key_present_on_list_size_of_10(self): list1: StringList = StringList() list1.add_strings([f"key{i}=value{i}" for i in range(0, 10)]) actual: bool = list1.contains_key("key1") self.assertTrue(actual) def test_value_of_key(self): list1: StringList = StringList() list1.add("key=value") expected = "value" actual = list1.value_of_key("key") self.assertEqual(expected, actual) def test_all_keys_empty(self): list1: StringList = StringList() expected = [] actual = list1.all_keys() self.assertEqual(expected, actual) def test_all_keys(self): list1: StringList = StringList() list1.add_strings([f"key{i}=value{i}" for i in range(0, 3)]) expected = ["key0", "key1", "key2"] actual = list1.all_keys() self.assertListEqual(expected, actual) def test_all_values_of_key(self): list1: StringList = StringList() list1.add_strings([f"key{i%2}=value{i}" for i in range(0, 10)]) expected = ["value0", "value2", "value4", "value6", "value8"] actual = list1.all_values_of_key("key0") self.assertListEqual(expected, actual) def test_assign(self): list1: StringList = StringList().add_strings([f"string {i}" for i in range(0, 3)]) list2: StringList = StringList() list2.assign(list1) self.assertListEqual(list1.values, list2.values) def test_assign_empty(self): list1: StringList = StringList() list2: StringList = StringList().add_strings([f"string {i}" for i in range(0, 3)]) expected = [] list2.assign(list1) actual = list2.values self.assertListEqual(expected, actual) def test_add_strings(self): list1: StringList = StringList().add_strings([f"string {i}" for i in range(0, 3)]) list2: StringList = StringList().add_strings(["a", "b", "c"]) expected = ["a", "b", "c", "string 0", "string 1", "string 2"] list2.add_string_list(list1) actual = list2.values self.assertEqual(6, list2.count()) self.assertEqual(expected, actual) def test_add_strings_empty(self): list1: StringList = StringList() list2: StringList = StringList().add_strings(["a", "b", "c"]) expected = ["a", "b", "c"] list2.add_string_list(list1) actual = list2.values self.assertEqual(3, list2.count()) self.assertEqual(expected, actual) def test_clone_empty(self): expected = [] list1: StringList = StringList() list2: StringList = list1.clone() actual = list2.values self.assertEqual(expected, actual) self.assertEqual(0, list2.count()) def test_clone(self): expected = ["a", "b", "c"] list1: StringList = StringList().add_strings(expected) list2: StringList = list1.clone() actual = list2.values self.assertEqual(expected, actual) def test_push(self): list1: StringList = StringList() self.assertEqual([], list1.values) list1.push("a") self.assertEqual(["a"], list1.values) list1.push("b") self.assertEqual(["a", "b"], list1.values) list1.push("c") self.assertEqual(["a", "b", "c"], list1.values) def test_pop(self): list1: StringList = StringList() \ .push("a") \ .push("b") \ .push("c") value1 = list1.pop() value2 = list1.pop() value3 = list1.pop() self.assertEqual(0, list1.count()) self.assertEqual(["c", "b", "a"], [value1, value2, value3]) def test_enqueue(self): list1: StringList = StringList() self.assertEqual([], list1.values) list1.enqueue("a") self.assertEqual(["a"], list1.values) list1.enqueue("b") self.assertEqual(["b", "a"], list1.values) list1.enqueue("c") self.assertEqual(["c", "b", "a"], list1.values) def test_dequeue(self): list1: StringList = StringList() \ .push("c") \ .push("b") \ .push("a") value1 = list1.dequeue() value2 = list1.dequeue() value3 = list1.dequeue() self.assertEqual(0, list1.count()) self.assertEqual(["a", "b", "c"], [value1, value2, value3]) def test_keep_sorted_property(self): list1: StringList = StringList() self.assertEqual(False, list1.keep_sorted) list1.keep_sorted = True self.assertEqual(True, list1.keep_sorted) def test_keep_sorted_property(self): list1: StringList = StringList() self.assertEqual(False, list1.keep_sorted) list1.keep_sorted = True self.assertEqual(True, list1.keep_sorted) def test_insertion_sort(self): list1: StringList = StringList() list1.keep_sorted = False list1.values = [0, 1, 2, 3, 4, 5] self.assertTrue(list1.is_sorted()) list1.reverse() self.assertFalse(list1.is_sorted()) list1._insertionsort() self.assertTrue(list1.is_sorted()) def test_reverse(self): list1: StringList = StringList().add_strings([f"{i}" for i in range(0, 3)]) expected = ["2", "1", "0"] list1.reverse() actual = list1.values self.assertEqual(expected, actual) def test_is_sorted(self): list1: StringList = StringList() list1.keep_sorted = False sorted1: bool = list1.is_sorted(list1._sort_comparer) list1.add_strings([f"{chr(i+65)}" for i in range(0, 25)]) sorted2: bool = list1.is_sorted() list1.reverse() sorted3: bool = list1.is_sorted() self.assertEqual(True, sorted1) self.assertEqual(True, sorted2) self.assertEqual(False, sorted3) def test_shuffle(self): list1: StringList = StringList() list1.keep_sorted = False ordered_list: List[str] = [f"{chr(i+65)}" for i in range(0, 25)] list1.add_strings(ordered_list) not_expected = ordered_list list1.shuffle() actual = list1.values self.assertNotEqual(not_expected, actual) def test_sort(self): list1: StringList = StringList() list1.keep_sorted = False list1.add_strings([f"{i}" for i in range(0, 10000)]) list1.shuffle() list1._quicksort(0, list1.count() - 1) self.assertTrue(list1.is_sorted()) def test_numeric_comparer(self): list1 = StringList().add_strings([f"{i}" for i in range(0, 15)]) comparer: StringComparer = AnonymousStringComparer(lambda left, right: int(left) - int(right)) expected = ["0", "1", "2", "3", "4", "5", "6", "7", "8", "9", "10", "11", "12", "13", "14"] list1.sort(comparer) actual = list1.values self.assertEqual(expected, actual) def test_lexical_comparer(self): list1 = StringList().add_strings([f"{i}" for i in range(0, 15)]) expected = ["0", "1", "10", "11", "12", "13", "14", "2", "3", "4", "5", "6", "7", "8", "9"] list1.sort() actual = list1.values self.assertEqual(expected, actual) def test_binary_search_present_0_to_99(self): list1 = StringList().add_strings([f"{i:03}" for i in range(0, 100)]) list1.keep_sorted = True for j in range(0, 100): i: int = list1.index_of(str(f"{j:03}")) self.assertEqual(j, i, f"{j}") def test_binary_search_present_0_to_98(self): list1 = StringList().add_strings([f"{i:03}" for i in range(0, 99)]) list1.keep_sorted = True for j in range(0, 99): i: int = list1.index_of(str(f"{j:03}")) self.assertEqual(j, i, f"{j}") def test_binary_search_present_0_to_2(self): list1 = StringList().add_strings([f"{i:03}" for i in range(0, 2)]) list1.keep_sorted = True for j in range(0, 2): i: int = list1.index_of(str(f"{j:03}")) self.assertEqual(j, i, f"{j}") def test_binary_search_present_0_to_1(self): list1 = StringList().add_strings([f"{i:03}" for i in range(0, 1)]) list1.keep_sorted = True for j in range(0, 1): i: int = list1.index_of(str(f"{j:03}")) self.assertEqual(j, i, f"{j}") def test_binary_search_present_single_element(self): list1 = StringList().add_strings([f"{i:03}" for i in range(0, 0)]) list1.keep_sorted = True for j in range(0, 0): i: int = list1.index_of(str(f"{j:03}")) self.assertEqual(j, i, f"{j}") def test_binary_search_missing_empty(self): list1 = StringList() list1.keep_sorted = True i: int = list1.index_of("missing") self.assertEqual(-1, i) def test_binary_search_missing_0_to_99(self): list1 = StringList().add_strings([f"{i:03}" for i in range(0, 100)]) list1.keep_sorted = True for j in range(0, 100): i: int = list1.index_of(f"{j:03}5") self.assertEqual(-1, i, f"{j}") def test_binary_search_missing_0_to_98(self): list1 = StringList().add_strings([f"{i:03}" for i in range(0, 99)]) list1.keep_sorted = True for j in range(0, 99): i: int = list1.index_of(f"{j:03}5") self.assertEqual(-1, i, f"{j}") def test_binary_search_missing_0_to_2(self): list1 = StringList().add_strings([f"{i:03}" for i in range(0, 2)]) list1.keep_sorted = True for j in range(0, 2): i: int = list1.index_of(f"{j:03}5") self.assertEqual(-1, i, f"{j}") def test_binary_search_missing_0_to_1(self): list1 = StringList().add_strings([f"{i:03}" for i in range(0, 1)]) list1.keep_sorted = True for j in range(0, 1): i: int = list1.index_of(f"{j:03}5") self.assertEqual(-1, i, f"{j}") def test_binary_search_missing_single_element(self): list1 = StringList().add_strings([f"{i:03}" for i in range(0, 0)]) list1.keep_sorted = True for j in range(0, 0): i: int = list1.index_of(f"{j:03}5") self.assertEqual(-1, i, f"{j}") def test_linear_search_empty(self): list1 = StringList() self.assertEqual(-1, list1.index_of("")) self.assertEqual(-1, list1.index_of("missing")) def test_linear_search_one_element(self): list1 = StringList().add("1") self.assertEqual(-1, list1.index_of("")) self.assertEqual(-1, list1.index_of("missing")) self.assertEqual(0, list1.index_of("1")) def test_linear_search_five_elements(self): list1 = StringList().add_strings([f"{i}" for i in range(0, 5)]) self.assertEqual(-1, list1.index_of("")) self.assertEqual(-1, list1.index_of("missing")) for j in range(0, 5): self.assertEqual(j, list1.index_of(str(j)), f"{j}") def test_swap(self): list1 = StringList().add_strings([f"{i}" for i in range(0, 5)]) list1.swap(1, 3) expected = ["0", "3", "2", "1", "4"] actual = list1.values self.assertEqual(expected, actual) def test_to_dictionary(self): list1 = StringList().add_strings([f"{i+1}={chr(i + 65)}" for i in range(0, 5)]) table1 = list1.to_dictionary() self.assertEqual(5, len(table1)) self.assertEqual(table1["1"], "A") self.assertEqual(table1["2"], "B") self.assertEqual(table1["3"], "C") self.assertEqual(table1["4"], "D") self.assertEqual(table1["5"], "E") def test_to_indexed_dictionary(self): list1 = StringList().add_strings([f"{i+1}={chr(i + 65)}" for i in range(0, 5)]) table1 = list1.to_indexed_dictionary() self.assertEqual(5, len(table1)) self.assertEqual(table1["1"], (0, "A")) self.assertEqual(table1["2"], (1, "B")) self.assertEqual(table1["3"], (2, "C")) self.assertEqual(table1["4"], (3, "D")) self.assertEqual(table1["5"], (4, "E")) def test_indexer_read(self): list1 = StringList().add_strings([f"{i}" for i in range(0, 5)]) for j in range(0, 5): expected = str(j) actual = list1[j] self.assertEqual(expected, actual) def test_indexer_write(self): values = [f"{i}" for i in range(0, 5)] list1 = StringList().add_strings(["", "", "", "", ""]) for j in range(0, 5): expected = str(values[j]) list1[j] = expected actual = list1.values[j] self.assertNotEqual("", actual) self.assertEqual(expected, actual, f"{j}") def test_maintain_sort_add(self): list1 = StringList(keep_sorted=True) self.assertTrue(list1.is_sorted()) list1.add("c") self.assertTrue(list1.is_sorted()) list1.add("b") self.assertTrue(list1.is_sorted()) list1.add("a") self.assertTrue(list1.is_sorted()) def test_maintain_sort_add_range(self): list1 = StringList(keep_sorted=True) list1.add_strings(["x", "y", "z"]) self.assertTrue(list1.is_sorted()) list1.add_strings(["c", "b", "a"]) self.assertTrue(list1.is_sorted()) def test_maintain_sort_enqueue(self): list1 = StringList(keep_sorted=True) self.assertTrue(list1.is_sorted()) list1.enqueue("a") self.assertTrue(list1.is_sorted()) list1.enqueue("b") self.assertTrue(list1.is_sorted()) list1.enqueue("c") self.assertTrue(list1.is_sorted()) def test_maintain_sort_push(self): list1 = StringList(keep_sorted=True) self.assertTrue(list1.is_sorted()) list1.push("c") self.assertTrue(list1.is_sorted()) list1.push("b") self.assertTrue(list1.is_sorted()) list1.push("a") self.assertTrue(list1.is_sorted()) def test_stack(self): list1 = StringList() list1.push("1") self.assertListEqual(["1"], list1.values) list1.push("2") self.assertListEqual(["1", "2"], list1.values) actual = list1.pop() self.assertEqual("2", actual) self.assertListEqual(["1"], list1.values) actual = list1.pop() self.assertEqual("1", actual) self.assertListEqual([], list1.values) def test_bottom_stack(self): list1 = StringList() list1.push_bottom("1") self.assertListEqual(["1"], list1.values) list1.push_bottom("2") self.assertListEqual(["2", "1"], list1.values) actual = list1.pop_bottom() self.assertEqual("2", actual) self.assertListEqual(["1"], list1.values) actual = list1.pop_bottom() self.assertEqual("1", actual) self.assertListEqual([], list1.values) def test_where(self): list1 = StringList().add_strings([f"{i}" for i in range(0, 10)]) list1.where(lambda index, line: index % 2 == 0) self.assertListEqual(["0", "2", "4", "6", "8"], list1.values) def test_select(self): base_values = [f"{i}" for i in range(0, 5)] list1 = StringList().add_strings(base_values) list1.select(lambda index, line: str(int(line) + 1)) expected = [f"{i+1}" for i in range(0, 5)] actual = list1.values self.assertListEqual(expected, actual) def test_distinct(self): input = ["a", "b", "c", "d", "b", "c"] expected = ["a", "b", "c", "d"] list1 = StringList().add_strings(input) list1.distinct() actual = list1.values self.assertListEqual(expected, actual) def test_union(self): list_a = ["a", "b", "c", ] list_b = ["b", "c", "d", "e"] list1 = StringList().add_strings(list_a) list1.union(list_b) expected = ["a", "b", "c", "d", "e"] actual = list1.values self.assertListEqual(expected, actual) def test_exclude(self): list_a = ["a", "b", "c"] list_b = ["b", "c", "d", "e"] list1 = StringList().add_strings(list_a) list1.exclude(list_b) expected = ["a"] actual = list1.values self.assertListEqual(expected, actual) def test_zip(self): list_a = ["a", "b", "c"] list_b = ["1", "2", "3"] list1 = StringList().add_strings(list_a) list1.zip(list_b, lambda index, left, right: f"{index}:({left},{right})") #print(list1.values) expected = ["0:(a,1)", "1:(b,2)", "2:(c,3)"] actual = list1.values self.assertListEqual(expected, actual) def test_first(self): list1 = StringList().add_strings([f"{i}" for i in range(0, 5)]) actual = list1.first() expected = "0" self.assertEqual(expected, actual) def test_first_empty(self): list1 = StringList() actual = list1.first("default") expected = "default" self.assertEqual(expected, actual) def test_last(self): list1 = StringList().add_strings([f"{i}" for i in range(0, 5)]) actual = list1.last() expected = "4" self.assertEqual(expected, actual) def test_last_empty(self): list1 = StringList() actual = list1.last("default") expected = "default" self.assertEqual(expected, actual) def test_skip(self): list1 = StringList().add_strings([f"{i}" for i in range(0, 5)]) actual = list1.skip().values expected = ["1", "2", "3", "4"] self.assertListEqual(expected, actual) def test_skip_2(self): list1 = StringList().add_strings([f"{i}" for i in range(0, 5)]) actual = list1.skip(2).values expected = ["2", "3", "4"] self.assertListEqual(expected, actual) def test_take(self): list1 = StringList().add_strings([f"{i}" for i in range(0, 5)]) actual = list1.take().values expected = ["0"] self.assertListEqual(expected, actual) def test_take_2(self): list1 = StringList().add_strings([f"{i}" for i in range(0, 5)]) actual = list1.take(2).values expected = ["0", "1"] self.assertListEqual(expected, actual)