Modernizes several `internal/*` packages under the Go proxy, replaces
third-party forks with standard-library primitives, and brings the
test suite from near-zero to high coverage across the touched packages.
Package changes
- **`internal/errors`** — Rewrites the `pkg/errors` fork as a thin
wrapper
over stdlib `errors`. A single `withStack` struct captures stack
traces via `runtime.Callers`; `fmt.Errorf("%w", ...)` handles all
message wrapping. Restores `errors.Is`/`As`/`Unwrap` chain traversal
(silently broken in the fork) and deletes ~190 lines of stack/frame
formatting. `Is`, `As`, `Unwrap`, and `Join` are re-exported so
callers need a single import.
- **`internal/logger`** — Swaps stdlib `log.Logger` for `log/slog` JSON
handlers with UTC timestamps and custom level labels (`verb`, `debug`,
`warn`, `error`). Hides `withContextID` (no external callers).
- **`internal/sync`** — Converts `Map[K, V]` from a concrete struct to
an interface with a `NewMap` constructor for testability.
- **`internal/signal`** — Adds `signalNotify` / `osExit` indirections so
`InstallSignals` and `InstallForceQuit` can be exercised without real
OS signals or process termination.
- **`internal/utils`** — Drops deprecated `io/ioutil` and the stdlib
`errors` alias (the internal `errors` package re-exports what's
needed).
- **`internal/version`** — No code changes; fully covered by new tests.
---------
Co-authored-by: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
83 lines
2.1 KiB
Go
83 lines
2.1 KiB
Go
// Copyright (c) 2026 Winlin
|
|
//
|
|
// SPDX-License-Identifier: MIT
|
|
package logger
|
|
|
|
import (
|
|
"context"
|
|
"encoding/hex"
|
|
"testing"
|
|
)
|
|
|
|
func TestGenerateContextID_LengthAndHex(t *testing.T) {
|
|
cid := GenerateContextID()
|
|
if len(cid) != 7 {
|
|
t.Fatalf("len(cid) = %d, want 7", len(cid))
|
|
}
|
|
if _, err := hex.DecodeString(cid + "0"); err != nil {
|
|
t.Fatalf("cid %q is not hex: %v", cid, err)
|
|
}
|
|
}
|
|
|
|
func TestGenerateContextID_Unique(t *testing.T) {
|
|
seen := make(map[string]struct{}, 1000)
|
|
for i := range 1000 {
|
|
cid := GenerateContextID()
|
|
if _, dup := seen[cid]; dup {
|
|
t.Fatalf("duplicate cid %q at iteration %d", cid, i)
|
|
}
|
|
seen[cid] = struct{}{}
|
|
}
|
|
}
|
|
|
|
func TestWithContext_AttachesCID(t *testing.T) {
|
|
ctx := WithContext(context.Background())
|
|
cid := ContextID(ctx)
|
|
if len(cid) != 7 {
|
|
t.Fatalf("ContextID length = %d, want 7", len(cid))
|
|
}
|
|
}
|
|
|
|
func TestWithContext_IndependentCIDs(t *testing.T) {
|
|
c1 := WithContext(context.Background())
|
|
c2 := WithContext(context.Background())
|
|
if ContextID(c1) == ContextID(c2) {
|
|
t.Fatalf("expected distinct cids, got %q twice", ContextID(c1))
|
|
}
|
|
}
|
|
|
|
func TestContextID_Missing(t *testing.T) {
|
|
if got := ContextID(context.Background()); got != "" {
|
|
t.Fatalf("ContextID on empty ctx = %q, want \"\"", got)
|
|
}
|
|
}
|
|
|
|
func TestContextID_WrongTypeReturnsEmpty(t *testing.T) {
|
|
ctx := context.WithValue(context.Background(), cidKey, 42)
|
|
if got := ContextID(ctx); got != "" {
|
|
t.Fatalf("ContextID with int value = %q, want \"\"", got)
|
|
}
|
|
}
|
|
|
|
func TestWithContextID_RoundTrip(t *testing.T) {
|
|
ctx := withContextID(context.Background(), "abcdef1")
|
|
if got := ContextID(ctx); got != "abcdef1" {
|
|
t.Fatalf("ContextID = %q, want %q", got, "abcdef1")
|
|
}
|
|
}
|
|
|
|
func TestWithContextID_Overwrite(t *testing.T) {
|
|
ctx := withContextID(context.Background(), "first00")
|
|
ctx = withContextID(ctx, "second1")
|
|
if got := ContextID(ctx); got != "second1" {
|
|
t.Fatalf("ContextID after overwrite = %q, want %q", got, "second1")
|
|
}
|
|
}
|
|
|
|
func TestCIDKey_NotCollidingWithPlainString(t *testing.T) {
|
|
ctx := context.WithValue(context.Background(), string(cidKey), "plain")
|
|
if got := ContextID(ctx); got != "" {
|
|
t.Fatalf("ContextID leaked through string key = %q, want \"\"", got)
|
|
}
|
|
}
|