github.com/sl1pm4t/consul@v1.4.5-0.20190325224627-74c31c540f9c/agent/structs/intention_test.go (about)

     1  package structs
     2  
     3  import (
     4  	"sort"
     5  	"strings"
     6  	"testing"
     7  
     8  	"github.com/stretchr/testify/assert"
     9  )
    10  
    11  func TestIntentionGetACLPrefix(t *testing.T) {
    12  	cases := []struct {
    13  		Name     string
    14  		Input    *Intention
    15  		Expected string
    16  	}{
    17  		{
    18  			"unset name",
    19  			&Intention{DestinationName: ""},
    20  			"",
    21  		},
    22  
    23  		{
    24  			"set name",
    25  			&Intention{DestinationName: "fo"},
    26  			"fo",
    27  		},
    28  	}
    29  
    30  	for _, tc := range cases {
    31  		t.Run(tc.Name, func(t *testing.T) {
    32  			actual, ok := tc.Input.GetACLPrefix()
    33  			if tc.Expected == "" {
    34  				if !ok {
    35  					return
    36  				}
    37  
    38  				t.Fatal("should not be ok")
    39  			}
    40  
    41  			if actual != tc.Expected {
    42  				t.Fatalf("bad: %q", actual)
    43  			}
    44  		})
    45  	}
    46  }
    47  
    48  func TestIntentionValidate(t *testing.T) {
    49  	cases := []struct {
    50  		Name   string
    51  		Modify func(*Intention)
    52  		Err    string
    53  	}{
    54  		{
    55  			"long description",
    56  			func(x *Intention) {
    57  				x.Description = strings.Repeat("x", metaValueMaxLength+1)
    58  			},
    59  			"description exceeds",
    60  		},
    61  
    62  		{
    63  			"no action set",
    64  			func(x *Intention) { x.Action = "" },
    65  			"action must be set",
    66  		},
    67  
    68  		{
    69  			"no SourceNS",
    70  			func(x *Intention) { x.SourceNS = "" },
    71  			"SourceNS must be set",
    72  		},
    73  
    74  		{
    75  			"no SourceName",
    76  			func(x *Intention) { x.SourceName = "" },
    77  			"SourceName must be set",
    78  		},
    79  
    80  		{
    81  			"no DestinationNS",
    82  			func(x *Intention) { x.DestinationNS = "" },
    83  			"DestinationNS must be set",
    84  		},
    85  
    86  		{
    87  			"no DestinationName",
    88  			func(x *Intention) { x.DestinationName = "" },
    89  			"DestinationName must be set",
    90  		},
    91  
    92  		{
    93  			"SourceNS partial wildcard",
    94  			func(x *Intention) { x.SourceNS = "foo*" },
    95  			"partial value",
    96  		},
    97  
    98  		{
    99  			"SourceName partial wildcard",
   100  			func(x *Intention) { x.SourceName = "foo*" },
   101  			"partial value",
   102  		},
   103  
   104  		{
   105  			"SourceName exact following wildcard",
   106  			func(x *Intention) {
   107  				x.SourceNS = "*"
   108  				x.SourceName = "foo"
   109  			},
   110  			"follow wildcard",
   111  		},
   112  
   113  		{
   114  			"DestinationNS partial wildcard",
   115  			func(x *Intention) { x.DestinationNS = "foo*" },
   116  			"partial value",
   117  		},
   118  
   119  		{
   120  			"DestinationName partial wildcard",
   121  			func(x *Intention) { x.DestinationName = "foo*" },
   122  			"partial value",
   123  		},
   124  
   125  		{
   126  			"DestinationName exact following wildcard",
   127  			func(x *Intention) {
   128  				x.DestinationNS = "*"
   129  				x.DestinationName = "foo"
   130  			},
   131  			"follow wildcard",
   132  		},
   133  
   134  		{
   135  			"SourceType is not set",
   136  			func(x *Intention) { x.SourceType = "" },
   137  			"SourceType must",
   138  		},
   139  
   140  		{
   141  			"SourceType is other",
   142  			func(x *Intention) { x.SourceType = IntentionSourceType("other") },
   143  			"SourceType must",
   144  		},
   145  	}
   146  
   147  	for _, tc := range cases {
   148  		t.Run(tc.Name, func(t *testing.T) {
   149  			assert := assert.New(t)
   150  			ixn := TestIntention(t)
   151  			tc.Modify(ixn)
   152  
   153  			err := ixn.Validate()
   154  			assert.Equal(err != nil, tc.Err != "", err)
   155  			if err == nil {
   156  				return
   157  			}
   158  
   159  			assert.Contains(strings.ToLower(err.Error()), strings.ToLower(tc.Err))
   160  		})
   161  	}
   162  }
   163  
   164  func TestIntentionPrecedenceSorter(t *testing.T) {
   165  	cases := []struct {
   166  		Name     string
   167  		Input    [][]string // SrcNS, SrcN, DstNS, DstN
   168  		Expected [][]string // Same structure as Input
   169  	}{
   170  		{
   171  			"exhaustive list",
   172  			[][]string{
   173  				{"*", "*", "exact", "*"},
   174  				{"*", "*", "*", "*"},
   175  				{"exact", "*", "exact", "exact"},
   176  				{"*", "*", "exact", "exact"},
   177  				{"exact", "exact", "*", "*"},
   178  				{"exact", "exact", "exact", "exact"},
   179  				{"exact", "exact", "exact", "*"},
   180  				{"exact", "*", "exact", "*"},
   181  				{"exact", "*", "*", "*"},
   182  			},
   183  			[][]string{
   184  				{"exact", "exact", "exact", "exact"},
   185  				{"exact", "*", "exact", "exact"},
   186  				{"*", "*", "exact", "exact"},
   187  				{"exact", "exact", "exact", "*"},
   188  				{"exact", "*", "exact", "*"},
   189  				{"*", "*", "exact", "*"},
   190  				{"exact", "exact", "*", "*"},
   191  				{"exact", "*", "*", "*"},
   192  				{"*", "*", "*", "*"},
   193  			},
   194  		},
   195  		{
   196  			"tiebreak deterministically",
   197  			[][]string{
   198  				{"a", "*", "a", "b"},
   199  				{"a", "*", "a", "a"},
   200  				{"b", "a", "a", "a"},
   201  				{"a", "b", "a", "a"},
   202  				{"a", "a", "b", "a"},
   203  				{"a", "a", "a", "b"},
   204  				{"a", "a", "a", "a"},
   205  			},
   206  			[][]string{
   207  				// Exact matches first in lexicographical order (arbitrary but
   208  				// deterministic)
   209  				{"a", "a", "a", "a"},
   210  				{"a", "a", "a", "b"},
   211  				{"a", "a", "b", "a"},
   212  				{"a", "b", "a", "a"},
   213  				{"b", "a", "a", "a"},
   214  				// Wildcards next, lexicographical
   215  				{"a", "*", "a", "a"},
   216  				{"a", "*", "a", "b"},
   217  			},
   218  		},
   219  	}
   220  
   221  	for _, tc := range cases {
   222  		t.Run(tc.Name, func(t *testing.T) {
   223  			assert := assert.New(t)
   224  
   225  			var input Intentions
   226  			for _, v := range tc.Input {
   227  				input = append(input, &Intention{
   228  					SourceNS:        v[0],
   229  					SourceName:      v[1],
   230  					DestinationNS:   v[2],
   231  					DestinationName: v[3],
   232  				})
   233  			}
   234  
   235  			// Set all the precedence values
   236  			for _, ixn := range input {
   237  				ixn.UpdatePrecedence()
   238  			}
   239  
   240  			// Sort
   241  			sort.Sort(IntentionPrecedenceSorter(input))
   242  
   243  			// Get back into a comparable form
   244  			var actual [][]string
   245  			for _, v := range input {
   246  				actual = append(actual, []string{
   247  					v.SourceNS,
   248  					v.SourceName,
   249  					v.DestinationNS,
   250  					v.DestinationName,
   251  				})
   252  			}
   253  			assert.Equal(tc.Expected, actual)
   254  		})
   255  	}
   256  }