b6f93e735f
- starting with the totalSupply function - sets contract config on transformer by passing it into the transformer initializer - handles block records with the same number for different nodes for both creating token_supply records, and finding missing blocks
208 lines
7.1 KiB
Go
208 lines
7.1 KiB
Go
// Copyright 2018 Vulcanize
|
|
//
|
|
// Licensed under the Apache License, Version 2.0 (the "License");
|
|
// you may not use this file except in compliance with the License.
|
|
// You may obtain a copy of the License at
|
|
//
|
|
// http://www.apache.org/licenses/LICENSE-2.0
|
|
//
|
|
// Unless required by applicable law or agreed to in writing, software
|
|
// distributed under the License is distributed on an "AS IS" BASIS,
|
|
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
// See the License for the specific language governing permissions and
|
|
// limitations under the License.
|
|
|
|
package every_block_test
|
|
|
|
import (
|
|
. "github.com/onsi/ginkgo"
|
|
. "github.com/onsi/gomega"
|
|
|
|
"github.com/vulcanize/vulcanizedb/examples/erc20_watcher/every_block"
|
|
"github.com/vulcanize/vulcanizedb/examples/test_helpers"
|
|
"github.com/vulcanize/vulcanizedb/pkg/core"
|
|
"github.com/vulcanize/vulcanizedb/pkg/datastore/postgres"
|
|
"github.com/vulcanize/vulcanizedb/pkg/datastore/postgres/repositories"
|
|
"github.com/vulcanize/vulcanizedb/test_config"
|
|
"math/rand"
|
|
)
|
|
|
|
var _ = Describe("ERC20 Token Repository", func() {
|
|
var db *postgres.DB
|
|
var blockId int64
|
|
var blockNumber int64
|
|
var repository every_block.TokenSupplyRepository
|
|
var blockRepository repositories.BlockRepository
|
|
testAddress := "abc"
|
|
|
|
BeforeEach(func() {
|
|
db = test_helpers.CreateNewDatabase()
|
|
repository = every_block.TokenSupplyRepository{DB: db}
|
|
_, err := db.Query(`DELETE FROM token_supply`)
|
|
Expect(err).NotTo(HaveOccurred())
|
|
|
|
blockRepository = *repositories.NewBlockRepository(db)
|
|
blockNumber = rand.Int63()
|
|
blockId = test_helpers.CreateBlock(blockNumber, blockRepository)
|
|
})
|
|
|
|
Describe("Create", func() {
|
|
It("creates a token supply record", func() {
|
|
supply := supplyModel(blockNumber, testAddress, "100")
|
|
err := repository.Create(supply)
|
|
Expect(err).NotTo(HaveOccurred())
|
|
|
|
dbResult := test_helpers.TokenSupplyDBRow{}
|
|
expectedTokenSupply := test_helpers.TokenSupplyDBRow{
|
|
Supply: int64(100),
|
|
BlockID: blockId,
|
|
TokenAddress: testAddress,
|
|
}
|
|
|
|
var count int
|
|
err = repository.DB.QueryRowx(`SELECT count(*) FROM token_supply`).Scan(&count)
|
|
Expect(err).NotTo(HaveOccurred())
|
|
Expect(count).To(Equal(1))
|
|
|
|
err = repository.DB.QueryRowx(`SELECT * FROM token_supply`).StructScan(&dbResult)
|
|
Expect(err).NotTo(HaveOccurred())
|
|
Expect(dbResult.Supply).To(Equal(expectedTokenSupply.Supply))
|
|
Expect(dbResult.BlockID).To(Equal(expectedTokenSupply.BlockID))
|
|
Expect(dbResult.TokenAddress).To(Equal(expectedTokenSupply.TokenAddress))
|
|
})
|
|
|
|
It("returns an error if fetching the block's id from the database fails", func() {
|
|
errorSupply := supplyModel(-1, "", "")
|
|
err := repository.Create(errorSupply)
|
|
|
|
Expect(err).To(HaveOccurred())
|
|
Expect(err.Error()).To(ContainSubstring("sql"))
|
|
Expect(err.Error()).To(ContainSubstring("block number -1"))
|
|
})
|
|
|
|
It("returns an error if inserting the token_supply fails", func() {
|
|
errorSupply := supplyModel(blockNumber, "", "")
|
|
err := repository.Create(errorSupply)
|
|
|
|
Expect(err).To(HaveOccurred())
|
|
Expect(err.Error()).To(ContainSubstring("pq"))
|
|
Expect(err.Error()).To(ContainSubstring("token_supply for block number"))
|
|
})
|
|
})
|
|
|
|
Describe("When there are multiple nodes", func() {
|
|
var node2DB *postgres.DB
|
|
var node2BlockRepo *repositories.BlockRepository
|
|
var node2BlockId int64
|
|
var node2TokenSupplyRepo every_block.TokenSupplyRepository
|
|
var tokenSupply every_block.TokenSupply
|
|
|
|
BeforeEach(func() {
|
|
node2DB = createDbForAnotherNode()
|
|
|
|
//create another block with the same number on node2
|
|
node2BlockRepo = repositories.NewBlockRepository(node2DB)
|
|
node2BlockId = test_helpers.CreateBlock(blockNumber, *node2BlockRepo)
|
|
|
|
tokenSupply = supplyModel(blockNumber, "abc", "100")
|
|
node2TokenSupplyRepo = every_block.TokenSupplyRepository{DB: node2DB}
|
|
})
|
|
|
|
It("only creates token_supply records for the current node (node2)", func() {
|
|
err := node2TokenSupplyRepo.Create(tokenSupply)
|
|
Expect(err).NotTo(HaveOccurred())
|
|
|
|
var tokenSupplies []test_helpers.TokenSupplyDBRow
|
|
err = node2TokenSupplyRepo.DB.Select(&tokenSupplies, `SELECT * FROM token_supply`)
|
|
Expect(err).NotTo(HaveOccurred())
|
|
Expect(len(tokenSupplies)).To(Equal(1))
|
|
Expect(tokenSupplies[0].BlockID).To(Equal(node2BlockId))
|
|
})
|
|
|
|
It("only includes missing block numbers for the current node", func() {
|
|
//create token_supply on original node
|
|
err := repository.Create(tokenSupply)
|
|
Expect(err).NotTo(HaveOccurred())
|
|
|
|
originalNodeMissingBlocks, err := repository.MissingBlocks(blockNumber, blockNumber)
|
|
Expect(err).NotTo(HaveOccurred())
|
|
Expect(len(originalNodeMissingBlocks)).To(Equal(0))
|
|
|
|
node2MissingBlocks, err := node2TokenSupplyRepo.MissingBlocks(blockNumber, blockNumber)
|
|
Expect(err).NotTo(HaveOccurred())
|
|
Expect(len(node2MissingBlocks)).To(Equal(1))
|
|
})
|
|
})
|
|
|
|
Describe("MissingBlocks", func() {
|
|
It("returns the block numbers for which an associated TokenSupply record hasn't been created", func() {
|
|
createTokenSupplyFor(repository, blockNumber)
|
|
|
|
newBlockNumber := blockNumber + 1
|
|
test_helpers.CreateBlock(newBlockNumber, blockRepository)
|
|
blocks, err := repository.MissingBlocks(blockNumber, newBlockNumber)
|
|
|
|
Expect(blocks).To(ConsistOf(newBlockNumber))
|
|
Expect(err).NotTo(HaveOccurred())
|
|
})
|
|
|
|
It("only returns blocks within the given range", func() {
|
|
newBlockNumber := blockNumber + 1
|
|
test_helpers.CreateBlock(newBlockNumber, blockRepository)
|
|
blocks, err := repository.MissingBlocks(blockNumber, blockNumber)
|
|
|
|
Expect(blocks).NotTo(ConsistOf(newBlockNumber))
|
|
Expect(err).NotTo(HaveOccurred())
|
|
})
|
|
|
|
It("does not return numbers that already have an associated TokenSupply record", func() {
|
|
createTokenSupplyFor(repository, blockNumber)
|
|
blocks, err := repository.MissingBlocks(blockNumber, blockNumber)
|
|
|
|
Expect(blocks).To(BeEmpty())
|
|
Expect(err).NotTo(HaveOccurred())
|
|
})
|
|
})
|
|
|
|
It("deletes the token supply record when the associated block is deleted", func() {
|
|
err := repository.Create(every_block.TokenSupply{BlockNumber: blockNumber, Value: "0"})
|
|
Expect(err).NotTo(HaveOccurred())
|
|
|
|
var count int
|
|
err = repository.DB.QueryRowx(`SELECT count(*) FROM token_supply`).Scan(&count)
|
|
Expect(err).NotTo(HaveOccurred())
|
|
Expect(count).To(Equal(1))
|
|
|
|
_, err = db.Query(`DELETE FROM blocks`)
|
|
Expect(err).NotTo(HaveOccurred())
|
|
|
|
err = repository.DB.QueryRowx(`SELECT count(*) FROM token_supply`).Scan(&count)
|
|
Expect(err).NotTo(HaveOccurred())
|
|
Expect(count).To(Equal(0))
|
|
})
|
|
})
|
|
|
|
func supplyModel(blockNumber int64, tokenAddress string, supplyValue string) every_block.TokenSupply {
|
|
return every_block.TokenSupply{
|
|
Value: supplyValue,
|
|
TokenAddress: tokenAddress,
|
|
BlockNumber: int64(blockNumber),
|
|
}
|
|
}
|
|
|
|
func createTokenSupplyFor(repository every_block.TokenSupplyRepository, blockNumber int64) {
|
|
err := repository.Create(every_block.TokenSupply{BlockNumber: blockNumber, Value: "0"})
|
|
Expect(err).NotTo(HaveOccurred())
|
|
}
|
|
|
|
func createDbForAnotherNode() *postgres.DB {
|
|
anotherNode := core.Node{
|
|
GenesisBlock: "GENESIS",
|
|
NetworkID: 1,
|
|
ID: "testNodeId",
|
|
ClientName: "Geth/v1.7.2-stable-1db4ecdc/darwin-amd64/go1.9",
|
|
}
|
|
|
|
return test_config.NewTestDBWithoutDeletingRecords(anotherNode)
|
|
}
|