packages feed

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 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             }         ]