add tests for proxy.Process
This commit is contained in:
5
Makefile
5
Makefile
@@ -22,10 +22,11 @@ linux:
|
|||||||
@echo "Building Linux binary..."
|
@echo "Building Linux binary..."
|
||||||
GOOS=linux GOARCH=amd64 go build -o $(BUILD_DIR)/$(APP_NAME)-linux-amd64
|
GOOS=linux GOARCH=amd64 go build -o $(BUILD_DIR)/$(APP_NAME)-linux-amd64
|
||||||
|
|
||||||
# for testing things
|
# for testing proxy.Process
|
||||||
simple-responder:
|
simple-responder:
|
||||||
@echo "Building simple responder"
|
@echo "Building simple responder"
|
||||||
go build -o $(BUILD_DIR)/simple-responder misc/simple-responder/simple-responder.go
|
GOOS=darwin GOARCH=arm64 go build -o $(BUILD_DIR)/simple-responder_darwin_arm64 misc/simple-responder/simple-responder.go
|
||||||
|
GOOS=linux GOARCH=amd64 go build -o $(BUILD_DIR)/simple-responder_linux_amd64 misc/simple-responder/simple-responder.go
|
||||||
|
|
||||||
# Ensure build directory exists
|
# Ensure build directory exists
|
||||||
$(BUILD_DIR):
|
$(BUILD_DIR):
|
||||||
|
|||||||
@@ -39,7 +39,7 @@ func main() {
|
|||||||
w.Write([]byte(response))
|
w.Write([]byte(response))
|
||||||
})
|
})
|
||||||
|
|
||||||
address := ":" + *port // Address with the specified port
|
address := "127.0.0.1:" + *port // Address with the specified port
|
||||||
fmt.Printf("Server is listening on port %s\n", *port)
|
fmt.Printf("Server is listening on port %s\n", *port)
|
||||||
|
|
||||||
// Start the server and log any error if it occurs
|
// Start the server and log any error if it occurs
|
||||||
|
|||||||
@@ -38,7 +38,6 @@ func (pm *ProxyManager) HandleFunc(w http.ResponseWriter, r *http.Request) {
|
|||||||
} else {
|
} else {
|
||||||
http.Error(w, "no strategy to handle request", http.StatusBadRequest)
|
http.Error(w, "no strategy to handle request", http.StatusBadRequest)
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -21,6 +21,10 @@ type Process struct {
|
|||||||
config ModelConfig
|
config ModelConfig
|
||||||
cmd *exec.Cmd
|
cmd *exec.Cmd
|
||||||
logMonitor *LogMonitor
|
logMonitor *LogMonitor
|
||||||
|
|
||||||
|
// Only useful for go testing the proxy functionality
|
||||||
|
// will leave the start/stop of process to go code
|
||||||
|
overrideProxyFunc *func(w http.ResponseWriter, r *http.Request)
|
||||||
}
|
}
|
||||||
|
|
||||||
func NewProcess(ID string, config ModelConfig, logMonitor *LogMonitor) *Process {
|
func NewProcess(ID string, config ModelConfig, logMonitor *LogMonitor) *Process {
|
||||||
@@ -115,6 +119,7 @@ func (p *Process) checkHealthEndpoint(cmdCtx context.Context, healthCheckTimeout
|
|||||||
startTime := time.Now()
|
startTime := time.Now()
|
||||||
|
|
||||||
for {
|
for {
|
||||||
|
time.Sleep(time.Second)
|
||||||
req, err := http.NewRequest("GET", healthURL, nil)
|
req, err := http.NewRequest("GET", healthURL, nil)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
@@ -141,7 +146,6 @@ func (p *Process) checkHealthEndpoint(cmdCtx context.Context, healthCheckTimeout
|
|||||||
// wait a bit longer for TCP connection issues
|
// wait a bit longer for TCP connection issues
|
||||||
if strings.Contains(err.Error(), "connection refused") {
|
if strings.Contains(err.Error(), "connection refused") {
|
||||||
fmt.Fprintf(p.logMonitor, "Connection refused on %s, ttl %.0fs\n", healthURL, ttl)
|
fmt.Fprintf(p.logMonitor, "Connection refused on %s, ttl %.0fs\n", healthURL, ttl)
|
||||||
|
|
||||||
time.Sleep(5 * time.Second)
|
time.Sleep(5 * time.Second)
|
||||||
} else {
|
} else {
|
||||||
time.Sleep(time.Second)
|
time.Sleep(time.Second)
|
||||||
@@ -162,13 +166,23 @@ func (p *Process) checkHealthEndpoint(cmdCtx context.Context, healthCheckTimeout
|
|||||||
if ttl < 0 {
|
if ttl < 0 {
|
||||||
return fmt.Errorf("failed to check health from: %s", healthURL)
|
return fmt.Errorf("failed to check health from: %s", healthURL)
|
||||||
}
|
}
|
||||||
|
|
||||||
time.Sleep(time.Second)
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// sends the request to the upstream process
|
|
||||||
func (p *Process) ProxyRequest(w http.ResponseWriter, r *http.Request) {
|
func (p *Process) ProxyRequest(w http.ResponseWriter, r *http.Request) {
|
||||||
|
if p.overrideProxyFunc != nil {
|
||||||
|
(*p.overrideProxyFunc)(w, r)
|
||||||
|
} else {
|
||||||
|
p.defaultProxyHandler(w, r)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (p *Process) SetOverride(f func(http.ResponseWriter, *http.Request)) {
|
||||||
|
p.overrideProxyFunc = &f
|
||||||
|
}
|
||||||
|
|
||||||
|
// sends the request to the upstream process
|
||||||
|
func (p *Process) defaultProxyHandler(w http.ResponseWriter, r *http.Request) {
|
||||||
if p.cmd == nil {
|
if p.cmd == nil {
|
||||||
http.Error(w, "process not started", http.StatusInternalServerError)
|
http.Error(w, "process not started", http.StatusInternalServerError)
|
||||||
return
|
return
|
||||||
|
|||||||
93
proxy/process_test.go
Normal file
93
proxy/process_test.go
Normal file
@@ -0,0 +1,93 @@
|
|||||||
|
package proxy
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
"math/rand"
|
||||||
|
"net/http"
|
||||||
|
"net/http/httptest"
|
||||||
|
"os"
|
||||||
|
"path/filepath"
|
||||||
|
"runtime"
|
||||||
|
"strings"
|
||||||
|
"testing"
|
||||||
|
)
|
||||||
|
|
||||||
|
// Check if the binary exists
|
||||||
|
func TestMain(m *testing.M) {
|
||||||
|
binaryPath := getBinaryPath()
|
||||||
|
if _, err := os.Stat(binaryPath); os.IsNotExist(err) {
|
||||||
|
fmt.Printf("simple-responder not found at %s, did you `make simple-responder`?\n", binaryPath)
|
||||||
|
os.Exit(1)
|
||||||
|
}
|
||||||
|
m.Run()
|
||||||
|
}
|
||||||
|
|
||||||
|
// Helper function to get the binary path
|
||||||
|
func getBinaryPath() string {
|
||||||
|
goos := runtime.GOOS
|
||||||
|
goarch := runtime.GOARCH
|
||||||
|
return filepath.Join("..", "build", fmt.Sprintf("simple-responder_%s_%s", goos, goarch))
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestProcess_StartProxyStop(t *testing.T) {
|
||||||
|
// Define the range
|
||||||
|
min := 12000
|
||||||
|
max := 13000
|
||||||
|
|
||||||
|
// Generate a random number between 12000 and 13000
|
||||||
|
randomPort := rand.Intn(max-min+1) + min
|
||||||
|
|
||||||
|
binaryPath := getBinaryPath()
|
||||||
|
|
||||||
|
// Create a log monitor
|
||||||
|
logMonitor := NewLogMonitor()
|
||||||
|
|
||||||
|
expectedMessage := "testing91931"
|
||||||
|
|
||||||
|
// Create a process configuration
|
||||||
|
config := ModelConfig{
|
||||||
|
Cmd: fmt.Sprintf("%s --port %d --respond '%s'", binaryPath, randomPort, expectedMessage),
|
||||||
|
Proxy: fmt.Sprintf("http://127.0.0.1:%d", randomPort),
|
||||||
|
CheckEndpoint: "/health",
|
||||||
|
}
|
||||||
|
|
||||||
|
// Create a process
|
||||||
|
process := NewProcess("test-process", config, logMonitor)
|
||||||
|
|
||||||
|
// Start the process
|
||||||
|
t.Logf("Starting %s on port %d", binaryPath, randomPort)
|
||||||
|
err := process.Start(5)
|
||||||
|
if err != nil {
|
||||||
|
t.Fatalf("Failed to start process: %v", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Create a test request
|
||||||
|
req := httptest.NewRequest("GET", "/", nil)
|
||||||
|
w := httptest.NewRecorder()
|
||||||
|
|
||||||
|
// Proxy the request
|
||||||
|
process.ProxyRequest(w, req)
|
||||||
|
|
||||||
|
// Check the response
|
||||||
|
if w.Code != http.StatusOK {
|
||||||
|
t.Errorf("Expected status code %d, got %d", http.StatusOK, w.Code)
|
||||||
|
}
|
||||||
|
|
||||||
|
if !strings.Contains(w.Body.String(), expectedMessage) {
|
||||||
|
t.Errorf("Expected body to contain '%s', got %q", expectedMessage, w.Body.String())
|
||||||
|
}
|
||||||
|
|
||||||
|
// Stop the process
|
||||||
|
process.Stop()
|
||||||
|
|
||||||
|
req = httptest.NewRequest("GET", "/", nil)
|
||||||
|
w = httptest.NewRecorder()
|
||||||
|
|
||||||
|
// Proxy the request
|
||||||
|
process.ProxyRequest(w, req)
|
||||||
|
|
||||||
|
// Check the response
|
||||||
|
if w.Code == http.StatusInternalServerError {
|
||||||
|
t.Errorf("Expected status code %d, got %d", http.StatusInternalServerError, w.Code)
|
||||||
|
}
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user