Drop the plan state from the store and the assignments: migration 0108 and placement-only assignments (release 6, issue 1945 B9, B4)
This commit is contained in:
@@ -49,23 +49,23 @@ func TestABuildIsKeptWholeAndReadBackWithItsReuseKeyAndWhatItPublished(t *testin
|
||||
func TestAWriteAgainstAMovedRevisionIsRefusedAndNothingIsLaidOver(t *testing.T) {
|
||||
ctx := context.Background()
|
||||
c := InMemory(nil)
|
||||
first, err := c.Assignments.Create(ctx, "anchor.notes", Assignment{Node: "anchor", Module: "notes", Commit: "c1"})
|
||||
first, err := c.Assignments.Create(ctx, "anchor.notes", Assignment{Node: "anchor", Module: "notes", RequiredBy: "c1"})
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
if _, err := c.Assignments.Create(ctx, "anchor.notes", Assignment{Node: "anchor", Module: "notes"}); !errors.Is(err, ErrExists) {
|
||||
t.Fatalf("a create of a key that holds a value answered %v", err)
|
||||
}
|
||||
second, err := c.Assignments.Update(ctx, "anchor.notes", Assignment{Node: "anchor", Module: "notes", Commit: "c2"}, first)
|
||||
second, err := c.Assignments.Update(ctx, "anchor.notes", Assignment{Node: "anchor", Module: "notes", RequiredBy: "c2"}, first)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
// A writer that read the first revision writes now.
|
||||
if _, err := c.Assignments.Update(ctx, "anchor.notes", Assignment{Node: "anchor", Module: "notes", Commit: "stale"}, first); !errors.Is(err, ErrMoved) {
|
||||
if _, err := c.Assignments.Update(ctx, "anchor.notes", Assignment{Node: "anchor", Module: "notes", RequiredBy: "stale"}, first); !errors.Is(err, ErrMoved) {
|
||||
t.Fatalf("a write at a moved revision answered %v", err)
|
||||
}
|
||||
got, _, _ := c.Assignments.Get(ctx, "anchor.notes")
|
||||
if got.Value.Commit != "c2" || got.Revision != second {
|
||||
if got.Value.RequiredBy != "c2" || got.Revision != second {
|
||||
t.Fatalf("the key that moved was laid over: %+v at %d", got.Value, got.Revision)
|
||||
}
|
||||
}
|
||||
@@ -91,8 +91,8 @@ func TestNoKeyOfTheChainIsEverRemoved(t *testing.T) {
|
||||
}
|
||||
ctx := context.Background()
|
||||
c := InMemory(nil)
|
||||
rev, _ := c.Assignments.Create(ctx, "anchor.notes", Assignment{Node: "anchor", Module: "notes", Commit: "c1"})
|
||||
if _, err := c.Assignments.Update(ctx, "anchor.notes", Assignment{Node: "anchor", Module: "notes", Commit: "c1"}, rev); err != nil {
|
||||
rev, _ := c.Assignments.Create(ctx, "anchor.notes", Assignment{Node: "anchor", Module: "notes", RequiredBy: "c1"})
|
||||
if _, err := c.Assignments.Update(ctx, "anchor.notes", Assignment{Node: "anchor", Module: "notes", RequiredBy: "c1"}, rev); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
keys, err := c.Assignments.Keys(ctx)
|
||||
@@ -190,31 +190,36 @@ func TestARolloutNamesEveryAssignmentItChangedWithBuildBeforeAndAfter(t *testing
|
||||
}
|
||||
}
|
||||
|
||||
// **An assignment names its build, artifact or package, commit and rollout**, and keeps the fields its readers read
|
||||
// under the names they read them by (ADR 0408 §3).
|
||||
func TestAnAssignmentNamesBuildArtifactCommitAndRollout(t *testing.T) {
|
||||
// **An assignment is placement only** (ADR 0539 §12): the node, the module, since when, what requires it and its
|
||||
// provisioning plan; no build, artifact, package, commit, rollout or time since is written in it, and a value of before
|
||||
// release 6 that names them is read with them ignored.
|
||||
func TestAnAssignmentIsPlacementOnly(t *testing.T) {
|
||||
a := Assignment{Node: "anchor", Module: "notes", Assigned: at(3), RequiredBy: "wiki",
|
||||
Provisioning: json.RawMessage(`{"plan":1}`), Build: "b2", Artifact: "sha256:bb", Commit: "c2", Rollout: "r1", Since: at(4)}
|
||||
Provisioning: json.RawMessage(`{"plan":1}`)}
|
||||
raw, _ := json.Marshal(a)
|
||||
for _, want := range []string{`"node":"anchor"`, `"module":"notes"`, `"assigned":"2026-10-18T03:00:00Z"`,
|
||||
`"required-by":"wiki"`, `"provisioning":{"plan":1}`, `"build":"b2"`, `"artifact":"sha256:bb"`, `"commit":"c2"`,
|
||||
`"rollout":"r1"`, `"since":"2026-10-18T04:00:00Z"`} {
|
||||
`"required-by":"wiki"`, `"provisioning":{"plan":1}`} {
|
||||
if !strings.Contains(string(raw), want) {
|
||||
t.Errorf("the assignment's value lacks %s: %s", want, raw)
|
||||
}
|
||||
}
|
||||
for _, not := range []string{`"build"`, `"artifact"`, `"package"`, `"commit"`, `"rollout"`, `"since"`, `"pulled-in"`, `"sent-unknown"`} {
|
||||
if strings.Contains(string(raw), not) {
|
||||
t.Errorf("the assignment's value names %s: %s", not, raw)
|
||||
}
|
||||
}
|
||||
if a.Key() != "anchor.notes" {
|
||||
t.Errorf("key %s", a.Key())
|
||||
}
|
||||
// An assignment of today carries none of the new fields, and says none: a reader of today reads the bytes it did.
|
||||
raw, _ = json.Marshal(Assignment{Node: "anchor", Module: "notes", Assigned: at(3)})
|
||||
if string(raw) != `{"node":"anchor","module":"notes","assigned":"2026-10-18T03:00:00Z"}` {
|
||||
t.Errorf("an assignment without a chain is %s", raw)
|
||||
// A value written before release 6 is read, its chain fields ignored, and written back without them.
|
||||
var old Assignment
|
||||
if err := json.Unmarshal([]byte(`{"node":"anchor","module":"notes","assigned":"2026-10-18T03:00:00Z","build":"b2","commit":"c2",`+
|
||||
`"rollout":"r1","since":"2026-10-18T04:00:00Z","pulled-in":true}`), &old); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
// A package in place of an artifact.
|
||||
raw, _ = json.Marshal(Assignment{Node: "a", Module: "m", Package: &Package{Name: "n", Version: "1"}})
|
||||
if !strings.Contains(string(raw), `"package":{"name":"n","version":"1"}`) {
|
||||
t.Errorf("the package is %s", raw)
|
||||
raw, _ = json.Marshal(old)
|
||||
if string(raw) != `{"node":"anchor","module":"notes","assigned":"2026-10-18T03:00:00Z"}` {
|
||||
t.Errorf("an old value written again is %s", raw)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -341,7 +346,7 @@ func TestAnEmptyBucketIsReadAsEmpty(t *testing.T) {
|
||||
func TestAnEndedAssignmentIsNoAssignmentAndStaysInTheBucket(t *testing.T) {
|
||||
ctx := context.Background()
|
||||
c := InMemory(nil)
|
||||
rev, err := c.Assignments.Create(ctx, "anchor.notes", Assignment{Node: "anchor", Module: "notes", Assigned: at(1), Commit: "c1"})
|
||||
rev, err := c.Assignments.Create(ctx, "anchor.notes", Assignment{Node: "anchor", Module: "notes", Assigned: at(1), RequiredBy: "c1"})
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
@@ -355,7 +360,7 @@ func TestAnEndedAssignmentIsNoAssignmentAndStaysInTheBucket(t *testing.T) {
|
||||
t.Fatal(err)
|
||||
}
|
||||
got, found, _ := c.Assignments.Get(ctx, "anchor.notes")
|
||||
if !found || got.Value.Stands() || got.Value.Commit != "c1" || got.Value.Ended.IsZero() {
|
||||
if !found || got.Value.Stands() || got.Value.RequiredBy != "c1" || got.Value.Ended.IsZero() {
|
||||
t.Fatalf("the ended value is %+v (found %v)", got.Value, found)
|
||||
}
|
||||
if history, _ := c.Assignments.History(ctx, "anchor.notes"); len(history) != 2 || !history[0].Value.Stands() {
|
||||
|
||||
Reference in New Issue
Block a user