git.sr.ht/~pingoo/stdx@v0.0.0-20240218134121-094174641f6e/mmdb/traverse_test.go (about) 1 package mmdb 2 3 import ( 4 "fmt" 5 "net" 6 "testing" 7 8 "github.com/stretchr/testify/assert" 9 "github.com/stretchr/testify/require" 10 ) 11 12 func TestNetworks(t *testing.T) { 13 for _, recordSize := range []uint{24, 28, 32} { 14 for _, ipVersion := range []uint{4, 6} { 15 fileName := testFile( 16 fmt.Sprintf("MaxMind-DB-test-ipv%d-%d.mmdb", ipVersion, recordSize), 17 ) 18 reader, err := Open(fileName) 19 require.Nil(t, err, "unexpected error while opening database: %v", err) 20 21 n := reader.Networks() 22 for n.Next() { 23 record := struct { 24 IP string `maxminddb:"ip"` 25 }{} 26 network, err := n.Network(&record) 27 assert.Nil(t, err) 28 assert.Equal(t, record.IP, network.IP.String(), 29 "expected %s got %s", record.IP, network.IP.String(), 30 ) 31 } 32 assert.Nil(t, n.Err()) 33 assert.NoError(t, reader.Close()) 34 } 35 } 36 } 37 38 func TestNetworksWithInvalidSearchTree(t *testing.T) { 39 reader, err := Open(testFile("MaxMind-DB-test-broken-search-tree-24.mmdb")) 40 require.Nil(t, err, "unexpected error while opening database: %v", err) 41 42 n := reader.Networks() 43 for n.Next() { 44 var record any 45 _, err := n.Network(&record) 46 assert.Nil(t, err) 47 } 48 assert.NotNil(t, n.Err(), "no error received when traversing an broken search tree") 49 assert.Equal(t, "invalid search tree at 128.128.128.128/32", n.Err().Error()) 50 51 assert.NoError(t, reader.Close()) 52 } 53 54 type networkTest struct { 55 Network string 56 Database string 57 Expected []string 58 Options []NetworksOption 59 } 60 61 var tests = []networkTest{ 62 { 63 Network: "0.0.0.0/0", 64 Database: "ipv4", 65 Expected: []string{ 66 "1.1.1.1/32", 67 "1.1.1.2/31", 68 "1.1.1.4/30", 69 "1.1.1.8/29", 70 "1.1.1.16/28", 71 "1.1.1.32/32", 72 }, 73 }, 74 { 75 Network: "1.1.1.1/30", 76 Database: "ipv4", 77 Expected: []string{ 78 "1.1.1.1/32", 79 "1.1.1.2/31", 80 }, 81 }, 82 { 83 Network: "1.1.1.1/32", 84 Database: "ipv4", 85 Expected: []string{ 86 "1.1.1.1/32", 87 }, 88 }, 89 { 90 Network: "255.255.255.0/24", 91 Database: "ipv4", 92 Expected: []string(nil), 93 }, 94 { 95 Network: "1.1.1.1/32", 96 Database: "mixed", 97 Expected: []string{ 98 "1.1.1.1/32", 99 }, 100 }, 101 { 102 Network: "255.255.255.0/24", 103 Database: "mixed", 104 Expected: []string(nil), 105 }, 106 { 107 Network: "::1:ffff:ffff/128", 108 Database: "ipv6", 109 Expected: []string{ 110 "::1:ffff:ffff/128", 111 }, 112 Options: []NetworksOption{SkipAliasedNetworks}, 113 }, 114 { 115 Network: "::/0", 116 Database: "ipv6", 117 Expected: []string{ 118 "::1:ffff:ffff/128", 119 "::2:0:0/122", 120 "::2:0:40/124", 121 "::2:0:50/125", 122 "::2:0:58/127", 123 }, 124 Options: []NetworksOption{SkipAliasedNetworks}, 125 }, 126 { 127 Network: "::2:0:40/123", 128 Database: "ipv6", 129 Expected: []string{ 130 "::2:0:40/124", 131 "::2:0:50/125", 132 "::2:0:58/127", 133 }, 134 Options: []NetworksOption{SkipAliasedNetworks}, 135 }, 136 { 137 Network: "0:0:0:0:0:ffff:ffff:ff00/120", 138 Database: "ipv6", 139 Expected: []string(nil), 140 }, 141 { 142 Network: "0.0.0.0/0", 143 Database: "mixed", 144 Expected: []string{ 145 "1.1.1.1/32", 146 "1.1.1.2/31", 147 "1.1.1.4/30", 148 "1.1.1.8/29", 149 "1.1.1.16/28", 150 "1.1.1.32/32", 151 }, 152 }, 153 { 154 Network: "0.0.0.0/0", 155 Database: "mixed", 156 Expected: []string{ 157 "1.1.1.1/32", 158 "1.1.1.2/31", 159 "1.1.1.4/30", 160 "1.1.1.8/29", 161 "1.1.1.16/28", 162 "1.1.1.32/32", 163 }, 164 Options: []NetworksOption{SkipAliasedNetworks}, 165 }, 166 { 167 Network: "::/0", 168 Database: "mixed", 169 Expected: []string{ 170 "::101:101/128", 171 "::101:102/127", 172 "::101:104/126", 173 "::101:108/125", 174 "::101:110/124", 175 "::101:120/128", 176 "::1:ffff:ffff/128", 177 "::2:0:0/122", 178 "::2:0:40/124", 179 "::2:0:50/125", 180 "::2:0:58/127", 181 "1.1.1.1/32", 182 "1.1.1.2/31", 183 "1.1.1.4/30", 184 "1.1.1.8/29", 185 "1.1.1.16/28", 186 "1.1.1.32/32", 187 "2001:0:101:101::/64", 188 "2001:0:101:102::/63", 189 "2001:0:101:104::/62", 190 "2001:0:101:108::/61", 191 "2001:0:101:110::/60", 192 "2001:0:101:120::/64", 193 "2002:101:101::/48", 194 "2002:101:102::/47", 195 "2002:101:104::/46", 196 "2002:101:108::/45", 197 "2002:101:110::/44", 198 "2002:101:120::/48", 199 }, 200 }, 201 { 202 Network: "::/0", 203 Database: "mixed", 204 Expected: []string{ 205 "1.1.1.1/32", 206 "1.1.1.2/31", 207 "1.1.1.4/30", 208 "1.1.1.8/29", 209 "1.1.1.16/28", 210 "1.1.1.32/32", 211 "::1:ffff:ffff/128", 212 "::2:0:0/122", 213 "::2:0:40/124", 214 "::2:0:50/125", 215 "::2:0:58/127", 216 }, 217 Options: []NetworksOption{SkipAliasedNetworks}, 218 }, 219 { 220 Network: "1.1.1.16/28", 221 Database: "mixed", 222 Expected: []string{ 223 "1.1.1.16/28", 224 }, 225 }, 226 { 227 Network: "1.1.1.4/30", 228 Database: "ipv4", 229 Expected: []string{ 230 "1.1.1.4/30", 231 }, 232 }, 233 } 234 235 func TestNetworksWithin(t *testing.T) { 236 for _, v := range tests { 237 for _, recordSize := range []uint{24, 28, 32} { 238 fileName := testFile(fmt.Sprintf("MaxMind-DB-test-%s-%d.mmdb", v.Database, recordSize)) 239 reader, err := Open(fileName) 240 require.Nil(t, err, "unexpected error while opening database: %v", err) 241 242 _, network, err := net.ParseCIDR(v.Network) 243 assert.Nil(t, err) 244 n := reader.NetworksWithin(network, v.Options...) 245 var innerIPs []string 246 247 for n.Next() { 248 record := struct { 249 IP string `maxminddb:"ip"` 250 }{} 251 network, err := n.Network(&record) 252 assert.Nil(t, err) 253 innerIPs = append(innerIPs, network.String()) 254 } 255 256 assert.Equal(t, v.Expected, innerIPs) 257 assert.Nil(t, n.Err()) 258 259 assert.NoError(t, reader.Close()) 260 } 261 } 262 } 263 264 var geoipTests = []networkTest{ 265 { 266 Network: "81.2.69.128/26", 267 Database: "GeoIP2-Country-Test.mmdb", 268 Expected: []string{ 269 "81.2.69.142/31", 270 "81.2.69.144/28", 271 "81.2.69.160/27", 272 }, 273 }, 274 } 275 276 func TestGeoIPNetworksWithin(t *testing.T) { 277 for _, v := range geoipTests { 278 fileName := testFile(v.Database) 279 reader, err := Open(fileName) 280 require.Nil(t, err, "unexpected error while opening database: %v", err) 281 282 _, network, err := net.ParseCIDR(v.Network) 283 assert.Nil(t, err) 284 n := reader.NetworksWithin(network) 285 var innerIPs []string 286 287 for n.Next() { 288 record := struct { 289 IP string `maxminddb:"ip"` 290 }{} 291 network, err := n.Network(&record) 292 assert.Nil(t, err) 293 innerIPs = append(innerIPs, network.String()) 294 } 295 296 assert.Equal(t, v.Expected, innerIPs) 297 assert.Nil(t, n.Err()) 298 299 assert.NoError(t, reader.Close()) 300 } 301 }