docs(ctx): add doc comments, remove dead WithContext interface, simplify HashFromContext

Remove unused WithContext interface (zero references in codebase), add
doc comments for all 14 exported symbols, and simplify HashFromContext
to match the one-liner pattern used by the other four getters.
Add 22 unit tests covering round-trip, empty context, wrong type, nil
values, multiple values, independent keys, and the Context interface.
This commit is contained in:
ginuerzh
2026-05-24 14:26:45 +08:00
parent 4efb4b9974
commit 419f4c4c73
2 changed files with 237 additions and 16 deletions
+211
View File
@@ -0,0 +1,211 @@
package ctx
import (
"context"
"net"
"testing"
)
func TestContextWithSrcAddr(t *testing.T) {
addr := &net.TCPAddr{IP: net.ParseIP("10.0.0.1"), Port: 8080}
ctx := ContextWithSrcAddr(context.Background(), addr)
got := SrcAddrFromContext(ctx)
if got != addr {
t.Errorf("SrcAddrFromContext() = %v, want %v", got, addr)
}
}
func TestSrcAddrFromContext_Empty(t *testing.T) {
if got := SrcAddrFromContext(context.Background()); got != nil {
t.Errorf("SrcAddrFromContext(empty) = %v, want nil", got)
}
}
func TestSrcAddrFromContext_WrongType(t *testing.T) {
ctx := context.WithValue(context.Background(), srcAddrKey{}, "not-an-addr")
if got := SrcAddrFromContext(ctx); got != nil {
t.Errorf("SrcAddrFromContext(wrong type) = %v, want nil", got)
}
}
func TestSrcAddrFromContext_NilAddr(t *testing.T) {
ctx := ContextWithSrcAddr(context.Background(), nil)
if got := SrcAddrFromContext(ctx); got != nil {
t.Errorf("SrcAddrFromContext(nil addr) = %v, want nil", got)
}
}
func TestContextWithDstAddr(t *testing.T) {
addr := &net.TCPAddr{IP: net.ParseIP("192.168.1.1"), Port: 443}
ctx := ContextWithDstAddr(context.Background(), addr)
got := DstAddrFromContext(ctx)
if got != addr {
t.Errorf("DstAddrFromContext() = %v, want %v", got, addr)
}
}
func TestDstAddrFromContext_Empty(t *testing.T) {
if got := DstAddrFromContext(context.Background()); got != nil {
t.Errorf("DstAddrFromContext(empty) = %v, want nil", got)
}
}
func TestDstAddrFromContext_NilAddr(t *testing.T) {
ctx := ContextWithDstAddr(context.Background(), nil)
if got := DstAddrFromContext(ctx); got != nil {
t.Errorf("DstAddrFromContext(nil addr) = %v, want nil", got)
}
}
func TestSid_String(t *testing.T) {
sid := Sid("session-123")
if s := sid.String(); s != "session-123" {
t.Errorf("Sid.String() = %q, want %q", s, "session-123")
}
}
func TestContextWithSid(t *testing.T) {
sid := Sid("abc-123")
ctx := ContextWithSid(context.Background(), sid)
got := SidFromContext(ctx)
if got != sid {
t.Errorf("SidFromContext() = %v, want %v", got, sid)
}
}
func TestSidFromContext_Empty(t *testing.T) {
if got := SidFromContext(context.Background()); got != "" {
t.Errorf("SidFromContext(empty) = %q, want empty string", got)
}
}
func TestSidFromContext_WrongType(t *testing.T) {
ctx := context.WithValue(context.Background(), sidKey{}, 42)
if got := SidFromContext(ctx); got != "" {
t.Errorf("SidFromContext(wrong type) = %q, want empty string", got)
}
}
func TestContextWithHash(t *testing.T) {
h := &Hash{Source: "client-ip"}
ctx := ContextWithHash(context.Background(), h)
got := HashFromContext(ctx)
if got != h {
t.Errorf("HashFromContext() = %v, want %v", got, h)
}
}
func TestHashFromContext_Empty(t *testing.T) {
if got := HashFromContext(context.Background()); got != nil {
t.Errorf("HashFromContext(empty) = %v, want nil", got)
}
}
func TestHashFromContext_WrongType(t *testing.T) {
ctx := context.WithValue(context.Background(), hashKey{}, "not-a-hash")
if got := HashFromContext(ctx); got != nil {
t.Errorf("HashFromContext(wrong type) = %v, want nil", got)
}
}
func TestHashFromContext_NilHash(t *testing.T) {
ctx := ContextWithHash(context.Background(), nil)
if got := HashFromContext(ctx); got != nil {
t.Errorf("HashFromContext(nil hash) = %v, want nil", got)
}
}
func TestClientID_String(t *testing.T) {
cid := ClientID("client-456")
if s := cid.String(); s != "client-456" {
t.Errorf("ClientID.String() = %q, want %q", s, "client-456")
}
}
func TestContextWithClientID(t *testing.T) {
cid := ClientID("user-789")
ctx := ContextWithClientID(context.Background(), cid)
got := ClientIDFromContext(ctx)
if got != cid {
t.Errorf("ClientIDFromContext() = %v, want %v", got, cid)
}
}
func TestClientIDFromContext_Empty(t *testing.T) {
if got := ClientIDFromContext(context.Background()); got != "" {
t.Errorf("ClientIDFromContext(empty) = %q, want empty string", got)
}
}
func TestClientIDFromContext_WrongType(t *testing.T) {
ctx := context.WithValue(context.Background(), clientIDKey{}, 99)
if got := ClientIDFromContext(ctx); got != "" {
t.Errorf("ClientIDFromContext(wrong type) = %q, want empty string", got)
}
}
func TestMultipleValuesInContext(t *testing.T) {
ctx := context.Background()
ctx = ContextWithSrcAddr(ctx, &net.TCPAddr{IP: net.ParseIP("10.0.0.1"), Port: 8080})
ctx = ContextWithDstAddr(ctx, &net.TCPAddr{IP: net.ParseIP("192.168.1.1"), Port: 443})
ctx = ContextWithSid(ctx, Sid("multi-session"))
ctx = ContextWithHash(ctx, &Hash{Source: "hash-src"})
ctx = ContextWithClientID(ctx, ClientID("multi-client"))
if got := SrcAddrFromContext(ctx); got == nil {
t.Error("SrcAddrFromContext() should not be nil")
}
if got := DstAddrFromContext(ctx); got == nil {
t.Error("DstAddrFromContext() should not be nil")
}
if got := SidFromContext(ctx); got != "multi-session" {
t.Errorf("SidFromContext() = %q, want %q", got, "multi-session")
}
if got := HashFromContext(ctx); got == nil || got.Source != "hash-src" {
t.Errorf("HashFromContext().Source = %v, want %q", got, "hash-src")
}
if got := ClientIDFromContext(ctx); got != "multi-client" {
t.Errorf("ClientIDFromContext() = %q, want %q", got, "multi-client")
}
}
func TestIndependentKeys(t *testing.T) {
ctx := ContextWithSrcAddr(context.Background(), &net.TCPAddr{IP: net.ParseIP("10.0.0.1"), Port: 8080})
// Other keys should not be affected.
if got := SidFromContext(ctx); got != "" {
t.Errorf("SidFromContext() = %q, want empty after setting SrcAddr", got)
}
if got := HashFromContext(ctx); got != nil {
t.Errorf("HashFromContext() = %v, want nil after setting SrcAddr", got)
}
}
type testContextConn struct {
ctx context.Context
}
func (c *testContextConn) Context() context.Context {
return c.ctx
}
func TestContextInterface(t *testing.T) {
ctx := context.Background()
ctx = ContextWithSid(ctx, Sid("iface-test"))
conn := &testContextConn{ctx: ctx}
cc, ok := any(conn).(Context)
if !ok {
t.Fatal("testContextConn should implement Context interface")
}
inner := cc.Context()
if got := SidFromContext(inner); got != "iface-test" {
t.Errorf("SidFromContext(inner) = %q, want %q", got, "iface-test")
}
}