// +build unittest package server import ( "encoding/json" "io/ioutil" "net/http" "net/http/httptest" "net/url" "os" "strconv" "strings" "testing" "time" "github.com/golang/glog" "github.com/gorilla/websocket" "github.com/martinboehm/btcutil/chaincfg" gosocketio "github.com/martinboehm/golang-socketio" "github.com/martinboehm/golang-socketio/transport" "github.com/trezor/blockbook/bchain" "github.com/trezor/blockbook/bchain/coins/btc" "github.com/trezor/blockbook/common" "github.com/trezor/blockbook/db" "github.com/trezor/blockbook/tests/dbtestdata" ) func TestMain(m *testing.M) { // set the current directory to blockbook root so that ./static/ works if err := os.Chdir(".."); err != nil { glog.Fatal("Chdir error:", err) } c := m.Run() chaincfg.ResetParams() os.Exit(c) } func setupRocksDB(t *testing.T, parser bchain.BlockChainParser) (*db.RocksDB, *common.InternalState, string) { tmp, err := ioutil.TempDir("", "testdb") if err != nil { t.Fatal(err) } d, err := db.NewRocksDB(tmp, 100000, -1, parser, nil) if err != nil { t.Fatal(err) } is, err := d.LoadInternalState("fakecoin") if err != nil { t.Fatal(err) } d.SetInternalState(is) block1 := dbtestdata.GetTestBitcoinTypeBlock1(parser) // setup internal state BlockTimes for i := uint32(0); i < block1.Height; i++ { is.BlockTimes = append(is.BlockTimes, 0) } // import data if err := d.ConnectBlock(block1); err != nil { t.Fatal(err) } block2 := dbtestdata.GetTestBitcoinTypeBlock2(parser) if err := d.ConnectBlock(block2); err != nil { t.Fatal(err) } if err := InitTestFiatRates(d); err != nil { t.Fatal(err) } is.FinishedSync(block2.Height) return d, is, tmp } func setupPublicHTTPServer(t *testing.T) (*PublicServer, string) { parser := btc.NewBitcoinParser( btc.GetChainParams("test"), &btc.Configuration{ BlockAddressesToKeep: 1, XPubMagic: 70617039, XPubMagicSegwitP2sh: 71979618, XPubMagicSegwitNative: 73342198, Slip44: 1, }) d, is, path := setupRocksDB(t, parser) // setup internal state and match BestHeight to test data is.Coin = "Fakecoin" is.CoinLabel = "Fake Coin" is.CoinShortcut = "FAKE" metrics, err := common.GetMetrics("Fakecoin") if err != nil { glog.Fatal("metrics: ", err) } chain, err := dbtestdata.NewFakeBlockChain(parser) if err != nil { glog.Fatal("fakechain: ", err) } mempool, err := chain.CreateMempool(chain) if err != nil { glog.Fatal("mempool: ", err) } // caching is switched off because test transactions do not have hex data txCache, err := db.NewTxCache(d, chain, metrics, is, false) if err != nil { glog.Fatal("txCache: ", err) } // s.Run is never called, binding can be to any port s, err := NewPublicServer("localhost:12345", "", d, chain, mempool, txCache, "", metrics, is, false) if err != nil { t.Fatal(err) } return s, path } func closeAndDestroyPublicServer(t *testing.T, s *PublicServer, dbpath string) { // destroy db if err := s.db.Close(); err != nil { t.Fatal(err) } os.RemoveAll(dbpath) } func newGetRequest(u string) *http.Request { r, err := http.NewRequest("GET", u, nil) if err != nil { glog.Fatal(err) } return r } func newPostFormRequest(u string, formdata ...string) *http.Request { form := url.Values{} for i := 0; i < len(formdata)-1; i += 2 { form.Add(formdata[i], formdata[i+1]) } r, err := http.NewRequest("POST", u, strings.NewReader(form.Encode())) if err != nil { glog.Fatal(err) } r.Header.Add("Content-Type", "application/x-www-form-urlencoded") return r } func newPostRequest(u string, body string) *http.Request { r, err := http.NewRequest("POST", u, strings.NewReader(body)) if err != nil { glog.Fatal(err) } r.Header.Add("Content-Type", "application/octet-stream") return r } func insertFiatRate(date string, rates map[string]float64, d *db.RocksDB) error { convertedDate, err := db.FiatRatesConvertDate(date) if err != nil { return err } ticker := &db.CurrencyRatesTicker{ Timestamp: convertedDate, Rates: rates, } return d.FiatRatesStoreTicker(ticker) } // InitTestFiatRates initializes test data for /api/v2/tickers endpoint func InitTestFiatRates(d *db.RocksDB) error { if err := insertFiatRate("20180320020000", map[string]float64{ "usd": 2000.0, "eur": 1300.0, }, d); err != nil { return err } if err := insertFiatRate("20180320030000", map[string]float64{ "usd": 2001.0, "eur": 1301.0, }, d); err != nil { return err } if err := insertFiatRate("20180320040000", map[string]float64{ "usd": 2002.0, "eur": 1302.0, }, d); err != nil { return err } if err := insertFiatRate("20180321055521", map[string]float64{ "usd": 2003.0, "eur": 1303.0, }, d); err != nil { return err } if err := insertFiatRate("20191121140000", map[string]float64{ "usd": 7814.5, "eur": 7100.0, }, d); err != nil { return err } return insertFiatRate("20191121143015", map[string]float64{ "usd": 7914.5, "eur": 7134.1, }, d) } func httpTestsBitcoinType(t *testing.T, ts *httptest.Server) { tests := []struct { name string r *http.Request status int contentType string body []string }{ { name: "explorerTx", r: newGetRequest(ts.URL + "/tx/fdd824a780cbb718eeb766eb05d83fdefc793a27082cd5e67f856d69798cf7db"), status: http.StatusOK, contentType: "text/html; charset=utf-8", body: []string{ `Fake Coin Explorer`, `