Add the build seat's ask run: a program built from a change, run over the heads (issue 1921)
A run ask has a program built at a commit and run in the build seat's sandbox over named heads, its input kept by the asker by digest and measured against a bound before asking (ADR 0644, ADR 0656; design 47's ask run). The checker asks it for the checking program in milestone 47/B0. Claude-Session: https://claude.ai/code/session_01NcbgfFSnn24M3GcqttoU7i
This commit is contained in:
@@ -16,20 +16,36 @@ func composeAsk() StepAsk {
|
||||
Request: json.RawMessage(`{"v":1,"cases":[{"name":"change","manifests":{"demo":{"digest":"d1"}}}]}`), Reader: "mesh-sdk head"}}
|
||||
}
|
||||
|
||||
// 1622: a compose ask encodes and decodes with every field.
|
||||
// runAsk is the checker's run of a checking program built at a mesh-delivery head, over two heads (issue 1921, B0).
|
||||
func runAsk() StepAsk {
|
||||
in, err := RunInputOf("mesh-delivery-checker.inputs", []byte(`{"v":1}`))
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
return StepAsk{ID: "mh3k2x9qa1b2c6", Kind: AskCheck, Language: AskGo, Asker: "mesh-delivery-checker",
|
||||
At: time.Date(2026, 11, 6, 22, 0, 0, 0, time.UTC),
|
||||
Run: &RunJob{Program: RunProgram{Repository: "novox/mesh-delivery", Commit: askCommit, Dir: "modules/mesh-delivery-checker",
|
||||
Package: "git.novox.be/novox/mesh-delivery/modules/mesh-delivery-checker/cmd/mesh-checking-program"},
|
||||
Heads: []RunHead{{Repository: "novox/mesh-delivery", Commit: askCommit}, {Repository: "novox/mesh-sdk", Commit: askCommit}},
|
||||
Input: in, Args: []string{"-verdict"}, Reader: "checking program of mesh-delivery head"},
|
||||
Packages: PackageVersions{"git.novox.be/novox/mesh-sdk/go": askCommit}}
|
||||
}
|
||||
|
||||
// 1622: a compose ask encodes and decodes with every field; 1921 (B0): a run ask too.
|
||||
func TestAComposeAskRoundTrips(t *testing.T) {
|
||||
a := composeAsk()
|
||||
raw, err := EncodeStepAsk(a)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
got, err := DecodeStepAsk(raw)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
a.V = StepAskVersion
|
||||
if !reflect.DeepEqual(got, a) {
|
||||
t.Fatalf("round trip:\n got %+v\nwant %+v", got, a)
|
||||
for _, a := range []StepAsk{composeAsk(), runAsk()} {
|
||||
raw, err := EncodeStepAsk(a)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
got, err := DecodeStepAsk(raw)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
a.V = StepAskVersion
|
||||
if !reflect.DeepEqual(got, a) {
|
||||
t.Fatalf("round trip:\n got %+v\nwant %+v", got, a)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -54,6 +70,41 @@ func TestAComposeAskIsRefusedWhereItDoesNotBelong(t *testing.T) {
|
||||
t.Errorf("a compose ask %s is encoded", name)
|
||||
}
|
||||
}
|
||||
// 1921 (B0): a run ask likewise goes only on the Go seat's check stream, alone, builds a clean package at a full
|
||||
// commit, reads each named head once at a full commit, and names an input kept by digest within its bound.
|
||||
for name, change := range map[string]func(*StepAsk){
|
||||
"on the delivery stream": func(a *StepAsk) { a.Kind = AskDelivery },
|
||||
"on the Node seat": func(a *StepAsk) { a.Language = AskNode },
|
||||
"beside a compose": func(a *StepAsk) { a.Compose = composeAsk().Compose },
|
||||
"with a short commit": func(a *StepAsk) { a.Run.Program.Commit = "0123456" },
|
||||
"outside the repository": func(a *StepAsk) { a.Run.Program.Dir = "../x" },
|
||||
"with no package": func(a *StepAsk) { a.Run.Program.Package = "" },
|
||||
"with no head": func(a *StepAsk) { a.Run.Heads = nil },
|
||||
"with a head twice": func(a *StepAsk) { a.Run.Heads = append(a.Run.Heads, a.Run.Heads[0]) },
|
||||
"with a head at a branch": func(a *StepAsk) { a.Run.Heads[1].Commit = "main" },
|
||||
"with an input in no state": func(a *StepAsk) { a.Run.Input.State = "inputs" },
|
||||
"with an input by no digest": func(a *StepAsk) { a.Run.Input.Digest = "d1" },
|
||||
"with an input over its bound": func(a *StepAsk) { a.Run.Input.Size = RunInputBound + 1 },
|
||||
"with an argument of the shell": func(a *StepAsk) { a.Run.Args = []string{"-x; rm"} },
|
||||
} {
|
||||
a := runAsk()
|
||||
change(&a)
|
||||
if _, err := EncodeStepAsk(a); err == nil {
|
||||
t.Errorf("a run ask %s is encoded", name)
|
||||
}
|
||||
}
|
||||
// The asker refuses an input over its bound before it asks, naming its size; the build module refuses bytes that
|
||||
// are not the input named.
|
||||
if _, err := RunInputOf("mesh-delivery-checker.inputs", make([]byte, RunInputBound+1)); err == nil || !strings.Contains(err.Error(), "786433 bytes") {
|
||||
t.Errorf("an input over its bound: %v", err)
|
||||
}
|
||||
in := runAsk().Run.Input
|
||||
if err := in.Verify([]byte(`{"v":1}`)); err != nil {
|
||||
t.Errorf("the input named: %v", err)
|
||||
}
|
||||
if err := in.Verify([]byte(`{"v":2}`)); err == nil {
|
||||
t.Error("another input read as the one named")
|
||||
}
|
||||
}
|
||||
|
||||
// 1622/AC3, 1921: a composer is kept under one key per repository, commit, directory, package, toolchain and asked versions, so two asks of
|
||||
@@ -86,4 +137,15 @@ func TestAComposerIsKeptByWhatItWasBuiltFrom(t *testing.T) {
|
||||
if ComposerKey("r", askCommit, "go", "p", tc, nil) != ComposerKey("r", askCommit, "go", "p", tc, PackageVersions{}) {
|
||||
t.Error("an empty ask changed the key")
|
||||
}
|
||||
// 1921 (B0): a run's program is kept the same way, under a key of its own kind.
|
||||
p := RunProgram{Repository: "novox/mesh-delivery", Commit: askCommit, Dir: "modules/mesh-delivery-checker", Package: "p"}
|
||||
rk := RunKey(p, tc, nil)
|
||||
if !strings.HasPrefix(rk, "program-") || len(rk) != len("program-")+16 || rk != RunKey(p, tc, nil) {
|
||||
t.Errorf("run key = %q", rk)
|
||||
}
|
||||
q := p
|
||||
q.Commit = strings.Repeat("1", 40)
|
||||
if RunKey(q, tc, nil) == rk || RunKey(p, tc, PackageVersions{"m/x": a}) == rk {
|
||||
t.Error("two programs built from different inputs share the key")
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user