github.com/chwjbn/xclash@v0.2.0/component/fakeip/pool_test.go (about) 1 package fakeip 2 3 import ( 4 "fmt" 5 "net" 6 "os" 7 "testing" 8 "time" 9 10 "github.com/chwjbn/xclash/component/profile/cachefile" 11 "github.com/chwjbn/xclash/component/trie" 12 13 "github.com/stretchr/testify/assert" 14 "go.etcd.io/bbolt" 15 ) 16 17 func createPools(options Options) ([]*Pool, string, error) { 18 pool, err := New(options) 19 if err != nil { 20 return nil, "", err 21 } 22 filePool, tempfile, err := createCachefileStore(options) 23 if err != nil { 24 return nil, "", err 25 } 26 27 return []*Pool{pool, filePool}, tempfile, nil 28 } 29 30 func createCachefileStore(options Options) (*Pool, string, error) { 31 pool, err := New(options) 32 if err != nil { 33 return nil, "", err 34 } 35 f, err := os.CreateTemp("", "clash") 36 if err != nil { 37 return nil, "", err 38 } 39 40 db, err := bbolt.Open(f.Name(), 0o666, &bbolt.Options{Timeout: time.Second}) 41 if err != nil { 42 return nil, "", err 43 } 44 45 pool.store = &cachefileStore{ 46 cache: &cachefile.CacheFile{DB: db}, 47 } 48 return pool, f.Name(), nil 49 } 50 51 func TestPool_Basic(t *testing.T) { 52 _, ipnet, _ := net.ParseCIDR("192.168.0.1/29") 53 pools, tempfile, err := createPools(Options{ 54 IPNet: ipnet, 55 Size: 10, 56 }) 57 assert.Nil(t, err) 58 defer os.Remove(tempfile) 59 60 for _, pool := range pools { 61 first := pool.Lookup("foo.com") 62 last := pool.Lookup("bar.com") 63 bar, exist := pool.LookBack(last) 64 65 assert.True(t, first.Equal(net.IP{192, 168, 0, 2})) 66 assert.Equal(t, pool.Lookup("foo.com"), net.IP{192, 168, 0, 2}) 67 assert.True(t, last.Equal(net.IP{192, 168, 0, 3})) 68 assert.True(t, exist) 69 assert.Equal(t, bar, "bar.com") 70 assert.Equal(t, pool.Gateway(), net.IP{192, 168, 0, 1}) 71 assert.Equal(t, pool.IPNet().String(), ipnet.String()) 72 assert.True(t, pool.Exist(net.IP{192, 168, 0, 3})) 73 assert.False(t, pool.Exist(net.IP{192, 168, 0, 4})) 74 assert.False(t, pool.Exist(net.ParseIP("::1"))) 75 } 76 } 77 78 func TestPool_CycleUsed(t *testing.T) { 79 _, ipnet, _ := net.ParseCIDR("192.168.0.1/29") 80 pools, tempfile, err := createPools(Options{ 81 IPNet: ipnet, 82 Size: 10, 83 }) 84 assert.Nil(t, err) 85 defer os.Remove(tempfile) 86 87 for _, pool := range pools { 88 foo := pool.Lookup("foo.com") 89 bar := pool.Lookup("bar.com") 90 for i := 0; i < 3; i++ { 91 pool.Lookup(fmt.Sprintf("%d.com", i)) 92 } 93 baz := pool.Lookup("baz.com") 94 next := pool.Lookup("foo.com") 95 assert.True(t, foo.Equal(baz)) 96 assert.True(t, next.Equal(bar)) 97 } 98 } 99 100 func TestPool_Skip(t *testing.T) { 101 _, ipnet, _ := net.ParseCIDR("192.168.0.1/30") 102 tree := trie.New() 103 tree.Insert("example.com", tree) 104 pools, tempfile, err := createPools(Options{ 105 IPNet: ipnet, 106 Size: 10, 107 Host: tree, 108 }) 109 assert.Nil(t, err) 110 defer os.Remove(tempfile) 111 112 for _, pool := range pools { 113 assert.True(t, pool.ShouldSkipped("example.com")) 114 assert.False(t, pool.ShouldSkipped("foo.com")) 115 } 116 } 117 118 func TestPool_MaxCacheSize(t *testing.T) { 119 _, ipnet, _ := net.ParseCIDR("192.168.0.1/24") 120 pool, _ := New(Options{ 121 IPNet: ipnet, 122 Size: 2, 123 }) 124 125 first := pool.Lookup("foo.com") 126 pool.Lookup("bar.com") 127 pool.Lookup("baz.com") 128 next := pool.Lookup("foo.com") 129 130 assert.False(t, first.Equal(next)) 131 } 132 133 func TestPool_DoubleMapping(t *testing.T) { 134 _, ipnet, _ := net.ParseCIDR("192.168.0.1/24") 135 pool, _ := New(Options{ 136 IPNet: ipnet, 137 Size: 2, 138 }) 139 140 // fill cache 141 fooIP := pool.Lookup("foo.com") 142 bazIP := pool.Lookup("baz.com") 143 144 // make foo.com hot 145 pool.Lookup("foo.com") 146 147 // should drop baz.com 148 barIP := pool.Lookup("bar.com") 149 150 _, fooExist := pool.LookBack(fooIP) 151 _, bazExist := pool.LookBack(bazIP) 152 _, barExist := pool.LookBack(barIP) 153 154 newBazIP := pool.Lookup("baz.com") 155 156 assert.True(t, fooExist) 157 assert.False(t, bazExist) 158 assert.True(t, barExist) 159 160 assert.False(t, bazIP.Equal(newBazIP)) 161 } 162 163 func TestPool_Clone(t *testing.T) { 164 _, ipnet, _ := net.ParseCIDR("192.168.0.1/24") 165 pool, _ := New(Options{ 166 IPNet: ipnet, 167 Size: 2, 168 }) 169 170 first := pool.Lookup("foo.com") 171 last := pool.Lookup("bar.com") 172 assert.True(t, first.Equal(net.IP{192, 168, 0, 2})) 173 assert.True(t, last.Equal(net.IP{192, 168, 0, 3})) 174 175 newPool, _ := New(Options{ 176 IPNet: ipnet, 177 Size: 2, 178 }) 179 newPool.CloneFrom(pool) 180 _, firstExist := newPool.LookBack(first) 181 _, lastExist := newPool.LookBack(last) 182 assert.True(t, firstExist) 183 assert.True(t, lastExist) 184 } 185 186 func TestPool_Error(t *testing.T) { 187 _, ipnet, _ := net.ParseCIDR("192.168.0.1/31") 188 _, err := New(Options{ 189 IPNet: ipnet, 190 Size: 10, 191 }) 192 193 assert.Error(t, err) 194 }