aboutsummaryrefslogtreecommitdiffstats
path: root/http/server_test.go
diff options
context:
space:
mode:
authorMarc Pervaz Boocha <mboocha@sudomsg.com>2025-08-02 20:55:11 +0530
committerMarc Pervaz Boocha <mboocha@sudomsg.com>2025-08-02 20:55:11 +0530
commitce6cf13c2d67c3368251d1eea5593198f5021330 (patch)
treed4c2347fd45fce395bf22a30e423697494d4284f /http/server_test.go
downloadkit-ce6cf13c2d67c3368251d1eea5593198f5021330.tar
kit-ce6cf13c2d67c3368251d1eea5593198f5021330.tar.gz
kit-ce6cf13c2d67c3368251d1eea5593198f5021330.tar.bz2
kit-ce6cf13c2d67c3368251d1eea5593198f5021330.tar.lz
kit-ce6cf13c2d67c3368251d1eea5593198f5021330.tar.xz
kit-ce6cf13c2d67c3368251d1eea5593198f5021330.tar.zst
kit-ce6cf13c2d67c3368251d1eea5593198f5021330.zip
Initial Commitv0.1.0
Diffstat (limited to 'http/server_test.go')
-rw-r--r--http/server_test.go159
1 files changed, 159 insertions, 0 deletions
diff --git a/http/server_test.go b/http/server_test.go
new file mode 100644
index 0000000..7138c73
--- /dev/null
+++ b/http/server_test.go
@@ -0,0 +1,159 @@
+package http_test
+
+import (
+ "context"
+ "io"
+ "net"
+ "net/http"
+ "strings"
+ "testing"
+ "time"
+
+ httpServer "go.sudomsg.com/kit/http"
+)
+
+// helper to find free TCP ports
+func newListener(tb testing.TB) net.Listener {
+ tb.Helper()
+
+ ln, err := net.Listen("tcp", "localhost:0")
+ if err != nil {
+ tb.Fatalf("failed to open listener: %v", err)
+ }
+ return ln
+}
+
+func TestOpenConfigListeners(t *testing.T) {
+ t.Parallel()
+ t.Run("successful config", func(t *testing.T) {
+ t.Parallel()
+ ctx := t.Context()
+
+ cfg := []httpServer.ServerConfig{
+ {Network: "tcp", Address: "localhost:0"},
+ {Network: "tcp", Address: "localhost:0"},
+ }
+
+ lns, err := httpServer.OpenConfigListners(ctx, cfg)
+ if err != nil {
+ t.Fatalf("unexpected error: %v", err)
+ }
+ defer lns.CloseAll()
+
+ if got := len(lns); got != len(cfg) {
+ t.Errorf("expected %d listeners, got %d", len(cfg), got)
+ }
+ })
+
+ t.Run("port conflict triggers cleanup", func(t *testing.T) {
+ t.Parallel()
+ ctx := t.Context()
+
+ conflict := newListener(t)
+ defer conflict.Close()
+
+ cfg := []httpServer.ServerConfig{
+ {Network: "tcp", Address: "localhost:0"},
+ {Network: "tcp", Address: conflict.Addr().String()}, // will fail
+ }
+
+ lns, err := httpServer.OpenConfigListners(ctx, cfg)
+ if err == nil {
+ defer lns.CloseAll()
+ t.Fatal("expected error due to conflict, got nil")
+ }
+ })
+}
+
+func TestCloseAll(t *testing.T) {
+ t.Run("closes all listeners", func(t *testing.T) {
+ t.Parallel()
+ ln1 := newListener(t)
+ ln2 := newListener(t)
+
+ ls := httpServer.Listeners{ln1, ln2}
+ err := ls.CloseAll()
+ if err != nil {
+ t.Errorf("unexpected error from CloseAll: %v", err)
+ }
+
+ for _, ln := range ls {
+ if _, err := ln.Accept(); err == nil {
+ t.Error("expected listener to be closed, but Accept succeeded")
+ }
+ }
+ })
+}
+
+func TestRunHTTPServers(t *testing.T) {
+ t.Parallel()
+ t.Run("basic serve and shutdown", func(t *testing.T) {
+ t.Parallel()
+ ctx := t.Context()
+ handler := http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
+ io.WriteString(w, "hello")
+ })
+
+ ln := newListener(t)
+ addr := ln.Addr().String()
+
+ ctx, cancel := context.WithCancel(ctx)
+ defer cancel()
+
+ go func() {
+ // Wait for server to be ready
+ time.Sleep(200 * time.Millisecond)
+
+ r, err := http.NewRequestWithContext(ctx, http.MethodGet, "http://"+addr, nil)
+ resp, err := http.DefaultClient.Do(r)
+ if err != nil {
+ t.Errorf("http.Do error: %v", err)
+ return
+ }
+ defer resp.Body.Close()
+
+ body, _ := io.ReadAll(resp.Body)
+ if got := strings.TrimSpace(string(body)); got != "hello" {
+ t.Errorf("unexpected response body: %q", got)
+ }
+
+ cancel() // shutdown the server
+ }()
+
+ err := httpServer.RunHTTPServers(ctx, httpServer.Listeners{ln}, handler)
+ if err != nil {
+ t.Fatalf("RunHTTPServers failed: %v", err)
+ }
+ })
+}
+
+func TestInvalidConfig(t *testing.T) {
+ t.Parallel()
+
+ tests := []struct {
+ name string
+ config httpServer.ServerConfig
+ }{
+ {
+ name: "invalid network",
+ config: httpServer.ServerConfig{Network: "invalid", Address: "localhost:0"},
+ },
+ {
+ name: "invalid address",
+ config: httpServer.ServerConfig{Network: "tcp", Address: "::::"},
+ },
+ }
+
+ for _, tt := range tests {
+ t.Run(tt.name, func(t *testing.T) {
+ t.Parallel()
+
+ ctx := t.Context()
+
+ _, err := httpServer.OpenConfigListners(ctx, []httpServer.ServerConfig{tt.config})
+ if err == nil {
+ t.Fatal("OpenConfigListners() expected error, got nil")
+ }
+ })
+ }
+}