// sender_test.go — тест безопасности enqueue ↔ closeAndWait (фикс 🔴3). // // Раньше поздний колбэк paho мог упасть «send on closed channel» при закрытии // канала во время enqueue. Мьютекс + closed-флаг должны это исключать. package bridge import ( "io" "log/slog" "sync" "testing" ) func TestDispatcherEnqueueCloseNoPanic(t *testing.T) { log := slog.New(slog.NewTextHandler(io.Discard, nil)) // client nil — enqueue/closeAndWait его не трогают (только worker'ы, которых не запускаем). d := newSQSDispatcher(nil, "http://queue", log) // Параллельный enqueue, пока основной поток закрывает канал. var wg sync.WaitGroup stop := make(chan struct{}) for i := 0; i < 4; i++ { wg.Add(1) go func() { defer wg.Done() for { select { case <-stop: return default: d.enqueue(TelemetryEnvelope{Namespace: "ns", DeviceID: "d"}) } } }() } d.closeAndWait() close(stop) wg.Wait() // После закрытия enqueue обязан вернуть false (канал закрыт), а не паниковать. if d.enqueue(TelemetryEnvelope{Namespace: "ns", DeviceID: "d"}) { t.Error("enqueue после close должен вернуть false") } }