110 lines
2.0 KiB
Go
110 lines
2.0 KiB
Go
|
package rpc
|
||
|
|
||
|
import (
|
||
|
"context"
|
||
|
"os"
|
||
|
"sync"
|
||
|
"testing"
|
||
|
|
||
|
"forge.cadoles.com/arcad/edge/pkg/app"
|
||
|
"forge.cadoles.com/arcad/edge/pkg/bus"
|
||
|
"forge.cadoles.com/arcad/edge/pkg/bus/memory"
|
||
|
"forge.cadoles.com/arcad/edge/pkg/module"
|
||
|
"github.com/pkg/errors"
|
||
|
"gitlab.com/wpetit/goweb/logger"
|
||
|
)
|
||
|
|
||
|
func TestServerExecDeadlock(t *testing.T) {
|
||
|
if testing.Verbose() {
|
||
|
logger.SetLevel(logger.LevelDebug)
|
||
|
}
|
||
|
|
||
|
b := memory.NewBus(memory.WithBufferSize(1))
|
||
|
|
||
|
server := app.NewServer(
|
||
|
module.ConsoleModuleFactory(),
|
||
|
ModuleFactory(b),
|
||
|
module.LifecycleModuleFactory(),
|
||
|
)
|
||
|
|
||
|
data, err := os.ReadFile("testdata/deadlock.js")
|
||
|
if err != nil {
|
||
|
t.Fatalf("%+v", errors.WithStack(err))
|
||
|
}
|
||
|
|
||
|
ctx := context.Background()
|
||
|
|
||
|
t.Log("starting server")
|
||
|
|
||
|
if err := server.Start(ctx, "deadlock.js", string(data)); err != nil {
|
||
|
t.Fatalf("%+v", errors.WithStack(err))
|
||
|
}
|
||
|
|
||
|
defer server.Stop()
|
||
|
|
||
|
t.Log("server started")
|
||
|
|
||
|
count := 100
|
||
|
delay := 100
|
||
|
|
||
|
var wg sync.WaitGroup
|
||
|
|
||
|
wg.Add(count)
|
||
|
|
||
|
for i := 0; i < count; i++ {
|
||
|
go func(i int) {
|
||
|
defer wg.Done()
|
||
|
|
||
|
t.Logf("calling %d", i)
|
||
|
|
||
|
isCanceled := i%2 == 0
|
||
|
|
||
|
var ctx context.Context
|
||
|
if isCanceled {
|
||
|
canceledCtx, cancel := context.WithCancel(context.Background())
|
||
|
cancel()
|
||
|
ctx = canceledCtx
|
||
|
} else {
|
||
|
ctx = context.Background()
|
||
|
}
|
||
|
|
||
|
env := NewRequestEnvelope(ctx, "doSomethingLong", map[string]any{
|
||
|
"i": i,
|
||
|
"delay": delay,
|
||
|
})
|
||
|
|
||
|
t.Logf("publishing envelope #%d", i)
|
||
|
|
||
|
reply, err := b.Request(ctx, env)
|
||
|
if err != nil {
|
||
|
if errors.Is(err, context.Canceled) && isCanceled {
|
||
|
return
|
||
|
}
|
||
|
|
||
|
if errors.Is(err, bus.ErrNoResponse) && isCanceled {
|
||
|
return
|
||
|
}
|
||
|
|
||
|
t.Errorf("%+v", errors.WithStack(err))
|
||
|
|
||
|
return
|
||
|
}
|
||
|
|
||
|
result, ok := reply.Message().(int64)
|
||
|
if !ok {
|
||
|
t.Errorf("response.Result: expected type '%T', got '%T'", int64(0), reply.Message())
|
||
|
|
||
|
return
|
||
|
}
|
||
|
|
||
|
if e, g := i, int(result); e != g {
|
||
|
t.Errorf("response.Result: expected '%v', got '%v'", e, g)
|
||
|
|
||
|
return
|
||
|
}
|
||
|
}(i)
|
||
|
}
|
||
|
|
||
|
wg.Wait()
|
||
|
}
|