1// Copyright 2015 go-swagger maintainers 2// 3// Licensed under the Apache License, Version 2.0 (the "License"); 4// you may not use this file except in compliance with the License. 5// You may obtain a copy of the License at 6// 7// http://www.apache.org/licenses/LICENSE-2.0 8// 9// Unless required by applicable law or agreed to in writing, software 10// distributed under the License is distributed on an "AS IS" BASIS, 11// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12// See the License for the specific language governing permissions and 13// limitations under the License. 14 15package validate 16 17import ( 18 "encoding/json" 19 "math" 20 "reflect" 21 "testing" 22 23 "github.com/stretchr/testify/assert" 24 "github.com/stretchr/testify/require" 25 26 "github.com/go-openapi/spec" 27 "github.com/go-openapi/strfmt" 28 "github.com/go-openapi/swag" 29) 30 31func TestSchemaValidator_Validate_Pattern(t *testing.T) { 32 var schemaJSON = ` 33{ 34 "properties": { 35 "name": { 36 "type": "string", 37 "pattern": "^[A-Za-z]+$", 38 "minLength": 1 39 }, 40 "place": { 41 "type": "string", 42 "pattern": "^[A-Za-z]+$", 43 "minLength": 1 44 } 45 }, 46 "required": [ 47 "name" 48 ] 49}` 50 51 schema := new(spec.Schema) 52 require.NoError(t, json.Unmarshal([]byte(schemaJSON), schema)) 53 54 var input map[string]interface{} 55 var inputJSON = `{"name": "Ivan"}` 56 57 require.NoError(t, json.Unmarshal([]byte(inputJSON), &input)) 58 assert.NoError(t, AgainstSchema(schema, input, strfmt.Default)) 59 60 input["place"] = json.Number("10") 61 62 assert.Error(t, AgainstSchema(schema, input, strfmt.Default)) 63 64} 65 66func TestSchemaValidator_PatternProperties(t *testing.T) { 67 var schemaJSON = ` 68{ 69 "properties": { 70 "name": { 71 "type": "string", 72 "pattern": "^[A-Za-z]+$", 73 "minLength": 1 74 } 75 }, 76 "patternProperties": { 77 "address-[0-9]+": { 78 "type": "string", 79 "pattern": "^[\\s|a-z]+$" 80 } 81 }, 82 "required": [ 83 "name" 84 ], 85 "additionalProperties": false 86}` 87 88 schema := new(spec.Schema) 89 require.NoError(t, json.Unmarshal([]byte(schemaJSON), schema)) 90 91 var input map[string]interface{} 92 93 // ok 94 var inputJSON = `{"name": "Ivan","address-1": "sesame street"}` 95 require.NoError(t, json.Unmarshal([]byte(inputJSON), &input)) 96 assert.NoError(t, AgainstSchema(schema, input, strfmt.Default)) 97 98 // fail pattern regexp 99 input["address-1"] = "1, Sesame Street" 100 assert.Error(t, AgainstSchema(schema, input, strfmt.Default)) 101 102 // fail patternProperties regexp 103 inputJSON = `{"name": "Ivan","address-1": "sesame street","address-A": "address"}` 104 require.NoError(t, json.Unmarshal([]byte(inputJSON), &input)) 105 assert.Error(t, AgainstSchema(schema, input, strfmt.Default)) 106 107} 108 109func TestSchemaValidator_Panic(t *testing.T) { 110 assert.PanicsWithValue(t, `Invalid schema provided to SchemaValidator: object has no field "pointer-to-nowhere"`, schemaValidatorPanicker) 111} 112 113func schemaValidatorPanicker() { 114 var schemaJSON = ` 115{ 116 "$ref": "#/pointer-to-nowhere" 117}` 118 119 schema := new(spec.Schema) 120 json.Unmarshal([]byte(schemaJSON), schema) 121 122 var input map[string]interface{} 123 124 // ok 125 var inputJSON = `{"name": "Ivan","address-1": "sesame street"}` 126 json.Unmarshal([]byte(inputJSON), &input) 127 // panics 128 AgainstSchema(schema, input, strfmt.Default) 129} 130 131// Test edge cases in schemaValidator which are difficult 132// to simulate with specs 133func TestSchemaValidator_EdgeCases(t *testing.T) { 134 var s *SchemaValidator 135 136 res := s.Validate("123") 137 assert.NotNil(t, res) 138 assert.True(t, res.IsValid()) 139 140 s = NewSchemaValidator(nil, nil, "", strfmt.Default) 141 assert.Nil(t, s) 142 143 v := "ABC" 144 b := s.Applies(v, reflect.String) 145 assert.False(t, b) 146 147 sp := spec.Schema{} 148 b = s.Applies(&sp, reflect.Struct) 149 assert.True(t, b) 150 151 spp := spec.Float64Property() 152 153 s = NewSchemaValidator(spp, nil, "", strfmt.Default) 154 155 s.SetPath("path") 156 assert.Equal(t, "path", s.Path) 157 158 r := s.Validate(nil) 159 assert.NotNil(t, r) 160 assert.False(t, r.IsValid()) 161 162 // Validating json.Number data against number|float64 163 j := json.Number("123") 164 r = s.Validate(j) 165 assert.True(t, r.IsValid()) 166 167 // Validating json.Number data against integer|int32 168 spp = spec.Int32Property() 169 s = NewSchemaValidator(spp, nil, "", strfmt.Default) 170 j = json.Number("123") 171 r = s.Validate(j) 172 assert.True(t, r.IsValid()) 173 174 bignum := swag.FormatFloat64(math.MaxFloat64) 175 j = json.Number(bignum) 176 r = s.Validate(j) 177 assert.False(t, r.IsValid()) 178 179 // Validating incorrect json.Number data 180 spp = spec.Float64Property() 181 s = NewSchemaValidator(spp, nil, "", strfmt.Default) 182 j = json.Number("AXF") 183 r = s.Validate(j) 184 assert.False(t, r.IsValid()) 185} 186 187func TestSchemaValidator_SchemaOptions(t *testing.T) { 188 var schemaJSON = ` 189{ 190 "properties": { 191 "spec": { 192 "properties": { 193 "replicas": { 194 "type": "integer" 195 } 196 } 197 } 198 } 199}` 200 201 schema := new(spec.Schema) 202 require.NoError(t, json.Unmarshal([]byte(schemaJSON), schema)) 203 204 var input map[string]interface{} 205 var inputJSON = `{"spec": {"items": ["foo", "bar"], "replicas": 1}}` 206 assert.NoError(t, json.Unmarshal([]byte(inputJSON), &input)) 207 208 // ok 209 s := NewSchemaValidator(schema, nil, "", strfmt.Default, DisableObjectArrayTypeCheck(true)) 210 result := s.Validate(input) 211 assert.True(t, result.IsValid()) 212 213 // fail 214 s = NewSchemaValidator(schema, nil, "", strfmt.Default) 215 result = s.Validate(input) 216 assert.False(t, result.IsValid()) 217 218} 219