import os
import tempfile
import unittest
try:
from .romxml import RomXml
from .rom_database import RomDbKey
except ImportError: from romxml import RomXml
from rom_database import RomDbKey
class TestRomXml(unittest.TestCase):
def _write_xml(self, xml_text: str) -> str:
fd, path = tempfile.mkstemp(suffix=".xml")
with os.fdopen(fd, "w", encoding="utf-8") as handle:
handle.write(xml_text)
return path
def test_next_record_parses_fields_and_uppercases_crc(self) -> None:
xml_text = """
<database>
<game>
<rom crc32="a1b2c3d4" />
<pcb mirroring="horizontal" />
<console region="PAL" />
</game>
</database>
"""
path = self._write_xml(xml_text)
try:
parser = RomXml(path)
record = parser.next_record()
finally:
os.unlink(path)
self.assertEqual(
record,
{
RomDbKey.CRC.value: "A1B2C3D4",
RomDbKey.NAMETABLE_LAYOUT.value: "horizontal",
RomDbKey.HARDWARE.value: "1",
RomDbKey.PRG_ROM_SIZE.value: "0",
RomDbKey.PRG_RAM_SIZE.value: "0",
RomDbKey.PRG_NVRAM_SIZE.value: "0",
RomDbKey.CHR_ROM_SIZE.value: "0",
RomDbKey.CHR_RAM_SIZE.value: "0",
RomDbKey.CHR_NVRAM_SIZE.value: "0"
}
)
def test_next_record_handles_missing_fields(self) -> None:
xml_text = """
<database>
<game>
<rom />
<pcb />
<console />
</game>
</database>
"""
path = self._write_xml(xml_text)
try:
parser = RomXml(path)
record = parser.next_record()
finally:
os.unlink(path)
self.assertEqual(record, {
RomDbKey.PRG_ROM_SIZE.value: "0",
RomDbKey.PRG_RAM_SIZE.value: "0",
RomDbKey.PRG_NVRAM_SIZE.value: "0",
RomDbKey.CHR_ROM_SIZE.value: "0",
RomDbKey.CHR_RAM_SIZE.value: "0",
RomDbKey.CHR_NVRAM_SIZE.value: "0"
})
def test_next_record_multiple_games(self) -> None:
xml_text = """
<database>
<game>
<rom crc32="00000001" />
</game>
<game>
<rom crc32="00000002" />
<pcb mirroring="vertical" />
</game>
</database>
"""
path = self._write_xml(xml_text)
try:
parser = RomXml(path)
first = parser.next_record()
second = parser.next_record()
third = parser.next_record()
finally:
os.unlink(path)
self.assertEqual(first, {
RomDbKey.CRC.value: "00000001",
RomDbKey.PRG_ROM_SIZE.value: "0",
RomDbKey.PRG_RAM_SIZE.value: "0",
RomDbKey.PRG_NVRAM_SIZE.value: "0",
RomDbKey.CHR_ROM_SIZE.value: "0",
RomDbKey.CHR_RAM_SIZE.value: "0",
RomDbKey.CHR_NVRAM_SIZE.value: "0"
})
self.assertEqual(second, {
RomDbKey.CRC.value: "00000002",
RomDbKey.NAMETABLE_LAYOUT.value: "vertical",
RomDbKey.PRG_ROM_SIZE.value: "0",
RomDbKey.PRG_RAM_SIZE.value: "0",
RomDbKey.PRG_NVRAM_SIZE.value: "0",
RomDbKey.CHR_ROM_SIZE.value: "0",
RomDbKey.CHR_RAM_SIZE.value: "0",
RomDbKey.CHR_NVRAM_SIZE.value: "0"
})
self.assertIsNone(third)
def test_next_record_ignores_non_game_elements(self) -> None:
xml_text = """
<database>
<header version="1" />
<game>
<rom crc32="deadbeef" />
</game>
</database>
"""
path = self._write_xml(xml_text)
try:
parser = RomXml(path)
record = parser.next_record()
finally:
os.unlink(path)
self.assertEqual(record, {
RomDbKey.CRC.value: "DEADBEEF",
RomDbKey.PRG_ROM_SIZE.value: "0",
RomDbKey.PRG_RAM_SIZE.value: "0",
RomDbKey.PRG_NVRAM_SIZE.value: "0",
RomDbKey.CHR_ROM_SIZE.value: "0",
RomDbKey.CHR_RAM_SIZE.value: "0",
RomDbKey.CHR_NVRAM_SIZE.value: "0"
})
def test_next_record_missing_crc_is_omitted(self) -> None:
xml_text = """
<database>
<game>
<rom size="16" />
</game>
</database>
"""
path = self._write_xml(xml_text)
try:
parser = RomXml(path)
record = parser.next_record()
finally:
os.unlink(path)
self.assertEqual(record, {
RomDbKey.PRG_ROM_SIZE.value: "0",
RomDbKey.PRG_RAM_SIZE.value: "0",
RomDbKey.PRG_NVRAM_SIZE.value: "0",
RomDbKey.CHR_ROM_SIZE.value: "0",
RomDbKey.CHR_RAM_SIZE.value: "0",
RomDbKey.CHR_NVRAM_SIZE.value: "0"
})
def test_next_record_parses_extended_rom_info(self) -> None:
xml_text = """
<database>
<game>
<!-- Licensed Japan 10-Yard Fight (rev0).nes -->
<prgrom size="16384" crc32="D3D248C9" sha1="64185EDC4FD64B5F5E565B90B0DDC241592D899C" sum16="0339"/>
<chrrom size="8192" crc32="9C124A53" sha1="BEDDF6A65A1A72410CFB1208E8B6B6E0CF5B2E74" sum16="16E5"/>
<rom size="24576" crc32="836C4FA7" sha1="55DC03A493150258E10166CF38ED76DFADE605D6"/>
<chrnvram size="8192"/>
<chrram size="8192"/>
<prgnvram size="8192"/>
<prgram size="8192"/>
<pcb mapper="0" submapper="0" mirroring="H" battery="0"/>
<console type="0" region="0"/>
<expansion type="1"/>
<vs hardware="0" ppu="5"/>
</game>
</database>
"""
path = self._write_xml(xml_text)
try:
parser = RomXml(path)
record = parser.next_record()
finally:
os.unlink(path)
self.assertEqual(
record,
{
RomDbKey.CRC.value: "836C4FA7",
RomDbKey.PRG_ROM_SIZE.value: "16384",
RomDbKey.PRG_ROM_CRC.value: "D3D248C9",
RomDbKey.PRG_NVRAM_SIZE.value: "8192",
RomDbKey.PRG_RAM_SIZE.value: "8192",
RomDbKey.CHR_ROM_SIZE.value: "8192",
RomDbKey.CHR_ROM_CRC.value: "9C124A53",
RomDbKey.CHR_NVRAM_SIZE.value: "8192",
RomDbKey.CHR_RAM_SIZE.value: "8192",
RomDbKey.MAPPER.value: "0",
RomDbKey.SUBMAPPER.value: "0",
RomDbKey.NAMETABLE_LAYOUT.value: "H",
RomDbKey.BATTERY.value: "0",
RomDbKey.HARDWARE.value: "2",
RomDbKey.EXPANSION_TYPE.value: "1",
RomDbKey.VS_HARDWARE_TYPE.value: "0",
RomDbKey.VS_PPU_TYPE.value: "5",
RomDbKey.CONSOLE_CLASS.value: "Licensed Japan 10-Yard Fight (rev0).nes"
},
)
def test_next_record_parses_extended_rom_info_missing_optional(self) -> None:
xml_text = """
<database>
<game>
<rom crc32="1234abcd" />
<pcb mapper="2" />
</game>
</database>
"""
path = self._write_xml(xml_text)
try:
parser = RomXml(path)
record = parser.next_record()
finally:
os.unlink(path)
self.assertEqual(record, {
RomDbKey.CRC.value: "1234ABCD",
RomDbKey.MAPPER.value: "2",
RomDbKey.PRG_ROM_SIZE.value: "0",
RomDbKey.PRG_RAM_SIZE.value: "0",
RomDbKey.PRG_NVRAM_SIZE.value: "0",
RomDbKey.CHR_ROM_SIZE.value: "0",
RomDbKey.CHR_RAM_SIZE.value: "0",
RomDbKey.CHR_NVRAM_SIZE.value: "0"
})
def test_normalize_label(self) -> None:
self.assertEqual(RomXml._normalize_label(None), "")
self.assertEqual(RomXml._normalize_label(" A B "), "A B")
self.assertEqual(RomXml._normalize_label("Label:"), "Label")
if __name__ == "__main__":
unittest.main()