Skip to content

Commit

Permalink
test: add unit tests
Browse files Browse the repository at this point in the history
  • Loading branch information
manifestori committed Dec 27, 2023
1 parent dda356c commit d57191f
Show file tree
Hide file tree
Showing 12 changed files with 2,943 additions and 14 deletions.
4 changes: 2 additions & 2 deletions cmd/cli/convert.go
Original file line number Diff line number Diff line change
Expand Up @@ -115,15 +115,15 @@ func runConvert(ctx context.Context, co *options.ConvertOptions, args []string)
// if format string is empty, it will try to detect the format automatically and return the inverse
func parseFormat(f, e string, r io.ReadSeekCloser) (*format.Format, error) {
if f == "" {
df, err := format.DetectFormat(r)
df, err := format.Detect(r)
if err != nil {
return nil, err
}

return df.Inverse()
}

format, err := format.ParseFormat(f, e)
format, err := format.Parse(f, e)
if err != nil {
return nil, err
}
Expand Down
5 changes: 3 additions & 2 deletions go.mod
Original file line number Diff line number Diff line change
@@ -1,14 +1,16 @@
module github.com/bom-squad/sbom-convert

go 1.21
go 1.21.5

require (
github.com/bom-squad/protobom v0.2.1-0.20231219021915-5cdfd2b45eda
github.com/google/go-cmp v0.6.0
github.com/muesli/mango-cobra v1.2.0
github.com/muesli/roff v0.1.0
github.com/spf13/cobra v1.8.0
github.com/spf13/pflag v1.0.5
github.com/spf13/viper v1.18.2
go.uber.org/mock v0.4.0
go.uber.org/zap v1.26.0
)

Expand All @@ -17,7 +19,6 @@ require (
github.com/anchore/go-struct-converter v0.0.0-20230627203149-c72ef8859ca9 // indirect
github.com/common-nighthawk/go-figure v0.0.0-20210622060536-734e95fb86be // indirect
github.com/fsnotify/fsnotify v1.7.0 // indirect
github.com/google/go-cmp v0.6.0 // indirect
github.com/google/uuid v1.5.0 // indirect
github.com/hashicorp/hcl v1.0.0 // indirect
github.com/inconshreveable/mousetrap v1.1.0 // indirect
Expand Down
2 changes: 2 additions & 0 deletions go.sum
Original file line number Diff line number Diff line change
Expand Up @@ -94,6 +94,8 @@ github.com/xeipuuv/gojsonschema v1.2.0 h1:LhYJRs+L4fBtjZUfuSZIKGeVu0QRy8e5Xi7D17
github.com/xeipuuv/gojsonschema v1.2.0/go.mod h1:anYRn/JVcOK2ZgGU+IjEV4nwlhoK5sQluxsYJ78Id3Y=
go.uber.org/goleak v1.2.0 h1:xqgm/S+aQvhWFTtR0XK3Jvg7z8kGV8P4X14IzwN3Eqk=
go.uber.org/goleak v1.2.0/go.mod h1:XJYK+MuIchqpmGmUSAzotztawfKvYLUIgg7guXrwVUo=
go.uber.org/mock v0.4.0 h1:VcM4ZOtdbR4f6VXfiOpwpVJDL6lCReaZ6mw31wqh7KU=
go.uber.org/mock v0.4.0/go.mod h1:a6FSlNadKUHUa9IP5Vyt1zh4fC7uAwxMutEAscFbkZc=
go.uber.org/multierr v1.10.0 h1:S0h4aNzvfcFsC3dRF1jLoaov7oRaKqRGC/pUEJ2yvPQ=
go.uber.org/multierr v1.10.0/go.mod h1:20+QtiLqy0Nd6FdQB9TLXag12DsQkrbs3htMFfDN80Y=
go.uber.org/zap v1.26.0 h1:sI7k6L95XOKS281NhVKOFCUNIvv9e0w4BF8N3u+tCRo=
Expand Down
21 changes: 14 additions & 7 deletions pkg/convert/convert.go
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,8 @@ var _ domain.ConvertService = (*Service)(nil)

type Service struct {
Format *format.Format
r domain.Reader
w domain.Writer
}

func NewService(opts ...Option) *Service {
Expand All @@ -24,21 +26,26 @@ func NewService(opts ...Option) *Service {
opt(s)
}

if s.r == nil {
s.r = reader.New()
}

if s.w == nil {
s.w = writer.New(
writer.WithFormat(s.Format.Format),
)
}

return s
}

type Option func(s *Service)

func (s *Service) Convert(_ context.Context, in io.ReadSeekCloser, out io.WriteCloser) error {
r := reader.New()
doc, err := r.ParseStream(in)
doc, err := s.r.ParseStream(in)
if err != nil {
return err
}

w := writer.New(
writer.WithFormat(s.Format.Format),
)

return w.WriteStream(doc, out)
return s.w.WriteStream(doc, out)
}
204 changes: 204 additions & 0 deletions pkg/convert/convert_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,204 @@
package convert_test

import (
"bytes"
"context"
"io"
"os"
"path/filepath"
"strings"
"testing"

"github.com/bom-squad/protobom/pkg/formats"
"github.com/bom-squad/protobom/pkg/reader"
"github.com/bom-squad/protobom/pkg/sbom"
"github.com/bom-squad/protobom/pkg/writer"
"github.com/google/go-cmp/cmp"
"github.com/google/go-cmp/cmp/cmpopts"
"go.uber.org/mock/gomock"

"github.com/bom-squad/sbom-convert/pkg/convert"
"github.com/bom-squad/sbom-convert/pkg/convert/mocks"
"github.com/bom-squad/sbom-convert/pkg/format"
)

type readSeekerCloser struct {
io.ReadSeeker
}

func (rsc *readSeekerCloser) Close() error {
return nil
}

type writerCloser struct {
io.Writer
}

func (wc *writerCloser) Close() error {
return nil
}

func readJSON(t *testing.T, dir string, path string) (res string) {
t.Helper()

if f, err := os.Open(filepath.Join(dir, path)); err != nil {
t.Fatal(err)
} else {
defer f.Close()

buf := &bytes.Buffer{}
if _, err := io.Copy(buf, f); err != nil {
t.Fatal(err)
}

res = buf.String()
}

return res
}

func TestService_Convert(t *testing.T) {
ctrl := gomock.NewController(t)
defer ctrl.Finish()

type args struct {
in io.ReadSeekCloser
out io.WriteCloser
}

type mockFunc func(in io.ReadSeekCloser, out io.WriteCloser) (*mocks.MockReader, *mocks.MockWriter)

tests := []struct {
name string
format format.Format
args args
mocks mockFunc
want string
wantErr bool
}{
{
name: "happy: convert sbom",
format: format.Format{Format: formats.CDX15JSON},
args: args{
in: &readSeekerCloser{strings.NewReader(readJSON(t, "testdata", "spdx-2.3.json"))},
out: &writerCloser{&bytes.Buffer{}},
},
mocks: func(in io.ReadSeekCloser, out io.WriteCloser) (*mocks.MockReader, *mocks.MockWriter) {
bom := &sbom.Document{}
mreader := mocks.NewMockReader(ctrl)
mreader.EXPECT().ParseStream(in).Return(bom, nil)

mwriter := mocks.NewMockWriter(ctrl)
mwriter.EXPECT().WriteStream(bom, out).Return(nil)

return mreader, mwriter
},

wantErr: false,
},
{
name: "sad: reader error",
format: format.Format{Format: formats.CDX15JSON},
args: args{
in: &readSeekerCloser{},
out: &writerCloser{},
},
mocks: func(in io.ReadSeekCloser, out io.WriteCloser) (*mocks.MockReader, *mocks.MockWriter) {
mreader := mocks.NewMockReader(ctrl)
mreader.EXPECT().ParseStream(in).Return(nil, io.EOF)

mwriter := mocks.NewMockWriter(ctrl)

return mreader, mwriter
},
wantErr: true,
},
{
name: "sad: writer error",
format: format.Format{Format: formats.CDX15JSON},
args: args{
in: &readSeekerCloser{strings.NewReader(readJSON(t, "testdata", "spdx-2.3.json"))},
out: &writerCloser{},
},
mocks: func(in io.ReadSeekCloser, out io.WriteCloser) (*mocks.MockReader, *mocks.MockWriter) {
bom := &sbom.Document{}
mreader := mocks.NewMockReader(ctrl)
mreader.EXPECT().ParseStream(in).Return(bom, nil)

mwriter := mocks.NewMockWriter(ctrl)
mwriter.EXPECT().WriteStream(bom, out).Return(io.EOF)

return mreader, mwriter
},
wantErr: true,
},
}

for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
tt := tt

mreader, mwriter := tt.mocks(tt.args.in, tt.args.out)

s := convert.NewService(
convert.WithFormat(&tt.format),
convert.WithReader(mreader),
convert.WithWriter(mwriter),
)

err := s.Convert(context.Background(), tt.args.in, tt.args.out)
if (err != nil) != tt.wantErr {
t.Errorf("Convert() error = %v, wantErr %v", err, tt.wantErr)
return
}
})
}
}

func TestNewService(t *testing.T) {
type args struct {
opts []convert.Option
}

treader := reader.New()
twriter := writer.New()
tests := []struct {
name string
args args
want *convert.Service
}{
{
name: "happy: new default service",
args: args{
opts: []convert.Option{
convert.WithFormat(&format.Format{Format: formats.CDX15JSON}),
convert.WithReader(nil),
convert.WithWriter(nil),
},
},
want: &convert.Service{
Format: &format.Format{Format: formats.CDX15JSON},
},
},
{
name: "happy: new service with reader and writer",
args: args{
opts: []convert.Option{
convert.WithFormat(&format.Format{Format: formats.CDX15JSON}),
convert.WithReader(treader),
convert.WithWriter(twriter),
},
},
want: &convert.Service{
Format: &format.Format{Format: formats.CDX15JSON},
},
},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
if got := convert.NewService(tt.args.opts...); !cmp.Equal(got, tt.want, cmpopts.IgnoreUnexported(convert.Service{})) {
t.Errorf("NewService() = %v, want %v", got, tt.want)
}
})
}
}
55 changes: 55 additions & 0 deletions pkg/convert/mocks/mock_reader.go

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Loading

0 comments on commit d57191f

Please sign in to comment.