2017-11-13 21:42:07 +00:00
|
|
|
package repositories_test
|
|
|
|
|
|
|
|
import (
|
|
|
|
"fmt"
|
|
|
|
"strings"
|
|
|
|
|
2017-12-19 20:14:41 +00:00
|
|
|
"io/ioutil"
|
|
|
|
"log"
|
|
|
|
|
2018-01-16 20:25:33 +00:00
|
|
|
"math/big"
|
|
|
|
|
2018-01-06 20:31:53 +00:00
|
|
|
"github.com/vulcanize/vulcanizedb/pkg/config"
|
|
|
|
"github.com/vulcanize/vulcanizedb/pkg/core"
|
|
|
|
"github.com/vulcanize/vulcanizedb/pkg/repositories"
|
|
|
|
"github.com/vulcanize/vulcanizedb/pkg/repositories/testing"
|
2017-11-13 21:42:07 +00:00
|
|
|
"github.com/jmoiron/sqlx"
|
|
|
|
_ "github.com/lib/pq"
|
|
|
|
. "github.com/onsi/ginkgo"
|
|
|
|
. "github.com/onsi/gomega"
|
|
|
|
)
|
|
|
|
|
2017-12-19 20:14:41 +00:00
|
|
|
func init() {
|
|
|
|
log.SetOutput(ioutil.Discard)
|
|
|
|
}
|
|
|
|
|
2017-11-13 21:42:07 +00:00
|
|
|
var _ = Describe("Postgres repository", func() {
|
|
|
|
|
|
|
|
It("connects to the database", func() {
|
|
|
|
cfg, _ := config.NewConfig("private")
|
|
|
|
pgConfig := config.DbConnectionString(cfg.Database)
|
|
|
|
db, err := sqlx.Connect("postgres", pgConfig)
|
|
|
|
Expect(err).Should(BeNil())
|
|
|
|
Expect(db).ShouldNot(BeNil())
|
|
|
|
})
|
|
|
|
|
2017-12-07 19:32:16 +00:00
|
|
|
testing.AssertRepositoryBehavior(func(node core.Node) repositories.Repository {
|
2017-11-13 21:42:07 +00:00
|
|
|
cfg, _ := config.NewConfig("private")
|
2017-12-07 19:32:16 +00:00
|
|
|
repository, _ := repositories.NewPostgres(cfg.Database, node)
|
2017-11-13 21:42:07 +00:00
|
|
|
testing.ClearData(repository)
|
|
|
|
return repository
|
|
|
|
})
|
|
|
|
|
2018-01-16 20:25:33 +00:00
|
|
|
It("serializes big.Int to db", func() {
|
|
|
|
// postgres driver doesn't support go big.Int type
|
|
|
|
// various casts in golang uint64, int64, overflow for
|
|
|
|
// transaction value (in wei) even though
|
|
|
|
// postgres numeric can handle an arbitrary
|
|
|
|
// sized int, so use string representation of big.Int
|
|
|
|
// and cast on insert
|
|
|
|
|
|
|
|
cfg, _ := config.NewConfig("private")
|
|
|
|
pgConfig := config.DbConnectionString(cfg.Database)
|
|
|
|
db, err := sqlx.Connect("postgres", pgConfig)
|
|
|
|
|
|
|
|
bi := new(big.Int)
|
|
|
|
bi.SetString("34940183920000000000", 10)
|
|
|
|
Expect(bi.String()).To(Equal("34940183920000000000"))
|
|
|
|
|
|
|
|
defer db.Exec(`DROP TABLE IF EXISTS example`)
|
|
|
|
_, err = db.Exec("CREATE TABLE example ( id INTEGER, data NUMERIC )")
|
|
|
|
Expect(err).ToNot(HaveOccurred())
|
|
|
|
|
|
|
|
sqlStatement := `
|
|
|
|
INSERT INTO example (id, data)
|
|
|
|
VALUES (1, cast($1 AS NUMERIC))`
|
|
|
|
_, err = db.Exec(sqlStatement, bi.String())
|
|
|
|
Expect(err).ToNot(HaveOccurred())
|
|
|
|
|
|
|
|
var data string
|
|
|
|
err = db.QueryRow(`SELECT data FROM example WHERE id = 1`).Scan(&data)
|
|
|
|
Expect(err).ToNot(HaveOccurred())
|
|
|
|
|
|
|
|
Expect(bi.String()).To(Equal(data))
|
|
|
|
actual := new(big.Int)
|
|
|
|
actual.SetString(data, 10)
|
|
|
|
Expect(actual).To(Equal(bi))
|
|
|
|
})
|
|
|
|
|
2017-11-13 21:42:07 +00:00
|
|
|
It("does not commit block if block is invalid", func() {
|
|
|
|
//badNonce violates db Nonce field length
|
|
|
|
badNonce := fmt.Sprintf("x %s", strings.Repeat("1", 100))
|
|
|
|
badBlock := core.Block{
|
|
|
|
Number: 123,
|
|
|
|
Nonce: badNonce,
|
|
|
|
Transactions: []core.Transaction{},
|
|
|
|
}
|
|
|
|
cfg, _ := config.NewConfig("private")
|
2018-01-10 21:54:36 +00:00
|
|
|
node := core.Node{GenesisBlock: "GENESIS", NetworkId: 1, Id: "x123", ClientName: "geth"}
|
2017-12-07 19:32:16 +00:00
|
|
|
repository, _ := repositories.NewPostgres(cfg.Database, node)
|
2017-11-13 21:42:07 +00:00
|
|
|
|
2017-12-19 20:14:41 +00:00
|
|
|
err1 := repository.CreateOrUpdateBlock(badBlock)
|
2017-12-13 16:51:11 +00:00
|
|
|
savedBlock, err2 := repository.FindBlockByNumber(123)
|
2017-11-13 21:42:07 +00:00
|
|
|
|
2017-12-13 16:51:11 +00:00
|
|
|
Expect(err1).To(HaveOccurred())
|
|
|
|
Expect(err2).To(HaveOccurred())
|
|
|
|
Expect(savedBlock).To(BeZero())
|
2017-11-13 21:42:07 +00:00
|
|
|
})
|
|
|
|
|
2017-12-04 15:53:36 +00:00
|
|
|
It("throws error when can't connect to the database", func() {
|
|
|
|
invalidDatabase := config.Database{}
|
2018-01-10 21:54:36 +00:00
|
|
|
node := core.Node{GenesisBlock: "GENESIS", NetworkId: 1, Id: "x123", ClientName: "geth"}
|
2017-12-07 19:32:16 +00:00
|
|
|
_, err := repositories.NewPostgres(invalidDatabase, node)
|
2017-12-04 15:53:36 +00:00
|
|
|
Expect(err).To(Equal(repositories.ErrDBConnectionFailed))
|
|
|
|
})
|
|
|
|
|
2017-12-07 19:32:16 +00:00
|
|
|
It("throws error when can't create node", func() {
|
|
|
|
cfg, _ := config.NewConfig("private")
|
|
|
|
badHash := fmt.Sprintf("x %s", strings.Repeat("1", 100))
|
2018-01-10 21:54:36 +00:00
|
|
|
node := core.Node{GenesisBlock: badHash, NetworkId: 1, Id: "x123", ClientName: "geth"}
|
2017-12-07 19:32:16 +00:00
|
|
|
_, err := repositories.NewPostgres(cfg.Database, node)
|
|
|
|
Expect(err).To(Equal(repositories.ErrUnableToSetNode))
|
|
|
|
})
|
|
|
|
|
2017-12-12 21:55:26 +00:00
|
|
|
It("does not commit log if log is invalid", func() {
|
|
|
|
//badTxHash violates db tx_hash field length
|
|
|
|
badTxHash := fmt.Sprintf("x %s", strings.Repeat("1", 100))
|
|
|
|
badLog := core.Log{
|
|
|
|
Address: "x123",
|
|
|
|
BlockNumber: 1,
|
|
|
|
TxHash: badTxHash,
|
|
|
|
}
|
|
|
|
cfg, _ := config.NewConfig("private")
|
2018-01-10 21:54:36 +00:00
|
|
|
node := core.Node{GenesisBlock: "GENESIS", NetworkId: 1, Id: "x123", ClientName: "geth"}
|
2017-12-12 21:55:26 +00:00
|
|
|
repository, _ := repositories.NewPostgres(cfg.Database, node)
|
|
|
|
|
|
|
|
err := repository.CreateLogs([]core.Log{badLog})
|
|
|
|
savedBlock := repository.FindLogs("x123", 1)
|
|
|
|
|
|
|
|
Expect(err).ToNot(BeNil())
|
|
|
|
Expect(savedBlock).To(BeNil())
|
|
|
|
})
|
|
|
|
|
2017-11-13 21:42:07 +00:00
|
|
|
It("does not commit block or transactions if transaction is invalid", func() {
|
|
|
|
//badHash violates db To field length
|
|
|
|
badHash := fmt.Sprintf("x %s", strings.Repeat("1", 100))
|
|
|
|
badTransaction := core.Transaction{To: badHash}
|
|
|
|
block := core.Block{
|
|
|
|
Number: 123,
|
|
|
|
Transactions: []core.Transaction{badTransaction},
|
|
|
|
}
|
|
|
|
cfg, _ := config.NewConfig("private")
|
2018-01-10 21:54:36 +00:00
|
|
|
node := core.Node{GenesisBlock: "GENESIS", NetworkId: 1, Id: "x123", ClientName: "geth"}
|
2017-12-07 19:32:16 +00:00
|
|
|
repository, _ := repositories.NewPostgres(cfg.Database, node)
|
2017-11-13 21:42:07 +00:00
|
|
|
|
2017-12-19 20:14:41 +00:00
|
|
|
err1 := repository.CreateOrUpdateBlock(block)
|
2017-12-13 16:51:11 +00:00
|
|
|
savedBlock, err2 := repository.FindBlockByNumber(123)
|
2017-11-13 21:42:07 +00:00
|
|
|
|
2017-12-13 16:51:11 +00:00
|
|
|
Expect(err1).To(HaveOccurred())
|
|
|
|
Expect(err2).To(HaveOccurred())
|
|
|
|
Expect(savedBlock).To(BeZero())
|
2017-11-13 21:42:07 +00:00
|
|
|
})
|
|
|
|
|
|
|
|
})
|