github.com/zntrio/harp/v2@v2.0.9/pkg/bundle/compare/diff_test.go (about)

     1  // Licensed to Elasticsearch B.V. under one or more contributor
     2  // license agreements. See the NOTICE file distributed with
     3  // this work for additional information regarding copyright
     4  // ownership. Elasticsearch B.V. licenses this file to you under
     5  // the Apache License, Version 2.0 (the "License"); you may
     6  // not use this file except in compliance with the License.
     7  // You may obtain a copy of the License at
     8  //
     9  //     http://www.apache.org/licenses/LICENSE-2.0
    10  //
    11  // Unless required by applicable law or agreed to in writing,
    12  // software distributed under the License is distributed on an
    13  // "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
    14  // KIND, either express or implied.  See the License for the
    15  // specific language governing permissions and limitations
    16  // under the License.
    17  
    18  package compare
    19  
    20  import (
    21  	"testing"
    22  
    23  	"github.com/google/go-cmp/cmp"
    24  	fuzz "github.com/google/gofuzz"
    25  
    26  	bundlev1 "github.com/zntrio/harp/v2/api/gen/go/harp/bundle/v1"
    27  	"github.com/zntrio/harp/v2/pkg/bundle/secret"
    28  )
    29  
    30  func MustPack(value interface{}) []byte {
    31  	out, err := secret.Pack(value)
    32  	if err != nil {
    33  		panic(err)
    34  	}
    35  
    36  	return out
    37  }
    38  
    39  func TestDiff(t *testing.T) {
    40  	type args struct {
    41  		src *bundlev1.Bundle
    42  		dst *bundlev1.Bundle
    43  	}
    44  	tests := []struct {
    45  		name    string
    46  		args    args
    47  		want    []DiffItem
    48  		wantErr bool
    49  	}{
    50  		{
    51  			name:    "src nil",
    52  			wantErr: true,
    53  		},
    54  		{
    55  			name: "dst nil",
    56  			args: args{
    57  				src: &bundlev1.Bundle{},
    58  			},
    59  			wantErr: true,
    60  		},
    61  		{
    62  			name: "identic",
    63  			args: args{
    64  				src: &bundlev1.Bundle{
    65  					Packages: []*bundlev1.Package{},
    66  				},
    67  				dst: &bundlev1.Bundle{
    68  					Packages: []*bundlev1.Package{},
    69  				},
    70  			},
    71  			wantErr: false,
    72  			want:    []DiffItem{},
    73  		},
    74  		{
    75  			name: "new package",
    76  			args: args{
    77  				src: &bundlev1.Bundle{
    78  					Packages: []*bundlev1.Package{},
    79  				},
    80  				dst: &bundlev1.Bundle{
    81  					Packages: []*bundlev1.Package{
    82  						{
    83  							Name: "app/test",
    84  							Secrets: &bundlev1.SecretChain{
    85  								Data: []*bundlev1.KV{
    86  									{
    87  										Key:   "key1",
    88  										Value: MustPack("payload"),
    89  									},
    90  								},
    91  							},
    92  						},
    93  					},
    94  				},
    95  			},
    96  			wantErr: false,
    97  			want: []DiffItem{
    98  				{Operation: Add, Type: "package", Path: "app/test"},
    99  				{Operation: Add, Type: "secret", Path: "app/test#key1", Value: "payload"},
   100  			},
   101  		},
   102  		{
   103  			name: "package removed",
   104  			args: args{
   105  				src: &bundlev1.Bundle{
   106  					Packages: []*bundlev1.Package{
   107  						{
   108  							Name: "app/test",
   109  							Secrets: &bundlev1.SecretChain{
   110  								Data: []*bundlev1.KV{
   111  									{
   112  										Key:   "key1",
   113  										Value: MustPack("payload"),
   114  									},
   115  								},
   116  							},
   117  						},
   118  					},
   119  				},
   120  				dst: &bundlev1.Bundle{
   121  					Packages: []*bundlev1.Package{},
   122  				},
   123  			},
   124  			wantErr: false,
   125  			want: []DiffItem{
   126  				{Operation: Remove, Type: "package", Path: "app/test"},
   127  			},
   128  		},
   129  		{
   130  			name: "secret added",
   131  			args: args{
   132  				src: &bundlev1.Bundle{
   133  					Packages: []*bundlev1.Package{
   134  						{
   135  							Name: "app/test",
   136  							Secrets: &bundlev1.SecretChain{
   137  								Data: []*bundlev1.KV{
   138  									{
   139  										Key:   "key1",
   140  										Value: MustPack("payload"),
   141  									},
   142  								},
   143  							},
   144  						},
   145  					},
   146  				},
   147  				dst: &bundlev1.Bundle{
   148  					Packages: []*bundlev1.Package{
   149  						{
   150  							Name: "app/test",
   151  							Secrets: &bundlev1.SecretChain{
   152  								Data: []*bundlev1.KV{
   153  									{
   154  										Key:   "key1",
   155  										Value: MustPack("payload"),
   156  									},
   157  									{
   158  										Key:   "key2",
   159  										Value: MustPack("newpayload"),
   160  									},
   161  								},
   162  							},
   163  						},
   164  					},
   165  				},
   166  			},
   167  			wantErr: false,
   168  			want: []DiffItem{
   169  				{Operation: Add, Type: "secret", Path: "app/test#key2", Value: "newpayload"},
   170  			},
   171  		},
   172  		{
   173  			name: "secret removed",
   174  			args: args{
   175  				src: &bundlev1.Bundle{
   176  					Packages: []*bundlev1.Package{
   177  						{
   178  							Name: "app/test",
   179  							Secrets: &bundlev1.SecretChain{
   180  								Data: []*bundlev1.KV{
   181  									{
   182  										Key:   "key1",
   183  										Value: MustPack("payload"),
   184  									},
   185  									{
   186  										Key:   "key2",
   187  										Value: MustPack("newpayload"),
   188  									},
   189  								},
   190  							},
   191  						},
   192  					},
   193  				},
   194  				dst: &bundlev1.Bundle{
   195  					Packages: []*bundlev1.Package{
   196  						{
   197  							Name: "app/test",
   198  							Secrets: &bundlev1.SecretChain{
   199  								Data: []*bundlev1.KV{
   200  									{
   201  										Key:   "key2",
   202  										Value: MustPack("newpayload"),
   203  									},
   204  								},
   205  							},
   206  						},
   207  					},
   208  				},
   209  			},
   210  			wantErr: false,
   211  			want: []DiffItem{
   212  				{Operation: Remove, Type: "secret", Path: "app/test#key1"},
   213  			},
   214  		},
   215  		{
   216  			name: "secret replaced",
   217  			args: args{
   218  				src: &bundlev1.Bundle{
   219  					Packages: []*bundlev1.Package{
   220  						{
   221  							Name: "app/test",
   222  							Secrets: &bundlev1.SecretChain{
   223  								Data: []*bundlev1.KV{
   224  									{
   225  										Key:   "key2",
   226  										Value: MustPack("oldpayload"),
   227  									},
   228  								},
   229  							},
   230  						},
   231  					},
   232  				},
   233  				dst: &bundlev1.Bundle{
   234  					Packages: []*bundlev1.Package{
   235  						{
   236  							Name: "app/test",
   237  							Secrets: &bundlev1.SecretChain{
   238  								Data: []*bundlev1.KV{
   239  									{
   240  										Key:   "key2",
   241  										Value: MustPack("newpayload"),
   242  									},
   243  								},
   244  							},
   245  						},
   246  					},
   247  				},
   248  			},
   249  			wantErr: false,
   250  			want: []DiffItem{
   251  				{Operation: Replace, Type: "secret", Path: "app/test#key2", Value: "newpayload"},
   252  			},
   253  		},
   254  		{
   255  			name: "no-op",
   256  			args: args{
   257  				src: &bundlev1.Bundle{
   258  					Packages: []*bundlev1.Package{
   259  						{
   260  							Name: "app/test",
   261  							Secrets: &bundlev1.SecretChain{
   262  								Data: []*bundlev1.KV{
   263  									{
   264  										Key:   "key2",
   265  										Value: MustPack("oldpayload"),
   266  									},
   267  								},
   268  							},
   269  						},
   270  					},
   271  				},
   272  				dst: &bundlev1.Bundle{
   273  					Packages: []*bundlev1.Package{
   274  						{
   275  							Name: "app/test",
   276  							Secrets: &bundlev1.SecretChain{
   277  								Data: []*bundlev1.KV{
   278  									{
   279  										Key:   "key2",
   280  										Value: MustPack("oldpayload"),
   281  									},
   282  								},
   283  							},
   284  						},
   285  					},
   286  				},
   287  			},
   288  			wantErr: false,
   289  			want:    []DiffItem{},
   290  		},
   291  	}
   292  	for _, tt := range tests {
   293  		t.Run(tt.name, func(t *testing.T) {
   294  			got, err := Diff(tt.args.src, tt.args.dst)
   295  			if (err != nil) != tt.wantErr {
   296  				t.Errorf("Diff() error = %v, wantErr %v", err, tt.wantErr)
   297  				return
   298  			}
   299  			if diff := cmp.Diff(got, tt.want); diff != "" {
   300  				t.Errorf("%q. Diff():\n-got/+want\ndiff %s", tt.name, diff)
   301  			}
   302  		})
   303  	}
   304  }
   305  
   306  func TestDiff_Fuzz(t *testing.T) {
   307  	// Making sure the descrption never panics
   308  	for i := 0; i < 50; i++ {
   309  		f := fuzz.New()
   310  
   311  		var (
   312  			src bundlev1.Bundle
   313  			dst bundlev1.Bundle
   314  		)
   315  
   316  		// Prepare arguments
   317  		f.Fuzz(&src)
   318  		f.Fuzz(&dst)
   319  
   320  		// Execute
   321  		Diff(&src, &dst)
   322  	}
   323  }