package helpers import ( "testing" "github.com/jfraeys/fetch_ml/internal/api/helpers" "github.com/jfraeys/fetch_ml/internal/manifest" "github.com/jfraeys/fetch_ml/internal/queue" ) func TestValidateCommitIDFormat(t *testing.T) { tests := []struct { name string commitID string wantOk bool wantErr string }{ { name: "valid commit ID", commitID: "aabbccddeeff00112233445566778899aabbccdd", wantOk: true, wantErr: "", }, { name: "too short", commitID: "aabbcc", wantOk: false, wantErr: "invalid commit_id length", }, { name: "too long", commitID: "aabbccddeeff00112233445566778899aabbccddeeff", wantOk: false, wantErr: "invalid commit_id length", }, { name: "invalid hex", commitID: "gggggggggggggggggggggggggggggggggggggggg", wantOk: false, wantErr: "invalid commit_id hex", }, { name: "mixed case valid", commitID: "AABBCCDDEEFF00112233445566778899AABBCCDD", wantOk: true, wantErr: "", }, { name: "empty", commitID: "", wantOk: false, wantErr: "invalid commit_id length", }, } for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { gotOk, gotErr := helpers.ValidateCommitIDFormat(tt.commitID) if gotOk != tt.wantOk { t.Errorf("ValidateCommitIDFormat() ok = %v, want %v", gotOk, tt.wantOk) } if gotErr != tt.wantErr { t.Errorf("ValidateCommitIDFormat() err = %q, want %q", gotErr, tt.wantErr) } }) } } func TestShouldRequireRunManifest(t *testing.T) { tests := []struct { name string status string want bool }{ {"running", "running", true}, {"completed", "completed", true}, {"failed", "failed", true}, {"queued", "queued", false}, {"pending", "pending", false}, {"cancelled", "cancelled", false}, {"unknown", "unknown", false}, {"empty", "", false}, {"RUNNING uppercase", "RUNNING", true}, {"Completed mixed", "Completed", true}, {" Running with space", " running", true}, } for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { task := &queue.Task{Status: tt.status} got := helpers.ShouldRequireRunManifest(task) if got != tt.want { t.Errorf("ShouldRequireRunManifest() = %v, want %v", got, tt.want) } }) } } func TestExpectedRunManifestBucketForStatus(t *testing.T) { tests := []struct { name string status string wantBucket string wantOk bool }{ {"queued", "queued", "pending", true}, {"pending", "pending", "pending", true}, {"running", "running", "running", true}, {"completed", "completed", "finished", true}, {"finished", "finished", "finished", true}, {"failed", "failed", "failed", true}, {"unknown", "unknown", "", false}, {"empty", "", "", false}, {"RUNNING uppercase", "RUNNING", "running", true}, } for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { gotBucket, gotOk := helpers.ExpectedRunManifestBucketForStatus(tt.status) if gotBucket != tt.wantBucket { t.Errorf("ExpectedRunManifestBucketForStatus() bucket = %q, want %q", gotBucket, tt.wantBucket) } if gotOk != tt.wantOk { t.Errorf("ExpectedRunManifestBucketForStatus() ok = %v, want %v", gotOk, tt.wantOk) } }) } } func TestValidateTaskIDMatch(t *testing.T) { tests := []struct { name string rmTaskID string expectedID string wantOk bool wantExpected string wantActual string }{ { name: "match", rmTaskID: "task-123", expectedID: "task-123", wantOk: true, wantExpected: "task-123", wantActual: "task-123", }, { name: "mismatch", rmTaskID: "task-123", expectedID: "task-456", wantOk: false, wantExpected: "task-456", wantActual: "task-123", }, { name: "empty rm task ID", rmTaskID: "", expectedID: "task-123", wantOk: false, wantExpected: "task-123", wantActual: "", }, { name: "whitespace trimmed - match", rmTaskID: "task-123", expectedID: "task-123", wantOk: true, wantExpected: "task-123", wantActual: "task-123", }, } for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { rm := &manifest.RunManifest{TaskID: tt.rmTaskID} got := helpers.ValidateTaskIDMatch(rm, tt.expectedID) if got.OK != tt.wantOk { t.Errorf("ValidateTaskIDMatch() OK = %v, want %v", got.OK, tt.wantOk) } if got.Expected != tt.wantExpected { t.Errorf("ValidateTaskIDMatch() Expected = %q, want %q", got.Expected, tt.wantExpected) } if got.Actual != tt.wantActual { t.Errorf("ValidateTaskIDMatch() Actual = %q, want %q", got.Actual, tt.wantActual) } }) } } func TestValidateCommitIDMatch(t *testing.T) { tests := []struct { name string rmCommitID string expectedID string wantOk bool wantExpected string wantActual string }{ { name: "both empty", rmCommitID: "", expectedID: "", wantOk: true, wantExpected: "", wantActual: "", }, { name: "match", rmCommitID: "abc123", expectedID: "abc123", wantOk: true, wantExpected: "abc123", wantActual: "abc123", }, { name: "mismatch", rmCommitID: "abc123", expectedID: "def456", wantOk: false, wantExpected: "def456", wantActual: "abc123", }, { name: "expected empty", rmCommitID: "abc123", expectedID: "", wantOk: true, wantExpected: "", wantActual: "", }, { name: "rm empty", rmCommitID: "", expectedID: "abc123", wantOk: true, wantExpected: "abc123", wantActual: "", }, { name: "whitespace trimmed", rmCommitID: " abc123 ", expectedID: "abc123", wantOk: true, wantExpected: "abc123", wantActual: "abc123", }, } for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { got := helpers.ValidateCommitIDMatch(tt.rmCommitID, tt.expectedID) if got.OK != tt.wantOk { t.Errorf("ValidateCommitIDMatch() OK = %v, want %v", got.OK, tt.wantOk) } if got.Expected != tt.wantExpected { t.Errorf("ValidateCommitIDMatch() Expected = %q, want %q", got.Expected, tt.wantExpected) } if got.Actual != tt.wantActual { t.Errorf("ValidateCommitIDMatch() Actual = %q, want %q", got.Actual, tt.wantActual) } }) } } func TestValidateDepsProvenance(t *testing.T) { tests := []struct { name string wantName string wantSHA string gotName string gotSHA string wantOk bool wantExpected string wantActual string }{ { name: "match", wantName: "requirements.txt", wantSHA: "abc123", gotName: "requirements.txt", gotSHA: "abc123", wantOk: true, wantExpected: "requirements.txt:abc123", wantActual: "requirements.txt:abc123", }, { name: "name mismatch", wantName: "requirements.txt", wantSHA: "abc123", gotName: "Pipfile", gotSHA: "abc123", wantOk: false, wantExpected: "requirements.txt:abc123", wantActual: "Pipfile:abc123", }, { name: "sha mismatch", wantName: "requirements.txt", wantSHA: "abc123", gotName: "requirements.txt", gotSHA: "def456", wantOk: false, wantExpected: "requirements.txt:abc123", wantActual: "requirements.txt:def456", }, { name: "want empty", wantName: "", wantSHA: "", gotName: "requirements.txt", gotSHA: "abc123", wantOk: true, wantExpected: "", wantActual: "", }, { name: "got empty", wantName: "requirements.txt", wantSHA: "abc123", gotName: "", gotSHA: "", wantOk: true, wantExpected: "", wantActual: "", }, { name: "both empty", wantName: "", wantSHA: "", gotName: "", gotSHA: "", wantOk: true, wantExpected: "", wantActual: "", }, } for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { got := helpers.ValidateDepsProvenance(tt.wantName, tt.wantSHA, tt.gotName, tt.gotSHA) if got.OK != tt.wantOk { t.Errorf("ValidateDepsProvenance() OK = %v, want %v", got.OK, tt.wantOk) } if got.Expected != tt.wantExpected { t.Errorf("ValidateDepsProvenance() Expected = %q, want %q", got.Expected, tt.wantExpected) } if got.Actual != tt.wantActual { t.Errorf("ValidateDepsProvenance() Actual = %q, want %q", got.Actual, tt.wantActual) } }) } } func TestValidateSnapshotID(t *testing.T) { tests := []struct { name string wantID string gotID string wantOk bool wantExpected string wantActual string }{ { name: "match", wantID: "snap-123", gotID: "snap-123", wantOk: true, wantExpected: "snap-123", wantActual: "snap-123", }, { name: "mismatch", wantID: "snap-123", gotID: "snap-456", wantOk: false, wantExpected: "snap-123", wantActual: "snap-456", }, { name: "want empty", wantID: "", gotID: "snap-123", wantOk: true, wantExpected: "", wantActual: "snap-123", }, { name: "got empty", wantID: "snap-123", gotID: "", wantOk: true, wantExpected: "snap-123", wantActual: "", }, { name: "both empty", wantID: "", gotID: "", wantOk: true, wantExpected: "", wantActual: "", }, } for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { got := helpers.ValidateSnapshotID(tt.wantID, tt.gotID) if got.OK != tt.wantOk { t.Errorf("ValidateSnapshotID() OK = %v, want %v", got.OK, tt.wantOk) } if got.Expected != tt.wantExpected { t.Errorf("ValidateSnapshotID() Expected = %q, want %q", got.Expected, tt.wantExpected) } if got.Actual != tt.wantActual { t.Errorf("ValidateSnapshotID() Actual = %q, want %q", got.Actual, tt.wantActual) } }) } } func TestValidateSnapshotSHA(t *testing.T) { tests := []struct { name string wantSHA string gotSHA string wantOk bool wantExpected string wantActual string }{ { name: "match", wantSHA: "sha256:abc123", gotSHA: "sha256:abc123", wantOk: true, wantExpected: "sha256:abc123", wantActual: "sha256:abc123", }, { name: "mismatch", wantSHA: "sha256:abc123", gotSHA: "sha256:def456", wantOk: false, wantExpected: "sha256:abc123", wantActual: "sha256:def456", }, { name: "want empty", wantSHA: "", gotSHA: "sha256:abc123", wantOk: true, wantExpected: "", wantActual: "sha256:abc123", }, { name: "got empty", wantSHA: "sha256:abc123", gotSHA: "", wantOk: true, wantExpected: "sha256:abc123", wantActual: "", }, { name: "both empty", wantSHA: "", gotSHA: "", wantOk: true, wantExpected: "", wantActual: "", }, } for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { got := helpers.ValidateSnapshotSHA(tt.wantSHA, tt.gotSHA) if got.OK != tt.wantOk { t.Errorf("ValidateSnapshotSHA() OK = %v, want %v", got.OK, tt.wantOk) } if got.Expected != tt.wantExpected { t.Errorf("ValidateSnapshotSHA() Expected = %q, want %q", got.Expected, tt.wantExpected) } if got.Actual != tt.wantActual { t.Errorf("ValidateSnapshotSHA() Actual = %q, want %q", got.Actual, tt.wantActual) } }) } }