chore: enable testifylint

Signed-off-by: Matthieu MOREL <matthieu.morel35@gmail.com>
pull/30811/head
Matthieu MOREL 5 months ago
parent 505b487de2
commit 9bd8b3e6ea

@ -27,6 +27,7 @@ linters:
- nakedret - nakedret
- revive - revive
- staticcheck - staticcheck
- testifylint
- thelper - thelper
- unused - unused
- usestdlibvars - usestdlibvars
@ -64,6 +65,10 @@ linters:
- github.com/evanphx/json-patch: - github.com/evanphx/json-patch:
recommendations: recommendations:
- github.com/evanphx/json-patch/v5 - github.com/evanphx/json-patch/v5
testifylint:
suite-extra-assert-call:
mode: require
run: run:
timeout: 10m timeout: 10m

@ -50,7 +50,7 @@ func TestCRDs(t *testing.T) {
is := assert.New(t) is := assert.New(t)
crds := chrt.CRDs() crds := chrt.CRDs()
is.Equal(2, len(crds)) is.Len(crds, 2)
is.Equal("crds/foo.yaml", crds[0].Name) is.Equal("crds/foo.yaml", crds[0].Name)
is.Equal("crds/foo/bar/baz.yaml", crds[1].Name) is.Equal("crds/foo/bar/baz.yaml", crds[1].Name)
} }
@ -94,7 +94,7 @@ func TestMetadata(t *testing.T) {
is.Equal("foo.yaml", chrt.Name()) is.Equal("foo.yaml", chrt.Name())
is.Equal("1.0.0", chrt.AppVersion()) is.Equal("1.0.0", chrt.AppVersion())
is.Equal(nil, chrt.Validate()) is.NoError(chrt.Validate())
} }
func TestIsRoot(t *testing.T) { func TestIsRoot(t *testing.T) {
@ -114,8 +114,8 @@ func TestIsRoot(t *testing.T) {
is := assert.New(t) is := assert.New(t)
is.Equal(false, chrt1.IsRoot()) is.False(chrt1.IsRoot())
is.Equal(true, chrt2.IsRoot()) is.True(chrt2.IsRoot())
} }
func TestChartPath(t *testing.T) { func TestChartPath(t *testing.T) {

@ -23,6 +23,7 @@ import (
"testing" "testing"
"github.com/stretchr/testify/assert" "github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"
batchv1 "k8s.io/api/batch/v1" batchv1 "k8s.io/api/batch/v1"
corev1 "k8s.io/api/core/v1" corev1 "k8s.io/api/core/v1"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
@ -107,9 +108,9 @@ func TestJobConditions(t *testing.T) {
t.Run(tc.name, func(t *testing.T) { t.Run(tc.name, func(t *testing.T) {
t.Parallel() t.Parallel()
us, err := toUnstructured(t, tc.job) us, err := toUnstructured(t, tc.job)
assert.NoError(t, err) require.NoError(t, err)
result, err := jobConditions(us) result, err := jobConditions(us)
assert.NoError(t, err) require.NoError(t, err)
assert.Equal(t, tc.expectedStatus, result.Status) assert.Equal(t, tc.expectedStatus, result.Status)
}) })
} }

@ -20,6 +20,7 @@ import (
"testing" "testing"
"github.com/stretchr/testify/assert" "github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"
v1 "k8s.io/api/core/v1" v1 "k8s.io/api/core/v1"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
@ -102,9 +103,9 @@ func TestPodConditions(t *testing.T) {
t.Run(tc.name, func(t *testing.T) { t.Run(tc.name, func(t *testing.T) {
t.Parallel() t.Parallel()
us, err := toUnstructured(t, tc.pod) us, err := toUnstructured(t, tc.pod)
assert.NoError(t, err) require.NoError(t, err)
result, err := podConditions(us) result, err := podConditions(us)
assert.NoError(t, err) require.NoError(t, err)
assert.Equal(t, tc.expectedStatus, result.Status) assert.Equal(t, tc.expectedStatus, result.Status)
}) })
} }

@ -347,10 +347,9 @@ func TestConfiguration_Init(t *testing.T) {
actualErr := cfg.Init(nil, "default", tt.helmDriver) actualErr := cfg.Init(nil, "default", tt.helmDriver)
if tt.expectErr { if tt.expectErr {
assert.Error(t, actualErr) assert.ErrorContains(t, actualErr, tt.errMsg)
assert.Contains(t, actualErr.Error(), tt.errMsg)
} else { } else {
assert.NoError(t, actualErr) require.NoError(t, actualErr)
assert.IsType(t, tt.expectedDriverType, cfg.Releases.Driver) assert.IsType(t, tt.expectedDriverType, cfg.Releases.Driver)
} }
}) })
@ -539,10 +538,9 @@ metadata:
merged, err := annotateAndMerge(tt.files) merged, err := annotateAndMerge(tt.files)
if tt.expectedError != "" { if tt.expectedError != "" {
assert.Error(t, err) require.ErrorContains(t, err, tt.expectedError)
assert.Contains(t, err.Error(), tt.expectedError)
} else { } else {
assert.NoError(t, err) require.NoError(t, err)
assert.NotNil(t, merged) assert.NotNil(t, merged)
assert.Equal(t, tt.expected, merged) assert.Equal(t, tt.expected, merged)
} }
@ -702,11 +700,10 @@ data:
files, err := splitAndDeannotate(tt.input) files, err := splitAndDeannotate(tt.input)
if tt.expectedError != "" { if tt.expectedError != "" {
assert.Error(t, err) assert.ErrorContains(t, err, tt.expectedError)
assert.Contains(t, err.Error(), tt.expectedError)
} else { } else {
assert.NoError(t, err) require.NoError(t, err)
assert.Equal(t, len(tt.expectedFiles), len(files)) assert.Len(t, files, len(tt.expectedFiles))
for expectedFile, expectedContent := range tt.expectedFiles { for expectedFile, expectedContent := range tt.expectedFiles {
actualContent, exists := files[expectedFile] actualContent, exists := files[expectedFile]
@ -757,7 +754,7 @@ data:
require.NoError(t, err) require.NoError(t, err)
// Compare the results // Compare the results
assert.Equal(t, len(originalFiles), len(reconstructed)) assert.Len(t, reconstructed, len(originalFiles))
for filename, originalContent := range originalFiles { for filename, originalContent := range originalFiles {
reconstructedContent, exists := reconstructed[filename] reconstructedContent, exists := reconstructed[filename]
assert.True(t, exists, "File %s should exist in reconstructed files", filename) assert.True(t, exists, "File %s should exist in reconstructed files", filename)
@ -791,10 +788,10 @@ func TestRenderResources_PostRenderer_Success(t *testing.T) {
mockPR, false, false, false, mockPR, false, false, false,
) )
assert.NoError(t, err) require.NoError(t, err)
assert.NotNil(t, hooks) assert.NotNil(t, hooks)
assert.NotNil(t, buf) assert.NotNil(t, buf)
assert.Equal(t, "", notes) assert.Empty(t, notes)
expectedBuf := `--- expectedBuf := `---
# Source: yellow/templates/foodpie # Source: yellow/templates/foodpie
foodpie: world foodpie: world
@ -834,8 +831,7 @@ func TestRenderResources_PostRenderer_Error(t *testing.T) {
mockPR, false, false, false, mockPR, false, false, false,
) )
assert.Error(t, err) assert.ErrorContains(t, err, "error while running post render on files")
assert.Contains(t, err.Error(), "error while running post render on files")
} }
func TestRenderResources_PostRenderer_MergeError(t *testing.T) { func TestRenderResources_PostRenderer_MergeError(t *testing.T) {
@ -862,8 +858,7 @@ func TestRenderResources_PostRenderer_MergeError(t *testing.T) {
mockPR, false, false, false, mockPR, false, false, false,
) )
assert.Error(t, err) assert.ErrorContains(t, err, "error merging manifests")
assert.Contains(t, err.Error(), "error merging manifests")
} }
func TestRenderResources_PostRenderer_SplitError(t *testing.T) { func TestRenderResources_PostRenderer_SplitError(t *testing.T) {
@ -884,8 +879,8 @@ func TestRenderResources_PostRenderer_SplitError(t *testing.T) {
mockPR, false, false, false, mockPR, false, false, false,
) )
assert.Error(t, err) require.Error(t, err)
assert.Contains(t, err.Error(), "error while parsing post rendered output: error parsing YAML: MalformedYAMLError:") assert.ErrorContains(t, err, "error while parsing post rendered output: error parsing YAML: MalformedYAMLError:")
} }
func TestRenderResources_PostRenderer_Integration(t *testing.T) { func TestRenderResources_PostRenderer_Integration(t *testing.T) {
@ -905,10 +900,10 @@ func TestRenderResources_PostRenderer_Integration(t *testing.T) {
mockPR, false, false, false, mockPR, false, false, false,
) )
assert.NoError(t, err) require.NoError(t, err)
assert.NotNil(t, hooks) assert.NotNil(t, hooks)
assert.NotNil(t, buf) assert.NotNil(t, buf)
assert.Equal(t, "", notes) // Notes should be empty for this test assert.Empty(t, notes) // Notes should be empty for this test
// Verify that the post-renderer modifications are present in the output // Verify that the post-renderer modifications are present in the output
output := buf.String() output := buf.String()
@ -941,8 +936,8 @@ func TestRenderResources_NoPostRenderer(t *testing.T) {
nil, false, false, false, nil, false, false, false,
) )
assert.NoError(t, err) require.NoError(t, err)
assert.NotNil(t, hooks) assert.NotNil(t, hooks)
assert.NotNil(t, buf) assert.NotNil(t, buf)
assert.Equal(t, "", notes) assert.Empty(t, notes)
} }

@ -23,6 +23,7 @@ import (
"testing" "testing"
"github.com/stretchr/testify/assert" "github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"
"helm.sh/helm/v4/internal/test" "helm.sh/helm/v4/internal/test"
chart "helm.sh/helm/v4/pkg/chart/v2" chart "helm.sh/helm/v4/pkg/chart/v2"
@ -70,7 +71,7 @@ func TestDependencyStatus_Dashes(t *testing.T) {
dir := t.TempDir() dir := t.TempDir()
chartpath := filepath.Join(dir, "charts") chartpath := filepath.Join(dir, "charts")
if err := os.MkdirAll(chartpath, 0700); err != nil { if err := os.MkdirAll(chartpath, 0o700); err != nil {
t.Fatal(err) t.Fatal(err)
} }
@ -104,7 +105,7 @@ func TestStatArchiveForStatus(t *testing.T) {
dir := t.TempDir() dir := t.TempDir()
chartpath := filepath.Join(dir, "charts") chartpath := filepath.Join(dir, "charts")
if err := os.MkdirAll(chartpath, 0700); err != nil { if err := os.MkdirAll(chartpath, 0o700); err != nil {
t.Fatal(err) t.Fatal(err)
} }
@ -118,13 +119,14 @@ func TestStatArchiveForStatus(t *testing.T) {
} }
is := assert.New(t) is := assert.New(t)
req := require.New(t)
lilithpath := filepath.Join(chartpath, "lilith-1.2.3.tgz") lilithpath := filepath.Join(chartpath, "lilith-1.2.3.tgz")
is.Empty(statArchiveForStatus(lilithpath, dep)) is.Empty(statArchiveForStatus(lilithpath, dep))
// save the chart (version 0.1.0, because that is the default) // save the chart (version 0.1.0, because that is the default)
where, err := chartutil.Save(lilith, chartpath) where, err := chartutil.Save(lilith, chartpath)
is.NoError(err) req.NoError(err)
// Should get "wrong version" because we asked for 1.2.3 and got 0.1.0 // Should get "wrong version" because we asked for 1.2.3 and got 0.1.0
is.Equal("wrong version", statArchiveForStatus(where, dep)) is.Equal("wrong version", statArchiveForStatus(where, dep))

@ -267,9 +267,9 @@ func TestGetMetadata_Run_WithMixedDependencies(t *testing.T) {
// Verify dependencies without aliases // Verify dependencies without aliases
assert.Equal(t, "nginx", result.Dependencies[1].Name) assert.Equal(t, "nginx", result.Dependencies[1].Name)
assert.Equal(t, "", result.Dependencies[1].Alias) assert.Empty(t, result.Dependencies[1].Alias)
assert.Equal(t, "postgresql", result.Dependencies[3].Name) assert.Equal(t, "postgresql", result.Dependencies[3].Name)
assert.Equal(t, "", result.Dependencies[3].Alias) assert.Empty(t, result.Dependencies[3].Alias)
} }
func TestGetMetadata_Run_WithAnnotations(t *testing.T) { func TestGetMetadata_Run_WithAnnotations(t *testing.T) {
@ -431,8 +431,7 @@ func TestGetMetadata_Run_UnreachableKubeClient(t *testing.T) {
client := NewGetMetadata(cfg) client := NewGetMetadata(cfg)
_, err := client.Run("test-release") _, err := client.Run("test-release")
assert.Error(t, err) assert.ErrorContains(t, err, "connection refused")
assert.Contains(t, err.Error(), "connection refused")
} }
func TestGetMetadata_Run_ReleaseNotFound(t *testing.T) { func TestGetMetadata_Run_ReleaseNotFound(t *testing.T) {
@ -440,8 +439,7 @@ func TestGetMetadata_Run_ReleaseNotFound(t *testing.T) {
client := NewGetMetadata(cfg) client := NewGetMetadata(cfg)
_, err := client.Run("non-existent-release") _, err := client.Run("non-existent-release")
assert.Error(t, err) assert.ErrorContains(t, err, "not found")
assert.Contains(t, err.Error(), "not found")
} }
func TestGetMetadata_Run_EmptyAppVersion(t *testing.T) { func TestGetMetadata_Run_EmptyAppVersion(t *testing.T) {
@ -473,7 +471,7 @@ func TestGetMetadata_Run_EmptyAppVersion(t *testing.T) {
result, err := client.Run(releaseName) result, err := client.Run(releaseName)
require.NoError(t, err) require.NoError(t, err)
assert.Equal(t, "", result.AppVersion) assert.Empty(t, result.AppVersion)
} }
func TestMetadata_FormattedDepNames(t *testing.T) { func TestMetadata_FormattedDepNames(t *testing.T) {
@ -625,10 +623,10 @@ func TestGetMetadata_Labels(t *testing.T) {
metaGetter := NewGetMetadata(actionConfigFixture(t)) metaGetter := NewGetMetadata(actionConfigFixture(t))
err := metaGetter.cfg.Releases.Create(rel) err := metaGetter.cfg.Releases.Create(rel)
assert.NoError(t, err) require.NoError(t, err)
metadata, err := metaGetter.Run(rel.Name) metadata, err := metaGetter.Run(rel.Name)
assert.NoError(t, err) require.NoError(t, err)
assert.Equal(t, metadata.Name, rel.Name) assert.Equal(t, metadata.Name, rel.Name)
assert.Equal(t, metadata.Labels, customLabels) assert.Equal(t, metadata.Labels, customLabels)

@ -35,7 +35,7 @@ func TestNewGetValues(t *testing.T) {
assert.NotNil(t, client) assert.NotNil(t, client)
assert.Equal(t, cfg, client.cfg) assert.Equal(t, cfg, client.cfg)
assert.Equal(t, 0, client.Version) assert.Equal(t, 0, client.Version)
assert.Equal(t, false, client.AllValues) assert.False(t, client.AllValues)
} }
func TestGetValues_Run_UserConfigOnly(t *testing.T) { func TestGetValues_Run_UserConfigOnly(t *testing.T) {
@ -175,8 +175,7 @@ func TestGetValues_Run_UnreachableKubeClient(t *testing.T) {
client := NewGetValues(cfg) client := NewGetValues(cfg)
_, err := client.Run("test-release") _, err := client.Run("test-release")
assert.Error(t, err) assert.ErrorContains(t, err, "connection refused")
assert.Contains(t, err.Error(), "connection refused")
} }
func TestGetValues_Run_ReleaseNotFound(t *testing.T) { func TestGetValues_Run_ReleaseNotFound(t *testing.T) {
@ -184,8 +183,7 @@ func TestGetValues_Run_ReleaseNotFound(t *testing.T) {
client := NewGetValues(cfg) client := NewGetValues(cfg)
_, err := client.Run("non-existent-release") _, err := client.Run("non-existent-release")
assert.Error(t, err) assert.ErrorContains(t, err, "not found")
assert.Contains(t, err.Error(), "not found")
} }
func TestGetValues_Run_NilConfig(t *testing.T) { func TestGetValues_Run_NilConfig(t *testing.T) {

@ -25,6 +25,7 @@ import (
"time" "time"
"github.com/stretchr/testify/assert" "github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"
v1 "k8s.io/api/core/v1" v1 "k8s.io/api/core/v1"
"k8s.io/apimachinery/pkg/util/yaml" "k8s.io/apimachinery/pkg/util/yaml"
"k8s.io/cli-runtime/pkg/resource" "k8s.io/cli-runtime/pkg/resource"
@ -173,6 +174,7 @@ func runInstallForHooksWithSuccess(t *testing.T, manifest, expectedNamespace str
expectedOutput = fmt.Sprintf("attempted to output logs for namespace: %s", expectedNamespace) expectedOutput = fmt.Sprintf("attempted to output logs for namespace: %s", expectedNamespace)
} }
is := assert.New(t) is := assert.New(t)
req := require.New(t)
instAction := installAction(t) instAction := installAction(t)
instAction.ReleaseName = "failed-hooks" instAction.ReleaseName = "failed-hooks"
outBuffer := &bytes.Buffer{} outBuffer := &bytes.Buffer{}
@ -185,7 +187,7 @@ func runInstallForHooksWithSuccess(t *testing.T, manifest, expectedNamespace str
vals := map[string]interface{}{} vals := map[string]interface{}{}
res, err := instAction.Run(buildChartWithTemplates(templates), vals) res, err := instAction.Run(buildChartWithTemplates(templates), vals)
is.NoError(err) req.NoError(err)
is.Equal(expectedOutput, outBuffer.String()) is.Equal(expectedOutput, outBuffer.String())
is.Equal(release.StatusDeployed, res.Info.Status) is.Equal(release.StatusDeployed, res.Info.Status)
} }
@ -197,6 +199,7 @@ func runInstallForHooksWithFailure(t *testing.T, manifest, expectedNamespace str
expectedOutput = fmt.Sprintf("attempted to output logs for namespace: %s", expectedNamespace) expectedOutput = fmt.Sprintf("attempted to output logs for namespace: %s", expectedNamespace)
} }
is := assert.New(t) is := assert.New(t)
req := require.New(t)
instAction := installAction(t) instAction := installAction(t)
instAction.ReleaseName = "failed-hooks" instAction.ReleaseName = "failed-hooks"
failingClient := instAction.cfg.KubeClient.(*kubefake.FailingKubeClient) failingClient := instAction.cfg.KubeClient.(*kubefake.FailingKubeClient)
@ -212,7 +215,7 @@ func runInstallForHooksWithFailure(t *testing.T, manifest, expectedNamespace str
vals := map[string]interface{}{} vals := map[string]interface{}{}
res, err := instAction.Run(buildChartWithTemplates(templates), vals) res, err := instAction.Run(buildChartWithTemplates(templates), vals)
is.Error(err) req.Error(err)
is.Contains(res.Info.Description, "failed pre-install") is.Contains(res.Info.Description, "failed pre-install")
is.Equal(expectedOutput, outBuffer.String()) is.Equal(expectedOutput, outBuffer.String())
is.Equal(release.StatusFailed, res.Info.Status) is.Equal(release.StatusFailed, res.Info.Status)
@ -239,7 +242,6 @@ func (*HookFailingKubeClient) Build(reader io.Reader, _ bool) (kube.ResourceList
configMap := &v1.ConfigMap{} configMap := &v1.ConfigMap{}
err := yaml.NewYAMLOrJSONDecoder(reader, 1000).Decode(configMap) err := yaml.NewYAMLOrJSONDecoder(reader, 1000).Decode(configMap)
if err != nil { if err != nil {
return kube.ResourceList{}, err return kube.ResourceList{}, err
} }
@ -345,10 +347,12 @@ data:
}, },
}, },
}, },
}, resource.Info{ },
resource.Info{
Name: "build-config-2", Name: "build-config-2",
Namespace: "test", Namespace: "test",
}, []resource.Info{ },
[]resource.Info{
{ {
// This should be in the record for `before-hook-creation` // This should be in the record for `before-hook-creation`
Name: "build-config-1", Name: "build-config-1",
@ -369,7 +373,8 @@ data:
Name: "build-config-1", Name: "build-config-1",
Namespace: "test", Namespace: "test",
}, },
}, true, },
true,
}, },
} }

@ -19,7 +19,6 @@ package action
import ( import (
"bytes" "bytes"
"context" "context"
"errors"
"fmt" "fmt"
"io" "io"
"io/fs" "io/fs"
@ -137,21 +136,21 @@ func TestInstallRelease(t *testing.T) {
if err != nil { if err != nil {
t.Fatalf("Failed install: %s", err) t.Fatalf("Failed install: %s", err)
} }
is.Equal(res.Name, "test-install-release", "Expected release name.") is.Equal("test-install-release", res.Name, "Expected release name.")
is.Equal(res.Namespace, "spaced") is.Equal("spaced", res.Namespace)
rel, err := instAction.cfg.Releases.Get(res.Name, res.Version) rel, err := instAction.cfg.Releases.Get(res.Name, res.Version)
is.NoError(err) req.NoError(err)
is.Len(rel.Hooks, 1) is.Len(rel.Hooks, 1)
is.Equal(rel.Hooks[0].Manifest, manifestWithHook) is.Equal(rel.Hooks[0].Manifest, manifestWithHook)
is.Equal(rel.Hooks[0].Events[0], release.HookPostInstall) is.Equal(release.HookPostInstall, rel.Hooks[0].Events[0])
is.Equal(rel.Hooks[0].Events[1], release.HookPreDelete, "Expected event 0 is pre-delete") is.Equal(release.HookPreDelete, rel.Hooks[0].Events[1], "Expected event 0 is pre-delete")
is.NotEqual(len(res.Manifest), 0) is.NotEmpty(res.Manifest)
is.NotEqual(len(rel.Manifest), 0) is.NotEmpty(rel.Manifest)
is.Contains(rel.Manifest, "---\n# Source: hello/templates/hello\nhello: world") is.Contains(rel.Manifest, "---\n# Source: hello/templates/hello\nhello: world")
is.Equal(rel.Info.Description, "Install complete") is.Equal("Install complete", rel.Info.Description)
// Detecting previous bug where context termination after successful release // Detecting previous bug where context termination after successful release
// caused release to fail. // caused release to fail.
@ -159,7 +158,7 @@ func TestInstallRelease(t *testing.T) {
time.Sleep(time.Millisecond * 100) time.Sleep(time.Millisecond * 100)
lastRelease, err := instAction.cfg.Releases.Last(rel.Name) lastRelease, err := instAction.cfg.Releases.Last(rel.Name)
req.NoError(err) req.NoError(err)
is.Equal(lastRelease.Info.Status, release.StatusDeployed) is.Equal(release.StatusDeployed, lastRelease.Info.Status)
} }
func TestInstallReleaseWithTakeOwnership_ResourceNotOwned(t *testing.T) { func TestInstallReleaseWithTakeOwnership_ResourceNotOwned(t *testing.T) {
@ -173,6 +172,7 @@ func TestInstallReleaseWithTakeOwnership_ResourceNotOwned(t *testing.T) {
// "Client{Namespace: namespace, kubeClient: k8sfake.NewClientset()}" // "Client{Namespace: namespace, kubeClient: k8sfake.NewClientset()}"
is := assert.New(t) is := assert.New(t)
req := require.New(t)
// Resource list from cluster is NOT owned by helm chart // Resource list from cluster is NOT owned by helm chart
config := actionConfigFixtureWithDummyResources(t, createDummyResourceList(false)) config := actionConfigFixtureWithDummyResources(t, createDummyResourceList(false))
@ -184,13 +184,14 @@ func TestInstallReleaseWithTakeOwnership_ResourceNotOwned(t *testing.T) {
} }
rel, err := instAction.cfg.Releases.Get(res.Name, res.Version) rel, err := instAction.cfg.Releases.Get(res.Name, res.Version)
is.NoError(err) req.NoError(err)
is.Equal(rel.Info.Description, "Install complete") is.Equal("Install complete", rel.Info.Description)
} }
func TestInstallReleaseWithTakeOwnership_ResourceOwned(t *testing.T) { func TestInstallReleaseWithTakeOwnership_ResourceOwned(t *testing.T) {
is := assert.New(t) is := assert.New(t)
req := require.New(t)
// Resource list from cluster is owned by helm chart // Resource list from cluster is owned by helm chart
config := actionConfigFixtureWithDummyResources(t, createDummyResourceList(true)) config := actionConfigFixtureWithDummyResources(t, createDummyResourceList(true))
@ -201,9 +202,9 @@ func TestInstallReleaseWithTakeOwnership_ResourceOwned(t *testing.T) {
t.Fatalf("Failed install: %s", err) t.Fatalf("Failed install: %s", err)
} }
rel, err := instAction.cfg.Releases.Get(res.Name, res.Version) rel, err := instAction.cfg.Releases.Get(res.Name, res.Version)
is.NoError(err) req.NoError(err)
is.Equal(rel.Info.Description, "Install complete") is.Equal("Install complete", rel.Info.Description)
} }
func TestInstallReleaseWithTakeOwnership_ResourceOwnedNoFlag(t *testing.T) { func TestInstallReleaseWithTakeOwnership_ResourceOwnedNoFlag(t *testing.T) {
@ -213,12 +214,12 @@ func TestInstallReleaseWithTakeOwnership_ResourceOwnedNoFlag(t *testing.T) {
config := actionConfigFixtureWithDummyResources(t, createDummyResourceList(false)) config := actionConfigFixtureWithDummyResources(t, createDummyResourceList(false))
instAction := installActionWithConfig(config) instAction := installActionWithConfig(config)
_, err := instAction.Run(buildChart(), nil) _, err := instAction.Run(buildChart(), nil)
is.Error(err) is.ErrorContains(err, "unable to continue with install")
is.Contains(err.Error(), "unable to continue with install")
} }
func TestInstallReleaseWithValues(t *testing.T) { func TestInstallReleaseWithValues(t *testing.T) {
is := assert.New(t) is := assert.New(t)
req := require.New(t)
instAction := installAction(t) instAction := installAction(t)
userVals := map[string]interface{}{ userVals := map[string]interface{}{
"nestedKey": map[string]interface{}{ "nestedKey": map[string]interface{}{
@ -234,19 +235,19 @@ func TestInstallReleaseWithValues(t *testing.T) {
if err != nil { if err != nil {
t.Fatalf("Failed install: %s", err) t.Fatalf("Failed install: %s", err)
} }
is.Equal(res.Name, "test-install-release", "Expected release name.") is.Equal("test-install-release", res.Name, "Expected release name.")
is.Equal(res.Namespace, "spaced") is.Equal("spaced", res.Namespace)
rel, err := instAction.cfg.Releases.Get(res.Name, res.Version) rel, err := instAction.cfg.Releases.Get(res.Name, res.Version)
is.NoError(err) req.NoError(err)
is.Len(rel.Hooks, 1) is.Len(rel.Hooks, 1)
is.Equal(rel.Hooks[0].Manifest, manifestWithHook) is.Equal(rel.Hooks[0].Manifest, manifestWithHook)
is.Equal(rel.Hooks[0].Events[0], release.HookPostInstall) is.Equal(release.HookPostInstall, rel.Hooks[0].Events[0])
is.Equal(rel.Hooks[0].Events[1], release.HookPreDelete, "Expected event 0 is pre-delete") is.Equal(release.HookPreDelete, rel.Hooks[0].Events[1], "Expected event 0 is pre-delete")
is.NotEqual(len(res.Manifest), 0) is.NotEmpty(res.Manifest)
is.NotEqual(len(rel.Manifest), 0) is.NotEmpty(rel.Manifest)
is.Contains(rel.Manifest, "---\n# Source: hello/templates/hello\nhello: world") is.Contains(rel.Manifest, "---\n# Source: hello/templates/hello\nhello: world")
is.Equal("Install complete", rel.Info.Description) is.Equal("Install complete", rel.Info.Description)
is.Equal(expectedUserValues, rel.Config) is.Equal(expectedUserValues, rel.Config)
@ -259,7 +260,7 @@ func TestInstallReleaseClientOnly(t *testing.T) {
instAction.Run(buildChart(), nil) // disregard output instAction.Run(buildChart(), nil) // disregard output
is.Equal(instAction.cfg.Capabilities, chartutil.DefaultCapabilities) is.Equal(instAction.cfg.Capabilities, chartutil.DefaultCapabilities)
is.Equal(instAction.cfg.KubeClient, &kubefake.PrintingKubeClient{Out: io.Discard}) is.Equal(&kubefake.PrintingKubeClient{Out: io.Discard}, instAction.cfg.KubeClient)
} }
func TestInstallRelease_NoName(t *testing.T) { func TestInstallRelease_NoName(t *testing.T) {
@ -270,11 +271,12 @@ func TestInstallRelease_NoName(t *testing.T) {
if err == nil { if err == nil {
t.Fatal("expected failure when no name is specified") t.Fatal("expected failure when no name is specified")
} }
assert.Contains(t, err.Error(), "no name provided") assert.ErrorContains(t, err, "no name provided")
} }
func TestInstallRelease_WithNotes(t *testing.T) { func TestInstallRelease_WithNotes(t *testing.T) {
is := assert.New(t) is := assert.New(t)
req := require.New(t)
instAction := installAction(t) instAction := installAction(t)
instAction.ReleaseName = "with-notes" instAction.ReleaseName = "with-notes"
vals := map[string]interface{}{} vals := map[string]interface{}{}
@ -283,25 +285,26 @@ func TestInstallRelease_WithNotes(t *testing.T) {
t.Fatalf("Failed install: %s", err) t.Fatalf("Failed install: %s", err)
} }
is.Equal(res.Name, "with-notes") is.Equal("with-notes", res.Name)
is.Equal(res.Namespace, "spaced") is.Equal("spaced", res.Namespace)
rel, err := instAction.cfg.Releases.Get(res.Name, res.Version) rel, err := instAction.cfg.Releases.Get(res.Name, res.Version)
is.NoError(err) req.NoError(err)
is.Len(rel.Hooks, 1) is.Len(rel.Hooks, 1)
is.Equal(rel.Hooks[0].Manifest, manifestWithHook) is.Equal(rel.Hooks[0].Manifest, manifestWithHook)
is.Equal(rel.Hooks[0].Events[0], release.HookPostInstall) is.Equal(release.HookPostInstall, rel.Hooks[0].Events[0])
is.Equal(rel.Hooks[0].Events[1], release.HookPreDelete, "Expected event 0 is pre-delete") is.Equal(release.HookPreDelete, rel.Hooks[0].Events[1], "Expected event 0 is pre-delete")
is.NotEqual(len(res.Manifest), 0) is.NotEmpty(res.Manifest)
is.NotEqual(len(rel.Manifest), 0) is.NotEmpty(rel.Manifest)
is.Contains(rel.Manifest, "---\n# Source: hello/templates/hello\nhello: world") is.Contains(rel.Manifest, "---\n# Source: hello/templates/hello\nhello: world")
is.Equal(rel.Info.Description, "Install complete") is.Equal("Install complete", rel.Info.Description)
is.Equal(rel.Info.Notes, "note here") is.Equal("note here", rel.Info.Notes)
} }
func TestInstallRelease_WithNotesRendered(t *testing.T) { func TestInstallRelease_WithNotesRendered(t *testing.T) {
is := assert.New(t) is := assert.New(t)
req := require.New(t)
instAction := installAction(t) instAction := installAction(t)
instAction.ReleaseName = "with-notes" instAction.ReleaseName = "with-notes"
vals := map[string]interface{}{} vals := map[string]interface{}{}
@ -311,16 +314,17 @@ func TestInstallRelease_WithNotesRendered(t *testing.T) {
} }
rel, err := instAction.cfg.Releases.Get(res.Name, res.Version) rel, err := instAction.cfg.Releases.Get(res.Name, res.Version)
is.NoError(err) req.NoError(err)
expectedNotes := fmt.Sprintf("got-%s", res.Name) expectedNotes := fmt.Sprintf("got-%s", res.Name)
is.Equal(expectedNotes, rel.Info.Notes) is.Equal(expectedNotes, rel.Info.Notes)
is.Equal(rel.Info.Description, "Install complete") is.Equal("Install complete", rel.Info.Description)
} }
func TestInstallRelease_WithChartAndDependencyParentNotes(t *testing.T) { func TestInstallRelease_WithChartAndDependencyParentNotes(t *testing.T) {
// Regression: Make sure that the child's notes don't override the parent's // Regression: Make sure that the child's notes don't override the parent's
is := assert.New(t) is := assert.New(t)
req := require.New(t)
instAction := installAction(t) instAction := installAction(t)
instAction.ReleaseName = "with-notes" instAction.ReleaseName = "with-notes"
vals := map[string]interface{}{} vals := map[string]interface{}{}
@ -331,14 +335,15 @@ func TestInstallRelease_WithChartAndDependencyParentNotes(t *testing.T) {
rel, err := instAction.cfg.Releases.Get(res.Name, res.Version) rel, err := instAction.cfg.Releases.Get(res.Name, res.Version)
is.Equal("with-notes", rel.Name) is.Equal("with-notes", rel.Name)
is.NoError(err) req.NoError(err)
is.Equal("parent", rel.Info.Notes) is.Equal("parent", rel.Info.Notes)
is.Equal(rel.Info.Description, "Install complete") is.Equal("Install complete", rel.Info.Description)
} }
func TestInstallRelease_WithChartAndDependencyAllNotes(t *testing.T) { func TestInstallRelease_WithChartAndDependencyAllNotes(t *testing.T) {
// Regression: Make sure that the child's notes don't override the parent's // Regression: Make sure that the child's notes don't override the parent's
is := assert.New(t) is := assert.New(t)
req := require.New(t)
instAction := installAction(t) instAction := installAction(t)
instAction.ReleaseName = "with-notes" instAction.ReleaseName = "with-notes"
instAction.SubNotes = true instAction.SubNotes = true
@ -350,16 +355,17 @@ func TestInstallRelease_WithChartAndDependencyAllNotes(t *testing.T) {
rel, err := instAction.cfg.Releases.Get(res.Name, res.Version) rel, err := instAction.cfg.Releases.Get(res.Name, res.Version)
is.Equal("with-notes", rel.Name) is.Equal("with-notes", rel.Name)
is.NoError(err) req.NoError(err)
// test run can return as either 'parent\nchild' or 'child\nparent' // test run can return as either 'parent\nchild' or 'child\nparent'
if !strings.Contains(rel.Info.Notes, "parent") && !strings.Contains(rel.Info.Notes, "child") { if !strings.Contains(rel.Info.Notes, "parent") && !strings.Contains(rel.Info.Notes, "child") {
t.Fatalf("Expected 'parent\nchild' or 'child\nparent', got '%s'", rel.Info.Notes) t.Fatalf("Expected 'parent\nchild' or 'child\nparent', got '%s'", rel.Info.Notes)
} }
is.Equal(rel.Info.Description, "Install complete") is.Equal("Install complete", rel.Info.Description)
} }
func TestInstallRelease_DryRun(t *testing.T) { func TestInstallRelease_DryRun(t *testing.T) {
is := assert.New(t) is := assert.New(t)
req := require.New(t)
instAction := installAction(t) instAction := installAction(t)
instAction.DryRun = true instAction.DryRun = true
vals := map[string]interface{}{} vals := map[string]interface{}{}
@ -375,14 +381,15 @@ func TestInstallRelease_DryRun(t *testing.T) {
is.NotContains(res.Manifest, "empty") is.NotContains(res.Manifest, "empty")
_, err = instAction.cfg.Releases.Get(res.Name, res.Version) _, err = instAction.cfg.Releases.Get(res.Name, res.Version)
is.Error(err) req.Error(err)
is.Len(res.Hooks, 1) is.Len(res.Hooks, 1)
is.True(res.Hooks[0].LastRun.CompletedAt.IsZero(), "expect hook to not be marked as run") is.True(res.Hooks[0].LastRun.CompletedAt.IsZero(), "expect hook to not be marked as run")
is.Equal(res.Info.Description, "Dry run complete") is.Equal("Dry run complete", res.Info.Description)
} }
func TestInstallRelease_DryRunHiddenSecret(t *testing.T) { func TestInstallRelease_DryRunHiddenSecret(t *testing.T) {
is := assert.New(t) is := assert.New(t)
req := require.New(t)
instAction := installAction(t) instAction := installAction(t)
// First perform a normal dry-run with the secret and confirm its presence. // First perform a normal dry-run with the secret and confirm its presence.
@ -395,8 +402,8 @@ func TestInstallRelease_DryRunHiddenSecret(t *testing.T) {
is.Contains(res.Manifest, "---\n# Source: hello/templates/secret.yaml\napiVersion: v1\nkind: Secret") is.Contains(res.Manifest, "---\n# Source: hello/templates/secret.yaml\napiVersion: v1\nkind: Secret")
_, err = instAction.cfg.Releases.Get(res.Name, res.Version) _, err = instAction.cfg.Releases.Get(res.Name, res.Version)
is.Error(err) req.Error(err)
is.Equal(res.Info.Description, "Dry run complete") is.Equal("Dry run complete", res.Info.Description)
// Perform a dry-run where the secret should not be present // Perform a dry-run where the secret should not be present
instAction.HideSecret = true instAction.HideSecret = true
@ -409,8 +416,8 @@ func TestInstallRelease_DryRunHiddenSecret(t *testing.T) {
is.NotContains(res2.Manifest, "---\n# Source: hello/templates/secret.yaml\napiVersion: v1\nkind: Secret") is.NotContains(res2.Manifest, "---\n# Source: hello/templates/secret.yaml\napiVersion: v1\nkind: Secret")
_, err = instAction.cfg.Releases.Get(res2.Name, res2.Version) _, err = instAction.cfg.Releases.Get(res2.Name, res2.Version)
is.Error(err) req.Error(err)
is.Equal(res2.Info.Description, "Dry run complete") is.Equal("Dry run complete", res2.Info.Description)
// Ensure there is an error when HideSecret True but not in a dry-run mode // Ensure there is an error when HideSecret True but not in a dry-run mode
instAction.DryRun = false instAction.DryRun = false
@ -455,7 +462,7 @@ func TestInstallReleaseIncorrectTemplate_DryRun(t *testing.T) {
t.Fatalf("Install should fail containing error: %s", expectedErr) t.Fatalf("Install should fail containing error: %s", expectedErr)
} }
if err != nil { if err != nil {
is.Contains(err.Error(), expectedErr) is.ErrorContains(err, expectedErr)
} }
} }
@ -477,6 +484,7 @@ func TestInstallRelease_NoHooks(t *testing.T) {
func TestInstallRelease_FailedHooks(t *testing.T) { func TestInstallRelease_FailedHooks(t *testing.T) {
is := assert.New(t) is := assert.New(t)
req := require.New(t)
instAction := installAction(t) instAction := installAction(t)
instAction.ReleaseName = "failed-hooks" instAction.ReleaseName = "failed-hooks"
failer := instAction.cfg.KubeClient.(*kubefake.FailingKubeClient) failer := instAction.cfg.KubeClient.(*kubefake.FailingKubeClient)
@ -487,14 +495,15 @@ func TestInstallRelease_FailedHooks(t *testing.T) {
vals := map[string]interface{}{} vals := map[string]interface{}{}
res, err := instAction.Run(buildChart(), vals) res, err := instAction.Run(buildChart(), vals)
is.Error(err) req.Error(err)
is.Contains(res.Info.Description, "failed post-install") is.Contains(res.Info.Description, "failed post-install")
is.Equal("", outBuffer.String()) is.Empty(outBuffer.String())
is.Equal(release.StatusFailed, res.Info.Status) is.Equal(release.StatusFailed, res.Info.Status)
} }
func TestInstallRelease_ReplaceRelease(t *testing.T) { func TestInstallRelease_ReplaceRelease(t *testing.T) {
is := assert.New(t) is := assert.New(t)
req := require.New(t)
instAction := installAction(t) instAction := installAction(t)
instAction.Replace = true instAction.Replace = true
@ -505,34 +514,35 @@ func TestInstallRelease_ReplaceRelease(t *testing.T) {
vals := map[string]interface{}{} vals := map[string]interface{}{}
res, err := instAction.Run(buildChart(), vals) res, err := instAction.Run(buildChart(), vals)
is.NoError(err) req.NoError(err)
// This should have been auto-incremented // This should have been auto-incremented
is.Equal(2, res.Version) is.Equal(2, res.Version)
is.Equal(res.Name, rel.Name) is.Equal(res.Name, rel.Name)
getres, err := instAction.cfg.Releases.Get(rel.Name, res.Version) getres, err := instAction.cfg.Releases.Get(rel.Name, res.Version)
is.NoError(err) req.NoError(err)
is.Equal(getres.Info.Status, release.StatusDeployed) is.Equal(release.StatusDeployed, getres.Info.Status)
} }
func TestInstallRelease_KubeVersion(t *testing.T) { func TestInstallRelease_KubeVersion(t *testing.T) {
is := assert.New(t) is := assert.New(t)
req := require.New(t)
instAction := installAction(t) instAction := installAction(t)
vals := map[string]interface{}{} vals := map[string]interface{}{}
_, err := instAction.Run(buildChart(withKube(">=0.0.0")), vals) _, err := instAction.Run(buildChart(withKube(">=0.0.0")), vals)
is.NoError(err) req.NoError(err)
// This should fail for a few hundred years // This should fail for a few hundred years
instAction.ReleaseName = "should-fail" instAction.ReleaseName = "should-fail"
vals = map[string]interface{}{} vals = map[string]interface{}{}
_, err = instAction.Run(buildChart(withKube(">=99.0.0")), vals) _, err = instAction.Run(buildChart(withKube(">=99.0.0")), vals)
is.Error(err) is.ErrorContains(err, "chart requires kubeVersion")
is.Contains(err.Error(), "chart requires kubeVersion")
} }
func TestInstallRelease_Wait(t *testing.T) { func TestInstallRelease_Wait(t *testing.T) {
is := assert.New(t) is := assert.New(t)
req := require.New(t)
instAction := installAction(t) instAction := installAction(t)
instAction.ReleaseName = "come-fail-away" instAction.ReleaseName = "come-fail-away"
failer := instAction.cfg.KubeClient.(*kubefake.FailingKubeClient) failer := instAction.cfg.KubeClient.(*kubefake.FailingKubeClient)
@ -544,14 +554,16 @@ func TestInstallRelease_Wait(t *testing.T) {
goroutines := runtime.NumGoroutine() goroutines := runtime.NumGoroutine()
res, err := instAction.Run(buildChart(), vals) res, err := instAction.Run(buildChart(), vals)
is.Error(err) req.Error(err)
is.Contains(res.Info.Description, "I timed out") is.Contains(res.Info.Description, "I timed out")
is.Equal(res.Info.Status, release.StatusFailed) is.Equal(release.StatusFailed, res.Info.Status)
is.Equal(goroutines, runtime.NumGoroutine()) is.Equal(goroutines, runtime.NumGoroutine())
} }
func TestInstallRelease_Wait_Interrupted(t *testing.T) { func TestInstallRelease_Wait_Interrupted(t *testing.T) {
is := assert.New(t) is := assert.New(t)
req := require.New(t)
instAction := installAction(t) instAction := installAction(t)
instAction.ReleaseName = "interrupted-release" instAction.ReleaseName = "interrupted-release"
failer := instAction.cfg.KubeClient.(*kubefake.FailingKubeClient) failer := instAction.cfg.KubeClient.(*kubefake.FailingKubeClient)
@ -566,15 +578,16 @@ func TestInstallRelease_Wait_Interrupted(t *testing.T) {
goroutines := runtime.NumGoroutine() goroutines := runtime.NumGoroutine()
_, err := instAction.RunWithContext(ctx, buildChart(), vals) _, err := instAction.RunWithContext(ctx, buildChart(), vals)
is.Error(err) req.ErrorContains(err, "context canceled")
is.Contains(err.Error(), "context canceled")
is.Equal(goroutines+1, runtime.NumGoroutine()) // installation goroutine still is in background is.Equal(goroutines+1, runtime.NumGoroutine()) // installation goroutine still is in background
time.Sleep(10 * time.Second) // wait for goroutine to finish time.Sleep(10 * time.Second) // wait for goroutine to finish
is.Equal(goroutines, runtime.NumGoroutine()) is.Equal(goroutines, runtime.NumGoroutine())
} }
func TestInstallRelease_WaitForJobs(t *testing.T) { func TestInstallRelease_WaitForJobs(t *testing.T) {
is := assert.New(t) is := assert.New(t)
req := require.New(t)
instAction := installAction(t) instAction := installAction(t)
instAction.ReleaseName = "come-fail-away" instAction.ReleaseName = "come-fail-away"
failer := instAction.cfg.KubeClient.(*kubefake.FailingKubeClient) failer := instAction.cfg.KubeClient.(*kubefake.FailingKubeClient)
@ -585,13 +598,14 @@ func TestInstallRelease_WaitForJobs(t *testing.T) {
vals := map[string]interface{}{} vals := map[string]interface{}{}
res, err := instAction.Run(buildChart(), vals) res, err := instAction.Run(buildChart(), vals)
is.Error(err) req.Error(err)
is.Contains(res.Info.Description, "I timed out") is.Contains(res.Info.Description, "I timed out")
is.Equal(res.Info.Status, release.StatusFailed) is.Equal(release.StatusFailed, res.Info.Status)
} }
func TestInstallRelease_Atomic(t *testing.T) { func TestInstallRelease_Atomic(t *testing.T) {
is := assert.New(t) is := assert.New(t)
req := require.New(t)
t.Run("atomic uninstall succeeds", func(t *testing.T) { t.Run("atomic uninstall succeeds", func(t *testing.T) {
instAction := installAction(t) instAction := installAction(t)
@ -606,13 +620,12 @@ func TestInstallRelease_Atomic(t *testing.T) {
vals := map[string]interface{}{} vals := map[string]interface{}{}
res, err := instAction.Run(buildChart(), vals) res, err := instAction.Run(buildChart(), vals)
is.Error(err) req.ErrorContains(err, "I timed out")
is.Contains(err.Error(), "I timed out") req.ErrorContains(err, "atomic")
is.Contains(err.Error(), "atomic")
// Now make sure it isn't in storage anymore // Now make sure it isn't in storage anymore
_, err = instAction.cfg.Releases.Get(res.Name, res.Version) _, err = instAction.cfg.Releases.Get(res.Name, res.Version)
is.Error(err) req.Error(err)
is.Equal(err, driver.ErrReleaseNotFound) is.Equal(err, driver.ErrReleaseNotFound)
}) })
@ -627,15 +640,15 @@ func TestInstallRelease_Atomic(t *testing.T) {
vals := map[string]interface{}{} vals := map[string]interface{}{}
_, err := instAction.Run(buildChart(), vals) _, err := instAction.Run(buildChart(), vals)
is.Error(err) req.ErrorContains(err, "I timed out")
is.Contains(err.Error(), "I timed out") req.ErrorContains(err, "uninstall fail")
is.Contains(err.Error(), "uninstall fail") is.ErrorContains(err, "an error occurred while uninstalling the release")
is.Contains(err.Error(), "an error occurred while uninstalling the release")
}) })
} }
func TestInstallRelease_Atomic_Interrupted(t *testing.T) {
func TestInstallRelease_Atomic_Interrupted(t *testing.T) {
is := assert.New(t) is := assert.New(t)
req := require.New(t)
instAction := installAction(t) instAction := installAction(t)
instAction.ReleaseName = "interrupted-release" instAction.ReleaseName = "interrupted-release"
failer := instAction.cfg.KubeClient.(*kubefake.FailingKubeClient) failer := instAction.cfg.KubeClient.(*kubefake.FailingKubeClient)
@ -650,20 +663,19 @@ func TestInstallRelease_Atomic_Interrupted(t *testing.T) {
goroutines := runtime.NumGoroutine() goroutines := runtime.NumGoroutine()
res, err := instAction.RunWithContext(ctx, buildChart(), vals) res, err := instAction.RunWithContext(ctx, buildChart(), vals)
is.Error(err) req.ErrorContains(err, "context canceled")
is.Contains(err.Error(), "context canceled") req.ErrorContains(err, "atomic")
is.Contains(err.Error(), "atomic") req.ErrorContains(err, "uninstalled")
is.Contains(err.Error(), "uninstalled")
// Now make sure it isn't in storage anymore // Now make sure it isn't in storage anymore
_, err = instAction.cfg.Releases.Get(res.Name, res.Version) _, err = instAction.cfg.Releases.Get(res.Name, res.Version)
is.Error(err) req.Error(err)
is.Equal(err, driver.ErrReleaseNotFound) is.Equal(err, driver.ErrReleaseNotFound)
is.Equal(goroutines+1, runtime.NumGoroutine()) // installation goroutine still is in background is.Equal(goroutines+1, runtime.NumGoroutine()) // installation goroutine still is in background
time.Sleep(10 * time.Second) // wait for goroutine to finish time.Sleep(10 * time.Second) // wait for goroutine to finish
is.Equal(goroutines, runtime.NumGoroutine()) is.Equal(goroutines, runtime.NumGoroutine())
} }
func TestNameTemplate(t *testing.T) { func TestNameTemplate(t *testing.T) {
testCases := []nameTemplateTestCase{ testCases := []nameTemplateTestCase{
// Just a straight up nop please // Just a straight up nop please
@ -735,6 +747,7 @@ func TestNameTemplate(t *testing.T) {
func TestInstallReleaseOutputDir(t *testing.T) { func TestInstallReleaseOutputDir(t *testing.T) {
is := assert.New(t) is := assert.New(t)
req := require.New(t)
instAction := installAction(t) instAction := installAction(t)
vals := map[string]interface{}{} vals := map[string]interface{}{}
@ -748,25 +761,26 @@ func TestInstallReleaseOutputDir(t *testing.T) {
} }
_, err = os.Stat(filepath.Join(dir, "hello/templates/goodbye")) _, err = os.Stat(filepath.Join(dir, "hello/templates/goodbye"))
is.NoError(err) req.NoError(err)
_, err = os.Stat(filepath.Join(dir, "hello/templates/hello")) _, err = os.Stat(filepath.Join(dir, "hello/templates/hello"))
is.NoError(err) req.NoError(err)
_, err = os.Stat(filepath.Join(dir, "hello/templates/with-partials")) _, err = os.Stat(filepath.Join(dir, "hello/templates/with-partials"))
is.NoError(err) req.NoError(err)
_, err = os.Stat(filepath.Join(dir, "hello/templates/rbac")) _, err = os.Stat(filepath.Join(dir, "hello/templates/rbac"))
is.NoError(err) req.NoError(err)
test.AssertGoldenFile(t, filepath.Join(dir, "hello/templates/rbac"), "rbac.txt") test.AssertGoldenFile(t, filepath.Join(dir, "hello/templates/rbac"), "rbac.txt")
_, err = os.Stat(filepath.Join(dir, "hello/templates/empty")) _, err = os.Stat(filepath.Join(dir, "hello/templates/empty"))
is.True(errors.Is(err, fs.ErrNotExist)) is.ErrorIs(err, fs.ErrNotExist)
} }
func TestInstallOutputDirWithReleaseName(t *testing.T) { func TestInstallOutputDirWithReleaseName(t *testing.T) {
is := assert.New(t) is := assert.New(t)
req := require.New(t)
instAction := installAction(t) instAction := installAction(t)
vals := map[string]interface{}{} vals := map[string]interface{}{}
@ -784,21 +798,21 @@ func TestInstallOutputDirWithReleaseName(t *testing.T) {
} }
_, err = os.Stat(filepath.Join(newDir, "hello/templates/goodbye")) _, err = os.Stat(filepath.Join(newDir, "hello/templates/goodbye"))
is.NoError(err) req.NoError(err)
_, err = os.Stat(filepath.Join(newDir, "hello/templates/hello")) _, err = os.Stat(filepath.Join(newDir, "hello/templates/hello"))
is.NoError(err) req.NoError(err)
_, err = os.Stat(filepath.Join(newDir, "hello/templates/with-partials")) _, err = os.Stat(filepath.Join(newDir, "hello/templates/with-partials"))
is.NoError(err) req.NoError(err)
_, err = os.Stat(filepath.Join(newDir, "hello/templates/rbac")) _, err = os.Stat(filepath.Join(newDir, "hello/templates/rbac"))
is.NoError(err) req.NoError(err)
test.AssertGoldenFile(t, filepath.Join(newDir, "hello/templates/rbac"), "rbac.txt") test.AssertGoldenFile(t, filepath.Join(newDir, "hello/templates/rbac"), "rbac.txt")
_, err = os.Stat(filepath.Join(newDir, "hello/templates/empty")) _, err = os.Stat(filepath.Join(newDir, "hello/templates/empty"))
is.True(errors.Is(err, fs.ErrNotExist)) is.ErrorIs(err, fs.ErrNotExist)
} }
func TestNameAndChart(t *testing.T) { func TestNameAndChart(t *testing.T) {

@ -20,6 +20,7 @@ import (
"testing" "testing"
"github.com/stretchr/testify/assert" "github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"
release "helm.sh/helm/v4/pkg/release/v1" release "helm.sh/helm/v4/pkg/release/v1"
"helm.sh/helm/v4/pkg/storage" "helm.sh/helm/v4/pkg/storage"
@ -59,8 +60,8 @@ func TestListStates(t *testing.T) {
func TestList_Empty(t *testing.T) { func TestList_Empty(t *testing.T) {
lister := NewList(actionConfigFixture(t)) lister := NewList(actionConfigFixture(t))
list, err := lister.Run() list, err := lister.Run()
assert.NoError(t, err) require.NoError(t, err)
assert.Len(t, list, 0) assert.Empty(t, list)
} }
func newListFixture(t *testing.T) *List { func newListFixture(t *testing.T) *List {
@ -70,31 +71,34 @@ func newListFixture(t *testing.T) *List {
func TestList_OneNamespace(t *testing.T) { func TestList_OneNamespace(t *testing.T) {
is := assert.New(t) is := assert.New(t)
req := require.New(t)
lister := newListFixture(t) lister := newListFixture(t)
makeMeSomeReleases(t, lister.cfg.Releases) makeMeSomeReleases(t, lister.cfg.Releases)
list, err := lister.Run() list, err := lister.Run()
is.NoError(err) req.NoError(err)
is.Len(list, 3) is.Len(list, 3)
} }
func TestList_AllNamespaces(t *testing.T) { func TestList_AllNamespaces(t *testing.T) {
is := assert.New(t) is := assert.New(t)
req := require.New(t)
lister := newListFixture(t) lister := newListFixture(t)
makeMeSomeReleases(t, lister.cfg.Releases) makeMeSomeReleases(t, lister.cfg.Releases)
lister.AllNamespaces = true lister.AllNamespaces = true
lister.SetStateMask() lister.SetStateMask()
list, err := lister.Run() list, err := lister.Run()
is.NoError(err) req.NoError(err)
is.Len(list, 3) is.Len(list, 3)
} }
func TestList_Sort(t *testing.T) { func TestList_Sort(t *testing.T) {
is := assert.New(t) is := assert.New(t)
req := require.New(t)
lister := newListFixture(t) lister := newListFixture(t)
lister.Sort = ByNameDesc // Other sorts are tested elsewhere lister.Sort = ByNameDesc // Other sorts are tested elsewhere
makeMeSomeReleases(t, lister.cfg.Releases) makeMeSomeReleases(t, lister.cfg.Releases)
list, err := lister.Run() list, err := lister.Run()
is.NoError(err) req.NoError(err)
is.Len(list, 3) is.Len(list, 3)
is.Equal("two", list[0].Name) is.Equal("two", list[0].Name)
is.Equal("three", list[1].Name) is.Equal("three", list[1].Name)
@ -103,11 +107,12 @@ func TestList_Sort(t *testing.T) {
func TestList_Limit(t *testing.T) { func TestList_Limit(t *testing.T) {
is := assert.New(t) is := assert.New(t)
req := require.New(t)
lister := newListFixture(t) lister := newListFixture(t)
lister.Limit = 2 lister.Limit = 2
makeMeSomeReleases(t, lister.cfg.Releases) makeMeSomeReleases(t, lister.cfg.Releases)
list, err := lister.Run() list, err := lister.Run()
is.NoError(err) req.NoError(err)
is.Len(list, 2) is.Len(list, 2)
// Lex order means one, three, two // Lex order means one, three, two
is.Equal("one", list[0].Name) is.Equal("one", list[0].Name)
@ -116,11 +121,12 @@ func TestList_Limit(t *testing.T) {
func TestList_BigLimit(t *testing.T) { func TestList_BigLimit(t *testing.T) {
is := assert.New(t) is := assert.New(t)
req := require.New(t)
lister := newListFixture(t) lister := newListFixture(t)
lister.Limit = 20 lister.Limit = 20
makeMeSomeReleases(t, lister.cfg.Releases) makeMeSomeReleases(t, lister.cfg.Releases)
list, err := lister.Run() list, err := lister.Run()
is.NoError(err) req.NoError(err)
is.Len(list, 3) is.Len(list, 3)
// Lex order means one, three, two // Lex order means one, three, two
@ -131,12 +137,13 @@ func TestList_BigLimit(t *testing.T) {
func TestList_LimitOffset(t *testing.T) { func TestList_LimitOffset(t *testing.T) {
is := assert.New(t) is := assert.New(t)
req := require.New(t)
lister := newListFixture(t) lister := newListFixture(t)
lister.Limit = 2 lister.Limit = 2
lister.Offset = 1 lister.Offset = 1
makeMeSomeReleases(t, lister.cfg.Releases) makeMeSomeReleases(t, lister.cfg.Releases)
list, err := lister.Run() list, err := lister.Run()
is.NoError(err) req.NoError(err)
is.Len(list, 2) is.Len(list, 2)
// Lex order means one, three, two // Lex order means one, three, two
@ -146,51 +153,54 @@ func TestList_LimitOffset(t *testing.T) {
func TestList_LimitOffsetOutOfBounds(t *testing.T) { func TestList_LimitOffsetOutOfBounds(t *testing.T) {
is := assert.New(t) is := assert.New(t)
req := require.New(t)
lister := newListFixture(t) lister := newListFixture(t)
lister.Limit = 2 lister.Limit = 2
lister.Offset = 3 // Last item is index 2 lister.Offset = 3 // Last item is index 2
makeMeSomeReleases(t, lister.cfg.Releases) makeMeSomeReleases(t, lister.cfg.Releases)
list, err := lister.Run() list, err := lister.Run()
is.NoError(err) req.NoError(err)
is.Len(list, 0) is.Empty(list)
lister.Limit = 10 lister.Limit = 10
lister.Offset = 1 lister.Offset = 1
list, err = lister.Run() list, err = lister.Run()
is.NoError(err) req.NoError(err)
is.Len(list, 2) is.Len(list, 2)
} }
func TestList_StateMask(t *testing.T) { func TestList_StateMask(t *testing.T) {
is := assert.New(t) is := assert.New(t)
req := require.New(t)
lister := newListFixture(t) lister := newListFixture(t)
makeMeSomeReleases(t, lister.cfg.Releases) makeMeSomeReleases(t, lister.cfg.Releases)
one, err := lister.cfg.Releases.Get("one", 1) one, err := lister.cfg.Releases.Get("one", 1)
is.NoError(err) req.NoError(err)
one.SetStatus(release.StatusUninstalled, "uninstalled") one.SetStatus(release.StatusUninstalled, "uninstalled")
err = lister.cfg.Releases.Update(one) err = lister.cfg.Releases.Update(one)
is.NoError(err) req.NoError(err)
res, err := lister.Run() res, err := lister.Run()
is.NoError(err) req.NoError(err)
is.Len(res, 2) is.Len(res, 2)
is.Equal("three", res[0].Name) is.Equal("three", res[0].Name)
is.Equal("two", res[1].Name) is.Equal("two", res[1].Name)
lister.StateMask = ListUninstalled lister.StateMask = ListUninstalled
res, err = lister.Run() res, err = lister.Run()
is.NoError(err) req.NoError(err)
is.Len(res, 1) is.Len(res, 1)
is.Equal("one", res[0].Name) is.Equal("one", res[0].Name)
lister.StateMask |= ListDeployed lister.StateMask |= ListDeployed
res, err = lister.Run() res, err = lister.Run()
is.NoError(err) req.NoError(err)
is.Len(res, 3) is.Len(res, 3)
} }
func TestList_StateMaskWithStaleRevisions(t *testing.T) { func TestList_StateMaskWithStaleRevisions(t *testing.T) {
is := assert.New(t) is := assert.New(t)
req := require.New(t)
lister := newListFixture(t) lister := newListFixture(t)
lister.StateMask = ListFailed lister.StateMask = ListFailed
@ -198,7 +208,7 @@ func TestList_StateMaskWithStaleRevisions(t *testing.T) {
res, err := lister.Run() res, err := lister.Run()
is.NoError(err) req.NoError(err)
is.Len(res, 1) is.Len(res, 1)
// "dirty" release should _not_ be present as most recent // "dirty" release should _not_ be present as most recent
@ -235,18 +245,19 @@ func makeMeSomeReleasesWithStaleFailure(t *testing.T, store *storage.Storage) {
} }
all, err := store.ListReleases() all, err := store.ListReleases()
assert.NoError(t, err) require.NoError(t, err)
assert.Len(t, all, 5, "sanity test: five items added") assert.Len(t, all, 5, "sanity test: five items added")
} }
func TestList_Filter(t *testing.T) { func TestList_Filter(t *testing.T) {
is := assert.New(t) is := assert.New(t)
req := require.New(t)
lister := newListFixture(t) lister := newListFixture(t)
lister.Filter = "th." lister.Filter = "th."
makeMeSomeReleases(t, lister.cfg.Releases) makeMeSomeReleases(t, lister.cfg.Releases)
res, err := lister.Run() res, err := lister.Run()
is.NoError(err) req.NoError(err)
is.Len(res, 1) is.Len(res, 1)
is.Equal("three", res[0].Name) is.Equal("three", res[0].Name)
} }
@ -283,7 +294,7 @@ func makeMeSomeReleases(t *testing.T, store *storage.Storage) {
} }
all, err := store.ListReleases() all, err := store.ListReleases()
assert.NoError(t, err) require.NoError(t, err)
assert.Len(t, all, 3, "sanity test: three items added") assert.Len(t, all, 3, "sanity test: three items added")
} }

@ -21,6 +21,7 @@ import (
"testing" "testing"
"github.com/stretchr/testify/assert" "github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"
"helm.sh/helm/v4/pkg/kube" "helm.sh/helm/v4/pkg/kube"
kubefake "helm.sh/helm/v4/pkg/kube/fake" kubefake "helm.sh/helm/v4/pkg/kube/fake"
@ -47,6 +48,7 @@ func TestUninstallRelease_ignoreNotFound(t *testing.T) {
func TestUninstallRelease_deleteRelease(t *testing.T) { func TestUninstallRelease_deleteRelease(t *testing.T) {
is := assert.New(t) is := assert.New(t)
req := require.New(t)
unAction := uninstallAction(t) unAction := uninstallAction(t)
unAction.DisableHooks = true unAction.DisableHooks = true
@ -71,7 +73,7 @@ func TestUninstallRelease_deleteRelease(t *testing.T) {
}` }`
unAction.cfg.Releases.Create(rel) unAction.cfg.Releases.Create(rel)
res, err := unAction.Run(rel.Name) res, err := unAction.Run(rel.Name)
is.NoError(err) req.NoError(err)
expected := `These resources were kept due to the resource policy: expected := `These resources were kept due to the resource policy:
[Secret] secret [Secret] secret
` `
@ -80,6 +82,7 @@ func TestUninstallRelease_deleteRelease(t *testing.T) {
func TestUninstallRelease_Wait(t *testing.T) { func TestUninstallRelease_Wait(t *testing.T) {
is := assert.New(t) is := assert.New(t)
req := require.New(t)
unAction := uninstallAction(t) unAction := uninstallAction(t)
unAction.DisableHooks = true unAction.DisableHooks = true
@ -104,9 +107,8 @@ func TestUninstallRelease_Wait(t *testing.T) {
failer.WaitForDeleteError = fmt.Errorf("U timed out") failer.WaitForDeleteError = fmt.Errorf("U timed out")
unAction.cfg.KubeClient = failer unAction.cfg.KubeClient = failer
res, err := unAction.Run(rel.Name) res, err := unAction.Run(rel.Name)
is.Error(err) req.ErrorContains(err, "U timed out")
is.Contains(err.Error(), "U timed out") is.Equal(release.StatusUninstalled, res.Release.Info.Status)
is.Equal(res.Release.Info.Status, release.StatusUninstalled)
} }
func TestUninstallRelease_Cascade(t *testing.T) { func TestUninstallRelease_Cascade(t *testing.T) {
@ -137,6 +139,5 @@ func TestUninstallRelease_Cascade(t *testing.T) {
failer.BuildDummy = true failer.BuildDummy = true
unAction.cfg.KubeClient = failer unAction.cfg.KubeClient = failer
_, err := unAction.Run(rel.Name) _, err := unAction.Run(rel.Name)
is.Error(err) is.ErrorContains(err, "failed to delete release: come-fail-away")
is.Contains(err.Error(), "failed to delete release: come-fail-away")
} }

@ -61,14 +61,14 @@ func TestUpgradeRelease_Success(t *testing.T) {
res, err := upAction.RunWithContext(ctx, rel.Name, buildChart(), vals) res, err := upAction.RunWithContext(ctx, rel.Name, buildChart(), vals)
done() done()
req.NoError(err) req.NoError(err)
is.Equal(res.Info.Status, release.StatusDeployed) is.Equal(release.StatusDeployed, res.Info.Status)
// Detecting previous bug where context termination after successful release // Detecting previous bug where context termination after successful release
// caused release to fail. // caused release to fail.
time.Sleep(time.Millisecond * 100) time.Sleep(time.Millisecond * 100)
lastRelease, err := upAction.cfg.Releases.Last(rel.Name) lastRelease, err := upAction.cfg.Releases.Last(rel.Name)
req.NoError(err) req.NoError(err)
is.Equal(lastRelease.Info.Status, release.StatusDeployed) is.Equal(release.StatusDeployed, lastRelease.Info.Status)
} }
func TestUpgradeRelease_Wait(t *testing.T) { func TestUpgradeRelease_Wait(t *testing.T) {
@ -90,7 +90,7 @@ func TestUpgradeRelease_Wait(t *testing.T) {
res, err := upAction.Run(rel.Name, buildChart(), vals) res, err := upAction.Run(rel.Name, buildChart(), vals)
req.Error(err) req.Error(err)
is.Contains(res.Info.Description, "I timed out") is.Contains(res.Info.Description, "I timed out")
is.Equal(res.Info.Status, release.StatusFailed) is.Equal(release.StatusFailed, res.Info.Status)
} }
func TestUpgradeRelease_WaitForJobs(t *testing.T) { func TestUpgradeRelease_WaitForJobs(t *testing.T) {
@ -113,7 +113,7 @@ func TestUpgradeRelease_WaitForJobs(t *testing.T) {
res, err := upAction.Run(rel.Name, buildChart(), vals) res, err := upAction.Run(rel.Name, buildChart(), vals)
req.Error(err) req.Error(err)
is.Contains(res.Info.Description, "I timed out") is.Contains(res.Info.Description, "I timed out")
is.Equal(res.Info.Status, release.StatusFailed) is.Equal(release.StatusFailed, res.Info.Status)
} }
func TestUpgradeRelease_CleanupOnFail(t *testing.T) { func TestUpgradeRelease_CleanupOnFail(t *testing.T) {
@ -138,7 +138,7 @@ func TestUpgradeRelease_CleanupOnFail(t *testing.T) {
req.Error(err) req.Error(err)
is.NotContains(err.Error(), "unable to cleanup resources") is.NotContains(err.Error(), "unable to cleanup resources")
is.Contains(res.Info.Description, "I timed out") is.Contains(res.Info.Description, "I timed out")
is.Equal(res.Info.Status, release.StatusFailed) is.Equal(release.StatusFailed, res.Info.Status)
} }
func TestUpgradeRelease_Atomic(t *testing.T) { func TestUpgradeRelease_Atomic(t *testing.T) {
@ -161,15 +161,14 @@ func TestUpgradeRelease_Atomic(t *testing.T) {
vals := map[string]interface{}{} vals := map[string]interface{}{}
res, err := upAction.Run(rel.Name, buildChart(), vals) res, err := upAction.Run(rel.Name, buildChart(), vals)
req.Error(err) req.ErrorContains(err, "arming key removed")
is.Contains(err.Error(), "arming key removed") req.ErrorContains(err, "atomic")
is.Contains(err.Error(), "atomic")
// Now make sure it is actually upgraded // Now make sure it is actually upgraded
updatedRes, err := upAction.cfg.Releases.Get(res.Name, 3) updatedRes, err := upAction.cfg.Releases.Get(res.Name, 3)
is.NoError(err) req.NoError(err)
// Should have rolled back to the previous // Should have rolled back to the previous
is.Equal(updatedRes.Info.Status, release.StatusDeployed) is.Equal(release.StatusDeployed, updatedRes.Info.Status)
}) })
t.Run("atomic uninstall fails", func(t *testing.T) { t.Run("atomic uninstall fails", func(t *testing.T) {
@ -186,14 +185,14 @@ func TestUpgradeRelease_Atomic(t *testing.T) {
vals := map[string]interface{}{} vals := map[string]interface{}{}
_, err := upAction.Run(rel.Name, buildChart(), vals) _, err := upAction.Run(rel.Name, buildChart(), vals)
req.Error(err) req.ErrorContains(err, "update fail")
is.Contains(err.Error(), "update fail") is.ErrorContains(err, "an error occurred while rolling back the release")
is.Contains(err.Error(), "an error occurred while rolling back the release")
}) })
} }
func TestUpgradeRelease_ReuseValues(t *testing.T) { func TestUpgradeRelease_ReuseValues(t *testing.T) {
is := assert.New(t) is := assert.New(t)
req := require.New(t)
t.Run("reuse values should work with values", func(t *testing.T) { t.Run("reuse values should work with values", func(t *testing.T) {
upAction := upgradeAction(t) upAction := upgradeAction(t)
@ -221,16 +220,16 @@ func TestUpgradeRelease_ReuseValues(t *testing.T) {
rel.Config = existingValues rel.Config = existingValues
err := upAction.cfg.Releases.Create(rel) err := upAction.cfg.Releases.Create(rel)
is.NoError(err) req.NoError(err)
upAction.ReuseValues = true upAction.ReuseValues = true
// setting newValues and upgrading // setting newValues and upgrading
res, err := upAction.Run(rel.Name, buildChart(), newValues) res, err := upAction.Run(rel.Name, buildChart(), newValues)
is.NoError(err) req.NoError(err)
// Now make sure it is actually upgraded // Now make sure it is actually upgraded
updatedRes, err := upAction.cfg.Releases.Get(res.Name, 2) updatedRes, err := upAction.cfg.Releases.Get(res.Name, 2)
is.NoError(err) req.NoError(err)
if updatedRes == nil { if updatedRes == nil {
is.Fail("Updated Release is nil") is.Fail("Updated Release is nil")
@ -277,7 +276,7 @@ func TestUpgradeRelease_ReuseValues(t *testing.T) {
Version: 1, Version: 1,
} }
err := upAction.cfg.Releases.Create(rel) err := upAction.cfg.Releases.Create(rel)
is.NoError(err) req.NoError(err)
upAction.ReuseValues = true upAction.ReuseValues = true
sampleChartWithSubChart := buildChart( sampleChartWithSubChart := buildChart(
@ -288,18 +287,18 @@ func TestUpgradeRelease_ReuseValues(t *testing.T) {
) )
// reusing values and upgrading // reusing values and upgrading
res, err := upAction.Run(rel.Name, sampleChartWithSubChart, map[string]interface{}{}) res, err := upAction.Run(rel.Name, sampleChartWithSubChart, map[string]interface{}{})
is.NoError(err) req.NoError(err)
// Now get the upgraded release // Now get the upgraded release
updatedRes, err := upAction.cfg.Releases.Get(res.Name, 2) updatedRes, err := upAction.cfg.Releases.Get(res.Name, 2)
is.NoError(err) req.NoError(err)
if updatedRes == nil { if updatedRes == nil {
is.Fail("Updated Release is nil") is.Fail("Updated Release is nil")
return return
} }
is.Equal(release.StatusDeployed, updatedRes.Info.Status) is.Equal(release.StatusDeployed, updatedRes.Info.Status)
is.Equal(0, len(updatedRes.Chart.Dependencies()), "expected 0 dependencies") is.Empty(updatedRes.Chart.Dependencies(), "expected 0 dependencies")
expectedValues := map[string]interface{}{ expectedValues := map[string]interface{}{
"subchart": map[string]interface{}{ "subchart": map[string]interface{}{
@ -312,6 +311,7 @@ func TestUpgradeRelease_ReuseValues(t *testing.T) {
func TestUpgradeRelease_ResetThenReuseValues(t *testing.T) { func TestUpgradeRelease_ResetThenReuseValues(t *testing.T) {
is := assert.New(t) is := assert.New(t)
req := require.New(t)
t.Run("reset then reuse values should work with values", func(t *testing.T) { t.Run("reset then reuse values should work with values", func(t *testing.T) {
upAction := upgradeAction(t) upAction := upgradeAction(t)
@ -342,16 +342,16 @@ func TestUpgradeRelease_ResetThenReuseValues(t *testing.T) {
rel.Config = existingValues rel.Config = existingValues
err := upAction.cfg.Releases.Create(rel) err := upAction.cfg.Releases.Create(rel)
is.NoError(err) req.NoError(err)
upAction.ResetThenReuseValues = true upAction.ResetThenReuseValues = true
// setting newValues and upgrading // setting newValues and upgrading
res, err := upAction.Run(rel.Name, buildChart(withValues(newChartValues)), newValues) res, err := upAction.Run(rel.Name, buildChart(withValues(newChartValues)), newValues)
is.NoError(err) req.NoError(err)
// Now make sure it is actually upgraded // Now make sure it is actually upgraded
updatedRes, err := upAction.cfg.Releases.Get(res.Name, 2) updatedRes, err := upAction.cfg.Releases.Get(res.Name, 2)
is.NoError(err) req.NoError(err)
if updatedRes == nil { if updatedRes == nil {
is.Fail("Updated Release is nil") is.Fail("Updated Release is nil")
@ -380,7 +380,7 @@ func TestUpgradeRelease_Pending(t *testing.T) {
vals := map[string]interface{}{} vals := map[string]interface{}{}
_, err := upAction.Run(rel.Name, buildChart(), vals) _, err := upAction.Run(rel.Name, buildChart(), vals)
req.Contains(err.Error(), "progress", err) req.ErrorContains(err, "progress", "%+v", err)
} }
func TestUpgradeRelease_Interrupted_Wait(t *testing.T) { func TestUpgradeRelease_Interrupted_Wait(t *testing.T) {
@ -406,7 +406,7 @@ func TestUpgradeRelease_Interrupted_Wait(t *testing.T) {
req.Error(err) req.Error(err)
is.Contains(res.Info.Description, "Upgrade \"interrupted-release\" failed: context canceled") is.Contains(res.Info.Description, "Upgrade \"interrupted-release\" failed: context canceled")
is.Equal(res.Info.Status, release.StatusFailed) is.Equal(release.StatusFailed, res.Info.Status)
} }
func TestUpgradeRelease_Interrupted_Atomic(t *testing.T) { func TestUpgradeRelease_Interrupted_Atomic(t *testing.T) {
@ -430,14 +430,13 @@ func TestUpgradeRelease_Interrupted_Atomic(t *testing.T) {
res, err := upAction.RunWithContext(ctx, rel.Name, buildChart(), vals) res, err := upAction.RunWithContext(ctx, rel.Name, buildChart(), vals)
req.Error(err) req.ErrorContains(err, "release interrupted-release failed, and has been rolled back due to atomic being set: context canceled")
is.Contains(err.Error(), "release interrupted-release failed, and has been rolled back due to atomic being set: context canceled")
// Now make sure it is actually upgraded // Now make sure it is actually upgraded
updatedRes, err := upAction.cfg.Releases.Get(res.Name, 3) updatedRes, err := upAction.cfg.Releases.Get(res.Name, 3)
is.NoError(err) req.NoError(err)
// Should have rolled back to the previous // Should have rolled back to the previous
is.Equal(updatedRes.Info.Status, release.StatusDeployed) is.Equal(release.StatusDeployed, updatedRes.Info.Status)
} }
func TestMergeCustomLabels(t *testing.T) { func TestMergeCustomLabels(t *testing.T) {
@ -457,6 +456,7 @@ func TestMergeCustomLabels(t *testing.T) {
func TestUpgradeRelease_Labels(t *testing.T) { func TestUpgradeRelease_Labels(t *testing.T) {
is := assert.New(t) is := assert.New(t)
req := require.New(t)
upAction := upgradeAction(t) upAction := upgradeAction(t)
rel := releaseStub() rel := releaseStub()
@ -469,7 +469,7 @@ func TestUpgradeRelease_Labels(t *testing.T) {
rel.Info.Status = release.StatusDeployed rel.Info.Status = release.StatusDeployed
err := upAction.cfg.Releases.Create(rel) err := upAction.cfg.Releases.Create(rel)
is.NoError(err) req.NoError(err)
upAction.Labels = map[string]string{ upAction.Labels = map[string]string{
"key1": "null", "key1": "null",
@ -478,11 +478,11 @@ func TestUpgradeRelease_Labels(t *testing.T) {
} }
// setting newValues and upgrading // setting newValues and upgrading
res, err := upAction.Run(rel.Name, buildChart(), nil) res, err := upAction.Run(rel.Name, buildChart(), nil)
is.NoError(err) req.NoError(err)
// Now make sure it is actually upgraded and labels were merged // Now make sure it is actually upgraded and labels were merged
updatedRes, err := upAction.cfg.Releases.Get(res.Name, 2) updatedRes, err := upAction.cfg.Releases.Get(res.Name, 2)
is.NoError(err) req.NoError(err)
if updatedRes == nil { if updatedRes == nil {
is.Fail("Updated Release is nil") is.Fail("Updated Release is nil")
@ -493,18 +493,19 @@ func TestUpgradeRelease_Labels(t *testing.T) {
// Now make sure it is suppressed release still contains original labels // Now make sure it is suppressed release still contains original labels
initialRes, err := upAction.cfg.Releases.Get(res.Name, 1) initialRes, err := upAction.cfg.Releases.Get(res.Name, 1)
is.NoError(err) req.NoError(err)
if initialRes == nil { if initialRes == nil {
is.Fail("Updated Release is nil") is.Fail("Updated Release is nil")
return return
} }
is.Equal(initialRes.Info.Status, release.StatusSuperseded) is.Equal(release.StatusSuperseded, initialRes.Info.Status)
is.Equal(initialRes.Labels, rel.Labels) is.Equal(initialRes.Labels, rel.Labels)
} }
func TestUpgradeRelease_SystemLabels(t *testing.T) { func TestUpgradeRelease_SystemLabels(t *testing.T) {
is := assert.New(t) is := assert.New(t)
req := require.New(t)
upAction := upgradeAction(t) upAction := upgradeAction(t)
rel := releaseStub() rel := releaseStub()
@ -517,7 +518,7 @@ func TestUpgradeRelease_SystemLabels(t *testing.T) {
rel.Info.Status = release.StatusDeployed rel.Info.Status = release.StatusDeployed
err := upAction.cfg.Releases.Create(rel) err := upAction.cfg.Releases.Create(rel)
is.NoError(err) req.NoError(err)
upAction.Labels = map[string]string{ upAction.Labels = map[string]string{
"key1": "null", "key1": "null",
@ -555,7 +556,7 @@ func TestUpgradeRelease_DryRun(t *testing.T) {
lastRelease, err := upAction.cfg.Releases.Last(rel.Name) lastRelease, err := upAction.cfg.Releases.Last(rel.Name)
req.NoError(err) req.NoError(err)
is.Equal(lastRelease.Info.Status, release.StatusDeployed) is.Equal(release.StatusDeployed, lastRelease.Info.Status)
is.Equal(1, lastRelease.Version) is.Equal(1, lastRelease.Version)
// Test the case for hiding the secret to ensure it is not displayed // Test the case for hiding the secret to ensure it is not displayed
@ -571,7 +572,7 @@ func TestUpgradeRelease_DryRun(t *testing.T) {
lastRelease, err = upAction.cfg.Releases.Last(rel.Name) lastRelease, err = upAction.cfg.Releases.Last(rel.Name)
req.NoError(err) req.NoError(err)
is.Equal(lastRelease.Info.Status, release.StatusDeployed) is.Equal(release.StatusDeployed, lastRelease.Info.Status)
is.Equal(1, lastRelease.Version) is.Equal(1, lastRelease.Version)
// Ensure in a dry run mode when using HideSecret // Ensure in a dry run mode when using HideSecret

@ -25,6 +25,7 @@ import (
"helm.sh/helm/v4/pkg/kube" "helm.sh/helm/v4/pkg/kube"
"github.com/stretchr/testify/assert" "github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"
appsv1 "k8s.io/api/apps/v1" appsv1 "k8s.io/api/apps/v1"
"k8s.io/apimachinery/pkg/api/meta" "k8s.io/apimachinery/pkg/api/meta"
@ -129,7 +130,7 @@ func TestRequireAdoption(t *testing.T) {
// Verify that a resource that lacks labels/annotations can be adopted // Verify that a resource that lacks labels/annotations can be adopted
found, err := requireAdoption(resources) found, err := requireAdoption(resources)
assert.NoError(t, err) require.NoError(t, err)
assert.Len(t, found, 1) assert.Len(t, found, 1)
assert.Equal(t, found[0], existing) assert.Equal(t, found[0], existing)
} }
@ -153,7 +154,7 @@ func TestExistingResourceConflict(t *testing.T) {
// Verify only existing resources are returned // Verify only existing resources are returned
found, err := existingResourceConflict(resources, releaseName, releaseNamespace) found, err := existingResourceConflict(resources, releaseName, releaseNamespace)
assert.NoError(t, err) require.NoError(t, err)
assert.Len(t, found, 1) assert.Len(t, found, 1)
assert.Equal(t, found[0], existing) assert.Equal(t, found[0], existing)
@ -168,21 +169,21 @@ func TestCheckOwnership(t *testing.T) {
// Verify that a resource that lacks labels/annotations is not owned // Verify that a resource that lacks labels/annotations is not owned
err := checkOwnership(deployFoo.Object, "rel-a", "ns-a") err := checkOwnership(deployFoo.Object, "rel-a", "ns-a")
assert.EqualError(t, err, `invalid ownership metadata; label validation error: missing key "app.kubernetes.io/managed-by": must be set to "Helm"; annotation validation error: missing key "meta.helm.sh/release-name": must be set to "rel-a"; annotation validation error: missing key "meta.helm.sh/release-namespace": must be set to "ns-a"`) require.EqualError(t, err, `invalid ownership metadata; label validation error: missing key "app.kubernetes.io/managed-by": must be set to "Helm"; annotation validation error: missing key "meta.helm.sh/release-name": must be set to "rel-a"; annotation validation error: missing key "meta.helm.sh/release-namespace": must be set to "ns-a"`)
// Set managed by label and verify annotation error message // Set managed by label and verify annotation error message
_ = accessor.SetLabels(deployFoo.Object, map[string]string{ _ = accessor.SetLabels(deployFoo.Object, map[string]string{
appManagedByLabel: appManagedByHelm, appManagedByLabel: appManagedByHelm,
}) })
err = checkOwnership(deployFoo.Object, "rel-a", "ns-a") err = checkOwnership(deployFoo.Object, "rel-a", "ns-a")
assert.EqualError(t, err, `invalid ownership metadata; annotation validation error: missing key "meta.helm.sh/release-name": must be set to "rel-a"; annotation validation error: missing key "meta.helm.sh/release-namespace": must be set to "ns-a"`) require.EqualError(t, err, `invalid ownership metadata; annotation validation error: missing key "meta.helm.sh/release-name": must be set to "rel-a"; annotation validation error: missing key "meta.helm.sh/release-namespace": must be set to "ns-a"`)
// Set only the release name annotation and verify missing release namespace error message // Set only the release name annotation and verify missing release namespace error message
_ = accessor.SetAnnotations(deployFoo.Object, map[string]string{ _ = accessor.SetAnnotations(deployFoo.Object, map[string]string{
helmReleaseNameAnnotation: "rel-a", helmReleaseNameAnnotation: "rel-a",
}) })
err = checkOwnership(deployFoo.Object, "rel-a", "ns-a") err = checkOwnership(deployFoo.Object, "rel-a", "ns-a")
assert.EqualError(t, err, `invalid ownership metadata; annotation validation error: missing key "meta.helm.sh/release-namespace": must be set to "ns-a"`) require.EqualError(t, err, `invalid ownership metadata; annotation validation error: missing key "meta.helm.sh/release-namespace": must be set to "ns-a"`)
// Set both release name and namespace annotations and verify no ownership errors // Set both release name and namespace annotations and verify no ownership errors
_ = accessor.SetAnnotations(deployFoo.Object, map[string]string{ _ = accessor.SetAnnotations(deployFoo.Object, map[string]string{
@ -190,15 +191,15 @@ func TestCheckOwnership(t *testing.T) {
helmReleaseNamespaceAnnotation: "ns-a", helmReleaseNamespaceAnnotation: "ns-a",
}) })
err = checkOwnership(deployFoo.Object, "rel-a", "ns-a") err = checkOwnership(deployFoo.Object, "rel-a", "ns-a")
assert.NoError(t, err) require.NoError(t, err)
// Verify ownership error for wrong release name // Verify ownership error for wrong release name
err = checkOwnership(deployFoo.Object, "rel-b", "ns-a") err = checkOwnership(deployFoo.Object, "rel-b", "ns-a")
assert.EqualError(t, err, `invalid ownership metadata; annotation validation error: key "meta.helm.sh/release-name" must equal "rel-b": current value is "rel-a"`) require.EqualError(t, err, `invalid ownership metadata; annotation validation error: key "meta.helm.sh/release-name" must equal "rel-b": current value is "rel-a"`)
// Verify ownership error for wrong release namespace // Verify ownership error for wrong release namespace
err = checkOwnership(deployFoo.Object, "rel-a", "ns-b") err = checkOwnership(deployFoo.Object, "rel-a", "ns-b")
assert.EqualError(t, err, `invalid ownership metadata; annotation validation error: key "meta.helm.sh/release-namespace" must equal "ns-b": current value is "ns-a"`) require.EqualError(t, err, `invalid ownership metadata; annotation validation error: key "meta.helm.sh/release-namespace" must equal "ns-b": current value is "ns-a"`)
// Verify ownership error for wrong manager label // Verify ownership error for wrong manager label
_ = accessor.SetLabels(deployFoo.Object, map[string]string{ _ = accessor.SetLabels(deployFoo.Object, map[string]string{
@ -218,23 +219,22 @@ func TestSetMetadataVisitor(t *testing.T) {
// Set release tracking metadata and verify no error // Set release tracking metadata and verify no error
err = resources.Visit(setMetadataVisitor("rel-a", "ns-a", true)) err = resources.Visit(setMetadataVisitor("rel-a", "ns-a", true))
assert.NoError(t, err) require.NoError(t, err)
// Verify that release "b" cannot take ownership of "a" // Verify that release "b" cannot take ownership of "a"
err = resources.Visit(setMetadataVisitor("rel-b", "ns-a", false)) err = resources.Visit(setMetadataVisitor("rel-b", "ns-a", false))
assert.Error(t, err) require.Error(t, err)
// Force release "b" to take ownership // Force release "b" to take ownership
err = resources.Visit(setMetadataVisitor("rel-b", "ns-a", true)) err = resources.Visit(setMetadataVisitor("rel-b", "ns-a", true))
assert.NoError(t, err) require.NoError(t, err)
// Check that there is now no ownership error when setting metadata without force // Check that there is now no ownership error when setting metadata without force
err = resources.Visit(setMetadataVisitor("rel-b", "ns-a", false)) err = resources.Visit(setMetadataVisitor("rel-b", "ns-a", false))
assert.NoError(t, err) require.NoError(t, err)
// Add a new resource that is missing ownership metadata and verify error // Add a new resource that is missing ownership metadata and verify error
resources.Append(newDeploymentResource("baz", "default")) resources.Append(newDeploymentResource("baz", "default"))
err = resources.Visit(setMetadataVisitor("rel-b", "ns-a", false)) err = resources.Visit(setMetadataVisitor("rel-b", "ns-a", false))
assert.Error(t, err) assert.ErrorContains(t, err, `Deployment "baz" in namespace "" cannot be owned`)
assert.Contains(t, err.Error(), `Deployment "baz" in namespace "" cannot be owned`)
} }

@ -50,7 +50,7 @@ func TestCRDs(t *testing.T) {
is := assert.New(t) is := assert.New(t)
crds := chrt.CRDs() crds := chrt.CRDs()
is.Equal(2, len(crds)) is.Len(crds, 2)
is.Equal("crds/foo.yaml", crds[0].Name) is.Equal("crds/foo.yaml", crds[0].Name)
is.Equal("crds/foo/bar/baz.yaml", crds[1].Name) is.Equal("crds/foo/bar/baz.yaml", crds[1].Name)
} }
@ -94,7 +94,7 @@ func TestMetadata(t *testing.T) {
is.Equal("foo.yaml", chrt.Name()) is.Equal("foo.yaml", chrt.Name())
is.Equal("1.0.0", chrt.AppVersion()) is.Equal("1.0.0", chrt.AppVersion())
is.Equal(nil, chrt.Validate()) is.NoError(chrt.Validate())
} }
func TestIsRoot(t *testing.T) { func TestIsRoot(t *testing.T) {
@ -114,8 +114,8 @@ func TestIsRoot(t *testing.T) {
is := assert.New(t) is := assert.New(t)
is.Equal(false, chrt1.IsRoot()) is.False(chrt1.IsRoot())
is.Equal(true, chrt2.IsRoot()) is.True(chrt2.IsRoot())
} }
func TestChartPath(t *testing.T) { func TestChartPath(t *testing.T) {

@ -26,6 +26,7 @@ import (
"time" "time"
"github.com/stretchr/testify/assert" "github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"
"sigs.k8s.io/yaml" "sigs.k8s.io/yaml"
chart "helm.sh/helm/v4/pkg/chart/v2" chart "helm.sh/helm/v4/pkg/chart/v2"
@ -677,7 +678,7 @@ func TestDedupeRepos(t *testing.T) {
func TestWriteLock(t *testing.T) { func TestWriteLock(t *testing.T) {
fixedTime, err := time.Parse(time.RFC3339, "2025-07-04T00:00:00Z") fixedTime, err := time.Parse(time.RFC3339, "2025-07-04T00:00:00Z")
assert.NoError(t, err) require.NoError(t, err)
lock := &chart.Lock{ lock := &chart.Lock{
Generated: fixedTime, Generated: fixedTime,
Digest: "sha256:12345", Digest: "sha256:12345",
@ -690,76 +691,75 @@ func TestWriteLock(t *testing.T) {
}, },
} }
expectedContent, err := yaml.Marshal(lock) expectedContent, err := yaml.Marshal(lock)
assert.NoError(t, err) require.NoError(t, err)
t.Run("v2 lock file", func(t *testing.T) { t.Run("v2 lock file", func(t *testing.T) {
dir := t.TempDir() dir := t.TempDir()
err := writeLock(dir, lock, false) err := writeLock(dir, lock, false)
assert.NoError(t, err) require.NoError(t, err)
lockfilePath := filepath.Join(dir, "Chart.lock") lockfilePath := filepath.Join(dir, "Chart.lock")
_, err = os.Stat(lockfilePath) _, err = os.Stat(lockfilePath)
assert.NoError(t, err, "Chart.lock should exist") require.NoError(t, err, "Chart.lock should exist")
content, err := os.ReadFile(lockfilePath) content, err := os.ReadFile(lockfilePath)
assert.NoError(t, err) require.NoError(t, err)
assert.Equal(t, expectedContent, content) assert.Equal(t, expectedContent, content)
// Check that requirements.lock does not exist // Check that requirements.lock does not exist
_, err = os.Stat(filepath.Join(dir, "requirements.lock")) _, err = os.Stat(filepath.Join(dir, "requirements.lock"))
assert.Error(t, err) require.Error(t, err)
assert.True(t, os.IsNotExist(err)) assert.True(t, os.IsNotExist(err))
}) })
t.Run("v1 lock file", func(t *testing.T) { t.Run("v1 lock file", func(t *testing.T) {
dir := t.TempDir() dir := t.TempDir()
err := writeLock(dir, lock, true) err := writeLock(dir, lock, true)
assert.NoError(t, err) require.NoError(t, err)
lockfilePath := filepath.Join(dir, "requirements.lock") lockfilePath := filepath.Join(dir, "requirements.lock")
_, err = os.Stat(lockfilePath) _, err = os.Stat(lockfilePath)
assert.NoError(t, err, "requirements.lock should exist") require.NoError(t, err, "requirements.lock should exist")
content, err := os.ReadFile(lockfilePath) content, err := os.ReadFile(lockfilePath)
assert.NoError(t, err) require.NoError(t, err)
assert.Equal(t, expectedContent, content) assert.Equal(t, expectedContent, content)
// Check that Chart.lock does not exist // Check that Chart.lock does not exist
_, err = os.Stat(filepath.Join(dir, "Chart.lock")) _, err = os.Stat(filepath.Join(dir, "Chart.lock"))
assert.Error(t, err) require.Error(t, err)
assert.True(t, os.IsNotExist(err)) assert.True(t, os.IsNotExist(err))
}) })
t.Run("overwrite existing lock file", func(t *testing.T) { t.Run("overwrite existing lock file", func(t *testing.T) {
dir := t.TempDir() dir := t.TempDir()
lockfilePath := filepath.Join(dir, "Chart.lock") lockfilePath := filepath.Join(dir, "Chart.lock")
assert.NoError(t, os.WriteFile(lockfilePath, []byte("old content"), 0644)) require.NoError(t, os.WriteFile(lockfilePath, []byte("old content"), 0644))
err = writeLock(dir, lock, false) err = writeLock(dir, lock, false)
assert.NoError(t, err) require.NoError(t, err)
content, err := os.ReadFile(lockfilePath) content, err := os.ReadFile(lockfilePath)
assert.NoError(t, err) require.NoError(t, err)
assert.Equal(t, expectedContent, content) assert.Equal(t, expectedContent, content)
}) })
t.Run("lock file is a symlink", func(t *testing.T) { t.Run("lock file is a symlink", func(t *testing.T) {
dir := t.TempDir() dir := t.TempDir()
dummyFile := filepath.Join(dir, "dummy.txt") dummyFile := filepath.Join(dir, "dummy.txt")
assert.NoError(t, os.WriteFile(dummyFile, []byte("dummy"), 0644)) require.NoError(t, os.WriteFile(dummyFile, []byte("dummy"), 0644))
lockfilePath := filepath.Join(dir, "Chart.lock") lockfilePath := filepath.Join(dir, "Chart.lock")
assert.NoError(t, os.Symlink(dummyFile, lockfilePath)) require.NoError(t, os.Symlink(dummyFile, lockfilePath))
err = writeLock(dir, lock, false) err = writeLock(dir, lock, false)
assert.Error(t, err) assert.ErrorContains(t, err, "the Chart.lock file is a symlink to")
assert.Contains(t, err.Error(), "the Chart.lock file is a symlink to")
}) })
t.Run("chart path is not a directory", func(t *testing.T) { t.Run("chart path is not a directory", func(t *testing.T) {
dir := t.TempDir() dir := t.TempDir()
filePath := filepath.Join(dir, "not-a-dir") filePath := filepath.Join(dir, "not-a-dir")
assert.NoError(t, os.WriteFile(filePath, []byte("file"), 0644)) require.NoError(t, os.WriteFile(filePath, []byte("file"), 0644))
err = writeLock(filePath, lock, false) err = writeLock(filePath, lock, false)
assert.Error(t, err) assert.Error(t, err)

@ -25,6 +25,7 @@ import (
"text/template" "text/template"
"github.com/stretchr/testify/assert" "github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"
"k8s.io/apimachinery/pkg/apis/meta/v1/unstructured" "k8s.io/apimachinery/pkg/apis/meta/v1/unstructured"
"k8s.io/apimachinery/pkg/runtime" "k8s.io/apimachinery/pkg/runtime"
@ -1332,7 +1333,7 @@ NestedHelperFunctions/charts/common/templates/_helpers_2.tpl:1:49
} }
_, err := Render(c, vals) _, err := Render(c, vals)
assert.NotNil(t, err) require.Error(t, err)
assert.Equal(t, expectedErrorMessage, err.Error()) assert.Equal(t, expectedErrorMessage, err.Error())
} }
@ -1365,7 +1366,7 @@ template: no template "nested_helper.name" associated with template "gotpl"`
} }
_, err := Render(c, vals) _, err := Render(c, vals)
assert.NotNil(t, err) require.Error(t, err)
assert.Equal(t, expectedErrorMessage, err.Error()) assert.Equal(t, expectedErrorMessage, err.Error())
} }

@ -107,5 +107,5 @@ func TestBlankLines(t *testing.T) {
as.Len(out, 4) as.Len(out, 4)
as.Equal("bar", out[0]) as.Equal("bar", out[0])
as.Equal("", out[3]) as.Empty(out[3])
} }

@ -22,10 +22,11 @@ import (
"text/template" "text/template"
"github.com/stretchr/testify/assert" "github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"
) )
func TestFuncs(t *testing.T) { func TestFuncs(t *testing.T) {
//TODO write tests for failure cases // TODO write tests for failure cases
tests := []struct { tests := []struct {
tpl, expect string tpl, expect string
vars interface{} vars interface{}
@ -132,7 +133,7 @@ keyInElement1 = "valueInElement1"`,
for _, tt := range tests { for _, tt := range tests {
var b strings.Builder var b strings.Builder
err := template.Must(template.New("test").Funcs(funcMap()).Parse(tt.tpl)).Execute(&b, tt.vars) err := template.Must(template.New("test").Funcs(funcMap()).Parse(tt.tpl)).Execute(&b, tt.vars)
assert.NoError(t, err) require.NoError(t, err)
assert.Equal(t, tt.expect, b.String(), tt.tpl) assert.Equal(t, tt.expect, b.String(), tt.tpl)
} }
@ -166,7 +167,7 @@ keyInElement1 = "valueInElement1"`,
var b strings.Builder var b strings.Builder
err := template.Must(template.New("test").Funcs(funcMap()).Parse(tt.tpl)).Execute(&b, tt.vars) err := template.Must(template.New("test").Funcs(funcMap()).Parse(tt.tpl)).Execute(&b, tt.vars)
if tt.expect != nil { if tt.expect != nil {
assert.NoError(t, err) require.NoError(t, err)
assert.Equal(t, tt.expect, b.String(), tt.tpl) assert.Equal(t, tt.expect, b.String(), tt.tpl)
} else { } else {
assert.Error(t, err) assert.Error(t, err)
@ -221,7 +222,7 @@ func TestMerge(t *testing.T) {
tpl := `{{merge .dst .src1 .src2}}` tpl := `{{merge .dst .src1 .src2}}`
var b strings.Builder var b strings.Builder
err := template.Must(template.New("test").Funcs(funcMap()).Parse(tpl)).Execute(&b, dict) err := template.Must(template.New("test").Funcs(funcMap()).Parse(tpl)).Execute(&b, dict)
assert.NoError(t, err) require.NoError(t, err)
expected := map[string]interface{}{ expected := map[string]interface{}{
"a": "one", // key overridden "a": "one", // key overridden

@ -26,6 +26,7 @@ import (
"time" "time"
"github.com/stretchr/testify/assert" "github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"
v1 "k8s.io/api/core/v1" v1 "k8s.io/api/core/v1"
"k8s.io/apimachinery/pkg/api/meta" "k8s.io/apimachinery/pkg/api/meta"
@ -725,6 +726,8 @@ func TestReal(t *testing.T) {
} }
func TestGetPodList(t *testing.T) { func TestGetPodList(t *testing.T) {
is := assert.New(t)
req := require.New(t)
namespace := "some-namespace" namespace := "some-namespace"
names := []string{"dave", "jimmy"} names := []string{"dave", "jimmy"}
var responsePodList v1.PodList var responsePodList v1.PodList
@ -736,12 +739,13 @@ func TestGetPodList(t *testing.T) {
c := Client{Namespace: namespace, kubeClient: kubeClient} c := Client{Namespace: namespace, kubeClient: kubeClient}
podList, err := c.GetPodList(namespace, metav1.ListOptions{}) podList, err := c.GetPodList(namespace, metav1.ListOptions{})
clientAssertions := assert.New(t) req.NoError(err)
clientAssertions.NoError(err) is.Equal(&responsePodList, podList)
clientAssertions.Equal(&responsePodList, podList)
} }
func TestOutputContainerLogsForPodList(t *testing.T) { func TestOutputContainerLogsForPodList(t *testing.T) {
is := assert.New(t)
req := require.New(t)
namespace := "some-namespace" namespace := "some-namespace"
somePodList := newPodList("jimmy", "three", "structs") somePodList := newPodList("jimmy", "three", "structs")
@ -750,9 +754,8 @@ func TestOutputContainerLogsForPodList(t *testing.T) {
outBuffer := &bytes.Buffer{} outBuffer := &bytes.Buffer{}
outBufferFunc := func(_, _, _ string) io.Writer { return outBuffer } outBufferFunc := func(_, _, _ string) io.Writer { return outBuffer }
err := c.OutputContainerLogsForPodList(&somePodList, namespace, outBufferFunc) err := c.OutputContainerLogsForPodList(&somePodList, namespace, outBufferFunc)
clientAssertions := assert.New(t) req.NoError(err)
clientAssertions.NoError(err) is.Equal("fake logsfake logsfake logs", outBuffer.String())
clientAssertions.Equal("fake logsfake logsfake logs", outBuffer.String())
} }
const testServiceManifest = ` const testServiceManifest = `

@ -25,6 +25,7 @@ import (
"testing" "testing"
"github.com/stretchr/testify/assert" "github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"
) )
type fakeRoundTripper struct { type fakeRoundTripper struct {
@ -138,11 +139,10 @@ func TestRetryingRoundTripper_RoundTrip(t *testing.T) {
resp, err := rt.RoundTrip(req) resp, err := rt.RoundTrip(req)
if tt.expectedErr != "" { if tt.expectedErr != "" {
assert.Error(t, err) assert.ErrorContains(t, err, tt.expectedErr)
assert.Contains(t, err.Error(), tt.expectedErr)
return return
} }
assert.NoError(t, err) require.NoError(t, err)
assert.Equal(t, tt.expectedCode, resp.StatusCode) assert.Equal(t, tt.expectedCode, resp.StatusCode)
assert.Equal(t, tt.expectedCalls, fakeRT.calls) assert.Equal(t, tt.expectedCalls, fakeRT.calls)

@ -167,7 +167,7 @@ func getRuntimeObjFromManifests(t *testing.T, manifests []string) []runtime.Obje
for _, manifest := range manifests { for _, manifest := range manifests {
m := make(map[string]interface{}) m := make(map[string]interface{})
err := yaml.Unmarshal([]byte(manifest), &m) err := yaml.Unmarshal([]byte(manifest), &m)
assert.NoError(t, err) require.NoError(t, err)
resource := &unstructured.Unstructured{Object: m} resource := &unstructured.Unstructured{Object: m}
objects = append(objects, resource) objects = append(objects, resource)
} }
@ -179,7 +179,7 @@ func getResourceListFromRuntimeObjs(t *testing.T, c *Client, objs []runtime.Obje
resourceList := ResourceList{} resourceList := ResourceList{}
for _, obj := range objs { for _, obj := range objs {
list, err := c.Build(objBody(obj), false) list, err := c.Build(objBody(obj), false)
assert.NoError(t, err) require.NoError(t, err)
resourceList = append(resourceList, list...) resourceList = append(resourceList, list...)
} }
return resourceList return resourceList
@ -226,7 +226,7 @@ func TestStatusWaitForDelete(t *testing.T) {
u := objToCreate.(*unstructured.Unstructured) u := objToCreate.(*unstructured.Unstructured)
gvr := getGVR(t, fakeMapper, u) gvr := getGVR(t, fakeMapper, u)
err := fakeClient.Tracker().Create(gvr, u, u.GetNamespace()) err := fakeClient.Tracker().Create(gvr, u, u.GetNamespace())
assert.NoError(t, err) require.NoError(t, err)
} }
objsToDelete := getRuntimeObjFromManifests(t, tt.manifestsToDelete) objsToDelete := getRuntimeObjFromManifests(t, tt.manifestsToDelete)
for _, objToDelete := range objsToDelete { for _, objToDelete := range objsToDelete {
@ -324,7 +324,7 @@ func TestStatusWait(t *testing.T) {
u := obj.(*unstructured.Unstructured) u := obj.(*unstructured.Unstructured)
gvr := getGVR(t, fakeMapper, u) gvr := getGVR(t, fakeMapper, u)
err := fakeClient.Tracker().Create(gvr, u, u.GetNamespace()) err := fakeClient.Tracker().Create(gvr, u, u.GetNamespace())
assert.NoError(t, err) require.NoError(t, err)
} }
resourceList := getResourceListFromRuntimeObjs(t, c, objs) resourceList := getResourceListFromRuntimeObjs(t, c, objs)
err := statusWaiter.Wait(resourceList, time.Second*3) err := statusWaiter.Wait(resourceList, time.Second*3)
@ -377,7 +377,7 @@ func TestWaitForJobComplete(t *testing.T) {
u := obj.(*unstructured.Unstructured) u := obj.(*unstructured.Unstructured)
gvr := getGVR(t, fakeMapper, u) gvr := getGVR(t, fakeMapper, u)
err := fakeClient.Tracker().Create(gvr, u, u.GetNamespace()) err := fakeClient.Tracker().Create(gvr, u, u.GetNamespace())
assert.NoError(t, err) require.NoError(t, err)
} }
resourceList := getResourceListFromRuntimeObjs(t, c, objs) resourceList := getResourceListFromRuntimeObjs(t, c, objs)
err := statusWaiter.WaitWithJobs(resourceList, time.Second*3) err := statusWaiter.WaitWithJobs(resourceList, time.Second*3)
@ -436,7 +436,7 @@ func TestWatchForReady(t *testing.T) {
u := obj.(*unstructured.Unstructured) u := obj.(*unstructured.Unstructured)
gvr := getGVR(t, fakeMapper, u) gvr := getGVR(t, fakeMapper, u)
err := fakeClient.Tracker().Create(gvr, u, u.GetNamespace()) err := fakeClient.Tracker().Create(gvr, u, u.GetNamespace())
assert.NoError(t, err) require.NoError(t, err)
} }
resourceList := getResourceListFromRuntimeObjs(t, c, objs) resourceList := getResourceListFromRuntimeObjs(t, c, objs)
err := statusWaiter.WatchUntilReady(resourceList, time.Second*3) err := statusWaiter.WatchUntilReady(resourceList, time.Second*3)

@ -23,6 +23,7 @@ import (
"testing" "testing"
"github.com/stretchr/testify/assert" "github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"
appsv1 "k8s.io/api/apps/v1" appsv1 "k8s.io/api/apps/v1"
appsv1beta1 "k8s.io/api/apps/v1beta1" appsv1beta1 "k8s.io/api/apps/v1beta1"
appsv1beta2 "k8s.io/api/apps/v1beta2" appsv1beta2 "k8s.io/api/apps/v1beta2"
@ -227,10 +228,9 @@ func TestSelectorsForObject(t *testing.T) {
t.Run(tt.name, func(t *testing.T) { t.Run(tt.name, func(t *testing.T) {
selector, err := SelectorsForObject(tt.object.(runtime.Object)) selector, err := SelectorsForObject(tt.object.(runtime.Object))
if tt.expectError { if tt.expectError {
assert.Error(t, err) assert.ErrorContains(t, err, tt.errorContains)
assert.Contains(t, err.Error(), tt.errorContains)
} else { } else {
assert.NoError(t, err) require.NoError(t, err)
expected := labels.Set(tt.expectedLabels) expected := labels.Set(tt.expectedLabels)
assert.True(t, selector.Matches(expected), "expected selector to match") assert.True(t, selector.Matches(expected), "expected selector to match")
} }

@ -22,6 +22,7 @@ import (
"time" "time"
"github.com/stretchr/testify/assert" "github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"
chartutil "helm.sh/helm/v4/pkg/chart/v2/util" chartutil "helm.sh/helm/v4/pkg/chart/v2/util"
"helm.sh/helm/v4/pkg/lint/support" "helm.sh/helm/v4/pkg/lint/support"
@ -122,7 +123,7 @@ func TestBadValues(t *testing.T) {
func TestBadCrdFile(t *testing.T) { func TestBadCrdFile(t *testing.T) {
m := RunAll(badCrdFileDir, values, namespace).Messages m := RunAll(badCrdFileDir, values, namespace).Messages
assert.Lenf(t, m, 2, "All didn't fail with expected errors, got %#v", m) assert.Lenf(t, m, 2, "All didn't fail with expected errors, got %#v", m)
assert.ErrorContains(t, m[0].Err, "apiVersion is not in 'apiextensions.k8s.io'") require.ErrorContains(t, m[0].Err, "apiVersion is not in 'apiextensions.k8s.io'")
assert.ErrorContains(t, m[1].Err, "object kind is not 'CustomResourceDefinition'") assert.ErrorContains(t, m[1].Err, "object kind is not 'CustomResourceDefinition'")
} }

@ -96,7 +96,7 @@ func TestValidateValuesFileSchemaFailure(t *testing.T) {
t.Fatal("expected values file to fail parsing") t.Fatal("expected values file to fail parsing")
} }
assert.Contains(t, err.Error(), "- at '/username': got number, want string") assert.ErrorContains(t, err, "- at '/username': got number, want string")
} }
func TestValidateValuesFileSchemaOverrides(t *testing.T) { func TestValidateValuesFileSchemaOverrides(t *testing.T) {
@ -153,7 +153,7 @@ func TestValidateValuesFile(t *testing.T) {
case err == nil && tt.errorMessage != "": case err == nil && tt.errorMessage != "":
t.Error("expected values file to fail parsing") t.Error("expected values file to fail parsing")
case err != nil && tt.errorMessage != "": case err != nil && tt.errorMessage != "":
assert.Contains(t, err.Error(), tt.errorMessage, "Failed with unexpected error") assert.ErrorContains(t, err, tt.errorMessage, "Failed with unexpected error")
} }
}) })
} }
@ -162,7 +162,7 @@ func TestValidateValuesFile(t *testing.T) {
func createTestingSchema(t *testing.T, dir string) string { func createTestingSchema(t *testing.T, dir string) string {
t.Helper() t.Helper()
schemafile := filepath.Join(dir, "values.schema.json") schemafile := filepath.Join(dir, "values.schema.json")
if err := os.WriteFile(schemafile, []byte(testSchema), 0700); err != nil { if err := os.WriteFile(schemafile, []byte(testSchema), 0o700); err != nil {
t.Fatalf("Failed to write schema to tmpdir: %s", err) t.Fatalf("Failed to write schema to tmpdir: %s", err)
} }
return schemafile return schemafile

@ -37,11 +37,12 @@ fi
func TestGetFullPath(t *testing.T) { func TestGetFullPath(t *testing.T) {
is := assert.New(t) is := assert.New(t)
req := require.New(t)
t.Run("full path resolves correctly", func(t *testing.T) { t.Run("full path resolves correctly", func(t *testing.T) {
testpath := setupTestingScript(t) testpath := setupTestingScript(t)
fullPath, err := getFullPath(testpath) fullPath, err := getFullPath(testpath)
is.NoError(err) req.NoError(err)
is.Equal(testpath, fullPath) is.Equal(testpath, fullPath)
}) })
@ -53,7 +54,7 @@ func TestGetFullPath(t *testing.T) {
relative, err := filepath.Rel(currentDir, testpath) relative, err := filepath.Rel(currentDir, testpath)
require.NoError(t, err) require.NoError(t, err)
fullPath, err := getFullPath(relative) fullPath, err := getFullPath(relative)
is.NoError(err) req.NoError(err)
is.Equal(testpath, fullPath) is.Equal(testpath, fullPath)
}) })
@ -63,7 +64,7 @@ func TestGetFullPath(t *testing.T) {
t.Setenv("PATH", filepath.Dir(testpath)) t.Setenv("PATH", filepath.Dir(testpath))
fullPath, err := getFullPath(filepath.Base(testpath)) fullPath, err := getFullPath(filepath.Base(testpath))
is.NoError(err) req.NoError(err)
is.Equal(testpath, fullPath) is.Equal(testpath, fullPath)
}) })
@ -107,13 +108,14 @@ func TestExecRun(t *testing.T) {
t.Skip("skipping on windows") t.Skip("skipping on windows")
} }
is := assert.New(t) is := assert.New(t)
req := require.New(t)
testpath := setupTestingScript(t) testpath := setupTestingScript(t)
renderer, err := NewExec(testpath) renderer, err := NewExec(testpath)
require.NoError(t, err) require.NoError(t, err)
output, err := renderer.Run(bytes.NewBufferString("FOOTEST")) output, err := renderer.Run(bytes.NewBufferString("FOOTEST"))
is.NoError(err) req.NoError(err)
is.Contains(output.String(), "BARTEST") is.Contains(output.String(), "BARTEST")
} }
@ -138,13 +140,14 @@ func TestNewExecWithOneArgsRun(t *testing.T) {
t.Skip("skipping on windows") t.Skip("skipping on windows")
} }
is := assert.New(t) is := assert.New(t)
req := require.New(t)
testpath := setupTestingScript(t) testpath := setupTestingScript(t)
renderer, err := NewExec(testpath, "ARG1") renderer, err := NewExec(testpath, "ARG1")
require.NoError(t, err) require.NoError(t, err)
output, err := renderer.Run(bytes.NewBufferString("FOOTEST")) output, err := renderer.Run(bytes.NewBufferString("FOOTEST"))
is.NoError(err) req.NoError(err)
is.Contains(output.String(), "ARG1") is.Contains(output.String(), "ARG1")
} }
@ -154,13 +157,14 @@ func TestNewExecWithTwoArgsRun(t *testing.T) {
t.Skip("skipping on windows") t.Skip("skipping on windows")
} }
is := assert.New(t) is := assert.New(t)
req := require.New(t)
testpath := setupTestingScript(t) testpath := setupTestingScript(t)
renderer, err := NewExec(testpath, "ARG1", "ARG2") renderer, err := NewExec(testpath, "ARG1", "ARG2")
require.NoError(t, err) require.NoError(t, err)
output, err := renderer.Run(bytes.NewBufferString("FOOTEST")) output, err := renderer.Run(bytes.NewBufferString("FOOTEST"))
is.NoError(err) req.NoError(err)
is.Contains(output.String(), "ARG1 ARG2") is.Contains(output.String(), "ARG1 ARG2")
} }

@ -17,7 +17,6 @@ limitations under the License.
package registry package registry
import ( import (
"errors"
"fmt" "fmt"
"os" "os"
"testing" "testing"
@ -47,12 +46,12 @@ func (suite *HTTPRegistryClientTestSuite) Test_0_Login() {
err := suite.RegistryClient.Login(suite.DockerRegistryHost, err := suite.RegistryClient.Login(suite.DockerRegistryHost,
LoginOptBasicAuth("badverybad", "ohsobad"), LoginOptBasicAuth("badverybad", "ohsobad"),
LoginOptPlainText(true)) LoginOptPlainText(true))
suite.NotNil(err, "error logging into registry with bad credentials") suite.Require().Error(err, "error logging into registry with bad credentials")
err = suite.RegistryClient.Login(suite.DockerRegistryHost, err = suite.RegistryClient.Login(suite.DockerRegistryHost,
LoginOptBasicAuth(testUsername, testPassword), LoginOptBasicAuth(testUsername, testPassword),
LoginOptPlainText(true)) LoginOptPlainText(true))
suite.Nil(err, "no error logging into registry with good credentials") suite.Require().NoError(err, "no error logging into registry with good credentials")
} }
func (suite *HTTPRegistryClientTestSuite) Test_1_Push() { func (suite *HTTPRegistryClientTestSuite) Test_1_Push() {
@ -72,8 +71,7 @@ func (suite *HTTPRegistryClientTestSuite) Test_4_ManInTheMiddle() {
// returns content that does not match the expected digest // returns content that does not match the expected digest
_, err := suite.RegistryClient.Pull(ref) _, err := suite.RegistryClient.Pull(ref)
suite.NotNil(err) suite.Assert().ErrorIs(err, content.ErrMismatchedDigest)
suite.True(errors.Is(err, content.ErrMismatchedDigest))
} }
func TestHTTPRegistryClientTestSuite(t *testing.T) { func TestHTTPRegistryClientTestSuite(t *testing.T) {

@ -44,12 +44,12 @@ func (suite *InsecureTLSRegistryClientTestSuite) Test_0_Login() {
err := suite.RegistryClient.Login(suite.DockerRegistryHost, err := suite.RegistryClient.Login(suite.DockerRegistryHost,
LoginOptBasicAuth("badverybad", "ohsobad"), LoginOptBasicAuth("badverybad", "ohsobad"),
LoginOptInsecure(true)) LoginOptInsecure(true))
suite.NotNil(err, "error logging into registry with bad credentials") suite.Require().Error(err, "error logging into registry with bad credentials")
err = suite.RegistryClient.Login(suite.DockerRegistryHost, err = suite.RegistryClient.Login(suite.DockerRegistryHost,
LoginOptBasicAuth(testUsername, testPassword), LoginOptBasicAuth(testUsername, testPassword),
LoginOptInsecure(true)) LoginOptInsecure(true))
suite.Nil(err, "no error logging into registry with good credentials") suite.Require().NoError(err, "no error logging into registry with good credentials")
} }
func (suite *InsecureTLSRegistryClientTestSuite) Test_1_Push() { func (suite *InsecureTLSRegistryClientTestSuite) Test_1_Push() {
@ -68,11 +68,11 @@ func (suite *InsecureTLSRegistryClientTestSuite) Test_4_Logout() {
err := suite.RegistryClient.Logout("this-host-aint-real:5000") err := suite.RegistryClient.Logout("this-host-aint-real:5000")
if err != nil { if err != nil {
// credential backend for mac generates an error // credential backend for mac generates an error
suite.NotNil(err, "failed to delete the credential for this-host-aint-real:5000") suite.Require().Error(err, "failed to delete the credential for this-host-aint-real:5000")
} }
err = suite.RegistryClient.Logout(suite.DockerRegistryHost) err = suite.RegistryClient.Logout(suite.DockerRegistryHost)
suite.Nil(err, "no error logging out of registry") suite.Require().NoError(err, "no error logging out of registry")
} }
func TestInsecureTLSRegistryClientTestSuite(t *testing.T) { func TestInsecureTLSRegistryClientTestSuite(t *testing.T) {

@ -44,12 +44,12 @@ func (suite *TLSRegistryClientTestSuite) Test_0_Login() {
err := suite.RegistryClient.Login(suite.DockerRegistryHost, err := suite.RegistryClient.Login(suite.DockerRegistryHost,
LoginOptBasicAuth("badverybad", "ohsobad"), LoginOptBasicAuth("badverybad", "ohsobad"),
LoginOptTLSClientConfig(tlsCert, tlsKey, tlsCA)) LoginOptTLSClientConfig(tlsCert, tlsKey, tlsCA))
suite.NotNil(err, "error logging into registry with bad credentials") suite.Require().Error(err, "error logging into registry with bad credentials")
err = suite.RegistryClient.Login(suite.DockerRegistryHost, err = suite.RegistryClient.Login(suite.DockerRegistryHost,
LoginOptBasicAuth(testUsername, testPassword), LoginOptBasicAuth(testUsername, testPassword),
LoginOptTLSClientConfig(tlsCert, tlsKey, tlsCA)) LoginOptTLSClientConfig(tlsCert, tlsKey, tlsCA))
suite.Nil(err, "no error logging into registry with good credentials") suite.Require().NoError(err, "no error logging into registry with good credentials")
} }
func (suite *TLSRegistryClientTestSuite) Test_1_Push() { func (suite *TLSRegistryClientTestSuite) Test_1_Push() {
@ -68,11 +68,11 @@ func (suite *TLSRegistryClientTestSuite) Test_4_Logout() {
err := suite.RegistryClient.Logout("this-host-aint-real:5000") err := suite.RegistryClient.Logout("this-host-aint-real:5000")
if err != nil { if err != nil {
// credential backend for mac generates an error // credential backend for mac generates an error
suite.NotNil(err, "failed to delete the credential for this-host-aint-real:5000") suite.Require().Error(err, "failed to delete the credential for this-host-aint-real:5000")
} }
err = suite.RegistryClient.Logout(suite.DockerRegistryHost) err = suite.RegistryClient.Logout(suite.DockerRegistryHost)
suite.Nil(err, "no error logging out of registry") suite.Require().NoError(err, "no error logging out of registry")
} }
func TestTLSRegistryClientTestSuite(t *testing.T) { func TestTLSRegistryClientTestSuite(t *testing.T) {

@ -73,7 +73,7 @@ type TestSuite struct {
func setup(suite *TestSuite, tlsEnabled, insecure bool) *registry.Registry { func setup(suite *TestSuite, tlsEnabled, insecure bool) *registry.Registry {
suite.WorkspaceDir = testWorkspaceDir suite.WorkspaceDir = testWorkspaceDir
os.RemoveAll(suite.WorkspaceDir) os.RemoveAll(suite.WorkspaceDir)
os.Mkdir(suite.WorkspaceDir, 0700) os.Mkdir(suite.WorkspaceDir, 0o700)
var ( var (
out bytes.Buffer out bytes.Buffer
@ -108,26 +108,26 @@ func setup(suite *TestSuite, tlsEnabled, insecure bool) *registry.Registry {
TLSClientConfig: tlsConf, TLSClientConfig: tlsConf,
}, },
} }
suite.Nil(err, "no error loading tls config") suite.Require().NoError(err, "no error loading tls config")
opts = append(opts, ClientOptHTTPClient(httpClient)) opts = append(opts, ClientOptHTTPClient(httpClient))
} else { } else {
opts = append(opts, ClientOptPlainHTTP()) opts = append(opts, ClientOptPlainHTTP())
} }
suite.RegistryClient, err = NewClient(opts...) suite.RegistryClient, err = NewClient(opts...)
suite.Nil(err, "no error creating registry client") suite.Require().NoError(err, "no error creating registry client")
// create htpasswd file (w BCrypt, which is required) // create htpasswd file (w BCrypt, which is required)
pwBytes, err := bcrypt.GenerateFromPassword([]byte(testPassword), bcrypt.DefaultCost) pwBytes, err := bcrypt.GenerateFromPassword([]byte(testPassword), bcrypt.DefaultCost)
suite.Nil(err, "no error generating bcrypt password for test htpasswd file") suite.Require().NoError(err, "no error generating bcrypt password for test htpasswd file")
htpasswdPath := filepath.Join(suite.WorkspaceDir, testHtpasswdFileBasename) htpasswdPath := filepath.Join(suite.WorkspaceDir, testHtpasswdFileBasename)
err = os.WriteFile(htpasswdPath, []byte(fmt.Sprintf("%s:%s\n", testUsername, string(pwBytes))), 0644) err = os.WriteFile(htpasswdPath, []byte(fmt.Sprintf("%s:%s\n", testUsername, string(pwBytes))), 0o644)
suite.Nil(err, "no error creating test htpasswd file") suite.Require().NoError(err, "no error creating test htpasswd file")
// Registry config // Registry config
config := &configuration.Configuration{} config := &configuration.Configuration{}
ln, err := net.Listen("tcp", "127.0.0.1:0") ln, err := net.Listen("tcp", "127.0.0.1:0")
suite.Nil(err, "no error finding free port for test registry") suite.Require().NoError(err, "no error finding free port for test registry")
defer ln.Close() defer ln.Close()
// Change the registry host to another host which is not localhost. // Change the registry host to another host which is not localhost.
@ -140,7 +140,7 @@ func setup(suite *TestSuite, tlsEnabled, insecure bool) *registry.Registry {
A: []string{"127.0.0.1"}, A: []string{"127.0.0.1"},
}, },
}, false) }, false)
suite.Nil(err, "no error creating mock DNS server") suite.Require().NoError(err, "no error creating mock DNS server")
suite.srv.PatchNet(net.DefaultResolver) suite.srv.PatchNet(net.DefaultResolver)
config.HTTP.Addr = ln.Addr().String() config.HTTP.Addr = ln.Addr().String()
@ -167,7 +167,7 @@ func setup(suite *TestSuite, tlsEnabled, insecure bool) *registry.Registry {
} }
} }
dockerRegistry, err := registry.NewRegistry(context.Background(), config) dockerRegistry, err := registry.NewRegistry(context.Background(), config)
suite.Nil(err, "no error creating test registry") suite.Require().NoError(err, "no error creating test registry")
suite.CompromisedRegistryHost = initCompromisedRegistryTestServer() suite.CompromisedRegistryHost = initCompromisedRegistryTestServer()
return dockerRegistry return dockerRegistry
@ -222,88 +222,87 @@ func initCompromisedRegistryTestServer() string {
} }
func testPush(suite *TestSuite) { func testPush(suite *TestSuite) {
testingChartCreationTime := "1977-09-02T22:04:05Z" testingChartCreationTime := "1977-09-02T22:04:05Z"
// Bad bytes // Bad bytes
ref := fmt.Sprintf("%s/testrepo/testchart:1.2.3", suite.DockerRegistryHost) ref := fmt.Sprintf("%s/testrepo/testchart:1.2.3", suite.DockerRegistryHost)
_, err := suite.RegistryClient.Push([]byte("hello"), ref, PushOptCreationTime(testingChartCreationTime)) _, err := suite.RegistryClient.Push([]byte("hello"), ref, PushOptCreationTime(testingChartCreationTime))
suite.NotNil(err, "error pushing non-chart bytes") suite.Require().Error(err, "error pushing non-chart bytes")
// Load a test chart // Load a test chart
chartData, err := os.ReadFile("../repo/repotest/testdata/examplechart-0.1.0.tgz") chartData, err := os.ReadFile("../repo/repotest/testdata/examplechart-0.1.0.tgz")
suite.Nil(err, "no error loading test chart") suite.Require().NoError(err, "no error loading test chart")
meta, err := extractChartMeta(chartData) meta, err := extractChartMeta(chartData)
suite.Nil(err, "no error extracting chart meta") suite.Require().NoError(err, "no error extracting chart meta")
// non-strict ref (chart name) // non-strict ref (chart name)
ref = fmt.Sprintf("%s/testrepo/boop:%s", suite.DockerRegistryHost, meta.Version) ref = fmt.Sprintf("%s/testrepo/boop:%s", suite.DockerRegistryHost, meta.Version)
_, err = suite.RegistryClient.Push(chartData, ref, PushOptCreationTime(testingChartCreationTime)) _, err = suite.RegistryClient.Push(chartData, ref, PushOptCreationTime(testingChartCreationTime))
suite.NotNil(err, "error pushing non-strict ref (bad basename)") suite.Require().Error(err, "error pushing non-strict ref (bad basename)")
// non-strict ref (chart name), with strict mode disabled // non-strict ref (chart name), with strict mode disabled
_, err = suite.RegistryClient.Push(chartData, ref, PushOptStrictMode(false), PushOptCreationTime(testingChartCreationTime)) _, err = suite.RegistryClient.Push(chartData, ref, PushOptStrictMode(false), PushOptCreationTime(testingChartCreationTime))
suite.Nil(err, "no error pushing non-strict ref (bad basename), with strict mode disabled") suite.Require().NoError(err, "no error pushing non-strict ref (bad basename), with strict mode disabled")
// non-strict ref (chart version) // non-strict ref (chart version)
ref = fmt.Sprintf("%s/testrepo/%s:latest", suite.DockerRegistryHost, meta.Name) ref = fmt.Sprintf("%s/testrepo/%s:latest", suite.DockerRegistryHost, meta.Name)
_, err = suite.RegistryClient.Push(chartData, ref, PushOptCreationTime(testingChartCreationTime)) _, err = suite.RegistryClient.Push(chartData, ref, PushOptCreationTime(testingChartCreationTime))
suite.NotNil(err, "error pushing non-strict ref (bad tag)") suite.Require().Error(err, "error pushing non-strict ref (bad tag)")
// non-strict ref (chart version), with strict mode disabled // non-strict ref (chart version), with strict mode disabled
_, err = suite.RegistryClient.Push(chartData, ref, PushOptStrictMode(false), PushOptCreationTime(testingChartCreationTime)) _, err = suite.RegistryClient.Push(chartData, ref, PushOptStrictMode(false), PushOptCreationTime(testingChartCreationTime))
suite.Nil(err, "no error pushing non-strict ref (bad tag), with strict mode disabled") suite.Require().NoError(err, "no error pushing non-strict ref (bad tag), with strict mode disabled")
// basic push, good ref // basic push, good ref
chartData, err = os.ReadFile("../downloader/testdata/local-subchart-0.1.0.tgz") chartData, err = os.ReadFile("../downloader/testdata/local-subchart-0.1.0.tgz")
suite.Nil(err, "no error loading test chart") suite.Require().NoError(err, "no error loading test chart")
meta, err = extractChartMeta(chartData) meta, err = extractChartMeta(chartData)
suite.Nil(err, "no error extracting chart meta") suite.Require().NoError(err, "no error extracting chart meta")
ref = fmt.Sprintf("%s/testrepo/%s:%s", suite.DockerRegistryHost, meta.Name, meta.Version) ref = fmt.Sprintf("%s/testrepo/%s:%s", suite.DockerRegistryHost, meta.Name, meta.Version)
_, err = suite.RegistryClient.Push(chartData, ref, PushOptCreationTime(testingChartCreationTime)) _, err = suite.RegistryClient.Push(chartData, ref, PushOptCreationTime(testingChartCreationTime))
suite.Nil(err, "no error pushing good ref") suite.Require().NoError(err, "no error pushing good ref")
_, err = suite.RegistryClient.Pull(ref) _, err = suite.RegistryClient.Pull(ref)
suite.Nil(err, "no error pulling a simple chart") suite.Require().NoError(err, "no error pulling a simple chart")
// Load another test chart // Load another test chart
chartData, err = os.ReadFile("../downloader/testdata/signtest-0.1.0.tgz") chartData, err = os.ReadFile("../downloader/testdata/signtest-0.1.0.tgz")
suite.Nil(err, "no error loading test chart") suite.Require().NoError(err, "no error loading test chart")
meta, err = extractChartMeta(chartData) meta, err = extractChartMeta(chartData)
suite.Nil(err, "no error extracting chart meta") suite.Require().NoError(err, "no error extracting chart meta")
// Load prov file // Load prov file
provData, err := os.ReadFile("../downloader/testdata/signtest-0.1.0.tgz.prov") provData, err := os.ReadFile("../downloader/testdata/signtest-0.1.0.tgz.prov")
suite.Nil(err, "no error loading test prov") suite.Require().NoError(err, "no error loading test prov")
// push with prov // push with prov
ref = fmt.Sprintf("%s/testrepo/%s:%s", suite.DockerRegistryHost, meta.Name, meta.Version) ref = fmt.Sprintf("%s/testrepo/%s:%s", suite.DockerRegistryHost, meta.Name, meta.Version)
result, err := suite.RegistryClient.Push(chartData, ref, PushOptProvData(provData), PushOptCreationTime(testingChartCreationTime)) result, err := suite.RegistryClient.Push(chartData, ref, PushOptProvData(provData), PushOptCreationTime(testingChartCreationTime))
suite.Nil(err, "no error pushing good ref with prov") suite.Require().NoError(err, "no error pushing good ref with prov")
_, err = suite.RegistryClient.Pull(ref, PullOptWithProv(true)) _, err = suite.RegistryClient.Pull(ref, PullOptWithProv(true))
suite.Nil(err, "no error pulling a simple chart") suite.Require().NoError(err, "no error pulling a simple chart")
// Validate the output // Validate the output
// Note: these digests/sizes etc may change if the test chart/prov files are modified, // Note: these digests/sizes etc may change if the test chart/prov files are modified,
// or if the format of the OCI manifest changes // or if the format of the OCI manifest changes
suite.Equal(ref, result.Ref) suite.Assert().Equal(ref, result.Ref)
suite.Equal(meta.Name, result.Chart.Meta.Name) suite.Assert().Equal(meta.Name, result.Chart.Meta.Name)
suite.Equal(meta.Version, result.Chart.Meta.Version) suite.Assert().Equal(meta.Version, result.Chart.Meta.Version)
suite.Equal(int64(742), result.Manifest.Size) suite.Assert().Equal(int64(742), result.Manifest.Size)
suite.Equal(int64(99), result.Config.Size) suite.Assert().Equal(int64(99), result.Config.Size)
suite.Equal(int64(973), result.Chart.Size) suite.Assert().Equal(int64(973), result.Chart.Size)
suite.Equal(int64(695), result.Prov.Size) suite.Assert().Equal(int64(695), result.Prov.Size)
suite.Equal( suite.Assert().Equal(
"sha256:fbbade96da6050f68f94f122881e3b80051a18f13ab5f4081868dd494538f5c2", "sha256:fbbade96da6050f68f94f122881e3b80051a18f13ab5f4081868dd494538f5c2",
result.Manifest.Digest) result.Manifest.Digest)
suite.Equal( suite.Assert().Equal(
"sha256:8d17cb6bf6ccd8c29aace9a658495cbd5e2e87fc267876e86117c7db681c9580", "sha256:8d17cb6bf6ccd8c29aace9a658495cbd5e2e87fc267876e86117c7db681c9580",
result.Config.Digest) result.Config.Digest)
suite.Equal( suite.Assert().Equal(
"sha256:e5ef611620fb97704d8751c16bab17fedb68883bfb0edc76f78a70e9173f9b55", "sha256:e5ef611620fb97704d8751c16bab17fedb68883bfb0edc76f78a70e9173f9b55",
result.Chart.Digest) result.Chart.Digest)
suite.Equal( suite.Assert().Equal(
"sha256:b0a02b7412f78ae93324d48df8fcc316d8482e5ad7827b5b238657a29a22f256", "sha256:b0a02b7412f78ae93324d48df8fcc316d8482e5ad7827b5b238657a29a22f256",
result.Prov.Digest) result.Prov.Digest)
} }
@ -312,91 +311,91 @@ func testPull(suite *TestSuite) {
// bad/missing ref // bad/missing ref
ref := fmt.Sprintf("%s/testrepo/no-existy:1.2.3", suite.DockerRegistryHost) ref := fmt.Sprintf("%s/testrepo/no-existy:1.2.3", suite.DockerRegistryHost)
_, err := suite.RegistryClient.Pull(ref) _, err := suite.RegistryClient.Pull(ref)
suite.NotNil(err, "error on bad/missing ref") suite.Require().Error(err, "error on bad/missing ref")
// Load test chart (to build ref pushed in previous test) // Load test chart (to build ref pushed in previous test)
chartData, err := os.ReadFile("../downloader/testdata/local-subchart-0.1.0.tgz") chartData, err := os.ReadFile("../downloader/testdata/local-subchart-0.1.0.tgz")
suite.Nil(err, "no error loading test chart") suite.Require().NoError(err, "no error loading test chart")
meta, err := extractChartMeta(chartData) meta, err := extractChartMeta(chartData)
suite.Nil(err, "no error extracting chart meta") suite.Require().NoError(err, "no error extracting chart meta")
ref = fmt.Sprintf("%s/testrepo/%s:%s", suite.DockerRegistryHost, meta.Name, meta.Version) ref = fmt.Sprintf("%s/testrepo/%s:%s", suite.DockerRegistryHost, meta.Name, meta.Version)
// Simple pull, chart only // Simple pull, chart only
_, err = suite.RegistryClient.Pull(ref) _, err = suite.RegistryClient.Pull(ref)
suite.Nil(err, "no error pulling a simple chart") suite.Require().NoError(err, "no error pulling a simple chart")
// Simple pull with prov (no prov uploaded) // Simple pull with prov (no prov uploaded)
_, err = suite.RegistryClient.Pull(ref, PullOptWithProv(true)) _, err = suite.RegistryClient.Pull(ref, PullOptWithProv(true))
suite.NotNil(err, "error pulling a chart with prov when no prov exists") suite.Require().Error(err, "error pulling a chart with prov when no prov exists")
// Simple pull with prov, ignoring missing prov // Simple pull with prov, ignoring missing prov
_, err = suite.RegistryClient.Pull(ref, _, err = suite.RegistryClient.Pull(ref,
PullOptWithProv(true), PullOptWithProv(true),
PullOptIgnoreMissingProv(true)) PullOptIgnoreMissingProv(true))
suite.Nil(err, suite.Require().NoError(err,
"no error pulling a chart with prov when no prov exists, ignoring missing") "no error pulling a chart with prov when no prov exists, ignoring missing")
// Load test chart (to build ref pushed in previous test) // Load test chart (to build ref pushed in previous test)
chartData, err = os.ReadFile("../downloader/testdata/signtest-0.1.0.tgz") chartData, err = os.ReadFile("../downloader/testdata/signtest-0.1.0.tgz")
suite.Nil(err, "no error loading test chart") suite.Require().NoError(err, "no error loading test chart")
meta, err = extractChartMeta(chartData) meta, err = extractChartMeta(chartData)
suite.Nil(err, "no error extracting chart meta") suite.Require().NoError(err, "no error extracting chart meta")
ref = fmt.Sprintf("%s/testrepo/%s:%s", suite.DockerRegistryHost, meta.Name, meta.Version) ref = fmt.Sprintf("%s/testrepo/%s:%s", suite.DockerRegistryHost, meta.Name, meta.Version)
// Load prov file // Load prov file
provData, err := os.ReadFile("../downloader/testdata/signtest-0.1.0.tgz.prov") provData, err := os.ReadFile("../downloader/testdata/signtest-0.1.0.tgz.prov")
suite.Nil(err, "no error loading test prov") suite.Require().NoError(err, "no error loading test prov")
// no chart and no prov causes error // no chart and no prov causes error
_, err = suite.RegistryClient.Pull(ref, _, err = suite.RegistryClient.Pull(ref,
PullOptWithChart(false), PullOptWithChart(false),
PullOptWithProv(false)) PullOptWithProv(false))
suite.NotNil(err, "error on both no chart and no prov") suite.Require().Error(err, "error on both no chart and no prov")
// full pull with chart and prov // full pull with chart and prov
result, err := suite.RegistryClient.Pull(ref, PullOptWithProv(true)) result, err := suite.RegistryClient.Pull(ref, PullOptWithProv(true))
suite.Require().Nil(err, "no error pulling a chart with prov") suite.Require().NoError(err, "no error pulling a chart with prov")
// Validate the output // Validate the output
// Note: these digests/sizes etc may change if the test chart/prov files are modified, // Note: these digests/sizes etc may change if the test chart/prov files are modified,
// or if the format of the OCI manifest changes // or if the format of the OCI manifest changes
suite.Equal(ref, result.Ref) suite.Assert().Equal(ref, result.Ref)
suite.Equal(meta.Name, result.Chart.Meta.Name) suite.Assert().Equal(meta.Name, result.Chart.Meta.Name)
suite.Equal(meta.Version, result.Chart.Meta.Version) suite.Assert().Equal(meta.Version, result.Chart.Meta.Version)
suite.Equal(int64(742), result.Manifest.Size) suite.Assert().Equal(int64(742), result.Manifest.Size)
suite.Equal(int64(99), result.Config.Size) suite.Assert().Equal(int64(99), result.Config.Size)
suite.Equal(int64(973), result.Chart.Size) suite.Assert().Equal(int64(973), result.Chart.Size)
suite.Equal(int64(695), result.Prov.Size) suite.Assert().Equal(int64(695), result.Prov.Size)
suite.Equal( suite.Assert().Equal(
"sha256:fbbade96da6050f68f94f122881e3b80051a18f13ab5f4081868dd494538f5c2", "sha256:fbbade96da6050f68f94f122881e3b80051a18f13ab5f4081868dd494538f5c2",
result.Manifest.Digest) result.Manifest.Digest)
suite.Equal( suite.Assert().Equal(
"sha256:8d17cb6bf6ccd8c29aace9a658495cbd5e2e87fc267876e86117c7db681c9580", "sha256:8d17cb6bf6ccd8c29aace9a658495cbd5e2e87fc267876e86117c7db681c9580",
result.Config.Digest) result.Config.Digest)
suite.Equal( suite.Assert().Equal(
"sha256:e5ef611620fb97704d8751c16bab17fedb68883bfb0edc76f78a70e9173f9b55", "sha256:e5ef611620fb97704d8751c16bab17fedb68883bfb0edc76f78a70e9173f9b55",
result.Chart.Digest) result.Chart.Digest)
suite.Equal( suite.Assert().Equal(
"sha256:b0a02b7412f78ae93324d48df8fcc316d8482e5ad7827b5b238657a29a22f256", "sha256:b0a02b7412f78ae93324d48df8fcc316d8482e5ad7827b5b238657a29a22f256",
result.Prov.Digest) result.Prov.Digest)
suite.Equal("{\"schemaVersion\":2,\"config\":{\"mediaType\":\"application/vnd.cncf.helm.config.v1+json\",\"digest\":\"sha256:8d17cb6bf6ccd8c29aace9a658495cbd5e2e87fc267876e86117c7db681c9580\",\"size\":99},\"layers\":[{\"mediaType\":\"application/vnd.cncf.helm.chart.provenance.v1.prov\",\"digest\":\"sha256:b0a02b7412f78ae93324d48df8fcc316d8482e5ad7827b5b238657a29a22f256\",\"size\":695},{\"mediaType\":\"application/vnd.cncf.helm.chart.content.v1.tar+gzip\",\"digest\":\"sha256:e5ef611620fb97704d8751c16bab17fedb68883bfb0edc76f78a70e9173f9b55\",\"size\":973}],\"annotations\":{\"org.opencontainers.image.created\":\"1977-09-02T22:04:05Z\",\"org.opencontainers.image.description\":\"A Helm chart for Kubernetes\",\"org.opencontainers.image.title\":\"signtest\",\"org.opencontainers.image.version\":\"0.1.0\"}}", suite.Assert().JSONEq("{\"schemaVersion\":2,\"config\":{\"mediaType\":\"application/vnd.cncf.helm.config.v1+json\",\"digest\":\"sha256:8d17cb6bf6ccd8c29aace9a658495cbd5e2e87fc267876e86117c7db681c9580\",\"size\":99},\"layers\":[{\"mediaType\":\"application/vnd.cncf.helm.chart.provenance.v1.prov\",\"digest\":\"sha256:b0a02b7412f78ae93324d48df8fcc316d8482e5ad7827b5b238657a29a22f256\",\"size\":695},{\"mediaType\":\"application/vnd.cncf.helm.chart.content.v1.tar+gzip\",\"digest\":\"sha256:e5ef611620fb97704d8751c16bab17fedb68883bfb0edc76f78a70e9173f9b55\",\"size\":973}],\"annotations\":{\"org.opencontainers.image.created\":\"1977-09-02T22:04:05Z\",\"org.opencontainers.image.description\":\"A Helm chart for Kubernetes\",\"org.opencontainers.image.title\":\"signtest\",\"org.opencontainers.image.version\":\"0.1.0\"}}",
string(result.Manifest.Data)) string(result.Manifest.Data))
suite.Equal("{\"name\":\"signtest\",\"version\":\"0.1.0\",\"description\":\"A Helm chart for Kubernetes\",\"apiVersion\":\"v1\"}", suite.Assert().JSONEq("{\"name\":\"signtest\",\"version\":\"0.1.0\",\"description\":\"A Helm chart for Kubernetes\",\"apiVersion\":\"v1\"}",
string(result.Config.Data)) string(result.Config.Data))
suite.Equal(chartData, result.Chart.Data) suite.Assert().Equal(chartData, result.Chart.Data)
suite.Equal(provData, result.Prov.Data) suite.Assert().Equal(provData, result.Prov.Data)
} }
func testTags(suite *TestSuite) { func testTags(suite *TestSuite) {
// Load test chart (to build ref pushed in previous test) // Load test chart (to build ref pushed in previous test)
chartData, err := os.ReadFile("../downloader/testdata/local-subchart-0.1.0.tgz") chartData, err := os.ReadFile("../downloader/testdata/local-subchart-0.1.0.tgz")
suite.Nil(err, "no error loading test chart") suite.Require().NoError(err, "no error loading test chart")
meta, err := extractChartMeta(chartData) meta, err := extractChartMeta(chartData)
suite.Nil(err, "no error extracting chart meta") suite.Require().NoError(err, "no error extracting chart meta")
ref := fmt.Sprintf("%s/testrepo/%s", suite.DockerRegistryHost, meta.Name) ref := fmt.Sprintf("%s/testrepo/%s", suite.DockerRegistryHost, meta.Name)
// Query for tags and validate length // Query for tags and validate length
tags, err := suite.RegistryClient.Tags(ref) tags, err := suite.RegistryClient.Tags(ref)
suite.Nil(err, "no error retrieving tags") suite.Require().NoError(err, "no error retrieving tags")
suite.Equal(1, len(tags)) suite.Assert().Len(tags, 1)
} }

@ -35,8 +35,7 @@ func MakeTestTLSConfig(t *testing.T, path string) *tls.Config {
tlsutil.WithCertKeyPairFiles(pub, priv), tlsutil.WithCertKeyPairFiles(pub, priv),
tlsutil.WithCAFile(ca), tlsutil.WithCAFile(ca),
) )
//require.Nil(t, err, err.Error()) require.NoError(t, err)
require.Nil(t, err)
tlsConf.ServerName = "helm.sh" tlsConf.ServerName = "helm.sh"

@ -68,7 +68,7 @@ func TestTime_AddDate(t *testing.T) {
func TestTime_In(t *testing.T) { func TestTime_In(t *testing.T) {
testingTime := givenTime(t) testingTime := givenTime(t)
edt, err := time.LoadLocation("America/New_York") edt, err := time.LoadLocation("America/New_York")
assert.NoError(t, err) require.NoError(t, err)
got := testingTime.In(edt) got := testingTime.In(edt)
assert.Equal(t, "America/New_York", got.Location().String()) assert.Equal(t, "America/New_York", got.Location().String())
} }
@ -76,13 +76,13 @@ func TestTime_In(t *testing.T) {
func TestTime_MarshalJSONNonZero(t *testing.T) { func TestTime_MarshalJSONNonZero(t *testing.T) {
testingTime := givenTime(t) testingTime := givenTime(t)
res, err := json.Marshal(testingTime) res, err := json.Marshal(testingTime)
assert.NoError(t, err) require.NoError(t, err)
assert.Equal(t, timeParseString, string(res)) assert.Equal(t, timeParseString, string(res))
} }
func TestTime_MarshalJSONZeroValue(t *testing.T) { func TestTime_MarshalJSONZeroValue(t *testing.T) {
res, err := json.Marshal(Time{}) res, err := json.Marshal(Time{})
assert.NoError(t, err) require.NoError(t, err)
assert.Equal(t, `""`, string(res)) assert.Equal(t, `""`, string(res))
} }
@ -119,21 +119,21 @@ func TestTime_UnmarshalJSONNonZeroValue(t *testing.T) {
testingTime := givenTime(t) testingTime := givenTime(t)
var myTime Time var myTime Time
err := json.Unmarshal([]byte(timeParseString), &myTime) err := json.Unmarshal([]byte(timeParseString), &myTime)
assert.NoError(t, err) require.NoError(t, err)
assert.True(t, testingTime.Equal(myTime)) assert.True(t, testingTime.Equal(myTime))
} }
func TestTime_UnmarshalJSONEmptyString(t *testing.T) { func TestTime_UnmarshalJSONEmptyString(t *testing.T) {
var myTime Time var myTime Time
err := json.Unmarshal([]byte(emptyString), &myTime) err := json.Unmarshal([]byte(emptyString), &myTime)
assert.NoError(t, err) require.NoError(t, err)
assert.True(t, myTime.IsZero()) assert.True(t, myTime.IsZero())
} }
func TestTime_UnmarshalJSONNullString(t *testing.T) { func TestTime_UnmarshalJSONNullString(t *testing.T) {
var myTime Time var myTime Time
err := json.Unmarshal([]byte("null"), &myTime) err := json.Unmarshal([]byte("null"), &myTime)
assert.NoError(t, err) require.NoError(t, err)
assert.True(t, myTime.IsZero()) assert.True(t, myTime.IsZero())
} }
@ -142,7 +142,7 @@ func TestTime_UnmarshalJSONZeroValue(t *testing.T) {
// with the current go default value of "0001-01-01T00:00:00Z" // with the current go default value of "0001-01-01T00:00:00Z"
var myTime Time var myTime Time
err := json.Unmarshal([]byte(`"0001-01-01T00:00:00Z"`), &myTime) err := json.Unmarshal([]byte(`"0001-01-01T00:00:00Z"`), &myTime)
assert.NoError(t, err) require.NoError(t, err)
assert.True(t, myTime.IsZero()) assert.True(t, myTime.IsZero())
} }

Loading…
Cancel
Save