package importer import ( "bytes" "os" "strings" "testing" ) func loadFixture(t *testing.T, name string) []byte { t.Helper() data, err := os.ReadFile("testdata/" + name) if err != nil { t.Fatalf("read fixture %s: %v", name, err) } return data } func TestGitleaksImporter_Name(t *testing.T) { if (GitleaksImporter{}).Name() != "gitleaks" { t.Errorf("GitleaksImporter.Name() = %q, want %q", (GitleaksImporter{}).Name(), "gitleaks") } if (GitleaksCSVImporter{}).Name() != "gitleaks-csv" { t.Errorf("GitleaksCSVImporter.Name() = %q, want %q", (GitleaksCSVImporter{}).Name(), "gitleaks-csv") } } func TestGitleaksImporter_JSON(t *testing.T) { data := loadFixture(t, "gitleaks-sample.json") findings, err := (GitleaksImporter{}).Import(bytes.NewReader(data)) if err != nil { t.Fatalf("Import: %v", err) } if len(findings) != 3 { t.Fatalf("expected 3 findings, got %d", len(findings)) } if findings[0].ProviderName != "openai" { t.Errorf("findings[0].ProviderName = %q, want %q", findings[0].ProviderName, "openai") } if findings[0].KeyValue != "sk-proj-1234567890abcdef1234" { t.Errorf("findings[0].KeyValue mismatch: %q", findings[0].KeyValue) } if findings[0].Source != "config/app.yml" { t.Errorf("findings[0].Source = %q", findings[0].Source) } if findings[0].LineNumber != 12 { t.Errorf("findings[0].LineNumber = %d, want 12", findings[0].LineNumber) } if findings[0].SourceType != "import:gitleaks" { t.Errorf("findings[0].SourceType = %q", findings[0].SourceType) } if findings[0].Confidence != "medium" { t.Errorf("findings[0].Confidence = %q, want medium", findings[0].Confidence) } if findings[0].VerifyStatus != "unverified" { t.Errorf("findings[0].VerifyStatus = %q, want unverified", findings[0].VerifyStatus) } if findings[0].Verified { t.Errorf("findings[0].Verified should be false") } if findings[0].KeyMasked == "" { t.Errorf("findings[0].KeyMasked should be set") } if findings[1].ProviderName != "aws" { t.Errorf("findings[1].ProviderName = %q, want aws", findings[1].ProviderName) } if findings[1].LineNumber != 55 { t.Errorf("findings[1].LineNumber = %d, want 55", findings[1].LineNumber) } if findings[2].ProviderName != "generic" { t.Errorf("findings[2].ProviderName = %q, want generic", findings[2].ProviderName) } } func TestGitleaksImporter_CSV(t *testing.T) { data := loadFixture(t, "gitleaks-sample.csv") findings, err := (GitleaksCSVImporter{}).Import(bytes.NewReader(data)) if err != nil { t.Fatalf("Import: %v", err) } if len(findings) != 3 { t.Fatalf("expected 3 findings, got %d", len(findings)) } if findings[0].ProviderName != "openai" { t.Errorf("findings[0].ProviderName = %q, want openai", findings[0].ProviderName) } if findings[0].KeyValue != "sk-proj-1234567890abcdef1234" { t.Errorf("findings[0].KeyValue = %q", findings[0].KeyValue) } if findings[0].Source != "config/app.yml" { t.Errorf("findings[0].Source = %q", findings[0].Source) } if findings[0].LineNumber != 12 { t.Errorf("findings[0].LineNumber = %d, want 12", findings[0].LineNumber) } if findings[1].ProviderName != "aws" { t.Errorf("findings[1].ProviderName = %q, want aws", findings[1].ProviderName) } if findings[2].ProviderName != "generic" { t.Errorf("findings[2].ProviderName = %q, want generic", findings[2].ProviderName) } } func TestGitleaksImporter_NormalizeRuleID(t *testing.T) { cases := []struct{ in, out string }{ {"openai-api-key", "openai"}, {"aws-access-token", "aws"}, {"anthropic-api-key", "anthropic"}, {"generic-api-key", "generic"}, {"github-pat", "github-pat"}, {"Some-Secret", "some"}, {"AWS-Access-Token", "aws"}, } for _, c := range cases { got := normalizeGitleaksRuleID(c.in) if got != c.out { t.Errorf("normalizeGitleaksRuleID(%q) = %q, want %q", c.in, got, c.out) } } } func TestGitleaksImporter_EmptyArray(t *testing.T) { findings, err := (GitleaksImporter{}).Import(strings.NewReader("[]")) if err != nil { t.Fatalf("Import: %v", err) } if len(findings) != 0 { t.Errorf("expected 0 findings, got %d", len(findings)) } } func TestGitleaksImporter_EmptyCSV(t *testing.T) { header := "RuleID,Commit,File,SymlinkFile,Secret,Match,StartLine,EndLine,StartColumn,EndColumn,Author,Message,Date,Email,Fingerprint,Tags\n" findings, err := (GitleaksCSVImporter{}).Import(strings.NewReader(header)) if err != nil { t.Fatalf("Import: %v", err) } if len(findings) != 0 { t.Errorf("expected 0 findings, got %d", len(findings)) } } func TestGitleaksImporter_InvalidJSON(t *testing.T) { _, err := (GitleaksImporter{}).Import(strings.NewReader("{not json")) if err == nil { t.Errorf("expected error for invalid JSON") } } func TestGitleaksImporter_SymlinkFallback(t *testing.T) { jsonInput := `[{"RuleID":"openai-api-key","Secret":"sk-proj-1234567890abcdef1234","File":"","SymlinkFile":"link/config.yml","StartLine":1}]` findings, err := (GitleaksImporter{}).Import(strings.NewReader(jsonInput)) if err != nil { t.Fatalf("Import: %v", err) } if len(findings) != 1 || findings[0].Source != "link/config.yml" { t.Errorf("expected symlink fallback source, got %+v", findings) } }