Write state diff to CSV #2
@ -1,13 +0,0 @@
|
|||||||
package builder_test
|
|
||||||
|
|
||||||
import (
|
|
||||||
"testing"
|
|
||||||
|
|
||||||
. "github.com/onsi/ginkgo"
|
|
||||||
. "github.com/onsi/gomega"
|
|
||||||
)
|
|
||||||
|
|
||||||
func TestBuilder(t *testing.T) {
|
|
||||||
RegisterFailHandler(Fail)
|
|
||||||
RunSpecs(t, "Builder Suite")
|
|
||||||
}
|
|
@ -1,36 +1,18 @@
|
|||||||
// Copyright 2015 The go-ethereum Authors
|
|
||||||
// This file is part of the go-ethereum library.
|
|
||||||
//
|
|
||||||
// The go-ethereum library is free software: you can redistribute it and/or modify
|
|
||||||
// it under the terms of the GNU Lesser General Public License as published by
|
|
||||||
// the Free Software Foundation, either version 3 of the License, or
|
|
||||||
// (at your option) any later version.
|
|
||||||
//
|
|
||||||
// The go-ethereum library is distributed in the hope that it will be useful,
|
|
||||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
||||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
||||||
// GNU Lesser General Public License for more details.
|
|
||||||
//
|
|
||||||
// You should have received a copy of the GNU Lesser General Public License
|
|
||||||
// along with the go-ethereum library. If not, see <http://www.gnu.org/licenses/>.
|
|
||||||
|
|
||||||
// Contains a batch of utility type declarations used by the tests. As the node
|
|
||||||
// operates on unique types, a lot of them are needed to check various features.
|
|
||||||
|
|
||||||
package builder_test
|
package builder_test
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"github.com/ethereum/go-ethereum/common"
|
"testing"
|
||||||
"github.com/ethereum/go-ethereum/consensus/ethash"
|
|
||||||
"github.com/ethereum/go-ethereum/core"
|
|
||||||
"github.com/ethereum/go-ethereum/core/types"
|
|
||||||
"github.com/ethereum/go-ethereum/crypto"
|
|
||||||
"github.com/ethereum/go-ethereum/ethdb"
|
|
||||||
"github.com/ethereum/go-ethereum/params"
|
|
||||||
b "github.com/ethereum/go-ethereum/statediff/builder"
|
|
||||||
"github.com/onsi/ginkgo"
|
|
||||||
"github.com/onsi/gomega"
|
|
||||||
"math/big"
|
"math/big"
|
||||||
|
"github.com/ethereum/go-ethereum/ethdb"
|
||||||
|
"github.com/ethereum/go-ethereum/crypto"
|
||||||
|
"github.com/ethereum/go-ethereum/core"
|
||||||
|
"github.com/ethereum/go-ethereum/common"
|
||||||
|
b "github.com/ethereum/go-ethereum/statediff/builder"
|
||||||
|
"github.com/ethereum/go-ethereum/core/types"
|
||||||
|
"github.com/ethereum/go-ethereum/params"
|
||||||
|
"github.com/ethereum/go-ethereum/consensus/ethash"
|
||||||
|
"bytes"
|
||||||
|
"reflect"
|
||||||
)
|
)
|
||||||
|
|
||||||
var (
|
var (
|
||||||
@ -116,204 +98,205 @@ func testChainGen(i int, block *core.BlockGen) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
var _ = ginkgo.Describe("", func() {
|
var (
|
||||||
|
block0Hash, block1Hash, block2Hash, block3Hash common.Hash
|
||||||
|
block0, block1, block2, block3 *types.Block
|
||||||
|
builder b.Builder
|
||||||
|
miningReward = int64(3000000000000000000)
|
||||||
|
burnAddress = common.HexToAddress("0x0")
|
||||||
|
diff *b.StateDiff
|
||||||
|
err error
|
||||||
|
)
|
||||||
|
|
||||||
|
func TestBuilder(t *testing.T) {
|
||||||
|
_, blocks := makeChain(3, 0, genesis)
|
||||||
|
block0Hash = common.HexToHash("0xd1721cfd0b29c36fd7a68f25c128e86413fb666a6e1d68e89b875bd299262661")
|
||||||
|
block1Hash = common.HexToHash("0x47c398dd688eaa4dd11b006888156783fe32df83d59b197c0fcd303408103d39")
|
||||||
|
block2Hash = common.HexToHash("0x351b2f531838683ba457e8ca4d3a844cc48147dceafbcb589dc6e3227856ee75")
|
||||||
|
block3Hash = common.HexToHash("0xfa40fbe2d98d98b3363a778d52f2bcd29d6790b9b3f3cab2b167fd12d3550f73")
|
||||||
|
|
||||||
|
block0 = blocks[block0Hash]
|
||||||
|
block1 = blocks[block1Hash]
|
||||||
|
block2 = blocks[block2Hash]
|
||||||
|
block3 = blocks[block3Hash]
|
||||||
|
builder = b.NewBuilder(testdb)
|
||||||
|
|
||||||
|
testEmptyDiff(t)
|
||||||
|
testBlock1(t)
|
||||||
|
testBlock2(t)
|
||||||
|
testBlock3(t)
|
||||||
|
}
|
||||||
|
|
||||||
|
var errorString = "Actual and expected do not match"
|
||||||
|
|
||||||
|
func testEmptyDiff(t *testing.T) {
|
||||||
|
expectedDiff := b.StateDiff{
|
||||||
|
BlockNumber: block0.Number().Int64(),
|
||||||
|
BlockHash: block0Hash,
|
||||||
|
CreatedAccounts: emptyAccountDiffEventualMap,
|
||||||
|
DeletedAccounts: emptyAccountDiffEventualMap,
|
||||||
|
UpdatedAccounts: emptyAccountDiffIncrementalMap,
|
||||||
|
}
|
||||||
|
|
||||||
|
diff, err := builder.BuildStateDiff(block0.Root(), block0.Root(), block0.Number().Int64(), block0Hash)
|
||||||
|
if err != nil {
|
||||||
|
t.Error(err)
|
||||||
|
}
|
||||||
|
|
||||||
|
if !equals(diff, &expectedDiff) {
|
||||||
|
t.Errorf("Actual and expected do not match:\nActual: %+v\nExpected: %+v", diff, expectedDiff)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func testBlock1(t *testing.T) {
|
||||||
|
//10000 transferred from testBankAddress to account1Addr
|
||||||
|
var balanceChange = int64(10000)
|
||||||
|
|
||||||
|
diff, err = builder.BuildStateDiff(block0.Root(), block1.Root(), block1.Number().Int64(), block1Hash)
|
||||||
|
if err != nil {
|
||||||
|
t.Error(err)
|
||||||
|
}
|
||||||
|
|
||||||
|
//it includes the block number and hash
|
||||||
|
if !equals(diff.BlockNumber, block1.Number().Int64()) { t.Errorf(errorString) }
|
||||||
|
if !equals(diff.BlockHash, block1Hash) { t.Errorf(errorString)}
|
||||||
|
|
||||||
|
//it returns an empty collection for deleted accounts
|
||||||
|
if !equals(diff.DeletedAccounts, emptyAccountDiffEventualMap) { t.Errorf(errorString)}
|
||||||
|
|
||||||
|
//it returns balance diffs for updated accounts
|
||||||
|
expectedBankBalanceDiff := b.DiffBigInt{
|
||||||
|
NewValue: big.NewInt(testBankFunds.Int64() - balanceChange),
|
||||||
|
OldValue: testBankFunds,
|
||||||
|
}
|
||||||
|
|
||||||
|
if !equals(len(diff.UpdatedAccounts), 1) { t.Errorf(errorString) }
|
||||||
|
if !equals(diff.UpdatedAccounts[testBankAddress].Balance, expectedBankBalanceDiff) { t.Errorf(errorString) }
|
||||||
|
|
||||||
|
//it returns balance diffs for new accounts
|
||||||
|
expectedAccount1BalanceDiff := b.DiffBigInt{
|
||||||
|
NewValue: big.NewInt(balanceChange),
|
||||||
|
OldValue: nil,
|
||||||
|
}
|
||||||
|
|
||||||
|
expectedBurnAddrBalanceDiff := b.DiffBigInt{
|
||||||
|
NewValue: big.NewInt(miningReward),
|
||||||
|
OldValue: nil,
|
||||||
|
}
|
||||||
|
|
||||||
|
if !equals(len(diff.CreatedAccounts), 2) {}
|
||||||
|
if !equals(diff.CreatedAccounts[account1Addr].Balance, expectedAccount1BalanceDiff) { t.Errorf(errorString) }
|
||||||
|
if !equals(diff.CreatedAccounts[burnAddress].Balance, expectedBurnAddrBalanceDiff) { t.Errorf(errorString) }
|
||||||
|
}
|
||||||
|
|
||||||
|
func testBlock2(t *testing.T) {
|
||||||
|
//1000 transferred from testBankAddress to account1Addr
|
||||||
|
//1000 transferred from account1Addr to account2Addr
|
||||||
var (
|
var (
|
||||||
block0Hash, block1Hash, block2Hash, block3Hash common.Hash
|
balanceChange = int64(1000)
|
||||||
block0, block1, block2, block3 *types.Block
|
block1BankBalance = int64(99990000)
|
||||||
builder b.Builder
|
block1Account1Balance = int64(10000)
|
||||||
miningReward = int64(3000000000000000000)
|
|
||||||
burnAddress = common.HexToAddress("0x0")
|
|
||||||
diff *b.StateDiff
|
|
||||||
err error
|
|
||||||
)
|
)
|
||||||
|
|
||||||
ginkgo.BeforeEach(func() {
|
diff, err = builder.BuildStateDiff(block1.Root(), block2.Root(), block2.Number().Int64(), block2Hash)
|
||||||
_, blocks := makeChain(3, 0, genesis)
|
if err != nil {
|
||||||
block0Hash = common.HexToHash("0xd1721cfd0b29c36fd7a68f25c128e86413fb666a6e1d68e89b875bd299262661")
|
t.Error(err)
|
||||||
block1Hash = common.HexToHash("0x47c398dd688eaa4dd11b006888156783fe32df83d59b197c0fcd303408103d39")
|
}
|
||||||
block2Hash = common.HexToHash("0x351b2f531838683ba457e8ca4d3a844cc48147dceafbcb589dc6e3227856ee75")
|
//it includes the block number and hash
|
||||||
block3Hash = common.HexToHash("0xfa40fbe2d98d98b3363a778d52f2bcd29d6790b9b3f3cab2b167fd12d3550f73")
|
if !equals(diff.BlockNumber, block2.Number().Int64()) { t.Errorf(errorString)}
|
||||||
|
if !equals(diff.BlockHash, block2Hash) {}
|
||||||
|
|
||||||
block0 = blocks[block0Hash]
|
//it returns an empty collection for deleted accounts
|
||||||
block1 = blocks[block1Hash]
|
if !equals(diff.DeletedAccounts, emptyAccountDiffEventualMap) { t.Errorf(errorString) }
|
||||||
block2 = blocks[block2Hash]
|
|
||||||
block3 = blocks[block3Hash]
|
|
||||||
builder = b.NewBuilder(testdb)
|
|
||||||
})
|
|
||||||
|
|
||||||
ginkgo.It("returns empty account diff collections when the state root hasn't changed", func() {
|
//it returns balance diffs for updated accounts
|
||||||
expectedDiff := b.StateDiff{
|
expectedBankBalanceDiff := b.DiffBigInt{
|
||||||
BlockNumber: block0.Number().Int64(),
|
NewValue: big.NewInt(block1BankBalance - balanceChange),
|
||||||
BlockHash: block0Hash,
|
OldValue: big.NewInt(block1BankBalance),
|
||||||
CreatedAccounts: emptyAccountDiffEventualMap,
|
}
|
||||||
DeletedAccounts: emptyAccountDiffEventualMap,
|
|
||||||
UpdatedAccounts: emptyAccountDiffIncrementalMap,
|
expectedAccount1BalanceDiff := b.DiffBigInt{
|
||||||
|
NewValue: big.NewInt(block1Account1Balance - balanceChange + balanceChange),
|
||||||
|
OldValue: big.NewInt(block1Account1Balance),
|
||||||
|
}
|
||||||
|
|
||||||
|
expectedBurnBalanceDiff := b.DiffBigInt{
|
||||||
|
NewValue: big.NewInt(miningReward + miningReward),
|
||||||
|
OldValue: big.NewInt(miningReward),
|
||||||
|
}
|
||||||
|
|
||||||
|
if !equals(len(diff.UpdatedAccounts), 3) { t.Errorf(errorString) }
|
||||||
|
if !equals(diff.UpdatedAccounts[testBankAddress].Balance, expectedBankBalanceDiff) { t.Errorf(errorString) }
|
||||||
|
if !equals(diff.UpdatedAccounts[account1Addr].Balance, expectedAccount1BalanceDiff) { t.Errorf(errorString) }
|
||||||
|
if !equals(diff.UpdatedAccounts[burnAddress].Balance, expectedBurnBalanceDiff) { t.Errorf(errorString) }
|
||||||
|
|
||||||
|
//it returns balance diffs for new accounts
|
||||||
|
expectedAccount2BalanceDiff := b.DiffBigInt{
|
||||||
|
NewValue: big.NewInt(balanceChange),
|
||||||
|
OldValue: nil,
|
||||||
|
}
|
||||||
|
|
||||||
|
expectedContractBalanceDiff := b.DiffBigInt{
|
||||||
|
NewValue: big.NewInt(0),
|
||||||
|
OldValue: nil,
|
||||||
|
}
|
||||||
|
|
||||||
|
if !equals(len(diff.CreatedAccounts), 2) { t.Errorf(errorString) }
|
||||||
|
if !equals(diff.CreatedAccounts[account2Addr].Balance, expectedAccount2BalanceDiff) { t.Errorf(errorString) }
|
||||||
|
if !equals(diff.CreatedAccounts[contractAddr].Balance, expectedContractBalanceDiff) { t.Errorf(errorString) }
|
||||||
|
}
|
||||||
|
|
||||||
|
func testBlock3(t *testing.T) {
|
||||||
|
diff, err = builder.BuildStateDiff(block2.Root(), block3.Root(), block3.Number().Int64(), block3Hash)
|
||||||
|
if err != nil {
|
||||||
|
t.Error(err)
|
||||||
|
}
|
||||||
|
|
||||||
|
//it includes the block number and hash
|
||||||
|
if !equals(diff.BlockNumber, block3.Number().Int64()) { t.Errorf(errorString) }
|
||||||
|
if !equals(diff.BlockHash, block3Hash) { t.Errorf(errorString) }
|
||||||
|
|
||||||
|
//it returns an empty collection for deleted accounts
|
||||||
|
if !equals(diff.DeletedAccounts, emptyAccountDiffEventualMap) { t.Errorf(errorString) }
|
||||||
|
|
||||||
|
//it returns an empty collection for created accounts
|
||||||
|
if !equals(diff.CreatedAccounts, emptyAccountDiffEventualMap) { t.Errorf(errorString) }
|
||||||
|
|
||||||
|
//it returns balance, storage and nonce diffs for updated accounts
|
||||||
|
block2Account2Balance := int64(1000)
|
||||||
|
expectedAcct2BalanceDiff := b.DiffBigInt{
|
||||||
|
NewValue: big.NewInt(block2Account2Balance + miningReward),
|
||||||
|
OldValue: big.NewInt(block2Account2Balance),
|
||||||
}
|
}
|
||||||
|
|
||||||
diff, err := builder.BuildStateDiff(block0.Root(), block0.Root(), block0.Number().Int64(), block0Hash)
|
expectedContractStorageDiff := make(map[string]b.DiffString)
|
||||||
|
newVal := "0x03"
|
||||||
|
oldVal := "0x0"
|
||||||
|
path := "0x405787fa12a823e0f2b7631cc41b3ba8828b3321ca811111fa75cd3aa3bb5ace"
|
||||||
|
expectedContractStorageDiff[path] = b.DiffString{
|
||||||
|
NewValue: &newVal,
|
||||||
|
OldValue: &oldVal,
|
||||||
|
}
|
||||||
|
|
||||||
gomega.Expect(err).NotTo(gomega.HaveOccurred())
|
oldNonce := uint64(2)
|
||||||
gomega.Expect(diff).To(gomega.Equal(&expectedDiff))
|
newNonce := uint64(3)
|
||||||
})
|
expectedBankNonceDiff := b.DiffUint64{
|
||||||
|
NewValue: &newNonce,
|
||||||
|
OldValue: &oldNonce,
|
||||||
|
}
|
||||||
|
|
||||||
ginkgo.Context("Block 1", func() {
|
if !equals(len(diff.UpdatedAccounts), 3) { t.Errorf(errorString) }
|
||||||
//10000 transferred from testBankAddress to account1Addr
|
if !equals(diff.UpdatedAccounts[account2Addr].Balance, expectedAcct2BalanceDiff) { t.Errorf(errorString) }
|
||||||
var balanceChange = int64(10000)
|
if !equals(diff.UpdatedAccounts[contractAddr].Storage, expectedContractStorageDiff) { t.Errorf(errorString) }
|
||||||
|
if !equals(diff.UpdatedAccounts[testBankAddress].Nonce, expectedBankNonceDiff) { t.Errorf(errorString) }
|
||||||
|
}
|
||||||
|
|
||||||
ginkgo.BeforeEach(func() {
|
func equals(actual, expected interface{}) (success bool) {
|
||||||
diff, err = builder.BuildStateDiff(block0.Root(), block1.Root(), block1.Number().Int64(), block1Hash)
|
if actualByteSlice, ok := actual.([]byte); ok {
|
||||||
|
if expectedByteSlice, ok := expected.([]byte); ok {
|
||||||
|
return bytes.Equal(actualByteSlice, expectedByteSlice)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
gomega.Expect(err).NotTo(gomega.HaveOccurred())
|
return reflect.DeepEqual(actual, expected)
|
||||||
})
|
}
|
||||||
|
|
||||||
ginkgo.It("includes the block number and hash", func() {
|
|
||||||
gomega.Expect(diff.BlockNumber).To(gomega.Equal(block1.Number().Int64()))
|
|
||||||
gomega.Expect(diff.BlockHash).To(gomega.Equal(block1Hash))
|
|
||||||
})
|
|
||||||
|
|
||||||
ginkgo.It("returns an empty collection for deleted accounts", func() {
|
|
||||||
gomega.Expect(diff.DeletedAccounts).To(gomega.Equal(emptyAccountDiffEventualMap))
|
|
||||||
})
|
|
||||||
|
|
||||||
ginkgo.It("returns balance diffs for updated accounts", func() {
|
|
||||||
expectedBankBalanceDiff := b.DiffBigInt{
|
|
||||||
NewValue: big.NewInt(testBankFunds.Int64() - balanceChange),
|
|
||||||
OldValue: testBankFunds,
|
|
||||||
}
|
|
||||||
|
|
||||||
gomega.Expect(len(diff.UpdatedAccounts)).To(gomega.Equal(1))
|
|
||||||
gomega.Expect(diff.UpdatedAccounts[testBankAddress].Balance).To(gomega.Equal(expectedBankBalanceDiff))
|
|
||||||
})
|
|
||||||
|
|
||||||
ginkgo.It("returns balance diffs for new accounts", func() {
|
|
||||||
expectedAccount1BalanceDiff := b.DiffBigInt{
|
|
||||||
NewValue: big.NewInt(balanceChange),
|
|
||||||
OldValue: nil,
|
|
||||||
}
|
|
||||||
|
|
||||||
expectedBurnAddrBalanceDiff := b.DiffBigInt{
|
|
||||||
NewValue: big.NewInt(miningReward),
|
|
||||||
OldValue: nil,
|
|
||||||
}
|
|
||||||
|
|
||||||
gomega.Expect(len(diff.CreatedAccounts)).To(gomega.Equal(2))
|
|
||||||
gomega.Expect(diff.CreatedAccounts[account1Addr].Balance).To(gomega.Equal(expectedAccount1BalanceDiff))
|
|
||||||
gomega.Expect(diff.CreatedAccounts[burnAddress].Balance).To(gomega.Equal(expectedBurnAddrBalanceDiff))
|
|
||||||
})
|
|
||||||
})
|
|
||||||
|
|
||||||
ginkgo.Context("Block 2", func() {
|
|
||||||
//1000 transferred from testBankAddress to account1Addr
|
|
||||||
//1000 transferred from account1Addr to account2Addr
|
|
||||||
var (
|
|
||||||
balanceChange = int64(1000)
|
|
||||||
block1BankBalance = int64(99990000)
|
|
||||||
block1Account1Balance = int64(10000)
|
|
||||||
)
|
|
||||||
|
|
||||||
ginkgo.BeforeEach(func() {
|
|
||||||
diff, err = builder.BuildStateDiff(block1.Root(), block2.Root(), block2.Number().Int64(), block2Hash)
|
|
||||||
|
|
||||||
gomega.Expect(err).NotTo(gomega.HaveOccurred())
|
|
||||||
})
|
|
||||||
|
|
||||||
ginkgo.It("includes the block number and hash", func() {
|
|
||||||
gomega.Expect(diff.BlockNumber).To(gomega.Equal(block2.Number().Int64()))
|
|
||||||
gomega.Expect(diff.BlockHash).To(gomega.Equal(block2Hash))
|
|
||||||
})
|
|
||||||
|
|
||||||
ginkgo.It("returns an empty collection for deleted accounts", func() {
|
|
||||||
gomega.Expect(diff.DeletedAccounts).To(gomega.Equal(emptyAccountDiffEventualMap))
|
|
||||||
})
|
|
||||||
|
|
||||||
ginkgo.It("returns balance diffs for updated accounts", func() {
|
|
||||||
expectedBankBalanceDiff := b.DiffBigInt{
|
|
||||||
NewValue: big.NewInt(block1BankBalance - balanceChange),
|
|
||||||
OldValue: big.NewInt(block1BankBalance),
|
|
||||||
}
|
|
||||||
|
|
||||||
expectedAccount1BalanceDiff := b.DiffBigInt{
|
|
||||||
NewValue: big.NewInt(block1Account1Balance - balanceChange + balanceChange),
|
|
||||||
OldValue: big.NewInt(block1Account1Balance),
|
|
||||||
}
|
|
||||||
|
|
||||||
expectedBurnBalanceDiff := b.DiffBigInt{
|
|
||||||
NewValue: big.NewInt(miningReward + miningReward),
|
|
||||||
OldValue: big.NewInt(miningReward),
|
|
||||||
}
|
|
||||||
|
|
||||||
gomega.Expect(len(diff.UpdatedAccounts)).To(gomega.Equal(3))
|
|
||||||
gomega.Expect(diff.UpdatedAccounts[testBankAddress].Balance).To(gomega.Equal(expectedBankBalanceDiff))
|
|
||||||
gomega.Expect(diff.UpdatedAccounts[account1Addr].Balance).To(gomega.Equal(expectedAccount1BalanceDiff))
|
|
||||||
gomega.Expect(diff.UpdatedAccounts[burnAddress].Balance).To(gomega.Equal(expectedBurnBalanceDiff))
|
|
||||||
})
|
|
||||||
|
|
||||||
ginkgo.It("returns balance diffs for new accounts", func() {
|
|
||||||
expectedAccount2BalanceDiff := b.DiffBigInt{
|
|
||||||
NewValue: big.NewInt(balanceChange),
|
|
||||||
OldValue: nil,
|
|
||||||
}
|
|
||||||
|
|
||||||
expectedContractBalanceDiff := b.DiffBigInt{
|
|
||||||
NewValue: big.NewInt(0),
|
|
||||||
OldValue: nil,
|
|
||||||
}
|
|
||||||
|
|
||||||
gomega.Expect(len(diff.CreatedAccounts)).To(gomega.Equal(2))
|
|
||||||
gomega.Expect(diff.CreatedAccounts[account2Addr].Balance).To(gomega.Equal(expectedAccount2BalanceDiff))
|
|
||||||
gomega.Expect(diff.CreatedAccounts[contractAddr].Balance).To(gomega.Equal(expectedContractBalanceDiff))
|
|
||||||
})
|
|
||||||
})
|
|
||||||
|
|
||||||
ginkgo.Context("Block 3", func() {
|
|
||||||
//the contract's storage is changed
|
|
||||||
//and the block is mined by account 2
|
|
||||||
ginkgo.BeforeEach(func() {
|
|
||||||
diff, err = builder.BuildStateDiff(block2.Root(), block3.Root(), block3.Number().Int64(), block3Hash)
|
|
||||||
|
|
||||||
gomega.Expect(err).NotTo(gomega.HaveOccurred())
|
|
||||||
})
|
|
||||||
|
|
||||||
ginkgo.It("includes the block number and hash", func() {
|
|
||||||
gomega.Expect(diff.BlockNumber).To(gomega.Equal(block3.Number().Int64()))
|
|
||||||
gomega.Expect(diff.BlockHash).To(gomega.Equal(block3Hash))
|
|
||||||
})
|
|
||||||
|
|
||||||
ginkgo.It("returns an empty collection for deleted accounts", func() {
|
|
||||||
gomega.Expect(diff.DeletedAccounts).To(gomega.Equal(emptyAccountDiffEventualMap))
|
|
||||||
})
|
|
||||||
|
|
||||||
ginkgo.It("returns an empty collection for created accounts", func() {
|
|
||||||
gomega.Expect(diff.CreatedAccounts).To(gomega.Equal(emptyAccountDiffEventualMap))
|
|
||||||
})
|
|
||||||
|
|
||||||
ginkgo.It("returns balance, storage and nonce diffs for updated accounts", func() {
|
|
||||||
block2Account2Balance := int64(1000)
|
|
||||||
expectedAcct2BalanceDiff := b.DiffBigInt{
|
|
||||||
NewValue: big.NewInt(block2Account2Balance + miningReward),
|
|
||||||
OldValue: big.NewInt(block2Account2Balance),
|
|
||||||
}
|
|
||||||
|
|
||||||
expectedContractStorageDiff := make(map[string]b.DiffString)
|
|
||||||
newVal := "0x03"
|
|
||||||
oldVal := "0x0"
|
|
||||||
path := "0x405787fa12a823e0f2b7631cc41b3ba8828b3321ca811111fa75cd3aa3bb5ace"
|
|
||||||
expectedContractStorageDiff[path] = b.DiffString{
|
|
||||||
NewValue: &newVal,
|
|
||||||
OldValue: &oldVal,
|
|
||||||
}
|
|
||||||
|
|
||||||
oldNonce := uint64(2)
|
|
||||||
newNonce := uint64(3)
|
|
||||||
expectedBankNonceDiff := b.DiffUint64{
|
|
||||||
NewValue: &newNonce,
|
|
||||||
OldValue: &oldNonce,
|
|
||||||
}
|
|
||||||
|
|
||||||
gomega.Expect(len(diff.UpdatedAccounts)).To(gomega.Equal(3))
|
|
||||||
gomega.Expect(diff.UpdatedAccounts[account2Addr].Balance).To(gomega.Equal(expectedAcct2BalanceDiff))
|
|
||||||
gomega.Expect(diff.UpdatedAccounts[contractAddr].Storage).To(gomega.Equal(expectedContractStorageDiff))
|
|
||||||
gomega.Expect(diff.UpdatedAccounts[testBankAddress].Nonce).To(gomega.Equal(expectedBankNonceDiff))
|
|
||||||
})
|
|
||||||
})
|
|
||||||
})
|
|
||||||
|
@ -1,13 +0,0 @@
|
|||||||
package extractor_test
|
|
||||||
|
|
||||||
import (
|
|
||||||
"testing"
|
|
||||||
|
|
||||||
. "github.com/onsi/ginkgo"
|
|
||||||
. "github.com/onsi/gomega"
|
|
||||||
)
|
|
||||||
|
|
||||||
func TestExtractor(t *testing.T) {
|
|
||||||
RegisterFailHandler(Fail)
|
|
||||||
RunSpecs(t, "Extractor Suite")
|
|
||||||
}
|
|
@ -1,101 +1,108 @@
|
|||||||
// Copyright 2015 The go-ethereum Authors
|
|
||||||
// This file is part of the go-ethereum library.
|
|
||||||
//
|
|
||||||
// The go-ethereum library is free software: you can redistribute it and/or modify
|
|
||||||
// it under the terms of the GNU Lesser General Public License as published by
|
|
||||||
// the Free Software Foundation, either version 3 of the License, or
|
|
||||||
// (at your option) any later version.
|
|
||||||
//
|
|
||||||
// The go-ethereum library is distributed in the hope that it will be useful,
|
|
||||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
||||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
||||||
// GNU Lesser General Public License for more details.
|
|
||||||
//
|
|
||||||
// You should have received a copy of the GNU Lesser General Public License
|
|
||||||
// along with the go-ethereum library. If not, see <http://www.gnu.org/licenses/>.
|
|
||||||
|
|
||||||
// Contains a batch of utility type declarations used by the tests. As the node
|
|
||||||
// operates on unique types, a lot of them are needed to check various features.
|
|
||||||
|
|
||||||
package extractor_test
|
package extractor_test
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"github.com/ethereum/go-ethereum/core/types"
|
"testing"
|
||||||
b "github.com/ethereum/go-ethereum/statediff/builder"
|
|
||||||
e "github.com/ethereum/go-ethereum/statediff/extractor"
|
|
||||||
"github.com/ethereum/go-ethereum/statediff/testhelpers"
|
"github.com/ethereum/go-ethereum/statediff/testhelpers"
|
||||||
"github.com/onsi/ginkgo"
|
|
||||||
"github.com/onsi/gomega"
|
|
||||||
"math/big"
|
"math/big"
|
||||||
"math/rand"
|
"math/rand"
|
||||||
|
b "github.com/ethereum/go-ethereum/statediff/builder"
|
||||||
|
e "github.com/ethereum/go-ethereum/statediff/extractor"
|
||||||
|
"github.com/ethereum/go-ethereum/core/types"
|
||||||
|
"bytes"
|
||||||
|
"reflect"
|
||||||
)
|
)
|
||||||
|
|
||||||
var _ = ginkgo.Describe("Extractor", func() {
|
var publisher testhelpers.MockPublisher
|
||||||
var publisher testhelpers.MockPublisher
|
var builder testhelpers.MockBuilder
|
||||||
var builder testhelpers.MockBuilder
|
var currentBlockNumber *big.Int
|
||||||
var currentBlockNumber *big.Int
|
var parentBlock, currentBlock *types.Block
|
||||||
var parentBlock, currentBlock *types.Block
|
var expectedStateDiff b.StateDiff
|
||||||
var expectedStateDiff b.StateDiff
|
var extractor e.Extractor
|
||||||
var extractor e.Extractor
|
var err error
|
||||||
var err error
|
|
||||||
|
|
||||||
ginkgo.BeforeEach(func() {
|
func TestExtractor(t *testing.T) {
|
||||||
publisher = testhelpers.MockPublisher{}
|
publisher = testhelpers.MockPublisher{}
|
||||||
builder = testhelpers.MockBuilder{}
|
builder = testhelpers.MockBuilder{}
|
||||||
extractor, err = e.NewExtractor(&builder, &publisher)
|
extractor, err = e.NewExtractor(&builder, &publisher)
|
||||||
gomega.Expect(err).NotTo(gomega.HaveOccurred())
|
if err != nil {
|
||||||
|
t.Error(err)
|
||||||
|
}
|
||||||
|
|
||||||
blockNumber := rand.Int63()
|
blockNumber := rand.Int63()
|
||||||
parentBlockNumber := big.NewInt(blockNumber - int64(1))
|
parentBlockNumber := big.NewInt(blockNumber - int64(1))
|
||||||
currentBlockNumber = big.NewInt(blockNumber)
|
currentBlockNumber = big.NewInt(blockNumber)
|
||||||
parentBlock = types.NewBlock(&types.Header{Number: parentBlockNumber}, nil, nil, nil)
|
parentBlock = types.NewBlock(&types.Header{Number: parentBlockNumber}, nil, nil, nil)
|
||||||
currentBlock = types.NewBlock(&types.Header{Number: currentBlockNumber}, nil, nil, nil)
|
currentBlock = types.NewBlock(&types.Header{Number: currentBlockNumber}, nil, nil, nil)
|
||||||
|
|
||||||
expectedStateDiff = b.StateDiff{
|
expectedStateDiff = b.StateDiff{
|
||||||
BlockNumber: blockNumber,
|
BlockNumber: blockNumber,
|
||||||
BlockHash: currentBlock.Hash(),
|
BlockHash: currentBlock.Hash(),
|
||||||
CreatedAccounts: nil,
|
CreatedAccounts: nil,
|
||||||
DeletedAccounts: nil,
|
DeletedAccounts: nil,
|
||||||
UpdatedAccounts: nil,
|
UpdatedAccounts: nil,
|
||||||
|
}
|
||||||
|
|
||||||
|
testBuildStateDiffStruct(t)
|
||||||
|
testBuildStateDiffErrorHandling(t)
|
||||||
|
testPublishingStateDiff(t)
|
||||||
|
testPublisherErrorHandling(t)
|
||||||
|
}
|
||||||
|
|
||||||
|
func testBuildStateDiffStruct(t *testing.T) {
|
||||||
|
builder.SetStateDiffToBuild(&expectedStateDiff)
|
||||||
|
|
||||||
|
_, err = extractor.ExtractStateDiff(*parentBlock, *currentBlock)
|
||||||
|
if err != nil {
|
||||||
|
t.Error(err)
|
||||||
|
}
|
||||||
|
|
||||||
|
if !equals(builder.OldStateRoot, parentBlock.Root()) { t.Error()}
|
||||||
|
if !equals(builder.NewStateRoot, currentBlock.Root()) { t.Error()}
|
||||||
|
if !equals(builder.BlockNumber,currentBlockNumber.Int64()) { t.Error()}
|
||||||
|
if !equals(builder.BlockHash, currentBlock.Hash()) { t.Error()}
|
||||||
|
}
|
||||||
|
|
||||||
|
func testBuildStateDiffErrorHandling(t *testing.T) {
|
||||||
|
builder.SetBuilderError(testhelpers.MockError)
|
||||||
|
|
||||||
|
_, err = extractor.ExtractStateDiff(*parentBlock, *currentBlock)
|
||||||
|
if err == nil {
|
||||||
|
t.Error(err)
|
||||||
|
}
|
||||||
|
|
||||||
|
if !equals(err, testhelpers.MockError) { t.Error() }
|
||||||
|
builder.SetBuilderError(nil)
|
||||||
|
}
|
||||||
|
|
||||||
|
func testPublishingStateDiff(t *testing.T) {
|
||||||
|
builder.SetStateDiffToBuild(&expectedStateDiff)
|
||||||
|
|
||||||
|
_, err = extractor.ExtractStateDiff(*parentBlock, *currentBlock)
|
||||||
|
if err != nil {
|
||||||
|
t.Error(err)
|
||||||
|
}
|
||||||
|
|
||||||
|
if !equals(publisher.StateDiff, &expectedStateDiff) { t.Error() }
|
||||||
|
}
|
||||||
|
|
||||||
|
func testPublisherErrorHandling(t *testing.T) {
|
||||||
|
publisher.SetPublisherError(testhelpers.MockError)
|
||||||
|
|
||||||
|
_, err = extractor.ExtractStateDiff(*parentBlock, *currentBlock)
|
||||||
|
if err == nil {
|
||||||
|
t.Error("Expected an error, but it didn't occur.")
|
||||||
|
}
|
||||||
|
if !equals(err, testhelpers.MockError) { t.Error() }
|
||||||
|
|
||||||
|
publisher.SetPublisherError(nil)
|
||||||
|
}
|
||||||
|
|
||||||
|
func equals(actual, expected interface{}) (success bool) {
|
||||||
|
if actualByteSlice, ok := actual.([]byte); ok {
|
||||||
|
if expectedByteSlice, ok := expected.([]byte); ok {
|
||||||
|
return bytes.Equal(actualByteSlice, expectedByteSlice)
|
||||||
}
|
}
|
||||||
})
|
}
|
||||||
|
|
||||||
ginkgo.It("builds a state diff struct", func() {
|
return reflect.DeepEqual(actual, expected)
|
||||||
builder.SetStateDiffToBuild(&expectedStateDiff)
|
}
|
||||||
|
|
||||||
_, err = extractor.ExtractStateDiff(*parentBlock, *currentBlock)
|
|
||||||
|
|
||||||
gomega.Expect(err).NotTo(gomega.HaveOccurred())
|
|
||||||
gomega.Expect(builder.OldStateRoot).To(gomega.Equal(parentBlock.Root()))
|
|
||||||
gomega.Expect(builder.NewStateRoot).To(gomega.Equal(currentBlock.Root()))
|
|
||||||
gomega.Expect(builder.BlockNumber).To(gomega.Equal(currentBlockNumber.Int64()))
|
|
||||||
gomega.Expect(builder.BlockHash).To(gomega.Equal(currentBlock.Hash()))
|
|
||||||
})
|
|
||||||
|
|
||||||
ginkgo.It("returns an error if building the state diff fails", func() {
|
|
||||||
builder.SetBuilderError(testhelpers.MockError)
|
|
||||||
|
|
||||||
_, err = extractor.ExtractStateDiff(*parentBlock, *currentBlock)
|
|
||||||
|
|
||||||
gomega.Expect(err).To(gomega.HaveOccurred())
|
|
||||||
gomega.Expect(err).To(gomega.MatchError(testhelpers.MockError))
|
|
||||||
})
|
|
||||||
|
|
||||||
ginkgo.It("publishes the state diff struct", func() {
|
|
||||||
builder.SetStateDiffToBuild(&expectedStateDiff)
|
|
||||||
|
|
||||||
_, err = extractor.ExtractStateDiff(*parentBlock, *currentBlock)
|
|
||||||
|
|
||||||
gomega.Expect(err).NotTo(gomega.HaveOccurred())
|
|
||||||
gomega.Expect(publisher.StateDiff).To(gomega.Equal(&expectedStateDiff))
|
|
||||||
})
|
|
||||||
|
|
||||||
ginkgo.It("returns an error if publishing the diff fails", func() {
|
|
||||||
publisher.SetPublisherError(testhelpers.MockError)
|
|
||||||
|
|
||||||
_, err = extractor.ExtractStateDiff(*parentBlock, *currentBlock)
|
|
||||||
|
|
||||||
gomega.Expect(err).To(gomega.HaveOccurred())
|
|
||||||
gomega.Expect(err).To(gomega.MatchError(testhelpers.MockError))
|
|
||||||
})
|
|
||||||
})
|
|
||||||
|
@ -1,13 +0,0 @@
|
|||||||
package publisher_test
|
|
||||||
|
|
||||||
import (
|
|
||||||
"testing"
|
|
||||||
|
|
||||||
. "github.com/onsi/ginkgo"
|
|
||||||
. "github.com/onsi/gomega"
|
|
||||||
)
|
|
||||||
|
|
||||||
func TestPublisher(t *testing.T) {
|
|
||||||
RegisterFailHandler(Fail)
|
|
||||||
RunSpecs(t, "Publisher Suite")
|
|
||||||
}
|
|
@ -1,169 +1,237 @@
|
|||||||
package publisher_test
|
package publisher_test
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"encoding/csv"
|
"testing"
|
||||||
"github.com/ethereum/go-ethereum/statediff"
|
|
||||||
"github.com/ethereum/go-ethereum/statediff/builder"
|
|
||||||
p "github.com/ethereum/go-ethereum/statediff/publisher"
|
|
||||||
"github.com/ethereum/go-ethereum/statediff/testhelpers"
|
|
||||||
"github.com/onsi/ginkgo"
|
|
||||||
"github.com/onsi/gomega"
|
|
||||||
"io/ioutil"
|
|
||||||
"os"
|
"os"
|
||||||
"path/filepath"
|
|
||||||
"strconv"
|
"strconv"
|
||||||
|
"github.com/ethereum/go-ethereum/statediff/testhelpers"
|
||||||
|
p "github.com/ethereum/go-ethereum/statediff/publisher"
|
||||||
|
"io/ioutil"
|
||||||
|
"github.com/ethereum/go-ethereum/statediff"
|
||||||
|
"encoding/csv"
|
||||||
|
"path/filepath"
|
||||||
|
"bytes"
|
||||||
|
"reflect"
|
||||||
|
"github.com/ethereum/go-ethereum/statediff/builder"
|
||||||
|
"github.com/pkg/errors"
|
||||||
)
|
)
|
||||||
|
|
||||||
var _ = ginkgo.Describe("Publisher", func() {
|
var (
|
||||||
var (
|
tempDir = os.TempDir()
|
||||||
tempDir = os.TempDir()
|
testFilePrefix = "test-statediff"
|
||||||
testFilePrefix = "test-statediff"
|
publisher p.Publisher
|
||||||
publisher p.Publisher
|
dir string
|
||||||
dir string
|
err error
|
||||||
err error
|
)
|
||||||
)
|
|
||||||
|
|
||||||
var expectedCreatedAccountRow = []string{
|
var expectedCreatedAccountRow = []string{
|
||||||
strconv.FormatInt(testhelpers.BlockNumber, 10),
|
strconv.FormatInt(testhelpers.BlockNumber, 10),
|
||||||
testhelpers.BlockHash,
|
testhelpers.BlockHash,
|
||||||
"created",
|
"created",
|
||||||
"created account code",
|
"created account code",
|
||||||
testhelpers.CodeHash,
|
testhelpers.CodeHash,
|
||||||
strconv.FormatUint(testhelpers.OldNonceValue, 10),
|
strconv.FormatUint(testhelpers.OldNonceValue, 10),
|
||||||
strconv.FormatUint(testhelpers.NewNonceValue, 10),
|
strconv.FormatUint(testhelpers.NewNonceValue, 10),
|
||||||
strconv.FormatInt(testhelpers.OldBalanceValue, 10),
|
strconv.FormatInt(testhelpers.OldBalanceValue, 10),
|
||||||
strconv.FormatInt(testhelpers.NewBalanceValue, 10),
|
strconv.FormatInt(testhelpers.NewBalanceValue, 10),
|
||||||
testhelpers.ContractRoot,
|
testhelpers.ContractRoot,
|
||||||
testhelpers.ContractRoot,
|
testhelpers.ContractRoot,
|
||||||
testhelpers.StoragePath,
|
testhelpers.StoragePath,
|
||||||
|
}
|
||||||
|
|
||||||
|
var expectedUpdatedAccountRow = []string{
|
||||||
|
strconv.FormatInt(testhelpers.BlockNumber, 10),
|
||||||
|
testhelpers.BlockHash,
|
||||||
|
"updated",
|
||||||
|
"",
|
||||||
|
testhelpers.CodeHash,
|
||||||
|
strconv.FormatUint(testhelpers.OldNonceValue, 10),
|
||||||
|
strconv.FormatUint(testhelpers.NewNonceValue, 10),
|
||||||
|
strconv.FormatInt(testhelpers.OldBalanceValue, 10),
|
||||||
|
strconv.FormatInt(testhelpers.NewBalanceValue, 10),
|
||||||
|
testhelpers.ContractRoot,
|
||||||
|
testhelpers.ContractRoot,
|
||||||
|
testhelpers.StoragePath,
|
||||||
|
}
|
||||||
|
|
||||||
|
var expectedDeletedAccountRow = []string{
|
||||||
|
strconv.FormatInt(testhelpers.BlockNumber, 10),
|
||||||
|
testhelpers.BlockHash,
|
||||||
|
"deleted",
|
||||||
|
"deleted account code",
|
||||||
|
testhelpers.CodeHash,
|
||||||
|
strconv.FormatUint(testhelpers.OldNonceValue, 10),
|
||||||
|
strconv.FormatUint(testhelpers.NewNonceValue, 10),
|
||||||
|
strconv.FormatInt(testhelpers.OldBalanceValue, 10),
|
||||||
|
strconv.FormatInt(testhelpers.NewBalanceValue, 10),
|
||||||
|
testhelpers.ContractRoot,
|
||||||
|
testhelpers.ContractRoot,
|
||||||
|
testhelpers.StoragePath,
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
func TestPublisher(t *testing.T) {
|
||||||
|
dir, err = ioutil.TempDir(tempDir, testFilePrefix)
|
||||||
|
if err != nil {
|
||||||
|
t.Error(err)
|
||||||
|
}
|
||||||
|
config := statediff.Config{
|
||||||
|
Path: dir,
|
||||||
|
Mode: statediff.CSV,
|
||||||
|
}
|
||||||
|
publisher, err = p.NewPublisher(config)
|
||||||
|
if err != nil {
|
||||||
|
t.Error(err)
|
||||||
}
|
}
|
||||||
|
|
||||||
var expectedUpdatedAccountRow = []string{
|
type Test func(t *testing.T)
|
||||||
strconv.FormatInt(testhelpers.BlockNumber, 10),
|
|
||||||
testhelpers.BlockHash,
|
var tests = []Test{testColumnHeaders,
|
||||||
"updated",
|
testAccountDiffs,
|
||||||
"",
|
testWhenNoDiff,
|
||||||
testhelpers.CodeHash,
|
testDefaultPublisher,
|
||||||
strconv.FormatUint(testhelpers.OldNonceValue, 10),
|
testDefaultDirectory,
|
||||||
strconv.FormatUint(testhelpers.NewNonceValue, 10),
|
|
||||||
strconv.FormatInt(testhelpers.OldBalanceValue, 10),
|
|
||||||
strconv.FormatInt(testhelpers.NewBalanceValue, 10),
|
|
||||||
testhelpers.ContractRoot,
|
|
||||||
testhelpers.ContractRoot,
|
|
||||||
testhelpers.StoragePath,
|
|
||||||
}
|
}
|
||||||
|
|
||||||
var expectedDeletedAccountRow = []string{
|
for _, test := range tests {
|
||||||
strconv.FormatInt(testhelpers.BlockNumber, 10),
|
test(t)
|
||||||
testhelpers.BlockHash,
|
removeFilesFromDir(dir, t)
|
||||||
"deleted",
|
}
|
||||||
"deleted account code",
|
}
|
||||||
testhelpers.CodeHash,
|
|
||||||
strconv.FormatUint(testhelpers.OldNonceValue, 10),
|
func removeFilesFromDir(dir string, t *testing.T) {
|
||||||
strconv.FormatUint(testhelpers.NewNonceValue, 10),
|
files, err := filepath.Glob(filepath.Join(dir, "*"))
|
||||||
strconv.FormatInt(testhelpers.OldBalanceValue, 10),
|
if err != nil {
|
||||||
strconv.FormatInt(testhelpers.NewBalanceValue, 10),
|
t.Error()
|
||||||
testhelpers.ContractRoot,
|
|
||||||
testhelpers.ContractRoot,
|
|
||||||
testhelpers.StoragePath,
|
|
||||||
}
|
}
|
||||||
|
|
||||||
ginkgo.BeforeEach(func() {
|
for _, file := range files {
|
||||||
dir, err = ioutil.TempDir(tempDir, testFilePrefix)
|
err = os.RemoveAll(file)
|
||||||
gomega.Expect(err).NotTo(gomega.HaveOccurred())
|
if err !=nil {
|
||||||
config := statediff.Config{
|
t.Error()
|
||||||
Path: dir,
|
|
||||||
Mode: statediff.CSV,
|
|
||||||
}
|
}
|
||||||
publisher, err = p.NewPublisher(config)
|
}
|
||||||
gomega.Expect(err).NotTo(gomega.HaveOccurred())
|
}
|
||||||
})
|
|
||||||
|
|
||||||
ginkgo.AfterEach(func() {
|
func testColumnHeaders(t *testing.T) {
|
||||||
os.RemoveAll(dir)
|
_, err = publisher.PublishStateDiff(&testhelpers.TestStateDiff)
|
||||||
})
|
if err != nil {
|
||||||
|
t.Error(err)
|
||||||
|
}
|
||||||
|
|
||||||
ginkgo.It("persists the column headers to a CSV file", func() {
|
file, err := getTestDiffFile(dir)
|
||||||
_, err = publisher.PublishStateDiff(&testhelpers.TestStateDiff)
|
if err != nil {
|
||||||
gomega.Expect(err).NotTo(gomega.HaveOccurred())
|
t.Error(err)
|
||||||
|
}
|
||||||
|
|
||||||
file, err := getTestDiffFile(dir)
|
lines, err := csv.NewReader(file).ReadAll()
|
||||||
gomega.Expect(err).NotTo(gomega.HaveOccurred())
|
if err != nil {
|
||||||
|
t.Error(err)
|
||||||
|
}
|
||||||
|
if len(lines) <= 1 { t.Error() }
|
||||||
|
|
||||||
lines, err := csv.NewReader(file).ReadAll()
|
if !equals(lines[0], p.Headers) { t.Error() }
|
||||||
gomega.Expect(len(lines) > 1).To(gomega.BeTrue())
|
}
|
||||||
gomega.Expect(lines[0]).To(gomega.Equal(p.Headers))
|
|
||||||
})
|
|
||||||
|
|
||||||
ginkgo.It("persists the created, upated and deleted account diffs to a CSV file", func() {
|
func testAccountDiffs(t *testing.T) {
|
||||||
_, err = publisher.PublishStateDiff(&testhelpers.TestStateDiff)
|
// it persists the created, updated and deleted account diffs to a CSV file
|
||||||
gomega.Expect(err).NotTo(gomega.HaveOccurred())
|
_, err = publisher.PublishStateDiff(&testhelpers.TestStateDiff)
|
||||||
|
if err != nil {
|
||||||
|
t.Error(err)
|
||||||
|
}
|
||||||
|
|
||||||
file, err := getTestDiffFile(dir)
|
file, err := getTestDiffFile(dir)
|
||||||
gomega.Expect(err).NotTo(gomega.HaveOccurred())
|
if err != nil {
|
||||||
|
t.Error(err)
|
||||||
|
}
|
||||||
|
|
||||||
lines, err := csv.NewReader(file).ReadAll()
|
lines, err := csv.NewReader(file).ReadAll()
|
||||||
gomega.Expect(len(lines) > 3).To(gomega.BeTrue())
|
if err != nil {
|
||||||
gomega.Expect(lines[1]).To(gomega.Equal(expectedCreatedAccountRow))
|
t.Error(err)
|
||||||
gomega.Expect(lines[2]).To(gomega.Equal(expectedUpdatedAccountRow))
|
}
|
||||||
gomega.Expect(lines[3]).To(gomega.Equal(expectedDeletedAccountRow))
|
if len(lines) <= 3 { t.Error() }
|
||||||
})
|
if !equals(lines[1], expectedCreatedAccountRow) { t.Error() }
|
||||||
|
if !equals(lines[2], expectedUpdatedAccountRow) { t.Error()}
|
||||||
|
if !equals(lines[3], expectedDeletedAccountRow) { t.Error()}
|
||||||
|
}
|
||||||
|
|
||||||
ginkgo.It("creates an empty CSV when there is no diff", func() {
|
func testWhenNoDiff(t *testing.T) {
|
||||||
emptyDiff := builder.StateDiff{}
|
//it creates an empty CSV when there is no diff", func() {
|
||||||
_, err = publisher.PublishStateDiff(&emptyDiff)
|
emptyDiff := builder.StateDiff{}
|
||||||
gomega.Expect(err).NotTo(gomega.HaveOccurred())
|
_, err = publisher.PublishStateDiff(&emptyDiff)
|
||||||
|
if err != nil {
|
||||||
|
t.Error(err)
|
||||||
|
}
|
||||||
|
|
||||||
file, err := getTestDiffFile(dir)
|
file, err := getTestDiffFile(dir)
|
||||||
gomega.Expect(err).NotTo(gomega.HaveOccurred())
|
if err != nil {
|
||||||
|
t.Error(err)
|
||||||
|
}
|
||||||
|
|
||||||
lines, err := csv.NewReader(file).ReadAll()
|
lines, err := csv.NewReader(file).ReadAll()
|
||||||
gomega.Expect(len(lines)).To(gomega.Equal(1))
|
if err != nil {
|
||||||
})
|
t.Error(err)
|
||||||
|
}
|
||||||
|
if !equals(len(lines), 1) { t.Error() }
|
||||||
|
}
|
||||||
|
|
||||||
ginkgo.It("defaults to publishing state diffs to a CSV file when no mode is configured", func() {
|
func testDefaultPublisher(t *testing.T) {
|
||||||
config := statediff.Config{Path: dir}
|
//it defaults to publishing state diffs to a CSV file when no mode is configured
|
||||||
publisher, err = p.NewPublisher(config)
|
config := statediff.Config{Path: dir}
|
||||||
gomega.Expect(err).NotTo(gomega.HaveOccurred())
|
publisher, err = p.NewPublisher(config)
|
||||||
|
if err != nil { t.Error(err) }
|
||||||
|
|
||||||
_, err = publisher.PublishStateDiff(&testhelpers.TestStateDiff)
|
_, err = publisher.PublishStateDiff(&testhelpers.TestStateDiff)
|
||||||
gomega.Expect(err).NotTo(gomega.HaveOccurred())
|
if err != nil { t.Error(err) }
|
||||||
|
|
||||||
file, err := getTestDiffFile(dir)
|
file, err := getTestDiffFile(dir)
|
||||||
gomega.Expect(err).NotTo(gomega.HaveOccurred())
|
if err != nil { t.Error(err) }
|
||||||
|
|
||||||
lines, err := csv.NewReader(file).ReadAll()
|
lines, err := csv.NewReader(file).ReadAll()
|
||||||
gomega.Expect(len(lines)).To(gomega.Equal(4))
|
if err != nil { t.Error(err) }
|
||||||
gomega.Expect(lines[0]).To(gomega.Equal(p.Headers))
|
if !equals(len(lines), 4) { t.Error()}
|
||||||
})
|
if !equals(lines[0],p.Headers) { t.Error()}
|
||||||
|
}
|
||||||
|
|
||||||
ginkgo.It("defaults to publishing CSV files in the current directory when no path is configured", func() {
|
func testDefaultDirectory(t *testing.T) {
|
||||||
config := statediff.Config{}
|
//it defaults to publishing CSV files in the current directory when no path is configured
|
||||||
publisher, err = p.NewPublisher(config)
|
config := statediff.Config{}
|
||||||
gomega.Expect(err).NotTo(gomega.HaveOccurred())
|
publisher, err = p.NewPublisher(config)
|
||||||
|
if err != nil { t.Error(err) }
|
||||||
|
|
||||||
err := os.Chdir(dir)
|
err := os.Chdir(dir)
|
||||||
gomega.Expect(err).NotTo(gomega.HaveOccurred())
|
if err != nil { t.Error(err) }
|
||||||
|
|
||||||
_, err = publisher.PublishStateDiff(&testhelpers.TestStateDiff)
|
_, err = publisher.PublishStateDiff(&testhelpers.TestStateDiff)
|
||||||
gomega.Expect(err).NotTo(gomega.HaveOccurred())
|
if err != nil { t.Error(err) }
|
||||||
|
|
||||||
file, err := getTestDiffFile(dir)
|
file, err := getTestDiffFile(dir)
|
||||||
gomega.Expect(err).NotTo(gomega.HaveOccurred())
|
if err != nil { t.Error(err) }
|
||||||
|
|
||||||
lines, err := csv.NewReader(file).ReadAll()
|
lines, err := csv.NewReader(file).ReadAll()
|
||||||
gomega.Expect(len(lines)).To(gomega.Equal(4))
|
if err != nil { t.Error(err) }
|
||||||
gomega.Expect(lines[0]).To(gomega.Equal(p.Headers))
|
if !equals(len(lines), 4) { t.Error() }
|
||||||
})
|
if !equals(lines[0], p.Headers) { t.Error() }
|
||||||
})
|
}
|
||||||
|
|
||||||
func getTestDiffFile(dir string) (*os.File, error) {
|
func getTestDiffFile(dir string) (*os.File, error) {
|
||||||
files, err := ioutil.ReadDir(dir)
|
files, err := ioutil.ReadDir(dir)
|
||||||
gomega.Expect(err).NotTo(gomega.HaveOccurred())
|
if err != nil { return nil, err }
|
||||||
gomega.Expect(len(files) > 0).To(gomega.BeTrue())
|
if len(files) == 0 { return nil, errors.New("There are 0 files.") }
|
||||||
|
|
||||||
fileName := files[0].Name()
|
fileName := files[0].Name()
|
||||||
filePath := filepath.Join(dir, fileName)
|
filePath := filepath.Join(dir, fileName)
|
||||||
|
|
||||||
return os.Open(filePath)
|
return os.Open(filePath)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func equals(actual, expected interface{}) (success bool) {
|
||||||
|
if actualByteSlice, ok := actual.([]byte); ok {
|
||||||
|
if expectedByteSlice, ok := expected.([]byte); ok {
|
||||||
|
return bytes.Equal(actualByteSlice, expectedByteSlice)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return reflect.DeepEqual(actual, expected)
|
||||||
|
}
|
||||||
|
@ -11,3 +11,6 @@ func TestStatediff(t *testing.T) {
|
|||||||
RegisterFailHandler(Fail)
|
RegisterFailHandler(Fail)
|
||||||
RunSpecs(t, "Statediff Suite")
|
RunSpecs(t, "Statediff Suite")
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//convert this over to use built in golang library
|
||||||
|
//only save the new value, and have a pointer to the old value - not sure how this pointer will work for the CSV version
|
||||||
|
Loading…
Reference in New Issue
Block a user