230 lines
8.3 KiB
Go
230 lines
8.3 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 flip_kick_test
|
|
|
|
import (
|
|
. "github.com/onsi/ginkgo"
|
|
. "github.com/onsi/gomega"
|
|
|
|
"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/pkg/fakes"
|
|
"github.com/vulcanize/vulcanizedb/pkg/transformers/flip_kick"
|
|
"github.com/vulcanize/vulcanizedb/pkg/transformers/test_data"
|
|
"github.com/vulcanize/vulcanizedb/test_config"
|
|
)
|
|
|
|
var _ = Describe("FlipKick Repository", func() {
|
|
var db *postgres.DB
|
|
var flipKickRepository flip_kick.FlipKickRepository
|
|
var headerId int64
|
|
var blockNumber int64
|
|
var flipKick = test_data.FlipKickModel
|
|
|
|
BeforeEach(func() {
|
|
db = test_config.NewTestDB(test_config.NewTestNode())
|
|
test_config.CleanTestDB(db)
|
|
flipKickRepository = flip_kick.FlipKickRepository{}
|
|
flipKickRepository.SetDB(db)
|
|
blockNumber = GinkgoRandomSeed()
|
|
headerId = createHeader(db, blockNumber)
|
|
|
|
_, err := db.Exec(`DELETE from maker.flip_kick;`)
|
|
Expect(err).NotTo(HaveOccurred())
|
|
})
|
|
|
|
Describe("Create", func() {
|
|
AfterEach(func() {
|
|
_, err := db.Exec(`DELETE from headers`)
|
|
Expect(err).NotTo(HaveOccurred())
|
|
})
|
|
|
|
It("persists flip_kick records", func() {
|
|
err := flipKickRepository.Create(headerId, []interface{}{flipKick})
|
|
Expect(err).NotTo(HaveOccurred())
|
|
|
|
assertDBRecordCount(db, "maker.flip_kick", 1)
|
|
|
|
dbResult := test_data.FlipKickDBRow{}
|
|
err = db.QueryRowx(`SELECT * FROM maker.flip_kick`).StructScan(&dbResult)
|
|
Expect(err).NotTo(HaveOccurred())
|
|
Expect(dbResult.HeaderId).To(Equal(headerId))
|
|
Expect(dbResult.BidId).To(Equal(flipKick.BidId))
|
|
Expect(dbResult.Lot).To(Equal(flipKick.Lot))
|
|
Expect(dbResult.Bid).To(Equal(flipKick.Bid))
|
|
Expect(dbResult.Gal).To(Equal(flipKick.Gal))
|
|
Expect(dbResult.End.Equal(flipKick.End)).To(BeTrue())
|
|
Expect(dbResult.Urn).To(Equal(flipKick.Urn))
|
|
Expect(dbResult.Tab).To(Equal(flipKick.Tab))
|
|
Expect(dbResult.TransactionIndex).To(Equal(flipKick.TransactionIndex))
|
|
Expect(dbResult.LogIndex).To(Equal(flipKick.LogIndex))
|
|
Expect(dbResult.Raw).To(MatchJSON(flipKick.Raw))
|
|
})
|
|
|
|
It("marks header checked", func() {
|
|
err := flipKickRepository.Create(headerId, []interface{}{flipKick})
|
|
Expect(err).NotTo(HaveOccurred())
|
|
|
|
var headerChecked bool
|
|
err = db.Get(&headerChecked, `SELECT flip_kick_checked FROM public.checked_headers WHERE header_id = $1`, headerId)
|
|
Expect(err).NotTo(HaveOccurred())
|
|
Expect(headerChecked).To(BeTrue())
|
|
})
|
|
|
|
It("updates the header to checked if checked headers row already exists", func() {
|
|
_, err := db.Exec(`INSERT INTO public.checked_headers (header_id) VALUES ($1)`, headerId)
|
|
Expect(err).NotTo(HaveOccurred())
|
|
err = flipKickRepository.Create(headerId, []interface{}{flipKick})
|
|
Expect(err).NotTo(HaveOccurred())
|
|
|
|
var headerChecked bool
|
|
err = db.Get(&headerChecked, `SELECT flip_kick_checked FROM public.checked_headers WHERE header_id = $1`, headerId)
|
|
Expect(err).NotTo(HaveOccurred())
|
|
Expect(headerChecked).To(BeTrue())
|
|
})
|
|
|
|
It("returns an error if inserting the flip_kick record fails", func() {
|
|
err := flipKickRepository.Create(headerId, []interface{}{flipKick})
|
|
Expect(err).NotTo(HaveOccurred())
|
|
|
|
err = flipKickRepository.Create(headerId, []interface{}{flipKick})
|
|
Expect(err).To(HaveOccurred())
|
|
Expect(err.Error()).To(ContainSubstring("pq: duplicate key value violates unique constraint"))
|
|
})
|
|
|
|
It("allows for multiple flip kick events in one transaction if they have different log indexes", func() {
|
|
newFlipKick := test_data.FlipKickModel
|
|
newFlipKick.LogIndex = newFlipKick.LogIndex + 1
|
|
err := flipKickRepository.Create(headerId, []interface{}{newFlipKick})
|
|
|
|
Expect(err).NotTo(HaveOccurred())
|
|
})
|
|
|
|
It("deletes the flip_kick records if its corresponding header record is deleted", func() {
|
|
err := flipKickRepository.Create(headerId, []interface{}{flipKick})
|
|
Expect(err).NotTo(HaveOccurred())
|
|
assertDBRecordCount(db, "maker.flip_kick", 1)
|
|
assertDBRecordCount(db, "headers", 1)
|
|
|
|
_, err = db.Exec(`DELETE FROM headers where id = $1`, headerId)
|
|
Expect(err).NotTo(HaveOccurred())
|
|
|
|
assertDBRecordCount(db, "headers", 0)
|
|
assertDBRecordCount(db, "maker.flip_kick", 0)
|
|
})
|
|
|
|
It("returns an error if the wrong model type is passed in", func() {
|
|
err := flipKickRepository.Create(headerId, []interface{}{test_data.WrongModel{}})
|
|
|
|
Expect(err).To(HaveOccurred())
|
|
Expect(err.Error()).To(ContainSubstring("model of type"))
|
|
})
|
|
})
|
|
|
|
Describe("MarkHeaderChecked", func() {
|
|
It("creates a row for a new headerID", func() {
|
|
err := flipKickRepository.MarkHeaderChecked(headerId)
|
|
|
|
Expect(err).NotTo(HaveOccurred())
|
|
var headerChecked bool
|
|
err = db.Get(&headerChecked, `SELECT flip_kick_checked FROM public.checked_headers WHERE header_id = $1`, headerId)
|
|
Expect(err).NotTo(HaveOccurred())
|
|
Expect(headerChecked).To(BeTrue())
|
|
})
|
|
|
|
It("updates row when headerID already exists", func() {
|
|
_, err := db.Exec(`INSERT INTO public.checked_headers (header_id) VALUES ($1)`, headerId)
|
|
Expect(err).NotTo(HaveOccurred())
|
|
|
|
err = flipKickRepository.MarkHeaderChecked(headerId)
|
|
|
|
Expect(err).NotTo(HaveOccurred())
|
|
var headerChecked bool
|
|
err = db.Get(&headerChecked, `SELECT flip_kick_checked FROM public.checked_headers WHERE header_id = $1`, headerId)
|
|
Expect(err).NotTo(HaveOccurred())
|
|
Expect(headerChecked).To(BeTrue())
|
|
})
|
|
})
|
|
|
|
Describe("When there are multiple nodes", func() {
|
|
var db2 *postgres.DB
|
|
var flipKickRepository2 flip_kick.FlipKickRepository
|
|
|
|
BeforeEach(func() {
|
|
//create database for the second node
|
|
node2 := core.Node{
|
|
GenesisBlock: "GENESIS",
|
|
NetworkID: 1,
|
|
ID: "node2",
|
|
ClientName: "Geth/v1.7.2-stable-1db4ecdc/darwin-amd64/go1.9",
|
|
}
|
|
db2 = test_config.NewTestDB(node2)
|
|
flipKickRepository2 = flip_kick.FlipKickRepository{}
|
|
flipKickRepository2.SetDB(db2)
|
|
createHeader(db2, blockNumber)
|
|
|
|
_, err := db2.Exec(`DELETE from maker.flip_kick;`)
|
|
Expect(err).NotTo(HaveOccurred())
|
|
})
|
|
|
|
It("only includes missing headers for the current node", func() {
|
|
node1missingHeaders, err := flipKickRepository.MissingHeaders(blockNumber, blockNumber)
|
|
Expect(err).NotTo(HaveOccurred())
|
|
Expect(len(node1missingHeaders)).To(Equal(1))
|
|
|
|
node2MissingHeaders, err := flipKickRepository2.MissingHeaders(blockNumber, blockNumber)
|
|
Expect(err).NotTo(HaveOccurred())
|
|
Expect(len(node2MissingHeaders)).To(Equal(1))
|
|
})
|
|
})
|
|
|
|
Describe("MissingHeaders", func() {
|
|
It("returns headers that haven't been marked as checked", func() {
|
|
startingBlock := blockNumber - 3
|
|
endingBlock := blockNumber + 3
|
|
err := flipKickRepository.MarkHeaderChecked(headerId)
|
|
Expect(err).NotTo(HaveOccurred())
|
|
|
|
newBlockNumber := blockNumber + 3
|
|
newHeaderId := createHeader(db, newBlockNumber)
|
|
createHeader(db, blockNumber+10) //this one is out of the block range and shouldn't be included
|
|
headers, err := flipKickRepository.MissingHeaders(startingBlock, endingBlock)
|
|
Expect(len(headers)).To(Equal(1))
|
|
Expect(headers[0].Id).To(Equal(newHeaderId))
|
|
Expect(headers[0].BlockNumber).To(Equal(newBlockNumber))
|
|
})
|
|
})
|
|
})
|
|
|
|
func assertDBRecordCount(db *postgres.DB, dbTable string, expectedCount int) {
|
|
var count int
|
|
query := `SELECT count(*) FROM ` + dbTable
|
|
err := db.QueryRow(query).Scan(&count)
|
|
Expect(err).NotTo(HaveOccurred())
|
|
Expect(count).To(Equal(expectedCount))
|
|
}
|
|
|
|
func createHeader(db *postgres.DB, blockNumber int64) (headerId int64) {
|
|
headerRepository := repositories.NewHeaderRepository(db)
|
|
_, err := headerRepository.CreateOrUpdateHeader(fakes.GetFakeHeader(blockNumber))
|
|
Expect(err).NotTo(HaveOccurred())
|
|
|
|
var dbHeader core.Header
|
|
err = db.Get(&dbHeader, `SELECT id, block_number, hash, raw FROM public.headers WHERE block_number = $1 AND eth_node_id = $2`, blockNumber, db.NodeID)
|
|
Expect(err).NotTo(HaveOccurred())
|
|
return dbHeader.Id
|
|
}
|