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  }