Footprint sideloading tests
This commit is contained in:
parent
24466eb01d
commit
0d73c59538
15 changed files with 315 additions and 14 deletions
15
src/cli.js
15
src/cli.js
|
@ -98,20 +98,25 @@ let injections = []
|
||||||
|
|
||||||
try {
|
try {
|
||||||
if (config_file.endsWith('.zip') || config_file.endsWith('.ekb')) {
|
if (config_file.endsWith('.zip') || config_file.endsWith('.ekb')) {
|
||||||
|
console.log('Analyzing bundle...');
|
||||||
[config_text, injections] = await io.unpack(
|
[config_text, injections] = await io.unpack(
|
||||||
(new jszip()).loadAsync(fs.readFileSync(config_file))
|
await (new jszip()).loadAsync(fs.readFileSync(config_file))
|
||||||
)
|
)
|
||||||
} else if (fs.statSync(config_file).isDirectory()) {
|
} else if (fs.statSync(config_file).isDirectory()) {
|
||||||
[config_text, injections] = await io.unpack(zip_from_dir(config_file))
|
console.log('Analyzing folder...');
|
||||||
|
[config_text, injections] = await io.unpack(
|
||||||
|
await zip_from_dir(config_file)
|
||||||
|
)
|
||||||
} else {
|
} else {
|
||||||
config_text = fs.readFileSync(config_file).toString()
|
config_text = fs.readFileSync(config_file).toString()
|
||||||
// no injections...
|
// no injections...
|
||||||
}
|
}
|
||||||
for (const [type, value] of injections) {
|
for (const [type, name, value] of injections) {
|
||||||
ergogen.inject(type, value)
|
ergogen.inject(type, name, value)
|
||||||
}
|
}
|
||||||
} catch (err) {
|
} catch (err) {
|
||||||
console.error(`Could not read config file "${config_file}": ${err}`)
|
console.error(`Could not read config file "${config_file}"!`)
|
||||||
|
console.error(err)
|
||||||
process.exit(2)
|
process.exit(2)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
11
src/io.js
11
src/io.js
|
@ -9,17 +9,22 @@ const kle = require('./kle')
|
||||||
exports.unpack = async (zip) => {
|
exports.unpack = async (zip) => {
|
||||||
|
|
||||||
// main config text (has to be called "config.ext" where ext is one of yaml/json/js)
|
// main config text (has to be called "config.ext" where ext is one of yaml/json/js)
|
||||||
const config_text = await zip.file(/^config\.(yaml|json|js)$/).async('string')
|
const candidates = zip.file(/^config\.(yaml|json|js)$/)
|
||||||
|
if (candidates.length != 1) {
|
||||||
|
throw new Error('Ambiguous config in bundle!')
|
||||||
|
}
|
||||||
|
const config_text = await candidates[0].async('string')
|
||||||
const injections = []
|
const injections = []
|
||||||
|
|
||||||
// bundled footprints
|
// bundled footprints
|
||||||
const fps = zip.folder('footprints')
|
const fps = zip.folder('footprints')
|
||||||
const module_prefix = 'const module = {};\n\n'
|
const module_prefix = 'const module = {};\n\n'
|
||||||
const module_suffix = '\n\nreturn module.exports;'
|
const module_suffix = '\n\nreturn module.exports;'
|
||||||
for (const fp in fps.file(/.*\.js$/)) {
|
for (const fp of fps.file(/.*\.js$/)) {
|
||||||
const name = fp.name.split('.')[0]
|
const name = fp.name.slice('footprints/'.length).split('.')[0]
|
||||||
const text = await fp.async('string')
|
const text = await fp.async('string')
|
||||||
const parsed = new Function(module_prefix + text + module_suffix)()
|
const parsed = new Function(module_prefix + text + module_suffix)()
|
||||||
|
// TODO: some sort of footprint validation?
|
||||||
injections.push(['footprint', name, parsed])
|
injections.push(['footprint', name, parsed])
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
1
test/cli/bad_bundle/command
Normal file
1
test/cli/bad_bundle/command
Normal file
|
@ -0,0 +1 @@
|
||||||
|
node src/cli.js test/
|
1
test/cli/bad_bundle/error
Normal file
1
test/cli/bad_bundle/error
Normal file
|
@ -0,0 +1 @@
|
||||||
|
Could not read config file "test/"!
|
1
test/cli/bundle/command
Normal file
1
test/cli/bundle/command
Normal file
|
@ -0,0 +1 @@
|
||||||
|
node src/cli.js test/fixtures/bundle --clean
|
14
test/cli/bundle/log
Normal file
14
test/cli/bundle/log
Normal file
|
@ -0,0 +1,14 @@
|
||||||
|
Ergogen <version> CLI
|
||||||
|
|
||||||
|
Analyzing folder...
|
||||||
|
Interpreting format: YAML
|
||||||
|
Preprocessing input...
|
||||||
|
Calculating variables...
|
||||||
|
Parsing points...
|
||||||
|
Generating outlines...
|
||||||
|
Modeling cases...
|
||||||
|
Scaffolding PCBs...
|
||||||
|
Cleaning output folder...
|
||||||
|
Writing output to disk...
|
||||||
|
Done.
|
||||||
|
|
98
test/cli/bundle/reference/outlines/box.dxf
Normal file
98
test/cli/bundle/reference/outlines/box.dxf
Normal file
|
@ -0,0 +1,98 @@
|
||||||
|
0
|
||||||
|
SECTION
|
||||||
|
2
|
||||||
|
HEADER
|
||||||
|
9
|
||||||
|
$INSUNITS
|
||||||
|
70
|
||||||
|
4
|
||||||
|
0
|
||||||
|
ENDSEC
|
||||||
|
0
|
||||||
|
SECTION
|
||||||
|
2
|
||||||
|
TABLES
|
||||||
|
0
|
||||||
|
TABLE
|
||||||
|
2
|
||||||
|
LTYPE
|
||||||
|
0
|
||||||
|
LTYPE
|
||||||
|
72
|
||||||
|
65
|
||||||
|
70
|
||||||
|
64
|
||||||
|
2
|
||||||
|
CONTINUOUS
|
||||||
|
3
|
||||||
|
______
|
||||||
|
73
|
||||||
|
0
|
||||||
|
40
|
||||||
|
0
|
||||||
|
0
|
||||||
|
ENDTAB
|
||||||
|
0
|
||||||
|
TABLE
|
||||||
|
2
|
||||||
|
LAYER
|
||||||
|
0
|
||||||
|
ENDTAB
|
||||||
|
0
|
||||||
|
ENDSEC
|
||||||
|
0
|
||||||
|
SECTION
|
||||||
|
2
|
||||||
|
ENTITIES
|
||||||
|
0
|
||||||
|
LINE
|
||||||
|
8
|
||||||
|
0
|
||||||
|
10
|
||||||
|
-9
|
||||||
|
20
|
||||||
|
-9
|
||||||
|
11
|
||||||
|
9
|
||||||
|
21
|
||||||
|
-9
|
||||||
|
0
|
||||||
|
LINE
|
||||||
|
8
|
||||||
|
0
|
||||||
|
10
|
||||||
|
9
|
||||||
|
20
|
||||||
|
-9
|
||||||
|
11
|
||||||
|
9
|
||||||
|
21
|
||||||
|
9
|
||||||
|
0
|
||||||
|
LINE
|
||||||
|
8
|
||||||
|
0
|
||||||
|
10
|
||||||
|
9
|
||||||
|
20
|
||||||
|
9
|
||||||
|
11
|
||||||
|
-9
|
||||||
|
21
|
||||||
|
9
|
||||||
|
0
|
||||||
|
LINE
|
||||||
|
8
|
||||||
|
0
|
||||||
|
10
|
||||||
|
-9
|
||||||
|
20
|
||||||
|
9
|
||||||
|
11
|
||||||
|
-9
|
||||||
|
21
|
||||||
|
-9
|
||||||
|
0
|
||||||
|
ENDSEC
|
||||||
|
0
|
||||||
|
EOF
|
122
test/cli/bundle/reference/pcbs/pcb.kicad_pcb
Normal file
122
test/cli/bundle/reference/pcbs/pcb.kicad_pcb
Normal file
|
@ -0,0 +1,122 @@
|
||||||
|
|
||||||
|
|
||||||
|
(kicad_pcb (version 20171130) (host pcbnew 5.1.6)
|
||||||
|
|
||||||
|
(page A3)
|
||||||
|
(title_block
|
||||||
|
(title pcb)
|
||||||
|
(rev v1.0.0)
|
||||||
|
(company Unknown)
|
||||||
|
)
|
||||||
|
|
||||||
|
(general
|
||||||
|
(thickness 1.6)
|
||||||
|
)
|
||||||
|
|
||||||
|
(layers
|
||||||
|
(0 F.Cu signal)
|
||||||
|
(31 B.Cu signal)
|
||||||
|
(32 B.Adhes user)
|
||||||
|
(33 F.Adhes user)
|
||||||
|
(34 B.Paste user)
|
||||||
|
(35 F.Paste user)
|
||||||
|
(36 B.SilkS user)
|
||||||
|
(37 F.SilkS user)
|
||||||
|
(38 B.Mask user)
|
||||||
|
(39 F.Mask user)
|
||||||
|
(40 Dwgs.User user)
|
||||||
|
(41 Cmts.User user)
|
||||||
|
(42 Eco1.User user)
|
||||||
|
(43 Eco2.User user)
|
||||||
|
(44 Edge.Cuts user)
|
||||||
|
(45 Margin user)
|
||||||
|
(46 B.CrtYd user)
|
||||||
|
(47 F.CrtYd user)
|
||||||
|
(48 B.Fab user)
|
||||||
|
(49 F.Fab user)
|
||||||
|
)
|
||||||
|
|
||||||
|
(setup
|
||||||
|
(last_trace_width 0.25)
|
||||||
|
(trace_clearance 0.2)
|
||||||
|
(zone_clearance 0.508)
|
||||||
|
(zone_45_only no)
|
||||||
|
(trace_min 0.2)
|
||||||
|
(via_size 0.8)
|
||||||
|
(via_drill 0.4)
|
||||||
|
(via_min_size 0.4)
|
||||||
|
(via_min_drill 0.3)
|
||||||
|
(uvia_size 0.3)
|
||||||
|
(uvia_drill 0.1)
|
||||||
|
(uvias_allowed no)
|
||||||
|
(uvia_min_size 0.2)
|
||||||
|
(uvia_min_drill 0.1)
|
||||||
|
(edge_width 0.05)
|
||||||
|
(segment_width 0.2)
|
||||||
|
(pcb_text_width 0.3)
|
||||||
|
(pcb_text_size 1.5 1.5)
|
||||||
|
(mod_edge_width 0.12)
|
||||||
|
(mod_text_size 1 1)
|
||||||
|
(mod_text_width 0.15)
|
||||||
|
(pad_size 1.524 1.524)
|
||||||
|
(pad_drill 0.762)
|
||||||
|
(pad_to_mask_clearance 0.05)
|
||||||
|
(aux_axis_origin 0 0)
|
||||||
|
(visible_elements FFFFFF7F)
|
||||||
|
(pcbplotparams
|
||||||
|
(layerselection 0x010fc_ffffffff)
|
||||||
|
(usegerberextensions false)
|
||||||
|
(usegerberattributes true)
|
||||||
|
(usegerberadvancedattributes true)
|
||||||
|
(creategerberjobfile true)
|
||||||
|
(excludeedgelayer true)
|
||||||
|
(linewidth 0.100000)
|
||||||
|
(plotframeref false)
|
||||||
|
(viasonmask false)
|
||||||
|
(mode 1)
|
||||||
|
(useauxorigin false)
|
||||||
|
(hpglpennumber 1)
|
||||||
|
(hpglpenspeed 20)
|
||||||
|
(hpglpendiameter 15.000000)
|
||||||
|
(psnegative false)
|
||||||
|
(psa4output false)
|
||||||
|
(plotreference true)
|
||||||
|
(plotvalue true)
|
||||||
|
(plotinvisibletext false)
|
||||||
|
(padsonsilk false)
|
||||||
|
(subtractmaskfromsilk false)
|
||||||
|
(outputformat 1)
|
||||||
|
(mirror false)
|
||||||
|
(drillshape 1)
|
||||||
|
(scaleselection 1)
|
||||||
|
(outputdirectory ""))
|
||||||
|
)
|
||||||
|
|
||||||
|
(net 0 "")
|
||||||
|
|
||||||
|
(net_class Default "This is the default net class."
|
||||||
|
(clearance 0.2)
|
||||||
|
(trace_width 0.25)
|
||||||
|
(via_dia 0.8)
|
||||||
|
(via_drill 0.4)
|
||||||
|
(uvia_dia 0.3)
|
||||||
|
(uvia_drill 0.1)
|
||||||
|
(add_net "")
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
|
(module injected_test_footprint (layer F.Cu) (tedit 5E1ADAC2)
|
||||||
|
(at 0 0 0)
|
||||||
|
|
||||||
|
|
||||||
|
(fp_text reference "I1" (at 0 0) (layer F.SilkS) hide (effects (font (size 1.27 1.27) (thickness 0.15))))
|
||||||
|
)
|
||||||
|
|
||||||
|
(gr_line (start -9 9) (end 9 9) (angle 90) (layer Edge.Cuts) (width 0.15))
|
||||||
|
(gr_line (start 9 9) (end 9 -9) (angle 90) (layer Edge.Cuts) (width 0.15))
|
||||||
|
(gr_line (start 9 -9) (end -9 -9) (angle 90) (layer Edge.Cuts) (width 0.15))
|
||||||
|
(gr_line (start -9 -9) (end -9 9) (angle 90) (layer Edge.Cuts) (width 0.15))
|
||||||
|
|
||||||
|
)
|
||||||
|
|
||||||
|
|
1
test/cli/zip/command
Normal file
1
test/cli/zip/command
Normal file
|
@ -0,0 +1 @@
|
||||||
|
node src/cli.js test/fixtures/bundle.zip --clean
|
14
test/cli/zip/log
Normal file
14
test/cli/zip/log
Normal file
|
@ -0,0 +1,14 @@
|
||||||
|
Ergogen <version> CLI
|
||||||
|
|
||||||
|
Analyzing bundle...
|
||||||
|
Interpreting format: YAML
|
||||||
|
Preprocessing input...
|
||||||
|
Calculating variables...
|
||||||
|
Parsing points...
|
||||||
|
Generating outlines...
|
||||||
|
Modeling cases...
|
||||||
|
Scaffolding PCBs...
|
||||||
|
Cleaning output folder...
|
||||||
|
Writing output to disk...
|
||||||
|
Done.
|
||||||
|
|
1
test/cli/zip/reference
Normal file
1
test/cli/zip/reference
Normal file
|
@ -0,0 +1 @@
|
||||||
|
../bundle/reference
|
BIN
test/fixtures/bundle.zip
vendored
Normal file
BIN
test/fixtures/bundle.zip
vendored
Normal file
Binary file not shown.
13
test/fixtures/bundle/config.yaml
vendored
Normal file
13
test/fixtures/bundle/config.yaml
vendored
Normal file
|
@ -0,0 +1,13 @@
|
||||||
|
points.zones.matrix:
|
||||||
|
outlines:
|
||||||
|
box:
|
||||||
|
- what: rectangle
|
||||||
|
where: true
|
||||||
|
size: 18
|
||||||
|
pcbs:
|
||||||
|
pcb:
|
||||||
|
outlines.edge.outline: box
|
||||||
|
footprints:
|
||||||
|
injected:
|
||||||
|
type: injected
|
||||||
|
anchor: matrix
|
13
test/fixtures/bundle/footprints/injected.js
vendored
Normal file
13
test/fixtures/bundle/footprints/injected.js
vendored
Normal file
|
@ -0,0 +1,13 @@
|
||||||
|
module.exports = {
|
||||||
|
params: {
|
||||||
|
class: 'I'
|
||||||
|
},
|
||||||
|
body: p => `
|
||||||
|
(module injected_test_footprint (layer F.Cu) (tedit 5E1ADAC2)
|
||||||
|
${p.at /* parametric position */}
|
||||||
|
|
||||||
|
${'' /* footprint reference */}
|
||||||
|
(fp_text reference "${p.ref}" (at 0 0) (layer F.SilkS) ${p.ref_hide} (effects (font (size 1.27 1.27) (thickness 0.15))))
|
||||||
|
)
|
||||||
|
`
|
||||||
|
}
|
|
@ -94,8 +94,9 @@ if (what) {
|
||||||
// --what is the same as above ('cli', or 'cli/prefix')
|
// --what is the same as above ('cli', or 'cli/prefix')
|
||||||
// --dump automatically overrides the old reference
|
// --dump automatically overrides the old reference
|
||||||
|
|
||||||
const read = (d, p) => fs.readFileSync(path.join(d, p)).toString()
|
const joiner = (a, b) => path.join(a, b)
|
||||||
const exists = (d, p) => fs.existsSync(path.join(d, p))
|
const read = (...args) => fs.readFileSync(args.reduce(joiner, '')).toString()
|
||||||
|
const exists = (...args) => fs.existsSync(args.reduce(joiner, ''))
|
||||||
const { execSync } = require('child_process')
|
const { execSync } = require('child_process')
|
||||||
const dircompare = require('dir-compare')
|
const dircompare = require('dir-compare')
|
||||||
|
|
||||||
|
@ -114,22 +115,33 @@ for (let w of cli_what) {
|
||||||
fs.removeSync(output_path)
|
fs.removeSync(output_path)
|
||||||
const version_regex = /\bv\d+\.\d+\.\d+(\-develop)?\b/
|
const version_regex = /\bv\d+\.\d+\.\d+(\-develop)?\b/
|
||||||
// correct execution
|
// correct execution
|
||||||
if (exists(t, 'log')) {
|
if (!exists(t, 'error')) {
|
||||||
const ref_log = read(t, 'log').replace(version_regex, '<version>')
|
let ref_log = ''
|
||||||
|
if (exists(t, 'log')) {
|
||||||
|
ref_log = read(t, 'log').replace(version_regex, '<version>')
|
||||||
|
}
|
||||||
const actual_log = execSync(command).toString().replace(version_regex, '<version>')
|
const actual_log = execSync(command).toString().replace(version_regex, '<version>')
|
||||||
if (dump) {
|
if (dump) {
|
||||||
fs.writeFileSync(path.join(t, 'log'), actual_log)
|
fs.writeFileSync(path.join(t, 'log'), actual_log)
|
||||||
}
|
}
|
||||||
const comp_res = dircompare.compareSync(output_path, path.join(t, 'reference'), {
|
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, {
|
||||||
compareContent: true
|
compareContent: true
|
||||||
})
|
})
|
||||||
if (dump) {
|
if (dump) {
|
||||||
fs.moveSync(output_path, path.join(t, 'reference'), {overwrite: true})
|
fs.moveSync(output_path, ref_path, {overwrite: true})
|
||||||
} else {
|
} else {
|
||||||
fs.removeSync(output_path)
|
fs.removeSync(output_path)
|
||||||
}
|
}
|
||||||
actual_log.should.equal(ref_log)
|
actual_log.should.equal(ref_log)
|
||||||
comp_res.same.should.be.true
|
comp_res.same.should.be.true
|
||||||
|
// deliberately incorrect execution
|
||||||
} else {
|
} else {
|
||||||
const ref_error = read(t, 'error')
|
const ref_error = read(t, 'error')
|
||||||
try {
|
try {
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue