mirror of
https://github.com/luxfi/netrunner.git
synced 2026-07-27 00:04:23 +00:00
225 lines
5.3 KiB
Go
225 lines
5.3 KiB
Go
// Copyright (C) 2025, Lux Industries Inc. All rights reserved.
|
|
// See the file LICENSE for licensing terms.
|
|
|
|
package orchestrator_test
|
|
|
|
import (
|
|
"context"
|
|
"testing"
|
|
"time"
|
|
|
|
"github.com/luxfi/netrunner/engines"
|
|
"github.com/luxfi/netrunner/orchestrator"
|
|
"github.com/stretchr/testify/require"
|
|
)
|
|
|
|
func TestMultiEngineOrchestration(t *testing.T) {
|
|
if testing.Short() {
|
|
t.Skip("skipping integration test")
|
|
}
|
|
|
|
ctx := context.Background()
|
|
host := orchestrator.NewHost()
|
|
|
|
// Test starting Lux engine
|
|
t.Run("StartLuxEngine", func(t *testing.T) {
|
|
config := &engines.NodeConfig{
|
|
NetworkID: 96369,
|
|
HTTPPort: 19630,
|
|
StakingPort: 19631,
|
|
LogLevel: "info",
|
|
Extra: map[string]interface{}{
|
|
"staking-enabled": false,
|
|
"sybil-protection-enabled": false,
|
|
"health-check-frequency": "2s",
|
|
},
|
|
}
|
|
|
|
err := host.StartEngine(ctx, "test-lux", engines.EngineLux, config)
|
|
require.NoError(t, err)
|
|
|
|
// Wait for health
|
|
time.Sleep(5 * time.Second)
|
|
|
|
// Check engine is listed
|
|
engines := host.ListEngines()
|
|
require.Len(t, engines, 1)
|
|
require.Equal(t, "test-lux", engines[0].Name)
|
|
require.Equal(t, "lux", engines[0].Type)
|
|
|
|
// Stop engine
|
|
err = host.StopEngine(ctx, "test-lux")
|
|
require.NoError(t, err)
|
|
})
|
|
|
|
// Test starting multiple engines
|
|
t.Run("MultipleEngines", func(t *testing.T) {
|
|
// Start Lux
|
|
luxConfig := &engines.NodeConfig{
|
|
NetworkID: 96369,
|
|
HTTPPort: 19640,
|
|
StakingPort: 19641,
|
|
LogLevel: "info",
|
|
}
|
|
err := host.StartEngine(ctx, "lux-1", engines.EngineLux, luxConfig)
|
|
require.NoError(t, err)
|
|
|
|
// Start Lux
|
|
avaConfig := &engines.NodeConfig{
|
|
NetworkID: 43114,
|
|
HTTPPort: 19650,
|
|
StakingPort: 19651,
|
|
LogLevel: "info",
|
|
}
|
|
err = host.StartEngine(ctx, "ava-1", engines.EngineLux, avaConfig)
|
|
require.NoError(t, err)
|
|
|
|
// Check both are running
|
|
engines := host.ListEngines()
|
|
require.Len(t, engines, 2)
|
|
|
|
// Clean up
|
|
host.StopEngine(ctx, "lux-1")
|
|
host.StopEngine(ctx, "ava-1")
|
|
})
|
|
}
|
|
|
|
func TestStackManifest(t *testing.T) {
|
|
manifest := &orchestrator.StackManifest{
|
|
Name: "test-stack",
|
|
Version: "1.0.0",
|
|
Description: "Test stack",
|
|
Engines: []orchestrator.EngineConfig{
|
|
{
|
|
Name: "lux-l1",
|
|
Type: "lux",
|
|
NetworkID: 96369,
|
|
HTTPPort: 9630,
|
|
StakingPort: 9631,
|
|
WaitHealthy: true,
|
|
},
|
|
{
|
|
Name: "lux-l2",
|
|
Type: "op",
|
|
NetworkID: 200200,
|
|
HTTPPort: 8545,
|
|
DependsOn: []string{"lux-l1"},
|
|
},
|
|
},
|
|
}
|
|
|
|
t.Run("Validate", func(t *testing.T) {
|
|
err := manifest.Validate()
|
|
require.NoError(t, err)
|
|
})
|
|
|
|
t.Run("SaveAndLoad", func(t *testing.T) {
|
|
// Save as YAML
|
|
yamlPath := "/tmp/test-stack.yaml"
|
|
err := manifest.Save(yamlPath)
|
|
require.NoError(t, err)
|
|
|
|
// Load back
|
|
loaded, err := orchestrator.LoadManifest(yamlPath)
|
|
require.NoError(t, err)
|
|
require.Equal(t, manifest.Name, loaded.Name)
|
|
require.Len(t, loaded.Engines, 2)
|
|
|
|
// Save as JSON
|
|
jsonPath := "/tmp/test-stack.json"
|
|
err = manifest.Save(jsonPath)
|
|
require.NoError(t, err)
|
|
|
|
// Load JSON
|
|
loaded, err = orchestrator.LoadManifest(jsonPath)
|
|
require.NoError(t, err)
|
|
require.Equal(t, manifest.Name, loaded.Name)
|
|
})
|
|
}
|
|
|
|
func TestPortManager(t *testing.T) {
|
|
pm := orchestrator.NewPortManager()
|
|
|
|
t.Run("AllocatePorts", func(t *testing.T) {
|
|
// Allocate HTTP ports
|
|
port1 := pm.AllocateHTTP()
|
|
port2 := pm.AllocateHTTP()
|
|
require.NotEqual(t, port1, port2)
|
|
|
|
// Allocate P2P ports
|
|
p2p1 := pm.AllocateP2P()
|
|
p2p2 := pm.AllocateP2P()
|
|
require.NotEqual(t, p2p1, p2p2)
|
|
|
|
// Release and reallocate
|
|
pm.Release(port1)
|
|
port3 := pm.AllocateHTTP()
|
|
// May or may not reuse port1 depending on system state
|
|
require.NotEqual(t, port3, port2)
|
|
})
|
|
|
|
t.Run("ReservePorts", func(t *testing.T) {
|
|
pm := orchestrator.NewPortManager()
|
|
|
|
// Reserve specific ports
|
|
err := pm.Reserve(20000, 20001, 20002)
|
|
require.NoError(t, err)
|
|
|
|
// Try to reserve again - should fail
|
|
err = pm.Reserve(20001)
|
|
require.Error(t, err)
|
|
})
|
|
}
|
|
|
|
func TestMetricsCollector(t *testing.T) {
|
|
mc := orchestrator.NewMetricsCollector()
|
|
|
|
t.Run("RecordAndRetrieve", func(t *testing.T) {
|
|
// Record metrics
|
|
mc.Record("engine1", map[string]interface{}{
|
|
"uptime_seconds": 100.0,
|
|
"running": true,
|
|
"peers": 5,
|
|
})
|
|
|
|
// Retrieve metrics
|
|
metrics := mc.Get("engine1")
|
|
require.NotNil(t, metrics)
|
|
require.Equal(t, "engine1", metrics.Name)
|
|
require.Equal(t, 100.0, metrics.Values["uptime_seconds"])
|
|
|
|
// Record more for history
|
|
for i := 0; i < 5; i++ {
|
|
mc.Record("engine1", map[string]interface{}{
|
|
"uptime_seconds": float64(100 + i*10),
|
|
"running": true,
|
|
})
|
|
time.Sleep(10 * time.Millisecond)
|
|
}
|
|
|
|
metrics = mc.Get("engine1")
|
|
require.Len(t, metrics.History, 6) // Initial + 5 more
|
|
})
|
|
|
|
t.Run("Summary", func(t *testing.T) {
|
|
mc := orchestrator.NewMetricsCollector()
|
|
|
|
mc.Record("engine1", map[string]interface{}{
|
|
"uptime_seconds": 100.0,
|
|
"running": true,
|
|
})
|
|
mc.Record("engine2", map[string]interface{}{
|
|
"uptime_seconds": 200.0,
|
|
"running": true,
|
|
})
|
|
mc.Record("engine3", map[string]interface{}{
|
|
"uptime_seconds": 50.0,
|
|
"running": false,
|
|
})
|
|
|
|
summary := mc.Summary()
|
|
require.Equal(t, 3, summary["engines"])
|
|
require.Equal(t, 350.0, summary["total_uptime_seconds"])
|
|
require.Equal(t, 2, summary["healthy_engines"])
|
|
})
|
|
} |