github.com/eliastor/durgaform@v0.0.0-20220816172711-d0ab2d17673e/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  }