git » dnss » commit 1865c02

httpserver: Add more tests to cover request resolution

author Alberto Bertogli
2023-02-26 21:53:48 UTC
committer Alberto Bertogli
2023-02-26 21:53:48 UTC
parent 678d6ab2a576559c07fd385efe35e43f33fb0f9e

httpserver: Add more tests to cover request resolution

There were some httpserver request resolution corner cases (usually
around upstream failure and fairly invalid requests) that weren't
covered by our tests.

This patch fixes that by a combination of Go and integration tests.

Note that we still have some specific situations uncovered, but the code
paths for those are much reduced and unusual to hit.

internal/httpserver/server_test.go +81 -0
tests/external.sh +10 -4

diff --git a/internal/httpserver/server_test.go b/internal/httpserver/server_test.go
new file mode 100644
index 0000000..40e019d
--- /dev/null
+++ b/internal/httpserver/server_test.go
@@ -0,0 +1,81 @@
+package httpserver
+
+import (
+	"errors"
+	"net/http"
+	"net/http/httptest"
+	"strings"
+	"testing"
+
+	"blitiri.com.ar/go/dnss/internal/testutil"
+)
+
+func TestBasic(t *testing.T) {
+	upstreamAddr := testutil.GetFreePort()
+	go testutil.ServeTestDNSServer(upstreamAddr,
+		testutil.MakeStaticHandler(t, "test. A 1.1.1.1"))
+	testutil.WaitForDNSServer(upstreamAddr)
+
+	srv := &Server{
+		Upstream: upstreamAddr,
+	}
+
+	// Simple successful query.
+	resp := query(t, srv, "GET",
+		"/ignored?dns=q80BAAABAAAAAAAAA3d3dwdleGFtcGxlA2NvbQAAAQAB", "")
+	if resp.StatusCode != http.StatusOK {
+		t.Errorf("good test: expected http status ok, got %v",
+			resp.StatusCode)
+	}
+
+	// Invalid request (error unpacking)
+	resp = query(t, srv, "GET",
+		"/ignored?dns=0000", "")
+	if resp.StatusCode != http.StatusBadRequest {
+		t.Errorf("unpacking test: expected bad request, got %v",
+			resp.StatusCode)
+	}
+
+	// Error reading request body.
+	{
+		req := httptest.NewRequest("POST", "/ignored", nil)
+		req.Header.Set("Content-Type", "application/dns-message")
+		req.Body = errorReadCloser{}
+		w := httptest.NewRecorder()
+		srv.Resolve(w, req)
+		resp := w.Result()
+		if resp.StatusCode != http.StatusBadRequest {
+			t.Errorf("bad body test: expected bad request, got %v",
+				resp.StatusCode)
+		}
+	}
+
+	// Upstream error.
+	// Put this last because we override the upstream address.
+	srv.Upstream = "localhost:0"
+	resp = query(t, srv, "GET",
+		"/ignored?dns=q80BAAABAAAAAAAAA3d3dwdleGFtcGxlA2NvbQAAAQAB", "")
+	if resp.StatusCode != http.StatusFailedDependency {
+		t.Errorf("bad upstream test: expected failed dependency, got %v",
+			resp.StatusCode)
+	}
+}
+
+func query(t *testing.T, srv *Server, method, url, body string) *http.Response {
+	t.Helper()
+
+	req := httptest.NewRequest(method, url, strings.NewReader(body))
+	req.Header.Set("Content-Type", "application/dns-message")
+
+	w := httptest.NewRecorder()
+	srv.Resolve(w, req)
+
+	return w.Result()
+}
+
+type errorReadCloser struct{}
+
+func (errorReadCloser) Read(p []byte) (int, error) {
+	return 0, errors.New("error for testing")
+}
+func (errorReadCloser) Close() error { return nil }
diff --git a/tests/external.sh b/tests/external.sh
index 232821b..37d1c1f 100755
--- a/tests/external.sh
+++ b/tests/external.sh
@@ -109,11 +109,9 @@ function resolve() {
 	fi
 }
 
-# HTTP GET, using wget.
+# wget wrapper, for convenience.
 function get() {
-	URL=$1
-
-	wget -O.wget.out $URL > .wget.log 2>&1
+	wget -O.wget.out "$@" > .wget.log 2>&1
 }
 
 function generate_certs() {
@@ -174,6 +172,14 @@ if get "http://localhost:1999/resolve?nothing"; then
 	exit 1
 fi
 
+if get --post-data "dns=q80BAAABAAAAAAAAA3d3dwdleGFtcGxlA2NvbQAAAQAB" \
+	--header "Content-Type: "\
+	"http://localhost:1999/resolve";
+then
+	echo "POST with invalid content type did not fail"
+	exit 1
+fi
+
 resolve
 kill $PID