go-ethereum/p2p/simulations/rest_api_server_test.go
zelig 7a6ff56333 p2p: network testing framework and protocol abstraction
subpackages:

* adapters:
  * msgpipes for simulated test connections
  * rlpx the RLPx adapter for normal non-test use
  * inproc simulated in-process network adapter
  * docker placeholder for docker cluster remote adapter
* protocols: easy-to-setup modular protocols
* simulations:
  * generic network model
  * journal, events, snapshots
  * cytoscape visualisation plugin
  * resourceful controller suite + REST API server
  * example: connectivity UX backend
* testing: test resource drivers
  * exchange: trigger/expect style driver for single node and its peers
  * sessions:   for unit testing protocols and protocol modules
  * (network: for network testing, benchmarking, stats, correctness, fault tolerance)
  * test peerpool

see more in the README-s in each subpackage

* p2p/server : conn/disconn hooks
* reporter remote client skeleton
2017-05-06 14:23:38 +01:00

137 lines
2.6 KiB
Go

package simulations
import (
"bytes"
"fmt"
"io"
"io/ioutil"
"net/http"
"testing"
)
const testPort = "8889"
type testController struct {
}
func (self *testController) SetResource(id string, c Controller) {
}
func (self *testController) Resource(id string) (Controller, error) {
if id == "missing" {
return nil, fmt.Errorf("missing")
}
return Controller(self), nil
}
func (self *testController) Handle(method string) (returnHandler, error) {
switch method {
case "POST":
case "DELETE":
default:
return nil, fmt.Errorf("allowed methods: POST DELETE")
}
return handlerf(method), nil
}
func handlerf(method string) returnHandler {
return func(r io.Reader) (io.ReadSeeker, error) {
body, err := ioutil.ReadAll(r)
if err != nil {
return nil, err
}
if string(body) == "invalid" {
return nil, fmt.Errorf("invalid body")
}
return io.ReadSeeker(bytes.NewReader([]byte("response"))), nil
}
}
func init() {
StartRestApiServer(testPort, &testController{})
}
type testRequest struct {
method string
path string
body string
response string
status int
}
type ReadCloser struct {
io.Reader
}
func (ReadCloser) Close() {}
func testResponses(t *testing.T, reqs ...*testRequest) {
for _, req := range reqs {
path := url(testPort, req.path)
var r *http.Response
var err error
switch req.method {
case "POST":
r, err = http.Post(path, "text/json", ReadCloser{bytes.NewReader([]byte(req.body))})
default:
r, err = http.Get(path)
}
if err != nil {
t.Fatalf("unexpected error on request: %v", err)
}
if r.StatusCode != req.status {
t.Fatalf("unexpected status on request: got %v, expected %v", r.StatusCode, req.status)
}
body, err := ioutil.ReadAll(r.Body)
if err != nil {
t.Fatalf("unexpected error on reading body: %v", err)
}
if string(body) != req.response {
t.Fatalf("unexpected response body. got '%s', expected '%v'", body, req.response)
}
}
}
func TestServerMethodNotAllowed(t *testing.T) {
testResponses(t,
&testRequest{
"GET",
"anypath",
"anybody",
"method GET not allowed (allowed methods: POST DELETE)\n",
http.StatusMethodNotAllowed,
})
}
func TestServerInvalid(t *testing.T) {
testResponses(t,
&testRequest{
"POST",
"anypath",
"invalid",
"handler error: invalid body\n",
http.StatusBadRequest,
})
}
func TestServerResourceNotFound(t *testing.T) {
testResponses(t,
&testRequest{
"POST",
"missing",
"anybody",
"resource missing not found\n",
http.StatusNotFound,
})
}
func TestServerSuccess(t *testing.T) {
testResponses(t,
&testRequest{
"POST",
"anypath",
"anybody",
"response",
http.StatusOK,
})
}