Files
dingtalk-workspace-cli/internal/transport/diagnostics_test.go
2026-06-18 18:34:12 +08:00

145 lines
4.1 KiB
Go

package transport
import (
"encoding/json"
"net/http"
"testing"
)
func TestExtractServerDiagnostics_SnakeCase(t *testing.T) {
t.Parallel()
data := json.RawMessage(`{"trace_id":"abc123","code":"PARAM_ERROR","technical_detail":"field required","retryable":false}`)
diag := ExtractServerDiagnostics(data)
if diag.TraceID != "abc123" {
t.Fatalf("TraceID = %q, want abc123", diag.TraceID)
}
if diag.ServerErrorCode != "PARAM_ERROR" {
t.Fatalf("ServerErrorCode = %q, want PARAM_ERROR", diag.ServerErrorCode)
}
if diag.TechnicalDetail != "field required" {
t.Fatalf("TechnicalDetail = %q, want 'field required'", diag.TechnicalDetail)
}
if diag.ServerRetryable == nil || *diag.ServerRetryable != false {
t.Fatalf("ServerRetryable = %v, want false", diag.ServerRetryable)
}
}
func TestExtractServerDiagnostics_CamelCase(t *testing.T) {
t.Parallel()
data := json.RawMessage(`{"traceId":"xyz789","errorCode":"AUTH_ERROR"}`)
diag := ExtractServerDiagnostics(data)
if diag.TraceID != "xyz789" {
t.Fatalf("TraceID = %q, want xyz789", diag.TraceID)
}
if diag.ServerErrorCode != "AUTH_ERROR" {
t.Fatalf("ServerErrorCode = %q, want AUTH_ERROR", diag.ServerErrorCode)
}
}
func TestExtractServerDiagnostics_Empty(t *testing.T) {
t.Parallel()
diag := ExtractServerDiagnostics(nil)
if !diag.IsEmpty() {
t.Fatal("expected empty diagnostics for nil input")
}
diag = ExtractServerDiagnostics(json.RawMessage(`{}`))
if !diag.IsEmpty() {
t.Fatal("expected empty diagnostics for empty object")
}
}
func TestExtractServerDiagnostics_Malformed(t *testing.T) {
t.Parallel()
diag := ExtractServerDiagnostics(json.RawMessage(`not json`))
if !diag.IsEmpty() {
t.Fatal("expected empty diagnostics for malformed JSON")
}
}
func TestExtractServerDiagnosticsFromMap(t *testing.T) {
t.Parallel()
content := map[string]any{
"trace_id": "trace-001",
"code": "TIMEOUT_ERROR",
"technical_detail": "deadline exceeded",
"retryable": true,
}
diag := ExtractServerDiagnosticsFromMap(content)
if diag.TraceID != "trace-001" {
t.Fatalf("TraceID = %q, want trace-001", diag.TraceID)
}
if diag.ServerErrorCode != "TIMEOUT_ERROR" {
t.Fatalf("ServerErrorCode = %q, want TIMEOUT_ERROR", diag.ServerErrorCode)
}
if diag.ServerRetryable == nil || *diag.ServerRetryable != true {
t.Fatal("expected retryable=true")
}
}
func TestExtractServerDiagnosticsFromMapNestedBusinessCode(t *testing.T) {
t.Parallel()
content := map[string]any{
"trace_id": "trace-002",
"code": "BUSINESS_ERROR",
"result": map[string]any{
"success": false,
"errorCode": "ROBOT_NOT_FOUND",
"errorMsg": "robot info is not exist",
},
}
diag := ExtractServerDiagnosticsFromMap(content)
if diag.TraceID != "trace-002" {
t.Fatalf("TraceID = %q, want trace-002", diag.TraceID)
}
if diag.ServerErrorCode != "ROBOT_NOT_FOUND" {
t.Fatalf("ServerErrorCode = %q, want ROBOT_NOT_FOUND", diag.ServerErrorCode)
}
}
func TestExtractServerDiagnosticsFromMap_Empty(t *testing.T) {
t.Parallel()
diag := ExtractServerDiagnosticsFromMap(nil)
if !diag.IsEmpty() {
t.Fatal("expected empty for nil map")
}
}
func TestExtractTraceIDFromHeaders(t *testing.T) {
t.Parallel()
tests := []struct {
name string
headers http.Header
want string
}{
{"x-trace-id", http.Header{"X-Trace-Id": {"abc"}}, "abc"},
{"x-request-id", http.Header{"X-Request-Id": {"def"}}, "def"},
{"dingtalk", http.Header{"X-Dingtalk-Trace-Id": {"ghi"}}, "ghi"},
{"priority", http.Header{
"X-Trace-Id": {"first"},
"X-Dingtalk-Trace-Id": {"second"},
}, "first"},
{"empty", http.Header{}, ""},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
t.Parallel()
if got := ExtractTraceIDFromHeaders(tt.headers); got != tt.want {
t.Fatalf("got %q, want %q", got, tt.want)
}
})
}
}
func TestCoalesceStr(t *testing.T) {
t.Parallel()
if got := coalesceStr("", "b"); got != "b" {
t.Fatalf("got %q, want b", got)
}
if got := coalesceStr("a", "b"); got != "a" {
t.Fatalf("got %q, want a", got)
}
if got := coalesceStr("", ""); got != "" {
t.Fatalf("got %q, want empty", got)
}
}