github.com/livekit/protocol@v1.16.1-0.20240517185851-47e4c6bba773/utils/multitonservice_test.go (about) 1 // Copyright 2023 LiveKit, Inc. 2 // 3 // Licensed under the Apache License, Version 2.0 (the "License"); 4 // you may not use this file except in compliance with the License. 5 // You may obtain a copy of the License at 6 // 7 // http://www.apache.org/licenses/LICENSE-2.0 8 // 9 // Unless required by applicable law or agreed to in writing, software 10 // distributed under the License is distributed on an "AS IS" BASIS, 11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 // See the License for the specific language governing permissions and 13 // limitations under the License. 14 15 package utils 16 17 import ( 18 "testing" 19 "time" 20 21 "github.com/stretchr/testify/require" 22 "go.uber.org/atomic" 23 ) 24 25 type testService struct { 26 key string 27 killCalls atomic.Int32 28 } 29 30 func newTestService(key string) *testService { 31 return &testService{key: key} 32 } 33 34 func (s *testService) Kill() { s.killCalls.Inc() } 35 36 func TestMultitonService(t *testing.T) { 37 t.Run("start and stop are called", func(t *testing.T) { 38 t.Parallel() 39 40 r := MultitonService[string]{} 41 svc := newTestService("foo") 42 stop := r.Replace("test", svc) 43 44 time.Sleep(time.Millisecond) 45 46 stop() 47 48 time.Sleep(time.Millisecond) 49 50 require.EqualValues(t, 1, svc.killCalls.Load()) 51 }) 52 53 t.Run("stop is idempotent", func(t *testing.T) { 54 t.Parallel() 55 56 r := MultitonService[string]{} 57 svc := newTestService("foo") 58 stop := r.Replace("test", svc) 59 60 for i := 0; i < 3; i++ { 61 time.Sleep(time.Millisecond) 62 63 stop() 64 } 65 66 require.EqualValues(t, 1, svc.killCalls.Load()) 67 }) 68 69 t.Run("replaced services are stopped", func(t *testing.T) { 70 t.Parallel() 71 72 r := MultitonService[string]{} 73 svc0 := newTestService("foo") 74 r.Replace("test", svc0) 75 76 time.Sleep(time.Millisecond) 77 78 svc1 := newTestService("foo") 79 r.Replace("test", svc1) 80 81 time.Sleep(time.Millisecond) 82 83 require.EqualValues(t, 1, svc0.killCalls.Load()) 84 require.EqualValues(t, 0, svc1.killCalls.Load()) 85 }) 86 87 t.Run("stop funcs for replaced services are neutered", func(t *testing.T) { 88 t.Parallel() 89 90 r := MultitonService[string]{} 91 svc0 := newTestService("foo") 92 stop0 := r.Replace("test", svc0) 93 94 time.Sleep(time.Millisecond) 95 96 svc1 := newTestService("foo") 97 r.Replace("test", svc1) 98 99 time.Sleep(time.Millisecond) 100 101 stop0() 102 103 time.Sleep(time.Millisecond) 104 105 require.EqualValues(t, 1, svc0.killCalls.Load()) 106 require.EqualValues(t, 0, svc1.killCalls.Load()) 107 }) 108 }