github.com/nspcc-dev/neo-go@v0.105.2-0.20240517133400-6be757af3eba/pkg/core/transaction/attribute_test.go (about)

     1  package transaction
     2  
     3  import (
     4  	"encoding/base64"
     5  	"encoding/json"
     6  	"testing"
     7  
     8  	"github.com/nspcc-dev/neo-go/internal/random"
     9  	"github.com/nspcc-dev/neo-go/internal/testserdes"
    10  	"github.com/nspcc-dev/neo-go/pkg/io"
    11  	"github.com/nspcc-dev/neo-go/pkg/util"
    12  	"github.com/stretchr/testify/assert"
    13  	"github.com/stretchr/testify/require"
    14  )
    15  
    16  func TestAttribute_EncodeBinary(t *testing.T) {
    17  	t.Run("HighPriority", func(t *testing.T) {
    18  		attr := &Attribute{
    19  			Type: HighPriority,
    20  		}
    21  		testserdes.EncodeDecodeBinary(t, attr, new(Attribute))
    22  	})
    23  	t.Run("OracleResponse", func(t *testing.T) {
    24  		attr := &Attribute{
    25  			Type: OracleResponseT,
    26  			Value: &OracleResponse{
    27  				ID:     0x1122334455,
    28  				Code:   Success,
    29  				Result: []byte{1, 2, 3},
    30  			},
    31  		}
    32  		testserdes.EncodeDecodeBinary(t, attr, new(Attribute))
    33  		for _, code := range []OracleResponseCode{ProtocolNotSupported, ConsensusUnreachable,
    34  			NotFound, Timeout, Forbidden, ResponseTooLarge, InsufficientFunds, Error} {
    35  			attr = &Attribute{
    36  				Type: OracleResponseT,
    37  				Value: &OracleResponse{
    38  					ID:     42,
    39  					Code:   code,
    40  					Result: []byte{},
    41  				},
    42  			}
    43  			testserdes.EncodeDecodeBinary(t, attr, new(Attribute))
    44  		}
    45  	})
    46  	t.Run("NotValidBefore", func(t *testing.T) {
    47  		t.Run("positive", func(t *testing.T) {
    48  			attr := &Attribute{
    49  				Type: NotValidBeforeT,
    50  				Value: &NotValidBefore{
    51  					Height: 123,
    52  				},
    53  			}
    54  			testserdes.EncodeDecodeBinary(t, attr, new(Attribute))
    55  		})
    56  		t.Run("bad format: too short", func(t *testing.T) {
    57  			bw := io.NewBufBinWriter()
    58  			bw.WriteBytes([]byte{1, 2, 3})
    59  			require.Error(t, testserdes.DecodeBinary(bw.Bytes(), new(NotValidBefore)))
    60  		})
    61  	})
    62  	t.Run("Reserved", func(t *testing.T) {
    63  		getReservedAttribute := func(t AttrType) *Attribute {
    64  			return &Attribute{
    65  				Type: t,
    66  				Value: &Reserved{
    67  					Value: []byte{1, 2, 3, 4, 5},
    68  				},
    69  			}
    70  		}
    71  		t.Run("lower bound", func(t *testing.T) {
    72  			testserdes.EncodeDecodeBinary(t, getReservedAttribute(ReservedLowerBound+3), new(Attribute))
    73  		})
    74  		t.Run("upper bound", func(t *testing.T) {
    75  			testserdes.EncodeDecodeBinary(t, getReservedAttribute(ReservedUpperBound), new(Attribute))
    76  		})
    77  		t.Run("inside bounds", func(t *testing.T) {
    78  			testserdes.EncodeDecodeBinary(t, getReservedAttribute(ReservedLowerBound+5), new(Attribute))
    79  		})
    80  		t.Run("not reserved", func(t *testing.T) {
    81  			_, err := testserdes.EncodeBinary(getReservedAttribute(ReservedLowerBound - 1))
    82  			require.Error(t, err)
    83  		})
    84  	})
    85  	t.Run("Conflicts", func(t *testing.T) {
    86  		t.Run("positive", func(t *testing.T) {
    87  			attr := &Attribute{
    88  				Type: ConflictsT,
    89  				Value: &Conflicts{
    90  					Hash: random.Uint256(),
    91  				},
    92  			}
    93  			testserdes.EncodeDecodeBinary(t, attr, new(Attribute))
    94  		})
    95  		t.Run("negative: bad uint256", func(t *testing.T) {
    96  			bw := io.NewBufBinWriter()
    97  			bw.WriteBytes(make([]byte, util.Uint256Size-1))
    98  			require.Error(t, testserdes.DecodeBinary(bw.Bytes(), new(Conflicts)))
    99  		})
   100  	})
   101  	t.Run("NotaryAssisted", func(t *testing.T) {
   102  		t.Run("positive", func(t *testing.T) {
   103  			attr := &Attribute{
   104  				Type: NotaryAssistedT,
   105  				Value: &NotaryAssisted{
   106  					NKeys: 3,
   107  				},
   108  			}
   109  			testserdes.EncodeDecodeBinary(t, attr, new(Attribute))
   110  		})
   111  		t.Run("bad format: too short", func(t *testing.T) {
   112  			bw := io.NewBufBinWriter()
   113  			bw.WriteBytes([]byte{})
   114  			require.Error(t, testserdes.DecodeBinary(bw.Bytes(), new(NotaryAssisted)))
   115  		})
   116  	})
   117  }
   118  
   119  func TestAttribute_MarshalJSON(t *testing.T) {
   120  	t.Run("HighPriority", func(t *testing.T) {
   121  		attr := &Attribute{Type: HighPriority}
   122  		data, err := json.Marshal(attr)
   123  		require.NoError(t, err)
   124  		require.JSONEq(t, `{"type":"HighPriority"}`, string(data))
   125  
   126  		actual := new(Attribute)
   127  		require.NoError(t, json.Unmarshal(data, actual))
   128  		require.Equal(t, attr, actual)
   129  	})
   130  	t.Run("OracleResponse", func(t *testing.T) {
   131  		res := []byte{1, 2, 3}
   132  		attr := &Attribute{
   133  			Type: OracleResponseT,
   134  			Value: &OracleResponse{
   135  				ID:     123,
   136  				Code:   Success,
   137  				Result: res,
   138  			},
   139  		}
   140  		data, err := json.Marshal(attr)
   141  		require.NoError(t, err)
   142  		require.JSONEq(t, `{
   143  			"type":"OracleResponse",
   144  			"id": 123,
   145  			"code": "Success",
   146  			"result": "`+base64.StdEncoding.EncodeToString(res)+`"}`, string(data))
   147  
   148  		actual := new(Attribute)
   149  		require.NoError(t, json.Unmarshal(data, actual))
   150  		require.Equal(t, attr, actual)
   151  		testserdes.EncodeDecodeBinary(t, attr, new(Attribute))
   152  	})
   153  	t.Run("NotValidBefore", func(t *testing.T) {
   154  		attr := &Attribute{
   155  			Type: NotValidBeforeT,
   156  			Value: &NotValidBefore{
   157  				Height: 123,
   158  			},
   159  		}
   160  		testserdes.MarshalUnmarshalJSON(t, attr, new(Attribute))
   161  	})
   162  	t.Run("Conflicts", func(t *testing.T) {
   163  		attr := &Attribute{
   164  			Type: ConflictsT,
   165  			Value: &Conflicts{
   166  				Hash: random.Uint256(),
   167  			},
   168  		}
   169  		testserdes.MarshalUnmarshalJSON(t, attr, new(Attribute))
   170  	})
   171  	t.Run("NotaryAssisted", func(t *testing.T) {
   172  		attr := &Attribute{
   173  			Type: NotaryAssistedT,
   174  			Value: &NotaryAssisted{
   175  				NKeys: 3,
   176  			},
   177  		}
   178  		testserdes.MarshalUnmarshalJSON(t, attr, new(Attribute))
   179  	})
   180  }
   181  
   182  func TestAttribute_Copy(t *testing.T) {
   183  	originals := []*Attribute{
   184  		{Type: HighPriority},
   185  		{Type: OracleResponseT, Value: &OracleResponse{ID: 123, Code: Success, Result: []byte{1, 2, 3}}},
   186  		{Type: NotValidBeforeT, Value: &NotValidBefore{Height: 123}},
   187  		{Type: ConflictsT, Value: &Conflicts{Hash: random.Uint256()}},
   188  		{Type: NotaryAssistedT, Value: &NotaryAssisted{NKeys: 3}},
   189  		{Type: ReservedLowerBound, Value: &Reserved{Value: []byte{1, 2, 3, 4, 5}}},
   190  		{Type: ReservedUpperBound, Value: &Reserved{Value: []byte{1, 2, 3, 4, 5}}},
   191  		{Type: ReservedLowerBound + 5, Value: &Reserved{Value: []byte{1, 2, 3, 4, 5}}},
   192  	}
   193  	require.Nil(t, (*Attribute)(nil).Copy())
   194  
   195  	for _, original := range originals {
   196  		cp := original.Copy()
   197  		require.NotNil(t, cp)
   198  		assert.Equal(t, original.Type, cp.Type)
   199  		assert.Equal(t, original.Value, cp.Value)
   200  		if original.Value != nil {
   201  			originalValueCopy := original.Value.Copy()
   202  			switch originalVal := originalValueCopy.(type) {
   203  			case *OracleResponse:
   204  				originalVal.Result = append(originalVal.Result, 0xFF)
   205  				assert.NotEqual(t, len(original.Value.(*OracleResponse).Result), len(originalVal.Result))
   206  			case *Conflicts:
   207  				originalVal.Hash = random.Uint256()
   208  				assert.NotEqual(t, original.Value.(*Conflicts).Hash, originalVal.Hash)
   209  			case *NotaryAssisted:
   210  				originalVal.NKeys++
   211  				assert.NotEqual(t, original.Value.(*NotaryAssisted).NKeys, originalVal.NKeys)
   212  			}
   213  			assert.Equal(t, cp.Value, original.Value)
   214  		}
   215  	}
   216  }