Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

CI: increase test coverage #1272

Merged
merged 1 commit into from
Aug 6, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions .github/workflows/node-test.yml
Original file line number Diff line number Diff line change
Expand Up @@ -69,6 +69,7 @@ jobs:
- path-filter
if: ${{ needs.path-filter.outputs.changes == 'true' }}
runs-on: ${{ matrix.os }}-latest
timeout-minutes: 10
strategy:
matrix:
os: [ ubuntu, macos, windows ]
Expand Down Expand Up @@ -97,6 +98,7 @@ jobs:
- path-filter
if: ${{ needs.path-filter.outputs.changes == 'true' }}
runs-on: ubuntu-latest
timeout-minutes: 10
strategy:
matrix:
node-version: [ lts, 18, 16.7.0 ]
Expand Down
5 changes: 3 additions & 2 deletions src/modules/candidateArchiveFileHasher.ts
Original file line number Diff line number Diff line change
Expand Up @@ -83,7 +83,8 @@ export default class CandidateArchiveFileHasher extends Module {
return romWithFiles;
}

if (inputFile.equals(romWithFiles.getOutputFile())) {
const outputFile = romWithFiles.getOutputFile();
if (inputFile.equals(outputFile)) {
// There's no need to calculate the checksum, {@link CandidateWriter} will skip
// writing over itself
return romWithFiles;
Expand All @@ -103,7 +104,7 @@ export default class CandidateArchiveFileHasher extends Module {
);
// {@link CandidateGenerator} would have copied undefined values from the input
// file, so we need to modify the expected output file as well for testing
const hashedOutputFile = romWithFiles.getOutputFile().withProps({
const hashedOutputFile = outputFile.withProps({
size: hashedInputFile.getSize(),
crc32: hashedInputFile.getCrc32(),
md5: hashedInputFile.getMd5(),
Expand Down
19 changes: 2 additions & 17 deletions src/modules/candidateGenerator.ts
Original file line number Diff line number Diff line change
Expand Up @@ -233,21 +233,6 @@ export default class CandidateGenerator extends Module {
.filter(([, romWithFiles]) => !romWithFiles)
.map(([rom]) => rom);

// If there is a CHD with every .bin file, then assume its .cue file is accurate
if (missingRoms.length > 0 && CandidateGenerator.onlyCueFilesMissingFromChd(
game,
foundRomsWithFiles.map((romWithFiles) => romWithFiles.getRom()),
)) {
const inputChds = foundRomsWithFiles
.map((romWithFiles) => romWithFiles.getOutputFile())
.filter((file) => file.getFilePath().toLowerCase().endsWith('.chd'))
.filter(ArrayPoly.filterUniqueMapped((file) => file.getFilePath()));
if (inputChds.length === 1) {
this.progressBar.logTrace(`${dat.getNameShort()}: ${game.getName()}: `);
return new ReleaseCandidate(game, release, foundRomsWithFiles);
}
}

// Ignore the Game if not every File is present
if (missingRoms.length > 0 && !this.options.getAllowIncompleteSets()) {
if (foundRomsWithFiles.length > 0) {
Expand Down Expand Up @@ -317,13 +302,13 @@ export default class CandidateGenerator extends Module {

// Filter to the Archives that contain every ROM in this Game
const archivesWithEveryRom = [...inputArchivesToRoms.entries()]
.filter(([archive, roms]) => {
.filter(([inputArchive, roms]) => {
if (roms.map((rom) => rom.hashCode()).join(',') === gameRoms.map((rom) => rom.hashCode()).join(',')) {
return true;
}
// If there is a CHD with every .bin file, and we're raw-copying it, then assume its .cue
// file is accurate
return archive instanceof Chd
return inputArchive instanceof Chd
&& !gameRoms.some((rom) => this.options.shouldZipRom(rom))
&& !gameRoms.some((rom) => this.options.shouldExtractRom(rom))
&& CandidateGenerator.onlyCueFilesMissingFromChd(game, roms);
Expand Down
20 changes: 10 additions & 10 deletions src/modules/datGameInferrer.ts
Original file line number Diff line number Diff line change
Expand Up @@ -190,12 +190,12 @@ export default class DATGameInferrer extends Module {
.map((binFile) => path.join(path.dirname(cueFile.getFilePath()), binFile.name))
.map((binFilePath) => rawFilePathsToFiles.get(binFilePath))
.filter(ArrayPoly.filterNotNullish);

if (binFiles.length > 0) {
const gameName = DATGameInferrer.getGameName(cueFile);
return [gameName, [cueFile, ...binFiles]];
if (binFiles.length === 0) {
return undefined;
}
return undefined;

const gameName = DATGameInferrer.getGameName(cueFile);
return [gameName, [cueFile, ...binFiles]];
} catch {
return undefined;
}
Expand Down Expand Up @@ -239,12 +239,12 @@ export default class DATGameInferrer extends Module {
.map((trackFilePath) => path.join(path.dirname(gdiFile.getFilePath()), trackFilePath))
.map((trackFilePath) => rawFilePathsToFiles.get(trackFilePath))
.filter(ArrayPoly.filterNotNullish);

if (trackFiles.length > 0) {
const gameName = DATGameInferrer.getGameName(gdiFile);
return [gameName, [gdiFile, ...trackFiles]];
if (trackFiles.length === 0) {
return undefined;
}
return undefined;

const gameName = DATGameInferrer.getGameName(gdiFile);
return [gameName, [gdiFile, ...trackFiles]];
} catch {
return undefined;
}
Expand Down
2 changes: 1 addition & 1 deletion src/modules/fixdatCreator.ts
Original file line number Diff line number Diff line change
Expand Up @@ -60,7 +60,7 @@ export default class FixdatCreator extends Module {
try {
fixdatDir = this.getDatOutputDirRoot(originalDat);
} catch (error) {
this.progressBar.logWarn(`failed to: ${error}`);
this.progressBar.logWarn(`${originalDat.getNameShort()}: failed to get output directory: ${error}`);
}
}
if (!await fsPoly.exists(fixdatDir)) {
Expand Down
24 changes: 17 additions & 7 deletions test/igir.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,12 @@ import ArrayPoly from '../src/polyfill/arrayPoly.js';
import fsPoly from '../src/polyfill/fsPoly.js';
import { ChecksumBitmask } from '../src/types/files/fileChecksums.js';
import FileFactory from '../src/types/files/fileFactory.js';
import Options, { FixExtension, GameSubdirMode, OptionsProps } from '../src/types/options.js';
import Options, {
FixExtension,
GameSubdirMode,
InputChecksumArchivesMode,
OptionsProps,
} from '../src/types/options.js';
import ProgressBarFake from './console/progressBarFake.js';

interface TestOutput {
Expand Down Expand Up @@ -143,17 +148,20 @@ describe('with explicit DATs', () => {
}), new Logger(LogLevel.NEVER)).main()).rejects.toThrow(/no valid dat files/i);
});

it('should copy and test', async () => {
it('should copy and test, without caching', async () => {
await copyFixturesToTemp(async (inputTemp, outputTemp) => {
const result = await runIgir({
commands: ['copy', 'test'],
dat: [path.join(inputTemp, 'dats', '*')],
input: [path.join(inputTemp, 'roms')],
inputExclude: [path.join(inputTemp, 'roms', 'discs')], // test archive scanning + matching
inputChecksumArchives: InputChecksumArchivesMode[InputChecksumArchivesMode.NEVER]
.toLowerCase(),
output: outputTemp,
dirDatName: true,
dirGameSubdir: GameSubdirMode[GameSubdirMode.MULTIPLE].toLowerCase(),
fixExtension: FixExtension[FixExtension.AUTO].toLowerCase(),
disableCache: true,
});

expect(result.outputFilesAndCrcs).toEqual([
Expand All @@ -178,7 +186,6 @@ describe('with explicit DATs', () => {
[`${path.join('One', 'GD-ROM.chd')}|track02.raw`, 'abc178d5'],
[`${path.join('One', 'GD-ROM.chd')}|track03.bin`, '61a363f1'],
[`${path.join('One', 'GD-ROM.chd')}|track04.bin`, 'fc5ff5a0'],
[`${path.join('One', 'Lorem Ipsum.zip')}|loremipsum.rom`, '70856527'],
[path.join('One', 'One Three', 'One.rom'), 'f817a89f'],
[path.join('One', 'One Three', 'Three.rom'), 'ff46c5d8'],
[`${path.join('One', 'Three Four Five', '2048')}|`, 'xxxxxxxx'], // hard disk
Expand Down Expand Up @@ -209,16 +216,19 @@ describe('with explicit DATs', () => {
});
});

it('should copy a 1G1R set', async () => {
it('should copy a 1G1R set, with a custom cache path', async () => {
await copyFixturesToTemp(async (inputTemp, outputTemp) => {
const result = await runIgir({
commands: ['copy'],
dat: [path.join(inputTemp, 'dats', 'one.dat')],
input: [path.join(inputTemp, 'roms')],
inputChecksumArchives: InputChecksumArchivesMode[InputChecksumArchivesMode.ALWAYS]
.toLowerCase(),
output: outputTemp,
dirGameSubdir: GameSubdirMode[GameSubdirMode.MULTIPLE].toLowerCase(),
single: true,
preferParent: true,
cachePath: inputTemp,
});

expect(result.outputFilesAndCrcs).toEqual([
Expand Down Expand Up @@ -784,7 +794,7 @@ describe('with explicit DATs', () => {
[`${path.join('One', 'CD-ROM.chd')}|CD-ROM.cue -> ${path.join('<input>', 'chd', 'CD-ROM.chd')}|CD-ROM.cue`, 'xxxxxxxx'],
[`${path.join('One', 'Fizzbuzz.nes')} -> ${path.join('<input>', 'raw', 'fizzbuzz.nes')}`, '370517b5'],
[`${path.join('One', 'Foobar.lnx')} -> ${path.join('<input>', 'foobar.lnx')}`, 'b22c9747'],
[`${path.join('One', 'GameCube NKit ISO.nkit.iso')}|5bc2ce5b.iso -> ${path.join('<input>', 'nkit', '5bc2ce5b.nkit.iso')}|5bc2ce5b.iso`, '5bc2ce5b'],
[`${path.join('One', 'GameCube NKit ISO.nkit.iso')}|GameCube NKit ISO.iso -> ${path.join('<input>', 'nkit', '5bc2ce5b.nkit.iso')}|GameCube NKit ISO.iso`, '5bc2ce5b'],
[`${path.join('One', 'GD-ROM.chd')}|GD-ROM.gdi -> ${path.join('<input>', 'chd', 'GD-ROM.chd')}|GD-ROM.gdi`, 'f16f621c'],
[`${path.join('One', 'GD-ROM.chd')}|track01.bin -> ${path.join('<input>', 'chd', 'GD-ROM.chd')}|track01.bin`, '9796ed9a'],
[`${path.join('One', 'GD-ROM.chd')}|track02.raw -> ${path.join('<input>', 'chd', 'GD-ROM.chd')}|track02.raw`, 'abc178d5'],
Expand Down Expand Up @@ -1053,13 +1063,13 @@ describe('with inferred DATs', () => {

it('should move to the same directory', async () => {
await copyFixturesToTemp(async (inputTemp, outputTemp) => {
const inputDir = path.join(inputTemp, 'roms', 'raw');
const inputDir = path.join(inputTemp, 'roms');
const inputBefore = await walkWithCrc(inputDir, inputDir);

await runIgir({
commands: ['move', 'test'],
input: [inputDir],
output: inputDir,
output: '{inputDirname}',
});

await expect(walkWithCrc(inputDir, inputDir)).resolves.toEqual(inputBefore);
Expand Down
46 changes: 46 additions & 0 deletions test/polyfill/fsPoly.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,52 @@ describe('isDirectory', () => {
});
});

describe('isHardlink', () => {
it('should return true for a hardlink', async () => {
const tempFileTarget = await fsPoly.mktemp(path.join(Temp.getTempDir(), 'target'));
const tempFileLink = await fsPoly.mktemp(path.join(Temp.getTempDir(), 'link'));

try {
await fsPoly.touch(tempFileTarget);

await fsPoly.hardlink(tempFileTarget, tempFileLink);
await expect(fsPoly.isHardlink(tempFileLink)).resolves.toEqual(true);
await expect(fsPoly.isHardlink(tempFileTarget)).resolves.toEqual(true);
} finally {
await fsPoly.rm(tempFileTarget, { force: true });
await fsPoly.rm(tempFileLink, { force: true });
}
});

it('should return false for a symlink', async () => {
const tempFileTarget = await fsPoly.mktemp(path.join(Temp.getTempDir(), 'target'));
const tempFileLink = await fsPoly.mktemp(path.join(Temp.getTempDir(), 'link'));

try {
await fsPoly.touch(tempFileTarget);

await fsPoly.symlink(tempFileTarget, tempFileLink);
await expect(fsPoly.isHardlink(tempFileLink)).resolves.toEqual(false);
await expect(fsPoly.isHardlink(tempFileTarget)).resolves.toEqual(false);
} finally {
await fsPoly.rm(tempFileTarget, { force: true });
await fsPoly.rm(tempFileLink, { force: true });
}
});

it('should return false for a file', async () => {
const tempFile = await fsPoly.mktemp(path.join(Temp.getTempDir(), 'temp'));
await fsPoly.touch(tempFile);
await expect(fsPoly.isHardlink(tempFile)).resolves.toEqual(false);
await fsPoly.rm(tempFile);
});

it('should return false for non-existent file', async () => {
const tempFile = await fsPoly.mktemp(path.join(Temp.getTempDir(), 'temp'));
await expect(fsPoly.isHardlink(tempFile)).resolves.toEqual(false);
});
});

describe('hardlink', () => {
it('should create a hardlink', async () => {
const tempFileTarget = await fsPoly.mktemp(path.join(Temp.getTempDir(), 'target'));
Expand Down
Loading