herald.go/server/notifier_test.go
Jonathan Moody 8fb3db8136
Add subscribe/unsubscribe RPCs. Add session, sessionManager, and serve JSON RPC (without HTTP). (#66)
* Move and rename BlockchainCodec, BlockchainCodecRequest.
These are not specifically "blockchain", rather they are
specific to how gorilla/rpc works.

* Move claimtrie-related service/handlers to jsonrpc_claimtrie.go.

* Pull out decode logic into named func newBlockHeaderElectrum().

* Rename BlockchainService -> BlockchainBlockService.

* Drop http.Request arg from handlers, and use RegisterTCPService().

* Implement GetStatus() to pull data from HashXStatus table.

* Make the service objects independent, so we don't have inheritance.

* Add core session/subscription logic (session.go).
Implement subsribe/unsubscribe handlers.

* Support both pure JSON and JSON-over-HTTP services.
Forward NotifierChan messages to sessionManager.

* Only assign default port (50001) if neither --json-rpc-port nor
--json-rpc-http-port are specified.

* Handle failures with goto instead of break. Update error logging.

* Add --max-sessions, --session-timeout args. Enforce max sessions.

* Changes to make session.go testable. Conn created with Pipe()
used in testing has no unique Addr.

* Add tests for headers, headers.subscribe, address.subscribe.

* HashXStatus, HashXMempoolStatus not populated by default. Fix GetStatus().

* Use time.Ticker object to drive management activity.
2022-10-04 17:05:06 +03:00

87 lines
1.7 KiB
Go

package server_test
import (
"context"
"encoding/hex"
"fmt"
"net"
"testing"
"time"
"github.com/lbryio/herald.go/internal"
"github.com/lbryio/herald.go/server"
"github.com/sirupsen/logrus"
)
const defaultBufferSize = 1024
func tcpConnReady(addr string) (net.Conn, error) {
sleepTime := time.Millisecond * 100
for {
if sleepTime > time.Second {
return nil, fmt.Errorf("timeout")
}
conn, err := net.Dial("tcp", addr)
if err != nil {
logrus.Warn(err)
time.Sleep(sleepTime)
sleepTime = sleepTime * 2
continue
}
return conn, nil
}
}
func tcpRead(conn net.Conn) ([]byte, error) {
buf := make([]byte, defaultBufferSize)
n, err := conn.Read(buf)
if err != nil {
return nil, err
}
if n != server.NotifierResponseLength {
return nil, fmt.Errorf("not all bytes read")
}
return buf[:n], nil
}
func TestNotifierServer(t *testing.T) {
args := makeDefaultArgs()
ctx := context.Background()
hub := server.MakeHubServer(ctx, args)
go hub.NotifierServer()
go hub.RunNotifier()
addr := fmt.Sprintf(":%s", args.NotifierPort)
logrus.Info(addr)
conn, err := tcpConnReady(addr)
if err != nil {
t.Fatal(err)
}
resCh := make(chan []byte)
go func() {
logrus.Warn("waiting for response")
res, err := tcpRead(conn)
logrus.Warn("got response")
if err != nil {
logrus.Warn(err)
return
}
resCh <- res
}()
// Hacky but needed because if the reader isn't ready
// before the writer sends it won't get the data
time.Sleep(time.Second)
hash, _ := hex.DecodeString("AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA")
logrus.Warn("sending hash")
hub.NotifierChan <- internal.HeightHash{Height: 1, BlockHash: hash}
res := <-resCh
logrus.Info(string(res))
}