checker: a carry keeps the composition it passed while no composed fingerprint changed, and composes again otherwise (ADR 0548 §5; issue 568 D3)
This commit is contained in:
@@ -43,6 +43,14 @@ func waitFor(t testing.TB, what string, ok func() bool) {
|
||||
}
|
||||
}
|
||||
|
||||
// pullWithFP is a pull request touching the module m at the fingerprint `src2:` and 64 times the hex digit d.
|
||||
func pullWithFP(repo string, number int, head string, d string) delivery.CandidatePull {
|
||||
p := pullOf(repo, number, head)
|
||||
p.Modules = []string{"m"}
|
||||
p.Fps = map[string]delivery.CandidateModule{"m": {FP2: "src2:" + strings.Repeat(d, 64)}}
|
||||
return p
|
||||
}
|
||||
|
||||
func TestOneCheckPerDelivery(t *testing.T) {
|
||||
ctx := context.Background()
|
||||
for name, run := range map[string]func(t *testing.T){
|
||||
@@ -145,6 +153,30 @@ func TestOneCheckPerDelivery(t *testing.T) {
|
||||
t.Error("the verdict key was made again: a carry rewrites it")
|
||||
}
|
||||
},
|
||||
// §5: the composition is kept when no fingerprint of a module it composed changed, and runs again otherwise.
|
||||
"a carry keeps a passed composition while the fingerprints stay the same": func(t *testing.T) {
|
||||
var kept []bool
|
||||
j := &judgeFunc{f: func(_ context.Context, c *Case, _ int) (Outcome, error) {
|
||||
kept = append(kept, c.Composition != nil)
|
||||
v := passing()
|
||||
v.Composition = &delivery.Composition{State: delivery.CompositionPass, SDK: "v0.1.14-x", FPSet: c.FPSet}
|
||||
return Outcome{Verdict: v}, nil
|
||||
}}
|
||||
r := newRig(t, j)
|
||||
cand := candidateOf(t, "feat/x", pullWithFP(repoA, 7, head1, "a"))
|
||||
r.ch.Candidate(ctx, "feat%2Fx", cand)
|
||||
r.ch.Wait()
|
||||
r.setTrunks(t, map[string]string{repoA: trunkA2, repoSDK: trunkS})
|
||||
r.ch.TrunkMoved(ctx) // the indexer's fingerprints of the candidate stay the same
|
||||
r.ch.Wait()
|
||||
r.ch.Candidate(ctx, "feat%2Fx", candidateOf(t, "feat/x", pullWithFP(repoA, 7, head1, "b"))) // a fingerprint changed with the move
|
||||
r.setTrunks(t, map[string]string{repoA: trunkA, repoSDK: trunkS})
|
||||
r.ch.TrunkMoved(ctx)
|
||||
r.ch.Wait()
|
||||
if len(kept) != 3 || kept[0] || !kept[1] || kept[2] {
|
||||
t.Errorf("the composition was kept in the checks %v; want composed, kept on the carry, composed again once a fingerprint changed", kept)
|
||||
}
|
||||
},
|
||||
// §5: a carry that fails names the move it failed on.
|
||||
"a carry that fails names the move": func(t *testing.T) {
|
||||
j := &judgeFunc{f: func(_ context.Context, c *Case, call int) (Outcome, error) {
|
||||
|
||||
@@ -127,6 +127,9 @@ func (ch *Checker) Composed(ctx context.Context, comp delivery.CompositionVerdic
|
||||
return
|
||||
}
|
||||
withComposition(&v, comp)
|
||||
if v.Composition != nil && v.Composition.State != delivery.CompositionNotRun {
|
||||
v.Composition.FPSet = cs.FPSet
|
||||
}
|
||||
data, err := delivery.EncodeVerdict(v)
|
||||
if err != nil {
|
||||
ch.logf("%s: the verdict with its composition cannot be written: %v", cs.Key, err)
|
||||
|
||||
@@ -52,6 +52,11 @@ type Case struct {
|
||||
// CarriedFrom are, for the carry of a verdict that passed, the trunk and sibling commits it was judged on (ADR 0548 §5);
|
||||
// nil for a whole check.
|
||||
CarriedFrom map[string]string
|
||||
// FPSet is the candidate's fingerprint set (Candidate.FPSet): a composition names the set it judged.
|
||||
FPSet string
|
||||
// Composition is, for a carry, the composition that passed on the same fingerprint set: it is kept and not asked again,
|
||||
// since no fingerprint of a module it composed changed (ADR 0548 §5). Nil composes.
|
||||
Composition *delivery.Composition
|
||||
}
|
||||
|
||||
// Progress is the step a check is at, written by the check and read when its bound passes.
|
||||
@@ -83,7 +88,7 @@ func CaseOf(c delivery.Candidate, trunk map[string]string) *Case {
|
||||
if err != nil {
|
||||
return nil
|
||||
}
|
||||
cs := &Case{Key: key, Group: c.Group, HeadsHash: c.HeadsHash, Heads: GateHeads(c), Trunk: map[string]string{}, Progress: &Progress{}}
|
||||
cs := &Case{Key: key, Group: c.Group, HeadsHash: c.HeadsHash, Heads: GateHeads(c), Trunk: map[string]string{}, Progress: &Progress{}, FPSet: c.FPSet}
|
||||
for _, p := range c.Pulls {
|
||||
switch head, known := trunk[p.Repository]; {
|
||||
case !known || head == "":
|
||||
|
||||
@@ -232,7 +232,7 @@ const (
|
||||
// commits are named as the carry's CarriedFrom. A verdict that stands is ranked with the carries: its claim finds nothing
|
||||
// to do.
|
||||
func (ch *Checker) prepare(ctx context.Context, cs *Case) {
|
||||
cs.Kind, cs.CarriedFrom = KindNew, nil
|
||||
cs.Kind, cs.CarriedFrom, cs.Composition = KindNew, nil, nil
|
||||
value, _, found, err := ch.Verdicts.Get(ctx, cs.Key)
|
||||
if err != nil || !found {
|
||||
return
|
||||
@@ -248,6 +248,10 @@ func (ch *Checker) prepare(ctx context.Context, cs *Case) {
|
||||
cs.Kind = KindTrunk
|
||||
if v.State == delivery.VerdictPass && ch.stale(v, cs) {
|
||||
cs.CarriedFrom = judgedOn(v)
|
||||
if c := v.Composition; c != nil && c.State == delivery.CompositionPass && c.FPSet != "" && c.FPSet == cs.FPSet {
|
||||
kept := *c
|
||||
cs.Composition = &kept
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -28,6 +28,7 @@ func TestAPassingCheckTakesTheAssignersComposition(t *testing.T) {
|
||||
f := &fakeCompositions{v: delivery.CompositionVerdict{Group: "feat/x", Heads: "0123456789ab", State: delivery.CompositionPass, SDK: "v0.1.14-x", Machines: []string{"g14"}, Took: 40}}
|
||||
b.ex.Compositions = f
|
||||
cs := caseOf(t, pullOf(repoA, 7, head1))
|
||||
cs.FPSet = "fps-of-the-candidate"
|
||||
v := b.judge(t, cs).Verdict
|
||||
if v.State != delivery.VerdictPass || v.Composition == nil || v.Composition.State != delivery.CompositionPass || v.Composition.SDK != "v0.1.14-x" || v.Took.Composition != 40 {
|
||||
t.Fatalf("verdict = %+v, composition %+v", v, v.Composition)
|
||||
@@ -38,6 +39,15 @@ func TestAPassingCheckTakesTheAssignersComposition(t *testing.T) {
|
||||
if !compositionMentions(v, "passed") {
|
||||
t.Errorf("the line says %q", compositionWords(v.Composition, v.Took.Composition))
|
||||
}
|
||||
if v.Composition.FPSet == "" || v.Composition.FPSet != cs.FPSet {
|
||||
t.Errorf("the composition names the fingerprint set %q, want the candidate's %q (ADR 0548 §5)", v.Composition.FPSet, cs.FPSet)
|
||||
}
|
||||
// ADR 0548 §5: a carry whose fingerprints did not change keeps the composition it passed and asks the assigner nothing.
|
||||
carry := caseOf(t, pullOf(repoA, 7, head1))
|
||||
carry.CarriedFrom, carry.Composition = map[string]string{repoA: trunkA2}, v.Composition
|
||||
if kept := b.judge(t, carry).Verdict; kept.Composition == nil || kept.Composition.SDK != "v0.1.14-x" || len(f.asked) != 1 {
|
||||
t.Errorf("the carry's composition is %+v and the assigner was asked %d times; want the kept one and no second ask", kept.Composition, len(f.asked))
|
||||
}
|
||||
}
|
||||
|
||||
func compositionMentions(v delivery.Verdict, word string) bool {
|
||||
|
||||
@@ -230,6 +230,13 @@ func (st *state) finish(ctx context.Context, v delivery.Verdict) Outcome {
|
||||
// fails the check, naming the machine it failed at. A try is not composed (it has no candidate); a composition that
|
||||
// cannot be had leaves it not run, said; with no assigner running it is not judged, said at once.
|
||||
func (st *state) composed(ctx context.Context, v *delivery.Verdict) {
|
||||
if st.c.Composition != nil && st.c.Try == nil {
|
||||
// A carry whose candidate's fingerprints did not change keeps the composition it passed (ADR 0548 §5).
|
||||
kept := *st.c.Composition
|
||||
v.Composition = &kept
|
||||
st.c.note("the composition is kept: no fingerprint of a module it composed changed")
|
||||
return
|
||||
}
|
||||
if st.j.Compositions == nil || st.c.Try != nil {
|
||||
return
|
||||
}
|
||||
@@ -243,6 +250,9 @@ func (st *state) composed(ctx context.Context, v *delivery.Verdict) {
|
||||
return
|
||||
}
|
||||
withComposition(v, comp)
|
||||
if v.Composition != nil && v.Composition.State != delivery.CompositionNotRun {
|
||||
v.Composition.FPSet = st.c.FPSet // a carry keeps it while the fingerprints stay the same (ADR 0548 §5)
|
||||
}
|
||||
}
|
||||
|
||||
// outcome fills the verdict's levels, times, machines and composition from what ran.
|
||||
|
||||
Reference in New Issue
Block a user