github.com/hashicorp/terraform-plugin-sdk@v1.17.2/internal/lang/funcs/cidr_test.go (about) 1 package funcs 2 3 import ( 4 "fmt" 5 "testing" 6 7 "github.com/zclconf/go-cty/cty" 8 ) 9 10 func TestCidrHost(t *testing.T) { 11 tests := []struct { 12 Prefix cty.Value 13 Hostnum cty.Value 14 Want cty.Value 15 Err bool 16 }{ 17 { 18 cty.StringVal("192.168.1.0/24"), 19 cty.NumberIntVal(5), 20 cty.StringVal("192.168.1.5"), 21 false, 22 }, 23 { 24 cty.StringVal("192.168.1.0/24"), 25 cty.NumberIntVal(-5), 26 cty.StringVal("192.168.1.251"), 27 false, 28 }, 29 { 30 cty.StringVal("192.168.1.0/24"), 31 cty.NumberIntVal(-256), 32 cty.StringVal("192.168.1.0"), 33 false, 34 }, 35 { 36 cty.StringVal("192.168.1.0/30"), 37 cty.NumberIntVal(255), 38 cty.UnknownVal(cty.String), 39 true, // 255 doesn't fit in two bits 40 }, 41 { 42 cty.StringVal("192.168.1.0/30"), 43 cty.NumberIntVal(-255), 44 cty.UnknownVal(cty.String), 45 true, // 255 doesn't fit in two bits 46 }, 47 { 48 cty.StringVal("not-a-cidr"), 49 cty.NumberIntVal(6), 50 cty.UnknownVal(cty.String), 51 true, // not a valid CIDR mask 52 }, 53 { 54 cty.StringVal("10.256.0.0/8"), 55 cty.NumberIntVal(6), 56 cty.UnknownVal(cty.String), 57 true, // can't have an octet >255 58 }, 59 } 60 61 for _, test := range tests { 62 t.Run(fmt.Sprintf("cidrhost(%#v, %#v)", test.Prefix, test.Hostnum), func(t *testing.T) { 63 got, err := CidrHost(test.Prefix, test.Hostnum) 64 65 if test.Err { 66 if err == nil { 67 t.Fatal("succeeded; want error") 68 } 69 return 70 } else if err != nil { 71 t.Fatalf("unexpected error: %s", err) 72 } 73 74 if !got.RawEquals(test.Want) { 75 t.Errorf("wrong result\ngot: %#v\nwant: %#v", got, test.Want) 76 } 77 }) 78 } 79 } 80 81 func TestCidrNetmask(t *testing.T) { 82 tests := []struct { 83 Prefix cty.Value 84 Want cty.Value 85 Err bool 86 }{ 87 { 88 cty.StringVal("192.168.1.0/24"), 89 cty.StringVal("255.255.255.0"), 90 false, 91 }, 92 { 93 cty.StringVal("192.168.1.0/32"), 94 cty.StringVal("255.255.255.255"), 95 false, 96 }, 97 { 98 cty.StringVal("0.0.0.0/0"), 99 cty.StringVal("0.0.0.0"), 100 false, 101 }, 102 { 103 cty.StringVal("1::/64"), 104 cty.StringVal("ffff:ffff:ffff:ffff::"), 105 false, 106 }, 107 { 108 cty.StringVal("not-a-cidr"), 109 cty.UnknownVal(cty.String), 110 true, // not a valid CIDR mask 111 }, 112 { 113 cty.StringVal("110.256.0.0/8"), 114 cty.UnknownVal(cty.String), 115 true, // can't have an octet >255 116 }, 117 } 118 119 for _, test := range tests { 120 t.Run(fmt.Sprintf("cidrnetmask(%#v)", test.Prefix), func(t *testing.T) { 121 got, err := CidrNetmask(test.Prefix) 122 123 if test.Err { 124 if err == nil { 125 t.Fatal("succeeded; want error") 126 } 127 return 128 } else if err != nil { 129 t.Fatalf("unexpected error: %s", err) 130 } 131 132 if !got.RawEquals(test.Want) { 133 t.Errorf("wrong result\ngot: %#v\nwant: %#v", got, test.Want) 134 } 135 }) 136 } 137 } 138 139 func TestCidrSubnet(t *testing.T) { 140 tests := []struct { 141 Prefix cty.Value 142 Newbits cty.Value 143 Netnum cty.Value 144 Want cty.Value 145 Err bool 146 }{ 147 { 148 cty.StringVal("192.168.2.0/20"), 149 cty.NumberIntVal(4), 150 cty.NumberIntVal(6), 151 cty.StringVal("192.168.6.0/24"), 152 false, 153 }, 154 { 155 cty.StringVal("fe80::/48"), 156 cty.NumberIntVal(16), 157 cty.NumberIntVal(6), 158 cty.StringVal("fe80:0:0:6::/64"), 159 false, 160 }, 161 { // IPv4 address encoded in IPv6 syntax gets normalized 162 cty.StringVal("::ffff:192.168.0.0/112"), 163 cty.NumberIntVal(8), 164 cty.NumberIntVal(6), 165 cty.StringVal("192.168.6.0/24"), 166 false, 167 }, 168 { // not enough bits left 169 cty.StringVal("192.168.0.0/30"), 170 cty.NumberIntVal(4), 171 cty.NumberIntVal(6), 172 cty.UnknownVal(cty.String), 173 true, 174 }, 175 { // can't encode 16 in 2 bits 176 cty.StringVal("192.168.0.0/168"), 177 cty.NumberIntVal(2), 178 cty.NumberIntVal(16), 179 cty.StringVal("fe80:0:0:6::/64"), 180 true, 181 }, 182 { // not a valid CIDR mask 183 cty.StringVal("not-a-cidr"), 184 cty.NumberIntVal(4), 185 cty.NumberIntVal(6), 186 cty.StringVal("fe80:0:0:6::/64"), 187 true, 188 }, 189 { // can't have an octet >255 190 cty.StringVal("10.256.0.0/8"), 191 cty.NumberIntVal(4), 192 cty.NumberIntVal(6), 193 cty.StringVal("fe80:0:0:6::/64"), 194 true, 195 }, 196 } 197 198 for _, test := range tests { 199 t.Run(fmt.Sprintf("cidrsubnet(%#v, %#v, %#v)", test.Prefix, test.Newbits, test.Netnum), func(t *testing.T) { 200 got, err := CidrSubnet(test.Prefix, test.Newbits, test.Netnum) 201 202 if test.Err { 203 if err == nil { 204 t.Fatal("succeeded; want error") 205 } 206 return 207 } else if err != nil { 208 t.Fatalf("unexpected error: %s", err) 209 } 210 211 if !got.RawEquals(test.Want) { 212 t.Errorf("wrong result\ngot: %#v\nwant: %#v", got, test.Want) 213 } 214 }) 215 } 216 } 217 func TestCidrSubnets(t *testing.T) { 218 tests := []struct { 219 Prefix cty.Value 220 Newbits []cty.Value 221 Want cty.Value 222 Err string 223 }{ 224 { 225 cty.StringVal("10.0.0.0/21"), 226 []cty.Value{ 227 cty.NumberIntVal(3), 228 cty.NumberIntVal(3), 229 cty.NumberIntVal(3), 230 cty.NumberIntVal(4), 231 cty.NumberIntVal(4), 232 cty.NumberIntVal(4), 233 cty.NumberIntVal(7), 234 cty.NumberIntVal(7), 235 cty.NumberIntVal(7), 236 }, 237 cty.ListVal([]cty.Value{ 238 cty.StringVal("10.0.0.0/24"), 239 cty.StringVal("10.0.1.0/24"), 240 cty.StringVal("10.0.2.0/24"), 241 cty.StringVal("10.0.3.0/25"), 242 cty.StringVal("10.0.3.128/25"), 243 cty.StringVal("10.0.4.0/25"), 244 cty.StringVal("10.0.4.128/28"), 245 cty.StringVal("10.0.4.144/28"), 246 cty.StringVal("10.0.4.160/28"), 247 }), 248 ``, 249 }, 250 { 251 cty.StringVal("10.0.0.0/30"), 252 []cty.Value{ 253 cty.NumberIntVal(1), 254 cty.NumberIntVal(3), 255 }, 256 cty.UnknownVal(cty.List(cty.String)), 257 `would extend prefix to 33 bits, which is too long for an IPv4 address`, 258 }, 259 { 260 cty.StringVal("10.0.0.0/8"), 261 []cty.Value{ 262 cty.NumberIntVal(1), 263 cty.NumberIntVal(1), 264 cty.NumberIntVal(1), 265 }, 266 cty.UnknownVal(cty.List(cty.String)), 267 `not enough remaining address space for a subnet with a prefix of 9 bits after 10.128.0.0/9`, 268 }, 269 { 270 cty.StringVal("10.0.0.0/8"), 271 []cty.Value{ 272 cty.NumberIntVal(1), 273 cty.NumberIntVal(0), 274 }, 275 cty.UnknownVal(cty.List(cty.String)), 276 `must extend prefix by at least one bit`, 277 }, 278 { 279 cty.StringVal("10.0.0.0/8"), 280 []cty.Value{ 281 cty.NumberIntVal(1), 282 cty.NumberIntVal(-1), 283 }, 284 cty.UnknownVal(cty.List(cty.String)), 285 `must extend prefix by at least one bit`, 286 }, 287 { 288 cty.StringVal("fe80::/48"), 289 []cty.Value{ 290 cty.NumberIntVal(1), 291 cty.NumberIntVal(33), 292 }, 293 cty.UnknownVal(cty.List(cty.String)), 294 `may not extend prefix by more than 32 bits`, 295 }, 296 } 297 298 for _, test := range tests { 299 t.Run(fmt.Sprintf("cidrsubnets(%#v, %#v)", test.Prefix, test.Newbits), func(t *testing.T) { 300 got, err := CidrSubnets(test.Prefix, test.Newbits...) 301 wantErr := test.Err != "" 302 303 if wantErr { 304 if err == nil { 305 t.Fatal("succeeded; want error") 306 } 307 if err.Error() != test.Err { 308 t.Fatalf("wrong error\ngot: %s\nwant: %s", err.Error(), test.Err) 309 } 310 return 311 } else if err != nil { 312 t.Fatalf("unexpected error: %s", err) 313 } 314 315 if !got.RawEquals(test.Want) { 316 t.Errorf("wrong result\ngot: %#v\nwant: %#v", got, test.Want) 317 } 318 }) 319 } 320 }