feat: 添加应用骨架,配置化 zap 日志贯穿全链路
- cmd/server/main.go: 使用 logger.NewLogger(cfg.Log) 替代 zap.NewProduction() - internal/app: 依赖注入组装 DB/Slurm/Service/Handler,传递 logger - internal/middleware: RequestLogger 请求日志中间件 - internal/server: 统一响应格式和路由注册 - go.mod: module 更名为 gcy_hpc_server,添加 gin/zap/lumberjack/gorm 依赖 - 日志初始化失败时 fail fast (os.Exit(1)) - GormLevel 从配置传递到 NewGormDB,支持 YAML 独立配置 Ultraworked with [Sisyphus](https://github.com/code-yeongyu/oh-my-openagent) Co-authored-by: Sisyphus <clio-agent@sisyphuslabs.ai>
This commit is contained in:
117
cmd/server/main_test.go
Normal file
117
cmd/server/main_test.go
Normal file
@@ -0,0 +1,117 @@
|
||||
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.JobTemplate{})
|
||||
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()))
|
||||
templateStore := store.NewTemplateStore(newTestDB())
|
||||
|
||||
router := server.NewRouter(
|
||||
handler.NewJobHandler(service.NewJobService(client, zap.NewNop()), zap.NewNop()),
|
||||
handler.NewClusterHandler(service.NewClusterService(client, zap.NewNop()), zap.NewNop()),
|
||||
handler.NewTemplateHandler(templateStore, zap.NewNop()),
|
||||
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/templates"},
|
||||
{"POST", "/api/v1/templates"},
|
||||
{"GET", "/api/v1/templates/:id"},
|
||||
{"PUT", "/api/v1/templates/:id"},
|
||||
{"DELETE", "/api/v1/templates/:id"},
|
||||
}
|
||||
|
||||
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()))
|
||||
templateStore := store.NewTemplateStore(newTestDB())
|
||||
|
||||
router := server.NewRouter(
|
||||
handler.NewJobHandler(service.NewJobService(client, zap.NewNop()), zap.NewNop()),
|
||||
handler.NewClusterHandler(service.NewClusterService(client, zap.NewNop()), zap.NewNop()),
|
||||
handler.NewTemplateHandler(templateStore, zap.NewNop()),
|
||||
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"])
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user