GATE: the gate's whole-module test opens a record and a source key from a take-in.taken, and its test bus declares the template states
The test bus made buckets from the old state section alone, so a template state (deliveries, groups, owed, conditions) was 'not declared'; it now makes a bucket for each requires entry of the template state under its local name (A-20). Builds: design 47 G §613, A-20, A-33, A-34 (G-17, G-20)
This commit is contained in:
@@ -82,7 +82,7 @@ func newTestBus(t *testing.T) *testBus {
|
||||
b := &testBus{nc: nc, js: js, kvs: map[string]jetstream.KeyValue{}, answers: map[string][]byte{}}
|
||||
// The controller's job: a bucket per state the manifest declares.
|
||||
m, _ := readManifest(t)
|
||||
for _, name := range m.buckets() {
|
||||
for _, name := range m.withTemplateStates() {
|
||||
kv, err := js.CreateKeyValue(context.Background(), jetstream.KeyValueConfig{Bucket: m.Module + "_" + name, History: 10})
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
@@ -101,7 +101,7 @@ func newTestBus(t *testing.T) *testBus {
|
||||
// The streams the events are on (mesh.mod.<module>.event.<name>, mesh.seat.<seat>.event.<name>).
|
||||
if _, err := js.CreateStream(context.Background(), jetstream.StreamConfig{Name: "EVENTS",
|
||||
Subjects: []string{"mesh.seat.git.event.>", "mesh.seat." + oc.Seat + ".event.>",
|
||||
"mesh.mod.mesh-delivery-forge-bridge.event.>", "mesh.mod.mesh-delivery-teller.event.>"}}); err != nil {
|
||||
"mesh.mod.mesh-delivery-forge-bridge.event.>", "mesh.mod.mesh-delivery-indexer.event.>"}}); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
return b
|
||||
|
||||
@@ -34,10 +34,28 @@ type manifest struct {
|
||||
State []any `json:"state"`
|
||||
Reads []string `json:"reads"`
|
||||
Tools []string `json:"tools"`
|
||||
// Requires are the bus state the module asks for: the template `state` entries are keyed buckets under their local names.
|
||||
Requires []struct {
|
||||
Name string `json:"name"`
|
||||
Storage string `json:"storage"`
|
||||
Template string `json:"template"`
|
||||
} `json:"requires"`
|
||||
// Capabilities are what the gate's machine's tool runner must state (buscalls.Capabilities).
|
||||
Capabilities []string `json:"capabilities"`
|
||||
}
|
||||
|
||||
// withTemplateStates are the buckets a test bus makes: the old `state` section's, and the `requires` entries of the template
|
||||
// `state` under their local names (design 47 G §613, A-20).
|
||||
func (m manifest) withTemplateStates() []string {
|
||||
out := m.buckets()
|
||||
for _, r := range m.Requires {
|
||||
if r.Storage == "key-value" && r.Template == "state" {
|
||||
out = append(out, r.Name)
|
||||
}
|
||||
}
|
||||
return out
|
||||
}
|
||||
|
||||
// buckets are the names of the state the manifest declares, each a bare name or an object with a name and a history.
|
||||
func (m manifest) buckets() []string {
|
||||
var out []string
|
||||
|
||||
@@ -0,0 +1,54 @@
|
||||
//go:build integration
|
||||
|
||||
package main
|
||||
|
||||
import (
|
||||
"context"
|
||||
"strings"
|
||||
"testing"
|
||||
"time"
|
||||
|
||||
mdc "git.novox.be/novox/mesh-delivery/contracts/go/clients/meshdeliveryclient"
|
||||
)
|
||||
|
||||
// The gate whole, over a real bus (design 47 G A-33, A-34): a take-in.taken the indexer says opens a delivery record in the
|
||||
// gate's ledger with the take-in as its outcome, writes the branch's source key and says source-moved; the gate asks the
|
||||
// controller nothing, and no state it no longer declares is needed (the template states are buckets under their local names).
|
||||
const eventWithin = 20 * time.Second
|
||||
|
||||
func TestAGateWholeTakesAnIndexersTakeInIntoARecordAndASourceKeyOverARealBus(t *testing.T) {
|
||||
b := newTestBus(t)
|
||||
ctx := context.Background()
|
||||
rt := b.start(t)
|
||||
evctx, cancel := context.WithCancel(ctx)
|
||||
defer cancel()
|
||||
rt.deliverEvents(evctx)
|
||||
rt.untilListening()
|
||||
merge := strings.Repeat("c", 40)
|
||||
b.publish(t, "mesh.mod.mesh-delivery-indexer.event.take-in.taken", map[string]any{"v": 1, "kind": "taken", "key": "m.00000000000000000001",
|
||||
"what": "revision", "branch": "main", "source": 3, "since": "2026-11-11T19:00:00Z",
|
||||
"merges": []any{map[string]any{"repository": "novox/app", "number": 5, "merge": merge}},
|
||||
"entries": []any{map[string]any{"module": "app", "commit": merge, "fingerprint": "f", "repository": "novox/app", "pull": 5}}})
|
||||
rt.until("the source key of main", eventWithin, func() bool {
|
||||
e, err := b.kvs["source"].Get(ctx, mdc.SourceKey("main"))
|
||||
if err != nil {
|
||||
return false
|
||||
}
|
||||
s, err := mdc.DecodeSource(e.Value())
|
||||
return err == nil && s.Heads["novox/app"] == merge
|
||||
})
|
||||
rt.until("the record of the take-in", eventWithin, func() bool {
|
||||
b.mu.Lock()
|
||||
defer b.mu.Unlock()
|
||||
if b.ledger == nil {
|
||||
return false
|
||||
}
|
||||
for instance := range b.ledger.states {
|
||||
if strings.Contains(instance, "main") {
|
||||
return true
|
||||
}
|
||||
}
|
||||
return false
|
||||
})
|
||||
rt.noControllerAsk()
|
||||
}
|
||||
Reference in New Issue
Block a user