github.com/aergoio/aergo@v1.3.1/state/contract_test.go (about)

     1  package state
     2  
     3  import (
     4  	"os"
     5  	"testing"
     6  
     7  	"github.com/aergoio/aergo-lib/db"
     8  	"github.com/aergoio/aergo/types"
     9  	"github.com/stretchr/testify/assert"
    10  )
    11  
    12  var chainStateDB *ChainStateDB
    13  var stateDB *StateDB
    14  
    15  func initTest(t *testing.T) {
    16  	chainStateDB = NewChainStateDB()
    17  	_ = chainStateDB.Init(string(db.BadgerImpl), "test", nil, false)
    18  	stateDB = chainStateDB.GetStateDB()
    19  	genesis := types.GetTestGenesis()
    20  
    21  	err := chainStateDB.SetGenesis(genesis, nil)
    22  	assert.NoError(t, err, "failed init")
    23  }
    24  func deinitTest() {
    25  	_ = chainStateDB.Close()
    26  	_ = os.RemoveAll("test")
    27  }
    28  func TestContractStateCode(t *testing.T) {
    29  	initTest(t)
    30  	defer deinitTest()
    31  	testAddress := []byte("test_address")
    32  	testBytes := []byte("test_bytes")
    33  
    34  	// open contract state
    35  	contractState, err := stateDB.OpenContractStateAccount(types.ToAccountID(testAddress))
    36  	assert.NoError(t, err, "could not open contract state")
    37  
    38  	// set code
    39  	err = contractState.SetCode(testBytes)
    40  	assert.NoError(t, err, "set code to contract state")
    41  
    42  	// get code
    43  	res, err := contractState.GetCode()
    44  	assert.NoError(t, err, "get code from contract state")
    45  	assert.Equal(t, testBytes, res, "different code detected")
    46  }
    47  
    48  func TestContractStateData(t *testing.T) {
    49  	initTest(t)
    50  	defer deinitTest()
    51  	testAddress := []byte("test_address")
    52  	testBytes := []byte("test_bytes")
    53  	testKey := []byte("test_key")
    54  
    55  	// open contract state
    56  	contractState, err := stateDB.OpenContractStateAccount(types.ToAccountID(testAddress))
    57  	assert.NoError(t, err, "could not open contract state")
    58  
    59  	// set data
    60  	err = contractState.SetData(testKey, testBytes)
    61  	assert.NoError(t, err, "set data to contract state")
    62  
    63  	// get data
    64  	res, err := contractState.GetData(testKey)
    65  	assert.NoError(t, err, "get data from contract state")
    66  	assert.Equal(t, testBytes, res, "different data detected")
    67  
    68  	// stage contract state
    69  	err = stateDB.StageContractState(contractState)
    70  	assert.NoError(t, err, "stage contract state")
    71  }
    72  
    73  func TestContractStateInitialData(t *testing.T) {
    74  	initTest(t)
    75  	defer deinitTest()
    76  	testAddress := []byte("test_address")
    77  	testBytes := []byte("test_bytes")
    78  	testKey := []byte("test_key")
    79  
    80  	// open contract state
    81  	contractState, err := stateDB.OpenContractStateAccount(types.ToAccountID(testAddress))
    82  	assert.NoError(t, err, "could not open contract state")
    83  
    84  	// get initial data
    85  	res, err := contractState.GetInitialData(testKey)
    86  	assert.NoError(t, err, "get initial data from contract state")
    87  	assert.Nil(t, res, "get initial data from contract state")
    88  
    89  	// set data
    90  	err = contractState.SetData(testKey, testBytes)
    91  	assert.NoError(t, err, "set data to contract state")
    92  
    93  	// get data
    94  	res, err = contractState.GetData(testKey)
    95  	assert.NoError(t, err, "get data from contract state")
    96  	assert.Equal(t, testBytes, res, "different data detected")
    97  
    98  	// get initial data
    99  	res, err = contractState.GetInitialData(testKey)
   100  	assert.NoError(t, err, "get initial data from contract state")
   101  	assert.Nil(t, res, "get initial data from contract state")
   102  
   103  	// stage contract state
   104  	err = stateDB.StageContractState(contractState)
   105  	assert.NoError(t, err, "stage contract state")
   106  
   107  	// update and commit statedb
   108  	err = stateDB.Update()
   109  	assert.NoError(t, err, "update statedb")
   110  	err = stateDB.Commit()
   111  	assert.NoError(t, err, "commit statedb")
   112  
   113  	// reopen contract state
   114  	contractState, err = stateDB.OpenContractStateAccount(types.ToAccountID(testAddress))
   115  	assert.NoError(t, err, "could not open contract state")
   116  
   117  	// get initial data
   118  	res, err = contractState.GetInitialData(testKey)
   119  	assert.NoError(t, err, "get initial data from contract state")
   120  	assert.Equal(t, testBytes, res, "get initial data from contract state")
   121  }
   122  
   123  func TestContractStateDataDelete(t *testing.T) {
   124  	initTest(t)
   125  	defer deinitTest()
   126  	testAddress := []byte("test_address")
   127  	testBytes := []byte("test_bytes")
   128  	testKey := []byte("test_key")
   129  
   130  	// open contract state and set test data
   131  	contractState, err := stateDB.OpenContractStateAccount(types.ToAccountID(testAddress))
   132  	assert.NoError(t, err, "could not open contract state")
   133  	err = contractState.SetData(testKey, testBytes)
   134  	assert.NoError(t, err, "set data to contract state")
   135  
   136  	// stage and re-open contract state
   137  	err = stateDB.StageContractState(contractState)
   138  	assert.NoError(t, err, "stage contract state")
   139  	contractState, err = stateDB.OpenContractState(types.ToAccountID(testAddress), contractState.State)
   140  	assert.NoError(t, err, "could not open contract state")
   141  
   142  	// get and delete test data
   143  	res, err := contractState.GetData(testKey)
   144  	assert.NoError(t, err, "get data from contract state")
   145  	assert.Equal(t, testBytes, res, "different data detected")
   146  	err = contractState.DeleteData(testKey)
   147  	assert.NoError(t, err, "delete data from contract state")
   148  
   149  	// stage and re-open contract state
   150  	err = stateDB.StageContractState(contractState)
   151  	assert.NoError(t, err, "stage contract state")
   152  	contractState, err = stateDB.OpenContractState(types.ToAccountID(testAddress), contractState.State)
   153  	assert.NoError(t, err, "could not open contract state")
   154  
   155  	// get test data
   156  	res, err = contractState.GetData(testKey)
   157  	assert.NoError(t, err, "get data from contract state")
   158  	assert.Nil(t, res, "garbage data detected")
   159  
   160  	// stage contract state
   161  	err = stateDB.StageContractState(contractState)
   162  	assert.NoError(t, err, "stage contract state")
   163  }
   164  
   165  func TestContractStateHasKey(t *testing.T) {
   166  	initTest(t)
   167  	defer deinitTest()
   168  	testAddress := []byte("test_address")
   169  	testBytes := []byte("test_bytes")
   170  	testKey := []byte("test_key")
   171  
   172  	// open contract state and set test data
   173  	contractState, err := stateDB.OpenContractStateAccount(types.ToAccountID(testAddress))
   174  	assert.NoError(t, err, "could not open contract state")
   175  	assert.False(t, contractState.HasKey(testKey))
   176  
   177  	err = contractState.SetData(testKey, testBytes)
   178  	assert.NoError(t, err, "set data to contract state")
   179  	assert.True(t, contractState.HasKey(testKey))
   180  
   181  	// get test data
   182  	_, err = contractState.GetData(testKey)
   183  	assert.NoError(t, err, "get data from contract state")
   184  	assert.True(t, contractState.HasKey(testKey))
   185  
   186  	// delete test data
   187  	err = contractState.DeleteData(testKey)
   188  	assert.NoError(t, err, "delete data from contract state")
   189  	assert.True(t, contractState.HasKey(testKey))
   190  
   191  	// stage contract state
   192  	err = stateDB.StageContractState(contractState)
   193  	assert.NoError(t, err, "stage contract state")
   194  
   195  	// update and commit
   196  	err = stateDB.Update()
   197  	assert.NoError(t, err, "failed to update stateDB")
   198  	err = stateDB.Commit()
   199  	assert.NoError(t, err, "failed to commit stateDB")
   200  
   201  	// re-open contract state
   202  	contractState, err = stateDB.OpenContractState(types.ToAccountID(testAddress), contractState.State)
   203  	assert.NoError(t, err, "could not open contract state")
   204  
   205  	// check key existence
   206  	assert.False(t, contractState.HasKey(testKey))
   207  }
   208  
   209  func TestContractStateEmpty(t *testing.T) {
   210  	initTest(t)
   211  	defer deinitTest()
   212  	testAddress := []byte("test_address")
   213  
   214  	// open contract state
   215  	contractState, err := stateDB.OpenContractStateAccount(types.ToAccountID(testAddress))
   216  	assert.NoError(t, err, "could not open contract state")
   217  
   218  	// stage contract state
   219  	err = stateDB.StageContractState(contractState)
   220  	assert.NoError(t, err, "stage contract state")
   221  }
   222  
   223  func TestContractStateReOpenData(t *testing.T) {
   224  	initTest(t)
   225  	defer deinitTest()
   226  	testAddress := []byte("test_address")
   227  	testBytes := []byte("test_bytes")
   228  	testKey := []byte("test_key")
   229  
   230  	// open contract state
   231  	contractState, err := stateDB.OpenContractStateAccount(types.ToAccountID(testAddress))
   232  	assert.NoError(t, err, "could not open contract state")
   233  
   234  	// set data
   235  	err = contractState.SetData(testKey, testBytes)
   236  	assert.NoError(t, err, "set data to contract state")
   237  
   238  	// get data
   239  	res, err := contractState.GetData(testKey)
   240  	assert.NoError(t, err, "get data from contract state")
   241  	assert.Equal(t, testBytes, res, "different data detected")
   242  
   243  	// stage contract state
   244  	err = stateDB.StageContractState(contractState)
   245  	assert.NoError(t, err, "stage contract state")
   246  
   247  	// re-open contract state
   248  	//contractState2, err := chainStateDB.OpenContractStateAccount(types.ToAccountID(testAddress))
   249  	contractState2, err := stateDB.OpenContractState(types.ToAccountID(testAddress), contractState.State)
   250  	assert.NoError(t, err, "could not open contract state")
   251  
   252  	// get data
   253  	res2, err := contractState2.GetData(testKey)
   254  	assert.NoError(t, err, "get data from contract state")
   255  	assert.Equal(t, testBytes, res2, "different data detected")
   256  }
   257  
   258  func TestContractStateRollback(t *testing.T) {
   259  	initTest(t)
   260  	defer deinitTest()
   261  
   262  	testAddress := []byte("test_address")
   263  	testKey := []byte("test_key")
   264  
   265  	// open contract state
   266  	contractState, err := stateDB.OpenContractStateAccount(types.ToAccountID(testAddress))
   267  	assert.NoError(t, err, "could not open contract state")
   268  
   269  	// test data
   270  	_ = contractState.SetData(testKey, []byte("1")) // rev 1
   271  	_ = contractState.SetData(testKey, []byte("2")) // rev 2
   272  	res, _ := contractState.GetData(testKey)
   273  	assert.Equal(t, []byte("2"), res)
   274  
   275  	// snapshot: rev 2
   276  	revision := contractState.Snapshot()
   277  	t.Log("revision", revision)
   278  	assert.Equal(t, 2, int(revision))
   279  
   280  	// test data
   281  	_ = contractState.SetData(testKey, []byte("3")) // rev 3
   282  	_ = contractState.SetData(testKey, []byte("4")) // rev 4
   283  	_ = contractState.SetData(testKey, []byte("5")) // rev 5
   284  	res, _ = contractState.GetData(testKey)
   285  	assert.Equal(t, []byte("5"), res)
   286  
   287  	// rollback: rev 2
   288  	contractState.Rollback(revision)
   289  	res, _ = contractState.GetData(testKey)
   290  	assert.Equal(t, []byte("2"), res)
   291  
   292  	// rollback to empty: rev 0
   293  	contractState.Rollback(Snapshot(0))
   294  	res, _ = contractState.GetData(testKey)
   295  	assert.Nil(t, res)
   296  }