From 124c36636ae408d4ea1fd4228413b088212309ad Mon Sep 17 00:00:00 2001 From: Tomasz Jarosik Date: Mon, 30 Sep 2024 22:19:45 +0100 Subject: [PATCH] Fix bug in ReadDigest() function --- pkg/dirimage/read.go | 3 +- pkg/dirimage/read_test.go | 99 +++++++++++++++++++++++++++++++++++++++ 2 files changed, 101 insertions(+), 1 deletion(-) create mode 100644 pkg/dirimage/read_test.go diff --git a/pkg/dirimage/read.go b/pkg/dirimage/read.go index 260b294..29add3f 100644 --- a/pkg/dirimage/read.go +++ b/pkg/dirimage/read.go @@ -137,5 +137,6 @@ func ReadDigest(dir string) (v1.Hash, error) { return v1.Hash{}, fmt.Errorf("failed to marshal manifest to JSON: %w", err) } hash := sha256.Sum256(jsonData) - return v1.NewHash(string(hash[:])) + hashString := fmt.Sprintf("sha256:%x", hash) + return v1.NewHash(hashString[:]) } diff --git a/pkg/dirimage/read_test.go b/pkg/dirimage/read_test.go new file mode 100644 index 0000000..fef3130 --- /dev/null +++ b/pkg/dirimage/read_test.go @@ -0,0 +1,99 @@ +package dirimage + +import ( + "crypto/sha256" + "encoding/json" + "fmt" + v1 "github.com/google/go-containerregistry/pkg/v1" + "github.com/stretchr/testify/assert" + "github.com/stretchr/testify/require" + "os" + "path/filepath" + "testing" +) + +// Helper function to write a manifest to a directory +func writeManifest(t *testing.T, dir string, manifest *v1.Manifest) { + t.Helper() + data, err := json.Marshal(manifest) + assert.NoError(t, err) + + err = os.WriteFile(filepath.Join(dir, LocalManifestFilename), data, 0644) + assert.NoError(t, err) +} + +func mustHash(t *testing.T, s string) v1.Hash { + h, err := v1.NewHash(s) + require.NoError(t, err) + return h +} + +func TestReadDigest_Success(t *testing.T) { + // Create a temporary directory for the test + dir, err := os.MkdirTemp("", "test-manifest") + assert.NoError(t, err) + defer os.RemoveAll(dir) + + // Create a sample v1.Manifest object + manifest := &v1.Manifest{ + SchemaVersion: 2, + MediaType: "application/vnd.docker.distribution.manifest.v2+json", + Config: v1.Descriptor{ + MediaType: "application/vnd.docker.container.image.v1+json", + Size: 1234, + Digest: mustHash(t, "sha256:1234567812345678123456781234567812345678123456781234567812345678"), + }, + Layers: []v1.Descriptor{ + { + MediaType: "application/vnd.docker.image.rootfs.diff.tar.gzip", + Size: 5678, + Digest: mustHash(t, "sha256:1234567812345678123456781234567812345678123456781234567812345678"), + }, + }, + } + + // Write the manifest to the directory + writeManifest(t, dir, manifest) + + // Read the digest + digest, err := ReadDigest(dir) + assert.NoError(t, err) + + // Manually calculate the expected hash + jsonData, err := json.Marshal(manifest) + assert.NoError(t, err) + expectedHash := sha256.Sum256(jsonData) + expectedDigest, err := v1.NewHash(fmt.Sprintf("sha256:%x", expectedHash[:])) + assert.NoError(t, err) + + // Compare the calculated digest with the expected digest + assert.Equal(t, expectedDigest, digest) +} + +func TestReadDigest_ManifestNotFound(t *testing.T) { + // Create a temporary directory for the test + dir, err := os.MkdirTemp("", "test-manifest-not-found") + assert.NoError(t, err) + defer os.RemoveAll(dir) + + // Try reading the digest from a directory without a manifest + _, err = ReadDigest(dir) + assert.Error(t, err) + assert.Contains(t, err.Error(), "unable to read manifest") +} + +func TestReadDigest_InvalidManifest(t *testing.T) { + // Create a temporary directory for the test + dir, err := os.MkdirTemp("", "test-invalid-manifest") + assert.NoError(t, err) + defer os.RemoveAll(dir) + + // Write invalid manifest data + err = os.WriteFile(filepath.Join(dir, LocalManifestFilename), []byte("invalid json"), 0644) + assert.NoError(t, err) + + // Try reading the digest + _, err = ReadDigest(dir) + assert.Error(t, err) + assert.Contains(t, err.Error(), "invalid character 'i' looking for beginning of value") +}