preallocate bindings capacity in dockerhub and groq, with unit tests (#5213)

* preallocate bindings capacity in dockerhub and groq, with unit tests

* ran linter
This commit is contained in:
Jordan Tunstill
2026-08-20 14:36:24 -07:00
committed by GitHub
parent 961030671f
commit 4ec774956c
4 changed files with 171 additions and 2 deletions
@@ -133,7 +133,7 @@ func secretInfoToAnalyzerResult(info *SecretInfo) *analyzers.AnalyzerResult {
result := analyzers.AnalyzerResult{
AnalyzerType: analyzers.AnalyzerTypeDockerHub,
Metadata: map[string]any{"Valid_Key": info.Valid},
Bindings: make([]analyzers.Binding, len(info.Repositories)),
Bindings: make([]analyzers.Binding, 0, len(info.Repositories)),
}
// extract information to create bindings and append to result bindings
@@ -15,6 +15,90 @@ import (
//go:embed result_output.json
var expectedOutput []byte
func repo(name string) Repository {
return Repository{
ID: "user123/repo/image/" + name,
Name: name,
Type: "image",
IsPrivate: true,
StarCount: 1,
PullCount: 2,
}
}
func TestSecretInfoToAnalyzerResult(t *testing.T) {
tests := []struct {
name string
repos []Repository
wantLen int
wantNames []string
}{
{
name: "one repository produces exactly one binding",
repos: []Repository{repo("repo1")},
wantLen: 1,
wantNames: []string{"repo1"},
},
{
name: "three repositories produce exactly three bindings, not six",
repos: []Repository{repo("repo1"), repo("repo2"), repo("repo3")},
wantLen: 3,
wantNames: []string{"repo1", "repo2", "repo3"},
},
{
name: "no repositories: no bindings",
repos: nil,
wantLen: 0,
},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
info := &SecretInfo{
Valid: true,
User: User{ID: "uuid-123", Username: "user123", Email: "[email protected]"},
Permissions: []string{"repo:admin"},
Repositories: tt.repos,
}
result := secretInfoToAnalyzerResult(info)
if result == nil {
t.Fatal("secretInfoToAnalyzerResult() returned nil")
}
if len(result.Bindings) != tt.wantLen {
t.Errorf("got %d bindings, want %d", len(result.Bindings), tt.wantLen)
}
// Mirrors the four proto min_len constraints so this test fails for
// the same reason the enterprise API does.
for i, binding := range result.Bindings {
if binding.Resource.Name == "" {
t.Errorf("binding[%d].Resource.Name is empty", i)
}
if binding.Resource.Type == "" {
t.Errorf("binding[%d].Resource.Type is empty", i)
}
if binding.Resource.FullyQualifiedName == "" {
t.Errorf("binding[%d].Resource.FullyQualifiedName is empty", i)
}
if binding.Permission.Value == "" {
t.Errorf("binding[%d].Permission.Value is empty", i)
}
}
for i, name := range tt.wantNames {
if i >= len(result.Bindings) {
break
}
if result.Bindings[i].Resource.Name != name {
t.Errorf("binding[%d].Resource.Name = %q, want %q", i, result.Bindings[i].Resource.Name, name)
}
}
})
}
}
func TestAnalyzer_Analyze(t *testing.T) {
ctx, cancel := context.WithTimeout(context.Background(), time.Minute*5)
defer cancel()
+1 -1
View File
@@ -121,7 +121,7 @@ func secretInfoToAnalyzerResult(info *SecretInfo) *analyzers.AnalyzerResult {
result := analyzers.AnalyzerResult{
AnalyzerType: analyzers.AnalyzerTypeGroq,
Metadata: map[string]any{"Valid_Key": info.Valid},
Bindings: make([]analyzers.Binding, len(info.GroqResources)),
Bindings: make([]analyzers.Binding, 0, len(info.GroqResources)),
}
// extract information to create bindings and append to result bindings
+85
View File
@@ -12,6 +12,91 @@ import (
"github.com/trufflesecurity/trufflehog/v3/pkg/context"
)
func resource(id, name, resourceType string) GroqResource {
return GroqResource{
ID: id,
Name: name,
Type: resourceType,
Permission: PermissionStrings[FullAccess],
Metadata: map[string]string{"status": "completed"},
}
}
func TestSecretInfoToAnalyzerResult(t *testing.T) {
tests := []struct {
name string
resources []GroqResource
wantLen int
wantNames []string
}{
{
name: "one resource produces exactly one binding",
resources: []GroqResource{resource("batch_123", "batch_123", "batch")},
wantLen: 1,
wantNames: []string{"batch_123"},
},
{
name: "three resources produce exactly three bindings, not six",
resources: []GroqResource{
resource("batch_123", "batch_123", "batch"),
resource("file_456", "training.jsonl", "file"),
resource("file_789", "eval.jsonl", "file"),
},
wantLen: 3,
wantNames: []string{"batch_123", "training.jsonl", "eval.jsonl"},
},
{
name: "no resources: no bindings",
resources: nil,
wantLen: 0,
},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
info := &SecretInfo{
Valid: true,
GroqResources: tt.resources,
}
result := secretInfoToAnalyzerResult(info)
if result == nil {
t.Fatal("secretInfoToAnalyzerResult() returned nil")
}
if len(result.Bindings) != tt.wantLen {
t.Errorf("got %d bindings, want %d", len(result.Bindings), tt.wantLen)
}
// Mirrors the four proto min_len constraints so this test fails for
// the same reason the enterprise API does.
for i, binding := range result.Bindings {
if binding.Resource.Name == "" {
t.Errorf("binding[%d].Resource.Name is empty", i)
}
if binding.Resource.Type == "" {
t.Errorf("binding[%d].Resource.Type is empty", i)
}
if binding.Resource.FullyQualifiedName == "" {
t.Errorf("binding[%d].Resource.FullyQualifiedName is empty", i)
}
if binding.Permission.Value == "" {
t.Errorf("binding[%d].Permission.Value is empty", i)
}
}
for i, name := range tt.wantNames {
if i >= len(result.Bindings) {
break
}
if result.Bindings[i].Resource.Name != name {
t.Errorf("binding[%d].Resource.Name = %q, want %q", i, result.Bindings[i].Resource.Name, name)
}
}
})
}
}
func TestAnalyzer_Analyze(t *testing.T) {
ctx, cancel := context.WithTimeout(context.Background(), time.Minute*5)
defer cancel()