1
2
3
4
5
6
7
8
9
10
11
12
13
14
15 package daemon
16
17 import (
18 "context"
19 "errors"
20 "fmt"
21 "io"
22 "strings"
23 "testing"
24
25 "github.com/docker/docker/api/types"
26
27 "github.com/google/go-containerregistry/pkg/name"
28 "github.com/google/go-containerregistry/pkg/v1/empty"
29 "github.com/google/go-containerregistry/pkg/v1/tarball"
30 )
31
32 type errReader struct {
33 err error
34 }
35
36 func (r *errReader) Read(_ []byte) (int, error) {
37 return 0, r.err
38 }
39
40 func (m *MockClient) ImageLoad(ctx context.Context, r io.Reader, _ bool) (types.ImageLoadResponse, error) {
41 if !m.negotiated {
42 return types.ImageLoadResponse{}, errors.New("you forgot to call NegotiateAPIVersion before calling ImageLoad")
43 }
44 if m.wantCtx != nil && m.wantCtx != ctx {
45 return types.ImageLoadResponse{}, fmt.Errorf("ImageLoad: wrong context")
46 }
47
48 _, _ = io.Copy(io.Discard, r)
49 return types.ImageLoadResponse{
50 Body: m.loadBody,
51 }, m.loadErr
52 }
53
54 func (m *MockClient) ImageTag(ctx context.Context, _, _ string) error {
55 if !m.negotiated {
56 return errors.New("you forgot to call NegotiateAPIVersion before calling ImageTag")
57 }
58 if m.wantCtx != nil && m.wantCtx != ctx {
59 return fmt.Errorf("ImageTag: wrong context")
60 }
61 return m.tagErr
62 }
63
64 func TestWriteImage(t *testing.T) {
65 for _, tc := range []struct {
66 name string
67 client *MockClient
68 wantResponse string
69 wantErr string
70 }{{
71 name: "success",
72 client: &MockClient{
73 inspectErr: errors.New("nope"),
74 loadBody: io.NopCloser(strings.NewReader("Loaded")),
75 },
76 wantResponse: "Loaded",
77 }, {
78 name: "load err",
79 client: &MockClient{
80 inspectErr: errors.New("nope"),
81 loadBody: io.NopCloser(strings.NewReader("Loaded")),
82 loadErr: fmt.Errorf("locked and loaded"),
83 },
84 wantErr: "locked and loaded",
85 }, {
86 name: "read err",
87 client: &MockClient{
88 inspectErr: errors.New("nope"),
89 loadBody: io.NopCloser(&errReader{fmt.Errorf("goodbye, world")}),
90 },
91 wantErr: "goodbye, world",
92 }, {
93 name: "skip load",
94 client: &MockClient{
95 tagErr: fmt.Errorf("called tag"),
96 },
97 wantErr: "called tag",
98 }, {
99 name: "skip tag",
100 client: &MockClient{
101 inspectResp: inspectResp,
102 tagErr: fmt.Errorf("called tag"),
103 },
104 wantResponse: "",
105 }} {
106 t.Run(tc.name, func(t *testing.T) {
107 image, err := tarball.ImageFromPath("../tarball/testdata/test_image_1.tar", nil)
108 if err != nil {
109 t.Errorf("Error loading image: %v", err.Error())
110 }
111 tag, err := name.NewTag("test_image_2:latest")
112 if err != nil {
113 t.Fatal(err)
114 }
115 response, err := Write(tag, image, WithClient(tc.client))
116 if tc.wantErr == "" {
117 if err != nil {
118 t.Errorf("Error writing image tar: %s", err.Error())
119 }
120 } else {
121 if err == nil {
122 t.Errorf("expected err")
123 } else if !strings.Contains(err.Error(), tc.wantErr) {
124 t.Errorf("Error writing image tar: wanted %s to contain %s", err.Error(), tc.wantErr)
125 }
126 }
127 if !strings.Contains(response, tc.wantResponse) {
128 t.Errorf("Error loading image. Response: %s", response)
129 }
130 })
131 }
132 }
133
134 func TestWriteDefaultClient(t *testing.T) {
135 wantErr := fmt.Errorf("bad client")
136 defaultClient = func() (Client, error) {
137 return nil, wantErr
138 }
139
140 tag, err := name.NewTag("test_image_2:latest")
141 if err != nil {
142 t.Fatal(err)
143 }
144
145 if _, err := Write(tag, empty.Image); !errors.Is(err, wantErr) {
146 t.Errorf("Write(): want %v; got %v", wantErr, err)
147 }
148
149 if err := Tag(tag, tag); !errors.Is(err, wantErr) {
150 t.Errorf("Tag(): want %v; got %v", wantErr, err)
151 }
152
153
154 ctx := context.TODO()
155 defaultClient = func() (Client, error) {
156 return &MockClient{
157 inspectErr: errors.New("nope"),
158 loadBody: io.NopCloser(strings.NewReader("Loaded")),
159 wantCtx: ctx,
160 }, nil
161 }
162 if err := Tag(tag, tag, WithContext(ctx)); err != nil {
163 t.Fatal(err)
164 }
165 if _, err := Write(tag, empty.Image, WithContext(ctx)); err != nil {
166 t.Fatal(err)
167 }
168 }
169
View as plain text