Second pass of test naming convention across xmrig_test.go, xmrig_gpu_test.go, stats_collector_test.go, manager_race_test.go, throttle_test.go, service_test.go, interface_test.go, database_race_test.go. 30 additional tests renamed. Co-Authored-By: Charon <charon@lethean.io>
267 lines
9.2 KiB
Go
267 lines
9.2 KiB
Go
package mining
|
|
|
|
import (
|
|
"context"
|
|
"net/http"
|
|
"net/http/httptest"
|
|
"strings"
|
|
"testing"
|
|
"time"
|
|
|
|
"github.com/gin-gonic/gin"
|
|
)
|
|
|
|
// mock := &MockMiner{GetNameFunc: func() string { return "test" }}
|
|
// mock.GetName() == "test"
|
|
type MockMiner struct {
|
|
InstallFunc func() error
|
|
UninstallFunc func() error
|
|
StartFunc func(config *Config) error
|
|
StopFunc func() error
|
|
GetStatsFunc func(ctx context.Context) (*PerformanceMetrics, error)
|
|
GetTypeFunc func() string
|
|
GetNameFunc func() string
|
|
GetPathFunc func() string
|
|
GetBinaryPathFunc func() string
|
|
CheckInstallationFunc func() (*InstallationDetails, error)
|
|
GetLatestVersionFunc func() (string, error)
|
|
GetHashrateHistoryFunc func() []HashratePoint
|
|
AddHashratePointFunc func(point HashratePoint)
|
|
ReduceHashrateHistoryFunc func(now time.Time)
|
|
GetLogsFunc func() []string
|
|
WriteStdinFunc func(input string) error
|
|
}
|
|
|
|
func (m *MockMiner) Install() error { return m.InstallFunc() }
|
|
func (m *MockMiner) Uninstall() error { return m.UninstallFunc() }
|
|
func (m *MockMiner) Start(config *Config) error { return m.StartFunc(config) }
|
|
func (m *MockMiner) Stop() error { return m.StopFunc() }
|
|
func (m *MockMiner) GetStats(ctx context.Context) (*PerformanceMetrics, error) {
|
|
return m.GetStatsFunc(ctx)
|
|
}
|
|
func (m *MockMiner) GetType() string {
|
|
if m.GetTypeFunc != nil {
|
|
return m.GetTypeFunc()
|
|
}
|
|
return "mock"
|
|
}
|
|
func (m *MockMiner) GetName() string { return m.GetNameFunc() }
|
|
func (m *MockMiner) GetPath() string { return m.GetPathFunc() }
|
|
func (m *MockMiner) GetBinaryPath() string { return m.GetBinaryPathFunc() }
|
|
func (m *MockMiner) CheckInstallation() (*InstallationDetails, error) {
|
|
return m.CheckInstallationFunc()
|
|
}
|
|
func (m *MockMiner) GetLatestVersion() (string, error) { return m.GetLatestVersionFunc() }
|
|
func (m *MockMiner) GetHashrateHistory() []HashratePoint { return m.GetHashrateHistoryFunc() }
|
|
func (m *MockMiner) AddHashratePoint(point HashratePoint) { m.AddHashratePointFunc(point) }
|
|
func (m *MockMiner) ReduceHashrateHistory(now time.Time) { m.ReduceHashrateHistoryFunc(now) }
|
|
func (m *MockMiner) GetLogs() []string { return m.GetLogsFunc() }
|
|
func (m *MockMiner) WriteStdin(input string) error { return m.WriteStdinFunc(input) }
|
|
|
|
// mock := &MockManager{ListMinersFunc: func() []Miner { return nil }}
|
|
// mock.ListMiners()
|
|
type MockManager struct {
|
|
ListMinersFunc func() []Miner
|
|
ListAvailableMinersFunc func() []AvailableMiner
|
|
StartMinerFunc func(ctx context.Context, minerType string, config *Config) (Miner, error)
|
|
StopMinerFunc func(ctx context.Context, minerName string) error
|
|
GetMinerFunc func(minerName string) (Miner, error)
|
|
GetMinerHashrateHistoryFunc func(minerName string) ([]HashratePoint, error)
|
|
UninstallMinerFunc func(ctx context.Context, minerType string) error
|
|
StopFunc func()
|
|
}
|
|
|
|
func (m *MockManager) ListMiners() []Miner { return m.ListMinersFunc() }
|
|
func (m *MockManager) ListAvailableMiners() []AvailableMiner { return m.ListAvailableMinersFunc() }
|
|
func (m *MockManager) StartMiner(ctx context.Context, minerType string, config *Config) (Miner, error) {
|
|
return m.StartMinerFunc(ctx, minerType, config)
|
|
}
|
|
func (m *MockManager) StopMiner(ctx context.Context, minerName string) error {
|
|
return m.StopMinerFunc(ctx, minerName)
|
|
}
|
|
func (m *MockManager) GetMiner(minerName string) (Miner, error) {
|
|
return m.GetMinerFunc(minerName)
|
|
}
|
|
func (m *MockManager) GetMinerHashrateHistory(minerName string) ([]HashratePoint, error) {
|
|
return m.GetMinerHashrateHistoryFunc(minerName)
|
|
}
|
|
func (m *MockManager) UninstallMiner(ctx context.Context, minerType string) error {
|
|
return m.UninstallMinerFunc(ctx, minerType)
|
|
}
|
|
func (m *MockManager) Stop() { m.StopFunc() }
|
|
|
|
var _ ManagerInterface = (*MockManager)(nil)
|
|
|
|
func setupTestRouter() (*gin.Engine, *MockManager) {
|
|
gin.SetMode(gin.TestMode)
|
|
router := gin.Default()
|
|
mockManager := &MockManager{
|
|
ListMinersFunc: func() []Miner { return []Miner{} },
|
|
ListAvailableMinersFunc: func() []AvailableMiner { return []AvailableMiner{} },
|
|
StartMinerFunc: func(ctx context.Context, minerType string, config *Config) (Miner, error) {
|
|
return nil, nil
|
|
},
|
|
StopMinerFunc: func(ctx context.Context, minerName string) error { return nil },
|
|
GetMinerFunc: func(minerName string) (Miner, error) { return nil, nil },
|
|
GetMinerHashrateHistoryFunc: func(minerName string) ([]HashratePoint, error) {
|
|
return nil, nil
|
|
},
|
|
UninstallMinerFunc: func(ctx context.Context, minerType string) error { return nil },
|
|
StopFunc: func() {},
|
|
}
|
|
service := &Service{
|
|
Manager: mockManager,
|
|
Router: router,
|
|
APIBasePath: "/",
|
|
SwaggerUIPath: "/swagger",
|
|
}
|
|
service.SetupRoutes()
|
|
return router, mockManager
|
|
}
|
|
|
|
func TestService_HandleListMiners_Good(t *testing.T) {
|
|
router, mockManager := setupTestRouter()
|
|
mockManager.ListMinersFunc = func() []Miner {
|
|
return []Miner{&XMRigMiner{BaseMiner: BaseMiner{Name: "test-miner"}}}
|
|
}
|
|
|
|
req, _ := http.NewRequest("GET", "/miners", nil)
|
|
w := httptest.NewRecorder()
|
|
router.ServeHTTP(w, req)
|
|
|
|
if w.Code != http.StatusOK {
|
|
t.Errorf("expected status %d, got %d", http.StatusOK, w.Code)
|
|
}
|
|
}
|
|
|
|
func TestService_HandleGetInfo_Good(t *testing.T) {
|
|
router, _ := setupTestRouter()
|
|
|
|
// Case 1: Successful response
|
|
req, _ := http.NewRequest("GET", "/info", nil)
|
|
w := httptest.NewRecorder()
|
|
router.ServeHTTP(w, req)
|
|
|
|
if w.Code != http.StatusOK {
|
|
t.Errorf("expected status %d, got %d", http.StatusOK, w.Code)
|
|
}
|
|
}
|
|
|
|
func TestService_HandleDoctor_Good(t *testing.T) {
|
|
router, mockManager := setupTestRouter()
|
|
mockManager.ListAvailableMinersFunc = func() []AvailableMiner {
|
|
return []AvailableMiner{{Name: "xmrig"}}
|
|
}
|
|
|
|
// Case 1: Successful response
|
|
req, _ := http.NewRequest("POST", "/doctor", nil)
|
|
w := httptest.NewRecorder()
|
|
router.ServeHTTP(w, req)
|
|
|
|
if w.Code != http.StatusOK {
|
|
t.Errorf("expected status %d, got %d", http.StatusOK, w.Code)
|
|
}
|
|
}
|
|
|
|
func TestService_HandleInstallMiner_Good(t *testing.T) {
|
|
router, _ := setupTestRouter()
|
|
|
|
// Test installing a miner
|
|
req, _ := http.NewRequest("POST", "/miners/xmrig/install", nil)
|
|
req.Header.Set("Content-Type", "application/json")
|
|
w := httptest.NewRecorder()
|
|
router.ServeHTTP(w, req)
|
|
|
|
// Installation endpoint should be accessible
|
|
if w.Code != http.StatusOK && w.Code != http.StatusInternalServerError {
|
|
t.Errorf("expected status 200 or 500, got %d", w.Code)
|
|
}
|
|
}
|
|
|
|
func TestService_HandleStopMiner_Good(t *testing.T) {
|
|
router, mockManager := setupTestRouter()
|
|
mockManager.StopMinerFunc = func(ctx context.Context, minerName string) error {
|
|
return nil
|
|
}
|
|
|
|
req, _ := http.NewRequest("DELETE", "/miners/test-miner", nil)
|
|
w := httptest.NewRecorder()
|
|
router.ServeHTTP(w, req)
|
|
|
|
if w.Code != http.StatusOK {
|
|
t.Errorf("expected status %d, got %d", http.StatusOK, w.Code)
|
|
}
|
|
}
|
|
|
|
func TestService_HandleGetMinerStats_Good(t *testing.T) {
|
|
router, mockManager := setupTestRouter()
|
|
mockManager.GetMinerFunc = func(minerName string) (Miner, error) {
|
|
return &MockMiner{
|
|
GetStatsFunc: func(ctx context.Context) (*PerformanceMetrics, error) {
|
|
return &PerformanceMetrics{Hashrate: 100}, nil
|
|
},
|
|
GetLogsFunc: func() []string { return []string{} },
|
|
}, nil
|
|
}
|
|
|
|
req, _ := http.NewRequest("GET", "/miners/test-miner/stats", nil)
|
|
w := httptest.NewRecorder()
|
|
router.ServeHTTP(w, req)
|
|
|
|
if w.Code != http.StatusOK {
|
|
t.Errorf("expected status %d, got %d", http.StatusOK, w.Code)
|
|
}
|
|
}
|
|
|
|
func TestService_HandleGetMinerHashrateHistory_Good(t *testing.T) {
|
|
router, mockManager := setupTestRouter()
|
|
mockManager.GetMinerHashrateHistoryFunc = func(minerName string) ([]HashratePoint, error) {
|
|
return []HashratePoint{{Timestamp: time.Now(), Hashrate: 100}}, nil
|
|
}
|
|
|
|
req, _ := http.NewRequest("GET", "/miners/test-miner/hashrate-history", nil)
|
|
w := httptest.NewRecorder()
|
|
router.ServeHTTP(w, req)
|
|
|
|
if w.Code != http.StatusOK {
|
|
t.Errorf("expected status %d, got %d", http.StatusOK, w.Code)
|
|
}
|
|
}
|
|
|
|
func TestService_GenerateRequestID_Good(t *testing.T) {
|
|
firstRequestID := generateRequestID()
|
|
secondRequestID := generateRequestID()
|
|
|
|
if firstRequestID == secondRequestID {
|
|
t.Fatalf("expected unique request IDs, got %q twice", firstRequestID)
|
|
}
|
|
|
|
for _, requestID := range []string{firstRequestID, secondRequestID} {
|
|
parts := strings.Split(requestID, "-")
|
|
if len(parts) != 2 {
|
|
t.Fatalf("expected request ID format timestamp-randomhex, got %q", requestID)
|
|
}
|
|
if len(parts[1]) != 16 {
|
|
t.Fatalf("expected 16 hex characters, got %q", parts[1])
|
|
}
|
|
}
|
|
}
|
|
|
|
func TestService_RequestIDMiddleware_Good(t *testing.T) {
|
|
gin.SetMode(gin.TestMode)
|
|
router := gin.New()
|
|
router.Use(requestIDMiddleware())
|
|
router.GET("/health", func(context *gin.Context) {
|
|
context.Status(http.StatusOK)
|
|
})
|
|
|
|
request, _ := http.NewRequest(http.MethodGet, "/health", nil)
|
|
request.Header.Set("X-Request-ID", "user-supplied-request-id")
|
|
|
|
responseRecorder := httptest.NewRecorder()
|
|
router.ServeHTTP(responseRecorder, request)
|
|
|
|
if responseRecorder.Header().Get("X-Request-ID") != "user-supplied-request-id" {
|
|
t.Fatalf("expected middleware to preserve request ID header, got %q", responseRecorder.Header().Get("X-Request-ID"))
|
|
}
|
|
}
|