github.com/xmplusdev/xray-core@v1.8.10/app/proxyman/outbound/handler_test.go (about) 1 package outbound_test 2 3 import ( 4 "context" 5 "fmt" 6 "sync" 7 "sync/atomic" 8 "testing" 9 "time" 10 11 "github.com/xmplusdev/xray-core/app/policy" 12 "github.com/xmplusdev/xray-core/app/proxyman" 13 . "github.com/xmplusdev/xray-core/app/proxyman/outbound" 14 "github.com/xmplusdev/xray-core/app/stats" 15 "github.com/xmplusdev/xray-core/common/net" 16 "github.com/xmplusdev/xray-core/common/serial" 17 core "github.com/xmplusdev/xray-core/core" 18 "github.com/xmplusdev/xray-core/features/outbound" 19 "github.com/xmplusdev/xray-core/proxy/freedom" 20 "github.com/xmplusdev/xray-core/transport/internet/stat" 21 ) 22 23 func TestInterfaces(t *testing.T) { 24 _ = (outbound.Handler)(new(Handler)) 25 _ = (outbound.Manager)(new(Manager)) 26 } 27 28 const xrayKey core.XrayKey = 1 29 30 func TestOutboundWithoutStatCounter(t *testing.T) { 31 config := &core.Config{ 32 App: []*serial.TypedMessage{ 33 serial.ToTypedMessage(&stats.Config{}), 34 serial.ToTypedMessage(&policy.Config{ 35 System: &policy.SystemPolicy{ 36 Stats: &policy.SystemPolicy_Stats{ 37 InboundUplink: true, 38 }, 39 }, 40 }), 41 }, 42 } 43 44 v, _ := core.New(config) 45 v.AddFeature((outbound.Manager)(new(Manager))) 46 ctx := context.WithValue(context.Background(), xrayKey, v) 47 h, _ := NewHandler(ctx, &core.OutboundHandlerConfig{ 48 Tag: "tag", 49 ProxySettings: serial.ToTypedMessage(&freedom.Config{}), 50 }) 51 conn, _ := h.(*Handler).Dial(ctx, net.TCPDestination(net.DomainAddress("localhost"), 13146)) 52 _, ok := conn.(*stat.CounterConnection) 53 if ok { 54 t.Errorf("Expected conn to not be CounterConnection") 55 } 56 } 57 58 func TestOutboundWithStatCounter(t *testing.T) { 59 config := &core.Config{ 60 App: []*serial.TypedMessage{ 61 serial.ToTypedMessage(&stats.Config{}), 62 serial.ToTypedMessage(&policy.Config{ 63 System: &policy.SystemPolicy{ 64 Stats: &policy.SystemPolicy_Stats{ 65 OutboundUplink: true, 66 OutboundDownlink: true, 67 }, 68 }, 69 }), 70 }, 71 } 72 73 v, _ := core.New(config) 74 v.AddFeature((outbound.Manager)(new(Manager))) 75 ctx := context.WithValue(context.Background(), xrayKey, v) 76 h, _ := NewHandler(ctx, &core.OutboundHandlerConfig{ 77 Tag: "tag", 78 ProxySettings: serial.ToTypedMessage(&freedom.Config{}), 79 }) 80 conn, _ := h.(*Handler).Dial(ctx, net.TCPDestination(net.DomainAddress("localhost"), 13146)) 81 _, ok := conn.(*stat.CounterConnection) 82 if !ok { 83 t.Errorf("Expected conn to be CounterConnection") 84 } 85 } 86 87 func TestTagsCache(t *testing.T) { 88 89 test_duration := 10 * time.Second 90 threads_num := 50 91 delay := 10 * time.Millisecond 92 tags_prefix := "node" 93 94 tags := sync.Map{} 95 counter := atomic.Uint64{} 96 97 ohm, err := New(context.Background(), &proxyman.OutboundConfig{}) 98 if err != nil { 99 t.Error("failed to create outbound handler manager") 100 } 101 config := &core.Config{ 102 App: []*serial.TypedMessage{}, 103 } 104 v, _ := core.New(config) 105 v.AddFeature(ohm) 106 ctx := context.WithValue(context.Background(), xrayKey, v) 107 108 stop_add_rm := false 109 wg_add_rm := sync.WaitGroup{} 110 addHandlers := func() { 111 defer wg_add_rm.Done() 112 for !stop_add_rm { 113 time.Sleep(delay) 114 idx := counter.Add(1) 115 tag := fmt.Sprintf("%s%d", tags_prefix, idx) 116 cfg := &core.OutboundHandlerConfig{ 117 Tag: tag, 118 ProxySettings: serial.ToTypedMessage(&freedom.Config{}), 119 } 120 if h, err := NewHandler(ctx, cfg); err == nil { 121 if err := ohm.AddHandler(ctx, h); err == nil { 122 // t.Log("add handler:", tag) 123 tags.Store(tag, nil) 124 } else { 125 t.Error("failed to add handler:", tag) 126 } 127 } else { 128 t.Error("failed to create handler:", tag) 129 } 130 } 131 } 132 133 rmHandlers := func() { 134 defer wg_add_rm.Done() 135 for !stop_add_rm { 136 time.Sleep(delay) 137 tags.Range(func(key interface{}, value interface{}) bool { 138 if _, ok := tags.LoadAndDelete(key); ok { 139 // t.Log("remove handler:", key) 140 ohm.RemoveHandler(ctx, key.(string)) 141 return false 142 } 143 return true 144 }) 145 } 146 } 147 148 selectors := []string{tags_prefix} 149 wg_get := sync.WaitGroup{} 150 stop_get := false 151 getTags := func() { 152 defer wg_get.Done() 153 for !stop_get { 154 time.Sleep(delay) 155 _ = ohm.Select(selectors) 156 // t.Logf("get tags: %v", tag) 157 } 158 } 159 160 for i := 0; i < threads_num; i++ { 161 wg_add_rm.Add(2) 162 go rmHandlers() 163 go addHandlers() 164 wg_get.Add(1) 165 go getTags() 166 } 167 168 time.Sleep(test_duration) 169 stop_add_rm = true 170 wg_add_rm.Wait() 171 stop_get = true 172 wg_get.Wait() 173 }