github.com/TeaOSLab/EdgeNode@v1.3.8/internal/iplibrary/ip_list_test.go (about)

     1  package iplibrary_test
     2  
     3  import (
     4  	"fmt"
     5  	"github.com/TeaOSLab/EdgeCommon/pkg/iputils"
     6  	"github.com/TeaOSLab/EdgeNode/internal/iplibrary"
     7  	"github.com/TeaOSLab/EdgeNode/internal/utils/fasttime"
     8  	"github.com/TeaOSLab/EdgeNode/internal/utils/testutils"
     9  	"github.com/iwind/TeaGo/assert"
    10  	"github.com/iwind/TeaGo/logs"
    11  	"github.com/iwind/TeaGo/rands"
    12  	"math/rand"
    13  	"runtime"
    14  	"runtime/debug"
    15  	"strconv"
    16  	"sync"
    17  	"testing"
    18  	"time"
    19  )
    20  
    21  func TestIPList_Add_Empty(t *testing.T) {
    22  	var ipList = iplibrary.NewIPList()
    23  	ipList.Add(&iplibrary.IPItem{
    24  		Id: 1,
    25  	})
    26  	logs.PrintAsJSON(ipList.ItemsMap(), t)
    27  	logs.PrintAsJSON(ipList.AllItemsMap(), t)
    28  	logs.PrintAsJSON(ipList.IPMap(), t)
    29  }
    30  
    31  func TestIPList_Add_One(t *testing.T) {
    32  	var a = assert.NewAssertion(t)
    33  
    34  	var ipList = iplibrary.NewIPList()
    35  	ipList.Add(&iplibrary.IPItem{
    36  		Id:     1,
    37  		IPFrom: iputils.ToBytes("192.168.1.1"),
    38  	})
    39  	ipList.Add(&iplibrary.IPItem{
    40  		Id:   2,
    41  		IPTo: iputils.ToBytes("192.168.1.2"),
    42  	})
    43  	ipList.Add(&iplibrary.IPItem{
    44  		Id:     3,
    45  		IPFrom: iputils.ToBytes("192.168.0.2"),
    46  	})
    47  	ipList.Add(&iplibrary.IPItem{
    48  		Id:     4,
    49  		IPFrom: iputils.ToBytes("192.168.0.2"),
    50  		IPTo:   iputils.ToBytes("192.168.0.1"),
    51  	})
    52  	ipList.Add(&iplibrary.IPItem{
    53  		Id:     5,
    54  		IPFrom: iputils.ToBytes("2001:db8:0:1::101"),
    55  	})
    56  	ipList.Add(&iplibrary.IPItem{
    57  		Id:     6,
    58  		IPFrom: nil,
    59  		Type:   "all",
    60  	})
    61  	t.Log("===items===")
    62  	logs.PrintAsJSON(ipList.ItemsMap(), t)
    63  
    64  	t.Log("===sorted items===")
    65  	logs.PrintAsJSON(ipList.SortedRangeItems(), t)
    66  
    67  	t.Log("===all items===")
    68  	a.IsTrue(len(ipList.AllItemsMap()) == 1)
    69  	logs.PrintAsJSON(ipList.AllItemsMap(), t) // ip => items
    70  
    71  	t.Log("===ip items===")
    72  	logs.PrintAsJSON(ipList.IPMap())
    73  }
    74  
    75  func TestIPList_Update(t *testing.T) {
    76  	var ipList = iplibrary.NewIPList()
    77  	ipList.Add(&iplibrary.IPItem{
    78  		Id:     1,
    79  		IPFrom: iputils.ToBytes("192.168.1.1"),
    80  	})
    81  
    82  	t.Log("===before===")
    83  	logs.PrintAsJSON(ipList.ItemsMap(), t)
    84  	logs.PrintAsJSON(ipList.SortedRangeItems(), t)
    85  	logs.PrintAsJSON(ipList.IPMap(), t)
    86  
    87  	/**ipList.Add(&iplibrary.IPItem{
    88  		Id:     2,
    89  		IPFrom: iputils.ToBytes("192.168.1.1"),
    90  	})**/
    91  	ipList.Add(&iplibrary.IPItem{
    92  		Id: 1,
    93  		//IPFrom: 123,
    94  		IPTo: iputils.ToBytes("192.168.1.2"),
    95  	})
    96  
    97  	t.Log("===after===")
    98  	logs.PrintAsJSON(ipList.ItemsMap(), t)
    99  	logs.PrintAsJSON(ipList.SortedRangeItems(), t)
   100  	logs.PrintAsJSON(ipList.IPMap(), t)
   101  }
   102  
   103  func TestIPList_Update_AllItems(t *testing.T) {
   104  	var ipList = iplibrary.NewIPList()
   105  	ipList.Add(&iplibrary.IPItem{
   106  		Id:     1,
   107  		Type:   iplibrary.IPItemTypeAll,
   108  		IPFrom: nil,
   109  	})
   110  	ipList.Add(&iplibrary.IPItem{
   111  		Id:   1,
   112  		IPTo: nil,
   113  	})
   114  	t.Log("===items map===")
   115  	logs.PrintAsJSON(ipList.ItemsMap(), t)
   116  	t.Log("===all items map===")
   117  	logs.PrintAsJSON(ipList.AllItemsMap(), t)
   118  	t.Log("===ip map===")
   119  	logs.PrintAsJSON(ipList.IPMap())
   120  }
   121  
   122  func TestIPList_Add_Range(t *testing.T) {
   123  	var a = assert.NewAssertion(t)
   124  
   125  	var ipList = iplibrary.NewIPList()
   126  	ipList.Add(&iplibrary.IPItem{
   127  		Id:     1,
   128  		IPFrom: iputils.ToBytes("192.168.1.1"),
   129  		IPTo:   iputils.ToBytes("192.168.2.1"),
   130  	})
   131  	ipList.Add(&iplibrary.IPItem{
   132  		Id:   2,
   133  		IPTo: iputils.ToBytes("192.168.1.2"),
   134  	})
   135  	ipList.Add(&iplibrary.IPItem{
   136  		Id:     3,
   137  		IPFrom: iputils.ToBytes("192.168.0.1"),
   138  		IPTo:   iputils.ToBytes("192.168.0.2"),
   139  	})
   140  
   141  	a.IsTrue(len(ipList.SortedRangeItems()) == 2)
   142  
   143  	t.Log(len(ipList.ItemsMap()), "ips")
   144  	t.Log("===items map===")
   145  	logs.PrintAsJSON(ipList.ItemsMap(), t)
   146  	t.Log("===sorted range items===")
   147  	logs.PrintAsJSON(ipList.SortedRangeItems())
   148  	t.Log("===all items map===")
   149  	logs.PrintAsJSON(ipList.AllItemsMap(), t)
   150  
   151  	t.Log("===ip map===")
   152  	logs.PrintAsJSON(ipList.IPMap(), t)
   153  }
   154  
   155  func TestNewIPList_Memory(t *testing.T) {
   156  	var list = iplibrary.NewIPList()
   157  
   158  	var count = 100
   159  	if testutils.IsSingleTesting() {
   160  		count = 2_000_000
   161  	}
   162  	var stat1 = testutils.ReadMemoryStat()
   163  
   164  	for i := 0; i < count; i++ {
   165  		list.AddDelay(&iplibrary.IPItem{
   166  			Id:        uint64(i),
   167  			IPFrom:    iputils.ToBytes(testutils.RandIP()),
   168  			IPTo:      iputils.ToBytes(testutils.RandIP()),
   169  			ExpiredAt: time.Now().Unix(),
   170  		})
   171  	}
   172  
   173  	list.Sort()
   174  
   175  	runtime.GC()
   176  
   177  	var stat2 = testutils.ReadMemoryStat()
   178  	t.Log((stat2.HeapInuse-stat1.HeapInuse)>>20, "MB")
   179  }
   180  
   181  func TestIPList_Contains(t *testing.T) {
   182  	var a = assert.NewAssertion(t)
   183  
   184  	var list = iplibrary.NewIPList()
   185  	for i := 0; i < 255; i++ {
   186  		list.Add(&iplibrary.IPItem{
   187  			Id:        uint64(i),
   188  			IPFrom:    iputils.ToBytes(strconv.Itoa(i) + ".168.0.1"),
   189  			IPTo:      iputils.ToBytes(strconv.Itoa(i) + ".168.255.1"),
   190  			ExpiredAt: 0,
   191  		})
   192  	}
   193  	for i := 0; i < 255; i++ {
   194  		list.Add(&iplibrary.IPItem{
   195  			Id:     uint64(1000 + i),
   196  			IPFrom: iputils.ToBytes("192.167.2." + strconv.Itoa(i)),
   197  		})
   198  	}
   199  
   200  	list.Add(&iplibrary.IPItem{
   201  		Id:     10000,
   202  		IPFrom: iputils.ToBytes("::1"),
   203  	})
   204  	list.Add(&iplibrary.IPItem{
   205  		Id:     10001,
   206  		IPFrom: iputils.ToBytes("::2"),
   207  		IPTo:   iputils.ToBytes("::5"),
   208  	})
   209  
   210  	t.Log(len(list.ItemsMap()), "ip")
   211  
   212  	var before = time.Now()
   213  	a.IsTrue(list.Contains(iputils.ToBytes("192.168.1.100")))
   214  	a.IsTrue(list.Contains(iputils.ToBytes("192.168.2.100")))
   215  	a.IsFalse(list.Contains(iputils.ToBytes("192.169.3.100")))
   216  	a.IsFalse(list.Contains(iputils.ToBytes("192.167.3.100")))
   217  	a.IsTrue(list.Contains(iputils.ToBytes("192.167.2.100")))
   218  	a.IsTrue(list.Contains(iputils.ToBytes("::1")))
   219  	a.IsTrue(list.Contains(iputils.ToBytes("::3")))
   220  	a.IsFalse(list.Contains(iputils.ToBytes("::8")))
   221  	t.Log(time.Since(before).Seconds()*1000, "ms")
   222  }
   223  
   224  func TestIPList_Contains_Many(t *testing.T) {
   225  	var list = iplibrary.NewIPList()
   226  	for i := 0; i < 1_000_000; i++ {
   227  		list.AddDelay(&iplibrary.IPItem{
   228  			Id:        uint64(i),
   229  			IPFrom:    iputils.ToBytes(strconv.Itoa(rands.Int(0, 255)) + "." + strconv.Itoa(rands.Int(0, 255)) + "." + strconv.Itoa(rands.Int(0, 255)) + "." + strconv.Itoa(rands.Int(0, 255))),
   230  			IPTo:      iputils.ToBytes(strconv.Itoa(rands.Int(0, 255)) + "." + strconv.Itoa(rands.Int(0, 255)) + "." + strconv.Itoa(rands.Int(0, 255)) + "." + strconv.Itoa(rands.Int(0, 255))),
   231  			ExpiredAt: 0,
   232  		})
   233  	}
   234  
   235  	var before = time.Now()
   236  	list.Sort()
   237  	t.Log("sort cost:", time.Since(before).Seconds()*1000, "ms")
   238  	t.Log(len(list.ItemsMap()), "ip")
   239  
   240  	before = time.Now()
   241  	_ = list.Contains(iputils.ToBytes("192.168.1.100"))
   242  	t.Log("contains cost:", time.Since(before).Seconds()*1000, "ms")
   243  }
   244  
   245  func TestIPList_ContainsAll(t *testing.T) {
   246  	var a = assert.NewAssertion(t)
   247  
   248  	{
   249  		var list = iplibrary.NewIPList()
   250  		list.Add(&iplibrary.IPItem{
   251  			Id:     1,
   252  			Type:   "all",
   253  			IPFrom: nil,
   254  		})
   255  		var b = list.Contains(iputils.ToBytes("192.168.1.1"))
   256  		a.IsTrue(b)
   257  
   258  		list.Delete(1)
   259  
   260  		b = list.Contains(iputils.ToBytes("192.168.1.1"))
   261  		a.IsFalse(b)
   262  	}
   263  
   264  	{
   265  		var list = iplibrary.NewIPList()
   266  		list.Add(&iplibrary.IPItem{
   267  			Id:     1,
   268  			Type:   "all",
   269  			IPFrom: iputils.ToBytes("0.0.0.0"),
   270  		})
   271  		var b = list.Contains(iputils.ToBytes("192.168.1.1"))
   272  		a.IsTrue(b)
   273  
   274  		list.Delete(1)
   275  
   276  		b = list.Contains(iputils.ToBytes("192.168.1.1"))
   277  		a.IsFalse(b)
   278  	}
   279  }
   280  
   281  func TestIPList_ContainsIPStrings(t *testing.T) {
   282  	var a = assert.NewAssertion(t)
   283  
   284  	var list = iplibrary.NewIPList()
   285  	for i := 0; i < 255; i++ {
   286  		list.Add(&iplibrary.IPItem{
   287  			Id:        uint64(i),
   288  			IPFrom:    iputils.ToBytes(strconv.Itoa(i) + ".168.0.1"),
   289  			IPTo:      iputils.ToBytes(strconv.Itoa(i) + ".168.255.1"),
   290  			ExpiredAt: 0,
   291  		})
   292  	}
   293  	t.Log(len(list.ItemsMap()), "ip")
   294  
   295  	{
   296  		item, ok := list.ContainsIPStrings([]string{"192.168.1.100"})
   297  		t.Log("item:", item)
   298  		a.IsTrue(ok)
   299  	}
   300  	{
   301  		item, ok := list.ContainsIPStrings([]string{"192.167.1.100"})
   302  		t.Log("item:", item)
   303  		a.IsFalse(ok)
   304  	}
   305  }
   306  
   307  func TestIPList_Delete(t *testing.T) {
   308  	var list = iplibrary.NewIPList()
   309  	list.Add(&iplibrary.IPItem{
   310  		Id:        1,
   311  		IPFrom:    iputils.ToBytes("192.168.0.1"),
   312  		ExpiredAt: 0,
   313  	})
   314  	list.Add(&iplibrary.IPItem{
   315  		Id:        2,
   316  		IPFrom:    iputils.ToBytes("192.168.0.1"),
   317  		ExpiredAt: 0,
   318  	})
   319  	list.Add(&iplibrary.IPItem{
   320  		Id:        3,
   321  		IPFrom:    iputils.ToBytes("192.168.1.1"),
   322  		IPTo:      iputils.ToBytes("192.168.2.1"),
   323  		ExpiredAt: 0,
   324  	})
   325  	t.Log("===before===")
   326  	logs.PrintAsJSON(list.ItemsMap(), t)
   327  	logs.PrintAsJSON(list.AllItemsMap(), t)
   328  	logs.PrintAsJSON(list.SortedRangeItems())
   329  	logs.PrintAsJSON(list.IPMap(), t)
   330  
   331  	{
   332  		var found bool
   333  		for _, item := range list.SortedRangeItems() {
   334  			if item.Id == 3 {
   335  				found = true
   336  				break
   337  			}
   338  		}
   339  		if !found {
   340  			t.Fatal("should be found")
   341  		}
   342  	}
   343  
   344  	list.Delete(1)
   345  
   346  	t.Log("===after===")
   347  	logs.PrintAsJSON(list.ItemsMap(), t)
   348  	logs.PrintAsJSON(list.AllItemsMap(), t)
   349  	logs.PrintAsJSON(list.SortedRangeItems())
   350  	logs.PrintAsJSON(list.IPMap(), t)
   351  
   352  	list.Delete(3)
   353  
   354  	{
   355  		var found bool
   356  		for _, item := range list.SortedRangeItems() {
   357  			if item.Id == 3 {
   358  				found = true
   359  				break
   360  			}
   361  		}
   362  		if found {
   363  			t.Fatal("should be not found")
   364  		}
   365  	}
   366  }
   367  
   368  func TestIPList_GC(t *testing.T) {
   369  	var a = assert.NewAssertion(t)
   370  
   371  	var list = iplibrary.NewIPList()
   372  	list.Add(&iplibrary.IPItem{
   373  		Id:        1,
   374  		IPFrom:    iputils.ToBytes("192.168.1.100"),
   375  		IPTo:      iputils.ToBytes("192.168.1.101"),
   376  		ExpiredAt: time.Now().Unix() + 1,
   377  	})
   378  	list.Add(&iplibrary.IPItem{
   379  		Id:        2,
   380  		IPFrom:    iputils.ToBytes("192.168.1.102"),
   381  		IPTo:      iputils.ToBytes("192.168.1.103"),
   382  		ExpiredAt: 0,
   383  	})
   384  	logs.PrintAsJSON(list.ItemsMap(), t)
   385  	logs.PrintAsJSON(list.AllItemsMap(), t)
   386  
   387  	time.Sleep(3 * time.Second)
   388  
   389  	t.Log("===AFTER GC===")
   390  	logs.PrintAsJSON(list.ItemsMap(), t)
   391  	logs.PrintAsJSON(list.SortedRangeItems(), t)
   392  
   393  	a.IsTrue(len(list.ItemsMap()) == 1)
   394  	a.IsTrue(len(list.SortedRangeItems()) == 1)
   395  }
   396  
   397  func TestManyLists(t *testing.T) {
   398  	debug.SetMaxThreads(20)
   399  
   400  	var lists = []*iplibrary.IPList{}
   401  	var locker = &sync.Mutex{}
   402  	for i := 0; i < 1000; i++ {
   403  		locker.Lock()
   404  		lists = append(lists, iplibrary.NewIPList())
   405  		locker.Unlock()
   406  	}
   407  
   408  	if testutils.IsSingleTesting() {
   409  		time.Sleep(3 * time.Second)
   410  	}
   411  	t.Log(runtime.NumGoroutine())
   412  	t.Log(len(lists), "lists")
   413  }
   414  
   415  func BenchmarkIPList_Add(b *testing.B) {
   416  	runtime.GOMAXPROCS(1)
   417  
   418  	var list = iplibrary.NewIPList()
   419  	for i := 1; i < 200_000; i++ {
   420  		list.AddDelay(&iplibrary.IPItem{
   421  			Id:        uint64(i),
   422  			IPFrom:    iputils.ToBytes(strconv.Itoa(rands.Int(0, 255)) + "." + strconv.Itoa(rands.Int(0, 255)) + ".0.1"),
   423  			IPTo:      iputils.ToBytes(strconv.Itoa(rands.Int(0, 255)) + "." + strconv.Itoa(rands.Int(0, 255)) + ".0.1"),
   424  			ExpiredAt: time.Now().Unix() + 60,
   425  		})
   426  	}
   427  
   428  	list.Sort()
   429  
   430  	b.Log(len(list.ItemsMap()), "ip")
   431  
   432  	b.ResetTimer()
   433  
   434  	for i := 0; i < b.N; i++ {
   435  		var ip = fmt.Sprintf("%d.%d.%d.%d", rand.Int()%255, rand.Int()%255, rand.Int()%255, rand.Int()%255)
   436  		list.Add(&iplibrary.IPItem{
   437  			Type:       "",
   438  			Id:         uint64(i % 1_000_000),
   439  			IPFrom:     iputils.ToBytes(ip),
   440  			IPTo:       nil,
   441  			ExpiredAt:  fasttime.Now().Unix() + 3600,
   442  			EventLevel: "",
   443  		})
   444  	}
   445  }
   446  
   447  func BenchmarkIPList_Contains(b *testing.B) {
   448  	runtime.GOMAXPROCS(1)
   449  
   450  	var list = iplibrary.NewIPList()
   451  	for i := 1; i < 1_000_000; i++ {
   452  		var item = &iplibrary.IPItem{
   453  			Id:        uint64(i),
   454  			IPFrom:    iputils.ToBytes(strconv.Itoa(rands.Int(0, 255)) + "." + strconv.Itoa(rands.Int(0, 255)) + ".0.1"),
   455  			ExpiredAt: time.Now().Unix() + 60,
   456  		}
   457  		if i%100 == 0 {
   458  			item.IPTo = iputils.ToBytes(strconv.Itoa(rands.Int(0, 255)) + "." + strconv.Itoa(rands.Int(0, 255)) + ".0.1")
   459  		}
   460  		list.Add(item)
   461  	}
   462  
   463  	//b.Log(len(list.ItemsMap()), "ip")
   464  
   465  	b.ResetTimer()
   466  	b.RunParallel(func(pb *testing.PB) {
   467  		for pb.Next() {
   468  			_ = list.Contains(iputils.ToBytes(testutils.RandIP()))
   469  		}
   470  	})
   471  }
   472  
   473  func BenchmarkIPList_Sort(b *testing.B) {
   474  	var list = iplibrary.NewIPList()
   475  	for i := 0; i < 1_000_000; i++ {
   476  		var item = &iplibrary.IPItem{
   477  			Id:        uint64(i),
   478  			IPFrom:    iputils.ToBytes(strconv.Itoa(rands.Int(0, 255)) + "." + strconv.Itoa(rands.Int(0, 255)) + ".0.1"),
   479  			ExpiredAt: time.Now().Unix() + 60,
   480  		}
   481  
   482  		if i%100 == 0 {
   483  			item.IPTo = iputils.ToBytes(strconv.Itoa(rands.Int(0, 255)) + "." + strconv.Itoa(rands.Int(0, 255)) + ".0.1")
   484  		}
   485  
   486  		list.AddDelay(item)
   487  	}
   488  
   489  	b.ResetTimer()
   490  	b.RunParallel(func(pb *testing.PB) {
   491  		for pb.Next() {
   492  			list.Sort()
   493  		}
   494  	})
   495  }