Files
apex-public/internal/eval/batch_test.go
T
2026-07-06 11:05:50 -04:00

110 lines
2.9 KiB
Go

package eval
import (
"context"
"database/sql"
"testing"
"time"
_ "modernc.org/sqlite"
)
func TestBatch_EmptyInputClosesChannel(t *testing.T) {
b := &Batch{Concurrency: 3}
ch := b.Run(context.Background(), nil)
select {
case _, ok := <-ch:
if ok {
t.Fatal("expected closed channel for empty input")
}
case <-time.After(100 * time.Millisecond):
t.Fatal("channel did not close")
}
}
func TestBatch_NilClientErrorsEveryJob(t *testing.T) {
b := &Batch{Concurrency: 2}
jobs := []JobContext{
{URL: "https://a", Company: "A", Title: "T"},
{URL: "https://b", Company: "B", Title: "T"},
}
ch := b.Run(context.Background(), jobs)
var starts, errors int
for ev := range ch {
switch ev.Kind {
case EventStart:
starts++
case EventError:
errors++
case EventDone:
t.Fatalf("unexpected EventDone with nil client")
}
}
if starts != 2 || errors != 2 {
t.Errorf("starts=%d errors=%d, want 2/2", starts, errors)
}
}
func TestBatch_DemoteBelowMinScore(t *testing.T) {
db := setupReportDB(t)
defer db.Close()
// Seed a job + application row (Evaluated, score=3.0).
if _, err := db.Exec(`INSERT INTO jobs (url, company, title, source) VALUES (?, ?, ?, ?)`,
"https://x/1", "Acme", "Engineer", "test"); err != nil {
t.Fatal(err)
}
var jobID int64
if err := db.QueryRow(`SELECT id FROM jobs WHERE url = ?`, "https://x/1").Scan(&jobID); err != nil {
t.Fatal(err)
}
res, err := db.Exec(`INSERT INTO applications (job_id, status, score) VALUES (?, 'Evaluated', 3.0)`, jobID)
if err != nil {
t.Fatal(err)
}
appID, _ := res.LastInsertId()
b := &Batch{DB: db, MinScore: 4.0}
if err := b.demoteBelowScore(context.Background(), appID); err != nil {
t.Fatalf("demote: %v", err)
}
var status string
if err := db.QueryRow(`SELECT status FROM applications WHERE id = ?`, appID).Scan(&status); err != nil {
t.Fatal(err)
}
if status != "Discarded" {
t.Errorf("status = %q, want Discarded", status)
}
// Now set the row to Applied and re-run demote — it must NOT regress.
if _, err := db.Exec(`UPDATE applications SET status = 'Applied' WHERE id = ?`, appID); err != nil {
t.Fatal(err)
}
if err := b.demoteBelowScore(context.Background(), appID); err != nil {
t.Fatalf("demote#2: %v", err)
}
_ = db.QueryRow(`SELECT status FROM applications WHERE id = ?`, appID).Scan(&status)
if status != "Applied" {
t.Errorf("user-advanced status must be preserved, got %q", status)
}
}
// silence unused-import warning when the only test using sql is compiled out.
var _ = (*sql.DB)(nil)
func TestBatch_ContextCanceledBeforeStart(t *testing.T) {
b := &Batch{Concurrency: 1}
jobs := []JobContext{{URL: "https://x", Company: "X", Title: "T"}}
ctx, cancel := context.WithCancel(context.Background())
cancel()
ch := b.Run(ctx, jobs)
var errs int
for ev := range ch {
if ev.Kind == EventError {
errs++
}
}
if errs != 1 {
t.Errorf("expected 1 error from canceled batch, got %d", errs)
}
}