Skip to content

Commit

Permalink
Merge pull request #490 from alphagov/populate-triemux-from-cs
Browse files Browse the repository at this point in the history
Add ability to load triemux from Content Store
  • Loading branch information
theseanything authored Dec 4, 2024
2 parents 444329d + 2bd126d commit 90ec177
Show file tree
Hide file tree
Showing 1,503 changed files with 268,621 additions and 314 deletions.
1 change: 1 addition & 0 deletions Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@ unit_tests:

integration_tests: build start_mongo
go test -race -v ./integration_tests
go test -race -v ./cs_integration_tests

start_mongo:
./mongo.sh start
Expand Down
99 changes: 99 additions & 0 deletions cs_integration_tests/backend_helpers.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,99 @@
package integration

import (
"net"
"net/http"
"net/http/httptest"
"strconv"
"time"

// revive:disable:dot-imports
. "github.com/onsi/gomega"
// revive:enable:dot-imports
"github.com/onsi/gomega/ghttp"
)

var backends = map[string]string{
"backend-1": "127.0.0.1:6789",
"backend-2": "127.0.0.1:6790",
"outer": "127.0.0.1:6792",
"inner": "127.0.0.1:6793",
"innerer": "127.0.0.1:6794",
"root": "127.0.0.1:6795",
"other": "127.0.0.1:6796",
"fallthrough": "127.0.0.1:6797",
"down": "127.0.0.1:6798",
"slow-1": "127.0.0.1:6799",
"slow-2": "127.0.0.1:6800",
"backend": "127.0.0.1:6801",
"be": "127.0.0.1:6802",
"not-running": "127.0.0.1:6803",
"with-path": "127.0.0.1:6804",
}

func startSimpleBackend(identifier, host string) *httptest.Server {
l, err := net.Listen("tcp", host)
Expect(err).NotTo(HaveOccurred())

ts := httptest.NewUnstartedServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
_, err := w.Write([]byte(identifier))
Expect(err).NotTo(HaveOccurred())
}))
ts.Listener.Close()
ts.Listener = l
ts.Start()
return ts
}

func startTarpitBackend(host string, delays ...time.Duration) *httptest.Server {
responseDelay := 2 * time.Second
if len(delays) > 0 {
responseDelay = delays[0]
}
bodyDelay := 0 * time.Second
if len(delays) > 1 {
bodyDelay = delays[1]
}

l, err := net.Listen("tcp", host)
Expect(err).NotTo(HaveOccurred())

ts := httptest.NewUnstartedServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
body := "Tarpit\n"

if responseDelay > 0 {
time.Sleep(responseDelay)
}
w.Header().Add("Content-Length", strconv.Itoa(len(body)))
w.WriteHeader(http.StatusOK)
w.(http.Flusher).Flush()

if bodyDelay > 0 {
time.Sleep(bodyDelay)
}
_, err := w.Write([]byte(body))
Expect(err).NotTo(HaveOccurred())
}))
ts.Listener.Close()
ts.Listener = l
ts.Start()
return ts
}

func startRecordingBackend(tls bool, host string) *ghttp.Server {
l, err := net.Listen("tcp", host)
Expect(err).NotTo(HaveOccurred())

ts := ghttp.NewUnstartedServer()
ts.HTTPTestServer.Listener.Close()
ts.HTTPTestServer.Listener = l
if tls {
ts.HTTPTestServer.StartTLS()
} else {
ts.Start()
}

ts.AllowUnhandledRequests = true
ts.UnhandledRequestStatusCode = http.StatusOK
return ts
}
23 changes: 23 additions & 0 deletions cs_integration_tests/error_handling_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
package integration

import (
. "github.com/onsi/ginkgo/v2"
. "github.com/onsi/gomega"
)

var _ = Describe("error handling", func() {

Describe("handling an empty routing table", func() {
BeforeEach(func() {
reloadRoutes(apiPort)
})

It("should return a 503 error to the client", func() {
resp := routerRequest(routerPort, "/")
Expect(resp.StatusCode).To(Equal(503))

resp = routerRequest(routerPort, "/foo")
Expect(resp.StatusCode).To(Equal(503))
})
})
})
35 changes: 35 additions & 0 deletions cs_integration_tests/gone_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
package integration

import (
. "github.com/onsi/ginkgo/v2"
. "github.com/onsi/gomega"
)

var _ = Describe("Gone routes", func() {

BeforeEach(func() {
addRoute("/foo", NewGoneRoute())
addRoute("/bar", NewGoneRoute("prefix"))
reloadRoutes(apiPort)
})

It("should support an exact gone route", func() {
resp := routerRequest(routerPort, "/foo")
Expect(resp.StatusCode).To(Equal(410))
Expect(readBody(resp)).To(Equal("410 Gone\n"))

resp = routerRequest(routerPort, "/foo/bar")
Expect(resp.StatusCode).To(Equal(404))
Expect(readBody(resp)).To(Equal("404 page not found\n"))
})

It("should support a prefix gone route", func() {
resp := routerRequest(routerPort, "/bar")
Expect(resp.StatusCode).To(Equal(410))
Expect(readBody(resp)).To(Equal("410 Gone\n"))

resp = routerRequest(routerPort, "/bar/baz")
Expect(resp.StatusCode).To(Equal(410))
Expect(readBody(resp)).To(Equal("410 Gone\n"))
})
})
83 changes: 83 additions & 0 deletions cs_integration_tests/http_request_helpers.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,83 @@
package integration

import (
"bufio"
"context"
"encoding/json"
"fmt"
"io"
"net"
"net/http"
"net/textproto"

// revive:disable:dot-imports
. "github.com/onsi/gomega"
// revive:enable:dot-imports
)

func routerRequest(port int, path string) *http.Response {
return doRequest(newRequest(http.MethodGet, routerURL(port, path)))
}

func routerRequestWithHeaders(port int, path string, headers map[string]string) *http.Response {
return doRequest(newRequestWithHeaders(http.MethodGet, routerURL(port, path), headers))
}

func newRequest(method, url string) *http.Request {
req, err := http.NewRequestWithContext(context.Background(), method, url, nil)
Expect(err).NotTo(HaveOccurred())
return req
}

func newRequestWithHeaders(method, url string, headers map[string]string) *http.Request {
req := newRequest(method, url)
for k, v := range headers {
req.Header.Set(k, v)
}
return req
}

func doRequest(req *http.Request) *http.Response {
if _, ok := req.Header[textproto.CanonicalMIMEHeaderKey("User-Agent")]; !ok {
// Setting a blank User-Agent causes the http lib not to output one, whereas if there
// is no header, it will output a default one.
// See: https://github.com/golang/go/blob/release-branch.go1.5/src/net/http/request.go#L419
req.Header.Set("User-Agent", "")
}
resp, err := http.DefaultTransport.RoundTrip(req)
Expect(err).NotTo(HaveOccurred())
return resp
}

func doHTTP10Request(req *http.Request) *http.Response {
conn, err := net.Dial("tcp", req.URL.Host)
Expect(err).NotTo(HaveOccurred())
defer conn.Close()

if req.Method == "" {
req.Method = http.MethodGet
}
req.Proto = "HTTP/1.0"
req.ProtoMinor = 0
fmt.Fprintf(conn, "%s %s %s\r\n", req.Method, req.URL.RequestURI(), req.Proto)
err = req.Header.Write(conn)
Expect(err).NotTo(HaveOccurred())
fmt.Fprintf(conn, "\r\n")

resp, err := http.ReadResponse(bufio.NewReader(conn), req)
Expect(err).NotTo(HaveOccurred())
return resp
}

func readBody(resp *http.Response) string {
bytes, err := io.ReadAll(resp.Body)
Expect(err).NotTo(HaveOccurred())
return string(bytes)
}

func readJSONBody(resp *http.Response, data interface{}) {
bytes, err := io.ReadAll(resp.Body)
Expect(err).NotTo(HaveOccurred())
err = json.Unmarshal(bytes, data)
Expect(err).NotTo(HaveOccurred())
}
56 changes: 56 additions & 0 deletions cs_integration_tests/integration_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,56 @@
package integration

import (
"context"
"runtime"
"testing"

. "github.com/onsi/ginkgo/v2"
. "github.com/onsi/gomega"
)

var cleanupPostgresContainer func()

func TestEverything(t *testing.T) {
RegisterFailHandler(Fail)
RunSpecs(t, "Integration test suite")
}

var _ = BeforeSuite(func() {
runtime.GOMAXPROCS(runtime.NumCPU())
err := setupTempLogfile()
if err != nil {
Fail(err.Error())
}

ctx := context.Background()

postgresContainer, cleanupPostgresContainer, err = runPostgresContainer(ctx)

if err != nil {
Fail(err.Error())
}

backendEnvVars := []string{}
for id, host := range backends {
envVar := "BACKEND_URL_" + id + "=http://" + host
backendEnvVars = append(backendEnvVars, envVar)
}

if err := startRouter(routerPort, apiPort, backendEnvVars); err != nil {
Fail(err.Error())
}
if err := initRouteHelper(); err != nil {
Fail(err.Error())
}
})

var _ = BeforeEach(func() {
resetTempLogfile()
})

var _ = AfterSuite(func() {
stopRouter(routerPort)
cleanupPostgresContainer()
cleanupTempLogfile()
})
16 changes: 16 additions & 0 deletions cs_integration_tests/metrics_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
package integration

import (
. "github.com/onsi/ginkgo/v2"
. "github.com/onsi/gomega"
)

var _ = Describe("/metrics API endpoint", func() {
Context("response body", func() {
It("should contain at least one metric", func() {
resp := doRequest(newRequest("GET", routerURL(apiPort, "/metrics")))
Expect(resp.StatusCode).To(Equal(200))
Expect(readBody(resp)).To(ContainSubstring("router_"))
})
})
})
Loading

0 comments on commit 90ec177

Please sign in to comment.