...

Source file src/helm.sh/helm/v3/internal/resolver/resolver_test.go

Documentation: helm.sh/helm/v3/internal/resolver

     1  /*
     2  Copyright The Helm Authors.
     3  Licensed under the Apache License, Version 2.0 (the "License");
     4  you may not use this file except in compliance with the License.
     5  You may obtain a copy of the License at
     6  
     7  http://www.apache.org/licenses/LICENSE-2.0
     8  
     9  Unless required by applicable law or agreed to in writing, software
    10  distributed under the License is distributed on an "AS IS" BASIS,
    11  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    12  See the License for the specific language governing permissions and
    13  limitations under the License.
    14  */
    15  
    16  package resolver
    17  
    18  import (
    19  	"runtime"
    20  	"testing"
    21  
    22  	"helm.sh/helm/v3/pkg/chart"
    23  	"helm.sh/helm/v3/pkg/registry"
    24  )
    25  
    26  func TestResolve(t *testing.T) {
    27  	tests := []struct {
    28  		name   string
    29  		req    []*chart.Dependency
    30  		expect *chart.Lock
    31  		err    bool
    32  	}{
    33  		{
    34  			name: "repo from invalid version",
    35  			req: []*chart.Dependency{
    36  				{Name: "base", Repository: "file://base", Version: "1.1.0"},
    37  			},
    38  			expect: &chart.Lock{
    39  				Dependencies: []*chart.Dependency{
    40  					{Name: "base", Repository: "file://base", Version: "0.1.0"},
    41  				},
    42  			},
    43  			err: true,
    44  		},
    45  		{
    46  			name: "version failure",
    47  			req: []*chart.Dependency{
    48  				{Name: "oedipus-rex", Repository: "http://example.com", Version: ">a1"},
    49  			},
    50  			err: true,
    51  		},
    52  		{
    53  			name: "cache index failure",
    54  			req: []*chart.Dependency{
    55  				{Name: "oedipus-rex", Repository: "http://example.com", Version: "1.0.0"},
    56  			},
    57  			expect: &chart.Lock{
    58  				Dependencies: []*chart.Dependency{
    59  					{Name: "oedipus-rex", Repository: "http://example.com", Version: "1.0.0"},
    60  				},
    61  			},
    62  		},
    63  		{
    64  			name: "chart not found failure",
    65  			req: []*chart.Dependency{
    66  				{Name: "redis", Repository: "http://example.com", Version: "1.0.0"},
    67  			},
    68  			err: true,
    69  		},
    70  		{
    71  			name: "constraint not satisfied failure",
    72  			req: []*chart.Dependency{
    73  				{Name: "alpine", Repository: "http://example.com", Version: ">=1.0.0"},
    74  			},
    75  			err: true,
    76  		},
    77  		{
    78  			name: "valid lock",
    79  			req: []*chart.Dependency{
    80  				{Name: "alpine", Repository: "http://example.com", Version: ">=0.1.0"},
    81  			},
    82  			expect: &chart.Lock{
    83  				Dependencies: []*chart.Dependency{
    84  					{Name: "alpine", Repository: "http://example.com", Version: "0.2.0"},
    85  				},
    86  			},
    87  		},
    88  		{
    89  			name: "repo from valid local path",
    90  			req: []*chart.Dependency{
    91  				{Name: "base", Repository: "file://base", Version: "0.1.0"},
    92  			},
    93  			expect: &chart.Lock{
    94  				Dependencies: []*chart.Dependency{
    95  					{Name: "base", Repository: "file://base", Version: "0.1.0"},
    96  				},
    97  			},
    98  		},
    99  		{
   100  			name: "repo from valid local path with range resolution",
   101  			req: []*chart.Dependency{
   102  				{Name: "base", Repository: "file://base", Version: "^0.1.0"},
   103  			},
   104  			expect: &chart.Lock{
   105  				Dependencies: []*chart.Dependency{
   106  					{Name: "base", Repository: "file://base", Version: "0.1.0"},
   107  				},
   108  			},
   109  		},
   110  		{
   111  			name: "repo from invalid local path",
   112  			req: []*chart.Dependency{
   113  				{Name: "nonexistent", Repository: "file://testdata/nonexistent", Version: "0.1.0"},
   114  			},
   115  			err: true,
   116  		},
   117  		{
   118  			name: "repo from valid path under charts path",
   119  			req: []*chart.Dependency{
   120  				{Name: "localdependency", Repository: "", Version: "0.1.0"},
   121  			},
   122  			expect: &chart.Lock{
   123  				Dependencies: []*chart.Dependency{
   124  					{Name: "localdependency", Repository: "", Version: "0.1.0"},
   125  				},
   126  			},
   127  		},
   128  		{
   129  			name: "repo from invalid path under charts path",
   130  			req: []*chart.Dependency{
   131  				{Name: "nonexistentdependency", Repository: "", Version: "0.1.0"},
   132  			},
   133  			expect: &chart.Lock{
   134  				Dependencies: []*chart.Dependency{
   135  					{Name: "nonexistentlocaldependency", Repository: "", Version: "0.1.0"},
   136  				},
   137  			},
   138  			err: true,
   139  		},
   140  	}
   141  
   142  	repoNames := map[string]string{"alpine": "kubernetes-charts", "redis": "kubernetes-charts"}
   143  	registryClient, _ := registry.NewClient()
   144  	r := New("testdata/chartpath", "testdata/repository", registryClient)
   145  	for _, tt := range tests {
   146  		t.Run(tt.name, func(t *testing.T) {
   147  			l, err := r.Resolve(tt.req, repoNames)
   148  			if err != nil {
   149  				if tt.err {
   150  					return
   151  				}
   152  				t.Fatal(err)
   153  			}
   154  
   155  			if tt.err {
   156  				t.Fatalf("Expected error in test %q", tt.name)
   157  			}
   158  
   159  			if h, err := HashReq(tt.req, tt.expect.Dependencies); err != nil {
   160  				t.Fatal(err)
   161  			} else if h != l.Digest {
   162  				t.Errorf("%q: hashes don't match.", tt.name)
   163  			}
   164  
   165  			// Check fields.
   166  			if len(l.Dependencies) != len(tt.req) {
   167  				t.Errorf("%s: wrong number of dependencies in lock", tt.name)
   168  			}
   169  			d0 := l.Dependencies[0]
   170  			e0 := tt.expect.Dependencies[0]
   171  			if d0.Name != e0.Name {
   172  				t.Errorf("%s: expected name %s, got %s", tt.name, e0.Name, d0.Name)
   173  			}
   174  			if d0.Repository != e0.Repository {
   175  				t.Errorf("%s: expected repo %s, got %s", tt.name, e0.Repository, d0.Repository)
   176  			}
   177  			if d0.Version != e0.Version {
   178  				t.Errorf("%s: expected version %s, got %s", tt.name, e0.Version, d0.Version)
   179  			}
   180  		})
   181  	}
   182  }
   183  
   184  func TestHashReq(t *testing.T) {
   185  	expect := "sha256:fb239e836325c5fa14b29d1540a13b7d3ba13151b67fe719f820e0ef6d66aaaf"
   186  
   187  	tests := []struct {
   188  		name         string
   189  		chartVersion string
   190  		lockVersion  string
   191  		wantError    bool
   192  	}{
   193  		{
   194  			name:         "chart with the expected digest",
   195  			chartVersion: "0.1.0",
   196  			lockVersion:  "0.1.0",
   197  			wantError:    false,
   198  		},
   199  		{
   200  			name:         "ranged version but same resolved lock version",
   201  			chartVersion: "^0.1.0",
   202  			lockVersion:  "0.1.0",
   203  			wantError:    true,
   204  		},
   205  		{
   206  			name:         "ranged version resolved as higher version",
   207  			chartVersion: "^0.1.0",
   208  			lockVersion:  "0.1.2",
   209  			wantError:    true,
   210  		},
   211  		{
   212  			name:         "different version",
   213  			chartVersion: "0.1.2",
   214  			lockVersion:  "0.1.2",
   215  			wantError:    true,
   216  		},
   217  		{
   218  			name:         "different version with a range",
   219  			chartVersion: "^0.1.2",
   220  			lockVersion:  "0.1.2",
   221  			wantError:    true,
   222  		},
   223  	}
   224  
   225  	for _, tt := range tests {
   226  		t.Run(tt.name, func(t *testing.T) {
   227  			req := []*chart.Dependency{
   228  				{Name: "alpine", Version: tt.chartVersion, Repository: "http://localhost:8879/charts"},
   229  			}
   230  			lock := []*chart.Dependency{
   231  				{Name: "alpine", Version: tt.lockVersion, Repository: "http://localhost:8879/charts"},
   232  			}
   233  			h, err := HashReq(req, lock)
   234  			if err != nil {
   235  				t.Fatal(err)
   236  			}
   237  			if !tt.wantError && expect != h {
   238  				t.Errorf("Expected %q, got %q", expect, h)
   239  			} else if tt.wantError && expect == h {
   240  				t.Errorf("Expected not %q, but same", expect)
   241  			}
   242  		})
   243  	}
   244  }
   245  
   246  func TestGetLocalPath(t *testing.T) {
   247  	tests := []struct {
   248  		name      string
   249  		repo      string
   250  		chartpath string
   251  		expect    string
   252  		winExpect string
   253  		err       bool
   254  	}{
   255  		{
   256  			name:      "absolute path",
   257  			repo:      "file:////",
   258  			expect:    "/",
   259  			winExpect: "\\",
   260  		},
   261  		{
   262  			name:      "relative path",
   263  			repo:      "file://../../testdata/chartpath/base",
   264  			chartpath: "foo/bar",
   265  			expect:    "testdata/chartpath/base",
   266  			winExpect: "testdata\\chartpath\\base",
   267  		},
   268  		{
   269  			name:      "current directory path",
   270  			repo:      "../charts/localdependency",
   271  			chartpath: "testdata/chartpath/charts",
   272  			expect:    "testdata/chartpath/charts/localdependency",
   273  			winExpect: "testdata\\chartpath\\charts\\localdependency",
   274  		},
   275  		{
   276  			name:      "invalid local path",
   277  			repo:      "file://testdata/nonexistent",
   278  			chartpath: "testdata/chartpath",
   279  			err:       true,
   280  		},
   281  		{
   282  			name:      "invalid path under current directory",
   283  			repo:      "charts/nonexistentdependency",
   284  			chartpath: "testdata/chartpath/charts",
   285  			err:       true,
   286  		},
   287  	}
   288  
   289  	for _, tt := range tests {
   290  		t.Run(tt.name, func(t *testing.T) {
   291  			p, err := GetLocalPath(tt.repo, tt.chartpath)
   292  			if err != nil {
   293  				if tt.err {
   294  					return
   295  				}
   296  				t.Fatal(err)
   297  			}
   298  			if tt.err {
   299  				t.Fatalf("Expected error in test %q", tt.name)
   300  			}
   301  			expect := tt.expect
   302  			if runtime.GOOS == "windows" {
   303  				expect = tt.winExpect
   304  			}
   305  			if p != expect {
   306  				t.Errorf("%q: expected %q, got %q", tt.name, expect, p)
   307  			}
   308  		})
   309  	}
   310  }
   311  

View as plain text