Add unit tests

Signed-off-by: Martin Hickey <martin.hickey@ie.ibm.com>
pull/5255/head
Martin Hickey 7 years ago
parent 5c4af6f275
commit 4356999b5f

@ -0,0 +1,232 @@
/*
Copyright The Helm Authors.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
package main
import (
"bytes"
"fmt"
"io/ioutil"
"os"
"path/filepath"
"strings"
"testing"
"k8s.io/helm/pkg/chart"
"k8s.io/helm/pkg/chartutil"
"k8s.io/helm/pkg/provenance"
"k8s.io/helm/pkg/repo"
"k8s.io/helm/pkg/repo/repotest"
)
func TestLibraryUpdateCmd(t *testing.T) {
defer resetEnv()()
hh := testHelmHome(t)
settings.Home = hh
srv := repotest.NewServer(hh.String())
defer srv.Stop()
copied, err := srv.CopyCharts("testdata/testcharts/lib-charts/*.tgz")
if err != nil {
t.Fatal(err)
}
t.Logf("Copied charts:\n%s", strings.Join(copied, "\n"))
t.Logf("Listening on directory %s", srv.Root())
chartname := "libup"
md := createTestingMetadataLibRef(chartname, srv.URL())
if _, err := chartutil.Create(md, hh.String()); err != nil {
t.Fatal(err)
}
out, err := executeCommand(nil, fmt.Sprintf("--home='%s' library update '%s'", hh, hh.Path(chartname)))
if err != nil {
t.Logf("Output: %s", out)
t.Fatal(err)
}
// This is written directly to stdout, so we have to capture as is.
if !strings.Contains(out, `update from the "test" chart repository`) {
t.Errorf("Repo did not get updated\n%s", out)
}
// Make sure the actual file got downloaded.
expect := hh.Path(chartname, "library/common-0.0.5.tgz")
if _, err := os.Stat(expect); err != nil {
t.Fatal(err)
}
hash, err := provenance.DigestFile(expect)
if err != nil {
t.Fatal(err)
}
i, err := repo.LoadIndexFile(hh.CacheIndex("test"))
if err != nil {
t.Fatal(err)
}
reqver := i.Entries["common"][0]
if h := reqver.Digest; h != hash {
t.Errorf("Failed hash match: expected %s, got %s", hash, h)
}
// Now change the libraries and update. This verifies that on update,
// old libraries are cleansed and new libraries are added.
md.Libraries = []*chart.Dependency{
{Name: "common", Version: "0.0.5", Repository: srv.URL()},
{Name: "compressedchart", Version: "0.3.0", Repository: srv.URL()},
}
dir := hh.Path(chartname, "Chart.yaml")
if err := chartutil.SaveChartfile(dir, md); err != nil {
t.Fatal(err)
}
out, err = executeCommand(nil, fmt.Sprintf("--home='%s' library update '%s'", hh, hh.Path(chartname)))
if err != nil {
t.Logf("Output: %s", out)
t.Fatal(err)
}
// In this second run, we should see compressedchart-0.3.0.tgz, and not
// the 0.1.0 version.
expect = hh.Path(chartname, "library/compressedchart-0.3.0.tgz")
if _, err := os.Stat(expect); err != nil {
t.Fatalf("Expected %q: %s", expect, err)
}
dontExpect := hh.Path(chartname, "library/compressedchart-0.1.0.tgz")
if _, err := os.Stat(dontExpect); err == nil {
t.Fatalf("Unexpected %q", dontExpect)
}
}
func TestLibraryUpdateCmd_SkipRefresh(t *testing.T) {
defer resetEnv()()
hh := testHelmHome(t)
settings.Home = hh
srv := repotest.NewServer(hh.String())
defer srv.Stop()
copied, err := srv.CopyCharts("testdata/testcharts/lib-charts/*.tgz")
if err != nil {
t.Fatal(err)
}
t.Logf("Copied charts:\n%s", strings.Join(copied, "\n"))
t.Logf("Listening on directory %s", srv.Root())
chartname := "libup"
if err := createTestingChartLibRef(hh.String(), chartname, srv.URL()); err != nil {
t.Fatal(err)
}
out, err := executeCommand(nil, fmt.Sprintf("--home='%s' library update --skip-refresh '%s'", hh, hh.Path(chartname)))
if err == nil {
t.Fatal("Expected failure to find the repo with skipRefresh")
}
// This is written directly to stdout, so we have to capture as is.
if strings.Contains(out, `update from the "test" chart repository`) {
t.Errorf("Repo was unexpectedly updated\n%s", out)
}
}
func TestLibraryUpdateCmd_DontDeleteOldChartsOnError(t *testing.T) {
defer resetEnv()()
hh := testHelmHome(t)
settings.Home = hh
srv := repotest.NewServer(hh.String())
defer srv.Stop()
copied, err := srv.CopyCharts("testdata/testcharts/lib-charts/*.tgz")
if err != nil {
t.Fatal(err)
}
t.Logf("Copied charts:\n%s", strings.Join(copied, "\n"))
t.Logf("Listening on directory %s", srv.Root())
chartname := "libupdelete"
if err := createTestingChartLibRef(hh.String(), chartname, srv.URL()); err != nil {
t.Fatal(err)
}
out := bytes.NewBuffer(nil)
o := &refUpdateOptions{}
o.helmhome = hh
o.chartpath = hh.Path(chartname)
if err := o.run(out, true); err != nil {
output := out.String()
t.Logf("Output: %s", output)
t.Fatal(err)
}
// Chart repo is down
srv.Stop()
if err := o.run(out, true); err == nil {
output := out.String()
t.Logf("Output: %s", output)
t.Fatal("Expected error, got nil")
}
// Make sure charts dir still has libraries
files, err := ioutil.ReadDir(filepath.Join(o.chartpath, "library"))
if err != nil {
t.Fatal(err)
}
libraries := []string{"common-0.0.5.tgz", "compressedchart-0.1.0.tgz"}
if len(libraries) != len(files) {
t.Fatalf("Expected %d chart library, got %d", len(libraries), len(files))
}
for index, file := range files {
if libraries[index] != file.Name() {
t.Fatalf("Chart library %s not matching %s", libraries[index], file.Name())
}
}
// Make sure tmpcharts is deleted
if _, err := os.Stat(filepath.Join(o.chartpath, "tmpcharts")); !os.IsNotExist(err) {
t.Fatalf("tmpcharts dir still exists")
}
}
// createTestingMetadataLibRef creates a basic chart that depends on lib chart
// common-0.0.5
//
// The baseURL can be used to point to a particular repository server.
func createTestingMetadataLibRef(name, baseURL string) *chart.Metadata {
return &chart.Metadata{
Name: name,
Version: "1.2.3",
Libraries: []*chart.Dependency{
{Name: "common", Version: "0.0.5", Repository: baseURL},
{Name: "compressedchart", Version: "0.1.0", Repository: baseURL},
},
}
}
// createTestingChartLibRef creates a basic chart that depends on
// lib chart common-0.0.5
//
// The baseURL can be used to point to a particular repository server.
func createTestingChartLibRef(dest, name, baseURL string) error {
cfile := createTestingMetadataLibRef(name, baseURL)
_, err := chartutil.Create(cfile, dest)
return err
}

@ -140,6 +140,12 @@ func TestPackage(t *testing.T) {
hasfile: "chart-missing-deps-0.1.0.tgz",
err: true,
},
{
name: "package testdata/testcharts/chart-missing-libs",
args: []string{"testdata/testcharts/chart-missing-libs"},
hasfile: "chart-missing-libs-0.1.0.tgz",
err: true,
},
{
name: "package --values does-not-exist",
args: []string{"testdata/testcharts/alpine"},

@ -0,0 +1,21 @@
# Patterns to ignore when building packages.
# This supports shell glob matching, relative path matching, and
# negation (prefixed with !). Only one pattern per line.
.DS_Store
# Common VCS dirs
.git/
.gitignore
.bzr/
.bzrignore
.hg/
.hgignore
.svn/
# Common backup files
*.swp
*.bak
*.tmp
*~
# Various IDEs
.project
.idea/
*.tmproj

@ -0,0 +1,10 @@
description: A Helm chart for Kubernetes
name: chart-missing-libs
version: 0.1.0
libraries:
- name: reqsubchart
version: 0.1.0
repository: "https://example.com/charts"
- name: reqsubchart2
version: 0.2.0
repository: "https://example.com/charts"

@ -0,0 +1,21 @@
# Patterns to ignore when building packages.
# This supports shell glob matching, relative path matching, and
# negation (prefixed with !). Only one pattern per line.
.DS_Store
# Common VCS dirs
.git/
.gitignore
.bzr/
.bzrignore
.hg/
.hgignore
.svn/
# Common backup files
*.swp
*.bak
*.tmp
*~
# Various IDEs
.project
.idea/
*.tmproj

@ -0,0 +1,3 @@
description: A Helm chart for Kubernetes
name: reqsubchart
version: 0.1.0

@ -0,0 +1,4 @@
# Default values for reqsubchart.
# This is a YAML-formatted file.
# Declare name/value pairs to be passed into your templates.
# name: value

@ -0,0 +1,4 @@
# Default values for reqtest.
# This is a YAML-formatted file.
# Declare name/value pairs to be passed into your templates.
# name: value

@ -21,7 +21,65 @@ import (
"k8s.io/helm/pkg/chart"
)
func TestResolve(t *testing.T) {
func TestDependencyResolve(t *testing.T) {
resolve(t, false)
}
func TestLibraryResolve(t *testing.T) {
resolve(t, true)
}
func TestHashReq(t *testing.T) {
expect := "sha256:d661820b01ed7bcf26eed8f01cf16380e0a76326ba33058d3150f919d9b15bc0"
req := []*chart.Dependency{
{Name: "alpine", Version: "0.1.0", Repository: "http://localhost:8879/charts"},
}
h, err := HashReq(req)
if err != nil {
t.Fatal(err)
}
if expect != h {
t.Errorf("Expected %q, got %q", expect, h)
}
req = []*chart.Dependency{}
h, err = HashReq(req)
if err != nil {
t.Fatal(err)
}
if expect == h {
t.Errorf("Expected %q != %q", expect, h)
}
}
func resolve(t *testing.T, isLib bool) {
var lock1 *chart.Lock
var lock2 *chart.Lock
if isLib {
lock1 = &chart.Lock{
Libraries: []*chart.Dependency{
{Name: "alpine", Repository: "http://example.com", Version: "0.2.0"},
},
}
lock2 = &chart.Lock{
Libraries: []*chart.Dependency{
{Name: "signtest", Repository: "file://../../../../cmd/helm/testdata/testcharts/signtest", Version: "0.1.0"},
},
}
} else {
lock1 = &chart.Lock{
Dependencies: []*chart.Dependency{
{Name: "alpine", Repository: "http://example.com", Version: "0.2.0"},
},
}
lock2 = &chart.Lock{
Dependencies: []*chart.Dependency{
{Name: "signtest", Repository: "file://../../../../cmd/helm/testdata/testcharts/signtest", Version: "0.1.0"},
},
}
}
tests := []struct {
name string
req []*chart.Dependency
@ -61,22 +119,14 @@ func TestResolve(t *testing.T) {
req: []*chart.Dependency{
{Name: "alpine", Repository: "http://example.com", Version: ">=0.1.0"},
},
expect: &chart.Lock{
Dependencies: []*chart.Dependency{
{Name: "alpine", Repository: "http://example.com", Version: "0.2.0"},
},
},
expect: lock1,
},
{
name: "repo from valid local path",
req: []*chart.Dependency{
{Name: "signtest", Repository: "file://../../../../cmd/helm/testdata/testcharts/signtest", Version: "0.1.0"},
},
expect: &chart.Lock{
Dependencies: []*chart.Dependency{
{Name: "signtest", Repository: "file://../../../../cmd/helm/testdata/testcharts/signtest", Version: "0.1.0"},
},
},
expect: lock2,
},
{
name: "repo from invalid local path",
@ -95,12 +145,18 @@ func TestResolve(t *testing.T) {
t.Fatal(err)
}
l, err := r.Resolve(tt.req, repoNames, hash, false)
if err != nil {
var l *chart.Lock
var errRes error
if isLib {
l, errRes = r.Resolve(tt.req, repoNames, hash, true)
} else {
l, errRes = r.Resolve(tt.req, repoNames, hash, false)
}
if errRes != nil {
if tt.err {
continue
}
t.Fatal(err)
t.Fatal(errRes)
}
if tt.err {
@ -114,11 +170,20 @@ func TestResolve(t *testing.T) {
}
// Check fields.
if len(l.Dependencies) != len(tt.req) {
var reqs []*chart.Dependency
var ttReqs []*chart.Dependency
if isLib {
reqs = l.Libraries
ttReqs = tt.expect.Libraries
} else {
reqs = l.Dependencies
ttReqs = tt.expect.Dependencies
}
if len(reqs) != len(tt.req) {
t.Errorf("%s: wrong number of dependencies in lock", tt.name)
}
d0 := l.Dependencies[0]
e0 := tt.expect.Dependencies[0]
d0 := reqs[0]
e0 := ttReqs[0]
if d0.Name != e0.Name {
t.Errorf("%s: expected name %s, got %s", tt.name, e0.Name, d0.Name)
}
@ -130,26 +195,3 @@ func TestResolve(t *testing.T) {
}
}
}
func TestHashReq(t *testing.T) {
expect := "sha256:d661820b01ed7bcf26eed8f01cf16380e0a76326ba33058d3150f919d9b15bc0"
req := []*chart.Dependency{
{Name: "alpine", Version: "0.1.0", Repository: "http://localhost:8879/charts"},
}
h, err := HashReq(req)
if err != nil {
t.Fatal(err)
}
if expect != h {
t.Errorf("Expected %q, got %q", expect, h)
}
req = []*chart.Dependency{}
h, err = HashReq(req)
if err != nil {
t.Fatal(err)
}
if expect == h {
t.Errorf("Expected %q != %q", expect, h)
}
}

Loading…
Cancel
Save