func TestServeMux_EncodedPathComponentParamExtraction(t *testing.T) {
	s := NewServeMux()
	var called bool
	var param string
	rightHandler := http.HandlerFunc(func(rw http.ResponseWriter, req *http.Request) {
		called = true
		param = PathParam(req, "id")
	})
	s.Route("/users/:id/info").Get(rightHandler)
	req := httptest.NewRequest(http.MethodGet, "/users/ji%2Fm/info", nil)
	s.ServeHTTP(nil, req)
	if !called {
		t.Error("None or wrong handler was called")
	}
	if param != "ji/m" {
		t.Error("Wrong path param returned")
	}
}
Ensure routing is not performed on decoded path components
and path parameter is properly extracted
package powermux
import (
	"io"
	"net/http"
	"net/http/httptest"
	"strings"
	"testing"
)
type dummyHandler string
func (h dummyHandler) ServeHTTP(w http.ResponseWriter, r *http.Request) {
	io.WriteString(w, string(h))
}
func (h dummyHandler) ServeHTTPMiddleware(w http.ResponseWriter, r *http.Request, n func(http.ResponseWriter, *http.Request)) {
	io.WriteString(w, string(h))
	n(w, r)
}
func dummyHandlerFunc(response string) func(w http.ResponseWriter, r *http.Request) {
	return func(w http.ResponseWriter, r *http.Request) {
		io.WriteString(w, response)
	}
}
var (
	rightHandler = dummyHandler("right")
	wrongHandler = dummyHandler("wrong")
	mid1         = dummyHandler("mid1")
	mid2         = dummyHandler("mid2")
)
var allMethods = []string{
	http.MethodDelete,
	http.MethodGet,
	http.MethodHead,
	http.MethodOptions,
	http.MethodPatch,
	http.MethodPost,
	http.MethodConnect,
	http.MethodPut,
}
func TestServeMux_ParamPrecedence(t *testing.T) {
	s := NewServeMux()
	s.Route("/users/:id/info").Get(wrongHandler)
	s.Route("/users/jim/info").Get(rightHandler)
	s.Route("/users/:id/detail").Get(wrongHandler)
	req := httptest.NewRequest(http.MethodGet, "/users/jim/info", nil)
	h, path := s.Handler(req)
	if h != rightHandler {
		t.Error("Wrong handler returned")
	}
	if path != "/users/jim/info" {
		t.Errorf("Wrong string path: %s", path)
	}
}
func TestServeMux_ParamPrecedenceParamExtraction(t *testing.T) {
	s := NewServeMux()
	var called bool
	var param string
	rightHandler := http.HandlerFunc(func(rw http.ResponseWriter, req *http.Request) {
		called = true
		param = PathParam(req, "id")
	})
	s.Route("/users/:id/info").Get(wrongHandler)
	s.Route("/users/jim/info").Get(rightHandler)
	s.Route("/users/:id/detail").Get(wrongHandler)
	req := httptest.NewRequest(http.MethodGet, "/users/jim/info", nil)
	s.ServeHTTP(nil, req)
	if !called {
		t.Error("None or wrong handler was called")
	}
	if param != "" {
		t.Error("Wrong path param returned")
	}
}
func TestServeMux_WildcardPrecedence(t *testing.T) {
	s := NewServeMux()
	s.Route("/users/*").Get(wrongHandler)
	s.Route("/users/john").Get(rightHandler)
	req := httptest.NewRequest(http.MethodGet, "/users/john", nil)
	h, path := s.Handler(req)
	if h != rightHandler {
		t.Error("Wrong handler returned")
	}
	if path != "/users/john" {
		t.Errorf("Wrong string path: %s", path)
	}
}
func TestServeMux_WildcardPathPrecedence(t *testing.T) {
	s := NewServeMux()
	s.Route("/users/*").Get(wrongHandler)
	s.Route("/users/:id").Get(rightHandler)
	req := httptest.NewRequest(http.MethodGet, "/users/john", nil)
	h, path := s.Handler(req)
	if h != rightHandler {
		t.Error("Wrong handler returned")
	}
	if path != "/users/:id" {
		t.Errorf("Wrong string path: %s", path)
	}
}
func TestServeMux_WildcardPathPrecedenceParamExtraction(t *testing.T) {
	s := NewServeMux()
	var called bool
	var param string
	rightHandler := http.HandlerFunc(func(rw http.ResponseWriter, req *http.Request) {
		called = true
		param = PathParam(req, "id")
	})
	s.Route("/users/*").Get(wrongHandler)
	s.Route("/users/:id").Get(rightHandler)
	req := httptest.NewRequest(http.MethodGet, "/users/john", nil)
	s.ServeHTTP(nil, req)
	if !called {
		t.Error("None or wrong handler was called")
	}
	if param != "john" {
		t.Error("Wrong path param returned")
	}
}
func TestServeMux_RedirectSlash(t *testing.T) {
	s := NewServeMux()
	req := httptest.NewRequest(http.MethodGet, "/users/", nil)
	rec := httptest.NewRecorder()
	s.ServeHTTP(rec, req)
	if rec.Code != http.StatusPermanentRedirect {
		t.Error("Not redirected")
	}
	if rec.HeaderMap.Get("Location") != "/users" {
		t.Error("Mis-redirected")
	}
}
func TestServeMux_RedirectSlashPath(t *testing.T) {
	s := NewServeMux()
	req := httptest.NewRequest(http.MethodGet, "/users/", nil)
	_, path := s.Handler(req)
	if path != "/users" {
		t.Error("Path not corrected")
	}
}
func TestServeMux_RedirectRoot(t *testing.T) {
	s := NewServeMux()
	req := httptest.NewRequest(http.MethodGet, "/", nil)
	rec := httptest.NewRecorder()
	s.ServeHTTP(rec, req)
	if rec.Code == http.StatusPermanentRedirect {
		t.Error("Redirected")
	}
}
func TestServeMux_HandleCorrectRoute(t *testing.T) {
	s := NewServeMux()
	s.Route("/a").Get(rightHandler)
	s.Route("/b").Get(wrongHandler)
	req := httptest.NewRequest(http.MethodGet, "/a", nil)
	h, path := s.Handler(req)
	if h != rightHandler {
		t.Error("Wrong handler returned")
	}
	if path != "/a" {
		t.Errorf("Wrong string path: %s", path)
	}
}
func TestServeMux_HandleCorrectRouteAfterParam(t *testing.T) {
	s := NewServeMux()
	s.Route("/base/:id/a").Get(rightHandler)
	s.Route("/base/:id/b").Get(wrongHandler)
	req := httptest.NewRequest(http.MethodGet, "/base/llama/a", nil)
	h, path := s.Handler(req)
	if h != rightHandler {
		t.Error("Wrong handler retured")
	}
	if path != "/base/:id/a" {
		t.Errorf("Wrong string path: %s", path)
	}
}
func TestServeMux_HandleCorrectRouteAfterParamExtraction(t *testing.T) {
	s := NewServeMux()
	var called bool
	var param string
	rightHandler := http.HandlerFunc(func(rw http.ResponseWriter, req *http.Request) {
		called = true
		param = PathParam(req, "id")
	})
	s.Route("/base/:id/a").Get(rightHandler)
	s.Route("/base/:id/b").Get(wrongHandler)
	req := httptest.NewRequest(http.MethodGet, "/base/llama/a", nil)
	s.ServeHTTP(nil, req)
	if !called {
		t.Error("None or wrong handler was called")
	}
	if param != "llama" {
		t.Error("Wrong path param returned")
	}
}
func TestServeMux_HandleCorrectMethod(t *testing.T) {
	s := NewServeMux()
	s.Route("/a").Post(rightHandler)
	s.Route("/a").Get(wrongHandler)
	req := httptest.NewRequest(http.MethodPost, "/a", nil)
	h, path := s.Handler(req)
	if h != rightHandler {
		t.Error("Wrong handler returned")
	}
	if path != "/a" {
		t.Errorf("Wrong string path: %s", path)
	}
}
func TestServeMux_HandleCorrectMethodAny(t *testing.T) {
	s := NewServeMux()
	s.Route("/a").Post(wrongHandler)
	s.Route("/a").Get(wrongHandler)
	s.Route("/a").Any(rightHandler)
	req := httptest.NewRequest(http.MethodDelete, "/a", nil)
	h, path := s.Handler(req)
	if h != rightHandler {
		t.Error("Wrong handler returned")
	}
	if path != "/a" {
		t.Errorf("Wrong string path: %s", path)
	}
}
func TestServeMux_HandleCorrectMethodHead(t *testing.T) {
	s := NewServeMux()
	s.Route("/a").Post(wrongHandler)
	s.Route("/a").Get(rightHandler)
	req := httptest.NewRequest(http.MethodHead, "/a", nil)
	h, path := s.Handler(req)
	if h != rightHandler {
		t.Error("Wrong handler returned")
	}
	if path != "/a" {
		t.Errorf("Wrong string path: %s", path)
	}
}
func TestServeMux_HandleWildcard(t *testing.T) {
	s := NewServeMux()
	s.Route("/a/*").Get(rightHandler)
	s.Route("/b").Get(wrongHandler)
	req := httptest.NewRequest(http.MethodGet, "/a/llama", nil)
	h, path := s.Handler(req)
	if h != rightHandler {
		t.Error("Wrong handler returned")
	}
	if path != "/a/*" {
		t.Errorf("Wrong string path: %s", path)
	}
}
func TestServeMux_HandleWildcardDepth(t *testing.T) {
	s := NewServeMux()
	s.Route("/a/*").Get(rightHandler)
	s.Route("/b").Get(wrongHandler)
	req := httptest.NewRequest(http.MethodGet, "/a/llama/4/5", nil)
	h, path := s.Handler(req)
	if h != rightHandler {
		t.Error("Wrong handler returned")
	}
	if path != "/a/*" {
		t.Errorf("Wrong string path: %s", path)
	}
}
func TestServeMux_HandleOrder(t *testing.T) {
	s := NewServeMux()
	s.Route("/a").Get(wrongHandler)
	s.Route("/b").Get(rightHandler)
	req := httptest.NewRequest(http.MethodGet, "/b", nil)
	h, path := s.Handler(req)
	if h != rightHandler {
		t.Error("Wrong handler returned")
	}
	if path != "/b" {
		t.Errorf("Wrong string path: %s", path)
	}
}
func TestServeMux_HandleOptionsAtDepth(t *testing.T) {
	s := NewServeMux()
	s.Route("/a").Options(rightHandler)
	s.Route("/a/b").Get(wrongHandler)
	req := httptest.NewRequest(http.MethodOptions, "/a/b", nil)
	h, path := s.Handler(req)
	if h != rightHandler {
		t.Error("Wrong handler returned")
	}
	if path != "/a/b" {
		t.Errorf("Wrong string path: %s", path)
	}
}
func TestServeMux_EncodedPathComponent(t *testing.T) {
	s := NewServeMux()
	s.Route("/users/:id/info").Get(rightHandler)
	req := httptest.NewRequest(http.MethodGet, "/users/ji%2Fm/info", nil)
	h, path := s.Handler(req)
	if h != rightHandler {
		t.Error("Wrong handler returned")
	}
	if path != "/users/:id/info" {
		t.Errorf("Wrong string path: %s", path)
	}
}