Add public server unit tests for ethereum type coins
This commit is contained in:
parent
e3bb706ea2
commit
89b1e75641
60
server/public_ethereumtype_test.go
Normal file
60
server/public_ethereumtype_test.go
Normal file
@ -0,0 +1,60 @@
|
|||||||
|
//go:build unittest
|
||||||
|
// +build unittest
|
||||||
|
|
||||||
|
package server
|
||||||
|
|
||||||
|
import (
|
||||||
|
"net/http"
|
||||||
|
"net/http/httptest"
|
||||||
|
"testing"
|
||||||
|
|
||||||
|
"github.com/golang/glog"
|
||||||
|
"github.com/trezor/blockbook/bchain/coins/eth"
|
||||||
|
"github.com/trezor/blockbook/tests/dbtestdata"
|
||||||
|
)
|
||||||
|
|
||||||
|
func httpTestsEthereumType(t *testing.T, ts *httptest.Server) {
|
||||||
|
tests := []httpTests{
|
||||||
|
{
|
||||||
|
name: "apiIndex",
|
||||||
|
r: newGetRequest(ts.URL + "/api"),
|
||||||
|
status: http.StatusOK,
|
||||||
|
contentType: "application/json; charset=utf-8",
|
||||||
|
body: []string{
|
||||||
|
`{"blockbook":{"coin":"Fakecoin"`,
|
||||||
|
`"bestHeight":4321001`,
|
||||||
|
`"decimals":18`,
|
||||||
|
`"backend":{"chain":"fakecoin","blocks":2,"headers":2,"bestBlockHash":"0x2b57e15e93a0ed197417a34c2498b7187df79099572c04a6b6e6ff418f74e6ee"`,
|
||||||
|
`"version":"001001","subversion":"/Fakecoin:0.0.1/"`,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "apiAddress EthAddr4b",
|
||||||
|
r: newGetRequest(ts.URL + "/api/v2/address/" + dbtestdata.EthAddr4b),
|
||||||
|
status: http.StatusOK,
|
||||||
|
contentType: "application/json; charset=utf-8",
|
||||||
|
body: []string{
|
||||||
|
`{"page":1,"totalPages":1,"itemsOnPage":1000,"address":"0x4Bda106325C335dF99eab7fE363cAC8A0ba2a24D","balance":"123450075","unconfirmedBalance":"0","unconfirmedTxs":0,"txs":1,"nonTokenTxs":1,"txids":["0xc92919ad24ffd58f760b18df7949f06e1190cf54a50a0e3745a385608ed3cbf2"],"nonce":"75","tokens":[{"type":"ERC20","name":"Contract 13","contract":"0x0d0F936Ee4c93e25944694D6C121de94D9760F11","transfers":2,"symbol":"S13","decimals":18},{"type":"ERC20","name":"Contract 74","contract":"0x4af4114F73d1c1C903aC9E0361b379D1291808A2","transfers":2,"symbol":"S74","decimals":18}],"erc20Contract":{"contract":"0x4Bda106325C335dF99eab7fE363cAC8A0ba2a24D","name":"Contract 75","symbol":"S75","decimals":18}}`,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
performHttpTests(tests, t, ts)
|
||||||
|
}
|
||||||
|
|
||||||
|
func Test_PublicServer_EthereumType(t *testing.T) {
|
||||||
|
parser := eth.NewEthereumParser(1)
|
||||||
|
chain, err := dbtestdata.NewFakeBlockChainEthereumType(parser)
|
||||||
|
if err != nil {
|
||||||
|
glog.Fatal("fakechain: ", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
s, dbpath := setupPublicHTTPServer(parser, chain, t)
|
||||||
|
defer closeAndDestroyPublicServer(t, s, dbpath)
|
||||||
|
s.ConnectFullPublicInterface()
|
||||||
|
// take the handler of the public server and pass it to the test server
|
||||||
|
ts := httptest.NewServer(s.https.Handler)
|
||||||
|
defer ts.Close()
|
||||||
|
|
||||||
|
httpTestsEthereumType(t, ts)
|
||||||
|
}
|
||||||
@ -36,7 +36,7 @@ func TestMain(m *testing.M) {
|
|||||||
os.Exit(c)
|
os.Exit(c)
|
||||||
}
|
}
|
||||||
|
|
||||||
func setupRocksDB(t *testing.T, parser bchain.BlockChainParser) (*db.RocksDB, *common.InternalState, string) {
|
func setupRocksDB(parser bchain.BlockChainParser, chain bchain.BlockChain, t *testing.T) (*db.RocksDB, *common.InternalState, string) {
|
||||||
tmp, err := ioutil.TempDir("", "testdb")
|
tmp, err := ioutil.TempDir("", "testdb")
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatal(err)
|
t.Fatal(err)
|
||||||
@ -50,7 +50,15 @@ func setupRocksDB(t *testing.T, parser bchain.BlockChainParser) (*db.RocksDB, *c
|
|||||||
t.Fatal(err)
|
t.Fatal(err)
|
||||||
}
|
}
|
||||||
d.SetInternalState(is)
|
d.SetInternalState(is)
|
||||||
block1 := dbtestdata.GetTestBitcoinTypeBlock1(parser)
|
// there are 2 simulated block, of height bestBlockHeight-1 and bestBlockHeight
|
||||||
|
bestHeight, err := chain.GetBestBlockHeight()
|
||||||
|
if err != nil {
|
||||||
|
t.Fatal(err)
|
||||||
|
}
|
||||||
|
block1, err := chain.GetBlock("", bestHeight-1)
|
||||||
|
if err != nil {
|
||||||
|
t.Fatal(err)
|
||||||
|
}
|
||||||
// setup internal state BlockTimes
|
// setup internal state BlockTimes
|
||||||
for i := uint32(0); i < block1.Height; i++ {
|
for i := uint32(0); i < block1.Height; i++ {
|
||||||
is.BlockTimes = append(is.BlockTimes, 0)
|
is.BlockTimes = append(is.BlockTimes, 0)
|
||||||
@ -59,7 +67,10 @@ func setupRocksDB(t *testing.T, parser bchain.BlockChainParser) (*db.RocksDB, *c
|
|||||||
if err := d.ConnectBlock(block1); err != nil {
|
if err := d.ConnectBlock(block1); err != nil {
|
||||||
t.Fatal(err)
|
t.Fatal(err)
|
||||||
}
|
}
|
||||||
block2 := dbtestdata.GetTestBitcoinTypeBlock2(parser)
|
block2, err := chain.GetBlock("", bestHeight)
|
||||||
|
if err != nil {
|
||||||
|
t.Fatal(err)
|
||||||
|
}
|
||||||
if err := d.ConnectBlock(block2); err != nil {
|
if err := d.ConnectBlock(block2); err != nil {
|
||||||
t.Fatal(err)
|
t.Fatal(err)
|
||||||
}
|
}
|
||||||
@ -70,31 +81,22 @@ func setupRocksDB(t *testing.T, parser bchain.BlockChainParser) (*db.RocksDB, *c
|
|||||||
return d, is, tmp
|
return d, is, tmp
|
||||||
}
|
}
|
||||||
|
|
||||||
func setupPublicHTTPServer(t *testing.T) (*PublicServer, string) {
|
var metrics *common.Metrics
|
||||||
parser := btc.NewBitcoinParser(
|
|
||||||
btc.GetChainParams("test"),
|
|
||||||
&btc.Configuration{
|
|
||||||
BlockAddressesToKeep: 1,
|
|
||||||
XPubMagic: 70617039,
|
|
||||||
XPubMagicSegwitP2sh: 71979618,
|
|
||||||
XPubMagicSegwitNative: 73342198,
|
|
||||||
Slip44: 1,
|
|
||||||
})
|
|
||||||
|
|
||||||
d, is, path := setupRocksDB(t, parser)
|
func setupPublicHTTPServer(parser bchain.BlockChainParser, chain bchain.BlockChain, t *testing.T) (*PublicServer, string) {
|
||||||
|
d, is, path := setupRocksDB(parser, chain, t)
|
||||||
// setup internal state and match BestHeight to test data
|
// setup internal state and match BestHeight to test data
|
||||||
is.Coin = "Fakecoin"
|
is.Coin = "Fakecoin"
|
||||||
is.CoinLabel = "Fake Coin"
|
is.CoinLabel = "Fake Coin"
|
||||||
is.CoinShortcut = "FAKE"
|
is.CoinShortcut = "FAKE"
|
||||||
|
|
||||||
metrics, err := common.GetMetrics("Fakecoin")
|
var err error
|
||||||
if err != nil {
|
// metrics can be setup only once
|
||||||
glog.Fatal("metrics: ", err)
|
if metrics == nil {
|
||||||
}
|
metrics, err = common.GetMetrics("Fakecoin")
|
||||||
|
if err != nil {
|
||||||
chain, err := dbtestdata.NewFakeBlockChain(parser)
|
glog.Fatal("metrics: ", err)
|
||||||
if err != nil {
|
}
|
||||||
glog.Fatal("fakechain: ", err)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
mempool, err := chain.CreateMempool(chain)
|
mempool, err := chain.CreateMempool(chain)
|
||||||
@ -204,14 +206,45 @@ func InitTestFiatRates(d *db.RocksDB) error {
|
|||||||
}, d)
|
}, d)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
type httpTests struct {
|
||||||
|
name string
|
||||||
|
r *http.Request
|
||||||
|
status int
|
||||||
|
contentType string
|
||||||
|
body []string
|
||||||
|
}
|
||||||
|
|
||||||
|
func performHttpTests(tests []httpTests, t *testing.T, ts *httptest.Server) {
|
||||||
|
for _, tt := range tests {
|
||||||
|
t.Run(tt.name, func(t *testing.T) {
|
||||||
|
resp, err := http.DefaultClient.Do(tt.r)
|
||||||
|
if err != nil {
|
||||||
|
t.Fatal(err)
|
||||||
|
}
|
||||||
|
defer resp.Body.Close()
|
||||||
|
if resp.StatusCode != tt.status {
|
||||||
|
t.Errorf("StatusCode = %v, want %v", resp.StatusCode, tt.status)
|
||||||
|
}
|
||||||
|
if resp.Header["Content-Type"][0] != tt.contentType {
|
||||||
|
t.Errorf("Content-Type = %v, want %v", resp.Header["Content-Type"][0], tt.contentType)
|
||||||
|
}
|
||||||
|
bb, err := ioutil.ReadAll(resp.Body)
|
||||||
|
if err != nil {
|
||||||
|
t.Fatal(err)
|
||||||
|
}
|
||||||
|
b := string(bb)
|
||||||
|
for _, c := range tt.body {
|
||||||
|
if !strings.Contains(b, c) {
|
||||||
|
t.Errorf("got %v, want to contain %v", b, c)
|
||||||
|
break
|
||||||
|
}
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
func httpTestsBitcoinType(t *testing.T, ts *httptest.Server) {
|
func httpTestsBitcoinType(t *testing.T, ts *httptest.Server) {
|
||||||
tests := []struct {
|
tests := []httpTests{
|
||||||
name string
|
|
||||||
r *http.Request
|
|
||||||
status int
|
|
||||||
contentType string
|
|
||||||
body []string
|
|
||||||
}{
|
|
||||||
{
|
{
|
||||||
name: "explorerTx",
|
name: "explorerTx",
|
||||||
r: newGetRequest(ts.URL + "/tx/fdd824a780cbb718eeb766eb05d83fdefc793a27082cd5e67f856d69798cf7db"),
|
r: newGetRequest(ts.URL + "/tx/fdd824a780cbb718eeb766eb05d83fdefc793a27082cd5e67f856d69798cf7db"),
|
||||||
@ -947,33 +980,7 @@ func httpTestsBitcoinType(t *testing.T, ts *httptest.Server) {
|
|||||||
},
|
},
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
performHttpTests(tests, t, ts)
|
||||||
for _, tt := range tests {
|
|
||||||
t.Run(tt.name, func(t *testing.T) {
|
|
||||||
resp, err := http.DefaultClient.Do(tt.r)
|
|
||||||
if err != nil {
|
|
||||||
t.Fatal(err)
|
|
||||||
}
|
|
||||||
defer resp.Body.Close()
|
|
||||||
if resp.StatusCode != tt.status {
|
|
||||||
t.Errorf("StatusCode = %v, want %v", resp.StatusCode, tt.status)
|
|
||||||
}
|
|
||||||
if resp.Header["Content-Type"][0] != tt.contentType {
|
|
||||||
t.Errorf("Content-Type = %v, want %v", resp.Header["Content-Type"][0], tt.contentType)
|
|
||||||
}
|
|
||||||
bb, err := ioutil.ReadAll(resp.Body)
|
|
||||||
if err != nil {
|
|
||||||
t.Fatal(err)
|
|
||||||
}
|
|
||||||
b := string(bb)
|
|
||||||
for _, c := range tt.body {
|
|
||||||
if !strings.Contains(b, c) {
|
|
||||||
t.Errorf("got %v, want to contain %v", b, c)
|
|
||||||
break
|
|
||||||
}
|
|
||||||
}
|
|
||||||
})
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func socketioTestsBitcoinType(t *testing.T, ts *httptest.Server) {
|
func socketioTestsBitcoinType(t *testing.T, ts *httptest.Server) {
|
||||||
@ -1558,7 +1565,22 @@ func websocketTestsBitcoinType(t *testing.T, ts *httptest.Server) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func Test_PublicServer_BitcoinType(t *testing.T) {
|
func Test_PublicServer_BitcoinType(t *testing.T) {
|
||||||
s, dbpath := setupPublicHTTPServer(t)
|
parser := btc.NewBitcoinParser(
|
||||||
|
btc.GetChainParams("test"),
|
||||||
|
&btc.Configuration{
|
||||||
|
BlockAddressesToKeep: 1,
|
||||||
|
XPubMagic: 70617039,
|
||||||
|
XPubMagicSegwitP2sh: 71979618,
|
||||||
|
XPubMagicSegwitNative: 73342198,
|
||||||
|
Slip44: 1,
|
||||||
|
})
|
||||||
|
|
||||||
|
chain, err := dbtestdata.NewFakeBlockChain(parser)
|
||||||
|
if err != nil {
|
||||||
|
glog.Fatal("fakechain: ", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
s, dbpath := setupPublicHTTPServer(parser, chain, t)
|
||||||
defer closeAndDestroyPublicServer(t, s, dbpath)
|
defer closeAndDestroyPublicServer(t, s, dbpath)
|
||||||
s.ConnectFullPublicInterface()
|
s.ConnectFullPublicInterface()
|
||||||
// take the handler of the public server and pass it to the test server
|
// take the handler of the public server and pass it to the test server
|
||||||
|
|||||||
128
tests/dbtestdata/fakechain_ethereumtype.go
Normal file
128
tests/dbtestdata/fakechain_ethereumtype.go
Normal file
@ -0,0 +1,128 @@
|
|||||||
|
package dbtestdata
|
||||||
|
|
||||||
|
import (
|
||||||
|
"encoding/json"
|
||||||
|
"math/big"
|
||||||
|
"strconv"
|
||||||
|
|
||||||
|
"github.com/trezor/blockbook/bchain"
|
||||||
|
)
|
||||||
|
|
||||||
|
type fakeBlockChainEthereumType struct {
|
||||||
|
*fakeBlockChain
|
||||||
|
}
|
||||||
|
|
||||||
|
// NewFakeBlockChainEthereumType returns mocked blockchain RPC interface used for tests
|
||||||
|
func NewFakeBlockChainEthereumType(parser bchain.BlockChainParser) (bchain.BlockChain, error) {
|
||||||
|
return &fakeBlockChainEthereumType{&fakeBlockChain{&bchain.BaseChain{Parser: parser}}}, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (c *fakeBlockChainEthereumType) CreateMempool(chain bchain.BlockChain) (bchain.Mempool, error) {
|
||||||
|
return bchain.NewMempoolEthereumType(chain, 1, false), nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (c *fakeBlockChainEthereumType) GetChainInfo() (v *bchain.ChainInfo, err error) {
|
||||||
|
return &bchain.ChainInfo{
|
||||||
|
Chain: c.GetNetworkName(),
|
||||||
|
Blocks: 2,
|
||||||
|
Headers: 2,
|
||||||
|
Bestblockhash: GetTestEthereumTypeBlock2(c.Parser).BlockHeader.Hash,
|
||||||
|
Version: "001001",
|
||||||
|
Subversion: c.GetSubversion(),
|
||||||
|
}, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (c *fakeBlockChainEthereumType) GetBestBlockHash() (v string, err error) {
|
||||||
|
return GetTestEthereumTypeBlock2(c.Parser).BlockHeader.Hash, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (c *fakeBlockChainEthereumType) GetBestBlockHeight() (v uint32, err error) {
|
||||||
|
return GetTestEthereumTypeBlock2(c.Parser).BlockHeader.Height, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (c *fakeBlockChainEthereumType) GetBlockHash(height uint32) (v string, err error) {
|
||||||
|
b1 := GetTestEthereumTypeBlock1(c.Parser)
|
||||||
|
if height == b1.BlockHeader.Height {
|
||||||
|
return b1.BlockHeader.Hash, nil
|
||||||
|
}
|
||||||
|
b2 := GetTestEthereumTypeBlock2(c.Parser)
|
||||||
|
if height == b2.BlockHeader.Height {
|
||||||
|
return b2.BlockHeader.Hash, nil
|
||||||
|
}
|
||||||
|
return "", bchain.ErrBlockNotFound
|
||||||
|
}
|
||||||
|
|
||||||
|
func (c *fakeBlockChainEthereumType) GetBlockHeader(hash string) (v *bchain.BlockHeader, err error) {
|
||||||
|
b1 := GetTestEthereumTypeBlock1(c.Parser)
|
||||||
|
if hash == b1.BlockHeader.Hash {
|
||||||
|
return &b1.BlockHeader, nil
|
||||||
|
}
|
||||||
|
b2 := GetTestEthereumTypeBlock2(c.Parser)
|
||||||
|
if hash == b2.BlockHeader.Hash {
|
||||||
|
return &b2.BlockHeader, nil
|
||||||
|
}
|
||||||
|
return nil, bchain.ErrBlockNotFound
|
||||||
|
}
|
||||||
|
|
||||||
|
func (c *fakeBlockChainEthereumType) GetBlock(hash string, height uint32) (v *bchain.Block, err error) {
|
||||||
|
b1 := GetTestEthereumTypeBlock1(c.Parser)
|
||||||
|
if hash == b1.BlockHeader.Hash || height == b1.BlockHeader.Height {
|
||||||
|
return b1, nil
|
||||||
|
}
|
||||||
|
b2 := GetTestEthereumTypeBlock2(c.Parser)
|
||||||
|
if hash == b2.BlockHeader.Hash || height == b2.BlockHeader.Height {
|
||||||
|
return b2, nil
|
||||||
|
}
|
||||||
|
return nil, bchain.ErrBlockNotFound
|
||||||
|
}
|
||||||
|
|
||||||
|
func (c *fakeBlockChainEthereumType) GetBlockInfo(hash string) (v *bchain.BlockInfo, err error) {
|
||||||
|
b1 := GetTestEthereumTypeBlock1(c.Parser)
|
||||||
|
if hash == b1.BlockHeader.Hash {
|
||||||
|
return getBlockInfo(b1), nil
|
||||||
|
}
|
||||||
|
b2 := GetTestEthereumTypeBlock2(c.Parser)
|
||||||
|
if hash == b2.BlockHeader.Hash {
|
||||||
|
return getBlockInfo(b2), nil
|
||||||
|
}
|
||||||
|
return nil, bchain.ErrBlockNotFound
|
||||||
|
}
|
||||||
|
|
||||||
|
func (c *fakeBlockChainEthereumType) GetTransaction(txid string) (v *bchain.Tx, err error) {
|
||||||
|
v = getTxInBlock(GetTestEthereumTypeBlock1(c.Parser), txid)
|
||||||
|
if v == nil {
|
||||||
|
v = getTxInBlock(GetTestEthereumTypeBlock2(c.Parser), txid)
|
||||||
|
}
|
||||||
|
if v != nil {
|
||||||
|
return v, nil
|
||||||
|
}
|
||||||
|
return nil, bchain.ErrTxNotFound
|
||||||
|
}
|
||||||
|
|
||||||
|
func (c *fakeBlockChainEthereumType) GetTransactionSpecific(tx *bchain.Tx) (v json.RawMessage, err error) {
|
||||||
|
txS, _ := tx.CoinSpecificData.(bchain.EthereumSpecificData)
|
||||||
|
|
||||||
|
rm, err := json.Marshal(txS)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
return json.RawMessage(rm), nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (c *fakeBlockChainEthereumType) EthereumTypeGetBalance(addrDesc bchain.AddressDescriptor) (*big.Int, error) {
|
||||||
|
return big.NewInt(123450000 + int64(addrDesc[0])), nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (c *fakeBlockChainEthereumType) EthereumTypeGetNonce(addrDesc bchain.AddressDescriptor) (uint64, error) {
|
||||||
|
return uint64(addrDesc[0]), nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (c *fakeBlockChainEthereumType) EthereumTypeGetErc20ContractInfo(contractDesc bchain.AddressDescriptor) (*bchain.Erc20Contract, error) {
|
||||||
|
addresses, _, _ := c.Parser.GetAddressesFromAddrDesc(contractDesc)
|
||||||
|
return &bchain.Erc20Contract{
|
||||||
|
Contract: addresses[0],
|
||||||
|
Name: "Contract " + strconv.Itoa(int(contractDesc[0])),
|
||||||
|
Symbol: "S" + strconv.Itoa(int(contractDesc[0])),
|
||||||
|
Decimals: 18,
|
||||||
|
}, nil
|
||||||
|
}
|
||||||
Loading…
Reference in New Issue
Block a user