Skip to content

Commit

Permalink
🍦 Changer serve.Server to align with http.Server (#19)
Browse files Browse the repository at this point in the history
Changer serve.Server to align with http.Server, implementing a Server
and ListenAndServe method. This makes it also easier to create
TestServer similar to httptest.Server.

This refactor was motivated by the desire to run a _ready_ jigServer in
a go routine as

   jigServer.Run()

or similar and to avoid separate network probing and readiness check.

Pull-Request: #19
  • Loading branch information
juliaogris committed Jan 17, 2022
1 parent ddd514b commit 0e51654
Show file tree
Hide file tree
Showing 3 changed files with 39 additions and 34 deletions.
3 changes: 1 addition & 2 deletions main.go
Original file line number Diff line number Diff line change
Expand Up @@ -36,11 +36,10 @@ func main() {

func (cs *cmdServe) Run() error {
s := serve.Server{
Listen: cs.Listen,
MethodDir: cs.MethodDir,
ProtoSet: cs.ProtoSet,
}
return s.Run()
return s.ListenAndServe(cs.Listen)
}

func (cb *cmdBones) Run() error {
Expand Down
59 changes: 36 additions & 23 deletions serve/server.go
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ package serve

import (
"errors"
"fmt"
"net"
"os"

Expand All @@ -19,48 +20,50 @@ import (
)

type Server struct {
Listen string
MethodDir string
ProtoSet string

methods map[string]method
gs *grpc.Server
lis net.Listener
files *protoregistry.Files
}

var errUnknownHandler = errors.New("Unknown handler")

func (s *Server) setup() error {
err := s.loadMethods()
if err != nil {
return err
func NewServer(methodDir, protoSet string) (*Server, error) {
s := &Server{
MethodDir: methodDir,
ProtoSet: protoSet,
}
if err := s.loadMethods(); err != nil {
return nil, err
}
return s, nil
}

func (s *Server) Serve(lis net.Listener) error {
s.gs = grpc.NewServer(
grpc.StreamInterceptor(s.intercept),
grpc.UnknownServiceHandler(unknownHandler),
)

reflection.NewService(s.files).Register(s.gs)
return s.gs.Serve(lis)
}

s.lis, err = net.Listen("tcp", s.Listen)
func (s *Server) ListenAndServe(listenAddr string) error {
l, err := net.Listen("tcp", listenAddr)
if err != nil {
return err
}
return nil
return s.Serve(l)
}

func (s *Server) Run() error {
if err := s.setup(); err != nil {
return err
func (s *Server) Stop() {
if s.gs != nil {
s.gs.GracefulStop()
}
return s.gs.Serve(s.lis)
}

func (s *Server) Stop() {
s.gs.GracefulStop()
}
func (s *Server) loadMethods() error {
b, err := os.ReadFile(s.ProtoSet)
if err != nil {
Expand Down Expand Up @@ -117,16 +120,26 @@ func unknownHandler(_ interface{}, stream grpc.ServerStream) error {

type TestServer struct {
Server
lis net.Listener
}

func (s *TestServer) Start() error {
if err := s.setup(); err != nil {
return err
// NewTestServer starts and returns a new TestServer.
// The caller should call Stop when finished, to shut it down.
func NewTestServer(methodDir, protoSet string) *TestServer {
s, err := NewServer(methodDir, protoSet)
if err != nil {
panic(fmt.Sprintf("failed to create TestServer: %v", err))
}
go s.gs.Serve(s.lis) //nolint:errcheck
return nil
ts := &TestServer{Server: *s}
l, err := net.Listen("tcp", "localhost:0")
if err != nil {
panic(fmt.Sprintf("TestServer failed to listen: %v", err))
}
ts.lis = l
go ts.Serve(l) //nolint: errcheck
return ts
}

func (s *TestServer) Addr() string {
return s.lis.Addr().String()
func (ts *TestServer) Addr() string {
return ts.lis.Addr().String()
}
11 changes: 2 additions & 9 deletions serve/server_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -10,13 +10,8 @@ import (
)

func newTestServer(methodDir string) *TestServer {
return &TestServer{
Server{
Listen: "localhost:0",
MethodDir: (filepath.Join("testdata", methodDir)),
ProtoSet: "testdata/greeter.pb",
},
}
methodDir = filepath.Join("testdata", methodDir)
return NewTestServer(methodDir, "testdata/greeter.pb")
}

type testCase struct {
Expand All @@ -26,7 +21,6 @@ type testCase struct {

func TestGreeterSample(t *testing.T) {
ts := newTestServer("sample")
require.NoError(t, ts.Start())
defer ts.Stop()

c, err := client.New(ts.Addr())
Expand Down Expand Up @@ -81,7 +75,6 @@ type testCaseStatus struct {

func TestGreeterSampleStatus(t *testing.T) {
ts := newTestServer("sample")
require.NoError(t, ts.Start())
defer ts.Stop()

c, err := client.New(ts.Addr())
Expand Down

0 comments on commit 0e51654

Please sign in to comment.