Files
zip/zap_integration_test.go
T
zeekay c581e0af7b feat: zip canonical home — the ZAP-native web framework, consolidated
zip is shared protocol infra (the fiber-over-ZAP web framework used by every
Lux/Hanzo/Zoo Go binary — nodes, gateway, cloud, iam, kms, o11y, ai, …), so its
home is the ZAP protocol family (zap-proto/{go,http,zapd,zip}), NOT any one org's
brand namespace. This consolidates the rich framework (formerly hanzoai/zip v0.5.0
— Ctx/Handler/Errorf/Err*/HTTPError, typed handlers, middleware, runtime/extension
loading, openapi, validate, zaprpc) with the real ZAP transport (ListenZAP/
ListenHTTP/Serve over zap-proto/http) into ONE canonical module.

Module path github.com/hanzoai/zip -> github.com/zap-proto/zip. Code identical to
hanzoai/zip v0.5.0; promoted to v1.0.0 as the stable shared-infra framework. The
prior hanzoai/zip lineage is retired — one home, one import path, one way.

Verified: go build/vet/test ./... green; the ZAP round-trip integration test serves
/v1/health over the real ZAP transport (200 + handler JSON).
2026-07-01 23:08:35 -07:00

73 lines
2.1 KiB
Go

package zip_test
import (
"strings"
"testing"
"time"
"github.com/valyala/fasthttp"
zaphttp "github.com/zap-proto/http"
"github.com/zap-proto/zip"
)
// TestListenZAP_RoundTrip proves the un-stubbed ListenZAP actually SERVES: a
// route registered on the App answers a real request over the ZAP transport,
// with the same handler/JSON path as HTTP. (Replaces the old stub that returned
// "ZAP wire dispatch not yet implemented".)
func TestListenZAP_RoundTrip(t *testing.T) {
app := zip.New(zip.Config{AppName: "zaptest", DisableStartupMessage: true})
app.Get("/v1/health", func(c *zip.Ctx) error {
return c.JSON(200, map[string]string{"status": "ok", "transport": "zap"})
})
const addr = "127.0.0.1:19653"
go func() { _ = app.ListenZAP(addr) }()
defer func() { _ = app.Shutdown() }()
// Wait for the ZAP listener to accept (bounded).
waitReachable(t, addr)
req := fasthttp.AcquireRequest()
resp := fasthttp.AcquireResponse()
defer fasthttp.ReleaseRequest(req)
defer fasthttp.ReleaseResponse(resp)
req.SetRequestURI("/v1/health")
req.Header.SetMethod(fasthttp.MethodGet)
tr := zaphttp.NewTransport(addr)
defer tr.CloseIdleConnections()
if err := tr.Do(req, resp); err != nil {
t.Fatalf("ZAP round-trip failed: %v", err)
}
if resp.StatusCode() != 200 {
t.Fatalf("status = %d, want 200", resp.StatusCode())
}
body := string(resp.Body())
if !strings.Contains(body, `"status":"ok"`) || !strings.Contains(body, `"transport":"zap"`) {
t.Fatalf("body over ZAP = %q, want the handler's JSON", body)
}
}
func waitReachable(t *testing.T, addr string) {
t.Helper()
tr := zaphttp.NewTransport(addr)
tr.SetDialTimeout(200 * time.Millisecond)
defer tr.CloseIdleConnections()
for i := 0; i < 50; i++ {
req := fasthttp.AcquireRequest()
resp := fasthttp.AcquireResponse()
req.SetRequestURI("/v1/health")
req.Header.SetMethod(fasthttp.MethodGet)
err := tr.Do(req, resp)
fasthttp.ReleaseRequest(req)
fasthttp.ReleaseResponse(resp)
if err == nil {
return
}
time.Sleep(40 * time.Millisecond)
}
t.Fatalf("ZAP listener at %s never became reachable", addr)
}