File: single_test.go

package info (click to toggle)
golang-github-containers-image 5.36.1-1
  • links: PTS, VCS
  • area: main
  • in suites: experimental
  • size: 5,152 kB
  • sloc: sh: 267; makefile: 100
file content (161 lines) | stat: -rw-r--r-- 6,274 bytes parent folder | download | duplicates (2)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
package copy

import (
	"bytes"
	"errors"
	"fmt"
	"io"
	"os"
	"testing"
	"time"

	"github.com/containers/image/v5/internal/private"
	"github.com/containers/image/v5/pkg/compression"
	compressiontypes "github.com/containers/image/v5/pkg/compression/types"
	"github.com/containers/image/v5/types"
	digest "github.com/opencontainers/go-digest"
	imgspecv1 "github.com/opencontainers/image-spec/specs-go/v1"
	"github.com/stretchr/testify/assert"
	"github.com/stretchr/testify/require"
)

func TestUpdatedBlobInfoFromReuse(t *testing.T) {
	srcInfo := types.BlobInfo{
		Digest:               "sha256:6a5a5368e0c2d3e5909184fa28ddfd56072e7ff3ee9a945876f7eee5896ef5bb",
		Size:                 51354364,
		URLs:                 []string{"https://layer.url"},
		Annotations:          map[string]string{"test-annotation-2": "two"},
		MediaType:            imgspecv1.MediaTypeImageLayerGzip,
		CompressionOperation: types.Compress,    // Might be set by blobCacheSource.LayerInfosForCopy
		CompressionAlgorithm: &compression.Gzip, // Set e.g. in copyLayer
		// CryptoOperation is not set by LayerInfos()
	}

	for _, c := range []struct {
		reused   private.ReusedBlob
		expected types.BlobInfo
	}{
		{ // A straightforward reuse without substitution
			reused: private.ReusedBlob{
				Digest: "sha256:6a5a5368e0c2d3e5909184fa28ddfd56072e7ff3ee9a945876f7eee5896ef5bb",
				Size:   51354364,
				// CompressionOperation not set
				// CompressionAlgorithm not set
			},
			expected: types.BlobInfo{
				Digest:               "sha256:6a5a5368e0c2d3e5909184fa28ddfd56072e7ff3ee9a945876f7eee5896ef5bb",
				Size:                 51354364,
				URLs:                 nil,
				Annotations:          map[string]string{"test-annotation-2": "two"},
				MediaType:            imgspecv1.MediaTypeImageLayerGzip,
				CompressionOperation: types.Compress,    // Might be set by blobCacheSource.LayerInfosForCopy
				CompressionAlgorithm: &compression.Gzip, // Set e.g. in copyLayer
				// CryptoOperation is set to the zero value
			},
		},
		{ // Reuse with substitution
			reused: private.ReusedBlob{
				Digest:                 "sha256:aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa",
				Size:                   513543640,
				CompressionOperation:   types.Decompress,
				CompressionAlgorithm:   nil,
				CompressionAnnotations: map[string]string{"decompressed": "value"},
			},
			expected: types.BlobInfo{
				Digest:               "sha256:aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa",
				Size:                 513543640,
				URLs:                 nil,
				Annotations:          map[string]string{"test-annotation-2": "two", "decompressed": "value"},
				MediaType:            imgspecv1.MediaTypeImageLayerGzip,
				CompressionOperation: types.Decompress,
				CompressionAlgorithm: nil,
				// CryptoOperation is set to the zero value
			},
		},
		{ // Reuse turning zstd into zstd:chunked
			reused: private.ReusedBlob{
				Digest:                 "sha256:6a5a5368e0c2d3e5909184fa28ddfd56072e7ff3ee9a945876f7eee5896ef5bb",
				Size:                   51354364,
				CompressionOperation:   types.Compress,
				CompressionAlgorithm:   &compression.ZstdChunked,
				CompressionAnnotations: map[string]string{"zstd-toc": "value"},
			},
			expected: types.BlobInfo{
				Digest:               "sha256:6a5a5368e0c2d3e5909184fa28ddfd56072e7ff3ee9a945876f7eee5896ef5bb",
				Size:                 51354364,
				URLs:                 nil,
				Annotations:          map[string]string{"test-annotation-2": "two", "zstd-toc": "value"},
				MediaType:            imgspecv1.MediaTypeImageLayerGzip,
				CompressionOperation: types.Compress,
				CompressionAlgorithm: &compression.ZstdChunked,
				// CryptoOperation is set to the zero value
			},
		},
	} {
		res := updatedBlobInfoFromReuse(srcInfo, c.reused)
		assert.Equal(t, c.expected, res, fmt.Sprintf("%#v", c.reused))
	}
}

func goDiffIDComputationGoroutineWithTimeout(layerStream io.ReadCloser, decompressor compressiontypes.DecompressorFunc) *diffIDResult {
	ch := make(chan diffIDResult)
	go diffIDComputationGoroutine(ch, layerStream, decompressor)
	timeout := time.After(time.Second)
	select {
	case res := <-ch:
		return &res
	case <-timeout:
		return nil
	}
}

func TestDiffIDComputationGoroutine(t *testing.T) {
	stream, err := os.Open("fixtures/Hello.uncompressed")
	require.NoError(t, err)
	res := goDiffIDComputationGoroutineWithTimeout(stream, nil)
	require.NotNil(t, res)
	assert.NoError(t, res.err)
	assert.Equal(t, "sha256:185f8db32271fe25f561a6fc938b2e264306ec304eda518007d1764826381969", res.digest.String())

	// Error reading input
	reader, writer := io.Pipe()
	err = writer.CloseWithError(errors.New("Expected error reading input in diffIDComputationGoroutine"))
	require.NoError(t, err)
	res = goDiffIDComputationGoroutineWithTimeout(reader, nil)
	require.NotNil(t, res)
	assert.Error(t, res.err)
}

func TestComputeDiffID(t *testing.T) {
	for _, c := range []struct {
		filename     string
		decompressor compressiontypes.DecompressorFunc
		result       digest.Digest
	}{
		{"fixtures/Hello.uncompressed", nil, "sha256:185f8db32271fe25f561a6fc938b2e264306ec304eda518007d1764826381969"},
		{"fixtures/Hello.gz", nil, "sha256:0bd4409dcd76476a263b8f3221b4ce04eb4686dec40bfdcc2e86a7403de13609"},
		{"fixtures/Hello.gz", compression.GzipDecompressor, "sha256:185f8db32271fe25f561a6fc938b2e264306ec304eda518007d1764826381969"},
		{"fixtures/Hello.zst", nil, "sha256:361a8e0372ad438a0316eb39a290318364c10b60d0a7e55b40aa3eafafc55238"},
		{"fixtures/Hello.zst", compression.ZstdDecompressor, "sha256:185f8db32271fe25f561a6fc938b2e264306ec304eda518007d1764826381969"},
	} {
		stream, err := os.Open(c.filename)
		require.NoError(t, err, c.filename)
		defer stream.Close()

		diffID, err := computeDiffID(stream, c.decompressor)
		require.NoError(t, err, c.filename)
		assert.Equal(t, c.result, diffID)
	}

	// Error initializing decompression
	_, err := computeDiffID(bytes.NewReader([]byte{}), compression.GzipDecompressor)
	assert.Error(t, err)

	// Error reading input
	reader, writer := io.Pipe()
	defer reader.Close()
	err = writer.CloseWithError(errors.New("Expected error reading input in computeDiffID"))
	require.NoError(t, err)
	_, err = computeDiffID(reader, nil)
	assert.Error(t, err)
}