github.com/xmplusdev/xmcore@v1.8.11-0.20240412132628-5518b55526af/app/router/condition_geoip_test.go (about) 1 package router_test 2 3 import ( 4 "os" 5 "path/filepath" 6 "testing" 7 8 "github.com/xmplusdev/xmcore/app/router" 9 "github.com/xmplusdev/xmcore/common" 10 "github.com/xmplusdev/xmcore/common/net" 11 "github.com/xmplusdev/xmcore/common/platform" 12 "github.com/xmplusdev/xmcore/common/platform/filesystem" 13 "google.golang.org/protobuf/proto" 14 ) 15 16 func init() { 17 wd, err := os.Getwd() 18 common.Must(err) 19 20 if _, err := os.Stat(platform.GetAssetLocation("geoip.dat")); err != nil && os.IsNotExist(err) { 21 common.Must(filesystem.CopyFile(platform.GetAssetLocation("geoip.dat"), filepath.Join(wd, "..", "..", "resources", "geoip.dat"))) 22 } 23 if _, err := os.Stat(platform.GetAssetLocation("geosite.dat")); err != nil && os.IsNotExist(err) { 24 common.Must(filesystem.CopyFile(platform.GetAssetLocation("geosite.dat"), filepath.Join(wd, "..", "..", "resources", "geosite.dat"))) 25 } 26 } 27 28 func TestGeoIPMatcherContainer(t *testing.T) { 29 container := &router.GeoIPMatcherContainer{} 30 31 m1, err := container.Add(&router.GeoIP{ 32 CountryCode: "CN", 33 }) 34 common.Must(err) 35 36 m2, err := container.Add(&router.GeoIP{ 37 CountryCode: "US", 38 }) 39 common.Must(err) 40 41 m3, err := container.Add(&router.GeoIP{ 42 CountryCode: "CN", 43 }) 44 common.Must(err) 45 46 if m1 != m3 { 47 t.Error("expect same matcher for same geoip, but not") 48 } 49 50 if m1 == m2 { 51 t.Error("expect different matcher for different geoip, but actually same") 52 } 53 } 54 55 func TestGeoIPMatcher(t *testing.T) { 56 cidrList := []*router.CIDR{ 57 {Ip: []byte{0, 0, 0, 0}, Prefix: 8}, 58 {Ip: []byte{10, 0, 0, 0}, Prefix: 8}, 59 {Ip: []byte{100, 64, 0, 0}, Prefix: 10}, 60 {Ip: []byte{127, 0, 0, 0}, Prefix: 8}, 61 {Ip: []byte{169, 254, 0, 0}, Prefix: 16}, 62 {Ip: []byte{172, 16, 0, 0}, Prefix: 12}, 63 {Ip: []byte{192, 0, 0, 0}, Prefix: 24}, 64 {Ip: []byte{192, 0, 2, 0}, Prefix: 24}, 65 {Ip: []byte{192, 168, 0, 0}, Prefix: 16}, 66 {Ip: []byte{192, 18, 0, 0}, Prefix: 15}, 67 {Ip: []byte{198, 51, 100, 0}, Prefix: 24}, 68 {Ip: []byte{203, 0, 113, 0}, Prefix: 24}, 69 {Ip: []byte{8, 8, 8, 8}, Prefix: 32}, 70 {Ip: []byte{91, 108, 4, 0}, Prefix: 16}, 71 } 72 73 matcher := &router.GeoIPMatcher{} 74 common.Must(matcher.Init(cidrList)) 75 76 testCases := []struct { 77 Input string 78 Output bool 79 }{ 80 { 81 Input: "192.168.1.1", 82 Output: true, 83 }, 84 { 85 Input: "192.0.0.0", 86 Output: true, 87 }, 88 { 89 Input: "192.0.1.0", 90 Output: false, 91 }, 92 { 93 Input: "0.1.0.0", 94 Output: true, 95 }, 96 { 97 Input: "1.0.0.1", 98 Output: false, 99 }, 100 { 101 Input: "8.8.8.7", 102 Output: false, 103 }, 104 { 105 Input: "8.8.8.8", 106 Output: true, 107 }, 108 { 109 Input: "2001:cdba::3257:9652", 110 Output: false, 111 }, 112 { 113 Input: "91.108.255.254", 114 Output: true, 115 }, 116 } 117 118 for _, testCase := range testCases { 119 ip := net.ParseAddress(testCase.Input).IP() 120 actual := matcher.Match(ip) 121 if actual != testCase.Output { 122 t.Error("expect input", testCase.Input, "to be", testCase.Output, ", but actually", actual) 123 } 124 } 125 } 126 127 func TestGeoIPMatcherRegression(t *testing.T) { 128 cidrList := []*router.CIDR{ 129 {Ip: []byte{98, 108, 20, 0}, Prefix: 22}, 130 {Ip: []byte{98, 108, 20, 0}, Prefix: 23}, 131 } 132 133 matcher := &router.GeoIPMatcher{} 134 common.Must(matcher.Init(cidrList)) 135 136 testCases := []struct { 137 Input string 138 Output bool 139 }{ 140 { 141 Input: "98.108.22.11", 142 Output: true, 143 }, 144 { 145 Input: "98.108.25.0", 146 Output: false, 147 }, 148 } 149 150 for _, testCase := range testCases { 151 ip := net.ParseAddress(testCase.Input).IP() 152 actual := matcher.Match(ip) 153 if actual != testCase.Output { 154 t.Error("expect input", testCase.Input, "to be", testCase.Output, ", but actually", actual) 155 } 156 } 157 } 158 159 func TestGeoIPReverseMatcher(t *testing.T) { 160 cidrList := []*router.CIDR{ 161 {Ip: []byte{8, 8, 8, 8}, Prefix: 32}, 162 {Ip: []byte{91, 108, 4, 0}, Prefix: 16}, 163 } 164 matcher := &router.GeoIPMatcher{} 165 matcher.SetReverseMatch(true) // Reverse match 166 common.Must(matcher.Init(cidrList)) 167 168 testCases := []struct { 169 Input string 170 Output bool 171 }{ 172 { 173 Input: "8.8.8.8", 174 Output: false, 175 }, 176 { 177 Input: "2001:cdba::3257:9652", 178 Output: true, 179 }, 180 { 181 Input: "91.108.255.254", 182 Output: false, 183 }, 184 } 185 186 for _, testCase := range testCases { 187 ip := net.ParseAddress(testCase.Input).IP() 188 actual := matcher.Match(ip) 189 if actual != testCase.Output { 190 t.Error("expect input", testCase.Input, "to be", testCase.Output, ", but actually", actual) 191 } 192 } 193 } 194 195 func TestGeoIPMatcher4CN(t *testing.T) { 196 ips, err := loadGeoIP("CN") 197 common.Must(err) 198 199 matcher := &router.GeoIPMatcher{} 200 common.Must(matcher.Init(ips)) 201 202 if matcher.Match([]byte{8, 8, 8, 8}) { 203 t.Error("expect CN geoip doesn't contain 8.8.8.8, but actually does") 204 } 205 } 206 207 func TestGeoIPMatcher6US(t *testing.T) { 208 ips, err := loadGeoIP("US") 209 common.Must(err) 210 211 matcher := &router.GeoIPMatcher{} 212 common.Must(matcher.Init(ips)) 213 214 if !matcher.Match(net.ParseAddress("2001:4860:4860::8888").IP()) { 215 t.Error("expect US geoip contain 2001:4860:4860::8888, but actually not") 216 } 217 } 218 219 func loadGeoIP(country string) ([]*router.CIDR, error) { 220 geoipBytes, err := filesystem.ReadAsset("geoip.dat") 221 if err != nil { 222 return nil, err 223 } 224 var geoipList router.GeoIPList 225 if err := proto.Unmarshal(geoipBytes, &geoipList); err != nil { 226 return nil, err 227 } 228 229 for _, geoip := range geoipList.Entry { 230 if geoip.CountryCode == country { 231 return geoip.Cidr, nil 232 } 233 } 234 235 panic("country not found: " + country) 236 } 237 238 func BenchmarkGeoIPMatcher4CN(b *testing.B) { 239 ips, err := loadGeoIP("CN") 240 common.Must(err) 241 242 matcher := &router.GeoIPMatcher{} 243 common.Must(matcher.Init(ips)) 244 245 b.ResetTimer() 246 247 for i := 0; i < b.N; i++ { 248 _ = matcher.Match([]byte{8, 8, 8, 8}) 249 } 250 } 251 252 func BenchmarkGeoIPMatcher6US(b *testing.B) { 253 ips, err := loadGeoIP("US") 254 common.Must(err) 255 256 matcher := &router.GeoIPMatcher{} 257 common.Must(matcher.Init(ips)) 258 259 b.ResetTimer() 260 261 for i := 0; i < b.N; i++ { 262 _ = matcher.Match(net.ParseAddress("2001:4860:4860::8888").IP()) 263 } 264 }