~adnano/go-gemini

b5c47a5ef0569fc6462b9715ccd3d770ff566c09 — Adnan Maolood 1 year, 9 days ago fb0d4d2
mux: Add more tests
1 files changed, 218 insertions(+), 2 deletions(-)

M mux_test.go
M mux_test.go => mux_test.go +218 -2
@@ 2,6 2,7 @@ package gemini

import (
	"context"
	"io"
	"net/url"
	"testing"
)


@@ 10,6 11,221 @@ type nopHandler struct{}

func (*nopHandler) ServeGemini(context.Context, ResponseWriter, *Request) {}

type nopResponseWriter struct {
	Status Status
	Meta   string
}

func (w *nopResponseWriter) WriteHeader(status Status, meta string) {
	w.Status = status
	w.Meta = meta
}

func (nopResponseWriter) SetMediaType(mediatype string) {}
func (nopResponseWriter) Write(b []byte) (int, error)   { return 0, io.EOF }
func (nopResponseWriter) Flush() error                  { return nil }

func TestMux(t *testing.T) {
	type Test struct {
		URL      string
		Pattern  string
		Redirect string
		NotFound bool
	}

	tests := []struct {
		Patterns []string
		Tests    []Test
	}{
		{
			Patterns: []string{"/a", "/b/", "/b/c/d", "/b/c/d/"},
			Tests: []Test{
				{
					URL:      "gemini://example.com",
					Redirect: "gemini://example.com/",
				},
				{
					URL:      "gemini://example.com/",
					NotFound: true,
				},
				{
					URL:      "gemini://example.com/c",
					NotFound: true,
				},
				{
					URL:     "gemini://example.com/a",
					Pattern: "/a",
				},
				{
					URL:      "gemini://example.com/a/",
					NotFound: true,
				},
				{
					URL:      "gemini://example.com/b",
					Redirect: "gemini://example.com/b/",
				},
				{
					URL:     "gemini://example.com/b/",
					Pattern: "/b/",
				},
				{
					URL:     "gemini://example.com/b/c",
					Pattern: "/b/",
				},
				{
					URL:     "gemini://example.com/b/c/d",
					Pattern: "/b/c/d",
				},
				{
					URL:     "gemini://example.com/b/c/d/e/",
					Pattern: "/b/c/d/",
				},
			},
		},
		{
			Patterns: []string{
				"/", "/a", "/b/",
				"example.com", "example.com/a", "example.com/b/",
				"*.example.com", "*.example.com/a", "*.example.com/b/",
			},
			Tests: []Test{
				{
					URL:     "gemini://example.net/",
					Pattern: "/",
				},
				{
					URL:     "gemini://example.net/a",
					Pattern: "/a",
				},
				{
					URL:      "gemini://example.net/b",
					Redirect: "gemini://example.net/b/",
				},
				{
					URL:     "gemini://example.net/b/",
					Pattern: "/b/",
				},
				{
					URL:     "gemini://example.com/",
					Pattern: "example.com",
				},
				{
					URL:      "gemini://example.com/b",
					Redirect: "gemini://example.com/b/",
				},
				{
					URL:     "gemini://example.com/b/",
					Pattern: "example.com/b/",
				},
				{
					URL:     "gemini://a.example.com/",
					Pattern: "*.example.com",
				},
				{
					URL:     "gemini://b.example.com/a",
					Pattern: "*.example.com/a",
				},
				{
					URL:      "gemini://c.example.com/b",
					Redirect: "gemini://c.example.com/b/",
				},
				{
					URL:     "gemini://d.example.com/b/",
					Pattern: "*.example.com/b/",
				},
			},
		},
		{
			Patterns: []string{"example.net", "*.example.org"},
			Tests: []Test{
				{
					// The following redirect occurs as a result of cleaning
					// the path provided to the Mux. This happens even if there
					// are no matching handlers.
					URL:      "gemini://example.com",
					Redirect: "gemini://example.com/",
				},
				{
					URL:      "gemini://example.com/",
					NotFound: true,
				},
				{
					URL:      "gemini://example.net",
					Redirect: "gemini://example.net/",
				},
				{
					URL:      "gemini://example.org/",
					NotFound: true,
				},
				{
					URL:      "gemini://gemini.example.org",
					Redirect: "gemini://gemini.example.org/",
				},
			},
		},
	}

	for _, test := range tests {
		type handler struct {
			nopHandler
			Pattern string
		}

		mux := &Mux{}
		for _, pattern := range test.Patterns {
			mux.Handle(pattern, &handler{
				Pattern: pattern,
			})
		}

		for _, test := range test.Tests {
			u, err := url.Parse(test.URL)
			if err != nil {
				panic(err)
			}

			req := &Request{URL: u}

			h := mux.Handler(req)

			if h, ok := h.(*handler); ok {
				if h.Pattern != test.Pattern {
					t.Errorf("wrong pattern for %q: expected %q, got %q", test.URL, test.Pattern, h.Pattern)
				}
				continue
			}

			// Check redirects and NotFounds
			w := &nopResponseWriter{}
			h.ServeGemini(context.Background(), w, req)

			switch w.Status {
			case StatusNotFound:
				if !test.NotFound {
					t.Errorf("expected pattern for %q, got NotFound", test.URL)
				}

			case StatusPermanentRedirect:
				if test.Redirect == "" {
					t.Errorf("expected pattern for %q, got redirect to %q", test.URL, w.Meta)
					break
				}

				res, err := url.Parse(test.Redirect)
				if err != nil {
					panic(err)
				}
				if w.Meta != res.String() {
					t.Errorf("bad redirect for %q: expected %q, got %q", test.URL, res.String(), w.Meta)
				}

			default:
				t.Errorf("unexpected response for %q: %d %s", test.URL, w.Status, w.Meta)
			}
		}
	}
}

func TestMuxMatch(t *testing.T) {
	type Match struct {
		URL string


@@ 115,12 331,12 @@ func TestMuxMatch(t *testing.T) {
		},
	}

	for i, test := range tests {
	for _, test := range tests {
		h := &nopHandler{}
		var mux Mux
		mux.Handle(test.Pattern, h)

		for _, match := range tests[i].Matches {
		for _, match := range test.Matches {
			u, err := url.Parse(match.URL)
			if err != nil {
				panic(err)