[DRE-commits] [ruby-json-schema] 04/09: Imported Upstream version 2.6.0+gh

Sagar Ippalpalli isaagar-guest at moszumanska.debian.org
Sun Mar 6 11:12:46 UTC 2016


This is an automated email from the git hooks/post-receive script.

isaagar-guest pushed a commit to branch master
in repository ruby-json-schema.

commit 9de5cfdc64c715be374037d664030edb9f330665
Author: isaagar <i.vikram15 at gmail.com>
Date:   Sat Mar 5 22:51:47 2016 +0530

    Imported Upstream version 2.6.0+gh
---
 .gitignore                                         |   7 +
 .gitmodules                                        |   4 +
 .travis.yml                                        |  27 +
 CHANGELOG.md                                       |  13 +
 CONTRIBUTING.md                                    |   7 +
 CONTRIBUTORS.md                                    |  34 ++
 Gemfile                                            |   5 +
 README.md => README.textile                        | 293 ++++-----
 Rakefile                                           |  26 +
 VERSION.yml                                        |   3 +
 gemfiles/Gemfile.multi_json.x                      |   5 +
 gemfiles/Gemfile.uuidtools.x                       |   5 +
 gemfiles/Gemfile.yajl-ruby.x                       |   5 +
 json-schema.gemspec                                |  27 +
 lib/json-schema/validator.rb                       |   2 +-
 metadata.yml                                       | 177 ------
 test/data/all_of_ref_data.json                     |   3 +
 test/data/any_of_ref_data.json                     |   7 +
 test/data/bad_data_1.json                          |   3 +
 test/data/good_data_1.json                         |   3 +
 test/data/one_of_ref_links_data.json               |   5 +
 test/schemas/address_microformat.json              |  18 +
 test/schemas/all_of_ref_base_schema.json           |   6 +
 test/schemas/all_of_ref_schema.json                |   7 +
 test/schemas/any_of_ref_jane_schema.json           |   4 +
 test/schemas/any_of_ref_jimmy_schema.json          |   4 +
 test/schemas/any_of_ref_john_schema.json           |   4 +
 test/schemas/any_of_ref_schema.json                |  15 +
 test/schemas/definition_schema.json                |  15 +
 ...and_additionalProperties-1-filename.schema.json |  34 ++
 ...ends_and_additionalProperties-1-ref.schema.json |  34 ++
 ...and_additionalProperties-2-filename.schema.json |  33 +
 ...ends_and_additionalProperties-2-ref.schema.json |  33 +
 test/schemas/good_schema_1.json                    |  10 +
 test/schemas/good_schema_2.json                    |  10 +
 test/schemas/good_schema_extends1.json             |  10 +
 test/schemas/good_schema_extends2.json             |  13 +
 test/schemas/inner.schema.json                     |  21 +
 test/schemas/one_of_ref_links_schema.json          |  16 +
 test/schemas/ref john with spaces schema.json      |  11 +
 test/schemas/relative_definition_schema.json       |   8 +
 test/schemas/self_link_schema.json                 |  17 +
 test/schemas/up_link_schema.json                   |  17 +
 test/support/array_validation.rb                   | 108 ++++
 test/support/enum_validation.rb                    | 133 ++++
 test/support/number_validation.rb                  |  93 +++
 test/support/object_validation.rb                  |  68 +++
 test/support/strict_validation.rb                  |  89 +++
 test/support/string_validation.rb                  | 154 +++++
 test/support/type_validation.rb                    |  81 +++
 test/test_all_of_ref_schema.rb                     |  35 ++
 test/test_any_of_ref_schema.rb                     |  35 ++
 test/test_bad_schema_ref.rb                        |  39 ++
 test/test_common_test_suite.rb                     |  66 ++
 test/test_custom_format.rb                         | 119 ++++
 test/test_definition.rb                            |  15 +
 test/test_extended_schema.rb                       |  62 ++
 test/test_extends_and_additionalProperties.rb      |  52 ++
 test/test_files_v3.rb                              |  43 ++
 test/test_fragment_resolution.rb                   |  30 +
 test/test_fragment_validation_with_ref.rb          |  34 ++
 test/test_full_validation.rb                       | 208 +++++++
 test/test_helper.rb                                |  37 ++
 test/test_initialize_data.rb                       | 124 ++++
 test/test_jsonschema_draft1.rb                     | 141 +++++
 test/test_jsonschema_draft2.rb                     | 113 ++++
 test/test_jsonschema_draft3.rb                     | 450 ++++++++++++++
 test/test_jsonschema_draft4.rb                     | 675 +++++++++++++++++++++
 test/test_list_option.rb                           |  21 +
 test/test_load_ref_schema.rb                       |  38 ++
 test/test_merge_missing_values.rb                  |  45 ++
 test/test_minitems.rb                              |  16 +
 test/test_one_of.rb                                |  85 +++
 test/test_ruby_schema.rb                           |  59 ++
 test/test_schema_loader.rb                         |  74 +++
 test/test_schema_type_attribute.rb                 |  20 +
 test/test_schema_validation.rb                     | 185 ++++++
 test/test_stringify.rb                             |  48 ++
 test/test_uri_related.rb                           |  67 ++
 test/test_validator.rb                             |  53 ++
 80 files changed, 4358 insertions(+), 358 deletions(-)

diff --git a/.gitignore b/.gitignore
new file mode 100644
index 0000000..554401e
--- /dev/null
+++ b/.gitignore
@@ -0,0 +1,7 @@
+/.project
+.*.swp
+pkg
+*.gem
+/Gemfile.lock
+.bundle
+.idea
diff --git a/.gitmodules b/.gitmodules
new file mode 100644
index 0000000..ea9a738
--- /dev/null
+++ b/.gitmodules
@@ -0,0 +1,4 @@
+[submodule "test/test-suite"]
+	path = test/test-suite
+	branch = develop
+	url = git://github.com/json-schema/JSON-Schema-Test-Suite.git
diff --git a/.travis.yml b/.travis.yml
new file mode 100644
index 0000000..e027c91
--- /dev/null
+++ b/.travis.yml
@@ -0,0 +1,27 @@
+language: "ruby"
+
+rvm:
+  - "1.8"
+  - "1.9"
+  - "2.0"
+  - "2.1"
+  - "2.2"
+  - "2.3.0"
+  - "jruby"
+  - "rbx"
+
+sudo: false
+
+install:
+  - bundle install --retry=3
+
+matrix:
+  include:
+    - rvm: "2.3.0"
+      gemfile: "gemfiles/Gemfile.multi_json.x"
+    - rvm: "2.3.0"
+      gemfile: "gemfiles/Gemfile.yajl-ruby.x"
+    - rvm: "2.3.0"
+      gemfile: "gemfiles/Gemfile.uuidtools.x"
+  allow_failures:
+    - rvm: "1.8"
diff --git a/CHANGELOG.md b/CHANGELOG.md
new file mode 100644
index 0000000..ddea5fc
--- /dev/null
+++ b/CHANGELOG.md
@@ -0,0 +1,13 @@
+# Change Log
+All notable changes to this project will be documented in this file.
+Please keep to the changelog format described on [keepachangelog.com](http://keepachangelog.com).
+This project adheres to [Semantic Versioning](http://semver.org/).
+
+## [Unreleased]
+### Added
+- Added a changelog
+
+### Changed
+- Improved performance by caching the parsing and normalization of URIs
+- Made validation failures raise a `JSON::Schema::SchemaParseError` and data
+  loading failures a `JSON::Schema::JsonLoadError`
diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md
new file mode 100644
index 0000000..1b2df76
--- /dev/null
+++ b/CONTRIBUTING.md
@@ -0,0 +1,7 @@
+The Ruby JSON Schema library is meant to be a community effort, and as such, there are no strict guidelines for contributing.
+
+All individuals that have a pull request merged will receive collaborator access to the repository. Due to the restrictions on RubyGems authentication, permissions to release a gem must be requested along with the email desired to be associated with the release credentials.
+
+Accepting changes to the JSON Schema library shall be made through the use of pull requests on GitHub. A pull request must receive at least two (2) "+1" comments from current contributors, and include a relevant changelog entry, before being accepted and merged. If a breaking issue and fix exists, please feel free to contact the project maintainer at hoxworth at gmail.com or @hoxworth for faster resolution.
+
+Releases follow semantic versioning and may be made at a maintainer's discretion.
diff --git a/CONTRIBUTORS.md b/CONTRIBUTORS.md
new file mode 100644
index 0000000..ddef10f
--- /dev/null
+++ b/CONTRIBUTORS.md
@@ -0,0 +1,34 @@
+CONTRIBUTORS
+------------
+
+* Kenny Hoxworth - @hoxworth
+* Jenny Duckett - @jennyd
+* Kevin Glowacz - @kjg
+* Seb Bacon - @sebbacon
+* Jonathan Chrisp - @jonathanchrisp
+* James McKinney - @jpmckinney
+* Kylo Ginsberg - @kylog
+* Alex Soto - @apsoto
+* Roger Leite - @rogerleite
+* Myron Marston - @myronmarston
+* Jesse Stuart - @jvatic
+* Brian Hoffman - @lcdhoffman
+* Simon Waddington - @goodsimon
+* Chris Baynes - @chris-baynes
+* David Barri - @japgolly
+* Tyler Hunt - @tylerhunt
+* @vapir
+* Tom May - @tommay
+* Chris Johnson - @kindkid
+* David Kellum - @dekellum
+* Miguel Herranz - @IPGlider
+* Nick Recobra - @oruen
+* Vasily Fedoseyev - @Vasfed
+* Jari Bakken - @jarib
+* Kyle Hargraves - @pd
+* Jamie Cobbett - @jamiecobbett
+* Iain Beeston - @iainbeeston
+* Matt Palmer - @mpalmer
+* Ben Kirzhner - @benkirzhner
+* RST-J - @RST-J
+* Christian Treppo - @treppo
diff --git a/Gemfile b/Gemfile
new file mode 100644
index 0000000..66a72b3
--- /dev/null
+++ b/Gemfile
@@ -0,0 +1,5 @@
+source "https://rubygems.org"
+
+gemspec
+
+gem "json", ">= 1.7", :platforms => [:mri_18, :mri_19]
diff --git a/README.md b/README.textile
similarity index 51%
rename from README.md
rename to README.textile
index 64319d9..ce6f802 100644
--- a/README.md
+++ b/README.textile
@@ -1,79 +1,48 @@
-![https://travis-ci.org/ruby-json-schema/json-schema](https://travis-ci.org/ruby-json-schema/json-schema.svg?branch=master)
-![https://codeclimate.com/github/ruby-json-schema/json-schema](https://codeclimate.com/github/ruby-json-schema/json-schema/badges/gpa.svg)
+!https://travis-ci.org/ruby-json-schema/json-schema.svg?branch=master!:https://travis-ci.org/ruby-json-schema/json-schema
+!https://codeclimate.com/github/ruby-json-schema/json-schema/badges/gpa.svg!:https://codeclimate.com/github/ruby-json-schema/json-schema
 
-Ruby JSON Schema Validator
-==========================
+h1. Ruby JSON Schema Validator
 
-This library is intended to provide Ruby with an interface for validating JSON
-objects against a JSON schema conforming to [JSON Schema Draft
-4](http://tools.ietf.org/html/draft-zyp-json-schema-04). Legacy support for
-[JSON Schema Draft 3](http://tools.ietf.org/html/draft-zyp-json-schema-03),
-[JSON Schema Draft 2](http://tools.ietf.org/html/draft-zyp-json-schema-02), and
-[JSON Schema Draft 1](http://tools.ietf.org/html/draft-zyp-json-schema-01) is
-also included.
+This library is intended to provide Ruby with an interface for validating JSON objects against a JSON schema conforming to "JSON Schema Draft 4":http://tools.ietf.org/html/draft-zyp-json-schema-04. Legacy support for "JSON Schema Draft 3":http://tools.ietf.org/html/draft-zyp-json-schema-03, "JSON Schema Draft 2":http://tools.ietf.org/html/draft-zyp-json-schema-02, and "JSON Schema Draft 1":http://tools.ietf.org/html/draft-zyp-json-schema-01 is also included.
 
-Additional Resources
---------------------
+h2. Additional Resources
 
-- [Google Groups](https://groups.google.com/forum/#!forum/ruby-json-schema)
-- #ruby-json-schema on chat.freenode.net
+* "Google Groups":https://groups.google.com/forum/#!forum/ruby-json-schema
+* #ruby-json-schema on chat.freenode.net
 
-Version 2.0.0 Upgrade Notes
----------------------------
+h2. Version 2.0.0 Upgrade Notes
 
-Please be aware that the upgrade to version 2.0.0 will use Draft-04 **by
-default**, so schemas that do not declare a validator using the `$schema`
-keyword will use Draft-04 now instead of Draft-03. This is the reason for the
-major version upgrade.
+Please be aware that the upgrade to version 2.0.0 will use Draft-04 *by default*, so schemas that do not declare a validator using the <code>$schema</code> keyword will use Draft-04 now instead of Draft-03. This is the reason for the major version upgrade.
 
-Installation
-------------
+h2. Installation
 
 From rubygems.org:
 
-```sh
+<pre>
 gem install json-schema
-```
+</pre>
 
 From the git repo:
 
-```sh
+<pre>
 $ gem build json-schema.gemspec
 $ gem install json-schema-2.5.2.gem
-```
+</pre>
 
-Usage
------
 
-Three base validation methods exist: 
+h2. Usage
 
-1. `validate`: returns a boolean on whether a validation attempt passes
-2. `validate!`: throws a `JSON::Schema::ValidationError` with an appropriate message/trace on where the validation failed
-3. `fully_validate`: builds an array of validation errors return when validation is complete
+Three base validation methods exist: <code>validate</code>, <code>validate!</code>, and <code>fully_validate</code>. The first returns a boolean on whether a validation attempt passes and the second will throw a <code>JSON::Schema::ValidationError</code> with an appropriate message/trace on where the validation failed. The third validation method does not immediately fail upon a validation error and instead builds an array of validation errors return when validation is complete.
 
-All methods take two arguments, which can be either a JSON string, a file
-containing JSON, or a Ruby object representing JSON data. The first argument to
-these methods is always the schema, the second is always the data to validate.
-An optional third options argument is also accepted; available options are used
-in the examples below.
+All methods take two arguments, which can be either a JSON string, a file containing JSON, or a Ruby object representing JSON data. The first argument to these methods is always the schema, the second is always the data to validate. An optional third options argument is also accepted; available options are used in the examples below.
 
-By default, the validator uses the [JSON Schema Draft
-4](http://tools.ietf.org/html/draft-zyp-json-schema-04) specification for
-validation; however, the user is free to specify additional specifications or
-extend existing ones. Legacy support for Draft 1, Draft 2, and Draft 3 is
-included by either passing an optional `:version` parameter to the `validate`
-method (set either as `:draft1` or `draft2`), or by declaring the `$schema`
-attribute in the schema and referencing the appropriate specification URI. Note
-that the `$schema` attribute takes precedence over the `:version` option during
-parsing and validation.
+By default, the validator uses the "JSON Schema Draft 4":http://tools.ietf.org/html/draft-zyp-json-schema-04 specification for validation; however, the user is free to specify additional specifications or extend existing ones. Legacy support for Draft 1, Draft 2, and Draft 3 is included by either passing an optional <code>:version</code> parameter to the <code>validate</code> method (set either as <code>:draft1</code> or <code>draft2</code>), or by declaring the <code>$schema</code> attr [...]
 
-### Validate Ruby objects against a Ruby schema
+h3. Validate Ruby objects against a Ruby schema
 
-For further information on json schema itself refer to <a
-href="http://spacetelescope.github.io/understanding-json-schema/">Understanding
-JSON Schema</a>.
+For further information on json schema itself refer to <a href="http://spacetelescope.github.io/understanding-json-schema/">Understanding JSON Schema</a>.
 
-```rb
+<pre>
 require 'rubygems'
 require 'json-schema'
 
@@ -90,35 +59,32 @@ data = {
 }
 
 JSON::Validator.validate(schema, data)
-```
+</pre>
 
-### Validate a JSON string against a JSON schema file
+h3. Validate a JSON string against a JSON schema file
 
-```rb
+<pre>
 require 'rubygems'
 require 'json-schema'
 
 JSON::Validator.validate('schema.json', '{"a" : 5}')
-```
+</pre>
 
-### Validate a list of objects against a schema that represents the individual objects
+h3. Validate a list of objects against a schema that represents the individual objects
 
-```rb
+<pre>
 require 'rubygems'
 require 'json-schema'
 
 data = ['user','user','user']
 JSON::Validator.validate('user.json', data, :list => true)
-```
+</pre>
 
-### Strictly validate an object's properties
+h3. Strictly validate an object's properties
 
-With the `:strict` option, validation fails when an object contains properties
-that are not defined in the schema's property list or doesn't match the
-`additionalProperties` property. Furthermore, all properties are treated as
-`required` regardless of `required` properties set in the schema.
+With the <code>:strict</code> option, validation fails when an object contains properties that are not defined in the schema's property list or doesn't match the <code>additionalProperties</code> property. Furthermore, all properties are treated as <code>required</code> regardless of <code>required</code> properties set in the schema.
 
-```rb
+<pre>
 require 'rubygems'
 require 'json-schema'
 
@@ -133,11 +99,11 @@ schema = {
 JSON::Validator.validate(schema, {"a" => 1, "b" => 2}, :strict => true)            # ==> true
 JSON::Validator.validate(schema, {"a" => 1, "b" => 2, "c" => 3}, :strict => true)  # ==> false
 JSON::Validator.validate(schema, {"a" => 1}, :strict => true)                      # ==> false
-```
+</pre>
 
-### Catch a validation error and print it out
+h3. Catch a validation error and print it out
 
-```rb
+<pre>
 require 'rubygems'
 require 'json-schema'
 
@@ -158,11 +124,12 @@ begin
 rescue JSON::Schema::ValidationError
   puts $!.message
 end
-```
+</pre>
 
-### Fully validate against a schema and catch all errors
 
-```rb
+h3. Fully validate against a schema and catch all errors
+
+<pre>
 require 'rubygems'
 require 'json-schema'
 
@@ -182,11 +149,11 @@ data = {
 errors = JSON::Validator.fully_validate(schema, data)
 
 # ["The property '#/a' of type String did not match the following type: integer in schema 03179a21-197e-5414-9611-e9f63e8324cd#", "The property '#/' did not contain a required property of 'b' in schema 03179a21-197e-5414-9611-e9f63e8324cd#"]
-```
+</pre>
 
-### Fully validate against a schema and catch all errors as objects
+h3. Fully validate against a schema and catch all errors as objects
 
-```rb
+<pre>
 require 'rubygems'
 require 'json-schema'
 
@@ -205,40 +172,41 @@ data = {
 
 errors = JSON::Validator.fully_validate(schema, data, :errors_as_objects => true)
 
-# [{:message=>"The property '#/a' of type String did not match the following type: integer in schema 03179a21-197e-5414-9611-e9f63e8324cd#", :schema=>#, :failed_attribute=>"Type", :fragment=>"#/a"}, {:message=>"The property '#/' did not contain a required property of 'b' in schema 03179a21-197e-5414-9611-e9f63e8324cd#", :schema=>#, :failed_attribute=>"Properties", :fragment=>"#/"}]
-```
+# [{:message=>"The property '#/a' of type String did not match the following type: integer in schema 03179a21-197e-5414-9611-e9f63e8324cd#", :schema=>#<URI::Generic:0x103a76198 URL:03179a21-197e-5414-9611-e9f63e8324cd#>, :failed_attribute=>"Type", :fragment=>"#/a"}, {:message=>"The property '#/' did not contain a required property of 'b' in schema 03179a21-197e-5414-9611-e9f63e8324cd#", :schema=>#<URI::Generic:0x103a76198 URL:03179a21-197e-5414-9611-e9f63e8324cd#>, :failed_attribute=>"Pr [...]
 
-### Validate against a fragment of a supplied schema
+</pre>
 
-```rb
-require 'rubygems'
-require 'json-schema'
+h3. Validate against a fragment of a supplied schema
 
-schema = {
-  "type" => "object",
-  "required" => ["a","b"],
-  "properties" => {
-    "a" => {"type" => "integer"},
-    "b" => {"type" => "string"},
-    "c" => {
-      "type" => "object",
-      "properties" => {
-        "z" => {"type" => "integer"}
+<pre>
+  require 'rubygems'
+  require 'json-schema'
+
+  schema = {
+    "type" => "object",
+    "required" => ["a","b"],
+    "properties" => {
+      "a" => {"type" => "integer"},
+      "b" => {"type" => "string"},
+      "c" => {
+        "type" => "object",
+        "properties" => {
+          "z" => {"type" => "integer"}
+        }
       }
     }
   }
-}
 
-data = {
-  "z" => 1
-}
+  data = {
+    "z" => 1
+  }
 
-JSON::Validator.validate(schema, data, :fragment => "#/properties/c")
-```
+  JSON::Validator.validate(schema, data, :fragment => "#/properties/c")
+</pre>
 
-### Validate a JSON object against a JSON schema object, while also validating the schema itself
+h3. Validate a JSON object against a JSON schema object, while also validating the schema itself
 
-```rb
+<pre>
 require 'rubygems'
 require 'json-schema'
 
@@ -255,16 +223,14 @@ data = {
 }
 
 JSON::Validator.validate(schema, data, :validate_schema => true)
-```
+</pre>
 
-### Validate a JSON object against a JSON schema object, while inserting default values from the schema
+h3. Validate a JSON object against a JSON schema object, while inserting default values from the schema
 
-With the `:insert_defaults` option set to true any missing property that has a
-default value specified in the schema will be inserted into the validated data.
-The inserted default value is validated hence catching a schema that specifies
-an invalid default value.
+With the :insert_defaults option set to true any missing property that has a
+default value specified in the schema will be inserted into the validated data. The inserted default value is validated hence catching a schema that specifies an invalid default value.
 
-```rb
+<pre>
 require 'rubygems'
 require 'json-schema'
 
@@ -292,11 +258,11 @@ JSON::Validator.validate(schema, data, :insert_defaults => true)
 #   "a" => 42,
 #   "b" => 5
 # }
-```
 
-### Validate an object against a JSON Schema Draft 2 schema
+</pre>
+h3. Validate an object against a JSON Schema Draft 2 schema
 
-```rb
+<pre>
 require 'rubygems'
 require 'json-schema'
 
@@ -312,23 +278,15 @@ data = {
 }
 
 JSON::Validator.validate(schema, data, :version => :draft2)
-```
+</pre>
 
-### Explicitly specifying the type of the data
+h3. Explicitly specifying the type of the data
 
-By default, json-schema accepts a variety of different types for the data
-parameter, and it will try to work out what to do with it dynamically. You can
-pass it a string uri (in which case it will download the json from that location
-before validating), a string of JSON text, or simply a ruby object (such as an
-array or hash representing parsed json). However, sometimes the nature of the
-data is ambiguous (for example, is "http://github.com" just a string, or is it a
-uri?). In other situations, you have already parsed your JSON, and you don't
-need to re-parse it.
+By default, json-schema accepts a variety of different types for the data parameter, and it will try to work out what to do with it dynamically. You can pass it a string uri (in which case it will download the json from that location before validating), a string of JSON text, or simply a ruby object (such as an array or hash representing parsed json). However, sometimes the nature of the data is ambiguous (for example, is "http://github.com" just a string, or is it a uri?). In other situ [...]
 
-If you want to be explict about what kind of data is being parsed, JSON schema
-supports a number of options:
+If you want to be explict about what kind of data is being parsed, JSON schema supports a number of options:
 
-```rb
+<pre>
 require 'rubygems'
 require 'json-schema'
 
@@ -347,15 +305,13 @@ JSON::Validator.validate(schema, '"https://api.github.com"', :json => true) # re
 
 # loads data from the uri
 JSON::Validator.validate(schema, 'https://api.github.com', :uri => true) # returns false
-```
+</pre>
 
-### Extend an existing schema and validate against it
+h3. Extend an existing schema and validate against it
 
-For this example, we are going to extend the [JSON Schema Draft
-3](http://tools.ietf.org/html/draft-zyp-json-schema-03) specification by adding
-a 'bitwise-and' property for validation.
+For this example, we are going to extend the "JSON Schema Draft 3":http://tools.ietf.org/html/draft-zyp-json-schema-03 specification by adding a 'bitwise-and' property for validation.
 
-```rb
+<pre>
 require 'rubygems'
 require 'json-schema'
 
@@ -401,18 +357,13 @@ data = {"a" => 1, "b" => 5}
 JSON::Validator.validate(schema,data) # => false
 data = {"a" => 0, "b" => "taco"}
 JSON::Validator.validate(schema,data) # => false
-```
+</pre>
 
-### Custom format validation
+h3. Custom format validation
 
-The JSON schema standard allows custom formats in schema definitions which
-should be ignored by validators that do not support them. JSON::Schema allows
-registering procs as custom format validators which receive the value to be
-checked as parameter and must raise a `JSON::Schema::CustomFormatError` to
-indicate a format violation. The error message will be prepended by the property
-name, e.g. [The property '#a']()
+The JSON schema standard allows custom formats in schema definitions which should be ignored by validators that do not support them. JSON::Schema allows registering procs as custom format validators which receive the value to be checked as parameter and must raise a <code>JSON::Schema::CustomFormatError</code> to indicate a format violation. The error message will be prepended by the property name, e.g. "The property '#a'":
 
-```rb
+<pre>
 require 'rubygems'
 require 'json-schema'
 
@@ -445,26 +396,21 @@ schema = {
   }
 }
 errors = JSON::Validator.fully_validate(schema, {"a" => "23"})
-```
 
-Controlling Remote Schema Reading
----------------------------------
+</pre>
+
+h2. Controlling Remote Schema Reading
 
-In some cases, you may wish to prevent the JSON Schema library from making HTTP
-calls or reading local files in order to resolve `$ref` schemas. If you fully
-control all schemas which should be used by validation, this could be
-accomplished by registering all referenced schemas with the validator in
-advance:
+In some cases, you may wish to prevent the JSON Schema library from making HTTP calls or reading local files in order to resolve <code>$ref</code> schemas. If you fully control all schemas which should be used by validation, this could be accomplished by registering all referenced schemas with the validator in advance:
 
-```rb
+<pre>
 schema = JSON::Schema.new(some_schema_definition, Addressable::URI.parse('http://example.com/my-schema'))
 JSON::Validator.add_schema(schema)
-```
+</pre>
 
-If more extensive control is necessary, the `JSON::Schema::Reader` instance used
-can be configured in a few ways:
+If more extensive control is necessary, the <code>JSON::Schema::Reader</code> instance used can be configured in a few ways:
 
-```rb
+<pre>
 # Change the default schema reader used
 JSON::Validator.schema_reader = JSON::Schema::Reader.new(:accept_uri => true, :accept_file => false)
 
@@ -473,47 +419,34 @@ schema_reader = JSON::Schema::Reader.new(
   :accept_uri => proc { |uri| uri.host == 'my-website.com' }
 )
 JSON::Validator.validate(some_schema, some_object, :schema_reader => schema_reader)
-```
+</pre>
 
-The `JSON::Schema::Reader` interface requires only an object which responds to
-`read(string)` and returns a `JSON::Schema` instance. See the [API
-documentation](http://www.rubydoc.info/github/ruby-json-schema/json-schema/master/JSON/Schema/Reader)
-for more information.
+The <code>JSON::Schema::Reader</code> interface requires only an object which responds to <code>read(string)</code> and returns a <code>JSON::Schema</code> instance. See the "API documentation":http://www.rubydoc.info/github/ruby-json-schema/json-schema/master/JSON/Schema/Reader for more information.
 
-JSON Backends
--------------
+h2. JSON Backends
 
-The JSON Schema library currently supports the `json` and `yajl-ruby` backend
-JSON parsers. If either of these libraries are installed, they will be
-automatically loaded and used to parse any JSON strings supplied by the user.
+The JSON Schema library currently supports the <code>json</code> and <code>yajl-ruby</code> backend JSON parsers. If either of these libraries are installed, they will be automatically loaded and used to parse any JSON strings supplied by the user.
 
-If more than one of the supported JSON backends are installed, the `yajl-ruby`
-parser is used by default. This can be changed by issuing the following before
-validation:
+If more than one of the supported JSON backends are installed, the <code>yajl-ruby</code> parser is used by default. This can be changed by issuing the following before validation:
 
-```rb
+<pre>
 JSON::Validator.json_backend = :json
-```
+</pre>
 
-Optionally, the JSON Schema library supports using the MultiJSON library for
-selecting JSON backends. If the MultiJSON library is installed, it will be
-autoloaded.
+Optionally, the JSON Schema library supports using the MultiJSON library for selecting JSON backends. If the MultiJSON library is installed, it will be autoloaded.
 
-Notes
------
+h2. Notes
 
 The 'format' attribute is only validated for the following values:
 
-- date-time
-- date
-- time
-- ip-address (IPv4 address in draft1, draft2 and draft3)
-- ipv4 (IPv4 address in draft4)
-- ipv6
-- uri
-
-All other 'format' attribute values are simply checked to ensure the instance
-value is of the correct datatype (e.g., an instance value is validated to be an
-integer or a float in the case of 'utc-millisec').
+* date-time
+* date
+* time
+* ip-address (IPv4 address in draft1, draft2 and draft3)
+* ipv4 (IPv4 address in draft4)
+* ipv6
+* uri
+
+All other 'format' attribute values are simply checked to ensure the instance value is of the correct datatype (e.g., an instance value is validated to be an integer or a float in the case of 'utc-millisec').
 
 Additionally, JSON::Validator does not handle any json hyperschema attributes.
diff --git a/Rakefile b/Rakefile
new file mode 100644
index 0000000..76591dd
--- /dev/null
+++ b/Rakefile
@@ -0,0 +1,26 @@
+require 'bundler'
+require 'rake'
+require 'rake/testtask'
+
+Bundler::GemHelper.install_tasks
+
+desc "Updates the json-schema common test suite to the latest version"
+task :update_common_tests do
+  unless File.read(".git/config").include?('submodule "test/test-suite"')
+    sh "git submodule init"
+  end
+  sh "git submodule update --remote --quiet"
+end
+
+Rake::TestTask.new do |t|
+  t.libs << "."
+  t.warning = true
+  t.verbose = true
+  t.test_files = FileList.new('test/test*.rb') do |fl|
+    fl.exclude(/test_helper\.rb$/)
+  end
+end
+
+task :test => :update_common_tests
+
+task :default => :test
diff --git a/VERSION.yml b/VERSION.yml
new file mode 100644
index 0000000..e9a7edd
--- /dev/null
+++ b/VERSION.yml
@@ -0,0 +1,3 @@
+major: 2
+minor: 6
+patch: 0
diff --git a/gemfiles/Gemfile.multi_json.x b/gemfiles/Gemfile.multi_json.x
new file mode 100644
index 0000000..349d18d
--- /dev/null
+++ b/gemfiles/Gemfile.multi_json.x
@@ -0,0 +1,5 @@
+source "https://rubygems.org"
+
+gemspec :path => "../"
+
+gem "multi_json"
diff --git a/gemfiles/Gemfile.uuidtools.x b/gemfiles/Gemfile.uuidtools.x
new file mode 100644
index 0000000..e3f30e9
--- /dev/null
+++ b/gemfiles/Gemfile.uuidtools.x
@@ -0,0 +1,5 @@
+source "https://rubygems.org"
+
+gemspec :path => "../"
+
+gem "uuidtools"
diff --git a/gemfiles/Gemfile.yajl-ruby.x b/gemfiles/Gemfile.yajl-ruby.x
new file mode 100644
index 0000000..c9f10cc
--- /dev/null
+++ b/gemfiles/Gemfile.yajl-ruby.x
@@ -0,0 +1,5 @@
+source "https://rubygems.org"
+
+gemspec :path => "../"
+
+gem "yajl-ruby"
diff --git a/json-schema.gemspec b/json-schema.gemspec
new file mode 100644
index 0000000..4c14452
--- /dev/null
+++ b/json-schema.gemspec
@@ -0,0 +1,27 @@
+require 'yaml'
+
+version_yaml = YAML.load(File.open('VERSION.yml').read)
+version = "#{version_yaml['major']}.#{version_yaml['minor']}.#{version_yaml['patch']}"
+gem_name = "json-schema"
+
+Gem::Specification.new do |s|
+  s.name = gem_name
+  s.version = version
+  s.authors = ["Kenny Hoxworth"]
+  s.email = "hoxworth at gmail.com"
+  s.homepage = "http://github.com/ruby-json-schema/json-schema/tree/master"
+  s.summary = "Ruby JSON Schema Validator"
+  s.files = Dir[ "lib/**/*", "resources/*.json" ]
+  s.require_path = "lib"
+  s.extra_rdoc_files = ["README.textile","LICENSE.md"]
+  s.required_ruby_version = ">= 1.8.7"
+  s.license = "MIT"
+  s.required_rubygems_version = ">= 1.8"
+
+  s.add_development_dependency "rake"
+  s.add_development_dependency "minitest", '~> 5.0'
+  s.add_development_dependency "webmock"
+  s.add_development_dependency "bundler"
+
+  s.add_runtime_dependency "addressable", '~> 2.3.8'
+end
diff --git a/lib/json-schema/validator.rb b/lib/json-schema/validator.rb
index 50b5b07..a447fcc 100644
--- a/lib/json-schema/validator.rb
+++ b/lib/json-schema/validator.rb
@@ -569,7 +569,7 @@ module JSON
         end
         Validator.add_schema(schema)
       else
-        raise JSON::Schema::SchemaParseError, "Invalid schema - must be either a string or a hash"
+        raise SchemaParseError, "Invalid schema - must be either a string or a hash"
       end
 
       schema
diff --git a/metadata.yml b/metadata.yml
deleted file mode 100644
index 3aefe5e..0000000
--- a/metadata.yml
+++ /dev/null
@@ -1,177 +0,0 @@
---- !ruby/object:Gem::Specification
-name: json-schema
-version: !ruby/object:Gem::Version
-  version: 2.6.1
-platform: ruby
-authors:
-- Kenny Hoxworth
-autorequire: 
-bindir: bin
-cert_chain: []
-date: 2016-02-26 00:00:00.000000000 Z
-dependencies:
-- !ruby/object:Gem::Dependency
-  name: rake
-  requirement: !ruby/object:Gem::Requirement
-    requirements:
-    - - ">="
-      - !ruby/object:Gem::Version
-        version: '0'
-  type: :development
-  prerelease: false
-  version_requirements: !ruby/object:Gem::Requirement
-    requirements:
-    - - ">="
-      - !ruby/object:Gem::Version
-        version: '0'
-- !ruby/object:Gem::Dependency
-  name: minitest
-  requirement: !ruby/object:Gem::Requirement
-    requirements:
-    - - "~>"
-      - !ruby/object:Gem::Version
-        version: '5.0'
-  type: :development
-  prerelease: false
-  version_requirements: !ruby/object:Gem::Requirement
-    requirements:
-    - - "~>"
-      - !ruby/object:Gem::Version
-        version: '5.0'
-- !ruby/object:Gem::Dependency
-  name: webmock
-  requirement: !ruby/object:Gem::Requirement
-    requirements:
-    - - ">="
-      - !ruby/object:Gem::Version
-        version: '0'
-  type: :development
-  prerelease: false
-  version_requirements: !ruby/object:Gem::Requirement
-    requirements:
-    - - ">="
-      - !ruby/object:Gem::Version
-        version: '0'
-- !ruby/object:Gem::Dependency
-  name: bundler
-  requirement: !ruby/object:Gem::Requirement
-    requirements:
-    - - ">="
-      - !ruby/object:Gem::Version
-        version: '0'
-  type: :development
-  prerelease: false
-  version_requirements: !ruby/object:Gem::Requirement
-    requirements:
-    - - ">="
-      - !ruby/object:Gem::Version
-        version: '0'
-- !ruby/object:Gem::Dependency
-  name: addressable
-  requirement: !ruby/object:Gem::Requirement
-    requirements:
-    - - "~>"
-      - !ruby/object:Gem::Version
-        version: 2.3.8
-  type: :runtime
-  prerelease: false
-  version_requirements: !ruby/object:Gem::Requirement
-    requirements:
-    - - "~>"
-      - !ruby/object:Gem::Version
-        version: 2.3.8
-description: 
-email: hoxworth at gmail.com
-executables: []
-extensions: []
-extra_rdoc_files:
-- README.md
-- LICENSE.md
-files:
-- LICENSE.md
-- README.md
-- lib/json-schema.rb
-- lib/json-schema/attribute.rb
-- lib/json-schema/attributes/additionalitems.rb
-- lib/json-schema/attributes/additionalproperties.rb
-- lib/json-schema/attributes/allof.rb
-- lib/json-schema/attributes/anyof.rb
-- lib/json-schema/attributes/dependencies.rb
-- lib/json-schema/attributes/disallow.rb
-- lib/json-schema/attributes/divisibleby.rb
-- lib/json-schema/attributes/enum.rb
-- lib/json-schema/attributes/extends.rb
-- lib/json-schema/attributes/format.rb
-- lib/json-schema/attributes/formats/custom.rb
-- lib/json-schema/attributes/formats/date.rb
-- lib/json-schema/attributes/formats/date_time.rb
-- lib/json-schema/attributes/formats/date_time_v4.rb
-- lib/json-schema/attributes/formats/ip.rb
-- lib/json-schema/attributes/formats/time.rb
-- lib/json-schema/attributes/formats/uri.rb
-- lib/json-schema/attributes/items.rb
-- lib/json-schema/attributes/limit.rb
-- lib/json-schema/attributes/maxdecimal.rb
-- lib/json-schema/attributes/multipleof.rb
-- lib/json-schema/attributes/not.rb
-- lib/json-schema/attributes/oneof.rb
-- lib/json-schema/attributes/pattern.rb
-- lib/json-schema/attributes/patternproperties.rb
-- lib/json-schema/attributes/properties.rb
-- lib/json-schema/attributes/properties_optional.rb
-- lib/json-schema/attributes/ref.rb
-- lib/json-schema/attributes/required.rb
-- lib/json-schema/attributes/type.rb
-- lib/json-schema/attributes/type_v4.rb
-- lib/json-schema/attributes/uniqueitems.rb
-- lib/json-schema/errors/custom_format_error.rb
-- lib/json-schema/errors/json_load_error.rb
-- lib/json-schema/errors/json_parse_error.rb
-- lib/json-schema/errors/schema_error.rb
-- lib/json-schema/errors/schema_parse_error.rb
-- lib/json-schema/errors/uri_error.rb
-- lib/json-schema/errors/validation_error.rb
-- lib/json-schema/schema.rb
-- lib/json-schema/schema/reader.rb
-- lib/json-schema/schema/validator.rb
-- lib/json-schema/util/array_set.rb
-- lib/json-schema/util/uri.rb
-- lib/json-schema/util/uuid.rb
-- lib/json-schema/validator.rb
-- lib/json-schema/validators/draft1.rb
-- lib/json-schema/validators/draft2.rb
-- lib/json-schema/validators/draft3.rb
-- lib/json-schema/validators/draft4.rb
-- lib/json-schema/validators/hyper-draft1.rb
-- lib/json-schema/validators/hyper-draft2.rb
-- lib/json-schema/validators/hyper-draft4.rb
-- resources/draft-01.json
-- resources/draft-02.json
-- resources/draft-03.json
-- resources/draft-04.json
-homepage: http://github.com/ruby-json-schema/json-schema/tree/master
-licenses:
-- MIT
-metadata: {}
-post_install_message: 
-rdoc_options: []
-require_paths:
-- lib
-required_ruby_version: !ruby/object:Gem::Requirement
-  requirements:
-  - - ">="
-    - !ruby/object:Gem::Version
-      version: 1.8.7
-required_rubygems_version: !ruby/object:Gem::Requirement
-  requirements:
-  - - ">="
-    - !ruby/object:Gem::Version
-      version: '1.8'
-requirements: []
-rubyforge_project: 
-rubygems_version: 2.5.1
-signing_key: 
-specification_version: 4
-summary: Ruby JSON Schema Validator
-test_files: []
-has_rdoc: 
diff --git a/test/data/all_of_ref_data.json b/test/data/all_of_ref_data.json
new file mode 100644
index 0000000..18534a5
--- /dev/null
+++ b/test/data/all_of_ref_data.json
@@ -0,0 +1,3 @@
+{
+  "name" : "john"
+}
diff --git a/test/data/any_of_ref_data.json b/test/data/any_of_ref_data.json
new file mode 100644
index 0000000..0e8dc43
--- /dev/null
+++ b/test/data/any_of_ref_data.json
@@ -0,0 +1,7 @@
+{
+  "names" :
+    [ "john"
+    , "jane"
+    , "jimmy"
+    ]
+}
diff --git a/test/data/bad_data_1.json b/test/data/bad_data_1.json
new file mode 100644
index 0000000..c9313bd
--- /dev/null
+++ b/test/data/bad_data_1.json
@@ -0,0 +1,3 @@
+{
+  "a" : "poop"
+}
\ No newline at end of file
diff --git a/test/data/good_data_1.json b/test/data/good_data_1.json
new file mode 100644
index 0000000..e7c07bf
--- /dev/null
+++ b/test/data/good_data_1.json
@@ -0,0 +1,3 @@
+{
+  "a" : 5
+}
\ No newline at end of file
diff --git a/test/data/one_of_ref_links_data.json b/test/data/one_of_ref_links_data.json
new file mode 100644
index 0000000..2d66e6f
--- /dev/null
+++ b/test/data/one_of_ref_links_data.json
@@ -0,0 +1,5 @@
+{ "links":
+  [{ "rel" : ["self"] , "href":"http://api.example.com/api/object/3" }
+  ,{ "rel" : ["up"] , "href":"http://api.example.com/api/object" }
+  ]
+}
diff --git a/test/schemas/address_microformat.json b/test/schemas/address_microformat.json
new file mode 100644
index 0000000..e1cdd20
--- /dev/null
+++ b/test/schemas/address_microformat.json
@@ -0,0 +1,18 @@
+{
+    "description": "An Address following the convention of http://microformats.org/wiki/hcard",
+    "type": "object",
+    "properties": {
+        "post-office-box": { "type": "string" },
+        "extended-address": { "type": "string" },
+        "street-address": { "type": "string" },
+        "locality":{ "type": "string" },
+        "region": { "type": "string" },
+        "postal-code": { "type": "string" },
+        "country-name": { "type": "string"}
+    },
+    "required": ["locality", "region", "country-name"],
+    "dependencies": {
+        "post-office-box": "street-address",
+        "extended-address": "street-address"
+    }
+}
diff --git a/test/schemas/all_of_ref_base_schema.json b/test/schemas/all_of_ref_base_schema.json
new file mode 100644
index 0000000..76a17b2
--- /dev/null
+++ b/test/schemas/all_of_ref_base_schema.json
@@ -0,0 +1,6 @@
+{
+	"type": "object",
+	"properties" : {
+   		"name" : { "type": "integer" }
+ 	}
+}
diff --git a/test/schemas/all_of_ref_schema.json b/test/schemas/all_of_ref_schema.json
new file mode 100644
index 0000000..36a6161
--- /dev/null
+++ b/test/schemas/all_of_ref_schema.json
@@ -0,0 +1,7 @@
+{ "$schema" : "http://json-schema.org/draft-04/schema#",
+  "type" : "object",
+  "allOf" :
+  [ { "$ref" : "all_of_ref_base_schema.json" }
+  ]
+
+}
diff --git a/test/schemas/any_of_ref_jane_schema.json b/test/schemas/any_of_ref_jane_schema.json
new file mode 100644
index 0000000..fc42b2d
--- /dev/null
+++ b/test/schemas/any_of_ref_jane_schema.json
@@ -0,0 +1,4 @@
+{ "$schema" : "http://json-schema.org/draft-04/schema#"
+, "type" : "string"
+, "pattern" : "jane"
+}
diff --git a/test/schemas/any_of_ref_jimmy_schema.json b/test/schemas/any_of_ref_jimmy_schema.json
new file mode 100644
index 0000000..f77d023
--- /dev/null
+++ b/test/schemas/any_of_ref_jimmy_schema.json
@@ -0,0 +1,4 @@
+{ "$schema" : "http://json-schema.org/draft-04/schema#"
+, "type" : "string"
+, "pattern" : "jimmy"
+}
diff --git a/test/schemas/any_of_ref_john_schema.json b/test/schemas/any_of_ref_john_schema.json
new file mode 100644
index 0000000..6d5cc9e
--- /dev/null
+++ b/test/schemas/any_of_ref_john_schema.json
@@ -0,0 +1,4 @@
+{ "$schema" : "http://json-schema.org/draft-04/schema#"
+, "type" : "string"
+, "pattern" : "john"
+}
diff --git a/test/schemas/any_of_ref_schema.json b/test/schemas/any_of_ref_schema.json
new file mode 100644
index 0000000..59863ae
--- /dev/null
+++ b/test/schemas/any_of_ref_schema.json
@@ -0,0 +1,15 @@
+{ "$schema" : "http://json-schema.org/draft-04/schema#"
+, "type" : "object"
+, "properties" :
+  { "names" :
+    { "type" : "array"
+    , "items" :
+      { "anyOf" :
+        [ { "$ref" : "any_of_ref_john_schema.json" }
+        , { "$ref" : "any_of_ref_jane_schema.json" }
+        , { "$ref" : "any_of_ref_jimmy_schema.json" }
+        ]
+      }
+    }
+  }
+}
diff --git a/test/schemas/definition_schema.json b/test/schemas/definition_schema.json
new file mode 100644
index 0000000..0f52036
--- /dev/null
+++ b/test/schemas/definition_schema.json
@@ -0,0 +1,15 @@
+{
+  "$schema": "http://json-schema.org/draft-04/schema#",
+  "description": "schema with definition",
+  "type": "object",
+  "properties": {
+    "a": {
+      "$ref": "#/definitions/foo"
+    }
+  },
+  "definitions": {
+    "foo": {
+      "type": "integer"
+    }
+  }
+}
diff --git a/test/schemas/extends_and_additionalProperties-1-filename.schema.json b/test/schemas/extends_and_additionalProperties-1-filename.schema.json
new file mode 100644
index 0000000..507d9cc
--- /dev/null
+++ b/test/schemas/extends_and_additionalProperties-1-filename.schema.json
@@ -0,0 +1,34 @@
+{
+  "$schema": "http://json-schema.org/draft-03/schema#",
+  "type": "object",
+  "extends": "inner.schema.json",
+  "properties": {
+    "outerA": {
+      "description": "blah",
+      "required": false,
+      "additionalProperties": false,
+      "properties": {
+        "outerA1": {
+		  "type":"boolean",
+          "required": false
+        }
+      }
+    },
+    "outerB": {
+      "required": false,
+      "type": "array",
+      "minItems": 1,
+      "maxItems": 50,
+      "items": {
+        "extends": "inner.schema.json",
+        "additionalProperties": false
+      }
+    },
+    "outerC": {
+      "description": "blah",
+      "type":"boolean",
+      "required": false
+    }
+  },
+  "additionalProperties": false
+}
diff --git a/test/schemas/extends_and_additionalProperties-1-ref.schema.json b/test/schemas/extends_and_additionalProperties-1-ref.schema.json
new file mode 100644
index 0000000..9be3b23
--- /dev/null
+++ b/test/schemas/extends_and_additionalProperties-1-ref.schema.json
@@ -0,0 +1,34 @@
+{
+  "$schema": "http://json-schema.org/draft-03/schema#",
+  "type": "object",
+  "extends": {"$ref":"inner.schema.json#"},
+  "properties": {
+    "outerA": {
+      "description": "blah",
+      "required": false,
+      "additionalProperties": false,
+      "properties": {
+        "outerA1": {
+		  "type":"boolean",
+          "required": false
+        }
+      }
+    },
+    "outerB": {
+      "required": false,
+      "type": "array",
+      "minItems": 1,
+      "maxItems": 50,
+      "items": {
+        "extends": {"$ref":"inner.schema.json#"},
+        "additionalProperties": false
+      }
+    },
+    "outerC": {
+      "description": "blah",
+      "type":"boolean",
+      "required": false
+    }
+  },
+  "additionalProperties": false
+}
diff --git a/test/schemas/extends_and_additionalProperties-2-filename.schema.json b/test/schemas/extends_and_additionalProperties-2-filename.schema.json
new file mode 100644
index 0000000..ec6363c
--- /dev/null
+++ b/test/schemas/extends_and_additionalProperties-2-filename.schema.json
@@ -0,0 +1,33 @@
+{
+  "$schema": "http://json-schema.org/draft-03/schema#",
+  "type": "object",
+  "extends": "inner.schema.json",
+  "additionalProperties": {
+    "outerA": {
+      "description": "blah",
+      "required": false,
+      "additionalProperties": false,
+      "properties": {
+        "outerA1": {
+		  "type":"boolean",
+          "required": false
+        }
+      }
+    },
+    "outerB": {
+      "required": false,
+      "type": "array",
+      "minItems": 1,
+      "maxItems": 50,
+      "items": {
+        "extends": "inner.schema.json",
+        "additionalProperties": false
+      }
+    },
+    "outerC": {
+      "description": "blah",
+      "type":"boolean",
+      "required": false
+    }
+  }
+}
diff --git a/test/schemas/extends_and_additionalProperties-2-ref.schema.json b/test/schemas/extends_and_additionalProperties-2-ref.schema.json
new file mode 100644
index 0000000..0b05c9b
--- /dev/null
+++ b/test/schemas/extends_and_additionalProperties-2-ref.schema.json
@@ -0,0 +1,33 @@
+{
+  "$schema": "http://json-schema.org/draft-03/schema#",
+  "type": "object",
+  "extends": {"$ref":"inner.schema.json#"},
+  "additionalProperties": {
+    "outerA": {
+      "description": "blah",
+      "required": false,
+      "additionalProperties": false,
+      "properties": {
+        "outerA1": {
+		  "type":"boolean",
+          "required": false
+        }
+      }
+    },
+    "outerB": {
+      "required": false,
+      "type": "array",
+      "minItems": 1,
+      "maxItems": 50,
+      "items": {
+        "extends": {"$ref":"inner.schema.json#"},
+        "additionalProperties": false
+      }
+    },
+    "outerC": {
+      "description": "blah",
+      "type":"boolean",
+      "required": false
+    }
+  }
+}
diff --git a/test/schemas/good_schema_1.json b/test/schemas/good_schema_1.json
new file mode 100644
index 0000000..92597fa
--- /dev/null
+++ b/test/schemas/good_schema_1.json
@@ -0,0 +1,10 @@
+{
+  "$schema" : "http://json-schema.org/draft-03/schema#",
+  "type" : "object",
+  "properties" : {
+    "a" : {
+      "type" : "integer",
+      "required" : true
+    }
+  }
+}
\ No newline at end of file
diff --git a/test/schemas/good_schema_2.json b/test/schemas/good_schema_2.json
new file mode 100644
index 0000000..caa8bb8
--- /dev/null
+++ b/test/schemas/good_schema_2.json
@@ -0,0 +1,10 @@
+{
+  "$schema" : "http://json-schema.org/draft-03/schema#",
+  "type" : "object",
+  "properties" : {
+    "b" : {
+      "required" : true,
+      "$ref" : "good_schema_1.json"
+    }
+  }
+}
diff --git a/test/schemas/good_schema_extends1.json b/test/schemas/good_schema_extends1.json
new file mode 100644
index 0000000..84d75b5
--- /dev/null
+++ b/test/schemas/good_schema_extends1.json
@@ -0,0 +1,10 @@
+{
+  "$schema" : "http://json-schema.org/draft-03/schema#",
+  "type" : "object",
+  "extends": {"$ref": "good_schema_1.json"},
+  "properties" : {
+    "c" : {
+      "required" : false
+    }
+  }
+}
diff --git a/test/schemas/good_schema_extends2.json b/test/schemas/good_schema_extends2.json
new file mode 100644
index 0000000..a2618d2
--- /dev/null
+++ b/test/schemas/good_schema_extends2.json
@@ -0,0 +1,13 @@
+{
+  "$schema" : "http://json-schema.org/draft-03/schema#",
+  "type" : "object",
+  "extends": [
+    {"$ref": "good_schema_1.json"},
+    {"$ref": "good_schema_2.json"}
+  ],
+  "properties" : {
+    "c" : {
+      "required" : false
+    }
+  }
+}
diff --git a/test/schemas/inner.schema.json b/test/schemas/inner.schema.json
new file mode 100644
index 0000000..2da7964
--- /dev/null
+++ b/test/schemas/inner.schema.json
@@ -0,0 +1,21 @@
+{
+  "$schema": "http://json-schema.org/draft-03/schema#",
+  "type": "object",
+  "properties": {
+    "innerA": {
+      "description": "blah",
+      "type":"boolean",
+      "required": false
+    },
+    "innerB": {
+      "description": "blah",
+      "type":"boolean",
+      "required": false
+    },
+    "innerC": {
+      "description": "blah",
+      "required": false,
+      "type": "boolean"
+    }
+  }
+}
diff --git a/test/schemas/one_of_ref_links_schema.json b/test/schemas/one_of_ref_links_schema.json
new file mode 100644
index 0000000..fedda6d
--- /dev/null
+++ b/test/schemas/one_of_ref_links_schema.json
@@ -0,0 +1,16 @@
+{ "$schema": "http://json-schema.org/draft-04/schema#"
+, "type": "object"
+, "properties":
+  { "links" :
+    { "type" : "array"
+    , "items" :
+      { "type" : "object"
+      , "oneOf" :
+        [ { "$ref" : "self_link_schema.json"}
+        , { "$ref" : "up_link_schema.json" }
+        ]
+      }
+    }
+  }
+}
+
diff --git a/test/schemas/ref john with spaces schema.json b/test/schemas/ref john with spaces schema.json
new file mode 100644
index 0000000..ea431dd
--- /dev/null
+++ b/test/schemas/ref john with spaces schema.json	
@@ -0,0 +1,11 @@
+{
+  "$schema" : "http://json-schema.org/draft-04/schema#",
+  "type" : "object",
+  "required" : ["first"],
+  "properties": {
+    "first": {
+      "type": "string",
+      "enum": ["john"]
+    }
+  }
+}
diff --git a/test/schemas/relative_definition_schema.json b/test/schemas/relative_definition_schema.json
new file mode 100644
index 0000000..240b35c
--- /dev/null
+++ b/test/schemas/relative_definition_schema.json
@@ -0,0 +1,8 @@
+{
+  "$schema": "http://json-schema.org/draft-04/schema#",
+  "properties": {
+    "a": {
+      "$ref": "definition_schema.json#/definitions/foo"
+    }
+  }
+}
\ No newline at end of file
diff --git a/test/schemas/self_link_schema.json b/test/schemas/self_link_schema.json
new file mode 100644
index 0000000..abe6e20
--- /dev/null
+++ b/test/schemas/self_link_schema.json
@@ -0,0 +1,17 @@
+{ "$schema": "http://json-schema.org/draft-04/schema#"
+, "type": "object"
+, "properties" :
+  { "rel" :
+    { "type" : "array"
+    , "items" :
+      [ { "type" : "string"
+        , "pattern" : "self"
+        }
+      ]
+    }
+  , "href" :
+    { "type" : "string"
+    }
+  }
+}
+
diff --git a/test/schemas/up_link_schema.json b/test/schemas/up_link_schema.json
new file mode 100644
index 0000000..d95c213
--- /dev/null
+++ b/test/schemas/up_link_schema.json
@@ -0,0 +1,17 @@
+{ "$schema": "http://json-schema.org/draft-04/schema#"
+, "type": "object"
+, "properties" :
+  { "rel" :
+    { "type" : "array"
+    , "items" :
+      [ { "type" : "string"
+        , "pattern" : "up"
+        }
+      ]
+    }
+  , "href" :
+    { "type" : "string"
+    }
+  }
+}
+
diff --git a/test/support/array_validation.rb b/test/support/array_validation.rb
new file mode 100644
index 0000000..3d6877f
--- /dev/null
+++ b/test/support/array_validation.rb
@@ -0,0 +1,108 @@
+module ArrayValidation
+  module ItemsTests
+    def test_items_single_schema
+      schema = { 'items' => { 'type' => 'string' } }
+
+      assert_valid schema, []
+      assert_valid schema, ['a']
+      assert_valid schema, ['a', 'b']
+
+      refute_valid schema, [1]
+      refute_valid schema, ['a', 1]
+
+      # other types are disregarded
+      assert_valid schema, {'a' => 'foo'}
+    end
+
+    def test_items_multiple_schemas
+      schema = {
+        'items' => [
+          { 'type' => 'string' },
+          { 'type' => 'integer' }
+        ]
+      }
+
+      assert_valid schema, ['b', 1]
+      assert_valid schema, ['b', 1, nil]
+      refute_valid schema, [1, 'b']
+      refute_valid schema, []
+    end
+
+    def test_minitems
+      schema = { 'minItems' => 1 }
+
+      assert_valid schema, [1]
+      assert_valid schema, [1, 2]
+      refute_valid schema, []
+
+      # other types are disregarded
+      assert_valid schema, 5
+    end
+
+    def test_maxitems
+      schema = { 'maxItems' => 1 }
+
+      assert_valid schema, []
+      assert_valid schema, [1]
+      refute_valid schema, [1, 2]
+
+      # other types are disregarded
+      assert_valid schema, 5
+    end
+  end
+
+  module AdditionalItemsTests
+    def test_additional_items_false
+      schema = {
+        'items' => [
+          { 'type' => 'integer' },
+          { 'type' => 'string' }
+        ],
+        'additionalItems' => false
+      }
+
+      assert_valid schema, [1, 'string']
+      refute_valid schema, [1, 'string', 2]
+      refute_valid schema, ['string', 1]
+    end
+
+    def test_additional_items_schema
+      schema = {
+        'items' => [
+          { 'type' => 'integer' },
+          { 'type' => 'string' }
+        ],
+        'additionalItems' => { 'type' => 'integer' }
+      }
+
+      assert_valid schema, [1, 'string']
+      assert_valid schema, [1, 'string', 2]
+      refute_valid schema, [1, 'string', 'string']
+    end
+  end
+
+  module UniqueItemsTests
+    def test_unique_items
+      schema = { 'uniqueItems' => true }
+
+      assert_valid schema, [nil, 5]
+      refute_valid schema, [nil, nil]
+
+      assert_valid schema, [true, false]
+      refute_valid schema, [true, true]
+
+      assert_valid schema, [4, 4.1]
+      refute_valid schema, [4, 4]
+
+      assert_valid schema, ['a', 'ab']
+      refute_valid schema, ['a', 'a']
+
+      assert_valid schema, [[1], [2]]
+      refute_valid schema, [[1], [1]]
+
+      assert_valid schema, [{'b' => 1}, {'c' => 2}]
+      assert_valid schema, [{'b' => 1}, {'c' => 1}]
+      refute_valid schema, [{'b' => 1}, {'b' => 1}]
+    end
+  end
+end
diff --git a/test/support/enum_validation.rb b/test/support/enum_validation.rb
new file mode 100644
index 0000000..c83e5b9
--- /dev/null
+++ b/test/support/enum_validation.rb
@@ -0,0 +1,133 @@
+module EnumValidation
+  module V1_V2
+    def test_enum_optional
+      schema = {
+        "properties" => {
+          "a" => {"enum" => [1,'boo',[1,2,3],{"a" => "b"}], "optional" => true}
+        }
+      }
+
+      data = {}
+      assert_valid schema, data
+    end
+  end
+
+  module V3_V4
+    def test_enum_optional
+      schema = {
+        "properties" => {
+          "a" => {"enum" => [1,'boo',[1,2,3],{"a" => "b"}]}
+        }
+      }
+
+      data = {}
+      assert_valid schema, data
+    end
+  end
+
+  module General
+    def test_enum_general
+      schema = {
+        "properties" => {
+          "a" => {"enum" => [1,'boo',[1,2,3],{"a" => "b"}]}
+        }
+      }
+
+      data = { "a" => 1 }
+      assert_valid schema, data
+
+      data["a"] = 'boo'
+      assert_valid schema, data
+
+      data["a"] = [1,2,3]
+      assert_valid schema, data
+
+      data["a"] = {"a" => "b"}
+      assert_valid schema, data
+
+      data["a"] = 'taco'
+      refute_valid schema, data
+    end
+
+    def test_enum_number_integer_includes_float
+      schema = {
+        "properties" => {
+          "a" => {
+            "type" => "number",
+            "enum" => [0, 1, 2]
+          }
+        }
+      }
+
+      data = { "a" => 0 }
+      assert_valid schema, data
+
+      data["a"] = 0.0
+      assert_valid schema, data
+
+      data["a"] = 1
+      assert_valid schema, data
+
+      data["a"] = 1.0
+      assert_valid schema, data
+    end
+
+    def test_enum_number_float_includes_integer
+      schema = {
+        "properties" => {
+          "a" => {
+            "type" => "number",
+            "enum" => [0.0, 1.0, 2.0]
+          }
+        }
+      }
+
+      data = { "a" => 0.0 }
+      assert_valid schema, data
+
+      data["a"] = 0
+      assert_valid schema, data
+
+
+      data["a"] = 1.0
+      assert_valid schema, data
+
+      data["a"] = 1
+      assert_valid schema, data
+    end
+
+    def test_enum_integer_excludes_float
+      schema = {
+        "properties" => {
+          "a" => {
+            "type" => "integer",
+            "enum" => [0, 1, 2]
+          }
+        }
+      }
+
+      data = { "a" => 0 }
+      assert_valid schema, data
+
+      data["a"] = 0.0
+      refute_valid schema, data
+
+
+      data["a"] = 1
+      assert_valid schema, data
+
+      data["a"] = 1.0
+      refute_valid schema, data
+    end
+
+    def test_enum_with_schema_validation
+      schema = {
+        "properties" => {
+          "a" => {"enum" => [1,'boo',[1,2,3],{"a" => "b"}]}
+        }
+      }
+      data = { "a" => 1 }
+      assert_valid(schema, data, :validate_schema => true)
+    end
+  end
+end
diff --git a/test/support/number_validation.rb b/test/support/number_validation.rb
new file mode 100644
index 0000000..c4d767e
--- /dev/null
+++ b/test/support/number_validation.rb
@@ -0,0 +1,93 @@
+module NumberValidation
+  module MinMaxTests
+    def test_minimum
+      schema = {
+        'properties' => {
+          'a' => { 'minimum' => 5 }
+        }
+      }
+
+      assert_valid schema, {'a' => 5}
+      assert_valid schema, {'a' => 6}
+
+      refute_valid schema, {'a' => 4}
+      refute_valid schema, {'a' => 4.99999}
+
+      # other types are disregarded
+      assert_valid schema, {'a' => 'str'}
+    end
+
+    def test_exclusive_minimum
+      schema = {
+        'properties' => {
+          'a' => { 'minimum' => 5 }.merge(exclusive_minimum)
+        }
+      }
+
+      assert_valid schema, {'a' => 6}
+      assert_valid schema, {'a' => 5.0001}
+      refute_valid schema, {'a' => 5}
+    end
+
+    def test_maximum
+      schema = {
+        'properties' => {
+          'a' => { 'maximum' => 5 }
+        }
+      }
+
+      assert_valid schema, {'a' => 4}
+      assert_valid schema, {'a' => 5}
+
+      refute_valid schema, {'a' => 6}
+      refute_valid schema, {'a' => 5.0001}
+    end
+
+    def test_exclusive_maximum
+      schema = {
+        'properties' => {
+          'a' => { 'maximum' => 5 }.merge(exclusive_maximum)
+        }
+      }
+
+      assert_valid schema, {'a' => 4}
+      assert_valid schema, {'a' => 4.99999}
+      refute_valid schema, {'a' => 5}
+    end
+  end
+
+  # draft3 introduced `divisibleBy`, renamed to `multipleOf` in draft4.
+  # Favor the newer name, but the behavior should be identical.
+  module MultipleOfTests
+    def multiple_of
+      'multipleOf'
+    end
+
+    def test_multiple_of
+      schema = {
+        'properties' => {
+          'a' => { multiple_of => 1.1 }
+        }
+      }
+
+      assert_valid schema, {'a' => 0}
+
+      assert_valid schema, {'a' => 2.2}
+      refute_valid schema, {'a' => 3.4}
+
+      # other types are disregarded
+      assert_valid schema, {'a' => 'hi'}
+    end
+
+    def test_multiple_of_zero
+      schema = {
+        'properties' => {
+          'a' => { multiple_of => 0 }
+        }
+      }
+
+      refute_valid schema, {'a' => 5}
+      refute_valid schema, {'a' => 0}
+    end
+  end
+end
diff --git a/test/support/object_validation.rb b/test/support/object_validation.rb
new file mode 100644
index 0000000..c5e1503
--- /dev/null
+++ b/test/support/object_validation.rb
@@ -0,0 +1,68 @@
+module ObjectValidation
+  module AdditionalPropertiesTests
+    def test_additional_properties_false
+      schema = {
+        'properties' => {
+          'a' => { 'type' => 'integer' }
+        },
+        'additionalProperties' => false
+      }
+
+      assert_valid schema, {'a' => 1}
+      refute_valid schema, {'a' => 1, 'b' => 2}
+    end
+
+    def test_additional_properties_schema
+      schema = {
+        'properties' => {
+          'a' => { 'type' => 'integer' }
+        },
+        'additionalProperties' => { 'type' => 'string' }
+      }
+
+      assert_valid schema, {'a' => 1}
+      assert_valid schema, {'a' => 1, 'b' => 'hi'}
+      refute_valid schema, {'a' => 1, 'b' => 2}
+    end
+  end
+
+  module PatternPropertiesTests
+    def test_pattern_properties
+      schema = {
+        'patternProperties' => {
+          "\\d+ taco" => { 'type' => 'integer' }
+        }
+      }
+
+      assert_valid schema, {'1 taco' => 1, '20 taco' => 20}
+      assert_valid schema, {'foo' => true, '1 taco' => 1}
+      refute_valid schema, {'1 taco' => 'yum'}
+    end
+
+    def test_pattern_properties_additional_properties_false
+      schema = {
+        'patternProperties' => {
+          "\\d+ taco" => { 'type' => 'integer' }
+        },
+        'additionalProperties' => false
+      }
+
+      assert_valid schema, {'1 taco' => 1}
+      refute_valid schema, {'1 taco' => 'yum'}
+      refute_valid schema, {'1 taco' => 1, 'foo' => true}
+    end
+
+    def test_pattern_properties_additional_properties_schema
+      schema = {
+        'patternProperties' => {
+          "\\d+ taco" => { 'type' => 'integer' }
+        },
+        'additionalProperties' => { 'type' => 'string' }
+      }
+
+      assert_valid schema, {'1 taco' => 1}
+      assert_valid schema, {'1 taco' => 1, 'foo' => 'bar'}
+      refute_valid schema, {'1 taco' => 1, 'foo' => 2}
+    end
+  end
+end
diff --git a/test/support/strict_validation.rb b/test/support/strict_validation.rb
new file mode 100644
index 0000000..06d9fd6
--- /dev/null
+++ b/test/support/strict_validation.rb
@@ -0,0 +1,89 @@
+module StrictValidation
+  def test_strict_properties
+    schema = {
+      "$schema" => "http://json-schema.org/draft-04/schema#",
+      "properties" => {
+        "a" => {"type" => "string"},
+        "b" => {"type" => "string"}
+      }
+    }
+
+    data = {"a" => "a"}
+    assert(!JSON::Validator.validate(schema,data,:strict => true))
+
+    data = {"b" => "b"}
+    assert(!JSON::Validator.validate(schema,data,:strict => true))
+
+    data = {"a" => "a", "b" => "b"}
+    assert(JSON::Validator.validate(schema,data,:strict => true))
+
+    data = {"a" => "a", "b" => "b", "c" => "c"}
+    assert(!JSON::Validator.validate(schema,data,:strict => true))
+  end
+
+  def test_strict_error_message
+    schema = { :type => 'object', :properties => { :a => { :type => 'string' } } }
+    data = { :a => 'abc', :b => 'abc' }
+    errors = JSON::Validator.fully_validate(schema,data,:strict => true)
+    assert_match("The property '#/' contained undefined properties: 'b' in schema", errors[0])
+  end
+
+  def test_strict_properties_additional_props
+    schema = {
+      "$schema" => "http://json-schema.org/draft-04/schema#",
+      "properties" => {
+        "a" => {"type" => "string"},
+        "b" => {"type" => "string"}
+      },
+      "additionalProperties" => {"type" => "integer"}
+    }
+
+    data = {"a" => "a"}
+    assert(!JSON::Validator.validate(schema,data,:strict => true))
+
+    data = {"b" => "b"}
+    assert(!JSON::Validator.validate(schema,data,:strict => true))
+
+    data = {"a" => "a", "b" => "b"}
+    assert(JSON::Validator.validate(schema,data,:strict => true))
+
+    data = {"a" => "a", "b" => "b", "c" => "c"}
+    assert(!JSON::Validator.validate(schema,data,:strict => true))
+
+    data = {"a" => "a", "b" => "b", "c" => 3}
+    assert(JSON::Validator.validate(schema,data,:strict => true))
+  end
+
+  def test_strict_properties_pattern_props
+    schema = {
+      "$schema" => "http://json-schema.org/draft-03/schema#",
+      "properties" => {
+        "a" => {"type" => "string"},
+        "b" => {"type" => "string"}
+      },
+      "patternProperties" => {"\\d+ taco" => {"type" => "integer"}}
+    }
+
+    data = {"a" => "a"}
+    assert(!JSON::Validator.validate(schema,data,:strict => true))
+
+    data = {"b" => "b"}
+    assert(!JSON::Validator.validate(schema,data,:strict => true))
+
+    data = {"a" => "a", "b" => "b"}
+    assert(JSON::Validator.validate(schema,data,:strict => true))
+
+    data = {"a" => "a", "b" => "b", "c" => "c"}
+    assert(!JSON::Validator.validate(schema,data,:strict => true))
+
+    data = {"a" => "a", "b" => "b", "c" => 3}
+    assert(!JSON::Validator.validate(schema,data,:strict => true))
+
+    data = {"a" => "a", "b" => "b", "23 taco" => 3}
+    assert(JSON::Validator.validate(schema,data,:strict => true))
+
+    data = {"a" => "a", "b" => "b", "23 taco" => "cheese"}
+    assert(!JSON::Validator.validate(schema,data,:strict => true))
+  end
+
+end
diff --git a/test/support/string_validation.rb b/test/support/string_validation.rb
new file mode 100644
index 0000000..b8d911c
--- /dev/null
+++ b/test/support/string_validation.rb
@@ -0,0 +1,154 @@
+module StringValidation
+  module ValueTests
+    def test_minlength
+      schema = {
+        'properties' => {
+          'a' => { 'minLength' => 1 }
+        }
+      }
+
+      assert_valid schema, {'a' => 't'}
+      refute_valid schema, {'a' => ''}
+
+      # other types are disregarded
+      assert_valid schema, {'a' => 5}
+    end
+
+    def test_maxlength
+      schema = {
+        'properties' => {
+          'a' => { 'maxLength' => 2 }
+        }
+      }
+
+      assert_valid schema, {'a' => 'tt'}
+      assert_valid schema, {'a' => ''}
+      refute_valid schema, {'a' => 'ttt'}
+
+      # other types are disregarded
+      assert_valid schema, {'a' => 5}
+    end
+
+    def test_pattern
+      schema = {
+        'properties' => {
+          'a' => { 'pattern' => "\\d+ taco" }
+        }
+      }
+
+      assert_valid schema, {'a' => '156 taco bell'}
+      refute_valid schema, {'a' => 'x taco'}
+
+      # other types are disregarded
+      assert_valid schema, {'a' => 5}
+    end
+  end
+
+  module FormatTests
+    # Draft1..3 use the format name `ip-address`; draft4 changed it to `ipv4`.
+    def ipv4_format
+      'ip-address'
+    end
+
+    def test_format_unknown
+      schema = {
+        'properties' => {
+          'a' => { 'format' => 'unknown' }
+        }
+      }
+
+      assert_valid schema, {'a' => 'absolutely anything!'}
+      assert_valid schema, {'a' => ''}
+    end
+
+    def test_format_union
+      schema = {
+        'properties' => {
+          'a' => {
+            'type'   => ['string', 'null'],
+            'format' => 'date-time'
+          }
+        }
+      }
+
+      assert_valid schema, {'a' => nil}
+      refute_valid schema, {'a' => 'wrong'}
+    end
+
+    def test_format_ipv4
+      schema = {
+        'properties' => {
+          'a' => { 'format' => ipv4_format }
+        }
+      }
+
+      assert_valid schema, {"a" => "1.1.1.1"}
+      refute_valid schema, {"a" => "1.1.1"}
+      refute_valid schema, {"a" => "1.1.1.300"}
+      refute_valid schema, {"a" => "1.1.1"}
+      refute_valid schema, {"a" => "1.1.1.1b"}
+
+      # other types are disregarded
+      assert_valid schema, {'a' => 5}
+    end
+
+    def test_format_ipv6
+      schema = {
+        'properties' => {
+          'a' => { 'format' => 'ipv6' }
+        }
+      }
+
+      assert_valid schema, {"a" => "1111:2222:8888:9999:aaaa:cccc:eeee:ffff"}
+      assert_valid schema, {"a" => "1111:0:8888:0:0:0:eeee:ffff"}
+      assert_valid schema, {"a" => "1111:2222:8888::eeee:ffff"}
+      assert_valid schema, {"a" => "::1"}
+
+      refute_valid schema, {"a" => "1111:2222:8888:99999:aaaa:cccc:eeee:ffff"}
+      refute_valid schema, {"a" => "1111:2222:8888:9999:aaaa:cccc:eeee:gggg"}
+      refute_valid schema, {"a" => "1111:2222::9999::cccc:eeee:ffff"}
+      refute_valid schema, {"a" => "1111:2222:8888:9999:aaaa:cccc:eeee:ffff:bbbb"}
+      refute_valid schema, {"a" => "42"}
+      refute_valid schema, {"a" => "b"}
+    end
+  end
+
+  # Draft1..3 explicitly support `date`, `time` formats in addition to
+  # the `date-time` format.
+  module DateAndTimeFormatTests
+    def test_format_time
+      schema = {
+        'properties' => {
+          'a' => { 'format' => 'time' }
+        }
+      }
+
+      assert_valid schema, {"a" => "12:00:00"}
+      refute_valid schema, {"a" => "12:00"}
+      refute_valid schema, {"a" => "12:00:60"}
+      refute_valid schema, {"a" => "12:60:00"}
+      refute_valid schema, {"a" => "24:00:00"}
+      refute_valid schema, {"a" => "0:00:00"}
+      refute_valid schema, {"a" => "-12:00:00"}
+      refute_valid schema, {"a" => "12:00:00b"}
+      assert_valid schema, {"a" => "12:00:00"}
+      refute_valid schema, {"a" => "12:00:00\nabc"}
+    end
+
+    def test_format_date
+      schema = {
+        'properties' => {
+          'a' => { 'format' => 'date' }
+        }
+      }
+
+      assert_valid schema, {"a" => "2010-01-01"}
+      refute_valid schema, {"a" => "2010-01-32"}
+      refute_valid schema, {"a" => "n2010-01-01"}
+      refute_valid schema, {"a" => "2010-1-01"}
+      refute_valid schema, {"a" => "2010-01-1"}
+      refute_valid schema, {"a" => "2010-01-01n"}
+      refute_valid schema, {"a" => "2010-01-01\nabc"}
+    end
+  end
+end
diff --git a/test/support/type_validation.rb b/test/support/type_validation.rb
new file mode 100644
index 0000000..20965b7
--- /dev/null
+++ b/test/support/type_validation.rb
@@ -0,0 +1,81 @@
+module TypeValidation
+  # The draft4 schema refers to the JSON types as 'simple types';
+  # see draft4#/definitions/simpleTypes
+  module SimpleTypeTests
+    TYPES = {
+      'integer' => 5,
+      'number'  => 5.0,
+      'string'  => 'str',
+      'boolean' => true,
+      'object'  => {},
+      'array'   => [],
+      'null'    => nil
+    }
+
+    TYPES.each do |name, value|
+      other_values = TYPES.values.reject { |v| v == value }
+
+      define_method(:"test_#{name}_type_property") do
+        schema = {
+          'properties' => { 'a' => { 'type' => name } }
+        }
+        assert_valid schema, {'a' => value}
+
+        other_values.each do |other_value|
+          refute_valid schema, {'a' => other_value}
+        end
+      end
+
+      define_method(:"test_#{name}_type_value") do
+        schema = { 'type' => name }
+        assert_valid schema, value
+
+        other_values.each do |other_value|
+          schema = { 'type' => name }
+          refute_valid schema, other_value
+        end
+      end
+    end
+
+    def test_type_union
+      schema = { 'type' => ['integer', 'string'] }
+      assert_valid schema, 5
+      assert_valid schema, 'str'
+      refute_valid schema, nil
+      refute_valid schema, [5, 'str']
+    end
+  end
+
+  # The draft1..3 schemas support an additional type, `any`.
+  module AnyTypeTests
+    def test_any_type
+      schema = { 'type' => 'any' }
+
+      SimpleTypeTests::TYPES.values.each do |value|
+        assert_valid schema, value
+      end
+    end
+  end
+
+  # The draft1..3 schemas support schemas as values for `type`.
+  module SchemaUnionTypeTests
+    def test_union_type_with_schemas
+      schema = {
+        'properties' => {
+          'a' => {
+            'type' => [
+              {'type' => 'string'},
+              {'type' => 'object', 'properties' => { 'b' => { 'type' => 'integer' }}}
+            ]
+          }
+        }
+      }
+
+      assert_valid schema, {'a' => 'test'}
+      refute_valid schema, {'a' => 5}
+
+      assert_valid schema, {'a' => {'b' => 5}}
+      refute_valid schema, {'a' => {'b' => 'taco'}}
+    end
+  end
+end
diff --git a/test/test_all_of_ref_schema.rb b/test/test_all_of_ref_schema.rb
new file mode 100644
index 0000000..8ab6bf0
--- /dev/null
+++ b/test/test_all_of_ref_schema.rb
@@ -0,0 +1,35 @@
+require File.expand_path('../test_helper', __FILE__)
+
+class AllOfRefSchemaTest < Minitest::Test
+  def schema
+    schema_fixture_path('all_of_ref_schema.json')
+  end
+
+  def data
+    data_fixture_path('all_of_ref_data.json')
+  end
+
+  def test_all_of_ref_schema_fails
+    refute_valid schema, data
+  end
+
+  def test_all_of_ref_schema_succeeds
+    assert_valid schema, %({"name": 42})
+  end
+
+  def test_all_of_ref_subschema_errors
+    errors = JSON::Validator.fully_validate(schema, data, :errors_as_objects => true)
+    nested_errors = errors[0][:errors]
+    assert_equal([:allof_0], nested_errors.keys, 'should have nested errors for each allOf subschema')
+    assert_match(/the property '#\/name' of type String did not match the following type: integer/i, nested_errors[:allof_0][0][:message])
+  end
+
+  def test_all_of_ref_message
+    errors = JSON::Validator.fully_validate(schema, data)
+    expected_message = """The property '#/' of type Hash did not match all of the required schemas. The schema specific errors were:
+
+- allOf #0:
+    - The property '#/name' of type String did not match the following type: integer"""
+    assert_equal(expected_message, errors[0])
+  end
+end
diff --git a/test/test_any_of_ref_schema.rb b/test/test_any_of_ref_schema.rb
new file mode 100644
index 0000000..475222d
--- /dev/null
+++ b/test/test_any_of_ref_schema.rb
@@ -0,0 +1,35 @@
+require File.expand_path('../test_helper', __FILE__)
+
+class AnyOfRefSchemaTest < Minitest::Test
+  def schema
+    schema_fixture_path('any_of_ref_schema.json')
+  end
+
+  def test_any_of_ref_schema
+    assert_valid schema, data_fixture_path('any_of_ref_data.json')
+  end
+
+  def test_any_of_ref_subschema_errors
+    data = %({"names": ["jack"]})
+    errors = JSON::Validator.fully_validate(schema, data, :errors_as_objects => true)
+    nested_errors = errors[0][:errors]
+    assert_equal([:anyof_0, :anyof_1, :anyof_2], nested_errors.keys, 'should have nested errors for each anyOf subschema')
+    assert_match(/the property '#\/names\/0' value "jack" did not match the regex 'john'/i, nested_errors[:anyof_0][0][:message])
+    assert_match(/the property '#\/names\/0' value "jack" did not match the regex 'jane'/i, nested_errors[:anyof_1][0][:message])
+    assert_match(/the property '#\/names\/0' value "jack" did not match the regex 'jimmy'/i, nested_errors[:anyof_2][0][:message])
+  end
+
+  def test_any_of_ref_message
+    data = %({"names": ["jack"]})
+    errors = JSON::Validator.fully_validate(schema, data)
+    expected_message = """The property '#/names/0' of type String did not match one or more of the required schemas. The schema specific errors were:
+
+- anyOf #0:
+    - The property '#/names/0' value \"jack\" did not match the regex 'john'
+- anyOf #1:
+    - The property '#/names/0' value \"jack\" did not match the regex 'jane'
+- anyOf #2:
+    - The property '#/names/0' value \"jack\" did not match the regex 'jimmy'"""
+    assert_equal(expected_message, errors[0])
+  end
+end
diff --git a/test/test_bad_schema_ref.rb b/test/test_bad_schema_ref.rb
new file mode 100644
index 0000000..ef4d976
--- /dev/null
+++ b/test/test_bad_schema_ref.rb
@@ -0,0 +1,39 @@
+require File.expand_path('../test_helper', __FILE__)
+require 'socket'
+
+
+class BadSchemaRefTest < Minitest::Test
+  def setup
+    WebMock.allow_net_connect!
+  end
+
+  def teardown
+    WebMock.disable_net_connect!
+  end
+
+  def test_bad_uri_ref
+    schema = {
+      "$schema" => "http://json-schema.org/draft-04/schema#",
+      "type" => "array",
+      "items" => { "$ref" => "../google.json"}
+    }
+
+    data = [1,2,3]
+    assert_raises(Errno::ENOENT) do
+      JSON::Validator.validate(schema,data)
+    end
+  end
+
+  def test_bad_host_ref
+    schema = {
+      "$schema" => "http://json-schema.org/draft-04/schema#",
+      "type" => "array",
+      "items" => { "$ref" => "http://ppcheesecheseunicornnuuuurrrrr.example.invalid/json.schema"}
+    }
+
+    data = [1,2,3]
+    assert_raises(SocketError, OpenURI::HTTPError) do
+      JSON::Validator.validate(schema,data)
+    end
+  end
+end
diff --git a/test/test_common_test_suite.rb b/test/test_common_test_suite.rb
new file mode 100644
index 0000000..3c9d3af
--- /dev/null
+++ b/test/test_common_test_suite.rb
@@ -0,0 +1,66 @@
+require File.expand_path('../test_helper', __FILE__)
+require 'json'
+
+class CommonTestSuiteTest < Minitest::Test
+  TEST_DIR = File.expand_path('../test-suite/tests', __FILE__)
+
+  # These are test files which we know fail spectacularly, either because we
+  # don't support that functionality or because they require external
+  # dependencies.  To allow finer-grained control over which tests to run,
+  # you can replace `:all` with an array containing the names of individual
+  # tests to skip.
+  IGNORED_TESTS = Hash.new { |h,k| h[k] = [] }.merge({
+    "draft3/optional/jsregex.json" => :all,
+    "draft3/optional/format.json" => [
+      "validation of regular expressions",
+      "validation of e-mail addresses",
+      "validation of URIs",
+      "validation of host names",
+      "validation of CSS colors"
+    ],
+    "draft4/optional/format.json" => [
+      "validation of URIs",
+      "validation of e-mail addresses",
+      "validation of host names"
+    ]
+  })
+
+  def setup
+    Dir["#{TEST_DIR}/../remotes/**/*.json"].each do |path|
+      schema = path.sub(%r{^.*/remotes/}, '')
+      stub_request(:get, "http://localhost:1234/#{schema}").
+        to_return(:body => File.read(path), :status => 200)
+    end
+  end
+
+  Dir["#{TEST_DIR}/*"].each do |suite|
+    version = File.basename(suite).to_sym
+    Dir["#{suite}/**/*.json"].each do |tfile|
+      test_list = JSON.parse(File.read(tfile))
+      rel_file = tfile[TEST_DIR.length+1..-1]
+
+      test_list.each do |test|
+        schema = test["schema"]
+        base_description = test["description"]
+
+        test["tests"].each do |t|
+          next if IGNORED_TESTS[rel_file] == :all
+          next if IGNORED_TESTS[rel_file].any? { |ignored|
+            base_description == ignored || "#{base_description}/#{t['description']}" == ignored
+          }
+
+          err_id = "#{rel_file}: #{base_description}/#{t['description']}"
+          define_method("test_#{err_id}") do
+            errors = JSON::Validator.fully_validate(schema,
+              t["data"],
+              :parse_data => false,
+              :validate_schema => true,
+              :version => version
+            )
+            assert_equal t["valid"], errors.empty?, "Common test suite case failed: #{err_id}"
+          end
+        end
+      end
+    end
+  end
+end
diff --git a/test/test_custom_format.rb b/test/test_custom_format.rb
new file mode 100644
index 0000000..794383e
--- /dev/null
+++ b/test/test_custom_format.rb
@@ -0,0 +1,119 @@
+# encoding: utf-8
+require File.expand_path('../test_helper', __FILE__)
+
+class JSONSchemaCustomFormatTest < Minitest::Test
+  def setup
+    @all_versions = ['draft1', 'draft2', 'draft3', 'draft4', nil]
+    @format_proc = lambda { |value| raise JSON::Schema::CustomFormatError.new("must be 42") unless value == "42" }
+    @schema_4 = {
+      "$schema" => "http://json-schema.org/draft-04/schema#",
+      "properties" => {
+        "a" => {
+          "type" => "string",
+          "format" => "custom",
+        },
+      }
+    }
+    @schema_3 = @schema_4.clone
+    @schema_3["$schema"] = "http://json-schema.org/draft-03/schema#"
+    @schema_2 = @schema_4.clone
+    @schema_2["$schema"] = "http://json-schema.org/draft-02/schema#"
+    @schema_1 = @schema_4.clone
+    @schema_1["$schema"] = "http://json-schema.org/draft-01/schema#"
+    @default = @schema_4.clone
+    @default.delete("$schema")
+    @schemas = {
+      "draft1" => @schema_1,
+      "draft2" => @schema_2,
+      "draft3" => @schema_3,
+      "draft4" => @schema_4,
+      nil => @default,
+    }
+    JSON::Validator.restore_default_formats
+  end
+
+  def test_single_registration
+    @all_versions.each do |version|
+      assert(JSON::Validator.validator_for_name(version).formats['custom'].nil?, "Format 'custom' for #{version || 'default'} should be nil")
+      JSON::Validator.register_format_validator("custom", @format_proc, [version])
+      assert(JSON::Validator.validator_for_name(version).formats['custom'].is_a?(JSON::Schema::CustomFormat), "Format 'custom' should be registered for #{version || 'default'}")
+      (@all_versions - [version]).each do |other_version|
+        assert(JSON::Validator.validator_for_name(other_version).formats['custom'].nil?, "Format 'custom' should still be nil for #{other_version || 'default'}")
+      end
+      JSON::Validator.deregister_format_validator("custom", [version])
+      assert(JSON::Validator.validator_for_name(version).formats['custom'].nil?, "Format 'custom' should be deregistered for #{version || 'default'}")
+    end
+  end
+
+  def test_register_for_all_by_default
+    JSON::Validator.register_format_validator("custom", @format_proc)
+    @all_versions.each do |version|
+      assert(JSON::Validator.validator_for_name(version).formats['custom'].is_a?(JSON::Schema::CustomFormat), "Format 'custom' should be registered for #{version || 'default'}")
+    end
+    JSON::Validator.restore_default_formats
+    @all_versions.each do |version|
+      assert(JSON::Validator.validator_for_name(version).formats['custom'].nil?, "Format 'custom' should still be nil for #{version || 'default'}")
+    end
+  end
+
+  def test_multi_registration
+    unregistered_version = @all_versions.delete("draft1")
+    JSON::Validator.register_format_validator("custom", @format_proc, @all_versions)
+    @all_versions.each do |version|
+      assert(JSON::Validator.validator_for_name(version).formats['custom'].is_a?(JSON::Schema::CustomFormat), "Format 'custom' should be registered for #{version || 'default'}")
+    end
+    assert(JSON::Validator.validator_for_name(unregistered_version).formats['custom'].nil?, "Format 'custom' should still be nil for #{unregistered_version}")
+  end
+
+  def test_format_validation
+    @all_versions.each do |version|
+      data = {
+        "a" => "23"
+      }
+      schema = @schemas[version]
+      prefix = "Validation for '#{version || 'default'}'"
+
+      assert(JSON::Validator.validate(schema, data), "#{prefix} succeeds with no 'custom' format validator registered")
+
+      JSON::Validator.register_format_validator("custom", @format_proc, [version])
+      data["a"] = "42"
+      assert(JSON::Validator.validate(schema, data), "#{prefix} succeeds with 'custom' format validator and correct data")
+
+      data["a"] = "23"
+      assert(!JSON::Validator.validate(schema, data), "#{prefix} fails with 'custom' format validator and wrong data")
+
+      errors = JSON::Validator.fully_validate(schema, data)
+      assert(errors.count == 1 && errors.first.match(/The property '#\/a' must be 42 in schema/), "#{prefix} records fromat error")
+
+      data["a"] = 23
+      errors = JSON::Validator.fully_validate(schema, data)
+      assert(errors.count == 1 && errors.first.match(/The property '#\/a' of type (?:integer|Fixnum) did not match the following type: string/), "#{prefix} records no fromat error on type mismatch")
+    end
+  end
+
+  def test_override_default_format
+    @all_versions.each do |version|
+      data = {
+        "a" => "2001:db8:85a3:0:0:8a2e:370:7334"
+      }
+      schema = @schemas[version]
+      schema["properties"]["a"]["format"] = "ipv6"
+      prefix = "Validation for '#{version || 'default'}'"
+
+      assert(JSON::Validator.validate(schema, data), "#{prefix} succeeds for default format with correct data")
+
+      data["a"] = "no_ip6_address"
+      assert(!JSON::Validator.validate(schema, data), "#{prefix} fails for default format and wrong data")
+
+      data["a"] = "42"
+      JSON::Validator.register_format_validator("ipv6", @format_proc, [version])
+      assert(JSON::Validator.validate(schema, data), "#{prefix} succeeds with overriden default format and correct data")
+
+      JSON::Validator.deregister_format_validator("ipv6", [version])
+      data["a"] = "2001:db8:85a3:0:0:8a2e:370:7334"
+      assert(JSON::Validator.validate(schema, data), "#{prefix} restores the default format on deregistration")
+    end
+  end
+end
+
+
diff --git a/test/test_definition.rb b/test/test_definition.rb
new file mode 100644
index 0000000..4254120
--- /dev/null
+++ b/test/test_definition.rb
@@ -0,0 +1,15 @@
+require File.expand_path('../test_helper', __FILE__)
+
+class RelativeDefinitionTest < Minitest::Test
+
+  def test_definition_schema
+    assert_valid schema_fixture_path('definition_schema.json'), {"a" => 5}
+  end
+
+  def test_relative_definition
+    schema = schema_fixture_path('relative_definition_schema.json')
+    assert_valid schema, {"a" => 5}
+    refute_valid schema, {"a" => "foo"}
+  end
+
+end
diff --git a/test/test_extended_schema.rb b/test/test_extended_schema.rb
new file mode 100644
index 0000000..b702386
--- /dev/null
+++ b/test/test_extended_schema.rb
@@ -0,0 +1,62 @@
+require File.expand_path('../test_helper', __FILE__)
+
+class BitwiseAndAttribute < JSON::Schema::Attribute
+  def self.validate(current_schema, data, fragments, processor, validator, options = {})
+    return unless data.is_a?(Integer)
+
+    if data & current_schema.schema['bitwise-and'].to_i == 0
+      message = "The property '#{build_fragment(fragments)}' did not evaluate to true when bitwise-AND'd with #{current_schema.schema['bitwise-and']}"
+      validation_error(processor, message, fragments, current_schema, self, options[:record_errors])
+    end
+  end
+end
+
+class ExtendedSchema < JSON::Schema::Validator
+  def initialize
+    super
+    extend_schema_definition("http://json-schema.org/draft-03/schema#")
+    @attributes["bitwise-and"] = BitwiseAndAttribute
+    @uri = Addressable::URI.parse("http://test.com/test.json")
+  end
+
+  JSON::Validator.register_validator(self.new)
+end
+
+class TestExtendedSchema < Minitest::Test
+  def test_extended_schema_validation
+    schema = {
+      "$schema" => "http://test.com/test.json",
+      "properties" => {
+        "a" => {
+          "bitwise-and" => 1
+        },
+        "b" => {
+          "type" => "string"
+        }
+      }
+    }
+
+    assert_valid schema, {"a" => 1, "b" => "taco"}
+    refute_valid schema, {"a" => 0, "b" => "taco"}
+    refute_valid schema, {"a" => 1, "b" => 5}
+  end
+
+  def test_unextended_schema
+    # Verify that using the original schema disregards the `bitwise-and` property
+    schema = {
+      "$schema" => "http://json-schema.org/draft-03/schema#",
+      "properties" => {
+        "a" => {
+          "bitwise-and" => 1
+        },
+        "b" => {
+          "type" => "string"
+        }
+      }
+    }
+
+    assert_valid schema, {"a" => 0, "b" => "taco"}
+    assert_valid schema, {"a" => 1, "b" => "taco"}
+    refute_valid schema, {"a" => 1, "b" => 5}
+  end
+end
diff --git a/test/test_extends_and_additionalProperties.rb b/test/test_extends_and_additionalProperties.rb
new file mode 100644
index 0000000..9f6b40d
--- /dev/null
+++ b/test/test_extends_and_additionalProperties.rb
@@ -0,0 +1,52 @@
+require File.expand_path('../test_helper', __FILE__)
+
+class ExtendsNestedTest < Minitest::Test
+
+  def assert_validity(valid, schema_name, data, msg)
+    msg = "Schema should be #{valid ? :valid : :invalid}.\n(#{schema_name}) #{msg}"
+    schema = schema_fixture_path("#{schema_name}.schema.json")
+    errors = JSON::Validator.fully_validate(schema, data)
+
+    if valid
+      assert_equal([], errors, msg)
+    else
+      refute_equal([], errors, msg)
+    end
+  end
+
+  %w[
+    extends_and_additionalProperties-1-filename
+    extends_and_additionalProperties-1-ref
+    extends_and_additionalProperties-2-filename
+    extends_and_additionalProperties-2-ref
+  ].each do |schema_name|
+    test_prefix = 'test_' + schema_name.gsub('-','_')
+
+    class_eval <<-EOB
+      def #{test_prefix}_valid_outer
+        assert_validity true, '#{schema_name}', {"outerC"=>true}, "Outer defn is broken, maybe the outer extends overrode it"
+      end
+
+      def #{test_prefix}_valid_outer_extended
+        assert_validity true, '#{schema_name}', {"innerA"=>true}, "Extends at the root level isn't working"
+      end
+
+      def #{test_prefix}_valid_inner
+        assert_validity true, '#{schema_name}', {"outerB"=>[{"innerA"=>true}]}, "Extends isn't working in the array element defn"
+      end
+
+      def #{test_prefix}_invalid_inner
+        assert_validity false, '#{schema_name}', {"outerB"=>[{"whaaaaat"=>true}]}, "Array element defn allowing anything when it should only allow what's in inner.schema"
+      end
+    EOB
+
+    if schema_name['extends_and_additionalProperties-1']
+      class_eval <<-EOB
+        def #{test_prefix}_invalid_outer
+          assert_validity false, '#{schema_name}', {"whaaaaat"=>true}, "Outer defn allowing anything when it shouldn't"
+        end
+      EOB
+    end
+
+  end
+end
diff --git a/test/test_files_v3.rb b/test/test_files_v3.rb
new file mode 100644
index 0000000..d85d970
--- /dev/null
+++ b/test/test_files_v3.rb
@@ -0,0 +1,43 @@
+require File.expand_path('../test_helper', __FILE__)
+
+class JSONSchemaTest < Minitest::Test
+
+  #
+  # These tests are ONLY run if there is an appropriate JSON backend parser available
+  #
+
+  def test_schema_from_file
+    assert_valid schema_fixture_path('good_schema_1.json'), { "a" => 5 }
+    refute_valid schema_fixture_path('good_schema_1.json'), { "a" => "bad" }
+  end
+
+  def test_data_from_file
+    schema = {"$schema" => "http://json-schema.org/draft-03/schema#","type" => "object", "properties" => {"a" => {"type" => "integer"}}}
+    assert_valid schema, data_fixture_path('good_data_1.json'), :uri => true
+    refute_valid schema, data_fixture_path('bad_data_1.json'), :uri => true
+  end
+
+  def test_data_from_json
+    if JSON::Validator.json_backend != nil
+      schema = {"$schema" => "http://json-schema.org/draft-03/schema#","type" => "object", "properties" => {"a" => {"type" => "integer"}}}
+      assert_valid schema, %Q({"a": 5}), :json => true
+      refute_valid schema, %Q({"a": "poop"}), :json => true
+    end
+  end
+
+  def test_both_from_file
+    assert_valid schema_fixture_path('good_schema_1.json'), data_fixture_path('good_data_1.json'), :uri => true
+    refute_valid schema_fixture_path('good_schema_1.json'), data_fixture_path('bad_data_1.json'), :uri => true
+  end
+
+  def test_file_ref
+    assert_valid schema_fixture_path('good_schema_2.json'), { "b" => { "a" => 5 } }
+    refute_valid schema_fixture_path('good_schema_1.json'), { "b" => { "a" => "boo" } }
+  end
+
+  def test_file_extends
+    assert_valid schema_fixture_path('good_schema_extends1.json'), { "a" => 5 }
+    assert_valid schema_fixture_path('good_schema_extends2.json'), { "a" => 5, "b" => { "a" => 5 } }
+  end
+
+end
diff --git a/test/test_fragment_resolution.rb b/test/test_fragment_resolution.rb
new file mode 100644
index 0000000..95985c4
--- /dev/null
+++ b/test/test_fragment_resolution.rb
@@ -0,0 +1,30 @@
+require File.expand_path('../test_helper', __FILE__)
+
+class FragmentResolution < Minitest::Test
+  def test_fragment_resolution
+    schema = {
+      "$schema" => "http://json-schema.org/draft-04/schema#",
+      "required" => ["a"],
+      "properties" => {
+        "a" => {
+          "type" => "object",
+          "properties" => {
+            "b" => {"type" => "integer" }
+          }
+        }
+      }
+    }
+
+    data = {"b" => 5}
+    refute_valid schema, data
+    assert_valid schema, data, :fragment => "#/properties/a"
+
+    assert_raises JSON::Schema::SchemaError do
+      JSON::Validator.validate!(schema,data,:fragment => "/properties/a")
+    end
+
+    assert_raises JSON::Schema::SchemaError do
+      JSON::Validator.validate!(schema,data,:fragment => "#/properties/b")
+    end
+  end
+end
diff --git a/test/test_fragment_validation_with_ref.rb b/test/test_fragment_validation_with_ref.rb
new file mode 100644
index 0000000..459c541
--- /dev/null
+++ b/test/test_fragment_validation_with_ref.rb
@@ -0,0 +1,34 @@
+require File.expand_path('../test_helper', __FILE__)
+
+class FragmentValidationWithRef < Minitest::Test
+  def whole_schema
+    {
+      "$schema" => "http://json-schema.org/draft-04/schema#",
+      "type" => "object",
+      "definitions" => {
+        "post" => {
+          "type" => "object",
+          "properties" => {
+            "content" => {
+              "type" => "string"
+            },
+            "author" => {
+              "type" => "string"
+            }
+          }
+        },
+        "posts" => {
+          "type" => "array",
+          "items" => {
+            "$ref" => "#/definitions/post"
+          }
+        }
+      }
+    }
+  end
+
+  def test_validation_of_fragment
+    data = [{"content" => "ohai", "author" => "Bob"}]
+    assert_valid whole_schema, data, :fragment => "#/definitions/posts"
+  end
+end
diff --git a/test/test_full_validation.rb b/test/test_full_validation.rb
new file mode 100644
index 0000000..4fe470a
--- /dev/null
+++ b/test/test_full_validation.rb
@@ -0,0 +1,208 @@
+require File.expand_path('../test_helper', __FILE__)
+
+class JSONFullValidation < Minitest::Test
+    
+  def test_full_validation
+    data = {"b" => {"a" => 5}}
+    schema = {
+      "$schema" => "http://json-schema.org/draft-03/schema#",
+      "type" => "object",
+      "properties" => {
+        "b" => {
+          "required" => true
+        }
+      }
+    }
+    
+    errors = JSON::Validator.fully_validate(schema,data)
+    assert(errors.empty?)
+
+    data = {"c" => 5}
+    schema = {
+      "$schema" => "http://json-schema.org/draft-03/schema#",
+      "type" => "object",
+      "properties" => {
+        "b" => {
+          "required" => true
+        },
+        "c" => {
+          "type" => "string"
+        }
+      }
+    }
+
+    errors = JSON::Validator.fully_validate(schema,data)
+    assert(errors.length == 2)
+  end
+  
+  def test_full_validation_with_union_types
+    data = {"b" => 5}
+    schema = {
+      "$schema" => "http://json-schema.org/draft-03/schema#",
+      "type" => "object",
+      "properties" => {
+        "b" => {
+          "type" => ["null","integer"]
+        }
+      }
+    }
+    
+    errors = JSON::Validator.fully_validate(schema,data)
+    assert(errors.empty?)
+    
+    schema = {
+      "$schema" => "http://json-schema.org/draft-03/schema#",
+      "type" => "object",
+      "properties" => {
+        "b" => {
+          "type" => ["integer","null"]
+        }
+      }
+    }
+    
+    errors = JSON::Validator.fully_validate(schema,data)
+    assert(errors.empty?)
+    
+    data = {"b" => "a string"}
+    
+    errors = JSON::Validator.fully_validate(schema,data)
+    assert(errors.length == 1)
+   
+    schema = {
+      "$schema" => "http://json-schema.org/draft-03/schema#",
+      "type" => "object",
+      "properties" => {
+        "b" => {
+          "type" => [
+            {
+              "type" => "object",
+              "properties" => {
+                "c" => {"type" => "string"}
+              }
+            },
+            {
+              "type" => "object",
+              "properties" => {
+                "d" => {"type" => "integer"}
+              }
+            }
+          ]
+        }
+      }
+    }
+    
+    data = {"b" => {"c" => "taco"}}
+    
+    errors = JSON::Validator.fully_validate(schema,data)
+    assert(errors.empty?)
+    
+    data = {"b" => {"d" => 6}}
+    
+    errors = JSON::Validator.fully_validate(schema,data)
+    assert(errors.empty?)
+    
+    data = {"b" => {"c" => 6, "d" => "OH GOD"}}
+    
+    errors = JSON::Validator.fully_validate(schema,data)
+    assert(errors.length == 1)
+  end
+  
+  
+  def test_full_validation_with_object_errors
+    data = {"b" => {"a" => 5}}
+    schema = {
+      "$schema" => "http://json-schema.org/draft-03/schema#",
+      "type" => "object",
+      "properties" => {
+        "b" => {
+          "required" => true
+        }
+      }
+    }
+    
+    errors = JSON::Validator.fully_validate(schema,data,:errors_as_objects => true)
+    assert(errors.empty?)
+
+    data = {"c" => 5}
+    schema = {
+      "$schema" => "http://json-schema.org/draft-03/schema#",
+      "type" => "object",
+      "properties" => {
+        "b" => {
+          "required" => true
+        },
+        "c" => {
+          "type" => "string"
+        }
+      }
+    }
+
+    errors = JSON::Validator.fully_validate(schema,data,:errors_as_objects => true)
+    assert(errors.length == 2)
+    assert(errors[0][:failed_attribute] == "Properties")
+    assert(errors[0][:fragment] == "#/")
+    assert(errors[1][:failed_attribute] == "Type")
+    assert(errors[1][:fragment] == "#/c")
+  end
+  
+  def test_full_validation_with_nested_required_properties
+    schema = {
+      "$schema" => "http://json-schema.org/draft-03/schema#",
+      "type" => "object",
+      "properties" => {
+        "x" => {
+          "required" => true,
+          "type" => "object",
+          "properties" => {
+            "a" => {"type"=>"integer","required"=>true},
+            "b" => {"type"=>"integer","required"=>true},
+            "c" => {"type"=>"integer","required"=>false},
+            "d" => {"type"=>"integer","required"=>false},
+            "e" => {"type"=>"integer","required"=>false},
+          }
+        }
+      }
+    }
+    data = {"x" => {"a"=>5, "d"=>5, "e"=>"what?"}}
+    
+    errors = JSON::Validator.fully_validate(schema,data,:errors_as_objects => true)
+    assert_equal 2, errors.length
+    assert_equal '#/x', errors[0][:fragment]
+    assert_equal 'Properties', errors[0][:failed_attribute]
+    assert_equal '#/x/e', errors[1][:fragment]
+    assert_equal 'Type', errors[1][:failed_attribute]
+  end
+  
+  def test_full_validation_with_nested_required_propertiesin_array
+    schema = {
+      "$schema" => "http://json-schema.org/draft-03/schema#",
+      "type" => "object",
+      "properties" => {
+        "x" => {
+          "required" => true,
+          "type" => "array",
+          "items" => {
+            "type" => "object",
+            "properties" => {
+              "a" => {"type"=>"integer","required"=>true},
+              "b" => {"type"=>"integer","required"=>true},
+              "c" => {"type"=>"integer","required"=>false},
+              "d" => {"type"=>"integer","required"=>false},
+              "e" => {"type"=>"integer","required"=>false},
+            }
+          }
+        }
+      }
+    }
+    missing_b= {"a"=>5}
+    e_is_wrong_type= {"a"=>5,"b"=>5,"e"=>"what?"}
+    data = {"x" => [missing_b, e_is_wrong_type]}
+    
+    errors = JSON::Validator.fully_validate(schema,data,:errors_as_objects => true)
+    assert_equal 2, errors.length
+    assert_equal '#/x/0', errors[0][:fragment]
+    assert_equal 'Properties', errors[0][:failed_attribute]
+    assert_equal '#/x/1/e', errors[1][:fragment]
+    assert_equal 'Type', errors[1][:failed_attribute]
+  end
+end
diff --git a/test/test_helper.rb b/test/test_helper.rb
new file mode 100644
index 0000000..1451086
--- /dev/null
+++ b/test/test_helper.rb
@@ -0,0 +1,37 @@
+require 'minitest/autorun'
+require 'webmock/minitest'
+
+$:.unshift(File.expand_path('../../lib', __FILE__))
+require 'json-schema'
+
+Dir[File.join(File.expand_path('../support', __FILE__), '*.rb')].each do |support_file|
+  require support_file
+end
+
+class Minitest::Test
+  def schema_fixture_path(filename)
+    File.join(File.dirname(__FILE__), 'schemas', filename)
+  end
+
+  def data_fixture_path(filename)
+    File.join(File.dirname(__FILE__), 'data', filename)
+  end
+
+  def assert_valid(schema, data, options = {})
+    if !options.key?(:version) && respond_to?(:schema_version)
+      options = options.merge(:version => schema_version)
+    end
+
+    errors = JSON::Validator.fully_validate(schema, data, options)
+    assert_equal([], errors, "#{data.inspect} should be valid for schema:\n#{schema.inspect}")
+  end
+
+  def refute_valid(schema, data, options = {})
+    if !options.key?(:version) && respond_to?(:schema_version)
+      options = options.merge(:version => schema_version)
+    end
+
+    errors = JSON::Validator.fully_validate(schema, data, options)
+    refute_equal([], errors, "#{data.inspect} should be invalid for schema:\n#{schema.inspect}")
+  end
+end
diff --git a/test/test_initialize_data.rb b/test/test_initialize_data.rb
new file mode 100644
index 0000000..77d6c11
--- /dev/null
+++ b/test/test_initialize_data.rb
@@ -0,0 +1,124 @@
+require File.expand_path('../test_helper', __FILE__)
+
+class InitializeDataTest < Minitest::Test
+
+  def test_parse_character_string
+    schema = {'type' => 'string'}
+    data = 'hello world'
+
+    assert(JSON::Validator.validate(schema, data))
+
+    assert(JSON::Validator.validate(schema, data, :parse_data => false))
+
+    assert_raises(JSON::Schema::JsonParseError) do
+      JSON::Validator.validate(schema, data, :json => true)
+    end
+
+    assert_raises(JSON::Schema::JsonLoadError) { JSON::Validator.validate(schema, data, :uri => true) }
+  end
+
+  def test_parse_integer_string
+    schema = {'type' => 'integer'}
+    data = '42'
+
+    assert(JSON::Validator.validate(schema, data))
+
+    refute(JSON::Validator.validate(schema, data, :parse_data => false))
+
+    assert(JSON::Validator.validate(schema, data, :json => true))
+
+    assert_raises(JSON::Schema::JsonLoadError) { JSON::Validator.validate(schema, data, :uri => true) }
+  end
+
+  def test_parse_hash_string
+    schema = { 'type' => 'object', 'properties' => { 'a' => { 'type' => 'string' } } }
+    data = '{"a": "b"}'
+
+    assert(JSON::Validator.validate(schema, data))
+
+    refute(JSON::Validator.validate(schema, data, :parse_data => false))
+
+    assert(JSON::Validator.validate(schema, data, :json => true))
+
+    assert_raises(JSON::Schema::JsonLoadError) { JSON::Validator.validate(schema, data, :uri => true) }
+  end
+
+  def test_parse_json_string
+    schema = {'type' => 'string'}
+    data = '"hello world"'
+
+    assert(JSON::Validator.validate(schema, data))
+
+    assert(JSON::Validator.validate(schema, data, :parse_data => false))
+
+    assert(JSON::Validator.validate(schema, data, :json => true))
+
+    assert_raises(JSON::Schema::JsonLoadError) { JSON::Validator.validate(schema, data, :uri => true) }
+  end
+
+  def test_parse_valid_uri_string
+    schema = {'type' => 'string'}
+    data = 'http://foo.bar/'
+
+    stub_request(:get, "foo.bar").to_return(:body => '"hello world"', :status => 200)
+
+    assert(JSON::Validator.validate(schema, data))
+
+    assert(JSON::Validator.validate(schema, data, :parse_data => false))
+
+    assert_raises(JSON::Schema::JsonParseError) do
+      JSON::Validator.validate(schema, data, :json => true)
+    end
+
+    assert(JSON::Validator.validate(schema, data, :uri => true))
+  end
+
+  def test_parse_invalid_uri_string
+    schema = {'type' => 'string'}
+    data = 'http://foo.bar/'
+
+    stub_request(:get, "foo.bar").to_timeout
+
+    assert(JSON::Validator.validate(schema, data))
+
+    assert(JSON::Validator.validate(schema, data, :parse_data => false))
+
+    stub_request(:get, "foo.bar").to_return(:status => [500, "Internal Server Error"])
+
+    assert(JSON::Validator.validate(schema, data))
+
+    assert(JSON::Validator.validate(schema, data, :parse_data => false))
+
+    assert_raises(JSON::Schema::JsonParseError) do
+      JSON::Validator.validate(schema, data, :json => true)
+    end
+
+    assert_raises(JSON::Schema::JsonLoadError) { JSON::Validator.validate(schema, data, :uri => true) }
+  end
+
+  def test_parse_integer
+    schema = {'type' => 'integer'}
+    data = 42
+
+    assert(JSON::Validator.validate(schema, data))
+
+    assert(JSON::Validator.validate(schema, data, :parse_data => false))
+
+    assert_raises(TypeError) { JSON::Validator.validate(schema, data, :json => true) }
+
+    assert_raises(TypeError) { JSON::Validator.validate(schema, data, :uri => true) }
+  end
+
+  def test_parse_hash
+    schema = { 'type' => 'object', 'properties' => { 'a' => { 'type' => 'string' } } }
+    data = { 'a' => 'b' }
+
+    assert(JSON::Validator.validate(schema, data))
+
+    assert(JSON::Validator.validate(schema, data, :parse_data => false))
+
+    assert_raises(TypeError) { JSON::Validator.validate(schema, data, :json => true) }
+
+    assert_raises(TypeError) { JSON::Validator.validate(schema, data, :uri => true) }
+  end
+end
diff --git a/test/test_jsonschema_draft1.rb b/test/test_jsonschema_draft1.rb
new file mode 100644
index 0000000..06c8298
--- /dev/null
+++ b/test/test_jsonschema_draft1.rb
@@ -0,0 +1,141 @@
+require File.expand_path('../test_helper', __FILE__)
+
+class JSONSchemaDraft1Test < Minitest::Test
+  def schema_version
+    :draft1
+  end
+
+  def exclusive_minimum
+    { 'minimumCanEqual' => false }
+  end
+
+  def exclusive_maximum
+    { 'maximumCanEqual' => false }
+  end
+
+  include ArrayValidation::ItemsTests
+
+  include EnumValidation::General
+  include EnumValidation::V1_V2
+
+  include NumberValidation::MinMaxTests
+
+  include ObjectValidation::AdditionalPropertiesTests
+
+  include StrictValidation
+
+  include StringValidation::ValueTests
+  include StringValidation::FormatTests
+  include StringValidation::DateAndTimeFormatTests
+
+  include TypeValidation::SimpleTypeTests
+  include TypeValidation::AnyTypeTests
+  include TypeValidation::SchemaUnionTypeTests
+
+  def test_optional
+    # Set up the default datatype
+    schema = {
+      "properties" => {
+        "a" => {"type" => "string"}
+      }
+    }
+    data = {}
+
+    refute_valid schema, data
+    data['a'] = "Hello"
+    assert_valid schema, data
+
+    schema = {
+      "properties" => {
+        "a" => {"type" => "integer", "optional" => "true"}
+      }
+    }
+
+    data = {}
+    assert_valid schema, data
+  end
+
+  def test_max_decimal
+    # Set up the default datatype
+    schema = {
+      "properties" => {
+        "a" => {"maxDecimal" => 2}
+      }
+    }
+
+    data = {
+      "a" => nil
+    }
+
+    data["a"] = 3.35
+    assert_valid schema, data
+
+    data["a"] = 3.455
+    refute_valid schema, data
+
+
+    schema["properties"]["a"]["maxDecimal"] = 0
+
+    data["a"] = 4.0
+    refute_valid schema, data
+
+    data["a"] = 'boo'
+    assert_valid schema, data
+
+    data["a"] = 5
+    assert_valid schema, data
+  end
+
+
+
+  def test_disallow
+    # Set up the default datatype
+    schema = {
+      "properties" => {
+        "a" => {"disallow" => "integer"}
+      }
+    }
+
+    data = {
+      "a" => nil
+    }
+
+
+    data["a"] = 'string'
+    assert_valid schema, data
+
+    data["a"] = 5
+    refute_valid schema, data
+
+
+    schema["properties"]["a"]["disallow"] = ["integer","string"]
+    data["a"] = 'string'
+    refute_valid schema, data
+
+    data["a"] = 5
+    refute_valid schema, data
+
+    data["a"] = false
+    assert_valid schema, data
+
+  end
+
+  def test_format_datetime
+    schema = {
+      "type" => "object",
+      "properties" => { "a" => {"type" => "string", "format" => "date-time"}}
+    }
+
+    assert_valid schema, {"a" => "2010-01-01T12:00:00Z"}
+    refute_valid schema, {"a" => "2010-01-32T12:00:00Z"}
+    refute_valid schema, {"a" => "2010-13-01T12:00:00Z"}
+    refute_valid schema, {"a" => "2010-01-01T24:00:00Z"}
+    refute_valid schema, {"a" => "2010-01-01T12:60:00Z"}
+    refute_valid schema, {"a" => "2010-01-01T12:00:60Z"}
+    refute_valid schema, {"a" => "2010-01-01T12:00:00z"}
+    refute_valid schema, {"a" => "2010-01-0112:00:00Z"}
+    refute_valid schema, {"a" => "2010-01-01T12:00:00Z\nabc"}
+  end
+
+end
+
diff --git a/test/test_jsonschema_draft2.rb b/test/test_jsonschema_draft2.rb
new file mode 100644
index 0000000..6b4c25c
--- /dev/null
+++ b/test/test_jsonschema_draft2.rb
@@ -0,0 +1,113 @@
+require File.expand_path('../test_helper', __FILE__)
+
+class JSONSchemaDraft2Test < Minitest::Test
+  def schema_version
+    :draft2
+  end
+
+  def exclusive_minimum
+    { 'minimumCanEqual' => false }
+  end
+
+  def exclusive_maximum
+    { 'maximumCanEqual' => false }
+  end
+
+  def multiple_of
+    'divisibleBy'
+  end
+
+  include ArrayValidation::ItemsTests
+  include ArrayValidation::UniqueItemsTests
+
+  include EnumValidation::General
+  include EnumValidation::V1_V2
+
+  include NumberValidation::MinMaxTests
+  include NumberValidation::MultipleOfTests
+
+  include ObjectValidation::AdditionalPropertiesTests
+
+  include StrictValidation
+
+  include StringValidation::ValueTests
+  include StringValidation::FormatTests
+  include StringValidation::DateAndTimeFormatTests
+
+  include TypeValidation::SimpleTypeTests
+  include TypeValidation::AnyTypeTests
+  include TypeValidation::SchemaUnionTypeTests
+
+  def test_optional
+    # Set up the default datatype
+    schema = {
+      "properties" => {
+        "a" => {"type" => "string"}
+      }
+    }
+    data = {}
+
+    refute_valid schema, data
+    data['a'] = "Hello"
+    assert_valid schema, data
+
+    schema = {
+      "properties" => {
+        "a" => {"type" => "integer", "optional" => "true"}
+      }
+    }
+
+    data = {}
+    assert_valid schema, data
+  end
+
+  def test_disallow
+    # Set up the default datatype
+    schema = {
+      "properties" => {
+        "a" => {"disallow" => "integer"}
+      }
+    }
+
+    data = {
+      "a" => nil
+    }
+
+
+    data["a"] = 'string'
+    assert_valid schema, data
+
+    data["a"] = 5
+    refute_valid schema, data
+
+
+    schema["properties"]["a"]["disallow"] = ["integer","string"]
+    data["a"] = 'string'
+    refute_valid schema, data
+
+    data["a"] = 5
+    refute_valid schema, data
+
+    data["a"] = false
+    assert_valid schema, data
+  end
+
+  def test_format_datetime
+    schema = {
+      "type" => "object",
+      "properties" => { "a" => {"type" => "string", "format" => "date-time"}}
+    }
+
+    assert_valid schema, {"a" => "2010-01-01T12:00:00Z"}
+    refute_valid schema, {"a" => "2010-01-32T12:00:00Z"}
+    refute_valid schema, {"a" => "2010-13-01T12:00:00Z"}
+    refute_valid schema, {"a" => "2010-01-01T24:00:00Z"}
+    refute_valid schema, {"a" => "2010-01-01T12:60:00Z"}
+    refute_valid schema, {"a" => "2010-01-01T12:00:60Z"}
+    refute_valid schema, {"a" => "2010-01-01T12:00:00z"}
+    refute_valid schema, {"a" => "2010-01-0112:00:00Z"}
+    refute_valid schema, {"a" => "2010-01-01T12:00:00Z\nabc"}
+  end
+
+end
+
diff --git a/test/test_jsonschema_draft3.rb b/test/test_jsonschema_draft3.rb
new file mode 100644
index 0000000..1c9cae7
--- /dev/null
+++ b/test/test_jsonschema_draft3.rb
@@ -0,0 +1,450 @@
+# encoding: utf-8
+require File.expand_path('../test_helper', __FILE__)
+
+class JSONSchemaDraft3Test < Minitest::Test
+  def schema_version
+    :draft3
+  end
+
+  def exclusive_minimum
+    { 'exclusiveMinimum' => true }
+  end
+
+  def exclusive_maximum
+    { 'exclusiveMaximum' => true }
+  end
+
+  def multiple_of
+    'divisibleBy'
+  end
+
+  include ArrayValidation::ItemsTests
+  include ArrayValidation::AdditionalItemsTests
+  include ArrayValidation::UniqueItemsTests
+
+  include EnumValidation::General
+  include EnumValidation::V3_V4
+
+  include NumberValidation::MinMaxTests
+  include NumberValidation::MultipleOfTests
+
+  include ObjectValidation::AdditionalPropertiesTests
+  include ObjectValidation::PatternPropertiesTests
+
+  include StrictValidation
+
+  include StringValidation::ValueTests
+  include StringValidation::FormatTests
+  include StringValidation::DateAndTimeFormatTests
+
+  include TypeValidation::SimpleTypeTests
+  include TypeValidation::AnyTypeTests
+  include TypeValidation::SchemaUnionTypeTests
+
+  def test_types
+    # Set up the default datatype
+    schema = {
+      "$schema" => "http://json-schema.org/draft-03/schema#",
+      "properties" => {
+        "a" => {}
+      }
+    }
+    data = {
+      "a" => nil
+    }
+
+    # Test an array of unioned-type objects that prevent additionalProperties
+    schema["properties"]["a"] = {
+      'type' => 'array',
+      'items' => {
+        'type' => [
+          { 'type' => 'object', 'properties' => { "b" => { "type" => "integer" } } },
+          { 'type' => 'object', 'properties' => { "c" => { "type" => "string" } } }
+        ],
+        'additionalProperties' => false
+      }
+    }
+
+    data["a"] = [{"b" => 5}, {"c" => "foo"}]
+    errors = JSON::Validator.fully_validate(schema, data)
+    assert(errors.empty?, errors.join("\n"))
+
+    # This should actually pass, because this matches the first schema in the union
+    data["a"] << {"c" => false}
+    assert_valid schema, data
+  end
+
+  def test_required
+    # Set up the default datatype
+    schema = {
+      "$schema" => "http://json-schema.org/draft-03/schema#",
+      "properties" => {
+        "a" => {"required" => true}
+      }
+    }
+    data = {}
+
+    refute_valid schema, data
+    data['a'] = "Hello"
+    assert_valid schema, data
+
+    schema = {
+      "$schema" => "http://json-schema.org/draft-03/schema#",
+      "properties" => {
+        "a" => {"type" => "integer"}
+      }
+    }
+
+    data = {}
+    assert_valid schema, data
+  end
+
+  def test_strict_properties_required_props
+    schema = {
+      "$schema" => "http://json-schema.org/draft-03/schema#",
+      "properties" => {
+        "a" => {"type" => "string", "required" => true},
+        "b" => {"type" => "string", "required" => false}
+      }
+    }
+
+    data = {"a" => "a"}
+    assert(JSON::Validator.validate(schema,data,:strict => true))
+
+    data = {"b" => "b"}
+    assert(!JSON::Validator.validate(schema,data,:strict => true))
+
+    data = {"a" => "a", "b" => "b"}
+    assert(JSON::Validator.validate(schema,data,:strict => true))
+  end
+
+  def test_strict_properties_additional_props
+    schema = {
+      "$schema" => "http://json-schema.org/draft-03/schema#",
+      "properties" => {
+        "a" => {"type" => "string"},
+        "b" => {"type" => "string"}
+      },
+      "additionalProperties" => {"type" => "integer"}
+    }
+
+    data = {"a" => "a"}
+    assert(!JSON::Validator.validate(schema,data,:strict => true))
+
+    data = {"b" => "b"}
+    assert(!JSON::Validator.validate(schema,data,:strict => true))
+
+    data = {"a" => "a", "b" => "b"}
+    assert(JSON::Validator.validate(schema,data,:strict => true))
+
+    data = {"a" => "a", "b" => "b", "c" => "c"}
+    assert(!JSON::Validator.validate(schema,data,:strict => true))
+
+    data = {"a" => "a", "b" => "b", "c" => 3}
+    assert(JSON::Validator.validate(schema,data,:strict => true))
+  end
+
+  def test_strict_properties_pattern_props
+    schema = {
+      "$schema" => "http://json-schema.org/draft-03/schema#",
+      "properties" => {
+        "a" => {"type" => "string"},
+        "b" => {"type" => "string"}
+      },
+      "patternProperties" => {"\\d+ taco" => {"type" => "integer"}}
+    }
+
+    data = {"a" => "a"}
+    assert(!JSON::Validator.validate(schema,data,:strict => true))
+
+    data = {"b" => "b"}
+    assert(!JSON::Validator.validate(schema,data,:strict => true))
+
+    data = {"a" => "a", "b" => "b"}
+    assert(JSON::Validator.validate(schema,data,:strict => true))
+
+    data = {"a" => "a", "b" => "b", "c" => "c"}
+    assert(!JSON::Validator.validate(schema,data,:strict => true))
+
+    data = {"a" => "a", "b" => "b", "c" => 3}
+    assert(!JSON::Validator.validate(schema,data,:strict => true))
+
+    data = {"a" => "a", "b" => "b", "23 taco" => 3}
+    assert(JSON::Validator.validate(schema,data,:strict => true))
+
+    data = {"a" => "a", "b" => "b", "23 taco" => "cheese"}
+    assert(!JSON::Validator.validate(schema,data,:strict => true))
+  end
+
+  def test_disallow
+    # Set up the default datatype
+    schema = {
+      "$schema" => "http://json-schema.org/draft-03/schema#",
+      "properties" => {
+        "a" => {"disallow" => "integer"}
+      }
+    }
+
+    data = {
+      "a" => nil
+    }
+
+
+    data["a"] = 'string'
+    assert_valid schema, data
+
+    data["a"] = 5
+    refute_valid schema, data
+
+
+    schema["properties"]["a"]["disallow"] = ["integer","string"]
+    data["a"] = 'string'
+    refute_valid schema, data
+
+    data["a"] = 5
+    refute_valid schema, data
+
+    data["a"] = false
+    assert_valid schema, data
+
+  end
+
+
+
+  def test_extends
+    schema = {
+      "$schema" => "http://json-schema.org/draft-03/schema#",
+      "properties" => {
+        "a" => { "type" => "integer"}
+      }
+    }
+
+    schema2 = {
+      "$schema" => "http://json-schema.org/draft-03/schema#",
+      "properties" => {
+        "a" => { "maximum" => 5 }
+      }
+    }
+
+    data = {
+      "a" => 10
+    }
+
+    assert_valid schema, data
+    assert(!JSON::Validator.validate(schema2,data))
+
+    schema["extends"] = schema2
+
+    refute_valid schema, data
+  end
+
+  def test_list_option
+    schema = {
+      "$schema" => "http://json-schema.org/draft-03/schema#",
+      "type" => "object",
+      "properties" => { "a" => {"type" => "integer", "required" => true} }
+    }
+
+    data = [{"a" => 1},{"a" => 2},{"a" => 3}]
+    assert(JSON::Validator.validate(schema,data,:list => true))
+    refute_valid schema, data
+
+    data = {"a" => 1}
+    assert(!JSON::Validator.validate(schema,data,:list => true))
+
+    data = [{"a" => 1},{"b" => 2},{"a" => 3}]
+    assert(!JSON::Validator.validate(schema,data,:list => true))
+  end
+
+
+  def test_self_reference
+    schema = {
+      "$schema" => "http://json-schema.org/draft-03/schema#",
+      "type" => "object",
+      "properties" => { "a" => {"type" => "integer"}, "b" => {"$ref" => "#"}}
+    }
+
+    assert_valid schema, {"a" => 5, "b" => {"b" => {"a" => 1}}}
+    refute_valid schema, {"a" => 5, "b" => {"b" => {"a" => 'taco'}}}
+  end
+
+  def test_format_datetime
+    schema = {
+      "$schema" => "http://json-schema.org/draft-03/schema#",
+      "type" => "object",
+      "properties" => { "a" => {"type" => "string", "format" => "date-time"}}
+    }
+
+    assert_valid schema, {"a" => "2010-01-01T12:00:00Z"}
+    assert_valid schema, {"a" => "2010-01-01T12:00:00.1Z"}
+    assert_valid schema, {"a" => "2010-01-01T12:00:00,1Z"}
+    refute_valid schema, {"a" => "2010-01-32T12:00:00Z"}
+    refute_valid schema, {"a" => "2010-13-01T12:00:00Z"}
+    refute_valid schema, {"a" => "2010-01-01T24:00:00Z"}
+    refute_valid schema, {"a" => "2010-01-01T12:60:00Z"}
+    refute_valid schema, {"a" => "2010-01-01T12:00:60Z"}
+    refute_valid schema, {"a" => "2010-01-01T12:00:00z"}
+    refute_valid schema, {"a" => "2010-01-0112:00:00Z"}
+    refute_valid schema, {"a" => "2010-01-01T12:00:00.1Z\nabc"}
+
+    # test with a specific timezone
+    assert_valid schema, {"a" => "2010-01-01T12:00:00+01"}
+    assert_valid schema, {"a" => "2010-01-01T12:00:00+01:00"}
+    assert_valid schema, {"a" => "2010-01-01T12:00:00+01:30"}
+    assert_valid schema, {"a" => "2010-01-01T12:00:00+0234"}
+    refute_valid schema, {"a" => "2010-01-01T12:00:00+01:"}
+    refute_valid schema, {"a" => "2010-01-01T12:00:00+0"}
+    # do not allow mixing Z and specific timezone
+    refute_valid schema, {"a" => "2010-01-01T12:00:00Z+01"}
+    refute_valid schema, {"a" => "2010-01-01T12:00:00+01Z"}
+    refute_valid schema, {"a" => "2010-01-01T12:00:00+01:30Z"}
+    refute_valid schema, {"a" => "2010-01-01T12:00:00+0Z"}
+
+    # test without any timezone
+    assert_valid schema, {"a" => "2010-01-01T12:00:00"}
+    assert_valid schema, {"a" => "2010-01-01T12:00:00.12345"}
+    assert_valid schema, {"a" => "2010-01-01T12:00:00,12345"}
+    assert_valid schema, {"a" => "2010-01-01T12:00:00.12345"}
+  end
+
+  def test_format_uri
+    data1 = {"a" => "http://gitbuh.com"}
+    data2 = {"a" => "::boo"}
+    data3 = {"a" => "http://ja.wikipedia.org/wiki/メインページ"}
+
+    schema = {
+        "$schema" => "http://json-schema.org/draft-03/schema#",
+        "type" => "object",
+        "properties" => { "a" => {"type" => "string", "format" => "uri"}}
+    }
+
+    assert(JSON::Validator.validate(schema,data1))
+    assert(!JSON::Validator.validate(schema,data2))
+    assert(JSON::Validator.validate(schema,data3))
+  end
+
+
+
+  def test_schema
+    schema = {
+      "$schema" => "http://json-schema.org/THIS-IS-NOT-A-SCHEMA",
+      "type" => "object"
+    }
+
+    data = {"a" => "taco"}
+    assert(!JSON::Validator.validate(schema, data))
+
+    schema = {
+      "$schema" => "http://json-schema.org/draft-03/schema#",
+      "type" => "object"
+    }
+    assert_valid schema, data
+  end
+
+  def test_dependency
+    schema = {
+      "$schema" => "http://json-schema.org/draft-03/schema#",
+      "type" => "object",
+      "properties" => {
+        "a" => {"type" => "integer"},
+        "b" => {"type" => "integer"}
+      },
+      "dependencies" => {
+        "a" => "b"
+      }
+    }
+
+    data = {"a" => 1, "b" => 2}
+    assert_valid schema, data
+    data = {"a" => 1}
+    refute_valid schema, data
+
+    schema = {
+      "$schema" => "http://json-schema.org/draft-03/schema#",
+      "type" => "object",
+      "properties" => {
+        "a" => {"type" => "integer"},
+        "b" => {"type" => "integer"},
+        "c" => {"type" => "integer"}
+      },
+      "dependencies" => {
+        "a" => ["b","c"]
+      }
+    }
+
+    data = {"a" => 1, "c" => 2}
+    refute_valid schema, data
+    data = {"a" => 1, "b" => 2, "c" => 3}
+    assert_valid schema, data
+  end
+
+  def test_default
+    schema = {
+      "$schema" => "http://json-schema.org/draft-03/schema#",
+      "type" => "object",
+      "properties" => {
+        "a" => {"type" => "integer", "default" => 42},
+        "b" => {"type" => "integer"}
+      }
+    }
+
+    data = {:b => 2}
+    assert_valid schema, data
+    assert_nil(data["a"])
+    assert(JSON::Validator.validate(schema,data, :insert_defaults => true))
+    assert_equal(42, data["a"])
+    assert_equal(2, data[:b])
+
+    schema = {
+      "$schema" => "http://json-schema.org/draft-03/schema#",
+      "type" => "object",
+      "properties" => {
+        "a" => {"type" => "integer", "default" => 42, "required" => true},
+        "b" => {"type" => "integer"}
+      }
+    }
+
+    data = {:b => 2}
+    refute_valid schema, data
+    assert_nil(data["a"])
+    assert(JSON::Validator.validate(schema,data, :insert_defaults => true))
+    assert_equal(42, data["a"])
+    assert_equal(2, data[:b])
+
+    schema = {
+      "$schema" => "http://json-schema.org/draft-03/schema#",
+      "type" => "object",
+      "properties" => {
+        "a" => {"type" => "integer", "default" => 42, "required" => true, "readonly" => true},
+        "b" => {"type" => "integer"}
+      }
+    }
+
+    data = {:b => 2}
+    refute_valid schema, data
+    assert_nil(data["a"])
+    assert(!JSON::Validator.validate(schema,data, :insert_defaults => true))
+    assert_nil(data["a"])
+    assert_equal(2, data[:b])
+
+    schema = {
+      "$schema" => "http://json-schema.org/draft-03/schema#",
+      "type" => "object",
+      "properties" => {
+        "a" => {"type" => "integer", "default" => "42"},
+        "b" => {"type" => "integer"}
+      }
+    }
+
+    data = {:b => 2}
+    assert_valid schema, data
+    assert_nil(data["a"])
+    assert(!JSON::Validator.validate(schema,data, :insert_defaults => true))
+    assert_equal("42",data["a"])
+    assert_equal(2, data[:b])
+
+  end
+
+
+end
+
diff --git a/test/test_jsonschema_draft4.rb b/test/test_jsonschema_draft4.rb
new file mode 100644
index 0000000..8ddb7e1
--- /dev/null
+++ b/test/test_jsonschema_draft4.rb
@@ -0,0 +1,675 @@
+# encoding: utf-8
+require File.expand_path('../test_helper', __FILE__)
+
+class JSONSchemaDraft4Test < Minitest::Test
+  def schema_version
+    :draft4
+  end
+
+  def exclusive_minimum
+    { 'exclusiveMinimum' => true }
+  end
+
+  def exclusive_maximum
+    { 'exclusiveMaximum' => true }
+  end
+
+  def ipv4_format
+    'ipv4'
+  end
+
+  include ArrayValidation::ItemsTests
+  include ArrayValidation::AdditionalItemsTests
+  include ArrayValidation::UniqueItemsTests
+
+  include EnumValidation::General
+  include EnumValidation::V3_V4
+
+  include NumberValidation::MinMaxTests
+  include NumberValidation::MultipleOfTests
+
+  include ObjectValidation::AdditionalPropertiesTests
+  include ObjectValidation::PatternPropertiesTests
+
+  include StrictValidation
+
+  include StringValidation::ValueTests
+  include StringValidation::FormatTests
+
+  include TypeValidation::SimpleTypeTests
+
+  def test_required
+    # Set up the default datatype
+    schema = {
+      "$schema" => "http://json-schema.org/draft-04/schema#",
+      "required" => ["a"],
+      "properties" => {
+        "a" => {}
+      }
+    }
+    data = {}
+
+    refute_valid schema, data
+    data['a'] = "Hello"
+    assert_valid schema, data
+
+    schema = {
+      "$schema" => "http://json-schema.org/draft-04/schema#",
+      "properties" => {
+        "a" => {"type" => "integer"}
+      }
+    }
+
+    data = {}
+    assert_valid schema, data
+  end
+
+  def test_min_properties
+    schema = { 'minProperties' => 2 }
+
+    assert_valid schema, {'a' => 1, 'b' => 2}
+    assert_valid schema, {'a' => 1, 'b' => 2, 'c' => 3}
+
+    refute_valid schema, {'a' => 1}
+    refute_valid schema, {}
+  end
+
+  def test_max_properties
+    schema = { 'maxProperties' => 2 }
+
+    assert_valid schema, {'a' => 1, 'b' => 2}
+    assert_valid schema, {'a' => 1}
+    assert_valid schema, {}
+
+    refute_valid schema, {'a' => 1, 'b' => 2, 'c' => 3}
+  end
+
+  def test_strict_properties
+    schema = {
+      "$schema" => "http://json-schema.org/draft-04/schema#",
+      "properties" => {
+        "a" => {"type" => "string"},
+        "b" => {"type" => "string"}
+      }
+    }
+
+    data = {"a" => "a"}
+    assert(!JSON::Validator.validate(schema,data,:strict => true))
+
+    data = {"b" => "b"}
+    assert(!JSON::Validator.validate(schema,data,:strict => true))
+
+    data = {"a" => "a", "b" => "b"}
+    assert(JSON::Validator.validate(schema,data,:strict => true))
+
+    data = {"a" => "a", "b" => "b", "c" => "c"}
+    assert(!JSON::Validator.validate(schema,data,:strict => true))
+  end
+
+  def test_strict_properties_additional_props
+    schema = {
+      "$schema" => "http://json-schema.org/draft-04/schema#",
+      "properties" => {
+        "a" => {"type" => "string"},
+        "b" => {"type" => "string"}
+      },
+      "additionalProperties" => {"type" => "integer"}
+    }
+
+    data = {"a" => "a"}
+    assert(!JSON::Validator.validate(schema,data,:strict => true))
+
+    data = {"b" => "b"}
+    assert(!JSON::Validator.validate(schema,data,:strict => true))
+
+    data = {"a" => "a", "b" => "b"}
+    assert(JSON::Validator.validate(schema,data,:strict => true))
+
+    data = {"a" => "a", "b" => "b", "c" => "c"}
+    assert(!JSON::Validator.validate(schema,data,:strict => true))
+
+    data = {"a" => "a", "b" => "b", "c" => 3}
+    assert(JSON::Validator.validate(schema,data,:strict => true))
+  end
+
+  def test_strict_properties_pattern_props
+    schema = {
+      "$schema" => "http://json-schema.org/draft-03/schema#",
+      "properties" => {
+        "a" => {"type" => "string"},
+        "b" => {"type" => "string"}
+      },
+      "patternProperties" => {"\\d+ taco" => {"type" => "integer"}}
+    }
+
+    data = {"a" => "a"}
+    assert(!JSON::Validator.validate(schema,data,:strict => true))
+
+    data = {"b" => "b"}
+    assert(!JSON::Validator.validate(schema,data,:strict => true))
+
+    data = {"a" => "a", "b" => "b"}
+    assert(JSON::Validator.validate(schema,data,:strict => true))
+
+    data = {"a" => "a", "b" => "b", "c" => "c"}
+    assert(!JSON::Validator.validate(schema,data,:strict => true))
+
+    data = {"a" => "a", "b" => "b", "c" => 3}
+    assert(!JSON::Validator.validate(schema,data,:strict => true))
+
+    data = {"a" => "a", "b" => "b", "23 taco" => 3}
+    assert(JSON::Validator.validate(schema,data,:strict => true))
+
+    data = {"a" => "a", "b" => "b", "23 taco" => "cheese"}
+    assert(!JSON::Validator.validate(schema,data,:strict => true))
+  end
+
+  def test_list_option
+    schema = {
+      "$schema" => "http://json-schema.org/draft-04/schema#",
+      "type" => "object",
+      "required" => ["a"],
+      "properties" => { "a" => {"type" => "integer"} }
+    }
+
+    data = [{"a" => 1},{"a" => 2},{"a" => 3}]
+    assert(JSON::Validator.validate(schema,data,:list => true))
+    refute_valid schema, data
+
+    data = {"a" => 1}
+    assert(!JSON::Validator.validate(schema,data,:list => true))
+
+    data = [{"a" => 1},{"b" => 2},{"a" => 3}]
+    assert(!JSON::Validator.validate(schema,data,:list => true))
+  end
+
+  def test_default_with_strict_and_anyof
+    schema = {
+      "anyOf" => [
+        {
+          "type" => "object",
+          "properties" => {
+            "foo" => {
+              "enum" => ["view", "search"],
+              "default" => "view"
+            }
+          }
+        },
+        {
+          "type" => "object",
+          "properties" => {
+            "bar" => {
+              "type" => "string"
+            }
+          }
+        }
+      ]
+    }
+
+    data = {
+      "bar" => "baz"
+    }
+
+    assert(JSON::Validator.validate(schema, data, :insert_defaults => true, :strict => true))
+  end
+
+  def test_default_with_anyof
+    schema = {
+      "anyOf" => [
+        {
+          "type" => "object",
+          "properties" => {
+            "foo" => {
+              "enum" => ["view", "search"],
+              "default" => "view"
+            }
+          }
+        },
+        {
+          "type" => "object",
+          "properties" => {
+            "bar" => {
+              "type" => "string"
+            }
+          }
+        }
+      ]
+    }
+
+    data = {}
+
+    assert(JSON::Validator.validate(schema, data, :insert_defaults => true, :strict => true))
+    assert(data['foo'] == 'view')
+  end
+
+  def test_default_with_strict_and_oneof
+    schema = {
+      "oneOf" => [
+        {
+          "type" => "object",
+          "properties" => {
+            "bar" => {
+              "type" => "string"
+            }
+          }
+        },
+        {
+          "type" => "object",
+          "properties" => {
+            "foo" => {
+              "enum" => ["view", "search"],
+              "default" => "view"
+            }
+          }
+        }
+      ]
+    }
+
+    data = {
+      "bar" => "baz"
+    }
+
+    assert(JSON::Validator.validate(schema, data, :insert_defaults => true, :strict => true))
+    assert(!data.key?('foo'))
+  end
+
+  def test_self_reference
+    schema = {
+      "$schema" => "http://json-schema.org/draft-04/schema#",
+      "type" => "object",
+      "properties" => { "a" => {"type" => "integer"}, "b" => {"$ref" => "#"}}
+    }
+
+    assert_valid schema, {"a" => 5, "b" => {"b" => {"a" => 1}}}
+    refute_valid schema, {"a" => 5, "b" => {"b" => {"a" => 'taco'}}}
+  end
+
+  def test_format_datetime
+    schema = {
+      "$schema" => "http://json-schema.org/draft-04/schema#",
+      "type" => "object",
+      "properties" => { "a" => {"type" => "string", "format" => "date-time"}}
+    }
+
+    assert_valid schema, {"a" => "2010-01-01T12:00:00Z"}
+    assert_valid schema, {"a" => "2010-01-01T12:00:00.1Z"}
+    refute_valid schema, {"a" => "2010-01-01T12:00:00,1Z"}
+    refute_valid schema, {"a" => "2010-01-01T12:00:00+0000"}
+    assert_valid schema, {"a" => "2010-01-01T12:00:00+00:00"}
+    refute_valid schema, {"a" => "2010-01-32T12:00:00Z"}
+    refute_valid schema, {"a" => "2010-13-01T12:00:00Z"}
+    assert_valid schema, {"a" => "2010-01-01T24:00:00Z"}
+    refute_valid schema, {"a" => "2010-01-01T12:60:00Z"}
+    assert_valid schema, {"a" => "2010-01-01T12:00:60Z"}
+    assert_valid schema, {"a" => "2010-01-01T12:00:00z"}
+    refute_valid schema, {"a" => "2010-01-0112:00:00Z"}
+  end
+
+  def test_format_uri
+    data1 = {"a" => "http://gitbuh.com"}
+    data2 = {"a" => "::boo"}
+    data3 = {"a" => "http://ja.wikipedia.org/wiki/メインページ"}
+
+    schema = {
+      "$schema" => "http://json-schema.org/draft-04/schema#",
+      "type" => "object",
+      "properties" => { "a" => {"type" => "string", "format" => "uri"}}
+    }
+
+    assert(JSON::Validator.validate(schema,data1))
+    assert(!JSON::Validator.validate(schema,data2))
+    assert(JSON::Validator.validate(schema,data3))
+  end
+
+  def test_schema
+    schema = {
+      "$schema" => "http://json-schema.org/THIS-IS-NOT-A-SCHEMA",
+      "type" => "object"
+    }
+
+    data = {"a" => "taco"}
+    assert(!JSON::Validator.validate(schema,data))
+
+    schema = {
+      "$schema" => "http://json-schema.org/draft-04/schema#",
+      "type" => "object"
+    }
+    assert_valid schema, data
+  end
+
+  def test_dependency
+    schema = {
+      "$schema" => "http://json-schema.org/draft-04/schema#",
+      "type" => "object",
+      "properties" => {
+        "a" => {"type" => "integer"},
+        "b" => {"type" => "integer"}
+      },
+      "dependencies" => {
+        "a" => ["b"]
+      }
+    }
+
+    data = {"a" => 1, "b" => 2}
+    assert_valid schema, data
+    data = {"a" => 1}
+    refute_valid schema, data
+
+    schema = {
+      "$schema" => "http://json-schema.org/draft-04/schema#",
+      "type" => "object",
+      "properties" => {
+        "a" => {"type" => "integer"},
+        "b" => {"type" => "integer"},
+        "c" => {"type" => "integer"}
+      },
+      "dependencies" => {
+        "a" => ["b","c"]
+      }
+    }
+
+    data = {"a" => 1, "c" => 2}
+    refute_valid schema, data
+    data = {"a" => 1, "b" => 2, "c" => 3}
+    assert_valid schema, data
+  end
+
+  def test_schema_dependency
+    schema = {
+      "type"=> "object",
+      "properties"=> {
+        "name"=> { "type"=> "string" },
+        "credit_card"=> { "type"=> "number" }
+      },
+      "required"=> ["name"],
+      "dependencies"=> {
+        "credit_card"=> {
+          "properties"=> {
+            "billing_address"=> { "type"=> "string" }
+          },
+          "required"=> ["billing_address"]
+        }
+      }
+    }
+    data = {
+      "name" => "John Doe",
+      "credit_card" => 5555555555555555
+    }
+    assert(!JSON::Validator.validate(schema,data), 'test schema dependency with invalid data')
+    data['billing_address'] = "Somewhere over the rainbow"
+    assert(JSON::Validator.validate(schema,data), 'test schema dependency with valid data')
+  end
+
+  def test_default
+    schema = {
+      "$schema" => "http://json-schema.org/draft-04/schema#",
+      "type" => "object",
+      "properties" => {
+        "a" => {"type" => "integer", "default" => 42},
+        "b" => {"type" => "integer"}
+      }
+    }
+
+    data = {:b => 2}
+    assert_valid schema, data
+    assert_nil(data["a"])
+    assert(JSON::Validator.validate(schema,data, :insert_defaults => true))
+    assert_equal(42, data["a"])
+    assert_equal(2, data[:b])
+
+    schema = {
+      "$schema" => "http://json-schema.org/draft-04/schema#",
+      "type" => "object",
+      "required" => ["a"],
+      "properties" => {
+        "a" => {"type" => "integer", "default" => 42},
+        "b" => {"type" => "integer"}
+      }
+    }
+
+    data = {:b => 2}
+    refute_valid schema, data
+    assert_nil(data["a"])
+    assert(JSON::Validator.validate(schema,data, :insert_defaults => true))
+    assert_equal(42, data["a"])
+    assert_equal(2, data[:b])
+
+    schema = {
+      "$schema" => "http://json-schema.org/draft-04/schema#",
+      "type" => "object",
+      "required" => ["a"],
+      "properties" => {
+        "a" => {"type" => "integer", "default" => 42, "readonly" => true},
+        "b" => {"type" => "integer"}
+      }
+    }
+
+    data = {:b => 2}
+    refute_valid schema, data
+    assert_nil(data["a"])
+    assert(!JSON::Validator.validate(schema,data, :insert_defaults => true))
+    assert_nil(data["a"])
+    assert_equal(2, data[:b])
+
+    schema = {
+      "$schema" => "http://json-schema.org/draft-04/schema#",
+      "type" => "object",
+      "properties" => {
+        "a" => {"type" => "integer", "default" => "42"},
+        "b" => {"type" => "integer"}
+      }
+    }
+
+    data = {:b => 2}
+    assert_valid schema, data
+    assert_nil(data["a"])
+    assert(!JSON::Validator.validate(schema,data, :insert_defaults => true))
+    assert_equal("42",data["a"])
+    assert_equal(2, data[:b])
+
+  end
+
+  def test_boolean_false_default
+    schema = {
+      "$schema" => "http://json-schema.org/draft-04/schema#",
+      "type" => "object",
+      "required" => ["a"],
+      "properties" => {
+        "a" => {"type" => "boolean", "default" => false},
+        "b" => {"type" => "integer"}
+      }
+    }
+
+    data = {:b => 2}
+    refute_valid schema, data
+    assert_nil(data["a"])
+    assert(JSON::Validator.validate(schema, data, :insert_defaults => true))
+    assert_equal(false, data["a"])
+    assert_equal(2, data[:b])
+  end
+
+  def test_all_of
+    schema = {
+      "$schema" => "http://json-schema.org/draft-04/schema#",
+      "allOf" => [
+        {
+          "properties" => {"a" => {"type" => "string"}},
+          "required" => ["a"]
+        },
+        {
+          "properties" => {"b" => {"type" => "integer"}}
+        }
+      ]
+    }
+
+    data = {"a" => "hello", "b" => 5}
+    assert_valid schema, data
+
+    data = {"a" => "hello"}
+    assert_valid schema, data
+
+    data = {"a" => "hello", "b" => "taco"}
+    refute_valid schema, data
+
+    data = {"b" => 5}
+    refute_valid schema, data
+  end
+
+
+  def test_any_of
+    schema = {
+      "$schema" => "http://json-schema.org/draft-04/schema#",
+      "anyOf" => [
+        {
+          "properties" => {"a" => {"type" => "string"}},
+          "required" => ["a"]
+        },
+        {
+          "properties" => {"b" => {"type" => "integer"}}
+        }
+      ]
+    }
+
+    data = {"a" => "hello", "b" => 5}
+    assert_valid schema, data
+
+    data = {"a" => "hello"}
+    assert_valid schema, data
+
+    data = {"a" => "hello", "b" => "taco"}
+    assert_valid schema, data
+
+    data = {"b" => 5}
+    assert_valid schema, data
+
+    data = {"a" => 5, "b" => "taco"}
+    refute_valid schema, data
+  end
+
+
+  def test_one_of
+    schema = {
+      "$schema" => "http://json-schema.org/draft-04/schema#",
+      "oneOf" => [
+        {
+          "properties" => {"a" => {"type" => "string"}},
+          "required" => ["a"]
+        },
+        {
+          "properties" => {"b" => {"type" => "integer"}}
+        }
+      ]
+    }
+
+    data = {"a" => "hello", "b" => 5}
+    refute_valid schema, data
+
+    # This passes because b is not required, thus matches both schemas
+    data = {"a" => "hello"}
+    refute_valid schema, data
+
+    data = {"a" => "hello", "b" => "taco"}
+    assert_valid schema, data
+
+    data = {"b" => 5}
+    assert_valid schema, data
+
+    data = {"a" => 5, "b" => "taco"}
+    refute_valid schema, data
+  end
+
+
+  def test_not
+    # Start with a simple not
+    schema = {
+      "$schema" => "http://json-schema.org/draft-04/schema#",
+      "properties" => {
+        "a" => {"not" => { "type" => ["string", "boolean"]}}
+      }
+    }
+
+    data = {"a" => 1}
+    assert_valid schema, data
+
+    data = {"a" => "hi!"}
+    refute_valid schema, data
+
+    data = {"a" => true}
+    refute_valid schema, data
+
+    # Sub-schema not
+    schema = {
+      "$schema" => "http://json-schema.org/draft-04/schema#",
+      "properties" => {
+        "a" => {"not" => {"anyOf" => [
+            {
+              "type" => ["string","boolean"]
+            },
+            {
+              "type" => "object",
+              "properties" => {
+                "b" => {"type" => "boolean"}
+              }
+            }
+          ]}
+        }
+      }
+    }
+
+    data = {"a" => 1}
+    assert_valid schema, data
+
+    data = {"a" => "hi!"}
+    refute_valid schema, data
+
+    data = {"a" => true}
+    refute_valid schema, data
+
+    data = {"a" => {"b" => true}}
+    refute_valid schema, data
+
+    data = {"a" => {"b" => 5}}
+    assert_valid schema, data
+  end
+
+  def test_not_fully_validate
+    # Start with a simple not
+    schema = {
+      "$schema" => "http://json-schema.org/draft-04/schema#",
+      "properties" => {
+        "a" => {"not" => { "type" => ["string", "boolean"]}}
+      }
+    }
+
+    data = {"a" => 1}
+    errors = JSON::Validator.fully_validate(schema,data)
+    assert_equal(0, errors.length)
+
+    data = {"a" => "taco"}
+    errors = JSON::Validator.fully_validate(schema,data)
+    assert_equal(1, errors.length)
+  end
+
+  def test_definitions
+    schema = {
+      "$schema" => "http://json-schema.org/draft-04/schema#",
+      "type" => "array",
+      "items" => { "$ref" => "#/definitions/positiveInteger"},
+      "definitions" => {
+        "positiveInteger" => {
+          "type" => "integer",
+          "minimum" => 0,
+          "exclusiveMinimum" => true
+        }
+      }
+    }
+
+    data = [1,2,3]
+    assert_valid schema, data
+
+    data = [-1,2,3]
+    refute_valid schema, data
+  end
+end
+
+
diff --git a/test/test_list_option.rb b/test/test_list_option.rb
new file mode 100644
index 0000000..2360cf5
--- /dev/null
+++ b/test/test_list_option.rb
@@ -0,0 +1,21 @@
+require File.expand_path('../test_helper', __FILE__)
+
+class ListOptionTest < Minitest::Test
+  def test_list_option_reusing_schemas
+    schema_hash = {
+      "$schema" => "http://json-schema.org/draft-04/schema#",
+      "type" => "object",
+      "properties" => { "a" => { "type" => "integer" } }
+    }
+
+    uri = Addressable::URI.parse('http://example.com/item')
+    schema = JSON::Schema.new(schema_hash, uri)
+    JSON::Validator.add_schema(schema)
+
+    data = {"a" => 1}
+    assert_valid uri.to_s, data
+
+    data = [{"a" => 1}]
+    assert_valid uri.to_s, data, :list => true
+  end
+end
diff --git a/test/test_load_ref_schema.rb b/test/test_load_ref_schema.rb
new file mode 100644
index 0000000..9af9a7a
--- /dev/null
+++ b/test/test_load_ref_schema.rb
@@ -0,0 +1,38 @@
+require File.expand_path('../test_helper', __FILE__)
+
+class LoadRefSchemaTests < Minitest::Test
+  def load_other_schema
+    JSON::Validator.add_schema(JSON::Schema.new(
+      {
+        '$schema' => 'http://json-schema.org/draft-04/schema#',
+        'type' => 'object',
+        'properties' => {
+          "title" => {
+            "type" => "string"
+          }
+        }
+      },
+      Addressable::URI.parse("http://example.com/schema#")
+    ))
+  end
+
+  def test_cached_schema
+    schema_url = "http://example.com/schema#"
+    schema = { "$ref" => schema_url }
+    data = {}
+    load_other_schema
+    _validator = JSON::Validator.new(schema, data)
+
+    assert JSON::Validator.schema_loaded?(schema_url)
+  end
+
+  def test_cached_schema_with_fragment
+    schema_url = "http://example.com/schema#"
+    schema = { "$ref" => "#{schema_url}/properties/title" }
+    data = {}
+    load_other_schema
+    _validator = JSON::Validator.new(schema, data)
+
+    assert JSON::Validator.schema_loaded?(schema_url)
+  end
+end
diff --git a/test/test_merge_missing_values.rb b/test/test_merge_missing_values.rb
new file mode 100644
index 0000000..a375a89
--- /dev/null
+++ b/test/test_merge_missing_values.rb
@@ -0,0 +1,45 @@
+require File.expand_path('../test_helper', __FILE__)
+
+class MergeMissingValuesTest < Minitest::Test
+  def test_merge_missing_values_for_string
+    original = 'foo'
+    updated = 'foo'
+    JSON::Validator.merge_missing_values(updated, original)
+    assert_equal('foo', original)
+  end
+
+  def test_merge_missing_values_for_empty_array
+    original = []
+    updated = []
+    JSON::Validator.merge_missing_values(updated, original)
+    assert_equal([], original)
+  end
+
+  def test_merge_missing_values_for_empty_hash
+    original = {}
+    updated = {}
+    JSON::Validator.merge_missing_values(updated, original)
+    assert_equal({}, original)
+  end
+
+  def test_merge_missing_values_for_new_values
+    original = {:hello => 'world'}
+    updated = {'hello' => 'world', 'foo' => 'bar'}
+    JSON::Validator.merge_missing_values(updated, original)
+    assert_equal({:hello => 'world', 'foo' => 'bar'}, original)
+  end
+
+  def test_merge_missing_values_for_nested_array
+    original = [:hello, 'world', 1, 2, 3, {:foo => :bar, 'baz' => 'qux'}]
+    updated = ['hello', 'world', 1, 2, 3, {'foo' => 'bar', 'baz' => 'qux', 'this_is' => 'new'}]
+    JSON::Validator.merge_missing_values(updated, original)
+    assert_equal([:hello, 'world', 1, 2, 3, {:foo => :bar, 'baz' => 'qux', 'this_is' => 'new'}], original)
+  end
+
+  def test_merge_missing_values_for_nested_hash
+    original = {:hello => 'world', :foo => ['bar', :baz, {:uno => {:due => 3}}]}
+    updated = {'hello' => 'world', 'foo' => ['bar', 'baz', {'uno' => {'due' => 3, 'this_is' => 'new'}}], 'ack' => 'sed'}
+    JSON::Validator.merge_missing_values(updated, original)
+    assert_equal({:hello => 'world', :foo => ['bar', :baz, {:uno => {:due => 3, 'this_is' => 'new'}}], 'ack' => 'sed'}, original)
+  end
+end
diff --git a/test/test_minitems.rb b/test/test_minitems.rb
new file mode 100644
index 0000000..d17d224
--- /dev/null
+++ b/test/test_minitems.rb
@@ -0,0 +1,16 @@
+require File.expand_path('../test_helper', __FILE__)
+
+class MinItemsTest < Minitest::Test
+  def test_minitems_nils
+    schema = {
+      "type" => "array",
+      "minItems" => 1,
+      "items" => { "type" => "object" }
+    }
+
+    errors = JSON::Validator.fully_validate(schema, [nil])
+    assert_equal(errors.length, 1)
+    assert(errors[0] !~ /minimum/)
+    assert(errors[0] =~ /NilClass/)
+  end
+end
diff --git a/test/test_one_of.rb b/test/test_one_of.rb
new file mode 100644
index 0000000..f26e924
--- /dev/null
+++ b/test/test_one_of.rb
@@ -0,0 +1,85 @@
+require File.expand_path('../test_helper', __FILE__)
+
+class OneOfTest < Minitest::Test
+  def test_one_of_links_schema
+    schema = schema_fixture_path('one_of_ref_links_schema.json')
+    data   = data_fixture_path('one_of_ref_links_data.json')
+    assert_valid schema, data
+  end
+
+  def test_one_of_with_string_patterns
+    schema = {
+      "$schema" => "http://json-schema.org/draft-04/schema#",
+      "oneOf" => [
+        {
+          "properties" => {"a" => {"type" => "string", "pattern" => "foo"}},
+        },
+        {
+          "properties" => {"a" => {"type" => "string", "pattern" => "bar"}},
+        },
+        {
+          "properties" => {"a" => {"type" => "string", "pattern" => "baz"}},
+        }
+      ]
+    }
+
+    assert_valid schema, { "a" => "foo" }
+    refute_valid schema, { "a" => "foobar" }
+    assert_valid schema, { "a" => "baz" }
+    refute_valid schema, { "a" => 5 }
+  end
+
+  def test_one_of_sub_errors
+    schema = {
+      "$schema" => "http://json-schema.org/draft-04/schema#",
+      "oneOf" => [
+        {
+          "properties" => {"a" => {"type" => "string", "pattern" => "foo"}},
+        },
+        {
+          "properties" => {"a" => {"type" => "string", "pattern" => "bar"}},
+        },
+        {
+          "properties" => {"a" => {"type" => "number", "minimum" => 10}},
+        }
+      ]
+    }
+
+    errors = JSON::Validator.fully_validate(schema, { "a" => 5 }, :errors_as_objects => true)
+    nested_errors = errors[0][:errors]
+    assert_equal([:oneof_0,:oneof_1,:oneof_2], nested_errors.keys, 'should have nested errors for each allOf subschema')
+    assert_match(/the property '#\/a' of type Fixnum did not match the following type: string/i, nested_errors[:oneof_0][0][:message])
+    assert_match(/the property '#\/a' did not have a minimum value of 10, inclusively/i, nested_errors[:oneof_2][0][:message])
+  end
+
+  def test_one_of_sub_errors_message
+    schema = {
+      "$schema" => "http://json-schema.org/draft-04/schema#",
+      "oneOf" => [
+        {
+          "properties" => {"a" => {"type" => "string", "pattern" => "foo"}},
+        },
+        {
+          "properties" => {"a" => {"type" => "string", "pattern" => "bar"}},
+        },
+        {
+          "properties" => {"a" => {"type" => "number", "minimum" => 10}},
+        }
+      ]
+    }
+
+    errors = JSON::Validator.fully_validate(schema, { "a" => 5 })
+    expected_message = """The property '#/' of type Hash did not match any of the required schemas. The schema specific errors were:
+
+- oneOf #0:
+    - The property '#/a' of type Fixnum did not match the following type: string
+- oneOf #1:
+    - The property '#/a' of type Fixnum did not match the following type: string
+- oneOf #2:
+    - The property '#/a' did not have a minimum value of 10, inclusively"""
+
+    assert_equal(expected_message, errors[0])
+
+  end
+
+end
diff --git a/test/test_ruby_schema.rb b/test/test_ruby_schema.rb
new file mode 100644
index 0000000..7693b33
--- /dev/null
+++ b/test/test_ruby_schema.rb
@@ -0,0 +1,59 @@
+require File.expand_path('../test_helper', __FILE__)
+
+class RubySchemaTest < Minitest::Test
+  def test_string_keys
+    schema = {
+      "type" => 'object',
+      "required" => ["a"],
+      "properties" => {
+        "a" => {"type" => "integer", "default" => 42},
+        "b" => {"type" => "integer"}
+      }
+    }
+
+    assert_valid schema, { "a" => 5 }
+  end
+
+  def test_symbol_keys
+    schema = {
+      :type => 'object',
+      :required => ["a"],
+      :properties => {
+        :a => {:type => "integer", :default => 42},
+        :b => {:type => "integer"}
+      }
+    }
+
+    assert_valid schema, { :a => 5 }
+  end
+
+  def test_symbol_keys_in_hash_within_array
+    schema = {
+      :type => 'object',
+      :properties => {
+        :a => {
+          :type => "array",
+          :items => [
+            {
+              :properties => {
+                :b => {
+                  :type => "integer"
+                }
+              }
+            }
+          ]
+        }
+      }
+    }
+
+    data = {
+      :a => [
+        {
+          :b => 1
+        }
+      ]
+    }
+
+    assert_valid schema, data, :validate_schema => true
+  end
+end
diff --git a/test/test_schema_loader.rb b/test/test_schema_loader.rb
new file mode 100644
index 0000000..1972c83
--- /dev/null
+++ b/test/test_schema_loader.rb
@@ -0,0 +1,74 @@
+require File.expand_path('../test_helper', __FILE__)
+
+class TestSchemaReader < Minitest::Test
+  ADDRESS_SCHEMA_URI  = 'http://json-schema.org/address'
+  ADDRESS_SCHEMA_PATH = File.expand_path('../schemas/address_microformat.json', __FILE__)
+
+  def stub_address_request(body = File.read(ADDRESS_SCHEMA_PATH))
+    stub_request(:get, ADDRESS_SCHEMA_URI).
+      to_return(:body => body, :status => 200)
+  end
+
+  def test_accept_all_uris
+    stub_address_request
+
+    reader = JSON::Schema::Reader.new
+    schema = reader.read(ADDRESS_SCHEMA_URI)
+
+    assert_equal schema.uri, Addressable::URI.parse("#{ADDRESS_SCHEMA_URI}#")
+  end
+
+  def test_accept_all_files
+    reader = JSON::Schema::Reader.new
+    schema = reader.read(ADDRESS_SCHEMA_PATH)
+
+    assert_equal schema.uri, Addressable::URI.convert_path(ADDRESS_SCHEMA_PATH + '#')
+  end
+
+  def test_refuse_all_uris
+    reader = JSON::Schema::Reader.new(:accept_uri => false)
+    refute reader.accept_uri?(Addressable::URI.parse('http://foo.com'))
+  end
+
+  def test_refuse_all_files
+    reader = JSON::Schema::Reader.new(:accept_file => false)
+    refute reader.accept_file?(Pathname.new('/foo/bar/baz'))
+  end
+
+  def test_accept_uri_proc
+    reader = JSON::Schema::Reader.new(
+      :accept_uri => proc { |uri| uri.host == 'json-schema.org' }
+    )
+
+    assert reader.accept_uri?(Addressable::URI.parse('http://json-schema.org/address'))
+    refute reader.accept_uri?(Addressable::URI.parse('http://sub.json-schema.org/address'))
+  end
+
+  def test_accept_file_proc
+    test_root = Pathname.new(__FILE__).expand_path.dirname
+
+    reader = JSON::Schema::Reader.new(
+      :accept_file => proc { |path| path.to_s.start_with?(test_root.to_s) }
+    )
+
+    assert reader.accept_file?(test_root.join('anything.json'))
+    refute reader.accept_file?(test_root.join('..', 'anything.json'))
+  end
+
+  def test_file_scheme
+    reader = JSON::Schema::Reader.new(:accept_uri => true, :accept_file => false)
+    assert_raises(JSON::Schema::ReadRefused) do
+      reader.read('file://' + ADDRESS_SCHEMA_PATH)
+    end
+  end
+
+  def test_parse_error
+    stub_address_request('this is totally not valid JSON!')
+
+    reader = JSON::Schema::Reader.new
+
+    assert_raises(JSON::Schema::JsonParseError) do
+      reader.read(ADDRESS_SCHEMA_URI)
+    end
+  end
+end
diff --git a/test/test_schema_type_attribute.rb b/test/test_schema_type_attribute.rb
new file mode 100644
index 0000000..5b446e9
--- /dev/null
+++ b/test/test_schema_type_attribute.rb
@@ -0,0 +1,20 @@
+require File.expand_path('../test_helper', __FILE__)
+
+class TestSchemaTypeAttribute < Minitest::Test
+  def test_type_of_data
+    assert_equal(type_of_data(String.new), 'string')
+    assert_equal(type_of_data(Numeric.new), 'number')
+    assert_equal(type_of_data(1), 'integer')
+    assert_equal(type_of_data(true), 'boolean')
+    assert_equal(type_of_data(false), 'boolean')
+    assert_equal(type_of_data(Hash.new), 'object')
+    assert_equal(type_of_data(nil), 'null')
+    assert_equal(type_of_data(Object.new), 'any')
+  end
+
+  private
+
+  def type_of_data(data)
+    JSON::Schema::TypeAttribute.type_of_data(data)
+  end
+end
diff --git a/test/test_schema_validation.rb b/test/test_schema_validation.rb
new file mode 100644
index 0000000..940715e
--- /dev/null
+++ b/test/test_schema_validation.rb
@@ -0,0 +1,185 @@
+require File.expand_path('../test_helper', __FILE__)
+require 'tmpdir'
+
+class JSONSchemaValidation < Minitest::Test
+  def valid_schema_v3
+    {
+      "$schema" => "http://json-schema.org/draft-03/schema#",
+      "type" => "object",
+      "properties" => {
+        "b" => {
+          "required" => true
+        }
+      }
+    }
+  end
+
+  def invalid_schema_v3
+    {
+      "$schema" => "http://json-schema.org/draft-03/schema#",
+      "type" => "object",
+      "properties" => {
+        "b" => {
+          "required" => "true"
+        }
+      }
+    }
+  end
+
+  def valid_schema_v4
+    {
+      "$schema" => "http://json-schema.org/draft-04/schema#",
+      "type" => "object",
+      "required" => ["b"],
+      "properties" => {
+      }
+    }
+  end
+
+  def invalid_schema_v4
+    {
+      "$schema" => "http://json-schema.org/draft-04/schema#",
+      "type" => "object",
+      "required" => "b",
+      "properties" => {
+      }
+    }
+  end
+
+  def symbolized_schema
+    {
+      :type => :object,
+      :required => [
+        :id,
+        :name,
+        :real_name,
+        :role,
+        :website,
+        :biography,
+        :created_at,
+        :demographic
+      ],
+      :properties => {
+        :id => {
+          :type => [
+            :integer
+          ]
+        },
+        :name => {
+          :type => [
+            :string
+          ]
+        },
+        :real_name => {
+          :type => [
+            :string
+          ]
+        },
+        :role => {
+          :type => [
+            :string
+          ]
+        },
+        :website => {
+          :type => [
+            :string,
+            :null
+          ]
+        },
+        :created_at => {
+          :type => [
+            :string
+          ]
+        },
+        :biography => {
+          :type => [
+            :string,
+            :null
+          ]
+        }
+      },
+      :relationships => {
+        :demographic => {
+          :type => :object,
+          :required => [
+            :id,
+            :gender
+          ],
+          :properties => {
+            :id => {
+              :type => [
+                :integer
+              ]
+            },
+            :gender => {
+              :type => [
+                :string
+              ]
+            }
+          }
+        }
+      }
+    }
+  end
+
+  def test_draft03_validation
+    data = {"b" => {"a" => 5}}
+    assert(JSON::Validator.validate(valid_schema_v3,data,:validate_schema => true, :version => :draft3))
+    assert(!JSON::Validator.validate(invalid_schema_v3,data,:validate_schema => true, :version => :draft3))
+  end
+
+  def test_validate_just_schema_draft03
+    errors = JSON::Validator.fully_validate_schema(valid_schema_v3, :version => :draft3)
+    assert_equal [], errors
+
+    errors = JSON::Validator.fully_validate_schema(invalid_schema_v3, :version => :draft3)
+    assert_equal 1, errors.size
+    assert_match(/the property .*required.*did not match/i, errors.first)
+  end
+
+
+  def test_draft04_validation
+    data = {"b" => {"a" => 5}}
+    assert(JSON::Validator.validate(valid_schema_v4,data,:validate_schema => true, :version => :draft4))
+    assert(!JSON::Validator.validate(invalid_schema_v4,data,:validate_schema => true, :version => :draft4))
+  end
+
+  def test_validate_just_schema_draft04
+    errors = JSON::Validator.fully_validate_schema(valid_schema_v4, :version => :draft4)
+    assert_equal [], errors
+
+    errors = JSON::Validator.fully_validate_schema(invalid_schema_v4, :version => :draft4)
+    assert_equal 1, errors.size
+    assert_match(/the property .*required.*did not match/i, errors.first)
+  end
+
+  def test_validate_schema_3_without_version_option
+    data = {"b" => {"a" => 5}}
+    assert(JSON::Validator.validate(valid_schema_v3,data,:validate_schema => true))
+    assert(!JSON::Validator.validate(invalid_schema_v3,data,:validate_schema => true))
+  end
+
+  def test_schema_validation_from_different_directory
+    Dir.mktmpdir do |tmpdir|
+      Dir.chdir(tmpdir) do
+        data = {"b" => {"a" => 5}}
+        assert(JSON::Validator.validate(valid_schema_v4,data,:validate_schema => true, :version => :draft4))
+        assert(!JSON::Validator.validate(invalid_schema_v4,data,:validate_schema => true, :version => :draft4))
+      end
+    end
+  end
+
+  def test_validate_schema_with_symbol_keys
+    data = {
+      "created_at" => "2014-01-25T00:58:33-08:00",
+      "id" => 8517194300913402149003,
+      "name" => "chelsey",
+      "real_name" => "Mekhi Hegmann",
+      "website" => nil,
+      "role" => "user",
+      "biography" => nil,
+      "demographic" => nil
+    }
+    assert(JSON::Validator.validate!(symbolized_schema, data, :validate_schema => true))
+  end
+end
diff --git a/test/test_stringify.rb b/test/test_stringify.rb
new file mode 100644
index 0000000..9999437
--- /dev/null
+++ b/test/test_stringify.rb
@@ -0,0 +1,48 @@
+require File.expand_path('../test_helper', __FILE__)
+
+class StringifyTest < Minitest::Test
+  def test_stringify_on_hash
+    hash = {
+      :a => 'foo',
+      'b' => :bar
+    }
+    assert_equal({'a' => 'foo', 'b' => 'bar'}, JSON::Schema.stringify(hash), 'symbol keys should be converted to strings')
+  end
+
+  def test_stringify_on_array
+    array = [
+      :a,
+      'b'
+    ]
+    assert_equal(['a', 'b'], JSON::Schema.stringify(array), 'symbols in an array should be converted to strings')
+  end
+
+  def test_stringify_on_hash_of_arrays
+    hash = {
+      :a => [:foo],
+      'b' => :bar
+    }
+    assert_equal({'a' => ['foo'], 'b' => 'bar'}, JSON::Schema.stringify(hash), 'symbols in a nested array should be converted to strings')
+  end
+
+  def test_stringify_on_array_of_hashes
+    array = [
+      :a,
+      {
+        :b => :bar
+      }
+    ]
+    assert_equal(['a', {'b' => 'bar'}], JSON::Schema.stringify(array), 'symbols keys in a nested hash should be converted to strings')
+  end
+
+  def test_stringify_on_hash_of_hashes
+    hash = {
+      :a => {
+        :b => {
+          :foo => :bar
+        }
+      }
+    }
+    assert_equal({'a' => {'b' => {'foo' => 'bar'} } }, JSON::Schema.stringify(hash), 'symbols in a nested hash of hashes should be converted to strings')
+  end
+end
diff --git a/test/test_uri_related.rb b/test/test_uri_related.rb
new file mode 100644
index 0000000..70069ba
--- /dev/null
+++ b/test/test_uri_related.rb
@@ -0,0 +1,67 @@
+# coding: utf-8
+require File.expand_path('../test_helper', __FILE__)
+
+class UriRelatedTest < Minitest::Test
+  def test_asian_characters
+    schema = {
+      "$schema"=> "http://json-schema.org/draft-04/schema#",
+      "id"=> "http://俺:鍵@例え.テスト/p?条件#ここ#",
+      "type" => "object",
+      "required" => ["a"],
+      "properties" => {
+        "a" => {
+          "id" => "a",
+          "type" => "integer"
+        }
+      }
+    }
+    data = { "a" => 5 }
+    assert_valid schema, data
+  end
+
+  def test_schema_ref_with_empty_fragment
+    schema = {
+      "$schema" => "http://json-schema.org/draft-04/schema#",
+      "type" => "object",
+      "required" => ["names"],
+      "properties"=> {
+        "names"=> {
+          "type"=> "array",
+          "items"=> {
+            "anyOf"=> [
+              { "$ref" => "test/schemas/ref john with spaces schema.json#" },
+            ]
+          }
+        }
+      }
+    }
+    data = {"names" => [{"first" => "john"}]}
+    assert_valid schema, data
+  end
+
+  def test_schema_ref_from_file_with_spaces
+    schema = {
+      "$schema" => "http://json-schema.org/draft-04/schema#",
+      "type" => "object",
+      "required" => ["names"],
+      "properties"=> {
+        "names"=> {
+          "type"=> "array",
+          "items"=> {
+            "anyOf"=> [
+              { "$ref" => "test/schemas/ref john with spaces schema.json" }
+            ]
+          }
+        }
+      }
+    }
+    data = {"names" => [{"first" => "john"}]}
+    assert_valid schema, data
+  end
+
+  def test_schema_from_file_with_spaces
+    data = {"first" => "john"}
+    schema = "test/schemas/ref john with spaces schema.json"
+    assert_valid schema, data
+  end
+end
diff --git a/test/test_validator.rb b/test/test_validator.rb
new file mode 100644
index 0000000..eb65de6
--- /dev/null
+++ b/test/test_validator.rb
@@ -0,0 +1,53 @@
+require File.expand_path('../test_helper', __FILE__)
+
+class TestValidator < Minitest::Test
+
+  class MockReader
+    def read(location)
+      schema = {
+        '$schema' => 'http://json-schema.org/draft-04/schema#',
+        'type' => 'string',
+        'minLength' => 2
+      }
+
+      JSON::Schema.new(schema, Addressable::URI.parse(location.to_s))
+    end
+  end
+
+  def setup
+    @original_reader = JSON::Validator.schema_reader
+  end
+
+  def teardown
+    JSON::Validator.schema_reader = @original_reader
+  end
+
+  def test_default_schema_reader
+    reader = JSON::Validator.schema_reader
+    assert reader.accept_uri?(Addressable::URI.parse('http://example.com'))
+    assert reader.accept_file?(Pathname.new('/etc/passwd'))
+  end
+
+  def test_set_default_schema_reader
+    JSON::Validator.schema_reader = MockReader.new
+
+    schema = { '$ref' => 'http://any.url/at/all' }
+    assert_valid schema, 'abc'
+    refute_valid schema, 'a'
+  end
+
+  def test_validate_with_reader
+    reader = MockReader.new
+    schema = { '$ref' => 'http://any.url/at/all' }
+    assert_valid schema, 'abc', :schema_reader => reader
+    refute_valid schema, 'a', :schema_reader => reader
+  end
+
+  def test_validate_list_with_reader
+    reader = MockReader.new
+    schema = { '$ref' => 'http://what.ever/schema' }
+    assert_valid schema, ['abc', 'def'], :schema_reader => reader, :list => true
+    refute_valid schema, ['abc', 'a'], :schema_reader => reader, :list => true
+  end
+
+end

-- 
Alioth's /usr/local/bin/git-commit-notice on /srv/git.debian.org/git/pkg-ruby-extras/ruby-json-schema.git



More information about the Pkg-ruby-extras-commits mailing list