Skip to content

Commit c175716

Browse files
CopilotTerryHowe
andcommitted
Add comprehensive test coverage for blob metadata text handlers
Co-authored-by: TerryHowe <[email protected]>
1 parent f7dea20 commit c175716

File tree

2 files changed

+367
-0
lines changed

2 files changed

+367
-0
lines changed
Lines changed: 190 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,190 @@
1+
/*
2+
Copyright The ORAS Authors.
3+
Licensed under the Apache License, Version 2.0 (the "License");
4+
you may not use this file except in compliance with the License.
5+
You may obtain a copy of the License at
6+
7+
http://www.apache.org/licenses/LICENSE-2.0
8+
9+
Unless required by applicable law or agreed to in writing, software
10+
distributed under the License is distributed on an "AS IS" BASIS,
11+
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12+
See the License for the specific language governing permissions and
13+
limitations under the License.
14+
*/
15+
16+
package text
17+
18+
import (
19+
"bytes"
20+
"io"
21+
"os"
22+
"testing"
23+
24+
"oras.land/oras/cmd/oras/internal/option"
25+
"oras.land/oras/cmd/oras/internal/output"
26+
)
27+
28+
func TestNewBlobDeleteHandler(t *testing.T) {
29+
printer := output.NewPrinter(&bytes.Buffer{}, os.Stderr)
30+
target := &option.Target{
31+
Type: "registry",
32+
RawReference: "localhost:5000/test@sha256:abcd1234",
33+
}
34+
35+
handler := NewBlobDeleteHandler(printer, target)
36+
37+
if handler == nil {
38+
t.Fatal("expected a non-nil handler")
39+
}
40+
41+
// Type assertion to access internal fields
42+
if bdh, ok := handler.(*BlobDeleteHandler); ok {
43+
if bdh.printer != printer {
44+
t.Errorf("expected handler.printer to be %v, got %v", printer, bdh.printer)
45+
}
46+
if bdh.target != target {
47+
t.Errorf("expected handler.target to be %v, got %v", target, bdh.target)
48+
}
49+
} else {
50+
t.Error("expected handler to be of type *BlobDeleteHandler")
51+
}
52+
}
53+
54+
func TestBlobDeleteHandler_OnBlobMissing(t *testing.T) {
55+
tests := []struct {
56+
name string
57+
out io.Writer
58+
target *option.Target
59+
wantErr bool
60+
wantOutput string
61+
}{
62+
{
63+
name: "blob missing with digest reference",
64+
out: &bytes.Buffer{},
65+
target: &option.Target{
66+
Type: "registry",
67+
RawReference: "localhost:5000/test@sha256:abcd1234",
68+
},
69+
wantErr: false,
70+
wantOutput: "Missing localhost:5000/test@sha256:abcd1234\n",
71+
},
72+
{
73+
name: "blob missing with tag reference",
74+
out: &bytes.Buffer{},
75+
target: &option.Target{
76+
Type: "registry",
77+
RawReference: "localhost:5000/test:latest",
78+
},
79+
wantErr: false,
80+
wantOutput: "Missing localhost:5000/test:latest\n",
81+
},
82+
{
83+
name: "blob missing with oci layout",
84+
out: &bytes.Buffer{},
85+
target: &option.Target{
86+
Type: "oci-layout",
87+
RawReference: "./layout@sha256:abcd1234",
88+
},
89+
wantErr: false,
90+
wantOutput: "Missing ./layout@sha256:abcd1234\n",
91+
},
92+
{
93+
name: "error writer",
94+
out: &errorWriter{},
95+
target: &option.Target{
96+
Type: "registry",
97+
RawReference: "localhost:5000/test@sha256:abcd1234",
98+
},
99+
wantErr: true,
100+
},
101+
}
102+
103+
for _, tt := range tests {
104+
t.Run(tt.name, func(t *testing.T) {
105+
printer := output.NewPrinter(tt.out, os.Stderr)
106+
handler := NewBlobDeleteHandler(printer, tt.target)
107+
108+
err := handler.OnBlobMissing()
109+
if (err != nil) != tt.wantErr {
110+
t.Errorf("OnBlobMissing() error = %v, wantErr %v", err, tt.wantErr)
111+
}
112+
113+
if !tt.wantErr {
114+
got := tt.out.(*bytes.Buffer).String()
115+
if got != tt.wantOutput {
116+
t.Errorf("OnBlobMissing() output = %q, want %q", got, tt.wantOutput)
117+
}
118+
}
119+
})
120+
}
121+
}
122+
123+
func TestBlobDeleteHandler_OnBlobDeleted(t *testing.T) {
124+
tests := []struct {
125+
name string
126+
out io.Writer
127+
target *option.Target
128+
wantErr bool
129+
wantOutput string
130+
}{
131+
{
132+
name: "blob deleted with digest reference",
133+
out: &bytes.Buffer{},
134+
target: &option.Target{
135+
Type: "registry",
136+
RawReference: "localhost:5000/test@sha256:abcd1234",
137+
},
138+
wantErr: false,
139+
wantOutput: "Deleted [registry] localhost:5000/test@sha256:abcd1234\n",
140+
},
141+
{
142+
name: "blob deleted with tag reference",
143+
out: &bytes.Buffer{},
144+
target: &option.Target{
145+
Type: "registry",
146+
RawReference: "localhost:5000/test:latest",
147+
},
148+
wantErr: false,
149+
wantOutput: "Deleted [registry] localhost:5000/test:latest\n",
150+
},
151+
{
152+
name: "blob deleted with oci layout",
153+
out: &bytes.Buffer{},
154+
target: &option.Target{
155+
Type: "oci-layout",
156+
RawReference: "./layout@sha256:abcd1234",
157+
},
158+
wantErr: false,
159+
wantOutput: "Deleted [oci-layout] ./layout@sha256:abcd1234\n",
160+
},
161+
{
162+
name: "error writer",
163+
out: &errorWriter{},
164+
target: &option.Target{
165+
Type: "registry",
166+
RawReference: "localhost:5000/test@sha256:abcd1234",
167+
},
168+
wantErr: true,
169+
},
170+
}
171+
172+
for _, tt := range tests {
173+
t.Run(tt.name, func(t *testing.T) {
174+
printer := output.NewPrinter(tt.out, os.Stderr)
175+
handler := NewBlobDeleteHandler(printer, tt.target)
176+
177+
err := handler.OnBlobDeleted()
178+
if (err != nil) != tt.wantErr {
179+
t.Errorf("OnBlobDeleted() error = %v, wantErr %v", err, tt.wantErr)
180+
}
181+
182+
if !tt.wantErr {
183+
got := tt.out.(*bytes.Buffer).String()
184+
if got != tt.wantOutput {
185+
t.Errorf("OnBlobDeleted() output = %q, want %q", got, tt.wantOutput)
186+
}
187+
}
188+
})
189+
}
190+
}
Lines changed: 177 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,177 @@
1+
/*
2+
Copyright The ORAS Authors.
3+
Licensed under the Apache License, Version 2.0 (the "License");
4+
you may not use this file except in compliance with the License.
5+
You may obtain a copy of the License at
6+
7+
http://www.apache.org/licenses/LICENSE-2.0
8+
9+
Unless required by applicable law or agreed to in writing, software
10+
distributed under the License is distributed on an "AS IS" BASIS,
11+
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12+
See the License for the specific language governing permissions and
13+
limitations under the License.
14+
*/
15+
16+
package text
17+
18+
import (
19+
"bytes"
20+
"fmt"
21+
"io"
22+
"os"
23+
"reflect"
24+
"testing"
25+
26+
"github.com/opencontainers/go-digest"
27+
ocispec "github.com/opencontainers/image-spec/specs-go/v1"
28+
"oras.land/oras/cmd/oras/internal/option"
29+
"oras.land/oras/cmd/oras/internal/output"
30+
)
31+
32+
func TestNewBlobPushHandler(t *testing.T) {
33+
printer := output.NewPrinter(&bytes.Buffer{}, os.Stderr)
34+
desc := ocispec.Descriptor{
35+
MediaType: "application/vnd.oci.image.layer.v1.tar",
36+
Digest: digest.FromString("test"),
37+
Size: 123,
38+
}
39+
40+
handler := NewBlobPushHandler(printer, desc)
41+
42+
if handler == nil {
43+
t.Fatal("expected a non-nil handler")
44+
}
45+
46+
// Type assertion to access internal fields
47+
if bph, ok := handler.(*BlobPushHandler); ok {
48+
if bph.printer != printer {
49+
t.Errorf("expected handler.printer to be %v, got %v", printer, bph.printer)
50+
}
51+
if !reflect.DeepEqual(bph.desc, desc) {
52+
t.Errorf("expected handler.desc to be %v, got %v", desc, bph.desc)
53+
}
54+
} else {
55+
t.Error("expected handler to be of type *BlobPushHandler")
56+
}
57+
}
58+
59+
func TestBlobPushHandler_OnBlobPushed(t *testing.T) {
60+
tests := []struct {
61+
name string
62+
out io.Writer
63+
target *option.Target
64+
wantErr bool
65+
wantOutput string
66+
}{
67+
{
68+
name: "successful push output",
69+
out: &bytes.Buffer{},
70+
target: &option.Target{
71+
Type: "registry",
72+
RawReference: "localhost:5000/test:latest",
73+
},
74+
wantErr: false,
75+
wantOutput: "Pushed: [registry] localhost:5000/test:latest\n",
76+
},
77+
{
78+
name: "oci layout target",
79+
out: &bytes.Buffer{},
80+
target: &option.Target{
81+
Type: "oci-layout",
82+
RawReference: "./layout:latest",
83+
},
84+
wantErr: false,
85+
wantOutput: "Pushed: [oci-layout] ./layout:latest\n",
86+
},
87+
}
88+
89+
for _, tt := range tests {
90+
t.Run(tt.name, func(t *testing.T) {
91+
printer := output.NewPrinter(tt.out, os.Stderr)
92+
desc := ocispec.Descriptor{
93+
MediaType: "application/vnd.oci.image.layer.v1.tar",
94+
Digest: digest.FromString("test"),
95+
Size: 123,
96+
}
97+
handler := NewBlobPushHandler(printer, desc)
98+
99+
err := handler.OnBlobPushed(tt.target)
100+
if (err != nil) != tt.wantErr {
101+
t.Errorf("OnBlobPushed() error = %v, wantErr %v", err, tt.wantErr)
102+
}
103+
104+
if !tt.wantErr {
105+
got := tt.out.(*bytes.Buffer).String()
106+
if got != tt.wantOutput {
107+
t.Errorf("OnBlobPushed() output = %q, want %q", got, tt.wantOutput)
108+
}
109+
}
110+
})
111+
}
112+
}
113+
114+
func TestBlobPushHandler_Render(t *testing.T) {
115+
content := []byte("test content")
116+
testDigest := digest.FromBytes(content)
117+
118+
tests := []struct {
119+
name string
120+
out io.Writer
121+
desc ocispec.Descriptor
122+
wantErr bool
123+
wantOutput string
124+
}{
125+
{
126+
name: "render digest output",
127+
out: &bytes.Buffer{},
128+
desc: ocispec.Descriptor{
129+
MediaType: "application/vnd.oci.image.layer.v1.tar",
130+
Digest: testDigest,
131+
Size: int64(len(content)),
132+
},
133+
wantErr: false,
134+
wantOutput: fmt.Sprintf("Digest: %s\n", testDigest),
135+
},
136+
{
137+
name: "render with different media type",
138+
out: &bytes.Buffer{},
139+
desc: ocispec.Descriptor{
140+
MediaType: "application/vnd.example.file",
141+
Digest: testDigest,
142+
Size: int64(len(content)),
143+
},
144+
wantErr: false,
145+
wantOutput: fmt.Sprintf("Digest: %s\n", testDigest),
146+
},
147+
{
148+
name: "error writer",
149+
out: &errorWriter{},
150+
desc: ocispec.Descriptor{
151+
MediaType: "application/vnd.oci.image.layer.v1.tar",
152+
Digest: testDigest,
153+
Size: int64(len(content)),
154+
},
155+
wantErr: true,
156+
},
157+
}
158+
159+
for _, tt := range tests {
160+
t.Run(tt.name, func(t *testing.T) {
161+
printer := output.NewPrinter(tt.out, os.Stderr)
162+
handler := NewBlobPushHandler(printer, tt.desc)
163+
164+
err := handler.Render()
165+
if (err != nil) != tt.wantErr {
166+
t.Errorf("Render() error = %v, wantErr %v", err, tt.wantErr)
167+
}
168+
169+
if !tt.wantErr {
170+
got := tt.out.(*bytes.Buffer).String()
171+
if got != tt.wantOutput {
172+
t.Errorf("Render() output = %q, want %q", got, tt.wantOutput)
173+
}
174+
}
175+
})
176+
}
177+
}

0 commit comments

Comments
 (0)