github.com/e154/smart-home@v0.17.2-0.20240311175135-e530a6e5cd45/system/bus/topic_test.go (about) 1 // This file is part of the Smart Home 2 // Program complex distribution https://github.com/e154/smart-home 3 // Copyright (C) 2023, Filippov Alex 4 // 5 // This library is free software: you can redistribute it and/or 6 // modify it under the terms of the GNU Lesser General Public 7 // License as published by the Free Software Foundation; either 8 // version 3 of the License, or (at your option) any later version. 9 // 10 // This library is distributed in the hope that it will be useful, 11 // but WITHOUT ANY WARRANTY; without even the implied warranty of 12 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 13 // Library General Public License for more details. 14 // 15 // You should have received a copy of the GNU Lesser General Public 16 // License along with this library. If not, see 17 // <https://www.gnu.org/licenses/>. 18 19 package bus 20 21 import ( 22 "fmt" 23 "go.uber.org/atomic" 24 "reflect" 25 "sync" 26 "testing" 27 "time" 28 29 "github.com/stretchr/testify/require" 30 ) 31 32 func TestTopic(t *testing.T) { 33 34 const topic = "test/topic" 35 36 b := NewTopic(topic) 37 38 var counter = 0 39 var wg = sync.WaitGroup{} 40 41 // Test Subscribe 42 fn := func(topic string, arg1 string, arg2 string) { 43 counter++ 44 wg.Done() 45 } 46 wg.Add(1) 47 err := b.Subscribe(fn) 48 if err != nil { 49 t.Errorf("Subscribe returned an error: %v", err) 50 } 51 52 // Test Publish 53 b.Publish("hello", "world") 54 55 wg.Wait() 56 57 require.Equal(t, counter, 1) 58 59 // ------------------------------------------------------------ 60 // Test Stat 61 stat := b.Stat() 62 require.Equal(t, stat.Topic, topic) 63 require.Equal(t, stat.Subscribers, 1) 64 65 // ------------------------------------------------------------ 66 67 // Test Unsubscribe 68 empty, err := b.Unsubscribe(fn) 69 if err != nil { 70 t.Errorf("Unsubscribe returned an error: %v", err) 71 } 72 require.Equal(t, true, empty) 73 74 // Test Publish 75 b.Publish("hello", "world") 76 77 time.Sleep(time.Second) 78 79 require.Equal(t, 1, counter) 80 81 // ------------------------------------------------------------ 82 83 stat = b.Stat() 84 require.Equal(t, stat.Topic, topic) 85 require.Equal(t, stat.Subscribers, 0) 86 // ------------------------------------------------------------ 87 88 // Test Subscribe 89 fn = func(topic string, arg1 string, arg2 string) { 90 counter++ 91 } 92 err = b.Subscribe(fn, false) 93 if err != nil { 94 t.Errorf("Subscribe returned an error: %v", err) 95 } 96 97 stat = b.Stat() 98 require.Equal(t, stat.Subscribers, 1) 99 100 // Test Close 101 b.Close() 102 103 stat = b.Stat() 104 require.Equal(t, stat.Subscribers, 0) 105 106 // Test Publish 107 b.Publish("foo", "bar") 108 109 time.Sleep(time.Second) 110 111 require.Equal(t, 1, counter) 112 113 // ------------------------------------------------------------ 114 // Test Stat 115 stat = b.Stat() 116 require.Equal(t, stat.Subscribers, 0) 117 // ------------------------------------------------------------ 118 119 fn = func(topic string, arg1 string, arg2 string) { 120 counter++ 121 } 122 err = b.Subscribe(fn, false) 123 if err != nil { 124 t.Errorf("Subscribe returned an error: %v", err) 125 } 126 127 // Test Close 128 b.Close() 129 130 // Test Publish 131 b.Publish("hello", "world") 132 133 time.Sleep(time.Second) 134 135 require.Equal(t, 1, counter) 136 137 /// Test Stat 138 stat = b.Stat() 139 require.Equal(t, stat.Subscribers, 0) 140 141 // ------------------------------------------------------------ 142 143 // Test buildHandlerArgs 144 args := buildHandlerArgs([]interface{}{topic, "hello", "world"}) 145 if len(args) != 3 { 146 t.Errorf("buildHandlerArgs returned the wrong number of arguments: %v", args) 147 } 148 if args[0].String() != topic { 149 t.Errorf("buildHandlerArgs returned the wrong topic: %v", args[0]) 150 } 151 if args[1].String() != "hello" { 152 t.Errorf("buildHandlerArgs returned the wrong arg1: %v", args[1]) 153 } 154 if args[2].String() != "world" { 155 t.Errorf("buildHandlerArgs returned the wrong arg2: %v", args[2]) 156 } 157 158 // Test reflection of buildHandlerArgs 159 if reflect.TypeOf(buildHandlerArgs).Kind() != reflect.Func { 160 t.Errorf("buildHandlerArgs is not a function") 161 } 162 } 163 164 func TestTopic2(t *testing.T) { 165 166 const topic = "test/topic" 167 168 b := NewTopic(topic) 169 170 var counter atomic.Int32 171 var wg = sync.WaitGroup{} 172 173 // Test Subscribe 174 fn := func(topic string, arg1 string, arg2 string) { 175 fmt.Println("fn1") 176 counter.Inc() 177 wg.Done() 178 } 179 180 fn2 := func(topic string, arg1 string, arg2 string) { 181 fmt.Println("fn2") 182 counter.Inc() 183 wg.Done() 184 } 185 186 fn3 := func(topic string, arg1 string, arg2 string) { 187 fmt.Println("fn3") 188 counter.Inc() 189 wg.Done() 190 } 191 192 wg.Add(3) 193 194 err := b.Subscribe(fn) 195 if err != nil { 196 t.Errorf("Subscribe returned an error: %v", err) 197 } 198 err = b.Subscribe(fn2) 199 if err != nil { 200 t.Errorf("Subscribe returned an error: %v", err) 201 } 202 err = b.Subscribe(fn3) 203 if err != nil { 204 t.Errorf("Subscribe returned an error: %v", err) 205 } 206 207 // Test Stat 208 stat := b.Stat() 209 require.Equal(t, 3, stat.Subscribers) 210 211 // Test Publish 212 b.Publish("hello", "world") 213 214 wg.Wait() 215 216 require.Equal(t, int32(3), counter.Load()) 217 } 218 219 func TestTopic3(t *testing.T) { 220 221 const topic = "test/topic" 222 223 b := NewTopic(topic) 224 225 // Test Subscribe 226 fn := func(topic string, arg1 string, arg2 string) {} 227 228 empty, err := b.Unsubscribe(fn) 229 require.Equal(t, nil, err) 230 require.Equal(t, true, empty) 231 232 err = b.Subscribe(fn) 233 require.Equal(t, nil, err) 234 235 // Test Stat 236 stat := b.Stat() 237 require.Equal(t, 1, stat.Subscribers) 238 239 empty, err = b.Unsubscribe(fn) 240 require.Equal(t, nil, err) 241 require.Equal(t, true, empty) 242 243 empty, err = b.Unsubscribe(fn) 244 require.Equal(t, nil, err) 245 require.Equal(t, true, empty) 246 } 247 248 func BenchmarkTopic(b *testing.B) { 249 250 const topic = "test/topic" 251 252 bus := NewTopic(topic) 253 254 var counter atomic.Int32 255 256 // Test Subscribe 257 fn := func(topic string, arg1 string, arg2 string) { 258 counter.Inc() 259 } 260 err := bus.Subscribe(fn) 261 require.NoError(b, err) 262 263 b.ResetTimer() 264 for i := 0; i < b.N; i++ { 265 bus.Publish("hello", "world") 266 } 267 268 time.Sleep(time.Second) 269 270 require.Equal(b, int32(b.N), counter.Load()) 271 }