2777 lines
65 KiB
Go
2777 lines
65 KiB
Go
// Code generated by go generate; DO NOT EDIT.
|
|
// 2022-05-19 20:30:46.817279 +0200 CEST m=+0.001015835
|
|
|
|
package ooapi
|
|
|
|
//go:generate go run ./internal/generator -file apis_test.go
|
|
|
|
import (
|
|
"context"
|
|
"encoding/json"
|
|
"errors"
|
|
"net/http"
|
|
"net/http/httptest"
|
|
"net/url"
|
|
"strings"
|
|
"sync"
|
|
"testing"
|
|
|
|
"github.com/google/go-cmp/cmp"
|
|
"github.com/ooni/probe-cli/v3/internal/netxlite"
|
|
"github.com/ooni/probe-cli/v3/internal/ooapi/apimodel"
|
|
)
|
|
|
|
func TestCheckReportIDInvalidURL(t *testing.T) {
|
|
api := &simpleCheckReportIDAPI{
|
|
BaseURL: "\t", // invalid
|
|
}
|
|
ctx := context.Background()
|
|
req := &apimodel.CheckReportIDRequest{}
|
|
ff := &fakeFill{}
|
|
ff.Fill(req)
|
|
resp, err := api.Call(ctx, req)
|
|
if err == nil || !strings.HasSuffix(err.Error(), "invalid control character in URL") {
|
|
t.Fatal("not the error we expected", err)
|
|
}
|
|
if resp != nil {
|
|
t.Fatal("expected nil resp")
|
|
}
|
|
}
|
|
|
|
func TestCheckReportIDWithHTTPErr(t *testing.T) {
|
|
errMocked := errors.New("mocked error")
|
|
clnt := &FakeHTTPClient{Err: errMocked}
|
|
api := &simpleCheckReportIDAPI{
|
|
HTTPClient: clnt,
|
|
}
|
|
ctx := context.Background()
|
|
req := &apimodel.CheckReportIDRequest{}
|
|
ff := &fakeFill{}
|
|
ff.Fill(req)
|
|
resp, err := api.Call(ctx, req)
|
|
if !errors.Is(err, errMocked) {
|
|
t.Fatal("not the error we expected", err)
|
|
}
|
|
if resp != nil {
|
|
t.Fatal("expected nil resp")
|
|
}
|
|
}
|
|
|
|
func TestCheckReportIDWithNewRequestErr(t *testing.T) {
|
|
errMocked := errors.New("mocked error")
|
|
api := &simpleCheckReportIDAPI{
|
|
RequestMaker: &FakeRequestMaker{Err: errMocked},
|
|
}
|
|
ctx := context.Background()
|
|
req := &apimodel.CheckReportIDRequest{}
|
|
ff := &fakeFill{}
|
|
ff.Fill(req)
|
|
resp, err := api.Call(ctx, req)
|
|
if !errors.Is(err, errMocked) {
|
|
t.Fatal("not the error we expected", err)
|
|
}
|
|
if resp != nil {
|
|
t.Fatal("expected nil resp")
|
|
}
|
|
}
|
|
|
|
func TestCheckReportIDWith401(t *testing.T) {
|
|
clnt := &FakeHTTPClient{Resp: &http.Response{StatusCode: 401}}
|
|
api := &simpleCheckReportIDAPI{
|
|
HTTPClient: clnt,
|
|
}
|
|
ctx := context.Background()
|
|
req := &apimodel.CheckReportIDRequest{}
|
|
ff := &fakeFill{}
|
|
ff.Fill(req)
|
|
resp, err := api.Call(ctx, req)
|
|
if !errors.Is(err, ErrUnauthorized) {
|
|
t.Fatal("not the error we expected", err)
|
|
}
|
|
if resp != nil {
|
|
t.Fatal("expected nil resp")
|
|
}
|
|
}
|
|
|
|
func TestCheckReportIDWith400(t *testing.T) {
|
|
clnt := &FakeHTTPClient{Resp: &http.Response{StatusCode: 400}}
|
|
api := &simpleCheckReportIDAPI{
|
|
HTTPClient: clnt,
|
|
}
|
|
ctx := context.Background()
|
|
req := &apimodel.CheckReportIDRequest{}
|
|
ff := &fakeFill{}
|
|
ff.Fill(req)
|
|
resp, err := api.Call(ctx, req)
|
|
if !errors.Is(err, ErrHTTPFailure) {
|
|
t.Fatal("not the error we expected", err)
|
|
}
|
|
if resp != nil {
|
|
t.Fatal("expected nil resp")
|
|
}
|
|
}
|
|
|
|
func TestCheckReportIDWithResponseBodyReadErr(t *testing.T) {
|
|
errMocked := errors.New("mocked error")
|
|
clnt := &FakeHTTPClient{Resp: &http.Response{
|
|
StatusCode: 200,
|
|
Body: &FakeBody{Err: errMocked},
|
|
}}
|
|
api := &simpleCheckReportIDAPI{
|
|
HTTPClient: clnt,
|
|
}
|
|
ctx := context.Background()
|
|
req := &apimodel.CheckReportIDRequest{}
|
|
ff := &fakeFill{}
|
|
ff.Fill(req)
|
|
resp, err := api.Call(ctx, req)
|
|
if !errors.Is(err, errMocked) {
|
|
t.Fatal("not the error we expected", err)
|
|
}
|
|
if resp != nil {
|
|
t.Fatal("expected nil resp")
|
|
}
|
|
}
|
|
|
|
func TestCheckReportIDWithUnmarshalFailure(t *testing.T) {
|
|
errMocked := errors.New("mocked error")
|
|
clnt := &FakeHTTPClient{Resp: &http.Response{
|
|
StatusCode: 200,
|
|
Body: &FakeBody{Data: []byte(`{}`)},
|
|
}}
|
|
api := &simpleCheckReportIDAPI{
|
|
HTTPClient: clnt,
|
|
JSONCodec: &FakeCodec{DecodeErr: errMocked},
|
|
}
|
|
ctx := context.Background()
|
|
req := &apimodel.CheckReportIDRequest{}
|
|
ff := &fakeFill{}
|
|
ff.Fill(req)
|
|
resp, err := api.Call(ctx, req)
|
|
if !errors.Is(err, errMocked) {
|
|
t.Fatal("not the error we expected", err)
|
|
}
|
|
if resp != nil {
|
|
t.Fatal("expected nil resp")
|
|
}
|
|
}
|
|
|
|
type handleCheckReportID struct {
|
|
accept string
|
|
body []byte
|
|
contentType string
|
|
count int32
|
|
method string
|
|
mu sync.Mutex
|
|
resp *apimodel.CheckReportIDResponse
|
|
url *url.URL
|
|
userAgent string
|
|
}
|
|
|
|
func (h *handleCheckReportID) ServeHTTP(w http.ResponseWriter, r *http.Request) {
|
|
defer h.mu.Unlock()
|
|
h.mu.Lock()
|
|
if h.count > 0 {
|
|
w.WriteHeader(400)
|
|
return
|
|
}
|
|
h.count++
|
|
if r.Body != nil {
|
|
data, err := netxlite.ReadAllContext(r.Context(), r.Body)
|
|
if err != nil {
|
|
w.WriteHeader(400)
|
|
return
|
|
}
|
|
h.body = data
|
|
}
|
|
h.method = r.Method
|
|
h.url = r.URL
|
|
h.accept = r.Header.Get("Accept")
|
|
h.contentType = r.Header.Get("Content-Type")
|
|
h.userAgent = r.Header.Get("User-Agent")
|
|
var out *apimodel.CheckReportIDResponse
|
|
ff := fakeFill{}
|
|
ff.Fill(&out)
|
|
h.resp = out
|
|
data, err := json.Marshal(out)
|
|
if err != nil {
|
|
w.WriteHeader(400)
|
|
return
|
|
}
|
|
w.Write(data)
|
|
}
|
|
|
|
func TestCheckReportIDRoundTrip(t *testing.T) {
|
|
// setup
|
|
handler := &handleCheckReportID{}
|
|
srvr := httptest.NewServer(handler)
|
|
defer srvr.Close()
|
|
req := &apimodel.CheckReportIDRequest{}
|
|
ff := &fakeFill{}
|
|
ff.Fill(&req)
|
|
api := &simpleCheckReportIDAPI{BaseURL: srvr.URL}
|
|
ff.Fill(&api.UserAgent)
|
|
// issue request
|
|
ctx := context.Background()
|
|
resp, err := api.Call(ctx, req)
|
|
if err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
if resp == nil {
|
|
t.Fatal("expected non-nil response here")
|
|
}
|
|
// compare our response and server's one
|
|
if diff := cmp.Diff(handler.resp, resp); diff != "" {
|
|
t.Fatal(diff)
|
|
}
|
|
// check whether headers are OK
|
|
if handler.accept != "application/json" {
|
|
t.Fatal("invalid accept header")
|
|
}
|
|
if handler.userAgent != api.UserAgent {
|
|
t.Fatal("invalid user-agent header")
|
|
}
|
|
// check whether the method is OK
|
|
if handler.method != "GET" {
|
|
t.Fatal("invalid method")
|
|
}
|
|
// check the query
|
|
httpReq, err := api.newRequest(context.Background(), req)
|
|
if err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
if diff := cmp.Diff(handler.url.Path, httpReq.URL.Path); diff != "" {
|
|
t.Fatal(diff)
|
|
}
|
|
if diff := cmp.Diff(handler.url.RawQuery, httpReq.URL.RawQuery); diff != "" {
|
|
t.Fatal(diff)
|
|
}
|
|
}
|
|
|
|
func TestCheckReportIDMandatoryFields(t *testing.T) {
|
|
clnt := &FakeHTTPClient{Resp: &http.Response{
|
|
StatusCode: 500,
|
|
}}
|
|
api := &simpleCheckReportIDAPI{
|
|
HTTPClient: clnt,
|
|
}
|
|
ctx := context.Background()
|
|
req := &apimodel.CheckReportIDRequest{} // deliberately empty
|
|
resp, err := api.Call(ctx, req)
|
|
if !errors.Is(err, ErrEmptyField) {
|
|
t.Fatal("not the error we expected", err)
|
|
}
|
|
if resp != nil {
|
|
t.Fatal("expected nil resp")
|
|
}
|
|
}
|
|
|
|
func TestCheckInInvalidURL(t *testing.T) {
|
|
api := &simpleCheckInAPI{
|
|
BaseURL: "\t", // invalid
|
|
}
|
|
ctx := context.Background()
|
|
req := &apimodel.CheckInRequest{}
|
|
ff := &fakeFill{}
|
|
ff.Fill(req)
|
|
resp, err := api.Call(ctx, req)
|
|
if err == nil || !strings.HasSuffix(err.Error(), "invalid control character in URL") {
|
|
t.Fatal("not the error we expected", err)
|
|
}
|
|
if resp != nil {
|
|
t.Fatal("expected nil resp")
|
|
}
|
|
}
|
|
|
|
func TestCheckInWithHTTPErr(t *testing.T) {
|
|
errMocked := errors.New("mocked error")
|
|
clnt := &FakeHTTPClient{Err: errMocked}
|
|
api := &simpleCheckInAPI{
|
|
HTTPClient: clnt,
|
|
}
|
|
ctx := context.Background()
|
|
req := &apimodel.CheckInRequest{}
|
|
ff := &fakeFill{}
|
|
ff.Fill(req)
|
|
resp, err := api.Call(ctx, req)
|
|
if !errors.Is(err, errMocked) {
|
|
t.Fatal("not the error we expected", err)
|
|
}
|
|
if resp != nil {
|
|
t.Fatal("expected nil resp")
|
|
}
|
|
}
|
|
|
|
func TestCheckInMarshalErr(t *testing.T) {
|
|
errMocked := errors.New("mocked error")
|
|
api := &simpleCheckInAPI{
|
|
JSONCodec: &FakeCodec{EncodeErr: errMocked},
|
|
}
|
|
ctx := context.Background()
|
|
req := &apimodel.CheckInRequest{}
|
|
ff := &fakeFill{}
|
|
ff.Fill(req)
|
|
resp, err := api.Call(ctx, req)
|
|
if !errors.Is(err, errMocked) {
|
|
t.Fatal("not the error we expected", err)
|
|
}
|
|
if resp != nil {
|
|
t.Fatal("expected nil resp")
|
|
}
|
|
}
|
|
|
|
func TestCheckInWithNewRequestErr(t *testing.T) {
|
|
errMocked := errors.New("mocked error")
|
|
api := &simpleCheckInAPI{
|
|
RequestMaker: &FakeRequestMaker{Err: errMocked},
|
|
}
|
|
ctx := context.Background()
|
|
req := &apimodel.CheckInRequest{}
|
|
ff := &fakeFill{}
|
|
ff.Fill(req)
|
|
resp, err := api.Call(ctx, req)
|
|
if !errors.Is(err, errMocked) {
|
|
t.Fatal("not the error we expected", err)
|
|
}
|
|
if resp != nil {
|
|
t.Fatal("expected nil resp")
|
|
}
|
|
}
|
|
|
|
func TestCheckInWith401(t *testing.T) {
|
|
clnt := &FakeHTTPClient{Resp: &http.Response{StatusCode: 401}}
|
|
api := &simpleCheckInAPI{
|
|
HTTPClient: clnt,
|
|
}
|
|
ctx := context.Background()
|
|
req := &apimodel.CheckInRequest{}
|
|
ff := &fakeFill{}
|
|
ff.Fill(req)
|
|
resp, err := api.Call(ctx, req)
|
|
if !errors.Is(err, ErrUnauthorized) {
|
|
t.Fatal("not the error we expected", err)
|
|
}
|
|
if resp != nil {
|
|
t.Fatal("expected nil resp")
|
|
}
|
|
}
|
|
|
|
func TestCheckInWith400(t *testing.T) {
|
|
clnt := &FakeHTTPClient{Resp: &http.Response{StatusCode: 400}}
|
|
api := &simpleCheckInAPI{
|
|
HTTPClient: clnt,
|
|
}
|
|
ctx := context.Background()
|
|
req := &apimodel.CheckInRequest{}
|
|
ff := &fakeFill{}
|
|
ff.Fill(req)
|
|
resp, err := api.Call(ctx, req)
|
|
if !errors.Is(err, ErrHTTPFailure) {
|
|
t.Fatal("not the error we expected", err)
|
|
}
|
|
if resp != nil {
|
|
t.Fatal("expected nil resp")
|
|
}
|
|
}
|
|
|
|
func TestCheckInWithResponseBodyReadErr(t *testing.T) {
|
|
errMocked := errors.New("mocked error")
|
|
clnt := &FakeHTTPClient{Resp: &http.Response{
|
|
StatusCode: 200,
|
|
Body: &FakeBody{Err: errMocked},
|
|
}}
|
|
api := &simpleCheckInAPI{
|
|
HTTPClient: clnt,
|
|
}
|
|
ctx := context.Background()
|
|
req := &apimodel.CheckInRequest{}
|
|
ff := &fakeFill{}
|
|
ff.Fill(req)
|
|
resp, err := api.Call(ctx, req)
|
|
if !errors.Is(err, errMocked) {
|
|
t.Fatal("not the error we expected", err)
|
|
}
|
|
if resp != nil {
|
|
t.Fatal("expected nil resp")
|
|
}
|
|
}
|
|
|
|
func TestCheckInWithUnmarshalFailure(t *testing.T) {
|
|
errMocked := errors.New("mocked error")
|
|
clnt := &FakeHTTPClient{Resp: &http.Response{
|
|
StatusCode: 200,
|
|
Body: &FakeBody{Data: []byte(`{}`)},
|
|
}}
|
|
api := &simpleCheckInAPI{
|
|
HTTPClient: clnt,
|
|
JSONCodec: &FakeCodec{DecodeErr: errMocked},
|
|
}
|
|
ctx := context.Background()
|
|
req := &apimodel.CheckInRequest{}
|
|
ff := &fakeFill{}
|
|
ff.Fill(req)
|
|
resp, err := api.Call(ctx, req)
|
|
if !errors.Is(err, errMocked) {
|
|
t.Fatal("not the error we expected", err)
|
|
}
|
|
if resp != nil {
|
|
t.Fatal("expected nil resp")
|
|
}
|
|
}
|
|
|
|
type handleCheckIn struct {
|
|
accept string
|
|
body []byte
|
|
contentType string
|
|
count int32
|
|
method string
|
|
mu sync.Mutex
|
|
resp *apimodel.CheckInResponse
|
|
url *url.URL
|
|
userAgent string
|
|
}
|
|
|
|
func (h *handleCheckIn) ServeHTTP(w http.ResponseWriter, r *http.Request) {
|
|
defer h.mu.Unlock()
|
|
h.mu.Lock()
|
|
if h.count > 0 {
|
|
w.WriteHeader(400)
|
|
return
|
|
}
|
|
h.count++
|
|
if r.Body != nil {
|
|
data, err := netxlite.ReadAllContext(r.Context(), r.Body)
|
|
if err != nil {
|
|
w.WriteHeader(400)
|
|
return
|
|
}
|
|
h.body = data
|
|
}
|
|
h.method = r.Method
|
|
h.url = r.URL
|
|
h.accept = r.Header.Get("Accept")
|
|
h.contentType = r.Header.Get("Content-Type")
|
|
h.userAgent = r.Header.Get("User-Agent")
|
|
var out *apimodel.CheckInResponse
|
|
ff := fakeFill{}
|
|
ff.Fill(&out)
|
|
h.resp = out
|
|
data, err := json.Marshal(out)
|
|
if err != nil {
|
|
w.WriteHeader(400)
|
|
return
|
|
}
|
|
w.Write(data)
|
|
}
|
|
|
|
func TestCheckInRoundTrip(t *testing.T) {
|
|
// setup
|
|
handler := &handleCheckIn{}
|
|
srvr := httptest.NewServer(handler)
|
|
defer srvr.Close()
|
|
req := &apimodel.CheckInRequest{}
|
|
ff := &fakeFill{}
|
|
ff.Fill(&req)
|
|
api := &simpleCheckInAPI{BaseURL: srvr.URL}
|
|
ff.Fill(&api.UserAgent)
|
|
// issue request
|
|
ctx := context.Background()
|
|
resp, err := api.Call(ctx, req)
|
|
if err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
if resp == nil {
|
|
t.Fatal("expected non-nil response here")
|
|
}
|
|
// compare our response and server's one
|
|
if diff := cmp.Diff(handler.resp, resp); diff != "" {
|
|
t.Fatal(diff)
|
|
}
|
|
// check whether headers are OK
|
|
if handler.accept != "application/json" {
|
|
t.Fatal("invalid accept header")
|
|
}
|
|
if handler.userAgent != api.UserAgent {
|
|
t.Fatal("invalid user-agent header")
|
|
}
|
|
// check whether the method is OK
|
|
if handler.method != "POST" {
|
|
t.Fatal("invalid method")
|
|
}
|
|
// check the body
|
|
if handler.contentType != "application/json" {
|
|
t.Fatal("invalid content-type header")
|
|
}
|
|
got := &apimodel.CheckInRequest{}
|
|
if err := json.Unmarshal(handler.body, &got); err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
if diff := cmp.Diff(req, got); diff != "" {
|
|
t.Fatal(diff)
|
|
}
|
|
}
|
|
|
|
func TestLoginInvalidURL(t *testing.T) {
|
|
api := &simpleLoginAPI{
|
|
BaseURL: "\t", // invalid
|
|
}
|
|
ctx := context.Background()
|
|
req := &apimodel.LoginRequest{}
|
|
ff := &fakeFill{}
|
|
ff.Fill(req)
|
|
resp, err := api.Call(ctx, req)
|
|
if err == nil || !strings.HasSuffix(err.Error(), "invalid control character in URL") {
|
|
t.Fatal("not the error we expected", err)
|
|
}
|
|
if resp != nil {
|
|
t.Fatal("expected nil resp")
|
|
}
|
|
}
|
|
|
|
func TestLoginWithHTTPErr(t *testing.T) {
|
|
errMocked := errors.New("mocked error")
|
|
clnt := &FakeHTTPClient{Err: errMocked}
|
|
api := &simpleLoginAPI{
|
|
HTTPClient: clnt,
|
|
}
|
|
ctx := context.Background()
|
|
req := &apimodel.LoginRequest{}
|
|
ff := &fakeFill{}
|
|
ff.Fill(req)
|
|
resp, err := api.Call(ctx, req)
|
|
if !errors.Is(err, errMocked) {
|
|
t.Fatal("not the error we expected", err)
|
|
}
|
|
if resp != nil {
|
|
t.Fatal("expected nil resp")
|
|
}
|
|
}
|
|
|
|
func TestLoginMarshalErr(t *testing.T) {
|
|
errMocked := errors.New("mocked error")
|
|
api := &simpleLoginAPI{
|
|
JSONCodec: &FakeCodec{EncodeErr: errMocked},
|
|
}
|
|
ctx := context.Background()
|
|
req := &apimodel.LoginRequest{}
|
|
ff := &fakeFill{}
|
|
ff.Fill(req)
|
|
resp, err := api.Call(ctx, req)
|
|
if !errors.Is(err, errMocked) {
|
|
t.Fatal("not the error we expected", err)
|
|
}
|
|
if resp != nil {
|
|
t.Fatal("expected nil resp")
|
|
}
|
|
}
|
|
|
|
func TestLoginWithNewRequestErr(t *testing.T) {
|
|
errMocked := errors.New("mocked error")
|
|
api := &simpleLoginAPI{
|
|
RequestMaker: &FakeRequestMaker{Err: errMocked},
|
|
}
|
|
ctx := context.Background()
|
|
req := &apimodel.LoginRequest{}
|
|
ff := &fakeFill{}
|
|
ff.Fill(req)
|
|
resp, err := api.Call(ctx, req)
|
|
if !errors.Is(err, errMocked) {
|
|
t.Fatal("not the error we expected", err)
|
|
}
|
|
if resp != nil {
|
|
t.Fatal("expected nil resp")
|
|
}
|
|
}
|
|
|
|
func TestLoginWith401(t *testing.T) {
|
|
clnt := &FakeHTTPClient{Resp: &http.Response{StatusCode: 401}}
|
|
api := &simpleLoginAPI{
|
|
HTTPClient: clnt,
|
|
}
|
|
ctx := context.Background()
|
|
req := &apimodel.LoginRequest{}
|
|
ff := &fakeFill{}
|
|
ff.Fill(req)
|
|
resp, err := api.Call(ctx, req)
|
|
if !errors.Is(err, ErrUnauthorized) {
|
|
t.Fatal("not the error we expected", err)
|
|
}
|
|
if resp != nil {
|
|
t.Fatal("expected nil resp")
|
|
}
|
|
}
|
|
|
|
func TestLoginWith400(t *testing.T) {
|
|
clnt := &FakeHTTPClient{Resp: &http.Response{StatusCode: 400}}
|
|
api := &simpleLoginAPI{
|
|
HTTPClient: clnt,
|
|
}
|
|
ctx := context.Background()
|
|
req := &apimodel.LoginRequest{}
|
|
ff := &fakeFill{}
|
|
ff.Fill(req)
|
|
resp, err := api.Call(ctx, req)
|
|
if !errors.Is(err, ErrHTTPFailure) {
|
|
t.Fatal("not the error we expected", err)
|
|
}
|
|
if resp != nil {
|
|
t.Fatal("expected nil resp")
|
|
}
|
|
}
|
|
|
|
func TestLoginWithResponseBodyReadErr(t *testing.T) {
|
|
errMocked := errors.New("mocked error")
|
|
clnt := &FakeHTTPClient{Resp: &http.Response{
|
|
StatusCode: 200,
|
|
Body: &FakeBody{Err: errMocked},
|
|
}}
|
|
api := &simpleLoginAPI{
|
|
HTTPClient: clnt,
|
|
}
|
|
ctx := context.Background()
|
|
req := &apimodel.LoginRequest{}
|
|
ff := &fakeFill{}
|
|
ff.Fill(req)
|
|
resp, err := api.Call(ctx, req)
|
|
if !errors.Is(err, errMocked) {
|
|
t.Fatal("not the error we expected", err)
|
|
}
|
|
if resp != nil {
|
|
t.Fatal("expected nil resp")
|
|
}
|
|
}
|
|
|
|
func TestLoginWithUnmarshalFailure(t *testing.T) {
|
|
errMocked := errors.New("mocked error")
|
|
clnt := &FakeHTTPClient{Resp: &http.Response{
|
|
StatusCode: 200,
|
|
Body: &FakeBody{Data: []byte(`{}`)},
|
|
}}
|
|
api := &simpleLoginAPI{
|
|
HTTPClient: clnt,
|
|
JSONCodec: &FakeCodec{DecodeErr: errMocked},
|
|
}
|
|
ctx := context.Background()
|
|
req := &apimodel.LoginRequest{}
|
|
ff := &fakeFill{}
|
|
ff.Fill(req)
|
|
resp, err := api.Call(ctx, req)
|
|
if !errors.Is(err, errMocked) {
|
|
t.Fatal("not the error we expected", err)
|
|
}
|
|
if resp != nil {
|
|
t.Fatal("expected nil resp")
|
|
}
|
|
}
|
|
|
|
type handleLogin struct {
|
|
accept string
|
|
body []byte
|
|
contentType string
|
|
count int32
|
|
method string
|
|
mu sync.Mutex
|
|
resp *apimodel.LoginResponse
|
|
url *url.URL
|
|
userAgent string
|
|
}
|
|
|
|
func (h *handleLogin) ServeHTTP(w http.ResponseWriter, r *http.Request) {
|
|
defer h.mu.Unlock()
|
|
h.mu.Lock()
|
|
if h.count > 0 {
|
|
w.WriteHeader(400)
|
|
return
|
|
}
|
|
h.count++
|
|
if r.Body != nil {
|
|
data, err := netxlite.ReadAllContext(r.Context(), r.Body)
|
|
if err != nil {
|
|
w.WriteHeader(400)
|
|
return
|
|
}
|
|
h.body = data
|
|
}
|
|
h.method = r.Method
|
|
h.url = r.URL
|
|
h.accept = r.Header.Get("Accept")
|
|
h.contentType = r.Header.Get("Content-Type")
|
|
h.userAgent = r.Header.Get("User-Agent")
|
|
var out *apimodel.LoginResponse
|
|
ff := fakeFill{}
|
|
ff.Fill(&out)
|
|
h.resp = out
|
|
data, err := json.Marshal(out)
|
|
if err != nil {
|
|
w.WriteHeader(400)
|
|
return
|
|
}
|
|
w.Write(data)
|
|
}
|
|
|
|
func TestLoginRoundTrip(t *testing.T) {
|
|
// setup
|
|
handler := &handleLogin{}
|
|
srvr := httptest.NewServer(handler)
|
|
defer srvr.Close()
|
|
req := &apimodel.LoginRequest{}
|
|
ff := &fakeFill{}
|
|
ff.Fill(&req)
|
|
api := &simpleLoginAPI{BaseURL: srvr.URL}
|
|
ff.Fill(&api.UserAgent)
|
|
// issue request
|
|
ctx := context.Background()
|
|
resp, err := api.Call(ctx, req)
|
|
if err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
if resp == nil {
|
|
t.Fatal("expected non-nil response here")
|
|
}
|
|
// compare our response and server's one
|
|
if diff := cmp.Diff(handler.resp, resp); diff != "" {
|
|
t.Fatal(diff)
|
|
}
|
|
// check whether headers are OK
|
|
if handler.accept != "application/json" {
|
|
t.Fatal("invalid accept header")
|
|
}
|
|
if handler.userAgent != api.UserAgent {
|
|
t.Fatal("invalid user-agent header")
|
|
}
|
|
// check whether the method is OK
|
|
if handler.method != "POST" {
|
|
t.Fatal("invalid method")
|
|
}
|
|
// check the body
|
|
if handler.contentType != "application/json" {
|
|
t.Fatal("invalid content-type header")
|
|
}
|
|
got := &apimodel.LoginRequest{}
|
|
if err := json.Unmarshal(handler.body, &got); err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
if diff := cmp.Diff(req, got); diff != "" {
|
|
t.Fatal(diff)
|
|
}
|
|
}
|
|
|
|
func TestMeasurementMetaInvalidURL(t *testing.T) {
|
|
api := &simpleMeasurementMetaAPI{
|
|
BaseURL: "\t", // invalid
|
|
}
|
|
ctx := context.Background()
|
|
req := &apimodel.MeasurementMetaRequest{}
|
|
ff := &fakeFill{}
|
|
ff.Fill(req)
|
|
resp, err := api.Call(ctx, req)
|
|
if err == nil || !strings.HasSuffix(err.Error(), "invalid control character in URL") {
|
|
t.Fatal("not the error we expected", err)
|
|
}
|
|
if resp != nil {
|
|
t.Fatal("expected nil resp")
|
|
}
|
|
}
|
|
|
|
func TestMeasurementMetaWithHTTPErr(t *testing.T) {
|
|
errMocked := errors.New("mocked error")
|
|
clnt := &FakeHTTPClient{Err: errMocked}
|
|
api := &simpleMeasurementMetaAPI{
|
|
HTTPClient: clnt,
|
|
}
|
|
ctx := context.Background()
|
|
req := &apimodel.MeasurementMetaRequest{}
|
|
ff := &fakeFill{}
|
|
ff.Fill(req)
|
|
resp, err := api.Call(ctx, req)
|
|
if !errors.Is(err, errMocked) {
|
|
t.Fatal("not the error we expected", err)
|
|
}
|
|
if resp != nil {
|
|
t.Fatal("expected nil resp")
|
|
}
|
|
}
|
|
|
|
func TestMeasurementMetaWithNewRequestErr(t *testing.T) {
|
|
errMocked := errors.New("mocked error")
|
|
api := &simpleMeasurementMetaAPI{
|
|
RequestMaker: &FakeRequestMaker{Err: errMocked},
|
|
}
|
|
ctx := context.Background()
|
|
req := &apimodel.MeasurementMetaRequest{}
|
|
ff := &fakeFill{}
|
|
ff.Fill(req)
|
|
resp, err := api.Call(ctx, req)
|
|
if !errors.Is(err, errMocked) {
|
|
t.Fatal("not the error we expected", err)
|
|
}
|
|
if resp != nil {
|
|
t.Fatal("expected nil resp")
|
|
}
|
|
}
|
|
|
|
func TestMeasurementMetaWith401(t *testing.T) {
|
|
clnt := &FakeHTTPClient{Resp: &http.Response{StatusCode: 401}}
|
|
api := &simpleMeasurementMetaAPI{
|
|
HTTPClient: clnt,
|
|
}
|
|
ctx := context.Background()
|
|
req := &apimodel.MeasurementMetaRequest{}
|
|
ff := &fakeFill{}
|
|
ff.Fill(req)
|
|
resp, err := api.Call(ctx, req)
|
|
if !errors.Is(err, ErrUnauthorized) {
|
|
t.Fatal("not the error we expected", err)
|
|
}
|
|
if resp != nil {
|
|
t.Fatal("expected nil resp")
|
|
}
|
|
}
|
|
|
|
func TestMeasurementMetaWith400(t *testing.T) {
|
|
clnt := &FakeHTTPClient{Resp: &http.Response{StatusCode: 400}}
|
|
api := &simpleMeasurementMetaAPI{
|
|
HTTPClient: clnt,
|
|
}
|
|
ctx := context.Background()
|
|
req := &apimodel.MeasurementMetaRequest{}
|
|
ff := &fakeFill{}
|
|
ff.Fill(req)
|
|
resp, err := api.Call(ctx, req)
|
|
if !errors.Is(err, ErrHTTPFailure) {
|
|
t.Fatal("not the error we expected", err)
|
|
}
|
|
if resp != nil {
|
|
t.Fatal("expected nil resp")
|
|
}
|
|
}
|
|
|
|
func TestMeasurementMetaWithResponseBodyReadErr(t *testing.T) {
|
|
errMocked := errors.New("mocked error")
|
|
clnt := &FakeHTTPClient{Resp: &http.Response{
|
|
StatusCode: 200,
|
|
Body: &FakeBody{Err: errMocked},
|
|
}}
|
|
api := &simpleMeasurementMetaAPI{
|
|
HTTPClient: clnt,
|
|
}
|
|
ctx := context.Background()
|
|
req := &apimodel.MeasurementMetaRequest{}
|
|
ff := &fakeFill{}
|
|
ff.Fill(req)
|
|
resp, err := api.Call(ctx, req)
|
|
if !errors.Is(err, errMocked) {
|
|
t.Fatal("not the error we expected", err)
|
|
}
|
|
if resp != nil {
|
|
t.Fatal("expected nil resp")
|
|
}
|
|
}
|
|
|
|
func TestMeasurementMetaWithUnmarshalFailure(t *testing.T) {
|
|
errMocked := errors.New("mocked error")
|
|
clnt := &FakeHTTPClient{Resp: &http.Response{
|
|
StatusCode: 200,
|
|
Body: &FakeBody{Data: []byte(`{}`)},
|
|
}}
|
|
api := &simpleMeasurementMetaAPI{
|
|
HTTPClient: clnt,
|
|
JSONCodec: &FakeCodec{DecodeErr: errMocked},
|
|
}
|
|
ctx := context.Background()
|
|
req := &apimodel.MeasurementMetaRequest{}
|
|
ff := &fakeFill{}
|
|
ff.Fill(req)
|
|
resp, err := api.Call(ctx, req)
|
|
if !errors.Is(err, errMocked) {
|
|
t.Fatal("not the error we expected", err)
|
|
}
|
|
if resp != nil {
|
|
t.Fatal("expected nil resp")
|
|
}
|
|
}
|
|
|
|
type handleMeasurementMeta struct {
|
|
accept string
|
|
body []byte
|
|
contentType string
|
|
count int32
|
|
method string
|
|
mu sync.Mutex
|
|
resp *apimodel.MeasurementMetaResponse
|
|
url *url.URL
|
|
userAgent string
|
|
}
|
|
|
|
func (h *handleMeasurementMeta) ServeHTTP(w http.ResponseWriter, r *http.Request) {
|
|
defer h.mu.Unlock()
|
|
h.mu.Lock()
|
|
if h.count > 0 {
|
|
w.WriteHeader(400)
|
|
return
|
|
}
|
|
h.count++
|
|
if r.Body != nil {
|
|
data, err := netxlite.ReadAllContext(r.Context(), r.Body)
|
|
if err != nil {
|
|
w.WriteHeader(400)
|
|
return
|
|
}
|
|
h.body = data
|
|
}
|
|
h.method = r.Method
|
|
h.url = r.URL
|
|
h.accept = r.Header.Get("Accept")
|
|
h.contentType = r.Header.Get("Content-Type")
|
|
h.userAgent = r.Header.Get("User-Agent")
|
|
var out *apimodel.MeasurementMetaResponse
|
|
ff := fakeFill{}
|
|
ff.Fill(&out)
|
|
h.resp = out
|
|
data, err := json.Marshal(out)
|
|
if err != nil {
|
|
w.WriteHeader(400)
|
|
return
|
|
}
|
|
w.Write(data)
|
|
}
|
|
|
|
func TestMeasurementMetaRoundTrip(t *testing.T) {
|
|
// setup
|
|
handler := &handleMeasurementMeta{}
|
|
srvr := httptest.NewServer(handler)
|
|
defer srvr.Close()
|
|
req := &apimodel.MeasurementMetaRequest{}
|
|
ff := &fakeFill{}
|
|
ff.Fill(&req)
|
|
api := &simpleMeasurementMetaAPI{BaseURL: srvr.URL}
|
|
ff.Fill(&api.UserAgent)
|
|
// issue request
|
|
ctx := context.Background()
|
|
resp, err := api.Call(ctx, req)
|
|
if err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
if resp == nil {
|
|
t.Fatal("expected non-nil response here")
|
|
}
|
|
// compare our response and server's one
|
|
if diff := cmp.Diff(handler.resp, resp); diff != "" {
|
|
t.Fatal(diff)
|
|
}
|
|
// check whether headers are OK
|
|
if handler.accept != "application/json" {
|
|
t.Fatal("invalid accept header")
|
|
}
|
|
if handler.userAgent != api.UserAgent {
|
|
t.Fatal("invalid user-agent header")
|
|
}
|
|
// check whether the method is OK
|
|
if handler.method != "GET" {
|
|
t.Fatal("invalid method")
|
|
}
|
|
// check the query
|
|
httpReq, err := api.newRequest(context.Background(), req)
|
|
if err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
if diff := cmp.Diff(handler.url.Path, httpReq.URL.Path); diff != "" {
|
|
t.Fatal(diff)
|
|
}
|
|
if diff := cmp.Diff(handler.url.RawQuery, httpReq.URL.RawQuery); diff != "" {
|
|
t.Fatal(diff)
|
|
}
|
|
}
|
|
|
|
func TestMeasurementMetaMandatoryFields(t *testing.T) {
|
|
clnt := &FakeHTTPClient{Resp: &http.Response{
|
|
StatusCode: 500,
|
|
}}
|
|
api := &simpleMeasurementMetaAPI{
|
|
HTTPClient: clnt,
|
|
}
|
|
ctx := context.Background()
|
|
req := &apimodel.MeasurementMetaRequest{} // deliberately empty
|
|
resp, err := api.Call(ctx, req)
|
|
if !errors.Is(err, ErrEmptyField) {
|
|
t.Fatal("not the error we expected", err)
|
|
}
|
|
if resp != nil {
|
|
t.Fatal("expected nil resp")
|
|
}
|
|
}
|
|
|
|
func TestRegisterInvalidURL(t *testing.T) {
|
|
api := &simpleRegisterAPI{
|
|
BaseURL: "\t", // invalid
|
|
}
|
|
ctx := context.Background()
|
|
req := &apimodel.RegisterRequest{}
|
|
ff := &fakeFill{}
|
|
ff.Fill(req)
|
|
resp, err := api.Call(ctx, req)
|
|
if err == nil || !strings.HasSuffix(err.Error(), "invalid control character in URL") {
|
|
t.Fatal("not the error we expected", err)
|
|
}
|
|
if resp != nil {
|
|
t.Fatal("expected nil resp")
|
|
}
|
|
}
|
|
|
|
func TestRegisterWithHTTPErr(t *testing.T) {
|
|
errMocked := errors.New("mocked error")
|
|
clnt := &FakeHTTPClient{Err: errMocked}
|
|
api := &simpleRegisterAPI{
|
|
HTTPClient: clnt,
|
|
}
|
|
ctx := context.Background()
|
|
req := &apimodel.RegisterRequest{}
|
|
ff := &fakeFill{}
|
|
ff.Fill(req)
|
|
resp, err := api.Call(ctx, req)
|
|
if !errors.Is(err, errMocked) {
|
|
t.Fatal("not the error we expected", err)
|
|
}
|
|
if resp != nil {
|
|
t.Fatal("expected nil resp")
|
|
}
|
|
}
|
|
|
|
func TestRegisterMarshalErr(t *testing.T) {
|
|
errMocked := errors.New("mocked error")
|
|
api := &simpleRegisterAPI{
|
|
JSONCodec: &FakeCodec{EncodeErr: errMocked},
|
|
}
|
|
ctx := context.Background()
|
|
req := &apimodel.RegisterRequest{}
|
|
ff := &fakeFill{}
|
|
ff.Fill(req)
|
|
resp, err := api.Call(ctx, req)
|
|
if !errors.Is(err, errMocked) {
|
|
t.Fatal("not the error we expected", err)
|
|
}
|
|
if resp != nil {
|
|
t.Fatal("expected nil resp")
|
|
}
|
|
}
|
|
|
|
func TestRegisterWithNewRequestErr(t *testing.T) {
|
|
errMocked := errors.New("mocked error")
|
|
api := &simpleRegisterAPI{
|
|
RequestMaker: &FakeRequestMaker{Err: errMocked},
|
|
}
|
|
ctx := context.Background()
|
|
req := &apimodel.RegisterRequest{}
|
|
ff := &fakeFill{}
|
|
ff.Fill(req)
|
|
resp, err := api.Call(ctx, req)
|
|
if !errors.Is(err, errMocked) {
|
|
t.Fatal("not the error we expected", err)
|
|
}
|
|
if resp != nil {
|
|
t.Fatal("expected nil resp")
|
|
}
|
|
}
|
|
|
|
func TestRegisterWith401(t *testing.T) {
|
|
clnt := &FakeHTTPClient{Resp: &http.Response{StatusCode: 401}}
|
|
api := &simpleRegisterAPI{
|
|
HTTPClient: clnt,
|
|
}
|
|
ctx := context.Background()
|
|
req := &apimodel.RegisterRequest{}
|
|
ff := &fakeFill{}
|
|
ff.Fill(req)
|
|
resp, err := api.Call(ctx, req)
|
|
if !errors.Is(err, ErrUnauthorized) {
|
|
t.Fatal("not the error we expected", err)
|
|
}
|
|
if resp != nil {
|
|
t.Fatal("expected nil resp")
|
|
}
|
|
}
|
|
|
|
func TestRegisterWith400(t *testing.T) {
|
|
clnt := &FakeHTTPClient{Resp: &http.Response{StatusCode: 400}}
|
|
api := &simpleRegisterAPI{
|
|
HTTPClient: clnt,
|
|
}
|
|
ctx := context.Background()
|
|
req := &apimodel.RegisterRequest{}
|
|
ff := &fakeFill{}
|
|
ff.Fill(req)
|
|
resp, err := api.Call(ctx, req)
|
|
if !errors.Is(err, ErrHTTPFailure) {
|
|
t.Fatal("not the error we expected", err)
|
|
}
|
|
if resp != nil {
|
|
t.Fatal("expected nil resp")
|
|
}
|
|
}
|
|
|
|
func TestRegisterWithResponseBodyReadErr(t *testing.T) {
|
|
errMocked := errors.New("mocked error")
|
|
clnt := &FakeHTTPClient{Resp: &http.Response{
|
|
StatusCode: 200,
|
|
Body: &FakeBody{Err: errMocked},
|
|
}}
|
|
api := &simpleRegisterAPI{
|
|
HTTPClient: clnt,
|
|
}
|
|
ctx := context.Background()
|
|
req := &apimodel.RegisterRequest{}
|
|
ff := &fakeFill{}
|
|
ff.Fill(req)
|
|
resp, err := api.Call(ctx, req)
|
|
if !errors.Is(err, errMocked) {
|
|
t.Fatal("not the error we expected", err)
|
|
}
|
|
if resp != nil {
|
|
t.Fatal("expected nil resp")
|
|
}
|
|
}
|
|
|
|
func TestRegisterWithUnmarshalFailure(t *testing.T) {
|
|
errMocked := errors.New("mocked error")
|
|
clnt := &FakeHTTPClient{Resp: &http.Response{
|
|
StatusCode: 200,
|
|
Body: &FakeBody{Data: []byte(`{}`)},
|
|
}}
|
|
api := &simpleRegisterAPI{
|
|
HTTPClient: clnt,
|
|
JSONCodec: &FakeCodec{DecodeErr: errMocked},
|
|
}
|
|
ctx := context.Background()
|
|
req := &apimodel.RegisterRequest{}
|
|
ff := &fakeFill{}
|
|
ff.Fill(req)
|
|
resp, err := api.Call(ctx, req)
|
|
if !errors.Is(err, errMocked) {
|
|
t.Fatal("not the error we expected", err)
|
|
}
|
|
if resp != nil {
|
|
t.Fatal("expected nil resp")
|
|
}
|
|
}
|
|
|
|
type handleRegister struct {
|
|
accept string
|
|
body []byte
|
|
contentType string
|
|
count int32
|
|
method string
|
|
mu sync.Mutex
|
|
resp *apimodel.RegisterResponse
|
|
url *url.URL
|
|
userAgent string
|
|
}
|
|
|
|
func (h *handleRegister) ServeHTTP(w http.ResponseWriter, r *http.Request) {
|
|
defer h.mu.Unlock()
|
|
h.mu.Lock()
|
|
if h.count > 0 {
|
|
w.WriteHeader(400)
|
|
return
|
|
}
|
|
h.count++
|
|
if r.Body != nil {
|
|
data, err := netxlite.ReadAllContext(r.Context(), r.Body)
|
|
if err != nil {
|
|
w.WriteHeader(400)
|
|
return
|
|
}
|
|
h.body = data
|
|
}
|
|
h.method = r.Method
|
|
h.url = r.URL
|
|
h.accept = r.Header.Get("Accept")
|
|
h.contentType = r.Header.Get("Content-Type")
|
|
h.userAgent = r.Header.Get("User-Agent")
|
|
var out *apimodel.RegisterResponse
|
|
ff := fakeFill{}
|
|
ff.Fill(&out)
|
|
h.resp = out
|
|
data, err := json.Marshal(out)
|
|
if err != nil {
|
|
w.WriteHeader(400)
|
|
return
|
|
}
|
|
w.Write(data)
|
|
}
|
|
|
|
func TestRegisterRoundTrip(t *testing.T) {
|
|
// setup
|
|
handler := &handleRegister{}
|
|
srvr := httptest.NewServer(handler)
|
|
defer srvr.Close()
|
|
req := &apimodel.RegisterRequest{}
|
|
ff := &fakeFill{}
|
|
ff.Fill(&req)
|
|
api := &simpleRegisterAPI{BaseURL: srvr.URL}
|
|
ff.Fill(&api.UserAgent)
|
|
// issue request
|
|
ctx := context.Background()
|
|
resp, err := api.Call(ctx, req)
|
|
if err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
if resp == nil {
|
|
t.Fatal("expected non-nil response here")
|
|
}
|
|
// compare our response and server's one
|
|
if diff := cmp.Diff(handler.resp, resp); diff != "" {
|
|
t.Fatal(diff)
|
|
}
|
|
// check whether headers are OK
|
|
if handler.accept != "application/json" {
|
|
t.Fatal("invalid accept header")
|
|
}
|
|
if handler.userAgent != api.UserAgent {
|
|
t.Fatal("invalid user-agent header")
|
|
}
|
|
// check whether the method is OK
|
|
if handler.method != "POST" {
|
|
t.Fatal("invalid method")
|
|
}
|
|
// check the body
|
|
if handler.contentType != "application/json" {
|
|
t.Fatal("invalid content-type header")
|
|
}
|
|
got := &apimodel.RegisterRequest{}
|
|
if err := json.Unmarshal(handler.body, &got); err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
if diff := cmp.Diff(req, got); diff != "" {
|
|
t.Fatal(diff)
|
|
}
|
|
}
|
|
|
|
func TestTestHelpersInvalidURL(t *testing.T) {
|
|
api := &simpleTestHelpersAPI{
|
|
BaseURL: "\t", // invalid
|
|
}
|
|
ctx := context.Background()
|
|
req := &apimodel.TestHelpersRequest{}
|
|
ff := &fakeFill{}
|
|
ff.Fill(req)
|
|
resp, err := api.Call(ctx, req)
|
|
if err == nil || !strings.HasSuffix(err.Error(), "invalid control character in URL") {
|
|
t.Fatal("not the error we expected", err)
|
|
}
|
|
if resp != nil {
|
|
t.Fatal("expected nil resp")
|
|
}
|
|
}
|
|
|
|
func TestTestHelpersWithHTTPErr(t *testing.T) {
|
|
errMocked := errors.New("mocked error")
|
|
clnt := &FakeHTTPClient{Err: errMocked}
|
|
api := &simpleTestHelpersAPI{
|
|
HTTPClient: clnt,
|
|
}
|
|
ctx := context.Background()
|
|
req := &apimodel.TestHelpersRequest{}
|
|
ff := &fakeFill{}
|
|
ff.Fill(req)
|
|
resp, err := api.Call(ctx, req)
|
|
if !errors.Is(err, errMocked) {
|
|
t.Fatal("not the error we expected", err)
|
|
}
|
|
if resp != nil {
|
|
t.Fatal("expected nil resp")
|
|
}
|
|
}
|
|
|
|
func TestTestHelpersWithNewRequestErr(t *testing.T) {
|
|
errMocked := errors.New("mocked error")
|
|
api := &simpleTestHelpersAPI{
|
|
RequestMaker: &FakeRequestMaker{Err: errMocked},
|
|
}
|
|
ctx := context.Background()
|
|
req := &apimodel.TestHelpersRequest{}
|
|
ff := &fakeFill{}
|
|
ff.Fill(req)
|
|
resp, err := api.Call(ctx, req)
|
|
if !errors.Is(err, errMocked) {
|
|
t.Fatal("not the error we expected", err)
|
|
}
|
|
if resp != nil {
|
|
t.Fatal("expected nil resp")
|
|
}
|
|
}
|
|
|
|
func TestTestHelpersWith401(t *testing.T) {
|
|
clnt := &FakeHTTPClient{Resp: &http.Response{StatusCode: 401}}
|
|
api := &simpleTestHelpersAPI{
|
|
HTTPClient: clnt,
|
|
}
|
|
ctx := context.Background()
|
|
req := &apimodel.TestHelpersRequest{}
|
|
ff := &fakeFill{}
|
|
ff.Fill(req)
|
|
resp, err := api.Call(ctx, req)
|
|
if !errors.Is(err, ErrUnauthorized) {
|
|
t.Fatal("not the error we expected", err)
|
|
}
|
|
if resp != nil {
|
|
t.Fatal("expected nil resp")
|
|
}
|
|
}
|
|
|
|
func TestTestHelpersWith400(t *testing.T) {
|
|
clnt := &FakeHTTPClient{Resp: &http.Response{StatusCode: 400}}
|
|
api := &simpleTestHelpersAPI{
|
|
HTTPClient: clnt,
|
|
}
|
|
ctx := context.Background()
|
|
req := &apimodel.TestHelpersRequest{}
|
|
ff := &fakeFill{}
|
|
ff.Fill(req)
|
|
resp, err := api.Call(ctx, req)
|
|
if !errors.Is(err, ErrHTTPFailure) {
|
|
t.Fatal("not the error we expected", err)
|
|
}
|
|
if resp != nil {
|
|
t.Fatal("expected nil resp")
|
|
}
|
|
}
|
|
|
|
func TestTestHelpersWithResponseBodyReadErr(t *testing.T) {
|
|
errMocked := errors.New("mocked error")
|
|
clnt := &FakeHTTPClient{Resp: &http.Response{
|
|
StatusCode: 200,
|
|
Body: &FakeBody{Err: errMocked},
|
|
}}
|
|
api := &simpleTestHelpersAPI{
|
|
HTTPClient: clnt,
|
|
}
|
|
ctx := context.Background()
|
|
req := &apimodel.TestHelpersRequest{}
|
|
ff := &fakeFill{}
|
|
ff.Fill(req)
|
|
resp, err := api.Call(ctx, req)
|
|
if !errors.Is(err, errMocked) {
|
|
t.Fatal("not the error we expected", err)
|
|
}
|
|
if resp != nil {
|
|
t.Fatal("expected nil resp")
|
|
}
|
|
}
|
|
|
|
func TestTestHelpersWithUnmarshalFailure(t *testing.T) {
|
|
errMocked := errors.New("mocked error")
|
|
clnt := &FakeHTTPClient{Resp: &http.Response{
|
|
StatusCode: 200,
|
|
Body: &FakeBody{Data: []byte(`{}`)},
|
|
}}
|
|
api := &simpleTestHelpersAPI{
|
|
HTTPClient: clnt,
|
|
JSONCodec: &FakeCodec{DecodeErr: errMocked},
|
|
}
|
|
ctx := context.Background()
|
|
req := &apimodel.TestHelpersRequest{}
|
|
ff := &fakeFill{}
|
|
ff.Fill(req)
|
|
resp, err := api.Call(ctx, req)
|
|
if !errors.Is(err, errMocked) {
|
|
t.Fatal("not the error we expected", err)
|
|
}
|
|
if resp != nil {
|
|
t.Fatal("expected nil resp")
|
|
}
|
|
}
|
|
|
|
type handleTestHelpers struct {
|
|
accept string
|
|
body []byte
|
|
contentType string
|
|
count int32
|
|
method string
|
|
mu sync.Mutex
|
|
resp apimodel.TestHelpersResponse
|
|
url *url.URL
|
|
userAgent string
|
|
}
|
|
|
|
func (h *handleTestHelpers) ServeHTTP(w http.ResponseWriter, r *http.Request) {
|
|
defer h.mu.Unlock()
|
|
h.mu.Lock()
|
|
if h.count > 0 {
|
|
w.WriteHeader(400)
|
|
return
|
|
}
|
|
h.count++
|
|
if r.Body != nil {
|
|
data, err := netxlite.ReadAllContext(r.Context(), r.Body)
|
|
if err != nil {
|
|
w.WriteHeader(400)
|
|
return
|
|
}
|
|
h.body = data
|
|
}
|
|
h.method = r.Method
|
|
h.url = r.URL
|
|
h.accept = r.Header.Get("Accept")
|
|
h.contentType = r.Header.Get("Content-Type")
|
|
h.userAgent = r.Header.Get("User-Agent")
|
|
var out apimodel.TestHelpersResponse
|
|
ff := fakeFill{}
|
|
ff.Fill(&out)
|
|
h.resp = out
|
|
data, err := json.Marshal(out)
|
|
if err != nil {
|
|
w.WriteHeader(400)
|
|
return
|
|
}
|
|
w.Write(data)
|
|
}
|
|
|
|
func TestTestHelpersRoundTrip(t *testing.T) {
|
|
// setup
|
|
handler := &handleTestHelpers{}
|
|
srvr := httptest.NewServer(handler)
|
|
defer srvr.Close()
|
|
req := &apimodel.TestHelpersRequest{}
|
|
ff := &fakeFill{}
|
|
ff.Fill(&req)
|
|
api := &simpleTestHelpersAPI{BaseURL: srvr.URL}
|
|
ff.Fill(&api.UserAgent)
|
|
// issue request
|
|
ctx := context.Background()
|
|
resp, err := api.Call(ctx, req)
|
|
if err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
if resp == nil {
|
|
t.Fatal("expected non-nil response here")
|
|
}
|
|
// compare our response and server's one
|
|
if diff := cmp.Diff(handler.resp, resp); diff != "" {
|
|
t.Fatal(diff)
|
|
}
|
|
// check whether headers are OK
|
|
if handler.accept != "application/json" {
|
|
t.Fatal("invalid accept header")
|
|
}
|
|
if handler.userAgent != api.UserAgent {
|
|
t.Fatal("invalid user-agent header")
|
|
}
|
|
// check whether the method is OK
|
|
if handler.method != "GET" {
|
|
t.Fatal("invalid method")
|
|
}
|
|
// check the query
|
|
httpReq, err := api.newRequest(context.Background(), req)
|
|
if err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
if diff := cmp.Diff(handler.url.Path, httpReq.URL.Path); diff != "" {
|
|
t.Fatal(diff)
|
|
}
|
|
if diff := cmp.Diff(handler.url.RawQuery, httpReq.URL.RawQuery); diff != "" {
|
|
t.Fatal(diff)
|
|
}
|
|
}
|
|
|
|
func TestTestHelpersResponseLiteralNull(t *testing.T) {
|
|
clnt := &FakeHTTPClient{Resp: &http.Response{
|
|
StatusCode: 200,
|
|
Body: &FakeBody{Data: []byte(`null`)},
|
|
}}
|
|
api := &simpleTestHelpersAPI{
|
|
HTTPClient: clnt,
|
|
}
|
|
ctx := context.Background()
|
|
req := &apimodel.TestHelpersRequest{}
|
|
ff := &fakeFill{}
|
|
ff.Fill(req)
|
|
resp, err := api.Call(ctx, req)
|
|
if !errors.Is(err, ErrJSONLiteralNull) {
|
|
t.Fatal("not the error we expected", err)
|
|
}
|
|
if resp != nil {
|
|
t.Fatal("expected nil resp")
|
|
}
|
|
}
|
|
|
|
func TestPsiphonConfigInvalidURL(t *testing.T) {
|
|
api := &simplePsiphonConfigAPI{
|
|
BaseURL: "\t", // invalid
|
|
}
|
|
ctx := context.Background()
|
|
req := &apimodel.PsiphonConfigRequest{}
|
|
ff := &fakeFill{}
|
|
ff.Fill(req)
|
|
resp, err := api.Call(ctx, req)
|
|
if err == nil || !strings.HasSuffix(err.Error(), "invalid control character in URL") {
|
|
t.Fatal("not the error we expected", err)
|
|
}
|
|
if resp != nil {
|
|
t.Fatal("expected nil resp")
|
|
}
|
|
}
|
|
|
|
func TestPsiphonConfigWithMissingToken(t *testing.T) {
|
|
api := &simplePsiphonConfigAPI{} // no token
|
|
ctx := context.Background()
|
|
req := &apimodel.PsiphonConfigRequest{}
|
|
ff := &fakeFill{}
|
|
ff.Fill(req)
|
|
resp, err := api.Call(ctx, req)
|
|
if !errors.Is(err, ErrMissingToken) {
|
|
t.Fatal("not the error we expected", err)
|
|
}
|
|
if resp != nil {
|
|
t.Fatal("expected nil resp")
|
|
}
|
|
}
|
|
|
|
func TestPsiphonConfigWithHTTPErr(t *testing.T) {
|
|
errMocked := errors.New("mocked error")
|
|
clnt := &FakeHTTPClient{Err: errMocked}
|
|
api := &simplePsiphonConfigAPI{
|
|
HTTPClient: clnt,
|
|
Token: "fakeToken",
|
|
}
|
|
ctx := context.Background()
|
|
req := &apimodel.PsiphonConfigRequest{}
|
|
ff := &fakeFill{}
|
|
ff.Fill(req)
|
|
resp, err := api.Call(ctx, req)
|
|
if !errors.Is(err, errMocked) {
|
|
t.Fatal("not the error we expected", err)
|
|
}
|
|
if resp != nil {
|
|
t.Fatal("expected nil resp")
|
|
}
|
|
}
|
|
|
|
func TestPsiphonConfigWithNewRequestErr(t *testing.T) {
|
|
errMocked := errors.New("mocked error")
|
|
api := &simplePsiphonConfigAPI{
|
|
RequestMaker: &FakeRequestMaker{Err: errMocked},
|
|
Token: "fakeToken",
|
|
}
|
|
ctx := context.Background()
|
|
req := &apimodel.PsiphonConfigRequest{}
|
|
ff := &fakeFill{}
|
|
ff.Fill(req)
|
|
resp, err := api.Call(ctx, req)
|
|
if !errors.Is(err, errMocked) {
|
|
t.Fatal("not the error we expected", err)
|
|
}
|
|
if resp != nil {
|
|
t.Fatal("expected nil resp")
|
|
}
|
|
}
|
|
|
|
func TestPsiphonConfigWith401(t *testing.T) {
|
|
clnt := &FakeHTTPClient{Resp: &http.Response{StatusCode: 401}}
|
|
api := &simplePsiphonConfigAPI{
|
|
HTTPClient: clnt,
|
|
Token: "fakeToken",
|
|
}
|
|
ctx := context.Background()
|
|
req := &apimodel.PsiphonConfigRequest{}
|
|
ff := &fakeFill{}
|
|
ff.Fill(req)
|
|
resp, err := api.Call(ctx, req)
|
|
if !errors.Is(err, ErrUnauthorized) {
|
|
t.Fatal("not the error we expected", err)
|
|
}
|
|
if resp != nil {
|
|
t.Fatal("expected nil resp")
|
|
}
|
|
}
|
|
|
|
func TestPsiphonConfigWith400(t *testing.T) {
|
|
clnt := &FakeHTTPClient{Resp: &http.Response{StatusCode: 400}}
|
|
api := &simplePsiphonConfigAPI{
|
|
HTTPClient: clnt,
|
|
Token: "fakeToken",
|
|
}
|
|
ctx := context.Background()
|
|
req := &apimodel.PsiphonConfigRequest{}
|
|
ff := &fakeFill{}
|
|
ff.Fill(req)
|
|
resp, err := api.Call(ctx, req)
|
|
if !errors.Is(err, ErrHTTPFailure) {
|
|
t.Fatal("not the error we expected", err)
|
|
}
|
|
if resp != nil {
|
|
t.Fatal("expected nil resp")
|
|
}
|
|
}
|
|
|
|
func TestPsiphonConfigWithResponseBodyReadErr(t *testing.T) {
|
|
errMocked := errors.New("mocked error")
|
|
clnt := &FakeHTTPClient{Resp: &http.Response{
|
|
StatusCode: 200,
|
|
Body: &FakeBody{Err: errMocked},
|
|
}}
|
|
api := &simplePsiphonConfigAPI{
|
|
HTTPClient: clnt,
|
|
Token: "fakeToken",
|
|
}
|
|
ctx := context.Background()
|
|
req := &apimodel.PsiphonConfigRequest{}
|
|
ff := &fakeFill{}
|
|
ff.Fill(req)
|
|
resp, err := api.Call(ctx, req)
|
|
if !errors.Is(err, errMocked) {
|
|
t.Fatal("not the error we expected", err)
|
|
}
|
|
if resp != nil {
|
|
t.Fatal("expected nil resp")
|
|
}
|
|
}
|
|
|
|
func TestPsiphonConfigWithUnmarshalFailure(t *testing.T) {
|
|
errMocked := errors.New("mocked error")
|
|
clnt := &FakeHTTPClient{Resp: &http.Response{
|
|
StatusCode: 200,
|
|
Body: &FakeBody{Data: []byte(`{}`)},
|
|
}}
|
|
api := &simplePsiphonConfigAPI{
|
|
HTTPClient: clnt,
|
|
JSONCodec: &FakeCodec{DecodeErr: errMocked},
|
|
Token: "fakeToken",
|
|
}
|
|
ctx := context.Background()
|
|
req := &apimodel.PsiphonConfigRequest{}
|
|
ff := &fakeFill{}
|
|
ff.Fill(req)
|
|
resp, err := api.Call(ctx, req)
|
|
if !errors.Is(err, errMocked) {
|
|
t.Fatal("not the error we expected", err)
|
|
}
|
|
if resp != nil {
|
|
t.Fatal("expected nil resp")
|
|
}
|
|
}
|
|
|
|
type handlePsiphonConfig struct {
|
|
accept string
|
|
body []byte
|
|
contentType string
|
|
count int32
|
|
method string
|
|
mu sync.Mutex
|
|
resp apimodel.PsiphonConfigResponse
|
|
url *url.URL
|
|
userAgent string
|
|
}
|
|
|
|
func (h *handlePsiphonConfig) ServeHTTP(w http.ResponseWriter, r *http.Request) {
|
|
defer h.mu.Unlock()
|
|
h.mu.Lock()
|
|
if h.count > 0 {
|
|
w.WriteHeader(400)
|
|
return
|
|
}
|
|
h.count++
|
|
if r.Body != nil {
|
|
data, err := netxlite.ReadAllContext(r.Context(), r.Body)
|
|
if err != nil {
|
|
w.WriteHeader(400)
|
|
return
|
|
}
|
|
h.body = data
|
|
}
|
|
h.method = r.Method
|
|
h.url = r.URL
|
|
h.accept = r.Header.Get("Accept")
|
|
h.contentType = r.Header.Get("Content-Type")
|
|
h.userAgent = r.Header.Get("User-Agent")
|
|
var out apimodel.PsiphonConfigResponse
|
|
ff := fakeFill{}
|
|
ff.Fill(&out)
|
|
h.resp = out
|
|
data, err := json.Marshal(out)
|
|
if err != nil {
|
|
w.WriteHeader(400)
|
|
return
|
|
}
|
|
w.Write(data)
|
|
}
|
|
|
|
func TestPsiphonConfigRoundTrip(t *testing.T) {
|
|
// setup
|
|
handler := &handlePsiphonConfig{}
|
|
srvr := httptest.NewServer(handler)
|
|
defer srvr.Close()
|
|
req := &apimodel.PsiphonConfigRequest{}
|
|
ff := &fakeFill{}
|
|
ff.Fill(&req)
|
|
api := &simplePsiphonConfigAPI{BaseURL: srvr.URL}
|
|
ff.Fill(&api.UserAgent)
|
|
ff.Fill(&api.Token)
|
|
// issue request
|
|
ctx := context.Background()
|
|
resp, err := api.Call(ctx, req)
|
|
if err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
if resp == nil {
|
|
t.Fatal("expected non-nil response here")
|
|
}
|
|
// compare our response and server's one
|
|
if diff := cmp.Diff(handler.resp, resp); diff != "" {
|
|
t.Fatal(diff)
|
|
}
|
|
// check whether headers are OK
|
|
if handler.accept != "application/json" {
|
|
t.Fatal("invalid accept header")
|
|
}
|
|
if handler.userAgent != api.UserAgent {
|
|
t.Fatal("invalid user-agent header")
|
|
}
|
|
// check whether the method is OK
|
|
if handler.method != "GET" {
|
|
t.Fatal("invalid method")
|
|
}
|
|
// check the query
|
|
httpReq, err := api.newRequest(context.Background(), req)
|
|
if err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
if diff := cmp.Diff(handler.url.Path, httpReq.URL.Path); diff != "" {
|
|
t.Fatal(diff)
|
|
}
|
|
if diff := cmp.Diff(handler.url.RawQuery, httpReq.URL.RawQuery); diff != "" {
|
|
t.Fatal(diff)
|
|
}
|
|
}
|
|
|
|
func TestPsiphonConfigResponseLiteralNull(t *testing.T) {
|
|
clnt := &FakeHTTPClient{Resp: &http.Response{
|
|
StatusCode: 200,
|
|
Body: &FakeBody{Data: []byte(`null`)},
|
|
}}
|
|
api := &simplePsiphonConfigAPI{
|
|
HTTPClient: clnt,
|
|
Token: "fakeToken",
|
|
}
|
|
ctx := context.Background()
|
|
req := &apimodel.PsiphonConfigRequest{}
|
|
ff := &fakeFill{}
|
|
ff.Fill(req)
|
|
resp, err := api.Call(ctx, req)
|
|
if !errors.Is(err, ErrJSONLiteralNull) {
|
|
t.Fatal("not the error we expected", err)
|
|
}
|
|
if resp != nil {
|
|
t.Fatal("expected nil resp")
|
|
}
|
|
}
|
|
|
|
func TestTorTargetsInvalidURL(t *testing.T) {
|
|
api := &simpleTorTargetsAPI{
|
|
BaseURL: "\t", // invalid
|
|
}
|
|
ctx := context.Background()
|
|
req := &apimodel.TorTargetsRequest{}
|
|
ff := &fakeFill{}
|
|
ff.Fill(req)
|
|
resp, err := api.Call(ctx, req)
|
|
if err == nil || !strings.HasSuffix(err.Error(), "invalid control character in URL") {
|
|
t.Fatal("not the error we expected", err)
|
|
}
|
|
if resp != nil {
|
|
t.Fatal("expected nil resp")
|
|
}
|
|
}
|
|
|
|
func TestTorTargetsWithMissingToken(t *testing.T) {
|
|
api := &simpleTorTargetsAPI{} // no token
|
|
ctx := context.Background()
|
|
req := &apimodel.TorTargetsRequest{}
|
|
ff := &fakeFill{}
|
|
ff.Fill(req)
|
|
resp, err := api.Call(ctx, req)
|
|
if !errors.Is(err, ErrMissingToken) {
|
|
t.Fatal("not the error we expected", err)
|
|
}
|
|
if resp != nil {
|
|
t.Fatal("expected nil resp")
|
|
}
|
|
}
|
|
|
|
func TestTorTargetsWithHTTPErr(t *testing.T) {
|
|
errMocked := errors.New("mocked error")
|
|
clnt := &FakeHTTPClient{Err: errMocked}
|
|
api := &simpleTorTargetsAPI{
|
|
HTTPClient: clnt,
|
|
Token: "fakeToken",
|
|
}
|
|
ctx := context.Background()
|
|
req := &apimodel.TorTargetsRequest{}
|
|
ff := &fakeFill{}
|
|
ff.Fill(req)
|
|
resp, err := api.Call(ctx, req)
|
|
if !errors.Is(err, errMocked) {
|
|
t.Fatal("not the error we expected", err)
|
|
}
|
|
if resp != nil {
|
|
t.Fatal("expected nil resp")
|
|
}
|
|
}
|
|
|
|
func TestTorTargetsWithNewRequestErr(t *testing.T) {
|
|
errMocked := errors.New("mocked error")
|
|
api := &simpleTorTargetsAPI{
|
|
RequestMaker: &FakeRequestMaker{Err: errMocked},
|
|
Token: "fakeToken",
|
|
}
|
|
ctx := context.Background()
|
|
req := &apimodel.TorTargetsRequest{}
|
|
ff := &fakeFill{}
|
|
ff.Fill(req)
|
|
resp, err := api.Call(ctx, req)
|
|
if !errors.Is(err, errMocked) {
|
|
t.Fatal("not the error we expected", err)
|
|
}
|
|
if resp != nil {
|
|
t.Fatal("expected nil resp")
|
|
}
|
|
}
|
|
|
|
func TestTorTargetsWith401(t *testing.T) {
|
|
clnt := &FakeHTTPClient{Resp: &http.Response{StatusCode: 401}}
|
|
api := &simpleTorTargetsAPI{
|
|
HTTPClient: clnt,
|
|
Token: "fakeToken",
|
|
}
|
|
ctx := context.Background()
|
|
req := &apimodel.TorTargetsRequest{}
|
|
ff := &fakeFill{}
|
|
ff.Fill(req)
|
|
resp, err := api.Call(ctx, req)
|
|
if !errors.Is(err, ErrUnauthorized) {
|
|
t.Fatal("not the error we expected", err)
|
|
}
|
|
if resp != nil {
|
|
t.Fatal("expected nil resp")
|
|
}
|
|
}
|
|
|
|
func TestTorTargetsWith400(t *testing.T) {
|
|
clnt := &FakeHTTPClient{Resp: &http.Response{StatusCode: 400}}
|
|
api := &simpleTorTargetsAPI{
|
|
HTTPClient: clnt,
|
|
Token: "fakeToken",
|
|
}
|
|
ctx := context.Background()
|
|
req := &apimodel.TorTargetsRequest{}
|
|
ff := &fakeFill{}
|
|
ff.Fill(req)
|
|
resp, err := api.Call(ctx, req)
|
|
if !errors.Is(err, ErrHTTPFailure) {
|
|
t.Fatal("not the error we expected", err)
|
|
}
|
|
if resp != nil {
|
|
t.Fatal("expected nil resp")
|
|
}
|
|
}
|
|
|
|
func TestTorTargetsWithResponseBodyReadErr(t *testing.T) {
|
|
errMocked := errors.New("mocked error")
|
|
clnt := &FakeHTTPClient{Resp: &http.Response{
|
|
StatusCode: 200,
|
|
Body: &FakeBody{Err: errMocked},
|
|
}}
|
|
api := &simpleTorTargetsAPI{
|
|
HTTPClient: clnt,
|
|
Token: "fakeToken",
|
|
}
|
|
ctx := context.Background()
|
|
req := &apimodel.TorTargetsRequest{}
|
|
ff := &fakeFill{}
|
|
ff.Fill(req)
|
|
resp, err := api.Call(ctx, req)
|
|
if !errors.Is(err, errMocked) {
|
|
t.Fatal("not the error we expected", err)
|
|
}
|
|
if resp != nil {
|
|
t.Fatal("expected nil resp")
|
|
}
|
|
}
|
|
|
|
func TestTorTargetsWithUnmarshalFailure(t *testing.T) {
|
|
errMocked := errors.New("mocked error")
|
|
clnt := &FakeHTTPClient{Resp: &http.Response{
|
|
StatusCode: 200,
|
|
Body: &FakeBody{Data: []byte(`{}`)},
|
|
}}
|
|
api := &simpleTorTargetsAPI{
|
|
HTTPClient: clnt,
|
|
JSONCodec: &FakeCodec{DecodeErr: errMocked},
|
|
Token: "fakeToken",
|
|
}
|
|
ctx := context.Background()
|
|
req := &apimodel.TorTargetsRequest{}
|
|
ff := &fakeFill{}
|
|
ff.Fill(req)
|
|
resp, err := api.Call(ctx, req)
|
|
if !errors.Is(err, errMocked) {
|
|
t.Fatal("not the error we expected", err)
|
|
}
|
|
if resp != nil {
|
|
t.Fatal("expected nil resp")
|
|
}
|
|
}
|
|
|
|
type handleTorTargets struct {
|
|
accept string
|
|
body []byte
|
|
contentType string
|
|
count int32
|
|
method string
|
|
mu sync.Mutex
|
|
resp apimodel.TorTargetsResponse
|
|
url *url.URL
|
|
userAgent string
|
|
}
|
|
|
|
func (h *handleTorTargets) ServeHTTP(w http.ResponseWriter, r *http.Request) {
|
|
defer h.mu.Unlock()
|
|
h.mu.Lock()
|
|
if h.count > 0 {
|
|
w.WriteHeader(400)
|
|
return
|
|
}
|
|
h.count++
|
|
if r.Body != nil {
|
|
data, err := netxlite.ReadAllContext(r.Context(), r.Body)
|
|
if err != nil {
|
|
w.WriteHeader(400)
|
|
return
|
|
}
|
|
h.body = data
|
|
}
|
|
h.method = r.Method
|
|
h.url = r.URL
|
|
h.accept = r.Header.Get("Accept")
|
|
h.contentType = r.Header.Get("Content-Type")
|
|
h.userAgent = r.Header.Get("User-Agent")
|
|
var out apimodel.TorTargetsResponse
|
|
ff := fakeFill{}
|
|
ff.Fill(&out)
|
|
h.resp = out
|
|
data, err := json.Marshal(out)
|
|
if err != nil {
|
|
w.WriteHeader(400)
|
|
return
|
|
}
|
|
w.Write(data)
|
|
}
|
|
|
|
func TestTorTargetsRoundTrip(t *testing.T) {
|
|
// setup
|
|
handler := &handleTorTargets{}
|
|
srvr := httptest.NewServer(handler)
|
|
defer srvr.Close()
|
|
req := &apimodel.TorTargetsRequest{}
|
|
ff := &fakeFill{}
|
|
ff.Fill(&req)
|
|
api := &simpleTorTargetsAPI{BaseURL: srvr.URL}
|
|
ff.Fill(&api.UserAgent)
|
|
ff.Fill(&api.Token)
|
|
// issue request
|
|
ctx := context.Background()
|
|
resp, err := api.Call(ctx, req)
|
|
if err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
if resp == nil {
|
|
t.Fatal("expected non-nil response here")
|
|
}
|
|
// compare our response and server's one
|
|
if diff := cmp.Diff(handler.resp, resp); diff != "" {
|
|
t.Fatal(diff)
|
|
}
|
|
// check whether headers are OK
|
|
if handler.accept != "application/json" {
|
|
t.Fatal("invalid accept header")
|
|
}
|
|
if handler.userAgent != api.UserAgent {
|
|
t.Fatal("invalid user-agent header")
|
|
}
|
|
// check whether the method is OK
|
|
if handler.method != "GET" {
|
|
t.Fatal("invalid method")
|
|
}
|
|
// check the query
|
|
httpReq, err := api.newRequest(context.Background(), req)
|
|
if err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
if diff := cmp.Diff(handler.url.Path, httpReq.URL.Path); diff != "" {
|
|
t.Fatal(diff)
|
|
}
|
|
if diff := cmp.Diff(handler.url.RawQuery, httpReq.URL.RawQuery); diff != "" {
|
|
t.Fatal(diff)
|
|
}
|
|
}
|
|
|
|
func TestTorTargetsResponseLiteralNull(t *testing.T) {
|
|
clnt := &FakeHTTPClient{Resp: &http.Response{
|
|
StatusCode: 200,
|
|
Body: &FakeBody{Data: []byte(`null`)},
|
|
}}
|
|
api := &simpleTorTargetsAPI{
|
|
HTTPClient: clnt,
|
|
Token: "fakeToken",
|
|
}
|
|
ctx := context.Background()
|
|
req := &apimodel.TorTargetsRequest{}
|
|
ff := &fakeFill{}
|
|
ff.Fill(req)
|
|
resp, err := api.Call(ctx, req)
|
|
if !errors.Is(err, ErrJSONLiteralNull) {
|
|
t.Fatal("not the error we expected", err)
|
|
}
|
|
if resp != nil {
|
|
t.Fatal("expected nil resp")
|
|
}
|
|
}
|
|
|
|
func TestURLsInvalidURL(t *testing.T) {
|
|
api := &simpleURLsAPI{
|
|
BaseURL: "\t", // invalid
|
|
}
|
|
ctx := context.Background()
|
|
req := &apimodel.URLsRequest{}
|
|
ff := &fakeFill{}
|
|
ff.Fill(req)
|
|
resp, err := api.Call(ctx, req)
|
|
if err == nil || !strings.HasSuffix(err.Error(), "invalid control character in URL") {
|
|
t.Fatal("not the error we expected", err)
|
|
}
|
|
if resp != nil {
|
|
t.Fatal("expected nil resp")
|
|
}
|
|
}
|
|
|
|
func TestURLsWithHTTPErr(t *testing.T) {
|
|
errMocked := errors.New("mocked error")
|
|
clnt := &FakeHTTPClient{Err: errMocked}
|
|
api := &simpleURLsAPI{
|
|
HTTPClient: clnt,
|
|
}
|
|
ctx := context.Background()
|
|
req := &apimodel.URLsRequest{}
|
|
ff := &fakeFill{}
|
|
ff.Fill(req)
|
|
resp, err := api.Call(ctx, req)
|
|
if !errors.Is(err, errMocked) {
|
|
t.Fatal("not the error we expected", err)
|
|
}
|
|
if resp != nil {
|
|
t.Fatal("expected nil resp")
|
|
}
|
|
}
|
|
|
|
func TestURLsWithNewRequestErr(t *testing.T) {
|
|
errMocked := errors.New("mocked error")
|
|
api := &simpleURLsAPI{
|
|
RequestMaker: &FakeRequestMaker{Err: errMocked},
|
|
}
|
|
ctx := context.Background()
|
|
req := &apimodel.URLsRequest{}
|
|
ff := &fakeFill{}
|
|
ff.Fill(req)
|
|
resp, err := api.Call(ctx, req)
|
|
if !errors.Is(err, errMocked) {
|
|
t.Fatal("not the error we expected", err)
|
|
}
|
|
if resp != nil {
|
|
t.Fatal("expected nil resp")
|
|
}
|
|
}
|
|
|
|
func TestURLsWith401(t *testing.T) {
|
|
clnt := &FakeHTTPClient{Resp: &http.Response{StatusCode: 401}}
|
|
api := &simpleURLsAPI{
|
|
HTTPClient: clnt,
|
|
}
|
|
ctx := context.Background()
|
|
req := &apimodel.URLsRequest{}
|
|
ff := &fakeFill{}
|
|
ff.Fill(req)
|
|
resp, err := api.Call(ctx, req)
|
|
if !errors.Is(err, ErrUnauthorized) {
|
|
t.Fatal("not the error we expected", err)
|
|
}
|
|
if resp != nil {
|
|
t.Fatal("expected nil resp")
|
|
}
|
|
}
|
|
|
|
func TestURLsWith400(t *testing.T) {
|
|
clnt := &FakeHTTPClient{Resp: &http.Response{StatusCode: 400}}
|
|
api := &simpleURLsAPI{
|
|
HTTPClient: clnt,
|
|
}
|
|
ctx := context.Background()
|
|
req := &apimodel.URLsRequest{}
|
|
ff := &fakeFill{}
|
|
ff.Fill(req)
|
|
resp, err := api.Call(ctx, req)
|
|
if !errors.Is(err, ErrHTTPFailure) {
|
|
t.Fatal("not the error we expected", err)
|
|
}
|
|
if resp != nil {
|
|
t.Fatal("expected nil resp")
|
|
}
|
|
}
|
|
|
|
func TestURLsWithResponseBodyReadErr(t *testing.T) {
|
|
errMocked := errors.New("mocked error")
|
|
clnt := &FakeHTTPClient{Resp: &http.Response{
|
|
StatusCode: 200,
|
|
Body: &FakeBody{Err: errMocked},
|
|
}}
|
|
api := &simpleURLsAPI{
|
|
HTTPClient: clnt,
|
|
}
|
|
ctx := context.Background()
|
|
req := &apimodel.URLsRequest{}
|
|
ff := &fakeFill{}
|
|
ff.Fill(req)
|
|
resp, err := api.Call(ctx, req)
|
|
if !errors.Is(err, errMocked) {
|
|
t.Fatal("not the error we expected", err)
|
|
}
|
|
if resp != nil {
|
|
t.Fatal("expected nil resp")
|
|
}
|
|
}
|
|
|
|
func TestURLsWithUnmarshalFailure(t *testing.T) {
|
|
errMocked := errors.New("mocked error")
|
|
clnt := &FakeHTTPClient{Resp: &http.Response{
|
|
StatusCode: 200,
|
|
Body: &FakeBody{Data: []byte(`{}`)},
|
|
}}
|
|
api := &simpleURLsAPI{
|
|
HTTPClient: clnt,
|
|
JSONCodec: &FakeCodec{DecodeErr: errMocked},
|
|
}
|
|
ctx := context.Background()
|
|
req := &apimodel.URLsRequest{}
|
|
ff := &fakeFill{}
|
|
ff.Fill(req)
|
|
resp, err := api.Call(ctx, req)
|
|
if !errors.Is(err, errMocked) {
|
|
t.Fatal("not the error we expected", err)
|
|
}
|
|
if resp != nil {
|
|
t.Fatal("expected nil resp")
|
|
}
|
|
}
|
|
|
|
type handleURLs struct {
|
|
accept string
|
|
body []byte
|
|
contentType string
|
|
count int32
|
|
method string
|
|
mu sync.Mutex
|
|
resp *apimodel.URLsResponse
|
|
url *url.URL
|
|
userAgent string
|
|
}
|
|
|
|
func (h *handleURLs) ServeHTTP(w http.ResponseWriter, r *http.Request) {
|
|
defer h.mu.Unlock()
|
|
h.mu.Lock()
|
|
if h.count > 0 {
|
|
w.WriteHeader(400)
|
|
return
|
|
}
|
|
h.count++
|
|
if r.Body != nil {
|
|
data, err := netxlite.ReadAllContext(r.Context(), r.Body)
|
|
if err != nil {
|
|
w.WriteHeader(400)
|
|
return
|
|
}
|
|
h.body = data
|
|
}
|
|
h.method = r.Method
|
|
h.url = r.URL
|
|
h.accept = r.Header.Get("Accept")
|
|
h.contentType = r.Header.Get("Content-Type")
|
|
h.userAgent = r.Header.Get("User-Agent")
|
|
var out *apimodel.URLsResponse
|
|
ff := fakeFill{}
|
|
ff.Fill(&out)
|
|
h.resp = out
|
|
data, err := json.Marshal(out)
|
|
if err != nil {
|
|
w.WriteHeader(400)
|
|
return
|
|
}
|
|
w.Write(data)
|
|
}
|
|
|
|
func TestURLsRoundTrip(t *testing.T) {
|
|
// setup
|
|
handler := &handleURLs{}
|
|
srvr := httptest.NewServer(handler)
|
|
defer srvr.Close()
|
|
req := &apimodel.URLsRequest{}
|
|
ff := &fakeFill{}
|
|
ff.Fill(&req)
|
|
api := &simpleURLsAPI{BaseURL: srvr.URL}
|
|
ff.Fill(&api.UserAgent)
|
|
// issue request
|
|
ctx := context.Background()
|
|
resp, err := api.Call(ctx, req)
|
|
if err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
if resp == nil {
|
|
t.Fatal("expected non-nil response here")
|
|
}
|
|
// compare our response and server's one
|
|
if diff := cmp.Diff(handler.resp, resp); diff != "" {
|
|
t.Fatal(diff)
|
|
}
|
|
// check whether headers are OK
|
|
if handler.accept != "application/json" {
|
|
t.Fatal("invalid accept header")
|
|
}
|
|
if handler.userAgent != api.UserAgent {
|
|
t.Fatal("invalid user-agent header")
|
|
}
|
|
// check whether the method is OK
|
|
if handler.method != "GET" {
|
|
t.Fatal("invalid method")
|
|
}
|
|
// check the query
|
|
httpReq, err := api.newRequest(context.Background(), req)
|
|
if err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
if diff := cmp.Diff(handler.url.Path, httpReq.URL.Path); diff != "" {
|
|
t.Fatal(diff)
|
|
}
|
|
if diff := cmp.Diff(handler.url.RawQuery, httpReq.URL.RawQuery); diff != "" {
|
|
t.Fatal(diff)
|
|
}
|
|
}
|
|
|
|
func TestOpenReportInvalidURL(t *testing.T) {
|
|
api := &simpleOpenReportAPI{
|
|
BaseURL: "\t", // invalid
|
|
}
|
|
ctx := context.Background()
|
|
req := &apimodel.OpenReportRequest{}
|
|
ff := &fakeFill{}
|
|
ff.Fill(req)
|
|
resp, err := api.Call(ctx, req)
|
|
if err == nil || !strings.HasSuffix(err.Error(), "invalid control character in URL") {
|
|
t.Fatal("not the error we expected", err)
|
|
}
|
|
if resp != nil {
|
|
t.Fatal("expected nil resp")
|
|
}
|
|
}
|
|
|
|
func TestOpenReportWithHTTPErr(t *testing.T) {
|
|
errMocked := errors.New("mocked error")
|
|
clnt := &FakeHTTPClient{Err: errMocked}
|
|
api := &simpleOpenReportAPI{
|
|
HTTPClient: clnt,
|
|
}
|
|
ctx := context.Background()
|
|
req := &apimodel.OpenReportRequest{}
|
|
ff := &fakeFill{}
|
|
ff.Fill(req)
|
|
resp, err := api.Call(ctx, req)
|
|
if !errors.Is(err, errMocked) {
|
|
t.Fatal("not the error we expected", err)
|
|
}
|
|
if resp != nil {
|
|
t.Fatal("expected nil resp")
|
|
}
|
|
}
|
|
|
|
func TestOpenReportMarshalErr(t *testing.T) {
|
|
errMocked := errors.New("mocked error")
|
|
api := &simpleOpenReportAPI{
|
|
JSONCodec: &FakeCodec{EncodeErr: errMocked},
|
|
}
|
|
ctx := context.Background()
|
|
req := &apimodel.OpenReportRequest{}
|
|
ff := &fakeFill{}
|
|
ff.Fill(req)
|
|
resp, err := api.Call(ctx, req)
|
|
if !errors.Is(err, errMocked) {
|
|
t.Fatal("not the error we expected", err)
|
|
}
|
|
if resp != nil {
|
|
t.Fatal("expected nil resp")
|
|
}
|
|
}
|
|
|
|
func TestOpenReportWithNewRequestErr(t *testing.T) {
|
|
errMocked := errors.New("mocked error")
|
|
api := &simpleOpenReportAPI{
|
|
RequestMaker: &FakeRequestMaker{Err: errMocked},
|
|
}
|
|
ctx := context.Background()
|
|
req := &apimodel.OpenReportRequest{}
|
|
ff := &fakeFill{}
|
|
ff.Fill(req)
|
|
resp, err := api.Call(ctx, req)
|
|
if !errors.Is(err, errMocked) {
|
|
t.Fatal("not the error we expected", err)
|
|
}
|
|
if resp != nil {
|
|
t.Fatal("expected nil resp")
|
|
}
|
|
}
|
|
|
|
func TestOpenReportWith401(t *testing.T) {
|
|
clnt := &FakeHTTPClient{Resp: &http.Response{StatusCode: 401}}
|
|
api := &simpleOpenReportAPI{
|
|
HTTPClient: clnt,
|
|
}
|
|
ctx := context.Background()
|
|
req := &apimodel.OpenReportRequest{}
|
|
ff := &fakeFill{}
|
|
ff.Fill(req)
|
|
resp, err := api.Call(ctx, req)
|
|
if !errors.Is(err, ErrUnauthorized) {
|
|
t.Fatal("not the error we expected", err)
|
|
}
|
|
if resp != nil {
|
|
t.Fatal("expected nil resp")
|
|
}
|
|
}
|
|
|
|
func TestOpenReportWith400(t *testing.T) {
|
|
clnt := &FakeHTTPClient{Resp: &http.Response{StatusCode: 400}}
|
|
api := &simpleOpenReportAPI{
|
|
HTTPClient: clnt,
|
|
}
|
|
ctx := context.Background()
|
|
req := &apimodel.OpenReportRequest{}
|
|
ff := &fakeFill{}
|
|
ff.Fill(req)
|
|
resp, err := api.Call(ctx, req)
|
|
if !errors.Is(err, ErrHTTPFailure) {
|
|
t.Fatal("not the error we expected", err)
|
|
}
|
|
if resp != nil {
|
|
t.Fatal("expected nil resp")
|
|
}
|
|
}
|
|
|
|
func TestOpenReportWithResponseBodyReadErr(t *testing.T) {
|
|
errMocked := errors.New("mocked error")
|
|
clnt := &FakeHTTPClient{Resp: &http.Response{
|
|
StatusCode: 200,
|
|
Body: &FakeBody{Err: errMocked},
|
|
}}
|
|
api := &simpleOpenReportAPI{
|
|
HTTPClient: clnt,
|
|
}
|
|
ctx := context.Background()
|
|
req := &apimodel.OpenReportRequest{}
|
|
ff := &fakeFill{}
|
|
ff.Fill(req)
|
|
resp, err := api.Call(ctx, req)
|
|
if !errors.Is(err, errMocked) {
|
|
t.Fatal("not the error we expected", err)
|
|
}
|
|
if resp != nil {
|
|
t.Fatal("expected nil resp")
|
|
}
|
|
}
|
|
|
|
func TestOpenReportWithUnmarshalFailure(t *testing.T) {
|
|
errMocked := errors.New("mocked error")
|
|
clnt := &FakeHTTPClient{Resp: &http.Response{
|
|
StatusCode: 200,
|
|
Body: &FakeBody{Data: []byte(`{}`)},
|
|
}}
|
|
api := &simpleOpenReportAPI{
|
|
HTTPClient: clnt,
|
|
JSONCodec: &FakeCodec{DecodeErr: errMocked},
|
|
}
|
|
ctx := context.Background()
|
|
req := &apimodel.OpenReportRequest{}
|
|
ff := &fakeFill{}
|
|
ff.Fill(req)
|
|
resp, err := api.Call(ctx, req)
|
|
if !errors.Is(err, errMocked) {
|
|
t.Fatal("not the error we expected", err)
|
|
}
|
|
if resp != nil {
|
|
t.Fatal("expected nil resp")
|
|
}
|
|
}
|
|
|
|
type handleOpenReport struct {
|
|
accept string
|
|
body []byte
|
|
contentType string
|
|
count int32
|
|
method string
|
|
mu sync.Mutex
|
|
resp *apimodel.OpenReportResponse
|
|
url *url.URL
|
|
userAgent string
|
|
}
|
|
|
|
func (h *handleOpenReport) ServeHTTP(w http.ResponseWriter, r *http.Request) {
|
|
defer h.mu.Unlock()
|
|
h.mu.Lock()
|
|
if h.count > 0 {
|
|
w.WriteHeader(400)
|
|
return
|
|
}
|
|
h.count++
|
|
if r.Body != nil {
|
|
data, err := netxlite.ReadAllContext(r.Context(), r.Body)
|
|
if err != nil {
|
|
w.WriteHeader(400)
|
|
return
|
|
}
|
|
h.body = data
|
|
}
|
|
h.method = r.Method
|
|
h.url = r.URL
|
|
h.accept = r.Header.Get("Accept")
|
|
h.contentType = r.Header.Get("Content-Type")
|
|
h.userAgent = r.Header.Get("User-Agent")
|
|
var out *apimodel.OpenReportResponse
|
|
ff := fakeFill{}
|
|
ff.Fill(&out)
|
|
h.resp = out
|
|
data, err := json.Marshal(out)
|
|
if err != nil {
|
|
w.WriteHeader(400)
|
|
return
|
|
}
|
|
w.Write(data)
|
|
}
|
|
|
|
func TestOpenReportRoundTrip(t *testing.T) {
|
|
// setup
|
|
handler := &handleOpenReport{}
|
|
srvr := httptest.NewServer(handler)
|
|
defer srvr.Close()
|
|
req := &apimodel.OpenReportRequest{}
|
|
ff := &fakeFill{}
|
|
ff.Fill(&req)
|
|
api := &simpleOpenReportAPI{BaseURL: srvr.URL}
|
|
ff.Fill(&api.UserAgent)
|
|
// issue request
|
|
ctx := context.Background()
|
|
resp, err := api.Call(ctx, req)
|
|
if err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
if resp == nil {
|
|
t.Fatal("expected non-nil response here")
|
|
}
|
|
// compare our response and server's one
|
|
if diff := cmp.Diff(handler.resp, resp); diff != "" {
|
|
t.Fatal(diff)
|
|
}
|
|
// check whether headers are OK
|
|
if handler.accept != "application/json" {
|
|
t.Fatal("invalid accept header")
|
|
}
|
|
if handler.userAgent != api.UserAgent {
|
|
t.Fatal("invalid user-agent header")
|
|
}
|
|
// check whether the method is OK
|
|
if handler.method != "POST" {
|
|
t.Fatal("invalid method")
|
|
}
|
|
// check the body
|
|
if handler.contentType != "application/json" {
|
|
t.Fatal("invalid content-type header")
|
|
}
|
|
got := &apimodel.OpenReportRequest{}
|
|
if err := json.Unmarshal(handler.body, &got); err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
if diff := cmp.Diff(req, got); diff != "" {
|
|
t.Fatal(diff)
|
|
}
|
|
}
|
|
|
|
func TestSubmitMeasurementInvalidURL(t *testing.T) {
|
|
api := &simpleSubmitMeasurementAPI{
|
|
BaseURL: "\t", // invalid
|
|
}
|
|
ctx := context.Background()
|
|
req := &apimodel.SubmitMeasurementRequest{}
|
|
ff := &fakeFill{}
|
|
ff.Fill(req)
|
|
resp, err := api.Call(ctx, req)
|
|
if err == nil || !strings.HasSuffix(err.Error(), "invalid control character in URL") {
|
|
t.Fatal("not the error we expected", err)
|
|
}
|
|
if resp != nil {
|
|
t.Fatal("expected nil resp")
|
|
}
|
|
}
|
|
|
|
func TestSubmitMeasurementWithHTTPErr(t *testing.T) {
|
|
errMocked := errors.New("mocked error")
|
|
clnt := &FakeHTTPClient{Err: errMocked}
|
|
api := &simpleSubmitMeasurementAPI{
|
|
HTTPClient: clnt,
|
|
}
|
|
ctx := context.Background()
|
|
req := &apimodel.SubmitMeasurementRequest{}
|
|
ff := &fakeFill{}
|
|
ff.Fill(req)
|
|
resp, err := api.Call(ctx, req)
|
|
if !errors.Is(err, errMocked) {
|
|
t.Fatal("not the error we expected", err)
|
|
}
|
|
if resp != nil {
|
|
t.Fatal("expected nil resp")
|
|
}
|
|
}
|
|
|
|
func TestSubmitMeasurementMarshalErr(t *testing.T) {
|
|
errMocked := errors.New("mocked error")
|
|
api := &simpleSubmitMeasurementAPI{
|
|
JSONCodec: &FakeCodec{EncodeErr: errMocked},
|
|
}
|
|
ctx := context.Background()
|
|
req := &apimodel.SubmitMeasurementRequest{}
|
|
ff := &fakeFill{}
|
|
ff.Fill(req)
|
|
resp, err := api.Call(ctx, req)
|
|
if !errors.Is(err, errMocked) {
|
|
t.Fatal("not the error we expected", err)
|
|
}
|
|
if resp != nil {
|
|
t.Fatal("expected nil resp")
|
|
}
|
|
}
|
|
|
|
func TestSubmitMeasurementWithNewRequestErr(t *testing.T) {
|
|
errMocked := errors.New("mocked error")
|
|
api := &simpleSubmitMeasurementAPI{
|
|
RequestMaker: &FakeRequestMaker{Err: errMocked},
|
|
}
|
|
ctx := context.Background()
|
|
req := &apimodel.SubmitMeasurementRequest{}
|
|
ff := &fakeFill{}
|
|
ff.Fill(req)
|
|
resp, err := api.Call(ctx, req)
|
|
if !errors.Is(err, errMocked) {
|
|
t.Fatal("not the error we expected", err)
|
|
}
|
|
if resp != nil {
|
|
t.Fatal("expected nil resp")
|
|
}
|
|
}
|
|
|
|
func TestSubmitMeasurementWith401(t *testing.T) {
|
|
clnt := &FakeHTTPClient{Resp: &http.Response{StatusCode: 401}}
|
|
api := &simpleSubmitMeasurementAPI{
|
|
HTTPClient: clnt,
|
|
}
|
|
ctx := context.Background()
|
|
req := &apimodel.SubmitMeasurementRequest{}
|
|
ff := &fakeFill{}
|
|
ff.Fill(req)
|
|
resp, err := api.Call(ctx, req)
|
|
if !errors.Is(err, ErrUnauthorized) {
|
|
t.Fatal("not the error we expected", err)
|
|
}
|
|
if resp != nil {
|
|
t.Fatal("expected nil resp")
|
|
}
|
|
}
|
|
|
|
func TestSubmitMeasurementWith400(t *testing.T) {
|
|
clnt := &FakeHTTPClient{Resp: &http.Response{StatusCode: 400}}
|
|
api := &simpleSubmitMeasurementAPI{
|
|
HTTPClient: clnt,
|
|
}
|
|
ctx := context.Background()
|
|
req := &apimodel.SubmitMeasurementRequest{}
|
|
ff := &fakeFill{}
|
|
ff.Fill(req)
|
|
resp, err := api.Call(ctx, req)
|
|
if !errors.Is(err, ErrHTTPFailure) {
|
|
t.Fatal("not the error we expected", err)
|
|
}
|
|
if resp != nil {
|
|
t.Fatal("expected nil resp")
|
|
}
|
|
}
|
|
|
|
func TestSubmitMeasurementWithResponseBodyReadErr(t *testing.T) {
|
|
errMocked := errors.New("mocked error")
|
|
clnt := &FakeHTTPClient{Resp: &http.Response{
|
|
StatusCode: 200,
|
|
Body: &FakeBody{Err: errMocked},
|
|
}}
|
|
api := &simpleSubmitMeasurementAPI{
|
|
HTTPClient: clnt,
|
|
}
|
|
ctx := context.Background()
|
|
req := &apimodel.SubmitMeasurementRequest{}
|
|
ff := &fakeFill{}
|
|
ff.Fill(req)
|
|
resp, err := api.Call(ctx, req)
|
|
if !errors.Is(err, errMocked) {
|
|
t.Fatal("not the error we expected", err)
|
|
}
|
|
if resp != nil {
|
|
t.Fatal("expected nil resp")
|
|
}
|
|
}
|
|
|
|
func TestSubmitMeasurementWithUnmarshalFailure(t *testing.T) {
|
|
errMocked := errors.New("mocked error")
|
|
clnt := &FakeHTTPClient{Resp: &http.Response{
|
|
StatusCode: 200,
|
|
Body: &FakeBody{Data: []byte(`{}`)},
|
|
}}
|
|
api := &simpleSubmitMeasurementAPI{
|
|
HTTPClient: clnt,
|
|
JSONCodec: &FakeCodec{DecodeErr: errMocked},
|
|
}
|
|
ctx := context.Background()
|
|
req := &apimodel.SubmitMeasurementRequest{}
|
|
ff := &fakeFill{}
|
|
ff.Fill(req)
|
|
resp, err := api.Call(ctx, req)
|
|
if !errors.Is(err, errMocked) {
|
|
t.Fatal("not the error we expected", err)
|
|
}
|
|
if resp != nil {
|
|
t.Fatal("expected nil resp")
|
|
}
|
|
}
|
|
|
|
type handleSubmitMeasurement struct {
|
|
accept string
|
|
body []byte
|
|
contentType string
|
|
count int32
|
|
method string
|
|
mu sync.Mutex
|
|
resp *apimodel.SubmitMeasurementResponse
|
|
url *url.URL
|
|
userAgent string
|
|
}
|
|
|
|
func (h *handleSubmitMeasurement) ServeHTTP(w http.ResponseWriter, r *http.Request) {
|
|
defer h.mu.Unlock()
|
|
h.mu.Lock()
|
|
if h.count > 0 {
|
|
w.WriteHeader(400)
|
|
return
|
|
}
|
|
h.count++
|
|
if r.Body != nil {
|
|
data, err := netxlite.ReadAllContext(r.Context(), r.Body)
|
|
if err != nil {
|
|
w.WriteHeader(400)
|
|
return
|
|
}
|
|
h.body = data
|
|
}
|
|
h.method = r.Method
|
|
h.url = r.URL
|
|
h.accept = r.Header.Get("Accept")
|
|
h.contentType = r.Header.Get("Content-Type")
|
|
h.userAgent = r.Header.Get("User-Agent")
|
|
var out *apimodel.SubmitMeasurementResponse
|
|
ff := fakeFill{}
|
|
ff.Fill(&out)
|
|
h.resp = out
|
|
data, err := json.Marshal(out)
|
|
if err != nil {
|
|
w.WriteHeader(400)
|
|
return
|
|
}
|
|
w.Write(data)
|
|
}
|
|
|
|
func TestSubmitMeasurementRoundTrip(t *testing.T) {
|
|
// setup
|
|
handler := &handleSubmitMeasurement{}
|
|
srvr := httptest.NewServer(handler)
|
|
defer srvr.Close()
|
|
req := &apimodel.SubmitMeasurementRequest{}
|
|
ff := &fakeFill{}
|
|
ff.Fill(&req)
|
|
api := &simpleSubmitMeasurementAPI{BaseURL: srvr.URL}
|
|
ff.Fill(&api.UserAgent)
|
|
// issue request
|
|
ctx := context.Background()
|
|
resp, err := api.Call(ctx, req)
|
|
if err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
if resp == nil {
|
|
t.Fatal("expected non-nil response here")
|
|
}
|
|
// compare our response and server's one
|
|
if diff := cmp.Diff(handler.resp, resp); diff != "" {
|
|
t.Fatal(diff)
|
|
}
|
|
// check whether headers are OK
|
|
if handler.accept != "application/json" {
|
|
t.Fatal("invalid accept header")
|
|
}
|
|
if handler.userAgent != api.UserAgent {
|
|
t.Fatal("invalid user-agent header")
|
|
}
|
|
// check whether the method is OK
|
|
if handler.method != "POST" {
|
|
t.Fatal("invalid method")
|
|
}
|
|
// check the body
|
|
if handler.contentType != "application/json" {
|
|
t.Fatal("invalid content-type header")
|
|
}
|
|
got := &apimodel.SubmitMeasurementRequest{}
|
|
if err := json.Unmarshal(handler.body, &got); err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
if diff := cmp.Diff(req, got); diff != "" {
|
|
t.Fatal(diff)
|
|
}
|
|
}
|
|
|
|
func TestSubmitMeasurementTemplateErr(t *testing.T) {
|
|
errMocked := errors.New("mocked error")
|
|
clnt := &FakeHTTPClient{Resp: &http.Response{
|
|
StatusCode: 500,
|
|
}}
|
|
api := &simpleSubmitMeasurementAPI{
|
|
HTTPClient: clnt,
|
|
TemplateExecutor: &FakeTemplateExecutor{Err: errMocked},
|
|
}
|
|
ctx := context.Background()
|
|
req := &apimodel.SubmitMeasurementRequest{}
|
|
ff := &fakeFill{}
|
|
ff.Fill(req)
|
|
resp, err := api.Call(ctx, req)
|
|
if !errors.Is(err, errMocked) {
|
|
t.Fatal("not the error we expected", err)
|
|
}
|
|
if resp != nil {
|
|
t.Fatal("expected nil resp")
|
|
}
|
|
}
|