Skip to content

Commit

Permalink
Improved tests
Browse files Browse the repository at this point in the history
  • Loading branch information
juamedgod committed Aug 18, 2023
1 parent 9b94d4a commit e3b6271
Show file tree
Hide file tree
Showing 32 changed files with 1,777 additions and 322 deletions.
22 changes: 3 additions & 19 deletions chartutils/chart_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,6 @@ package chartutils
import (
"bytes"
"fmt"
"log"
"os"
"path/filepath"
"testing"
Expand All @@ -15,24 +14,9 @@ import (
"github.com/stretchr/testify/require"
)

var (
sb *tu.Sandbox
)

func TestMain(m *testing.M) {

sb = tu.NewSandbox()
c := m.Run()

if err := sb.Cleanup(); err != nil {
log.Printf("WARN: failed to cleanup test sandbox: %v", err)
}

os.Exit(c)
}

func TestLoadChart(t *testing.T) {

func (suite *ChartUtilsTestSuite) TestLoadChart() {
sb := suite.sb
t := suite.T()
type rawChartData struct {
Dependencies []struct {
Name string
Expand Down
2 changes: 1 addition & 1 deletion chartutils/chartutils.go
Original file line number Diff line number Diff line change
Expand Up @@ -56,7 +56,7 @@ func AnnotateChart(chartPath string, opts ...Option) error {
func GetChartRoot(chartPath string) (string, error) {
fi, err := os.Stat(chartPath)
if err != nil {
return "", fmt.Errorf("cannot access Helm chart %q: %v", chartPath, err)
return "", fmt.Errorf("cannot access path %q: %v", chartPath, err)
}
// we either got the path to chart dir, or to the chart yaml
if fi.IsDir() {
Expand Down
82 changes: 82 additions & 0 deletions chartutils/chartutils_test.go
Original file line number Diff line number Diff line change
@@ -1 +1,83 @@
package chartutils

import (
"fmt"
"path/filepath"
"testing"

tu "github.com/vmware-labs/distribution-tooling-for-helm/internal/testutil"

"github.com/stretchr/testify/suite"
)

type ChartUtilsTestSuite struct {
suite.Suite
sb *tu.Sandbox
}

func (suite *ChartUtilsTestSuite) TearDownSuite() {
_ = suite.sb.Cleanup()
}

func (suite *ChartUtilsTestSuite) SetupSuite() {
suite.sb = tu.NewSandbox()
}

func TestChartUtilsTestSuite(t *testing.T) {
suite.Run(t, new(ChartUtilsTestSuite))
}

func (suite *ChartUtilsTestSuite) TestAnnotateChart() {
t := suite.T()
require := suite.Require()

sb := suite.sb
serverURL := "localhost"
scenarioName := "plain-chart"
defaultAnnotationsKey := "images"
// customAnnotationsKey := "artifacthub.io/images"
scenarioDir := fmt.Sprintf("../testdata/scenarios/%s", scenarioName)

type testImage struct {
Name string
Registry string
Repository string
Tag string
Digest string
}

images := []testImage{
{
Name: "bitnami-shell",
Registry: "docker.io",
Repository: "bitnami/bitnami-shell",
Tag: "1.0.0",
},
{
Name: "wordpress",
Registry: "docker.io",
Repository: "bitnami/wordpress",
Tag: "latest",
},
}
t.Run("Annotates a chart", func(t *testing.T) {
dest := sb.TempFile()
chartDir := filepath.Join(dest, scenarioName)
annotationsKey := defaultAnnotationsKey
require.NoError(tu.RenderScenario(scenarioDir, dest,
map[string]interface{}{"ServerURL": serverURL, "ValuesImages": images},
))

expectedImages := make([]tu.AnnotationEntry, 0)
for _, img := range images {
url := fmt.Sprintf("%s/%s:%s", img.Registry, img.Repository, img.Tag)
expectedImages = append(expectedImages, tu.AnnotationEntry{
Name: img.Name,
Image: url,
})
}

require.NoError(AnnotateChart(chartDir, WithAnnotationsKey(annotationsKey)))
tu.AssertChartAnnotations(t, chartDir, annotationsKey, expectedImages)
})
}
150 changes: 150 additions & 0 deletions chartutils/images_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,150 @@
package chartutils

import (
"fmt"
"io"
"log"
"net/http/httptest"
"net/url"
"os"
"path/filepath"
"testing"

"github.com/google/go-containerregistry/pkg/crane"
"github.com/google/go-containerregistry/pkg/registry"
"github.com/vmware-labs/distribution-tooling-for-helm/imagelock"
tu "github.com/vmware-labs/distribution-tooling-for-helm/internal/testutil"
)

func (suite *ChartUtilsTestSuite) TestPullImages() {
require := suite.Require()
t := suite.T()

silentLog := log.New(io.Discard, "", 0)
s := httptest.NewServer(registry.New(registry.Logger(silentLog)))
defer s.Close()
u, err := url.Parse(s.URL)
if err != nil {
t.Fatal(err)
}

imageName := "test:mytag"

images, err := tu.AddSampleImagesToRegistry(imageName, u.Host)
if err != nil {
t.Fatal(err)
}

sb := suite.sb

serverURL := u.Host
scenarioName := "complete-chart"
chartName := "test"

scenarioDir := fmt.Sprintf("../testdata/scenarios/%s", scenarioName)

suite.T().Run("Pulls images", func(t *testing.T) {
dest := sb.TempFile()
require.NoError(tu.RenderScenario(scenarioDir, dest,
map[string]interface{}{"ServerURL": serverURL, "Images": images, "Name": chartName, "RepositoryURL": serverURL},
))
chartDir := filepath.Join(dest, scenarioName)
imagesDir := filepath.Join(chartDir, "images")

require.NoError(err)

lock, err := imagelock.FromYAMLFile(filepath.Join(chartDir, "Images.lock"))
require.NoError(err)
require.NoError(PullImages(lock, imagesDir))

require.DirExists(imagesDir)

for _, imgData := range images {
for _, digestData := range imgData.Digests {
imgFile := filepath.Join(imagesDir, fmt.Sprintf("%s.tar", digestData.Digest.Encoded()))
suite.Assert().FileExists(imgFile)
}
}
})
}

func (suite *ChartUtilsTestSuite) TestPushImages() {

t := suite.T()
sb := suite.sb
require := suite.Require()
assert := suite.Assert()

silentLog := log.New(io.Discard, "", 0)
s := httptest.NewServer(registry.New(registry.Logger(silentLog)))
defer s.Close()

u, err := url.Parse(s.URL)
if err != nil {
t.Fatal(err)
}
serverURL := u.Host

t.Run("Pushing works", func(t *testing.T) {
scenarioName := "complete-chart"
chartName := "test"

scenarioDir := fmt.Sprintf("../testdata/scenarios/%s", scenarioName)
imageName := "test:mytag"

imageData := tu.ImageData{Name: "test", Image: "test:mytag"}
architectures := []string{
"linux/amd64",
"linux/arm",
}
craneImgs, err := tu.CreateSampleImages(&imageData, architectures)

if err != nil {
t.Fatal(err)
}

require.Equal(len(architectures), len(imageData.Digests))

images := []tu.ImageData{imageData}
dest := sb.TempFile()
require.NoError(tu.RenderScenario(scenarioDir, dest,
map[string]interface{}{
"ServerURL": serverURL, "Images": images,
"Name": chartName, "RepositoryURL": serverURL,
},
))

chartDir := filepath.Join(dest, scenarioName)
imagesDir := filepath.Join(chartDir, "images")
require.NoError(os.MkdirAll(imagesDir, 0755))
for _, img := range craneImgs {
d, err := img.Digest()
if err != nil {
t.Fatal(err)
}
imgFile := filepath.Join(imagesDir, fmt.Sprintf("%s.tar", d.Hex))
if err := crane.Save(img, imageName, imgFile); err != nil {
t.Fatal(err)
}
}

t.Run("Push images", func(t *testing.T) {
require.NoError(err)
lock, err := imagelock.FromYAMLFile(filepath.Join(chartDir, "Images.lock"))
require.NoError(err)
require.NoError(PushImages(lock, imagesDir))

// Verify the images were pushed
for _, img := range images {
src := fmt.Sprintf("%s/%s", u.Host, img.Image)
remoteDigests, err := tu.ReadRemoteImageManifest(src)
if err != nil {
t.Fatal(err)
}
for _, dgstData := range img.Digests {
assert.Equal(dgstData.Digest.Hex(), remoteDigests[dgstData.Arch].Digest.Hex())
}
}
})
})
}
53 changes: 21 additions & 32 deletions cmd/dt/annotate_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -7,18 +7,11 @@ import (
"regexp"
"testing"

"gopkg.in/yaml.v3"
tu "github.com/vmware-labs/distribution-tooling-for-helm/internal/testutil"

"helm.sh/helm/v3/pkg/chart"
"helm.sh/helm/v3/pkg/chart/loader"

tu "github.com/vmware-labs/distribution-tooling-for-helm/internal/testutil"
)

type rawImageEntry struct {
Name string
Image string
}
type testImage struct {
Name string
Registry string
Expand All @@ -31,28 +24,12 @@ func (img *testImage) URL() string {
return fmt.Sprintf("%s/%s:%s", img.Registry, img.Repository, img.Tag)
}

func verifyChartAnnotations(suite *CmdSuite, chartDir string, annotationsKey string, expectedImages []testImage) *chart.Chart {
rawExpectedImages := make([]rawImageEntry, 0)
for _, img := range expectedImages {
rawExpectedImages = append(rawExpectedImages, rawImageEntry{
Name: img.Name,
Image: img.URL(),
})
}
require := suite.Require()

c, err := loader.Load(chartDir)
require.NoError(err)

gotImages := make([]rawImageEntry, 0)
require.NoError(yaml.Unmarshal([]byte(c.Metadata.Annotations[annotationsKey]), &gotImages))
suite.Assert().EqualValues(rawExpectedImages, gotImages)
return c
}

func (suite *CmdSuite) TestAnnotateCommand() {
sb := suite.sb
t := suite.T()
require := suite.Require()
assert := suite.Assert()

serverURL := "localhost"
scenarioName := "plain-chart"
defaultAnnotationsKey := "images"
Expand All @@ -77,7 +54,7 @@ func (suite *CmdSuite) TestAnnotateCommand() {
"Successfully annotates a Helm chart": "",
"Successfully annotates a Helm chart with custom key": customAnnotationsKey,
} {
suite.T().Run(title, func(t *testing.T) {
t.Run(title, func(t *testing.T) {
dest := sb.TempFile()
require.NoError(tu.RenderScenario(scenarioDir, dest,
map[string]interface{}{"ServerURL": serverURL, "ValuesImages": images},
Expand All @@ -94,10 +71,18 @@ func (suite *CmdSuite) TestAnnotateCommand() {
args = []string{"charts", "--annotations-key", key, "annotate", chartDir}
}
dt(args...).AssertSuccess(t)
_ = verifyChartAnnotations(suite, chartDir, key, images)

expectedImages := make([]tu.AnnotationEntry, 0)
for _, img := range images {
expectedImages = append(expectedImages, tu.AnnotationEntry{
Name: img.Name,
Image: img.URL(),
})
}
tu.AssertChartAnnotations(t, chartDir, key, expectedImages)
})
}
suite.T().Run("Corner cases", func(t *testing.T) {
t.Run("Corner cases", func(t *testing.T) {
t.Run("Handle empty image list case", func(t *testing.T) {
dest := sb.TempFile()
require.NoError(tu.RenderScenario(scenarioDir, dest,
Expand All @@ -107,8 +92,12 @@ func (suite *CmdSuite) TestAnnotateCommand() {
chartDir := filepath.Join(dest, scenarioName)
dt("charts", "annotate", chartDir).AssertSuccess(t)

c := verifyChartAnnotations(suite, chartDir, defaultAnnotationsKey, nil)
suite.Assert().Equal(0, len(c.Metadata.Annotations))
tu.AssertChartAnnotations(t, chartDir, defaultAnnotationsKey, make([]tu.AnnotationEntry, 0))

c, err := loader.Load(chartDir)
require.NoError(err)

assert.Equal(0, len(c.Metadata.Annotations))
})
t.Run("Handle errors annotating", func(t *testing.T) {
dest := sb.TempFile()
Expand Down
20 changes: 20 additions & 0 deletions cmd/dt/chart_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
package main

import (
"fmt"
"testing"
)

func (suite *CmdSuite) TestChartsHelp() {
t := suite.T()
t.Run("Shows Help", func(t *testing.T) {
res := dt("charts")
res.AssertSuccess(t)
for _, reStr := range []string{
`annotate\s+Annotates a Helm chart`,
`relocate\s+Relocates a Helm chart`,
} {
res.AssertSuccessMatch(t, fmt.Sprintf(`(?s).*Available Commands:.*\n\s*%s.*`, reStr))
}
})
}
Loading

0 comments on commit e3b6271

Please sign in to comment.