package sourceagent import ( "context" "testing" "time" "github.com/local/glpi-neural-brain/internal/articlequality" ) func TestExecuteArticleQualityJobIsDeterministicAndModelFree(t *testing.T) { req := ArticleQualityComputeRequest{JobID: "q1", Payload: articlequality.Request{ ArticleType: "reference", Title: "Kurze Referenz", Problem: "Ein kurzer technischer Hinweis.", Answer: "## Kernaussagen\n- T1018 beschreibt System Discovery.", Sources: []articlequality.Document{{ID: "s1", Text: "T1018 Remote System Discovery ATT&CK"}}, }} a := ExecuteArticleQualityJob(req) b := ExecuteArticleQualityJob(req) if a.Quality.Algorithm != articlequality.Algorithm || b.Quality.Algorithm != articlequality.Algorithm { t.Fatalf("unexpected algorithm: %+v %+v", a.Quality, b.Quality) } if a.Quality.Passed || b.Quality.Passed || a.Quality.Score != b.Quality.Score || a.Quality.WordCount != b.Quality.WordCount { t.Fatalf("article quality CPU result must be deterministic and reject the short reference: %+v %+v", a.Quality, b.Quality) } } func TestArticleQualityComputeClaimCompleteLifecycle(t *testing.T) { s := &Store{articleQualityJobs: map[string]*articleQualityJobState{}} ctx, cancel := context.WithTimeout(context.Background(), time.Second) defer cancel() done := make(chan ArticleQualityComputeResult, 1) errCh := make(chan error, 1) go func() { res, err := s.SubmitArticleQualityJob(ctx, ArticleQualityComputeRequest{JobID: "job-1", Payload: articlequality.Request{ArticleType: "reference", Title: "T", Answer: "kurz"}}) if err != nil { errCh <- err return } done <- res }() deadline := time.Now().Add(500 * time.Millisecond) var job ArticleQualityComputeRequest var ok bool for time.Now().Before(deadline) { job, ok = s.ClaimArticleQualityJob("agent-1", time.Minute) if ok { break } time.Sleep(time.Millisecond) } if !ok || job.JobID != "job-1" { t.Fatalf("job was not claimable: %+v ok=%v", job, ok) } result := ExecuteArticleQualityJob(job) if err := s.CompleteArticleQualityJob("agent-1", result); err != nil { t.Fatal(err) } select { case err := <-errCh: t.Fatal(err) case res := <-done: if res.JobID != "job-1" || res.Quality.Algorithm != articlequality.Algorithm { t.Fatalf("unexpected completed result: %+v", res) } case <-ctx.Done(): t.Fatal("timed out waiting for completed quality job") } }