@@ -2200,3 +2200,130 @@ func TestSessionAffinitySelectorUsesRequestPayloadWhenOriginalRequestMissing(t *
22002200 t .Fatalf ("request-only conversation changed auth from %q to %q" , first .ID , second .ID )
22012201 }
22022202}
2203+
2204+ func TestSessionCache_StopConcurrent (t * testing.T ) {
2205+ t .Parallel ()
2206+ for iter := 0 ; iter < 100 ; iter ++ {
2207+ cache := NewSessionCache (time .Minute )
2208+ var wg sync.WaitGroup
2209+ for i := 0 ; i < 20 ; i ++ {
2210+ wg .Add (1 )
2211+ go func () {
2212+ defer wg .Done ()
2213+ cache .Stop ()
2214+ }()
2215+ }
2216+ wg .Wait ()
2217+ }
2218+ }
2219+
2220+ type mockStoppableSelector struct {
2221+ stopped bool
2222+ }
2223+
2224+ func (m * mockStoppableSelector ) Pick (ctx context.Context , provider , model string , opts cliproxyexecutor.Options , auths []* Auth ) (* Auth , error ) {
2225+ return nil , nil
2226+ }
2227+
2228+ func (m * mockStoppableSelector ) Stop () {
2229+ m .stopped = true
2230+ }
2231+
2232+ func TestManagerSetSelectorStopsReplacedStoppableSelector (t * testing.T ) {
2233+ t .Parallel ()
2234+ mockSelector := & mockStoppableSelector {}
2235+ manager := NewManager (nil , mockSelector , nil )
2236+
2237+ manager .SetSelector (& RoundRobinSelector {})
2238+
2239+ if ! mockSelector .stopped {
2240+ t .Fatal ("expected previous StoppableSelector to be stopped when replaced via SetSelector" )
2241+ }
2242+ }
2243+
2244+ type zeroSizeSelectorA struct {
2245+ stopped * bool
2246+ }
2247+
2248+ func (z zeroSizeSelectorA ) Pick (ctx context.Context , provider , model string , opts cliproxyexecutor.Options , auths []* Auth ) (* Auth , error ) {
2249+ return nil , nil
2250+ }
2251+
2252+ func (z zeroSizeSelectorA ) Stop () {
2253+ if z .stopped != nil {
2254+ * z .stopped = true
2255+ }
2256+ }
2257+
2258+ type zeroSizeSelectorB struct {}
2259+
2260+ func (z zeroSizeSelectorB ) Pick (ctx context.Context , provider , model string , opts cliproxyexecutor.Options , auths []* Auth ) (* Auth , error ) {
2261+ return nil , nil
2262+ }
2263+
2264+ func TestManagerSetSelectorDifferentZeroSizedSelectors (t * testing.T ) {
2265+ t .Parallel ()
2266+ stoppedA := false
2267+ selA := zeroSizeSelectorA {stopped : & stoppedA }
2268+ selB := zeroSizeSelectorB {}
2269+
2270+ manager := NewManager (nil , selA , nil )
2271+ manager .SetSelector (selB )
2272+
2273+ if ! stoppedA {
2274+ t .Fatal ("expected zeroSizeSelectorA to be stopped when replaced by zeroSizeSelectorB" )
2275+ }
2276+ if manager .Selector () != selB {
2277+ t .Fatalf ("expected manager selector to be selB, got %#v" , manager .Selector ())
2278+ }
2279+ }
2280+
2281+ type uncomparableSelector struct {
2282+ fn func ()
2283+ }
2284+
2285+ func (u uncomparableSelector ) Pick (ctx context.Context , provider , model string , opts cliproxyexecutor.Options , auths []* Auth ) (* Auth , error ) {
2286+ return nil , nil
2287+ }
2288+
2289+ func TestManagerSetSelectorUncomparableTypes (t * testing.T ) {
2290+ t .Parallel ()
2291+ manager := NewManager (nil , nil , nil )
2292+
2293+ sel1 := uncomparableSelector {fn : func () {}}
2294+ sel2 := uncomparableSelector {fn : func () {}}
2295+
2296+ // Setting uncomparable types must not panic
2297+ manager .SetSelector (sel1 )
2298+ manager .SetSelector (sel2 )
2299+ manager .SetSelector (nil )
2300+ }
2301+
2302+ func TestManagerSetSelectorSameInstanceDoesNotStop (t * testing.T ) {
2303+ t .Parallel ()
2304+ mockSelector := & mockStoppableSelector {}
2305+ manager := NewManager (nil , mockSelector , nil )
2306+
2307+ // Setting the same instance should be a no-op and not call Stop
2308+ manager .SetSelector (mockSelector )
2309+ if mockSelector .stopped {
2310+ t .Fatal ("setting the same selector instance unexpectedly called Stop" )
2311+ }
2312+ }
2313+
2314+ func TestManagerSetSelectorConcurrent (t * testing.T ) {
2315+ t .Parallel ()
2316+ manager := NewManager (nil , nil , nil )
2317+ var wg sync.WaitGroup
2318+ for i := 0 ; i < 20 ; i ++ {
2319+ wg .Add (1 )
2320+ go func () {
2321+ defer wg .Done ()
2322+ for j := 0 ; j < 10 ; j ++ {
2323+ sel := & mockStoppableSelector {}
2324+ manager .SetSelector (sel )
2325+ }
2326+ }()
2327+ }
2328+ wg .Wait ()
2329+ }
0 commit comments