github.com/stefanmcshane/helm@v0.0.0-20221213002717-88a4a2c6e77d/pkg/releaseutil/kind_sorter_test.go (about)

     1  /*
     2  Copyright The Helm Authors.
     3  
     4  Licensed under the Apache License, Version 2.0 (the "License");
     5  you may not use this file except in compliance with the License.
     6  You may obtain a copy of the License at
     7  
     8      http://www.apache.org/licenses/LICENSE-2.0
     9  
    10  Unless required by applicable law or agreed to in writing, software
    11  distributed under the License is distributed on an "AS IS" BASIS,
    12  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    13  See the License for the specific language governing permissions and
    14  limitations under the License.
    15  */
    16  
    17  package releaseutil
    18  
    19  import (
    20  	"bytes"
    21  	"testing"
    22  
    23  	"github.com/stefanmcshane/helm/pkg/release"
    24  )
    25  
    26  func TestKindSorter(t *testing.T) {
    27  	manifests := []Manifest{
    28  		{
    29  			Name: "U",
    30  			Head: &SimpleHead{Kind: "IngressClass"},
    31  		},
    32  		{
    33  			Name: "E",
    34  			Head: &SimpleHead{Kind: "SecretList"},
    35  		},
    36  		{
    37  			Name: "i",
    38  			Head: &SimpleHead{Kind: "ClusterRole"},
    39  		},
    40  		{
    41  			Name: "I",
    42  			Head: &SimpleHead{Kind: "ClusterRoleList"},
    43  		},
    44  		{
    45  			Name: "j",
    46  			Head: &SimpleHead{Kind: "ClusterRoleBinding"},
    47  		},
    48  		{
    49  			Name: "J",
    50  			Head: &SimpleHead{Kind: "ClusterRoleBindingList"},
    51  		},
    52  		{
    53  			Name: "f",
    54  			Head: &SimpleHead{Kind: "ConfigMap"},
    55  		},
    56  		{
    57  			Name: "u",
    58  			Head: &SimpleHead{Kind: "CronJob"},
    59  		},
    60  		{
    61  			Name: "2",
    62  			Head: &SimpleHead{Kind: "CustomResourceDefinition"},
    63  		},
    64  		{
    65  			Name: "n",
    66  			Head: &SimpleHead{Kind: "DaemonSet"},
    67  		},
    68  		{
    69  			Name: "r",
    70  			Head: &SimpleHead{Kind: "Deployment"},
    71  		},
    72  		{
    73  			Name: "!",
    74  			Head: &SimpleHead{Kind: "HonkyTonkSet"},
    75  		},
    76  		{
    77  			Name: "v",
    78  			Head: &SimpleHead{Kind: "Ingress"},
    79  		},
    80  		{
    81  			Name: "t",
    82  			Head: &SimpleHead{Kind: "Job"},
    83  		},
    84  		{
    85  			Name: "c",
    86  			Head: &SimpleHead{Kind: "LimitRange"},
    87  		},
    88  		{
    89  			Name: "a",
    90  			Head: &SimpleHead{Kind: "Namespace"},
    91  		},
    92  		{
    93  			Name: "A",
    94  			Head: &SimpleHead{Kind: "NetworkPolicy"},
    95  		},
    96  		{
    97  			Name: "g",
    98  			Head: &SimpleHead{Kind: "PersistentVolume"},
    99  		},
   100  		{
   101  			Name: "h",
   102  			Head: &SimpleHead{Kind: "PersistentVolumeClaim"},
   103  		},
   104  		{
   105  			Name: "o",
   106  			Head: &SimpleHead{Kind: "Pod"},
   107  		},
   108  		{
   109  			Name: "3",
   110  			Head: &SimpleHead{Kind: "PodDisruptionBudget"},
   111  		},
   112  		{
   113  			Name: "C",
   114  			Head: &SimpleHead{Kind: "PodSecurityPolicy"},
   115  		},
   116  		{
   117  			Name: "q",
   118  			Head: &SimpleHead{Kind: "ReplicaSet"},
   119  		},
   120  		{
   121  			Name: "p",
   122  			Head: &SimpleHead{Kind: "ReplicationController"},
   123  		},
   124  		{
   125  			Name: "b",
   126  			Head: &SimpleHead{Kind: "ResourceQuota"},
   127  		},
   128  		{
   129  			Name: "k",
   130  			Head: &SimpleHead{Kind: "Role"},
   131  		},
   132  		{
   133  			Name: "K",
   134  			Head: &SimpleHead{Kind: "RoleList"},
   135  		},
   136  		{
   137  			Name: "l",
   138  			Head: &SimpleHead{Kind: "RoleBinding"},
   139  		},
   140  		{
   141  			Name: "L",
   142  			Head: &SimpleHead{Kind: "RoleBindingList"},
   143  		},
   144  		{
   145  			Name: "e",
   146  			Head: &SimpleHead{Kind: "Secret"},
   147  		},
   148  		{
   149  			Name: "m",
   150  			Head: &SimpleHead{Kind: "Service"},
   151  		},
   152  		{
   153  			Name: "d",
   154  			Head: &SimpleHead{Kind: "ServiceAccount"},
   155  		},
   156  		{
   157  			Name: "s",
   158  			Head: &SimpleHead{Kind: "StatefulSet"},
   159  		},
   160  		{
   161  			Name: "1",
   162  			Head: &SimpleHead{Kind: "StorageClass"},
   163  		},
   164  		{
   165  			Name: "w",
   166  			Head: &SimpleHead{Kind: "APIService"},
   167  		},
   168  		{
   169  			Name: "x",
   170  			Head: &SimpleHead{Kind: "HorizontalPodAutoscaler"},
   171  		},
   172  	}
   173  
   174  	for _, test := range []struct {
   175  		description string
   176  		order       KindSortOrder
   177  		expected    string
   178  	}{
   179  		{"install", InstallOrder, "aAbcC3deEf1gh2iIjJkKlLmnopqrxstuUvw!"},
   180  		{"uninstall", UninstallOrder, "wvUmutsxrqponLlKkJjIi2hg1fEed3CcbAa!"},
   181  	} {
   182  		var buf bytes.Buffer
   183  		t.Run(test.description, func(t *testing.T) {
   184  			if got, want := len(test.expected), len(manifests); got != want {
   185  				t.Fatalf("Expected %d names in order, got %d", want, got)
   186  			}
   187  			defer buf.Reset()
   188  			orig := manifests
   189  			for _, r := range sortManifestsByKind(manifests, test.order) {
   190  				buf.WriteString(r.Name)
   191  			}
   192  			if got := buf.String(); got != test.expected {
   193  				t.Errorf("Expected %q, got %q", test.expected, got)
   194  			}
   195  			for i, manifest := range orig {
   196  				if manifest != manifests[i] {
   197  					t.Fatal("Expected input to sortManifestsByKind to stay the same")
   198  				}
   199  			}
   200  		})
   201  	}
   202  }
   203  
   204  // TestKindSorterKeepOriginalOrder verifies manifests of same kind are kept in original order
   205  func TestKindSorterKeepOriginalOrder(t *testing.T) {
   206  	manifests := []Manifest{
   207  		{
   208  			Name: "a",
   209  			Head: &SimpleHead{Kind: "ClusterRole"},
   210  		},
   211  		{
   212  			Name: "A",
   213  			Head: &SimpleHead{Kind: "ClusterRole"},
   214  		},
   215  		{
   216  			Name: "0",
   217  			Head: &SimpleHead{Kind: "ConfigMap"},
   218  		},
   219  		{
   220  			Name: "1",
   221  			Head: &SimpleHead{Kind: "ConfigMap"},
   222  		},
   223  		{
   224  			Name: "z",
   225  			Head: &SimpleHead{Kind: "ClusterRoleBinding"},
   226  		},
   227  		{
   228  			Name: "!",
   229  			Head: &SimpleHead{Kind: "ClusterRoleBinding"},
   230  		},
   231  		{
   232  			Name: "u2",
   233  			Head: &SimpleHead{Kind: "Unknown"},
   234  		},
   235  		{
   236  			Name: "u1",
   237  			Head: &SimpleHead{Kind: "Unknown"},
   238  		},
   239  		{
   240  			Name: "t3",
   241  			Head: &SimpleHead{Kind: "Unknown2"},
   242  		},
   243  	}
   244  	for _, test := range []struct {
   245  		description string
   246  		order       KindSortOrder
   247  		expected    string
   248  	}{
   249  		// expectation is sorted by kind (unknown is last) and within each group of same kind, the order is kept
   250  		{"cm,clusterRole,clusterRoleBinding,Unknown,Unknown2", InstallOrder, "01aAz!u2u1t3"},
   251  	} {
   252  		var buf bytes.Buffer
   253  		t.Run(test.description, func(t *testing.T) {
   254  			defer buf.Reset()
   255  			for _, r := range sortManifestsByKind(manifests, test.order) {
   256  				buf.WriteString(r.Name)
   257  			}
   258  			if got := buf.String(); got != test.expected {
   259  				t.Errorf("Expected %q, got %q", test.expected, got)
   260  			}
   261  		})
   262  	}
   263  }
   264  
   265  func TestKindSorterNamespaceAgainstUnknown(t *testing.T) {
   266  	unknown := Manifest{
   267  		Name: "a",
   268  		Head: &SimpleHead{Kind: "Unknown"},
   269  	}
   270  	namespace := Manifest{
   271  		Name: "b",
   272  		Head: &SimpleHead{Kind: "Namespace"},
   273  	}
   274  
   275  	manifests := []Manifest{unknown, namespace}
   276  	manifests = sortManifestsByKind(manifests, InstallOrder)
   277  
   278  	expectedOrder := []Manifest{namespace, unknown}
   279  	for i, manifest := range manifests {
   280  		if expectedOrder[i].Name != manifest.Name {
   281  			t.Errorf("Expected %s, got %s", expectedOrder[i].Name, manifest.Name)
   282  		}
   283  	}
   284  }
   285  
   286  // test hook sorting with a small subset of kinds, since it uses the same algorithm as sortManifestsByKind
   287  func TestKindSorterForHooks(t *testing.T) {
   288  	hooks := []*release.Hook{
   289  		{
   290  			Name: "i",
   291  			Kind: "ClusterRole",
   292  		},
   293  		{
   294  			Name: "j",
   295  			Kind: "ClusterRoleBinding",
   296  		},
   297  		{
   298  			Name: "c",
   299  			Kind: "LimitRange",
   300  		},
   301  		{
   302  			Name: "a",
   303  			Kind: "Namespace",
   304  		},
   305  	}
   306  
   307  	for _, test := range []struct {
   308  		description string
   309  		order       KindSortOrder
   310  		expected    string
   311  	}{
   312  		{"install", InstallOrder, "acij"},
   313  		{"uninstall", UninstallOrder, "jica"},
   314  	} {
   315  		var buf bytes.Buffer
   316  		t.Run(test.description, func(t *testing.T) {
   317  			if got, want := len(test.expected), len(hooks); got != want {
   318  				t.Fatalf("Expected %d names in order, got %d", want, got)
   319  			}
   320  			defer buf.Reset()
   321  			orig := hooks
   322  			for _, r := range sortHooksByKind(hooks, test.order) {
   323  				buf.WriteString(r.Name)
   324  			}
   325  			for i, hook := range orig {
   326  				if hook != hooks[i] {
   327  					t.Fatal("Expected input to sortHooksByKind to stay the same")
   328  				}
   329  			}
   330  			if got := buf.String(); got != test.expected {
   331  				t.Errorf("Expected %q, got %q", test.expected, got)
   332  			}
   333  		})
   334  	}
   335  }