mirror of
https://github.com/sipeed/picoclaw.git
synced 2026-06-12 18:08:54 +00:00
f1cb7cc8f5
* fix gateway reload will cause pico stop working issue * fix for review
163 lines
4.3 KiB
Go
163 lines
4.3 KiB
Go
package channels
|
|
|
|
import (
|
|
"net/http"
|
|
"net/http/httptest"
|
|
"sync"
|
|
"testing"
|
|
)
|
|
|
|
func TestDynamicServeMuxExactMatch(t *testing.T) {
|
|
dm := newDynamicServeMux()
|
|
dm.HandleFunc("/health", func(w http.ResponseWriter, r *http.Request) {
|
|
w.WriteHeader(http.StatusOK)
|
|
})
|
|
|
|
rec := httptest.NewRecorder()
|
|
dm.ServeHTTP(rec, httptest.NewRequest(http.MethodGet, "/health", nil))
|
|
if rec.Code != http.StatusOK {
|
|
t.Fatalf("expected 200, got %d", rec.Code)
|
|
}
|
|
}
|
|
|
|
func TestDynamicServeMuxSubtreePrefixMatch(t *testing.T) {
|
|
dm := newDynamicServeMux()
|
|
dm.HandleFunc("/api/", func(w http.ResponseWriter, r *http.Request) {
|
|
w.WriteHeader(http.StatusCreated)
|
|
})
|
|
|
|
for _, path := range []string{"/api/", "/api/v1", "/api/v1/resource"} {
|
|
rec := httptest.NewRecorder()
|
|
dm.ServeHTTP(rec, httptest.NewRequest(http.MethodGet, path, nil))
|
|
if rec.Code != http.StatusCreated {
|
|
t.Fatalf("path %q: expected 201, got %d", path, rec.Code)
|
|
}
|
|
}
|
|
}
|
|
|
|
func TestDynamicServeMuxExactOverPrefix(t *testing.T) {
|
|
dm := newDynamicServeMux()
|
|
dm.HandleFunc("/api", func(w http.ResponseWriter, r *http.Request) {
|
|
w.WriteHeader(http.StatusOK)
|
|
})
|
|
dm.HandleFunc("/api/", func(w http.ResponseWriter, r *http.Request) {
|
|
w.WriteHeader(http.StatusCreated)
|
|
})
|
|
|
|
// Exact match wins
|
|
rec := httptest.NewRecorder()
|
|
dm.ServeHTTP(rec, httptest.NewRequest(http.MethodGet, "/api", nil))
|
|
if rec.Code != http.StatusOK {
|
|
t.Fatalf("exact match: expected 200, got %d", rec.Code)
|
|
}
|
|
|
|
// Prefix match for sub-paths
|
|
rec = httptest.NewRecorder()
|
|
dm.ServeHTTP(rec, httptest.NewRequest(http.MethodGet, "/api/v1", nil))
|
|
if rec.Code != http.StatusCreated {
|
|
t.Fatalf("prefix match: expected 201, got %d", rec.Code)
|
|
}
|
|
}
|
|
|
|
func TestDynamicServeMuxLongestPrefixWins(t *testing.T) {
|
|
dm := newDynamicServeMux()
|
|
dm.HandleFunc("/a/", func(w http.ResponseWriter, r *http.Request) {
|
|
w.WriteHeader(http.StatusOK)
|
|
})
|
|
dm.HandleFunc("/a/b/", func(w http.ResponseWriter, r *http.Request) {
|
|
w.WriteHeader(http.StatusAccepted)
|
|
})
|
|
|
|
rec := httptest.NewRecorder()
|
|
dm.ServeHTTP(rec, httptest.NewRequest(http.MethodGet, "/a/b/c", nil))
|
|
if rec.Code != http.StatusAccepted {
|
|
t.Fatalf("longest prefix: expected 202, got %d", rec.Code)
|
|
}
|
|
}
|
|
|
|
func TestDynamicServeMuxNotFound(t *testing.T) {
|
|
dm := newDynamicServeMux()
|
|
rec := httptest.NewRecorder()
|
|
dm.ServeHTTP(rec, httptest.NewRequest(http.MethodGet, "/nonexistent", nil))
|
|
if rec.Code != http.StatusNotFound {
|
|
t.Fatalf("expected 404, got %d", rec.Code)
|
|
}
|
|
}
|
|
|
|
func TestDynamicServeMuxUnhandle(t *testing.T) {
|
|
dm := newDynamicServeMux()
|
|
dm.HandleFunc("/test", func(w http.ResponseWriter, r *http.Request) {
|
|
w.WriteHeader(http.StatusOK)
|
|
})
|
|
|
|
// Verify it works before removal
|
|
rec := httptest.NewRecorder()
|
|
dm.ServeHTTP(rec, httptest.NewRequest(http.MethodGet, "/test", nil))
|
|
if rec.Code != http.StatusOK {
|
|
t.Fatalf("before unhandle: expected 200, got %d", rec.Code)
|
|
}
|
|
|
|
// Remove and verify 404
|
|
dm.Unhandle("/test")
|
|
rec = httptest.NewRecorder()
|
|
dm.ServeHTTP(rec, httptest.NewRequest(http.MethodGet, "/test", nil))
|
|
if rec.Code != http.StatusNotFound {
|
|
t.Fatalf("after unhandle: expected 404, got %d", rec.Code)
|
|
}
|
|
}
|
|
|
|
func TestDynamicServeMuxConcurrent(t *testing.T) {
|
|
dm := newDynamicServeMux()
|
|
dm.HandleFunc("/static", func(w http.ResponseWriter, r *http.Request) {
|
|
w.WriteHeader(http.StatusOK)
|
|
})
|
|
|
|
var wg sync.WaitGroup
|
|
const goroutines = 50
|
|
|
|
// Concurrent Handle/Unhandle
|
|
for i := 0; i < goroutines; i++ {
|
|
wg.Add(1)
|
|
go func(i int) {
|
|
defer wg.Done()
|
|
pattern := "/concurrent"
|
|
if i%2 == 0 {
|
|
dm.HandleFunc(pattern, func(w http.ResponseWriter, r *http.Request) {
|
|
w.WriteHeader(http.StatusAccepted)
|
|
})
|
|
} else {
|
|
dm.Unhandle(pattern)
|
|
}
|
|
}(i)
|
|
}
|
|
|
|
// Concurrent ServeHTTP
|
|
for i := 0; i < goroutines; i++ {
|
|
wg.Add(1)
|
|
go func() {
|
|
defer wg.Done()
|
|
rec := httptest.NewRecorder()
|
|
dm.ServeHTTP(rec, httptest.NewRequest(http.MethodGet, "/static", nil))
|
|
// Should not panic; result is either 200 or 404
|
|
_ = rec.Code
|
|
}()
|
|
}
|
|
|
|
wg.Wait()
|
|
}
|
|
|
|
func TestDynamicServeMuxHandleUsesHandler(t *testing.T) {
|
|
dm := newDynamicServeMux()
|
|
|
|
var called bool
|
|
dm.Handle("/handler", http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
|
|
called = true
|
|
}))
|
|
|
|
rec := httptest.NewRecorder()
|
|
dm.ServeHTTP(rec, httptest.NewRequest(http.MethodGet, "/handler", nil))
|
|
if !called {
|
|
t.Fatal("handler was not called")
|
|
}
|
|
}
|