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  }