Documentation
¶
Index ¶
- Constants
- Variables
- func ContainsAny(s string, subs ...string) bool
- func RandomSubID() string
- func WaitForAllRelaysReady(maxAttempts int) error
- func WaitForRelayReady(t *testing.T, maxAttempts int)
- func WaitForRelayReadyAt(t *testing.T, httpURL string, maxAttempts int)
- type TestClient
- func (c *TestClient) AwaitCommit(evtID string, timeout time.Duration) bool
- func (c *TestClient) Close()
- func (c *TestClient) ExpectAuthChallenge(timeout time.Duration) string
- func (c *TestClient) ExpectClosed(subID string, timeout time.Duration) string
- func (c *TestClient) ExpectEOSE(subID string, timeout time.Duration) []map[string]interface{}
- func (c *TestClient) ExpectNotice(timeout time.Duration) string
- func (c *TestClient) ExpectOK(eventID string, timeout time.Duration) (bool, string)
- func (c *TestClient) PerformAuth(kp *TestKeypair, relayURL string, timeout time.Duration) (bool, string)
- func (c *TestClient) ReadMessage(timeout time.Duration) []interface{}
- func (c *TestClient) ReadMessageRaw(timeout time.Duration) json.RawMessage
- func (c *TestClient) SendEvent(evt nostr.Event)
- func (c *TestClient) SendMessage(msg interface{})
- func (c *TestClient) Subscribe(subID string, filters ...map[string]interface{})
- func (c *TestClient) TryReadMessage(timeout time.Duration) ([]interface{}, error)
- type TestKeypair
Constants ¶
const ( TestRelayURL = "ws://127.0.0.1:8182" TestHTTPURL = "http://127.0.0.1:8182" )
Default (legacy) endpoints — used by the happy-path tests in relay_test.go, api_test.go, websocket_test.go.
We use 127.0.0.1 instead of "localhost" on purpose: docker-compose's port publishing on Linux binds to IPv4 0.0.0.0 only, but Go's resolver on some hosts (notably GitHub Actions ubuntu runners) returns ::1 for "localhost" first, producing intermittent "connection refused" errors as the test harness dials an IPv6 address docker never bound.
const ( DefaultRelayURL = "ws://127.0.0.1:8182" RateLimitRelayURL = "ws://127.0.0.1:8183" BlacklistRelayURL = "ws://127.0.0.1:8184" WhitelistRelayURL = "ws://127.0.0.1:8185" AuthRelayURL = "ws://127.0.0.1:8186" TimeCheckRelayURL = "ws://127.0.0.1:8187" EventPurgeRelayURL = "ws://127.0.0.1:8188" HotReloadRelayURL = "ws://127.0.0.1:8189" NIP86RelayURL = "ws://127.0.0.1:8190" DefaultHTTPURL = "http://127.0.0.1:8182" RateLimitHTTPURL = "http://127.0.0.1:8183" BlacklistHTTPURL = "http://127.0.0.1:8184" WhitelistHTTPURL = "http://127.0.0.1:8185" AuthHTTPURL = "http://127.0.0.1:8186" TimeCheckHTTPURL = "http://127.0.0.1:8187" EventPurgeHTTPURL = "http://127.0.0.1:8188" HotReloadHTTPURL = "http://127.0.0.1:8189" NIP86HTTPURL = "http://127.0.0.1:8190" )
Per-scenario relay endpoints. Each URL targets a dedicated docker-compose service backed by a config fixture in tests/docker/configs/.
const ( NIP86OwnerSeed = "grain-test-nip86-owner" NIP86AllowedSeed = "grain-test-nip86-allowed" NIP86BannedSeed = "grain-test-nip86-banned" )
NIP-86 fixture seeds. The genconfigs tool plants the pubkeys derived from these seeds into nip86-*.yml / nip86-relay_metadata.json so the integration tests can use NewDeterministicKeypair to recover the same keys. Keep these in sync with tests/genconfigs/main.go.
const WhitelistSeed = "grain-test-whitelist-allowed"
WhitelistSeed MUST match tests/genconfigs/main.go.WhitelistSeed — the whitelist-rules.yml fixture contains the pubkey derived from this seed.
Variables ¶
var AllRelayHTTPURLs = []string{ DefaultHTTPURL, RateLimitHTTPURL, BlacklistHTTPURL, WhitelistHTTPURL, AuthHTTPURL, TimeCheckHTTPURL, EventPurgeHTTPURL, HotReloadHTTPURL, NIP86HTTPURL, }
AllRelayHTTPURLs is used by TestMain readiness checks.
Functions ¶
func ContainsAny ¶ added in v0.5.0
ContainsAny reports whether s contains any of the given substrings. Handy for matching reject messages against alternatives.
func RandomSubID ¶ added in v0.5.0
func RandomSubID() string
RandomSubID generates a random subscription ID for tests.
func WaitForAllRelaysReady ¶ added in v0.5.0
WaitForAllRelaysReady pings every per-scenario relay endpoint in parallel so one slow-starting container can't block the others. Progress is logged to stderr for CI visibility.
func WaitForRelayReady ¶
WaitForRelayReady waits for the default relay to be ready.
func WaitForRelayReadyAt ¶ added in v0.5.0
WaitForRelayReadyAt waits for a specific relay endpoint to be ready. Returns an error (rather than t.Fatalf) so callers in TestMain — where no real *testing.T exists — can handle the failure themselves.
Types ¶
type TestClient ¶
type TestClient struct {
// contains filtered or unexported fields
}
TestClient wraps a WebSocket connection for testing
func NewTestClient ¶
func NewTestClient(t *testing.T) *TestClient
NewTestClient creates a new WebSocket connection to the default test relay.
func NewTestClientAt ¶ added in v0.5.0
func NewTestClientAt(t *testing.T, url string) *TestClient
NewTestClientAt creates a new WebSocket connection to the given relay URL.
func (*TestClient) AwaitCommit ¶ added in v0.8.0
func (c *TestClient) AwaitCommit(evtID string, timeout time.Duration) bool
AwaitCommit blocks until an event with id evtID is queryable on the relay, or the deadline passes (returns true once found, false on timeout).
nostrdb's ingester acks OK on *enqueue*, not on commit — the writer thread commits a short time later. A read issued immediately after OK can therefore precede the commit and see nothing (the async-commit race). Call this after ExpectOK for any event a subsequent query depends on, so the read is deterministic. Because the ingester→writer queue is FIFO, awaiting the last event of an ordered publish implies the earlier ones have committed too.
It uses a dedicated probe subscription that it opens, drains to EOSE, and CLOSEs, and ignores frames for other subscription IDs, so the caller's own message stream is unaffected.
func (*TestClient) ExpectAuthChallenge ¶ added in v0.5.0
func (c *TestClient) ExpectAuthChallenge(timeout time.Duration) string
ExpectAuthChallenge returns the NIP-42 AUTH challenge. GRAIN sends the challenge proactively on connect, which NewTestClientAt captures into initialChallenge; this method returns that captured value. If none was captured (older relays or a reconnect), it falls back to reading frames until an AUTH arrives.
func (*TestClient) ExpectClosed ¶ added in v0.5.0
func (c *TestClient) ExpectClosed(subID string, timeout time.Duration) string
ExpectClosed reads messages until a CLOSED for subID is received.
func (*TestClient) ExpectEOSE ¶ added in v0.5.0
func (c *TestClient) ExpectEOSE(subID string, timeout time.Duration) []map[string]interface{}
ExpectEOSE reads messages until it gets an EOSE for the given subscription ID. Returns any EVENT messages received before the EOSE.
func (*TestClient) ExpectNotice ¶ added in v0.5.0
func (c *TestClient) ExpectNotice(timeout time.Duration) string
ExpectNotice reads messages until a NOTICE is received, then returns its message text. Fails if one doesn't arrive before timeout.
func (*TestClient) ExpectOK ¶ added in v0.5.0
ExpectOK reads messages until it gets an OK for the given event ID. Returns (accepted bool, message string).
func (*TestClient) PerformAuth ¶ added in v0.5.0
func (c *TestClient) PerformAuth(kp *TestKeypair, relayURL string, timeout time.Duration) (bool, string)
PerformAuth executes a NIP-42 challenge/response exchange: reads the AUTH challenge, signs a kind-22242 event with the required relay + challenge tags, sends it, and waits for OK. Returns the OK message text.
func (*TestClient) ReadMessage ¶
func (c *TestClient) ReadMessage(timeout time.Duration) []interface{}
ReadMessage reads a message from the relay with timeout
func (*TestClient) ReadMessageRaw ¶ added in v0.5.0
func (c *TestClient) ReadMessageRaw(timeout time.Duration) json.RawMessage
ReadMessageRaw reads a raw JSON message from the relay
func (*TestClient) SendEvent ¶ added in v0.5.0
func (c *TestClient) SendEvent(evt nostr.Event)
SendEvent publishes an EVENT message to the relay
func (*TestClient) SendMessage ¶
func (c *TestClient) SendMessage(msg interface{})
SendMessage sends a message to the relay
func (*TestClient) Subscribe ¶ added in v0.5.0
func (c *TestClient) Subscribe(subID string, filters ...map[string]interface{})
Subscribe sends a REQ with the given subscription ID and filters
func (*TestClient) TryReadMessage ¶ added in v0.5.0
func (c *TestClient) TryReadMessage(timeout time.Duration) ([]interface{}, error)
TryReadMessage reads a message from the relay, returning nil and the error if the read times out or fails. Unlike ReadMessage it does not call t.Fatalf.
type TestKeypair ¶ added in v0.5.0
type TestKeypair struct {
PrivKey *btcec.PrivateKey
PubKey string // hex-encoded x-only public key
}
TestKeypair holds a private key and its corresponding public key hex for testing.
func NewDeterministicKeypair ¶ added in v0.5.0
func NewDeterministicKeypair(seed string) *TestKeypair
NewDeterministicKeypair derives a keypair from a fixed seed. The same seed always produces the same pubkey, so config YAML fixtures generated by tests/genconfigs/main.go can reference it. MUST stay in sync with tests/genconfigs/main.go.DerivePubKeyHex.
func NewTestKeypair ¶ added in v0.5.0
func NewTestKeypair() *TestKeypair
NewTestKeypair generates a random keypair for testing.
func (*TestKeypair) SignEventAt ¶ added in v0.5.0
func (kp *TestKeypair) SignEventAt(kind int, content string, tags [][]string, createdAt int64) nostr.Event
SignEventAt signs an event with a custom created_at (for drift tests).
Directories
¶
| Path | Synopsis |
|---|---|
|
genconfigs writes dynamic test fixtures that depend on deterministically derived keypairs (so test Go code and config YAML agree on the same pubkey).
|
genconfigs writes dynamic test fixtures that depend on deterministically derived keypairs (so test Go code and config YAML agree on the same pubkey). |