The facts carry a level as the rules read it, and a seat list the program cannot make ends the check without a verdict asked (issue 1921, B0 review round 1)
A level's digest, unmet packages, kept packages' names and test packages are read by no rule: a mesh-catalog check step's two levels were 78682 bytes as facts and are 4506. A build node with no job run held a check four begin bounds; it now holds it two. Claude-Session: https://claude.ai/code/session_01NcbgfFSnn24M3GcqttoU7i
This commit is contained in:
@@ -827,12 +827,12 @@ func TestACheckThatCannotBeJudgedFailsNamingWhy(t *testing.T) { // 1289/AC4, 192
|
||||
env map[string]string
|
||||
words string
|
||||
tests bool // the digest and test steps ran
|
||||
dropped int32 // the run asks dropped: each put twice, the seat list's and the verdict's
|
||||
dropped int32 // the run asks dropped: the seat list's, put twice, and no verdict asked after it
|
||||
program bool // the checking program judged it
|
||||
}{
|
||||
{name: "a head that does not merge", set: func(f *fakeBuildModules) { f.conflict.Store(true) }, words: "files in conflict: a.go, sub/b.go", program: true},
|
||||
{name: "a run ask no build node begins", set: func(f *fakeBuildModules) { f.drop.Store(true) }, env: map[string]string{"MESH_CHECKER_BEGIN_BOUND": "500ms"},
|
||||
words: "no build node began the job run of the asks", tests: true, dropped: 4},
|
||||
words: "no build node began the job run of the asks", tests: true, dropped: 2},
|
||||
{name: "a program that does not build", set: func(f *fakeBuildModules) { f.broken.Store("go build: undefined: rules.Nothing") },
|
||||
words: "by the checking program: its run ask", tests: true},
|
||||
} {
|
||||
|
||||
@@ -380,16 +380,16 @@ func TestACleanMergeIsFetchedAtItsTrunkAndBothLevelsPass(t *testing.T) { // 1679
|
||||
run func(a delivery.StepAsk, s delivery.Step) (delivery.Step, bool)
|
||||
at string // the commit the program is built at; empty when it fails
|
||||
fails string
|
||||
runs int // the run asks put when it fails: each put twice when never begun
|
||||
runs int // the run asks put when it fails: each put twice when never begun, and none after the seat list's
|
||||
}{
|
||||
{name: "at the group's mesh-delivery head", at: head1},
|
||||
{name: "at mesh-delivery's trunk", repo: "novox/mesh-catalog", at: trunkD},
|
||||
{name: "never begun", run: func(delivery.StepAsk, delivery.Step) (delivery.Step, bool) { return delivery.Step{}, true },
|
||||
fails: "no build node began the job run of the asks", runs: 4},
|
||||
fails: "no build node began the job run of the asks", runs: 2},
|
||||
{name: "does not build", run: func(_ delivery.StepAsk, s delivery.Step) (delivery.Step, bool) {
|
||||
s.State, s.Reason = delivery.StepFailed, "the program does not build: undefined: rules.Nothing"
|
||||
return s, true
|
||||
}, fails: "by the checking program: its run ask", runs: 2},
|
||||
}, fails: "by the checking program: its run ask", runs: 1},
|
||||
{name: "a rule the change alters", at: head1, run: func(a delivery.StepAsk, s delivery.Step) (delivery.Step, bool) {
|
||||
if a.Run.Args[0] != "-verdict" {
|
||||
return s, false
|
||||
@@ -411,7 +411,7 @@ func TestACleanMergeIsFetchedAtItsTrunkAndBothLevelsPass(t *testing.T) { // 1679
|
||||
if v.State != delivery.VerdictFail || !strings.Contains(v.Failed.Words, row.fails) {
|
||||
t.Errorf("%s: verdict %+v, want a fail saying %q", row.name, v, row.fails)
|
||||
}
|
||||
if row.at == "" && (len(b.runs) != row.runs || v.JudgedBy != nil) {
|
||||
if row.at == "" && (len(b.runs) != row.runs || v.JudgedBy != nil || slices.ContainsFunc(b.runs, func(a delivery.StepAsk) bool { return a.Run.Args[0] == "-verdict" })) {
|
||||
t.Errorf("%s: %d run asks, judged by %+v: want %d and none judging", row.name, len(b.runs), v.JudgedBy, row.runs)
|
||||
}
|
||||
} else if v.State != delivery.VerdictPass {
|
||||
@@ -428,10 +428,18 @@ func TestACleanMergeIsFetchedAtItsTrunkAndBothLevelsPass(t *testing.T) { // 1679
|
||||
t.Fatalf("%s: run asks %+v, want the seat list and then the verdict", row.name, b.runs)
|
||||
}
|
||||
in := b.runs[1].Run.Input // the facts kept as their exact bytes under their digest
|
||||
if body, _, found, _ := b.inputs.Get(context.Background(), in.Digest); !found || in.Verify(body) != nil || in.State != InputsState ||
|
||||
body, _, found, _ := b.inputs.Get(context.Background(), in.Digest)
|
||||
if !found || in.Verify(body) != nil || in.State != InputsState ||
|
||||
!strings.Contains(string(body), `"group":"feat/x"`) {
|
||||
t.Errorf("%s: the verdict's input %+v is not kept whole: %s", row.name, in, body)
|
||||
}
|
||||
// Review round 1 of milestone 47/B0: a level is carried as the rules read it, without its digest, its packages or
|
||||
// its kept packages' names, so a group's facts stay within the input's bound.
|
||||
for _, unread := range []string{`"digest":{`, `"packages":[`, `"unmet"`, `"package":"m/`} {
|
||||
if strings.Contains(string(body), unread) {
|
||||
t.Errorf("%s: the facts carry %s, which no rule reads: %s", row.name, unread, body)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -307,12 +307,18 @@ func (j *Examiner) Judge(ctx context.Context, c *Case) (Outcome, error) {
|
||||
st.judgeAll(ctx)
|
||||
st.takeTryCandidate(ctx)
|
||||
// The heads' seat list, from the checking program, before the validator and the composer are asked (ADR 0636 §4).
|
||||
st.seatList(ctx)
|
||||
st.judgeManifests(ctx)
|
||||
st.refuseCycle(ctx)
|
||||
st.compose(ctx)
|
||||
// The verdict is the checking program's of the facts (ADR 0644 §1, ADR 0656 §5).
|
||||
answer, by := st.judged(ctx)
|
||||
// A list it cannot make ends the check there, failed naming the checking program, worded from the facts so far.
|
||||
var answer rules.Answer
|
||||
var by *delivery.JudgedBy
|
||||
if st.seatList(ctx) {
|
||||
st.judgeManifests(ctx)
|
||||
st.refuseCycle(ctx)
|
||||
st.compose(ctx)
|
||||
// The verdict is the checking program's of the facts (ADR 0644 §1, ADR 0656 §5).
|
||||
answer, by = st.judged(ctx)
|
||||
} else {
|
||||
answer = rules.Answer{V: rules.AnswerVersion, Verdict: rules.Judge(st.factsOf())}
|
||||
}
|
||||
for _, n := range answer.Notes {
|
||||
st.c.note(n)
|
||||
}
|
||||
@@ -691,7 +697,7 @@ func (st *state) level(ctx context.Context, t *target, la delivery.LevelAnswer)
|
||||
t.judgedBy(la.Judged) // the candidate judged the level: nothing is kept (ADR 0535 §4)
|
||||
}
|
||||
_, elapsed, results := st.levels.Level(t.pull.Repository, t.pull.Number, t.module, t.node, la)
|
||||
st.facts = append(st.facts, rules.Step{Repository: t.pull.Repository, Number: t.pull.Number, Module: t.module, Node: t.node, Level: &la})
|
||||
st.facts = append(st.facts, rules.Step{Repository: t.pull.Repository, Number: t.pull.Number, Module: t.module, Node: t.node, Level: rules.LevelFact(la)})
|
||||
var digests map[string]string
|
||||
if t.module == buildrun.GoBuildModule && la.Digest != nil {
|
||||
// The packages come as a list, never keyed by a package path (issue 1930); an answer stored before reads too.
|
||||
|
||||
@@ -165,10 +165,12 @@ func (st *state) waitBegun(ctx context.Context, a delivery.StepAsk) (delivery.St
|
||||
}
|
||||
|
||||
// seatList asks the checking program for the heads' seat list, which the validator's and the composer's requests carry
|
||||
// (ADR 0636 §4); the list and what it left out are the check's notes. A list it cannot make fails the check, naming why.
|
||||
func (st *state) seatList(ctx context.Context) {
|
||||
// (ADR 0636 §4); the list and what it left out are the check's notes. A list it cannot make fails the check, naming why,
|
||||
// and answers false: the check ends there, with no verdict asked of a program that could not answer its list (review
|
||||
// round 1 of milestone 47/B0: a build node with no job run would hold the check two begin bounds more).
|
||||
func (st *state) seatList(ctx context.Context) bool {
|
||||
if st.narrowTry() {
|
||||
return
|
||||
return true
|
||||
}
|
||||
body, err := json.Marshal(st.factsHead())
|
||||
if err == nil {
|
||||
@@ -184,11 +186,12 @@ func (st *state) seatList(ctx context.Context) {
|
||||
for _, l := range a.Left {
|
||||
st.c.note("the heads' seat list leaves out " + l.Path + ": " + l.Why)
|
||||
}
|
||||
return
|
||||
return true
|
||||
}
|
||||
}
|
||||
}
|
||||
st.fail(goModule, "the heads' seat list could not be made by the checking program: "+err.Error())
|
||||
return false
|
||||
}
|
||||
|
||||
// factsHead are the facts that name the check, without what the asking gathered.
|
||||
|
||||
@@ -64,6 +64,36 @@ type Step struct {
|
||||
Manifests *Manifests `json:"manifests,omitempty"`
|
||||
}
|
||||
|
||||
// LevelFact is a level answer as the facts carry it: only what the rules read (Tally.Level), so a group's facts stay
|
||||
// within the run input's bound (delivery.RunInputOf). The digest, the unmet packages and the level's judged program
|
||||
// are left out, the kept packages are one count, and each test result keeps only the fields Tested names, without its
|
||||
// packages, bounds and judged program (review round 1 of milestone 47/B0). An answer this cannot read is carried as given,
|
||||
// for the rules to refuse it.
|
||||
func LevelFact(la delivery.LevelAnswer) *delivery.LevelAnswer {
|
||||
out := &delivery.LevelAnswer{Level: la.Level}
|
||||
kept := 0
|
||||
for _, k := range la.Kept {
|
||||
kept += k.Tests
|
||||
}
|
||||
if len(la.Kept) > 0 {
|
||||
out.Kept = []delivery.KeptTaken{{Tests: kept}}
|
||||
}
|
||||
for _, raw := range la.Tests {
|
||||
var res Tested
|
||||
if err := json.Unmarshal(raw, &res); err != nil {
|
||||
out.Tests = append(out.Tests, raw)
|
||||
continue
|
||||
}
|
||||
res.Packages, res.JudgedBy, res.Bound, res.SetupBound, res.OverWhich = nil, "", 0, 0, ""
|
||||
small, err := json.Marshal(res)
|
||||
if err != nil {
|
||||
small = raw
|
||||
}
|
||||
out.Tests = append(out.Tests, small)
|
||||
}
|
||||
return out
|
||||
}
|
||||
|
||||
// DecodeFacts reads facts, refusing a version this program does not read, naming it.
|
||||
func DecodeFacts(data []byte) (Facts, error) {
|
||||
var f Facts
|
||||
|
||||
Reference in New Issue
Block a user