From b7bc99a540fb2006b0c53576c2dcff34e9a65b04 Mon Sep 17 00:00:00 2001 From: Kevin Diu Date: Thu, 10 Sep 2020 18:21:27 +0900 Subject: [PATCH] :white_check_mark: :recycle: Implement zstd test (#676) * implement zstd test * add comment * remove unused code and fix e2e test --- internal/compress/zstd.go | 13 + internal/compress/zstd/zstd.go | 17 +- internal/compress/zstd_test.go | 954 ++++++++++++++++++++++----------- 3 files changed, 663 insertions(+), 321 deletions(-) diff --git a/internal/compress/zstd.go b/internal/compress/zstd.go index 503ef1af07..f42d387637 100644 --- a/internal/compress/zstd.go +++ b/internal/compress/zstd.go @@ -32,6 +32,7 @@ type zstdCompressor struct { zstd zstd.Zstd } +// NewZstd returns the zstd compressor object or any initialization error. func NewZstd(opts ...ZstdOption) (Compressor, error) { c := &zstdCompressor{ zstd: zstd.New(), @@ -45,6 +46,8 @@ func NewZstd(opts ...ZstdOption) (Compressor, error) { return c, nil } +// CompressVector compresses the data given and returns the compressed data. +// If CompressVector fails, it will return an error. func (z *zstdCompressor) CompressVector(vector []float32) ([]byte, error) { gob, err := z.gobc.CompressVector(vector) if err != nil { @@ -70,6 +73,8 @@ func (z *zstdCompressor) CompressVector(vector []float32) ([]byte, error) { return buf.Bytes(), nil } +// DecompressVector decompresses the compressed data and returns the data. +// If decompress fails, it will return an error. func (z *zstdCompressor) DecompressVector(bs []byte) ([]float32, error) { buf := new(bytes.Buffer) zr, err := z.zstd.NewReader(bytes.NewReader(bs)) @@ -91,6 +96,7 @@ func (z *zstdCompressor) DecompressVector(bs []byte) ([]float32, error) { return vec, nil } +// Reader returns io.ReadCloser implementation. func (z *zstdCompressor) Reader(src io.ReadCloser) (io.ReadCloser, error) { r, err := z.zstd.NewReader(src) if err != nil { @@ -103,6 +109,7 @@ func (z *zstdCompressor) Reader(src io.ReadCloser) (io.ReadCloser, error) { }, nil } +// Writer returns io.WriteCloser implementation. func (z *zstdCompressor) Writer(dst io.WriteCloser) (io.WriteCloser, error) { w, err := z.zstd.NewWriter(dst, z.eoptions...) if err != nil { @@ -120,10 +127,13 @@ type zstdReader struct { r io.Reader } +// Read returns the number of bytes for read p (0 <= n <= len(p)). +// If any errors occurs, it will return an error. func (z *zstdReader) Read(p []byte) (n int, err error) { return z.r.Read(p) } +// Close closes the reader. func (z *zstdReader) Close() error { return z.src.Close() } @@ -133,10 +143,13 @@ type zstdWriter struct { w io.WriteCloser } +// Write returns the number of bytes written from p (0 <= n <= len(p)). +// If any errors occurs, it will return an error. func (z *zstdWriter) Write(p []byte) (n int, err error) { return z.w.Write(p) } +// Close closes the writer. func (z *zstdWriter) Close() (err error) { err = z.w.Close() if err != nil { diff --git a/internal/compress/zstd/zstd.go b/internal/compress/zstd/zstd.go index bc4bcd6fd0..046d9e55da 100644 --- a/internal/compress/zstd/zstd.go +++ b/internal/compress/zstd/zstd.go @@ -21,8 +21,13 @@ import ( "github.com/klauspost/compress/zstd" ) -// EOption is type alias of zstd.EOption. -type EOption = zstd.EOption +type ( + // EOption is type alias of zstd.EOption. + EOption = zstd.EOption + + // DOption is type alias of zstd.DOption. + DOption = zstd.DOption +) // Encoder represents an interface for Encoder of zstd. type Encoder interface { @@ -39,8 +44,8 @@ type Decoder interface { // Zstd is an interface to create Writer and Reader implementation. type Zstd interface { - NewWriter(w io.Writer, opts ...zstd.EOption) (Encoder, error) - NewReader(r io.Reader, opts ...zstd.DOption) (Decoder, error) + NewWriter(w io.Writer, opts ...EOption) (Encoder, error) + NewReader(r io.Reader, opts ...DOption) (Decoder, error) } type compress struct{} @@ -51,11 +56,11 @@ func New() Zstd { } // NewWriter returns Encoder implementation. -func (*compress) NewWriter(w io.Writer, opts ...zstd.EOption) (Encoder, error) { +func (*compress) NewWriter(w io.Writer, opts ...EOption) (Encoder, error) { return zstd.NewWriter(w, opts...) } // NewReader returns Decoder implementation. -func (*compress) NewReader(r io.Reader, opts ...zstd.DOption) (Decoder, error) { +func (*compress) NewReader(r io.Reader, opts ...DOption) (Decoder, error) { return zstd.NewReader(r, opts...) } diff --git a/internal/compress/zstd_test.go b/internal/compress/zstd_test.go index a4a524151c..7329e5cf7b 100644 --- a/internal/compress/zstd_test.go +++ b/internal/compress/zstd_test.go @@ -24,47 +24,24 @@ import ( "github.com/vdaas/vald/internal/compress/zstd" "github.com/vdaas/vald/internal/errors" + "github.com/vdaas/vald/internal/test/comparator" "go.uber.org/goleak" ) -func TestZstdCompressVector(t *testing.T) { - tests := []struct { - vector []float32 - }{ - { - vector: []float32{0.1, 0.2, 0.3}, - }, - { - vector: []float32{0.4, 0.2, 0.3, 0.1}, - }, - { - vector: []float32{0.1, 0.5, 0.12, 0.13, 1.0}, - }, - } - - for _, tc := range tests { - zstdc, err := NewZstd() - if err != nil { - t.Fatalf("initialize failed: %s", err) - } - - compressed, err := zstdc.CompressVector(tc.vector) - if err != nil { - t.Fatalf("Compress failed: %s", err) - } - - decompressed, err := zstdc.DecompressVector(compressed) - if err != nil { - t.Fatalf("Decompress failed: %s", err) - } - t.Logf("converted: origin %+v, compressed -> decompressed %+v", tc.vector, decompressed) - for i := range tc.vector { - if tc.vector[i] != decompressed[i] { - t.Fatalf("Invalid convert: origin %+v, compressed -> decompressed %+v", tc.vector, decompressed) +var ( + zstdCompressorComparatorOptions = []comparator.Option{ + comparator.AllowUnexported(zstdCompressor{}), + comparator.Comparer(func(x, y gobCompressor) bool { + return reflect.DeepEqual(x, y) + }), + comparator.Comparer(func(x, y zstd.EOption) bool { + if (x == nil && y != nil) || (x != nil && y == nil) { + return false } - } + return reflect.ValueOf(x).Pointer() == reflect.ValueOf(y).Pointer() + }), } -} +) func TestNewZstd(t *testing.T) { type args struct { @@ -86,37 +63,64 @@ func TestNewZstd(t *testing.T) { if !errors.Is(err, w.err) { return errors.Errorf("got_error: \"%#v\",\n\t\t\t\twant: \"%#v\"", err, w.err) } - if !reflect.DeepEqual(got, w.want) { - return errors.Errorf("got: \"%#v\",\n\t\t\t\twant: \"%#v\"", got, w.want) + if diff := comparator.Diff(w.want, got, zstdCompressorComparatorOptions...); diff != "" { + return errors.Errorf("err: %s", diff) } return nil } tests := []test{ - // TODO test cases - /* - { - name: "test_case_1", - args: args { - opts: nil, - }, - want: want{}, - checkFunc: defaultCheckFunc, - }, - */ - - // TODO test cases - /* - func() test { - return test { - name: "test_case_2", - args: args { - opts: nil, - }, - want: want{}, - checkFunc: defaultCheckFunc, - } - }(), - */ + { + name: "return zstd when option is nil", + args: args{ + opts: nil, + }, + want: want{ + want: &zstdCompressor{ + gobc: func() Compressor { + gobc, _ := NewGob() + return gobc + }(), + eoptions: []zstd.EOption{ + zstd.WithEncoderLevel(3), + }, + zstd: zstd.New(), + }, + }, + }, + { + name: "set zstd option when option is not nil", + args: args{ + opts: []ZstdOption{ + WithZstdCompressionLevel(2), + }, + }, + want: want{ + want: &zstdCompressor{ + gobc: func() Compressor { + gobc, _ := NewGob() + return gobc + }(), + eoptions: []zstd.EOption{ + zstd.WithEncoderLevel(3), + zstd.WithEncoderLevel(2), + }, + zstd: zstd.New(), + }, + }, + }, + { + name: "set zstd option when option return error", + args: args{ + opts: []ZstdOption{ + func(*zstdCompressor) error { + return errors.New("opts err") + }, + }, + }, + want: want{ + err: errors.New("opts err"), + }, + }, } for _, test := range tests { @@ -148,6 +152,7 @@ func Test_zstdCompressor_CompressVector(t *testing.T) { type fields struct { gobc Compressor eoptions []zstd.EOption + zstd zstd.Zstd } type want struct { want []byte @@ -172,39 +177,133 @@ func Test_zstdCompressor_CompressVector(t *testing.T) { return nil } tests := []test{ - // TODO test cases - /* - { - name: "test_case_1", - args: args { - vector: nil, - }, - fields: fields { - gobc: nil, - eoptions: nil, - }, - want: want{}, - checkFunc: defaultCheckFunc, - }, - */ - - // TODO test cases - /* - func() test { - return test { - name: "test_case_2", - args: args { - vector: nil, - }, - fields: fields { - gobc: nil, - eoptions: nil, - }, - want: want{}, - checkFunc: defaultCheckFunc, - } - }(), - */ + { + name: "return compressed vector", + args: args{ + vector: []float32{0.1, 0.2, 0.3}, + }, + fields: fields{ + gobc: &MockCompressor{ + CompressVectorFunc: func(vector []float32) (bytes []byte, err error) { + return ([]byte("vdaas/vald")), nil + }, + }, + zstd: &zstd.MockZstd{ + NewWriterFunc: func(w io.Writer, opts ...zstd.EOption) (zstd.Encoder, error) { + return &zstd.MockEncoder{ + WriteFunc: func([]byte) (int, error) { + return 0, nil + }, + CloseFunc: func() error { + return nil + }, + ReadFromFunc: func(r io.Reader) (int64, error) { + return io.Copy(w, r) + }, + }, nil + }, + }, + }, + want: want{ + want: []byte("vdaas/vald"), + }, + }, + { + name: "return error when gobc failed to compress vector", + args: args{ + vector: []float32{0.1, 0.2, 0.3}, + }, + fields: fields{ + gobc: &MockCompressor{ + CompressVectorFunc: func(vector []float32) (bytes []byte, err error) { + return nil, errors.New("gobc err") + }, + }, + }, + want: want{ + err: errors.New("gobc err"), + }, + }, + { + name: "return error when writer cannot be init", + args: args{ + vector: []float32{0.1, 0.2, 0.3}, + }, + fields: fields{ + gobc: &MockCompressor{ + CompressVectorFunc: func(vector []float32) (bytes []byte, err error) { + return ([]byte("vdaas/vald")), nil + }, + }, + zstd: &zstd.MockZstd{ + NewWriterFunc: func(w io.Writer, opts ...zstd.EOption) (zstd.Encoder, error) { + return nil, errors.New("new writer err") + }, + }, + }, + want: want{ + err: errors.New("new writer err"), + }, + }, + { + name: "return error when writer cannot read from source", + args: args{ + vector: []float32{0.1, 0.2, 0.3}, + }, + fields: fields{ + gobc: &MockCompressor{ + CompressVectorFunc: func(vector []float32) (bytes []byte, err error) { + return ([]byte("vdaas/vald")), nil + }, + }, + zstd: &zstd.MockZstd{ + NewWriterFunc: func(w io.Writer, opts ...zstd.EOption) (zstd.Encoder, error) { + return &zstd.MockEncoder{ + WriteFunc: func([]byte) (int, error) { + return 0, nil + }, + ReadFromFunc: func(r io.Reader) (int64, error) { + return 0, errors.New("readFrom err") + }, + }, nil + }, + }, + }, + want: want{ + err: errors.New("readFrom err"), + }, + }, + { + name: "return error when writer cannot be closed", + args: args{ + vector: []float32{0.1, 0.2, 0.3}, + }, + fields: fields{ + gobc: &MockCompressor{ + CompressVectorFunc: func(vector []float32) (bytes []byte, err error) { + return ([]byte("vdaas/vald")), nil + }, + }, + zstd: &zstd.MockZstd{ + NewWriterFunc: func(w io.Writer, opts ...zstd.EOption) (zstd.Encoder, error) { + return &zstd.MockEncoder{ + WriteFunc: func([]byte) (int, error) { + return 0, nil + }, + CloseFunc: func() error { + return errors.New("close err") + }, + ReadFromFunc: func(r io.Reader) (int64, error) { + return io.Copy(w, r) + }, + }, nil + }, + }, + }, + want: want{ + err: errors.New("close err"), + }, + }, } for _, test := range tests { @@ -222,6 +321,7 @@ func Test_zstdCompressor_CompressVector(t *testing.T) { z := &zstdCompressor{ gobc: test.fields.gobc, eoptions: test.fields.eoptions, + zstd: test.fields.zstd, } got, err := z.CompressVector(test.args.vector) @@ -233,6 +333,74 @@ func Test_zstdCompressor_CompressVector(t *testing.T) { } } +func Test_E2E_zstdCompressor_CompressVector(t *testing.T) { + type args struct { + vector []float32 + } + type want struct { + want []float32 + err error + } + type test struct { + name string + args args + want want + checkFunc func(want, []byte, error, Compressor) error + beforeFunc func(args) + afterFunc func(args) + } + + defaultCheckFunc := func(w want, got []byte, err error, l Compressor) error { + if !errors.Is(err, w.err) { + return errors.Errorf("got error = %v, want %v", err, w.err) + } + decompressed, err := l.DecompressVector(got) + if err != nil { + return errors.Errorf("decompress error: %v", err) + } + if !reflect.DeepEqual(decompressed, w.want) { + return errors.Errorf("got = %v, want %v", decompressed, w.want) + } + return nil + } + tests := []test{ + { + name: "returns same vector after decompress the compressed data", + args: args{ + vector: []float32{0.1, 0.2, 0.3}, + }, + want: want{ + want: []float32{0.1, 0.2, 0.3}, + }, + }, + } + + for _, test := range tests { + t.Run(test.name, func(tt *testing.T) { + defer goleak.VerifyNone(tt) + if test.beforeFunc != nil { + test.beforeFunc(test.args) + } + if test.afterFunc != nil { + defer test.afterFunc(test.args) + } + if test.checkFunc == nil { + test.checkFunc = defaultCheckFunc + } + + g, err := NewZstd() + if err != nil { + t.Fatal(err) + } + + got, err := g.CompressVector(test.args.vector) + if err := test.checkFunc(test.want, got, err, g); err != nil { + tt.Errorf("error = %v", err) + } + }) + } +} + func Test_zstdCompressor_DecompressVector(t *testing.T) { type args struct { bs []byte @@ -240,6 +408,7 @@ func Test_zstdCompressor_DecompressVector(t *testing.T) { type fields struct { gobc Compressor eoptions []zstd.EOption + zstd zstd.Zstd } type want struct { want []float32 @@ -264,39 +433,117 @@ func Test_zstdCompressor_DecompressVector(t *testing.T) { return nil } tests := []test{ - // TODO test cases - /* - { - name: "test_case_1", - args: args { - bs: nil, - }, - fields: fields { - gobc: nil, - eoptions: nil, - }, - want: want{}, - checkFunc: defaultCheckFunc, - }, - */ - - // TODO test cases - /* - func() test { - return test { - name: "test_case_2", - args: args { - bs: nil, - }, - fields: fields { - gobc: nil, - eoptions: nil, - }, - want: want{}, - checkFunc: defaultCheckFunc, - } - }(), - */ + { + name: "return decompress data", + args: args{ + bs: []byte("vdaas/vald"), + }, + fields: fields{ + gobc: &MockCompressor{ + DecompressVectorFunc: func(bytes []byte) (vector []float32, err error) { + return []float32{0.1, 0.2, 0.3}, nil + }, + }, + zstd: &zstd.MockZstd{ + NewReaderFunc: func(r io.Reader, opts ...zstd.DOption) (zstd.Decoder, error) { + return &zstd.MockDecoder{ + ReadFunc: func([]byte) (int, error) { + return 0, nil + }, + CloseFunc: func() { + }, + WriteToFunc: func(w io.Writer) (int64, error) { + return io.Copy(w, r) + }, + }, nil + }, + }, + }, + want: want{ + want: []float32{0.1, 0.2, 0.3}, + }, + }, + { + name: "return error when failed to init reader", + args: args{ + bs: []byte("vdaas/vald"), + }, + fields: fields{ + gobc: &MockCompressor{ + DecompressVectorFunc: func(bytes []byte) (vector []float32, err error) { + return []float32{0.1, 0.2, 0.3}, nil + }, + }, + zstd: &zstd.MockZstd{ + NewReaderFunc: func(r io.Reader, opts ...zstd.DOption) (zstd.Decoder, error) { + return nil, errors.New("new reader err") + }, + }, + }, + want: want{ + err: errors.New("new reader err"), + }, + }, + { + name: "return error when error write to buffer", + args: args{ + bs: []byte("vdaas/vald"), + }, + fields: fields{ + gobc: &MockCompressor{ + DecompressVectorFunc: func(bytes []byte) (vector []float32, err error) { + return []float32{0.1, 0.2, 0.3}, nil + }, + }, + zstd: &zstd.MockZstd{ + NewReaderFunc: func(r io.Reader, opts ...zstd.DOption) (zstd.Decoder, error) { + return &zstd.MockDecoder{ + ReadFunc: func([]byte) (int, error) { + return 0, nil + }, + CloseFunc: func() { + }, + WriteToFunc: func(w io.Writer) (int64, error) { + return 0, errors.New("write to err") + }, + }, nil + }, + }, + }, + want: want{ + err: errors.New("write to err"), + }, + }, + { + name: "return error when error to decompress vecotr", + args: args{ + bs: []byte("vdaas/vald"), + }, + fields: fields{ + gobc: &MockCompressor{ + DecompressVectorFunc: func(bytes []byte) (vector []float32, err error) { + return nil, errors.New("decom vec err") + }, + }, + zstd: &zstd.MockZstd{ + NewReaderFunc: func(r io.Reader, opts ...zstd.DOption) (zstd.Decoder, error) { + return &zstd.MockDecoder{ + ReadFunc: func([]byte) (int, error) { + return 0, nil + }, + CloseFunc: func() { + }, + WriteToFunc: func(w io.Writer) (int64, error) { + return 0, nil + }, + }, nil + }, + }, + }, + want: want{ + err: errors.New("decom vec err"), + }, + }, } for _, test := range tests { @@ -314,6 +561,7 @@ func Test_zstdCompressor_DecompressVector(t *testing.T) { z := &zstdCompressor{ gobc: test.fields.gobc, eoptions: test.fields.eoptions, + zstd: test.fields.zstd, } got, err := z.DecompressVector(test.args.bs) @@ -332,6 +580,7 @@ func Test_zstdCompressor_Reader(t *testing.T) { type fields struct { gobc Compressor eoptions []zstd.EOption + zstd zstd.Zstd } type want struct { want io.ReadCloser @@ -356,39 +605,53 @@ func Test_zstdCompressor_Reader(t *testing.T) { return nil } tests := []test{ - // TODO test cases - /* - { - name: "test_case_1", - args: args { - src: nil, - }, - fields: fields { - gobc: nil, - eoptions: nil, - }, - want: want{}, - checkFunc: defaultCheckFunc, - }, - */ - - // TODO test cases - /* - func() test { - return test { - name: "test_case_2", - args: args { - src: nil, - }, - fields: fields { - gobc: nil, - eoptions: nil, - }, - want: want{}, - checkFunc: defaultCheckFunc, - } - }(), - */ + func() test { + d := &zstd.MockDecoder{ + ReadFunc: func([]byte) (int, error) { + return 0, nil + }, + CloseFunc: func() { + }, + WriteToFunc: func(w io.Writer) (int64, error) { + return 0, nil + }, + } + return test{ + name: "return read closer", + args: args{ + src: nil, + }, + fields: fields{ + zstd: &zstd.MockZstd{ + NewReaderFunc: func(r io.Reader, opts ...zstd.DOption) (zstd.Decoder, error) { + return d, nil + }, + }, + }, + want: want{ + want: &zstdReader{ + src: nil, + r: d, + }, + }, + } + }(), + { + name: "return closer error when failed to init reader", + args: args{ + src: nil, + }, + fields: fields{ + zstd: &zstd.MockZstd{ + NewReaderFunc: func(r io.Reader, opts ...zstd.DOption) (zstd.Decoder, error) { + return nil, errors.New("new reader err") + }, + }, + }, + want: want{ + err: errors.New("new reader err"), + }, + }, } for _, test := range tests { @@ -406,6 +669,7 @@ func Test_zstdCompressor_Reader(t *testing.T) { z := &zstdCompressor{ gobc: test.fields.gobc, eoptions: test.fields.eoptions, + zstd: test.fields.zstd, } got, err := z.Reader(test.args.src) @@ -424,6 +688,7 @@ func Test_zstdCompressor_Writer(t *testing.T) { type fields struct { gobc Compressor eoptions []zstd.EOption + zstd zstd.Zstd } type want struct { want io.WriteCloser @@ -448,39 +713,53 @@ func Test_zstdCompressor_Writer(t *testing.T) { return nil } tests := []test{ - // TODO test cases - /* - { - name: "test_case_1", - args: args { - dst: nil, - }, - fields: fields { - gobc: nil, - eoptions: nil, - }, - want: want{}, - checkFunc: defaultCheckFunc, - }, - */ - - // TODO test cases - /* - func() test { - return test { - name: "test_case_2", - args: args { - dst: nil, - }, - fields: fields { - gobc: nil, - eoptions: nil, - }, - want: want{}, - checkFunc: defaultCheckFunc, - } - }(), - */ + func() test { + e := &zstd.MockEncoder{ + WriteFunc: func([]byte) (int, error) { + return 0, nil + }, + CloseFunc: func() error { + return nil + }, + ReadFromFunc: func(r io.Reader) (int64, error) { + return 0, nil + }, + } + return test{ + name: "return writer", + args: args{ + dst: nil, + }, + fields: fields{ + zstd: &zstd.MockZstd{ + NewWriterFunc: func(w io.Writer, opts ...zstd.EOption) (zstd.Encoder, error) { + return e, nil + }, + }, + }, + want: want{ + want: &zstdWriter{ + dst: nil, + w: e, + }}, + } + }(), + { + name: "return error when failed to init writer", + args: args{ + dst: nil, + }, + fields: fields{ + zstd: &zstd.MockZstd{ + NewWriterFunc: func(w io.Writer, opts ...zstd.EOption) (zstd.Encoder, error) { + return nil, errors.New("new writer err") + }, + }, + }, + want: want{ + err: errors.New("new writer err"), + }, + }, } for _, test := range tests { @@ -498,6 +777,7 @@ func Test_zstdCompressor_Writer(t *testing.T) { z := &zstdCompressor{ gobc: test.fields.gobc, eoptions: test.fields.eoptions, + zstd: test.fields.zstd, } got, err := z.Writer(test.args.dst) @@ -540,39 +820,39 @@ func Test_zstdReader_Read(t *testing.T) { return nil } tests := []test{ - // TODO test cases - /* - { - name: "test_case_1", - args: args { - p: nil, - }, - fields: fields { - src: nil, - r: nil, - }, - want: want{}, - checkFunc: defaultCheckFunc, - }, - */ - - // TODO test cases - /* - func() test { - return test { - name: "test_case_2", - args: args { - p: nil, - }, - fields: fields { - src: nil, - r: nil, - }, - want: want{}, - checkFunc: defaultCheckFunc, - } - }(), - */ + { + name: "returns n when read success", + args: args{ + p: []byte{}, + }, + fields: fields{ + r: &MockReadCloser{ + ReadFunc: func(p []byte) (int, error) { + return 10, nil + }, + }, + }, + want: want{ + wantN: 10, + err: nil, + }, + }, + { + name: "returns error when read failed", + args: args{ + p: []byte{}, + }, + fields: fields{ + r: &MockReadCloser{ + ReadFunc: func(p []byte) (int, error) { + return 0, errors.New("read err") + }, + }, + }, + want: want{ + err: errors.New("read err"), + }, + }, } for _, test := range tests { @@ -624,33 +904,32 @@ func Test_zstdReader_Close(t *testing.T) { return nil } tests := []test{ - // TODO test cases - /* - { - name: "test_case_1", - fields: fields { - src: nil, - r: nil, - }, - want: want{}, - checkFunc: defaultCheckFunc, - }, - */ - - // TODO test cases - /* - func() test { - return test { - name: "test_case_2", - fields: fields { - src: nil, - r: nil, - }, - want: want{}, - checkFunc: defaultCheckFunc, - } - }(), - */ + { + name: "returns nil when close success", + fields: fields{ + src: &MockReadCloser{ + CloseFunc: func() error { + return nil + }, + }, + }, + want: want{ + err: nil, + }, + }, + { + name: "returns error when failed close", + fields: fields{ + src: &MockReadCloser{ + CloseFunc: func() error { + return errors.New("close err") + }, + }, + }, + want: want{ + err: errors.New("close err"), + }, + }, } for _, test := range tests { @@ -710,39 +989,39 @@ func Test_zstdWriter_Write(t *testing.T) { return nil } tests := []test{ - // TODO test cases - /* - { - name: "test_case_1", - args: args { - p: nil, - }, - fields: fields { - dst: nil, - w: nil, - }, - want: want{}, - checkFunc: defaultCheckFunc, - }, - */ - - // TODO test cases - /* - func() test { - return test { - name: "test_case_2", - args: args { - p: nil, - }, - fields: fields { - dst: nil, - w: nil, - }, - want: want{}, - checkFunc: defaultCheckFunc, - } - }(), - */ + { + name: "returns n when write success", + args: args{ + p: []byte{}, + }, + fields: fields{ + w: &MockWriteCloser{ + WriteFunc: func(p []byte) (int, error) { + return 10, nil + }, + }, + }, + want: want{ + wantN: 10, + err: nil, + }, + }, + { + name: "returns error when write failed", + args: args{ + p: []byte{}, + }, + fields: fields{ + w: &MockWriteCloser{ + WriteFunc: func(p []byte) (int, error) { + return 0, errors.New("write err") + }, + }, + }, + want: want{ + err: errors.New("write err"), + }, + }, } for _, test := range tests { @@ -794,33 +1073,78 @@ func Test_zstdWriter_Close(t *testing.T) { return nil } tests := []test{ - // TODO test cases - /* - { - name: "test_case_1", - fields: fields { - dst: nil, - w: nil, - }, - want: want{}, - checkFunc: defaultCheckFunc, - }, - */ - - // TODO test cases - /* - func() test { - return test { - name: "test_case_2", - fields: fields { - dst: nil, - w: nil, - }, - want: want{}, - checkFunc: defaultCheckFunc, - } - }(), - */ + { + name: "returns nil when close success", + fields: fields{ + dst: &MockWriteCloser{ + CloseFunc: func() error { + return nil + }, + }, + w: &MockWriteCloser{ + CloseFunc: func() error { + return nil + }, + }, + }, + want: want{ + err: nil, + }, + }, + { + name: "returns error when w close failed", + fields: fields{ + dst: &MockWriteCloser{ + CloseFunc: func() error { + return nil + }, + }, + w: &MockWriteCloser{ + CloseFunc: func() error { + return errors.New("w close err") + }, + }, + }, + want: want{ + err: errors.New("w close err"), + }, + }, + { + name: "returns error when dst close failed", + fields: fields{ + dst: &MockWriteCloser{ + CloseFunc: func() error { + return errors.New("dst close err") + }, + }, + w: &MockWriteCloser{ + CloseFunc: func() error { + return nil + }, + }, + }, + want: want{ + err: errors.New("dst close err"), + }, + }, + { + name: "returns error when dst and close failed", + fields: fields{ + dst: &MockWriteCloser{ + CloseFunc: func() error { + return errors.New("dst close err") + }, + }, + w: &MockWriteCloser{ + CloseFunc: func() error { + return errors.New("w close err") + }, + }, + }, + want: want{ + err: errors.Wrap(errors.New("dst close err"), "w close err"), + }, + }, } for _, test := range tests {