* clear

* feat: Add everything

* fix: Commenht
This commit is contained in:
Prad Nukala
2025-10-03 14:45:52 -04:00
committed by GitHub
parent 43b4a11c06
commit 13e6c3e84d
1935 changed files with 655061 additions and 40058 deletions
+223
View File
@@ -0,0 +1,223 @@
package server
import (
"bytes"
"encoding/json"
"net/http"
"net/http/httptest"
"runtime"
"testing"
"time"
"github.com/hibiken/asynq"
"github.com/labstack/echo/v4"
"github.com/sonr-io/sonr/crypto/mpc"
)
// MockAsynqClient provides a test double for asynq.Client
type MockAsynqClient struct {
enqueuedTasks []MockTask
}
type MockTask struct {
Type string
Payload []byte
Queue string
}
func (m *MockAsynqClient) Enqueue(task *asynq.Task, opts ...asynq.Option) (*asynq.TaskInfo, error) {
mockTask := MockTask{
Type: task.Type(),
Payload: task.Payload(),
Queue: "default",
}
m.enqueuedTasks = append(m.enqueuedTasks, mockTask)
return &asynq.TaskInfo{
ID: "test-task-id",
Type: task.Type(),
Queue: mockTask.Queue,
}, nil
}
func (m *MockAsynqClient) Close() error {
return nil
}
// setupTestEcho creates a test Echo server and mock client for benchmarking
func setupTestEcho() (*echo.Echo, *MockAsynqClient) {
mockClient := &MockAsynqClient{}
config := &Config{
JWTSecret: []byte("test-secret"),
IPFSClient: &MockIPFSClient{},
}
s := NewServer(config)
return s.Echo(), mockClient
}
// BenchmarkHealthCheckHandler measures the performance of the health check endpoint
func BenchmarkHealthCheckHandler(b *testing.B) {
e, _ := setupTestEcho()
b.ResetTimer()
b.ReportAllocs()
b.RunParallel(func(pb *testing.PB) {
for pb.Next() {
req := httptest.NewRequest("GET", "/health", nil)
rr := httptest.NewRecorder()
e.ServeHTTP(rr, req)
if rr.Code != http.StatusOK {
b.Errorf("Expected status 200, got %d", rr.Code)
}
}
})
}
// BenchmarkGenerateHandler measures the performance of the generate endpoint
func BenchmarkGenerateHandler(b *testing.B) {
e, client := setupTestEcho()
payload := map[string]any{
"user_id": 123,
"priority": "default",
}
var buf bytes.Buffer
json.NewEncoder(&buf).Encode(payload)
requestBody := buf.Bytes()
b.ResetTimer()
b.ReportAllocs()
b.RunParallel(func(pb *testing.PB) {
for pb.Next() {
req := httptest.NewRequest("POST", "/vault/generate", bytes.NewReader(requestBody))
req.Header.Set("Content-Type", "application/json")
rr := httptest.NewRecorder()
e.ServeHTTP(rr, req)
if rr.Code != http.StatusOK {
b.Errorf("Expected status 200, got %d", rr.Code)
}
}
})
b.StopTimer()
b.Logf("Tasks enqueued: %d", len(client.enqueuedTasks))
}
// BenchmarkSignHandler measures the performance of the sign endpoint
func BenchmarkSignHandler(b *testing.B) {
e, client := setupTestEcho()
payload := map[string]any{
"message": []byte("benchmark test message"),
"enclave": &mpc.EnclaveData{},
"priority": "default",
}
var buf bytes.Buffer
json.NewEncoder(&buf).Encode(payload)
requestBody := buf.Bytes()
b.ResetTimer()
b.ReportAllocs()
b.RunParallel(func(pb *testing.PB) {
for pb.Next() {
req := httptest.NewRequest("POST", "/vault/sign", bytes.NewReader(requestBody))
req.Header.Set("Content-Type", "application/json")
rr := httptest.NewRecorder()
e.ServeHTTP(rr, req)
if rr.Code != http.StatusOK {
b.Errorf("Expected status 200, got %d", rr.Code)
}
}
})
b.StopTimer()
b.Logf("Tasks enqueued: %d", len(client.enqueuedTasks))
}
// BenchmarkMemoryAllocation measures memory allocation patterns
func BenchmarkMemoryAllocation(b *testing.B) {
e, _ := setupTestEcho()
payload := map[string]any{
"user_id": 123,
}
var buf bytes.Buffer
json.NewEncoder(&buf).Encode(payload)
requestBody := buf.Bytes()
var m1, m2 runtime.MemStats
runtime.GC()
runtime.ReadMemStats(&m1)
b.ReportAllocs()
for b.Loop() {
req := httptest.NewRequest("POST", "/vault/generate", bytes.NewReader(requestBody))
req.Header.Set("Content-Type", "application/json")
rr := httptest.NewRecorder()
e.ServeHTTP(rr, req)
}
b.StopTimer()
runtime.GC()
runtime.ReadMemStats(&m2)
b.Logf("Memory allocated per operation: %d bytes", (m2.TotalAlloc-m1.TotalAlloc)/uint64(b.N))
b.Logf("Total allocations: %d", m2.Mallocs-m1.Mallocs)
}
// BenchmarkLatencyMeasurement measures end-to-end latency
func BenchmarkLatencyMeasurement(b *testing.B) {
e, _ := setupTestEcho()
payload := map[string]any{
"user_id": 123,
}
var buf bytes.Buffer
json.NewEncoder(&buf).Encode(payload)
requestBody := buf.Bytes()
var totalLatency time.Duration
minLatency := time.Hour
var maxLatency time.Duration
for b.Loop() {
start := time.Now()
req := httptest.NewRequest("POST", "/vault/generate", bytes.NewReader(requestBody))
req.Header.Set("Content-Type", "application/json")
rr := httptest.NewRecorder()
e.ServeHTTP(rr, req)
latency := time.Since(start)
totalLatency += latency
if latency < minLatency {
minLatency = latency
}
if latency > maxLatency {
maxLatency = latency
}
if rr.Code != http.StatusOK {
b.Errorf("Expected status 200, got %d", rr.Code)
}
}
b.StopTimer()
avgLatency := totalLatency / time.Duration(b.N)
b.Logf("Average latency: %v", avgLatency)
b.Logf("Min latency: %v", minLatency)
b.Logf("Max latency: %v", maxLatency)
}
+118
View File
@@ -0,0 +1,118 @@
// Package server provides the HTTP server for the highway server
package server
import (
"net/http"
"github.com/gorilla/websocket"
"github.com/hibiken/asynq"
echojwt "github.com/labstack/echo-jwt/v4"
"github.com/labstack/echo/v4"
"github.com/labstack/echo/v4/middleware"
"github.com/sonr-io/sonr/bridge/handlers"
"github.com/sonr-io/sonr/types/ipfs"
)
const (
DefaultHTTPAddr = ":8080"
)
// Config holds server configuration
type Config struct {
HTTPAddr string
JWTSecret []byte
IPFSClient ipfs.IPFSClient
}
// Server represents the HTTP server
type Server struct {
config *Config
echo *echo.Echo
upgrader *websocket.Upgrader
connectionManager *handlers.ConnectionManager
sseManager *handlers.SSEManager
vaultHandlers *handlers.VaultHandlers
}
// NewServer creates a new server instance
func NewServer(config *Config) *Server {
// WebSocket upgrader with CORS settings
upgrader := &websocket.Upgrader{
CheckOrigin: func(r *http.Request) bool {
return true // Allow all origins in development
},
}
// Create connection managers
connectionManager := handlers.NewConnectionManager()
sseManager := handlers.NewSSEManager()
// Create vault handlers
vaultHandlers := handlers.NewVaultHandlers(config.IPFSClient, connectionManager, sseManager)
return &Server{
config: config,
echo: echo.New(),
upgrader: upgrader,
connectionManager: connectionManager,
sseManager: sseManager,
vaultHandlers: vaultHandlers,
}
}
// Echo returns the underlying Echo instance for testing
func (s *Server) Echo() *echo.Echo {
return s.echo
}
// Start starts the HTTP server
func (s *Server) Start(client *asynq.Client) error {
s.setupMiddleware()
s.setupRoutes(client)
addr := s.config.HTTPAddr
if addr == "" {
addr = DefaultHTTPAddr
}
return s.echo.Start(addr)
}
// setupMiddleware configures Echo middleware
func (s *Server) setupMiddleware() {
s.echo.Use(middleware.Logger())
s.echo.Use(middleware.Recover())
s.echo.Use(middleware.CORS())
}
// setupRoutes configures all routes
func (s *Server) setupRoutes(client *asynq.Client) {
// Initialize health checker
handlers.InitHealthChecker(client, s.config.IPFSClient)
// Public endpoints (no authentication required)
s.echo.GET("/health", handlers.HealthCheckHandler) // Liveness probe
s.echo.GET("/ready", handlers.ReadinessHandler) // Readiness probe
s.echo.POST("/auth/login", handlers.LoginHandler(s.config.JWTSecret))
// JWT middleware configuration
jwtConfig := echojwt.Config{
SigningKey: s.config.JWTSecret,
SigningMethod: "HS256",
}
// Protected vault endpoints group with JWT middleware
vault := s.echo.Group("/vault")
vault.Use(echojwt.WithConfig(jwtConfig))
vault.POST("/generate", s.vaultHandlers.GenerateHandler(client))
vault.POST("/sign", s.vaultHandlers.SignHandler(client))
vault.POST("/verify", s.vaultHandlers.VerifyHandler(client))
vault.POST("/export", s.vaultHandlers.ExportHandler(client))
vault.POST("/import", s.vaultHandlers.ImportHandler(client))
vault.POST("/refresh", s.vaultHandlers.RefreshHandler(client))
// WebSocket endpoint for real-time task status updates
vault.GET("/ws/:task_id", handlers.WebSocketHandler(s.upgrader, s.connectionManager))
// Server-Sent Events endpoint for task progress streaming
vault.GET("/events/:task_id", handlers.SSEHandler(s.sseManager))
}
+110
View File
@@ -0,0 +1,110 @@
package server
import (
"encoding/json"
"net/http"
"net/http/httptest"
"testing"
"github.com/labstack/echo/v4"
"github.com/sonr-io/sonr/bridge/handlers"
"github.com/sonr-io/sonr/types/ipfs"
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"
)
// MockIPFSClient provides a test implementation of IPFSClient for server tests
type MockIPFSClient struct{}
func (m *MockIPFSClient) Add(data []byte) (string, error) { return "mock-cid", nil }
func (m *MockIPFSClient) AddFile(
file ipfs.File,
) (string, error) {
return "mock-file-cid", nil
}
func (m *MockIPFSClient) AddFolder(
folder ipfs.Folder,
) (string, error) {
return "mock-folder-cid", nil
}
func (m *MockIPFSClient) Get(
cid string,
) ([]byte, error) {
return []byte("mock-ipfs-data"), nil
}
func (m *MockIPFSClient) GetFile(cid string) (ipfs.File, error) { return nil, nil }
func (m *MockIPFSClient) GetFolder(cid string) (ipfs.Folder, error) { return nil, nil }
func (m *MockIPFSClient) Pin(cid string, name string) error { return nil }
func (m *MockIPFSClient) Unpin(cid string) error { return nil }
func (m *MockIPFSClient) Exists(cid string) (bool, error) { return true, nil }
func (m *MockIPFSClient) IsPinned(ipns string) (bool, error) { return true, nil }
func (m *MockIPFSClient) Ls(cid string) ([]string, error) {
return []string{"mock-file1", "mock-file2"}, nil
}
func (m *MockIPFSClient) NodeStatus() (*ipfs.NodeStatus, error) {
return &ipfs.NodeStatus{
PeerID: "mock-peer-id",
Version: "mock-version",
PeerType: "kubo",
ConnectedPeers: 3,
}, nil
}
func setupTestServer() *Server {
config := &Config{
JWTSecret: []byte("test-secret"),
IPFSClient: &MockIPFSClient{},
}
s := NewServer(config)
// Setup routes manually for testing since we can't call Start() which would block
e := s.Echo()
// Setup middleware
e.Use(func(next echo.HandlerFunc) echo.HandlerFunc {
return func(c echo.Context) error {
return next(c)
}
})
// Setup routes manually (mimicking server.setupRoutes)
e.GET("/health", handlers.HealthCheckHandler)
e.POST("/auth/login", handlers.LoginHandler(config.JWTSecret))
return s
}
func TestHealthCheckHandler(t *testing.T) {
s := setupTestServer()
e := s.Echo()
req, err := http.NewRequest("GET", "/health", nil)
require.NoError(t, err)
rr := httptest.NewRecorder()
e.ServeHTTP(rr, req)
assert.Equal(t, http.StatusOK, rr.Code)
assert.Equal(t, "application/json", rr.Header().Get("Content-Type"))
var response map[string]string
err = json.Unmarshal(rr.Body.Bytes(), &response)
require.NoError(t, err)
// When health checker is not initialized, it returns "starting" status
// This is expected behavior in test environment
assert.Equal(t, "starting", response["status"])
}
func TestVaultHandlersCreation(t *testing.T) {
// Test the vault handlers creation
vaultHandlers := handlers.NewVaultHandlers(
&MockIPFSClient{},
handlers.NewConnectionManager(),
handlers.NewSSEManager(),
)
assert.NotNil(t, vaultHandlers)
}