github.com/e154/smart-home@v0.17.2-0.20240311175135-e530a6e5cd45/common/debounce/debounce_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 debounce 20 21 import ( 22 "fmt" 23 "sync" 24 "sync/atomic" 25 "testing" 26 "time" 27 ) 28 29 func TestDebounce(t *testing.T) { 30 var ( 31 counter1 uint64 32 counter2 uint64 33 ) 34 35 f1 := func() { 36 atomic.AddUint64(&counter1, 1) 37 } 38 39 f2 := func() { 40 atomic.AddUint64(&counter2, 1) 41 } 42 43 f3 := func() { 44 atomic.AddUint64(&counter2, 2) 45 } 46 47 debounced := New(100 * time.Millisecond) 48 49 for i := 0; i < 3; i++ { 50 for j := 0; j < 10; j++ { 51 debounced(f1) 52 } 53 54 time.Sleep(200 * time.Millisecond) 55 } 56 57 for i := 0; i < 4; i++ { 58 for j := 0; j < 10; j++ { 59 debounced(f2) 60 } 61 for j := 0; j < 10; j++ { 62 debounced(f3) 63 } 64 65 time.Sleep(200 * time.Millisecond) 66 } 67 68 c1 := int(atomic.LoadUint64(&counter1)) 69 c2 := int(atomic.LoadUint64(&counter2)) 70 if c1 != 3 { 71 t.Error("Expected count 3, was", c1) 72 } 73 if c2 != 8 { 74 t.Error("Expected count 8, was", c2) 75 } 76 77 fmt.Println("counter1", c1) 78 fmt.Println("counter2", c2) 79 } 80 81 func TestDebounceConcurrentAdd(t *testing.T) { 82 var wg sync.WaitGroup 83 84 var flag uint64 85 86 debounced := New(100 * time.Millisecond) 87 88 for i := 0; i < 10; i++ { 89 wg.Add(1) 90 go func() { 91 defer wg.Done() 92 debounced(func() { 93 atomic.CompareAndSwapUint64(&flag, 0, 1) 94 }) 95 }() 96 } 97 wg.Wait() 98 99 time.Sleep(500 * time.Millisecond) 100 c := int(atomic.LoadUint64(&flag)) 101 if c != 1 { 102 t.Error("Flag not set") 103 } 104 } 105 106 // Issue #1 107 func TestDebounceDelayed(t *testing.T) { 108 109 var ( 110 counter1 uint64 111 ) 112 113 f1 := func() { 114 atomic.AddUint64(&counter1, 1) 115 } 116 117 debounced := New(100 * time.Millisecond) 118 119 time.Sleep(110 * time.Millisecond) 120 121 debounced(f1) 122 123 time.Sleep(200 * time.Millisecond) 124 125 c1 := int(atomic.LoadUint64(&counter1)) 126 if c1 != 1 { 127 t.Error("Expected count 1, was", c1) 128 } 129 130 } 131 132 func BenchmarkDebounce(b *testing.B) { 133 var counter uint64 134 135 f := func() { 136 atomic.AddUint64(&counter, 1) 137 } 138 139 debounced := New(100 * time.Millisecond) 140 141 b.ResetTimer() 142 for i := 0; i < b.N; i++ { 143 debounced(f) 144 } 145 146 c := int(atomic.LoadUint64(&counter)) 147 if c != 0 { 148 b.Fatal("Expected count 0, was", c) 149 } 150 } 151 152 func ExampleNew() { 153 var counter uint64 154 155 f := func() { 156 atomic.AddUint64(&counter, 1) 157 } 158 159 debounced := New(100 * time.Millisecond) 160 161 for i := 0; i < 3; i++ { 162 for j := 0; j < 10; j++ { 163 debounced(f) 164 } 165 166 time.Sleep(200 * time.Millisecond) 167 } 168 169 c := int(atomic.LoadUint64(&counter)) 170 171 fmt.Println("Counter is", c) 172 // Output: Counter is 3 173 } 174 175 func ExampleNew2() { 176 var counter1 uint64 177 var counter2 uint64 178 179 f := func() { 180 atomic.AddUint64(&counter1, 1) 181 } 182 183 f2 := func() { 184 atomic.AddUint64(&counter2, 1) 185 } 186 187 debounced := New(100 * time.Millisecond) 188 189 debounced(f) // will be reset and dropped!!! 190 for i := 0; i < 10; i++ { 191 debounced(f2) 192 } 193 194 time.Sleep(time.Millisecond * 500) 195 196 c1 := int(atomic.LoadUint64(&counter1)) 197 c2 := int(atomic.LoadUint64(&counter2)) 198 199 fmt.Println("Counter1 is", c1) 200 fmt.Println("Counter2 is", c2) 201 // Output: Counter1 is 0 202 // Counter2 is 1 203 }