--- /dev/null
+package database
+
+import (
+ "os"
+ "testing"
+
+ dbm "github.com/vapor/database/leveldb"
+ "github.com/vapor/database/storage"
+ "github.com/vapor/protocol/bc"
+ "github.com/vapor/protocol/state"
+ "github.com/vapor/testutil"
+)
+
+func TestSaveUtxoView(t *testing.T) {
+ testDB := dbm.NewDB("testdb", "leveldb", "temp")
+ batch := testDB.NewBatch()
+ defer func() {
+ testDB.Close()
+ os.RemoveAll("temp")
+ }()
+
+ cases := []struct {
+ hash bc.Hash
+ utxoEntry *storage.UtxoEntry
+ exist bool
+ }{
+ {
+ hash: bc.Hash{V0: 0},
+ utxoEntry: storage.NewUtxoEntry(storage.CoinbaseUTXOType, 0, true),
+ exist: true,
+ },
+ {
+ hash: bc.Hash{V0: 1},
+ utxoEntry: storage.NewUtxoEntry(storage.CoinbaseUTXOType, 0, false),
+ exist: true,
+ },
+ {
+ hash: bc.Hash{V0: 2},
+ utxoEntry: storage.NewUtxoEntry(storage.NormalUTXOType, 0, false),
+ exist: true,
+ },
+ {
+ hash: bc.Hash{V0: 3},
+ utxoEntry: storage.NewUtxoEntry(storage.NormalUTXOType, 0, true),
+ exist: false,
+ },
+ {
+ hash: bc.Hash{V0: 4},
+ utxoEntry: storage.NewUtxoEntry(storage.CrosschainUTXOType, 0, true),
+ exist: true,
+ },
+ {
+ hash: bc.Hash{V0: 5},
+ utxoEntry: storage.NewUtxoEntry(storage.CrosschainUTXOType, 0, false),
+ exist: false,
+ },
+ {
+ hash: bc.Hash{V0: 6},
+ utxoEntry: storage.NewUtxoEntry(storage.VoteUTXOType, 0, true),
+ exist: false,
+ },
+ {
+ hash: bc.Hash{V0: 7},
+ utxoEntry: storage.NewUtxoEntry(storage.VoteUTXOType, 0, false),
+ exist: true,
+ },
+ }
+
+ view := state.NewUtxoViewpoint()
+ for _, c := range cases {
+ view.Entries[c.hash] = c.utxoEntry
+ }
+
+ saveUtxoView(batch, view)
+ batch.Write()
+
+ for _, c := range cases {
+ entry, err := getUtxo(testDB, &c.hash)
+
+ if !c.exist {
+ if err == nil {
+ t.Errorf("%v should be unexisted, but it's in the db", c)
+ }
+ continue
+ }
+
+ if !testutil.DeepEqual(entry, c.utxoEntry) {
+ t.Errorf("%v utxo in the db isn't match", c)
+ }
+ }
+}
+
+func TestGetTransactionsUtxo(t *testing.T) {
+ testDB := dbm.NewDB("testdb", "leveldb", "temp")
+ defer os.RemoveAll("temp")
+
+ batch := testDB.NewBatch()
+ inputView := state.NewUtxoViewpoint()
+ for i := 0; i <= 2; i++ {
+ inputView.Entries[bc.Hash{V0: uint64(i)}] = storage.NewUtxoEntry(storage.NormalUTXOType, uint64(i), false)
+ }
+ saveUtxoView(batch, inputView)
+ batch.Write()
+
+ cases := []struct {
+ txs []*bc.Tx
+ inputView *state.UtxoViewpoint
+ fetchView *state.UtxoViewpoint
+ err bool
+ }{
+
+ {
+ txs: []*bc.Tx{
+ &bc.Tx{
+ SpentOutputIDs: []bc.Hash{bc.Hash{V0: 10}},
+ },
+ },
+ inputView: state.NewUtxoViewpoint(),
+ fetchView: state.NewUtxoViewpoint(),
+ err: false,
+ },
+ {
+ txs: []*bc.Tx{
+ &bc.Tx{
+ SpentOutputIDs: []bc.Hash{bc.Hash{V0: 0}},
+ },
+ },
+ inputView: state.NewUtxoViewpoint(),
+ fetchView: &state.UtxoViewpoint{
+ Entries: map[bc.Hash]*storage.UtxoEntry{
+ bc.Hash{V0: 0}: storage.NewUtxoEntry(storage.NormalUTXOType, 0, false),
+ },
+ },
+ err: false,
+ },
+ {
+ txs: []*bc.Tx{
+ &bc.Tx{
+ SpentOutputIDs: []bc.Hash{
+ bc.Hash{V0: 0},
+ bc.Hash{V0: 1},
+ },
+ },
+ },
+ inputView: state.NewUtxoViewpoint(),
+ fetchView: &state.UtxoViewpoint{
+ Entries: map[bc.Hash]*storage.UtxoEntry{
+ bc.Hash{V0: 0}: storage.NewUtxoEntry(storage.NormalUTXOType, 0, false),
+ bc.Hash{V0: 1}: storage.NewUtxoEntry(storage.NormalUTXOType, 1, false),
+ },
+ },
+ err: false,
+ },
+ {
+ txs: []*bc.Tx{
+ &bc.Tx{
+ SpentOutputIDs: []bc.Hash{
+ bc.Hash{V0: 0},
+ bc.Hash{V0: 1},
+ },
+ },
+ &bc.Tx{
+ SpentOutputIDs: []bc.Hash{
+ bc.Hash{V0: 2},
+ },
+ },
+ },
+ inputView: state.NewUtxoViewpoint(),
+ fetchView: &state.UtxoViewpoint{
+ Entries: map[bc.Hash]*storage.UtxoEntry{
+ bc.Hash{V0: 0}: storage.NewUtxoEntry(storage.NormalUTXOType, 0, false),
+ bc.Hash{V0: 1}: storage.NewUtxoEntry(storage.NormalUTXOType, 1, false),
+ bc.Hash{V0: 2}: storage.NewUtxoEntry(storage.NormalUTXOType, 2, false),
+ },
+ },
+ err: false,
+ },
+ {
+ txs: []*bc.Tx{
+ &bc.Tx{
+ SpentOutputIDs: []bc.Hash{bc.Hash{V0: 0}},
+ },
+ },
+ inputView: &state.UtxoViewpoint{
+ Entries: map[bc.Hash]*storage.UtxoEntry{
+ bc.Hash{V0: 0}: storage.NewUtxoEntry(storage.NormalUTXOType, 1, false),
+ },
+ },
+ fetchView: &state.UtxoViewpoint{
+ Entries: map[bc.Hash]*storage.UtxoEntry{
+ bc.Hash{V0: 0}: storage.NewUtxoEntry(storage.NormalUTXOType, 1, false),
+ },
+ },
+ err: false,
+ },
+ }
+
+ for i, c := range cases {
+ if err := getTransactionsUtxo(testDB, c.inputView, c.txs); c.err != (err != nil) {
+ t.Errorf("test case %d, want err = %v, get err = %v", i, c.err, err)
+ }
+ if !testutil.DeepEqual(c.inputView, c.fetchView) {
+ t.Errorf("test case %d, want %v, get %v", i, c.fetchView, c.inputView)
+ }
+ }
+}