github.com/turingchain2020/turingchain@v1.1.21/common/db/table/table_test.go (about)

     1  // Copyright Turing Corp. 2018 All Rights Reserved.
     2  // Use of this source code is governed by a BSD-style
     3  // license that can be found in the LICENSE file.
     4  package table
     5  
     6  import (
     7  	"bytes"
     8  	"testing"
     9  
    10  	"github.com/turingchain2020/turingchain/common/db"
    11  	"github.com/turingchain2020/turingchain/types"
    12  	"github.com/turingchain2020/turingchain/util"
    13  	"github.com/golang/protobuf/proto"
    14  	"github.com/stretchr/testify/assert"
    15  )
    16  
    17  func TestTransactinList(t *testing.T) {
    18  	dir, ldb, kvdb := util.CreateTestDB()
    19  	defer util.CloseTestDB(dir, ldb)
    20  	opt := &Option{
    21  		Prefix:  "prefix",
    22  		Name:    "name",
    23  		Primary: "Hash",
    24  		Index:   []string{"From", "To"},
    25  	}
    26  	cfg := types.NewTuringchainConfig(types.GetDefaultCfgstring())
    27  	table, err := NewTable(NewTransactionRow(), kvdb, opt)
    28  	assert.Nil(t, err)
    29  	addr1, priv := util.Genaddress()
    30  	tx1 := util.CreateNoneTx(cfg, priv)
    31  	err = table.Add(tx1)
    32  	assert.Nil(t, err)
    33  	tx2 := util.CreateNoneTx(cfg, priv)
    34  	err = table.Add(tx2)
    35  	assert.Nil(t, err)
    36  
    37  	addr2, priv := util.Genaddress()
    38  	tx3 := util.CreateNoneTx(cfg, priv)
    39  	err = table.Add(tx3)
    40  	assert.Nil(t, err)
    41  	tx4 := util.CreateNoneTx(cfg, priv)
    42  	err = table.Add(tx4)
    43  	assert.Nil(t, err)
    44  	//添加一个无效的类型
    45  	err = table.Add(nil)
    46  	assert.Equal(t, types.ErrTypeAsset, err)
    47  	kvs, err := table.Save()
    48  	assert.Nil(t, err)
    49  	assert.Equal(t, len(kvs), 12)
    50  	//save to database
    51  	util.SaveKVList(ldb, kvs)
    52  	//测试查询
    53  	query := table.GetQuery(kvdb)
    54  
    55  	rows, err := query.ListIndex("From", []byte(addr1), nil, 0, 0)
    56  	assert.Nil(t, err)
    57  	assert.Equal(t, 2, len(rows))
    58  	if bytes.Compare(tx1.Hash(), tx2.Hash()) > 0 {
    59  		assert.Equal(t, true, proto.Equal(tx1, rows[0].Data))
    60  		assert.Equal(t, true, proto.Equal(tx2, rows[1].Data))
    61  	} else {
    62  		assert.Equal(t, true, proto.Equal(tx1, rows[1].Data))
    63  		assert.Equal(t, true, proto.Equal(tx2, rows[0].Data))
    64  	}
    65  	//prefix full
    66  	rows, err = query.ListIndex("From", []byte(addr2), nil, 0, 0)
    67  	assert.Nil(t, err)
    68  	assert.Equal(t, 2, len(rows))
    69  	if bytes.Compare(tx3.Hash(), tx4.Hash()) > 0 {
    70  		assert.Equal(t, true, proto.Equal(tx3, rows[0].Data))
    71  		assert.Equal(t, true, proto.Equal(tx4, rows[1].Data))
    72  	} else {
    73  		assert.Equal(t, true, proto.Equal(tx3, rows[1].Data))
    74  		assert.Equal(t, true, proto.Equal(tx4, rows[0].Data))
    75  	}
    76  	//prefix part
    77  	rows, err = query.ListIndex("From", []byte(addr2[0:10]), nil, 0, 0)
    78  	assert.Nil(t, err)
    79  	assert.Equal(t, 2, len(rows))
    80  	if bytes.Compare(tx3.Hash(), tx4.Hash()) > 0 {
    81  		assert.Equal(t, true, proto.Equal(tx3, rows[0].Data))
    82  		assert.Equal(t, true, proto.Equal(tx4, rows[1].Data))
    83  	} else {
    84  		assert.Equal(t, true, proto.Equal(tx3, rows[1].Data))
    85  		assert.Equal(t, true, proto.Equal(tx4, rows[0].Data))
    86  	}
    87  	//count
    88  	rows, err = query.ListIndex("From", []byte(addr2[0:10]), nil, 1, 0)
    89  	assert.Nil(t, err)
    90  	assert.Equal(t, 1, len(rows))
    91  	if bytes.Compare(tx3.Hash(), tx4.Hash()) > 0 {
    92  		assert.Equal(t, true, proto.Equal(tx3, rows[0].Data))
    93  	} else {
    94  		assert.Equal(t, true, proto.Equal(tx4, rows[0].Data))
    95  	}
    96  	primary := rows[0].Primary
    97  	//primary
    98  	rows, err = query.ListIndex("From", nil, primary, 1, 0)
    99  	assert.Nil(t, err)
   100  	assert.Equal(t, 1, len(rows))
   101  	if bytes.Compare(tx3.Hash(), tx4.Hash()) > 0 {
   102  		assert.Equal(t, true, proto.Equal(tx4, rows[0].Data))
   103  	} else {
   104  		assert.Equal(t, true, proto.Equal(tx3, rows[0].Data))
   105  	}
   106  	//prefix + primary
   107  	rows, err = query.ListIndex("From", []byte(addr2[0:10]), primary, 0, 0)
   108  	assert.Nil(t, err)
   109  	assert.Equal(t, 1, len(rows))
   110  	if bytes.Compare(tx3.Hash(), tx4.Hash()) > 0 {
   111  		assert.Equal(t, true, proto.Equal(tx4, rows[0].Data))
   112  	} else {
   113  		assert.Equal(t, true, proto.Equal(tx3, rows[0].Data))
   114  	}
   115  	//List data
   116  	rows, err = query.List("From", tx3, primary, 0, 0)
   117  	assert.Nil(t, err)
   118  	assert.Equal(t, 1, len(rows))
   119  	if bytes.Compare(tx3.Hash(), tx4.Hash()) > 0 {
   120  		assert.Equal(t, true, proto.Equal(tx4, rows[0].Data))
   121  	} else {
   122  		assert.Equal(t, true, proto.Equal(tx3, rows[0].Data))
   123  	}
   124  
   125  	rows, err = query.ListIndex("From", []byte(addr1[0:10]), primary, 0, 0)
   126  	assert.Equal(t, types.ErrNotFound, err)
   127  	assert.Equal(t, 0, len(rows))
   128  	//ListPrimary all
   129  	rows, err = query.ListIndex("primary", nil, nil, 0, 0)
   130  	assert.Nil(t, err)
   131  	assert.Equal(t, 4, len(rows))
   132  
   133  	//ListPrimary all
   134  	rows, err = query.List("primary", nil, nil, 0, 0)
   135  	assert.Nil(t, err)
   136  	assert.Equal(t, 4, len(rows))
   137  
   138  	row, err := query.ListOne("primary", nil, nil)
   139  	assert.Nil(t, err)
   140  	assert.Equal(t, row, rows[0])
   141  
   142  	primary = rows[0].Primary
   143  	rows, err = query.ListIndex("auto", primary, nil, 0, 0)
   144  	assert.Nil(t, err)
   145  	assert.Equal(t, 1, len(rows))
   146  
   147  	rows, err = query.List("", rows[0].Data, nil, 0, 0)
   148  	assert.Nil(t, err)
   149  	assert.Equal(t, 1, len(rows))
   150  
   151  	rows, err = query.ListIndex("", nil, primary, 0, 0)
   152  	assert.Nil(t, err)
   153  	assert.Equal(t, 3, len(rows))
   154  }
   155  
   156  func TestTransactinListAuto(t *testing.T) {
   157  	dir, ldb, kvdb := util.CreateTestDB()
   158  	defer util.CloseTestDB(dir, ldb)
   159  	opt := &Option{
   160  		Prefix:  "prefix",
   161  		Name:    "name",
   162  		Primary: "",
   163  		Index:   []string{"From", "To"},
   164  	}
   165  	cfg := types.NewTuringchainConfig(types.GetDefaultCfgstring())
   166  	table, err := NewTable(NewTransactionRow(), kvdb, opt)
   167  	assert.Nil(t, err)
   168  	addr1, priv := util.Genaddress()
   169  	tx1 := util.CreateNoneTx(cfg, priv)
   170  	err = table.Add(tx1)
   171  	assert.Nil(t, err)
   172  	tx2 := util.CreateNoneTx(cfg, priv)
   173  	err = table.Add(tx2)
   174  	assert.Nil(t, err)
   175  
   176  	addr2, priv := util.Genaddress()
   177  	tx3 := util.CreateNoneTx(cfg, priv)
   178  	err = table.Add(tx3)
   179  	assert.Nil(t, err)
   180  	tx4 := util.CreateNoneTx(cfg, priv)
   181  	err = table.Add(tx4)
   182  	assert.Nil(t, err)
   183  	//添加一个无效的类型
   184  	err = table.Add(nil)
   185  	assert.Equal(t, types.ErrTypeAsset, err)
   186  	kvs, err := table.Save()
   187  	assert.Nil(t, err)
   188  	assert.Equal(t, len(kvs), 13)
   189  	//save to database
   190  	util.SaveKVList(ldb, kvs)
   191  	//测试查询
   192  	query := table.GetQuery(kvdb)
   193  
   194  	rows, err := query.ListIndex("From", []byte(addr1), nil, 0, db.ListASC)
   195  	assert.Nil(t, err)
   196  	assert.Equal(t, 2, len(rows))
   197  	assert.Equal(t, true, proto.Equal(tx1, rows[0].Data))
   198  	assert.Equal(t, true, proto.Equal(tx2, rows[1].Data))
   199  	//prefix full
   200  	rows, err = query.ListIndex("From", []byte(addr2), nil, 0, db.ListASC)
   201  	assert.Nil(t, err)
   202  	assert.Equal(t, 2, len(rows))
   203  	assert.Equal(t, true, proto.Equal(tx3, rows[0].Data))
   204  	assert.Equal(t, true, proto.Equal(tx4, rows[1].Data))
   205  	//prefix part
   206  	rows, err = query.ListIndex("From", []byte(addr2[0:10]), nil, 0, db.ListASC)
   207  	assert.Nil(t, err)
   208  	assert.Equal(t, 2, len(rows))
   209  	assert.Equal(t, true, proto.Equal(tx3, rows[0].Data))
   210  	assert.Equal(t, true, proto.Equal(tx4, rows[1].Data))
   211  	//count
   212  	rows, err = query.ListIndex("From", []byte(addr2[0:10]), nil, 1, db.ListASC)
   213  	assert.Nil(t, err)
   214  	assert.Equal(t, 1, len(rows))
   215  	assert.Equal(t, true, proto.Equal(tx3, rows[0].Data))
   216  	primary := rows[0].Primary
   217  	//primary
   218  	rows, err = query.ListIndex("From", nil, primary, 1, db.ListASC)
   219  	assert.Nil(t, err)
   220  	assert.Equal(t, 1, len(rows))
   221  	assert.Equal(t, true, proto.Equal(tx4, rows[0].Data))
   222  	//prefix + primary
   223  	rows, err = query.ListIndex("From", []byte(addr2[0:10]), primary, 0, db.ListASC)
   224  	assert.Nil(t, err)
   225  	assert.Equal(t, 1, len(rows))
   226  	assert.Equal(t, true, proto.Equal(tx4, rows[0].Data))
   227  	rows, err = query.ListIndex("From", []byte(addr1[0:10]), primary, 0, db.ListASC)
   228  	assert.Equal(t, types.ErrNotFound, err)
   229  	assert.Equal(t, 0, len(rows))
   230  	//ListPrimary all
   231  	rows, err = query.ListIndex("", nil, nil, 0, db.ListASC)
   232  	assert.Nil(t, err)
   233  	assert.Equal(t, 4, len(rows))
   234  
   235  	primary = rows[0].Primary
   236  	rows, err = query.ListIndex("", primary, nil, 0, db.ListASC)
   237  	assert.Nil(t, err)
   238  	assert.Equal(t, 1, len(rows))
   239  
   240  	rows, err = query.ListIndex("", nil, primary, 0, db.ListASC)
   241  	assert.Nil(t, err)
   242  	assert.Equal(t, 3, len(rows))
   243  }
   244  
   245  func TestRow(t *testing.T) {
   246  	cfg := types.NewTuringchainConfig(types.GetDefaultCfgstring())
   247  	rowmeta := NewTransactionRow()
   248  	row := rowmeta.CreateRow()
   249  	_, priv := util.Genaddress()
   250  	tx1 := util.CreateNoneTx(cfg, priv)
   251  	row.Data = tx1
   252  	row.Primary = tx1.Hash()
   253  	data, err := row.Encode()
   254  	assert.Nil(t, err)
   255  	primary, protodata, err := DecodeRow(data)
   256  	assert.Nil(t, err)
   257  	assert.Equal(t, primary, row.Primary)
   258  	var tx types.Transaction
   259  	err = types.Decode(protodata, &tx)
   260  	assert.Nil(t, err)
   261  	assert.Equal(t, proto.Equal(&tx, tx1), true)
   262  }
   263  
   264  func TestDel(t *testing.T) {
   265  	dir, ldb, kvdb := util.CreateTestDB()
   266  	defer util.CloseTestDB(dir, ldb)
   267  	opt := &Option{
   268  		Prefix:  "prefix",
   269  		Name:    "name",
   270  		Primary: "Hash",
   271  		Index:   []string{"From", "To"},
   272  	}
   273  	cfg := types.NewTuringchainConfig(types.GetDefaultCfgstring())
   274  	table, err := NewTable(NewTransactionRow(), kvdb, opt)
   275  	assert.Nil(t, err)
   276  	addr1, priv := util.Genaddress()
   277  	tx1 := util.CreateNoneTx(cfg, priv)
   278  	err = table.Add(tx1)
   279  	assert.Nil(t, err)
   280  
   281  	_, priv = util.Genaddress()
   282  	tx2 := util.CreateNoneTx(cfg, priv)
   283  	err = table.Add(tx2)
   284  	assert.Nil(t, err)
   285  
   286  	//删除掉一个
   287  	err = table.Del(tx1.Hash())
   288  	assert.Nil(t, err)
   289  
   290  	//save 然后从列表中读取
   291  	kvs, err := table.Save()
   292  	assert.Nil(t, err)
   293  	assert.Equal(t, 3, len(kvs))
   294  	//save to database
   295  	util.SaveKVList(ldb, kvs)
   296  	//printKV(kvs)
   297  	query := table.GetQuery(kvdb)
   298  	rows, err := query.ListIndex("From", []byte(addr1[0:10]), nil, 0, 0)
   299  	assert.Equal(t, types.ErrNotFound, err)
   300  	assert.Equal(t, 0, len(rows))
   301  }
   302  
   303  func TestUpdate(t *testing.T) {
   304  	dir, ldb, kvdb := util.CreateTestDB()
   305  	defer util.CloseTestDB(dir, ldb)
   306  	opt := &Option{
   307  		Prefix:  "prefix",
   308  		Name:    "name",
   309  		Primary: "Hash",
   310  		Index:   []string{"From", "To"},
   311  	}
   312  	cfg := types.NewTuringchainConfig(types.GetDefaultCfgstring())
   313  	table, err := NewTable(NewTransactionRow(), kvdb, opt)
   314  	assert.Nil(t, err)
   315  	_, priv := util.Genaddress()
   316  	tx1 := util.CreateNoneTx(cfg, priv)
   317  	err = table.Add(tx1)
   318  	assert.Nil(t, err)
   319  
   320  	err = table.Update([]byte("hello"), tx1)
   321  	assert.Equal(t, err, types.ErrInvalidParam)
   322  
   323  	tx1.Signature = nil
   324  	err = table.Update(tx1.Hash(), tx1)
   325  	assert.Nil(t, err)
   326  	kvs, err := table.Save()
   327  	assert.Nil(t, err)
   328  	assert.Equal(t, len(kvs), 3)
   329  	//save to database
   330  	util.SaveKVList(ldb, kvs)
   331  	query := table.GetQuery(kvdb)
   332  	rows, err := query.ListIndex("From", []byte(tx1.From()), nil, 0, 0)
   333  	assert.Nil(t, err)
   334  	assert.Equal(t, rows[0].Data.(*types.Transaction).From(), tx1.From())
   335  }
   336  
   337  func TestReplaceTwice(t *testing.T) {
   338  	dir, ldb, kvdb := util.CreateTestDB()
   339  	defer util.CloseTestDB(dir, ldb)
   340  	opt := &Option{
   341  		Prefix:  "prefix-hello",
   342  		Name:    "name",
   343  		Primary: "Hash",
   344  		Index:   []string{"From", "To"},
   345  	}
   346  	cfg := types.NewTuringchainConfig(types.GetDefaultCfgstring())
   347  	table, err := NewTable(NewTransactionRow(), kvdb, opt)
   348  	assert.Nil(t, err)
   349  	addr1, priv := util.Genaddress()
   350  	tx1 := util.CreateNoneTx(cfg, priv)
   351  	err = table.Add(tx1)
   352  	assert.Nil(t, err)
   353  
   354  	//修改sign的内容不改变hash,但是会改变from 值,这个时候,应该是from 做了修改,而不是产生两条记录
   355  	tx2 := types.Clone(tx1).(*types.Transaction)
   356  	tx2.Signature.Pubkey[16] = tx2.Signature.Pubkey[16] + 1
   357  	assert.Equal(t, tx1.From(), addr1)
   358  	assert.Equal(t, tx1.Hash(), tx2.Hash())
   359  
   360  	err = table.Replace(tx2)
   361  	assert.Nil(t, err)
   362  
   363  	//修改sign的内容不改变hash,但是会改变from 值,这个时候,应该是from 做了修改,而不是产生两条记录
   364  	tx3 := types.Clone(tx1).(*types.Transaction)
   365  	tx3.Signature.Pubkey[10] = tx3.Signature.Pubkey[10] + 1
   366  	assert.Equal(t, tx1.From(), addr1)
   367  	assert.Equal(t, tx1.Hash(), tx2.Hash())
   368  	assert.Equal(t, tx1.Hash(), tx3.Hash())
   369  
   370  	err = table.Replace(tx3)
   371  	assert.Nil(t, err)
   372  	//save 然后从列表中读取
   373  	kvs, err := table.Save()
   374  	assert.Nil(t, err)
   375  	util.SaveKVList(ldb, kvs)
   376  	query := table.GetQuery(kvdb)
   377  	_, err = query.ListIndex("From", []byte(tx2.From()), nil, 0, 0)
   378  	assert.Equal(t, err, types.ErrNotFound)
   379  }
   380  
   381  func TestReplace(t *testing.T) {
   382  	dir, ldb, kvdb := util.CreateTestDB()
   383  	defer util.CloseTestDB(dir, ldb)
   384  	opt := &Option{
   385  		Prefix:  "prefix-hello",
   386  		Name:    "name",
   387  		Primary: "Hash",
   388  		Index:   []string{"From", "To"},
   389  	}
   390  	cfg := types.NewTuringchainConfig(types.GetDefaultCfgstring())
   391  	table, err := NewTable(NewTransactionRow(), kvdb, opt)
   392  	assert.Nil(t, err)
   393  	addr1, priv := util.Genaddress()
   394  	tx1 := util.CreateNoneTx(cfg, priv)
   395  	err = table.Add(tx1)
   396  	assert.Nil(t, err)
   397  
   398  	err = table.Add(tx1)
   399  	assert.Equal(t, err, ErrDupPrimaryKey)
   400  
   401  	//不改变hash,改变签名
   402  	tx2 := *tx1
   403  	tx2.Signature = nil
   404  	err = table.Replace(&tx2)
   405  	assert.Nil(t, err)
   406  	//save 然后从列表中读取
   407  	kvs, err := table.Save()
   408  	assert.Nil(t, err)
   409  	assert.Equal(t, 3, len(kvs))
   410  	//save to database
   411  	util.SaveKVList(ldb, kvs)
   412  	query := table.GetQuery(kvdb)
   413  	_, err = query.ListIndex("From", []byte(addr1[0:10]), nil, 0, 0)
   414  	assert.Equal(t, err, types.ErrNotFound)
   415  
   416  	rows, err := query.ListIndex("From", []byte(tx2.From()), nil, 0, 0)
   417  	assert.Nil(t, err)
   418  	assert.Equal(t, rows[0].Data.(*types.Transaction).From(), tx2.From())
   419  }
   420  
   421  type TransactionRow struct {
   422  	*types.Transaction
   423  }
   424  
   425  func NewTransactionRow() *TransactionRow {
   426  	return &TransactionRow{Transaction: &types.Transaction{}}
   427  }
   428  
   429  func (tx *TransactionRow) CreateRow() *Row {
   430  	return &Row{Data: &types.Transaction{}}
   431  }
   432  
   433  func (tx *TransactionRow) SetPayload(data types.Message) error {
   434  	if txdata, ok := data.(*types.Transaction); ok {
   435  		tx.Transaction = txdata
   436  		return nil
   437  	}
   438  	return types.ErrTypeAsset
   439  }
   440  
   441  func (tx *TransactionRow) Get(key string) ([]byte, error) {
   442  	if key == "Hash" {
   443  		return tx.Hash(), nil
   444  	} else if key == "From" {
   445  		return []byte(tx.From()), nil
   446  	} else if key == "To" {
   447  		return []byte(tx.To), nil
   448  	}
   449  	return nil, types.ErrNotFound
   450  }