package bootstrap import ( "encoding/json" "fmt" "net" "net/http" "os" "path/filepath" "sort" "testing" "iop/packages/go/config" ) func newTestConfig() *config.EdgeConfig { return &config.EdgeConfig{ Server: config.EdgeServerConf{Listen: "127.0.0.1:0"}, Logging: config.LoggingConf{Level: "error"}, Metrics: config.MetricsConf{Port: 0}, Nodes: []config.NodeDefinition{ {ID: "node-1", Alias: "alias-1", Token: "tok-1"}, }, } } func serveNormalizedLogPath() string { if exe, err := os.Executable(); err == nil { return filepath.Join(filepath.Dir(exe), "logs", "edge.log") } if wd, err := os.Getwd(); err == nil { return filepath.Join(wd, "logs", "edge.log") } return "logs/edge.log" } func serveNormalizedArtifactDir(dir string) string { if dir == "" { dir = "artifacts" } if filepath.IsAbs(dir) { return dir } bd := binaryDirForTest() return filepath.Join(bd, dir) } func binaryDirForTest() string { if exe, err := os.Executable(); err == nil { return filepath.Dir(exe) } if wd, err := os.Getwd(); err == nil { return wd } return "." } // loadServeNormalizedConfig loads an Edge config and applies the same // normalization iop-edge serve performs, so refresh classification compares // effective values. func loadServeNormalizedConfig(t *testing.T, path string) *config.EdgeConfig { t.Helper() cfg, err := config.LoadEdge(path) if err != nil { t.Fatalf("load config %s: %v", path, err) } cfg.Logging.Path = serveNormalizedLogPath() cfg.Bootstrap.ArtifactDir = serveNormalizedArtifactDir(cfg.Bootstrap.ArtifactDir) return cfg } // providerPoolConfigYAML builds an Edge config with one provider-pool model and // one node provider. The extra parameter lets callers inject a candidate // variation (e.g. a different capacity or an invalid adapter block). func providerPoolConfigYAML(serverAddr, openAIAddr, providerBlock string) string { return fmt.Sprintf(` server: listen: %q bootstrap: listen: "0.0.0.0:18080" artifact_dir: "artifacts" logging: level: "error" refresh: enabled: true listen: "127.0.0.1:0" openai: enabled: true listen: %q adapter: "openai_compat" target: "" a2a: listen: "0.0.0.0:8081" metrics: port: 0 models: - id: "qwen3.6:35b" display_name: "Qwen" providers: prov-a: "served-qwen" nodes: - id: "node-1" alias: "n1" token: "tok-1" adapters: %s providers: - id: "prov-a" type: "vllm" category: "api" adapter: "vllm-gpu" models: ["served-qwen"] health: "available" capacity: 2 max_queue: 4 queue_timeout_ms: 5000 `, serverAddr, openAIAddr, providerBlock) } const validAdapterBlock = ` openai_compat_instances: - name: "vllm-gpu" enabled: true provider: "vllm" endpoint: "http://127.0.0.1:8000/v1"` // invalidAdapterBlock enables an openai_compat instance but leaves endpoint // empty, which ValidateEdgeConfig rejects. const invalidAdapterBlock = ` openai_compat_instances: - name: "vllm-gpu" enabled: true provider: "vllm" endpoint: ""` // modelsResponse represents the JSON response from /v1/models. type modelsResponse struct { Object string `json:"object"` Data []modelItem `json:"data"` } // modelItem represents a single model entry in the /v1/models response. type modelItem struct { ID string `json:"id"` Object string `json:"object"` Created int64 `json:"created"` OwnedBy string `json:"owned_by"` } // modelIDs returns the sorted list of model IDs from /v1/models. // This avoids flaky timestamp comparisons on the `created` field. func modelIDs(t *testing.T, client *http.Client, openAIAddr string) []string { t.Helper() resp, err := client.Get("http://" + openAIAddr + "/v1/models") if err != nil { t.Fatalf("GET /v1/models: %v", err) } defer resp.Body.Close() if resp.StatusCode != http.StatusOK { t.Fatalf("GET /v1/models status=%d", resp.StatusCode) } var body modelsResponse if err := json.NewDecoder(resp.Body).Decode(&body); err != nil { t.Fatalf("decode /v1/models body: %v", err) } ids := make([]string, 0, len(body.Data)) for _, m := range body.Data { ids = append(ids, m.ID) } sort.Strings(ids) return ids } func containsString(s []string, want string) bool { for _, v := range s { if v == want { return true } } return false } func freeTCPAddr(t *testing.T) string { t.Helper() ln, err := net.Listen("tcp", "127.0.0.1:0") if err != nil { t.Fatalf("listen free tcp addr: %v", err) } addr := ln.Addr().String() if err := ln.Close(); err != nil { t.Fatalf("close free tcp addr listener: %v", err) } return addr }