@novox/mesh-sdk and @novox:registry= are the software's package path, as the Go module path is; who@node is still a node name (1838/AC2). Reading every module, a regexp compiled per name per line made the check take 41 s; compiled once, 7.5 s.
201 lines
6.6 KiB
Go
201 lines
6.6 KiB
Go
package main
|
|
|
|
import (
|
|
"os"
|
|
"path/filepath"
|
|
"strings"
|
|
"testing"
|
|
)
|
|
|
|
var names = []string{"novox", "ace", "shanks", "g14"}
|
|
|
|
func TestANodeNameIsRefusedWhereItIsWritten(t *testing.T) {
|
|
cases := map[string]struct{ file, src string }{
|
|
"manifest string": {"modules/kernel/module.json", "{\n \"description\": \"as on Shanks\"\n}\n"},
|
|
"file line": {"modules/kernel/files/boot.sh", "#!/bin/sh\necho run on g14\n"},
|
|
"go identifier": {"modules/kernel/cmd/x/a.go", "package main\n\nfunc novox() {}\n"},
|
|
"test name": {"modules/kernel/cmd/x/a_test.go", "package main\n\nfunc TestAce(t *testing.T) {}\n\nfunc TestOnAce_x(t *testing.T) {}\n"},
|
|
}
|
|
for name, c := range cases {
|
|
if got := scan(c.file, c.src, names); len(got) == 0 {
|
|
t.Errorf("%s: %q not refused", name, c.src)
|
|
}
|
|
}
|
|
}
|
|
|
|
func TestTheFindingNamesTheLineAndTheWord(t *testing.T) {
|
|
got := scan("f.sh", "a\nb\nrun on ACE now\n", names)
|
|
if len(got) != 1 || !strings.HasPrefix(got[0], "f.sh:3:") || !strings.Contains(got[0], "ace") {
|
|
t.Errorf("got %v", got)
|
|
}
|
|
}
|
|
|
|
func TestTheForgeIsNotANodeName(t *testing.T) {
|
|
for _, s := range []string{
|
|
"see novox/hq issue 5",
|
|
"module git.novox.be/novox/mesh-sdk/go v1.2.3",
|
|
"https://git.novox.be/novox/mesh-catalog",
|
|
"git.novox.be",
|
|
"space trace surface grace g14x",
|
|
} {
|
|
if got := scan("f", s, names); len(got) != 0 {
|
|
t.Errorf("%q refused: %v", s, got)
|
|
}
|
|
}
|
|
}
|
|
|
|
func TestANodeNameInAPathOrJoinedIsRefused(t *testing.T) {
|
|
for _, s := range []string{
|
|
"modules/kernel/testdata/novox/meminfo",
|
|
"/srv/novox/data",
|
|
"testdata/shanks-meminfo.txt",
|
|
"on-shanks",
|
|
"shanks-desktop",
|
|
"mesh-novox",
|
|
"func novoxTree() {}",
|
|
"aceFiles := 1",
|
|
"g14Meminfo := 2",
|
|
"novox_tree := 3",
|
|
} {
|
|
if got := scan("f", s, names); len(got) == 0 {
|
|
t.Errorf("%q not refused", s)
|
|
}
|
|
}
|
|
}
|
|
|
|
func TestANodeNamedPathIsRefusedThroughRun(t *testing.T) {
|
|
root := t.TempDir()
|
|
p := filepath.Join(root, "modules/kernel/testdata/ace/x")
|
|
os.MkdirAll(filepath.Dir(p), 0o755)
|
|
os.WriteFile(p, []byte("clean\n"), 0o644)
|
|
got, err := run(root, names, []string{"kernel"})
|
|
if err != nil || len(got) != 1 || !strings.HasPrefix(got[0], "modules/kernel/testdata/ace/x:0: ") {
|
|
t.Errorf("got %v, %v", got, err)
|
|
}
|
|
}
|
|
|
|
func TestCheckReturnsOneOnAFindingAndTwoOnAnUnreadableList(t *testing.T) {
|
|
root := t.TempDir()
|
|
write := func(p, s string) {
|
|
p = filepath.Join(root, p)
|
|
os.MkdirAll(filepath.Dir(p), 0o755)
|
|
os.WriteFile(p, []byte(s), 0o644)
|
|
}
|
|
write("particulars", "ace\n")
|
|
write("modules/kernel/a", "clean\n")
|
|
if got := check(root); got != 0 {
|
|
t.Errorf("clean = %d, want 0", got)
|
|
}
|
|
write("modules/kernel/a", "on ace\n")
|
|
if got := check(root); got != 1 {
|
|
t.Errorf("finding = %d, want 1", got)
|
|
}
|
|
os.Remove(filepath.Join(root, "particulars"))
|
|
if got := check(root); got != 2 {
|
|
t.Errorf("no list = %d, want 2", got)
|
|
}
|
|
}
|
|
|
|
func TestRunReadsOnlyTheModulesItIsGiven(t *testing.T) {
|
|
root := t.TempDir()
|
|
write := func(p, s string) {
|
|
p = filepath.Join(root, p)
|
|
os.MkdirAll(filepath.Dir(p), 0o755)
|
|
os.WriteFile(p, []byte(s), 0o644)
|
|
}
|
|
write("modules/kernel/files/a", "on novox\n")
|
|
write("modules/other/files/a", "on novox\n")
|
|
got, err := run(root, names, []string{"kernel"})
|
|
if err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
if len(got) != 1 || !strings.Contains(got[0], "modules/kernel/files/a:1") {
|
|
t.Errorf("got %v", got)
|
|
}
|
|
}
|
|
|
|
// 1838/AC1: the check reads every directory under modules/ and no list of covered modules, so a module is
|
|
// covered from its first commit.
|
|
func TestEveryModuleIsReadWithoutAList(t *testing.T) {
|
|
root := t.TempDir()
|
|
write := func(p, s string) {
|
|
p = filepath.Join(root, p)
|
|
os.MkdirAll(filepath.Dir(p), 0o755)
|
|
os.WriteFile(p, []byte(s), 0o644)
|
|
}
|
|
write("particulars", "novox\n")
|
|
write("modules/kernel/files/a", "clean\n")
|
|
if got := check(root); got != 0 {
|
|
t.Errorf("clean, no covered list = %d, want 0", got)
|
|
}
|
|
write("modules/new-module/files/a", "on novox\n")
|
|
if got := check(root); got != 1 {
|
|
t.Errorf("a finding in a module no list names = %d, want 1", got)
|
|
}
|
|
}
|
|
|
|
// 1838/AC2: the hardware model's own name and the software's own name are not node names.
|
|
func TestTheHardwareModelAndTheSoftwareAreNotNodeNames(t *testing.T) {
|
|
for _, s := range []string{
|
|
"modules/asus-zephyrus-g14/README.md",
|
|
"the asus-zephyrus-g14 module",
|
|
"ASUS_ZEPHYRUS_G14=1",
|
|
"product_family: ROG Zephyrus G14",
|
|
"# This machine is a node of a Novox mesh",
|
|
"Novox Mesh turns a handful of personal machines into one system",
|
|
"<!-- novox mesh: this file was changed on two nodes",
|
|
`const sealInfo = "novox-mesh sealed box v1"`,
|
|
"module git.novox.be/novox/mesh-catalog/modules/kernel",
|
|
} {
|
|
if got := scan("f", s, names); len(got) != 0 {
|
|
t.Errorf("%q refused: %v", s, got)
|
|
}
|
|
}
|
|
}
|
|
|
|
// 1838/AC2: a node name standing alone is still one, beside the hardware's or the software's name too.
|
|
func TestANodeNameBesideTheHardwareOrTheSoftwareIsRefused(t *testing.T) {
|
|
cases := map[string]string{
|
|
"g14": "the asus-zephyrus-g14 module on g14",
|
|
"shanks": "Novox Mesh on shanks",
|
|
"novox": "resolves under novox.internal",
|
|
"ace": "ROG Zephyrus G14 beside ace",
|
|
"novox mesh-ish": "mesh.mod.gitea.call.x.novox-mesh-vault",
|
|
}
|
|
for want, s := range cases {
|
|
got := scan("modules/m/a.go", s, names)
|
|
if len(got) != 1 || !strings.HasPrefix(got[0], "modules/m/a.go:1: ") {
|
|
t.Errorf("%s: %q gave %v, want one finding naming file:line", want, s, got)
|
|
}
|
|
}
|
|
}
|
|
|
|
// 1838/AC2: the software's npm scope (@novox/mesh-sdk, @novox:registry=) is its package path, as the Go module
|
|
// path is; a session's who@node naming a node is still a node name.
|
|
func TestTheSoftwaresNpmScopeIsNotANodeName(t *testing.T) {
|
|
for _, s := range []string{
|
|
"printf '%s\\n' ${shellQuote(`@novox:registry=${registry}`)}",
|
|
"const url = `${asked}@novox%2fmesh-sdk`;",
|
|
"# The @novox scope resolves from the mesh's own package registry",
|
|
`"dependencies": { "@novox/mesh-sdk": "^0.1.0" }`,
|
|
} {
|
|
if got := scan("f", s, names); len(got) != 0 {
|
|
t.Errorf("%q refused: %v", s, got)
|
|
}
|
|
}
|
|
for _, s := range []string{"by fix-1@novox", "jochen@novox:"} {
|
|
if got := scan("f", s, names); len(got) != 1 {
|
|
t.Errorf("%q gave %v, want one finding", s, got)
|
|
}
|
|
}
|
|
}
|
|
|
|
// 1838/AC1: reading every module, the check compiles its matchers once, not once a line: a line read costs a
|
|
// few allocations, not a regexp compiled per name (the whole catalogue took 41 s with one per line).
|
|
func TestALineIsReadWithoutCompilingAMatcher(t *testing.T) {
|
|
line := "a line of code that names nothing at all, with git.novox.be/novox/mesh-sdk in it"
|
|
if n := testing.AllocsPerRun(100, func() { hits(line, names) }); n > 20 {
|
|
t.Errorf("a line costs %.0f allocations, want at most 20", n)
|
|
}
|
|
}
|