package module import ( "context" "fmt" "os" "sync" "testing" "time" "forge.cadoles.com/arcad/edge/pkg/app" "forge.cadoles.com/arcad/edge/pkg/bus/memory" "github.com/pkg/errors" "gitlab.com/wpetit/goweb/logger" ) func TestServerExecDeadlock(t *testing.T) { if testing.Verbose() { logger.SetLevel(logger.LevelDebug) } bus := memory.NewBus(memory.WithBufferSize(1)) server := app.NewServer( ConsoleModuleFactory(), RPCModuleFactory(bus), LifecycleModuleFactory(), ) data, err := os.ReadFile("testdata/deadlock.js") if err != nil { t.Fatalf("%+v", errors.WithStack(err)) } if err := server.Load("deadlock.js", string(data)); err != nil { t.Fatalf("%+v", errors.WithStack(err)) } ctx := context.Background() if err := server.Start(ctx); err != nil { t.Fatalf("%+v", errors.WithStack(err)) } defer server.Stop() messages, err := bus.Subscribe(ctx, MessageNamespaceServer) if err != nil { t.Fatalf("%+v", errors.WithStack(err)) } count := 100 delay := 500 var wg sync.WaitGroup wg.Add(1) go func() { defer wg.Done() received := 0 for range messages { received++ t.Logf("received %d", received) if received == count { bus.Unsubscribe(ctx, MessageNamespaceServer, messages) return } } }() wg.Add(count) for i := 0; i < count; i++ { go func(i int) { defer wg.Done() timeout := time.Duration(delay*5) * time.Millisecond t.Logf("sending message %d with timeout %s", i, timeout.String()) // ctx, cancel := context.WithTimeout(context.Background(), timeout) // defer cancel() msg := NewClientMessage(context.Background(), map[string]any{ "jsonrpc": "2.0", "method": "doSomethingLong", "id": fmt.Sprintf("msg-%d", i), "params": map[string]any{ "i": i, "delay": delay, }, }) t.Logf("publishing message #%d", i) if err := bus.Publish(ctx, msg); err != nil { t.Errorf("%+v", errors.WithStack(err)) } }(i) } wg.Wait() }