176 lines
5.6 KiB
Go
176 lines
5.6 KiB
Go
package main
|
|
|
|
import (
|
|
"bufio"
|
|
"bytes"
|
|
"os"
|
|
"os/exec"
|
|
"path/filepath"
|
|
"regexp"
|
|
"strconv"
|
|
"strings"
|
|
"testing"
|
|
)
|
|
|
|
// Every file in this repository is published as the member repository's
|
|
// source, so the platform's former internal name must not appear in any of
|
|
// them. The only exceptions are identifiers that installed bastions, the
|
|
// harness images, or the host still read or write under that name. Each is
|
|
// listed in keptOldNames with what holds it in place; removing one means
|
|
// changing the other side first. Prose, comments and the changelog are never
|
|
// exceptions.
|
|
//
|
|
// The forbidden word is assembled from bytes so that this file does not
|
|
// contain it outside the exception list.
|
|
var oldName = string([]byte{0x73, 0x6b, 0x65, 0x6d, 0x61})
|
|
|
|
var keptOldNames = []string{
|
|
// Delegation tag the host mints for an agent's environment; agents
|
|
// already launched with it carry this name (env.go agentTokenEnvNames).
|
|
"SKEMA_AGENT_TOKEN",
|
|
// Variables the published harness image reads; it reads no other
|
|
// spelling yet (harness.go, lab.go).
|
|
"SKEMA_SIDECAR_BIND",
|
|
"SKEMA_APP_ID",
|
|
"SKEMA_WORKSPACE",
|
|
// The harness image's workspace root, a path inside that image (lab.go).
|
|
"/var/lib/skema/projects",
|
|
// The device-fingerprint URI SAN in the operator CSR. The host and the
|
|
// platform accept only this prefix at redeem (pair.go fpSANPrefix).
|
|
"urn:skema:hwfp:",
|
|
}
|
|
|
|
// keptOldNameRe matches any kept identifier as a whole token: not preceded or
|
|
// followed by a character that would make it part of a longer name.
|
|
var keptOldNameRe = func() *regexp.Regexp {
|
|
alts := make([]string, len(keptOldNames))
|
|
for i, k := range keptOldNames {
|
|
alts[i] = regexp.QuoteMeta(k)
|
|
}
|
|
return regexp.MustCompile(`(?i)(^|[^A-Za-z0-9_])(` + strings.Join(alts, "|") + `)`)
|
|
}()
|
|
|
|
// lineHasOldName reports whether line still carries the old name once every
|
|
// kept identifier is set aside. A kept identifier glued to a longer name (a
|
|
// trailing letter, digit or underscore) is not set aside, so the check still
|
|
// sees the old name in it.
|
|
func lineHasOldName(line string) bool {
|
|
locs := keptOldNameRe.FindAllStringSubmatchIndex(line, -1)
|
|
var b strings.Builder
|
|
prev := 0
|
|
for _, l := range locs {
|
|
start, end := l[4], l[5] // the identifier itself
|
|
if end < len(line) && isNameByte(line[end]) {
|
|
continue // part of a longer name: not a kept identifier
|
|
}
|
|
b.WriteString(line[prev:start])
|
|
b.WriteByte(' ')
|
|
prev = end
|
|
}
|
|
b.WriteString(line[prev:])
|
|
return strings.Contains(strings.ToLower(b.String()), oldName)
|
|
}
|
|
|
|
func isNameByte(c byte) bool {
|
|
return c == '_' || c >= '0' && c <= '9' || c >= 'a' && c <= 'z' || c >= 'A' && c <= 'Z'
|
|
}
|
|
|
|
// publishedFiles lists the files the member repository receives: what git
|
|
// tracks at the repository root (the publisher stages `git archive` of the
|
|
// release commit). Outside a git checkout it walks the tree instead.
|
|
func publishedFiles(t *testing.T, root string) []string {
|
|
t.Helper()
|
|
if out, err := exec.Command("git", "-C", root, "ls-files", "-z").Output(); err == nil && len(out) > 0 {
|
|
var files []string
|
|
for _, f := range bytes.Split(out, []byte{0}) {
|
|
if len(f) > 0 {
|
|
files = append(files, string(f))
|
|
}
|
|
}
|
|
return files
|
|
}
|
|
var files []string
|
|
err := filepath.Walk(root, func(p string, info os.FileInfo, err error) error {
|
|
if err != nil {
|
|
return err
|
|
}
|
|
if info.IsDir() && info.Name() == ".git" {
|
|
return filepath.SkipDir
|
|
}
|
|
if info.Mode().IsRegular() {
|
|
rel, _ := filepath.Rel(root, p)
|
|
files = append(files, rel)
|
|
}
|
|
return nil
|
|
})
|
|
if err != nil {
|
|
t.Fatalf("walking %s: %v", root, err)
|
|
}
|
|
return files
|
|
}
|
|
|
|
func TestPublishedSourceCarriesNoOldInternalName(t *testing.T) {
|
|
root, err := filepath.Abs("..")
|
|
if err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
files := publishedFiles(t, root)
|
|
if len(files) < 50 {
|
|
t.Fatalf("found only %d files under %s; the scan is not looking at the repository", len(files), root)
|
|
}
|
|
var hits []string
|
|
for _, rel := range files {
|
|
if strings.Contains(strings.ToLower(rel), oldName) {
|
|
hits = append(hits, rel+": (in the file name)")
|
|
}
|
|
data, err := os.ReadFile(filepath.Join(root, rel))
|
|
if err != nil {
|
|
continue // a tracked file deleted in the working tree
|
|
}
|
|
sc := bufio.NewScanner(bytes.NewReader(data))
|
|
sc.Buffer(make([]byte, 0, 1<<20), 1<<24)
|
|
n := 0
|
|
for sc.Scan() {
|
|
n++
|
|
if lineHasOldName(sc.Text()) {
|
|
hits = append(hits, rel+":"+strconv.Itoa(n)+": "+strings.TrimSpace(sc.Text()))
|
|
}
|
|
}
|
|
}
|
|
if len(hits) > 0 {
|
|
t.Errorf("the old internal name appears in %d published lines. Reword prose; an identifier "+
|
|
"may be added to keptOldNames only when something outside this repository still reads it:\n %s",
|
|
len(hits), strings.Join(hits, "\n "))
|
|
}
|
|
}
|
|
|
|
// The check itself: it must catch the word in prose and in a longer name, and
|
|
// pass the kept identifiers.
|
|
func TestOldNameCheckCatchesProseAndPassesKeptIdentifiers(t *testing.T) {
|
|
up := strings.ToUpper(oldName)
|
|
title := strings.ToUpper(oldName[:1]) + oldName[1:]
|
|
for _, line := range []string{
|
|
"// see " + oldName + " #649",
|
|
"// the " + title + " server",
|
|
up + "_NEW_VAR",
|
|
keptOldNames[0] + "X", // a kept name with a suffix is a different name
|
|
keptOldNames[len(keptOldNames)-1] + "x " + oldName,
|
|
} {
|
|
if !lineHasOldName(line) {
|
|
t.Errorf("not caught: %q", line)
|
|
}
|
|
}
|
|
for _, line := range []string{
|
|
`var agentTokenEnvNames = []string{"PRIVATAE_AGENT_TOKEN", "SKEMA_AGENT_TOKEN"}`,
|
|
`const fpSANPrefix = "urn:skema:hwfp:"`,
|
|
`labWorkspace = "/var/lib/skema/projects"`,
|
|
`- {name: SKEMA_WORKSPACE, value: "%s"}`,
|
|
`"-e", "SKEMA_APP_ID=" + spec.HarnessID}`,
|
|
"nothing to see here",
|
|
} {
|
|
if lineHasOldName(line) {
|
|
t.Errorf("flagged a kept identifier: %q", line)
|
|
}
|
|
}
|
|
}
|