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 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 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 AccountResource 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, 3) w = rh.Get("/accounts?limit=1", test.RequestHelperNoop) So(w.Code, ShouldEqual, 200) So(w.Body, ShouldBePageOf, 1) }) }) }
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 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 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 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 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 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 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 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 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 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 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 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] dets, _ := r.Details() 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") }) }) }
func TestCoreOfferPageByAddressQuery(t *testing.T) { test.LoadScenario("trades") Convey("CoreOfferPageByAddressQuery", t, func() { makeQuery := func(c string, o string, l int32, a string) CoreOfferPageByAddressQuery { pq, err := NewPageQuery(c, o, l) So(err, ShouldBeNil) return CoreOfferPageByAddressQuery{ SqlQuery: SqlQuery{core}, PageQuery: pq, Address: a, } } var records []CoreOfferRecord Convey("works with native offers", func() { MustSelect(ctx, makeQuery("", "asc", 0, "GCXKG6RN4ONIEPCMNFB732A436Z5PNDSRLGWK7GBLCMQLIFO4S7EYWVU"), &records) So(len(records), ShouldEqual, 1) }) Convey("filters properly", func() { MustSelect(ctx, makeQuery("", "desc", 0, "GBRPYHIL2CI3FNQ4BXLFMNDLFJUNPU2HY3ZMFSHONUCEOASW7QC7OX2H"), &records) So(len(records), ShouldEqual, 0) MustSelect(ctx, makeQuery("", "asc", 0, "GA5WBPYA5Y4WAEHXWR2UKO2UO4BUGHUQ74EUPKON2QHV4WRHOIRNKKH2"), &records) So(len(records), ShouldEqual, 3) }) Convey("orders properly", func() { // asc orders ascending by id MustSelect(ctx, makeQuery("", "asc", 0, "GA5WBPYA5Y4WAEHXWR2UKO2UO4BUGHUQ74EUPKON2QHV4WRHOIRNKKH2"), &records) So(records, ShouldBeOrderedAscending, func(r interface{}) int64 { So(r, ShouldHaveSameTypeAs, CoreOfferRecord{}) return r.(CoreOfferRecord).OfferID }) // desc orders descending by id MustSelect(ctx, makeQuery("", "desc", 0, "GA5WBPYA5Y4WAEHXWR2UKO2UO4BUGHUQ74EUPKON2QHV4WRHOIRNKKH2"), &records) So(records, ShouldBeOrderedDescending, func(r interface{}) int64 { So(r, ShouldHaveSameTypeAs, CoreOfferRecord{}) return r.(CoreOfferRecord).OfferID }) }) Convey("limits properly", func() { // returns number specified MustSelect(ctx, makeQuery("", "asc", 2, "GA5WBPYA5Y4WAEHXWR2UKO2UO4BUGHUQ74EUPKON2QHV4WRHOIRNKKH2"), &records) So(len(records), ShouldEqual, 2) // returns all rows if limit is higher MustSelect(ctx, makeQuery("", "asc", 10, "GA5WBPYA5Y4WAEHXWR2UKO2UO4BUGHUQ74EUPKON2QHV4WRHOIRNKKH2"), &records) So(len(records), ShouldEqual, 3) }) Convey("cursor works properly", func() { var record CoreOfferRecord // lowest id if ordered ascending and no cursor MustGet(ctx, makeQuery("", "asc", 0, "GA5WBPYA5Y4WAEHXWR2UKO2UO4BUGHUQ74EUPKON2QHV4WRHOIRNKKH2"), &record) So(record.OfferID, ShouldEqual, 1) // highest id if ordered descending and no cursor MustGet(ctx, makeQuery("", "desc", 0, "GA5WBPYA5Y4WAEHXWR2UKO2UO4BUGHUQ74EUPKON2QHV4WRHOIRNKKH2"), &record) So(record.OfferID, ShouldEqual, 3) // starts after the cursor if ordered ascending MustGet(ctx, makeQuery("1", "asc", 0, "GA5WBPYA5Y4WAEHXWR2UKO2UO4BUGHUQ74EUPKON2QHV4WRHOIRNKKH2"), &record) So(record.OfferID, ShouldEqual, 2) // starts before the cursor if ordered descending MustGet(ctx, makeQuery("3", "desc", 0, "GA5WBPYA5Y4WAEHXWR2UKO2UO4BUGHUQ74EUPKON2QHV4WRHOIRNKKH2"), &record) So(record.OfferID, ShouldEqual, 2) }) }) }
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 = "c492d87c4642815dfb3c7dcce01af4effd162b031064098a0d786b6e0a00fd74" 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 TestTransactionPageQuery(t *testing.T) { test.LoadScenario("base") Convey("TransactionPageQuery", t, func() { var records []TransactionRecord makeQuery := func(c string, o string, l int32) TransactionPageQuery { pq, err := NewPageQuery(c, o, l) So(err, ShouldBeNil) return TransactionPageQuery{ 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, TransactionRecord{}) return r.(TransactionRecord).Id }) // desc orders descending by id MustSelect(ctx, makeQuery("", "desc", 0), &records) So(records, ShouldBeOrderedDescending, func(r interface{}) int64 { So(r, ShouldHaveSameTypeAs, TransactionRecord{}) return r.(TransactionRecord).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 TransactionRecord // lowest id if ordered ascending and no cursor MustGet(ctx, makeQuery("", "asc", 0), &record) So(record.Id, ShouldEqual, 8589938688) // highest id if ordered descending and no cursor MustGet(ctx, makeQuery("", "desc", 0), &record) So(record.Id, ShouldEqual, 12884905984) // starts after the cursor if ordered ascending MustGet(ctx, makeQuery("8589938688", "asc", 0), &record) So(record.Id, ShouldEqual, 8589942784) // starts before the cursor if ordered descending MustGet(ctx, makeQuery("12884905984", "desc", 0), &record) So(record.Id, ShouldEqual, 8589946880) }) Convey("restricts to address properly", func() { address := "GBRPYHIL2CI3FNQ4BXLFMNDLFJUNPU2HY3ZMFSHONUCEOASW7QC7OX2H" q := makeQuery("", "asc", 0) q.AccountAddress = address MustSelect(ctx, q, &records) So(len(records), ShouldEqual, 3) for _, r := range records { So(r.Account, ShouldEqual, address) } }) Convey("restricts to ledger properly", func() { q := makeQuery("", "asc", 0) q.LedgerSequence = 3 MustSelect(ctx, q, &records) So(len(records), ShouldEqual, 1) for _, r := range records { So(r.LedgerSequence, ShouldEqual, q.LedgerSequence) } }) }) }
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, ShouldEqual, 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, ShouldEqual, 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, ShouldEqual, 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, ShouldEqual, 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), ShouldEqual, ErrNoResults) }) Convey("Properly forwards non-RecordNotFound errors", func() { query := &BrokenQuery{errors.New("Some error")} So(Get(ctx, query, &result).Error(), ShouldEqual, "Some error") }) }) }
func TestOrderBookSummaryQuery(t *testing.T) { Convey("OrderBookSummaryQuery", t, func() { test.LoadScenario("order_books") q := OrderBookSummaryQuery{ SqlQuery: SqlQuery{core}, SellingType: xdr.AssetTypeAssetTypeCreditAlphanum4, SellingCode: "USD", SellingIssuer: "GC23QF2HUE52AMXUFUH3AYJAXXGXXV2VHXYYR6EYXETPKDXZSAW67XO4", BuyingType: xdr.AssetTypeAssetTypeNative, } Convey("loads correctly", func() { var result OrderBookSummaryRecord So(Select(ctx, q, &result), ShouldBeNil) asks := result.Asks() bids := result.Bids() So(asks[0].Amount, ShouldEqual, 10) So(asks[0].Pricen, ShouldEqual, 15) So(asks[0].Priced, ShouldEqual, 1) So(asks[1].Amount, ShouldEqual, 100) So(asks[1].Pricen, ShouldEqual, 20) So(asks[1].Priced, ShouldEqual, 1) So(asks[2].Amount, ShouldEqual, 1000) So(asks[2].Pricen, ShouldEqual, 50) So(asks[2].Priced, ShouldEqual, 1) So(bids[0].Amount, ShouldEqual, 1) So(bids[0].Pricen, ShouldEqual, 10) So(bids[0].Priced, ShouldEqual, 1) So(bids[1].Amount, ShouldEqual, 11) So(bids[1].Pricen, ShouldEqual, 9) So(bids[1].Priced, ShouldEqual, 1) So(bids[2].Amount, ShouldEqual, 200) So(bids[2].Pricen, ShouldEqual, 5) So(bids[2].Priced, ShouldEqual, 1) }) Convey("works in either direction", func() { var result OrderBookSummaryRecord var inversion OrderBookSummaryRecord So(Select(ctx, q, &result), ShouldBeNil) So(Select(ctx, q.Invert(), &inversion), ShouldBeNil) asks := result.Asks() bids := result.Bids() iasks := inversion.Asks() ibids := inversion.Bids() So(len(result), ShouldEqual, 6) So(len(inversion), ShouldEqual, 6) // the asks of one side are the bids on the other So(asks[0].Pricef, ShouldEqual, ibids[0].InvertPricef()) So(asks[1].Pricef, ShouldEqual, ibids[1].InvertPricef()) So(asks[2].Pricef, ShouldEqual, ibids[2].InvertPricef()) So(bids[0].Pricef, ShouldEqual, iasks[0].InvertPricef()) So(bids[1].Pricef, ShouldEqual, iasks[1].InvertPricef()) So(bids[2].Pricef, ShouldEqual, iasks[2].InvertPricef()) }) Convey("Invert()", func() { q2 := q.Invert() So(q2.SellingType, ShouldEqual, q.BuyingType) So(q2.SellingCode, ShouldEqual, q.BuyingCode) So(q2.SellingIssuer, ShouldEqual, q.BuyingIssuer) So(q2.BuyingType, ShouldEqual, q.SellingType) So(q2.BuyingCode, ShouldEqual, q.SellingCode) So(q2.BuyingIssuer, ShouldEqual, q.SellingIssuer) }) }) }
func TestEffectPageQuery(t *testing.T) { test.LoadScenario("base") Convey("EffectPageQuery", t, func() { var records []EffectRecord makeQuery := func(c string, o string, l int32) EffectPageQuery { pq := MustPageQuery(c, o, l) return EffectPageQuery{ SqlQuery: SqlQuery{history}, PageQuery: pq, } } Convey("orders properly", func() { // asc orders ascending by operation_id, order MustSelect(ctx, makeQuery("", "asc", 0), &records) var cmp OrderComparator = func(idx int, l, r interface{}) string { leff := l.(EffectRecord) reff := r.(EffectRecord) if leff.ID() > reff.ID() { return fmt.Sprintf("effects are not in order: %s %s", leff.ID(), reff.ID()) } return "" } So(records, ShouldBeOrdered, cmp) // desc orders descending by id MustSelect(ctx, makeQuery("", "desc", 0), &records) cmp = func(idx int, l, r interface{}) string { leff := l.(EffectRecord) reff := r.(EffectRecord) if leff.ID() < reff.ID() { return fmt.Sprintf("effects are not in order: %s %s", leff.ID(), reff.ID()) } return "" } So(records, ShouldBeOrdered, cmp) }) 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", 20), &records) So(len(records), ShouldEqual, 11) }) Convey("cursor works properly", func() { var record EffectRecord // lowest id if ordered ascending and no cursor MustGet(ctx, makeQuery("", "asc", 0), &record) So(record.HistoryOperationID, ShouldEqual, 8589938689) So(record.Order, ShouldEqual, 1) // highest id if ordered descending and no cursor MustGet(ctx, makeQuery("", "desc", 0), &record) So(record.HistoryOperationID, ShouldEqual, 12884905985) So(record.Order, ShouldEqual, 2) // starts after the cursor if ordered ascending MustGet(ctx, makeQuery("8589938689-1", "asc", 0), &record) So(record.HistoryOperationID, ShouldEqual, 8589938689) So(record.Order, ShouldEqual, 2) // starts before the cursor if ordered descending MustGet(ctx, makeQuery("12884905985-2", "desc", 0), &record) So(record.HistoryOperationID, ShouldEqual, 12884905985) So(record.Order, ShouldEqual, 1) }) Convey("restricts to address properly", func() { address := "GCXKG6RN4ONIEPCMNFB732A436Z5PNDSRLGWK7GBLCMQLIFO4S7EYWVU" q := makeQuery("", "asc", 0) q.Filter = &EffectAccountFilter{q.SqlQuery, address} MustSelect(ctx, q, &records) So(len(records), ShouldEqual, 3) So(records[0].HistoryAccountID, ShouldEqual, 8589938689) So(records[1].HistoryAccountID, ShouldEqual, 8589938689) So(records[2].HistoryAccountID, ShouldEqual, 8589938689) }) Convey("restricts to ledger properly", func() { q := makeQuery("", "asc", 0) q.Filter = &EffectLedgerFilter{3} MustSelect(ctx, q, &records) So(len(records), ShouldEqual, 2) for _, r := range records { toid := ParseTotalOrderId(r.HistoryOperationID) So(toid.LedgerSequence, ShouldEqual, 3) } }) Convey("restricts to operation properly", func() { q := makeQuery("", "asc", 0) q.Filter = &EffectOperationFilter{8589938689} MustSelect(ctx, q, &records) So(len(records), ShouldEqual, 3) for _, r := range records { toid := ParseTotalOrderId(r.HistoryOperationID) So(toid.LedgerSequence, ShouldEqual, 2) So(toid.TransactionOrder, ShouldEqual, 1) So(toid.OperationOrder, ShouldEqual, 1) } }) Convey("restricts to transaction properly", func() { q := makeQuery("", "asc", 0) hash := "c492d87c4642815dfb3c7dcce01af4effd162b031064098a0d786b6e0a00fd74" q.Filter = &EffectTransactionFilter{q.SqlQuery, hash} MustSelect(ctx, q, &records) So(len(records), ShouldEqual, 3) for _, r := range records { toid := ParseTotalOrderId(r.HistoryOperationID) So(toid.LedgerSequence, ShouldEqual, 2) So(toid.TransactionOrder, ShouldEqual, 1) } }) }) }
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 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 OrderBookSummaryResource err := json.Unmarshal(w.Body.Bytes(), &result) So(err, ShouldBeNil) So(result.Selling.AssetType, ShouldEqual, "native") So(result.Selling.AssetCode, ShouldEqual, "") So(result.Selling.AssetIssuer, ShouldEqual, "") So(result.Buying.AssetType, ShouldEqual, "credit_alphanum4") So(result.Buying.AssetCode, ShouldEqual, "USD") So(result.Buying.AssetIssuer, ShouldEqual, "GC23QF2HUE52AMXUFUH3AYJAXXGXXV2VHXYYR6EYXETPKDXZSAW67XO4") So(len(result.Asks), ShouldEqual, 3) So(len(result.Bids), ShouldEqual, 3) }) }) }
func TestTransactionActions(t *testing.T) { Convey("Transactions Actions:", t, func() { test.LoadScenario("base") app := NewTestApp() defer app.Close() rh := NewRequestHelper(app) Convey("GET /transactions/c492d87c4642815dfb3c7dcce01af4effd162b031064098a0d786b6e0a00fd74", func() { w := rh.Get("/transactions/c492d87c4642815dfb3c7dcce01af4effd162b031064098a0d786b6e0a00fd74", test.RequestHelperNoop) So(w.Code, ShouldEqual, 200) var result TransactionResource err := json.Unmarshal(w.Body.Bytes(), &result) So(err, ShouldBeNil) So(result.Hash, ShouldEqual, "c492d87c4642815dfb3c7dcce01af4effd162b031064098a0d786b6e0a00fd74") }) Convey("GET /transactions/not_real", func() { w := rh.Get("/transactions/not_real", test.RequestHelperNoop) So(w.Code, ShouldEqual, 404) }) Convey("GET /ledgers/100/transactions", func() { w := rh.Get("/ledgers/100/transactions", test.RequestHelperNoop) So(w.Code, ShouldEqual, 404) }) Convey("GET /transactions", func() { w := rh.Get("/transactions", test.RequestHelperNoop) So(w.Code, ShouldEqual, 200) So(w.Body, ShouldBePageOf, 4) }) Convey("GET /ledgers/:ledger_id/transactions", func() { w := rh.Get("/ledgers/1/transactions", test.RequestHelperNoop) So(w.Code, ShouldEqual, 200) So(w.Body, ShouldBePageOf, 0) w = rh.Get("/ledgers/2/transactions", test.RequestHelperNoop) So(w.Code, ShouldEqual, 200) So(w.Body, ShouldBePageOf, 3) w = rh.Get("/ledgers/3/transactions", test.RequestHelperNoop) So(w.Code, ShouldEqual, 200) So(w.Body, ShouldBePageOf, 1) }) Convey("GET /accounts/:account_od/transactions", func() { w := rh.Get("/accounts/GBRPYHIL2CI3FNQ4BXLFMNDLFJUNPU2HY3ZMFSHONUCEOASW7QC7OX2H/transactions", test.RequestHelperNoop) So(w.Code, ShouldEqual, 200) So(w.Body, ShouldBePageOf, 3) w = rh.Get("/accounts/GA5WBPYA5Y4WAEHXWR2UKO2UO4BUGHUQ74EUPKON2QHV4WRHOIRNKKH2/transactions", test.RequestHelperNoop) So(w.Code, ShouldEqual, 200) So(w.Body, ShouldBePageOf, 1) w = rh.Get("/accounts/GCXKG6RN4ONIEPCMNFB732A436Z5PNDSRLGWK7GBLCMQLIFO4S7EYWVU/transactions", test.RequestHelperNoop) So(w.Code, ShouldEqual, 200) So(w.Body, ShouldBePageOf, 2) }) }) }
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("NewApp adds a sentry hook when the provided config's SentryDSN is valid", t, func() { config := NewTestConfig() config.SentryDSN = "https://*****:*****@app.getsentry.com/44303" app, _ := NewApp(config) defer app.Close() // we have to use reflection to see if the hook is added :( r := reflect.ValueOf(app.log.Logger.Hooks) So(r.Kind(), ShouldEqual, reflect.Map) expectations := []struct { Level logrus.Level Assertion func(actual interface{}, options ...interface{}) string }{ {logrus.DebugLevel, shouldNotHaveASentryHook}, {logrus.InfoLevel, shouldNotHaveASentryHook}, {logrus.WarnLevel, shouldNotHaveASentryHook}, {logrus.ErrorLevel, shouldHaveASentryHook}, {logrus.PanicLevel, shouldHaveASentryHook}, {logrus.FatalLevel, shouldHaveASentryHook}, } for _, expectation := range expectations { hooks := r.MapIndex(reflect.ValueOf(expectation.Level)).Interface() So(hooks, expectation.Assertion) } }) Convey("NewApp does not add a sentry hook if config's SentryDSN is empty", t, func() { config := NewTestConfig() config.SentryDSN = "" app, _ := NewApp(config) defer app.Close() // we have to use reflection to see if the hook is added :( r := reflect.ValueOf(app.log.Logger.Hooks) So(r.Kind(), ShouldEqual, reflect.Map) expectations := []struct { Level logrus.Level Assertion func(actual interface{}, options ...interface{}) string }{ {logrus.DebugLevel, shouldNotHaveASentryHook}, {logrus.InfoLevel, shouldNotHaveASentryHook}, {logrus.WarnLevel, shouldNotHaveASentryHook}, {logrus.ErrorLevel, shouldNotHaveASentryHook}, {logrus.PanicLevel, shouldNotHaveASentryHook}, {logrus.FatalLevel, shouldNotHaveASentryHook}, } for _, expectation := range expectations { hooksv := r.MapIndex(reflect.ValueOf(expectation.Level)) var hooks []logrus.Hook if hooksv.IsValid() { hooks = hooksv.Interface().([]logrus.Hook) } else { hooks = nil } So(hooks, expectation.Assertion) } }) 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) }) }
func TestCoreOfferPageByCurrencyQuery(t *testing.T) { test.LoadScenario("order_books") Convey("CoreOfferPageByCurrencyQuery", t, func() { var records []CoreOfferRecord makeQuery := func(c string, o string, l int32) CoreOfferPageByCurrencyQuery { pq, err := NewPageQuery(c, o, l) So(err, ShouldBeNil) return CoreOfferPageByCurrencyQuery{ SqlQuery: SqlQuery{core}, PageQuery: pq, } } simpleQuery := makeQuery("", "asc", 0) simpleQuery.SellingAssetType = xdr.AssetTypeAssetTypeCreditAlphanum4 simpleQuery.SellingAssetCode = "USD" simpleQuery.SellingIssuer = "GC23QF2HUE52AMXUFUH3AYJAXXGXXV2VHXYYR6EYXETPKDXZSAW67XO4" simpleQuery.BuyingAssetType = xdr.AssetTypeAssetTypeNative Convey("filters properly", func() { // native offers q := simpleQuery MustSelect(ctx, q, &records) So(len(records), ShouldEqual, 3) // all non-native q.SellingAssetType = xdr.AssetTypeAssetTypeCreditAlphanum4 q.SellingAssetCode = "USD" q.SellingIssuer = "GC23QF2HUE52AMXUFUH3AYJAXXGXXV2VHXYYR6EYXETPKDXZSAW67XO4" q.BuyingAssetType = xdr.AssetTypeAssetTypeCreditAlphanum4 q.BuyingAssetCode = "BTC" q.BuyingIssuer = "GC23QF2HUE52AMXUFUH3AYJAXXGXXV2VHXYYR6EYXETPKDXZSAW67XO4" MustSelect(ctx, q, &records) So(len(records), ShouldEqual, 3) // non-existent order book q.SellingAssetType = xdr.AssetTypeAssetTypeCreditAlphanum4 q.SellingAssetCode = "USD" q.SellingIssuer = "GC23QF2HUE52AMXUFUH3AYJAXXGXXV2VHXYYR6EYXETPKDXZSAW67XO4" q.BuyingAssetType = xdr.AssetTypeAssetTypeCreditAlphanum4 q.BuyingAssetCode = "EUR" q.BuyingIssuer = "GC23QF2HUE52AMXUFUH3AYJAXXGXXV2VHXYYR6EYXETPKDXZSAW67XO4" MustSelect(ctx, q, &records) So(len(records), ShouldEqual, 0) }) Convey("orders properly", func() { // asc orders ascending by price q := simpleQuery MustSelect(ctx, q, &records) So(records, ShouldBeOrderedAscending, func(r interface{}) int64 { So(r, ShouldHaveSameTypeAs, CoreOfferRecord{}) return int64(r.(CoreOfferRecord).Price * 10000000) }) // asc orders ascending by price q = simpleQuery q.PageQuery.Order = "desc" MustSelect(ctx, q, &records) So(records, ShouldBeOrderedDescending, func(r interface{}) int64 { So(r, ShouldHaveSameTypeAs, CoreOfferRecord{}) return int64(r.(CoreOfferRecord).Price * 10000000) }) }) Convey("limits properly", func() { // returns number specified q := simpleQuery q.PageQuery.Limit = 2 MustSelect(ctx, q, &records) So(len(records), ShouldEqual, 2) // returns all rows if limit is higher q = simpleQuery q.PageQuery.Limit = 10 MustSelect(ctx, q, &records) So(len(records), ShouldEqual, 3) }) Convey("cursor works properly", func() { var record CoreOfferRecord // lowest price if ordered ascending and no cursor q := simpleQuery MustGet(ctx, q, &record) So(record.Price, ShouldEqual, 15) // highest id if ordered descending and no cursor q = simpleQuery q.PageQuery.Order = "desc" q.PageQuery.Cursor = fmt.Sprintf("%d", math.MaxInt64) MustGet(ctx, q, &record) So(record.Price, ShouldEqual, 50) // starts after the cursor if ordered ascending q = simpleQuery q.PageQuery.Cursor = "15" MustGet(ctx, q, &record) So(record.Price, ShouldEqual, 20) // starts before the cursor if ordered descending q = simpleQuery q.PageQuery.Order = "desc" q.PageQuery.Cursor = "50" MustGet(ctx, q, &record) So(record.Price, ShouldEqual, 20) }) }) }