160 lines
5.7 KiB
Go
160 lines
5.7 KiB
Go
package main
|
|
|
|
import (
|
|
"net/http"
|
|
"net/http/httptest"
|
|
"os"
|
|
"path/filepath"
|
|
"strings"
|
|
"testing"
|
|
)
|
|
|
|
func TestMapTileProxyFetchesAndCaches(t *testing.T) {
|
|
st := openTestStore(t)
|
|
defer st.Close()
|
|
|
|
requests := 0
|
|
upstream := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
|
|
requests++
|
|
if r.URL.Path != "/3/1/2.png" {
|
|
t.Fatalf("upstream path = %q, want /3/1/2.png", r.URL.Path)
|
|
}
|
|
w.Header().Set("Content-Type", "image/png")
|
|
_, _ = w.Write([]byte("tile-data"))
|
|
}))
|
|
defer upstream.Close()
|
|
|
|
row, err := st.CreateMapTileSource(mapTileSourceInput{Name: "Tiles", URLTemplate: upstream.URL + "/{z}/{x}/{y}.png", MaxZoom: 18, Enabled: true, ProxyEnabled: true})
|
|
if err != nil {
|
|
t.Fatalf("CreateMapTileSource() error = %v", err)
|
|
}
|
|
|
|
cacheDir := t.TempDir()
|
|
router := newRouter(webConfig{StaticDir: t.TempDir(), MapTileCacheDir: cacheDir}, st, nil, nil, nil, nil, nil, nil)
|
|
|
|
url := "/api/map/" + row.URLTemplateHash + "?x=1&y=2&z=3"
|
|
for i := 0; i < 2; i++ {
|
|
recorder := httptest.NewRecorder()
|
|
req := httptest.NewRequest(http.MethodGet, url, nil)
|
|
router.ServeHTTP(recorder, req)
|
|
if recorder.Code != http.StatusOK {
|
|
t.Fatalf("request %d status = %d, body = %s", i+1, recorder.Code, recorder.Body.String())
|
|
}
|
|
if recorder.Body.String() != "tile-data" {
|
|
t.Fatalf("request %d body = %q, want tile-data", i+1, recorder.Body.String())
|
|
}
|
|
}
|
|
if requests != 1 {
|
|
t.Fatalf("upstream requests = %d, want 1", requests)
|
|
}
|
|
|
|
cachePath := filepath.Join(cacheDir, row.URLTemplateHash, "3", "1", "2.tile")
|
|
data, err := os.ReadFile(cachePath)
|
|
if err != nil {
|
|
t.Fatalf("read cache file %s: %v", cachePath, err)
|
|
}
|
|
if string(data) != "tile-data" {
|
|
t.Fatalf("cache file = %q, want tile-data", string(data))
|
|
}
|
|
}
|
|
|
|
func TestMapTileProxyRejectsInvalidCoordinates(t *testing.T) {
|
|
st := openTestStore(t)
|
|
defer st.Close()
|
|
|
|
row, err := st.CreateMapTileSource(mapTileSourceInput{Name: "Tiles", URLTemplate: "https://tiles.example.com/{z}/{x}/{y}.png", MaxZoom: 3, Enabled: true, ProxyEnabled: true})
|
|
if err != nil {
|
|
t.Fatalf("CreateMapTileSource() error = %v", err)
|
|
}
|
|
|
|
router := newRouter(webConfig{StaticDir: t.TempDir(), MapTileCacheDir: t.TempDir()}, st, nil, nil, nil, nil, nil, nil)
|
|
|
|
cases := []string{
|
|
"/api/map/" + row.URLTemplateHash + "?y=0&z=0",
|
|
"/api/map/" + row.URLTemplateHash + "?x=-1&y=0&z=0",
|
|
"/api/map/" + row.URLTemplateHash + "?x=0&y=0&z=4",
|
|
"/api/map/" + row.URLTemplateHash + "?x=2&y=0&z=1",
|
|
}
|
|
for _, url := range cases {
|
|
recorder := httptest.NewRecorder()
|
|
req := httptest.NewRequest(http.MethodGet, url, nil)
|
|
router.ServeHTTP(recorder, req)
|
|
if recorder.Code != http.StatusBadRequest {
|
|
t.Fatalf("%s status = %d, want 400; body = %s", url, recorder.Code, recorder.Body.String())
|
|
}
|
|
}
|
|
}
|
|
|
|
func TestMapTileProxyUnknownAndDisabledSource(t *testing.T) {
|
|
st := openTestStore(t)
|
|
defer st.Close()
|
|
|
|
disabled, err := st.CreateMapTileSource(mapTileSourceInput{Name: "Disabled", URLTemplate: "https://disabled.example.com/{z}/{x}/{y}.png", MaxZoom: 3, Enabled: false})
|
|
if err != nil {
|
|
t.Fatalf("CreateMapTileSource(disabled) error = %v", err)
|
|
}
|
|
proxyDisabled, err := st.CreateMapTileSource(mapTileSourceInput{Name: "ProxyDisabled", URLTemplate: "https://proxy-disabled.example.com/{z}/{x}/{y}.png", MaxZoom: 3, Enabled: true, ProxyEnabled: false})
|
|
if err != nil {
|
|
t.Fatalf("CreateMapTileSource(proxy disabled) error = %v", err)
|
|
}
|
|
|
|
router := newRouter(webConfig{StaticDir: t.TempDir(), MapTileCacheDir: t.TempDir()}, st, nil, nil, nil, nil, nil, nil)
|
|
|
|
cases := []string{
|
|
"/api/map/not-a-hash?x=0&y=0&z=0",
|
|
"/api/map/aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa?x=0&y=0&z=0",
|
|
"/api/map/" + disabled.URLTemplateHash + "?x=0&y=0&z=0",
|
|
"/api/map/" + proxyDisabled.URLTemplateHash + "?x=0&y=0&z=0",
|
|
}
|
|
wantStatus := []int{http.StatusBadRequest, http.StatusNotFound, http.StatusNotFound, http.StatusNotFound}
|
|
for i, url := range cases {
|
|
recorder := httptest.NewRecorder()
|
|
req := httptest.NewRequest(http.MethodGet, url, nil)
|
|
router.ServeHTTP(recorder, req)
|
|
if recorder.Code != wantStatus[i] {
|
|
t.Fatalf("%s status = %d, want %d; body = %s", url, recorder.Code, wantStatus[i], recorder.Body.String())
|
|
}
|
|
}
|
|
}
|
|
|
|
func TestMapTileProxyUpstreamStatus(t *testing.T) {
|
|
st := openTestStore(t)
|
|
defer st.Close()
|
|
|
|
upstream := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
|
|
if strings.Contains(r.URL.Path, "/404/") {
|
|
http.NotFound(w, r)
|
|
return
|
|
}
|
|
http.Error(w, "upstream error", http.StatusInternalServerError)
|
|
}))
|
|
defer upstream.Close()
|
|
|
|
row404, err := st.CreateMapTileSource(mapTileSourceInput{Name: "NotFoundTiles", URLTemplate: upstream.URL + "/404/{z}/{x}/{y}.png", MaxZoom: 18, Enabled: true, ProxyEnabled: true})
|
|
if err != nil {
|
|
t.Fatalf("CreateMapTileSource(404) error = %v", err)
|
|
}
|
|
row500, err := st.CreateMapTileSource(mapTileSourceInput{Name: "StatusTiles", URLTemplate: upstream.URL + "/{z}/{x}/{y}.png", MaxZoom: 18, Enabled: true, ProxyEnabled: true})
|
|
if err != nil {
|
|
t.Fatalf("CreateMapTileSource(500) error = %v", err)
|
|
}
|
|
|
|
router := newRouter(webConfig{StaticDir: t.TempDir(), MapTileCacheDir: t.TempDir()}, st, nil, nil, nil, nil, nil, nil)
|
|
|
|
cases := []struct {
|
|
url string
|
|
want int
|
|
}{
|
|
{url: "/api/map/" + row404.URLTemplateHash + "?x=0&y=0&z=0", want: http.StatusNotFound},
|
|
{url: "/api/map/" + row500.URLTemplateHash + "?x=0&y=0&z=0", want: http.StatusBadGateway},
|
|
}
|
|
for _, tc := range cases {
|
|
recorder := httptest.NewRecorder()
|
|
req := httptest.NewRequest(http.MethodGet, tc.url, nil)
|
|
router.ServeHTTP(recorder, req)
|
|
if recorder.Code != tc.want {
|
|
t.Fatalf("%s status = %d, want %d; body = %s", tc.url, recorder.Code, tc.want, recorder.Body.String())
|
|
}
|
|
}
|
|
}
|