Share self-contained schema compilation
This commit is contained in:
@@ -314,6 +314,10 @@ framing, containment, and freezing cases. External-reference successes become
|
|||||||
expected errors. Root compilation alone is intentionally not the completed
|
expected errors. Root compilation alone is intentionally not the completed
|
||||||
self-containment remedy; Stage 12 checks otherwise unused schema declarations.
|
self-containment remedy; Stage 12 checks otherwise unused schema declarations.
|
||||||
|
|
||||||
|
Completion: host and filesystem validation share root-document compilation with
|
||||||
|
a context-aware external-resource rejection loader. Focused validation tests
|
||||||
|
pass on Go 1.27.3; checking unused declarations remains in the following unit.
|
||||||
|
|
||||||
## Stage 12: Check Declared Schema Locations Through The Compiler
|
## Stage 12: Check Declared Schema Locations Through The Compiler
|
||||||
|
|
||||||
**Catalog:** 6, 21, resource-policy completion. **Scope:** schema-location traversal.
|
**Catalog:** 6, 21, resource-policy completion. **Scope:** schema-location traversal.
|
||||||
|
|||||||
@@ -35,14 +35,13 @@ func TestValidationCancellationBeforeWorkDoesNotOpenSchemaSource(t *testing.T) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestValidationCancellationBetweenReferencedSchemaReadChunks(t *testing.T) {
|
func TestValidationCancellationBetweenRootSchemaReadChunks(t *testing.T) {
|
||||||
ctx, cancel := context.WithCancel(context.Background())
|
ctx, cancel := context.WithCancel(context.Background())
|
||||||
source := &controlledSchemaFS{
|
source := &controlledSchemaFS{
|
||||||
FS: fstest.MapFS{
|
FS: fstest.MapFS{
|
||||||
"root.json": {Data: []byte(`{"$ref":"child.json"}`)},
|
"root.json": {Data: []byte(`{"type":"string"}` + strings.Repeat(" ", schemaReadChunkSize*2))},
|
||||||
"child.json": {Data: []byte(`{"type":"string"}` + strings.Repeat(" ", schemaReadChunkSize*2))},
|
|
||||||
},
|
},
|
||||||
target: "child.json",
|
target: "root.json",
|
||||||
cancel: cancel,
|
cancel: cancel,
|
||||||
}
|
}
|
||||||
validator := NewFSValidator(source, ".")
|
validator := NewFSValidator(source, ".")
|
||||||
@@ -57,8 +56,8 @@ func TestValidationCancellationBetweenReferencedSchemaReadChunks(t *testing.T) {
|
|||||||
if reads := source.reads.Load(); reads != 1 {
|
if reads := source.reads.Load(); reads != 1 {
|
||||||
t.Fatalf("controlled child reads = %d, want 1", reads)
|
t.Fatalf("controlled child reads = %d, want 1", reads)
|
||||||
}
|
}
|
||||||
if closes := source.closes.Load(); closes != 1 {
|
if closes := source.closes.Load(); closes != 2 {
|
||||||
t.Fatalf("controlled child closes = %d, want 1", closes)
|
t.Fatalf("controlled root closes = %d, want stat and read handles closed", closes)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -75,51 +75,23 @@ func (v *StandardValidator) PrepareValidation(ctx context.Context, contract doma
|
|||||||
if err := ctx.Err(); err != nil {
|
if err := ctx.Err(); err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
prepared := &preparedValidation{contract: contract}
|
prepared := &preparedValidation{contract: contract}
|
||||||
if contract.ValidationMode != domain.ValidationJSONSchema {
|
if contract.ValidationMode != domain.ValidationJSONSchema {
|
||||||
return prepared, nil
|
return prepared, nil
|
||||||
}
|
}
|
||||||
|
name, err := v.resolveSchemaPath(ctx, contract.SchemaPath)
|
||||||
resolvedSchemaPath, err := v.resolveSchemaPath(ctx, contract.SchemaPath)
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
schemaDocument, err := loadJSONSchemaFile(ctx, resolvedSchemaPath)
|
document, err := loadJSONSchemaFile(ctx, name)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, fmt.Errorf("failed to compile JSON schema %q: %w", resolvedSchemaPath, err)
|
return nil, fmt.Errorf("failed to compile JSON schema %q: %w", name, err)
|
||||||
}
|
}
|
||||||
schemaRoot, err := v.schemaRoot()
|
schema, err := compileSchemaDocument(ctx, fileSchemaResourceURL(name).String(), document)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, fmt.Errorf("failed to compile JSON schema %q: %w", name, err)
|
||||||
}
|
}
|
||||||
if err := ctx.Err(); err != nil {
|
prepared.schemaDocument, prepared.schema = document, schema
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
compiler := newSchemaCompiler(standardSchemaLoader{ctx: ctx, root: schemaRoot})
|
|
||||||
resourceURL := fileSchemaResourceURL(resolvedSchemaPath)
|
|
||||||
if err := ctx.Err(); err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
if err := compiler.AddResource(resourceURL.String(), schemaDocument); err != nil {
|
|
||||||
if contextErr := ctx.Err(); contextErr != nil {
|
|
||||||
return nil, contextErr
|
|
||||||
}
|
|
||||||
return nil, fmt.Errorf("failed to register JSON schema %q: %w", resolvedSchemaPath, err)
|
|
||||||
}
|
|
||||||
if err := ctx.Err(); err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
schema, err := compileJSONSchema(ctx, resourceURL.String(), compiler.Compile)
|
|
||||||
if err != nil {
|
|
||||||
return nil, fmt.Errorf("failed to compile JSON schema %q: %w", resolvedSchemaPath, err)
|
|
||||||
}
|
|
||||||
if err := ctx.Err(); err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
|
|
||||||
prepared.schemaDocument = schemaDocument
|
|
||||||
prepared.schema = schema
|
|
||||||
return prepared, nil
|
return prepared, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -127,40 +99,19 @@ func (v *FSValidator) PrepareValidation(ctx context.Context, contract domain.Out
|
|||||||
if err := ctx.Err(); err != nil {
|
if err := ctx.Err(); err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
prepared := &preparedValidation{contract: contract}
|
prepared := &preparedValidation{contract: contract}
|
||||||
if contract.ValidationMode != domain.ValidationJSONSchema {
|
if contract.ValidationMode != domain.ValidationJSONSchema {
|
||||||
return prepared, nil
|
return prepared, nil
|
||||||
}
|
}
|
||||||
|
name, document, err := v.loadSchemaDocument(ctx, contract.SchemaPath)
|
||||||
schemaName, schemaDocument, err := v.loadSchemaDocument(ctx, contract.SchemaPath)
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
resourceURL := fsSchemaResourceURL(schemaName)
|
schema, err := compileSchemaDocument(ctx, fsSchemaResourceURL(name).String(), document)
|
||||||
compiler := newSchemaCompiler(fsSchemaLoader{ctx: ctx, fsys: v.fsys, root: filecatalog.CleanFSRoot(v.root)})
|
|
||||||
if err := ctx.Err(); err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
if err := compiler.AddResource(resourceURL.String(), schemaDocument); err != nil {
|
|
||||||
if contextErr := ctx.Err(); contextErr != nil {
|
|
||||||
return nil, contextErr
|
|
||||||
}
|
|
||||||
return nil, fmt.Errorf("failed to register JSON schema %q: %w", schemaName, err)
|
|
||||||
}
|
|
||||||
if err := ctx.Err(); err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
schema, err := compileJSONSchema(ctx, resourceURL.String(), compiler.Compile)
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, fmt.Errorf("failed to compile JSON schema %q: %w", schemaName, err)
|
return nil, fmt.Errorf("failed to compile JSON schema %q: %w", name, err)
|
||||||
}
|
}
|
||||||
if err := ctx.Err(); err != nil {
|
prepared.schemaDocument, prepared.schema = document, schema
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
|
|
||||||
prepared.schemaDocument = schemaDocument
|
|
||||||
prepared.schema = schema
|
|
||||||
return prepared, nil
|
return prepared, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -247,56 +198,30 @@ func validateArtifact(ctx context.Context, artifact *domain.Artifact, contract d
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (v *StandardValidator) validateJSONSchema(ctx context.Context, instance any, schemaPath string) ([]string, error) {
|
func (v *StandardValidator) validateJSONSchema(ctx context.Context, instance any, schemaPath string) ([]string, error) {
|
||||||
resolvedSchemaPath, err := v.resolveSchemaPath(ctx, schemaPath)
|
name, err := v.resolveSchemaPath(ctx, schemaPath)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
document, err := loadJSONSchemaFile(ctx, name)
|
||||||
schemaRoot, err := v.schemaRoot()
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, fmt.Errorf("failed to compile JSON schema %q: %w", name, err)
|
||||||
}
|
}
|
||||||
if err := ctx.Err(); err != nil {
|
schema, err := compileSchemaDocument(ctx, fileSchemaResourceURL(name).String(), document)
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
compiler := newSchemaCompiler(standardSchemaLoader{ctx: ctx, root: schemaRoot})
|
|
||||||
resourceURL := fileSchemaResourceURL(resolvedSchemaPath)
|
|
||||||
schema, err := compileJSONSchema(ctx, resourceURL.String(), compiler.Compile)
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, fmt.Errorf("failed to compile JSON schema %q: %w", resolvedSchemaPath, err)
|
return nil, fmt.Errorf("failed to compile JSON schema %q: %w", name, err)
|
||||||
}
|
}
|
||||||
|
|
||||||
return executeJSONSchema(ctx, schema, instance)
|
return executeJSONSchema(ctx, schema, instance)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (v *FSValidator) validateJSONSchema(ctx context.Context, instance any, schemaPath string) ([]string, error) {
|
func (v *FSValidator) validateJSONSchema(ctx context.Context, instance any, schemaPath string) ([]string, error) {
|
||||||
schemaName, schemaDoc, err := v.loadSchemaDocument(ctx, schemaPath)
|
name, document, err := v.loadSchemaDocument(ctx, schemaPath)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
schema, err := compileSchemaDocument(ctx, fsSchemaResourceURL(name).String(), document)
|
||||||
resourceURL := fsSchemaResourceURL(schemaName)
|
|
||||||
if err := validateSchemaDialect(schemaDoc); err != nil {
|
|
||||||
return nil, fmt.Errorf("failed to compile JSON schema %q: %w", schemaName, err)
|
|
||||||
}
|
|
||||||
compiler := newSchemaCompiler(fsSchemaLoader{ctx: ctx, fsys: v.fsys, root: filecatalog.CleanFSRoot(v.root)})
|
|
||||||
if err := ctx.Err(); err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
if err := compiler.AddResource(resourceURL.String(), schemaDoc); err != nil {
|
|
||||||
if contextErr := ctx.Err(); contextErr != nil {
|
|
||||||
return nil, contextErr
|
|
||||||
}
|
|
||||||
return nil, fmt.Errorf("failed to register JSON schema %q: %w", schemaName, err)
|
|
||||||
}
|
|
||||||
if err := ctx.Err(); err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
schema, err := compileJSONSchema(ctx, resourceURL.String(), compiler.Compile)
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, fmt.Errorf("failed to compile JSON schema %q: %w", schemaName, err)
|
return nil, fmt.Errorf("failed to compile JSON schema %q: %w", name, err)
|
||||||
}
|
}
|
||||||
|
|
||||||
return executeJSONSchema(ctx, schema, instance)
|
return executeJSONSchema(ctx, schema, instance)
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -489,11 +414,29 @@ func fsSchemaResourceURL(schemaName string) *url.URL {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func newSchemaCompiler(loader jsonschema.URLLoader) *jsonschema.Compiler {
|
type externalSchemaLoader struct{ ctx context.Context }
|
||||||
|
|
||||||
|
func (l externalSchemaLoader) Load(resourceURL string) (any, error) {
|
||||||
|
if err := l.ctx.Err(); err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
return nil, fmt.Errorf("external schema resource %q is not supported; use a self-contained schema", resourceURL)
|
||||||
|
}
|
||||||
|
|
||||||
|
func compileSchemaDocument(ctx context.Context, resourceURL string, document any) (*jsonschema.Schema, error) {
|
||||||
|
if err := ctx.Err(); err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
compiler := jsonschema.NewCompiler()
|
compiler := jsonschema.NewCompiler()
|
||||||
compiler.DefaultDraft(jsonschema.Draft2020)
|
compiler.DefaultDraft(jsonschema.Draft2020)
|
||||||
compiler.UseLoader(loader)
|
compiler.UseLoader(externalSchemaLoader{ctx: ctx})
|
||||||
return compiler
|
if err := compiler.AddResource(resourceURL, document); err != nil {
|
||||||
|
if contextErr := ctx.Err(); contextErr != nil {
|
||||||
|
return nil, contextErr
|
||||||
|
}
|
||||||
|
return nil, fmt.Errorf("register schema: %w", err)
|
||||||
|
}
|
||||||
|
return compileJSONSchema(ctx, resourceURL, compiler.Compile)
|
||||||
}
|
}
|
||||||
|
|
||||||
type schemaExecutor interface {
|
type schemaExecutor interface {
|
||||||
@@ -544,36 +487,6 @@ func validateSchemaDialect(doc any) error {
|
|||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
type standardSchemaLoader struct {
|
|
||||||
ctx context.Context
|
|
||||||
root string
|
|
||||||
}
|
|
||||||
|
|
||||||
func (l standardSchemaLoader) Load(resourceURL string) (any, error) {
|
|
||||||
if err := l.ctx.Err(); err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
parsed, err := url.Parse(resourceURL)
|
|
||||||
if err != nil || parsed.Scheme != "file" || parsed.Host != "" || parsed.RawQuery != "" || parsed.Opaque != "" {
|
|
||||||
return nil, fmt.Errorf("schema reference %q is not a contained file reference", resourceURL)
|
|
||||||
}
|
|
||||||
fileName, err := (jsonschema.FileLoader{}).ToFile(resourceURL)
|
|
||||||
if err != nil {
|
|
||||||
return nil, fmt.Errorf("schema reference %q is not a contained file reference: %w", resourceURL, err)
|
|
||||||
}
|
|
||||||
resolved, err := containedFilesystemPath(l.root, fileName)
|
|
||||||
if err != nil {
|
|
||||||
if contextErr := l.ctx.Err(); contextErr != nil {
|
|
||||||
return nil, contextErr
|
|
||||||
}
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
if err := l.ctx.Err(); err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
return loadJSONSchemaFile(l.ctx, resolved)
|
|
||||||
}
|
|
||||||
|
|
||||||
func containedFilesystemPath(root, name string) (string, error) {
|
func containedFilesystemPath(root, name string) (string, error) {
|
||||||
candidate := name
|
candidate := name
|
||||||
if !filepath.IsAbs(candidate) {
|
if !filepath.IsAbs(candidate) {
|
||||||
@@ -666,66 +579,3 @@ func readSchemaFile(ctx context.Context, open func() (fs.File, error)) ([]byte,
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
type fsSchemaLoader struct {
|
|
||||||
ctx context.Context
|
|
||||||
fsys fs.FS
|
|
||||||
root string
|
|
||||||
}
|
|
||||||
|
|
||||||
func (l fsSchemaLoader) Load(resourceURL string) (any, error) {
|
|
||||||
if err := l.ctx.Err(); err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
parsed, err := url.Parse(resourceURL)
|
|
||||||
if err != nil {
|
|
||||||
return nil, fmt.Errorf("invalid schema reference %q: %w", resourceURL, err)
|
|
||||||
}
|
|
||||||
if parsed.Scheme != "promptkit-schema" || parsed.Host != "" || parsed.RawQuery != "" || parsed.Opaque != "" {
|
|
||||||
return nil, fmt.Errorf("schema reference %q is not allowed", resourceURL)
|
|
||||||
}
|
|
||||||
name := strings.TrimPrefix(parsed.Path, "/")
|
|
||||||
name = path.Clean(name)
|
|
||||||
if l.root == "." {
|
|
||||||
if strings.HasPrefix(name, "../") || name == ".." {
|
|
||||||
return nil, fmt.Errorf("schema reference %q escapes source root", resourceURL)
|
|
||||||
}
|
|
||||||
} else if name != l.root && !strings.HasPrefix(name, l.root+"/") {
|
|
||||||
return nil, fmt.Errorf("schema reference %q escapes source root", resourceURL)
|
|
||||||
}
|
|
||||||
|
|
||||||
rootInfo, err := fs.Stat(l.fsys, l.root)
|
|
||||||
if err != nil {
|
|
||||||
if contextErr := l.ctx.Err(); contextErr != nil {
|
|
||||||
return nil, contextErr
|
|
||||||
}
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
if err := l.ctx.Err(); err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
if !rootInfo.IsDir() && name != l.root {
|
|
||||||
return nil, fmt.Errorf("schema reference %q is outside the configured schema file", resourceURL)
|
|
||||||
}
|
|
||||||
|
|
||||||
raw, err := readSchemaFile(l.ctx, func() (fs.File, error) {
|
|
||||||
return l.fsys.Open(name)
|
|
||||||
})
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
doc, err := decodeJSONValue(l.ctx, raw)
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
if err := validateSchemaDialect(doc); err != nil {
|
|
||||||
if contextErr := l.ctx.Err(); contextErr != nil {
|
|
||||||
return nil, contextErr
|
|
||||||
}
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
if err := l.ctx.Err(); err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
return doc, nil
|
|
||||||
}
|
|
||||||
|
|||||||
@@ -232,8 +232,9 @@ func TestStandardValidatorPreparedSchemaSurvivesSourceRemoval(t *testing.T) {
|
|||||||
"title": "original root",
|
"title": "original root",
|
||||||
"type": "object",
|
"type": "object",
|
||||||
"required": ["value"],
|
"required": ["value"],
|
||||||
|
"$defs": {"value": {"type":"integer", "minimum":2}},
|
||||||
"properties": {
|
"properties": {
|
||||||
"value": {"$ref": "value.json"}
|
"value": {"$ref": "#/$defs/value"}
|
||||||
}
|
}
|
||||||
}`)
|
}`)
|
||||||
rootPath := filepath.Join(tmp, "schema.json")
|
rootPath := filepath.Join(tmp, "schema.json")
|
||||||
@@ -415,8 +416,9 @@ func TestFSValidatorPreparedSchemaSurvivesSourceMutation(t *testing.T) {
|
|||||||
"title": "original root",
|
"title": "original root",
|
||||||
"type": "object",
|
"type": "object",
|
||||||
"required": ["value"],
|
"required": ["value"],
|
||||||
|
"$defs": {"value": {"type":"integer", "minimum":2}},
|
||||||
"properties": {
|
"properties": {
|
||||||
"value": {"$ref": "value.json"}
|
"value": {"$ref": "#/$defs/value"}
|
||||||
}
|
}
|
||||||
}`)
|
}`)
|
||||||
fsys := fstest.MapFS{
|
fsys := fstest.MapFS{
|
||||||
@@ -525,8 +527,8 @@ func assertSchemaValidation(t *testing.T, validator Validator, schemaPath string
|
|||||||
ValidationMode: domain.ValidationJSONSchema,
|
ValidationMode: domain.ValidationJSONSchema,
|
||||||
SchemaPath: schemaPath,
|
SchemaPath: schemaPath,
|
||||||
})
|
})
|
||||||
if err != nil || !result.IsValid {
|
if err == nil || !strings.Contains(err.Error(), "external schema resource") {
|
||||||
t.Fatalf("validate schema %q: result=%#v error=%v", schemaPath, result, err)
|
t.Fatalf("external reference schema %q: result=%#v error=%v", schemaPath, result, err)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -631,9 +633,9 @@ func TestStandardValidatorJSONSchemaReferenceBoundaries(t *testing.T) {
|
|||||||
wantError string
|
wantError string
|
||||||
writeOuter bool
|
writeOuter bool
|
||||||
}{
|
}{
|
||||||
{name: "contained relative reference", reference: "child.json"},
|
{name: "contained relative reference", reference: "child.json", wantError: "external schema resource"},
|
||||||
{name: "remote reference", reference: "https://example.test/schema.json", wantError: "not a contained file reference"},
|
{name: "remote reference", reference: "https://example.test/schema.json", wantError: "external schema resource"},
|
||||||
{name: "escaping reference", reference: "../outside.json", wantError: "escapes source root", writeOuter: true},
|
{name: "escaping reference", reference: "../outside.json", wantError: "external schema resource", writeOuter: true},
|
||||||
}
|
}
|
||||||
|
|
||||||
for _, tc := range tests {
|
for _, tc := range tests {
|
||||||
@@ -676,9 +678,9 @@ func TestFSValidatorJSONSchemaReferenceBoundaries(t *testing.T) {
|
|||||||
wantError string
|
wantError string
|
||||||
}{
|
}{
|
||||||
{name: "same document fragment", reference: "#/$defs/value"},
|
{name: "same document fragment", reference: "#/$defs/value"},
|
||||||
{name: "contained relative reference", reference: "child.json"},
|
{name: "contained relative reference", reference: "child.json", wantError: "external schema resource"},
|
||||||
{name: "remote reference", reference: "https://example.test/schema.json", wantError: "is not allowed"},
|
{name: "remote reference", reference: "https://example.test/schema.json", wantError: "external schema resource"},
|
||||||
{name: "escaping reference", reference: "../outside.json", wantError: "escapes source root"},
|
{name: "escaping reference", reference: "../outside.json", wantError: "external schema resource"},
|
||||||
}
|
}
|
||||||
|
|
||||||
for _, tc := range tests {
|
for _, tc := range tests {
|
||||||
|
|||||||
Reference in New Issue
Block a user