ooni-probe-cli/internal/cmd/oohelperd/internal/internal_test.go
Simone Basso 4eeadd06a5
refactor: move more commands to internal/cmd (#207)
* refactor: move more commands to internal/cmd

Part of https://github.com/ooni/probe/issues/1335.

We would like all commands to be at the same level of engine
rather than inside engine (now that we can do it).

* fix: update .gitignore

* refactor: also move jafar outside engine

* We should be good now?
2021-02-03 12:23:15 +01:00

161 lines
3.8 KiB
Go

package internal_test
import (
"encoding/json"
"errors"
"io/ioutil"
"net"
"net/http"
"net/http/httptest"
"strings"
"testing"
"github.com/ooni/probe-cli/v3/internal/cmd/oohelperd/internal"
"github.com/ooni/probe-cli/v3/internal/engine/netx/resolver"
)
const simplerequest = `{
"http_request": "https://dns.google",
"http_request_headers": {
"Accept": [
"*/*"
],
"Accept-Language": [
"en-US;q=0.8,en;q=0.5"
],
"User-Agent": [
"Mozilla/5.0"
]
},
"tcp_connect": [
"8.8.8.8:443"
]
}`
const requestWithoutDomainName = `{
"http_request": "https://8.8.8.8",
"http_request_headers": {
"Accept": [
"*/*"
],
"Accept-Language": [
"en-US;q=0.8,en;q=0.5"
],
"User-Agent": [
"Mozilla/5.0"
]
},
"tcp_connect": [
"8.8.8.8:443"
]
}`
func TestWorkingAsIntended(t *testing.T) {
handler := internal.Handler{
Client: http.DefaultClient,
Dialer: new(net.Dialer),
MaxAcceptableBody: 1 << 24,
Resolver: resolver.SystemResolver{},
}
srv := httptest.NewServer(handler)
defer srv.Close()
type expectationSpec struct {
name string
reqMethod string
reqContentType string
reqBody string
respStatusCode int
respContentType string
parseBody bool
}
expectations := []expectationSpec{{
name: "check for invalid method",
reqMethod: "GET",
respStatusCode: 400,
}, {
name: "check for invalid content-type",
reqMethod: "POST",
respStatusCode: 400,
}, {
name: "check for invalid request body",
reqMethod: "POST",
reqContentType: "application/json",
reqBody: "{",
respStatusCode: 400,
}, {
name: "with measurement failure",
reqMethod: "POST",
reqContentType: "application/json",
reqBody: `{"http_request": "http://[::1]aaaa"}`,
respStatusCode: 400,
}, {
name: "with reasonably good request",
reqMethod: "POST",
reqContentType: "application/json",
reqBody: simplerequest,
respStatusCode: 200,
respContentType: "application/json",
parseBody: true,
}, {
name: "when there's no domain name in the request",
reqMethod: "POST",
reqContentType: "application/json",
reqBody: requestWithoutDomainName,
respStatusCode: 200,
respContentType: "application/json",
parseBody: true,
}}
for _, expect := range expectations {
t.Run(expect.name, func(t *testing.T) {
body := strings.NewReader(expect.reqBody)
req, err := http.NewRequest(expect.reqMethod, srv.URL, body)
if err != nil {
t.Fatalf("%s: %+v", expect.name, err)
}
if expect.reqContentType != "" {
req.Header.Add("content-type", expect.reqContentType)
}
resp, err := http.DefaultClient.Do(req)
if err != nil {
t.Fatalf("%s: %+v", expect.name, err)
}
defer resp.Body.Close()
if resp.StatusCode != expect.respStatusCode {
t.Fatalf("unexpected status code: %+v", resp.StatusCode)
}
if v := resp.Header.Get("content-type"); v != expect.respContentType {
t.Fatalf("unexpected content-type: %s", v)
}
data, err := ioutil.ReadAll(resp.Body)
if err != nil {
t.Fatal(err)
}
if !expect.parseBody {
return
}
var v interface{}
if err := json.Unmarshal(data, &v); err != nil {
t.Fatal(err)
}
})
}
}
func TestHandlerWithRequestBodyReadingError(t *testing.T) {
expected := errors.New("mocked error")
handler := internal.Handler{MaxAcceptableBody: 1 << 24}
rw := internal.NewFakeResponseWriter()
req := &http.Request{
Method: "POST",
Header: map[string][]string{
"Content-Type": {"application/json"},
"Content-Length": {"2048"},
},
Body: &internal.FakeBody{Err: expected},
}
handler.ServeHTTP(rw, req)
if rw.StatusCode != 400 {
t.Fatal("unexpected status code")
}
}