feat: complete API-driven projects with infrastructure and business acceptance
This commit is contained in:
@@ -4,8 +4,11 @@ import (
|
||||
"bytes"
|
||||
"encoding/json"
|
||||
"errors"
|
||||
"io"
|
||||
"net/http/httptest"
|
||||
"strings"
|
||||
"testing"
|
||||
"time"
|
||||
|
||||
apierrors "git.yuntuo.hk/k2safe/go-omni/errors"
|
||||
"git.yuntuo.hk/k2safe/go-omni/httpx"
|
||||
@@ -42,12 +45,19 @@ func TestAccessLogReportsCommittedStatus(t *testing.T) {
|
||||
ctx.WriteError(err)
|
||||
}
|
||||
var entry struct {
|
||||
Message string `json:"msg"`
|
||||
Status int
|
||||
Route string
|
||||
RequestID string `json:"requestId"`
|
||||
}
|
||||
if err := json.Unmarshal(output.Bytes(), &entry); err != nil {
|
||||
t.Fatal(err)
|
||||
decoder := json.NewDecoder(&output)
|
||||
for {
|
||||
if err := decoder.Decode(&entry); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
if entry.Message == "http.request" {
|
||||
break
|
||||
}
|
||||
}
|
||||
if entry.Status != tc.status || w.Code != tc.status || entry.Route != "/users/:id" || entry.RequestID != "logRequest" {
|
||||
t.Fatalf("log=%s response=%d; expected status %d and request metadata", &output, w.Code, tc.status)
|
||||
@@ -86,3 +96,48 @@ func TestAccessLogUsesVerifiedClientIP(t *testing.T) {
|
||||
t.Fatalf("expected verified client IP, got %q", entry.ClientIP)
|
||||
}
|
||||
}
|
||||
|
||||
func TestSlowAndPanicLogs(t *testing.T) {
|
||||
var out bytes.Buffer
|
||||
logger, _ := logx.New(logx.Config{Writer: &out})
|
||||
logx.SetDefault(logger)
|
||||
defer logx.SetDefault(nil)
|
||||
ctx := httpx.NewContext(httptest.NewRequest("GET", "/panic?secret=hidden", nil), httptest.NewRecorder(), nil)
|
||||
chain := middleware.RequestID("X-Request-ID")(middleware.AccessLog(middleware.WithSlowRequestThreshold(time.Nanosecond))(middleware.Recovery()(func(c *httpx.Context) error { panic("boom") })))
|
||||
err := chain(ctx)
|
||||
if err == nil {
|
||||
t.Fatal("panic not recovered")
|
||||
}
|
||||
decoder := json.NewDecoder(&out)
|
||||
count := 0
|
||||
for {
|
||||
var entry map[string]any
|
||||
err := decoder.Decode(&entry)
|
||||
if err == io.EOF {
|
||||
break
|
||||
}
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
count++
|
||||
if entry["requestId"] == "" || entry["level"] != "ERROR" {
|
||||
t.Fatal(entry)
|
||||
}
|
||||
if entry["msg"] == "http.panic" && !strings.Contains(entry["stack"].(string), "TestSlowAndPanicLogs") {
|
||||
t.Fatal(entry)
|
||||
}
|
||||
if entry["msg"] == "http.request" && (entry["slow"] != true || entry["status"] != float64(500)) {
|
||||
t.Fatal(entry)
|
||||
}
|
||||
}
|
||||
if count != 2 {
|
||||
t.Fatal(count)
|
||||
}
|
||||
out.Reset()
|
||||
ctx = httpx.NewContext(httptest.NewRequest("GET", "/slow", nil), httptest.NewRecorder(), nil)
|
||||
err = middleware.AccessLog(middleware.WithSlowRequestThreshold(time.Nanosecond))(func(c *httpx.Context) error { return c.OK("done") })(ctx)
|
||||
var entry map[string]any
|
||||
if err != nil || json.Unmarshal(out.Bytes(), &entry) != nil || entry["level"] != "WARN" || entry["slow"] != true {
|
||||
t.Fatal(out.String(), err)
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user