Files
cmroubao/backend-api/internal/usecase/execution_result_service_test.go
T

132 lines
3.9 KiB
Go
Raw Normal View History

package usecase
import (
"strings"
"testing"
)
func TestValidateCandidateCommandAcceptsEmptyMatchedBatch(t *testing.T) {
command := validAIExecutionCandidateCommand()
command.Candidates = nil
command.Recommendation = nil
if err := validateCandidateCommand(command); err != nil {
t.Fatalf("validate empty matched batch: %v", err)
}
}
func TestValidateCandidateCommandAcceptsMatchedColorAndSize(t *testing.T) {
command := validAIExecutionCandidateCommand()
if err := validateCandidateCommand(command); err != nil {
t.Fatalf("validate matched candidate: %v", err)
}
}
func TestValidateCandidateCommandRejectsUnknownHardConstraint(t *testing.T) {
command := validAIExecutionCandidateCommand()
command.Candidates[0].Evaluation.HardConstraints[1].Status = "UNKNOWN"
command.Candidates[0].Evaluation.Decision = "REJECT"
command.Candidates[0].Evaluation.RejectionReasons = []string{"尺码无法确认"}
command.Recommendation = nil
if err := validateCandidateCommand(command); err != nil {
t.Fatalf("validate observed unknown hard constraint: %v", err)
}
}
func TestValidateCandidateCommandRejectsV2CandidateWithoutHardConstraints(t *testing.T) {
command := validAIExecutionCandidateCommand()
command.Candidates[0].Evaluation.HardConstraints = nil
if err := validateCandidateCommand(command); err == nil {
t.Fatal("expected missing v2 hard constraints to be rejected")
}
}
func TestValidateCandidateCommandRejectsWeakV2Candidate(t *testing.T) {
command := validAIExecutionCandidateCommand()
command.Candidates[0].Evaluation.Score = 0.74
if err := validateCandidateCommand(command); err == nil {
t.Fatal("expected weak v2 candidate to be rejected")
}
}
func TestValidateCandidateCommandAcceptsV2RecommendationUsingOriginalOrdinal(t *testing.T) {
command := validAIExecutionCandidateCommand()
second := command.Candidates[0]
second.Ordinal = 2
second.Title = "拼多多图片候选 2"
command.Candidates = append(command.Candidates, second)
command.Recommendation.CandidateOrdinal = 2
if err := validateCandidateCommand(command); err != nil {
t.Fatalf("validate recommendation using original ordinal: %v", err)
}
}
func TestValidateCandidateCommandRejectsV2RecommendationForRejectedCandidate(t *testing.T) {
command := validAIExecutionCandidateCommand()
second := command.Candidates[0]
second.Ordinal = 2
second.Title = "拼多多图片候选 2"
second.Evaluation = &CandidateEvaluation{
Decision: "REJECT",
Score: 0.2,
Confidence: 0.9,
RejectionReasons: []string{"颜色不匹配"},
}
command.Candidates = append(command.Candidates, second)
command.Recommendation.CandidateOrdinal = 2
if err := validateCandidateCommand(command); err == nil {
t.Fatal("expected recommendation for rejected candidate to be rejected")
}
}
func validAIExecutionCandidateCommand() StoreExecutionCandidatesCommand {
return StoreExecutionCandidatesCommand{
TaskContentSHA256: strings.Repeat("a", 64),
ExecutionMode: aiAssistedMode,
SearchQuery: "PDD_IMAGE_SEARCH",
Provenance: &ExecutionProvenance{
ProviderID: "openai-compatible",
Model: "test-model",
PromptVersion: "candidate-evaluation-v2",
SchemaVersion: 2,
},
Candidates: []ExecutionCandidate{
{
Ordinal: 1,
Title: "拼多多图片候选 1",
Evaluation: &CandidateEvaluation{
Decision: "REVIEW",
Score: 0.9,
Matched: []string{"图片相似"},
Confidence: 0.9,
HardConstraints: []CandidateHardConstraintEvaluation{
{
Kind: "COLOR",
Expected: "BLACK",
Status: "MATCH",
Evidence: "截图显示黑色",
},
{
Kind: "SIZE",
Expected: "L",
Status: "MATCH",
Evidence: "截图显示 L 码",
},
},
},
},
},
Recommendation: &CandidateRecommendation{
CandidateOrdinal: 1,
PolicyVersion: "sku-hard-constraints-v1",
Reasons: []string{"SKU 颜色和尺码硬约束均匹配"},
},
}
}