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  }