mesh/merge-gate head c4913dbbcb35 merged into trunk 9daeab209ba4 — pass: builds brother → shanks; no bus step; every machine composes with the change as it…
mesh/repo-check head c4913dbbcb35 merged into trunk 9daeab209ba4 — pass: its merge-check.sh passed, each part in its toolchain: merge-check.sh (go), merge-…
mesh/delivery delivered
96 lines
2.2 KiB
Go
96 lines
2.2 KiB
Go
package main
|
|
|
|
import (
|
|
"go/ast"
|
|
"go/parser"
|
|
"go/token"
|
|
"sort"
|
|
"strconv"
|
|
"testing"
|
|
)
|
|
|
|
// 1528: a tool reads only arguments its input schema declares; the console refuses an undeclared
|
|
// one before it reaches the tool (scanner.scan read apart, which its schema never named).
|
|
func TestEveryArgumentAToolReadsIsDeclared(t *testing.T) {
|
|
fs := token.NewFileSet()
|
|
f, err := parser.ParseFile(fs, "main.go", nil, 0)
|
|
if err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
checked := 0
|
|
ast.Inspect(f, func(n ast.Node) bool {
|
|
lit, ok := n.(*ast.CompositeLit)
|
|
if !ok {
|
|
return true
|
|
}
|
|
var name string
|
|
var input, run ast.Expr
|
|
for _, e := range lit.Elts {
|
|
kv, ok := e.(*ast.KeyValueExpr)
|
|
if !ok {
|
|
continue
|
|
}
|
|
switch k, _ := kv.Key.(*ast.Ident); {
|
|
case k == nil:
|
|
case k.Name == "Name":
|
|
if b, ok := kv.Value.(*ast.BasicLit); ok {
|
|
name, _ = strconv.Unquote(b.Value)
|
|
}
|
|
case k.Name == "Input":
|
|
input = kv.Value
|
|
case k.Name == "Run":
|
|
run = kv.Value
|
|
}
|
|
}
|
|
if name == "" || input == nil || run == nil {
|
|
return true
|
|
}
|
|
declared := map[string]bool{}
|
|
ast.Inspect(input, func(m ast.Node) bool {
|
|
kv, ok := m.(*ast.KeyValueExpr)
|
|
if !ok {
|
|
return true
|
|
}
|
|
if k, ok := kv.Key.(*ast.BasicLit); ok && k.Value == `"properties"` {
|
|
if props, ok := kv.Value.(*ast.CompositeLit); ok {
|
|
for _, p := range props.Elts {
|
|
if pkv, ok := p.(*ast.KeyValueExpr); ok {
|
|
if b, ok := pkv.Key.(*ast.BasicLit); ok {
|
|
s, _ := strconv.Unquote(b.Value)
|
|
declared[s] = true
|
|
}
|
|
}
|
|
}
|
|
}
|
|
return false
|
|
}
|
|
return true
|
|
})
|
|
var missing []string
|
|
ast.Inspect(run, func(m ast.Node) bool {
|
|
ix, ok := m.(*ast.IndexExpr)
|
|
if !ok {
|
|
return true
|
|
}
|
|
if id, ok := ix.X.(*ast.Ident); ok && id.Name == "args" {
|
|
if b, ok := ix.Index.(*ast.BasicLit); ok && b.Kind == token.STRING {
|
|
s, _ := strconv.Unquote(b.Value)
|
|
if !declared[s] {
|
|
missing = append(missing, s)
|
|
}
|
|
}
|
|
}
|
|
return true
|
|
})
|
|
checked++
|
|
if len(missing) > 0 {
|
|
sort.Strings(missing)
|
|
t.Errorf("%s reads %v, which its input schema does not declare", name, missing)
|
|
}
|
|
return false
|
|
})
|
|
if checked < 5 {
|
|
t.Fatalf("checked %d tools; the test no longer finds the tool literals", checked)
|
|
}
|
|
}
|