github.com/graywolf-at-work-2/terraform-vendor@v1.4.5/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 // We inadvertently inherited a pre-Go1.17 standard library quirk 37 // if parsing zero-prefix parts as decimal rather than octal. 38 // Go 1.17 resolved that quirk by making zero-prefix invalid, but 39 // we've preserved our existing behavior for backward compatibility, 40 // on the grounds that these functions are for generating addresses 41 // rather than validating or processing them. We do always generate 42 // a canonical result regardless of the input, though. 43 cty.StringVal("010.001.0.0/24"), 44 cty.NumberIntVal(6), 45 cty.StringVal("10.1.0.6"), 46 false, 47 }, 48 { 49 cty.StringVal("192.168.1.0/30"), 50 cty.NumberIntVal(255), 51 cty.UnknownVal(cty.String), 52 true, // 255 doesn't fit in two bits 53 }, 54 { 55 cty.StringVal("192.168.1.0/30"), 56 cty.NumberIntVal(-255), 57 cty.UnknownVal(cty.String), 58 true, // 255 doesn't fit in two bits 59 }, 60 { 61 cty.StringVal("not-a-cidr"), 62 cty.NumberIntVal(6), 63 cty.UnknownVal(cty.String), 64 true, // not a valid CIDR mask 65 }, 66 { 67 cty.StringVal("10.256.0.0/8"), 68 cty.NumberIntVal(6), 69 cty.UnknownVal(cty.String), 70 true, // can't have an octet >255 71 }, 72 { // fractions are Not Ok 73 cty.StringVal("10.256.0.0/8"), 74 cty.NumberFloatVal(.75), 75 cty.UnknownVal(cty.String), 76 true, 77 }, 78 } 79 80 for _, test := range tests { 81 t.Run(fmt.Sprintf("cidrhost(%#v, %#v)", test.Prefix, test.Hostnum), func(t *testing.T) { 82 got, err := CidrHost(test.Prefix, test.Hostnum) 83 84 if test.Err { 85 if err == nil { 86 t.Fatal("succeeded; want error") 87 } 88 return 89 } else if err != nil { 90 t.Fatalf("unexpected error: %s", err) 91 } 92 93 if !got.RawEquals(test.Want) { 94 t.Errorf("wrong result\ngot: %#v\nwant: %#v", got, test.Want) 95 } 96 }) 97 } 98 } 99 100 func TestCidrNetmask(t *testing.T) { 101 tests := []struct { 102 Prefix cty.Value 103 Want cty.Value 104 Err bool 105 }{ 106 { 107 cty.StringVal("192.168.1.0/24"), 108 cty.StringVal("255.255.255.0"), 109 false, 110 }, 111 { 112 cty.StringVal("192.168.1.0/32"), 113 cty.StringVal("255.255.255.255"), 114 false, 115 }, 116 { 117 cty.StringVal("0.0.0.0/0"), 118 cty.StringVal("0.0.0.0"), 119 false, 120 }, 121 { 122 // We inadvertently inherited a pre-Go1.17 standard library quirk 123 // if parsing zero-prefix parts as decimal rather than octal. 124 // Go 1.17 resolved that quirk by making zero-prefix invalid, but 125 // we've preserved our existing behavior for backward compatibility, 126 // on the grounds that these functions are for generating addresses 127 // rather than validating or processing them. 128 cty.StringVal("010.001.0.0/24"), 129 cty.StringVal("255.255.255.0"), 130 false, 131 }, 132 { 133 cty.StringVal("not-a-cidr"), 134 cty.UnknownVal(cty.String), 135 true, // not a valid CIDR mask 136 }, 137 { 138 cty.StringVal("110.256.0.0/8"), 139 cty.UnknownVal(cty.String), 140 true, // can't have an octet >255 141 }, 142 { 143 cty.StringVal("1::/64"), 144 cty.UnknownVal(cty.String), 145 true, // IPv6 is invalid 146 }, 147 } 148 149 for _, test := range tests { 150 t.Run(fmt.Sprintf("cidrnetmask(%#v)", test.Prefix), func(t *testing.T) { 151 got, err := CidrNetmask(test.Prefix) 152 153 if test.Err { 154 if err == nil { 155 t.Fatal("succeeded; want error") 156 } 157 return 158 } else if err != nil { 159 t.Fatalf("unexpected error: %s", err) 160 } 161 162 if !got.RawEquals(test.Want) { 163 t.Errorf("wrong result\ngot: %#v\nwant: %#v", got, test.Want) 164 } 165 }) 166 } 167 } 168 169 func TestCidrSubnet(t *testing.T) { 170 tests := []struct { 171 Prefix cty.Value 172 Newbits cty.Value 173 Netnum cty.Value 174 Want cty.Value 175 Err bool 176 }{ 177 { 178 cty.StringVal("192.168.2.0/20"), 179 cty.NumberIntVal(4), 180 cty.NumberIntVal(6), 181 cty.StringVal("192.168.6.0/24"), 182 false, 183 }, 184 { 185 cty.StringVal("fe80::/48"), 186 cty.NumberIntVal(16), 187 cty.NumberIntVal(6), 188 cty.StringVal("fe80:0:0:6::/64"), 189 false, 190 }, 191 { // IPv4 address encoded in IPv6 syntax gets normalized 192 cty.StringVal("::ffff:192.168.0.0/112"), 193 cty.NumberIntVal(8), 194 cty.NumberIntVal(6), 195 cty.StringVal("192.168.6.0/24"), 196 false, 197 }, 198 { 199 cty.StringVal("fe80::/48"), 200 cty.NumberIntVal(33), 201 cty.NumberIntVal(6), 202 cty.StringVal("fe80::3:0:0:0/81"), 203 false, 204 }, 205 { 206 // We inadvertently inherited a pre-Go1.17 standard library quirk 207 // if parsing zero-prefix parts as decimal rather than octal. 208 // Go 1.17 resolved that quirk by making zero-prefix invalid, but 209 // we've preserved our existing behavior for backward compatibility, 210 // on the grounds that these functions are for generating addresses 211 // rather than validating or processing them. We do always generate 212 // a canonical result regardless of the input, though. 213 cty.StringVal("010.001.0.0/24"), 214 cty.NumberIntVal(4), 215 cty.NumberIntVal(1), 216 cty.StringVal("10.1.0.16/28"), 217 false, 218 }, 219 { // not enough bits left 220 cty.StringVal("192.168.0.0/30"), 221 cty.NumberIntVal(4), 222 cty.NumberIntVal(6), 223 cty.UnknownVal(cty.String), 224 true, 225 }, 226 { // can't encode 16 in 2 bits 227 cty.StringVal("192.168.0.0/168"), 228 cty.NumberIntVal(2), 229 cty.NumberIntVal(16), 230 cty.UnknownVal(cty.String), 231 true, 232 }, 233 { // not a valid CIDR mask 234 cty.StringVal("not-a-cidr"), 235 cty.NumberIntVal(4), 236 cty.NumberIntVal(6), 237 cty.UnknownVal(cty.String), 238 true, 239 }, 240 { // can't have an octet >255 241 cty.StringVal("10.256.0.0/8"), 242 cty.NumberIntVal(4), 243 cty.NumberIntVal(6), 244 cty.UnknownVal(cty.String), 245 true, 246 }, 247 { // fractions are Not Ok 248 cty.StringVal("10.256.0.0/8"), 249 cty.NumberFloatVal(2.0 / 3.0), 250 cty.NumberFloatVal(.75), 251 cty.UnknownVal(cty.String), 252 true, 253 }, 254 } 255 256 for _, test := range tests { 257 t.Run(fmt.Sprintf("cidrsubnet(%#v, %#v, %#v)", test.Prefix, test.Newbits, test.Netnum), func(t *testing.T) { 258 got, err := CidrSubnet(test.Prefix, test.Newbits, test.Netnum) 259 260 if test.Err { 261 if err == nil { 262 t.Fatal("succeeded; want error") 263 } 264 return 265 } else if err != nil { 266 t.Fatalf("unexpected error: %s", err) 267 } 268 269 if !got.RawEquals(test.Want) { 270 t.Errorf("wrong result\ngot: %#v\nwant: %#v", got, test.Want) 271 } 272 }) 273 } 274 } 275 func TestCidrSubnets(t *testing.T) { 276 tests := []struct { 277 Prefix cty.Value 278 Newbits []cty.Value 279 Want cty.Value 280 Err string 281 }{ 282 { 283 cty.StringVal("10.0.0.0/21"), 284 []cty.Value{ 285 cty.NumberIntVal(3), 286 cty.NumberIntVal(3), 287 cty.NumberIntVal(3), 288 cty.NumberIntVal(4), 289 cty.NumberIntVal(4), 290 cty.NumberIntVal(4), 291 cty.NumberIntVal(7), 292 cty.NumberIntVal(7), 293 cty.NumberIntVal(7), 294 }, 295 cty.ListVal([]cty.Value{ 296 cty.StringVal("10.0.0.0/24"), 297 cty.StringVal("10.0.1.0/24"), 298 cty.StringVal("10.0.2.0/24"), 299 cty.StringVal("10.0.3.0/25"), 300 cty.StringVal("10.0.3.128/25"), 301 cty.StringVal("10.0.4.0/25"), 302 cty.StringVal("10.0.4.128/28"), 303 cty.StringVal("10.0.4.144/28"), 304 cty.StringVal("10.0.4.160/28"), 305 }), 306 ``, 307 }, 308 { 309 // We inadvertently inherited a pre-Go1.17 standard library quirk 310 // if parsing zero-prefix parts as decimal rather than octal. 311 // Go 1.17 resolved that quirk by making zero-prefix invalid, but 312 // we've preserved our existing behavior for backward compatibility, 313 // on the grounds that these functions are for generating addresses 314 // rather than validating or processing them. We do always generate 315 // a canonical result regardless of the input, though. 316 cty.StringVal("010.0.0.0/21"), 317 []cty.Value{ 318 cty.NumberIntVal(3), 319 }, 320 cty.ListVal([]cty.Value{ 321 cty.StringVal("10.0.0.0/24"), 322 }), 323 ``, 324 }, 325 { 326 cty.StringVal("10.0.0.0/30"), 327 []cty.Value{ 328 cty.NumberIntVal(1), 329 cty.NumberIntVal(3), 330 }, 331 cty.UnknownVal(cty.List(cty.String)), 332 `would extend prefix to 33 bits, which is too long for an IPv4 address`, 333 }, 334 { 335 cty.StringVal("10.0.0.0/8"), 336 []cty.Value{ 337 cty.NumberIntVal(1), 338 cty.NumberIntVal(1), 339 cty.NumberIntVal(1), 340 }, 341 cty.UnknownVal(cty.List(cty.String)), 342 `not enough remaining address space for a subnet with a prefix of 9 bits after 10.128.0.0/9`, 343 }, 344 { 345 cty.StringVal("10.0.0.0/8"), 346 []cty.Value{ 347 cty.NumberIntVal(1), 348 cty.NumberIntVal(0), 349 }, 350 cty.UnknownVal(cty.List(cty.String)), 351 `must extend prefix by at least one bit`, 352 }, 353 { 354 cty.StringVal("10.0.0.0/8"), 355 []cty.Value{ 356 cty.NumberIntVal(1), 357 cty.NumberIntVal(-1), 358 }, 359 cty.UnknownVal(cty.List(cty.String)), 360 `must extend prefix by at least one bit`, 361 }, 362 { 363 cty.StringVal("fe80::/48"), 364 []cty.Value{ 365 cty.NumberIntVal(1), 366 cty.NumberIntVal(33), 367 }, 368 cty.UnknownVal(cty.List(cty.String)), 369 `may not extend prefix by more than 32 bits`, 370 }, 371 } 372 373 for _, test := range tests { 374 t.Run(fmt.Sprintf("cidrsubnets(%#v, %#v)", test.Prefix, test.Newbits), func(t *testing.T) { 375 got, err := CidrSubnets(test.Prefix, test.Newbits...) 376 wantErr := test.Err != "" 377 378 if wantErr { 379 if err == nil { 380 t.Fatal("succeeded; want error") 381 } 382 if err.Error() != test.Err { 383 t.Fatalf("wrong error\ngot: %s\nwant: %s", err.Error(), test.Err) 384 } 385 return 386 } else if err != nil { 387 t.Fatalf("unexpected error: %s", err) 388 } 389 390 if !got.RawEquals(test.Want) { 391 t.Errorf("wrong result\ngot: %#v\nwant: %#v", got, test.Want) 392 } 393 }) 394 } 395 }