test: harden group load verification

This commit is contained in:
richjohnrambo
2026-09-28 00:58:24 +08:00
parent 622fc50418
commit cb2210aa3e
17 changed files with 491 additions and 38 deletions
+66 -3
View File
@@ -38,6 +38,7 @@ type coordinatorState struct {
ready map[string]AgentReady
armed map[string]bool
ledgers map[string][]AcceptedMessage
observed map[string][]AcceptedMessage
summaries map[string]AgentSummary
complete chan struct{}
completeOnce sync.Once
@@ -57,12 +58,14 @@ func runCoordinator(ctx context.Context, listen, runID, scenario, output string,
start: StartInfo{RunID: runID, Scenario: scenario}, startDelay: startDelay, commitDelay: 5 * time.Second,
expectedAgents: expectedAgents,
ready: make(map[string]AgentReady), ledgers: make(map[string][]AcceptedMessage),
armed: make(map[string]bool), summaries: make(map[string]AgentSummary), complete: make(chan struct{}),
observed: make(map[string][]AcceptedMessage),
armed: make(map[string]bool), summaries: make(map[string]AgentSummary), complete: make(chan struct{}),
}
mux := http.NewServeMux()
mux.HandleFunc("/v1/ready", state.handleReady)
mux.HandleFunc("/v1/start", state.handleStart)
mux.HandleFunc("/v1/ledger", state.handleLedger)
mux.HandleFunc("/v1/observed", state.handleObserved)
mux.HandleFunc("/v1/summary", state.handleSummary)
mux.HandleFunc("/v1/status", state.handleStatus)
server := &http.Server{Addr: listen, Handler: mux, ReadHeaderTimeout: 5 * time.Second}
@@ -91,6 +94,44 @@ func runCoordinator(ctx context.Context, listen, runID, scenario, output string,
return nil
}
func (s *coordinatorState) handleObserved(w http.ResponseWriter, r *http.Request) {
machine := strings.ToLower(strings.TrimSpace(r.URL.Query().Get("machine")))
switch r.Method {
case http.MethodPost:
if machine != "a" && machine != "b" {
http.Error(w, "invalid machine", http.StatusBadRequest)
return
}
var messages []AcceptedMessage
if !decodeLimitedJSON(w, r, &messages) {
return
}
s.mu.Lock()
if s.observed == nil {
s.observed = make(map[string][]AcceptedMessage)
}
s.observed[machine] = messages
count := len(s.observed)
s.mu.Unlock()
writeJSON(w, http.StatusOK, map[string]int{"submitted_agents": count})
case http.MethodGet:
s.mu.Lock()
defer s.mu.Unlock()
if len(s.observed) < s.expectedAgents {
writeJSON(w, http.StatusAccepted, map[string]int{"submitted_agents": len(s.observed), "expected_agents": s.expectedAgents})
return
}
var merged []AcceptedMessage
for _, messages := range s.observed {
merged = append(merged, messages...)
}
merged = mergeMessageLedgers(nil, merged)
writeJSON(w, http.StatusOK, merged)
default:
http.Error(w, "method not allowed", http.StatusMethodNotAllowed)
}
}
func (s *coordinatorState) handleReady(w http.ResponseWriter, r *http.Request) {
if r.Method != http.MethodPost {
http.Error(w, "method not allowed", http.StatusMethodNotAllowed)
@@ -223,7 +264,7 @@ func (s *coordinatorState) handleStatus(w http.ResponseWriter, _ *http.Request)
defer s.mu.Unlock()
writeJSON(w, http.StatusOK, map[string]any{
"start": s.start, "ready": s.ready, "armed": s.armed,
"ledger_agents": len(s.ledgers), "summary_agents": len(s.summaries),
"ledger_agents": len(s.ledgers), "observed_agents": len(s.observed), "summary_agents": len(s.summaries),
})
}
@@ -233,8 +274,9 @@ func (s *coordinatorState) writeOutput(path string) error {
Start StartInfo `json:"start"`
Ready map[string]AgentReady `json:"ready"`
Ledgers map[string][]AcceptedMessage `json:"ledgers"`
Observed map[string][]AcceptedMessage `json:"observed"`
Summaries map[string]AgentSummary `json:"summaries"`
}{s.start, s.ready, s.ledgers, s.summaries}
}{s.start, s.ready, s.ledgers, s.observed, s.summaries}
s.mu.Unlock()
raw, err := json.MarshalIndent(data, "", " ")
if err != nil {
@@ -324,6 +366,27 @@ func (c *coordinatorClient) ledger(ctx context.Context) ([]AcceptedMessage, erro
}
}
func (c *coordinatorClient) submitObserved(ctx context.Context, machine string, messages []AcceptedMessage) error {
_, err := c.request(ctx, http.MethodPost, "/v1/observed?machine="+machine, messages, nil)
return err
}
func (c *coordinatorClient) observed(ctx context.Context) ([]AcceptedMessage, error) {
for {
var messages []AcceptedMessage
status, err := c.request(ctx, http.MethodGet, "/v1/observed", nil, &messages)
if err != nil {
return nil, err
}
if status == http.StatusOK {
return messages, nil
}
if err = waitContext(ctx, time.Second); err != nil {
return nil, err
}
}
}
func (c *coordinatorClient) submitSummary(ctx context.Context, summary AgentSummary) error {
_, err := c.request(ctx, http.MethodPost, "/v1/summary", summary, nil)
return err