Fix test instabilities by refactoring to make address dynamic and readable
This commit is contained in:
parent
bc366583a4
commit
1d2087e2b9
7 changed files with 82 additions and 31 deletions
|
@ -1,6 +1,7 @@
|
||||||
package main
|
package main
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"fmt"
|
||||||
"os"
|
"os"
|
||||||
"testing"
|
"testing"
|
||||||
|
|
||||||
|
@ -10,16 +11,27 @@ import (
|
||||||
"github.com/stretchr/testify/assert"
|
"github.com/stretchr/testify/assert"
|
||||||
)
|
)
|
||||||
|
|
||||||
var serv rove.Server = "localhost:8080"
|
// To be set by the main function
|
||||||
|
var serv rove.Server
|
||||||
|
|
||||||
func TestMain(m *testing.M) {
|
func TestMain(m *testing.M) {
|
||||||
s := server.NewServer(server.OptionPort(8080))
|
s := server.NewServer()
|
||||||
s.Initialise()
|
if err := s.Initialise(); err != nil {
|
||||||
|
fmt.Println(err)
|
||||||
|
os.Exit(1)
|
||||||
|
}
|
||||||
|
|
||||||
|
serv = rove.Server(s.Addr())
|
||||||
|
|
||||||
go s.Run()
|
go s.Run()
|
||||||
|
|
||||||
|
fmt.Printf("Test server hosted on %s", serv)
|
||||||
code := m.Run()
|
code := m.Run()
|
||||||
|
|
||||||
s.Close()
|
if err := s.Close(); err != nil {
|
||||||
|
fmt.Println(err)
|
||||||
|
os.Exit(1)
|
||||||
|
}
|
||||||
|
|
||||||
os.Exit(code)
|
os.Exit(code)
|
||||||
}
|
}
|
||||||
|
|
|
@ -6,6 +6,7 @@ import (
|
||||||
"os"
|
"os"
|
||||||
"os/signal"
|
"os/signal"
|
||||||
"syscall"
|
"syscall"
|
||||||
|
"time"
|
||||||
|
|
||||||
"github.com/mdiluz/rove/pkg/persistence"
|
"github.com/mdiluz/rove/pkg/persistence"
|
||||||
"github.com/mdiluz/rove/pkg/server"
|
"github.com/mdiluz/rove/pkg/server"
|
||||||
|
@ -13,8 +14,9 @@ import (
|
||||||
)
|
)
|
||||||
|
|
||||||
var ver = flag.Bool("version", false, "Display version number")
|
var ver = flag.Bool("version", false, "Display version number")
|
||||||
var port = flag.Int("port", 8080, "The port to host on")
|
var port = flag.String("address", ":8080", "The address to host on")
|
||||||
var data = flag.String("data", os.TempDir(), "Directory to store persistant data")
|
var data = flag.String("data", os.TempDir(), "Directory to store persistant data")
|
||||||
|
var quit = flag.Int("quit", 0, "Quit after n seconds, useful for testing")
|
||||||
|
|
||||||
func main() {
|
func main() {
|
||||||
flag.Parse()
|
flag.Parse()
|
||||||
|
@ -32,7 +34,7 @@ func main() {
|
||||||
|
|
||||||
// Create the server data
|
// Create the server data
|
||||||
s := server.NewServer(
|
s := server.NewServer(
|
||||||
server.OptionPort(*port),
|
server.OptionAddress(*port),
|
||||||
server.OptionPersistentData())
|
server.OptionPersistentData())
|
||||||
|
|
||||||
// Initialise the server
|
// Initialise the server
|
||||||
|
@ -52,9 +54,19 @@ func main() {
|
||||||
os.Exit(0)
|
os.Exit(0)
|
||||||
}()
|
}()
|
||||||
|
|
||||||
fmt.Println("Running...")
|
// Quit after a time if requested
|
||||||
|
if *quit != 0 {
|
||||||
|
go func() {
|
||||||
|
time.Sleep(time.Duration(*quit) * time.Second)
|
||||||
|
if err := s.Close(); err != nil {
|
||||||
|
panic(err)
|
||||||
|
}
|
||||||
|
os.Exit(0)
|
||||||
|
}()
|
||||||
|
}
|
||||||
|
|
||||||
// Run the server
|
// Run the server
|
||||||
|
fmt.Printf("Serving HTTP on %s\n", s.Addr())
|
||||||
s.Run()
|
s.Run()
|
||||||
|
|
||||||
// Close the server
|
// Close the server
|
||||||
|
|
|
@ -2,6 +2,7 @@ package main
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"flag"
|
"flag"
|
||||||
|
"fmt"
|
||||||
"os"
|
"os"
|
||||||
"path"
|
"path"
|
||||||
"testing"
|
"testing"
|
||||||
|
@ -11,14 +12,26 @@ import (
|
||||||
"github.com/stretchr/testify/assert"
|
"github.com/stretchr/testify/assert"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
var address string
|
||||||
|
|
||||||
func TestMain(m *testing.M) {
|
func TestMain(m *testing.M) {
|
||||||
s := server.NewServer(server.OptionPort(8080))
|
s := server.NewServer()
|
||||||
s.Initialise()
|
if err := s.Initialise(); err != nil {
|
||||||
|
fmt.Println(err)
|
||||||
|
os.Exit(1)
|
||||||
|
}
|
||||||
|
|
||||||
|
address = s.Addr()
|
||||||
|
|
||||||
go s.Run()
|
go s.Run()
|
||||||
|
|
||||||
|
fmt.Printf("Test server hosted on %s", address)
|
||||||
code := m.Run()
|
code := m.Run()
|
||||||
|
|
||||||
s.Close()
|
if err := s.Close(); err != nil {
|
||||||
|
fmt.Println(err)
|
||||||
|
os.Exit(1)
|
||||||
|
}
|
||||||
|
|
||||||
os.Exit(code)
|
os.Exit(code)
|
||||||
}
|
}
|
||||||
|
@ -31,7 +44,7 @@ func Test_InnerMain(t *testing.T) {
|
||||||
assert.Error(t, InnerMain("status"))
|
assert.Error(t, InnerMain("status"))
|
||||||
|
|
||||||
// Now set the host
|
// Now set the host
|
||||||
flag.Set("host", "localhost:8080")
|
flag.Set("host", address)
|
||||||
|
|
||||||
// No error now as we have a host
|
// No error now as we have a host
|
||||||
assert.NoError(t, InnerMain("status"))
|
assert.NoError(t, InnerMain("status"))
|
||||||
|
|
|
@ -11,6 +11,6 @@ services:
|
||||||
image: rove-server:latest
|
image: rove-server:latest
|
||||||
ports:
|
ports:
|
||||||
- "80:80"
|
- "80:80"
|
||||||
command: ./rove-server --port 80 --data=/mnt/rove-server
|
command: ./rove-server --address ":80" --data=/mnt/rove-server ${ROVE_ARGS}
|
||||||
volumes:
|
volumes:
|
||||||
- persistent-data:/mnt/rove-server:rw
|
- persistent-data:/mnt/rove-server:rw
|
||||||
|
|
|
@ -5,6 +5,7 @@ import (
|
||||||
"encoding/json"
|
"encoding/json"
|
||||||
"fmt"
|
"fmt"
|
||||||
"log"
|
"log"
|
||||||
|
"net"
|
||||||
"net/http"
|
"net/http"
|
||||||
"sync"
|
"sync"
|
||||||
"time"
|
"time"
|
||||||
|
@ -27,12 +28,14 @@ const (
|
||||||
|
|
||||||
// Server contains the relevant data to run a game server
|
// Server contains the relevant data to run a game server
|
||||||
type Server struct {
|
type Server struct {
|
||||||
port int
|
address string
|
||||||
|
|
||||||
accountant *accounts.Accountant
|
accountant *accounts.Accountant
|
||||||
world *game.World
|
world *game.World
|
||||||
|
|
||||||
|
listener net.Listener
|
||||||
server *http.Server
|
server *http.Server
|
||||||
|
|
||||||
router *mux.Router
|
router *mux.Router
|
||||||
|
|
||||||
persistence int
|
persistence int
|
||||||
|
@ -43,10 +46,10 @@ type Server struct {
|
||||||
// ServerOption defines a server creation option
|
// ServerOption defines a server creation option
|
||||||
type ServerOption func(s *Server)
|
type ServerOption func(s *Server)
|
||||||
|
|
||||||
// OptionPort sets the server port for hosting
|
// OptionAddress sets the server address for hosting
|
||||||
func OptionPort(port int) ServerOption {
|
func OptionAddress(address string) ServerOption {
|
||||||
return func(s *Server) {
|
return func(s *Server) {
|
||||||
s.port = port
|
s.address = address
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -64,7 +67,7 @@ func NewServer(opts ...ServerOption) *Server {
|
||||||
|
|
||||||
// Set up the default server
|
// Set up the default server
|
||||||
s := &Server{
|
s := &Server{
|
||||||
port: 8080,
|
address: "",
|
||||||
persistence: EphemeralData,
|
persistence: EphemeralData,
|
||||||
router: router,
|
router: router,
|
||||||
}
|
}
|
||||||
|
@ -75,7 +78,7 @@ func NewServer(opts ...ServerOption) *Server {
|
||||||
}
|
}
|
||||||
|
|
||||||
// Set up the server object
|
// Set up the server object
|
||||||
s.server = &http.Server{Addr: fmt.Sprintf(":%d", s.port), Handler: router}
|
s.server = &http.Server{Addr: s.address, Handler: s.router}
|
||||||
|
|
||||||
// Create the accountant
|
// Create the accountant
|
||||||
s.accountant = accounts.NewAccountant()
|
s.accountant = accounts.NewAccountant()
|
||||||
|
@ -85,7 +88,10 @@ func NewServer(opts ...ServerOption) *Server {
|
||||||
}
|
}
|
||||||
|
|
||||||
// Initialise sets up internal state ready to serve
|
// Initialise sets up internal state ready to serve
|
||||||
func (s *Server) Initialise() error {
|
func (s *Server) Initialise() (err error) {
|
||||||
|
|
||||||
|
// Add to our sync
|
||||||
|
s.sync.Add(1)
|
||||||
|
|
||||||
// Load the accounts if requested
|
// Load the accounts if requested
|
||||||
if s.persistence == PersistentData {
|
if s.persistence == PersistentData {
|
||||||
|
@ -99,19 +105,26 @@ func (s *Server) Initialise() error {
|
||||||
s.router.HandleFunc(route.path, s.wrapHandler(route.method, route.handler))
|
s.router.HandleFunc(route.path, s.wrapHandler(route.method, route.handler))
|
||||||
}
|
}
|
||||||
|
|
||||||
// Add to our sync
|
// Start the listen
|
||||||
s.sync.Add(1)
|
if s.listener, err = net.Listen("tcp", s.server.Addr); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
s.address = s.listener.Addr().String()
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Addr will return the server address set after the listen
|
||||||
|
func (s Server) Addr() string {
|
||||||
|
return s.address
|
||||||
|
}
|
||||||
|
|
||||||
// Run executes the server
|
// Run executes the server
|
||||||
func (s *Server) Run() {
|
func (s *Server) Run() {
|
||||||
defer s.sync.Done()
|
defer s.sync.Done()
|
||||||
|
|
||||||
// Listen and serve the http requests
|
// Serve the http requests
|
||||||
fmt.Printf("Serving HTTP on port %d\n", s.port)
|
if err := s.server.Serve(s.listener); err != nil && err != http.ErrServerClosed {
|
||||||
if err := s.server.ListenAndServe(); err != nil && err != http.ErrServerClosed {
|
|
||||||
log.Fatal(err)
|
log.Fatal(err)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -11,12 +11,12 @@ func TestNewServer(t *testing.T) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestNewServer_OptionPort(t *testing.T) {
|
func TestNewServer_OptionAddress(t *testing.T) {
|
||||||
server := NewServer(OptionPort(1234))
|
server := NewServer(OptionAddress(":1234"))
|
||||||
if server == nil {
|
if server == nil {
|
||||||
t.Error("Failed to create server")
|
t.Error("Failed to create server")
|
||||||
} else if server.port != 1234 {
|
} else if server.address != ":1234" {
|
||||||
t.Error("Failed to set server port")
|
t.Error("Failed to set server address")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -36,6 +36,7 @@ func TestServer_Run(t *testing.T) {
|
||||||
} else if err := server.Initialise(); err != nil {
|
} else if err := server.Initialise(); err != nil {
|
||||||
t.Error(err)
|
t.Error(err)
|
||||||
}
|
}
|
||||||
|
|
||||||
go server.Run()
|
go server.Run()
|
||||||
|
|
||||||
if err := server.Close(); err != nil {
|
if err := server.Close(); err != nil {
|
||||||
|
@ -50,6 +51,7 @@ func TestServer_RunPersistentData(t *testing.T) {
|
||||||
} else if err := server.Initialise(); err != nil {
|
} else if err := server.Initialise(); err != nil {
|
||||||
t.Error(err)
|
t.Error(err)
|
||||||
}
|
}
|
||||||
|
|
||||||
go server.Run()
|
go server.Run()
|
||||||
|
|
||||||
if err := server.Close(); err != nil {
|
if err := server.Close(); err != nil {
|
||||||
|
|
|
@ -9,8 +9,7 @@ go mod download
|
||||||
go build ./...
|
go build ./...
|
||||||
|
|
||||||
# Run the server and shut it down again to ensure our docker-compose works
|
# Run the server and shut it down again to ensure our docker-compose works
|
||||||
docker-compose up --detach --build
|
ROVE_ARGS="--quit 1" docker-compose up --build --exit-code-from=rove-server --abort-on-container-exit
|
||||||
docker-compose down
|
|
||||||
|
|
||||||
# Run tests with coverage
|
# Run tests with coverage
|
||||||
go test -v ./... -cover -coverprofile=/tmp/c.out
|
go test -v ./... -cover -coverprofile=/tmp/c.out
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue