From 762166884502fc2c008950e98ab5c4c568526b2f Mon Sep 17 00:00:00 2001 From: a <a@tuxpa.in> Date: Tue, 1 Aug 2023 02:57:53 -0500 Subject: [PATCH] wip --- contrib/codecs/http/codec.go | 6 +- contrib/codecs/redis/client.go | 231 +++++++++++++++++++++++++++++ contrib/codecs/redis/codec.go | 89 +++++++++++ contrib/codecs/redis/codec_test.go | 39 +++++ contrib/codecs/redis/const.go | 18 +++ contrib/codecs/redis/redis.go | 69 +++++++++ contrib/codecs/redis/server.go | 32 ++++ go.mod | 7 + go.sum | 19 +++ pkg/jrpctest/suites.go | 2 +- 10 files changed, 510 insertions(+), 2 deletions(-) create mode 100644 contrib/codecs/redis/client.go create mode 100644 contrib/codecs/redis/codec.go create mode 100644 contrib/codecs/redis/codec_test.go create mode 100644 contrib/codecs/redis/const.go create mode 100644 contrib/codecs/redis/redis.go create mode 100644 contrib/codecs/redis/server.go diff --git a/contrib/codecs/http/codec.go b/contrib/codecs/http/codec.go index 4949b64..ee21a7d 100644 --- a/contrib/codecs/http/codec.go +++ b/contrib/codecs/http/codec.go @@ -37,10 +37,14 @@ type httpError struct { } func NewCodec(w http.ResponseWriter, r *http.Request) *Codec { + ir := io.Writer(w) + if w == nil { + ir = io.Discard + } c := &Codec{ r: r, w: w, - wr: bufio.NewWriter(w), + wr: bufio.NewWriter(ir), msgs: make(chan *serverutil.Bundle, 1), errCh: make(chan httpError, 1), } diff --git a/contrib/codecs/redis/client.go b/contrib/codecs/redis/client.go new file mode 100644 index 0000000..c73ff35 --- /dev/null +++ b/contrib/codecs/redis/client.go @@ -0,0 +1,231 @@ +package redis + +import ( + "bytes" + "context" + "encoding/json" + "fmt" + "sync" + + "gfx.cafe/open/jrpc/pkg/clientutil" + "gfx.cafe/open/jrpc/pkg/codec" + "github.com/redis/go-redis/v9" + "github.com/rs/xid" +) + +type Client struct { + p *clientutil.IdReply + + c redis.UniversalClient + clientId string + domain string + + ctx context.Context + cn context.CancelFunc + + m codec.Middlewares + handler codec.Handler + mu sync.RWMutex + + handlerPeer codec.PeerInfo +} + +func NewClient(c redis.UniversalClient, domain string) *Client { + cl := &Client{ + c: c, + p: clientutil.NewIdReply(), + handlerPeer: codec.PeerInfo{ + Transport: "redis", + RemoteAddr: "", + }, + domain: domain, + // this doesn't need to be secure bc... you have access to the redis instance lol + clientId: xid.New().String(), + handler: codec.HandlerFunc(func(w codec.ResponseWriter, r *codec.Request) {}), + } + cl.ctx, cl.cn = context.WithCancel(context.Background()) + go cl.listen() + return cl +} + +func (c *Client) SetHandlerPeer(pi codec.PeerInfo) { + c.handlerPeer = pi +} + +func (c *Client) Mount(h codec.Middleware) { + c.mu.Lock() + defer c.mu.Unlock() + c.m = append(c.m, h) + c.handler = c.m.HandlerFunc(func(w codec.ResponseWriter, r *codec.Request) { + // do nothing on no handler + }) +} + +func (c *Client) listen() error { + subCh := fmt.Sprintf(c.domain + "." + c.clientId) + sub := c.c.PSubscribe(c.ctx, subCh) + msgCh := sub.Channel() + for { + incomingMsg := <-msgCh + msgs, _ := codec.ParseMessage(stringToBytes(incomingMsg.Payload)) + for i := range msgs { + v := msgs[i] + if v == nil { + continue + } + id := v.ID + // messages without ids are notifications + if id == nil { + var handler codec.Handler + c.mu.RLock() + handler = c.handler + c.mu.RUnlock() + // writer should only be allowed to send notifications + // reader should contain the message above + // the context is the client context + req := codec.NewRawRequest(c.ctx, + nil, + v.Method, + v.Params, + ) + req.Peer = c.handlerPeer + handler.ServeRPC(nil, req) + continue + } + var err error + if v.Error != nil { + err = v.Error + } + c.p.Resolve(*id, v.Result, err) + } + } + +} + +func (c *Client) Do(ctx context.Context, result any, method string, params any) error { + id := c.p.NextId() + req, err := codec.NewRequest(ctx, codec.NewId(id), method, params) + if err != nil { + return err + } + fwd, err := json.Marshal(req) + if err != nil { + return err + } + toFwd, _ := json.Marshal(&RedisRequest{ + ReplyChannel: c.clientId, + Message: fwd, + }) + err = c.writeContext(req.Context(), toFwd) + if err != nil { + return err + } + ans, err := c.p.Ask(req.Context(), *id) + if err != nil { + return err + } + if result != nil { + err = json.Unmarshal(ans, result) + if err != nil { + return err + } + } + return nil +} + +func (c *Client) BatchCall(ctx context.Context, b ...*codec.BatchElem) error { + if ctx == nil { + ctx = context.Background() + } + buf := new(bytes.Buffer) + enc := json.NewEncoder(buf) + reqs := make([]*codec.Request, 0, len(b)) + ids := make([]*codec.ID, 0, len(b)) + for _, v := range b { + id := c.p.NextId() + req, err := codec.NewRequest(ctx, codec.NewId(id), v.Method, v.Params) + if err != nil { + return err + } + ids = append(ids, id) + reqs = append(reqs, req) + } + err := enc.Encode(reqs) + if err != nil { + return err + } + pkg, _ := json.Marshal(&RedisRequest{ + ReplyChannel: c.clientId, + Message: buf.Bytes(), + }) + err = c.writeContext(ctx, pkg) + if err != nil { + return err + } + // TODO: wait for response + wg := sync.WaitGroup{} + wg.Add(len(ids)) + for i := range ids { + idx := i + go func() { + defer wg.Done() + ans, err := c.p.Ask(reqs[idx].Context(), *ids[idx]) + if err != nil { + b[idx].Error = err + return + } + if b[idx].Result != nil { + err = json.Unmarshal(ans, b[idx].Result) + if err != nil { + b[idx].Error = err + return + } + } + }() + } + wg.Wait() + + return err +} +func (c *Client) Notify(ctx context.Context, method string, params any) error { + if ctx == nil { + ctx = context.Background() + } + req, err := codec.NewRequest(ctx, nil, method, params) + if err != nil { + return err + } + fwd, err := json.Marshal(req) + if err != nil { + return err + } + return c.writeContext(ctx, fwd) +} + +func (c *Client) SetHeader(key string, value string) { +} + +func (c *Client) Close() error { + c.cn() + return nil +} + +func (c *Client) writeContext(ctx context.Context, xs []byte) error { + errch := make(chan error) + go func() { + err := c.c.LPush(ctx, c.domain+reqDomainSuffix, xs).Err() + select { + case errch <- err: + case <-ctx.Done(): + case <-c.ctx.Done(): + } + }() + select { + case err := <-errch: + return err + case <-c.ctx.Done(): + return c.ctx.Err() + case <-ctx.Done(): + return ctx.Err() + } +} diff --git a/contrib/codecs/redis/codec.go b/contrib/codecs/redis/codec.go new file mode 100644 index 0000000..5c0ec05 --- /dev/null +++ b/contrib/codecs/redis/codec.go @@ -0,0 +1,89 @@ +package redis + +import ( + "bytes" + "context" + "encoding/json" + "sync/atomic" + + "gfx.cafe/open/jrpc/pkg/codec" + "gfx.cafe/open/jrpc/pkg/serverutil" +) + +var _ codec.ReaderWriter = (*Codec)(nil) + +type Codec struct { + ctx context.Context + cn func() + + wr bytes.Buffer + replier func(json.RawMessage) error + ansCh chan *serverutil.Bundle + closed atomic.Bool + closeCh chan struct{} + + i codec.PeerInfo +} + +type httpError struct { + code int + err error +} + +func NewCodec(req *RedisRequest, replier func(json.RawMessage) error) *Codec { + c := &Codec{ + replier: replier, + ansCh: make(chan *serverutil.Bundle, 1), + closeCh: make(chan struct{}), + } + c.ctx, c.cn = context.WithCancel(context.Background()) + bundle := serverutil.ParseBundle(req.Message) + c.ansCh <- bundle + return c +} + +// gets the peer info +func (c *Codec) PeerInfo() codec.PeerInfo { + return c.i +} + +func (c *Codec) ReadBatch(ctx context.Context) ([]*codec.Message, bool, error) { + select { + case ans := <-c.ansCh: + return ans.Messages, ans.Batch, nil + case <-ctx.Done(): + return nil, false, ctx.Err() + case <-c.ctx.Done(): + return nil, false, c.ctx.Err() + } +} + +// closes the connection +func (c *Codec) Close() error { + if c.closed.CompareAndSwap(false, true) { + close(c.closeCh) + } + c.cn() + return nil +} + +func (c *Codec) Write(p []byte) (n int, err error) { + return c.wr.Write(p) +} + +func (c *Codec) Flush() (err error) { + c.replier(c.wr.Bytes()) + c.wr.Reset() + c.Close() + return +} + +// Closed returns a channel which is closed when the connection is closed. +func (c *Codec) Closed() <-chan struct{} { + return c.closeCh +} + +// RemoteAddr returns the peer address of the connection. +func (c *Codec) RemoteAddr() string { + return "" +} diff --git a/contrib/codecs/redis/codec_test.go b/contrib/codecs/redis/codec_test.go new file mode 100644 index 0000000..000a913 --- /dev/null +++ b/contrib/codecs/redis/codec_test.go @@ -0,0 +1,39 @@ +package redis + +import ( + "context" + "testing" + + "gfx.cafe/open/jrpc/pkg/codec" + "gfx.cafe/open/jrpc/pkg/server" + + "gfx.cafe/open/jrpc/pkg/jrpctest" + "github.com/alicebob/miniredis/v2" + "github.com/redis/go-redis/v9" + "github.com/stretchr/testify/require" +) + +func TestBasicSuite(t *testing.T) { + redisServer := miniredis.RunT(t) + _ = redisServer + connOpts := &redis.UniversalOptions{ + Addrs: []string{"localhost:6379"}, + } + domain := "jrpc" + + jrpctest.RunBasicTestSuite(t, jrpctest.BasicTestSuiteArgs{ + ServerMaker: func() (*server.Server, jrpctest.ClientMaker, func()) { + ctx, cn := context.WithCancel(context.Background()) + ss, err := CreateServerStream(ctx, domain, connOpts) + require.NoError(t, err) + s := jrpctest.NewServer() + go (&Server{Server: s}).ServeRedis(ctx, ss) + return s, func() codec.Conn { + conn := NewClient(redis.NewUniversalClient(connOpts), domain) + return conn + }, func() { + cn() + } + }, + }) +} diff --git a/contrib/codecs/redis/const.go b/contrib/codecs/redis/const.go new file mode 100644 index 0000000..62e650c --- /dev/null +++ b/contrib/codecs/redis/const.go @@ -0,0 +1,18 @@ +package redis + +import "errors" + +const ( + // NOTE: if you change this, you will have to change the thing in jrpctest... its what its for now until tests get refactored + maxRequestContentLength = 1024 * 1024 * 5 + contentType = "application/json" +) + +// https://www.jsonrpc.org/historical/json-rpc-over-http.html#id13 +var acceptedContentTypes = []string{ + // https://www.jsonrpc.org/historical/json-rpc-over-http.html#id13 + contentType, "application/json-rpc", "application/jsonrequest", + // these are added because they make sense, fight me! + "application/jsonrpc2", "application/json-rpc2", "application/jrpc", +} +var ErrInvalidContentType = errors.New("invalid content type") diff --git a/contrib/codecs/redis/redis.go b/contrib/codecs/redis/redis.go new file mode 100644 index 0000000..656a9a4 --- /dev/null +++ b/contrib/codecs/redis/redis.go @@ -0,0 +1,69 @@ +package redis + +import ( + "context" + "encoding/json" + "log" + "time" + "unsafe" + + "github.com/redis/go-redis/v9" + "github.com/rs/xid" +) + +type ServerStream struct { + client redis.UniversalClient + domain string + + id xid.ID +} + +func CreateServerStream(ctx context.Context, domain string, opts *redis.UniversalOptions) (*ServerStream, error) { + c := redis.NewUniversalClient(opts) + // the xid doesn't need to be secure, since we assume anyone with access to the redis cluster can do anything anyways. + s := &ServerStream{ + client: c, + id: xid.New(), + domain: domain, + } + return s, nil +} + +type RedisRequest struct { + ReplyChannel string `json:"r"` + Message json.RawMessage `json:"msg"` +} + +func (s *ServerStream) ReadRequest(ctx context.Context) (*RedisRequest, func(json.RawMessage) error, error) { + timeout := time.Hour + res, err := s.client.BLPop(ctx, timeout, s.domain+reqDomainSuffix).Result() + if err != nil { + return nil, nil, err + } + if len(res) != 2 { + return nil, nil, err + } + redisReq := &RedisRequest{} + err = json.Unmarshal(stringToBytes(res[1]), redisReq) + if err != nil { + return nil, nil, err + } + log.Println("got req", redisReq.ReplyChannel, string(redisReq.Message)) + return redisReq, func(rm json.RawMessage) error { + target := s.domain + "." + redisReq.ReplyChannel + log.Println("replying", target, string(rm)) + return s.client.Publish(context.Background(), target, string(rm)).Err() + }, nil +} + +const reqDomainSuffix = ".req" +const respDomainSuffix = ".resp" + +func stringToBytes(s string) []byte { + return *(*[]byte)(unsafe.Pointer( + &struct { + string + Cap int + }{s, len(s)}, + )) +} diff --git a/contrib/codecs/redis/server.go b/contrib/codecs/redis/server.go new file mode 100644 index 0000000..54771e1 --- /dev/null +++ b/contrib/codecs/redis/server.go @@ -0,0 +1,32 @@ +package redis + +import ( + "context" + + "gfx.cafe/open/jrpc/pkg/server" + "tuxpa.in/a/zlog/log" +) + +type Server struct { + Server *server.Server +} + +func (s *Server) ServeRedis(ctx context.Context, stream *ServerStream) { + for { + select { + case <-ctx.Done(): + return + default: + } + req, fn, err := stream.ReadRequest(ctx) + if err != nil { + log.Err(err).Msg("while reading bpop") + continue + } + if req == nil { + continue + } + cd := NewCodec(req, fn) + s.Server.ServeCodec(ctx, cd) + } +} diff --git a/go.mod b/go.mod index bc2cf24..606f5e2 100644 --- a/go.mod +++ b/go.mod @@ -8,11 +8,14 @@ require ( gfx.cafe/util/go/frand v0.0.0-20230121041905-80dafb1e973e gfx.cafe/util/go/generic v0.0.0-20230502013805-237fcc25d586 github.com/alecthomas/kong v0.7.1 + github.com/alicebob/miniredis/v2 v2.30.4 github.com/davecgh/go-spew v1.1.1 github.com/deckarep/golang-set v1.8.0 github.com/go-faster/jx v1.0.0 github.com/goccy/go-json v0.10.0 github.com/iancoleman/strcase v0.3.0 + github.com/redis/go-redis/v9 v9.0.5 + github.com/rs/xid v1.4.0 github.com/stretchr/testify v1.8.2 sigs.k8s.io/yaml v1.3.0 tuxpa.in/a/zlog v1.61.0 @@ -20,6 +23,9 @@ require ( require ( github.com/aead/chacha20 v0.0.0-20180709150244-8b13a72661da // indirect + github.com/alicebob/gopher-json v0.0.0-20200520072559-a9ecdc9d1d3a // indirect + github.com/cespare/xxhash/v2 v2.2.0 // indirect + github.com/dgryski/go-rendezvous v0.0.0-20200823014737-9f7001d12a5f // indirect github.com/go-faster/errors v0.6.1 // indirect github.com/klauspost/compress v1.15.15 // indirect github.com/kr/pretty v0.3.1 // indirect @@ -28,6 +34,7 @@ require ( github.com/pmezard/go-difflib v1.0.0 // indirect github.com/rs/zerolog v1.29.0 // indirect github.com/segmentio/asm v1.2.0 // indirect + github.com/yuin/gopher-lua v1.1.0 // indirect golang.org/x/exp v0.0.0-20230206171751-46f607a40771 // indirect golang.org/x/sys v0.7.0 // indirect gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c // indirect diff --git a/go.sum b/go.sum index accaa5d..fdfc007 100644 --- a/go.sum +++ b/go.sum @@ -12,6 +12,17 @@ github.com/alecthomas/assert/v2 v2.1.0 h1:tbredtNcQnoSd3QBhQWI7QZ3XHOVkw1Moklp2o github.com/alecthomas/kong v0.7.1 h1:azoTh0IOfwlAX3qN9sHWTxACE2oV8Bg2gAwBsMwDQY4= github.com/alecthomas/kong v0.7.1/go.mod h1:n1iCIO2xS46oE8ZfYCNDqdR0b0wZNrXAIAqro/2132U= github.com/alecthomas/repr v0.1.0 h1:ENn2e1+J3k09gyj2shc0dHr/yjaWSHRlrJ4DPMevDqE= +github.com/alicebob/gopher-json v0.0.0-20200520072559-a9ecdc9d1d3a h1:HbKu58rmZpUGpz5+4FfNmIU+FmZg2P3Xaj2v2bfNWmk= +github.com/alicebob/gopher-json v0.0.0-20200520072559-a9ecdc9d1d3a/go.mod h1:SGnFV6hVsYE877CKEZ6tDNTjaSXYUk6QqoIK6PrAtcc= +github.com/alicebob/miniredis/v2 v2.30.4 h1:8S4/o1/KoUArAGbGwPxcwf0krlzceva2XVOSchFS7Eo= +github.com/alicebob/miniredis/v2 v2.30.4/go.mod h1:b25qWj4fCEsBeAAR2mlb0ufImGC6uH3VlUfb/HS5zKg= +github.com/bsm/ginkgo/v2 v2.7.0 h1:ItPMPH90RbmZJt5GtkcNvIRuGEdwlBItdNVoyzaNQao= +github.com/bsm/gomega v1.26.0 h1:LhQm+AFcgV2M0WyKroMASzAzCAJVpAxQXv4SaI9a69Y= +github.com/cespare/xxhash/v2 v2.2.0 h1:DC2CZ1Ep5Y4k3ZQ899DldepgrayRUGE6BBZ/cd9Cj44= +github.com/cespare/xxhash/v2 v2.2.0/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs= +github.com/chzyer/logex v1.1.10/go.mod h1:+Ywpsq7O8HXn0nuIou7OrIPyXbp3wmkHB+jjWRnGsAI= +github.com/chzyer/readline v0.0.0-20180603132655-2972be24d48e/go.mod h1:nSuG5e5PlCu98SY8svDHJxuZscDgtXS6KTTbou5AhLI= +github.com/chzyer/test v0.0.0-20180213035817-a1ea475d72b1/go.mod h1:Q3SI9o4m/ZMnBNeIyt5eFwwo7qiLfzFZmjNmxjkiQlU= github.com/coreos/go-systemd/v22 v22.3.3-0.20220203105225-a9a7ef127534/go.mod h1:Y58oyj3AT4RCenI/lSvhwexgC+NSVTIJ3seZv2GcEnc= github.com/coreos/go-systemd/v22 v22.5.0/go.mod h1:Y58oyj3AT4RCenI/lSvhwexgC+NSVTIJ3seZv2GcEnc= github.com/creack/pty v1.1.9/go.mod h1:oKZEueFk5CKHvIhNR5MUki03XCEU+Q6VDXinZuGJ33E= @@ -20,6 +31,8 @@ github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/deckarep/golang-set v1.8.0 h1:sk9/l/KqpunDwP7pSjUg0keiOOLEnOBHzykLrsPppp4= github.com/deckarep/golang-set v1.8.0/go.mod h1:5nI87KwE7wgsBU1F4GKAw2Qod7p5kyS383rP6+o6qqo= +github.com/dgryski/go-rendezvous v0.0.0-20200823014737-9f7001d12a5f h1:lO4WD4F/rVNCu3HqELle0jiPLLBs70cWOduZpkS1E78= +github.com/dgryski/go-rendezvous v0.0.0-20200823014737-9f7001d12a5f/go.mod h1:cuUVRXasLTGF7a8hSLbxyZXjz+1KgoB3wDUb6vlszIc= github.com/go-faster/errors v0.6.1 h1:nNIPOBkprlKzkThvS/0YaX8Zs9KewLCOSFQS5BU06FI= github.com/go-faster/errors v0.6.1/go.mod h1:5MGV2/2T9yvlrbhe9pD9LO5Z/2zCSq2T8j+Jpi2LAyY= github.com/go-faster/jx v1.0.0 h1:HE+ms2e6ZGkZ6u13t8u+onBinrPvIPI+0hWXGELm74g= @@ -53,8 +66,11 @@ github.com/pkg/diff v0.0.0-20210226163009-20ebb0f2a09e/go.mod h1:pJLUxLENpZxwdsK github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM= github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= +github.com/redis/go-redis/v9 v9.0.5 h1:CuQcn5HIEeK7BgElubPP8CGtE0KakrnbBSTLjathl5o= +github.com/redis/go-redis/v9 v9.0.5/go.mod h1:WqMKv5vnQbRuZstUwxQI195wHy+t4PuXDOjzMvcuQHk= github.com/rogpeppe/go-internal v1.9.0 h1:73kH8U+JUqXU8lRuOHeVHaa/SZPifC7BkcraZVejAe8= github.com/rogpeppe/go-internal v1.9.0/go.mod h1:WtVeX8xhTBvf0smdhujwtBcq4Qrzq/fJaraNFVN+nFs= +github.com/rs/xid v1.4.0 h1:qd7wPTDkN6KQx2VmMBLrpHkiyQwgFXRnkOLacUiaSNY= github.com/rs/xid v1.4.0/go.mod h1:trrq9SKmegXys3aeAKXMUTdJsYXVwGY3RLcfgqegfbg= github.com/rs/zerolog v1.28.0/go.mod h1:NILgTygv/Uej1ra5XxGf82ZFSLk58MFGAUS2o6usyD0= github.com/rs/zerolog v1.29.0 h1:Zes4hju04hjbvkVkOhdl2HpZa+0PmVwigmo8XoORE5w= @@ -68,8 +84,11 @@ github.com/stretchr/testify v1.7.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/ github.com/stretchr/testify v1.8.0/go.mod h1:yNjHg4UonilssWZ8iaSj1OCr/vHnekPRkoO+kdMU+MU= github.com/stretchr/testify v1.8.2 h1:+h33VjcLVPDHtOdpUCuF+7gSuG3yGIftsP1YvFihtJ8= github.com/stretchr/testify v1.8.2/go.mod h1:w2LPCIKwWwSfY2zedu0+kehJoqGctiVI29o6fzry7u4= +github.com/yuin/gopher-lua v1.1.0 h1:BojcDhfyDWgU2f2TOzYK/g5p2gxMrku8oupLDqlnSqE= +github.com/yuin/gopher-lua v1.1.0/go.mod h1:GBR0iDaNXjAgGg9zfCvksxSRnQx76gclCIb7kdAd1Pw= golang.org/x/exp v0.0.0-20230206171751-46f607a40771 h1:xP7rWLUr1e1n2xkK5YB4LI0hPEy3LJC6Wk+D4pGlOJg= golang.org/x/exp v0.0.0-20230206171751-46f607a40771/go.mod h1:CxIveKay+FTh1D0yPZemJVgC/95VzuuOLq5Qi4xnoYc= +golang.org/x/sys v0.0.0-20190204203706-41f3e6584952/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20210630005230-0f9fa26af87c/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20210927094055-39ccf1dd6fa6/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20220811171246-fbc7d0a398ab/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= diff --git a/pkg/jrpctest/suites.go b/pkg/jrpctest/suites.go index f91364b..9bb6bf1 100644 --- a/pkg/jrpctest/suites.go +++ b/pkg/jrpctest/suites.go @@ -122,7 +122,7 @@ func RunBasicTestSuite(t *testing.T, args BasicTestSuiteArgs) { } }) - makeTest("ResposeType", func(t *testing.T, server *server.Server, client codec.Conn) { + makeTest("ResposeType2", func(t *testing.T, server *server.Server, client codec.Conn) { if err := codec.CallInto(nil, client, nil, "test_echo", "hello", 10, &EchoArgs{"world"}); err != nil { t.Errorf("Passing nil as result should be fine, but got an error: %v", err) } -- GitLab