func TestPaymentActions(t *testing.T) { test.LoadScenario("base") app := NewTestApp() defer app.Close() rh := NewRequestHelper(app) Convey("Payment Actions:", t, func() { Convey("GET /payments", func() { w := rh.Get("/payments", test.RequestHelperNoop) So(w.Code, ShouldEqual, 200) So(w.Body, ShouldBePageOf, 4) }) Convey("GET /ledgers/:ledger_id/payments", func() { w := rh.Get("/ledgers/1/payments", test.RequestHelperNoop) So(w.Code, ShouldEqual, 200) So(w.Body, ShouldBePageOf, 0) w = rh.Get("/ledgers/3/payments", test.RequestHelperNoop) So(w.Code, ShouldEqual, 200) So(w.Body, ShouldBePageOf, 1) }) Convey("GET /accounts/:account_id/payments", func() { w := rh.Get("/accounts/GA5WBPYA5Y4WAEHXWR2UKO2UO4BUGHUQ74EUPKON2QHV4WRHOIRNKKH2/payments", test.RequestHelperNoop) So(w.Code, ShouldEqual, 200) So(w.Body, ShouldBePageOf, 1) test.LoadScenario("pathed_payment") w = rh.Get("/accounts/GCQPYGH4K57XBDENKKX55KDTWOTK5WDWRQOH2LHEDX3EKVIQRLMESGBG/payments", test.RequestHelperNoop) So(w.Code, ShouldEqual, 200) So(w.Body, ShouldBePageOf, 3) }) Convey("GET /transactions/:tx_id/payments", func() { test.LoadScenario("pathed_payment") w := rh.Get("/transactions/42450ffe3956b8618cffaae48665c252869440aeb41fd8bf4921929a61982630/payments", test.RequestHelperNoop) So(w.Code, ShouldEqual, 200) So(w.Body, ShouldBePageOf, 0) w = rh.Get("/transactions/95324dec7c94f8cc992522794b2a84a732cddcb5641992589cfe328884a4c132/payments", test.RequestHelperNoop) So(w.Code, ShouldEqual, 200) So(w.Body, ShouldBePageOf, 1) }) }) }
func TestPaymentActions(t *testing.T) { test.LoadScenario("base") app := NewTestApp() defer app.Close() rh := NewRequestHelper(app) Convey("Payment Actions:", t, func() { Convey("GET /payments", func() { w := rh.Get("/payments", test.RequestHelperNoop) So(w.Code, ShouldEqual, 200) So(w.Body, ShouldBePageOf, 4) }) Convey("GET /ledgers/:ledger_id/payments", func() { w := rh.Get("/ledgers/1/payments", test.RequestHelperNoop) So(w.Code, ShouldEqual, 200) So(w.Body, ShouldBePageOf, 0) w = rh.Get("/ledgers/3/payments", test.RequestHelperNoop) So(w.Code, ShouldEqual, 200) So(w.Body, ShouldBePageOf, 1) }) Convey("GET /accounts/:account_id/payments", func() { w := rh.Get("/accounts/GA5WBPYA5Y4WAEHXWR2UKO2UO4BUGHUQ74EUPKON2QHV4WRHOIRNKKH2/payments", test.RequestHelperNoop) So(w.Code, ShouldEqual, 200) So(w.Body, ShouldBePageOf, 1) test.LoadScenario("pathed_payment") w = rh.Get("/accounts/GCQPYGH4K57XBDENKKX55KDTWOTK5WDWRQOH2LHEDX3EKVIQRLMESGBG/payments", test.RequestHelperNoop) So(w.Code, ShouldEqual, 200) So(w.Body, ShouldBePageOf, 3) }) Convey("GET /transactions/:tx_id/payments", func() { test.LoadScenario("pathed_payment") w := rh.Get("/transactions/b52f16ffb98c047e33b9c2ec30880330cde71f85b3443dae2c5cb86c7d4d8452/payments", test.RequestHelperNoop) So(w.Code, ShouldEqual, 200) So(w.Body, ShouldBePageOf, 0) w = rh.Get("/transactions/1d2a4be72470658f68db50eef29ea0af3f985ce18b5c218f03461d40c47dc292/payments", test.RequestHelperNoop) So(w.Code, ShouldEqual, 200) So(w.Body, ShouldBePageOf, 1) }) }) }
func TestHistoryAccountByAddressQuery(t *testing.T) { test.LoadScenario("base") Convey("AccountByAddress", t, func() { var account HistoryAccountRecord Convey("Existing record behavior", func() { address := "GBRPYHIL2CI3FNQ4BXLFMNDLFJUNPU2HY3ZMFSHONUCEOASW7QC7OX2H" q := HistoryAccountByAddressQuery{ SqlQuery{history}, address, } err := Get(ctx, q, &account) So(err, ShouldBeNil) So(account.Id, ShouldEqual, 0) So(account.Address, ShouldEqual, address) }) Convey("Missing record behavior", func() { address := "not real" q := HistoryAccountByAddressQuery{ SqlQuery{history}, address, } err := Get(ctx, q, &account) So(err, ShouldEqual, ErrNoResults) }) }) }
func TestOperationByIdQuery(t *testing.T) { test.LoadScenario("base") Convey("OperationByIdQuery", t, func() { var op OperationRecord Convey("Existing record behavior", func() { id := int64(8589938689) q := OperationByIdQuery{ SqlQuery{history}, id, } err := Get(ctx, q, &op) So(err, ShouldBeNil) So(op.Id, ShouldEqual, id) So(op.TransactionId, ShouldEqual, id-1) }) Convey("Missing record behavior", func() { id := int64(0) q := OperationByIdQuery{ SqlQuery{history}, id, } err := Get(ctx, q, &op) So(err, ShouldEqual, ErrNoResults) }) }) }
func TestTradeActions(t *testing.T) { Convey("Trade Actions:", t, func() { test.LoadScenario("trades") app := NewTestApp() defer app.Close() rh := NewRequestHelper(app) Convey("GET /accounts/:account_id/trades", func() { w := rh.Get("/accounts/GA5WBPYA5Y4WAEHXWR2UKO2UO4BUGHUQ74EUPKON2QHV4WRHOIRNKKH2/trades", test.RequestHelperNoop) So(w.Code, ShouldEqual, 200) So(w.Body, ShouldBePageOf, 1) }) Convey("GET /order_book/trades", func() { url := "/order_book/trades?" + "selling_asset_type=credit_alphanum4&" + "selling_asset_code=EUR&" + "selling_asset_issuer=GCQPYGH4K57XBDENKKX55KDTWOTK5WDWRQOH2LHEDX3EKVIQRLMESGBG&" + "buying_asset_type=credit_alphanum4&" + "buying_asset_code=USD&" + "buying_asset_issuer=GC23QF2HUE52AMXUFUH3AYJAXXGXXV2VHXYYR6EYXETPKDXZSAW67XO4" w := rh.Get(url, test.RequestHelperNoop) So(w.Code, ShouldEqual, 200) So(w.Body, ShouldBePageOf, 1) }) }) }
func TestLedgerActions(t *testing.T) { test.LoadScenario("base") app := NewTestApp() defer app.Close() rh := NewRequestHelper(app) Convey("Ledger Actions:", t, func() { Convey("GET /ledgers/1", func() { w := rh.Get("/ledgers/1", test.RequestHelperNoop) So(w.Code, ShouldEqual, 200) var result LedgerResource err := json.Unmarshal(w.Body.Bytes(), &result) So(err, ShouldBeNil) So(result.Sequence, ShouldEqual, 1) }) Convey("GET /ledgers/100", func() { w := rh.Get("/ledgers/100", test.RequestHelperNoop) So(w.Code, ShouldEqual, 404) }) Convey("GET /ledgers", func() { Convey("With Default Params", func() { w := rh.Get("/ledgers", test.RequestHelperNoop) var result map[string]interface{} err := json.Unmarshal(w.Body.Bytes(), &result) So(err, ShouldBeNil) So(w.Code, ShouldEqual, 200) embedded := result["_embedded"].(map[string]interface{}) records := embedded["records"].([]interface{}) So(len(records), ShouldEqual, 3) }) Convey("With A Limit", func() { w := rh.Get("/ledgers?limit=1", test.RequestHelperNoop) var result map[string]interface{} err := json.Unmarshal(w.Body.Bytes(), &result) So(err, ShouldBeNil) So(w.Code, ShouldEqual, 200) embedded := result["_embedded"].(map[string]interface{}) records := embedded["records"].([]interface{}) So(len(records), ShouldEqual, 1) }) }) }) }
func TestPathActions(t *testing.T) { test.LoadScenario("paths") app := NewTestApp() defer app.Close() rh := NewRequestHelper(app) Convey("Path Actions:", t, func() { Convey("(no query args): GET /paths", func() { w := rh.Get("/paths", test.RequestHelperNoop) t.Log(w.Body.String()) So(w.Code, ShouldEqual, 400) }) Convey("(happy path): GET /paths?{all args}", func() { qs := "?destination_account=GAEDTJ4PPEFVW5XV2S7LUXBEHNQMX5Q2GM562RJGOQG7GVCE5H3HIB4V" + "&source_account=GARSFJNXJIHO6ULUBK3DBYKVSIZE7SC72S5DYBCHU7DKL22UXKVD7MXP" + "&destination_asset_type=credit_alphanum4" + "&destination_asset_code=EUR" + "&destination_asset_issuer=GDSBCQO34HWPGUGQSP3QBFEXVTSR2PW46UIGTHVWGWJGQKH3AFNHXHXN" + "&destination_amount=10" w := rh.Get("/paths"+qs, test.RequestHelperNoop) So(w.Code, ShouldEqual, 200) t.Log(qs) t.Log(w.Body.String()) So(w.Body, ShouldBePageOf, 4) }) }) }
func TestAccountActions(t *testing.T) { Convey("Account Actions:", t, func() { test.LoadScenario("base") app := NewTestApp() defer app.Close() rh := NewRequestHelper(app) Convey("GET /accounts/GBRPYHIL2CI3FNQ4BXLFMNDLFJUNPU2HY3ZMFSHONUCEOASW7QC7OX2H", func() { w := rh.Get("/accounts/GBRPYHIL2CI3FNQ4BXLFMNDLFJUNPU2HY3ZMFSHONUCEOASW7QC7OX2H", test.RequestHelperNoop) So(w.Code, ShouldEqual, 200) var result resource.Account err := json.Unmarshal(w.Body.Bytes(), &result) So(err, ShouldBeNil) So(result.Sequence, ShouldEqual, "3") }) Convey("GET /accounts/100", func() { w := rh.Get("/accounts/100", test.RequestHelperNoop) So(w.Code, ShouldEqual, 404) }) Convey("GET /accounts", func() { w := rh.Get("/accounts", test.RequestHelperNoop) So(w.Code, ShouldEqual, 200) So(w.Body, ShouldBePageOf, 4) w = rh.Get("/accounts?limit=1", test.RequestHelperNoop) So(w.Code, ShouldEqual, 200) So(w.Body, ShouldBePageOf, 1) }) }) }
func TestLedgerPageQuery(t *testing.T) { test.LoadScenario("base") var records []LedgerRecord Convey("LedgerPageQuery", t, func() { pq, err := NewPageQuery("", "asc", 2) So(err, ShouldBeNil) q := LedgerPageQuery{SqlQuery{history}, pq} err = Select(ctx, q, &records) So(err, ShouldBeNil) So(len(records), ShouldEqual, 2) So(records, ShouldBeOrderedAscending, func(r interface{}) int64 { return r.(LedgerRecord).Id }) lastLedger := records[len(records)-1] q.Cursor = lastLedger.PagingToken() err = Select(ctx, q, &records) So(err, ShouldBeNil) t.Log(records) So(len(records), ShouldEqual, 1) }) }
func TestRootAction(t *testing.T) { Convey("GET /", t, func() { test.LoadScenario("base") server := test.NewStaticMockServer(`{ "info": { "network": "test", "build": "test-core" } }`) defer server.Close() app := NewTestApp() app.horizonVersion = "test-horizon" app.config.StellarCoreURL = server.URL defer app.Close() rh := NewRequestHelper(app) w := rh.Get("/", test.RequestHelperNoop) So(w.Code, ShouldEqual, 200) var result resource.Root err := json.Unmarshal(w.Body.Bytes(), &result) So(err, ShouldBeNil) So(result.HorizonVersion, ShouldEqual, "test-horizon") So(result.StellarCoreVersion, ShouldEqual, "test-core") }) }
func TestAccountByAddressQuery(t *testing.T) { test.LoadScenario("non_native_payment") Convey("AccountByAddress", t, func() { var account AccountRecord notreal := "not_real" withtl := "GBXGQJWVLWOYHFLVTKWV5FGHA3LNYY2JQKM7OAJAUEQFU6LPCSEFVXON" notl := "GBRPYHIL2CI3FNQ4BXLFMNDLFJUNPU2HY3ZMFSHONUCEOASW7QC7OX2H" q := AccountByAddressQuery{ Core: SqlQuery{core}, History: SqlQuery{history}, Address: withtl, } err := Get(ctx, q, &account) So(err, ShouldBeNil) So(account.Address, ShouldEqual, withtl) So(account.Seqnum, ShouldEqual, 8589934593) So(len(account.Trustlines), ShouldEqual, 1) q.Address = notl err = Get(ctx, q, &account) So(err, ShouldBeNil) So(len(account.Trustlines), ShouldEqual, 0) q.Address = notreal err = Get(ctx, q, &account) So(err, ShouldEqual, ErrNoResults) }) }
func TestLedgerBySequenceQuery(t *testing.T) { Convey("LedgerBySequenceQuery", t, func() { test.LoadScenario("base") var record LedgerRecord Convey("Existing record behavior", func() { sequence := int32(2) q := LedgerBySequenceQuery{ SqlQuery{history}, sequence, } err := Get(ctx, q, &record) So(err, ShouldBeNil) So(record.Sequence, ShouldEqual, sequence) }) Convey("Missing record behavior", func() { sequence := int32(-1) query := LedgerBySequenceQuery{ SqlQuery{history}, sequence, } err := Get(ctx, query, &record) So(err, ShouldEqual, ErrNoResults) }) }) }
func TestFinder(t *testing.T) { Convey("Finder", t, func() { test.LoadScenario("paths") conn := test.OpenDatabase(test.StellarCoreDatabaseUrl()) defer conn.Close() finder := &Finder{ Ctx: test.Context(), SqlQuery: db.SqlQuery{conn}, } native := makeAsset(xdr.AssetTypeAssetTypeNative, "", "") usd := makeAsset( xdr.AssetTypeAssetTypeCreditAlphanum4, "USD", "GDSBCQO34HWPGUGQSP3QBFEXVTSR2PW46UIGTHVWGWJGQKH3AFNHXHXN") eur := makeAsset( xdr.AssetTypeAssetTypeCreditAlphanum4, "EUR", "GDSBCQO34HWPGUGQSP3QBFEXVTSR2PW46UIGTHVWGWJGQKH3AFNHXHXN") Convey("Find", func() { query := paths.Query{ DestinationAddress: "GAEDTJ4PPEFVW5XV2S7LUXBEHNQMX5Q2GM562RJGOQG7GVCE5H3HIB4V", DestinationAsset: eur, DestinationAmount: xdr.Int64(200000000), SourceAssets: []xdr.Asset{usd}, } paths, err := finder.Find(query) So(err, ShouldBeNil) So(len(paths), ShouldEqual, 4) query.DestinationAmount = xdr.Int64(200000001) paths, err = finder.Find(query) So(err, ShouldBeNil) So(len(paths), ShouldEqual, 2) query.DestinationAmount = xdr.Int64(500000001) paths, err = finder.Find(query) So(err, ShouldBeNil) So(len(paths), ShouldEqual, 0) }) Convey("regression: paths that involve native currencies can be found", func() { query := paths.Query{ DestinationAddress: "GDSBCQO34HWPGUGQSP3QBFEXVTSR2PW46UIGTHVWGWJGQKH3AFNHXHXN", DestinationAsset: native, DestinationAmount: xdr.Int64(1), SourceAssets: []xdr.Asset{usd, native}, } paths, err := finder.Find(query) So(err, ShouldBeNil) So(len(paths), ShouldEqual, 2) }) }) }
func TestEffectActions(t *testing.T) { test.LoadScenario("base") Convey("Effect Actions:", t, func() { app := NewTestApp() defer app.Close() rh := NewRequestHelper(app) Convey("GET /effects", func() { w := rh.Get("/effects?limit=20", test.RequestHelperNoop) So(w.Code, ShouldEqual, 200) So(w.Body, ShouldBePageOf, 11) // test streaming, regression for https://github.com/stellar/horizon/issues/147 w = rh.Get("/effects?limit=2", test.RequestHelperStreaming) So(w.Code, ShouldEqual, 200) }) Convey("GET /ledgers/:ledger_id/effects", func() { w := rh.Get("/ledgers/1/effects", test.RequestHelperNoop) So(w.Code, ShouldEqual, 200) So(w.Body, ShouldBePageOf, 0) w = rh.Get("/ledgers/2/effects", test.RequestHelperNoop) So(w.Code, ShouldEqual, 200) So(w.Body, ShouldBePageOf, 9) w = rh.Get("/ledgers/3/effects", test.RequestHelperNoop) So(w.Code, ShouldEqual, 200) So(w.Body, ShouldBePageOf, 2) }) Convey("GET /accounts/:account_id/effects", func() { w := rh.Get("/accounts/GBRPYHIL2CI3FNQ4BXLFMNDLFJUNPU2HY3ZMFSHONUCEOASW7QC7OX2H/effects", test.RequestHelperNoop) So(w.Code, ShouldEqual, 200) So(w.Body, ShouldBePageOf, 3) w = rh.Get("/accounts/GA5WBPYA5Y4WAEHXWR2UKO2UO4BUGHUQ74EUPKON2QHV4WRHOIRNKKH2/effects", test.RequestHelperNoop) So(w.Code, ShouldEqual, 200) So(w.Body, ShouldBePageOf, 2) w = rh.Get("/accounts/GCXKG6RN4ONIEPCMNFB732A436Z5PNDSRLGWK7GBLCMQLIFO4S7EYWVU/effects", test.RequestHelperNoop) So(w.Code, ShouldEqual, 200) So(w.Body, ShouldBePageOf, 3) }) Convey("GET /transactions/:tx_id/effects", func() { w := rh.Get("/transactions/2374e99349b9ef7dba9a5db3339b78fda8f34777b1af33ba468ad5c0df946d4d/effects", test.RequestHelperNoop) So(w.Code, ShouldEqual, 200) So(w.Body, ShouldBePageOf, 3) }) Convey("GET /operations/:op_id/effects", func() { w := rh.Get("/operations/8589938689/effects", test.RequestHelperNoop) So(w.Code, ShouldEqual, 200) So(w.Body, ShouldBePageOf, 3) }) }) }
func TestEffectActions(t *testing.T) { test.LoadScenario("base") Convey("Effect Actions:", t, func() { app := NewTestApp() defer app.Close() rh := NewRequestHelper(app) Convey("GET /effects", func() { w := rh.Get("/effects?limit=20", test.RequestHelperNoop) So(w.Code, ShouldEqual, 200) So(w.Body, ShouldBePageOf, 11) }) Convey("GET /ledgers/:ledger_id/effects", func() { w := rh.Get("/ledgers/1/effects", test.RequestHelperNoop) So(w.Code, ShouldEqual, 200) So(w.Body, ShouldBePageOf, 0) w = rh.Get("/ledgers/2/effects", test.RequestHelperNoop) So(w.Code, ShouldEqual, 200) So(w.Body, ShouldBePageOf, 9) w = rh.Get("/ledgers/3/effects", test.RequestHelperNoop) So(w.Code, ShouldEqual, 200) So(w.Body, ShouldBePageOf, 2) }) Convey("GET /accounts/:account_id/effects", func() { w := rh.Get("/accounts/GBRPYHIL2CI3FNQ4BXLFMNDLFJUNPU2HY3ZMFSHONUCEOASW7QC7OX2H/effects", test.RequestHelperNoop) So(w.Code, ShouldEqual, 200) So(w.Body, ShouldBePageOf, 3) w = rh.Get("/accounts/GA5WBPYA5Y4WAEHXWR2UKO2UO4BUGHUQ74EUPKON2QHV4WRHOIRNKKH2/effects", test.RequestHelperNoop) So(w.Code, ShouldEqual, 200) So(w.Body, ShouldBePageOf, 2) w = rh.Get("/accounts/GCXKG6RN4ONIEPCMNFB732A436Z5PNDSRLGWK7GBLCMQLIFO4S7EYWVU/effects", test.RequestHelperNoop) So(w.Code, ShouldEqual, 200) So(w.Body, ShouldBePageOf, 3) }) Convey("GET /transactions/:tx_id/effects", func() { w := rh.Get("/transactions/c492d87c4642815dfb3c7dcce01af4effd162b031064098a0d786b6e0a00fd74/effects", test.RequestHelperNoop) So(w.Code, ShouldEqual, 200) So(w.Body, ShouldBePageOf, 3) }) Convey("GET /operations/:op_id/effects", func() { w := rh.Get("/operations/8589938689/effects", test.RequestHelperNoop) So(w.Code, ShouldEqual, 200) So(w.Body, ShouldBePageOf, 3) }) }) }
func TestEffectPageQueryByOrderBook(t *testing.T) { test.LoadScenario("trades") Convey("EffectOrderBookFilter", t, func() { var records []EffectRecord Convey("restricts to order book properly", func() { q := EffectPageQuery{ SqlQuery: SqlQuery{history}, PageQuery: MustPageQuery("", "asc", 0), Filter: &EffectOrderBookFilter{ SellingType: xdr.AssetTypeAssetTypeCreditAlphanum4, SellingCode: "EUR", SellingIssuer: "GCQPYGH4K57XBDENKKX55KDTWOTK5WDWRQOH2LHEDX3EKVIQRLMESGBG", BuyingType: xdr.AssetTypeAssetTypeCreditAlphanum4, BuyingCode: "USD", BuyingIssuer: "GC23QF2HUE52AMXUFUH3AYJAXXGXXV2VHXYYR6EYXETPKDXZSAW67XO4", }, } MustSelect(ctx, q, &records) So(len(records), ShouldEqual, 1) r := records[0] var dets map[string]interface{} _ = r.UnmarshalDetails(&dets) So(dets["sold_asset_type"].(string), ShouldEqual, "credit_alphanum4") So(dets["sold_asset_code"], ShouldEqual, "EUR") So(dets["sold_asset_issuer"], ShouldEqual, "GCQPYGH4K57XBDENKKX55KDTWOTK5WDWRQOH2LHEDX3EKVIQRLMESGBG") So(dets["bought_asset_type"].(string), ShouldEqual, "credit_alphanum4") So(dets["bought_asset_code"], ShouldEqual, "USD") So(dets["bought_asset_issuer"], ShouldEqual, "GC23QF2HUE52AMXUFUH3AYJAXXGXXV2VHXYYR6EYXETPKDXZSAW67XO4") }) Convey("regression: does not crash when using a native asset", func() { q := EffectPageQuery{ SqlQuery: SqlQuery{history}, PageQuery: MustPageQuery("", "asc", 0), Filter: &EffectOrderBookFilter{ SellingType: xdr.AssetTypeAssetTypeNative, BuyingType: xdr.AssetTypeAssetTypeCreditAlphanum4, BuyingCode: "USD", BuyingIssuer: "GC23QF2HUE52AMXUFUH3AYJAXXGXXV2VHXYYR6EYXETPKDXZSAW67XO4", }, } MustSelect(ctx, q, &records) }) }) }
func TestRootAction(t *testing.T) { Convey("GET /", t, func() { test.LoadScenario("base") app := NewTestApp() defer app.Close() rh := NewRequestHelper(app) w := rh.Get("/", test.RequestHelperNoop) So(w.Code, ShouldEqual, 200) }) }
func TestLedgerState(t *testing.T) { test.LoadScenario("base") horizon := OpenTestDatabase() defer horizon.Close() core := OpenStellarCoreTestDatabase() defer core.Close() Convey("db.UpdateLedgerState", t, func() { So(horizonLedgerGauge.Value(), ShouldEqual, 0) So(stellarCoreLedgerGauge.Value(), ShouldEqual, 0) UpdateLedgerState(test.Context(), SqlQuery{horizon}, SqlQuery{core}) So(horizonLedgerGauge.Value(), ShouldEqual, 3) So(stellarCoreLedgerGauge.Value(), ShouldEqual, 3) }) }
func TestLedgerStateQuery(t *testing.T) { test.LoadScenario("base") Convey("LedgerStateQuery", t, func() { var ls LedgerState q := LedgerStateQuery{ SqlQuery{history}, SqlQuery{core}, } err := Get(ctx, q, &ls) So(err, ShouldBeNil) So(ls.HorizonSequence, ShouldEqual, 3) So(ls.StellarCoreSequence, ShouldEqual, 3) }) }
func TestOfferActions(t *testing.T) { test.LoadScenario("trades") app := NewTestApp() defer app.Close() rh := NewRequestHelper(app) Convey("Offer Actions:", t, func() { Convey("GET /accounts/GA5WBPYA5Y4WAEHXWR2UKO2UO4BUGHUQ74EUPKON2QHV4WRHOIRNKKH2/offers", func() { w := rh.Get("/accounts/GA5WBPYA5Y4WAEHXWR2UKO2UO4BUGHUQ74EUPKON2QHV4WRHOIRNKKH2/offers", test.RequestHelperNoop) So(w.Code, ShouldEqual, 200) So(w.Body, ShouldBePageOf, 3) }) }) }
func TestOrderBook(t *testing.T) { Convey("orderBook", t, func() { test.LoadScenario("paths") conn := test.OpenDatabase(test.StellarCoreDatabaseUrl()) defer conn.Close() ob := orderBook{ Selling: makeAsset( xdr.AssetTypeAssetTypeCreditAlphanum4, "EUR", "GDSBCQO34HWPGUGQSP3QBFEXVTSR2PW46UIGTHVWGWJGQKH3AFNHXHXN"), Buying: makeAsset( xdr.AssetTypeAssetTypeCreditAlphanum4, "USD", "GDSBCQO34HWPGUGQSP3QBFEXVTSR2PW46UIGTHVWGWJGQKH3AFNHXHXN"), DB: db.SqlQuery{conn}, } Convey("Cost", func() { r, err := ob.Cost(ob.Buying, 10) So(err, ShouldBeNil) So(r, ShouldEqual, xdr.Int64(10)) // this cost should consume the entire lowest priced order, whose price // is 1.0, thus the output should be the same r, err = ob.Cost(ob.Buying, 100000000) So(err, ShouldBeNil) So(r, ShouldEqual, xdr.Int64(100000000)) // now we are taking from the next offer, where the price is 2.0 r, err = ob.Cost(ob.Buying, 100000001) So(err, ShouldBeNil) So(r, ShouldEqual, xdr.Int64(100000002)) r, err = ob.Cost(ob.Buying, 500000000) So(err, ShouldBeNil) So(r, ShouldEqual, xdr.Int64(900000000)) r, err = ob.Cost(ob.Buying, 500000001) So(err, ShouldNotBeNil) }) }) }
func TestTransactionByHashQuery(t *testing.T) { Convey("TransactionByHashQuery", t, func() { test.LoadScenario("base") var record TransactionRecord Convey("Existing record behavior", func() { hash := "c492d87c4642815dfb3c7dcce01af4effd162b031064098a0d786b6e0a00fd74" q := TransactionByHashQuery{SqlQuery{history}, hash} err := Get(ctx, q, &record) So(err, ShouldBeNil) So(record.TransactionHash, ShouldEqual, hash) }) Convey("Missing record behavior", func() { hash := "not_real" q := TransactionByHashQuery{SqlQuery{history}, hash} err := Get(ctx, q, &record) So(err, ShouldEqual, ErrNoResults) }) }) }
func TestTransactionByHashQuery(t *testing.T) { Convey("TransactionByHashQuery", t, func() { test.LoadScenario("base") var record TransactionRecord Convey("Existing record behavior", func() { hash := "2374e99349b9ef7dba9a5db3339b78fda8f34777b1af33ba468ad5c0df946d4d" q := TransactionByHashQuery{SqlQuery{history}, hash} err := Get(ctx, q, &record) So(err, ShouldBeNil) So(record.TransactionHash, ShouldEqual, hash) }) Convey("Missing record behavior", func() { hash := "not_real" q := TransactionByHashQuery{SqlQuery{history}, hash} err := Get(ctx, q, &record) So(err, ShouldEqual, ErrNoResults) }) }) }
func TestCoreTrustlinesByAddressQuery(t *testing.T) { test.LoadScenario("non_native_payment") Convey("CoreTrustlinesByAddress", t, func() { var tls []CoreTrustlineRecord withtl := "GBXGQJWVLWOYHFLVTKWV5FGHA3LNYY2JQKM7OAJAUEQFU6LPCSEFVXON" notl := "GBRPYHIL2CI3FNQ4BXLFMNDLFJUNPU2HY3ZMFSHONUCEOASW7QC7OX2H" q := CoreTrustlinesByAddressQuery{ SqlQuery{core}, withtl, } err := Select(ctx, q, &tls) So(err, ShouldBeNil) So(len(tls), ShouldEqual, 1) tl := tls[0] So(tl.Accountid, ShouldEqual, withtl) So(tl.Issuer, ShouldEqual, "GC23QF2HUE52AMXUFUH3AYJAXXGXXV2VHXYYR6EYXETPKDXZSAW67XO4") So(tl.Balance, ShouldEqual, 500000000) So(tl.Tlimit, ShouldEqual, 9223372036854775807) So(tl.Assetcode, ShouldEqual, "USD") q = CoreTrustlinesByAddressQuery{ SqlQuery{core}, notl, } err = Select(ctx, q, &tls) So(err, ShouldBeNil) t.Log(tls) So(len(tls), ShouldEqual, 0) }) }
func TestRootAction(t *testing.T) { Convey("GET /", t, func() { test.LoadScenario("base") app := NewTestApp() app.coreVersion = "test-core" app.horizonVersion = "test-horizon" defer app.Close() rh := NewRequestHelper(app) w := rh.Get("/", test.RequestHelperNoop) So(w.Code, ShouldEqual, 200) var result resource.Root err := json.Unmarshal(w.Body.Bytes(), &result) So(err, ShouldBeNil) So(result.HorizonVersion, ShouldEqual, "test-horizon") So(result.StellarCoreVersion, ShouldEqual, "test-core") }) }
func TestOperationPageQuery(t *testing.T) { test.LoadScenario("base") Convey("OperationPageQuery", t, func() { var records []OperationRecord makeQuery := func(c string, o string, l int32) OperationPageQuery { pq, err := NewPageQuery(c, o, l) So(err, ShouldBeNil) return OperationPageQuery{ SqlQuery: SqlQuery{history}, PageQuery: pq, } } Convey("orders properly", func() { // asc orders ascending by id MustSelect(ctx, makeQuery("", "asc", 0), &records) So(records, ShouldBeOrderedAscending, func(r interface{}) int64 { So(r, ShouldHaveSameTypeAs, OperationRecord{}) return r.(OperationRecord).Id }) // desc orders descending by id MustSelect(ctx, makeQuery("", "desc", 0), &records) So(records, ShouldBeOrderedDescending, func(r interface{}) int64 { So(r, ShouldHaveSameTypeAs, OperationRecord{}) return r.(OperationRecord).Id }) }) Convey("limits properly", func() { // returns number specified MustSelect(ctx, makeQuery("", "asc", 3), &records) So(len(records), ShouldEqual, 3) // returns all rows if limit is higher MustSelect(ctx, makeQuery("", "asc", 10), &records) So(len(records), ShouldEqual, 4) }) Convey("cursor works properly", func() { var record OperationRecord // lowest id if ordered ascending and no cursor MustGet(ctx, makeQuery("", "asc", 0), &record) So(record.Id, ShouldEqual, 8589938689) // highest id if ordered descending and no cursor MustGet(ctx, makeQuery("", "desc", 0), &record) So(record.Id, ShouldEqual, 12884905985) // starts after the cursor if ordered ascending MustGet(ctx, makeQuery("8589938689", "asc", 0), &record) So(record.Id, ShouldEqual, 8589942785) // starts before the cursor if ordered descending MustGet(ctx, makeQuery("12884905985", "desc", 0), &record) So(record.Id, ShouldEqual, 8589946881) }) Convey("restricts to address properly", func() { address := "GBXGQJWVLWOYHFLVTKWV5FGHA3LNYY2JQKM7OAJAUEQFU6LPCSEFVXON" q := makeQuery("", "asc", 0) q.AccountAddress = address MustSelect(ctx, q, &records) So(len(records), ShouldEqual, 2) So(records[0].Id, ShouldEqual, 8589946881) So(records[1].Id, ShouldEqual, 12884905985) }) Convey("restricts to ledger properly", func() { q := makeQuery("", "asc", 0) q.LedgerSequence = 2 MustSelect(ctx, q, &records) So(len(records), ShouldEqual, 3) for _, r := range records { toid := ParseTotalOrderId(r.TransactionId) So(toid.LedgerSequence, ShouldEqual, 2) } }) Convey("restricts to transaction properly", func() { q := makeQuery("", "asc", 0) q.TransactionHash = "2374e99349b9ef7dba9a5db3339b78fda8f34777b1af33ba468ad5c0df946d4d" MustSelect(ctx, q, &records) So(len(records), ShouldEqual, 1) for _, r := range records { So(r.TransactionId, ShouldEqual, 8589938688) } }) Convey("errors if more than one filter is supplied", func() { table := []struct { Hash string Ledger int32 Address string }{ {"1", 1, "1"}, {"", 1, "1"}, {"1", 1, ""}, {"1", 0, "1"}, } for _, o := range table { q := makeQuery("", "asc", 0) q.TransactionHash = o.Hash q.LedgerSequence = o.Ledger q.AccountAddress = o.Address err := Select(ctx, q, &records) So(err, ShouldNotBeNil) } }) Convey("obeys the type filter", func() { test.LoadScenario("pathed_payment") q := makeQuery("", "asc", 0) q.TypeFilter = PaymentTypeFilter MustSelect(ctx, q, &records) So(len(records), ShouldEqual, 10) }) }) }
func TestOperationActions(t *testing.T) { test.LoadScenario("base") Convey("Operation Actions:", t, func() { app := NewTestApp() defer app.Close() rh := NewRequestHelper(app) Convey("GET /operations", func() { w := rh.Get("/operations", test.RequestHelperNoop) So(w.Code, ShouldEqual, 200) So(w.Body, ShouldBePageOf, 4) }) Convey("GET /ledgers/:ledger_id/operations", func() { w := rh.Get("/ledgers/1/operations", test.RequestHelperNoop) So(w.Code, ShouldEqual, 200) So(w.Body, ShouldBePageOf, 0) w = rh.Get("/ledgers/2/operations", test.RequestHelperNoop) So(w.Code, ShouldEqual, 200) So(w.Body, ShouldBePageOf, 3) w = rh.Get("/ledgers/3/operations", test.RequestHelperNoop) So(w.Code, ShouldEqual, 200) So(w.Body, ShouldBePageOf, 1) }) Convey("GET /accounts/:account_id/operations", func() { w := rh.Get("/accounts/GBRPYHIL2CI3FNQ4BXLFMNDLFJUNPU2HY3ZMFSHONUCEOASW7QC7OX2H/operations", test.RequestHelperNoop) So(w.Code, ShouldEqual, 200) So(w.Body, ShouldBePageOf, 3) w = rh.Get("/accounts/GA5WBPYA5Y4WAEHXWR2UKO2UO4BUGHUQ74EUPKON2QHV4WRHOIRNKKH2/operations", test.RequestHelperNoop) So(w.Code, ShouldEqual, 200) So(w.Body, ShouldBePageOf, 1) w = rh.Get("/accounts/GCXKG6RN4ONIEPCMNFB732A436Z5PNDSRLGWK7GBLCMQLIFO4S7EYWVU/operations", test.RequestHelperNoop) So(w.Code, ShouldEqual, 200) So(w.Body, ShouldBePageOf, 2) }) Convey("GET /transactions/:tx_id/operations", func() { w := rh.Get("/transactions/c492d87c4642815dfb3c7dcce01af4effd162b031064098a0d786b6e0a00fd74/operations", test.RequestHelperNoop) So(w.Code, ShouldEqual, 200) So(w.Body, ShouldBePageOf, 1) w = rh.Get("/transactions/f70627f6d076a346902bdeaa0d55d8403dfcbdfad1c79d58baf54031a5c477ce/operations", test.RequestHelperNoop) So(w.Code, ShouldEqual, 200) So(w.Body, ShouldBePageOf, 1) }) Convey("GET /operations/:id", func() { w := rh.Get("/operations/8589938689", test.RequestHelperNoop) So(w.Code, ShouldEqual, 200) var result OperationResource err := json.Unmarshal(w.Body.Bytes(), &result) So(err, ShouldBeNil) So(result["paging_token"], ShouldEqual, "8589938689") w = rh.Get("/operations/10", test.RequestHelperNoop) So(w.Code, ShouldEqual, 404) }) Convey("GET /ledgers/100/operations", func() { w := rh.Get("/ledgers/100/operations", test.RequestHelperNoop) So(w.Code, ShouldEqual, 404) }) }) }
func TestDBPackage(t *testing.T) { test.LoadScenario("non_native_payment") Convey("db.Select", t, func() { Convey("overwrites the destination", func() { records := []mockResult{{1}, {2}} query := &mockQuery{5} err := Select(ctx, query, &records) So(err, ShouldBeNil) So(len(records), ShouldEqual, 5) }) Convey("works on []interface{} destinations", func() { var records []mockResult query := &mockQuery{5} err := Select(ctx, query, &records) So(err, ShouldBeNil) So(len(records), ShouldEqual, 5) }) Convey("returns an error when the provided destination is nil", func() { query := &mockQuery{5} err := Select(ctx, query, nil) So(err, test.ShouldBeErr, ErrDestinationNil) }) Convey("returns an error when the provided destination is not a pointer", func() { var records []mockResult query := &mockQuery{5} err := Select(ctx, query, records) So(err, test.ShouldBeErr, ErrDestinationNotPointer) }) Convey("returns an error when the provided destination is not a slice", func() { var records string query := &mockQuery{5} err := Select(ctx, query, &records) So(err, test.ShouldBeErr, ErrDestinationNotSlice) }) Convey("returns an error when the provided destination is a slice of an invalid type", func() { var records []string query := &mockQuery{5} err := Select(ctx, query, &records) So(err, test.ShouldBeErr, ErrDestinationIncompatible) }) }) Convey("db.Get", t, func() { var result mockResult Convey("returns the first record", func() { So(Get(ctx, &mockQuery{2}, &result), ShouldBeNil) So(result, ShouldResemble, mockResult{0}) }) Convey("Missing records returns nil", func() { So(Get(ctx, &mockQuery{0}, &result), test.ShouldBeErr, ErrNoResults) }) Convey("Properly forwards non-RecordNotFound errors", func() { query := &BrokenQuery{errors.New("Some error")} So(Get(ctx, query, &result).Error(), ShouldEqual, "Some error") }) }) }
func TestOrderBookActions(t *testing.T) { test.LoadScenario("order_books") app := NewTestApp() defer app.Close() rh := NewRequestHelper(app) Convey("Order Book Actions:", t, func() { Convey("(no query args): GET /order_book", func() { w := rh.Get("/order_book", test.RequestHelperNoop) So(w.Code, ShouldEqual, 400) So(w.Body, ShouldBeProblem, problem.P{Type: "invalid_order_book"}) }) Convey("(missing currency): GET /order_book?selling_asset_type=native", func() { w := rh.Get("/order_book?selling_asset_type=native", test.RequestHelperNoop) So(w.Code, ShouldEqual, 400) So(w.Body, ShouldBeProblem, problem.P{Type: "invalid_order_book"}) }) Convey("(invalid type): GET /order_book?selling_asset_type=native&buying_asset_type=nothing", func() { w := rh.Get("/order_book?selling_asset_type=native&buying_asset_type=nothing", test.RequestHelperNoop) So(w.Code, ShouldEqual, 400) So(w.Body, ShouldBeProblem, problem.P{Type: "invalid_order_book"}) w = rh.Get("/order_book?selling_asset_type=nothing&buying_asset_type=native", test.RequestHelperNoop) So(w.Code, ShouldEqual, 400) So(w.Body, ShouldBeProblem, problem.P{Type: "invalid_order_book"}) }) Convey("(missing code): GET /order_book?selling_asset_type=native&buying_asset_type=credit_alphanum4&buying_asset_issuer=123", func() { w := rh.Get("/order_book?selling_asset_type=native&buying_asset_type=credit_alphanum4&buying_asset_issuer=123", test.RequestHelperNoop) So(w.Code, ShouldEqual, 400) So(w.Body, ShouldBeProblem, problem.P{Type: "invalid_order_book"}) w = rh.Get("/order_book?buying_asset_type=native&selling_asset_type=credit_alphanum4&selling_asset_issuer=123", test.RequestHelperNoop) So(w.Code, ShouldEqual, 400) So(w.Body, ShouldBeProblem, problem.P{Type: "invalid_order_book"}) }) Convey("(missing issuer): GET /order_book?selling_asset_type=native&buying_asset_type=credit_alphanum4&buying_asset_code=USD", func() { w := rh.Get("/order_book?selling_asset_type=native&buying_asset_type=credit_alphanum4&buying_asset_code=USD", test.RequestHelperNoop) So(w.Code, ShouldEqual, 400) So(w.Body, ShouldBeProblem, problem.P{Type: "invalid_order_book"}) w = rh.Get("/order_book?buying_asset_type=native&selling_asset_type=credit_alphanum4&selling_asset_code=USD", test.RequestHelperNoop) So(w.Code, ShouldEqual, 400) So(w.Body, ShouldBeProblem, problem.P{Type: "invalid_order_book"}) }) Convey("(same currency): GET /order_book?selling_asset_type=native&buying_asset_type=native", func() { w := rh.Get("/order_book?selling_asset_type=native&buying_asset_type=native", test.RequestHelperNoop) So(w.Code, ShouldEqual, 200) var result map[string]interface{} err := json.Unmarshal(w.Body.Bytes(), &result) So(err, ShouldBeNil) // ensure bids and asks are empty prices := result["asks"].([]interface{}) So(len(prices), ShouldEqual, 0) prices = result["bids"].([]interface{}) So(len(prices), ShouldEqual, 0) }) Convey("(incomplete currency): GET /order_book?selling_asset_type=native&buying_asset_type=credit_alphanum4&buying_asset_code=USD", func() { w := rh.Get("/order_book?selling_asset_type=native&buying_asset_type=credit_alphanum4&buying_asset_code=USD", test.RequestHelperNoop) So(w.Code, ShouldEqual, 400) So(w.Body, ShouldBeProblem, problem.P{Type: "invalid_order_book"}) }) Convey("(happy path): GET /order_book?selling_asset_type=native&buying_asset_type=credit_alphanum4&buying_asset_code=USD&buying_asset_issuer=GC23QF2HUE52AMXUFUH3AYJAXXGXXV2VHXYYR6EYXETPKDXZSAW67XO4", func() { w := rh.Get("/order_book?selling_asset_type=native&buying_asset_type=credit_alphanum4&buying_asset_code=USD&buying_asset_issuer=GC23QF2HUE52AMXUFUH3AYJAXXGXXV2VHXYYR6EYXETPKDXZSAW67XO4", test.RequestHelperNoop) t.Log(w.Body.String()) So(w.Code, ShouldEqual, 200) var result resource.OrderBookSummary err := json.Unmarshal(w.Body.Bytes(), &result) So(err, ShouldBeNil) So(result.Selling.Type, ShouldEqual, "native") So(result.Selling.Code, ShouldEqual, "") So(result.Selling.Issuer, ShouldEqual, "") So(result.Buying.Type, ShouldEqual, "credit_alphanum4") So(result.Buying.Code, ShouldEqual, "USD") So(result.Buying.Issuer, ShouldEqual, "GC23QF2HUE52AMXUFUH3AYJAXXGXXV2VHXYYR6EYXETPKDXZSAW67XO4") So(len(result.Asks), ShouldEqual, 3) So(len(result.Bids), ShouldEqual, 3) So(result.Asks[0].Amount, ShouldEqual, "1.0000000") So(result.Asks[1].Amount, ShouldEqual, "11.0000000") So(result.Asks[2].Amount, ShouldEqual, "200.0000000") So(result.Bids[0].Amount, ShouldEqual, "10.0000000") So(result.Bids[1].Amount, ShouldEqual, "100.0000000") So(result.Bids[2].Amount, ShouldEqual, "1000.0000000") }) }) }
func TestApp(t *testing.T) { Convey("NewApp establishes the app in its context", t, func() { app, err := NewApp(NewTestConfig()) So(err, ShouldBeNil) defer app.Close() found, ok := AppFromContext(app.ctx) So(ok, ShouldBeTrue) So(found, ShouldEqual, app) }) Convey("NewApp panics if the provided config's SentryDSN is invalid", t, func() { config := NewTestConfig() config.SentryDSN = "Not a url" So(func() { app, _ := NewApp(config) app.Close() }, ShouldPanic) }) Convey("CORS support", t, func() { app := NewTestApp() defer app.Close() rh := NewRequestHelper(app) w := rh.Get("/", test.RequestHelperNoop) So(w.Code, ShouldEqual, 200) So(w.HeaderMap.Get("Access-Control-Allow-Origin"), ShouldEqual, "") w = rh.Get("/", func(r *http.Request) { r.Header.Set("Origin", "somewhere.com") }) So(w.Code, ShouldEqual, 200) So(w.HeaderMap.Get("Access-Control-Allow-Origin"), ShouldEqual, "somewhere.com") }) Convey("Trailing slash causes redirect", t, func() { test.LoadScenario("base") app := NewTestApp() defer app.Close() rh := NewRequestHelper(app) w := rh.Get("/accounts", test.RequestHelperNoop) So(w.Code, ShouldEqual, 200) w = rh.Get("/accounts/", test.RequestHelperNoop) So(w.Code, ShouldEqual, 200) }) Convey("app.UpdateMetrics", t, func() { test.LoadScenario("base") app := NewTestApp() defer app.Close() So(app.horizonLedgerGauge.Value(), ShouldEqual, 0) So(app.stellarCoreLedgerGauge.Value(), ShouldEqual, 0) app.UpdateMetrics(test.Context()) So(app.horizonLedgerGauge.Value(), ShouldEqual, 3) So(app.stellarCoreLedgerGauge.Value(), ShouldEqual, 3) }) }