package main import ( "encoding/json" "net/http" "net/http/httptest" "testing" "gcy_hpc_server/internal/handler" "gcy_hpc_server/internal/model" "gcy_hpc_server/internal/server" "gcy_hpc_server/internal/service" "gcy_hpc_server/internal/slurm" "gcy_hpc_server/internal/store" "go.uber.org/zap" "gorm.io/driver/sqlite" "gorm.io/gorm" "gorm.io/gorm/logger" ) func newTestDB() *gorm.DB { db, _ := gorm.Open(sqlite.Open(":memory:"), &gorm.Config{Logger: logger.Default.LogMode(logger.Silent)}) db.AutoMigrate(&model.Application{}) return db } func TestRouterRegistration(t *testing.T) { slurmSrv := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { w.Header().Set("Content-Type", "application/json") w.WriteHeader(http.StatusOK) json.NewEncoder(w).Encode(map[string]interface{}{"jobs": []interface{}{}}) })) defer slurmSrv.Close() client, _ := slurm.NewClientWithOpts(slurmSrv.URL, slurm.WithHTTPClient(slurmSrv.Client())) jobSvc := service.NewJobService(client, zap.NewNop()) appStore := store.NewApplicationStore(newTestDB()) appSvc := service.NewApplicationService(appStore, jobSvc, "", zap.NewNop()) appH := handler.NewApplicationHandler(appSvc, zap.NewNop()) router := server.NewRouter( handler.NewJobHandler(jobSvc, zap.NewNop()), handler.NewClusterHandler(service.NewClusterService(client, zap.NewNop()), zap.NewNop()), appH, nil, ) routes := router.Routes() expected := []struct { method string path string }{ {"POST", "/api/v1/jobs/submit"}, {"GET", "/api/v1/jobs"}, {"GET", "/api/v1/jobs/history"}, {"GET", "/api/v1/jobs/:id"}, {"DELETE", "/api/v1/jobs/:id"}, {"GET", "/api/v1/nodes"}, {"GET", "/api/v1/nodes/:name"}, {"GET", "/api/v1/partitions"}, {"GET", "/api/v1/partitions/:name"}, {"GET", "/api/v1/diag"}, {"GET", "/api/v1/applications"}, {"POST", "/api/v1/applications"}, {"GET", "/api/v1/applications/:id"}, {"PUT", "/api/v1/applications/:id"}, {"DELETE", "/api/v1/applications/:id"}, {"POST", "/api/v1/applications/:id/submit"}, } routeMap := map[string]bool{} for _, r := range routes { routeMap[r.Method+" "+r.Path] = true } for _, exp := range expected { key := exp.method + " " + exp.path if !routeMap[key] { t.Errorf("missing route: %s", key) } } if len(routes) < len(expected) { t.Errorf("expected at least %d routes, got %d", len(expected), len(routes)) } } func TestSmokeGetJobsEndpoint(t *testing.T) { slurmSrv := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { w.Header().Set("Content-Type", "application/json") json.NewEncoder(w).Encode(map[string]interface{}{"jobs": []interface{}{}}) })) defer slurmSrv.Close() client, _ := slurm.NewClientWithOpts(slurmSrv.URL, slurm.WithHTTPClient(slurmSrv.Client())) jobSvc := service.NewJobService(client, zap.NewNop()) appStore := store.NewApplicationStore(newTestDB()) appSvc := service.NewApplicationService(appStore, jobSvc, "", zap.NewNop()) appH := handler.NewApplicationHandler(appSvc, zap.NewNop()) router := server.NewRouter( handler.NewJobHandler(jobSvc, zap.NewNop()), handler.NewClusterHandler(service.NewClusterService(client, zap.NewNop()), zap.NewNop()), appH, nil, ) w := httptest.NewRecorder() req, _ := http.NewRequest(http.MethodGet, "/api/v1/jobs", nil) router.ServeHTTP(w, req) if w.Code != http.StatusOK { t.Fatalf("expected 200, got %d: %s", w.Code, w.Body.String()) } var resp map[string]interface{} if err := json.Unmarshal(w.Body.Bytes(), &resp); err != nil { t.Fatalf("failed to parse response: %v", err) } if success, ok := resp["success"].(bool); !ok || !success { t.Fatalf("expected success=true, got %v", resp["success"]) } }