Merge pull request 'mesh-build-node tests: never install a toolchain from the registry in the integration level; skip as NOT RUN when none is installed (issue 890)' (#491) from fix/build-node-tests-offline into main
This commit was merged in pull request #491.
This commit is contained in:
@@ -17,11 +17,11 @@ import (
|
|||||||
"git.novox.be/novox/mesh-sdk/go/forgekey"
|
"git.novox.be/novox/mesh-sdk/go/forgekey"
|
||||||
)
|
)
|
||||||
|
|
||||||
// realMachine gives the tests the real toolchain of the module's own lock and makes two workspaces holding one fixture
|
// realMachine gives the tests the real toolchain of the module's own lock and makes three workspaces holding one fixture
|
||||||
// bundle. The toolchain is the one this node's installed Node build module keeps (ADR 0533 §1): the integration level
|
// bundle. The toolchain is the one this node's installed Node build module keeps (ADR 0533 §1), copied into the test's
|
||||||
// is given its toolchains read-only and no network, so it is copied into the test's own cache from there. Only where
|
// own cache: the integration level is given its toolchains read-only and no network, so it is never installed from the
|
||||||
// no toolchain is installed (a desk) is it installed with `npm ci --ignore-scripts` from the mesh's registry, as the
|
// registry here. Where no Node build module has installed one (a node without it, a desk), the test is skipped by
|
||||||
// module does, which needs the network.
|
// name: an install from the public registry inside a shut-off level only fails, after 70 s of npm's retries.
|
||||||
func realMachine(t *testing.T) (*Module, string) {
|
func realMachine(t *testing.T) (*Module, string) {
|
||||||
t.Helper()
|
t.Helper()
|
||||||
for _, p := range []string{"node", "npm", "bwrap"} { // bwrap: tsc, esbuild and the scripts run shut off (1309)
|
for _, p := range []string{"node", "npm", "bwrap"} { // bwrap: tsc, esbuild and the scripts run shut off (1309)
|
||||||
@@ -44,16 +44,19 @@ func realMachine(t *testing.T) (*Module, string) {
|
|||||||
run := forgekey.ExecRunnerFor(0)
|
run := forgekey.ExecRunnerFor(0)
|
||||||
m := &Module{Node: "ace", Recipe: lock, Work: work, Run: run, Ctx: context.Background(),
|
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) {
|
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
|
return Registry{}, fmt.Errorf("the integration test installs no toolchain from a registry: it has no network")
|
||||||
}}}
|
}}}
|
||||||
withStore(t, m)
|
withStore(t, m)
|
||||||
if from := installedToolchain(t, filepath.Join(CacheDir, "toolchain"), filepath.Join(home, "toolchain", "package-lock.json")); from != "" {
|
from := installedToolchain(t, filepath.Join(CacheDir, "toolchain"), filepath.Join(home, "toolchain", "package-lock.json"))
|
||||||
copyToolchain(t, from, m.Toolchain.Paths.Dir(m.Recipe.Version()))
|
if from == "" {
|
||||||
|
t.Skipf("NOT RUN: no Node toolchain is installed under %s for this account to read (no Node build module on this node); "+
|
||||||
|
"the integration level has no network to install one, so this runs on a node that holds the Node build module", filepath.Join(CacheDir, "toolchain"))
|
||||||
}
|
}
|
||||||
if err := m.Toolchain.Ensure(context.Background(), m.Recipe.Version()); err != nil {
|
copyToolchain(t, from, m.Toolchain.Paths.Dir(m.Recipe.Version()))
|
||||||
t.Fatalf("no toolchain of this lock is installed under %s, and installing it from the registry failed: %v", filepath.Join(CacheDir, "toolchain"), err)
|
if err := m.Toolchain.Ensure(context.Background(), m.Recipe.Version()); err != nil { // present: opens it, installs nothing
|
||||||
|
t.Fatalf("the toolchain copied from %s cannot be used: %v", from, err)
|
||||||
}
|
}
|
||||||
for _, id := range []string{"w1", "w2"} {
|
for _, id := range []string{"w1", "w2", "w3"} {
|
||||||
for p, body := range map[string]string{
|
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/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/package.json": `{"name":"m","type":"module","scripts":{"test":"node -e \"process.exit(0)\""}}`,
|
||||||
@@ -65,10 +68,36 @@ func realMachine(t *testing.T) (*Module, string) {
|
|||||||
return m, work
|
return m, work
|
||||||
}
|
}
|
||||||
|
|
||||||
// 1490/AC2: a fixture TypeScript bundle importing @novox/mesh-sdk, built twice by the real tsc and esbuild, has equal
|
// 1490/AC2, 1491 and issue 1869, in one test so the toolchain is copied once: the real type-check and test script of the
|
||||||
// digests, and its archive holds the bundled .js, the .serve.mjs launcher and package.json.
|
// fixture pass the unit level; a package whose test imports its own build output (as mesh-sdk's do) passes the unit level,
|
||||||
func TestAFixtureBundleBuiltTwiceHasOneDigest(t *testing.T) {
|
// the test step emitting it with the real tsc, shut off, before the test script runs; and the fixture TypeScript bundle
|
||||||
|
// importing @novox/mesh-sdk, built twice by the real tsc and esbuild, has equal digests, its archive holding the bundled
|
||||||
|
// .js, the .serve.mjs launcher and package.json. The unit levels run in w3, so the two builds' workspaces stay alike.
|
||||||
|
func TestTheFixturePassesTheUnitLevelAndBuildsTwiceToOneDigest(t *testing.T) {
|
||||||
m, work := realMachine(t)
|
m, work := realMachine(t)
|
||||||
|
out, err := m.test(context.Background(), map[string]any{"workspace": "w3", "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("the fixture's unit level: result = %+v", r)
|
||||||
|
}
|
||||||
|
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, "w3", "tree", filepath.FromSlash(p)), body, 0o644)
|
||||||
|
}
|
||||||
|
out, err = m.test(context.Background(), map[string]any{"workspace": "w3", "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("the package importing its build: result = %+v", r)
|
||||||
|
}
|
||||||
var digests []string
|
var digests []string
|
||||||
for _, id := range []string{"w1", "w2"} {
|
for _, id := range []string{"w1", "w2"} {
|
||||||
out, err := m.build(context.Background(), map[string]any{"workspace": id, "module": "modules/m", "artifact": "tools"})
|
out, err := m.build(context.Background(), map[string]any{"workspace": id, "module": "modules/m", "artifact": "tools"})
|
||||||
@@ -89,43 +118,6 @@ func TestAFixtureBundleBuiltTwiceHasOneDigest(t *testing.T) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// 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)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// installedToolchain is the toolchain directory under toolchains that this node's Node build module installed: the
|
// installedToolchain is the toolchain directory under toolchains that this node's Node build module installed: the
|
||||||
// one installed from the lock at lockPath, byte for byte, or, when the change carries a lock no delivered release has
|
// one installed from the lock at lockPath, byte for byte, or, when the change carries a lock no delivered release has
|
||||||
// installed yet, the one installed last, said in the test's log (ADR 0533 §3: a new lock is proven by the module that
|
// installed yet, the one installed last, said in the test's log (ADR 0533 §3: a new lock is proven by the module that
|
||||||
|
|||||||
Reference in New Issue
Block a user