Avoid copying output during basic validation
This commit is contained in:
@@ -151,7 +151,8 @@ control into the rendered prompt. The
|
|||||||
`internal/validate` provides validators backed by an operating-system
|
`internal/validate` provides validators backed by an operating-system
|
||||||
filesystem or an `fs.FS`. Invalid generated content is returned as a validation
|
filesystem or an `fs.FS`. Invalid generated content is returned as a validation
|
||||||
result; inability to load, register, or compile a schema is an operational
|
result; inability to load, register, or compile a schema is an operational
|
||||||
error.
|
error. Basic validation checks body emptiness on the byte slice directly
|
||||||
|
instead of first making a response-sized string copy.
|
||||||
|
|
||||||
Every preparation operation creates one operation-local validation plan. None,
|
Every preparation operation creates one operation-local validation plan. None,
|
||||||
basic, and JSON modes retain the effective output contract without source
|
basic, and JSON modes retain the effective output contract without source
|
||||||
|
|||||||
@@ -188,7 +188,7 @@ func validateArtifact(ctx context.Context, artifact *domain.Artifact, contract d
|
|||||||
res.IsValid = true
|
res.IsValid = true
|
||||||
return res, nil
|
return res, nil
|
||||||
case domain.ValidationBasic:
|
case domain.ValidationBasic:
|
||||||
empty := strings.TrimSpace(string(artifact.Body)) == ""
|
empty := len(bytes.TrimSpace(artifact.Body)) == 0
|
||||||
if err := ctx.Err(); err != nil {
|
if err := ctx.Err(); err != nil {
|
||||||
return domain.ValidationResult{}, err
|
return domain.ValidationResult{}, err
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -36,8 +36,15 @@ func TestStandardValidatorNoneSkipped(t *testing.T) {
|
|||||||
|
|
||||||
func TestStandardValidatorBasicSuccess(t *testing.T) {
|
func TestStandardValidatorBasicSuccess(t *testing.T) {
|
||||||
v := NewStandardValidator("")
|
v := NewStandardValidator("")
|
||||||
|
for _, tc := range []struct {
|
||||||
res, err := v.Validate(context.Background(), &domain.Artifact{Body: []byte("hello")}, domain.OutputContract{
|
name string
|
||||||
|
body []byte
|
||||||
|
}{
|
||||||
|
{name: "text", body: []byte("hello")},
|
||||||
|
{name: "invalid UTF-8 byte", body: []byte{0xff}},
|
||||||
|
} {
|
||||||
|
t.Run(tc.name, func(t *testing.T) {
|
||||||
|
res, err := v.Validate(context.Background(), &domain.Artifact{Body: tc.body}, domain.OutputContract{
|
||||||
ValidationMode: domain.ValidationBasic,
|
ValidationMode: domain.ValidationBasic,
|
||||||
})
|
})
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@@ -46,12 +53,22 @@ func TestStandardValidatorBasicSuccess(t *testing.T) {
|
|||||||
if res.Status != domain.ValidationPassed || !res.IsValid {
|
if res.Status != domain.ValidationPassed || !res.IsValid {
|
||||||
t.Fatalf("expected passed/valid, got status=%q valid=%v", res.Status, res.IsValid)
|
t.Fatalf("expected passed/valid, got status=%q valid=%v", res.Status, res.IsValid)
|
||||||
}
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestStandardValidatorBasicFailureEmpty(t *testing.T) {
|
func TestStandardValidatorBasicFailureEmpty(t *testing.T) {
|
||||||
v := NewStandardValidator("")
|
v := NewStandardValidator("")
|
||||||
|
for _, tc := range []struct {
|
||||||
res, err := v.Validate(context.Background(), &domain.Artifact{Body: []byte(" \n\t ")}, domain.OutputContract{
|
name string
|
||||||
|
body []byte
|
||||||
|
}{
|
||||||
|
{name: "empty bytes", body: []byte{}},
|
||||||
|
{name: "ASCII whitespace", body: []byte(" \n\t ")},
|
||||||
|
{name: "Unicode whitespace", body: []byte("\u2003\u00a0\u3000")},
|
||||||
|
} {
|
||||||
|
t.Run(tc.name, func(t *testing.T) {
|
||||||
|
res, err := v.Validate(context.Background(), &domain.Artifact{Body: tc.body}, domain.OutputContract{
|
||||||
ValidationMode: domain.ValidationBasic,
|
ValidationMode: domain.ValidationBasic,
|
||||||
})
|
})
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@@ -63,6 +80,8 @@ func TestStandardValidatorBasicFailureEmpty(t *testing.T) {
|
|||||||
if len(res.Errors) == 0 {
|
if len(res.Errors) == 0 {
|
||||||
t.Fatal("expected validation errors")
|
t.Fatal("expected validation errors")
|
||||||
}
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestStandardValidatorReportsZeroRepairAttempts(t *testing.T) {
|
func TestStandardValidatorReportsZeroRepairAttempts(t *testing.T) {
|
||||||
@@ -947,7 +966,8 @@ func BenchmarkBasicValidation(b *testing.B) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
b.ReportAllocs()
|
b.ReportAllocs()
|
||||||
b.SetBytes(int64(len(benchmark.body)))
|
// Nonempty input can be classified from its boundary bytes without
|
||||||
|
// scanning the body, so report latency rather than bytes per second.
|
||||||
b.ResetTimer()
|
b.ResetTimer()
|
||||||
for range b.N {
|
for range b.N {
|
||||||
result, err := validator.Validate(ctx, artifact, contract)
|
result, err := validator.Validate(ctx, artifact, contract)
|
||||||
|
|||||||
Reference in New Issue
Block a user