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