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  }