const fs = require('fs').promises const path = require('path') const test = require('ava') const {execFilePromise, matchOutput, wait} = require('./util') // We are going to run the server directly, not through npm const {INIT_CWD, ...MAKE_ENV} = process.env process.chdir(__dirname) async function makeC(dir) { try { await fs.rmdir(dir, {recursive: true}) } catch {} await fs.mkdir(dir) await fs.writeFile(`${dir}/c`, 'cde') } async function make(dir, ...targets) { const {stdout} = await execFilePromise( 'node', ['../../make.js', '../special-cases-makefile.js', ...targets], {cwd: dir, env: MAKE_ENV} ) return stdout } async function makeError(dir, ...targets) { let output try { output = await make(dir, ...targets) } catch (e) { return {output: e.stdout, code: e.code} } return {output, code: 0} } test('request source file', async t => { const dir = 'source-file' await makeC(dir) const {mtimeMs} = await fs.stat(`${dir}/c`) // Request that c (an existing file) is built await wait(100) const output = await make(dir, 'c') // Check that no files were created and c was not modified const files = await fs.readdir(dir) t.deepEqual(files, ['c'], 'Incorrect list of files') const {mtimeMs: newMtime} = await fs.stat(`${dir}/c`) t.deepEqual(newMtime, mtimeMs, 'File c should not have been modified') // Check that the output from make.js is valid t.deepEqual(output, '', 'Unexpected make.js output') }) test('no dependencies and no build command', async t => { const dir = 'no-dependencies' await makeC(dir) const output = await make(dir, 'all') // Check that the correct files exist and have the right contents const files = await fs.readdir(dir) t.deepEqual(new Set(files), new Set(['a', 'b', 'c']), 'Incorrect list of files') const aContents = await fs.readFile(`${dir}/a`, 'utf8') t.deepEqual(aContents, 'abc', `File ${dir}/a has incorrect contents`) const bContents = await fs.readFile(`${dir}/b`, 'utf8') t.deepEqual(bContents, 'bcd', `File ${dir}/b has incorrect contents`) const cContents = await fs.readFile(`${dir}/c`, 'utf8') t.deepEqual(cContents, 'cde', `File ${dir}/c has incorrect contents`) // Check that the output from make.js is valid matchOutput(output, [ {target: 'a', dependencies: [], lines: ['node ../create.js a abc']}, {target: 'b', dependencies: [], lines: ['node ../create.js b bcd']} ]) // Store the modification times to ensure make.js doesn't rebuild the files const initialMtimes = await Promise.all(files.map(async file => { const {mtimeMs} = await fs.stat(`${dir}/${file}`) return {file, mtimeMs} })) // Running make.js again should not do anything await wait(100) const output2 = await make(dir, 'all') await Promise.all(initialMtimes.map(async ({file, mtimeMs}) => { const {mtimeMs: newMtime} = await fs.stat(`${dir}/${file}`) t.deepEqual(newMtime, mtimeMs, `File ${dir}/${file} should not have been modified`) })) t.deepEqual(output2, '', 'Unexpected make.js output') }) test('phony target', async t => { // Build a, b, and c const dir = 'phony-target' await makeC(dir) await make(dir, 'all') const files = await fs.readdir(dir) t.deepEqual(new Set(files), new Set(['a', 'b', 'c']), 'Incorrect list of files') // Run 'clean' several times; the command should run every time for (let i = 0; i < 10; i++) { const output = await make(dir, 'clean') t.deepEqual(await fs.readdir(dir), ['c'], 'Incorrect list of files') t.deepEqual(output, 'node ../remove.js a b\n', 'Unexpected make.js output') } }) test('build error', async t => { const dir = 'build-error' try { await fs.rmdir(dir, {recursive: true}) } catch {} await fs.mkdir(dir) // Build error1, then error2, then error3 const {output, code} = await makeError(dir, 'error3') t.truthy(code, 'make.js should have exited with an error') t.deepEqual( output, 'node ../create.js error1 e\n' + 'node ../cat.js error2 error2\n', 'Unexpected make.js output' ) // error1 should have been created, but not error2 const files = await fs.readdir(dir) t.deepEqual(files, ['error1'], 'Incorrect list of files') // Building again should only try to build error2 const {output: output2, code: code2} = await makeError(dir, 'error3') t.truthy(code2, 'make.js should have exited with an error') t.deepEqual(output2, 'node ../cat.js error2 error2\n', 'Unexpected make.js output') })