| 1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768 |
- package service
- import (
- "context"
- "testing"
- "time"
- "github.com/mhsanaei/3x-ui/v3/internal/database/model"
- "github.com/mhsanaei/3x-ui/v3/internal/web/runtime"
- )
- type blockingResetRuntime struct {
- fakeNodeRuntime
- reached chan struct{}
- release chan struct{}
- }
- func (b *blockingResetRuntime) ResetAllTraffics(context.Context) error {
- close(b.reached)
- <-b.release
- return nil
- }
- func TestResetAllTrafficsDoesNotBlockWriterOnNodeCall(t *testing.T) {
- db := initTrafficTestDB(t)
- resetTrafficWriterForTest(t)
- StartTrafficWriter()
- mgr := runtime.NewManager(runtime.LocalDeps{APIPort: func() int { return 0 }})
- runtime.SetManager(mgr)
- t.Cleanup(func() { runtime.SetManager(nil) })
- node := &model.Node{Name: "n1", Address: "127.0.0.1", Port: 2096, ApiToken: "tok", Enable: true, Status: "online"}
- if err := db.Create(node).Error; err != nil {
- t.Fatalf("create node: %v", err)
- }
- fake := &blockingResetRuntime{reached: make(chan struct{}), release: make(chan struct{})}
- mgr.SetRuntimeOverride(node.Id, fake)
- done := make(chan error, 1)
- go func() { done <- (&InboundService{}).ResetAllTraffics() }()
- select {
- case <-fake.reached:
- case <-time.After(3 * time.Second):
- close(fake.release)
- t.Fatal("node ResetAllTraffics was never reached")
- }
- writerFree := make(chan error, 1)
- go func() { writerFree <- submitTrafficWrite(func() error { return nil }) }()
- select {
- case err := <-writerFree:
- if err != nil {
- close(fake.release)
- t.Fatalf("concurrent writer submit failed: %v", err)
- }
- case <-time.After(2 * time.Second):
- close(fake.release)
- <-done
- t.Fatal("the serial traffic writer was blocked by a node reset HTTP call")
- }
- close(fake.release)
- if err := <-done; err != nil {
- t.Fatalf("ResetAllTraffics: %v", err)
- }
- }
|