From cccf51f9bf5caf3a62047416961c5cf420446334 Mon Sep 17 00:00:00 2001 From: Bryce Gibson Date: Sat, 25 Sep 2021 17:34:46 +1000 Subject: [PATCH] Add test suite using the built artefact. Smoke tests the different fs methods. Not perfect in any world, but better than nothing. --- package-lock.json | 15 +++ package.json | 5 + test/integration/index.js | 18 ++++ test/integration/tests.integration-spec.js | 112 +++++++++++++++++++++ 4 files changed, 150 insertions(+) create mode 100644 test/integration/index.js create mode 100644 test/integration/tests.integration-spec.js diff --git a/package-lock.json b/package-lock.json index fd02711..88bbcaf 100644 --- a/package-lock.json +++ b/package-lock.json @@ -28,6 +28,7 @@ "ora": "^3.4.0", "resolve-dependencies": "^6.0.8", "rimraf": "^3.0.2", + "run-script-os": "^1.1.6", "webpack-config-prefabs": "0.0.5" }, "bin": { @@ -3934,6 +3935,15 @@ "resolved": "https://registry.npmjs.org/run-parallel/-/run-parallel-1.1.9.tgz", "integrity": "sha512-DEqnSRTDw/Tc3FXf49zedI638Z9onwUotBMiUFKmrO2sdFKIbXamXGQ3Axd4qgphxKB4kw/qP1w5kTxnfU1B9Q==" }, + "node_modules/run-script-os": { + "version": "1.1.6", + "resolved": "https://registry.npmjs.org/run-script-os/-/run-script-os-1.1.6.tgz", + "integrity": "sha512-ql6P2LzhBTTDfzKts+Qo4H94VUKpxKDFz6QxxwaUZN0mwvi7L3lpOI7BqPCq7lgDh3XLl0dpeXwfcVIitlrYrw==", + "bin": { + "run-os": "index.js", + "run-script-os": "index.js" + } + }, "node_modules/safe-buffer": { "version": "5.1.2", "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", @@ -8234,6 +8244,11 @@ "resolved": "https://registry.npmjs.org/run-parallel/-/run-parallel-1.1.9.tgz", "integrity": "sha512-DEqnSRTDw/Tc3FXf49zedI638Z9onwUotBMiUFKmrO2sdFKIbXamXGQ3Axd4qgphxKB4kw/qP1w5kTxnfU1B9Q==" }, + "run-script-os": { + "version": "1.1.6", + "resolved": "https://registry.npmjs.org/run-script-os/-/run-script-os-1.1.6.tgz", + "integrity": "sha512-ql6P2LzhBTTDfzKts+Qo4H94VUKpxKDFz6QxxwaUZN0mwvi7L3lpOI7BqPCq7lgDh3XLl0dpeXwfcVIitlrYrw==" + }, "safe-buffer": { "version": "5.1.2", "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", diff --git a/package.json b/package.json index 33fe36d..d0729ec 100644 --- a/package.json +++ b/package.json @@ -11,6 +11,10 @@ "scripts": { "ci:build": "ts-node tasks/build", "test": "mocha", + "test:integration": "node index.js --build -i test/integration/index.js -o integration-tests --verbose -r test/integration -r node_modules/ && npm run test:integration:run", + "test:integration:run": "run-script-os", + "test:integration:run:win32": "integration-tests.exe", + "test:integration:run:default": "./integration-tests", "lint": "tslint \"{src,plugins,tasks}/**/*.ts\" --fix", "prepare": "npm run lint && npm run build && npm test", "prebuild": "rimraf lib", @@ -59,6 +63,7 @@ "ora": "^3.4.0", "resolve-dependencies": "^6.0.8", "rimraf": "^3.0.2", + "run-script-os": "^1.1.6", "webpack-config-prefabs": "0.0.5" }, "devDependencies": { diff --git a/test/integration/index.js b/test/integration/index.js new file mode 100644 index 0000000..9f4ce9d --- /dev/null +++ b/test/integration/index.js @@ -0,0 +1,18 @@ +const { mkdtemp } = require('fs/promises') +const os = require('os') +const path = require('path') +const rimraf = require('rimraf') + +async function runTests() { + const tempdir = await mkdtemp(path.join(os.tmpdir(), 'nexe-')) + process.on('beforeExit', () => rimraf.sync(tempdir)) + process.chdir(tempdir) + const Mocha = require('mocha') + const mocha = new Mocha() + mocha.addFile('test/integration/tests.integration-spec.js') + mocha.run((failures) => { + process.exitCode = failures ? 1 : 0 + }) +} + +runTests() diff --git a/test/integration/tests.integration-spec.js b/test/integration/tests.integration-spec.js new file mode 100644 index 0000000..a8ff1be --- /dev/null +++ b/test/integration/tests.integration-spec.js @@ -0,0 +1,112 @@ +const { expect } = require('chai') +const fs = require('fs') +const { dirname, basename }= require('path') + +const files = { zipFs: 'test/integration/tests.integration-spec.js', real: 'real', real2: 'real2' } +describe('SnapshotZipFS', () => { + console.error('Note: these tests are order dependant, so subsequent failures are likely a flow on effect.') + it('checks existance from the zipFs', () => expect(fs.existsSync(files.zipFs)).to.equal(true)) + it('checks non-existance from the zipFs', () => expect(fs.existsSync('not found')).to.equal(false)) + it('reads from the zipFs', () => expect(fs.readFileSync(files.zipFs, 'utf8')).to.include('SnapshotZipFS')) + it('copies from the zipFs', () => expect(() => fs.copyFileSync(files.zipFs, files.real)).not.to.throw()) + it('reads from the real fs', () => expect(fs.readFileSync(files.real, 'utf8')).to.include('SnapshotZipFS')) + it('checks non-existance from the real fs', () => expect(fs.existsSync(files.real2)).to.equal(false)) + it('copies from the real fs', () => expect(() => fs.copyFileSync(files.real, files.real2)).not.to.throw()) + it('checks existance from the real fs', () => expect(fs.existsSync(files.real2)).to.equal(true)) + it('unlinks from the real fs', () => expect(() => fs.unlinkSync(files.real2)).not.to.throw()) + it('symlinks the real fs', () => expect(() => fs.symlinkSync('tmp', files.real2)).not.to.throw()) + it('readlinks the real fs', () => expect(fs.readlinkSync(files.real2)).to.equal('tmp')) + it('truncates the real fs', () => expect(() => fs.truncateSync(files.real)).not.to.throw()) + it('writeFiles the real fs', () => expect(() => fs.writeFileSync(files.real2, 'testing')).not.to.throw()) + it('accesses the real fs', () => expect(() => fs.accessSync(files.real)).not.to.throw()) + it('accesses the zipFs', () => expect(() => fs.accessSync(files.zipFs)).not.to.throw()) + it('stats the real fs', () => expect(fs.statSync(files.real2).size).to.be.greaterThan(0)) + it('stats the zipFs', () => expect(fs.statSync(files.zipFs).size).to.be.greaterThan(0)) + it('readdirs from the zipFs', () => expect(fs.readdirSync(dirname(files.zipFs))).to.include(basename(files.zipFs))) + it('readdirs from the real fs', () => expect(fs.readdirSync('.')).to.include(files.real)) + it('readdirs from both', () => { + expect(fs.readdirSync('.')).to.include(files.real), + expect(fs.readdirSync('.')).to.include('test') + }) + let dir + it('opendirs the zipFs fs', async () => { + expect(() => dir = fs.opendirSync(dirname(files.zipFs))).not.to.throw() + const names = [] + for await (const dirent of dir) { + names.push(dirent.name) + } + expect(names).to.include(basename(files.zipFs)) + }) + it('opendirs the real fs and zipFs', async () => { + expect(() => dir = fs.opendirSync('.')).not.to.throw() + const names = [] + for await (const dirent of dir) { + names.push(dirent.name) + } + expect(names).to.include(files.real) + expect(names).to.include('test') + }) + it('createWriteStreams to the real fs', () => expect(() => fs.createWriteStream('createWriteStream')).not.to.throw()) + it('createReadStreams to the real fs', () => expect(() => fs.createReadStream(files.real)).not.to.throw()) + it('createReadStreams to the zipFs', () => expect(() => fs.createReadStream(files.zipFs)).not.to.throw()) + it('renames to the realFs', () => { + expect(() => fs.renameSync(files.real2, 'rename')).not.to.throw() + expect(fs.existsSync('rename')).to.equal(true) + }) + + describe('write actions to the zipFs', () => { + it(`won't truncate to the zipFs`, () => expect(() => fs.truncateSync(files.zipFs)).to.throw()) + it(`won't unlink from the zipFs`, () => expect(() => fs.unlinkSync(files.zipFs)).to.throw()) + it(`won't appendFile to the zipFs`, () => expect(() => fs.appendFileSync(files.zipFs, 'xxx')).to.throw()) + it(`won't symlink to the zipFs`, () => expect(() => fs.symlinkSync('tmp', files.zipFs)).to.throw()) + it(`won't chmod to the zipFs`, () => expect(() => fs.chmodSync(files.zipFs, 0o666)).to.throw()) + it(`won't chown to the zipFs`, () => expect(() => fs.chownSync(files.zipFs, 0, 0)).to.throw()) + it(`won't writeFile the zipFs`, () => expect(() => fs.writeFileSync(files.zipFs, 'testing')).to.throw()) + it(`won't createWriteStreams to the zipFs`, () => expect(() => fs.createWriteStream(files.zipFs)).to.throw()) + it(`won't rename to the zipFs`, () => expect(() => fs.renameSync(files.real, files.zipFs)).to.throw()) + }) + + ;[ 'zipFs', 'real' ].forEach((k) => { + it(`watches the ${k} fs`, () => expect(() => fs.watch(files[k], () => null).close()).not.to.throw()) + it(`watchFiles the ${k} fs`, () => expect(() => fs.watchFile(files[k], () => null)).not.to.throw()) + it(`unwatchFiles the ${k} fs`, () => expect(() => fs.unwatchFile(files[k])).not.to.throw()) + }) + let buffer = Buffer.alloc(8092), fd + describe('zipfs file descriptors', () => { + it('opens files in the zipFs', () => { + expect(() => (fd = fs.openSync(files.zipFs, 'a+'))).not.to.throw() + expect(fd).to.not.be.null + }) + it('reads file descriptors from the zipFs', () => { + expect(() => fs.readSync(fd, buffer)).not.to.throw() + expect(buffer.toString()).to.include('SnapshotZipFS') + }) + it('fstats the zipFs', () => expect(fs.fstatSync(fd).size).to.be.greaterThan(0)) + it(`won't write to the zipFs`, () => expect(() => fs.writeSync(fd, 'xxx')).to.throw()) + it(`won't fchmod the zipFs`, () => expect(() => fs.fchmodSync(fd)).to.throw()) + it(`won't fchown the zipFs`, () => expect(() => fs.fchownSync(fd)).to.throw()) + it(`won't ftruncate the zipFs`, () => expect(() => fs.ftruncateSync(fd)).to.throw()) + it('closes file descriptors from the zipFs', () => expect(() => fs.closeSync(fd)).not.to.throw()) + }) + + fd = null + buffer = Buffer.alloc(8092) + describe('real file descriptors', () => { + it('opens files in the real fs', () => { + expect(() => (fd = fs.openSync(files.real2, 'a+'))).not.to.throw() + expect(fd).to.not.be.null + }) + it('reads file descriptors from the real', () => { + expect(() => fs.readSync(fd, buffer)).not.to.throw() + expect(buffer.toString()).to.include('SnapshotZipFS') + }) + it('will write to the real fs', () => expect(() => fs.writeSync(fd, 'xxx')).not.to.throw()) + it('fstats the real fs', () => expect(fs.fstatSync(fd).size).to.be.greaterThan(0)) + it('closes file descriptors from the real fs', () => expect(() => fs.closeSync(fd)).not.to.throw()) + }) + + describe('path clashes', () => { + it('delegates directory creation to the real fs', () => expect(() => fs.mkdirSync('test')).not.to.throw()) + it('delegates directory removal to the real fs', () => expect(() => fs.rmdirSync('test')).not.to.throw()) + }) +})