2020-12-31 15:50:04 -08:00
|
|
|
const fs = require('fs-extra')
|
|
|
|
const path = require('path')
|
|
|
|
const yaml = require('js-yaml')
|
|
|
|
const glob = require('glob')
|
2021-01-03 10:48:37 -08:00
|
|
|
const u = require('../src/utils')
|
2021-07-14 10:35:47 -07:00
|
|
|
const a = require('../src/assert')
|
2021-01-03 10:48:37 -08:00
|
|
|
const ergogen = require('../src/ergogen')
|
2021-07-11 11:36:11 -07:00
|
|
|
require('./helpers/mock_footprints').inject(ergogen)
|
2021-01-03 10:48:37 -08:00
|
|
|
|
|
|
|
let what = process.env.npm_config_what
|
2022-02-27 09:19:50 -08:00
|
|
|
const dump = process.env.npm_config_dump
|
2023-01-23 14:34:06 -08:00
|
|
|
const lineends = /(?:\r\n|\r|\n)/g
|
2022-02-27 09:19:50 -08:00
|
|
|
|
2023-01-31 14:30:01 -08:00
|
|
|
const handle_slash = (() => {
|
|
|
|
if (path.sep == '\\') {
|
|
|
|
return str => str.replace(/\\/g,'/')
|
|
|
|
} else {
|
|
|
|
return str => str
|
|
|
|
}
|
|
|
|
})()
|
2022-02-27 09:19:50 -08:00
|
|
|
|
2021-07-11 04:44:43 -07:00
|
|
|
|
|
|
|
// Unit tests
|
|
|
|
// the --what switch supports each unit individually
|
2021-07-14 10:35:47 -07:00
|
|
|
// the --dump switch does nothing here
|
2021-07-11 04:44:43 -07:00
|
|
|
|
2021-01-03 10:48:37 -08:00
|
|
|
what = what ? what.split(',') : false
|
2023-01-31 14:30:01 -08:00
|
|
|
for (const unit of glob.sync(handle_slash(path.join(__dirname, 'unit', '*.js')))) {
|
2021-01-03 10:48:37 -08:00
|
|
|
const base = path.basename(unit, '.js')
|
|
|
|
if (what && !what.includes(base)) continue
|
|
|
|
require(`./unit/${base}.js`)
|
|
|
|
}
|
2020-12-31 15:50:04 -08:00
|
|
|
|
2022-02-27 09:19:50 -08:00
|
|
|
|
|
|
|
|
2021-07-11 04:44:43 -07:00
|
|
|
// Integration tests
|
|
|
|
// the --what switch supports categories (like `points` and `outlines`)
|
2022-12-03 08:19:51 -08:00
|
|
|
// as well as individual tests using slash-notation (like `points/default`)
|
2022-02-27 09:19:50 -08:00
|
|
|
// the --dump switch can output the new results, overriding the old reference
|
2021-07-11 04:44:43 -07:00
|
|
|
|
2023-01-23 14:34:06 -08:00
|
|
|
const dump_structure = (obj, depth=-1, prefix='', breadcrumbs=[]) => {
|
|
|
|
if (a.type(obj)() != 'object') {
|
|
|
|
console.log(prefix + breadcrumbs.join('_'))
|
|
|
|
return
|
|
|
|
}
|
|
|
|
if (depth == 0) return
|
|
|
|
for (const [key, val] of Object.entries(obj)) {
|
|
|
|
breadcrumbs.push(key)
|
|
|
|
dump_structure(val, depth-1, prefix, breadcrumbs)
|
|
|
|
breadcrumbs.pop()
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2020-12-31 15:50:04 -08:00
|
|
|
const cap = s => s.charAt(0).toUpperCase() + s.slice(1)
|
|
|
|
|
2021-07-11 04:44:43 -07:00
|
|
|
const test = function(input_path) {
|
|
|
|
this.timeout(120000)
|
2021-07-16 16:15:27 -07:00
|
|
|
this.slow(120000)
|
2021-07-11 04:44:43 -07:00
|
|
|
title = path.basename(input_path, '.yaml').split('_').join(' ')
|
2021-07-15 13:03:03 -07:00
|
|
|
it(title, async function() {
|
2023-01-23 14:34:06 -08:00
|
|
|
|
2021-07-11 04:44:43 -07:00
|
|
|
const input = yaml.load(fs.readFileSync(input_path).toString())
|
2023-01-23 14:34:06 -08:00
|
|
|
const base = path.join(path.dirname(input_path), path.basename(input_path, '.yaml'))
|
2023-01-31 14:30:01 -08:00
|
|
|
const references = glob.sync(handle_slash(base) + '___*')
|
2023-01-23 14:34:06 -08:00
|
|
|
|
|
|
|
// handle deliberately wrong inputs
|
|
|
|
const exception = base + '___EXCEPTION.txt'
|
|
|
|
if (fs.existsSync(exception)) {
|
|
|
|
const exception_snippet = fs.readFileSync(exception).toString()
|
|
|
|
return await ergogen.process(input, true).should.be.rejectedWith(exception_snippet)
|
|
|
|
}
|
|
|
|
|
2022-02-27 09:19:50 -08:00
|
|
|
const output = await ergogen.process(input, true)
|
2021-07-14 10:35:47 -07:00
|
|
|
|
2022-02-27 09:19:50 -08:00
|
|
|
// compare output vs. reference
|
2023-01-23 14:34:06 -08:00
|
|
|
if (references.length) {
|
|
|
|
for (const expected_path of references) {
|
|
|
|
let expected = fs.readFileSync(expected_path).toString()
|
|
|
|
if (expected_path.endsWith('.json')) {
|
|
|
|
expected = JSON.parse(expected)
|
2022-02-27 09:19:50 -08:00
|
|
|
}
|
2023-01-23 14:34:06 -08:00
|
|
|
const comp_path = expected_path.split('___')[1].split('.')[0].split('_').join('.')
|
|
|
|
const output_part = u.deep(output, comp_path)
|
|
|
|
if (dump) {
|
|
|
|
if (a.type(output_part)() == 'string') {
|
|
|
|
fs.writeFileSync(expected_path, output_part)
|
|
|
|
} else {
|
|
|
|
fs.writeJSONSync(expected_path, output_part, {spaces: 4})
|
|
|
|
}
|
2023-01-23 01:02:08 -08:00
|
|
|
} else {
|
2023-01-23 14:34:06 -08:00
|
|
|
if (a.type(output_part)() == 'string') {
|
|
|
|
const parse_out = output_part.replace(lineends, '\n')
|
|
|
|
const parse_exp = expected.replace(lineends, '\n')
|
|
|
|
parse_out.should.deep.equal(parse_exp)
|
|
|
|
} else {
|
|
|
|
// JSON can hide negative zeroes, for example, so we canonical-ize first
|
|
|
|
const canonical_part = JSON.parse(JSON.stringify(output_part))
|
|
|
|
canonical_part.should.deep.equal(expected)
|
|
|
|
}
|
2023-01-23 01:02:08 -08:00
|
|
|
}
|
2022-02-27 09:19:50 -08:00
|
|
|
}
|
2023-01-23 14:34:06 -08:00
|
|
|
|
|
|
|
// explicit dump-ing above only works, if there are already files with the right name
|
|
|
|
// if there aren't, dump now outputs a list of candidates that could be referenced
|
|
|
|
} else if (dump) {
|
|
|
|
dump_structure(output, 3, base + '___')
|
2020-12-31 15:50:04 -08:00
|
|
|
}
|
|
|
|
})
|
2021-07-11 04:44:43 -07:00
|
|
|
}
|
|
|
|
|
|
|
|
if (what) {
|
|
|
|
for (const w of what) {
|
|
|
|
let regex
|
|
|
|
let title
|
|
|
|
if (w.includes('/')) {
|
|
|
|
title = cap(w.split('/')[0]) + ' (partial)'
|
|
|
|
regex = path.join(__dirname, w + '*.yaml')
|
|
|
|
} else {
|
|
|
|
title = cap(w)
|
|
|
|
regex = path.join(__dirname, w, '*.yaml')
|
|
|
|
}
|
|
|
|
describe(title, function() {
|
2023-01-31 14:30:01 -08:00
|
|
|
for (const i of glob.sync(handle_slash(regex))) {
|
2021-07-11 04:44:43 -07:00
|
|
|
test.call(this, i)
|
|
|
|
}
|
|
|
|
})
|
|
|
|
}
|
|
|
|
} else {
|
2022-12-03 09:11:11 -08:00
|
|
|
for (const part of ['points', 'outlines', 'cases', 'pcbs', 'footprints']) {
|
2021-07-11 04:44:43 -07:00
|
|
|
describe(cap(part), function() {
|
2023-01-31 14:30:01 -08:00
|
|
|
for (const i of glob.sync(handle_slash(path.join(__dirname, part, '*.yaml')))) {
|
2021-07-11 04:44:43 -07:00
|
|
|
test.call(this, i)
|
|
|
|
}
|
|
|
|
})
|
|
|
|
}
|
|
|
|
}
|
2021-07-16 16:15:27 -07:00
|
|
|
|
2022-02-27 09:19:50 -08:00
|
|
|
|
|
|
|
|
2021-07-16 16:15:27 -07:00
|
|
|
// End-to-end tests to actually drive the CLI as well
|
2022-02-27 09:19:50 -08:00
|
|
|
// --what is the same as above ('cli', or 'cli/prefix')
|
|
|
|
// --dump automatically overrides the old reference
|
2021-07-16 16:15:27 -07:00
|
|
|
|
2022-11-14 13:24:07 -08:00
|
|
|
const joiner = (a, b) => path.join(a, b)
|
|
|
|
const read = (...args) => fs.readFileSync(args.reduce(joiner, '')).toString()
|
|
|
|
const exists = (...args) => fs.existsSync(args.reduce(joiner, ''))
|
2021-07-16 16:15:27 -07:00
|
|
|
const { execSync } = require('child_process')
|
|
|
|
const dircompare = require('dir-compare')
|
|
|
|
|
2021-07-17 06:23:19 -07:00
|
|
|
const cli_what = what ? what.filter(w => w.startsWith('cli')) : ['cli']
|
|
|
|
|
|
|
|
for (let w of cli_what) {
|
|
|
|
if (!w.includes('/')) w += '/'
|
|
|
|
if (!w.endsWith('*')) w += '*'
|
2021-07-16 16:15:27 -07:00
|
|
|
describe('CLI', function() {
|
|
|
|
this.timeout(120000)
|
|
|
|
this.slow(120000)
|
2023-01-31 14:30:01 -08:00
|
|
|
for (const t of glob.sync(handle_slash(path.join(__dirname, w)))) {
|
2021-12-18 10:53:33 -08:00
|
|
|
it(path.basename(t).split('_').join(' '), function() {
|
2021-07-16 16:15:27 -07:00
|
|
|
const command = read(t, 'command')
|
|
|
|
const output_path = exists(t, 'path') ? read(t, 'path') : 'output'
|
2021-07-17 06:23:19 -07:00
|
|
|
fs.removeSync(output_path)
|
2022-01-22 14:13:18 -08:00
|
|
|
const version_regex = /\bv\d+\.\d+\.\d+(\-develop)?\b/
|
2021-07-16 16:15:27 -07:00
|
|
|
// correct execution
|
2022-11-14 13:24:07 -08:00
|
|
|
if (!exists(t, 'error')) {
|
|
|
|
let ref_log = ''
|
|
|
|
if (exists(t, 'log')) {
|
|
|
|
ref_log = read(t, 'log').replace(version_regex, '<version>')
|
|
|
|
}
|
2021-07-16 16:15:27 -07:00
|
|
|
const actual_log = execSync(command).toString().replace(version_regex, '<version>')
|
2021-07-17 06:23:19 -07:00
|
|
|
if (dump) {
|
|
|
|
fs.writeFileSync(path.join(t, 'log'), actual_log)
|
|
|
|
}
|
2022-11-14 13:24:07 -08:00
|
|
|
let ref_path = path.join(t, 'reference')
|
|
|
|
if (!exists(ref_path)) {
|
|
|
|
fs.mkdirpSync(ref_path)
|
|
|
|
}
|
|
|
|
if (fs.statSync(ref_path).isFile()) {
|
|
|
|
ref_path = path.resolve(path.join(t, read(ref_path).trim()))
|
|
|
|
}
|
|
|
|
const comp_res = dircompare.compareSync(output_path, ref_path, {
|
2023-01-23 01:02:08 -08:00
|
|
|
compareContent: true,
|
2023-01-23 14:34:06 -08:00
|
|
|
ignoreLineEnding: true,
|
2023-01-23 01:02:08 -08:00
|
|
|
compareFileSync: dircompare.fileCompareHandlers.lineBasedFileCompare.compareSync,
|
2023-01-23 14:34:06 -08:00
|
|
|
compareFileAsync: dircompare.fileCompareHandlers.lineBasedFileCompare.compareAsync
|
2021-07-16 16:15:27 -07:00
|
|
|
})
|
2021-12-15 13:45:35 -08:00
|
|
|
if (dump) {
|
2022-11-14 13:24:07 -08:00
|
|
|
fs.moveSync(output_path, ref_path, {overwrite: true})
|
2021-12-15 13:45:35 -08:00
|
|
|
} else {
|
2021-07-17 06:23:19 -07:00
|
|
|
fs.removeSync(output_path)
|
|
|
|
}
|
2023-01-23 14:34:06 -08:00
|
|
|
const parse_act_log = actual_log.replace(lineends, '\n')
|
|
|
|
const parse_ref_log = ref_log.replace(lineends, '\n')
|
2023-01-23 01:02:08 -08:00
|
|
|
parse_act_log.should.equal(parse_ref_log)
|
2021-12-15 13:45:35 -08:00
|
|
|
comp_res.same.should.be.true
|
2022-11-14 13:24:07 -08:00
|
|
|
// deliberately incorrect execution
|
2021-07-16 16:15:27 -07:00
|
|
|
} else {
|
2022-02-27 09:19:50 -08:00
|
|
|
const ref_error = read(t, 'error')
|
2021-07-16 16:15:27 -07:00
|
|
|
try {
|
|
|
|
execSync(command, {stdio: 'pipe'})
|
|
|
|
throw 'should_have_thrown'
|
|
|
|
} catch (ex) {
|
|
|
|
if (ex === 'should_have_thrown') {
|
|
|
|
throw new Error('This command should have thrown!')
|
|
|
|
}
|
2022-02-27 09:19:50 -08:00
|
|
|
const actual_error = ex.stderr.toString().split('\n')[0]
|
2021-07-17 06:23:19 -07:00
|
|
|
if (dump) {
|
|
|
|
fs.writeFileSync(path.join(t, 'error'), actual_error)
|
|
|
|
}
|
|
|
|
actual_error.includes(ref_error).should.be.true
|
2021-07-16 16:15:27 -07:00
|
|
|
}
|
|
|
|
}
|
|
|
|
})
|
|
|
|
}
|
|
|
|
})
|
2023-01-31 14:30:01 -08:00
|
|
|
}
|