102 lines
4.1 KiB
Go
102 lines
4.1 KiB
Go
package store
|
|
|
|
import (
|
|
"strings"
|
|
"testing"
|
|
)
|
|
|
|
func TestCurrentControlAckOnlyAfterDispatchAndInSameTransaction(t *testing.T) {
|
|
s := preparedCurrentCallStore(t)
|
|
if err := s.PrepareControl(currentDispatcherID, 1001, "task-asr", "pause"); err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
if admitted, err := s.CanAdmit(currentDispatcherID, 1001, "task-asr"); err != nil || admitted {
|
|
t.Fatalf("pause preparation failed to close task admission: %v %v", admitted, err)
|
|
}
|
|
if events, err := s.ListPendingOutbox(currentDispatcherID); err != nil || len(events) != 0 {
|
|
t.Fatalf("ack existed before Agent dispatch: %+v %v", events, err)
|
|
}
|
|
if err := s.CompleteControl(currentDispatcherID, 1001, "task-asr", "pause", "pause-event-1"); err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
outbox, err := s.ListPendingOutbox(currentDispatcherID)
|
|
if err != nil || len(outbox) != 1 || outbox[0].EventType != "task.control" || !strings.Contains(string(outbox[0].Body), `"status":"applied"`) {
|
|
t.Fatalf("missing applied control ack: %+v %v", outbox, err)
|
|
}
|
|
if err := s.MarkOutboxConfirmed(currentDispatcherID, "pause-event-1"); err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
// A repeated control must be dispatched again, not suppressed by event ID.
|
|
if err := s.PrepareControl(currentDispatcherID, 1001, "task-asr", "pause"); err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
if err := s.CompleteControl(currentDispatcherID, 1001, "task-asr", "pause", "pause-event-1"); err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
outbox, err = s.ListPendingOutbox(currentDispatcherID)
|
|
if err != nil || len(outbox) != 1 || outbox[0].EventID != "pause-event-1" {
|
|
t.Fatalf("repeated control failed to resend same acknowledgment: %+v %v", outbox, err)
|
|
}
|
|
}
|
|
|
|
func TestCurrentResumeDoesNotOpenAdmissionWhenAckOutboxFails(t *testing.T) {
|
|
s := preparedCurrentCallStore(t)
|
|
if err := s.PrepareControl(currentDispatcherID, 1001, "task-asr", "pause"); err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
if err := s.CompleteControl(currentDispatcherID, 1001, "task-asr", "pause", "pause-1"); err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
if err := s.PrepareControl(currentDispatcherID, 1001, "task-asr", "resume"); err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
if _, err := s.db.Exec(`CREATE TRIGGER fail_resume_ack BEFORE INSERT ON dispatcher_outbox WHEN NEW.event_id='resume-1' BEGIN SELECT RAISE(ABORT,'injected MQ outbox failure'); END`); err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
if err := s.CompleteControl(currentDispatcherID, 1001, "task-asr", "resume", "resume-1"); err == nil {
|
|
t.Fatal("opened admission without durable resume acknowledgment")
|
|
}
|
|
if admitted, err := s.CanAdmit(currentDispatcherID, 1001, "task-asr"); err != nil || admitted {
|
|
t.Fatalf("resume outbox failure opened admission: %v %v", admitted, err)
|
|
}
|
|
if _, err := s.db.Exec(`DROP TRIGGER fail_resume_ack`); err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
if err := s.CompleteControl(currentDispatcherID, 1001, "task-asr", "resume", "resume-1"); err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
if admitted, err := s.CanAdmit(currentDispatcherID, 1001, "task-asr"); err != nil || !admitted {
|
|
t.Fatalf("successful resume did not open admission: %v %v", admitted, err)
|
|
}
|
|
}
|
|
|
|
func TestCurrentStopRejectsResumeAndSuppressesOldCommands(t *testing.T) {
|
|
s := preparedCurrentCallStore(t)
|
|
cmd := currentCall("queued-stop")
|
|
if _, _, err := s.RecordExecute(cmd); err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
if err := s.PrepareControl(currentDispatcherID, 1001, "task-asr", "stop"); err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
if commands, err := s.ListPendingExecute(currentDispatcherID); err != nil || len(commands) != 0 {
|
|
t.Fatalf("stopped task retained dispatchable old command: %+v %v", commands, err)
|
|
}
|
|
if err := s.CompleteControl(currentDispatcherID, 1001, "task-asr", "stop", "stop-1"); err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
if err := s.PrepareControl(currentDispatcherID, 1001, "task-asr", "resume"); err == nil {
|
|
t.Fatal("stopped task accepted resume")
|
|
}
|
|
if err := s.RejectControl(currentDispatcherID, 1001, "resume-1"); err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
outbox, err := s.ListPendingOutbox(currentDispatcherID)
|
|
if err != nil || len(outbox) != 2 {
|
|
t.Fatalf("stop/rejected resume acknowledgments missing: %+v %v", outbox, err)
|
|
}
|
|
if strings.Contains(string(outbox[1].Body), `"status":"applied"`) {
|
|
t.Fatalf("stopped task resume falsely applied: %s", outbox[1].Body)
|
|
}
|
|
}
|