github.com/guobinqiu/cuckoofilter@v0.0.0-20220511032311-1b6ac21c7f3c/server/server_test.go (about) 1 package server 2 3 import ( 4 "context" 5 "github.com/golang/protobuf/ptypes/empty" 6 "github.com/google/uuid" 7 pb "github.com/guobinqiu/cuckoofilter/cuckoofilter" 8 "github.com/panmari/cuckoofilter" 9 "github.com/stretchr/testify/assert" 10 "os" 11 "testing" 12 "time" 13 ) 14 15 func TestCreateFilter(t *testing.T) { 16 ctx, cancel := context.WithTimeout(context.Background(), 10*time.Second) 17 defer cancel() 18 19 s := NewServer() 20 var res *pb.CreateFilterResponse 21 res, _ = s.CreateFilter(ctx, &pb.CreateFilterRequest{FilterName: "aaa", Capacity: 100}) 22 assert.Equal(t, res.Status, StatusOK) 23 } 24 25 func TestCreateFilterAlreadyExist(t *testing.T) { 26 ctx, cancel := context.WithTimeout(context.Background(), 10*time.Second) 27 defer cancel() 28 29 s := NewServer() 30 s.Filters["aaa"] = cuckoo.NewFilter(100) 31 32 var res *pb.CreateFilterResponse 33 res, _ = s.CreateFilter(ctx, &pb.CreateFilterRequest{FilterName: "aaa", Capacity: 100}) 34 assert.Equal(t, res.Status, StatusFilterAlreadyExist) 35 } 36 37 func TestDeleteFilter(t *testing.T) { 38 ctx, cancel := context.WithTimeout(context.Background(), 10*time.Second) 39 defer cancel() 40 41 s := NewServer() 42 s.Filters["aaa"] = cuckoo.NewFilter(100) 43 44 var res *pb.DeleteFilterResponse 45 res, _ = s.DeleteFilter(ctx, &pb.DeleteFilterRequest{FilterName: "aaa"}) 46 47 assert.Equal(t, res.Status, StatusOK) 48 } 49 50 func TestDeleteFilterNoFilterFound(t *testing.T) { 51 ctx, cancel := context.WithTimeout(context.Background(), 10*time.Second) 52 defer cancel() 53 54 s := NewServer() 55 s.Filters["aaa"] = cuckoo.NewFilter(100) 56 57 var res *pb.DeleteFilterResponse 58 res, _ = s.DeleteFilter(ctx, &pb.DeleteFilterRequest{FilterName: "bbb"}) 59 60 assert.Equal(t, res.Status, StatusNoFilterFound) 61 } 62 63 func TestListFilter(t *testing.T) { 64 ctx, cancel := context.WithTimeout(context.Background(), 10*time.Second) 65 defer cancel() 66 67 s := NewServer() 68 69 var res *pb.ListFiltersResponse 70 res, _ = s.ListFilters(ctx, new(empty.Empty)) 71 72 assert.Len(t, res.Filters, 0) 73 } 74 75 func TestListFilterEmpty(t *testing.T) { 76 ctx, cancel := context.WithTimeout(context.Background(), 10*time.Second) 77 defer cancel() 78 79 s := NewServer() 80 s.Filters["aaa"] = cuckoo.NewFilter(100) 81 s.Filters["bbb"] = cuckoo.NewFilter(100) 82 83 var res *pb.ListFiltersResponse 84 res, _ = s.ListFilters(ctx, new(empty.Empty)) 85 86 assert.Len(t, res.Filters, 2) 87 } 88 89 func TestInsertElement(t *testing.T) { 90 ctx, cancel := context.WithTimeout(context.Background(), 10*time.Second) 91 defer cancel() 92 93 s := NewServer() 94 s.Filters["aaa"] = cuckoo.NewFilter(100) 95 96 var res *pb.InsertElementResponse 97 res, _ = s.InsertElement(ctx, &pb.InsertElementRequest{FilterName: "aaa", Element: "jack"}) 98 99 assert.Equal(t, res.Status, StatusOK) 100 } 101 102 func TestInsertElementNoFilterFound(t *testing.T) { 103 ctx, cancel := context.WithTimeout(context.Background(), 10*time.Second) 104 defer cancel() 105 106 s := NewServer() 107 s.Filters["aaa"] = cuckoo.NewFilter(100) 108 109 var res *pb.InsertElementResponse 110 res, _ = s.InsertElement(ctx, &pb.InsertElementRequest{FilterName: "bbb", Element: "jack"}) 111 112 assert.Equal(t, res.Status, StatusNoFilterFound) 113 } 114 115 func TestDeleteElement(t *testing.T) { 116 ctx, cancel := context.WithTimeout(context.Background(), 10*time.Second) 117 defer cancel() 118 119 s := NewServer() 120 filter := cuckoo.NewFilter(100) 121 s.Filters["aaa"] = filter 122 filter.Insert([]byte("jack")) 123 124 var res *pb.DeleteElementResponse 125 res, _ = s.DeleteElement(ctx, &pb.DeleteElementRequest{FilterName: "aaa", Element: "jack"}) 126 127 assert.Equal(t, res.Status, StatusOK) 128 } 129 130 func TestDeleteElementNoElementFound(t *testing.T) { 131 ctx, cancel := context.WithTimeout(context.Background(), 10*time.Second) 132 defer cancel() 133 134 s := NewServer() 135 filter := cuckoo.NewFilter(100) 136 s.Filters["aaa"] = filter 137 filter.Insert([]byte("jack")) 138 139 var res *pb.DeleteElementResponse 140 res, _ = s.DeleteElement(ctx, &pb.DeleteElementRequest{FilterName: "aaa", Element: "mary"}) 141 142 assert.Equal(t, res.Status, StatusNoElementFound) 143 } 144 145 func TestDeleteElementNoFilterFound(t *testing.T) { 146 ctx, cancel := context.WithTimeout(context.Background(), 10*time.Second) 147 defer cancel() 148 149 s := NewServer() 150 filter := cuckoo.NewFilter(100) 151 s.Filters["aaa"] = filter 152 filter.Insert([]byte("jack")) 153 154 var res *pb.DeleteElementResponse 155 res, _ = s.DeleteElement(ctx, &pb.DeleteElementRequest{FilterName: "bbb", Element: "jack"}) 156 157 assert.Equal(t, res.Status, StatusNoFilterFound) 158 } 159 160 func TestCountElements(t *testing.T) { 161 ctx, cancel := context.WithTimeout(context.Background(), 10*time.Second) 162 defer cancel() 163 164 s := NewServer() 165 filter := cuckoo.NewFilter(100) 166 s.Filters["aaa"] = filter 167 filter.Insert([]byte("jack")) 168 filter.Insert([]byte("mary")) 169 170 var res *pb.CountElementsResponse 171 res, _ = s.CountElements(ctx, &pb.CountElementsRequest{FilterName: "aaa"}) 172 173 assert.True(t, res.Len == 2) 174 } 175 176 func TestCountElementsNoFilterFound(t *testing.T) { 177 ctx, cancel := context.WithTimeout(context.Background(), 10*time.Second) 178 defer cancel() 179 180 s := NewServer() 181 filter := cuckoo.NewFilter(100) 182 s.Filters["aaa"] = filter 183 filter.Insert([]byte("jack")) 184 filter.Insert([]byte("mary")) 185 186 var res *pb.CountElementsResponse 187 res, _ = s.CountElements(ctx, &pb.CountElementsRequest{FilterName: "bbb"}) 188 189 assert.Equal(t, res.Status, StatusNoFilterFound) 190 } 191 192 func TestResetFilter(t *testing.T) { 193 ctx, cancel := context.WithTimeout(context.Background(), 10*time.Second) 194 defer cancel() 195 196 s := NewServer() 197 filter := cuckoo.NewFilter(100) 198 s.Filters["aaa"] = filter 199 filter.Insert([]byte("jack")) 200 filter.Insert([]byte("mary")) 201 202 s.ResetFilter(ctx, &pb.ResetFilterRequest{FilterName: "aaa"}) 203 204 assert.Zero(t, filter.Count()) 205 } 206 207 func TestResetFilterNoFilterFound(t *testing.T) { 208 ctx, cancel := context.WithTimeout(context.Background(), 10*time.Second) 209 defer cancel() 210 211 s := NewServer() 212 filter := cuckoo.NewFilter(100) 213 s.Filters["aaa"] = filter 214 filter.Insert([]byte("jack")) 215 filter.Insert([]byte("mary")) 216 217 var res *pb.ResetFilterResponse 218 res, _ = s.ResetFilter(ctx, &pb.ResetFilterRequest{FilterName: "bbb"}) 219 220 assert.Equal(t, res.Status, StatusNoFilterFound) 221 } 222 223 func TestLookupElement(t *testing.T) { 224 ctx, cancel := context.WithTimeout(context.Background(), 10*time.Second) 225 defer cancel() 226 227 s := NewServer() 228 filter := cuckoo.NewFilter(100) 229 s.Filters["aaa"] = filter 230 filter.Insert([]byte("jack")) 231 232 var res *pb.LookupElementResponse 233 res, _ = s.LookupElement(ctx, &pb.LookupElementRequest{FilterName: "aaa", Element: "jack"}) 234 235 assert.Equal(t, res.Status, StatusOK) 236 } 237 238 func TestLookupElementNoFilterFound(t *testing.T) { 239 ctx, cancel := context.WithTimeout(context.Background(), 10*time.Second) 240 defer cancel() 241 242 s := NewServer() 243 filter := cuckoo.NewFilter(100) 244 s.Filters["aaa"] = filter 245 filter.Insert([]byte("jack")) 246 247 var res *pb.LookupElementResponse 248 res, _ = s.LookupElement(ctx, &pb.LookupElementRequest{FilterName: "bbb", Element: "jack"}) 249 250 assert.Equal(t, res.Status, StatusNoFilterFound) 251 } 252 253 func TestLookupElementNoElementFound(t *testing.T) { 254 ctx, cancel := context.WithTimeout(context.Background(), 10*time.Second) 255 defer cancel() 256 257 s := NewServer() 258 filter := cuckoo.NewFilter(100) 259 s.Filters["aaa"] = filter 260 filter.Insert([]byte("jack")) 261 262 var res *pb.LookupElementResponse 263 res, _ = s.LookupElement(ctx, &pb.LookupElementRequest{FilterName: "aaa", Element: "mary"}) 264 265 assert.Equal(t, res.Status, StatusNoElementFound) 266 } 267 268 func TestLookupElements(t *testing.T) { 269 ctx, cancel := context.WithTimeout(context.Background(), 10*time.Second) 270 defer cancel() 271 272 s := NewServer() 273 filter := cuckoo.NewFilter(100) 274 s.Filters["aaa"] = filter 275 filter.Insert([]byte("jack")) 276 277 var res *pb.LookupElementsResponse 278 res, _ = s.LookupElements(ctx, &pb.LookupElementsRequest{FilterName: "aaa", Elements: []string{"jack", "rose"}}) 279 280 assert.Equal(t, res.Status, StatusOK) 281 assert.Equal(t, res.MatchedElements, []string{"jack"}) 282 assert.Equal(t, res.UnmatchedElements, []string{"rose"}) 283 } 284 285 func TestLookupElementsNoFilterFound(t *testing.T) { 286 ctx, cancel := context.WithTimeout(context.Background(), 10*time.Second) 287 defer cancel() 288 289 s := NewServer() 290 filter := cuckoo.NewFilter(100) 291 s.Filters["aaa"] = filter 292 filter.Insert([]byte("jack")) 293 294 var res *pb.LookupElementsResponse 295 res, _ = s.LookupElements(ctx, &pb.LookupElementsRequest{FilterName: "bbb", Elements: []string{"jack"}}) 296 297 assert.Equal(t, res.Status, StatusNoFilterFound) 298 } 299 300 func TestLookupElementsOverLimitation(t *testing.T) { 301 ctx, cancel := context.WithTimeout(context.Background(), 10*time.Second) 302 defer cancel() 303 304 s := NewServer() 305 filter := cuckoo.NewFilter(100) 306 s.Filters["aaa"] = filter 307 filter.Insert([]byte("")) 308 309 var res *pb.LookupElementsResponse 310 elements := make([]string, 5000) 311 res, _ = s.LookupElements(ctx, &pb.LookupElementsRequest{FilterName: "aaa", Elements: elements}) 312 assert.Equal(t, res.Status, StatusOK) 313 314 elements = make([]string, 5001) 315 res, _ = s.LookupElements(ctx, &pb.LookupElementsRequest{FilterName: "aaa", Elements: elements}) 316 assert.Equal(t, res.Status, StatusOverLimitation) 317 } 318 319 func TestInsertElements(t *testing.T) { 320 ctx, cancel := context.WithTimeout(context.Background(), 10*time.Second) 321 defer cancel() 322 323 s := NewServer() 324 s.Filters["aaa"] = cuckoo.NewFilter(100) 325 326 var res *pb.InsertElementsResponse 327 res, _ = s.InsertElements(ctx, &pb.InsertElementsRequest{FilterName: "aaa", Elements: []string{"jack"}}) 328 329 assert.Equal(t, res.Status, StatusOK) 330 } 331 332 func TestLookupElementsStream(t *testing.T) { 333 334 } 335 336 func TestDumpAndLoad(t *testing.T) { 337 f1 := cuckoo.NewFilter(3) 338 f1.Insert([]byte("a")) 339 f1.Insert([]byte("b")) 340 f1.Insert([]byte("c")) 341 342 f2 := cuckoo.NewFilter(3) 343 f2.Insert([]byte("x")) 344 f2.Insert([]byte("y")) 345 f2.Insert([]byte("z")) 346 347 s := NewServer() 348 s.Filters["aaa"] = f1 349 s.Filters["bbb"] = f2 350 351 dir := "dump" 352 assert.NoError(t, s.Dump(dir)) 353 354 s = NewServer() 355 s.Load(dir) 356 357 assert.True(t, s.Filters["aaa"].Lookup([]byte("a"))) 358 assert.True(t, s.Filters["aaa"].Lookup([]byte("b"))) 359 assert.True(t, s.Filters["aaa"].Lookup([]byte("c"))) 360 assert.False(t, s.Filters["aaa"].Lookup([]byte("d"))) 361 362 assert.True(t, s.Filters["bbb"].Lookup([]byte("x"))) 363 assert.True(t, s.Filters["bbb"].Lookup([]byte("y"))) 364 assert.True(t, s.Filters["bbb"].Lookup([]byte("z"))) 365 assert.False(t, s.Filters["bbb"].Lookup([]byte("w"))) 366 367 os.RemoveAll(dir) 368 } 369 370 func BenchmarkLoad1Million(b *testing.B) { load("aaa", 1000000) } 371 func BenchmarkLoad10Million(b *testing.B) { load("aaa", 10000000) } 372 func BenchmarkLoad100Million(b *testing.B) { load("aaa", 100000000) } 373 374 //func BenchmarkLoad1000Million(b *testing.B) { load("aaa", 1000000000) } 375 376 func BenchmarkLookupElement1Million(b *testing.B) { benchmarkLookupElement("aaa", 1000000, b) } 377 func BenchmarkLookupElement10Million(b *testing.B) { benchmarkLookupElement("aaa", 10000000, b) } 378 func BenchmarkLookupElement100Million(b *testing.B) { benchmarkLookupElement("aaa", 100000000, b) } 379 380 //func BenchmarkLookupElement1000Million(b *testing.B) { benchmarkLookupElement("aaa", 1000000000, b) } 381 382 func benchmarkLookupElement(filterName string, filterCapacity uint, b *testing.B) { 383 ctx, cancel := context.WithTimeout(context.Background(), 10*time.Second) 384 defer cancel() 385 s, lastElement := load(filterName, filterCapacity) 386 b.ResetTimer() 387 for i := 0; i < b.N; i++ { 388 s.LookupElement(ctx, &pb.LookupElementRequest{FilterName: filterName, Element: lastElement}) 389 } 390 } 391 392 func load(filterName string, filterCapacity uint) (s *cuckooFilterServer, lastElement string) { 393 ctx, cancel := context.WithTimeout(context.Background(), 10*time.Second) 394 defer cancel() 395 396 s = NewServer() 397 s.Filters[filterName] = cuckoo.NewFilter(filterCapacity) 398 399 var i uint 400 for i = 0; i < filterCapacity-1; i++ { 401 s.InsertElement(ctx, &pb.InsertElementRequest{FilterName: filterName, Element: uuid.New().String()}) 402 } 403 404 lastElement = uuid.New().String() 405 s.InsertElement(ctx, &pb.InsertElementRequest{FilterName: filterName, Element: lastElement}) 406 407 return 408 }