aeson-schema 0.4.1.1 → 0.4.1.2
raw patch · 35 files changed
+1332/−113 lines, 35 filesdep +faildep ~QuickCheckdep ~aesondep ~regex-basenew-uploader
Dependencies added: fail
Dependency ranges changed: QuickCheck, aeson, regex-base, regex-compat, syb, template-haskell, vector
Files
- CHANGELOG.md +3/−0
- aeson-schema.cabal +9/−8
- src/Data/Aeson/Schema/Choice/TH.hs +15/−5
- src/Data/Aeson/Schema/CodeGen.hs +15/−4
- src/Data/Aeson/Schema/CodeGenM.hs +32/−5
- src/Data/Aeson/Schema/Types.hs +4/−7
- src/Data/Aeson/TH/Lift.hs +0/−2
- test/Data/Aeson/Schema/CodeGen/Tests.hs +5/−13
- test/TestSuite.hs +4/−6
- test/test-suite/tests/draft3/additionalItems.json +19/−4
- test/test-suite/tests/draft3/additionalProperties.json +30/−0
- test/test-suite/tests/draft3/default.json +49/−0
- test/test-suite/tests/draft3/dependencies.json +108/−0
- test/test-suite/tests/draft3/disallow.json +80/−0
- test/test-suite/tests/draft3/divisibleBy.json +38/−1
- test/test-suite/tests/draft3/enum.json +33/−1
- test/test-suite/tests/draft3/extends.json +94/−0
- test/test-suite/tests/draft3/items.json +45/−40
- test/test-suite/tests/draft3/maxItems.json +5/−0
- test/test-suite/tests/draft3/maxLength.json +10/−0
- test/test-suite/tests/draft3/maximum.json +5/−0
- test/test-suite/tests/draft3/minItems.json +5/−0
- test/test-suite/tests/draft3/minLength.json +10/−0
- test/test-suite/tests/draft3/minimum.json +5/−0
- test/test-suite/tests/draft3/optional/bignum.json +107/−0
- test/test-suite/tests/draft3/optional/format.json +204/−0
- test/test-suite/tests/draft3/optional/jsregex.json +18/−0
- test/test-suite/tests/draft3/optional/zeroTerminatedFloats.json +15/−0
- test/test-suite/tests/draft3/pattern.json +16/−0
- test/test-suite/tests/draft3/patternProperties.json +37/−1
- test/test-suite/tests/draft3/properties.json +59/−0
- test/test-suite/tests/draft3/ref.json +159/−0
- test/test-suite/tests/draft3/refRemote.json +74/−0
- test/test-suite/tests/draft3/type.json +2/−2
- test/test-suite/tests/draft3/uniqueItems.json +18/−14
CHANGELOG.md view
@@ -1,3 +1,6 @@+# 0.4.1.2+- Bump upper bounds on aeson and newest TH+ # 0.4.0.0 - Add Data.Aeson.Schema.CodeGenM.Options type which allows
aeson-schema.cabal view
@@ -1,5 +1,5 @@ name: aeson-schema-version: 0.4.1.1+version: 0.4.1.2 synopsis: Haskell JSON schema validator and parser generator description: This library provides validation of JSON values against schemata. Given a schema, it can also produce data types corresponding to the schema and a parser. homepage: https://github.com/Fuuzetsu/aeson-schema@@ -12,7 +12,7 @@ category: Data build-type: Simple cabal-version: >= 1.8-tested-with: GHC==7.8.4, GHC==7.10.2+tested-with: GHC==7.10.3, GHC==8.0.1, GHC==8.2.2 extra-source-files: CHANGELOG.md data-files: test/test-suite/tests/draft3/optional/*.json, test/test-suite/tests/draft3/*.json@@ -35,24 +35,25 @@ Data.Aeson.TH.Lift extensions: OverloadedStrings build-depends: base > 4 && < 5,- aeson >= 0.11.0.0 && < 0.12,- vector >= 0.10 && < 0.12,+ aeson >= 0.11.0.0 && < 1.3,+ vector >= 0.10 && < 0.13, text >= 1.2 && < 1.3, regex-pcre >= 0.94.4 && < 0.95, unordered-containers >= 0.2.5.1 && < 2.6, containers >= 0.5.0.0 && < 0.6, attoparsec >= 0.12.1.2 && < 0.14,- template-haskell,+ template-haskell >= 2.10.0 && < 2.14, th-lift >= 0.7 && < 0.8, mtl >= 2 && < 3, transformers >= 0.3.0.0 && < 0.6,- QuickCheck >= 2.4.2 && < 2.9,- syb >= 0.4.4 && < 0.7,+ QuickCheck >= 2.4.2 && < 2.11,+ syb >= 0.4.4 && < 0.8, bytestring >= 0.9.2.1 && < 0.11, scientific >= 0.3.3.7 && < 0.4, ghc-prim, regex-compat,- regex-base+ regex-base,+ fail test-suite tests ghc-options: -Wall
src/Data/Aeson/Schema/Choice/TH.hs view
@@ -1,10 +1,11 @@ {-# LANGUAGE TemplateHaskell #-}+{-# LANGUAGE CPP #-} module Data.Aeson.Schema.Choice.TH ( generateChoice ) where -import Control.Applicative (Alternative (..), (<$>))+import Control.Applicative (Alternative (..)) import Control.Monad (forM) import Data.Aeson (FromJSON (..), ToJSON (..)) import Language.Haskell.TH@@ -14,13 +15,24 @@ generateChoice n | n < 2 = return [] generateChoice n = do tyName <- newName $ "Choice" ++ show n- let tyParamNames = map (mkName . singleton) $ take n ['a'..]+ let tyParamNames = map (mkName . return) $ take n ['a'..] let tyParams = map varT tyParamNames conNames <- mapM (newName . \i -> "Choice" ++ show i ++ "of" ++ show n) [1..n]++#if MIN_VERSION_template_haskell(2,12,0)+ let cons = zipWith normalC conNames $ map ((:[]) . bangType (pure $ Bang NoSourceUnpackedness NoSourceStrictness)) tyParams+ let derv = derivClause Nothing $ map conT [''Eq, ''Ord, ''Show, ''Read]+ dataDec <- dataD (cxt []) tyName (map PlainTV tyParamNames) Nothing cons [derv]+#elif MIN_VERSION_template_haskell(2,11,0)+ let cons = zipWith normalC conNames $ map ((:[]) . bangType (pure $ Bang NoSourceUnpackedness NoSourceStrictness)) tyParams+ dataDec <- dataD (cxt []) tyName (map PlainTV tyParamNames) Nothing cons $ mapM conT [''Eq, ''Ord, ''Show, ''Read]+#else let cons = zipWith normalC conNames $ map ((:[]) . strictType notStrict) tyParams dataDec <- dataD (cxt []) tyName (map PlainTV tyParamNames) cons [''Eq, ''Ord, ''Show, ''Read]+#endif+ let tyCon = appConT tyName tyParams- let genClassConstraints c = cxt $ map (classP c . singleton) tyParams+ let genClassConstraints c = cxt $ map (\tp -> conT c `appT` tp) tyParams instToJSON <- instanceD (genClassConstraints ''ToJSON) (conT ''ToJSON `appT` tyCon) [ funD 'toJSON $ zipWith genToJSONClause conNames tyParamNames ]@@ -82,8 +94,6 @@ return [typeDec, funDef] return $ [dataDec, instToJSON, instFromJSON, instArbitrary, choiceFunDec, choiceFun, mapChoiceFunDec, mapChoiceFun] ++ choiceIofNFuns where- singleton :: a -> [a]- singleton = (:[]) genToJSONClause :: Name -> Name -> ClauseQ genToJSONClause con param = clause [conP con [varP param]] (normalB . appE (varE 'toJSON) . varE $ param) [] mkNames :: Char -> [Name]
src/Data/Aeson/Schema/CodeGen.hs view
@@ -2,6 +2,7 @@ {-# LANGUAGE FlexibleInstances #-} {-# LANGUAGE TemplateHaskell #-} {-# LANGUAGE TupleSections #-}+{-# LANGUAGE CPP #-} module Data.Aeson.Schema.CodeGen ( Declaration (..)@@ -11,13 +12,12 @@ , generateModule ) where -import Control.Applicative (Applicative (..), (<$>), (<*>),- (<|>))+import Control.Applicative ((<|>)) import Control.Arrow (first, second) import Control.Monad (forM_, unless, when, zipWithM) import Control.Monad.RWS.Lazy (MonadReader (..), MonadWriter (..), evalRWST)-import Data.Aeson+import Data.Aeson hiding (Options) import Data.Aeson.Types (parse) import Data.Char (isAlphaNum, isLetter, toLower, toUpper)@@ -31,7 +31,7 @@ isInteger) import Data.Text (Text, pack, unpack) import qualified Data.Text as T-import Data.Traversable (forM, traverse)+import Data.Traversable (forM) import Data.Tuple (swap) import qualified Data.Vector as V import Language.Haskell.TH@@ -102,8 +102,19 @@ let typeName = typeMap M.! name ((typeQ, fromJsonQ, toJsonQ), defNewtype) <- generateSchema (Just typeName) name schema when defNewtype $ do++#if MIN_VERSION_template_haskell(2,12,0)+ let newtypeCon = normalC typeName [bangType (pure $ Bang NoSourceUnpackedness NoSourceStrictness) typeQ]+ let deriv = derivClause Nothing $ map conT $ _derivingTypeclasses opts+ newtypeDec <- runQ $ newtypeD (cxt []) typeName [] Nothing newtypeCon [deriv]+#elif MIN_VERSION_template_haskell(2,11,0)+ let newtypeCon = normalC typeName [bangType (pure $ Bang NoSourceUnpackedness NoSourceStrictness) typeQ]+ newtypeDec <- runQ $ newtypeD (cxt []) typeName [] Nothing newtypeCon (mapM conT $ _derivingTypeclasses opts)+#else let newtypeCon = normalC typeName [strictType notStrict typeQ] newtypeDec <- runQ $ newtypeD (cxt []) typeName [] newtypeCon (_derivingTypeclasses opts)+#endif+ fromJSONInst <- runQ $ instanceD (cxt []) (conT ''FromJSON `appT` conT typeName) [ valD (varP $ mkName "parseJSON") (normalB [| fmap $(conE typeName) . $fromJsonQ |]) [] ]
src/Data/Aeson/Schema/CodeGenM.hs view
@@ -2,6 +2,7 @@ {-# LANGUAGE GeneralizedNewtypeDeriving #-} {-# LANGUAGE TupleSections #-} {-# LANGUAGE TemplateHaskell #-}+{-# LANGUAGE CPP #-} module Data.Aeson.Schema.CodeGenM ( Declaration (..)@@ -17,7 +18,7 @@ , askEnv ) where -import Control.Applicative (Applicative (..), (<$>))+import qualified Control.Monad.Fail as Fail import Control.Monad.IO.Class (MonadIO (..)) import Control.Monad.RWS.Lazy (MonadReader (..), MonadState (..), MonadWriter (..), RWST (..))@@ -26,7 +27,7 @@ import Data.Function (on) import qualified Data.HashSet as HS import qualified Data.Map as M-import Data.Monoid ((<>), mconcat)+import Data.Monoid ((<>)) import Data.Text (Text, pack) import qualified Data.Text as T import Language.Haskell.TH@@ -68,8 +69,13 @@ -- types in the generated code. newtype CodeGenM s a = CodeGenM { unCodeGenM :: RWST (Options, s) Code StringSet Q a- } deriving (Monad, Applicative, Functor, MonadReader (Options, s), MonadWriter Code, MonadState StringSet)+ } deriving ( Monad, Applicative, Functor, MonadReader (Options, s)+ , MonadWriter Code, MonadState StringSet) +instance Fail.MonadFail (CodeGenM s) where+ fail = CodeGenM . fail++ -- | Extra options used for the codegen data Options = Options { _extraModules :: [String]@@ -152,10 +158,23 @@ return a qLookupName b = CodeGenM . MT.lift . (if b then lookupTypeName else lookupValueName) qReify = CodeGenM . MT.lift . reify- qReifyInstances name = CodeGenM . MT.lift . reifyInstances name qLocation = CodeGenM . MT.lift $ location qRunIO = CodeGenM . MT.lift . runIO qAddDependentFile = CodeGenM . MT.lift . addDependentFile+ qReifyInstances name = CodeGenM . MT.lift . reifyInstances name+ qReifyRoles = CodeGenM . MT.lift . reifyRoles+ qReifyAnnotations = CodeGenM . MT.lift . reifyAnnotations+ qReifyModule = CodeGenM . MT.lift . reifyModule+ qAddTopDecls = CodeGenM . MT.lift . addTopDecls+ qAddModFinalizer = CodeGenM . MT.lift . addModFinalizer+ qGetQ = CodeGenM $ MT.lift getQ+ qPutQ = CodeGenM . MT.lift . putQ+#if MIN_VERSION_template_haskell(2,11,0)+ qReifyFixity = CodeGenM . MT.lift . reifyFixity+ qReifyConStrictness = CodeGenM . MT.lift . reifyConStrictness+ qIsExtEnabled = CodeGenM . MT.lift . isExtEnabled+ qExtsEnabled = CodeGenM $ MT.lift extsEnabled+#endif instance MonadIO (CodeGenM s) where liftIO = qRunIO@@ -188,6 +207,14 @@ indent :: Text -> Text indent = (" " <>) - -- Template Haskell+#if MIN_VERSION_template_haskell(2,12,0)+ constructor = recC name $ map (\(fieldName, fieldType, _) -> (fieldName,Bang NoSourceUnpackedness NoSourceStrictness,) <$> fieldType) fields+ deriv = derivClause Nothing $ map conT classes+ dataDec = dataD (cxt []) name [] Nothing [constructor] $ [deriv]+#elif MIN_VERSION_template_haskell(2,11,0)+ constructor = recC name $ map (\(fieldName, fieldType, _) -> (fieldName,Bang NoSourceUnpackedness NoSourceStrictness,) <$> fieldType) fields+ dataDec = dataD (cxt []) name [] Nothing [constructor] $ mapM conT classes+#else constructor = recC name $ map (\(fieldName, fieldType, _) -> (fieldName,NotStrict,) <$> fieldType) fields dataDec = dataD (cxt []) name [] [constructor] classes+#endif
src/Data/Aeson/Schema/Types.hs view
@@ -13,7 +13,6 @@ , schemaQQ ) where -import Control.Applicative ((<*>), (*>), (<*)) import Control.Arrow (second) import Control.Monad (liftM) import Data.Aeson (FromJSON (..), Value (..), (.!=),@@ -27,14 +26,12 @@ import Data.ByteString.Lazy.Char8 (pack) import Data.Foldable (Foldable (..), toList) import Data.Function (on)-import Data.Functor ((<$>)) import Data.HashMap.Strict (HashMap) import qualified Data.HashMap.Strict as H import qualified Data.Map as M import Data.Maybe (catMaybes) import Data.Scientific (Scientific) import Data.Text (Text, unpack)-import Data.Traversable (traverse) import qualified Data.Vector as V import Language.Haskell.TH.Quote (QuasiQuoter (..)) import Language.Haskell.TH (varE, recUpdE)@@ -67,12 +64,12 @@ -- | Primitive JSON types data SchemaType = StringType | NumberType- | IntegerType+ | IntegerType | BooleanType- | ObjectType+ | ObjectType | ArrayType- | NullType- | AnyType -- ^ any of the above+ | NullType+ | AnyType -- ^ any of the above deriving (Eq, Ord, Enum, Bounded, Show, Read) instance FromJSON SchemaType where
src/Data/Aeson/TH/Lift.hs view
@@ -4,12 +4,10 @@ module Data.Aeson.TH.Lift () where -import Data.Aeson (Value (..)) import qualified Data.HashMap.Lazy as HM import qualified Data.Scientific as S import Data.Text (Text, pack, unpack) import qualified Data.Vector as V-import Language.Haskell.TH import Language.Haskell.TH.Syntax (Lift (..)) instance Lift Text where
test/Data/Aeson/Schema/CodeGen/Tests.hs view
@@ -1,12 +1,6 @@+{-# LANGUAGE QuasiQuotes #-}+{-# LANGUAGE TupleSections #-} {-# OPTIONS_GHC -fno-warn-orphans #-}-{-# LANGUAGE ExistentialQuantification #-}-{-# LANGUAGE FlexibleInstances #-}-{-# LANGUAGE ImpredicativeTypes #-}-{-# LANGUAGE QuasiQuotes #-}-{-# LANGUAGE RankNTypes #-}-{-# LANGUAGE ScopedTypeVariables #-}-{-# LANGUAGE TupleSections #-}- module Data.Aeson.Schema.CodeGen.Tests ( tests ) where@@ -16,10 +10,8 @@ import Test.Framework.Providers.QuickCheck2 import qualified Test.HUnit as HU import Test.QuickCheck hiding (Result (..))-import Test.QuickCheck.Property (Result (..), failed,- ioProperty, succeeded)+import Test.QuickCheck.Property (Result (reason), failed, succeeded) -import Control.Applicative (pure, (<$>), (<*>)) import Control.Concurrent (forkIO) import Control.Concurrent.Chan (Chan, newChan, readChan, writeChan)@@ -100,9 +92,9 @@ arbitrary = arbitraryValue 3 instance Arbitrary SchemaType where- arbitrary = elements [minBound..maxBound]+ arbitrary = elements [minBound .. maxBound] -arbitrarySchema :: (Eq a) => Int -> Gen (Schema a)+arbitrarySchema :: Eq a => Int -> Gen (Schema a) arbitrarySchema 0 = return empty arbitrarySchema depth = do typ <- shortListOf1 (choice2of arbitrary subSchema)
test/TestSuite.hs view
@@ -1,8 +1,6 @@-import Control.Applicative ((<$>)) import Test.Framework import qualified Data.Text as T -import qualified Data.Aeson.Schema.Choice.Tests import qualified Data.Aeson.Schema.CodeGen.Tests import qualified Data.Aeson.Schema.Types.Tests import qualified Data.Aeson.Schema.Validator.Tests@@ -28,11 +26,11 @@ runTest :: String -> IO () runTest tc = do at <- allTests- let schemaTests = findTest at - if length schemaTests == 0 - then fail "test not found" + let schemaTests = findTest at+ if length schemaTests == 0+ then fail "test not found" else- defaultMain + defaultMain [ testGroup "Data.Aeson.Schema.Validator" $ Data.Aeson.Schema.Validator.Tests.tests schemaTests , buildTest $ testGroup "Data.Aeson.Schema.CodeGen" <$> Data.Aeson.Schema.CodeGen.Tests.tests schemaTests
test/test-suite/tests/draft3/additionalItems.json view
@@ -53,13 +53,28 @@ }, { "description": "additionalItems as false without items",- "schema": {- "additionalItems": false- },+ "schema": {"additionalItems": false}, "tests": [ {- "description": "items should allow anything",+ "description":+ "items defaults to empty schema so everything is valid", "data": [ 1, 2, 3, 4, 5 ],+ "valid": true+ },+ {+ "description": "ignores non-arrays",+ "data": {"foo" : "bar"},+ "valid": true+ }+ ]+ },+ {+ "description": "additionalItems are allowed by default",+ "schema": {"items": []},+ "tests": [+ {+ "description": "only the first items are validated",+ "data": [1, "foo", false], "valid": true } ]
test/test-suite/tests/draft3/additionalProperties.json view
@@ -4,6 +4,7 @@ "additionalProperties being false does not allow other properties", "schema": { "properties": {"foo": {}, "bar": {}},+ "patternProperties": { "^v": {} }, "additionalProperties": false }, "tests": [@@ -16,6 +17,16 @@ "description": "an additional property is invalid", "data": {"foo" : 1, "bar" : 2, "quux" : "boom"}, "valid": false+ },+ {+ "description": "ignores non-objects",+ "data": [1, 2, 3],+ "valid": true+ },+ {+ "description": "patternProperties are not additional properties",+ "data": {"foo":1, "vroom": 2},+ "valid": true } ] },@@ -40,6 +51,25 @@ { "description": "an additional invalid property is invalid", "data": {"foo" : 1, "bar" : 2, "quux" : 12},+ "valid": false+ }+ ]+ },+ {+ "description":+ "additionalProperties can exist by itself",+ "schema": {+ "additionalProperties": {"type": "boolean"}+ },+ "tests": [+ {+ "description": "an additional valid property is valid",+ "data": {"foo" : true},+ "valid": true+ },+ {+ "description": "an additional invalid property is invalid",+ "data": {"foo" : 1}, "valid": false } ]
+ test/test-suite/tests/draft3/default.json view
@@ -0,0 +1,49 @@+[+ {+ "description": "invalid type for default",+ "schema": {+ "properties": {+ "foo": {+ "type": "integer",+ "default": []+ }+ }+ },+ "tests": [+ {+ "description": "valid when property is specified",+ "data": {"foo": 13},+ "valid": true+ },+ {+ "description": "still valid when the invalid default is used",+ "data": {},+ "valid": true+ }+ ]+ },+ {+ "description": "invalid string value for default",+ "schema": {+ "properties": {+ "bar": {+ "type": "string",+ "minLength": 4,+ "default": "bad"+ }+ }+ },+ "tests": [+ {+ "description": "valid when property is specified",+ "data": {"bar": "good"},+ "valid": true+ },+ {+ "description": "still valid when the invalid default is used",+ "data": {},+ "valid": true+ }+ ]+ }+]
+ test/test-suite/tests/draft3/dependencies.json view
@@ -0,0 +1,108 @@+[+ {+ "description": "dependencies",+ "schema": {+ "dependencies": {"bar": "foo"}+ },+ "tests": [+ {+ "description": "neither",+ "data": {},+ "valid": true+ },+ {+ "description": "nondependant",+ "data": {"foo": 1},+ "valid": true+ },+ {+ "description": "with dependency",+ "data": {"foo": 1, "bar": 2},+ "valid": true+ },+ {+ "description": "missing dependency",+ "data": {"bar": 2},+ "valid": false+ },+ {+ "description": "ignores non-objects",+ "data": "foo",+ "valid": true+ }+ ]+ },+ {+ "description": "multiple dependencies",+ "schema": {+ "dependencies": {"quux": ["foo", "bar"]}+ },+ "tests": [+ {+ "description": "neither",+ "data": {},+ "valid": true+ },+ {+ "description": "nondependants",+ "data": {"foo": 1, "bar": 2},+ "valid": true+ },+ {+ "description": "with dependencies",+ "data": {"foo": 1, "bar": 2, "quux": 3},+ "valid": true+ },+ {+ "description": "missing dependency",+ "data": {"foo": 1, "quux": 2},+ "valid": false+ },+ {+ "description": "missing other dependency",+ "data": {"bar": 1, "quux": 2},+ "valid": false+ },+ {+ "description": "missing both dependencies",+ "data": {"quux": 1},+ "valid": false+ }+ ]+ },+ {+ "description": "multiple dependencies subschema",+ "schema": {+ "dependencies": {+ "bar": {+ "properties": {+ "foo": {"type": "integer"},+ "bar": {"type": "integer"}+ }+ }+ }+ },+ "tests": [+ {+ "description": "valid",+ "data": {"foo": 1, "bar": 2},+ "valid": true+ },+ {+ "description": "wrong type",+ "data": {"foo": "quux", "bar": 2},+ "valid": false+ },+ {+ "description": "wrong type other",+ "data": {"foo": 2, "bar": "quux"},+ "valid": false+ },+ {+ "description": "wrong type both",+ "data": {"foo": "quux", "bar": "quux"},+ "valid": false+ }+ ]+ }+]
+ test/test-suite/tests/draft3/disallow.json view
@@ -0,0 +1,80 @@+[+ {+ "description": "disallow",+ "schema": {+ "disallow": "integer"+ },+ "tests": [+ {+ "description": "allowed",+ "data": "foo",+ "valid": true+ },+ {+ "description": "disallowed",+ "data": 1,+ "valid": false+ }+ ]+ },+ {+ "description": "multiple disallow",+ "schema": {+ "disallow": ["integer", "boolean"]+ },+ "tests": [+ {+ "description": "valid",+ "data": "foo",+ "valid": true+ },+ {+ "description": "mismatch",+ "data": 1,+ "valid": false+ },+ {+ "description": "other mismatch",+ "data": true,+ "valid": false+ }+ ]+ },+ {+ "description": "multiple disallow subschema",+ "schema": {+ "disallow":+ ["string",+ {+ "type": "object",+ "properties": {+ "foo": {+ "type": "string"+ }+ }+ }]+ },+ "tests": [+ {+ "description": "match",+ "data": 1,+ "valid": true+ },+ {+ "description": "other match",+ "data": {"foo": 1},+ "valid": true+ },+ {+ "description": "mismatch",+ "data": "foo",+ "valid": false+ },+ {+ "description": "other mismatch",+ "data": {"foo": "bar"},+ "valid": false+ }+ ]+ }+]
test/test-suite/tests/draft3/divisibleBy.json view
@@ -1,6 +1,27 @@ [ {- "description": "divisibleBy validation",+ "description": "by int",+ "schema": {"divisibleBy": 2},+ "tests": [+ {+ "description": "int by int",+ "data": 10,+ "valid": true+ },+ {+ "description": "int by int fail",+ "data": 7,+ "valid": false+ },+ {+ "description": "ignores non-numbers",+ "data": "foo",+ "valid": true+ }+ ]+ },+ {+ "description": "by number", "schema": {"divisibleBy": 1.5}, "tests": [ {@@ -16,6 +37,22 @@ { "description": "35 is not divisible by 1.5", "data": 35,+ "valid": false+ }+ ]+ },+ {+ "description": "by small number",+ "schema": {"divisibleBy": 0.0001},+ "tests": [+ {+ "description": "0.0075 is divisible by 0.0001",+ "data": 0.0075,+ "valid": true+ },+ {+ "description": "0.00751 is not divisible by 0.0001",+ "data": 0.00751, "valid": false } ]
test/test-suite/tests/draft3/enum.json view
@@ -17,7 +17,7 @@ }, { "description": "heterogeneous enum validation",- "schema": {"enum": [1, "foo", [], true, {"foo": 12}]},+ "schema": {"enum": [6, "foo", [], true, {"foo": 12}]}, "tests": [ { "description": "one of the enum is valid",@@ -32,6 +32,38 @@ { "description": "objects are deep compared", "data": {"foo": false},+ "valid": false+ }+ ]+ },+ {+ "description": "enums in properties",+ "schema": {+ "type":"object",+ "properties": {+ "foo": {"enum":["foo"]},+ "bar": {"enum":["bar"], "required":true}+ }+ },+ "tests": [+ {+ "description": "both properties are valid",+ "data": {"foo":"foo", "bar":"bar"},+ "valid": true+ },+ {+ "description": "missing optional property is valid",+ "data": {"bar":"bar"},+ "valid": true+ },+ {+ "description": "missing required property is invalid",+ "data": {"foo":"foo"},+ "valid": false+ },+ {+ "description": "missing all properties is invalid",+ "data": {}, "valid": false } ]
+ test/test-suite/tests/draft3/extends.json view
@@ -0,0 +1,94 @@+[+ {+ "description": "extends",+ "schema": {+ "properties": {"bar": {"type": "integer", "required": true}},+ "extends": {+ "properties": {+ "foo": {"type": "string", "required": true}+ }+ }+ },+ "tests": [+ {+ "description": "extends",+ "data": {"foo": "baz", "bar": 2},+ "valid": true+ },+ {+ "description": "mismatch extends",+ "data": {"foo": "baz"},+ "valid": false+ },+ {+ "description": "mismatch extended",+ "data": {"bar": 2},+ "valid": false+ },+ {+ "description": "wrong type",+ "data": {"foo": "baz", "bar": "quux"},+ "valid": false+ }+ ]+ },+ {+ "description": "multiple extends",+ "schema": {+ "properties": {"bar": {"type": "integer", "required": true}},+ "extends" : [+ {+ "properties": {+ "foo": {"type": "string", "required": true}+ }+ },+ {+ "properties": {+ "baz": {"type": "null", "required": true}+ }+ }+ ]+ },+ "tests": [+ {+ "description": "valid",+ "data": {"foo": "quux", "bar": 2, "baz": null},+ "valid": true+ },+ {+ "description": "mismatch first extends",+ "data": {"bar": 2, "baz": null},+ "valid": false+ },+ {+ "description": "mismatch second extends",+ "data": {"foo": "quux", "bar": 2},+ "valid": false+ },+ {+ "description": "mismatch both",+ "data": {"bar": 2},+ "valid": false+ }+ ]+ },+ {+ "description": "extends simple types",+ "schema": {+ "minimum": 20,+ "extends": {"maximum": 30}+ },+ "tests": [+ {+ "description": "valid",+ "data": 25,+ "valid": true+ },+ {+ "description": "mismatch extends",+ "data": 35,+ "valid": false+ }+ ]+ }+]
test/test-suite/tests/draft3/items.json view
@@ -1,41 +1,46 @@-[ - { - "description": "a schema given for items", - "schema": { - "items": {"type": "integer"} - }, - "tests": [ - { - "description": "valid items", - "data": [ 1, 2, 3 ], - "valid": true - }, - { - "description": "wrong type of items", - "data": [1, "x"], - "valid": false - } - ] - }, - { - "description": "an array of schemas for items", - "schema": { - "items": [ - {"type": "integer"}, - {"type": "string"} - ] - }, - "tests": [ - { - "description": "correct types", - "data": [ 1, "foo" ], - "valid": true - }, - { - "description": "wrong types", - "data": [ "foo", 1 ], - "valid": false - } - ] - } +[+ {+ "description": "a schema given for items",+ "schema": {+ "items": {"type": "integer"}+ },+ "tests": [+ {+ "description": "valid items",+ "data": [ 1, 2, 3 ],+ "valid": true+ },+ {+ "description": "wrong type of items",+ "data": [1, "x"],+ "valid": false+ },+ {+ "description": "ignores non-arrays",+ "data": {"foo" : "bar"},+ "valid": true+ }+ ]+ },+ {+ "description": "an array of schemas for items",+ "schema": {+ "items": [+ {"type": "integer"},+ {"type": "string"}+ ]+ },+ "tests": [+ {+ "description": "correct types",+ "data": [ 1, "foo" ],+ "valid": true+ },+ {+ "description": "wrong types",+ "data": [ "foo", 1 ],+ "valid": false+ }+ ]+ } ]
test/test-suite/tests/draft3/maxItems.json view
@@ -17,6 +17,11 @@ "description": "too long is invalid", "data": [1, 2, 3], "valid": false+ },+ {+ "description": "ignores non-arrays",+ "data": "foobar",+ "valid": true } ] }
test/test-suite/tests/draft3/maxLength.json view
@@ -17,6 +17,16 @@ "description": "too long is invalid", "data": "foo", "valid": false+ },+ {+ "description": "ignores non-strings",+ "data": 10,+ "valid": true+ },+ {+ "description": "two supplementary Unicode code points is long enough",+ "data": "\uD83D\uDCA9\uD83D\uDCA9",+ "valid": true } ] }
test/test-suite/tests/draft3/maximum.json view
@@ -12,6 +12,11 @@ "description": "above the maximum is invalid", "data": 3.5, "valid": false+ },+ {+ "description": "ignores non-numbers",+ "data": "x",+ "valid": true } ] },
test/test-suite/tests/draft3/minItems.json view
@@ -17,6 +17,11 @@ "description": "too short is invalid", "data": [], "valid": false+ },+ {+ "description": "ignores non-arrays",+ "data": "",+ "valid": true } ] }
test/test-suite/tests/draft3/minLength.json view
@@ -17,6 +17,16 @@ "description": "too short is invalid", "data": "f", "valid": false+ },+ {+ "description": "ignores non-strings",+ "data": 1,+ "valid": true+ },+ {+ "description": "one supplementary Unicode code point is not long enough",+ "data": "\uD83D\uDCA9",+ "valid": false } ] }
test/test-suite/tests/draft3/minimum.json view
@@ -12,6 +12,11 @@ "description": "below the minimum is invalid", "data": 0.6, "valid": false+ },+ {+ "description": "ignores non-numbers",+ "data": "x",+ "valid": true } ] },
+ test/test-suite/tests/draft3/optional/bignum.json view
@@ -0,0 +1,107 @@+[+ {+ "description": "integer",+ "schema": {"type": "integer"},+ "tests": [+ {+ "description": "a bignum is an integer",+ "data": 12345678910111213141516171819202122232425262728293031,+ "valid": true+ }+ ]+ },+ {+ "description": "number",+ "schema": {"type": "number"},+ "tests": [+ {+ "description": "a bignum is a number",+ "data": 98249283749234923498293171823948729348710298301928331,+ "valid": true+ }+ ]+ },+ {+ "description": "integer",+ "schema": {"type": "integer"},+ "tests": [+ {+ "description": "a negative bignum is an integer",+ "data": -12345678910111213141516171819202122232425262728293031,+ "valid": true+ }+ ]+ },+ {+ "description": "number",+ "schema": {"type": "number"},+ "tests": [+ {+ "description": "a negative bignum is a number",+ "data": -98249283749234923498293171823948729348710298301928331,+ "valid": true+ }+ ]+ },+ {+ "description": "string",+ "schema": {"type": "string"},+ "tests": [+ {+ "description": "a bignum is not a string",+ "data": 98249283749234923498293171823948729348710298301928331,+ "valid": false+ }+ ]+ },+ {+ "description": "integer comparison",+ "schema": {"maximum": 18446744073709551615},+ "tests": [+ {+ "description": "comparison works for high numbers",+ "data": 18446744073709551600,+ "valid": true+ }+ ]+ },+ {+ "description": "float comparison with high precision",+ "schema": {+ "maximum": 972783798187987123879878123.18878137,+ "exclusiveMaximum": true+ },+ "tests": [+ {+ "description": "comparison works for high numbers",+ "data": 972783798187987123879878123.188781371,+ "valid": false+ }+ ]+ },+ {+ "description": "integer comparison",+ "schema": {"minimum": -18446744073709551615},+ "tests": [+ {+ "description": "comparison works for very negative numbers",+ "data": -18446744073709551600,+ "valid": true+ }+ ]+ },+ {+ "description": "float comparison with high precision on negative numbers",+ "schema": {+ "minimum": -972783798187987123879878123.18878137,+ "exclusiveMinimum": true+ },+ "tests": [+ {+ "description": "comparison works for very negative numbers",+ "data": -972783798187987123879878123.188781371,+ "valid": false+ }+ ]+ }+]
test/test-suite/tests/draft3/optional/format.json view
@@ -14,5 +14,209 @@ "valid": false } ]+ },+ {+ "description": "validation of date-time strings",+ "schema": {"format": "date-time"},+ "tests": [+ {+ "description": "a valid date-time string",+ "data": "1963-06-19T08:30:06.283185Z",+ "valid": true+ },+ {+ "description": "an invalid date-time string",+ "data": "06/19/1963 08:30:06 PST",+ "valid": false+ },+ {+ "description": "only RFC3339 not all of ISO 8601 are valid",+ "data": "2013-350T01:01:01",+ "valid": false+ }+ ]+ },+ {+ "description": "validation of date strings",+ "schema": {"format": "date"},+ "tests": [+ {+ "description": "a valid date string",+ "data": "1963-06-19",+ "valid": true+ },+ {+ "description": "an invalid date string",+ "data": "06/19/1963",+ "valid": false+ }+ ]+ },+ {+ "description": "validation of time strings",+ "schema": {"format": "time"},+ "tests": [+ {+ "description": "a valid time string",+ "data": "08:30:06",+ "valid": true+ },+ {+ "description": "an invalid time string",+ "data": "8:30 AM",+ "valid": false+ }+ ]+ },+ {+ "description": "validation of URIs",+ "schema": {"format": "uri"},+ "tests": [+ {+ "description": "a valid URI",+ "data": "http://foo.bar/?baz=qux#quux",+ "valid": true+ },+ {+ "description": "a valid protocol-relative URI",+ "data": "//foo.bar/?baz=qux#quux",+ "valid": true+ },+ {+ "description": "an invalid URI",+ "data": "\\\\WINDOWS\\fileshare",+ "valid": false+ },+ {+ "description": "an invalid URI though valid URI reference",+ "data": "abc",+ "valid": false+ }+ ]+ },+ {+ "description": "validation of e-mail addresses",+ "schema": {"format": "email"},+ "tests": [+ {+ "description": "a valid e-mail address",+ "data": "joe.bloggs@example.com",+ "valid": true+ },+ {+ "description": "an invalid e-mail address",+ "data": "2962",+ "valid": false+ }+ ]+ },+ {+ "description": "validation of IP addresses",+ "schema": {"format": "ip-address"},+ "tests": [+ {+ "description": "a valid IP address",+ "data": "192.168.0.1",+ "valid": true+ },+ {+ "description": "an IP address with too many components",+ "data": "127.0.0.0.1",+ "valid": false+ },+ {+ "description": "an IP address with out-of-range values",+ "data": "256.256.256.256",+ "valid": false+ }+ ]+ },+ {+ "description": "validation of IPv6 addresses",+ "schema": {"format": "ipv6"},+ "tests": [+ {+ "description": "a valid IPv6 address",+ "data": "::1",+ "valid": true+ },+ {+ "description": "an IPv6 address with out-of-range values",+ "data": "12345::",+ "valid": false+ },+ {+ "description": "an IPv6 address with too many components",+ "data": "1:1:1:1:1:1:1:1:1:1:1:1:1:1:1:1",+ "valid": false+ },+ {+ "description": "an IPv6 address containing illegal characters",+ "data": "::laptop",+ "valid": false+ }+ ]+ },+ {+ "description": "validation of host names",+ "schema": {"format": "host-name"},+ "tests": [+ {+ "description": "a valid host name",+ "data": "www.example.com",+ "valid": true+ },+ {+ "description": "a host name starting with an illegal character",+ "data": "-a-host-name-that-starts-with--",+ "valid": false+ },+ {+ "description": "a host name containing illegal characters",+ "data": "not_a_valid_host_name",+ "valid": false+ },+ {+ "description": "a host name with a component too long",+ "data": "a-vvvvvvvvvvvvvvvveeeeeeeeeeeeeeeerrrrrrrrrrrrrrrryyyyyyyyyyyyyyyy-long-host-name-component",+ "valid": false+ }+ ]+ },+ {+ "description": "validation of CSS colors",+ "schema": {"format": "color"},+ "tests": [+ {+ "description": "a valid CSS color name",+ "data": "fuchsia",+ "valid": true+ },+ {+ "description": "a valid six-digit CSS color code",+ "data": "#CC8899",+ "valid": true+ },+ {+ "description": "a valid three-digit CSS color code",+ "data": "#C89",+ "valid": true+ },+ {+ "description": "an invalid CSS color code",+ "data": "#00332520",+ "valid": false+ },+ {+ "description": "an invalid CSS color name",+ "data": "puce",+ "valid": false+ },+ {+ "description": "a CSS color name containing invalid characters",+ "data": "light_grayish_red-violet",+ "valid": false+ }+ ] } ]
+ test/test-suite/tests/draft3/optional/jsregex.json view
@@ -0,0 +1,18 @@+[+ {+ "description": "ECMA 262 regex dialect recognition",+ "schema": { "format": "regex" },+ "tests": [+ {+ "description": "[^] is a valid regex",+ "data": "[^]",+ "valid": true+ },+ {+ "description": "ECMA 262 has no support for lookbehind",+ "data": "(?<=foo)bar",+ "valid": false+ }+ ]+ }+]
+ test/test-suite/tests/draft3/optional/zeroTerminatedFloats.json view
@@ -0,0 +1,15 @@+[+ {+ "description": "some languages do not distinguish between different types of numeric value",+ "schema": {+ "type": "integer"+ },+ "tests": [+ {+ "description": "a float is not an integer even without fractional part",+ "data": 1.0,+ "valid": false+ }+ ]+ }+]
test/test-suite/tests/draft3/pattern.json view
@@ -12,6 +12,22 @@ "description": "a non-matching pattern is invalid", "data": "abc", "valid": false+ },+ {+ "description": "ignores non-strings",+ "data": true,+ "valid": true+ }+ ]+ },+ {+ "description": "pattern is not anchored",+ "schema": {"pattern": "a+"},+ "tests": [+ {+ "description": "matches a substring",+ "data": "xxaayy",+ "valid": true } ] }
test/test-suite/tests/draft3/patternProperties.json view
@@ -27,11 +27,16 @@ "description": "multiple invalid matches is invalid", "data": {"foo": "bar", "foooooo" : "baz"}, "valid": false+ },+ {+ "description": "ignores non-objects",+ "data": 12,+ "valid": true } ] }, {- "description": "multiple simulatneous patternProperties are validated",+ "description": "multiple simultaneous patternProperties are validated", "schema": { "patternProperties": { "a*": {"type": "integer"},@@ -67,6 +72,37 @@ { "description": "an invalid due to both is invalid", "data": {"aaa": "foo", "aaaa": 31},+ "valid": false+ }+ ]+ },+ {+ "description": "regexes are not anchored by default and are case sensitive",+ "schema": {+ "patternProperties": {+ "[0-9]{2,}": { "type": "boolean" },+ "X_": { "type": "string" }+ }+ },+ "tests": [+ {+ "description": "non recognized members are ignored",+ "data": { "answer 1": "42" },+ "valid": true+ },+ {+ "description": "recognized members are accounted for",+ "data": { "a31b": null },+ "valid": false+ },+ {+ "description": "regexes are case sensitive",+ "data": { "a_x_3": 3 },+ "valid": true+ },+ {+ "description": "regexes are case sensitive, 2",+ "data": { "a_X_3": 3 }, "valid": false } ]
test/test-suite/tests/draft3/properties.json view
@@ -27,6 +27,65 @@ "description": "doesn't invalidate other properties", "data": {"quux": []}, "valid": true+ },+ {+ "description": "ignores non-objects",+ "data": [],+ "valid": true+ }+ ]+ },+ {+ "description":+ "properties, patternProperties, additionalProperties interaction",+ "schema": {+ "properties": {+ "foo": {"type": "array", "maxItems": 3},+ "bar": {"type": "array"}+ },+ "patternProperties": {"f.o": {"minItems": 2}},+ "additionalProperties": {"type": "integer"}+ },+ "tests": [+ {+ "description": "property validates property",+ "data": {"foo": [1, 2]},+ "valid": true+ },+ {+ "description": "property invalidates property",+ "data": {"foo": [1, 2, 3, 4]},+ "valid": false+ },+ {+ "description": "patternProperty invalidates property",+ "data": {"foo": []},+ "valid": false+ },+ {+ "description": "patternProperty validates nonproperty",+ "data": {"fxo": [1, 2]},+ "valid": true+ },+ {+ "description": "patternProperty invalidates nonproperty",+ "data": {"fxo": []},+ "valid": false+ },+ {+ "description": "additionalProperty ignores property",+ "data": {"bar": []},+ "valid": true+ },+ {+ "description": "additionalProperty validates others",+ "data": {"quux": 3},+ "valid": true+ },+ {+ "description": "additionalProperty invalidates others",+ "data": {"quux": "foo"},+ "valid": false } ] }
+ test/test-suite/tests/draft3/ref.json view
@@ -0,0 +1,159 @@+[+ {+ "description": "root pointer ref",+ "schema": {+ "properties": {+ "foo": {"$ref": "#"}+ },+ "additionalProperties": false+ },+ "tests": [+ {+ "description": "match",+ "data": {"foo": false},+ "valid": true+ },+ {+ "description": "recursive match",+ "data": {"foo": {"foo": false}},+ "valid": true+ },+ {+ "description": "mismatch",+ "data": {"bar": false},+ "valid": false+ },+ {+ "description": "recursive mismatch",+ "data": {"foo": {"bar": false}},+ "valid": false+ }+ ]+ },+ {+ "description": "relative pointer ref to object",+ "schema": {+ "properties": {+ "foo": {"type": "integer"},+ "bar": {"$ref": "#/properties/foo"}+ }+ },+ "tests": [+ {+ "description": "match",+ "data": {"bar": 3},+ "valid": true+ },+ {+ "description": "mismatch",+ "data": {"bar": true},+ "valid": false+ }+ ]+ },+ {+ "description": "relative pointer ref to array",+ "schema": {+ "items": [+ {"type": "integer"},+ {"$ref": "#/items/0"}+ ]+ },+ "tests": [+ {+ "description": "match array",+ "data": [1, 2],+ "valid": true+ },+ {+ "description": "mismatch array",+ "data": [1, "foo"],+ "valid": false+ }+ ]+ },+ {+ "description": "escaped pointer ref",+ "schema": {+ "tilda~field": {"type": "integer"},+ "slash/field": {"type": "integer"},+ "percent%field": {"type": "integer"},+ "properties": {+ "tilda": {"$ref": "#/tilda~0field"},+ "slash": {"$ref": "#/slash~1field"},+ "percent": {"$ref": "#/percent%25field"}+ }+ },+ "tests": [+ {+ "description": "slash invalid",+ "data": {"slash": "aoeu"},+ "valid": false+ },+ {+ "description": "tilda invalid",+ "data": {"tilda": "aoeu"},+ "valid": false+ },+ {+ "description": "percent invalid",+ "data": {"percent": "aoeu"},+ "valid": false+ },+ {+ "description": "slash valid",+ "data": {"slash": 123},+ "valid": true+ },+ {+ "description": "tilda valid",+ "data": {"tilda": 123},+ "valid": true+ },+ {+ "description": "percent valid",+ "data": {"percent": 123},+ "valid": true+ }+ ]+ },+ {+ "description": "nested refs",+ "schema": {+ "definitions": {+ "a": {"type": "integer"},+ "b": {"$ref": "#/definitions/a"},+ "c": {"$ref": "#/definitions/b"}+ },+ "$ref": "#/definitions/c"+ },+ "tests": [+ {+ "description": "nested ref valid",+ "data": 5,+ "valid": true+ },+ {+ "description": "nested ref invalid",+ "data": "a",+ "valid": false+ }+ ]+ },+ {+ "description": "remote ref, containing refs itself",+ "schema": {"$ref": "http://json-schema.org/draft-03/schema#"},+ "tests": [+ {+ "description": "remote ref valid",+ "data": {"items": {"type": "integer"}},+ "valid": true+ },+ {+ "description": "remote ref invalid",+ "data": {"items": {"type": 1}},+ "valid": false+ }+ ]+ }+]
+ test/test-suite/tests/draft3/refRemote.json view
@@ -0,0 +1,74 @@+[+ {+ "description": "remote ref",+ "schema": {"$ref": "http://localhost:1234/integer.json"},+ "tests": [+ {+ "description": "remote ref valid",+ "data": 1,+ "valid": true+ },+ {+ "description": "remote ref invalid",+ "data": "a",+ "valid": false+ }+ ]+ },+ {+ "description": "fragment within remote ref",+ "schema": {"$ref": "http://localhost:1234/subSchemas.json#/integer"},+ "tests": [+ {+ "description": "remote fragment valid",+ "data": 1,+ "valid": true+ },+ {+ "description": "remote fragment invalid",+ "data": "a",+ "valid": false+ }+ ]+ },+ {+ "description": "ref within remote ref",+ "schema": {+ "$ref": "http://localhost:1234/subSchemas.json#/refToInteger"+ },+ "tests": [+ {+ "description": "ref within ref valid",+ "data": 1,+ "valid": true+ },+ {+ "description": "ref within ref invalid",+ "data": "a",+ "valid": false+ }+ ]+ },+ {+ "description": "change resolution scope",+ "schema": {+ "id": "http://localhost:1234/",+ "items": {+ "id": "folder/",+ "items": {"$ref": "folderInteger.json"}+ }+ },+ "tests": [+ {+ "description": "changed scope ref valid",+ "data": [[1]],+ "valid": true+ },+ {+ "description": "changed scope ref invalid",+ "data": [["a"]],+ "valid": false+ }+ ]+ }+]
test/test-suite/tests/draft3/type.json view
@@ -188,7 +188,7 @@ "valid": false }, {- "description": "an array is not an array",+ "description": "an array is an array", "data": [], "valid": true },@@ -234,7 +234,7 @@ "valid": false }, {- "description": "a boolean is not a boolean",+ "description": "a boolean is a boolean", "data": true, "valid": true },
test/test-suite/tests/draft3/uniqueItems.json view
@@ -14,6 +14,11 @@ "valid": false }, {+ "description": "numbers are unique if mathematically unequal",+ "data": [1.0, 1.00, 1],+ "valid": false+ },+ { "description": "unique array of objects is valid", "data": [{"foo": "bar"}, {"foo": "baz"}], "valid": true@@ -48,26 +53,25 @@ "description": "non-unique array of arrays is invalid", "data": [["foo"], ["foo"]], "valid": false- }- ]- },- {- "description": "heterogeneous enum validation",- "schema": {"enum": [1, "foo", [], true, {"foo": 12}]},- "tests": [+ }, {- "description": "one of the enum is valid",- "data": [],+ "description": "1 and true are unique",+ "data": [1, true], "valid": true }, {- "description": "something else is invalid",- "data": null,- "valid": false+ "description": "0 and false are unique",+ "data": [0, false],+ "valid": true }, {- "description": "objects are deep compared",- "data": {"foo": false},+ "description": "unique heterogeneous types are valid",+ "data": [{}, [1], true, null, 1],+ "valid": true+ },+ {+ "description": "non-unique heterogeneous types are invalid",+ "data": [{}, [1], true, null, {}, 1], "valid": false } ]