github.com/ethereum/go-ethereum@v1.16.1/internal/era/e2store/e2store_test.go (about)

     1  // Copyright 2024 The go-ethereum Authors
     2  // This file is part of the go-ethereum library.
     3  //
     4  // The go-ethereum library is free software: you can redistribute it and/or modify
     5  // it under the terms of the GNU Lesser General Public License as published by
     6  // the Free Software Foundation, either version 3 of the License, or
     7  // (at your option) any later version.
     8  //
     9  // The go-ethereum library is distributed in the hope that it will be useful,
    10  // but WITHOUT ANY WARRANTY; without even the implied warranty of
    11  // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
    12  // GNU Lesser General Public License for more details.
    13  //
    14  // You should have received a copy of the GNU Lesser General Public License
    15  // along with the go-ethereum library. If not, see <http://www.gnu.org/licenses/>.
    16  
    17  package e2store
    18  
    19  import (
    20  	"bytes"
    21  	"errors"
    22  	"io"
    23  	"testing"
    24  
    25  	"github.com/ethereum/go-ethereum/common"
    26  )
    27  
    28  func TestEncode(t *testing.T) {
    29  	t.Parallel()
    30  
    31  	for _, test := range []struct {
    32  		entries []Entry
    33  		want    string
    34  		name    string
    35  	}{
    36  		{
    37  			name:    "emptyEntry",
    38  			entries: []Entry{{0xffff, nil}},
    39  			want:    "ffff000000000000",
    40  		},
    41  		{
    42  			name:    "beef",
    43  			entries: []Entry{{42, common.Hex2Bytes("beef")}},
    44  			want:    "2a00020000000000beef",
    45  		},
    46  		{
    47  			name: "twoEntries",
    48  			entries: []Entry{
    49  				{42, common.Hex2Bytes("beef")},
    50  				{9, common.Hex2Bytes("abcdabcd")},
    51  			},
    52  			want: "2a00020000000000beef0900040000000000abcdabcd",
    53  		},
    54  	} {
    55  		tt := test
    56  		t.Run(tt.name, func(t *testing.T) {
    57  			t.Parallel()
    58  
    59  			var (
    60  				b = bytes.NewBuffer(nil)
    61  				w = NewWriter(b)
    62  			)
    63  			for _, e := range tt.entries {
    64  				if _, err := w.Write(e.Type, e.Value); err != nil {
    65  					t.Fatalf("encoding error: %v", err)
    66  				}
    67  			}
    68  			if want, have := common.FromHex(tt.want), b.Bytes(); !bytes.Equal(want, have) {
    69  				t.Fatalf("encoding mismatch (want %x, have %x", want, have)
    70  			}
    71  			r := NewReader(bytes.NewReader(b.Bytes()))
    72  			for _, want := range tt.entries {
    73  				have, err := r.Read()
    74  				if err != nil {
    75  					t.Fatalf("decoding error: %v", err)
    76  				}
    77  				if have.Type != want.Type {
    78  					t.Fatalf("decoded entry does type mismatch (want %v, got %v)", want.Type, have.Type)
    79  				}
    80  				if !bytes.Equal(have.Value, want.Value) {
    81  					t.Fatalf("decoded entry does not match (want %#x, got %#x)", want.Value, have.Value)
    82  				}
    83  			}
    84  		})
    85  	}
    86  }
    87  
    88  func TestDecode(t *testing.T) {
    89  	t.Parallel()
    90  
    91  	for i, tt := range []struct {
    92  		have string
    93  		err  error
    94  	}{
    95  		{ // basic valid decoding
    96  			have: "ffff000000000000",
    97  		},
    98  		{ // basic invalid decoding
    99  			have: "ffff000000000001",
   100  			err:  errors.New("reserved bytes are non-zero"),
   101  		},
   102  		{ // no more entries to read, returns EOF
   103  			have: "",
   104  			err:  io.EOF,
   105  		},
   106  		{ // malformed type
   107  			have: "bad",
   108  			err:  io.ErrUnexpectedEOF,
   109  		},
   110  		{ // malformed length
   111  			have: "badbeef",
   112  			err:  io.ErrUnexpectedEOF,
   113  		},
   114  		{ // specified length longer than actual value
   115  			have: "beef010000000000",
   116  			err:  io.ErrUnexpectedEOF,
   117  		},
   118  	} {
   119  		r := NewReader(bytes.NewReader(common.FromHex(tt.have)))
   120  		if tt.err != nil {
   121  			_, err := r.Read()
   122  			if err == nil && tt.err != nil {
   123  				t.Fatalf("test %d, expected error, got none", i)
   124  			}
   125  			if err != nil && tt.err == nil {
   126  				t.Fatalf("test %d, expected no error, got %v", i, err)
   127  			}
   128  			if err != nil && tt.err != nil && err.Error() != tt.err.Error() {
   129  				t.Fatalf("expected error %v, got %v", tt.err, err)
   130  			}
   131  			continue
   132  		}
   133  	}
   134  }
   135  
   136  func FuzzCodec(f *testing.F) {
   137  	f.Fuzz(func(t *testing.T, input []byte) {
   138  		r := NewReader(bytes.NewReader(input))
   139  		entry, err := r.Read()
   140  		if err != nil {
   141  			return
   142  		}
   143  		var (
   144  			b = bytes.NewBuffer(nil)
   145  			w = NewWriter(b)
   146  		)
   147  		w.Write(entry.Type, entry.Value)
   148  		output := b.Bytes()
   149  		// Only care about the input that was actually consumed
   150  		input = input[:r.offset]
   151  		if !bytes.Equal(input, output) {
   152  			t.Fatalf("decode-encode mismatch, input %#x output %#x", input, output)
   153  		}
   154  	})
   155  }