Update gcmtest.py

Added 10 custom exceptions and tests for it; std documentation added
This commit is contained in:
tmpz23 2022-06-12 18:55:43 +02:00 committed by GitHub
parent fd1b0145c8
commit 09581855ff
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23

View File

@ -3,9 +3,11 @@ from pathlib import Path
import os import os
import shutil import shutil
from time import time from time import time
from gcmtool import Gcm
from gcmtool import InvalidDVDMagicError, InvalidUnpackFolderError, InvalidPackIsoError, InvalidFSTSizeError, DolSizeOverflowError, InvalidRootFileFolderCountError, InvalidFSTFileSizeError, FSTDirNotFoundError, FSTFileNotFoundError, BadAlignError
__version__ = "0.0.7" __version__ = "0.0.8"
__author__ = "rigodron, algoflash, GGLinnk" __author__ = "rigodron, algoflash, GGLinnk"
__license__ = "MIT" __license__ = "MIT"
__status__ = "developpement" __status__ = "developpement"
@ -48,8 +50,8 @@ def print_paths_differences(folder1_paths:list, folder2_paths:list):
print(path) print(path)
# compare two files
def compare_files(file1_path:Path, file2_path:Path): def compare_files(file1_path:Path, file2_path:Path):
"Compare two files."
CLUSTER_LEN = 131072 CLUSTER_LEN = 131072
with file1_path.open("rb") as file1, file2_path.open("rb") as file2: with file1_path.open("rb") as file1, file2_path.open("rb") as file2:
# Init # Init
@ -63,9 +65,11 @@ def compare_files(file1_path:Path, file2_path:Path):
return True return True
# compare two GCM
# -> raise an exception if there is a difference
def compare_GCM(folder1: Path, folder2: Path): def compare_GCM(folder1: Path, folder2: Path):
"""
Compare two GCM
-> raise an exception if there is a difference
"""
folder1_root_paths = list((folder1 / "root").glob("**/*")) folder1_root_paths = list((folder1 / "root").glob("**/*"))
folder1_file_count = len(folder1_root_paths) folder1_file_count = len(folder1_root_paths)
print(f"compare \"{folder1}\" - \"{folder2}\" ({folder1_file_count} files)") print(f"compare \"{folder1}\" - \"{folder2}\" ({folder1_file_count} files)")
@ -110,7 +114,7 @@ def gcmtool_stats(path:Path):
raise Exception("Error while getting stats.") raise Exception("Error while getting stats.")
TEST_COUNT = 4 TEST_COUNT = 5
start = time() start = time()
print("###############################################################################") print("###############################################################################")
@ -121,7 +125,6 @@ if unpack_path.is_dir() or unpack2_path.is_dir() or repack_path.is_dir():
raise Exception(f"Error - Please remove:\n-{unpack_path}\n-{unpack2_path}\n-{repack_path}") raise Exception(f"Error - Please remove:\n-{unpack_path}\n-{unpack2_path}\n-{repack_path}")
test_storage() test_storage()
print("###############################################################################") print("###############################################################################")
print(f"# TEST 1/{TEST_COUNT}") print(f"# TEST 1/{TEST_COUNT}")
print("# Comparing roms_path->unpack->[unpack_path] ROMs with [dolphin_unpack_path]") print("# Comparing roms_path->unpack->[unpack_path] ROMs with [dolphin_unpack_path]")
@ -140,7 +143,6 @@ print("#########################################################################
print(f"# TEST 2/{TEST_COUNT}") print(f"# TEST 2/{TEST_COUNT}")
print("# Testing stats on folders & isos") print("# Testing stats on folders & isos")
print("###############################################################################") print("###############################################################################")
for iso_path in roms_path.glob("*"): for iso_path in roms_path.glob("*"):
if iso_path.is_file(): if iso_path.is_file():
gcmtool_stats(iso_path) gcmtool_stats(iso_path)
@ -192,20 +194,164 @@ unpack2_path.mkdir()
for iso_path in repack_path.glob("*"): for iso_path in repack_path.glob("*"):
gcmtool_unpack(iso_path, unpack2_path / iso_path.name) gcmtool_unpack(iso_path, unpack2_path / iso_path.name)
# remove repack_path
shutil.rmtree(repack_path)
# compare unpack_path unpack2_path # compare unpack_path unpack2_path
for folder_path in unpack_path.glob("*"): for folder_path in unpack_path.glob("*"):
compare_GCM(folder_path, unpack2_path / folder_path.name) compare_GCM(folder_path, unpack2_path / folder_path.name)
# remove unpack2_path
shutil.rmtree(unpack_path)
shutil.rmtree(unpack2_path)
print("###############################################################################")
print(f"# TEST 5/{TEST_COUNT}")
print("# Testing exceptions.")
print("###############################################################################")
gcm = Gcm()
first_repacked = list(repack_path.glob("*"))[0]
# change DVD magic
with first_repacked.open("rb+") as first_repacked_file:
first_repacked_file.seek(0x1c)
first_repacked_file.write(b"\xC2\x33\x9F\x3E")
try:
gcm.unpack(first_repacked, unpack2_path / first_repacked.name)
raise Exception("Error - InvalidDVDMagicError should have been triggered.")
except InvalidDVDMagicError:
print("Correct InvalidDVDMagicError triggered.")
# restore DVD magic
with first_repacked.open("rb+") as first_repacked_file:
first_repacked_file.seek(0x1c)
first_repacked_file.write(b"\xC2\x33\x9F\x3D")
(unpack2_path / first_repacked.stem).mkdir(parents=True)
try:
gcm.unpack(first_repacked, unpack2_path / first_repacked.stem)
raise Exception("Error - InvalidUnpackFolderError should have been triggered.")
except InvalidUnpackFolderError:
print("Correct InvalidUnpackFolderError triggered.")
shutil.rmtree(unpack2_path)
unpack_path.mkdir()
first_unpacked = unpack_path / "Final Fantasy - Crystal Chronicles (Europe) (En,Fr,De,Es,It).iso"
gcmtool_unpack(roms_path / first_unpacked.name, first_unpacked)
try:
gcm.pack(first_unpacked, first_repacked)
raise Exception("Error - InvalidPackIsoError should have been triggered.")
except InvalidPackIsoError:
print("Correct InvalidPackIsoError triggered.")
fst_data = (first_unpacked / "sys/fst.bin").read_bytes()
(first_unpacked / "sys/fst.bin").write_bytes(fst_data + b"\x00")
try:
gcm.pack(first_unpacked, repack_path / (first_unpacked.stem + "except.iso"))
raise Exception("Error - InvalidFSTSizeError should have been triggered.")
except InvalidFSTSizeError:
print("Correct InvalidFSTSizeError triggered.")
(first_unpacked / "sys/fst.bin").write_bytes(fst_data)
(first_unpacked / "root/aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa").mkdir()
try:
gcm.pack(first_unpacked, repack_path / (first_unpacked.stem + "except.iso"))
raise Exception("Error - InvalidRootFileFolderCountError should have been triggered.")
except InvalidRootFileFolderCountError:
print("Correct InvalidRootFileFolderCountError triggered.")
(first_unpacked / "root/aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa").rmdir()
first_unpacked_file = None
first_unpacked_dir = None
for path in (first_unpacked / "root").glob("*"):
if path.is_file() and first_unpacked_file is None:
first_unpacked_file = path
elif path.is_dir() and first_unpacked_dir is None:
first_unpacked_dir = path
if first_unpacked_file is not None and first_unpacked_dir is not None:
break
first_unpacked_file_data = first_unpacked_file.read_bytes()
first_unpacked_file.write_bytes(first_unpacked_file_data + b"\x00")
try:
gcm.pack(first_unpacked, repack_path / (first_unpacked.stem + "except.iso"))
raise Exception("Error - InvalidFSTFileSizeError should have been triggered.")
except InvalidFSTFileSizeError:
print("Correct InvalidFSTFileSizeError triggered.")
first_unpacked_file.write_bytes(first_unpacked_file_data)
new_dir = first_unpacked_dir.rename(first_unpacked_dir.parent / (first_unpacked_dir.name +"aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"))
try:
gcm.pack(first_unpacked, repack_path / (first_unpacked.stem + "except.iso"))
raise Exception("Error - FSTDirNotFoundError should have been triggered.")
except FSTDirNotFoundError:
print("Correct FSTDirNotFoundError triggered.")
new_dir.rename(first_unpacked_dir)
new_file = first_unpacked_file.rename(first_unpacked_file.parent / (first_unpacked_file.name +"aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"))
try:
gcm.pack(first_unpacked, repack_path / (first_unpacked.stem + "except.iso"))
raise Exception("Error - FSTFileNotFoundError should have been triggered.")
except FSTFileNotFoundError:
print("Correct FSTFileNotFoundError triggered.")
new_file.rename(first_unpacked_file)
try:
gcm.stats(first_unpacked, 0x800)
raise Exception("Error - BadAlignError should have been triggered.")
except BadAlignError:
print("Correct BadAlignError triggered.")
#| 0001ec00 | 0023f9a0 | 00220da0 | boot.dol
#| 0023fa00 | 00276058 | 00036658 | fst.bin
# dol size for overflowing on FST + 1: 0023fa00 - 0001ec00 = 220e00
backup_dol_data = (first_unpacked / "sys/boot.dol").read_bytes()
with (first_unpacked / "sys/boot.dol").open("rb+") as bootdol_file:
bootdol_file.seek(0x220e00)
bootdol_file.write(b"\x00")
try:
gcm.pack(first_unpacked, repack_path / (first_unpacked.stem + "except.iso"))
raise Exception("Error - DolSizeOverflowError should have been triggered.")
except DolSizeOverflowError:
print("Correct DolSizeOverflowError triggered.")
(first_unpacked / "sys/boot.dol").write_bytes(backup_dol_data)
with (first_unpacked / "sys/boot.dol").open("rb+") as bootdol_file:
bootdol_file.seek(0x220dff)
bootdol_file.write(b"\x00")
gcm.pack(first_unpacked, repack_path / (first_unpacked.stem + "ok1.iso"))
print("Correct pack with max dol size before FST.")
# patch boot.bin to put fst before dol and make dol overflow on first file
# fst_len = 00036658 and new offset 0001ec00
with (first_unpacked / "sys/boot.bin").open("rb+") as bootbin:
bootbin.seek(0x420) # dol offset
bootbin.write(b"\x00\x05\x53\x00") # after the FST
# now seeked on FST offset
bootbin.write(b"\x00\x01\xEC\x00") # replace the dol
#| 0001ec00 | 00055258 | 00036658 | fst.bin
#| 00055300 | ? | ? | boot.dol
#| 00278000 | 005111de | 002991de | game.MAP
# max dol size = 00278000 - 00055300 = 222D00
with (first_unpacked / "sys/boot.dol").open("rb+") as bootdol_file:
bootdol_file.seek(0x222cff)
bootdol_file.write(b"\x00")
gcm.pack(first_unpacked, repack_path / (first_unpacked.stem + "ok2.iso"))
print("Correct pack with max dol size before first file.")
with (first_unpacked / "sys/boot.dol").open("rb+") as first_unpacked_file:
first_unpacked_file.seek(0x222d00)
first_unpacked_file.write(b"\x00")
try:
gcm.pack(first_unpacked, repack_path / (first_unpacked.stem + "except.iso"))
raise Exception("Error - DolSizeOverflowError should have been triggered.")
except DolSizeOverflowError:
print("Correct DolSizeOverflowError triggered.")
# Remove tests folders # Remove tests folders
print("###############################################################################") print("###############################################################################")
print(f"# Cleaning test folders.") print(f"# Cleaning test folders.")
print("###############################################################################") print("###############################################################################")
shutil.rmtree(repack_path)
shutil.rmtree(unpack_path) shutil.rmtree(unpack_path)
shutil.rmtree(unpack2_path)
end = time() end = time()
print("###############################################################################") print("###############################################################################")