github.com/zntrio/harp/v2@v2.0.9/pkg/container/codec_test.go (about)

     1  // Licensed to Elasticsearch B.V. under one or more contributor
     2  // license agreements. See the NOTICE file distributed with
     3  // this work for additional information regarding copyright
     4  // ownership. Elasticsearch B.V. licenses this file to you under
     5  // the Apache License, Version 2.0 (the "License"); you may
     6  // not use this file except in compliance with the License.
     7  // You may obtain a copy of the License at
     8  //
     9  //     http://www.apache.org/licenses/LICENSE-2.0
    10  //
    11  // Unless required by applicable law or agreed to in writing,
    12  // software distributed under the License is distributed on an
    13  // "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
    14  // KIND, either express or implied.  See the License for the
    15  // specific language governing permissions and limitations
    16  // under the License.
    17  
    18  package container
    19  
    20  import (
    21  	"bytes"
    22  	"encoding/hex"
    23  	"io"
    24  	"testing"
    25  
    26  	"github.com/google/go-cmp/cmp"
    27  	"github.com/google/go-cmp/cmp/cmpopts"
    28  	fuzz "github.com/google/gofuzz"
    29  
    30  	containerv1 "github.com/zntrio/harp/v2/api/gen/go/harp/container/v1"
    31  )
    32  
    33  var (
    34  	opt = cmp.FilterPath(
    35  		func(p cmp.Path) bool {
    36  			// Remove ignoring of the fields below once go-cmp is able to ignore generated fields.
    37  			// See https://github.com/google/go-cmp/issues/153
    38  			ignoreXXXCache :=
    39  				p.String() == "XXX_sizecache" ||
    40  					p.String() == "Headers.XXX_sizecache"
    41  			return ignoreXXXCache
    42  		}, cmp.Ignore())
    43  
    44  	ignoreOpts = []cmp.Option{
    45  		cmpopts.IgnoreUnexported(containerv1.Container{}),
    46  		cmpopts.IgnoreUnexported(containerv1.Header{}),
    47  		opt,
    48  	}
    49  )
    50  
    51  // -----------------------------------------------------------------------------
    52  
    53  func mustHexDecode(in string) []byte {
    54  	out, err := hex.DecodeString(in)
    55  	if err != nil {
    56  		panic(err)
    57  	}
    58  	return out
    59  }
    60  
    61  func TestDump(t *testing.T) {
    62  	type args struct {
    63  		c *containerv1.Container
    64  	}
    65  	tests := []struct {
    66  		name    string
    67  		args    args
    68  		wantW   []byte
    69  		wantErr bool
    70  	}{
    71  		{
    72  			name:    "nil",
    73  			wantW:   nil,
    74  			wantErr: true,
    75  		},
    76  		{
    77  			name: "empty",
    78  			args: args{
    79  				c: &containerv1.Container{},
    80  			},
    81  			wantW:   mustHexDecode("53cb37010002"),
    82  			wantErr: false,
    83  		},
    84  		{
    85  			name: "not empty",
    86  			args: args{
    87  				c: &containerv1.Container{
    88  					Headers: &containerv1.Header{
    89  						ContentEncoding: "gzip",
    90  						ContentType:     "harp.bundle.v1.Bundle",
    91  					},
    92  					Raw: []byte{0x00, 0x00},
    93  				},
    94  			},
    95  			wantW:   mustHexDecode("53cb370100020a1d0a04677a69701215686172702e62756e646c652e76312e42756e646c6512020000"),
    96  			wantErr: false,
    97  		},
    98  	}
    99  	for _, tt := range tests {
   100  		t.Run(tt.name, func(t *testing.T) {
   101  			w := &bytes.Buffer{}
   102  			if err := Dump(w, tt.args.c); (err != nil) != tt.wantErr {
   103  				t.Errorf("Dump() error = %v, wantErr %v", err, tt.wantErr)
   104  				return
   105  			}
   106  			gotW := w.Bytes()
   107  			if diff := cmp.Diff(gotW, tt.wantW, ignoreOpts...); diff != "" {
   108  				t.Errorf("Dump()\n-got/+want\ndiff %s", diff)
   109  			}
   110  		})
   111  	}
   112  }
   113  
   114  func TestLoad(t *testing.T) {
   115  	type args struct {
   116  		r io.Reader
   117  	}
   118  	tests := []struct {
   119  		name    string
   120  		args    args
   121  		want    *containerv1.Container
   122  		wantErr bool
   123  	}{
   124  		{
   125  			name:    "nil",
   126  			want:    nil,
   127  			wantErr: true,
   128  		},
   129  		{
   130  			name: "invalid magic",
   131  			args: args{
   132  				r: bytes.NewReader(mustHexDecode("FFFFFFFF0001")),
   133  			},
   134  			want:    nil,
   135  			wantErr: true,
   136  		},
   137  		{
   138  			name: "invalid version",
   139  			args: args{
   140  				r: bytes.NewReader(mustHexDecode("53cb37010002")),
   141  			},
   142  			want:    nil,
   143  			wantErr: true,
   144  		},
   145  		{
   146  			name: "empty container",
   147  			args: args{
   148  				r: bytes.NewReader(mustHexDecode("53cb37010001")),
   149  			},
   150  			want:    nil,
   151  			wantErr: true,
   152  		},
   153  		{
   154  			name: "invalid container",
   155  			args: args{
   156  				r: bytes.NewReader(mustHexDecode("53cb370100010a")),
   157  			},
   158  			want:    nil,
   159  			wantErr: true,
   160  		},
   161  		{
   162  			name: "valid",
   163  			args: args{
   164  				r: bytes.NewReader(mustHexDecode("53cb370100020a1d0a04677a69701215686172702e62756e646c652e76312e42756e646c6512020000")),
   165  			},
   166  			want: &containerv1.Container{
   167  				Headers: &containerv1.Header{
   168  					ContentEncoding: "gzip",
   169  					ContentType:     "harp.bundle.v1.Bundle",
   170  				},
   171  				Raw: []byte{0x00, 0x00},
   172  			},
   173  			wantErr: false,
   174  		},
   175  	}
   176  	for _, tt := range tests {
   177  		t.Run(tt.name, func(t *testing.T) {
   178  			got, err := Load(tt.args.r)
   179  			if (err != nil) != tt.wantErr {
   180  				t.Errorf("Load() error = %v, wantErr %v", err, tt.wantErr)
   181  				return
   182  			}
   183  			if diff := cmp.Diff(got, tt.want, ignoreOpts...); diff != "" {
   184  				t.Errorf("Load()\n-got/+want\ndiff %s", diff)
   185  			}
   186  		})
   187  	}
   188  }
   189  
   190  // -----------------------------------------------------------------------------
   191  
   192  func Test_Load_Fuzz(t *testing.T) {
   193  	// Making sure the function never panics
   194  	for i := 0; i < 50000; i++ {
   195  		f := fuzz.New()
   196  
   197  		// Prepare arguments
   198  		var (
   199  			raw []byte
   200  		)
   201  
   202  		f.Fuzz(&raw)
   203  
   204  		// Execute
   205  		Load(bytes.NewReader(raw))
   206  	}
   207  }
   208  
   209  func Test_Dump_Fuzz(t *testing.T) {
   210  	// Making sure the function never panics
   211  	for i := 0; i < 50000; i++ {
   212  		f := fuzz.New()
   213  
   214  		// Prepare arguments
   215  		var (
   216  			input containerv1.Container
   217  		)
   218  
   219  		f.Fuzz(&input)
   220  
   221  		// Execute
   222  		Dump(io.Discard, &input)
   223  	}
   224  }