package server import ( "encoding/json" "net/http" "net/http/httptest" "strings" "testing" "time" "git.mchus.pro/mchus/logpile/internal/models" ) func TestApplyArchiveSourceMetadata(t *testing.T) { result := &models.AnalysisResult{} applyArchiveSourceMetadata(result) if result.SourceType != models.SourceTypeArchive { t.Fatalf("expected source type %q, got %q", models.SourceTypeArchive, result.SourceType) } if result.Protocol != "" { t.Fatalf("expected empty protocol for archive, got %q", result.Protocol) } if result.TargetHost != "" { t.Fatalf("expected empty target host for archive, got %q", result.TargetHost) } if result.CollectedAt.IsZero() { t.Fatalf("expected collected_at to be set") } } func TestNewAPIResultMetadata(t *testing.T) { req := CollectRequest{ Host: "bmc-api.local", Protocol: "redfish", Port: 443, Username: "admin", AuthType: "password", Password: "super-secret", TLSMode: "strict", } result := newAPIResult(req) if result.SourceType != models.SourceTypeAPI { t.Fatalf("expected source type %q, got %q", models.SourceTypeAPI, result.SourceType) } if result.Protocol != req.Protocol { t.Fatalf("expected protocol %q, got %q", req.Protocol, result.Protocol) } if result.TargetHost != req.Host { t.Fatalf("expected target host %q, got %q", req.Host, result.TargetHost) } if result.CollectedAt.IsZero() { t.Fatalf("expected collected_at to be set") } if len(result.Events) != 0 || len(result.FRU) != 0 || len(result.Sensors) != 0 { t.Fatalf("expected empty slices for api result") } raw, err := json.Marshal(result) if err != nil { t.Fatalf("marshal result: %v", err) } if string(raw) == "" { t.Fatalf("expected non-empty json") } if strings.Contains(string(raw), req.Password) || (req.Token != "" && strings.Contains(string(raw), req.Token)) { t.Fatalf("secrets should not be present in api result") } } func TestStatusAndConfigExposeSourceMetadata(t *testing.T) { s := &Server{} s.SetDetectedVendor("nvidia") s.SetResult(&models.AnalysisResult{ Filename: "archive.tar.gz", SourceType: models.SourceTypeArchive, Protocol: "", TargetHost: "", CollectedAt: time.Now().UTC(), Events: []models.Event{{ID: "1"}}, Sensors: []models.SensorReading{{Name: "Temp1"}}, FRU: []models.FRUInfo{{Description: "Board"}}, }) statusReq := httptest.NewRequest(http.MethodGet, "/api/status", nil) statusRec := httptest.NewRecorder() s.handleGetStatus(statusRec, statusReq) if statusRec.Code != http.StatusOK { t.Fatalf("expected 200 from /api/status, got %d", statusRec.Code) } var statusPayload map[string]interface{} if err := json.NewDecoder(statusRec.Body).Decode(&statusPayload); err != nil { t.Fatalf("decode status payload: %v", err) } if loaded, _ := statusPayload["loaded"].(bool); !loaded { t.Fatalf("expected loaded=true") } if statusPayload["source_type"] != models.SourceTypeArchive { t.Fatalf("expected source_type in status payload") } if _, ok := statusPayload["stats"]; !ok { t.Fatalf("expected legacy stats field to remain") } configReq := httptest.NewRequest(http.MethodGet, "/api/config", nil) configRec := httptest.NewRecorder() s.handleGetConfig(configRec, configReq) if configRec.Code != http.StatusOK { t.Fatalf("expected 200 from /api/config, got %d", configRec.Code) } var configPayload map[string]interface{} if err := json.NewDecoder(configRec.Body).Decode(&configPayload); err != nil { t.Fatalf("decode config payload: %v", err) } if configPayload["source_type"] != models.SourceTypeArchive { t.Fatalf("expected source_type in config payload") } if _, ok := configPayload["hardware"]; !ok { t.Fatalf("expected legacy hardware field in config payload") } if _, ok := configPayload["specification"]; !ok { t.Fatalf("expected legacy specification field in config payload") } }