diff options
author | Bryan Bishop <kanzure@gmail.com> | 2013-08-04 17:16:27 -0500 |
---|---|---|
committer | Bryan Bishop <kanzure@gmail.com> | 2013-08-04 17:16:27 -0500 |
commit | b2a7156acbe8b485e35beaccab1f8457fec24eaf (patch) | |
tree | e01dc63a281679af8b436c734428a2da4b54d3c9 | |
parent | 3011f9243cbe4b0de7ab2392941385c705697909 (diff) | |
parent | 611c2ecdd05cdb7e4a2726132b12e10b86acc275 (diff) |
Merge branch 'better-testing' into master
-rw-r--r-- | pokemontools/crystal.py | 12 | ||||
-rw-r--r-- | tests/integration/__init__.py | 0 | ||||
-rw-r--r-- | tests/integration/tests.py | 382 | ||||
-rw-r--r-- | tests/tests.py | 489 |
4 files changed, 412 insertions, 471 deletions
diff --git a/pokemontools/crystal.py b/pokemontools/crystal.py index 9ee6ec0..dcd95d9 100644 --- a/pokemontools/crystal.py +++ b/pokemontools/crystal.py @@ -6663,9 +6663,11 @@ def get_dependencies_for(some_object, recompute=False, global_dependencies=set() print "asm is: \n\n" + to_asm(some_object) raise e -def isolate_incbins(): +def isolate_incbins(asm=None): "find each incbin line" - global incbin_lines, asm + global incbin_lines + if asm == None: + asm = globals()["asm"] incbin_lines = [] for line in asm: if line == "": continue @@ -6687,7 +6689,7 @@ def process_incbins(): load_asm() # get a list of incbins if that hasn't happened yet if incbin_lines == [] or incbin_lines == None: - isolate_incbins() + isolate_incbins(asm=asm) # reset the global that this function creates processed_incbins = {} # for each incbin.. @@ -6728,7 +6730,7 @@ def reset_incbins(): incbin_lines = [] processed_incbins = {} load_asm() - isolate_incbins() + isolate_incbins(asm=asm) process_incbins() def find_incbin_to_replace_for(address, debug=False, rom_file="../baserom.gbc"): @@ -7340,7 +7342,7 @@ def analyze_intervals(): if asm == None: load_asm() if processed_incbins == {}: - isolate_incbins() + isolate_incbins(asm=asm) process_incbins() results = [] ordered_keys = sorted(processed_incbins, key=lambda entry: processed_incbins[entry]["interval"]) diff --git a/tests/integration/__init__.py b/tests/integration/__init__.py new file mode 100644 index 0000000..e69de29 --- /dev/null +++ b/tests/integration/__init__.py diff --git a/tests/integration/tests.py b/tests/integration/tests.py new file mode 100644 index 0000000..7dcfbf4 --- /dev/null +++ b/tests/integration/tests.py @@ -0,0 +1,382 @@ +# -*- coding: utf-8 -*- + +import os +from copy import copy +import hashlib +import random +import json + +from pokemontools.interval_map import IntervalMap +from pokemontools.chars import chars, jap_chars + +from pokemontools.romstr import ( + RomStr, + AsmList, +) + +from pokemontools.item_constants import ( + item_constants, + find_item_label_by_id, + generate_item_constants, +) + +from pokemontools.pointers import ( + calculate_bank, + calculate_pointer, +) + +from pokemontools.pksv import ( + pksv_gs, + pksv_crystal, +) + +from pokemontools.labels import ( + remove_quoted_text, + line_has_comment_address, + line_has_label, + get_label_from_line, +) + +from pokemontools.crystal import ( + rom, + load_rom, + rom_until, + direct_load_rom, + parse_script_engine_script_at, + parse_text_engine_script_at, + parse_text_at2, + find_all_text_pointers_in_script_engine_script, + SingleByteParam, + HexByte, + MultiByteParam, + PointerLabelParam, + ItemLabelByte, + DollarSignByte, + DecimalParam, + rom_interval, + map_names, + Label, + scan_for_predefined_labels, + all_labels, + write_all_labels, + parse_map_header_at, + old_parse_map_header_at, + process_00_subcommands, + parse_all_map_headers, + translate_command_byte, + map_name_cleaner, + load_map_group_offsets, + load_asm, + asm, + is_valid_address, + index, + how_many_until, + grouper, + get_pokemon_constant_by_id, + generate_map_constant_labels, + get_map_constant_label_by_id, + get_id_for_map_constant_label, + calculate_pointer_from_bytes_at, + isolate_incbins, + process_incbins, + get_labels_between, + generate_diff_insert, + find_labels_without_addresses, + rom_text_at, + get_label_for, + split_incbin_line_into_three, + reset_incbins, +) + +import unittest + +class BasicTestCase(unittest.TestCase): + "this is where i cram all of my unit tests together" + + @classmethod + def setUpClass(cls): + global rom + cls.rom = direct_load_rom() + rom = cls.rom + + @classmethod + def tearDownClass(cls): + del cls.rom + + def test_direct_load_rom(self): + rom = self.rom + self.assertEqual(len(rom), 2097152) + self.failUnless(isinstance(rom, RomStr)) + + def test_load_rom(self): + global rom + rom = None + load_rom() + self.failIf(rom == None) + rom = RomStr(None) + load_rom() + self.failIf(rom == RomStr(None)) + + def test_load_asm(self): + asm = load_asm() + joined_lines = "\n".join(asm) + self.failUnless("SECTION" in joined_lines) + self.failUnless("bank" in joined_lines) + self.failUnless(isinstance(asm, AsmList)) + + def test_rom_file_existence(self): + "ROM file must exist" + self.failUnless("baserom.gbc" in os.listdir("../")) + + def test_rom_md5(self): + "ROM file must have the correct md5 sum" + rom = self.rom + correct = "9f2922b235a5eeb78d65594e82ef5dde" + md5 = hashlib.md5() + md5.update(rom) + md5sum = md5.hexdigest() + self.assertEqual(md5sum, correct) + + def test_bizarre_http_presence(self): + rom_segment = self.rom[0x112116:0x112116+8] + self.assertEqual(rom_segment, "HTTP/1.0") + + def test_rom_interval(self): + address = 0x100 + interval = 10 + correct_strings = ['0x0', '0xc3', '0x6e', '0x1', '0xce', + '0xed', '0x66', '0x66', '0xcc', '0xd'] + byte_strings = rom_interval(address, interval, strings=True) + self.assertEqual(byte_strings, correct_strings) + correct_ints = [0, 195, 110, 1, 206, 237, 102, 102, 204, 13] + ints = rom_interval(address, interval, strings=False) + self.assertEqual(ints, correct_ints) + + def test_rom_until(self): + address = 0x1337 + byte = 0x13 + bytes = rom_until(address, byte, strings=True) + self.failUnless(len(bytes) == 3) + self.failUnless(bytes[0] == '0xd5') + bytes = rom_until(address, byte, strings=False) + self.failUnless(len(bytes) == 3) + self.failUnless(bytes[0] == 0xd5) + + def test_how_many_until(self): + how_many = how_many_until(chr(0x13), 0x1337) + self.assertEqual(how_many, 3) + + def test_calculate_pointer_from_bytes_at(self): + addr1 = calculate_pointer_from_bytes_at(0x100, bank=False) + self.assertEqual(addr1, 0xc300) + addr2 = calculate_pointer_from_bytes_at(0x100, bank=True) + self.assertEqual(addr2, 0x2ec3) + + def test_rom_text_at(self): + self.assertEquals(rom_text_at(0x112116, 8), "HTTP/1.0") + +class TestRomStr(unittest.TestCase): + sample_text = "hello world!" + sample = None + + def test_rom_interval(self): + global rom + load_rom() + address = 0x100 + interval = 10 + correct_strings = ['0x0', '0xc3', '0x6e', '0x1', '0xce', + '0xed', '0x66', '0x66', '0xcc', '0xd'] + byte_strings = rom.interval(address, interval, strings=True) + self.assertEqual(byte_strings, correct_strings) + correct_ints = [0, 195, 110, 1, 206, 237, 102, 102, 204, 13] + ints = rom.interval(address, interval, strings=False) + self.assertEqual(ints, correct_ints) + + def test_rom_until(self): + global rom + load_rom() + address = 0x1337 + byte = 0x13 + bytes = rom.until(address, byte, strings=True) + self.failUnless(len(bytes) == 3) + self.failUnless(bytes[0] == '0xd5') + bytes = rom.until(address, byte, strings=False) + self.failUnless(len(bytes) == 3) + self.failUnless(bytes[0] == 0xd5) + +class TestAsmList(unittest.TestCase): + # this test takes a lot of time :( + def xtest_scan_for_predefined_labels(self): + # label keys: line_number, bank, label, offset, address + load_asm() + all_labels = scan_for_predefined_labels() + label_names = [x["label"] for x in all_labels] + self.assertIn("GetFarByte", label_names) + self.assertIn("AddNTimes", label_names) + self.assertIn("CheckShininess", label_names) + +class TestEncodedText(unittest.TestCase): + """for testing chars-table encoded text chunks""" + + def test_process_00_subcommands(self): + g = process_00_subcommands(0x197186, 0x197186+601, debug=False) + self.assertEqual(len(g), 42) + self.assertEqual(len(g[0]), 13) + self.assertEqual(g[1], [184, 174, 180, 211, 164, 127, 20, 231, 81]) + + def test_parse_text_at2(self): + oakspeech = parse_text_at2(0x197186, 601, debug=False) + self.assertIn("encyclopedia", oakspeech) + self.assertIn("researcher", oakspeech) + self.assertIn("dependable", oakspeech) + + def test_parse_text_engine_script_at(self): + p = parse_text_engine_script_at(0x197185, debug=False) + self.assertEqual(len(p.commands), 2) + self.assertEqual(len(p.commands[0]["lines"]), 41) + +class TestScript(unittest.TestCase): + """for testing parse_script_engine_script_at and script parsing in + general. Script should be a class.""" + #def test_parse_script_engine_script_at(self): + # pass # or raise NotImplementedError, bryan_message + + def test_find_all_text_pointers_in_script_engine_script(self): + address = 0x197637 # 0x197634 + script = parse_script_engine_script_at(address, debug=False) + bank = calculate_bank(address) + r = find_all_text_pointers_in_script_engine_script(script, bank=bank, debug=False) + results = list(r) + self.assertIn(0x197661, results) + +class TestByteParams(unittest.TestCase): + @classmethod + def setUpClass(cls): + load_rom() + cls.address = 10 + cls.sbp = SingleByteParam(address=cls.address) + + @classmethod + def tearDownClass(cls): + del cls.sbp + + def test__init__(self): + self.assertEqual(self.sbp.size, 1) + self.assertEqual(self.sbp.address, self.address) + + def test_parse(self): + self.sbp.parse() + self.assertEqual(str(self.sbp.byte), str(45)) + + def test_to_asm(self): + self.assertEqual(self.sbp.to_asm(), "$2d") + self.sbp.should_be_decimal = True + self.assertEqual(self.sbp.to_asm(), str(45)) + + # HexByte and DollarSignByte are the same now + def test_HexByte_to_asm(self): + h = HexByte(address=10) + a = h.to_asm() + self.assertEqual(a, "$2d") + + def test_DollarSignByte_to_asm(self): + d = DollarSignByte(address=10) + a = d.to_asm() + self.assertEqual(a, "$2d") + + def test_ItemLabelByte_to_asm(self): + i = ItemLabelByte(address=433) + self.assertEqual(i.byte, 54) + self.assertEqual(i.to_asm(), "COIN_CASE") + self.assertEqual(ItemLabelByte(address=10).to_asm(), "$2d") + + def test_DecimalParam_to_asm(self): + d = DecimalParam(address=10) + x = d.to_asm() + self.assertEqual(x, str(0x2d)) + +class TestMultiByteParam(unittest.TestCase): + def setup_for(self, somecls, byte_size=2, address=443, **kwargs): + self.cls = somecls(address=address, size=byte_size, **kwargs) + self.assertEqual(self.cls.address, address) + self.assertEqual(self.cls.bytes, rom_interval(address, byte_size, strings=False)) + self.assertEqual(self.cls.size, byte_size) + + def test_two_byte_param(self): + self.setup_for(MultiByteParam, byte_size=2) + self.assertEqual(self.cls.to_asm(), "$f0c0") + + def test_three_byte_param(self): + self.setup_for(MultiByteParam, byte_size=3) + + def test_PointerLabelParam_no_bank(self): + self.setup_for(PointerLabelParam, bank=None) + # assuming no label at this location.. + self.assertEqual(self.cls.to_asm(), "$f0c0") + global all_labels + # hm.. maybe all_labels should be using a class? + all_labels = [{"label": "poop", "address": 0xf0c0, + "offset": 0xf0c0, "bank": 0, + "line_number": 2 + }] + self.assertEqual(self.cls.to_asm(), "poop") + +class TestPostParsing: #(unittest.TestCase): + """tests that must be run after parsing all maps""" + def test_signpost_counts(self): + self.assertEqual(len(map_names[1][1]["signposts"]), 0) + self.assertEqual(len(map_names[1][2]["signposts"]), 2) + self.assertEqual(len(map_names[10][5]["signposts"]), 7) + + def test_warp_counts(self): + self.assertEqual(map_names[10][5]["warp_count"], 9) + self.assertEqual(map_names[18][5]["warp_count"], 3) + self.assertEqual(map_names[15][1]["warp_count"], 2) + + def test_map_sizes(self): + self.assertEqual(map_names[15][1]["height"], 18) + self.assertEqual(map_names[15][1]["width"], 10) + self.assertEqual(map_names[7][1]["height"], 4) + self.assertEqual(map_names[7][1]["width"], 4) + + def test_map_connection_counts(self): + self.assertEqual(map_names[7][1]["connections"], 0) + self.assertEqual(map_names[10][1]["connections"], 12) + self.assertEqual(map_names[10][2]["connections"], 12) + self.assertEqual(map_names[11][1]["connections"], 9) # or 13? + + def test_second_map_header_address(self): + self.assertEqual(map_names[11][1]["second_map_header_address"], 0x9509c) + self.assertEqual(map_names[1][5]["second_map_header_address"], 0x95bd0) + + def test_event_address(self): + self.assertEqual(map_names[17][5]["event_address"], 0x194d67) + self.assertEqual(map_names[23][3]["event_address"], 0x1a9ec9) + + def test_people_event_counts(self): + self.assertEqual(len(map_names[23][3]["people_events"]), 4) + self.assertEqual(len(map_names[10][3]["people_events"]), 9) + +class TestMapParsing(unittest.TestCase): + def test_parse_all_map_headers(self): + global parse_map_header_at, old_parse_map_header_at, counter + counter = 0 + for k in map_names.keys(): + if "offset" not in map_names[k].keys(): + map_names[k]["offset"] = 0 + temp = parse_map_header_at + temp2 = old_parse_map_header_at + def parse_map_header_at(address, map_group=None, map_id=None, debug=False): + global counter + counter += 1 + return {} + old_parse_map_header_at = parse_map_header_at + parse_all_map_headers(debug=False) + # parse_all_map_headers is currently doing it 2x + # because of the new/old map header parsing routines + self.assertEqual(counter, 388 * 2) + parse_map_header_at = temp + old_parse_map_header_at = temp2 + +if __name__ == "__main__": + unittest.main() diff --git a/tests/tests.py b/tests/tests.py index 606c105..3b77d41 100644 --- a/tests/tests.py +++ b/tests/tests.py @@ -1,8 +1,6 @@ # -*- coding: utf-8 -*- import os -import sys -import inspect from copy import copy import hashlib import random @@ -90,34 +88,12 @@ from pokemontools.crystal import ( reset_incbins, ) -# for testing all this crap -try: - import unittest2 as unittest -except ImportError: - import unittest - -# check for things we need in unittest -if not hasattr(unittest.TestCase, 'setUpClass'): - sys.stderr.write("The unittest2 module or Python 2.7 is required to run this script.") - sys.exit(1) +import unittest +import mock class TestCram(unittest.TestCase): "this is where i cram all of my unit tests together" - @classmethod - def setUpClass(cls): - global rom - cls.rom = direct_load_rom() - rom = cls.rom - - @classmethod - def tearDownClass(cls): - del cls.rom - - def test_generic_useless(self): - "do i know how to write a test?" - self.assertEqual(1, 1) - def test_map_name_cleaner(self): name = "hello world" cleaned_name = map_name_cleaner(name) @@ -139,75 +115,10 @@ class TestCram(unittest.TestCase): self.assertNotEqual(data, groups) self.assertNotEqual(len(data), len(groups)) - def test_direct_load_rom(self): - rom = self.rom - self.assertEqual(len(rom), 2097152) - self.failUnless(isinstance(rom, RomStr)) - - def test_load_rom(self): - global rom - rom = None - load_rom() - self.failIf(rom == None) - rom = RomStr(None) - load_rom() - self.failIf(rom == RomStr(None)) - - def test_load_asm(self): - asm = load_asm() - joined_lines = "\n".join(asm) - self.failUnless("SECTION" in joined_lines) - self.failUnless("bank" in joined_lines) - self.failUnless(isinstance(asm, AsmList)) - - def test_rom_file_existence(self): - "ROM file must exist" - self.failUnless("baserom.gbc" in os.listdir("../")) - - def test_rom_md5(self): - "ROM file must have the correct md5 sum" - rom = self.rom - correct = "9f2922b235a5eeb78d65594e82ef5dde" - md5 = hashlib.md5() - md5.update(rom) - md5sum = md5.hexdigest() - self.assertEqual(md5sum, correct) - - def test_bizarre_http_presence(self): - rom_segment = self.rom[0x112116:0x112116+8] - self.assertEqual(rom_segment, "HTTP/1.0") - - def test_rom_interval(self): - address = 0x100 - interval = 10 - correct_strings = ['0x0', '0xc3', '0x6e', '0x1', '0xce', - '0xed', '0x66', '0x66', '0xcc', '0xd'] - byte_strings = rom_interval(address, interval, strings=True) - self.assertEqual(byte_strings, correct_strings) - correct_ints = [0, 195, 110, 1, 206, 237, 102, 102, 204, 13] - ints = rom_interval(address, interval, strings=False) - self.assertEqual(ints, correct_ints) - - def test_rom_until(self): - address = 0x1337 - byte = 0x13 - bytes = rom_until(address, byte, strings=True) - self.failUnless(len(bytes) == 3) - self.failUnless(bytes[0] == '0xd5') - bytes = rom_until(address, byte, strings=False) - self.failUnless(len(bytes) == 3) - self.failUnless(bytes[0] == 0xd5) - - def test_how_many_until(self): - how_many = how_many_until(chr(0x13), 0x1337) - self.assertEqual(how_many, 3) - def test_calculate_bank(self): self.failUnless(calculate_bank(0x8000) == 2) self.failUnless(calculate_bank("0x9000") == 2) self.failUnless(calculate_bank(0) == 0) - for address in [0x4000, 0x5000, 0x6000, 0x7000]: - self.assertRaises(Exception, calculate_bank, address) def test_calculate_pointer(self): # for offset <= 0x4000 @@ -218,15 +129,6 @@ class TestCram(unittest.TestCase): # for offset >= 0x7FFF self.assertEqual(calculate_pointer(0x8FFF, bank=6), calculate_pointer(0x8FFF, bank=7)) - def test_calculate_pointer_from_bytes_at(self): - addr1 = calculate_pointer_from_bytes_at(0x100, bank=False) - self.assertEqual(addr1, 0xc300) - addr2 = calculate_pointer_from_bytes_at(0x100, bank=True) - self.assertEqual(addr2, 0x2ec3) - - def test_rom_text_at(self): - self.assertEquals(rom_text_at(0x112116, 8), "HTTP/1.0") - def test_translate_command_byte(self): self.failUnless(translate_command_byte(crystal=0x0) == 0x0) self.failUnless(translate_command_byte(crystal=0x10) == 0x10) @@ -397,31 +299,6 @@ class TestRomStr(unittest.TestCase): self.assertEquals(len(self.sample_text), self.sample.length()) self.assertEquals(len(self.sample), self.sample.length()) - def test_rom_interval(self): - global rom - load_rom() - address = 0x100 - interval = 10 - correct_strings = ['0x0', '0xc3', '0x6e', '0x1', '0xce', - '0xed', '0x66', '0x66', '0xcc', '0xd'] - byte_strings = rom.interval(address, interval, strings=True) - self.assertEqual(byte_strings, correct_strings) - correct_ints = [0, 195, 110, 1, 206, 237, 102, 102, 204, 13] - ints = rom.interval(address, interval, strings=False) - self.assertEqual(ints, correct_ints) - - def test_rom_until(self): - global rom - load_rom() - address = 0x1337 - byte = 0x13 - bytes = rom.until(address, byte, strings=True) - self.failUnless(len(bytes) == 3) - self.failUnless(bytes[0] == '0xd5') - bytes = rom.until(address, byte, strings=False) - self.failUnless(len(bytes) == 3) - self.failUnless(bytes[0] == 0xd5) - class TestAsmList(unittest.TestCase): """AsmList is a class that should act exactly like list() except that it never shows the contents of its list @@ -528,22 +405,14 @@ class TestAsmList(unittest.TestCase): self.assertEqual(labels[0]["label"], "HelloWorld") del asm - # this test takes a lot of time :( - def xtest_scan_for_predefined_labels(self): - # label keys: line_number, bank, label, offset, address - load_asm() - all_labels = scan_for_predefined_labels() - label_names = [x["label"] for x in all_labels] - self.assertIn("GetFarByte", label_names) - self.assertIn("AddNTimes", label_names) - self.assertIn("CheckShininess", label_names) - def test_write_all_labels(self): """dumping json into a file""" filename = "test_labels.json" + # remove the current file if os.path.exists(filename): os.system("rm " + filename) + # make up some labels labels = [] # fake label 1 @@ -552,26 +421,33 @@ class TestAsmList(unittest.TestCase): # fake label 2 label = {"line_number": 15, "bank": 2, "label": "SomeOtherLabel", "address": 0x9F0A} labels.append(label) + # dump to file write_all_labels(labels, filename=filename) + # open the file and read the contents file_handler = open(filename, "r") contents = file_handler.read() file_handler.close() + # parse into json obj = json.read(contents) + # begin testing self.assertEqual(len(obj), len(labels)) self.assertEqual(len(obj), 2) self.assertEqual(obj, labels) + # remove the current file + if os.path.exists(filename): + os.system("rm " + filename) + def test_isolate_incbins(self): - global asm asm = ["123", "456", "789", "abc", "def", "ghi", 'INCBIN "baserom.gbc",$12DA,$12F8 - $12DA', "jkl", 'INCBIN "baserom.gbc",$137A,$13D0 - $137A'] - lines = isolate_incbins() + lines = isolate_incbins(asm=asm) self.assertIn(asm[6], lines) self.assertIn(asm[8], lines) for line in lines: @@ -610,18 +486,22 @@ class TestAsmList(unittest.TestCase): asm = ['first line', 'second line', 'third line', 'INCBIN "baserom.gbc",$90,$200 - $90', 'fifth line', 'last line'] - isolate_incbins() + isolate_incbins(asm=asm) process_incbins() line_num = find_incbin_to_replace_for(0x100) # must be the 4th line (the INBIN line) self.assertEqual(line_num, 3) - def test_split_incbin_line_into_three(self): + @mock.patch("os.lstat") + def test_split_incbin_line_into_three(self, mock_os_lstat): global asm, incbin_lines, processed_incbins + + mock_os_lstat.return_value.st_size = 0x10000 + asm = ['first line', 'second line', 'third line', 'INCBIN "baserom.gbc",$90,$200 - $90', 'fifth line', 'last line'] - isolate_incbins() + isolate_incbins(asm=asm) process_incbins() content = split_incbin_line_into_three(3, 0x100, 10) # must end up with three INCBINs in output @@ -634,7 +514,7 @@ class TestAsmList(unittest.TestCase): 'INCBIN "baserom.gbc",$90,$200 - $90', 'fifth line', 'last line', 'INCBIN "baserom.gbc",$33F,$4000 - $33F'] - isolate_incbins() + isolate_incbins(asm=asm) process_incbins() largest = analyze_intervals() self.assertEqual(largest[0]["line_number"], 6) @@ -654,27 +534,6 @@ class TestAsmList(unittest.TestCase): self.assertNotIn("No newline at end of file", diff) self.assertIn("+"+asm[1], diff) -class TestMapParsing(unittest.TestCase): - def test_parse_all_map_headers(self): - global parse_map_header_at, old_parse_map_header_at, counter - counter = 0 - for k in map_names.keys(): - if "offset" not in map_names[k].keys(): - map_names[k]["offset"] = 0 - temp = parse_map_header_at - temp2 = old_parse_map_header_at - def parse_map_header_at(address, map_group=None, map_id=None, debug=False): - global counter - counter += 1 - return {} - old_parse_map_header_at = parse_map_header_at - parse_all_map_headers(debug=False) - # parse_all_map_headers is currently doing it 2x - # because of the new/old map header parsing routines - self.assertEqual(counter, 388 * 2) - parse_map_header_at = temp - old_parse_map_header_at = temp2 - class TestTextScript(unittest.TestCase): """for testing 'in-script' commands, etc.""" #def test_to_asm(self): @@ -687,47 +546,16 @@ class TestTextScript(unittest.TestCase): class TestEncodedText(unittest.TestCase): """for testing chars-table encoded text chunks""" - def test_process_00_subcommands(self): - g = process_00_subcommands(0x197186, 0x197186+601, debug=False) - self.assertEqual(len(g), 42) - self.assertEqual(len(g[0]), 13) - self.assertEqual(g[1], [184, 174, 180, 211, 164, 127, 20, 231, 81]) - - def test_parse_text_at2(self): - oakspeech = parse_text_at2(0x197186, 601, debug=False) - self.assertIn("encyclopedia", oakspeech) - self.assertIn("researcher", oakspeech) - self.assertIn("dependable", oakspeech) - - def test_parse_text_engine_script_at(self): - p = parse_text_engine_script_at(0x197185, debug=False) - self.assertEqual(len(p.commands), 2) - self.assertEqual(len(p.commands[0]["lines"]), 41) - # don't really care about these other two def test_parse_text_from_bytes(self): pass def test_parse_text_at(self): pass -class TestScript(unittest.TestCase): - """for testing parse_script_engine_script_at and script parsing in - general. Script should be a class.""" - #def test_parse_script_engine_script_at(self): - # pass # or raise NotImplementedError, bryan_message - - def test_find_all_text_pointers_in_script_engine_script(self): - address = 0x197637 # 0x197634 - script = parse_script_engine_script_at(address, debug=False) - bank = calculate_bank(address) - r = find_all_text_pointers_in_script_engine_script(script, bank=bank, debug=False) - results = list(r) - self.assertIn(0x197661, results) - class TestLabel(unittest.TestCase): def test_label_making(self): line_number = 2 address = 0xf0c0 label_name = "poop" - l = Label(name=label_name, address=address, line_number=line_number) + l = Label(name=label_name, address=address, line_number=line_number, object={}) self.failUnless(hasattr(l, "name")) self.failUnless(hasattr(l, "address")) self.failUnless(hasattr(l, "line_number")) @@ -738,277 +566,6 @@ class TestLabel(unittest.TestCase): self.assertEqual(l.name, label_name) self.assertEqual(l.address, address) -class TestByteParams(unittest.TestCase): - @classmethod - def setUpClass(cls): - load_rom() - cls.address = 10 - cls.sbp = SingleByteParam(address=cls.address) - - @classmethod - def tearDownClass(cls): - del cls.sbp - - def test__init__(self): - self.assertEqual(self.sbp.size, 1) - self.assertEqual(self.sbp.address, self.address) - - def test_parse(self): - self.sbp.parse() - self.assertEqual(str(self.sbp.byte), str(45)) - - def test_to_asm(self): - self.assertEqual(self.sbp.to_asm(), "$2d") - self.sbp.should_be_decimal = True - self.assertEqual(self.sbp.to_asm(), str(45)) - - # HexByte and DollarSignByte are the same now - def test_HexByte_to_asm(self): - h = HexByte(address=10) - a = h.to_asm() - self.assertEqual(a, "$2d") - - def test_DollarSignByte_to_asm(self): - d = DollarSignByte(address=10) - a = d.to_asm() - self.assertEqual(a, "$2d") - - def test_ItemLabelByte_to_asm(self): - i = ItemLabelByte(address=433) - self.assertEqual(i.byte, 54) - self.assertEqual(i.to_asm(), "COIN_CASE") - self.assertEqual(ItemLabelByte(address=10).to_asm(), "$2d") - - def test_DecimalParam_to_asm(self): - d = DecimalParam(address=10) - x = d.to_asm() - self.assertEqual(x, str(0x2d)) - -class TestMultiByteParam(unittest.TestCase): - def setup_for(self, somecls, byte_size=2, address=443, **kwargs): - self.cls = somecls(address=address, size=byte_size, **kwargs) - self.assertEqual(self.cls.address, address) - self.assertEqual(self.cls.bytes, rom_interval(address, byte_size, strings=False)) - self.assertEqual(self.cls.size, byte_size) - - def test_two_byte_param(self): - self.setup_for(MultiByteParam, byte_size=2) - self.assertEqual(self.cls.to_asm(), "$f0c0") - - def test_three_byte_param(self): - self.setup_for(MultiByteParam, byte_size=3) - - def test_PointerLabelParam_no_bank(self): - self.setup_for(PointerLabelParam, bank=None) - # assuming no label at this location.. - self.assertEqual(self.cls.to_asm(), "$f0c0") - global all_labels - # hm.. maybe all_labels should be using a class? - all_labels = [{"label": "poop", "address": 0xf0c0, - "offset": 0xf0c0, "bank": 0, - "line_number": 2 - }] - self.assertEqual(self.cls.to_asm(), "poop") - -class TestPostParsing: #(unittest.TestCase): - """tests that must be run after parsing all maps""" - @classmethod - def setUpClass(cls): - run_main() - - def test_signpost_counts(self): - self.assertEqual(len(map_names[1][1]["signposts"]), 0) - self.assertEqual(len(map_names[1][2]["signposts"]), 2) - self.assertEqual(len(map_names[10][5]["signposts"]), 7) - - def test_warp_counts(self): - self.assertEqual(map_names[10][5]["warp_count"], 9) - self.assertEqual(map_names[18][5]["warp_count"], 3) - self.assertEqual(map_names[15][1]["warp_count"], 2) - - def test_map_sizes(self): - self.assertEqual(map_names[15][1]["height"], 18) - self.assertEqual(map_names[15][1]["width"], 10) - self.assertEqual(map_names[7][1]["height"], 4) - self.assertEqual(map_names[7][1]["width"], 4) - - def test_map_connection_counts(self): - self.assertEqual(map_names[7][1]["connections"], 0) - self.assertEqual(map_names[10][1]["connections"], 12) - self.assertEqual(map_names[10][2]["connections"], 12) - self.assertEqual(map_names[11][1]["connections"], 9) # or 13? - - def test_second_map_header_address(self): - self.assertEqual(map_names[11][1]["second_map_header_address"], 0x9509c) - self.assertEqual(map_names[1][5]["second_map_header_address"], 0x95bd0) - - def test_event_address(self): - self.assertEqual(map_names[17][5]["event_address"], 0x194d67) - self.assertEqual(map_names[23][3]["event_address"], 0x1a9ec9) - - def test_people_event_counts(self): - self.assertEqual(len(map_names[23][3]["people_events"]), 4) - self.assertEqual(len(map_names[10][3]["people_events"]), 9) - -class TestMetaTesting(unittest.TestCase): - """test whether or not i am finding at least - some of the tests in this file""" - tests = None - - def setUp(self): - if self.tests == None: - self.__class__.tests = assemble_test_cases() - - def test_assemble_test_cases_count(self): - "does assemble_test_cases find some tests?" - self.failUnless(len(self.tests) > 0) - - def test_assemble_test_cases_inclusion(self): - "is this class found by assemble_test_cases?" - # i guess it would have to be for this to be running? - self.failUnless(self.__class__ in self.tests) - - def test_assemble_test_cases_others(self): - "test other inclusions for assemble_test_cases" - self.failUnless(TestRomStr in self.tests) - self.failUnless(TestCram in self.tests) - - def test_check_has_test(self): - self.failUnless(check_has_test("beaver", ["test_beaver"])) - self.failUnless(check_has_test("beaver", ["test_beaver_2"])) - self.failIf(check_has_test("beaver_1", ["test_beaver"])) - - def test_find_untested_methods(self): - untested = find_untested_methods() - # the return type must be an iterable - self.failUnless(hasattr(untested, "__iter__")) - #.. basically, a list - self.failUnless(isinstance(untested, list)) - - def test_find_untested_methods_method(self): - """create a function and see if it is found""" - # setup a function in the global namespace - global some_random_test_method - # define the method - def some_random_test_method(): pass - # first make sure it is in the global scope - members = inspect.getmembers(sys.modules[__name__], inspect.isfunction) - func_names = [functuple[0] for functuple in members] - self.assertIn("some_random_test_method", func_names) - # test whether or not it is found by find_untested_methods - untested = find_untested_methods() - self.assertIn("some_random_test_method", untested) - # remove the test method from the global namespace - del some_random_test_method - - def test_load_tests(self): - loader = unittest.TestLoader() - suite = load_tests(loader, None, None) - suite._tests[0]._testMethodName - membership_test = lambda member: \ - inspect.isclass(member) and issubclass(member, unittest.TestCase) - tests = inspect.getmembers(sys.modules[__name__], membership_test) - classes = [x[1] for x in tests] - for test in suite._tests: - self.assertIn(test.__class__, classes) - - def test_report_untested(self): - untested = find_untested_methods() - output = report_untested() - if len(untested) > 0: - self.assertIn("NOT TESTED", output) - for name in untested: - self.assertIn(name, output) - elif len(untested) == 0: - self.assertNotIn("NOT TESTED", output) - -def assemble_test_cases(): - """finds classes that inherit from unittest.TestCase - because i am too lazy to remember to add them to a - global list of tests for the suite runner""" - classes = [] - clsmembers = inspect.getmembers(sys.modules[__name__], inspect.isclass) - for (name, some_class) in clsmembers: - if issubclass(some_class, unittest.TestCase): - classes.append(some_class) - return classes - -def load_tests(loader, tests, pattern): - suite = unittest.TestSuite() - for test_class in assemble_test_cases(): - tests = loader.loadTestsFromTestCase(test_class) - suite.addTests(tests) - return suite - -def check_has_test(func_name, tested_names): - """checks if there is a test dedicated to this function""" - if "test_"+func_name in tested_names: - return True - for name in tested_names: - if "test_"+func_name in name: - return True - return False - -def find_untested_methods(): - """finds all untested functions in this module - by searching for method names in test case - method names.""" - untested = [] - avoid_funcs = ["main", "run_tests", "run_main", "copy", "deepcopy"] - test_funcs = [] - # get a list of all classes in this module - classes = inspect.getmembers(sys.modules[__name__], inspect.isclass) - # for each class.. - for (name, klass) in classes: - # only look at those that have tests - if issubclass(klass, unittest.TestCase): - # look at this class' methods - funcs = inspect.getmembers(klass, inspect.ismethod) - # for each method.. - for (name2, func) in funcs: - # store the ones that begin with test_ - if "test_" in name2 and name2[0:5] == "test_": - test_funcs.append([name2, func]) - # assemble a list of all test method names (test_x, test_y, ..) - tested_names = [funcz[0] for funcz in test_funcs] - # now get a list of all functions in this module - funcs = inspect.getmembers(sys.modules[__name__], inspect.isfunction) - # for each function.. - for (name, func) in funcs: - # we don't care about some of these - if name in avoid_funcs: continue - # skip functions beginning with _ - if name[0] == "_": continue - # check if this function has a test named after it - has_test = check_has_test(name, tested_names) - if not has_test: - untested.append(name) - return untested - -def report_untested(): - """ - This reports about untested functions in the global namespace. This was - originally in the crystal module, where it would list out the majority of - the functions. Maybe it should be moved back. - """ - untested = find_untested_methods() - output = "NOT TESTED: [" - first = True - for name in untested: - if first: - output += name - first = False - else: output += ", "+name - output += "]\n" - output += "total untested: " + str(len(untested)) - return output - -def run_tests(): # rather than unittest.main() - loader = unittest.TestLoader() - suite = load_tests(loader, None, None) - unittest.TextTestRunner(verbosity=2).run(suite) - print report_untested() - # run the unit tests when this file is executed directly if __name__ == "__main__": - run_tests() + unittest.main() |