subnet_test.go 3.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126
  1. /*
  2. * Copyright (c) 2016, Psiphon Inc.
  3. * All rights reserved.
  4. *
  5. * This program is free software: you can redistribute it and/or modify
  6. * it under the terms of the GNU General Public License as published by
  7. * the Free Software Foundation, either version 3 of the License, or
  8. * (at your option) any later version.
  9. *
  10. * This program is distributed in the hope that it will be useful,
  11. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  12. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  13. * GNU General Public License for more details.
  14. *
  15. * You should have received a copy of the GNU General Public License
  16. * along with this program. If not, see <http://www.gnu.org/licenses/>.
  17. *
  18. */
  19. package common
  20. import (
  21. "encoding/binary"
  22. "io/ioutil"
  23. "math/rand"
  24. "net"
  25. "testing"
  26. )
  27. func TestSubnetLookup(t *testing.T) {
  28. CIDRs := []string{
  29. "192.168.0.0/16",
  30. "10.0.0.0/8",
  31. "172.16.0.0/12",
  32. "100.64.0.0/10"}
  33. routes := []byte("192.168.0.0\t255.255.0.0\n10.0.0.0\t255.0.0.0\n" +
  34. "172.16.0.0\t255.240.0.0\n100.64.0.0\t255.192.0.0\n")
  35. var subnetLookup SubnetLookup
  36. t.Run("new subnet lookup", func(t *testing.T) {
  37. var err error
  38. subnetLookup, err = NewSubnetLookup(CIDRs)
  39. if err != nil {
  40. t.Fatalf("NewSubnetLookup failed: %s", err)
  41. }
  42. })
  43. var subnetLookupRoutes SubnetLookup
  44. t.Run("new subnet lookup (routes case)", func(t *testing.T) {
  45. var err error
  46. subnetLookupRoutes, err = NewSubnetLookupFromRoutes(routes)
  47. if err != nil {
  48. t.Fatalf("NewSubnetLookupFromRoutes failed: %s", err)
  49. }
  50. })
  51. if subnetLookup == nil || subnetLookupRoutes == nil {
  52. t.Fatalf("new subnet list failed")
  53. }
  54. testCases := []struct {
  55. description string
  56. ipAddress net.IP
  57. expectedResult bool
  58. }{
  59. {"IP address in subnet", net.ParseIP("172.17.3.2"), true},
  60. {"IP address not in subnet", net.ParseIP("169.254.1.1"), false},
  61. {"IP address not in subnet (prefix case)", net.ParseIP("172.15.3.2"), false},
  62. }
  63. for _, testCase := range testCases {
  64. t.Run(testCase.description, func(t *testing.T) {
  65. result := subnetLookup.ContainsIPAddress(testCase.ipAddress)
  66. if result != testCase.expectedResult {
  67. t.Fatalf(
  68. "ContainsIPAddress returned %+v expected %+v",
  69. result, testCase.expectedResult)
  70. }
  71. result = subnetLookupRoutes.ContainsIPAddress(testCase.ipAddress)
  72. if result != testCase.expectedResult {
  73. t.Fatalf(
  74. "ContainsIPAddress (routes case) returned %+v expected %+v",
  75. result, testCase.expectedResult)
  76. }
  77. })
  78. }
  79. }
  80. func BenchmarkSubnetLookup(b *testing.B) {
  81. var subnetLookup SubnetLookup
  82. b.Run("load routes file", func(b *testing.B) {
  83. routesData, err := ioutil.ReadFile("test_routes.dat")
  84. if err != nil {
  85. b.Skipf("can't load test routes file: %s", err)
  86. }
  87. for n := 0; n < b.N; n++ {
  88. subnetLookup, err = NewSubnetLookupFromRoutes(routesData)
  89. if err != nil {
  90. b.Fatalf("NewSubnetLookup failed: %s", err)
  91. }
  92. }
  93. })
  94. if subnetLookup == nil {
  95. b.Skipf("no test routes file")
  96. }
  97. b.Run("lookup random IP address", func(b *testing.B) {
  98. for n := 0; n < b.N; n++ {
  99. ip := make([]byte, 4)
  100. binary.BigEndian.PutUint32(ip, rand.Uint32())
  101. _ = subnetLookup.ContainsIPAddress(net.IP(ip))
  102. }
  103. })
  104. }