diff --git a/src/modules/romHeaderProcessor.ts b/src/modules/romHeaderProcessor.ts index 182a52292..de9b6fcda 100644 --- a/src/modules/romHeaderProcessor.ts +++ b/src/modules/romHeaderProcessor.ts @@ -2,6 +2,7 @@ import ProgressBar, { ProgressBarSymbol } from '../console/progressBar.js'; import DriveSemaphore from '../driveSemaphore.js'; import ArchiveEntry from '../types/files/archives/archiveEntry.js'; import File from '../types/files/file.js'; +import FileCache from '../types/files/fileCache.js'; import ROMHeader from '../types/files/romHeader.js'; import Options from '../types/options.js'; import Module from './module.js'; @@ -72,30 +73,17 @@ export default class ROMHeaderProcessor extends Module { return inputFile; } - // Can get FileHeader from extension, use that - const headerForFilename = ROMHeader.headerFromFilename(inputFile.getExtractedFilePath()); - if (headerForFilename) { - this.progressBar.logTrace(`${inputFile.toString()}: reading potentially headered file by filename: ${headerForFilename.getHeaderedFileExtension()}`); - const fileWithHeader = await inputFile.withFileHeader(headerForFilename); - if (fileWithHeader.getFileHeader()) { - this.progressBar.logTrace(`${inputFile.toString()}: found header by filename: ${headerForFilename.getHeaderedFileExtension()}`); - } else { - this.progressBar.logTrace(`${inputFile.toString()}: found non-applicable header by filename: ${headerForFilename.getHeaderedFileExtension()}`); - } - return fileWithHeader; - } - // Should get FileHeader from File, try to - if (this.options.shouldReadFileForHeader(inputFile.getExtractedFilePath())) { + if (ROMHeader.headerFromFilename(inputFile.getExtractedFilePath()) !== undefined + || this.options.shouldReadFileForHeader(inputFile.getExtractedFilePath()) + ) { this.progressBar.logTrace(`${inputFile.toString()}: reading potentially headered file by file contents`); - const headerForFileStream = await inputFile.createReadStream( - async (stream) => ROMHeader.headerFromFileStream(stream), - ); + const headerForFileStream = await FileCache.getOrComputeFileHeader(inputFile); if (headerForFileStream) { this.progressBar.logTrace(`${inputFile.toString()}: found header by file contents: ${headerForFileStream.getHeaderedFileExtension()}`); return inputFile.withFileHeader(headerForFileStream); } - this.progressBar.logWarn(`${inputFile.toString()}: didn't find header by file contents`); + this.progressBar.logTrace(`${inputFile.toString()}: didn't find header by file contents`); } // Should not get FileHeader diff --git a/src/types/files/archives/archiveEntry.ts b/src/types/files/archives/archiveEntry.ts index c97191392..e3439c59a 100644 --- a/src/types/files/archives/archiveEntry.ts +++ b/src/types/files/archives/archiveEntry.ts @@ -233,14 +233,9 @@ export default class ArchiveEntry extends File implements Arc } async withFileHeader(fileHeader: ROMHeader): Promise> { - // Make sure the file actually has the right file signature - const hasHeader = await this.createReadStream( - async (stream) => fileHeader.fileHasHeader(stream), - ); - if (!hasHeader) { + if (fileHeader === this.fileHeader) { return this; } - return ArchiveEntry.entryOf({ ...this, fileHeader, diff --git a/src/types/files/file.ts b/src/types/files/file.ts index 9ee2f0f4f..1c5148786 100644 --- a/src/types/files/file.ts +++ b/src/types/files/file.ts @@ -444,14 +444,9 @@ export default class File implements FileProps { } async withFileHeader(fileHeader: ROMHeader): Promise { - // Make sure the file actually has the right file signature - const hasHeader = await this.createReadStream( - async (stream) => fileHeader.fileHasHeader(stream), - ); - if (!hasHeader) { + if (fileHeader === this.fileHeader) { return this; } - return File.fileOf({ ...this, fileHeader, diff --git a/src/types/files/fileCache.ts b/src/types/files/fileCache.ts index dbea08dff..1ff231586 100644 --- a/src/types/files/fileCache.ts +++ b/src/types/files/fileCache.ts @@ -6,16 +6,18 @@ import Archive from './archives/archive.js'; import ArchiveEntry, { ArchiveEntryProps } from './archives/archiveEntry.js'; import File, { FileProps } from './file.js'; import { ChecksumBitmask } from './fileChecksums.js'; +import ROMHeader from './romHeader.js'; interface CacheValue { fileSize: number, modifiedTimeMillis: number, - value: FileProps | ArchiveEntryProps[], + value: FileProps | ArchiveEntryProps[] | string | undefined, } enum ValueType { - FILE = 'F', - ARCHIVE_ENTRIES = 'A', + FILE_CHECKSUMS = 'F', + ARCHIVE_CHECKSUMS = 'A', + FILE_HEADER = 'H', } export default class FileCache { @@ -43,6 +45,7 @@ export default class FileCache { const keyRegex = new RegExp(`^V${prevVersion}\\|`); return this.cache.delete(keyRegex); })); + // await this.cache.delete(new RegExp(`\\|[^${Object.values(ValueType).join()}]$`)); // Delete keys for deleted files const disks = FsPoly.disksSync(); @@ -71,7 +74,7 @@ export default class FileCache { await this.cache.save(); } - static async getOrComputeFile( + static async getOrComputeFileChecksums( filePath: string, checksumBitmask: number, ): Promise { @@ -81,7 +84,7 @@ export default class FileCache { // NOTE(cemmer): we're explicitly not catching ENOENT errors here, we want it to bubble up const stats = await FsPoly.stat(filePath); - const cacheKey = this.getCacheKey(filePath, ValueType.FILE); + const cacheKey = this.getCacheKey(filePath, ValueType.FILE_CHECKSUMS); // NOTE(cemmer): we're using the cache as a mutex here, so even if this function is called // multiple times concurrently, entries will only be fetched once. @@ -131,7 +134,7 @@ export default class FileCache { }); } - static async getOrComputeEntries( + static async getOrComputeArchiveChecksums( archive: T, checksumBitmask: number, ): Promise[]> { @@ -141,7 +144,7 @@ export default class FileCache { // NOTE(cemmer): we're explicitly not catching ENOENT errors here, we want it to bubble up const stats = await FsPoly.stat(archive.getFilePath()); - const cacheKey = this.getCacheKey(archive.getFilePath(), ValueType.ARCHIVE_ENTRIES); + const cacheKey = this.getCacheKey(archive.getFilePath(), ValueType.ARCHIVE_CHECKSUMS); // NOTE(cemmer): we're using the cache as a mutex here, so even if this function is called // multiple times concurrently, entries will only be fetched once. @@ -192,6 +195,39 @@ export default class FileCache { }))); } + static async getOrComputeFileHeader(file: File): Promise { + // NOTE(cemmer): we're explicitly not catching ENOENT errors here, we want it to bubble up + const stats = await FsPoly.stat(file.getFilePath()); + const cacheKey = this.getCacheKey(file.toString(), ValueType.FILE_HEADER); + + const cachedValue = await this.cache.getOrCompute( + cacheKey, + async () => { + const header = await file.createReadStream( + async (stream) => ROMHeader.headerFromFileStream(stream), + ); + return { + fileSize: stats.size, + modifiedTimeMillis: stats.mtimeMs, + value: header?.getName(), + }; + }, + (cached) => { + if (cached.fileSize !== stats.size || cached.modifiedTimeMillis !== stats.mtimeMs) { + // File has changed since being cached + return true; + } + return false; + }, + ); + + const cachedHeaderName = cachedValue.value as string | undefined; + if (!cachedHeaderName) { + return undefined; + } + return ROMHeader.headerFromName(cachedHeaderName); + } + private static getCacheKey(filePath: string, valueType: ValueType): string { return `V${FileCache.VERSION}|${filePath}|${valueType}`; } diff --git a/src/types/files/fileFactory.ts b/src/types/files/fileFactory.ts index fc030ceb5..f5cc86ae6 100644 --- a/src/types/files/fileFactory.ts +++ b/src/types/files/fileFactory.ts @@ -49,7 +49,7 @@ export default class FileFactory { filePath: string, checksumBitmask: number, ): Promise { - return FileCache.getOrComputeFile(filePath, checksumBitmask); + return FileCache.getOrComputeFileChecksums(filePath, checksumBitmask); } public static async archiveFileFrom( @@ -94,7 +94,7 @@ export default class FileFactory { return undefined; } - return FileCache.getOrComputeEntries(archive, checksumBitmask); + return FileCache.getOrComputeArchiveChecksums(archive, checksumBitmask); } /** diff --git a/src/types/files/romHeader.ts b/src/types/files/romHeader.ts index acf6bc5ee..1f4d04681 100644 --- a/src/types/files/romHeader.ts +++ b/src/types/files/romHeader.ts @@ -1,6 +1,8 @@ import path from 'node:path'; import { Readable } from 'node:stream'; +import { Memoize } from 'typescript-memoize'; + import ArrayPoly from '../../polyfill/arrayPoly.js'; export default class ROMHeader { @@ -62,6 +64,10 @@ export default class ROMHeader { .sort(); } + static headerFromName(name: string): ROMHeader | undefined { + return this.HEADERS[name]; + } + static headerFromFilename(filePath: string): ROMHeader | undefined { const headers = Object.values(this.HEADERS); for (const header of headers) { @@ -123,6 +129,12 @@ export default class ROMHeader { return undefined; } + @Memoize() + getName(): string { + return Object.keys(ROMHeader.HEADERS) + .find((name) => ROMHeader.HEADERS[name] === this) as string; + } + getDataOffsetBytes(): number { return this.dataOffsetBytes; } @@ -134,13 +146,4 @@ export default class ROMHeader { getHeaderlessFileExtension(): string { return this.headerlessFileExtension; } - - async fileHasHeader(stream: Readable): Promise { - const header = await ROMHeader.readHeaderHex( - stream, - this.headerOffsetBytes, - this.headerOffsetBytes + this.headerValue.length / 2, - ); - return header.toUpperCase() === this.headerValue.toUpperCase(); - } } diff --git a/test/types/files/archives/archiveEntry.test.ts b/test/types/files/archives/archiveEntry.test.ts index be357fd53..248d8b7cd 100644 --- a/test/types/files/archives/archiveEntry.test.ts +++ b/test/types/files/archives/archiveEntry.test.ts @@ -179,34 +179,6 @@ describe('getCrc32WithoutHeader', () => { expect(archiveEntry.getSha256WithoutHeader()).toBeUndefined(); }); - test.each([ - ['./test/fixtures/roms/7z/fizzbuzz.7z', '370517b5'], - ['./test/fixtures/roms/gz/fizzbuzz.gz', '370517b5'], - ['./test/fixtures/roms/rar/fizzbuzz.rar', '370517b5'], - ['./test/fixtures/roms/tar/fizzbuzz.tar.gz', '370517b5'], - ['./test/fixtures/roms/zip/fizzbuzz.zip', '370517b5'], - ['./test/fixtures/roms/7z/foobar.7z', 'b22c9747'], - ['./test/fixtures/roms/gz/foobar.gz', 'b22c9747'], - ['./test/fixtures/roms/rar/foobar.rar', 'b22c9747'], - ['./test/fixtures/roms/tar/foobar.tar.gz', 'b22c9747'], - ['./test/fixtures/roms/zip/foobar.zip', 'b22c9747'], - ])('should hash the full archive entry when header is given but not present in file: %s', async (filePath, expectedCrc) => { - const archiveEntries = await FileFactory.filesFrom(filePath); - expect(archiveEntries).toHaveLength(1); - const archiveEntry = await archiveEntries[0].withFileHeader( - ROMHeader.headerFromFilename(archiveEntries[0].getExtractedFilePath()) as ROMHeader, - ); - - expect(archiveEntry.getCrc32()).toEqual(expectedCrc); - expect(archiveEntry.getCrc32WithoutHeader()).toEqual(expectedCrc); - expect(archiveEntry.getMd5()).toBeUndefined(); - expect(archiveEntry.getMd5WithoutHeader()).toBeUndefined(); - expect(archiveEntry.getSha1()).toBeUndefined(); - expect(archiveEntry.getSha1WithoutHeader()).toBeUndefined(); - expect(archiveEntry.getSha256()).toBeUndefined(); - expect(archiveEntry.getSha256WithoutHeader()).toBeUndefined(); - }); - test.each([ ['./test/fixtures/roms/headered/diagnostic_test_cartridge.a78.7z', 'a1eaa7c1'], ['./test/fixtures/roms/headered/fds_joypad_test.fds.zip', '3ecbac61'], @@ -298,33 +270,6 @@ describe('getMd5WithoutHeader', () => { expect(archiveEntry.getSha256WithoutHeader()).toBeUndefined(); }); - test.each([ - ['./test/fixtures/roms/7z/fizzbuzz.7z', 'cbe8410861130a91609295349918c2c2'], - ['./test/fixtures/roms/gz/fizzbuzz.gz', 'cbe8410861130a91609295349918c2c2'], - ['./test/fixtures/roms/rar/fizzbuzz.rar', 'cbe8410861130a91609295349918c2c2'], - ['./test/fixtures/roms/tar/fizzbuzz.tar.gz', 'cbe8410861130a91609295349918c2c2'], - ['./test/fixtures/roms/zip/fizzbuzz.zip', 'cbe8410861130a91609295349918c2c2'], - ['./test/fixtures/roms/7z/foobar.7z', '14758f1afd44c09b7992073ccf00b43d'], - ['./test/fixtures/roms/gz/foobar.gz', '14758f1afd44c09b7992073ccf00b43d'], - ['./test/fixtures/roms/rar/foobar.rar', '14758f1afd44c09b7992073ccf00b43d'], - ['./test/fixtures/roms/tar/foobar.tar.gz', '14758f1afd44c09b7992073ccf00b43d'], - ['./test/fixtures/roms/zip/foobar.zip', '14758f1afd44c09b7992073ccf00b43d'], - ])('should hash the full archive entry when header is given but not present in file: %s', async (filePath, expectedMd5) => { - const archiveEntries = await FileFactory.filesFrom(filePath, ChecksumBitmask.MD5); - expect(archiveEntries).toHaveLength(1); - const archiveEntry = await archiveEntries[0].withFileHeader( - ROMHeader.headerFromFilename(archiveEntries[0].getExtractedFilePath()) as ROMHeader, - ); - - // Some archives store CRC32, or otherwise it won't be defined - expect(archiveEntry.getMd5()).toEqual(expectedMd5); - expect(archiveEntry.getMd5WithoutHeader()).toEqual(expectedMd5); - expect(archiveEntry.getSha1()).toBeUndefined(); - expect(archiveEntry.getSha1WithoutHeader()).toBeUndefined(); - expect(archiveEntry.getSha256()).toBeUndefined(); - expect(archiveEntry.getSha256WithoutHeader()).toBeUndefined(); - }); - test.each([ ['./test/fixtures/roms/headered/diagnostic_test_cartridge.a78.7z', '91041aadd1700a7a4076f4005f2c362f'], ['./test/fixtures/roms/headered/fds_joypad_test.fds.zip', '26df56a7e5b096577338bcc4c334ec7d'], @@ -416,33 +361,6 @@ describe('getSha1WithoutHeader', () => { expect(archiveEntry.getSha256WithoutHeader()).toBeUndefined(); }); - test.each([ - ['./test/fixtures/roms/7z/fizzbuzz.7z', '5a316d9f0e06964d94cdd62a933803d7147ddadb'], - ['./test/fixtures/roms/gz/fizzbuzz.gz', '5a316d9f0e06964d94cdd62a933803d7147ddadb'], - ['./test/fixtures/roms/rar/fizzbuzz.rar', '5a316d9f0e06964d94cdd62a933803d7147ddadb'], - ['./test/fixtures/roms/tar/fizzbuzz.tar.gz', '5a316d9f0e06964d94cdd62a933803d7147ddadb'], - ['./test/fixtures/roms/zip/fizzbuzz.zip', '5a316d9f0e06964d94cdd62a933803d7147ddadb'], - ['./test/fixtures/roms/7z/foobar.7z', '988881adc9fc3655077dc2d4d757d480b5ea0e11'], - ['./test/fixtures/roms/gz/foobar.gz', '988881adc9fc3655077dc2d4d757d480b5ea0e11'], - ['./test/fixtures/roms/rar/foobar.rar', '988881adc9fc3655077dc2d4d757d480b5ea0e11'], - ['./test/fixtures/roms/tar/foobar.tar.gz', '988881adc9fc3655077dc2d4d757d480b5ea0e11'], - ['./test/fixtures/roms/zip/foobar.zip', '988881adc9fc3655077dc2d4d757d480b5ea0e11'], - ])('should hash the full archive entry when header is given but not present in file: %s', async (filePath, expectedSha1) => { - const archiveEntries = await FileFactory.filesFrom(filePath, ChecksumBitmask.SHA1); - expect(archiveEntries).toHaveLength(1); - const archiveEntry = await archiveEntries[0].withFileHeader( - ROMHeader.headerFromFilename(archiveEntries[0].getExtractedFilePath()) as ROMHeader, - ); - - // Some archives store CRC32, or otherwise it won't be defined - expect(archiveEntry.getMd5()).toBeUndefined(); - expect(archiveEntry.getMd5WithoutHeader()).toBeUndefined(); - expect(archiveEntry.getSha1()).toEqual(expectedSha1); - expect(archiveEntry.getSha1WithoutHeader()).toEqual(expectedSha1); - expect(archiveEntry.getSha256()).toBeUndefined(); - expect(archiveEntry.getSha256WithoutHeader()).toBeUndefined(); - }); - test.each([ ['./test/fixtures/roms/headered/diagnostic_test_cartridge.a78.7z', '76ec76c423d88bdf739e673c051c5b9c174881c6'], ['./test/fixtures/roms/headered/fds_joypad_test.fds.zip', '7b6bd1a69bbc5d8121c72dd1eedfb6752fe11787'], @@ -534,33 +452,6 @@ describe('getSha256WithoutHeader', () => { expect(archiveEntry.getSha256WithoutHeader()).toEqual(expectedSha256); }); - test.each([ - ['./test/fixtures/roms/7z/fizzbuzz.7z', '6e809804766eaa4dd42a2607b789f3e4e5d32fc321ba8dd3ef39ddc1ea2888e9'], - ['./test/fixtures/roms/gz/fizzbuzz.gz', '6e809804766eaa4dd42a2607b789f3e4e5d32fc321ba8dd3ef39ddc1ea2888e9'], - ['./test/fixtures/roms/rar/fizzbuzz.rar', '6e809804766eaa4dd42a2607b789f3e4e5d32fc321ba8dd3ef39ddc1ea2888e9'], - ['./test/fixtures/roms/tar/fizzbuzz.tar.gz', '6e809804766eaa4dd42a2607b789f3e4e5d32fc321ba8dd3ef39ddc1ea2888e9'], - ['./test/fixtures/roms/zip/fizzbuzz.zip', '6e809804766eaa4dd42a2607b789f3e4e5d32fc321ba8dd3ef39ddc1ea2888e9'], - ['./test/fixtures/roms/7z/foobar.7z', 'aec070645fe53ee3b3763059376134f058cc337247c978add178b6ccdfb0019f'], - ['./test/fixtures/roms/gz/foobar.gz', 'aec070645fe53ee3b3763059376134f058cc337247c978add178b6ccdfb0019f'], - ['./test/fixtures/roms/rar/foobar.rar', 'aec070645fe53ee3b3763059376134f058cc337247c978add178b6ccdfb0019f'], - ['./test/fixtures/roms/tar/foobar.tar.gz', 'aec070645fe53ee3b3763059376134f058cc337247c978add178b6ccdfb0019f'], - ['./test/fixtures/roms/zip/foobar.zip', 'aec070645fe53ee3b3763059376134f058cc337247c978add178b6ccdfb0019f'], - ])('should hash the full archive entry when header is given but not present in file: %s', async (filePath, expectedSha256) => { - const archiveEntries = await FileFactory.filesFrom(filePath, ChecksumBitmask.SHA256); - expect(archiveEntries).toHaveLength(1); - const archiveEntry = await archiveEntries[0].withFileHeader( - ROMHeader.headerFromFilename(archiveEntries[0].getExtractedFilePath()) as ROMHeader, - ); - - // Some archives store CRC32, or otherwise it won't be defined - expect(archiveEntry.getMd5()).toBeUndefined(); - expect(archiveEntry.getMd5WithoutHeader()).toBeUndefined(); - expect(archiveEntry.getSha1()).toBeUndefined(); - expect(archiveEntry.getSha1WithoutHeader()).toBeUndefined(); - expect(archiveEntry.getSha256()).toEqual(expectedSha256); - expect(archiveEntry.getSha256WithoutHeader()).toEqual(expectedSha256); - }); - test.each([ ['./test/fixtures/roms/headered/diagnostic_test_cartridge.a78.7z', '248faac52d828b3542b74ff478e87afc6748949ad0f294fe75e6be94966a7558'], ['./test/fixtures/roms/headered/fds_joypad_test.fds.zip', '29e56794d15ccaa79e48ec0c80004f8745cfb116cce43b99435ae8790e79c327'], diff --git a/test/types/files/file.test.ts b/test/types/files/file.test.ts index d67cf8eb0..512f66278 100644 --- a/test/types/files/file.test.ts +++ b/test/types/files/file.test.ts @@ -166,22 +166,6 @@ describe('getCrc32WithoutHeader', () => { expect(file.getSha256WithoutHeader()).toBeUndefined(); }); - test.each([ - ['./test/fixtures/roms/raw/fizzbuzz.nes', '370517b5'], - ['./test/fixtures/roms/raw/foobar.lnx', 'b22c9747'], - ])('should hash the full file when header is given but not present in file: %s', async (filePath, expectedCrc) => { - const file = await (await File.fileOf({ filePath }, ChecksumBitmask.CRC32)) - .withFileHeader(ROMHeader.headerFromFilename(filePath) as ROMHeader); - expect(file.getCrc32()).toEqual(expectedCrc); - expect(file.getCrc32WithoutHeader()).toEqual(expectedCrc); - expect(file.getMd5()).toBeUndefined(); - expect(file.getMd5WithoutHeader()).toBeUndefined(); - expect(file.getSha1()).toBeUndefined(); - expect(file.getSha1WithoutHeader()).toBeUndefined(); - expect(file.getSha256()).toBeUndefined(); - expect(file.getSha256WithoutHeader()).toBeUndefined(); - }); - test.each([ ['./test/fixtures/roms/headered/allpads.nes', '6339abe6'], ['./test/fixtures/roms/headered/speed_test_v51.smc', '8beffd94'], @@ -234,22 +218,6 @@ describe('getMd5WithoutHeader', () => { expect(file.getSha256WithoutHeader()).toBeUndefined(); }); - test.each([ - ['./test/fixtures/roms/raw/fizzbuzz.nes', 'cbe8410861130a91609295349918c2c2'], - ['./test/fixtures/roms/raw/foobar.lnx', '14758f1afd44c09b7992073ccf00b43d'], - ])('should hash the full file when header is given but not present in file: %s', async (filePath, expectedMd5) => { - const file = await (await File.fileOf({ filePath }, ChecksumBitmask.MD5)) - .withFileHeader(ROMHeader.headerFromFilename(filePath) as ROMHeader); - expect(file.getCrc32()).toBeUndefined(); - expect(file.getCrc32WithoutHeader()).toBeUndefined(); - expect(file.getMd5()).toEqual(expectedMd5); - expect(file.getMd5WithoutHeader()).toEqual(expectedMd5); - expect(file.getSha1()).toBeUndefined(); - expect(file.getSha1WithoutHeader()).toBeUndefined(); - expect(file.getSha256()).toBeUndefined(); - expect(file.getSha256WithoutHeader()).toBeUndefined(); - }); - test.each([ ['./test/fixtures/roms/headered/allpads.nes', 'd632fd16189bd32f574b0b12c10ede47'], ['./test/fixtures/roms/headered/speed_test_v51.smc', 'cf62b6d186954e6f5d9feec3adc8ffbc'], @@ -302,22 +270,6 @@ describe('getSha1WithoutHeader', () => { expect(file.getSha256WithoutHeader()).toBeUndefined(); }); - test.each([ - ['./test/fixtures/roms/raw/fizzbuzz.nes', '5a316d9f0e06964d94cdd62a933803d7147ddadb'], - ['./test/fixtures/roms/raw/foobar.lnx', '988881adc9fc3655077dc2d4d757d480b5ea0e11'], - ])('should hash the full file when header is given but not present in file: %s', async (filePath, expectedSha1) => { - const file = await (await File.fileOf({ filePath }, ChecksumBitmask.SHA1)) - .withFileHeader(ROMHeader.headerFromFilename(filePath) as ROMHeader); - expect(file.getCrc32()).toBeUndefined(); - expect(file.getCrc32WithoutHeader()).toBeUndefined(); - expect(file.getMd5()).toBeUndefined(); - expect(file.getMd5WithoutHeader()).toBeUndefined(); - expect(file.getSha1()).toEqual(expectedSha1); - expect(file.getSha1WithoutHeader()).toEqual(expectedSha1); - expect(file.getSha256()).toBeUndefined(); - expect(file.getSha256WithoutHeader()).toBeUndefined(); - }); - test.each([ ['./test/fixtures/roms/headered/allpads.nes', 'f181104ca6ea30fa166260ab29395ce1fcdaa48e'], ['./test/fixtures/roms/headered/speed_test_v51.smc', '2f2f061ee81bafb4c48b83993a56969012162d68'], @@ -370,22 +322,6 @@ describe('getSha256WithoutHeader', () => { expect(file.getSha256WithoutHeader()).toEqual(expectedSha256); }); - test.each([ - ['./test/fixtures/roms/raw/fizzbuzz.nes', '6e809804766eaa4dd42a2607b789f3e4e5d32fc321ba8dd3ef39ddc1ea2888e9'], - ['./test/fixtures/roms/raw/foobar.lnx', 'aec070645fe53ee3b3763059376134f058cc337247c978add178b6ccdfb0019f'], - ])('should hash the full file when header is given but not present in file: %s', async (filePath, expectedSha256) => { - const file = await (await File.fileOf({ filePath }, ChecksumBitmask.SHA256)) - .withFileHeader(ROMHeader.headerFromFilename(filePath) as ROMHeader); - expect(file.getCrc32()).toBeUndefined(); - expect(file.getCrc32WithoutHeader()).toBeUndefined(); - expect(file.getMd5()).toBeUndefined(); - expect(file.getMd5WithoutHeader()).toBeUndefined(); - expect(file.getSha1()).toBeUndefined(); - expect(file.getSha1WithoutHeader()).toBeUndefined(); - expect(file.getSha256()).toEqual(expectedSha256); - expect(file.getSha256WithoutHeader()).toEqual(expectedSha256); - }); - test.each([ ['./test/fixtures/roms/headered/allpads.nes', '0b755904293f112d53ce159a613ef38aca68c84027ee8573a1d54f6317c3d755'], ['./test/fixtures/roms/headered/speed_test_v51.smc', '21c24e4b0ec2cb32eeba25c5311aa39bd3228fc1327d2719c0b88671884c2541'], diff --git a/test/types/files/fileCache.test.ts b/test/types/files/fileCache.test.ts index 1cad28793..892551f4c 100644 --- a/test/types/files/fileCache.test.ts +++ b/test/types/files/fileCache.test.ts @@ -12,8 +12,8 @@ describe('loadFile', () => { await FileCache.loadFile(tempCache); // Compute some values - await FileCache.getOrComputeFile(path.join('test', 'fixtures', 'roms', 'raw', 'fizzbuzz.nes'), ChecksumBitmask.CRC32); - await FileCache.getOrComputeEntries(new Zip(path.join('test', 'fixtures', 'roms', 'zip', 'foobar.zip')), ChecksumBitmask.CRC32); + await FileCache.getOrComputeFileChecksums(path.join('test', 'fixtures', 'roms', 'raw', 'fizzbuzz.nes'), ChecksumBitmask.CRC32); + await FileCache.getOrComputeArchiveChecksums(new Zip(path.join('test', 'fixtures', 'roms', 'zip', 'foobar.zip')), ChecksumBitmask.CRC32); await FileCache.save(); await FileCache.loadFile(tempCache); diff --git a/test/types/files/fileHeader.test.ts b/test/types/files/romHeader.test.ts similarity index 94% rename from test/types/files/fileHeader.test.ts rename to test/types/files/romHeader.test.ts index dffd609da..c5b7091e8 100644 --- a/test/types/files/fileHeader.test.ts +++ b/test/types/files/romHeader.test.ts @@ -14,6 +14,7 @@ describe('headerFromFilename', () => { ])('should get a file header for extension: %s', (filePath) => { const fileHeader = ROMHeader.headerFromFilename(filePath); expect(fileHeader).toBeDefined(); + expect(fileHeader?.getName()).toBeTruthy(); }); test.each([ @@ -39,6 +40,7 @@ describe('headerFromFileStream', () => { await headeredRom.createReadStream(async (stream) => { const fileHeader = await ROMHeader.headerFromFileStream(stream); expect(fileHeader).toBeDefined(); + expect(fileHeader?.getName()).toBeTruthy(); }); } });