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 #1130

Merged
merged 2 commits into from
May 10, 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
11 changes: 0 additions & 11 deletions src/types/dats/dat.ts
Original file line number Diff line number Diff line change
Expand Up @@ -107,17 +107,6 @@ export default abstract class DAT {
return FsPoly.makeLegal(filename.trim());
}

/**
* Is this a {@link LogiqxDAT} that only contains BIOS files.
*/
isBiosDat(): boolean {
return (this.getGames().length > 0 && this.getGames().every((game) => game.isBios()))
// Redump-style DAT names
|| this.getName().match(/(\W|^)BIOS(\W|$)/i) !== null
// libretro-style DAT comments
|| (this.getHeader().getComment() ?? '').match(/(\W|^)BIOS(\W|$)/i) !== null;
}

/**
* Does a DAT explicitly contain headered ROMs. It is possible for a DAT to be both non-headered
* and non-headerless.
Expand Down
22 changes: 22 additions & 0 deletions test/driveSemaphore.test.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
import DriveSemaphore from '../src/driveSemaphore.js';

describe('map', () => {
it('should handle thrown errors', async () => {
await expect(
new DriveSemaphore().map(
['file'],
() => { throw new Error('error'); },
),
).rejects.toThrow('error');
});

it('should handle thrown literals', async () => {
await expect(
new DriveSemaphore().map(
['file'],
// eslint-disable-next-line @typescript-eslint/no-throw-literal
() => { throw 'message'; },
),
).rejects.toThrow('message');
});
});
14 changes: 14 additions & 0 deletions test/modules/argumentsParser.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -841,6 +841,13 @@ describe('options', () => {
expect(argumentsParser.parse([...dummyCommandAndRequiredArgs, '--filter-language', 'EN,it']).getFilterLanguage()).toEqual(new Set(['EN', 'IT']));
expect(argumentsParser.parse([...dummyCommandAndRequiredArgs, '--filter-language', 'en,IT,JA']).getFilterLanguage()).toEqual(new Set(['EN', 'IT', 'JA']));
expect(argumentsParser.parse([...dummyCommandAndRequiredArgs, '--filter-language', 'EN,en']).getFilterLanguage()).toEqual(new Set(['EN']));

expect(() => argumentsParser.parse([...dummyCommandAndRequiredArgs, '--language-filter'])).toThrow(/not enough arguments/i);
expect(argumentsParser.parse([...dummyCommandAndRequiredArgs, '-L', 'EN']).getFilterLanguage()).toEqual(new Set(['EN']));
expect(argumentsParser.parse([...dummyCommandAndRequiredArgs, '--language-filter', 'EN']).getFilterLanguage()).toEqual(new Set(['EN']));
expect(argumentsParser.parse([...dummyCommandAndRequiredArgs, '--language-filter', 'EN,it']).getFilterLanguage()).toEqual(new Set(['EN', 'IT']));
expect(argumentsParser.parse([...dummyCommandAndRequiredArgs, '--language-filter', 'en,IT,JA']).getFilterLanguage()).toEqual(new Set(['EN', 'IT', 'JA']));
expect(argumentsParser.parse([...dummyCommandAndRequiredArgs, '--language-filter', 'EN,en']).getFilterLanguage()).toEqual(new Set(['EN']));
});

it('should parse "filter-region"', () => {
Expand All @@ -852,6 +859,13 @@ describe('options', () => {
expect(argumentsParser.parse([...dummyCommandAndRequiredArgs, '--filter-region', 'USA,eur']).getFilterRegion()).toEqual(new Set(['USA', 'EUR']));
expect(argumentsParser.parse([...dummyCommandAndRequiredArgs, '--filter-region', 'usa,EUR,JPN']).getFilterRegion()).toEqual(new Set(['USA', 'EUR', 'JPN']));
expect(argumentsParser.parse([...dummyCommandAndRequiredArgs, '--filter-region', 'USA,usa']).getFilterRegion()).toEqual(new Set(['USA']));

expect(() => argumentsParser.parse([...dummyCommandAndRequiredArgs, '--region-filter'])).toThrow(/not enough arguments/i);
expect(argumentsParser.parse([...dummyCommandAndRequiredArgs, '-R', 'USA']).getFilterRegion()).toEqual(new Set(['USA']));
expect(argumentsParser.parse([...dummyCommandAndRequiredArgs, '--region-filter', 'USA']).getFilterRegion()).toEqual(new Set(['USA']));
expect(argumentsParser.parse([...dummyCommandAndRequiredArgs, '--region-filter', 'USA,eur']).getFilterRegion()).toEqual(new Set(['USA', 'EUR']));
expect(argumentsParser.parse([...dummyCommandAndRequiredArgs, '--region-filter', 'usa,EUR,JPN']).getFilterRegion()).toEqual(new Set(['USA', 'EUR', 'JPN']));
expect(argumentsParser.parse([...dummyCommandAndRequiredArgs, '--region-filter', 'USA,usa']).getFilterRegion()).toEqual(new Set(['USA']));
});

it('should parse "no-bios"', () => {
Expand Down
15 changes: 15 additions & 0 deletions test/modules/datMergerSplitter.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2292,3 +2292,18 @@ describe('FinalBurn Neo Neo Geo e544671', () => {
]);
});
});

test.each([
[MergeMode.NONMERGED],
[MergeMode.SPLIT],
[MergeMode.MERGED],
])('should handle invalid romOf attributes: %s', () => {
// TODO(cemmer)
});

test.each([
[MergeMode.SPLIT],
[MergeMode.MERGED],
])('should handle invalid cloneOf attributes: %s', () => {
// TODO(cemmer)
});
26 changes: 20 additions & 6 deletions test/modules/directoryCleaner.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ import Constants from '../../src/constants.js';
import DirectoryCleaner from '../../src/modules/directoryCleaner.js';
import fsPoly from '../../src/polyfill/fsPoly.js';
import File from '../../src/types/files/file.js';
import Options from '../../src/types/options.js';
import Options, { OptionsProps } from '../../src/types/options.js';
import ProgressBarFake from '../console/progressBarFake.js';

const ROM_FIXTURES_DIR = path.join('test', 'fixtures', 'roms');
Expand All @@ -16,6 +16,7 @@ const ROM_FIXTURES_DIR = path.join('test', 'fixtures', 'roms');
* so it's fine if we implement some workarounds here.
*/
async function runOutputCleaner(
optionsProps: OptionsProps,
cleanExclude: string[],
writtenFilePathsToExclude: string[],
): Promise<string[]> {
Expand All @@ -31,6 +32,7 @@ async function runOutputCleaner(

await new DirectoryCleaner(
new Options({
...optionsProps,
commands: ['move', 'clean'],
cleanExclude: cleanExclude.map((filePath) => path.join(tempDir, filePath)),
}),
Expand All @@ -50,20 +52,20 @@ it('should delete nothing if nothing written', async () => {
const existingFiles = (await fsPoly.walk(ROM_FIXTURES_DIR))
.map((filePath) => filePath.replace(/^test[\\/]fixtures[\\/]roms[\\/]/, ''))
.sort();
const filesRemaining = await runOutputCleaner([], []);
const filesRemaining = await runOutputCleaner({}, [], []);
expect(filesRemaining).toEqual(existingFiles);
});

it('should delete nothing if no excess files', async () => {
const existingFiles = (await fsPoly.walk(ROM_FIXTURES_DIR))
.map((filePath) => filePath.replace(/^test[\\/]fixtures[\\/]roms[\\/]/, ''))
.sort();
const filesRemaining = await runOutputCleaner([], existingFiles);
const filesRemaining = await runOutputCleaner({}, [], existingFiles);
expect(filesRemaining).toEqual(existingFiles);
});

it('should delete some if all unmatched and some excluded', async () => {
const filesRemaining = await runOutputCleaner([
const filesRemaining = await runOutputCleaner({}, [
path.join('**', 'foobar.*'),
], [
'non-existent file',
Expand All @@ -79,7 +81,7 @@ it('should delete some if all unmatched and some excluded', async () => {
});

it('should delete some if some matched and nothing excluded', async () => {
const filesRemaining = await runOutputCleaner([], [
const filesRemaining = await runOutputCleaner({}, [], [
path.join('7z', 'empty.7z'),
path.join('raw', 'fizzbuzz.nes'),
path.join('zip', 'foobar.zip'),
Expand All @@ -93,11 +95,23 @@ it('should delete some if some matched and nothing excluded', async () => {
});

it('should delete everything if all unmatched and nothing excluded', async () => {
await expect(runOutputCleaner([], [
await expect(runOutputCleaner({}, [], [
'non-existent file',
])).resolves.toHaveLength(0);
});

it('should delete nothing if all unmatched but doing a dry run', async () => {
const existingFiles = (await fsPoly.walk(ROM_FIXTURES_DIR))
.map((filePath) => filePath.replace(/^test[\\/]fixtures[\\/]roms[\\/]/, ''))
.sort();
const filesRemaining = await runOutputCleaner({
cleanDryRun: true,
}, [], [
'non-existent file',
]);
expect(filesRemaining).toEqual(existingFiles);
});

it('should delete hard links', async () => {
const tempDir = await fsPoly.mkdtemp(Constants.GLOBAL_TEMP_DIR);
try {
Expand Down
2 changes: 1 addition & 1 deletion test/modules/romScanner.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -57,7 +57,7 @@ describe('multiple files', () => {
const scannedRealFiles = (await createRomScanner(['test/fixtures/roms']).scan())
.sort((a, b) => a.getFilePath().localeCompare(b.getFilePath()));

// Given some symlinked files
// Given some hard linked files
const tempDir = await fsPoly.mkdtemp(Constants.GLOBAL_TEMP_DIR);
try {
const filesDir = path.join(tempDir, 'files');
Expand Down
28 changes: 28 additions & 0 deletions test/polyfill/fsPoly.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -261,3 +261,31 @@ describe('realpath', () => {
await expect(fsPoly.realpath('.')).resolves.toEqual(process.cwd());
});
});

describe('touch', () => {
it('should mkdir and touch', async () => {
const tempDir = await fsPoly.mkdtemp(Constants.GLOBAL_TEMP_DIR);
await fsPoly.rm(tempDir, { recursive: true });
const tempFile = await fsPoly.mktemp(path.join(tempDir, 'temp'));
try {
await fsPoly.touch(tempFile);
await expect(fsPoly.exists(tempFile)).resolves.toEqual(true);
} finally {
await fsPoly.rm(tempDir, { recursive: true, force: true });
}
});
});

describe('touchSync', () => {
it('should mkdir and touch', async () => {
const tempDir = await fsPoly.mkdtemp(Constants.GLOBAL_TEMP_DIR);
await fsPoly.rm(tempDir, { recursive: true });
const tempFile = await fsPoly.mktemp(path.join(tempDir, 'temp'));
try {
fsPoly.touchSync(tempFile);
await expect(fsPoly.exists(tempFile)).resolves.toEqual(true);
} finally {
await fsPoly.rm(tempDir, { recursive: true, force: true });
}
});
});
28 changes: 28 additions & 0 deletions test/types/cache.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -165,6 +165,34 @@ describe('set', () => {
});
});

describe('delete', () => {
it('should delete a single key', async () => {
const cache = new Cache<string>();

await cache.set('key', 'value');
await expect(cache.has('key')).resolves.toEqual(true);

await cache.delete('key');
await expect(cache.has('key')).resolves.toEqual(false);
});

it('should delete regex-matched keys', async () => {
const cache = new Cache<string>();

await cache.set('key1', 'value');
await expect(cache.has('key1')).resolves.toEqual(true);
await cache.set('key2', 'value');
await expect(cache.has('key2')).resolves.toEqual(true);
await cache.set('key3', 'value');
await expect(cache.has('key3')).resolves.toEqual(true);

await cache.delete(/key[12]/);
await expect(cache.has('key1')).resolves.toEqual(false);
await expect(cache.has('key2')).resolves.toEqual(false);
await expect(cache.has('key3')).resolves.toEqual(true);
});
});

describe('load', () => {
it('should not throw on nonexistent file', async () => {
const tempFile = await FsPoly.mktemp(path.join(Constants.GLOBAL_TEMP_DIR, 'cache'));
Expand Down
3 changes: 3 additions & 0 deletions test/types/indexedFiles.test.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import ROM from '../../src/types/dats/rom.js';
import File from '../../src/types/files/file.js';
import ROMHeader from '../../src/types/files/romHeader.js';
import IndexedFiles from '../../src/types/indexedFiles.js';

describe('findFiles', () => {
Expand All @@ -14,6 +15,7 @@ describe('findFiles', () => {
size: 2,
crc32: '22222222',
md5: '22222222222222222222222222222222',
fileHeader: ROMHeader.headerFromFilename('two.lnx'),
}),
File.fileOf({
filePath: 'three',
Expand All @@ -36,6 +38,7 @@ describe('findFiles', () => {
size: 6,
sha1: '6666666666666666666666666666666666666666',
sha256: '6666666666666666666666666666666666666666666666666666666666666666',
fileHeader: ROMHeader.headerFromFilename('six.nes'),
}),
File.fileOf({
filePath: 'seven',
Expand Down
Loading