package zrpc import ( "encoding/json" "os" "strconv" "strings" "testing" "time" ini "gopkg.in/ini.v1" ) // Live tests against a local dragonxd. Skipped unless ZRPC_CONF points at a // DRAGONX.conf, so `go test ./...` stays hermetic. func liveClient(t *testing.T, timeout time.Duration) *Client { t.Helper() conf := os.Getenv("ZRPC_CONF") if conf == "" { t.Skip("ZRPC_CONF not set; skipping live RPC test") } cfg, err := ini.Load(conf) if err != nil { t.Fatalf("load conf: %v", err) } k := func(n string) string { return cfg.Section("").Key(n).String() } return New(k("rpcbind")+":"+k("rpcport"), k("rpcuser"), k("rpcpassword"), timeout, 8) } func TestLiveSuccess(t *testing.T) { c := liveClient(t, 30*time.Second) res, err := c.RawRequest("getblockchaininfo", nil) if err != nil { t.Fatalf("getblockchaininfo: %v", err) } var f map[string]interface{} if err := json.Unmarshal(res, &f); err != nil { t.Fatalf("unmarshal: %v", err) } if f["chain"] != "main" { t.Fatalf("chain = %v, want main", f["chain"]) } t.Logf("ok: chain=%v blocks=%v", f["chain"], f["blocks"]) } // The error string must stay ": " -- common.GetSaplingInfo // recovers the numeric code with strings.SplitN(err.Error(), ":", 2). func TestLiveErrorStringShape(t *testing.T) { c := liveClient(t, 30*time.Second) p := []json.RawMessage{json.RawMessage(`"99999999"`)} _, err := c.RawRequest("getblock", p) if err == nil { t.Fatal("expected an error for an out-of-range height") } parts := strings.SplitN(err.Error(), ":", 2) code, perr := strconv.ParseInt(parts[0], 10, 32) if perr != nil { t.Fatalf("error string %q does not start with a numeric code", err.Error()) } if code != -8 { t.Logf("note: code %d (expected -8 for a bad height, but any numeric code proves the shape)", code) } t.Logf("ok: %q -> code %d", err.Error(), code) } // A timeout must actually abort the call rather than hanging. func TestLiveTimeoutFires(t *testing.T) { c := liveClient(t, 1*time.Nanosecond) start := time.Now() _, err := c.RawRequest("getblockchaininfo", nil) elapsed := time.Since(start) if err == nil { t.Fatal("expected a timeout error") } if elapsed > 5*time.Second { t.Fatalf("timeout did not fire promptly: %v", elapsed) } t.Logf("ok: timed out in %v with %v", elapsed, err) } func TestNoMethod(t *testing.T) { c := New("127.0.0.1:1", "u", "p", time.Second, 8) if _, err := c.RawRequest("", nil); err == nil || err.Error() != "no method" { t.Fatalf(`RawRequest("") = %v, want "no method"`, err) } }