build-agent's check container has no bwrap; the build nodes, where the checker runs from R4e, do. The sibling test and the real Node build skip naming it, and the pull-head pin test still runs its fetch half and skips only the shut-off build.
118 lines
5.0 KiB
Go
118 lines
5.0 KiB
Go
//go:build integration
|
|
|
|
package main
|
|
|
|
import (
|
|
"context"
|
|
"os"
|
|
"os/exec"
|
|
"path/filepath"
|
|
"slices"
|
|
"testing"
|
|
|
|
"git.novox.be/novox/mesh-sdk/go/forgekey"
|
|
)
|
|
|
|
// realMachine installs the real toolchain from the module's own lock (npm ci --ignore-scripts, from the mesh's
|
|
// registry for @novox, which reads without a credential) and makes two workspaces holding one fixture bundle.
|
|
func realMachine(t *testing.T) (*Module, string) {
|
|
t.Helper()
|
|
for _, p := range []string{"node", "npm", "bwrap"} { // bwrap: tsc, esbuild and the scripts run shut off (1309)
|
|
if _, err := exec.LookPath(p); err != nil {
|
|
t.Skipf("NOT RUN: no %s installed where this check runs (the mesh's Go toolchain image holds none); proven live on a build node", p)
|
|
}
|
|
}
|
|
home, cache, work := t.TempDir(), t.TempDir(), t.TempDir()
|
|
for _, n := range []string{"package.json", "package-lock.json"} {
|
|
raw, err := os.ReadFile(filepath.Join(moduleDir, "toolchain", n))
|
|
if err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
write(t, filepath.Join(home, "toolchain", n), string(raw), 0o644)
|
|
}
|
|
lock, err := ReadRecipe(filepath.Join(home, "toolchain", "package-lock.json"))
|
|
if err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
run := forgekey.ExecRunnerFor(0)
|
|
m := &Module{Node: "ace", Recipe: lock, Work: work, Run: run, Ctx: context.Background(),
|
|
Toolchain: &Toolchain{Paths: Paths{Home: home, Cache: cache}, Run: run, Registry: func() (Registry, error) {
|
|
return Registry{URL: "https://git.novox.be/api/packages/novox/npm/"}, nil
|
|
}}}
|
|
withStore(t, m)
|
|
if err := m.Toolchain.Ensure(context.Background(), m.Recipe.Version()); err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
for _, id := range []string{"w1", "w2"} {
|
|
for p, body := range map[string]string{
|
|
"modules/m/module.json": `{"module":"m","build":{"artifacts":[{"name":"tools","kind":"bundle","language":"typescript","entrypoints":["tools/index.js"]}]}}`,
|
|
"modules/m/package.json": `{"name":"m","type":"module","scripts":{"test":"node -e \"process.exit(0)\""}}`,
|
|
"modules/m/tools/index.ts": "import { serveRegisteredOverStdio } from \"@novox/mesh-sdk/stdio\";\nexport const f: () => Promise<void> = serveRegisteredOverStdio as () => Promise<void>;\n",
|
|
} {
|
|
write(t, filepath.Join(work, id, "tree", filepath.FromSlash(p)), body, 0o644)
|
|
}
|
|
}
|
|
return m, work
|
|
}
|
|
|
|
// 1490/AC2: a fixture TypeScript bundle importing @novox/mesh-sdk, built twice by the real tsc and esbuild, has equal
|
|
// digests, and its archive holds the bundled .js, the .serve.mjs launcher and package.json.
|
|
func TestAFixtureBundleBuiltTwiceHasOneDigest(t *testing.T) {
|
|
m, work := realMachine(t)
|
|
var digests []string
|
|
for _, id := range []string{"w1", "w2"} {
|
|
out, err := m.build(context.Background(), map[string]any{"workspace": id, "module": "modules/m", "artifact": "tools"})
|
|
if err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
r := out.(BuildResult)
|
|
digests = append(digests, r.Digest)
|
|
if want := []string{"package.json", "tools/index.js", "tools/index.serve.mjs"}; !slices.Equal(r.Files, want) {
|
|
t.Errorf("files = %v, want %v", r.Files, want)
|
|
}
|
|
}
|
|
if digests[0] != digests[1] {
|
|
t.Errorf("digests differ: %v", digests)
|
|
}
|
|
if links := symlinksUnder(t, work); len(links) != 0 {
|
|
t.Errorf("symlinks in the workspaces: %v", links)
|
|
}
|
|
}
|
|
|
|
// 1491: the real type-check and test script of the same fixture pass the unit level.
|
|
func TestTheFixturePassesTheUnitLevel(t *testing.T) {
|
|
m, _ := realMachine(t)
|
|
out, err := m.test(context.Background(), map[string]any{"workspace": "w1", "module": "modules/m", "level": "unit"})
|
|
if err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
if r := out.(*TestResult); !r.Passed || r.NoTests || len(r.Ran) != 2 {
|
|
t.Errorf("result = %+v", r)
|
|
}
|
|
}
|
|
|
|
// Issue 1869: a package whose test imports its own build output (as mesh-sdk's do) passes the unit level: the test step
|
|
// emits it with the real tsc, shut off, before the test script runs.
|
|
func TestAPackageWhoseTestsImportItsBuildPassesTheUnitLevel(t *testing.T) {
|
|
if _, err := exec.LookPath("bwrap"); err != nil {
|
|
t.Skip("NOT RUN: no bubblewrap installed where this check runs; every build node has it (the module declares it)")
|
|
}
|
|
m, work := realMachine(t)
|
|
for p, body := range map[string]string{
|
|
"modules/p/package.json": `{"name":"p","type":"module","scripts":{"build":"tsc","test":"node --test test/a.test.mjs","prepare":"tsc"}}`,
|
|
"modules/p/tsconfig.json": `{"compilerOptions":{"module":"NodeNext","moduleResolution":"NodeNext","target":"ES2022","outDir":"dist","rootDir":"src"},"include":["src"]}`,
|
|
"modules/p/src/index.ts": "export const answer: number = 42;\n",
|
|
"modules/p/test/a.test.mjs": "import { test } from 'node:test';\nimport assert from 'node:assert';\nimport { answer } from '../dist/index.js';\n" +
|
|
"test('the build is there', () => assert.equal(answer, 42));\n",
|
|
} {
|
|
write(t, filepath.Join(work, "w1", "tree", filepath.FromSlash(p)), body, 0o644)
|
|
}
|
|
out, err := m.test(context.Background(), map[string]any{"workspace": "w1", "module": "modules/p", "level": "unit"})
|
|
if err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
if r := out.(*TestResult); !r.Passed || !slices.Equal(r.Ran, []string{"build", "test"}) {
|
|
t.Errorf("result = %+v", r)
|
|
}
|
|
}
|