github.com/database64128/shadowsocks-go@v1.10.2-0.20240315062903-143a773533f1/domainset/matcher_suffix_test.go (about)

     1  package domainset
     2  
     3  import (
     4  	"fmt"
     5  	"testing"
     6  )
     7  
     8  const (
     9  	shortDomain  = "localhost"
    10  	mediumDomain = "mirror.pkgbuild.com"
    11  	longDomain   = "cant.come.up.with.a.long.domain.name"
    12  )
    13  
    14  var testSuffixes = [...]string{
    15  	"example.com",
    16  	"github.com",
    17  	"cube64128.xyz",
    18  	"api.ipify.org",
    19  	"api6.ipify.org",
    20  	"archlinux.org",
    21  	"cloudflare.com",
    22  	"localdomain",
    23  }
    24  
    25  func testSuffixMatcher(t *testing.T, m Matcher) {
    26  	testMatcher(t, m, "com", false)
    27  	testMatcher(t, m, "example.com", true)
    28  	testMatcher(t, m, "www.example.com", true)
    29  	testMatcher(t, m, "gobyexample.com", false)
    30  	testMatcher(t, m, "example.org", false)
    31  	testMatcher(t, m, "github.com", true)
    32  	testMatcher(t, m, "api.github.com", true)
    33  	testMatcher(t, m, "raw.githubusercontent.com", false)
    34  	testMatcher(t, m, "github.blog", false)
    35  	testMatcher(t, m, "cube64128.xyz", true)
    36  	testMatcher(t, m, "www.cube64128.xyz", true)
    37  	testMatcher(t, m, "notcube64128.xyz", false)
    38  	testMatcher(t, m, "org", false)
    39  	testMatcher(t, m, "ipify.org", false)
    40  	testMatcher(t, m, "api.ipify.org", true)
    41  	testMatcher(t, m, "api6.ipify.org", true)
    42  	testMatcher(t, m, "api64.ipify.org", false)
    43  	testMatcher(t, m, "www.ipify.org", false)
    44  	testMatcher(t, m, "archlinux.org", true)
    45  	testMatcher(t, m, "aur.archlinux.org", true)
    46  	testMatcher(t, m, "cloudflare", false)
    47  	testMatcher(t, m, "cloudflare.com", true)
    48  	testMatcher(t, m, "dash.cloudflare.com", true)
    49  	testMatcher(t, m, "api.cloudflare.com", true)
    50  	testMatcher(t, m, "localdomain", true)
    51  	testMatcher(t, m, "www.localdomain", true)
    52  }
    53  
    54  func TestSuffixLinearMatcher(t *testing.T) {
    55  	slm := SuffixLinearMatcher(testSuffixes[:])
    56  	testSuffixMatcher(t, &slm)
    57  }
    58  
    59  func TestSuffixMapMatcher(t *testing.T) {
    60  	smm := SuffixMapMatcherFromSlice(testSuffixes[:])
    61  	testSuffixMatcher(t, &smm)
    62  }
    63  
    64  func TestSuffixTrieMatcher(t *testing.T) {
    65  	stm := DomainSuffixTrieFromSlice(testSuffixes[:])
    66  	testSuffixMatcher(t, stm)
    67  }
    68  
    69  func benchmarkSuffixMatcher(b *testing.B, count int, name string, m Matcher) {
    70  	b.Run(fmt.Sprintf("%d/%s/Hit", count, name), func(b *testing.B) {
    71  		for i := range b.N {
    72  			m.Match(testSuffixes[i%count])
    73  		}
    74  	})
    75  	b.Run(fmt.Sprintf("%d/%s/Miss/Short", count, name), func(b *testing.B) {
    76  		for range b.N {
    77  			m.Match(shortDomain)
    78  		}
    79  	})
    80  	b.Run(fmt.Sprintf("%d/%s/Miss/Medium", count, name), func(b *testing.B) {
    81  		for range b.N {
    82  			m.Match(mediumDomain)
    83  		}
    84  	})
    85  	b.Run(fmt.Sprintf("%d/%s/Miss/Long", count, name), func(b *testing.B) {
    86  		for range b.N {
    87  			m.Match(longDomain)
    88  		}
    89  	})
    90  }
    91  
    92  func BenchmarkSuffixMatchers(b *testing.B) {
    93  	for i := len(testSuffixes) / 2; i <= len(testSuffixes); i += 2 {
    94  		slm := SuffixLinearMatcher(testSuffixes[:i])
    95  		smm := SuffixMapMatcherFromSlice(testSuffixes[:i])
    96  		stm := DomainSuffixTrieFromSlice(testSuffixes[:i])
    97  		benchmarkSuffixMatcher(b, i, "Linear", &slm)
    98  		benchmarkSuffixMatcher(b, i, "Map", &smm)
    99  		benchmarkSuffixMatcher(b, i, "Trie", stm)
   100  	}
   101  }