Refactor and implement the api functions
This commit is contained in:
parent
3474e6ca8c
commit
f82565bf22
5 changed files with 139 additions and 108 deletions
2
.vscode/launch.json
vendored
2
.vscode/launch.json
vendored
|
@ -9,7 +9,7 @@
|
||||||
"type": "go",
|
"type": "go",
|
||||||
"request": "launch",
|
"request": "launch",
|
||||||
"mode": "auto",
|
"mode": "auto",
|
||||||
"program": "${workspaceFolder}/",
|
"program": "${workspaceFolder}/cmd/rove-server/main.go",
|
||||||
"cwd": "${workspaceFolder}",
|
"cwd": "${workspaceFolder}",
|
||||||
"env": {},
|
"env": {},
|
||||||
"args": [],
|
"args": [],
|
||||||
|
|
|
@ -1,10 +1,17 @@
|
||||||
package server
|
package rove
|
||||||
|
|
||||||
import "github.com/mdiluz/rove/pkg/game"
|
import (
|
||||||
|
"github.com/mdiluz/rove/pkg/game"
|
||||||
|
)
|
||||||
|
|
||||||
// ==============================
|
// ==============================
|
||||||
// API: /status method: GET
|
// API: /status method: GET
|
||||||
// Queries the status of the server
|
|
||||||
|
// Status queries the status of the server
|
||||||
|
func (s Server) Status() (r StatusResponse, err error) {
|
||||||
|
s.GET("status", &r)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
// StatusResponse is a struct that contains information on the status of the server
|
// StatusResponse is a struct that contains information on the status of the server
|
||||||
type StatusResponse struct {
|
type StatusResponse struct {
|
||||||
|
@ -14,8 +21,13 @@ type StatusResponse struct {
|
||||||
|
|
||||||
// ==============================
|
// ==============================
|
||||||
// API: /register method: POST
|
// API: /register method: POST
|
||||||
// Registers a user account by name
|
|
||||||
|
// Register registers a user account by name
|
||||||
// Responds with a unique ID for that account to be used in future requests
|
// Responds with a unique ID for that account to be used in future requests
|
||||||
|
func (s Server) Register(d RegisterData) (r RegisterResponse, err error) {
|
||||||
|
err = s.POST("register", d, &r)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
// RegisterData describes the data to send when registering
|
// RegisterData describes the data to send when registering
|
||||||
type RegisterData struct {
|
type RegisterData struct {
|
||||||
|
@ -32,8 +44,13 @@ type RegisterResponse struct {
|
||||||
|
|
||||||
// ==============================
|
// ==============================
|
||||||
// API: /spawn method: POST
|
// API: /spawn method: POST
|
||||||
// Spawns the rover for an account
|
|
||||||
|
// Spawn spawns the rover for an account
|
||||||
// Responds with the position of said rover
|
// Responds with the position of said rover
|
||||||
|
func (s Server) Spawn(d SpawnData) (r SpawnResponse, err error) {
|
||||||
|
err = s.POST("spawn", d, &r)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
// SpawnData is the data to be sent for the spawn command
|
// SpawnData is the data to be sent for the spawn command
|
||||||
type SpawnData struct {
|
type SpawnData struct {
|
||||||
|
@ -51,7 +68,12 @@ type SpawnResponse struct {
|
||||||
|
|
||||||
// ==============================
|
// ==============================
|
||||||
// API: /commands method: POST
|
// API: /commands method: POST
|
||||||
// Issues a set of commands from the user
|
|
||||||
|
// Commands issues a set of commands from the user
|
||||||
|
func (s Server) Commands(d CommandsData) (r CommandsResponse, err error) {
|
||||||
|
err = s.POST("commands", d, &r)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
// CommandsData is a set of commands to execute in order
|
// CommandsData is a set of commands to execute in order
|
||||||
type CommandsData struct {
|
type CommandsData struct {
|
||||||
|
@ -70,17 +92,6 @@ const (
|
||||||
CommandMove = "move"
|
CommandMove = "move"
|
||||||
)
|
)
|
||||||
|
|
||||||
const (
|
|
||||||
BearingNorth = "North"
|
|
||||||
BearingNorthEast
|
|
||||||
BearingEast
|
|
||||||
BearingSouthEast
|
|
||||||
BearingSouth
|
|
||||||
BearingSouthWest
|
|
||||||
BearingWest
|
|
||||||
BearingNorthWest
|
|
||||||
)
|
|
||||||
|
|
||||||
// Command describes a single command to execute
|
// Command describes a single command to execute
|
||||||
// it contains the type, and then any members used for each command type
|
// it contains the type, and then any members used for each command type
|
||||||
type Command struct {
|
type Command struct {
|
||||||
|
@ -94,7 +105,13 @@ type Command struct {
|
||||||
|
|
||||||
// ================
|
// ================
|
||||||
// API: /radar POST
|
// API: /radar POST
|
||||||
// Queries the current radar for the user
|
|
||||||
|
// Radar queries the current radar for the user
|
||||||
|
// Commands issues a set of commands from the user
|
||||||
|
func (s Server) Radar(d RadarData) (r RadarResponse, err error) {
|
||||||
|
err = s.POST("radar", d, &r)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
// RadarData describes the input data to request an accounts current radar
|
// RadarData describes the input data to request an accounts current radar
|
||||||
type RadarData struct {
|
type RadarData struct {
|
64
pkg/rove/http.go
Normal file
64
pkg/rove/http.go
Normal file
|
@ -0,0 +1,64 @@
|
||||||
|
package rove
|
||||||
|
|
||||||
|
import (
|
||||||
|
"bytes"
|
||||||
|
"encoding/json"
|
||||||
|
"fmt"
|
||||||
|
"net/http"
|
||||||
|
"net/url"
|
||||||
|
)
|
||||||
|
|
||||||
|
// Server is a simple wrapper to a server path
|
||||||
|
type Server string
|
||||||
|
|
||||||
|
// GET performs a GET request
|
||||||
|
func (s Server) GET(path string, out interface{}) error {
|
||||||
|
url := url.URL{
|
||||||
|
Scheme: "http",
|
||||||
|
Host: string(s),
|
||||||
|
Path: path,
|
||||||
|
}
|
||||||
|
if resp, err := http.Get(url.String()); err != nil {
|
||||||
|
return err
|
||||||
|
|
||||||
|
} else if resp.StatusCode != http.StatusOK {
|
||||||
|
return fmt.Errorf("http.Get returned status %d: %s", resp.StatusCode, resp.Status)
|
||||||
|
|
||||||
|
} else {
|
||||||
|
return json.NewDecoder(resp.Body).Decode(out)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// POST performs a POST request
|
||||||
|
func (s Server) POST(path string, in interface{}, out interface{}) error {
|
||||||
|
url := url.URL{
|
||||||
|
Scheme: "http",
|
||||||
|
Host: string(s),
|
||||||
|
Path: path,
|
||||||
|
}
|
||||||
|
client := &http.Client{}
|
||||||
|
|
||||||
|
// Marshal the input
|
||||||
|
marshalled, err := json.Marshal(in)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
// Set up the request
|
||||||
|
req, err := http.NewRequest("POST", url.String(), bytes.NewReader(marshalled))
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
// Do the POST
|
||||||
|
req.Header.Set("Content-Type", "application/json")
|
||||||
|
if resp, err := client.Do(req); err != nil {
|
||||||
|
return err
|
||||||
|
|
||||||
|
} else if resp.StatusCode != http.StatusOK {
|
||||||
|
return fmt.Errorf("http returned status %d", resp.StatusCode)
|
||||||
|
|
||||||
|
} else {
|
||||||
|
return json.NewDecoder(resp.Body).Decode(out)
|
||||||
|
}
|
||||||
|
}
|
39
pkg/rove/integration_test.go
Normal file
39
pkg/rove/integration_test.go
Normal file
|
@ -0,0 +1,39 @@
|
||||||
|
package rove
|
||||||
|
|
||||||
|
import (
|
||||||
|
"testing"
|
||||||
|
|
||||||
|
"github.com/google/uuid"
|
||||||
|
"github.com/stretchr/testify/assert"
|
||||||
|
)
|
||||||
|
|
||||||
|
var server Server = "localhost:80"
|
||||||
|
|
||||||
|
func TestStatus(t *testing.T) {
|
||||||
|
status, err := server.Status()
|
||||||
|
assert.NoError(t, err, "Status must not return error")
|
||||||
|
assert.True(t, status.Ready, "Server must return ready")
|
||||||
|
assert.NotZero(t, len(status.Version), "Version must not be empty")
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestRegister(t *testing.T) {
|
||||||
|
d1 := RegisterData{
|
||||||
|
Name: uuid.New().String(),
|
||||||
|
}
|
||||||
|
r1, err := server.Register(d1)
|
||||||
|
assert.NoError(t, err, "Register must not return error")
|
||||||
|
assert.True(t, r1.Success, "Register must return success")
|
||||||
|
assert.NotZero(t, len(r1.Id), "Register must return registration ID")
|
||||||
|
|
||||||
|
d2 := RegisterData{
|
||||||
|
Name: uuid.New().String(),
|
||||||
|
}
|
||||||
|
r2, err := server.Register(d2)
|
||||||
|
assert.NoError(t, err, "Register must not return error")
|
||||||
|
assert.True(t, r2.Success, "Register must return success")
|
||||||
|
assert.NotZero(t, len(r2.Id), "Register must return registration ID")
|
||||||
|
|
||||||
|
r3, err := server.Register(d1)
|
||||||
|
assert.NoError(t, err, "Register must not return error")
|
||||||
|
assert.False(t, r3.Success, "Register must return fail for duplicate registration")
|
||||||
|
}
|
|
@ -1,89 +0,0 @@
|
||||||
// +build integration
|
|
||||||
|
|
||||||
package server
|
|
||||||
|
|
||||||
import (
|
|
||||||
"bytes"
|
|
||||||
"encoding/json"
|
|
||||||
"fmt"
|
|
||||||
"net/http"
|
|
||||||
"net/url"
|
|
||||||
"testing"
|
|
||||||
|
|
||||||
"github.com/google/uuid"
|
|
||||||
"github.com/stretchr/testify/assert"
|
|
||||||
)
|
|
||||||
|
|
||||||
var serverUrl = "localhost:80"
|
|
||||||
|
|
||||||
func TestStatus(t *testing.T) {
|
|
||||||
url := url.URL{
|
|
||||||
Scheme: "http",
|
|
||||||
Host: serverUrl,
|
|
||||||
Path: "status",
|
|
||||||
}
|
|
||||||
resp, err := http.Get(url.String())
|
|
||||||
assert.NoError(t, err, "http.Get must not return error")
|
|
||||||
assert.Equal(t, http.StatusOK, resp.StatusCode, "http.Get must return StatusOK")
|
|
||||||
|
|
||||||
var status StatusResponse
|
|
||||||
err = json.NewDecoder(resp.Body).Decode(&status)
|
|
||||||
assert.NoError(t, err, "json decode must not return error")
|
|
||||||
|
|
||||||
assert.NoError(t, err, "Status must not return error")
|
|
||||||
assert.True(t, status.Ready, "Server must return ready")
|
|
||||||
assert.NotZero(t, len(status.Version), "Version must not be empty")
|
|
||||||
}
|
|
||||||
|
|
||||||
// helper for register test
|
|
||||||
func register(name string) (register RegisterResponse, err error) {
|
|
||||||
url := url.URL{
|
|
||||||
Scheme: "http",
|
|
||||||
Host: serverUrl,
|
|
||||||
Path: "register",
|
|
||||||
}
|
|
||||||
|
|
||||||
// Marshal the register data struct
|
|
||||||
data := RegisterData{Name: name}
|
|
||||||
marshalled, err := json.Marshal(data)
|
|
||||||
|
|
||||||
// Set up the request
|
|
||||||
req, err := http.NewRequest("POST", url.String(), bytes.NewReader(marshalled))
|
|
||||||
req.Header.Set("Content-Type", "application/json")
|
|
||||||
|
|
||||||
// Do the request
|
|
||||||
client := &http.Client{}
|
|
||||||
if resp, err := client.Do(req); err != nil {
|
|
||||||
return RegisterResponse{}, err
|
|
||||||
} else {
|
|
||||||
defer resp.Body.Close()
|
|
||||||
|
|
||||||
// Handle any errors
|
|
||||||
if resp.StatusCode != http.StatusOK {
|
|
||||||
return RegisterResponse{}, fmt.Errorf("Status request returned %d", resp.StatusCode)
|
|
||||||
} else {
|
|
||||||
// Decode the reply
|
|
||||||
err = json.NewDecoder(resp.Body).Decode(®ister)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestRegister(t *testing.T) {
|
|
||||||
a := uuid.New().String()
|
|
||||||
reg1, err := register(a)
|
|
||||||
assert.NoError(t, err, "Register must not return error")
|
|
||||||
assert.True(t, reg1.Success, "Register must return success")
|
|
||||||
assert.NotZero(t, len(reg1.Id), "Register must return registration ID")
|
|
||||||
|
|
||||||
b := uuid.New().String()
|
|
||||||
reg2, err := register(b)
|
|
||||||
assert.NoError(t, err, "Register must not return error")
|
|
||||||
assert.True(t, reg2.Success, "Register must return success")
|
|
||||||
assert.NotZero(t, len(reg2.Id), "Register must return registration ID")
|
|
||||||
|
|
||||||
reg2, err = register(a)
|
|
||||||
assert.NoError(t, err, "Register must not return error")
|
|
||||||
assert.False(t, reg2.Success, "Register must return fail for duplicate registration")
|
|
||||||
}
|
|
Loading…
Add table
Reference in a new issue