github.com/stefanmcshane/helm@v0.0.0-20221213002717-88a4a2c6e77d/pkg/lint/rules/chartfile_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 rules
    18  
    19  import (
    20  	"os"
    21  	"path/filepath"
    22  	"strings"
    23  	"testing"
    24  
    25  	"github.com/pkg/errors"
    26  
    27  	"github.com/stefanmcshane/helm/pkg/chart"
    28  	"github.com/stefanmcshane/helm/pkg/chartutil"
    29  	"github.com/stefanmcshane/helm/pkg/lint/support"
    30  )
    31  
    32  const (
    33  	badChartDir        = "testdata/badchartfile"
    34  	anotherBadChartDir = "testdata/anotherbadchartfile"
    35  )
    36  
    37  var (
    38  	badChartFilePath         = filepath.Join(badChartDir, "Chart.yaml")
    39  	nonExistingChartFilePath = filepath.Join(os.TempDir(), "Chart.yaml")
    40  )
    41  
    42  var badChart, _ = chartutil.LoadChartfile(badChartFilePath)
    43  
    44  // Validation functions Test
    45  func TestValidateChartYamlNotDirectory(t *testing.T) {
    46  	_ = os.Mkdir(nonExistingChartFilePath, os.ModePerm)
    47  	defer os.Remove(nonExistingChartFilePath)
    48  
    49  	err := validateChartYamlNotDirectory(nonExistingChartFilePath)
    50  	if err == nil {
    51  		t.Errorf("validateChartYamlNotDirectory to return a linter error, got no error")
    52  	}
    53  }
    54  
    55  func TestValidateChartYamlFormat(t *testing.T) {
    56  	err := validateChartYamlFormat(errors.New("Read error"))
    57  	if err == nil {
    58  		t.Errorf("validateChartYamlFormat to return a linter error, got no error")
    59  	}
    60  
    61  	err = validateChartYamlFormat(nil)
    62  	if err != nil {
    63  		t.Errorf("validateChartYamlFormat to return no error, got a linter error")
    64  	}
    65  }
    66  
    67  func TestValidateChartName(t *testing.T) {
    68  	err := validateChartName(badChart)
    69  	if err == nil {
    70  		t.Errorf("validateChartName to return a linter error, got no error")
    71  	}
    72  }
    73  
    74  func TestValidateChartVersion(t *testing.T) {
    75  	var failTest = []struct {
    76  		Version  string
    77  		ErrorMsg string
    78  	}{
    79  		{"", "version is required"},
    80  		{"1.2.3.4", "version '1.2.3.4' is not a valid SemVer"},
    81  		{"waps", "'waps' is not a valid SemVer"},
    82  		{"-3", "'-3' is not a valid SemVer"},
    83  	}
    84  
    85  	var successTest = []string{"0.0.1", "0.0.1+build", "0.0.1-beta"}
    86  
    87  	for _, test := range failTest {
    88  		badChart.Version = test.Version
    89  		err := validateChartVersion(badChart)
    90  		if err == nil || !strings.Contains(err.Error(), test.ErrorMsg) {
    91  			t.Errorf("validateChartVersion(%s) to return \"%s\", got no error", test.Version, test.ErrorMsg)
    92  		}
    93  	}
    94  
    95  	for _, version := range successTest {
    96  		badChart.Version = version
    97  		err := validateChartVersion(badChart)
    98  		if err != nil {
    99  			t.Errorf("validateChartVersion(%s) to return no error, got a linter error", version)
   100  		}
   101  	}
   102  }
   103  
   104  func TestValidateChartMaintainer(t *testing.T) {
   105  	var failTest = []struct {
   106  		Name     string
   107  		Email    string
   108  		ErrorMsg string
   109  	}{
   110  		{"", "", "each maintainer requires a name"},
   111  		{"", "test@test.com", "each maintainer requires a name"},
   112  		{"John Snow", "wrongFormatEmail.com", "invalid email"},
   113  	}
   114  
   115  	var successTest = []struct {
   116  		Name  string
   117  		Email string
   118  	}{
   119  		{"John Snow", ""},
   120  		{"John Snow", "john@winterfell.com"},
   121  	}
   122  
   123  	for _, test := range failTest {
   124  		badChart.Maintainers = []*chart.Maintainer{{Name: test.Name, Email: test.Email}}
   125  		err := validateChartMaintainer(badChart)
   126  		if err == nil || !strings.Contains(err.Error(), test.ErrorMsg) {
   127  			t.Errorf("validateChartMaintainer(%s, %s) to return \"%s\", got no error", test.Name, test.Email, test.ErrorMsg)
   128  		}
   129  	}
   130  
   131  	for _, test := range successTest {
   132  		badChart.Maintainers = []*chart.Maintainer{{Name: test.Name, Email: test.Email}}
   133  		err := validateChartMaintainer(badChart)
   134  		if err != nil {
   135  			t.Errorf("validateChartMaintainer(%s, %s) to return no error, got %s", test.Name, test.Email, err.Error())
   136  		}
   137  	}
   138  }
   139  
   140  func TestValidateChartSources(t *testing.T) {
   141  	var failTest = []string{"", "RiverRun", "john@winterfell", "riverrun.io"}
   142  	var successTest = []string{"http://riverrun.io", "https://riverrun.io", "https://riverrun.io/blackfish"}
   143  	for _, test := range failTest {
   144  		badChart.Sources = []string{test}
   145  		err := validateChartSources(badChart)
   146  		if err == nil || !strings.Contains(err.Error(), "invalid source URL") {
   147  			t.Errorf("validateChartSources(%s) to return \"invalid source URL\", got no error", test)
   148  		}
   149  	}
   150  
   151  	for _, test := range successTest {
   152  		badChart.Sources = []string{test}
   153  		err := validateChartSources(badChart)
   154  		if err != nil {
   155  			t.Errorf("validateChartSources(%s) to return no error, got %s", test, err.Error())
   156  		}
   157  	}
   158  }
   159  
   160  func TestValidateChartIconPresence(t *testing.T) {
   161  	err := validateChartIconPresence(badChart)
   162  	if err == nil {
   163  		t.Errorf("validateChartIconPresence to return a linter error, got no error")
   164  	}
   165  }
   166  
   167  func TestValidateChartIconURL(t *testing.T) {
   168  	var failTest = []string{"RiverRun", "john@winterfell", "riverrun.io"}
   169  	var successTest = []string{"http://riverrun.io", "https://riverrun.io", "https://riverrun.io/blackfish.png"}
   170  	for _, test := range failTest {
   171  		badChart.Icon = test
   172  		err := validateChartIconURL(badChart)
   173  		if err == nil || !strings.Contains(err.Error(), "invalid icon URL") {
   174  			t.Errorf("validateChartIconURL(%s) to return \"invalid icon URL\", got no error", test)
   175  		}
   176  	}
   177  
   178  	for _, test := range successTest {
   179  		badChart.Icon = test
   180  		err := validateChartSources(badChart)
   181  		if err != nil {
   182  			t.Errorf("validateChartIconURL(%s) to return no error, got %s", test, err.Error())
   183  		}
   184  	}
   185  }
   186  
   187  func TestChartfile(t *testing.T) {
   188  	t.Run("Chart.yaml basic validity issues", func(t *testing.T) {
   189  		linter := support.Linter{ChartDir: badChartDir}
   190  		Chartfile(&linter)
   191  		msgs := linter.Messages
   192  		expectedNumberOfErrorMessages := 6
   193  
   194  		if len(msgs) != expectedNumberOfErrorMessages {
   195  			t.Errorf("Expected %d errors, got %d", expectedNumberOfErrorMessages, len(msgs))
   196  			return
   197  		}
   198  
   199  		if !strings.Contains(msgs[0].Err.Error(), "name is required") {
   200  			t.Errorf("Unexpected message 0: %s", msgs[0].Err)
   201  		}
   202  
   203  		if !strings.Contains(msgs[1].Err.Error(), "apiVersion is required. The value must be either \"v1\" or \"v2\"") {
   204  			t.Errorf("Unexpected message 1: %s", msgs[1].Err)
   205  		}
   206  
   207  		if !strings.Contains(msgs[2].Err.Error(), "version '0.0.0.0' is not a valid SemVer") {
   208  			t.Errorf("Unexpected message 2: %s", msgs[2].Err)
   209  		}
   210  
   211  		if !strings.Contains(msgs[3].Err.Error(), "icon is recommended") {
   212  			t.Errorf("Unexpected message 3: %s", msgs[3].Err)
   213  		}
   214  
   215  		if !strings.Contains(msgs[4].Err.Error(), "chart type is not valid in apiVersion") {
   216  			t.Errorf("Unexpected message 4: %s", msgs[4].Err)
   217  		}
   218  
   219  		if !strings.Contains(msgs[5].Err.Error(), "dependencies are not valid in the Chart file with apiVersion") {
   220  			t.Errorf("Unexpected message 5: %s", msgs[5].Err)
   221  		}
   222  	})
   223  
   224  	t.Run("Chart.yaml validity issues due to type mismatch", func(t *testing.T) {
   225  		linter := support.Linter{ChartDir: anotherBadChartDir}
   226  		Chartfile(&linter)
   227  		msgs := linter.Messages
   228  		expectedNumberOfErrorMessages := 3
   229  
   230  		if len(msgs) != expectedNumberOfErrorMessages {
   231  			t.Errorf("Expected %d errors, got %d", expectedNumberOfErrorMessages, len(msgs))
   232  			return
   233  		}
   234  
   235  		if !strings.Contains(msgs[0].Err.Error(), "version should be of type string") {
   236  			t.Errorf("Unexpected message 0: %s", msgs[0].Err)
   237  		}
   238  
   239  		if !strings.Contains(msgs[1].Err.Error(), "version '7.2445e+06' is not a valid SemVer") {
   240  			t.Errorf("Unexpected message 1: %s", msgs[1].Err)
   241  		}
   242  
   243  		if !strings.Contains(msgs[2].Err.Error(), "appVersion should be of type string") {
   244  			t.Errorf("Unexpected message 2: %s", msgs[2].Err)
   245  		}
   246  	})
   247  }