* Prepare readme for release * Update vendored packages * New version of dns dependency handles rejecting UPDATEs under the hood * Go 1.11 required
332 lines
7.2 KiB
Go
332 lines
7.2 KiB
Go
// Copyright 2015 xeipuuv ( https://github.com/xeipuuv )
|
|
//
|
|
// Licensed under the Apache License, Version 2.0 (the "License");
|
|
// you may not use this file except in compliance with the License.
|
|
// You may obtain a copy of the License at
|
|
//
|
|
// http://www.apache.org/licenses/LICENSE-2.0
|
|
//
|
|
// Unless required by applicable law or agreed to in writing, software
|
|
// distributed under the License is distributed on an "AS IS" BASIS,
|
|
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
// See the License for the specific language governing permissions and
|
|
// limitations under the License.
|
|
|
|
// author xeipuuv
|
|
// author-github https://github.com/xeipuuv
|
|
// author-mail xeipuuv@gmail.com
|
|
//
|
|
// repository-name gojsonschema
|
|
// repository-desc An implementation of JSON Schema, based on IETF's draft v4 - Go language.
|
|
//
|
|
// description (Unit) Tests for schema validation.
|
|
//
|
|
// created 16-06-2013
|
|
|
|
package gojsonschema
|
|
|
|
import (
|
|
"bytes"
|
|
"fmt"
|
|
"io"
|
|
"io/ioutil"
|
|
"os"
|
|
"path/filepath"
|
|
"testing"
|
|
|
|
"github.com/stretchr/testify/assert"
|
|
)
|
|
|
|
const displayErrorMessages = false
|
|
|
|
const circularReference = `{
|
|
"type": "object",
|
|
"properties": {
|
|
"games": {
|
|
"type": "array",
|
|
"items": {
|
|
"$ref": "#/definitions/game"
|
|
}
|
|
}
|
|
},
|
|
"definitions": {
|
|
"game": {
|
|
"type": "object",
|
|
"properties": {
|
|
"winner": {
|
|
"$ref": "#/definitions/player"
|
|
},
|
|
"loser": {
|
|
"$ref": "#/definitions/player"
|
|
}
|
|
}
|
|
},
|
|
"player": {
|
|
"type": "object",
|
|
"properties": {
|
|
"user": {
|
|
"$ref": "#/definitions/user"
|
|
},
|
|
"game": {
|
|
"$ref": "#/definitions/game"
|
|
}
|
|
}
|
|
},
|
|
"user": {
|
|
"type": "object",
|
|
"properties": {
|
|
"fullName": {
|
|
"type": "string"
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}`
|
|
|
|
func TestCircularReference(t *testing.T) {
|
|
loader := NewStringLoader(circularReference)
|
|
// call the target function
|
|
_, err := NewSchema(loader)
|
|
if err != nil {
|
|
t.Errorf("Got error: %s", err.Error())
|
|
}
|
|
}
|
|
|
|
// From http://json-schema.org/examples.html
|
|
const simpleSchema = `{
|
|
"title": "Example Schema",
|
|
"type": "object",
|
|
"properties": {
|
|
"firstName": {
|
|
"type": "string"
|
|
},
|
|
"lastName": {
|
|
"type": "string"
|
|
},
|
|
"age": {
|
|
"description": "Age in years",
|
|
"type": "integer",
|
|
"minimum": 0
|
|
}
|
|
},
|
|
"required": ["firstName", "lastName"]
|
|
}`
|
|
|
|
func TestLoaders(t *testing.T) {
|
|
// setup reader loader
|
|
reader := bytes.NewBufferString(simpleSchema)
|
|
readerLoader, wrappedReader := NewReaderLoader(reader)
|
|
|
|
// drain reader
|
|
by, err := ioutil.ReadAll(wrappedReader)
|
|
assert.Nil(t, err)
|
|
assert.Equal(t, simpleSchema, string(by))
|
|
|
|
// setup writer loaders
|
|
writer := &bytes.Buffer{}
|
|
writerLoader, wrappedWriter := NewWriterLoader(writer)
|
|
|
|
// fill writer
|
|
n, err := io.WriteString(wrappedWriter, simpleSchema)
|
|
assert.Nil(t, err)
|
|
assert.Equal(t, n, len(simpleSchema))
|
|
|
|
loaders := []JSONLoader{
|
|
NewStringLoader(simpleSchema),
|
|
readerLoader,
|
|
writerLoader,
|
|
}
|
|
|
|
for _, l := range loaders {
|
|
_, err := NewSchema(l)
|
|
assert.Nil(t, err, "loader: %T", l)
|
|
}
|
|
}
|
|
|
|
const invalidPattern = `{
|
|
"title": "Example Pattern",
|
|
"type": "object",
|
|
"properties": {
|
|
"invalid": {
|
|
"type": "string",
|
|
"pattern": 99999
|
|
}
|
|
}
|
|
}`
|
|
|
|
func TestLoadersWithInvalidPattern(t *testing.T) {
|
|
// setup reader loader
|
|
reader := bytes.NewBufferString(invalidPattern)
|
|
readerLoader, wrappedReader := NewReaderLoader(reader)
|
|
|
|
// drain reader
|
|
by, err := ioutil.ReadAll(wrappedReader)
|
|
assert.Nil(t, err)
|
|
assert.Equal(t, invalidPattern, string(by))
|
|
|
|
// setup writer loaders
|
|
writer := &bytes.Buffer{}
|
|
writerLoader, wrappedWriter := NewWriterLoader(writer)
|
|
|
|
// fill writer
|
|
n, err := io.WriteString(wrappedWriter, invalidPattern)
|
|
assert.Nil(t, err)
|
|
assert.Equal(t, n, len(invalidPattern))
|
|
|
|
loaders := []JSONLoader{
|
|
NewStringLoader(invalidPattern),
|
|
readerLoader,
|
|
writerLoader,
|
|
}
|
|
|
|
for _, l := range loaders {
|
|
_, err := NewSchema(l)
|
|
assert.NotNil(t, err, "expected error loading invalid pattern: %T", l)
|
|
}
|
|
}
|
|
|
|
const refPropertySchema = `{
|
|
"$id" : "http://localhost/schema.json",
|
|
"properties" : {
|
|
"$id" : {
|
|
"$id": "http://localhost/foo.json"
|
|
},
|
|
"$ref" : {
|
|
"const": {
|
|
"$ref" : "hello.world"
|
|
}
|
|
},
|
|
"const" : {
|
|
"$ref" : "#/definitions/$ref"
|
|
}
|
|
},
|
|
"definitions" : {
|
|
"$ref" : {
|
|
"const": {
|
|
"$ref" : "hello.world"
|
|
}
|
|
}
|
|
},
|
|
"dependencies" : {
|
|
"$ref" : [ "const" ],
|
|
"const" : [ "$ref" ]
|
|
}
|
|
}`
|
|
|
|
func TestRefProperty(t *testing.T) {
|
|
schemaLoader := NewStringLoader(refPropertySchema)
|
|
documentLoader := NewStringLoader(`{
|
|
"$ref" : { "$ref" : "hello.world" },
|
|
"const" : { "$ref" : "hello.world" }
|
|
}`)
|
|
// call the target function
|
|
s, err := NewSchema(schemaLoader)
|
|
if err != nil {
|
|
t.Errorf("Got error: %s", err.Error())
|
|
}
|
|
result, err := s.Validate(documentLoader)
|
|
if err != nil {
|
|
t.Errorf("Got error: %s", err.Error())
|
|
}
|
|
if !result.Valid() {
|
|
for _, err := range result.Errors() {
|
|
fmt.Println(err.String())
|
|
}
|
|
t.Errorf("Got invalid validation result.")
|
|
}
|
|
}
|
|
|
|
func TestFragmentLoader(t *testing.T) {
|
|
wd, err := os.Getwd()
|
|
|
|
if err != nil {
|
|
panic(err.Error())
|
|
}
|
|
|
|
fileName := filepath.Join(wd, "testdata", "extra", "fragment_schema.json")
|
|
|
|
schemaLoader := NewReferenceLoader("file://" + filepath.ToSlash(fileName) + "#/definitions/x")
|
|
schema, err := NewSchema(schemaLoader)
|
|
|
|
if err != nil {
|
|
t.Errorf("Encountered error while loading schema: %s", err.Error())
|
|
}
|
|
|
|
validDocument := NewStringLoader(`5`)
|
|
invalidDocument := NewStringLoader(`"a"`)
|
|
|
|
result, err := schema.Validate(validDocument)
|
|
|
|
if assert.Nil(t, err, "Unexpected error while validating document: %T", err) {
|
|
if !result.Valid() {
|
|
t.Errorf("Got invalid validation result.")
|
|
}
|
|
}
|
|
|
|
result, err = schema.Validate(invalidDocument)
|
|
|
|
if assert.Nil(t, err, "Unexpected error while validating document: %T", err) {
|
|
if len(result.Errors()) != 1 || result.Errors()[0].Type() != "invalid_type" {
|
|
t.Errorf("Got invalid validation result.")
|
|
}
|
|
}
|
|
}
|
|
|
|
// Inspired by http://json-schema.org/latest/json-schema-core.html#rfc.section.8.2.3
|
|
const locationIndependentSchema = `{
|
|
"definitions": {
|
|
"A": {
|
|
"$id": "#foo"
|
|
},
|
|
"B": {
|
|
"$id": "http://example.com/other.json",
|
|
"definitions": {
|
|
"X": {
|
|
"$id": "#bar",
|
|
"allOf": [false]
|
|
},
|
|
"Y": {
|
|
"$id": "t/inner.json"
|
|
}
|
|
}
|
|
},
|
|
"C": {
|
|
"$id" : "#frag",
|
|
"$ref": "http://example.com/other.json#bar"
|
|
}
|
|
},
|
|
"$ref": "#frag"
|
|
}`
|
|
|
|
func TestLocationIndependentIdentifier(t *testing.T) {
|
|
schemaLoader := NewStringLoader(locationIndependentSchema)
|
|
documentLoader := NewStringLoader(`{}`)
|
|
|
|
s, err := NewSchema(schemaLoader)
|
|
if err != nil {
|
|
t.Errorf("Got error: %s", err.Error())
|
|
}
|
|
|
|
result, err := s.Validate(documentLoader)
|
|
if err != nil {
|
|
t.Errorf("Got error: %s", err.Error())
|
|
}
|
|
|
|
if len(result.Errors()) != 2 || result.Errors()[0].Type() != "number_not" || result.Errors()[1].Type() != "number_all_of" {
|
|
t.Errorf("Got invalid validation result.")
|
|
}
|
|
}
|
|
|
|
const incorrectRefSchema = `{
|
|
"$ref" : "#/fail"
|
|
}`
|
|
|
|
func TestIncorrectRef(t *testing.T) {
|
|
|
|
schemaLoader := NewStringLoader(incorrectRefSchema)
|
|
s, err := NewSchema(schemaLoader)
|
|
|
|
assert.Nil(t, s)
|
|
assert.Equal(t, "Object has no key 'fail'", err.Error())
|
|
}
|