Skip to content

Commit

Permalink
Split jsonrpc2.go file into multiple files (#65)
Browse files Browse the repository at this point in the history
This merge request moves some of the contents from the jsonrpc2.go file
into their own designated file. The new files being introduced
(excluding test files) are as follows:

* conn.go
* request.go
* response.go

The motive of this change is to make it easier to navigate the code.
Without this change, the jsonrpc2.go file is 813 lines of code.
  • Loading branch information
samherrmann authored Feb 9, 2023
1 parent 028a50b commit 846c29e
Show file tree
Hide file tree
Showing 10 changed files with 1,028 additions and 978 deletions.
460 changes: 460 additions & 0 deletions conn.go

Large diffs are not rendered by default.

103 changes: 103 additions & 0 deletions conn_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,103 @@
package jsonrpc2_test

import (
"context"
"io"
"net"
"testing"
"time"

"github.com/sourcegraph/jsonrpc2"
)

func TestConn_DisconnectNotify(t *testing.T) {

t.Run("EOF", func(t *testing.T) {
connA, connB := net.Pipe()
c := jsonrpc2.NewConn(context.Background(), jsonrpc2.NewPlainObjectStream(connB), nil)
// By closing connA, connB receives io.EOF
if err := connA.Close(); err != nil {
t.Error(err)
}
assertDisconnect(t, c, connB)
})

t.Run("Close", func(t *testing.T) {
_, connB := net.Pipe()
c := jsonrpc2.NewConn(context.Background(), jsonrpc2.NewPlainObjectStream(connB), nil)
if err := c.Close(); err != nil {
t.Error(err)
}
assertDisconnect(t, c, connB)
})

t.Run("Close async", func(t *testing.T) {
done := make(chan struct{})
_, connB := net.Pipe()
c := jsonrpc2.NewConn(context.Background(), jsonrpc2.NewPlainObjectStream(connB), nil)
go func() {
if err := c.Close(); err != nil && err != jsonrpc2.ErrClosed {
t.Error(err)
}
close(done)
}()
assertDisconnect(t, c, connB)
<-done
})

t.Run("protocol error", func(t *testing.T) {
connA, connB := net.Pipe()
c := jsonrpc2.NewConn(context.Background(), jsonrpc2.NewPlainObjectStream(connB), nil)
connA.Write([]byte("invalid json"))
assertDisconnect(t, c, connB)
})
}

func TestConn_Close(t *testing.T) {
t.Run("waiting for response", func(t *testing.T) {
connA, connB := net.Pipe()
nodeA := jsonrpc2.NewConn(
context.Background(),
jsonrpc2.NewPlainObjectStream(connA), noopHandler{},
)
defer nodeA.Close()
nodeB := jsonrpc2.NewConn(
context.Background(),
jsonrpc2.NewPlainObjectStream(connB),
noopHandler{},
)
defer nodeB.Close()

ready := make(chan struct{})
done := make(chan struct{})
go func() {
close(ready)
err := nodeB.Call(context.Background(), "m", nil, nil)
if err != jsonrpc2.ErrClosed {
t.Errorf("got error %v, want %v", err, jsonrpc2.ErrClosed)
}
close(done)
}()
// Wait for the request to be sent before we close the connection.
<-ready
if err := nodeB.Close(); err != nil && err != jsonrpc2.ErrClosed {
t.Error(err)
}
assertDisconnect(t, nodeB, connB)
<-done
})
}

func assertDisconnect(t *testing.T, c *jsonrpc2.Conn, conn io.Writer) {
select {
case <-c.DisconnectNotify():
case <-time.After(200 * time.Millisecond):
t.Fatal("no disconnect notification")
}
// Assert that conn is closed by trying to write to it.
_, got := conn.Write(nil)
want := io.ErrClosedPipe
if got != want {
t.Fatalf("got %q, want %q", got, want)
}
}
35 changes: 35 additions & 0 deletions internal_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
package jsonrpc2

import (
"encoding/json"
"testing"
)

func TestAnyMessage(t *testing.T) {
tests := map[string]struct {
request, response, invalid bool
}{
// Single messages
`{}`: {invalid: true},
`{"foo":"bar"}`: {invalid: true},
`{"method":"m"}`: {request: true},
`{"result":123}`: {response: true},
`{"result":null}`: {response: true},
`{"error":{"code":456,"message":"m"}}`: {response: true},
}
for s, want := range tests {
var m anyMessage
if err := json.Unmarshal([]byte(s), &m); err != nil {
if !want.invalid {
t.Errorf("%s: error: %v", s, err)
}
continue
}
if (m.request != nil) != want.request {
t.Errorf("%s: got request %v, want %v", s, m.request != nil, want.request)
}
if (m.response != nil) != want.response {
t.Errorf("%s: got response %v, want %v", s, m.response != nil, want.response)
}
}
}
Loading

0 comments on commit 846c29e

Please sign in to comment.