github.com/containerd/Containerd@v1.4.13/content/helpers_test.go (about)

     1  /*
     2     Copyright The containerd Authors.
     3  
     4     Licensed under the Apache License, Version 2.0 (the "License");
     5     you may not use this file except in compliance with the License.
     6     You may obtain a copy of the License at
     7  
     8         http://www.apache.org/licenses/LICENSE-2.0
     9  
    10     Unless required by applicable law or agreed to in writing, software
    11     distributed under the License is distributed on an "AS IS" BASIS,
    12     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    13     See the License for the specific language governing permissions and
    14     limitations under the License.
    15  */
    16  
    17  package content
    18  
    19  import (
    20  	"bytes"
    21  	"context"
    22  	_ "crypto/sha256" // required by go-digest
    23  	"io"
    24  	"strings"
    25  	"testing"
    26  
    27  	"github.com/containerd/containerd/errdefs"
    28  	"github.com/opencontainers/go-digest"
    29  	"gotest.tools/v3/assert"
    30  	is "gotest.tools/v3/assert/cmp"
    31  )
    32  
    33  type copySource struct {
    34  	reader io.Reader
    35  	size   int64
    36  	digest digest.Digest
    37  }
    38  
    39  func TestCopy(t *testing.T) {
    40  	defaultSource := newCopySource("this is the source to copy")
    41  
    42  	var testcases = []struct {
    43  		name     string
    44  		source   copySource
    45  		writer   fakeWriter
    46  		expected string
    47  	}{
    48  		{
    49  			name:     "copy no offset",
    50  			source:   defaultSource,
    51  			writer:   fakeWriter{},
    52  			expected: "this is the source to copy",
    53  		},
    54  		{
    55  			name:     "copy with offset from seeker",
    56  			source:   defaultSource,
    57  			writer:   fakeWriter{status: Status{Offset: 8}},
    58  			expected: "the source to copy",
    59  		},
    60  		{
    61  			name:     "copy with offset from unseekable source",
    62  			source:   copySource{reader: bytes.NewBufferString("foobar"), size: 6},
    63  			writer:   fakeWriter{status: Status{Offset: 3}},
    64  			expected: "bar",
    65  		},
    66  		{
    67  			name:   "commit already exists",
    68  			source: defaultSource,
    69  			writer: fakeWriter{commitFunc: func() error {
    70  				return errdefs.ErrAlreadyExists
    71  			}},
    72  		},
    73  	}
    74  
    75  	for _, testcase := range testcases {
    76  		t.Run(testcase.name, func(t *testing.T) {
    77  			err := Copy(context.Background(),
    78  				&testcase.writer,
    79  				testcase.source.reader,
    80  				testcase.source.size,
    81  				testcase.source.digest)
    82  
    83  			assert.NilError(t, err)
    84  			assert.Check(t, is.Equal(testcase.source.digest, testcase.writer.committedDigest))
    85  			assert.Check(t, is.Equal(testcase.expected, testcase.writer.String()))
    86  		})
    87  	}
    88  }
    89  
    90  func newCopySource(raw string) copySource {
    91  	return copySource{
    92  		reader: strings.NewReader(raw),
    93  		size:   int64(len(raw)),
    94  		digest: digest.FromBytes([]byte(raw)),
    95  	}
    96  }
    97  
    98  type fakeWriter struct {
    99  	bytes.Buffer
   100  	committedDigest digest.Digest
   101  	status          Status
   102  	commitFunc      func() error
   103  }
   104  
   105  func (f *fakeWriter) Close() error {
   106  	f.Buffer.Reset()
   107  	return nil
   108  }
   109  
   110  func (f *fakeWriter) Commit(ctx context.Context, size int64, expected digest.Digest, opts ...Opt) error {
   111  	f.committedDigest = expected
   112  	if f.commitFunc == nil {
   113  		return nil
   114  	}
   115  	return f.commitFunc()
   116  }
   117  
   118  func (f *fakeWriter) Digest() digest.Digest {
   119  	return f.committedDigest
   120  }
   121  
   122  func (f *fakeWriter) Status() (Status, error) {
   123  	return f.status, nil
   124  }
   125  
   126  func (f *fakeWriter) Truncate(size int64) error {
   127  	f.Buffer.Truncate(int(size))
   128  	return nil
   129  }