github.com/klaytn/klaytn@v1.10.2/datasync/chaindatafetcher/kas/repository_traces_test.go (about)

     1  // Copyright 2020 The klaytn Authors
     2  // This file is part of the klaytn library.
     3  //
     4  // The klaytn 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 klaytn 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 klaytn library. If not, see <http://www.gnu.org/licenses/>.
    16  
    17  package kas
    18  
    19  import (
    20  	"testing"
    21  
    22  	"github.com/klaytn/klaytn/common"
    23  
    24  	"github.com/klaytn/klaytn/blockchain/types"
    25  
    26  	"github.com/klaytn/klaytn/blockchain/vm"
    27  	"github.com/stretchr/testify/assert"
    28  )
    29  
    30  // A specific types of transaction returns empty trace result which is defined as a variable `emptyTraceResult`.
    31  // As a result of the tracing, `reflect.DeepEqual` returns an error while comparing with the not-initialized slice.
    32  func TestRepository_isEmptyTraceResult(t *testing.T) {
    33  	// right empty result.
    34  	data := &vm.InternalTxTrace{
    35  		Value: "0x0",
    36  		Calls: []*vm.InternalTxTrace{},
    37  	}
    38  	assert.True(t, isEmptyTraceResult(data))
    39  
    40  	// wrong empty result.
    41  	data = &vm.InternalTxTrace{
    42  		Value: "0x0",
    43  	}
    44  	assert.False(t, isEmptyTraceResult(data))
    45  }
    46  
    47  func makeOffset(offset int64) *int64 {
    48  	return &offset
    49  }
    50  
    51  func makeEntryTx() *Tx {
    52  	txhash := genRandomHash()
    53  	return &Tx{
    54  		TransactionId:   100000000000,
    55  		TransactionHash: txhash.Bytes(),
    56  		Status:          int(types.ReceiptStatusSuccessful),
    57  		Timestamp:       1,
    58  		TypeInt:         int(types.TxTypeLegacyTransaction),
    59  	}
    60  }
    61  
    62  func makeInternalTrace(callType, value string, from *common.Address, to *common.Address) *vm.InternalTxTrace {
    63  	return &vm.InternalTxTrace{
    64  		Type:  callType,
    65  		From:  from,
    66  		To:    to,
    67  		Value: value,
    68  	}
    69  }
    70  
    71  func makeExpectedInternalTx(offset int64, entryTx *Tx, trace *vm.InternalTxTrace) *Tx {
    72  	return &Tx{
    73  		TransactionId:   entryTx.TransactionId + offset,
    74  		FromAddr:        trace.From.Bytes(),
    75  		ToAddr:          trace.To.Bytes(),
    76  		Value:           trace.Value,
    77  		TransactionHash: entryTx.TransactionHash,
    78  		Status:          entryTx.Status,
    79  		Timestamp:       entryTx.Timestamp,
    80  		TypeInt:         entryTx.TypeInt,
    81  		Internal:        true,
    82  	}
    83  }
    84  
    85  func TestRepository_transformToInternalTx(t *testing.T) {
    86  	type args struct {
    87  		trace       *vm.InternalTxTrace
    88  		offset      *int64
    89  		entryTx     *Tx
    90  		isFirstCall bool
    91  	}
    92  
    93  	// valid test case
    94  	entryTx := makeEntryTx()
    95  	trace := makeInternalTrace("TEST", "0x1", genRandomAddress(), genRandomAddress())
    96  	args1 := args{trace, makeOffset(1), entryTx, false}
    97  	expected1 := []*Tx{makeExpectedInternalTx(2, entryTx, trace)}
    98  
    99  	// valid test case 2
   100  	entryTx2 := makeEntryTx()
   101  	trace2 := makeInternalTrace("TEST", "0x1", genRandomAddress(), genRandomAddress())
   102  	innerTrace := makeInternalTrace("TEST", "0x2", genRandomAddress(), genRandomAddress())
   103  	trace2.Calls = []*vm.InternalTxTrace{innerTrace}
   104  	args2 := args{trace2, makeOffset(0), entryTx2, false}
   105  
   106  	expected2 := []*Tx{
   107  		makeExpectedInternalTx(1, entryTx2, trace2),
   108  		makeExpectedInternalTx(2, entryTx2, innerTrace),
   109  	}
   110  
   111  	tests := []struct {
   112  		name     string
   113  		args     args
   114  		expected []*Tx
   115  		err      error
   116  	}{
   117  		{
   118  			name:     "success_valid_internal_tx",
   119  			args:     args1,
   120  			expected: expected1,
   121  			err:      nil,
   122  		},
   123  		{
   124  			name:     "success_valid_internal_tx_with_inner_calls",
   125  			args:     args2,
   126  			expected: expected2,
   127  			err:      nil,
   128  		},
   129  		{
   130  			name: "fail_noOpcodeError",
   131  			args: args{
   132  				trace:       makeInternalTrace("", "0x1", genRandomAddress(), genRandomAddress()),
   133  				offset:      makeOffset(0),
   134  				entryTx:     makeEntryTx(),
   135  				isFirstCall: false,
   136  			},
   137  			expected: nil,
   138  			err:      noOpcodeError,
   139  		},
   140  		{
   141  			name: "fail_noFromFieldError",
   142  			args: args{
   143  				trace:       makeInternalTrace("TEST", "0x1", nil, genRandomAddress()),
   144  				offset:      makeOffset(0),
   145  				entryTx:     makeEntryTx(),
   146  				isFirstCall: false,
   147  			},
   148  			expected: nil,
   149  			err:      noFromFieldError,
   150  		},
   151  		{
   152  			name: "fail_noToFieldError",
   153  			args: args{
   154  				trace:       makeInternalTrace("TEST", "0x1", genRandomAddress(), nil),
   155  				offset:      makeOffset(0),
   156  				entryTx:     makeEntryTx(),
   157  				isFirstCall: false,
   158  			},
   159  			expected: nil,
   160  			err:      noToFieldError,
   161  		},
   162  		{
   163  			name: "success_ignore_selfdestruct",
   164  			args: args{
   165  				trace:       makeInternalTrace(selfDestructType, "0x1", genRandomAddress(), genRandomAddress()),
   166  				offset:      makeOffset(0),
   167  				entryTx:     makeEntryTx(),
   168  				isFirstCall: false,
   169  			},
   170  			expected: nil,
   171  			err:      nil,
   172  		},
   173  		{
   174  			name: "success_ignore_firstCall",
   175  			args: args{
   176  				trace:       makeInternalTrace("TEST", "0x1", genRandomAddress(), genRandomAddress()),
   177  				offset:      makeOffset(0),
   178  				entryTx:     makeEntryTx(),
   179  				isFirstCall: true,
   180  			},
   181  			expected: nil,
   182  			err:      nil,
   183  		},
   184  		{
   185  			name: "success_empty_value",
   186  			args: args{
   187  				trace:       makeInternalTrace("TEST", "", genRandomAddress(), genRandomAddress()),
   188  				offset:      makeOffset(0),
   189  				entryTx:     makeEntryTx(),
   190  				isFirstCall: false,
   191  			},
   192  			expected: nil,
   193  			err:      nil,
   194  		},
   195  	}
   196  
   197  	for _, tt := range tests {
   198  		t.Run(tt.name, func(t *testing.T) {
   199  			got, err := transformToInternalTx(tt.args.trace, tt.args.offset, tt.args.entryTx, tt.args.isFirstCall)
   200  			assert.Equal(t, tt.expected, got)
   201  			assert.Equal(t, tt.err, err)
   202  		})
   203  	}
   204  }