From 6a9019d9a1f76145288186623030e7c87c25d8ae Mon Sep 17 00:00:00 2001 From: Daniel Fireman Date: Tue, 21 May 2019 14:03:59 -0300 Subject: [PATCH 1/8] Add support to go 1.11 and go modules. Also adding resource.CastColumn (needed to do in one shot because needed to update the tableschema version and it broke the tests --- .travis.yml | 5 ++- README.md | 28 +++++------- datapackage/resource.go | 19 ++++++++ datapackage/resource_test.go | 86 ++++++++++++++++++++++++++++++++++-- go.mod | 8 ++++ go.sum | 9 ++++ 6 files changed, 135 insertions(+), 20 deletions(-) create mode 100644 go.mod create mode 100644 go.sum diff --git a/.travis.yml b/.travis.yml index f3f60f4..98200d3 100644 --- a/.travis.yml +++ b/.travis.yml @@ -4,13 +4,16 @@ go: - 1.8.x - 1.9.x - 1.10.x - + - 1.11.x notificaitons: email: recipients: danielfireman@gmail.com on_success: change on_failure: always +env: + - GO111MODULE=on + before_install: - go get github.com/mattn/goveralls diff --git a/README.md b/README.md index a18cc17..e80141b 100644 --- a/README.md +++ b/README.md @@ -3,21 +3,7 @@ # datapackage-go A Go library for working with [Data Packages](http://specs.frictionlessdata.io/data-package/). - - -- [datapackage-go](#datapackage-go) - - [Install](#install) - - [Main Features](#main-features) - - [Loading and validating tabular data package descriptors](#loading-and-validating-tabular-data-package-descriptors) - - [Accessing data package resources](#accessing-data-package-resources) - - [Loading zip bundles](#loading-zip-bundles) - - [Creating a zip bundle with the data package.](#creating-a-zip-bundle-with-the-data-package) - - [CSV dialect support](#csv-dialect-support) - - [Loading multipart resources](#loading-multipart-resources) - - [Loading non-tabular resources](#loading-non-tabular-resources) - - [Manipulating data packages programatically](#manipulating-data-packages-programatically) - - +autoauto- [datapackage-go](#datapackage-go)auto - [Install](#install)auto - [Main Features](#main-features)auto - [Loading and validating tabular data package descriptors](#loading-and-validating-tabular-data-package-descriptors)auto - [Accessing data package resources](#accessing-data-package-resources)auto - [Loading zip bundles](#loading-zip-bundles)auto - [Creating a zip bundle with the data package.](#creating-a-zip-bundle-with-the-data-package)auto - [CSV dialect support](#csv-dialect-support)auto - [Loading multipart resources](#loading-multipart-resources)auto - [Loading non-tabular resources](#loading-non-tabular-resources)auto - [Manipulating data packages programatically](#manipulating-data-packages-programatically)autoauto ## Install @@ -95,7 +81,7 @@ fmt.Printf("+v", cities) // [{City:london Year:2017 Population:8780000} {City:paris Year:2017 Population:2240000} {City:rome Year:2017 Population:2860000}] ``` -Finally, if the data is to big to be loaded at once or if you would like to perform line-by-line processing, you could iterate through the resource contents: +If the data is to big to be loaded at once or if you would like to perform line-by-line processing, you could iterate through the resource contents: ```go iter, _ := resource.Iter(csv.LoadHeaders()) @@ -109,6 +95,16 @@ for iter.Next() { // {City:paris Year:2017 Population:2240000} // {City:rome Year:2017 Population:2860000}] ``` + +Or you might want to process specific columns, for instance to perform an statical analysis: + +```go +var population []float64 +resource.CastColumn("population", &population, csv.LoadHeaders()) +fmt.Println(ages) +// Output: [8780000 2240000 2860000] +``` + ### Loading zip bundles It is very common to store the data in zip bundles containing the descriptor and data files. Those are natively supported by our the [datapackage.Load](https://godoc.org/github.com/frictionlessdata/datapackage-go/datapackage#Load) method. For example, lets say we have the following `package.zip` bundle: diff --git a/datapackage/resource.go b/datapackage/resource.go index 7b55529..ec3742e 100644 --- a/datapackage/resource.go +++ b/datapackage/resource.go @@ -343,6 +343,25 @@ func (r *Resource) Cast(out interface{}, opts ...csv.CreationOpts) error { return sch.CastTable(tbl, out) } +// CastColumn casts a column from tabular resource contents. +// The out argument must necessarily be the address for a slice. The slice +// may be nil or previously allocated. +func (r *Resource) CastColumn(name string, out interface{}, opts ...csv.CreationOpts) error { + sch, err := r.GetSchema() + if err != nil { + return err + } + tab, err := r.GetTable(opts...) + if err != nil { + return err + } + col, err := tab.ReadColumn(name) + if err != nil { + return err + } + return sch.CastColumn(col, name, out) +} + // NewResourceWithDefaultRegistry creates a new Resource from the passed-in descriptor. // It uses the default registry to validate the resource descriptor. func NewResourceWithDefaultRegistry(d map[string]interface{}) (*Resource, error) { diff --git a/datapackage/resource_test.go b/datapackage/resource_test.go index 58e5f6c..24c3034 100644 --- a/datapackage/resource_test.go +++ b/datapackage/resource_test.go @@ -10,9 +10,27 @@ import ( "testing" "github.com/frictionlessdata/datapackage-go/validator" + "github.com/frictionlessdata/tableschema-go/csv" + "github.com/frictionlessdata/tableschema-go/schema" "github.com/matryer/is" ) +func ExampleResource_CastColumn() { + resStr := ` + { + "name": "col", + "data": "name,age\nfoo,42\nbar,84", + "format": "csv", + "profile": "tabular-data-resource", + "schema": {"fields": [{"name": "name", "type": "string"},{"name": "age", "type": "integer"}]} + }` + res, _ := NewResourceFromString(resStr, validator.MustInMemoryRegistry()) + var ages []float64 + res.CastColumn("age", &ages, csv.LoadHeaders()) + fmt.Println(ages) + // Output: [42 84] +} + func TestNewResourceWithDefaultRegistry(t *testing.T) { res, _ := NewResourceWithDefaultRegistry(r1) fmt.Println(res.Name()) @@ -152,9 +170,9 @@ func TestNew(t *testing.T) { map[string]interface{}{"name": "foo", "path": "foo.csv", "schema": ts.URL}, validator.MustInMemoryRegistry(), ) - is.NoErr(err) + is.NoErr(err) // Resource should be created successfully. sch, err := r.GetSchema() - is.Equal(sch.Fields[0].Type, "string") + is.Equal(sch.Fields[0].Type, schema.StringType) }) t.Run("InvalidRemote", func(t *testing.T) { _, err := NewResource( @@ -177,7 +195,7 @@ func TestNew(t *testing.T) { ) is.NoErr(err) sch, err := r.GetSchema() - is.Equal(sch.Fields[0].Type, "string") + is.Equal(sch.Fields[0].Type, schema.StringType) }) t.Run("InvalidLocal", func(t *testing.T) { _, err := NewResource( @@ -457,3 +475,65 @@ func TestResource_RawRead(t *testing.T) { is.Equal(string(contents), "{\"foo\":\"1234\"}") }) } + +func TestResource_ReadColumn(t *testing.T) { + resStr := ` + { + "name": "col", + "data": "name,age\nfoo,42\nbar,84", + "format": "csv", + "profile": "tabular-data-resource", + "schema": {"fields": [{"name": "name", "type": "string"},{"name": "age", "type": "integer"}]} + }` + t.Run("Valid", func(t *testing.T) { + is := is.New(t) + res, err := NewResourceFromString(resStr, validator.MustInMemoryRegistry()) + is.NoErr(err) + var ages []float64 + is.NoErr(res.CastColumn("age", &ages, csv.LoadHeaders())) + is.Equal(float64(42), ages[0]) + is.Equal(float64(84), ages[1]) + }) + t.Run("NoSchema", func(t *testing.T) { + res := NewUncheckedResource(map[string]interface{}{}) + var ages []float64 + if res.CastColumn("age", &ages) == nil { + t.Fatal("want:err got:nil") + } + }) + t.Run("NoData", func(t *testing.T) { + res := NewUncheckedResource(map[string]interface{}{ + "schema": map[string]interface{}{}, + }) + var ages []float64 + if res.CastColumn("age", &ages) == nil { + t.Fatal("want:err got:nil") + } + }) + t.Run("HeaderNotFound", func(t *testing.T) { + is := is.New(t) + res, err := NewResourceFromString(resStr, validator.MustInMemoryRegistry()) + is.NoErr(err) + var ages []float64 + if res.CastColumn("foo", &ages) == nil { + t.Fatal("want:err got:nil") + } + }) + t.Run("FieldNotFound", func(t *testing.T) { + is := is.New(t) + resStr := ` + { + "name": "col", + "data": "name,age\nfoo,42\nbar,84", + "format": "csv", + "profile": "tabular-data-resource", + "schema": {"fields": [{"name": "name", "type": "string"},{"name": "Age", "type": "integer"}]} + }` + res, err := NewResourceFromString(resStr, validator.MustInMemoryRegistry()) + is.NoErr(err) + var ages []float64 + if res.CastColumn("age", &ages) == nil { + t.Fatal("want:err got:nil") + } + }) +} diff --git a/go.mod b/go.mod new file mode 100644 index 0000000..a791c29 --- /dev/null +++ b/go.mod @@ -0,0 +1,8 @@ +module github.com/frictionlessdata/datapackage-go + +require ( + github.com/frictionlessdata/tableschema-go v0.1.5-0.20190521014818-f9bf38926664 + github.com/matryer/is v1.2.0 + github.com/santhosh-tekuri/jsonschema v1.2.4 + github.com/satori/go.uuid v1.2.0 +) diff --git a/go.sum b/go.sum new file mode 100644 index 0000000..52975bf --- /dev/null +++ b/go.sum @@ -0,0 +1,9 @@ +github.com/frictionlessdata/tableschema-go v0.1.5-0.20190521014818-f9bf38926664 h1:IvuZMJ6dH1ye2bWmM8Yla6jj1xIPBR/nZJlm6P4ZSD4= +github.com/frictionlessdata/tableschema-go v0.1.5-0.20190521014818-f9bf38926664/go.mod h1:OfuE6zbfQdlwx5q9vf5XWXEGJ0LYZcd9ML3zme5rP3k= +github.com/matryer/is v0.0.0-20170112134659-c0323ceb4e99/go.mod h1:2fLPjFQM9rhQ15aVEtbuwhJinnOqrmgXPNdZsdwlWXA= +github.com/matryer/is v1.2.0/go.mod h1:2fLPjFQM9rhQ15aVEtbuwhJinnOqrmgXPNdZsdwlWXA= +github.com/santhosh-tekuri/jsonschema v1.2.4 h1:hNhW8e7t+H1vgY+1QeEQpveR6D4+OwKPXCfD2aieJis= +github.com/santhosh-tekuri/jsonschema v1.2.4/go.mod h1:TEAUOeZSmIxTTuHatJzrvARHiuO9LYd+cIxzgEHCQI4= +github.com/satori/go.uuid v1.1.0/go.mod h1:dA0hQrYB0VpLJoorglMZABFdXlWrHn1NEOzdhQKdks0= +github.com/satori/go.uuid v1.2.0 h1:0uYX9dsZ2yD7q2RtLRtPSdGDWzjeM3TbMJP9utgA0ww= +github.com/satori/go.uuid v1.2.0/go.mod h1:dA0hQrYB0VpLJoorglMZABFdXlWrHn1NEOzdhQKdks0= From 118be2c850c67ed0543f9c80bac31029af2977ab Mon Sep 17 00:00:00 2001 From: Daniel Fireman Date: Tue, 21 May 2019 14:17:58 -0300 Subject: [PATCH 2/8] bumping tableschema version --- Gopkg.lock | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Gopkg.lock b/Gopkg.lock index ee29e16..1c7ecb1 100644 --- a/Gopkg.lock +++ b/Gopkg.lock @@ -4,8 +4,8 @@ [[projects]] name = "github.com/frictionlessdata/tableschema-go" packages = ["csv","schema","table"] - revision = "de3a51f8487b68142a2826f6ffe521222a342273" - version = "1.1" + revision = "f9bf38926664ea64d9749ee7024987a1e967004d" + version = "1.4" [[projects]] branch = "master" From a3cceb35006be4f4488c4ff2d279b556118b0f4a Mon Sep 17 00:00:00 2001 From: Daniel Fireman Date: Tue, 21 May 2019 14:22:04 -0300 Subject: [PATCH 3/8] fixing version when using with GoDep --- Gopkg.lock | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Gopkg.lock b/Gopkg.lock index 1c7ecb1..db26e8f 100644 --- a/Gopkg.lock +++ b/Gopkg.lock @@ -5,7 +5,7 @@ name = "github.com/frictionlessdata/tableschema-go" packages = ["csv","schema","table"] revision = "f9bf38926664ea64d9749ee7024987a1e967004d" - version = "1.4" + version = "v1.4" [[projects]] branch = "master" From 4213f8f7f8c85d3a446df9d6457c9ba3b7bc1bac Mon Sep 17 00:00:00 2001 From: Daniel Fireman Date: Tue, 21 May 2019 14:26:37 -0300 Subject: [PATCH 4/8] Removing vendor dir --- .../tableschema-go/.gitignore | 18 - .../tableschema-go/.travis.yml | 18 - .../tableschema-go/CONTRIBUTING.md | 28 - .../tableschema-go/Gopkg.lock | 21 - .../tableschema-go/Gopkg.toml | 26 - .../frictionlessdata/tableschema-go/LICENSE | 21 - .../frictionlessdata/tableschema-go/README.md | 251 ------- .../tableschema-go/csv/iterator_test.go | 55 -- .../tableschema-go/csv/table.go | 262 ------- .../tableschema-go/csv/table_test.go | 135 ---- .../examples/infer/data_infer_utf8.csv | 5 - .../tableschema-go/examples/infer/main.go | 34 - .../examples/validate/capital.csv | 5 - .../tableschema-go/examples/validate/main.go | 60 -- .../examples/validate/schema.json | 23 - .../tableschema-go/schema/any.go | 11 - .../tableschema-go/schema/any_test.go | 21 - .../tableschema-go/schema/array.go | 18 - .../tableschema-go/schema/boolean.go | 39 - .../tableschema-go/schema/boolean_test.go | 78 -- .../tableschema-go/schema/date.go | 28 - .../tableschema-go/schema/date_test.go | 40 -- .../tableschema-go/schema/datetime.go | 139 ---- .../tableschema-go/schema/datetime_test.go | 126 ---- .../tableschema-go/schema/duration.go | 65 -- .../tableschema-go/schema/duration_test.go | 85 --- .../tableschema-go/schema/field.go | 268 ------- .../tableschema-go/schema/field_test.go | 276 ------- .../tableschema-go/schema/geopoint.go | 103 --- .../tableschema-go/schema/geopoint_test.go | 102 --- .../tableschema-go/schema/infer.go | 211 ------ .../tableschema-go/schema/infer_test.go | 215 ------ .../tableschema-go/schema/integer.go | 53 -- .../tableschema-go/schema/integer_test.go | 67 -- .../tableschema-go/schema/number.go | 61 -- .../tableschema-go/schema/number_test.go | 94 --- .../tableschema-go/schema/object.go | 16 - .../tableschema-go/schema/object_test.go | 26 - .../tableschema-go/schema/schema.go | 431 ----------- .../tableschema-go/schema/schema_test.go | 629 ---------------- .../tableschema-go/schema/string.go | 59 -- .../tableschema-go/schema/string_test.go | 69 -- .../tableschema-go/schema/time.go | 41 -- .../tableschema-go/schema/time_test.go | 76 -- .../tableschema-go/table/table.go | 137 ---- vendor/github.com/matryer/is/.gitignore | 24 - vendor/github.com/matryer/is/.travis.yml | 19 - vendor/github.com/matryer/is/LICENSE | 674 ------------------ vendor/github.com/matryer/is/README.md | 30 - vendor/github.com/matryer/is/is.go | 397 ----------- vendor/github.com/matryer/is/is_test.go | 252 ------- .../matryer/is/misc/delicious-failures.png | Bin 277442 -> 0 bytes .../matryer/is/testdata/example_test.go | 29 - .../santhosh-tekuri/jsonschema/.travis.yml | 10 - .../santhosh-tekuri/jsonschema/LICENSE | 27 - .../santhosh-tekuri/jsonschema/README.md | 141 ---- .../santhosh-tekuri/jsonschema/cmd/jv/main.go | 42 -- .../santhosh-tekuri/jsonschema/compiler.go | 492 ------------- .../santhosh-tekuri/jsonschema/doc.go | 74 -- .../santhosh-tekuri/jsonschema/draft4.go | 172 ----- .../santhosh-tekuri/jsonschema/draft6.go | 170 ----- .../santhosh-tekuri/jsonschema/errors.go | 122 ---- .../jsonschema/formats/formats.go | 217 ------ .../jsonschema/formats/formats_test.go | 137 ---- .../santhosh-tekuri/jsonschema/go.test.sh | 12 - .../jsonschema/httploader/httploader.go | 43 -- .../jsonschema/loader/loader.go | 101 --- .../santhosh-tekuri/jsonschema/resource.go | 235 ------ .../santhosh-tekuri/jsonschema/schema.go | 508 ------------- .../santhosh-tekuri/jsonschema/schema_test.go | 336 --------- .../jsonschema/testdata/customer.json | 12 - .../jsonschema/testdata/customer_schema.json | 10 - .../jsonschema/testdata/definitions.json | 11 - .../jsonschema/testdata/draft4.json | 231 ------ .../testdata/draft4/additionalItems.json | 87 --- .../testdata/draft4/additionalProperties.json | 88 --- .../jsonschema/testdata/draft4/allOf.json | 112 --- .../jsonschema/testdata/draft4/anyOf.json | 68 -- .../jsonschema/testdata/draft4/default.json | 49 -- .../testdata/draft4/definitions.json | 32 - .../testdata/draft4/dependencies.json | 113 --- .../jsonschema/testdata/draft4/enum.json | 72 -- .../jsonschema/testdata/draft4/items.json | 78 -- .../jsonschema/testdata/draft4/maxItems.json | 28 - .../jsonschema/testdata/draft4/maxLength.json | 33 - .../testdata/draft4/maxProperties.json | 28 - .../jsonschema/testdata/draft4/maximum.json | 47 -- .../jsonschema/testdata/draft4/minItems.json | 28 - .../jsonschema/testdata/draft4/minLength.json | 33 - .../testdata/draft4/minProperties.json | 28 - .../jsonschema/testdata/draft4/minimum.json | 47 -- .../testdata/draft4/multipleOf.json | 60 -- .../jsonschema/testdata/draft4/not.json | 96 --- .../jsonschema/testdata/draft4/oneOf.json | 68 -- .../testdata/draft4/optional/bignum.json | 107 --- .../draft4/optional/ecmascript-regex.json | 13 - .../testdata/draft4/optional/format.json | 148 ---- .../draft4/optional/zeroTerminatedFloats.json | 15 - .../jsonschema/testdata/draft4/pattern.json | 34 - .../testdata/draft4/patternProperties.json | 110 --- .../testdata/draft4/properties.json | 92 --- .../jsonschema/testdata/draft4/ref.json | 300 -------- .../jsonschema/testdata/draft4/refRemote.json | 171 ----- .../jsonschema/testdata/draft4/required.json | 44 -- .../jsonschema/testdata/draft4/santhosh.json | 130 ---- .../jsonschema/testdata/draft4/type.json | 345 --------- .../testdata/draft4/uniqueItems.json | 79 -- .../jsonschema/testdata/draft6.json | 213 ------ .../testdata/draft6/additionalItems.json | 87 --- .../testdata/draft6/additionalProperties.json | 88 --- .../jsonschema/testdata/draft6/allOf.json | 145 ---- .../jsonschema/testdata/draft6/anyOf.json | 101 --- .../testdata/draft6/boolean_schema.json | 104 --- .../jsonschema/testdata/draft6/const.json | 65 -- .../jsonschema/testdata/draft6/contains.json | 95 --- .../jsonschema/testdata/draft6/default.json | 49 -- .../testdata/draft6/definitions.json | 32 - .../testdata/draft6/dependencies.json | 162 ----- .../jsonschema/testdata/draft6/enum.json | 72 -- .../testdata/draft6/exclusiveMaximum.json | 30 - .../testdata/draft6/exclusiveMinimum.json | 30 - .../jsonschema/testdata/draft6/items.json | 133 ---- .../jsonschema/testdata/draft6/maxItems.json | 28 - .../jsonschema/testdata/draft6/maxLength.json | 33 - .../testdata/draft6/maxProperties.json | 28 - .../jsonschema/testdata/draft6/maximum.json | 28 - .../jsonschema/testdata/draft6/minItems.json | 28 - .../jsonschema/testdata/draft6/minLength.json | 33 - .../testdata/draft6/minProperties.json | 28 - .../jsonschema/testdata/draft6/minimum.json | 28 - .../testdata/draft6/multipleOf.json | 60 -- .../jsonschema/testdata/draft6/not.json | 117 --- .../jsonschema/testdata/draft6/oneOf.json | 112 --- .../testdata/draft6/optional/bignum.json | 105 --- .../draft6/optional/ecmascript-regex.json | 13 - .../testdata/draft6/optional/format.json | 261 ------- .../draft6/optional/zeroTerminatedFloats.json | 15 - .../jsonschema/testdata/draft6/pattern.json | 34 - .../testdata/draft6/patternProperties.json | 141 ---- .../testdata/draft6/properties.json | 123 ---- .../testdata/draft6/propertyNames.json | 68 -- .../jsonschema/testdata/draft6/ref.json | 332 --------- .../jsonschema/testdata/draft6/refRemote.json | 171 ----- .../jsonschema/testdata/draft6/required.json | 60 -- .../jsonschema/testdata/draft6/type.json | 345 --------- .../testdata/draft6/uniqueItems.json | 79 -- .../jsonschema/testdata/invalid_schema.json | 1 - .../jsonschema/testdata/invalid_schemas.json | 268 ------- .../remotes/folder/folderInteger.json | 3 - .../jsonschema/testdata/remotes/integer.json | 3 - .../jsonschema/testdata/remotes/name.json | 11 - .../testdata/remotes/subSchemas.json | 8 - .../jsonschema/testdata/syntax_error.json | 1 - vendor/github.com/satori/go.uuid/.travis.yml | 15 - vendor/github.com/satori/go.uuid/LICENSE | 20 - vendor/github.com/satori/go.uuid/README.md | 65 -- .../satori/go.uuid/benchmarks_test.go | 121 ---- vendor/github.com/satori/go.uuid/uuid.go | 488 ------------- vendor/github.com/satori/go.uuid/uuid_test.go | 633 ---------------- 159 files changed, 17170 deletions(-) delete mode 100644 vendor/github.com/frictionlessdata/tableschema-go/.gitignore delete mode 100644 vendor/github.com/frictionlessdata/tableschema-go/.travis.yml delete mode 100644 vendor/github.com/frictionlessdata/tableschema-go/CONTRIBUTING.md delete mode 100644 vendor/github.com/frictionlessdata/tableschema-go/Gopkg.lock delete mode 100644 vendor/github.com/frictionlessdata/tableschema-go/Gopkg.toml delete mode 100644 vendor/github.com/frictionlessdata/tableschema-go/LICENSE delete mode 100644 vendor/github.com/frictionlessdata/tableschema-go/README.md delete mode 100644 vendor/github.com/frictionlessdata/tableschema-go/csv/iterator_test.go delete mode 100644 vendor/github.com/frictionlessdata/tableschema-go/csv/table.go delete mode 100644 vendor/github.com/frictionlessdata/tableschema-go/csv/table_test.go delete mode 100644 vendor/github.com/frictionlessdata/tableschema-go/examples/infer/data_infer_utf8.csv delete mode 100644 vendor/github.com/frictionlessdata/tableschema-go/examples/infer/main.go delete mode 100644 vendor/github.com/frictionlessdata/tableschema-go/examples/validate/capital.csv delete mode 100644 vendor/github.com/frictionlessdata/tableschema-go/examples/validate/main.go delete mode 100644 vendor/github.com/frictionlessdata/tableschema-go/examples/validate/schema.json delete mode 100644 vendor/github.com/frictionlessdata/tableschema-go/schema/any.go delete mode 100644 vendor/github.com/frictionlessdata/tableschema-go/schema/any_test.go delete mode 100644 vendor/github.com/frictionlessdata/tableschema-go/schema/array.go delete mode 100644 vendor/github.com/frictionlessdata/tableschema-go/schema/boolean.go delete mode 100644 vendor/github.com/frictionlessdata/tableschema-go/schema/boolean_test.go delete mode 100644 vendor/github.com/frictionlessdata/tableschema-go/schema/date.go delete mode 100644 vendor/github.com/frictionlessdata/tableschema-go/schema/date_test.go delete mode 100644 vendor/github.com/frictionlessdata/tableschema-go/schema/datetime.go delete mode 100644 vendor/github.com/frictionlessdata/tableschema-go/schema/datetime_test.go delete mode 100644 vendor/github.com/frictionlessdata/tableschema-go/schema/duration.go delete mode 100644 vendor/github.com/frictionlessdata/tableschema-go/schema/duration_test.go delete mode 100644 vendor/github.com/frictionlessdata/tableschema-go/schema/field.go delete mode 100644 vendor/github.com/frictionlessdata/tableschema-go/schema/field_test.go delete mode 100644 vendor/github.com/frictionlessdata/tableschema-go/schema/geopoint.go delete mode 100644 vendor/github.com/frictionlessdata/tableschema-go/schema/geopoint_test.go delete mode 100644 vendor/github.com/frictionlessdata/tableschema-go/schema/infer.go delete mode 100644 vendor/github.com/frictionlessdata/tableschema-go/schema/infer_test.go delete mode 100644 vendor/github.com/frictionlessdata/tableschema-go/schema/integer.go delete mode 100644 vendor/github.com/frictionlessdata/tableschema-go/schema/integer_test.go delete mode 100644 vendor/github.com/frictionlessdata/tableschema-go/schema/number.go delete mode 100644 vendor/github.com/frictionlessdata/tableschema-go/schema/number_test.go delete mode 100644 vendor/github.com/frictionlessdata/tableschema-go/schema/object.go delete mode 100644 vendor/github.com/frictionlessdata/tableschema-go/schema/object_test.go delete mode 100644 vendor/github.com/frictionlessdata/tableschema-go/schema/schema.go delete mode 100644 vendor/github.com/frictionlessdata/tableschema-go/schema/schema_test.go delete mode 100644 vendor/github.com/frictionlessdata/tableschema-go/schema/string.go delete mode 100644 vendor/github.com/frictionlessdata/tableschema-go/schema/string_test.go delete mode 100644 vendor/github.com/frictionlessdata/tableschema-go/schema/time.go delete mode 100644 vendor/github.com/frictionlessdata/tableschema-go/schema/time_test.go delete mode 100644 vendor/github.com/frictionlessdata/tableschema-go/table/table.go delete mode 100644 vendor/github.com/matryer/is/.gitignore delete mode 100644 vendor/github.com/matryer/is/.travis.yml delete mode 100644 vendor/github.com/matryer/is/LICENSE delete mode 100644 vendor/github.com/matryer/is/README.md delete mode 100644 vendor/github.com/matryer/is/is.go delete mode 100644 vendor/github.com/matryer/is/is_test.go delete mode 100644 vendor/github.com/matryer/is/misc/delicious-failures.png delete mode 100644 vendor/github.com/matryer/is/testdata/example_test.go delete mode 100644 vendor/github.com/santhosh-tekuri/jsonschema/.travis.yml delete mode 100644 vendor/github.com/santhosh-tekuri/jsonschema/LICENSE delete mode 100644 vendor/github.com/santhosh-tekuri/jsonschema/README.md delete mode 100644 vendor/github.com/santhosh-tekuri/jsonschema/cmd/jv/main.go delete mode 100644 vendor/github.com/santhosh-tekuri/jsonschema/compiler.go delete mode 100644 vendor/github.com/santhosh-tekuri/jsonschema/doc.go delete mode 100644 vendor/github.com/santhosh-tekuri/jsonschema/draft4.go delete mode 100644 vendor/github.com/santhosh-tekuri/jsonschema/draft6.go delete mode 100644 vendor/github.com/santhosh-tekuri/jsonschema/errors.go delete mode 100644 vendor/github.com/santhosh-tekuri/jsonschema/formats/formats.go delete mode 100644 vendor/github.com/santhosh-tekuri/jsonschema/formats/formats_test.go delete mode 100755 vendor/github.com/santhosh-tekuri/jsonschema/go.test.sh delete mode 100644 vendor/github.com/santhosh-tekuri/jsonschema/httploader/httploader.go delete mode 100644 vendor/github.com/santhosh-tekuri/jsonschema/loader/loader.go delete mode 100644 vendor/github.com/santhosh-tekuri/jsonschema/resource.go delete mode 100644 vendor/github.com/santhosh-tekuri/jsonschema/schema.go delete mode 100644 vendor/github.com/santhosh-tekuri/jsonschema/schema_test.go delete mode 100644 vendor/github.com/santhosh-tekuri/jsonschema/testdata/customer.json delete mode 100644 vendor/github.com/santhosh-tekuri/jsonschema/testdata/customer_schema.json delete mode 100644 vendor/github.com/santhosh-tekuri/jsonschema/testdata/definitions.json delete mode 100644 vendor/github.com/santhosh-tekuri/jsonschema/testdata/draft4.json delete mode 100644 vendor/github.com/santhosh-tekuri/jsonschema/testdata/draft4/additionalItems.json delete mode 100644 vendor/github.com/santhosh-tekuri/jsonschema/testdata/draft4/additionalProperties.json delete mode 100644 vendor/github.com/santhosh-tekuri/jsonschema/testdata/draft4/allOf.json delete mode 100644 vendor/github.com/santhosh-tekuri/jsonschema/testdata/draft4/anyOf.json delete mode 100644 vendor/github.com/santhosh-tekuri/jsonschema/testdata/draft4/default.json delete mode 100644 vendor/github.com/santhosh-tekuri/jsonschema/testdata/draft4/definitions.json delete mode 100644 vendor/github.com/santhosh-tekuri/jsonschema/testdata/draft4/dependencies.json delete mode 100644 vendor/github.com/santhosh-tekuri/jsonschema/testdata/draft4/enum.json delete mode 100644 vendor/github.com/santhosh-tekuri/jsonschema/testdata/draft4/items.json delete mode 100644 vendor/github.com/santhosh-tekuri/jsonschema/testdata/draft4/maxItems.json delete mode 100644 vendor/github.com/santhosh-tekuri/jsonschema/testdata/draft4/maxLength.json delete mode 100644 vendor/github.com/santhosh-tekuri/jsonschema/testdata/draft4/maxProperties.json delete mode 100644 vendor/github.com/santhosh-tekuri/jsonschema/testdata/draft4/maximum.json delete mode 100644 vendor/github.com/santhosh-tekuri/jsonschema/testdata/draft4/minItems.json delete mode 100644 vendor/github.com/santhosh-tekuri/jsonschema/testdata/draft4/minLength.json delete mode 100644 vendor/github.com/santhosh-tekuri/jsonschema/testdata/draft4/minProperties.json delete mode 100644 vendor/github.com/santhosh-tekuri/jsonschema/testdata/draft4/minimum.json delete mode 100644 vendor/github.com/santhosh-tekuri/jsonschema/testdata/draft4/multipleOf.json delete mode 100644 vendor/github.com/santhosh-tekuri/jsonschema/testdata/draft4/not.json delete mode 100644 vendor/github.com/santhosh-tekuri/jsonschema/testdata/draft4/oneOf.json delete mode 100644 vendor/github.com/santhosh-tekuri/jsonschema/testdata/draft4/optional/bignum.json delete mode 100644 vendor/github.com/santhosh-tekuri/jsonschema/testdata/draft4/optional/ecmascript-regex.json delete mode 100644 vendor/github.com/santhosh-tekuri/jsonschema/testdata/draft4/optional/format.json delete mode 100644 vendor/github.com/santhosh-tekuri/jsonschema/testdata/draft4/optional/zeroTerminatedFloats.json delete mode 100644 vendor/github.com/santhosh-tekuri/jsonschema/testdata/draft4/pattern.json delete mode 100644 vendor/github.com/santhosh-tekuri/jsonschema/testdata/draft4/patternProperties.json delete mode 100644 vendor/github.com/santhosh-tekuri/jsonschema/testdata/draft4/properties.json delete mode 100644 vendor/github.com/santhosh-tekuri/jsonschema/testdata/draft4/ref.json delete mode 100644 vendor/github.com/santhosh-tekuri/jsonschema/testdata/draft4/refRemote.json delete mode 100644 vendor/github.com/santhosh-tekuri/jsonschema/testdata/draft4/required.json delete mode 100644 vendor/github.com/santhosh-tekuri/jsonschema/testdata/draft4/santhosh.json delete mode 100644 vendor/github.com/santhosh-tekuri/jsonschema/testdata/draft4/type.json delete mode 100644 vendor/github.com/santhosh-tekuri/jsonschema/testdata/draft4/uniqueItems.json delete mode 100644 vendor/github.com/santhosh-tekuri/jsonschema/testdata/draft6.json delete mode 100644 vendor/github.com/santhosh-tekuri/jsonschema/testdata/draft6/additionalItems.json delete mode 100644 vendor/github.com/santhosh-tekuri/jsonschema/testdata/draft6/additionalProperties.json delete mode 100644 vendor/github.com/santhosh-tekuri/jsonschema/testdata/draft6/allOf.json delete mode 100644 vendor/github.com/santhosh-tekuri/jsonschema/testdata/draft6/anyOf.json delete mode 100644 vendor/github.com/santhosh-tekuri/jsonschema/testdata/draft6/boolean_schema.json delete mode 100644 vendor/github.com/santhosh-tekuri/jsonschema/testdata/draft6/const.json delete mode 100644 vendor/github.com/santhosh-tekuri/jsonschema/testdata/draft6/contains.json delete mode 100644 vendor/github.com/santhosh-tekuri/jsonschema/testdata/draft6/default.json delete mode 100644 vendor/github.com/santhosh-tekuri/jsonschema/testdata/draft6/definitions.json delete mode 100644 vendor/github.com/santhosh-tekuri/jsonschema/testdata/draft6/dependencies.json delete mode 100644 vendor/github.com/santhosh-tekuri/jsonschema/testdata/draft6/enum.json delete mode 100644 vendor/github.com/santhosh-tekuri/jsonschema/testdata/draft6/exclusiveMaximum.json delete mode 100644 vendor/github.com/santhosh-tekuri/jsonschema/testdata/draft6/exclusiveMinimum.json delete mode 100644 vendor/github.com/santhosh-tekuri/jsonschema/testdata/draft6/items.json delete mode 100644 vendor/github.com/santhosh-tekuri/jsonschema/testdata/draft6/maxItems.json delete mode 100644 vendor/github.com/santhosh-tekuri/jsonschema/testdata/draft6/maxLength.json delete mode 100644 vendor/github.com/santhosh-tekuri/jsonschema/testdata/draft6/maxProperties.json delete mode 100644 vendor/github.com/santhosh-tekuri/jsonschema/testdata/draft6/maximum.json delete mode 100644 vendor/github.com/santhosh-tekuri/jsonschema/testdata/draft6/minItems.json delete mode 100644 vendor/github.com/santhosh-tekuri/jsonschema/testdata/draft6/minLength.json delete mode 100644 vendor/github.com/santhosh-tekuri/jsonschema/testdata/draft6/minProperties.json delete mode 100644 vendor/github.com/santhosh-tekuri/jsonschema/testdata/draft6/minimum.json delete mode 100644 vendor/github.com/santhosh-tekuri/jsonschema/testdata/draft6/multipleOf.json delete mode 100644 vendor/github.com/santhosh-tekuri/jsonschema/testdata/draft6/not.json delete mode 100644 vendor/github.com/santhosh-tekuri/jsonschema/testdata/draft6/oneOf.json delete mode 100644 vendor/github.com/santhosh-tekuri/jsonschema/testdata/draft6/optional/bignum.json delete mode 100644 vendor/github.com/santhosh-tekuri/jsonschema/testdata/draft6/optional/ecmascript-regex.json delete mode 100644 vendor/github.com/santhosh-tekuri/jsonschema/testdata/draft6/optional/format.json delete mode 100644 vendor/github.com/santhosh-tekuri/jsonschema/testdata/draft6/optional/zeroTerminatedFloats.json delete mode 100644 vendor/github.com/santhosh-tekuri/jsonschema/testdata/draft6/pattern.json delete mode 100644 vendor/github.com/santhosh-tekuri/jsonschema/testdata/draft6/patternProperties.json delete mode 100644 vendor/github.com/santhosh-tekuri/jsonschema/testdata/draft6/properties.json delete mode 100644 vendor/github.com/santhosh-tekuri/jsonschema/testdata/draft6/propertyNames.json delete mode 100644 vendor/github.com/santhosh-tekuri/jsonschema/testdata/draft6/ref.json delete mode 100644 vendor/github.com/santhosh-tekuri/jsonschema/testdata/draft6/refRemote.json delete mode 100644 vendor/github.com/santhosh-tekuri/jsonschema/testdata/draft6/required.json delete mode 100644 vendor/github.com/santhosh-tekuri/jsonschema/testdata/draft6/type.json delete mode 100644 vendor/github.com/santhosh-tekuri/jsonschema/testdata/draft6/uniqueItems.json delete mode 100644 vendor/github.com/santhosh-tekuri/jsonschema/testdata/invalid_schema.json delete mode 100644 vendor/github.com/santhosh-tekuri/jsonschema/testdata/invalid_schemas.json delete mode 100644 vendor/github.com/santhosh-tekuri/jsonschema/testdata/remotes/folder/folderInteger.json delete mode 100644 vendor/github.com/santhosh-tekuri/jsonschema/testdata/remotes/integer.json delete mode 100644 vendor/github.com/santhosh-tekuri/jsonschema/testdata/remotes/name.json delete mode 100644 vendor/github.com/santhosh-tekuri/jsonschema/testdata/remotes/subSchemas.json delete mode 100644 vendor/github.com/santhosh-tekuri/jsonschema/testdata/syntax_error.json delete mode 100644 vendor/github.com/satori/go.uuid/.travis.yml delete mode 100644 vendor/github.com/satori/go.uuid/LICENSE delete mode 100644 vendor/github.com/satori/go.uuid/README.md delete mode 100644 vendor/github.com/satori/go.uuid/benchmarks_test.go delete mode 100644 vendor/github.com/satori/go.uuid/uuid.go delete mode 100644 vendor/github.com/satori/go.uuid/uuid_test.go diff --git a/vendor/github.com/frictionlessdata/tableschema-go/.gitignore b/vendor/github.com/frictionlessdata/tableschema-go/.gitignore deleted file mode 100644 index ae453ff..0000000 --- a/vendor/github.com/frictionlessdata/tableschema-go/.gitignore +++ /dev/null @@ -1,18 +0,0 @@ -# Binaries for programs and plugins -*.exe -*.dll -*.so -*.dylib - -# Test binary, build with `go test -c` -*.test - -# Output of the go coverage tool, specifically when used with LiteIDE -*.out - -# Project-local glide cache, RE: https://github.com/Masterminds/glide/issues/736 -.glide/ - -**/*.coverprofile - -.vscode \ No newline at end of file diff --git a/vendor/github.com/frictionlessdata/tableschema-go/.travis.yml b/vendor/github.com/frictionlessdata/tableschema-go/.travis.yml deleted file mode 100644 index 7e57cab..0000000 --- a/vendor/github.com/frictionlessdata/tableschema-go/.travis.yml +++ /dev/null @@ -1,18 +0,0 @@ - -language: go -sudo: false -go: - - 1.8.x - - 1.9.x - -notificaitons: - email: - recipients: danielfireman@gmail.com - on_success: change - on_failure: always - -before_install: - - go get github.com/mattn/goveralls - -script: - - $HOME/gopath/bin/goveralls -service=travis-ci -ignore=examples/infer/main.go,examples/validate/main.go diff --git a/vendor/github.com/frictionlessdata/tableschema-go/CONTRIBUTING.md b/vendor/github.com/frictionlessdata/tableschema-go/CONTRIBUTING.md deleted file mode 100644 index 4c797c8..0000000 --- a/vendor/github.com/frictionlessdata/tableschema-go/CONTRIBUTING.md +++ /dev/null @@ -1,28 +0,0 @@ -# Contributing to tableschema-go - -Found a problem and would like to fix it? Have that great idea and would love to see it done? Let's do it! - -> Please open an issue before start working - -That could save a lot of time from everyone and we are super happy to answer questions and help you alonge the way. - -This project shares Go's code of conduct [values](https://golang.org/conduct#values) and [unwelcomed behavior](https://golang.org/conduct#unwelcome_behavior). Not sure what those mean or why we need those? Please give yourself a few minutes to get acquainted to those topics. - -* Before start coding: - * Fork and pull the latest version of the master branch - * Make sure you have go 1.8+ installed and you're using it - -* Requirements - * Compliance with [these guidelines](https://code.google.com/p/go-wiki/wiki/CodeReviewComments) - * Good unit test coverage - * [Good commit messages](http://tbaggery.com/2008/04/19/a-note-about-git-commit-messages.html) - -* Before sending the PR - -```sh -$ cd $GOPATH/src/github.com/frictionlessdata/tableschema-go -$ ./fmt.sh -$ go test ./.. -``` - -If all tests pass, you're ready to send the PR! :D diff --git a/vendor/github.com/frictionlessdata/tableschema-go/Gopkg.lock b/vendor/github.com/frictionlessdata/tableschema-go/Gopkg.lock deleted file mode 100644 index f8842a8..0000000 --- a/vendor/github.com/frictionlessdata/tableschema-go/Gopkg.lock +++ /dev/null @@ -1,21 +0,0 @@ -# This file is autogenerated, do not edit; changes may be undone by the next 'dep ensure'. - - -[[projects]] - branch = "master" - name = "github.com/matryer/is" - packages = ["."] - revision = "c0323ceb4e996e4a8795670d1fb6f60e65b82fd2" - -[[projects]] - name = "github.com/satori/go.uuid" - packages = ["."] - revision = "879c5887cd475cd7864858769793b2ceb0d44feb" - version = "v1.1.0" - -[solve-meta] - analyzer-name = "dep" - analyzer-version = 1 - inputs-digest = "1ad488c5d7626ee23a29a6f0e4de915d8668ad0eff6659419ef4cf5f02d1a692" - solver-name = "gps-cdcl" - solver-version = 1 diff --git a/vendor/github.com/frictionlessdata/tableschema-go/Gopkg.toml b/vendor/github.com/frictionlessdata/tableschema-go/Gopkg.toml deleted file mode 100644 index 542aa80..0000000 --- a/vendor/github.com/frictionlessdata/tableschema-go/Gopkg.toml +++ /dev/null @@ -1,26 +0,0 @@ - -# Gopkg.toml example -# -# Refer to https://github.com/golang/dep/blob/master/docs/Gopkg.toml.md -# for detailed Gopkg.toml documentation. -# -# required = ["github.com/user/thing/cmd/thing"] -# ignored = ["github.com/user/project/pkgX", "bitbucket.org/user/project/pkgA/pkgY"] -# -# [[constraint]] -# name = "github.com/user/project" -# version = "1.0.0" -# -# [[constraint]] -# name = "github.com/user/project2" -# branch = "dev" -# source = "github.com/myfork/project2" -# -# [[override]] -# name = "github.com/x/y" -# version = "2.4.0" - - -[[constraint]] - name = "github.com/satori/go.uuid" - version = "1.1.0" diff --git a/vendor/github.com/frictionlessdata/tableschema-go/LICENSE b/vendor/github.com/frictionlessdata/tableschema-go/LICENSE deleted file mode 100644 index 38351f0..0000000 --- a/vendor/github.com/frictionlessdata/tableschema-go/LICENSE +++ /dev/null @@ -1,21 +0,0 @@ -MIT License - -Copyright (c) 2017 Frictionless Data - -Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files (the "Software"), to deal -in the Software without restriction, including without limitation the rights -to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -copies of the Software, and to permit persons to whom the Software is -furnished to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in all -copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE -SOFTWARE. diff --git a/vendor/github.com/frictionlessdata/tableschema-go/README.md b/vendor/github.com/frictionlessdata/tableschema-go/README.md deleted file mode 100644 index 00949bb..0000000 --- a/vendor/github.com/frictionlessdata/tableschema-go/README.md +++ /dev/null @@ -1,251 +0,0 @@ -[![Build Status](https://travis-ci.org/frictionlessdata/tableschema-go.svg?branch=master)](https://travis-ci.org/frictionlessdata/tableschema-go) [![Coverage Status](https://coveralls.io/repos/github/frictionlessdata/tableschema-go/badge.svg?branch=master)](https://coveralls.io/github/frictionlessdata/tableschema-go?branch=master) [![Go Report Card](https://goreportcard.com/badge/github.com/frictionlessdata/tableschema-go)](https://goreportcard.com/report/github.com/frictionlessdata/tableschema-go) [![Gitter chat](https://badges.gitter.im/gitterHQ/gitter.png)](https://gitter.im/frictionlessdata/chat) [![GoDoc](https://godoc.org/github.com/frictionlessdata/tableschema-go?status.svg)](https://godoc.org/github.com/frictionlessdata/tableschema-go) - -# tableschema-go - -[Table schema](http://specs.frictionlessdata.io/table-schema/) tooling in Go. - -# Getting started - -## Installation - -This package uses [semantic versioning 2.0.0](http://semver.org/). - -### Using dep - -```sh -$ dep init -$ dep ensure -add github.com/frictionlessdata/tableschema-go/csv@>=0.1 -``` - - -# Main Features - -## Tabular Data Load - -Have tabular data stored in local files? Remote files? Packages like the [csv](https://godoc.org/github.com/frictionlessdata/tableschema-go/csv) are going to help on loading the data you need and making it ready for processing. - -```go -package main - -import "github.com/frictionlessdata/tableschema-go/csv" - -func main() { - tab, err := csv.NewTable(csv.Remote("myremotetable"), csv.LoadHeaders()) - // Error handling. -} -``` - -Supported physical representations: - -* [CSV](https://godoc.org/github.com/frictionlessdata/tableschema-go/csv) - -You would like to use tableschema-go but the physical representation you use is not listed here? No problem! Please create an issue before start contributing. We will be happy to help you along the way. - -## Schema Inference and Configuration - -Got that new dataset and wants to start getting your hands dirty ASAP? No problems, let the [schema package](https://github.com/frictionlessdata/tableschema-go/tree/master/schema) try to infer -the data types based on the table data. - -```go -package main - -import ( - "github.com/frictionlessdata/tableschema-go/csv" - "github.com/frictionlessdata/tableschema-go/schema" -) - -func main() { - tab, _ := csv.NewTable(csv.Remote("myremotetable"), csv.LoadHeaders()) - sch, _ := schema.Infer(tab) - fmt.Printf("%+v", sch) -} -``` - -> Want to go faster? Please give [InferImplicitCasting](https://godoc.org/github.com/frictionlessdata/tableschema-go/schema#InferImplicitCasting) a try and let us know how it goes. - -There might be cases in which the inferred schema is not correct. One of those cases is when your data use strings like "N/A" to represent missing cells. That would usually make our inferential algorithm think the field is a string. - -When that happens, you can manually perform those last minutes tweaks [Schema](https://godoc.org/github.com/frictionlessdata/tableschema-go/schema#Schema). - -```go - sch.MissingValues = []string{"N/A"} - sch.GetField("ID").Type = schema.IntegerType -``` - -After all that, you could persist your schema to disk: - -```go -sch.SaveToFile("users_schema.json") -``` - -And use the local schema later: - -```go -sch, _ := sch.LoadFromFile("users_schema.json") -``` - -Finally, if your schema is saved remotely, you can also use it: - -```go -sch, _ := schema.LoadRemote("http://myfoobar/users/schema.json") -``` - -## Processing Tabular Data - -Once you have the data, you would like to process using language data types. [schema.CastTable](https://godoc.org/github.com/frictionlessdata/tableschema-go/schema#example-Schema-CastTable) and [schema.CastRow](https://godoc.org/github.com/frictionlessdata/tableschema-go/schema#example-Schema-CastRow) are your friends on this journey. - -```go -package main - -import ( - "github.com/frictionlessdata/tableschema-go/csv" - "github.com/frictionlessdata/tableschema-go/schema" -) - -type user struct { - ID int - Age int - Name string -} - -func main() { - tab, _ := csv.NewTable(csv.FromFile("users.csv"), csv.LoadHeaders()) - sch, _ := schema.Infer(tab) - var users []user - sch.CastTable(tab, &users) - // Users slice contains the table contents properly raw into - // language types. Each row will be a new user appended to the slice. -} -``` - -If you have a lot of data and can no load everything in memory, you can easily iterate trough it: - -```go -... - iter, _ := sch.Iter() - for iter.Next() { - var u user - sch.CastRow(iter.Row(), &u) - // Variable u is now filled with row contents properly raw - // to language types. - } -... -``` - -> Even better if you could do it regardless the physical representation! The [table](https://godoc.org/github.com/frictionlessdata/tableschema-go/table) package declares some interfaces that will help you to achieve this goal: - -* [Table](https://godoc.org/github.com/frictionlessdata/tableschema-go/table#Table) -* [Iterator](https://godoc.org/github.com/frictionlessdata/tableschema-go/table#Iterator) - -### Field - -Class represents field in the schema. - -For example, data values can be castd to native Go types. Decoding a value will check if the value is of the expected type, is in the correct format, and complies with any constraints imposed by a schema. - -```javascript -{ - 'name': 'birthday', - 'type': 'date', - 'format': 'default', - 'constraints': { - 'required': True, - 'minimum': '2015-05-30' - } -} -``` - -The following example will raise exception the passed-in is less than allowed by `minimum` constraints of the field. `Errors` will be returned as well when the user tries to cast values which are not well formatted dates. - -```go -date, err := field.Cast("2014-05-29") -// uh oh, something went wrong -``` - -Values that can't be castd will return an `error`. -Casting a value that doesn't meet the constraints will return an `error`. - -Available types, formats and resultant value of the cast: - -| Type | Formats | Casting result | -| ---- | ------- | -------------- | -| any | default | interface{} | -| object | default | interface{} | -| array | default | []interface{} | -| boolean | default | bool | -| duration | default | time.Time | -| geopoint | default, array, object | [float64, float64] | -| integer | default | int64 | -| number | default | float64 | -| string | default, uri, email, binary | string | -| date | default, any, | time.Time | -| datetime | default, any, | time.Time | -| time | default, any, | time.Time | -| year | default | time.Time | -| yearmonth | default | time.Time | - -## Saving Tabular Data - -Once you're done processing the data, it is time to persist results. As an example, let us assume we have a remote table schema called `summary`, which contains two fields: - -* `Date`: of type [date](https://specs.frictionlessdata.io/table-schema/#date) -* `AverageAge`: of type [number](https://specs.frictionlessdata.io/table-schema/#number) - - -```go -import ( - "github.com/frictionlessdata/tableschema-go/csv" - "github.com/frictionlessdata/tableschema-go/schema" -) - - -type summaryEntry struct { - Date time.Time - AverageAge float64 -} - -func WriteSummary(summary []summaryEntry, path string) { - sch, _ := schema.LoadRemote("http://myfoobar/users/summary/schema.json") - - f, _ := os.Create(path) - defer f.Close() - - w := csv.NewWriter(f) - defer w.Flush() - - w.Write([]string{"Date", "AverageAge"}) - for _, summ := range summary{ - row, _ := sch.UncastRow(summ) - w.Write(row) - } -} -``` - -# API Reference and More Examples - -More detailed documentation about API methods and plenty of examples is available at [https://godoc.org/github.com/frictionlessdata/tableschema-go](https://godoc.org/github.com/frictionlessdata/tableschema-go) - -# Contributing - -Found a problem and would like to fix it? Have that great idea and would love to see it in the repository? - -> Please open an issue before start working - -That could save a lot of time from everyone and we are super happy to answer questions and help you alonge the way. Furthermore, feel free to join [frictionlessdata Gitter chat room](https://gitter.im/frictionlessdata/chat) and ask questions. - -This project follows the [Open Knowledge International coding standards](https://github.com/okfn/coding-standards) - -* Before start coding: - * Fork and pull the latest version of the master branch - * Make sure you have go 1.8+ installed and you're using it - * Make sure you [dep](https://github.com/golang/dep) installed - -* Before sending the PR: - -```sh -$ cd $GOPATH/src/github.com/frictionlessdata/tableschema-go -$ dep ensure -$ go test ./.. -``` - -And make sure your all tests pass. diff --git a/vendor/github.com/frictionlessdata/tableschema-go/csv/iterator_test.go b/vendor/github.com/frictionlessdata/tableschema-go/csv/iterator_test.go deleted file mode 100644 index 9eb352a..0000000 --- a/vendor/github.com/frictionlessdata/tableschema-go/csv/iterator_test.go +++ /dev/null @@ -1,55 +0,0 @@ -package csv - -import ( - "testing" - - "github.com/matryer/is" -) - -type iterTestValue struct { - Name string -} - -const ( - dontSkipHeaders = false - skipHeaders = true -) - -func TestNewIterator(t *testing.T) { - t.Run("EmptyString", func(t *testing.T) { - is := is.New(t) - iter := newIterator(stringReadCloser(""), defaultDialect, dontSkipHeaders) - is.True(!iter.Next()) // more iterations than it should - is.NoErr(iter.Err()) - }) -} - -func TestIterator_Next(t *testing.T) { - t.Run("TwoRows", func(t *testing.T) { - is := is.New(t) - iter := newIterator(stringReadCloser("foo\nbar"), defaultDialect, dontSkipHeaders) - is.True(iter.Next()) // want two more iterations - is.True(iter.Next()) // want one more interation - is.True(!iter.Next()) // more iterations than it should - is.NoErr(iter.Err()) - }) - t.Run("TwoRowsSkipHeaders", func(t *testing.T) { - is := is.New(t) - iter := newIterator(stringReadCloser("name\nbar"), defaultDialect, skipHeaders) - is.True(iter.Next()) // want one interation - is.True(!iter.Next()) // more iterations than it should - is.NoErr(iter.Err()) - }) -} - -func TestIterator_Row(t *testing.T) { - t.Run("OneRow", func(t *testing.T) { - is := is.New(t) - iter := newIterator(stringReadCloser("name"), defaultDialect, dontSkipHeaders) - is.True(iter.Next()) // want one iteration - - got := iter.Row() - want := []string{"name"} - is.Equal(want, got) - }) -} diff --git a/vendor/github.com/frictionlessdata/tableschema-go/csv/table.go b/vendor/github.com/frictionlessdata/tableschema-go/csv/table.go deleted file mode 100644 index b7fe29f..0000000 --- a/vendor/github.com/frictionlessdata/tableschema-go/csv/table.go +++ /dev/null @@ -1,262 +0,0 @@ -package csv - -import ( - "bytes" - "encoding/csv" - "fmt" - "io" - "io/ioutil" - "net/http" - "os" - "strings" - "sync" - "time" - - "github.com/frictionlessdata/tableschema-go/table" -) - -// Table represents a Table backed by a CSV physical representation. -type Table struct { - headers []string - source Source - skipHeaders bool - dialect dialect -} - -// dialect represents CSV dialect configuration options. -// http://frictionlessdata.io/specs/csv-dialect/ -type dialect struct { - // Delimiter specifies the character sequence which should separate fields (aka columns). - delimiter rune - // Specifies how to interpret whitespace which immediately follows a delimiter; - // if false, it means that whitespace immediately after a delimiter should be treated as part of the following field. - skipInitialSpace bool -} - -var defaultDialect = dialect{ - delimiter: ',', - skipInitialSpace: true, -} - -// NewTable creates a table.Table from the CSV table physical representation. -// CreationOpts are executed in the order they are declared. -// If a dialect is not configured via SetDialect, DefautltDialect is used. -func NewTable(source Source, opts ...CreationOpts) (*Table, error) { - t := Table{source: source, dialect: defaultDialect} - for _, opt := range opts { - if err := opt(&t); err != nil { - return nil, err - } - } - return &t, nil -} - -// Iter returns an Iterator to read the table. Iter returns an error -// if the table physical source can not be iterated. -// The iteration process always start at the beginning of the CSV and -// is backed by a new reading. -func (table *Table) Iter() (table.Iterator, error) { - src, err := table.source() - if err != nil { - return nil, err - } - return newIterator(src, table.dialect, table.skipHeaders), nil -} - -// ReadAll reads all rows from the table and return it as strings. -func (table *Table) ReadAll() ([][]string, error) { - var r [][]string - iter, err := table.Iter() - if err != nil { - return nil, err - } - defer iter.Close() - for iter.Next() { - r = append(r, iter.Row()) - } - return r, nil -} - -// Headers returns the headers of the tabular data. -func (table *Table) Headers() []string { - return table.headers -} - -// String returns a string version of the table. -func (table *Table) String() string { - var buf bytes.Buffer - w := csv.NewWriter(&buf) - rows, err := table.ReadAll() - if err != nil { - return "" - } - w.WriteAll(rows) - return buf.String() -} - -func newIterator(source io.ReadCloser, dialect dialect, skipHeaders bool) *csvIterator { - r := csv.NewReader(source) - r.Comma = dialect.delimiter - r.TrimLeadingSpace = dialect.skipInitialSpace - return &csvIterator{ - source: source, - reader: r, - skipHeaders: skipHeaders, - } -} - -type csvIterator struct { - reader *csv.Reader - source io.ReadCloser - - current []string - err error - skipHeaders bool -} - -func (i *csvIterator) Next() bool { - if i.err != nil { - return false - } - var err error - i.current, err = i.reader.Read() - if err != io.EOF { - i.err = err - } - if i.skipHeaders { - i.skipHeaders = false - i.Next() - } - return err == nil -} - -func (i *csvIterator) Row() []string { - return i.current -} - -func (i *csvIterator) Err() error { - return i.err -} - -func (i *csvIterator) Close() error { - return i.source.Close() -} - -// CreationOpts defines functional options for creating Tables. -type CreationOpts func(t *Table) error - -// Source defines a table physical data source. -type Source func() (io.ReadCloser, error) - -// FromFile defines a file-based Source. -func FromFile(path string) Source { - return func() (io.ReadCloser, error) { - f, err := os.Open(path) - if err != nil { - return nil, err - } - return f, nil - } -} - -var ( - httpClient *http.Client - once sync.Once -) - -const remoteFetchTimeoutSecs = 15 - -// Remote fetches the source schema from a remote URL. -func Remote(url string) Source { - return func() (io.ReadCloser, error) { - once.Do(func() { - httpClient = &http.Client{ - Timeout: remoteFetchTimeoutSecs * time.Second, - } - }) - resp, err := httpClient.Get(url) - if err != nil { - return nil, err - } - defer resp.Body.Close() - body, err := ioutil.ReadAll(resp.Body) - return stringReadCloser(string(body)), nil - } -} - -// FromString defines a string-based source. -func FromString(str string) Source { - return func() (io.ReadCloser, error) { - return stringReadCloser(str), nil - } -} - -func stringReadCloser(s string) io.ReadCloser { - return ioutil.NopCloser(strings.NewReader(s)) -} - -func errorSource() Source { - return func() (io.ReadCloser, error) { - return nil, fmt.Errorf("error source") - } -} - -// LoadHeaders uses the first line of the CSV as table headers. -// The header line will be skipped during iteration -func LoadHeaders() CreationOpts { - return func(reader *Table) error { - reader.skipHeaders = false - iter, err := reader.Iter() - if err != nil { - return err - } - if iter.Next() { - reader.headers = iter.Row() - } - reader.skipHeaders = true - return nil - } -} - -// SetHeaders sets the table headers. -func SetHeaders(headers ...string) CreationOpts { - return func(reader *Table) error { - reader.headers = headers - return nil - } -} - -// Delimiter specifies the character sequence which should separate fields (aka columns). -func Delimiter(d rune) CreationOpts { - return func(t *Table) error { - t.dialect.delimiter = d - return nil - } -} - -// ConsiderInitialSpace configures the CSV parser to treat the whitespace immediately after a delimiter as part of the following field. -func ConsiderInitialSpace() CreationOpts { - return func(t *Table) error { - t.dialect.skipInitialSpace = false - return nil - } -} - -func errorOpts(headers ...string) CreationOpts { - return func(_ *Table) error { - return fmt.Errorf("error opts") - } -} - -// NewWriter creates a writer which appends records to a CSV raw file. -// -// As returned by NewWriter, a csv.Writer writes records terminated by a -// newline and uses ',' as the field delimiter. The exported fields can be -// changed to customize the details before the first call to Write or WriteAll. -// -// Comma is the field delimiter. -// -// If UseCRLF is true, the csv.Writer ends each record with \r\n instead of \n. -func NewWriter(w io.Writer) *csv.Writer { - return csv.NewWriter(w) -} diff --git a/vendor/github.com/frictionlessdata/tableschema-go/csv/table_test.go b/vendor/github.com/frictionlessdata/tableschema-go/csv/table_test.go deleted file mode 100644 index 309e303..0000000 --- a/vendor/github.com/frictionlessdata/tableschema-go/csv/table_test.go +++ /dev/null @@ -1,135 +0,0 @@ -package csv - -import ( - "bytes" - "fmt" - "net/http" - "net/http/httptest" - "testing" - - "github.com/matryer/is" -) - -type csvRow struct { - Name string -} - -func ExampleTable_Iter() { - table, _ := NewTable(FromString("\"name\"\nfoo\nbar"), LoadHeaders()) - iter, _ := table.Iter() - defer iter.Close() - for iter.Next() { - fmt.Println(iter.Row()) - } - // Output:[foo] - // [bar] -} - -func ExampleTable_ReadAll() { - table, _ := NewTable(FromString("\"name\"\nfoo\nbar"), LoadHeaders()) - rows, _ := table.ReadAll() - fmt.Print(rows) - // Output:[[foo] [bar]] -} - -func ExampleNewWriter() { - var buf bytes.Buffer - w := NewWriter(&buf) - w.Write([]string{"foo", "bar"}) - w.Flush() - fmt.Println(buf.String()) - // Output:foo,bar -} - -func TestRemote(t *testing.T) { - is := is.New(t) - h := func(w http.ResponseWriter, r *http.Request) { - fmt.Fprintf(w, "\"name\"\nfoo\nbar") - } - ts := httptest.NewServer(http.HandlerFunc(h)) - defer ts.Close() - table, _ := NewTable(Remote(ts.URL), LoadHeaders()) - got, _ := table.ReadAll() - want := [][]string{{"foo"}, {"bar"}} - is.Equal(want, got) - - t.Run("Error", func(t *testing.T) { - is := is.New(t) - _, err := NewTable(Remote("invalidURL"), LoadHeaders()) - is.True(err != nil) - }) -} - -func TestLoadHeaders(t *testing.T) { - t.Run("EmptyString", func(t *testing.T) { - is := is.New(t) - table, err := NewTable(FromString(""), LoadHeaders()) - is.NoErr(err) - is.Equal(len(table.Headers()), 0) - }) - t.Run("SimpleCase", func(t *testing.T) { - is := is.New(t) - in := `"name" -"bar"` - table, err := NewTable(FromString(in), LoadHeaders()) - is.NoErr(err) - - want := []string{"name"} - is.Equal(want, table.Headers()) - - iter, _ := table.Iter() - iter.Next() - want = []string{"bar"} - is.Equal(want, iter.Row()) - is.True(!iter.Next()) - }) -} - -func TestNewTable(t *testing.T) { - t.Run("ErrorOpts", func(t *testing.T) { - is := is.New(t) - table, err := NewTable(FromString(""), errorOpts()) - is.True(table == nil) - is.True(err != nil) - }) - t.Run("ErrorSource", func(t *testing.T) { - is := is.New(t) - _, err := NewTable(errorSource(), LoadHeaders()) - is.True(err != nil) - }) -} - -func TestSetHeaders(t *testing.T) { - is := is.New(t) - in := "Foo" - table, err := NewTable(FromString(in), SetHeaders("name")) - is.NoErr(err) - want := []string{"name"} - is.Equal(want, table.Headers()) - - iter, _ := table.Iter() - iter.Next() - want = []string{"Foo"} - is.Equal(want, iter.Row()) - is.True(!iter.Next()) -} - -func TestDelimiter(t *testing.T) { - is := is.New(t) - in := "Foo;Bar" - table, err := NewTable(FromString(in), Delimiter(';')) - is.NoErr(err) - contents, err := table.ReadAll() - is.NoErr(err) - is.Equal(contents, [][]string{{"Foo", "Bar"}}) -} - -func TestConsiderInitialSpace(t *testing.T) { - is := is.New(t) - in := " Foo" - table, err := NewTable(FromString(in), ConsiderInitialSpace()) - is.NoErr(err) - contents, err := table.ReadAll() - is.NoErr(err) - is.Equal(contents, [][]string{{" Foo"}}) -} diff --git a/vendor/github.com/frictionlessdata/tableschema-go/examples/infer/data_infer_utf8.csv b/vendor/github.com/frictionlessdata/tableschema-go/examples/infer/data_infer_utf8.csv deleted file mode 100644 index 385002e..0000000 --- a/vendor/github.com/frictionlessdata/tableschema-go/examples/infer/data_infer_utf8.csv +++ /dev/null @@ -1,5 +0,0 @@ -1,39,Paul -2,23,Jimmy -3,36,Jane -4,28,Judy -5,37,Iñtërnâtiônàlizætiøn \ No newline at end of file diff --git a/vendor/github.com/frictionlessdata/tableschema-go/examples/infer/main.go b/vendor/github.com/frictionlessdata/tableschema-go/examples/infer/main.go deleted file mode 100644 index 7a3049a..0000000 --- a/vendor/github.com/frictionlessdata/tableschema-go/examples/infer/main.go +++ /dev/null @@ -1,34 +0,0 @@ -package main - -import ( - "fmt" - - "github.com/frictionlessdata/tableschema-go/csv" - "github.com/frictionlessdata/tableschema-go/schema" -) - -type user struct { - ID int - Age int - Name string -} - -func main() { - tab, err := csv.NewTable(csv.FromFile("data_infer_utf8.csv"), csv.SetHeaders("ID", "Age", "Name")) - if err != nil { - panic(err) - } - fmt.Println("## Raw Table ##") - fmt.Println(tab) - sch, err := schema.Infer(tab) - if err != nil { - panic(err) - } - - fmt.Println("## Schema ##") - fmt.Println(sch) - var users []user - sch.CastTable(tab, &users) - - fmt.Printf("\n## Cast Table ##\n%+v\n", users) -} diff --git a/vendor/github.com/frictionlessdata/tableschema-go/examples/validate/capital.csv b/vendor/github.com/frictionlessdata/tableschema-go/examples/validate/capital.csv deleted file mode 100644 index b45c39d..0000000 --- a/vendor/github.com/frictionlessdata/tableschema-go/examples/validate/capital.csv +++ /dev/null @@ -1,5 +0,0 @@ -id,capital,url -1,39.00,http://www.test.com -2,23.00,http://www.test.de -3,36.00,http://www.test.uk -4,28.00,http://www.test.co.il \ No newline at end of file diff --git a/vendor/github.com/frictionlessdata/tableschema-go/examples/validate/main.go b/vendor/github.com/frictionlessdata/tableschema-go/examples/validate/main.go deleted file mode 100644 index f5049c6..0000000 --- a/vendor/github.com/frictionlessdata/tableschema-go/examples/validate/main.go +++ /dev/null @@ -1,60 +0,0 @@ -package main - -import ( - "log" - - "github.com/frictionlessdata/tableschema-go/csv" - "github.com/frictionlessdata/tableschema-go/schema" -) - -// Example of how to read, validate and change a schema. -func main() { - // Reading schem. - capitalSchema, err := schema.LoadFromFile("schema.json") - if err != nil { - log.Fatal(err) - } - // Validate schema. - if err := capitalSchema.Validate(); err != nil { - log.Fatal(err) - } - - // Printing schema fields names. - log.Println("Fields:") - for i, f := range capitalSchema.Fields { - log.Printf("%d - %s\n", i, f.Name) - } - - // Working with schema fields. - if capitalSchema.HasField("Capital") { - log.Println("Field capital exists in schema") - } else { - log.Fatalf("Schema must have the field capital") - } - field, _ := capitalSchema.GetField("URL") - if field.TestString("http://new.url.com") { - value, err := field.Cast("http://new.url.com") - log.Printf("URL unmarshal to value: %v\n", value) - if err != nil { - log.Fatalf("Error casting value: %q", err) - } - } else { - log.Fatalf("Value http://new.url.com must fit in field capital.") - } - - // Dealing with tabular data associated with the schema. - table, err := csv.NewTable(csv.FromFile("capital.csv"), csv.LoadHeaders()) - capitalRow := struct { - ID int - Capital float64 - URL string - }{} - - iter, _ := table.Iter() - for iter.Next() { - if err := capitalSchema.CastRow(iter.Row(), &capitalRow); err != nil { - log.Fatalf("Couldn't unmarshal row:%v err:%q", iter.Row(), err) - } - log.Printf("Cast Row: %+v\n", capitalRow) - } -} diff --git a/vendor/github.com/frictionlessdata/tableschema-go/examples/validate/schema.json b/vendor/github.com/frictionlessdata/tableschema-go/examples/validate/schema.json deleted file mode 100644 index 2dcfd2e..0000000 --- a/vendor/github.com/frictionlessdata/tableschema-go/examples/validate/schema.json +++ /dev/null @@ -1,23 +0,0 @@ -{ - "fields": [ - { - "name": "ID", - "title": "", - "description": "", - "type": "integer", - "format": "default" - }, - { - "name": "Capital", - "title": "", - "description": "", - "type": "number" - }, - { - "name": "URL", - "title": "", - "description": "", - "type": "string" - } - ] -} \ No newline at end of file diff --git a/vendor/github.com/frictionlessdata/tableschema-go/schema/any.go b/vendor/github.com/frictionlessdata/tableschema-go/schema/any.go deleted file mode 100644 index 1872308..0000000 --- a/vendor/github.com/frictionlessdata/tableschema-go/schema/any.go +++ /dev/null @@ -1,11 +0,0 @@ -package schema - -import "fmt" - -func castAny(value interface{}) (interface{}, error) { - return value, nil -} - -func uncastAny(value interface{}) (string, error) { - return fmt.Sprintf("%v", value), nil -} diff --git a/vendor/github.com/frictionlessdata/tableschema-go/schema/any_test.go b/vendor/github.com/frictionlessdata/tableschema-go/schema/any_test.go deleted file mode 100644 index bbc2a65..0000000 --- a/vendor/github.com/frictionlessdata/tableschema-go/schema/any_test.go +++ /dev/null @@ -1,21 +0,0 @@ -package schema - -import ( - "testing" - - "github.com/matryer/is" -) - -func TestCastAny(t *testing.T) { - is := is.New(t) - got, err := castAny("foo") - is.NoErr(err) - is.Equal("foo", got) -} - -func TestUncastAny(t *testing.T) { - is := is.New(t) - got, err := uncastAny(10) - is.NoErr(err) - is.Equal("10", got) -} diff --git a/vendor/github.com/frictionlessdata/tableschema-go/schema/array.go b/vendor/github.com/frictionlessdata/tableschema-go/schema/array.go deleted file mode 100644 index d01bfd8..0000000 --- a/vendor/github.com/frictionlessdata/tableschema-go/schema/array.go +++ /dev/null @@ -1,18 +0,0 @@ -package schema - -import ( - "encoding/json" - "fmt" -) - -func castArray(value string) (interface{}, error) { - var obj interface{} - if err := json.Unmarshal([]byte(value), &obj); err != nil { - return nil, err - } - arr, ok := obj.([]interface{}) - if !ok { - return nil, fmt.Errorf("%s is not an JSON array", value) - } - return arr, nil -} diff --git a/vendor/github.com/frictionlessdata/tableschema-go/schema/boolean.go b/vendor/github.com/frictionlessdata/tableschema-go/schema/boolean.go deleted file mode 100644 index cc19c9b..0000000 --- a/vendor/github.com/frictionlessdata/tableschema-go/schema/boolean.go +++ /dev/null @@ -1,39 +0,0 @@ -package schema - -import ( - "fmt" - "reflect" -) - -func castBoolean(value string, trueValues, falseValues []string) (bool, error) { - for _, v := range trueValues { - if value == v { - return true, nil - } - } - for _, v := range falseValues { - if value == v { - return false, nil - } - } - return false, fmt.Errorf("invalid boolean value:%s", value) -} - -func uncastBoolean(value interface{}, trueValues, falseValues []string) (string, error) { - switch value.(type) { - case bool: - return fmt.Sprintf("%v", value), nil - case string: - for _, v := range trueValues { - if value == v { - return value.(string), nil - } - } - for _, v := range falseValues { - if value == v { - return value.(string), nil - } - } - } - return "", fmt.Errorf("invalid boolean - value:\"%v\" type:%v", value, reflect.ValueOf(value).Type()) -} diff --git a/vendor/github.com/frictionlessdata/tableschema-go/schema/boolean_test.go b/vendor/github.com/frictionlessdata/tableschema-go/schema/boolean_test.go deleted file mode 100644 index deeced2..0000000 --- a/vendor/github.com/frictionlessdata/tableschema-go/schema/boolean_test.go +++ /dev/null @@ -1,78 +0,0 @@ -package schema - -import ( - "testing" - - "github.com/matryer/is" -) - -func TestCastBoolean(t *testing.T) { - data := []struct { - Desc string - TrueValues []string - FalseValues []string - Value string - Expected bool - }{ - {"simple true value", []string{"1"}, []string{"0"}, "1", true}, - {"simple false value", []string{"1"}, []string{"0"}, "0", false}, - {"duplicate value, true wins", []string{"1"}, []string{"1"}, "1", true}, - } - for _, d := range data { - t.Run(d.Desc, func(t *testing.T) { - is := is.New(t) - b, err := castBoolean(d.Value, d.TrueValues, d.FalseValues) - is.NoErr(err) - is.Equal(b, d.Expected) - }) - } -} - -func TestCastBoolean_Error(t *testing.T) { - is := is.New(t) - _, err := castBoolean("foo", defaultTrueValues, defaultFalseValues) - is.True(err != nil) -} - -func TestUncastBoolean(t *testing.T) { - t.Run("Success", func(t *testing.T) { - data := []struct { - desc string - value interface{} - want string - trueValues []string - falseValues []string - }{ - {"True", true, "true", []string{}, []string{}}, - {"False", false, "false", []string{}, []string{}}, - {"TrueFromTrueValues", "0", "0", []string{"0"}, []string{}}, - {"FalseFromFalseValues", "1", "1", []string{}, []string{"1"}}, - } - for _, d := range data { - t.Run(d.desc, func(t *testing.T) { - is := is.New(t) - got, err := uncastBoolean(d.value, d.trueValues, d.falseValues) - is.NoErr(err) - is.Equal(d.want, got) - }) - } - }) - t.Run("Error", func(t *testing.T) { - data := []struct { - desc string - value interface{} - trueValues []string - falseValues []string - }{ - {"InvalidType", 10, []string{}, []string{}}, - {"NotInTrueOrFalseValues", "1", []string{}, []string{}}, - } - for _, d := range data { - t.Run(d.desc, func(t *testing.T) { - is := is.New(t) - _, err := uncastBoolean(d.value, d.trueValues, d.falseValues) - is.True(err != nil) - }) - } - }) -} diff --git a/vendor/github.com/frictionlessdata/tableschema-go/schema/date.go b/vendor/github.com/frictionlessdata/tableschema-go/schema/date.go deleted file mode 100644 index 7aed3e6..0000000 --- a/vendor/github.com/frictionlessdata/tableschema-go/schema/date.go +++ /dev/null @@ -1,28 +0,0 @@ -package schema - -import "time" - -func castDate(format, value string, c Constraints) (time.Time, error) { - y, err := castDateWithoutChecks(format, value) - if err != nil { - return y, err - } - var max, min time.Time - if c.Maximum != "" { - max, err = castDateWithoutChecks(format, c.Maximum) - if err != nil { - return max, err - } - } - if c.Minimum != "" { - min, err = castDateWithoutChecks(format, c.Minimum) - if err != nil { - return min, err - } - } - return checkConstraints(y, max, min, DateType) -} - -func castDateWithoutChecks(format, value string) (time.Time, error) { - return castDefaultOrCustomTime("2006-01-02", format, value) -} diff --git a/vendor/github.com/frictionlessdata/tableschema-go/schema/date_test.go b/vendor/github.com/frictionlessdata/tableschema-go/schema/date_test.go deleted file mode 100644 index 1fd4a30..0000000 --- a/vendor/github.com/frictionlessdata/tableschema-go/schema/date_test.go +++ /dev/null @@ -1,40 +0,0 @@ -package schema - -import ( - "testing" - - "github.com/matryer/is" -) - -func TestCastDate(t *testing.T) { - t.Run("ValidMaximum", func(t *testing.T) { - is := is.New(t) - _, err := castDate("2006-01-02", "2006-01-02", Constraints{Maximum: "2007-01-02"}) - is.NoErr(err) - }) - t.Run("ValidMinimum", func(t *testing.T) { - is := is.New(t) - _, err := castDate("2006-01-02", "2007-01-02", Constraints{Minimum: "2006-01-02"}) - is.NoErr(err) - }) - t.Run("Error", func(t *testing.T) { - data := []struct { - desc string - date string - constraints Constraints - }{ - {"InvalidDate", "foo", Constraints{}}, - {"DateBiggerThanMaximum", "2006-01-02", Constraints{Maximum: "2005-01-02"}}, - {"InvalidMaximum", "2006-01-02", Constraints{Maximum: "boo"}}, - {"DateSmallerThanMinimum", "2005-01-02", Constraints{Minimum: "2006-01-02"}}, - {"InvalidMinimum", "2006-01-02", Constraints{Minimum: "boo"}}, - } - for _, d := range data { - t.Run(d.desc, func(t *testing.T) { - is := is.New(t) - _, err := castDate("2006-01-02", d.date, d.constraints) - is.True(err != nil) - }) - } - }) -} diff --git a/vendor/github.com/frictionlessdata/tableschema-go/schema/datetime.go b/vendor/github.com/frictionlessdata/tableschema-go/schema/datetime.go deleted file mode 100644 index d9c49e9..0000000 --- a/vendor/github.com/frictionlessdata/tableschema-go/schema/datetime.go +++ /dev/null @@ -1,139 +0,0 @@ -package schema - -import ( - "fmt" - "strings" - "time" -) - -// Go has a different date formatting style. Converting to the one -// used in https://specs.frictionlessdata.io/table-schema/#date -// https://docs.python.org/2/library/datetime.html#strftime-strptime-behavior -var strftimeToGoConversionTable = map[string]string{ - "%d": "02", - "%-d": "2", - "%B": "January", - "%b": "Jan", - "%h": "Jan", - "%m": "01", - "%_m": " 1", - "%-m": "1", - "%Y": "2006", - "%y": "06", - "%H": "15", - "%I": "03", - "%M": "04", - "%S": "05", - "%f": "999999", - "%z": "Z0700", - "%:z": "Z07:00", - "%Z": "MST", - "%p": "PM", -} - -func castYearMonth(value string, c Constraints) (time.Time, error) { - y, err := castYearMonthWithoutChecks(value) - if err != nil { - return y, err - } - var max, min time.Time - if c.Maximum != "" { - max, err = castYearMonthWithoutChecks(c.Maximum) - if err != nil { - return y, err - } - } - if c.Minimum != "" { - min, err = castYearMonthWithoutChecks(c.Minimum) - if err != nil { - return y, err - } - } - return checkConstraints(y, max, min, YearMonthType) -} - -func castYearMonthWithoutChecks(value string) (time.Time, error) { - return time.Parse("2006-01", value) -} - -func castYearWithoutChecks(value string) (time.Time, error) { - return time.Parse("2006", value) -} - -func castYear(value string, c Constraints) (time.Time, error) { - y, err := castYearWithoutChecks(value) - if err != nil { - return y, err - } - var max, min time.Time - if c.Maximum != "" { - max, err = castYearWithoutChecks(c.Maximum) - if err != nil { - return y, err - } - } - if c.Minimum != "" { - min, err = castYearWithoutChecks(c.Minimum) - if err != nil { - return y, err - } - } - return checkConstraints(y, max, min, YearType) -} - -func castDateTime(value string, c Constraints) (time.Time, error) { - dt, err := castDateTimeWithoutChecks(value) - if err != nil { - return dt, err - } - var max, min time.Time - if c.Maximum != "" { - max, err = castDateTimeWithoutChecks(c.Maximum) - if err != nil { - return dt, err - } - } - if c.Minimum != "" { - min, err = castDateTimeWithoutChecks(c.Minimum) - if err != nil { - return dt, err - } - } - return checkConstraints(dt, max, min, DateTimeType) -} - -func castDateTimeWithoutChecks(value string) (time.Time, error) { - return time.Parse(time.RFC3339, value) -} - -func checkConstraints(v, max, min time.Time, t string) (time.Time, error) { - if !max.IsZero() && v.After(max) { - return v, fmt.Errorf("constraint check error: %s:%v > maximum:%v", t, v, max) - } - if !min.IsZero() && v.Before(min) { - return v, fmt.Errorf("constraint check error: %s:%v < minimum:%v", t, v, min) - } - return v, nil -} - -func castDefaultOrCustomTime(defaultFormat, format, value string) (time.Time, error) { - switch format { - case "", defaultFieldFormat: - t, err := time.Parse(defaultFormat, value) - if err != nil { - return t, err - } - return t.In(time.UTC), nil - case AnyDateFormat: - return time.Unix(0, 0), fmt.Errorf("any date format not yet supported. Please file an issue at github.com/frictionlessdata/tableschema-go") - } - goFormat := format - for f, s := range strftimeToGoConversionTable { - goFormat = strings.Replace(goFormat, f, s, -1) - } - t, err := time.Parse(goFormat, value) - if err != nil { - return t, err - } - return t.In(time.UTC), nil -} diff --git a/vendor/github.com/frictionlessdata/tableschema-go/schema/datetime_test.go b/vendor/github.com/frictionlessdata/tableschema-go/schema/datetime_test.go deleted file mode 100644 index 8d4e714..0000000 --- a/vendor/github.com/frictionlessdata/tableschema-go/schema/datetime_test.go +++ /dev/null @@ -1,126 +0,0 @@ -package schema - -import ( - "testing" - - "github.com/matryer/is" -) - -func TestCastDatetime(t *testing.T) { - t.Run("ValidMaximum", func(t *testing.T) { - is := is.New(t) - _, err := castDateTime("2013-01-24T22:01:00+07:00", Constraints{Maximum: "2014-01-24T22:01:00Z"}) - is.NoErr(err) - }) - t.Run("ValidMinimum", func(t *testing.T) { - is := is.New(t) - _, err := castDateTime("2013-01-24T22:01:00Z", Constraints{Minimum: "2012-01-24T22:01:00Z"}) - is.NoErr(err) - }) - t.Run("Error", func(t *testing.T) { - data := []struct { - desc string - datetime string - constraints Constraints - }{ - { - "InvalidDateTime", - "foo", - Constraints{}, - }, - { - "DateTimeBiggerThanMaximum", - "2013-01-24T22:01:00Z", - Constraints{Maximum: "2013-01-24T01:01:00Z"}, - }, - { - "InvalidMaximum", - "2013-01-24T22:01:00Z", - Constraints{Maximum: "boo"}, - }, - { - "DateTimeSmallerThanMinimum", - "2013-01-24T22:01:00Z", - Constraints{Minimum: "2013-01-24T22:01:01Z"}, - }, - { - "InvalidMinimum", - "2013-01-24T22:01:00Z", - Constraints{Minimum: "boo"}, - }, - } - for _, d := range data { - t.Run(d.desc, func(t *testing.T) { - is := is.New(t) - _, err := castDateTime(d.datetime, d.constraints) - is.True(err != nil) - }) - } - }) -} - -func TestCastYear(t *testing.T) { - t.Run("ValidMaximum", func(t *testing.T) { - is := is.New(t) - _, err := castYear("2006", Constraints{Maximum: "2007"}) - is.NoErr(err) - }) - t.Run("ValidMinimum", func(t *testing.T) { - is := is.New(t) - _, err := castYear("2007", Constraints{Minimum: "2006"}) - is.NoErr(err) - }) - t.Run("Error", func(t *testing.T) { - data := []struct { - desc string - year string - constraints Constraints - }{ - {"InvalidYear", "foo", Constraints{}}, - {"YearBiggerThanMaximum", "2006", Constraints{Maximum: "2005"}}, - {"InvalidMaximum", "2005", Constraints{Maximum: "boo"}}, - {"YearSmallerThanMinimum", "2005", Constraints{Minimum: "2006"}}, - {"InvalidMinimum", "2005", Constraints{Minimum: "boo"}}, - } - for _, d := range data { - t.Run(d.desc, func(t *testing.T) { - is := is.New(t) - _, err := castYear(d.year, d.constraints) - is.True(err != nil) - }) - } - }) -} - -func TestCastYearMonth(t *testing.T) { - t.Run("ValidMaximum", func(t *testing.T) { - is := is.New(t) - _, err := castYearMonth("2006-02", Constraints{Maximum: "2006-03"}) - is.NoErr(err) - }) - t.Run("ValidMinimum", func(t *testing.T) { - is := is.New(t) - _, err := castYearMonth("2006-03", Constraints{Minimum: "2006-02"}) - is.NoErr(err) - }) - t.Run("Error", func(t *testing.T) { - data := []struct { - desc string - year string - constraints Constraints - }{ - {"InvalidYear", "foo", Constraints{}}, - {"YearBiggerThanMaximum", "2006-02", Constraints{Maximum: "2006-01"}}, - {"InvalidMaximum", "2005-02", Constraints{Maximum: "boo"}}, - {"YearSmallerThanMinimum", "2006-02", Constraints{Minimum: "2006-03"}}, - {"InvalidMinimum", "2005-02", Constraints{Minimum: "boo"}}, - } - for _, d := range data { - t.Run(d.desc, func(t *testing.T) { - is := is.New(t) - _, err := castYearMonth(d.year, d.constraints) - is.True(err != nil) - }) - } - }) -} diff --git a/vendor/github.com/frictionlessdata/tableschema-go/schema/duration.go b/vendor/github.com/frictionlessdata/tableschema-go/schema/duration.go deleted file mode 100644 index be11f59..0000000 --- a/vendor/github.com/frictionlessdata/tableschema-go/schema/duration.go +++ /dev/null @@ -1,65 +0,0 @@ -package schema - -import ( - "fmt" - "reflect" - "regexp" - "strconv" - "strings" - "time" -) - -var durationRegexp = regexp.MustCompile( - `P(?P\d+Y)?(?P\d+M)?(?P\d+D)?T?(?P\d+H)?(?P\d+M)?(?P\d+\.?\d*S)?`) - -const ( - hoursInYear = time.Duration(24*360) * time.Hour - hoursInMonth = time.Duration(24*30) * time.Hour - hoursInDay = time.Duration(24) * time.Hour -) - -func castDuration(value string) (time.Duration, error) { - matches := durationRegexp.FindStringSubmatch(value) - if len(matches) == 0 { - return 0, fmt.Errorf("Invalid duration:\"%s\"", value) - } - years := parseIntDuration(matches[1], hoursInYear) - months := parseIntDuration(matches[2], hoursInMonth) - days := parseIntDuration(matches[3], hoursInDay) - hours := parseIntDuration(matches[4], time.Hour) - minutes := parseIntDuration(matches[5], time.Minute) - seconds := parseSeconds(matches[6]) - return years + months + days + hours + minutes + seconds, nil -} - -func parseIntDuration(v string, multiplier time.Duration) time.Duration { - if len(v) == 0 { - return 0 - } - // Ignoring error here because only digits could come from the regular expression. - d, _ := strconv.Atoi(v[0 : len(v)-1]) - return time.Duration(d) * multiplier -} - -func parseSeconds(v string) time.Duration { - if len(v) == 0 { - return 0 - } - // Ignoring error here because only valid arbitrary precision floats could come from the regular expression. - d, _ := strconv.ParseFloat(v[0:len(v)-1], 64) - return time.Duration(d * 10e8) -} - -func uncastDuration(in interface{}) (string, error) { - v, ok := in.(time.Duration) - if !ok { - return "", fmt.Errorf("invalid duration - value:%v type:%v", in, reflect.ValueOf(in).Type()) - } - y := v / hoursInYear - r := v % hoursInYear - m := r / hoursInMonth - r = r % hoursInMonth - d := r / hoursInDay - r = r % hoursInDay - return strings.ToUpper(fmt.Sprintf("P%dY%dM%dDT%s", y, m, d, r.String())), nil -} diff --git a/vendor/github.com/frictionlessdata/tableschema-go/schema/duration_test.go b/vendor/github.com/frictionlessdata/tableschema-go/schema/duration_test.go deleted file mode 100644 index 2d53b9b..0000000 --- a/vendor/github.com/frictionlessdata/tableschema-go/schema/duration_test.go +++ /dev/null @@ -1,85 +0,0 @@ -package schema - -import ( - "testing" - "time" - - "github.com/matryer/is" -) - -func TestCastDuration_Success(t *testing.T) { - data := []struct { - desc string - value string - want time.Duration - }{ - {"OnlyP", "P", time.Duration(0)}, - {"OnlyHour", "P2H", time.Duration(2) * time.Hour}, - {"SecondsWithDecimal", "P22.519S", 22519 * time.Millisecond}, - {"HourDefaultZero", "PH", time.Duration(0) * time.Hour}, - {"OnlyPeriod", "P3Y6M4D", 3*hoursInYear + 6*hoursInMonth + 4*hoursInDay}, - {"OnlyTime", "PT12H30M5S", 12*time.Hour + 30*time.Minute + 5*time.Second}, - {"Complex", "P3Y6M4DT12H30M5S", 3*hoursInYear + 6*hoursInMonth + 4*hoursInDay + 12*time.Hour + 30*time.Minute + 5*time.Second}, - {"2Years", "P2Y", (2 * 360 * 24) * time.Hour}, - {"StringFieldsAreIgnored", "PfooHdddS", time.Duration(0)}, - } - for _, d := range data { - t.Run(d.desc, func(t *testing.T) { - is := is.New(t) - got, err := castDuration(d.value) - is.NoErr(err) - is.Equal(got, d.want) - }) - } -} - -func TestCastDuration_Error(t *testing.T) { - data := []struct { - desc string - value string - }{ - {"WrongStartChar", "C2H"}, - } - for _, d := range data { - t.Run(d.desc, func(t *testing.T) { - is := is.New(t) - _, err := castDuration(d.value) - is.True(err != nil) - }) - } -} - -func TestUncastDuration(t *testing.T) { - t.Run("Success", func(t *testing.T) { - data := []struct { - desc string - value time.Duration - want string - }{ - {"1Year", 1*hoursInYear + 1*hoursInMonth + 1*hoursInDay + 1*time.Hour + 1*time.Minute + 500*time.Millisecond, "P1Y1M1DT1H1M0.5S"}, - } - for _, d := range data { - t.Run(d.desc, func(t *testing.T) { - is := is.New(t) - got, err := uncastDuration(d.value) - is.NoErr(err) - is.Equal(d.want, got) - }) - } - }) - t.Run("Error", func(t *testing.T) { - data := []struct { - desc string - value interface{} - }{ - {"InvalidType", 10}, - } - for _, d := range data { - t.Run(d.desc, func(t *testing.T) { - is := is.New(t) - _, err := uncastDuration(d.value) - is.True(err != nil) - }) - } - }) -} diff --git a/vendor/github.com/frictionlessdata/tableschema-go/schema/field.go b/vendor/github.com/frictionlessdata/tableschema-go/schema/field.go deleted file mode 100644 index 37257cb..0000000 --- a/vendor/github.com/frictionlessdata/tableschema-go/schema/field.go +++ /dev/null @@ -1,268 +0,0 @@ -package schema - -import ( - "encoding/json" - "fmt" - "reflect" - "regexp" -) - -// Default for schema fields. -const ( - defaultFieldType = "string" - defaultFieldFormat = "default" -) - -// Default schema variables. -var ( - defaultTrueValues = []string{"yes", "y", "true", "t", "1"} - defaultFalseValues = []string{"no", "n", "false", "f", "0"} - defaultDecimalChar = "." - defaultGroupChar = "," - defaultBareNumber = true -) - -// Field types. -const ( - IntegerType = "integer" - StringType = "string" - BooleanType = "boolean" - NumberType = "number" - DateType = "date" - ObjectType = "object" - ArrayType = "array" - DateTimeType = "datetime" - TimeType = "time" - YearMonthType = "yearmonth" - YearType = "year" - DurationType = "duration" - GeoPointType = "geopoint" - AnyType = "any" -) - -// Formats. -const ( - AnyDateFormat = "any" -) - -// Constraints can be used by consumers to list constraints for validating -// field values. -type Constraints struct { - // Required indicates whether this field is allowed to be null. - // Schema.MissingValues define how the string representation can - // represent null values. - Required bool `json:"required,omitempty"` - - // Unique indicates whether this field is allowed to have duplicates. - // This constrain is only relevant for Schema.CastTable - Unique bool `json:"unique,omitempty"` - - Maximum string `json:"maximum,omitempty"` - Minimum string `json:"minimum,omitempty"` - MinLength int `json:"minLength,omitempty"` - MaxLength int `json:"maxLength,omitempty"` - Pattern string `json:"pattern,omitempty"` - compiledPattern *regexp.Regexp - - // Enum indicates that the value of the field must exactly match a value in the enum array. - // The values of the fields could need encoding, depending on the type. - // It applies to all field types. - Enum []interface{} `json:"enum,omitempty"` - // rawEnum keeps the raw version of the enum objects, to make validation faster and easier. - rawEnum map[string]struct{} -} - -// Field describes a single field in the table schema. -// More: https://specs.frictionlessdata.io/table-schema/#field-descriptors -type Field struct { - // Name of the field. It is mandatory and shuold correspond to the name of field/column in the data file (if it has a name). - Name string `json:"name"` - Type string `json:"type,omitempty"` - Format string `json:"format,omitempty"` - // A human readable label or title for the field. - Title string `json:"title,omitempty"` - // A description for this field e.g. "The recipient of the funds" - Description string `json:"description,omitempty"` - - // Boolean properties. Define set of the values that represent true and false, respectively. - // https://specs.frictionlessdata.io/table-schema/#boolean - TrueValues []string `json:"trueValues,omitempty"` - FalseValues []string `json:"falseValues,omitempty"` - - // Number/Integer properties. - - // A string whose value is used to represent a decimal point within the number. The default value is ".". - DecimalChar string `json:"decimalChar,omitempty"` - // A string whose value is used to group digits within the number. The default value is null. A common value is "," e.g. "100,000". - GroupChar string `json:"groupChar,omitempty"` - // If true the physical contents of this field must follow the formatting constraints already set out. - // If false the contents of this field may contain leading and/or trailing non-numeric characters which - // are going to be stripped. Default value is true: - BareNumber bool `json:"bareNumber,omitempty"` - - // MissingValues is a map which dictates which string values should be treated as null - // values. - MissingValues map[string]struct{} `json:"-"` - - // Constraints can be used by consumers to list constraints for validating - // field values. - Constraints Constraints -} - -// UnmarshalJSON sets *f to a copy of data. It will respect the default values -// described at: https://specs.frictionlessdata.io/table-schema/ -func (f *Field) UnmarshalJSON(data []byte) error { - // This is neded so it does not call UnmarshalJSON from recursively. - type fieldAlias Field - u := &fieldAlias{ - Type: defaultFieldType, - Format: defaultFieldFormat, - TrueValues: defaultTrueValues, - FalseValues: defaultFalseValues, - DecimalChar: defaultDecimalChar, - GroupChar: defaultGroupChar, - BareNumber: defaultBareNumber, - } - if err := json.Unmarshal(data, u); err != nil { - return err - } - *f = Field(*u) - // Transformation/Validation that should be done at creation time. - if f.Constraints.Pattern != "" { - p, err := regexp.Compile(f.Constraints.Pattern) - if err != nil { - return err - } - f.Constraints.compiledPattern = p - } - if f.Constraints.Enum != nil { - f.Constraints.rawEnum = make(map[string]struct{}) - for i := range f.Constraints.Enum { - e, err := f.Uncast(f.Constraints.Enum[i]) - if err != nil { - return err - } - f.Constraints.rawEnum[e] = struct{}{} - } - } - return nil -} - -// Cast casts the passed-in string against field type. Returns an error -// if the value can not be cast or any field constraint can not be satisfied. -func (f *Field) Cast(value string) (interface{}, error) { - if f.Constraints.Required { - _, ok := f.MissingValues[value] - if ok { - return nil, fmt.Errorf("%s is required", f.Name) - } - } - var castd interface{} - var err error - switch f.Type { - case IntegerType: - castd, err = castInt(f.BareNumber, value, f.Constraints) - case StringType: - castd, err = castString(f.Format, value, f.Constraints) - case BooleanType: - castd, err = castBoolean(value, f.TrueValues, f.FalseValues) - case NumberType: - castd, err = castNumber(f.DecimalChar, f.GroupChar, f.BareNumber, value, f.Constraints) - case DateType: - castd, err = castDate(f.Format, value, f.Constraints) - case ObjectType: - castd, err = castObject(value) - case ArrayType: - castd, err = castArray(value) - case TimeType: - castd, err = castTime(f.Format, value, f.Constraints) - case YearMonthType: - castd, err = castYearMonth(value, f.Constraints) - case YearType: - castd, err = castYear(value, f.Constraints) - case DateTimeType: - castd, err = castDateTime(value, f.Constraints) - case DurationType: - castd, err = castDuration(value) - case GeoPointType: - castd, err = castGeoPoint(f.Format, value) - case AnyType: - castd, err = castAny(value) - } - if err != nil { - return nil, err - } - if castd == nil { - return nil, fmt.Errorf("invalid field type: %s", f.Type) - } - if len(f.Constraints.rawEnum) > 0 { - rawValue, err := f.Uncast(castd) - if err != nil { - return nil, err - } - if _, ok := f.Constraints.rawEnum[rawValue]; !ok { - return nil, fmt.Errorf("castd value:%s does not match enum constraints:%v", rawValue, f.Constraints.rawEnum) - } - } - return castd, nil -} - -// Uncast uncasts the passed-in value into a string. It returns an error if the -// the type of the passed-in value can not be converted to field type. -func (f *Field) Uncast(in interface{}) (string, error) { - // This indirect avoids the need to custom-case pointer types. - inValue := reflect.Indirect(reflect.ValueOf(in)) - inInterface := inValue.Interface() - ok := false - switch f.Type { - case IntegerType: - var a int64 - ok = reflect.TypeOf(inInterface).ConvertibleTo(reflect.ValueOf(a).Type()) - if ok { - inInterface = inValue.Convert(reflect.ValueOf(a).Type()).Interface() - } - case NumberType: - var a float64 - ok = reflect.TypeOf(inInterface).ConvertibleTo(reflect.ValueOf(a).Type()) - if ok { - inInterface = inValue.Convert(reflect.ValueOf(a).Type()).Interface() - } - case BooleanType: - return uncastBoolean(in, f.TrueValues, f.FalseValues) - case DurationType: - return uncastDuration(inInterface) - case GeoPointType: - return uncastGeoPoint(f.Format, in) - case DateType, DateTimeType, TimeType, YearMonthType, YearType: - return uncastTime(inInterface) - case ObjectType: - return uncastObject(inInterface) - case StringType: - _, ok = inInterface.(string) - case ArrayType: - ok = reflect.TypeOf(inInterface).Kind() == reflect.Slice - case AnyType: - return uncastAny(in) - } - if !ok { - return "", fmt.Errorf("can not convert \"%d\" which type is %s to type %s", in, reflect.TypeOf(in), f.Type) - } - return fmt.Sprintf("%v", inInterface), nil -} - -// TestString checks whether the value can be unmarshalled to the field type. -func (f *Field) TestString(value string) bool { - _, err := f.Cast(value) - return err == nil -} - -// asReadField returns the field passed-in as parameter like it's been read as JSON. -// That include setting default values. -// Created for being used in tests. -// IMPORTANT: Not ready for being used in production due to possibly bad performance. -func asJSONField(f Field) Field { - var out Field - data, _ := json.Marshal(&f) - json.Unmarshal(data, &out) - return out -} diff --git a/vendor/github.com/frictionlessdata/tableschema-go/schema/field_test.go b/vendor/github.com/frictionlessdata/tableschema-go/schema/field_test.go deleted file mode 100644 index 83997b9..0000000 --- a/vendor/github.com/frictionlessdata/tableschema-go/schema/field_test.go +++ /dev/null @@ -1,276 +0,0 @@ -package schema - -import ( - "encoding/json" - "fmt" - "testing" - "time" - - "github.com/matryer/is" -) - -func ExampleField_Cast() { - in := `{ - "name": "id", - "type": "string", - "format": "default", - "constraints": { - "required": true, - "minLen": "5", - "maxLen": "10", - "pattern": ".*11$", - "enum":["1234511"] - } - }` - var field Field - json.Unmarshal([]byte(in), &field) - v, err := field.Cast("1234511") - if err != nil { - panic(err) - } - fmt.Println(v) - // Output: 1234511 -} - -func TestDefaultValues(t *testing.T) { - data := []struct { - Desc string - JSON string - Field Field - }{ - { - "Default Values", - `{"name":"n1"}`, - Field{Name: "n1", Type: defaultFieldType, Format: defaultFieldFormat, TrueValues: defaultTrueValues, FalseValues: defaultFalseValues, - DecimalChar: defaultDecimalChar, GroupChar: defaultGroupChar, BareNumber: defaultBareNumber}, - }, - { - "Overrinding default values", - `{"name":"n2","type":"t2","format":"f2","falseValues":["f2"],"trueValues":["t2"]}`, - Field{Name: "n2", Type: "t2", Format: "f2", TrueValues: []string{"t2"}, FalseValues: []string{"f2"}, - DecimalChar: defaultDecimalChar, GroupChar: defaultGroupChar, BareNumber: defaultBareNumber}, - }, - } - for _, d := range data { - t.Run(d.Desc, func(t *testing.T) { - is := is.New(t) - var f Field - is.NoErr(json.Unmarshal([]byte(d.JSON), &f)) - is.Equal(f, d.Field) - }) - } -} - -func TestField_Cast(t *testing.T) { - data := []struct { - Desc string - Value string - Field Field - Expected interface{} - }{ - {"Integer", "42", Field{Type: IntegerType}, int64(42)}, - {"String_URI", "http:/frictionlessdata.io", Field{Type: StringType, Format: "uri"}, "http:/frictionlessdata.io"}, - {"Boolean_TrueValues", "1", Field{Type: BooleanType, TrueValues: []string{"1"}}, true}, - {"Boolean_FalseValues", "0", Field{Type: BooleanType, FalseValues: []string{"0"}}, false}, - {"Number", "42.5", Field{Type: NumberType}, 42.5}, - {"Date_NoFormat", "2015-10-15", Field{Type: DateType}, time.Date(2015, time.October, 15, 0, 0, 0, 0, time.UTC)}, - {"Date_DefaultFormat", "2015-10-15", Field{Type: DateType, Format: defaultFieldFormat}, time.Date(2015, time.October, 15, 0, 0, 0, 0, time.UTC)}, - {"Date_CustomFormat", "15/10/2015", Field{Type: DateType, Format: "%d/%m/%Y"}, time.Date(2015, time.October, 15, 0, 0, 0, 0, time.UTC)}, - {"Time_NoFormat", "10:10:10", Field{Type: TimeType}, time.Date(0000, time.January, 01, 10, 10, 10, 00, time.UTC)}, - {"Time_DefaultFormat", "10:10:10", Field{Type: TimeType, Format: defaultFieldFormat}, time.Date(0000, time.January, 01, 10, 10, 10, 00, time.UTC)}, - {"Time_CustomFormat", "10-10-10", Field{Type: TimeType, Format: "%H-%M-%S"}, time.Date(0000, time.January, 01, 10, 10, 10, 00, time.UTC)}, - {"YearMonth", "2017-08", Field{Type: YearMonthType}, time.Date(2017, time.August, 01, 00, 00, 00, 00, time.UTC)}, - {"Year", "2017", Field{Type: YearType}, time.Date(2017, time.January, 01, 00, 00, 00, 00, time.UTC)}, - {"DateTime_NoFormat", "2008-09-15T10:53:00Z", Field{Type: DateTimeType}, time.Date(2008, time.September, 15, 10, 53, 00, 00, time.UTC)}, - {"DateTime_DefaultFormat", "2008-09-15T10:53:00Z", Field{Type: DateTimeType, Format: defaultFieldFormat}, time.Date(2008, time.September, 15, 10, 53, 00, 00, time.UTC)}, - {"Duration", "P2H", Field{Type: DurationType}, 2 * time.Hour}, - {"GeoPoint", "90,45", Field{Type: GeoPointType}, GeoPoint{90, 45}}, - {"Any", "10", Field{Type: AnyType}, "10"}, - } - for _, d := range data { - t.Run(d.Desc, func(t *testing.T) { - is := is.New(t) - c, err := d.Field.Cast(d.Value) - is.NoErr(err) - is.Equal(c, d.Expected) - }) - } - t.Run("Object_Success", func(t *testing.T) { - is := is.New(t) - f := Field{Type: ObjectType} - obj, err := f.Cast(`{"name":"foo"}`) - is.NoErr(err) - - objMap, ok := obj.(map[string]interface{}) - is.True(ok) - is.Equal(len(objMap), 1) - is.Equal(objMap["name"], "foo") - }) - t.Run("Object_Failure", func(t *testing.T) { - is := is.New(t) - f := Field{Type: ObjectType} - _, err := f.Cast(`{"name"}`) - is.True(err != nil) - }) - t.Run("Array_Success", func(t *testing.T) { - is := is.New(t) - f := Field{Type: ArrayType} - obj, err := f.Cast(`["foo"]`) - is.NoErr(err) - - arr, ok := obj.([]interface{}) - is.True(ok) - is.Equal(len(arr), 1) - is.Equal(arr[0], "foo") - }) - t.Run("Array_Failure", func(t *testing.T) { - is := is.New(t) - f := Field{Type: ArrayType} - _, err := f.Cast(`{"name":"foo"}`) - is.True(err != nil) - }) - t.Run("InvalidDate", func(t *testing.T) { - data := []struct { - desc string - field Field - value string - }{ - {"InvalidFormat_Any", Field{Type: DateType, Format: "any"}, "2015-10-15"}, - {"InvalidFormat_Strftime", Field{Type: DateType, Format: "Fooo"}, "2015-10-15"}, - } - for _, d := range data { - t.Run(d.desc, func(t *testing.T) { - is := is.New(t) - _, err := d.field.Cast(d.value) - is.True(err != nil) - }) - } - }) - t.Run("InvalidFieldType", func(t *testing.T) { - is := is.New(t) - f := Field{Type: "invalidType"} - _, err := f.Cast("42") - is.True(err != nil) - }) - t.Run("Constraints", func(t *testing.T) { - t.Run("Required", func(t *testing.T) { - is := is.New(t) - f := Field{Type: StringType, Constraints: Constraints{Required: true}, MissingValues: map[string]struct{}{"NA": struct{}{}}} - _, err := f.Cast("NA") - is.True(err != nil) - }) - t.Run("Enum", func(t *testing.T) { - data := []struct { - desc string - field Field - value string - }{ - { - "SimpleCase", - Field{Type: IntegerType, Constraints: Constraints{rawEnum: map[string]struct{}{"1": struct{}{}}}}, - "1", - }, - { - "NilEnumList", - Field{Type: IntegerType}, - "10", - }, - { - "EmptyEnumList", - Field{Type: IntegerType, Constraints: Constraints{rawEnum: map[string]struct{}{}}}, - "10", - }, - } - for _, d := range data { - t.Run(d.desc, func(t *testing.T) { - is := is.New(t) - _, err := d.field.Cast(d.value) - is.NoErr(err) - }) - } - }) - t.Run("EnumError", func(t *testing.T) { - data := []struct { - desc string - field Field - value string - }{ - {"NonEmptyEnumList", Field{Type: IntegerType, Constraints: Constraints{rawEnum: map[string]struct{}{"8": struct{}{}, "9": struct{}{}}}}, "10"}, - } - for _, d := range data { - t.Run(d.desc, func(t *testing.T) { - is := is.New(t) - _, err := d.field.Cast(d.value) - is.True(err != nil) - }) - } - }) - }) -} - -func TestUnmarshalJSON_InvalidField(t *testing.T) { - is := is.New(t) - var f Field - is.True(json.Unmarshal([]byte("{Foo:1}"), &f) != nil) -} - -func TestTestString(t *testing.T) { - is := is.New(t) - f := Field{Type: "integer"} - is.True(f.TestString("42")) - is.True(!f.TestString("boo")) -} - -func TestField_Uncast(t *testing.T) { - t.Run("Success", func(t *testing.T) { - data := []struct { - desc string - field Field - value interface{} - want string - }{ - {"Int", Field{Type: IntegerType}, 1, "1"}, - {"Number", Field{Type: NumberType}, 1.0, "1"}, - {"IntNumberImplicitCast", Field{Type: NumberType}, 100, "100"}, - {"NumberToIntImplicitCast", Field{Type: IntegerType}, 100.5, "100"}, - {"Boolean", Field{Type: BooleanType}, true, "true"}, - {"Duration", Field{Type: DurationType}, 1 * time.Second, "P0Y0M0DT1S"}, - {"GeoPoint", Field{Type: GeoPointType}, "10,10", "10,10"}, - {"String", Field{Type: StringType}, "foo", "foo"}, - {"Array", Field{Type: ArrayType}, []string{"foo"}, "[foo]"}, - {"Date", Field{Type: DateType}, time.Unix(1, 0), "1970-01-01T00:00:01Z"}, - {"Year", Field{Type: YearType}, time.Unix(1, 0), "1970-01-01T00:00:01Z"}, - {"YearMonth", Field{Type: YearMonthType}, time.Unix(1, 0), "1970-01-01T00:00:01Z"}, - {"DateTime", Field{Type: DateTimeType}, time.Unix(1, 0), "1970-01-01T00:00:01Z"}, - {"Date", Field{Type: DateType}, time.Unix(1, 0), "1970-01-01T00:00:01Z"}, - {"Object", Field{Type: ObjectType}, eoStruct{Name: "Foo"}, `{"name":"Foo"}`}, - {"Any", Field{Type: AnyType}, "10", "10"}, - } - for _, d := range data { - t.Run(d.desc, func(t *testing.T) { - is := is.New(t) - got, err := d.field.Uncast(d.value) - is.NoErr(err) - is.Equal(d.want, got) - }) - } - }) - t.Run("Error", func(t *testing.T) { - data := []struct { - desc string - field Field - value interface{} - }{ - {"StringToIntCast", Field{Type: IntegerType}, "1.5"}, - {"StringToNumberCast", Field{Type: NumberType}, "1.5"}, - {"InvalidType", Field{Type: "Boo"}, "1"}, - } - for _, d := range data { - t.Run(d.desc, func(t *testing.T) { - is := is.New(t) - _, err := d.field.Uncast(d.value) - is.True(err != nil) - }) - } - }) -} diff --git a/vendor/github.com/frictionlessdata/tableschema-go/schema/geopoint.go b/vendor/github.com/frictionlessdata/tableschema-go/schema/geopoint.go deleted file mode 100644 index 6fc4a75..0000000 --- a/vendor/github.com/frictionlessdata/tableschema-go/schema/geopoint.go +++ /dev/null @@ -1,103 +0,0 @@ -package schema - -import ( - "encoding/json" - "fmt" - "reflect" - "regexp" - "strconv" -) - -// Formats specific to GeoPoint field type. -const ( - GeoPointArrayFormat = "array" - GeoPointObjectFormat = "object" -) - -// GeoPoint represents a "geopoint" cell. -// More at: https://specs.frictionlessdata.io/table-schema/#geopoint -type GeoPoint struct { - Lon float64 `json:"lon,omitempty"` - Lat float64 `json:"lat,omitempty"` -} - -// UnmarshalJSON sets *f to a copy of data. It will respect the default values -func (p *GeoPoint) UnmarshalJSON(data []byte) error { - type geoPointAlias struct { - Lon *float64 `json:"lon,omitempty"` - Lat *float64 `json:"lat,omitempty"` - } - var a geoPointAlias - if err := json.Unmarshal(data, &a); err != nil { - return err - } - if a.Lon == nil || a.Lat == nil { - return fmt.Errorf("Invalid geopoint:\"%s\"", string(data)) - } - p.Lon = *a.Lon - p.Lat = *a.Lat - return nil -} - -var ( - geoPointDefaultRegexp = regexp.MustCompile(`^([-+]?[0-9]*\.?[0-9]*), ?([-+]?[0-9]*\.?[0-9]*)$`) - geoPointArrayRegexp = regexp.MustCompile(`^\[([-+]?[0-9]*\.?[0-9]+), ?([-+]?[0-9]*\.?[0-9]+)\]$`) -) - -func castGeoPoint(format, value string) (GeoPoint, error) { - switch format { - case "", defaultFieldFormat: - return applyGeoPointRegexp(geoPointDefaultRegexp, value) - case GeoPointArrayFormat: - return applyGeoPointRegexp(geoPointArrayRegexp, value) - case GeoPointObjectFormat: - var p GeoPoint - if err := json.Unmarshal([]byte(value), &p); err != nil { - return GeoPoint{}, err - } - return p, nil - } - return GeoPoint{}, fmt.Errorf("invalid geopoint format:%s", format) -} - -func applyGeoPointRegexp(r *regexp.Regexp, value string) (GeoPoint, error) { - matches := r.FindStringSubmatch(value) - if len(matches) == 0 || len(matches[1]) == 0 || len(matches[2]) == 0 { - return GeoPoint{}, fmt.Errorf("Invalid geopoint:\"%s\"", value) - } - lon, _ := strconv.ParseFloat(matches[1], 64) - lat, _ := strconv.ParseFloat(matches[2], 64) - return GeoPoint{lon, lat}, nil -} - -func uncastGeoPoint(format string, gp interface{}) (string, error) { - switch format { - case "", defaultFieldFormat: - value, ok := gp.(string) - if ok { - _, err := applyGeoPointRegexp(geoPointDefaultRegexp, value) - if err != nil { - return "", err - } - return value, nil - } - return "", fmt.Errorf("invalid object type to uncast to geopoint dfault format. want:string got:%v", reflect.TypeOf(gp).String()) - case GeoPointArrayFormat: - value, ok := gp.(string) - if ok { - _, err := applyGeoPointRegexp(geoPointArrayRegexp, value) - if err != nil { - return "", err - } - return value, nil - } - return "", fmt.Errorf("invalid object type to uncast to geopoint %s format. want:string got:%v", GeoPointArrayFormat, reflect.TypeOf(gp).String()) - case GeoPointObjectFormat: - value, ok := gp.(GeoPoint) - if ok { - return fmt.Sprintf("%+v", value), nil - } - return "", fmt.Errorf("invalid object type to uncast to geopoint %s format. want:schema.Geopoint got:%v", GeoPointObjectFormat, reflect.TypeOf(gp).String()) - } - return "", fmt.Errorf("invalid geopoint - type:%v value:\"%v\" format:%s", gp, reflect.ValueOf(gp).Type(), format) -} diff --git a/vendor/github.com/frictionlessdata/tableschema-go/schema/geopoint_test.go b/vendor/github.com/frictionlessdata/tableschema-go/schema/geopoint_test.go deleted file mode 100644 index 7f25a1d..0000000 --- a/vendor/github.com/frictionlessdata/tableschema-go/schema/geopoint_test.go +++ /dev/null @@ -1,102 +0,0 @@ -package schema - -import ( - "testing" - - "github.com/matryer/is" -) - -func TestCastGeoPoint(t *testing.T) { - data := []struct { - desc string - format string - value string - want GeoPoint - }{ - {"DefaultNoParentheses", defaultFieldFormat, "90,40", GeoPoint{90, 40}}, - {"DefaultNoParenthesesFloats", defaultFieldFormat, "90.5,40.44", GeoPoint{90.5, 40.44}}, - {"DefaultNoParenthesesNegative", defaultFieldFormat, "-90.10,-40", GeoPoint{-90.10, -40}}, - {"DefaultNoParenthesesEmptyFormat", "", "90,40", GeoPoint{90, 40}}, - {"DefaultWithSpace", "", "90, 40", GeoPoint{90, 40}}, - {"DefaultWithSpaceNegative", "", "-90, -40", GeoPoint{-90, -40}}, - {"Array", GeoPointArrayFormat, "[90,40]", GeoPoint{90, 40}}, - {"ArrayFloat", GeoPointArrayFormat, "[90.5,40.44]", GeoPoint{90.5, 40.44}}, - {"ArrayNegative", GeoPointArrayFormat, "[-90.5,-40]", GeoPoint{-90.5, -40}}, - {"ArrayWithSpace", GeoPointArrayFormat, "[90, 40]", GeoPoint{90, 40}}, - {"ArrayWithSpaceNegative", GeoPointArrayFormat, "[-90, -40]", GeoPoint{-90, -40}}, - {"Object", GeoPointObjectFormat, `{"lon": 90, "lat": 45}`, GeoPoint{90, 45}}, - } - for _, d := range data { - t.Run(d.desc, func(t *testing.T) { - is := is.New(t) - got, err := castGeoPoint(d.format, d.value) - is.NoErr(err) - is.Equal(got, d.want) - }) - } - t.Run("Error", func(t *testing.T) { - data := []struct { - desc string - format string - value string - }{ - {"BadJSON", GeoPointObjectFormat, ""}, - {"BadGeoPointJSON", GeoPointObjectFormat, `{"longi": 90, "lat": 45}`}, - {"BadFormat", "badformat", `{"longi": 90, "lat": 45}`}, - {"InvalidDefault", defaultFieldFormat, "/10,10/"}, - {"InvalidArray", defaultFieldFormat, "/[10,10]/"}, - } - for _, d := range data { - t.Run(d.desc, func(t *testing.T) { - is := is.New(t) - _, err := castGeoPoint(d.format, d.value) - is.True(err != nil) - }) - } - }) -} - -func TestUncastGeoPoint(t *testing.T) { - t.Run("Success", func(t *testing.T) { - data := []struct { - desc string - format string - value interface{} - want string - }{ - {"GeoPointObject", GeoPointObjectFormat, GeoPoint{10, 10}, "{Lon:10 Lat:10}"}, - {"GeoPointArray", GeoPointArrayFormat, "[10,10]", "[10,10]"}, - {"GeoPointDefault", defaultFieldFormat, "10,10", "10,10"}, - } - for _, d := range data { - t.Run(d.desc, func(t *testing.T) { - is := is.New(t) - got, err := uncastGeoPoint(d.format, d.value) - is.NoErr(err) - is.Equal(d.want, got) - }) - } - }) - t.Run("Error", func(t *testing.T) { - data := []struct { - desc string - format string - value interface{} - }{ - {"InvalidObjectType_Object", GeoPointObjectFormat, int(10)}, - {"InvalidObjectType_Array", GeoPointArrayFormat, int(10)}, - {"InvalidArray", GeoPointArrayFormat, "10,10"}, - {"InvalidObjectType_Empty", "", int(10)}, - {"InvalidObjectType_Default", defaultFieldFormat, int(10)}, - {"InvalidDefault", defaultFieldFormat, "/10,10/"}, - {"InvalidFormat", "badFormat", int(10)}, - } - for _, d := range data { - t.Run(d.desc, func(t *testing.T) { - is := is.New(t) - _, err := uncastGeoPoint(d.format, d.value) - is.True(err != nil) - }) - } - }) -} diff --git a/vendor/github.com/frictionlessdata/tableschema-go/schema/infer.go b/vendor/github.com/frictionlessdata/tableschema-go/schema/infer.go deleted file mode 100644 index 74093c4..0000000 --- a/vendor/github.com/frictionlessdata/tableschema-go/schema/infer.go +++ /dev/null @@ -1,211 +0,0 @@ -package schema - -import ( - "fmt" - - "github.com/frictionlessdata/tableschema-go/table" -) - -var ( - // https://specs.frictionlessdata.io/table-schema/#boolean - booleanValues = map[string]struct{}{ - "true": struct{}{}, - "True": struct{}{}, - "TRUE": struct{}{}, - "1": struct{}{}, - "false": struct{}{}, - "False": struct{}{}, - "FALSE": struct{}{}, - "0": struct{}{}, - } - // This structure is optmized for querying. - // It should point a type to what is allowed to be implicitly cast. - // The inner set must be sorted by the narrower first. - implicitCast = map[string][]string{ - IntegerType: []string{IntegerType, NumberType, StringType}, - NumberType: []string{NumberType, StringType}, - BooleanType: []string{BooleanType, IntegerType, NumberType, StringType}, - YearMonthType: []string{YearMonthType, DateType, StringType}, - YearType: []string{YearType, IntegerType, NumberType, StringType}, - DateType: []string{DateType, DateTimeType, StringType}, - DateTimeType: []string{DateTimeType, StringType}, - TimeType: []string{TimeType, StringType}, - DurationType: []string{DurationType, StringType}, - ObjectType: []string{ObjectType, StringType}, - ArrayType: []string{ArrayType, StringType}, - GeoPointType: []string{GeoPointType, ArrayType, StringType}, - StringType: []string{}, - } - - // Types ordered from narrower to wider. - orderedTypes = []string{BooleanType, YearType, IntegerType, GeoPointType, NumberType, YearMonthType, DateType, DateTimeType, TimeType, DurationType, ArrayType, ObjectType} - - noConstraints = Constraints{} -) - -// Maximum number of rows used to infer schema. -const maxNumRowsInfer = 100 - -// Infer infers a schema from a slice of the tabular data. For columns that contain -// cells that can inferred as different types, the most popular type is set as the field -// type. For instance, a column with values 10.1, 10, 10 will inferred as being of type -// "integer". -func Infer(tab table.Table) (*Schema, error) { - s, err := sample(tab) - if err != nil { - return nil, err - } - return infer(tab.Headers(), s) -} - -func sample(tab table.Table) ([][]string, error) { - iter, err := tab.Iter() - if err != nil { - return nil, err - } - var t [][]string - for count := 0; count < maxNumRowsInfer && iter.Next(); count++ { - t = append(t, iter.Row()) - } - if iter.Err() != nil { - return nil, iter.Err() - } - return t, nil -} - -func infer(headers []string, table [][]string) (*Schema, error) { - inferredTypes := make([]map[string]int, len(headers)) - for rowID := range table { - row := table[rowID] - // TODO(danielfireman): the python version does some normalization on - // the number of columns and headers. Need to look closer at this. - if len(headers) != len(row) { - return nil, fmt.Errorf("data is not tabular. headers:%v row[%d]:%v", headers, rowID, row) - } - for cellIndex, cell := range row { - if inferredTypes[cellIndex] == nil { - inferredTypes[cellIndex] = make(map[string]int) - } - // The list bellow must be ordered by the narrower field type. - t := findType(cell, orderedTypes) - inferredTypes[cellIndex][t]++ - } - } - schema := Schema{} - for index := range headers { - schema.Fields = append(schema.Fields, - Field{ - Name: headers[index], - Type: defaultFieldType, - Format: defaultFieldFormat, - }) - count := 0 - for t, c := range inferredTypes[index] { - if c > count { - f := &schema.Fields[index] - f.Type = t - count = c - } - } - } - return &schema, nil -} - -// InferImplicitCasting uses a implicit casting for infering the type of columns -// that have cells of diference types. For instance, a column with values 10.1, 10, 10 -// will inferred as being of type "number" ("integer" can be implicitly cast to "number"). -// -// For medium to big tables, this method is faster than the Infer. -func InferImplicitCasting(tab table.Table) (*Schema, error) { - s, err := sample(tab) - if err != nil { - return nil, err - } - return inferImplicitCasting(tab.Headers(), s) -} - -func inferImplicitCasting(headers []string, table [][]string) (*Schema, error) { - inferredTypes := make([]string, len(headers)) - for rowID := range table { - row := table[rowID] - // TODO(danielfireman): the python version does some normalization on - // the number of columns and headers. Need to look closer at this. - if len(headers) != len(row) { - return nil, fmt.Errorf("data is not tabular. headers:%v row[%d]:%v", headers, rowID, row) - } - for cellIndex, cell := range row { - if inferredTypes[cellIndex] == "" { - t := findType(cell, orderedTypes) - inferredTypes[cellIndex] = t - } else { - inferredTypes[cellIndex] = findType(cell, implicitCast[inferredTypes[cellIndex]]) - } - } - } - schema := Schema{} - for index := range headers { - schema.Fields = append(schema.Fields, - Field{ - Name: headers[index], - Type: inferredTypes[index], - Format: defaultFieldFormat, - }) - } - return &schema, nil -} - -func findType(value string, checkOrder []string) string { - for _, t := range checkOrder { - switch t { - case BooleanType: - if _, ok := booleanValues[value]; ok { - return BooleanType - } - case IntegerType: - if _, err := castInt(defaultBareNumber, value, noConstraints); err == nil { - return IntegerType - } - case NumberType: - if _, err := castNumber(defaultDecimalChar, defaultGroupChar, defaultBareNumber, value, noConstraints); err == nil { - return NumberType - } - case DateType: - if _, err := castDate(defaultFieldFormat, value, noConstraints); err == nil { - return DateType - } - case ArrayType: - if _, err := castArray(value); err == nil { - return ArrayType - } - case ObjectType: - if _, err := castObject(value); err == nil { - return ObjectType - } - case TimeType: - if _, err := castTime(defaultFieldFormat, value, noConstraints); err == nil { - return TimeType - } - case YearMonthType: - if _, err := castYearMonth(value, noConstraints); err == nil { - return YearMonthType - } - case YearType: - if _, err := castYear(value, noConstraints); err == nil { - return YearType - } - case DateTimeType: - if _, err := castDateTime(value, noConstraints); err == nil { - return DateTimeType - } - case DurationType: - if _, err := castDuration(value); err == nil { - return DurationType - } - case GeoPointType: - if _, err := castGeoPoint(defaultFieldFormat, value); err == nil { - return GeoPointType - } - } - } - return StringType -} diff --git a/vendor/github.com/frictionlessdata/tableschema-go/schema/infer_test.go b/vendor/github.com/frictionlessdata/tableschema-go/schema/infer_test.go deleted file mode 100644 index 446bb8b..0000000 --- a/vendor/github.com/frictionlessdata/tableschema-go/schema/infer_test.go +++ /dev/null @@ -1,215 +0,0 @@ -package schema - -import ( - "fmt" - "sort" - "testing" - - "github.com/matryer/is" - - "github.com/frictionlessdata/tableschema-go/table" -) - -func Exampleinfer() { - tab := table.FromSlices( - []string{"Person", "Height"}, - [][]string{ - []string{"Foo", "5"}, - []string{"Bar", "4"}, - []string{"Bez", "5.5"}, - }) - s, _ := Infer(tab) - fmt.Println("Fields:") - for _, f := range s.Fields { - fmt.Printf("{Name:%s Type:%s Format:%s}\n", f.Name, f.Type, f.Format) - } - // Output: Fields: - // {Name:Person Type:string Format:default} - // {Name:Height Type:integer Format:default} -} - -func ExampleInferImplicitCasting() { - tab := table.FromSlices( - []string{"Person", "Height"}, - [][]string{ - []string{"Foo", "5"}, - []string{"Bar", "4"}, - []string{"Bez", "5.5"}, - }) - s, _ := InferImplicitCasting(tab) - fmt.Println("Fields:") - for _, f := range s.Fields { - fmt.Printf("{Name:%s Type:%s Format:%s}\n", f.Name, f.Type, f.Format) - } - // Output: Fields: - // {Name:Person Type:string Format:default} - // {Name:Height Type:number Format:default} -} - -func TestInfer(t *testing.T) { - data := []struct { - desc string - headers []string - table [][]string - want Schema - }{ - {"1Cell_Date", []string{"Birthday"}, [][]string{[]string{"1983-10-15"}}, Schema{Fields: []Field{{Name: "Birthday", Type: DateType, Format: defaultFieldFormat}}}}, - {"1Cell_Integer", []string{"Age"}, [][]string{[]string{"10"}}, Schema{Fields: []Field{{Name: "Age", Type: IntegerType, Format: defaultFieldFormat}}}}, - {"1Cell_Number", []string{"Weight"}, [][]string{[]string{"20.2"}}, Schema{Fields: []Field{{Name: "Weight", Type: NumberType, Format: defaultFieldFormat}}}}, - {"1Cell_Boolean", []string{"Foo"}, [][]string{[]string{"0"}}, Schema{Fields: []Field{{Name: "Foo", Type: BooleanType, Format: defaultFieldFormat}}}}, - {"1Cell_Object", []string{"Foo"}, [][]string{[]string{`{"name":"foo"}`}}, Schema{Fields: []Field{{Name: "Foo", Type: ObjectType, Format: defaultFieldFormat}}}}, - {"1Cell_Array", []string{"Foo"}, [][]string{[]string{`["name"]`}}, Schema{Fields: []Field{{Name: "Foo", Type: ArrayType, Format: defaultFieldFormat}}}}, - {"1Cell_String", []string{"Foo"}, [][]string{[]string{"name"}}, Schema{Fields: []Field{{Name: "Foo", Type: StringType, Format: defaultFieldFormat}}}}, - {"1Cell_Time", []string{"Foo"}, [][]string{[]string{"10:15:50"}}, Schema{Fields: []Field{{Name: "Foo", Type: TimeType, Format: defaultFieldFormat}}}}, - {"1Cell_YearMonth", []string{"YearMonth"}, [][]string{[]string{"2017-08"}}, Schema{Fields: []Field{{Name: "YearMonth", Type: YearMonthType, Format: defaultFieldFormat}}}}, - {"1Cell_Year", []string{"Year"}, [][]string{[]string{"2017"}}, Schema{Fields: []Field{{Name: "Year", Type: YearType, Format: defaultFieldFormat}}}}, - {"1Cell_DateTime", []string{"DateTime"}, [][]string{[]string{"2008-09-15T15:53:00+05:00"}}, Schema{Fields: []Field{{Name: "DateTime", Type: DateTimeType, Format: defaultFieldFormat}}}}, - {"1Cell_Duration", []string{"Duration"}, [][]string{[]string{"P3Y6M4DT12H30M5S"}}, Schema{Fields: []Field{{Name: "Duration", Type: DurationType, Format: defaultFieldFormat}}}}, - {"1Cell_GeoPoint", []string{"GeoPoint"}, [][]string{[]string{"90,45"}}, Schema{Fields: []Field{{Name: "GeoPoint", Type: GeoPointType, Format: defaultFieldFormat}}}}, - {"ManyCells", - []string{"Name", "Age", "Weight", "Bogus", "Boolean", "Boolean1"}, - [][]string{ - []string{"Foo", "10", "20.2", "1", "1", "1"}, - []string{"Foo", "10", "30", "1", "1", "1"}, - []string{"Foo", "10", "30", "Daniel", "1", "2"}, - }, - Schema{Fields: []Field{ - {Name: "Name", Type: StringType, Format: defaultFieldFormat}, - {Name: "Age", Type: IntegerType, Format: defaultFieldFormat}, - {Name: "Weight", Type: IntegerType, Format: defaultFieldFormat}, - {Name: "Bogus", Type: BooleanType, Format: defaultFieldFormat}, - {Name: "Boolean", Type: BooleanType, Format: defaultFieldFormat}, - {Name: "Boolean1", Type: BooleanType, Format: defaultFieldFormat}, - }}, - }, - } - for _, d := range data { - t.Run(d.desc, func(t *testing.T) { - is := is.New(t) - s, err := infer(d.headers, d.table) - is.NoErr(err) - - sort.Sort(s.Fields) - sort.Sort(d.want.Fields) - is.Equal(s, &d.want) - }) - } - t.Run("Error", func(t *testing.T) { - data := []struct { - desc string - headers []string - table [][]string - }{ - {"NotATable", []string{}, [][]string{[]string{"1"}}}, - } - for _, d := range data { - t.Run(d.desc, func(t *testing.T) { - is := is.New(t) - _, err := infer(d.headers, d.table) - is.True(err != nil) - }) - } - }) -} - -func TestInferImplicitCasting(t *testing.T) { - data := []struct { - desc string - headers []string - table [][]string - want Schema - }{ - {"1Cell_Date", []string{"Birthday"}, [][]string{[]string{"1983-10-15"}}, Schema{Fields: []Field{{Name: "Birthday", Type: DateType, Format: defaultFieldFormat}}}}, - {"1Cell_Integer", []string{"Age"}, [][]string{[]string{"10"}}, Schema{Fields: []Field{{Name: "Age", Type: IntegerType, Format: defaultFieldFormat}}}}, - {"1Cell_Number", []string{"Weight"}, [][]string{[]string{"20.2"}}, Schema{Fields: []Field{{Name: "Weight", Type: NumberType, Format: defaultFieldFormat}}}}, - {"1Cell_Boolean", []string{"Foo"}, [][]string{[]string{"0"}}, Schema{Fields: []Field{{Name: "Foo", Type: BooleanType, Format: defaultFieldFormat}}}}, - {"1Cell_Object", []string{"Foo"}, [][]string{[]string{`{"name":"foo"}`}}, Schema{Fields: []Field{{Name: "Foo", Type: ObjectType, Format: defaultFieldFormat}}}}, - {"1Cell_Array", []string{"Foo"}, [][]string{[]string{`["name"]`}}, Schema{Fields: []Field{{Name: "Foo", Type: ArrayType, Format: defaultFieldFormat}}}}, - {"1Cell_String", []string{"Foo"}, [][]string{[]string{"name"}}, Schema{Fields: []Field{{Name: "Foo", Type: StringType, Format: defaultFieldFormat}}}}, - {"1Cell_Time", []string{"Foo"}, [][]string{[]string{"10:15:50"}}, Schema{Fields: []Field{{Name: "Foo", Type: TimeType, Format: defaultFieldFormat}}}}, - {"1Cell_YearMonth", []string{"YearMonth"}, [][]string{[]string{"2017-08"}}, Schema{Fields: []Field{{Name: "YearMonth", Type: YearMonthType, Format: defaultFieldFormat}}}}, - {"1Cell_Year", []string{"Year"}, [][]string{[]string{"2017"}}, Schema{Fields: []Field{{Name: "Year", Type: YearType, Format: defaultFieldFormat}}}}, - {"1Cell_DateTime", []string{"DateTime"}, [][]string{[]string{"2008-09-15T15:53:00+05:00"}}, Schema{Fields: []Field{{Name: "DateTime", Type: DateTimeType, Format: defaultFieldFormat}}}}, - {"1Cell_Duration", []string{"Duration"}, [][]string{[]string{"P3Y6M4DT12H30M5S"}}, Schema{Fields: []Field{{Name: "Duration", Type: DurationType, Format: defaultFieldFormat}}}}, - {"1Cell_GeoPoint", []string{"GeoPoint"}, [][]string{[]string{"90,45"}}, Schema{Fields: []Field{{Name: "GeoPoint", Type: GeoPointType, Format: defaultFieldFormat}}}}, - {"ManyCells", - []string{"Name", "Age", "Weight", "Bogus", "Boolean", "Int"}, - [][]string{ - []string{"Foo", "10", "20.2", "1", "1", "1"}, - []string{"Foo", "10", "30", "1", "1", "1"}, - []string{"Foo", "10", "30", "Daniel", "1", "2"}, - }, - Schema{Fields: []Field{ - {Name: "Name", Type: StringType, Format: defaultFieldFormat}, - {Name: "Age", Type: IntegerType, Format: defaultFieldFormat}, - {Name: "Weight", Type: NumberType, Format: defaultFieldFormat}, - {Name: "Bogus", Type: StringType, Format: defaultFieldFormat}, - {Name: "Boolean", Type: BooleanType, Format: defaultFieldFormat}, - {Name: "Int", Type: IntegerType, Format: defaultFieldFormat}, - }}, - }, - } - for _, d := range data { - t.Run(d.desc, func(t *testing.T) { - is := is.New(t) - s, err := inferImplicitCasting(d.headers, d.table) - is.NoErr(err) - - sort.Sort(s.Fields) - sort.Sort(d.want.Fields) - is.Equal(s, &d.want) - }) - } - t.Run("Error", func(t *testing.T) { - data := []struct { - desc string - headers []string - table [][]string - }{ - {"NotATable", []string{}, [][]string{[]string{"1"}}}, - } - for _, d := range data { - t.Run(d.desc, func(t *testing.T) { - is := is.New(t) - _, err := inferImplicitCasting(d.headers, d.table) - is.True(err != nil) - }) - } - }) -} - -var ( - benchmarkHeaders = []string{"Name", "Birthday", "Weight", "Address", "Siblings"} - benchmarkTable = [][]string{ - []string{"Foo", "2015-10-12", "20.2", `{"Street":"Foo", "Number":10, "City":"New York", "State":"NY"}`, `["Foo"]`}, - []string{"Bar", "2015-10-12", "30", `{"Street":"Foo", "Number":10, "City":"New York", "State":"NY"}`, `["Foo"]`}, - []string{"Bez", "2015-10-12", "30", `{"Street":"Foo", "Number":10, "City":"New York", "State":"NY"}`, `["Foo"]`}, - } -) - -func benchmarkinfer(growthMultiplier int, b *testing.B) { - for n := 0; n < b.N; n++ { - infer(benchmarkHeaders, generateBenchmarkTable(growthMultiplier)) - } -} - -func benchmarkInferImplicitCasting(growthMultiplier int, b *testing.B) { - for n := 0; n < b.N; n++ { - inferImplicitCasting(benchmarkHeaders, generateBenchmarkTable(growthMultiplier)) - } -} - -func generateBenchmarkTable(growthMultiplier int) [][]string { - var t [][]string - for i := 0; i < growthMultiplier; i++ { - t = append(t, benchmarkTable...) - } - return t -} - -func BenchmarkInferSmall(b *testing.B) { benchmarkinfer(1, b) } -func BenchmarkInferMedium(b *testing.B) { benchmarkinfer(100, b) } -func BenchmarkInferBig(b *testing.B) { benchmarkinfer(1000, b) } -func BenchmarkInferImplicitCastingSmall(b *testing.B) { benchmarkInferImplicitCasting(1, b) } -func BenchmarkInferImplicitCastingMedium(b *testing.B) { benchmarkInferImplicitCasting(100, b) } -func BenchmarkInferImplicitCastingBig(b *testing.B) { benchmarkInferImplicitCasting(1000, b) } diff --git a/vendor/github.com/frictionlessdata/tableschema-go/schema/integer.go b/vendor/github.com/frictionlessdata/tableschema-go/schema/integer.go deleted file mode 100644 index 5356f3e..0000000 --- a/vendor/github.com/frictionlessdata/tableschema-go/schema/integer.go +++ /dev/null @@ -1,53 +0,0 @@ -package schema - -import ( - "fmt" - "regexp" - "strconv" -) - -// CastInt casts an integer value (passed-in as unicode string) against a field. Returns an -// error if the value can not be converted to integer. -func castInt(bareNumber bool, value string, c Constraints) (int64, error) { - v := value - if !bareNumber { - var err error - v, err = stripIntegerFromString(v) - if err != nil { - return 0, err - } - } - returned, err := strconv.ParseInt(v, 10, 64) - if err != nil { - return 0, err - } - if c.Maximum != "" { - max, err := strconv.ParseInt(c.Maximum, 10, 64) - if err != nil { - return 0, fmt.Errorf("invalid maximum integer: %v", c.Maximum) - } - if returned > max { - return 0, fmt.Errorf("constraint check error: integer:%d > maximum:%d", returned, max) - } - } - if c.Minimum != "" { - min, err := strconv.ParseInt(c.Minimum, 10, 64) - if err != nil { - return 0, fmt.Errorf("invalid minimum integer: %v", c.Minimum) - } - if returned < min { - return 0, fmt.Errorf("constraint check error: integer:%d < minimum:%d", returned, min) - } - } - return returned, nil -} - -var bareIntegerRegexp = regexp.MustCompile(`((^[0-9]+)|([0-9]+$))`) - -func stripIntegerFromString(v string) (string, error) { - matches := bareIntegerRegexp.FindStringSubmatch(v) - if matches == nil { - return "", fmt.Errorf("invalid integer to strip:%s", v) - } - return matches[1], nil -} diff --git a/vendor/github.com/frictionlessdata/tableschema-go/schema/integer_test.go b/vendor/github.com/frictionlessdata/tableschema-go/schema/integer_test.go deleted file mode 100644 index 0d49c9d..0000000 --- a/vendor/github.com/frictionlessdata/tableschema-go/schema/integer_test.go +++ /dev/null @@ -1,67 +0,0 @@ -package schema - -import ( - "testing" - - "github.com/matryer/is" -) - -const notBareInt = false - -func TestCastInt(t *testing.T) { - t.Run("Success", func(t *testing.T) { - data := []struct { - desc string - number string - want int64 - bn bool - }{ - {"Positive_WithSignal", "+10", 10, defaultBareNumber}, - {"Positive_WithoutSignal", "10", 10, defaultBareNumber}, - {"Negative", "-10", -10, defaultBareNumber}, - {"BareNumber", "€95", 95, notBareInt}, - {"BareNumber_TrailingAtBeginning", "€95", 95, notBareInt}, - {"BareNumber_TrailingAtBeginningSpace", "EUR 95", 95, notBareInt}, - {"BareNumber_TrailingAtEnd", "95%", 95, notBareInt}, - {"BareNumber_TrailingAtEndSpace", "95 %", 95, notBareInt}, - } - for _, d := range data { - t.Run(d.desc, func(t *testing.T) { - is := is.New(t) - got, err := castInt(d.bn, d.number, Constraints{}) - is.NoErr(err) - is.Equal(d.want, got) - }) - } - }) - t.Run("ValidMaximum", func(t *testing.T) { - is := is.New(t) - _, err := castInt(defaultBareNumber, "2", Constraints{Maximum: "2"}) - is.NoErr(err) - }) - t.Run("ValidMinimum", func(t *testing.T) { - is := is.New(t) - _, err := castInt(defaultBareNumber, "2", Constraints{Minimum: "1"}) - is.NoErr(err) - }) - t.Run("Error", func(t *testing.T) { - data := []struct { - desc string - number string - constraints Constraints - }{ - {"InvalidIntToStrip_TooManyNumbers", "+10++10", Constraints{}}, - {"NumBiggerThanMaximum", "3", Constraints{Maximum: "2"}}, - {"InvalidMaximum", "1", Constraints{Maximum: "boo"}}, - {"NumSmallerThanMinimum", "1", Constraints{Minimum: "2"}}, - {"InvalidMinimum", "1", Constraints{Minimum: "boo"}}, - } - for _, d := range data { - t.Run(d.desc, func(t *testing.T) { - is := is.New(t) - _, err := castInt(defaultBareNumber, d.number, d.constraints) - is.True(err != nil) - }) - } - }) -} diff --git a/vendor/github.com/frictionlessdata/tableschema-go/schema/number.go b/vendor/github.com/frictionlessdata/tableschema-go/schema/number.go deleted file mode 100644 index def1c93..0000000 --- a/vendor/github.com/frictionlessdata/tableschema-go/schema/number.go +++ /dev/null @@ -1,61 +0,0 @@ -package schema - -import ( - "fmt" - "regexp" - "strconv" - "strings" -) - -func castNumber(decimalChar, groupChar string, bareNumber bool, value string, c Constraints) (float64, error) { - dc := decimalChar - if groupChar != "" { - dc = decimalChar - } - v := strings.Replace(value, dc, ".", 1) - gc := defaultGroupChar - if groupChar != "" { - gc = groupChar - } - v = strings.Replace(v, gc, "", -1) - if !bareNumber { - var err error - v, err = stripNumberFromString(v) - if err != nil { - return 0, err - } - } - returned, err := strconv.ParseFloat(v, 64) - if err != nil { - return 0, err - } - if c.Maximum != "" { - max, err := strconv.ParseFloat(c.Maximum, 64) - if err != nil { - return 0, fmt.Errorf("invalid maximum number: %v", c.Maximum) - } - if returned > max { - return 0, fmt.Errorf("constraint check error: integer:%f > maximum:%f", returned, max) - } - } - if c.Minimum != "" { - min, err := strconv.ParseFloat(c.Minimum, 64) - if err != nil { - return 0, fmt.Errorf("invalid minimum integer: %v", c.Minimum) - } - if returned < min { - return 0, fmt.Errorf("constraint check error: integer:%f < minimum:%f", returned, min) - } - } - return returned, nil -} - -var bareNumberRegexp = regexp.MustCompile(`((^[0-9]+\.?[0-9]*)|([0-9]+\.?[0-9]*$))`) - -func stripNumberFromString(v string) (string, error) { - matches := bareNumberRegexp.FindStringSubmatch(v) - if matches == nil { - return "", fmt.Errorf("invalid number to strip:%s", v) - } - return matches[1], nil -} diff --git a/vendor/github.com/frictionlessdata/tableschema-go/schema/number_test.go b/vendor/github.com/frictionlessdata/tableschema-go/schema/number_test.go deleted file mode 100644 index e33b8dd..0000000 --- a/vendor/github.com/frictionlessdata/tableschema-go/schema/number_test.go +++ /dev/null @@ -1,94 +0,0 @@ -package schema - -import ( - "math" - "testing" - - "github.com/matryer/is" -) - -const notBareNumber = false - -func TestCastNumber(t *testing.T) { - t.Run("Success", func(t *testing.T) { - data := []struct { - desc string - number string - want float64 - dc string - gc string - bn bool - }{ - {"Positive_WithSignal", "+10.10", 10.10, defaultDecimalChar, defaultGroupChar, defaultBareNumber}, - {"Positive_WithoutSignal", "10.10", 10.10, defaultDecimalChar, defaultGroupChar, defaultBareNumber}, - {"Negative", "-10.10", -10.10, defaultDecimalChar, defaultGroupChar, defaultBareNumber}, - {"BareNumber", "€95", 95, defaultDecimalChar, defaultGroupChar, notBareNumber}, - {"BareNumber_TrailingAtBeginning", "€95", 95, defaultDecimalChar, defaultGroupChar, notBareNumber}, - {"BareNumber_TrailingAtBeginningSpace", "EUR 95", 95, defaultDecimalChar, defaultGroupChar, notBareNumber}, - {"BareNumber_TrailingAtEnd", "95%", 95, defaultDecimalChar, defaultGroupChar, notBareNumber}, - {"BareNumber_TrailingAtEndSpace", "95 %", 95, defaultDecimalChar, defaultGroupChar, notBareNumber}, - {"GroupChar", "100,000", 100000, defaultDecimalChar, defaultGroupChar, defaultBareNumber}, - {"DecimalChar", "95;10", 95.10, ";", defaultGroupChar, defaultBareNumber}, - {"Mix", "EUR 95;10", 95.10, ";", ";", notBareNumber}, - } - for _, d := range data { - t.Run(d.desc, func(t *testing.T) { - is := is.New(t) - got, err := castNumber(d.dc, d.gc, d.bn, d.number, Constraints{}) - is.NoErr(err) - is.Equal(d.want, got) - }) - } - }) - t.Run("NaN", func(t *testing.T) { - is := is.New(t) - got, err := castNumber(defaultDecimalChar, defaultGroupChar, defaultBareNumber, "NaN", Constraints{}) - is.NoErr(err) - is.True(math.IsNaN(got)) - }) - t.Run("INF", func(t *testing.T) { - is := is.New(t) - got, err := castNumber(defaultDecimalChar, defaultGroupChar, defaultBareNumber, "INF", Constraints{}) - is.NoErr(err) - is.True(math.IsInf(got, 1)) - }) - t.Run("NegativeINF", func(t *testing.T) { - is := is.New(t) - got, err := castNumber(defaultDecimalChar, defaultGroupChar, defaultBareNumber, "-INF", Constraints{}) - is.NoErr(err) - is.True(math.IsInf(got, -1)) - }) - t.Run("ValidMaximum", func(t *testing.T) { - is := is.New(t) - _, err := castNumber(defaultDecimalChar, defaultGroupChar, defaultBareNumber, "2", Constraints{Maximum: "2"}) - is.NoErr(err) - }) - t.Run("ValidMinimum", func(t *testing.T) { - is := is.New(t) - _, err := castNumber(defaultDecimalChar, defaultGroupChar, defaultBareNumber, "2", Constraints{Minimum: "2"}) - is.NoErr(err) - }) - t.Run("Error", func(t *testing.T) { - data := []struct { - desc string - number string - dc string - gc string - bn bool - constraints Constraints - }{ - {"InvalidNumberToStrip_TooManyNumbers", "+10.10++10", defaultDecimalChar, defaultGroupChar, notBareNumber, Constraints{}}, - {"NumBiggerThanMaximum", "3", defaultDecimalChar, defaultGroupChar, notBareNumber, Constraints{Maximum: "2"}}, - {"InvalidMaximum", "1", defaultDecimalChar, defaultGroupChar, notBareNumber, Constraints{Maximum: "boo"}}, - {"NumSmallerThanMinimum", "1", defaultDecimalChar, defaultGroupChar, notBareNumber, Constraints{Minimum: "2"}}, - {"InvalidMinimum", "1", defaultDecimalChar, defaultGroupChar, notBareNumber, Constraints{Minimum: "boo"}}, - } - for _, d := range data { - t.Run(d.desc, func(t *testing.T) { - is := is.New(t) - _, err := castNumber(defaultDecimalChar, defaultGroupChar, defaultBareNumber, d.number, d.constraints) - is.True(err != nil) - }) - } - }) -} diff --git a/vendor/github.com/frictionlessdata/tableschema-go/schema/object.go b/vendor/github.com/frictionlessdata/tableschema-go/schema/object.go deleted file mode 100644 index aeb2db7..0000000 --- a/vendor/github.com/frictionlessdata/tableschema-go/schema/object.go +++ /dev/null @@ -1,16 +0,0 @@ -package schema - -import "encoding/json" - -func castObject(value string) (interface{}, error) { - var obj interface{} - if err := json.Unmarshal([]byte(value), &obj); err != nil { - return nil, err - } - return obj, nil -} - -func uncastObject(value interface{}) (string, error) { - b, err := json.Marshal(value) - return string(b), err -} diff --git a/vendor/github.com/frictionlessdata/tableschema-go/schema/object_test.go b/vendor/github.com/frictionlessdata/tableschema-go/schema/object_test.go deleted file mode 100644 index e7ece48..0000000 --- a/vendor/github.com/frictionlessdata/tableschema-go/schema/object_test.go +++ /dev/null @@ -1,26 +0,0 @@ -package schema - -import "testing" -import "github.com/matryer/is" - -type eoStruct struct { - Name string `json:"name"` -} - -func TestUncastObject(t *testing.T) { - data := []struct { - desc string - value interface{} - want string - }{ - {"Simple", eoStruct{Name: "Foo"}, `{"name":"Foo"}`}, - } - for _, d := range data { - t.Run(d.desc, func(t *testing.T) { - is := is.New(t) - got, err := uncastObject(d.value) - is.NoErr(err) - is.Equal(d.want, got) - }) - } -} diff --git a/vendor/github.com/frictionlessdata/tableschema-go/schema/schema.go b/vendor/github.com/frictionlessdata/tableschema-go/schema/schema.go deleted file mode 100644 index c683fd8..0000000 --- a/vendor/github.com/frictionlessdata/tableschema-go/schema/schema.go +++ /dev/null @@ -1,431 +0,0 @@ -package schema - -import ( - "bytes" - "encoding/json" - "fmt" - "io" - "net/http" - "os" - "reflect" - "sort" - "strings" - "sync" - "time" - - "github.com/frictionlessdata/tableschema-go/table" -) - -// InvalidPosition is returned by GetField call when -// it refers to a field that does not exist in the schema. -const InvalidPosition = -1 - -// Unexported tagname for the tableheader -const tableheaderTag = "tableheader" - -// Read reads and parses a descriptor to create a schema. -// -// Example - Reading a schema from a file: -// -// f, err := os.Open("foo/bar/schema.json") -// if err != nil { -// panic(err) -// } -// s, err := Read(f) -// if err != nil { -// panic(err) -// } -// fmt.Println(s) -func Read(r io.Reader) (*Schema, error) { - var s Schema - dec := json.NewDecoder(r) - if err := dec.Decode(&s); err != nil { - return nil, err - } - if len(s.MissingValues) == 0 { - return &s, nil - } - // Transforming the list in a set. - valueSet := make(map[string]struct{}, len(s.MissingValues)) - for _, v := range s.MissingValues { - valueSet[v] = struct{}{} - } - // Updating fields. - for i := range s.Fields { - s.Fields[i].MissingValues = make(map[string]struct{}, len(valueSet)) - for k, v := range valueSet { - s.Fields[i].MissingValues[k] = v - } - } - return &s, nil -} - -// LoadFromFile loads and parses a schema descriptor from a local file. -func LoadFromFile(path string) (*Schema, error) { - f, err := os.Open(path) - if err != nil { - return nil, err - } - return Read(f) -} - -var ( - httpClient *http.Client - once sync.Once -) - -const remoteFetchTimeoutSecs = 15 - -// LoadRemote downloads and parses a schema descriptor from the specified URL. -func LoadRemote(url string) (*Schema, error) { - once.Do(func() { - httpClient = &http.Client{ - Timeout: remoteFetchTimeoutSecs * time.Second, - } - }) - resp, err := httpClient.Get(url) - if err != nil { - return nil, err - } - defer resp.Body.Close() - return Read(resp.Body) -} - -// Fields represents a list of schema fields. -type Fields []Field - -func (f Fields) Len() int { return len(f) } -func (f Fields) Swap(i, j int) { f[i], f[j] = f[j], f[i] } -func (f Fields) Less(i, j int) bool { return strings.Compare(f[i].Name, f[j].Name) == -1 } - -// ForeignKeyReference represents the field reference by a foreign key. -type ForeignKeyReference struct { - Resource string `json:"resource,omitempty"` - Fields []string `json:"-"` - FieldsPlaceholder interface{} `json:"fields,omitempty"` -} - -// ForeignKeys defines a schema foreign key -type ForeignKeys struct { - Fields []string `json:"-"` - FieldsPlaceholder interface{} `json:"fields,omitempty"` - Reference ForeignKeyReference `json:"reference,omitempty"` -} - -// Schema describes tabular data. -type Schema struct { - Fields Fields `json:"fields,omitempty"` - PrimaryKeyPlaceholder interface{} `json:"primaryKey,omitempty"` - PrimaryKeys []string `json:"-"` - ForeignKeys ForeignKeys `json:"foreignKeys,omitempty"` - MissingValues []string `json:"missingValues,omitempty"` -} - -// GetField fetches the index and field referenced by the name argument. -func (s *Schema) GetField(name string) (*Field, int) { - for i := range s.Fields { - if name == s.Fields[i].Name { - return &s.Fields[i], i - } - } - return nil, InvalidPosition -} - -// HasField returns checks whether the schema has a field with the passed-in. -func (s *Schema) HasField(name string) bool { - _, pos := s.GetField(name) - return pos != InvalidPosition -} - -// Validate checks whether the schema is valid. If it is not, returns an error -// describing the problem. -// More at: https://specs.frictionlessdata.io/table-schema/ -func (s *Schema) Validate() error { - // Checking if all fields have a name. - for _, f := range s.Fields { - if f.Name == "" { - return fmt.Errorf("invalid field: attribute name is mandatory") - } - } - // Checking primary keys. - for _, pk := range s.PrimaryKeys { - if !s.HasField(pk) { - return fmt.Errorf("invalid primary key: there is no field %s", pk) - } - } - // Checking foreign keys. - for _, fk := range s.ForeignKeys.Fields { - if !s.HasField(fk) { - return fmt.Errorf("invalid foreign keys: there is no field %s", fk) - } - } - if len(s.ForeignKeys.Reference.Fields) != len(s.ForeignKeys.Fields) { - return fmt.Errorf("invalid foreign key: foreignKey.fields must contain the same number entries as foreignKey.reference.fields") - } - return nil -} - -// Write writes the schema descriptor. -func (s *Schema) Write(w io.Writer) error { - pp, err := json.MarshalIndent(s, "", " ") - if err != nil { - return err - } - w.Write(pp) - return nil -} - -// SaveToFile writes the schema descriptor in local file. -func (s *Schema) SaveToFile(path string) error { - f, err := os.Create(path) - if err != nil { - return err - } - return s.Write(f) -} - -// CastRow casts the passed-in row to schema types and stores it in the value pointed -// by out. The out value must be pointer to a struct. Only exported fields will be unmarshalled. -// The lowercased field name is used as the key for each exported field. -// -// If a value in the row cannot be marshalled to its respective schema field (Field.Unmarshal), -// this call will return an error. Furthermore, this call is also going to return an error if -// the schema field value can not be unmarshalled to the struct field type. -func (s *Schema) CastRow(row []string, out interface{}) error { - if reflect.ValueOf(out).Kind() != reflect.Ptr || reflect.Indirect(reflect.ValueOf(out)).Kind() != reflect.Struct { - return fmt.Errorf("can only cast pointer to structs") - } - outv := reflect.Indirect(reflect.ValueOf(out)) - outt := outv.Type() - for i := 0; i < outt.NumField(); i++ { - fieldValue := outv.Field(i) - if fieldValue.CanSet() { // Only consider exported fields. - field := outt.Field(i) - fieldName, ok := field.Tag.Lookup(tableheaderTag) - if !ok { // if no tag is set use own name - fieldName = field.Name - } - f, fieldIndex := s.GetField(fieldName) - if fieldIndex != InvalidPosition { - cell := row[fieldIndex] - if s.isMissingValue(cell) { - continue - } - v, err := f.Cast(cell) - if err != nil { - return err - } - toSetValue := reflect.ValueOf(v) - toSetType := toSetValue.Type() - if !toSetType.ConvertibleTo(field.Type) { - return fmt.Errorf("value:%s field:%s - can not convert from %v to %v", field.Name, cell, toSetType, field.Type) - } - fieldValue.Set(toSetValue.Convert(field.Type)) - } - } - } - return nil -} - -type rawCell struct { - pos int - val string -} - -type rawRow []rawCell - -func (r rawRow) Len() int { return len(r) } -func (r rawRow) Swap(i, j int) { r[i], r[j] = r[j], r[i] } -func (r rawRow) Less(i, j int) bool { return r[i].pos < r[j].pos } - -// UncastRow uncasts struct into a row. This method can only uncast structs (or pointer to structs) and -// will error out if nil is passed. -// The order of the cells in the returned row is the schema declaration order. -func (s *Schema) UncastRow(in interface{}) ([]string, error) { - inValue := reflect.Indirect(reflect.ValueOf(in)) - if inValue.Kind() != reflect.Struct { - return nil, fmt.Errorf("can only uncast structs and does not support nil pointers") - } - inType := inValue.Type() - var row rawRow - for i := 0; i < inType.NumField(); i++ { - structFieldValue := inValue.Field(i) - fieldName, ok := inType.Field(i).Tag.Lookup(tableheaderTag) - if !ok { - fieldName = inType.Field(i).Name - } - f, fieldIndex := s.GetField(fieldName) - if fieldIndex != InvalidPosition { - cell, err := f.Uncast(structFieldValue.Interface()) - if err != nil { - return nil, err - } - row = append(row, rawCell{fieldIndex, cell}) - } - } - sort.Sort(row) - ret := make([]string, len(row)) - for i := range row { - ret[i] = row[i].val - } - return ret, nil -} - -func (s *Schema) isMissingValue(value string) bool { - for _, mv := range s.MissingValues { - if mv == value { - return true - } - } - return false -} - -// UnmarshalJSON sets *f to a copy of data. It will respect the default values -// described at: https://specs.frictionlessdata.io/table-schema/ -func (s *Schema) UnmarshalJSON(data []byte) error { - // This is neded so it does not call UnmarshalJSON from recursively. - type schemaAlias Schema - var a schemaAlias - if err := json.Unmarshal(data, &a); err != nil { - return err - } - if err := processPlaceholder(a.PrimaryKeyPlaceholder, &a.PrimaryKeys); err != nil { - return fmt.Errorf("primaryKey must be either a string or list") - } - a.PrimaryKeyPlaceholder = nil - if err := processPlaceholder(a.ForeignKeys.FieldsPlaceholder, &a.ForeignKeys.Fields); err != nil { - return fmt.Errorf("foreignKeys.fields must be either a string or list") - } - a.ForeignKeys.FieldsPlaceholder = nil - if err := processPlaceholder(a.ForeignKeys.Reference.FieldsPlaceholder, &a.ForeignKeys.Reference.Fields); err != nil { - return fmt.Errorf("foreignKeys.reference.fields must be either a string or list") - } - a.ForeignKeys.Reference.FieldsPlaceholder = nil - *s = Schema(a) - return nil -} - -// MarshalJSON returns the JSON encoding of s. -func (s *Schema) MarshalJSON() ([]byte, error) { - type schemaAlias Schema - a := schemaAlias(*s) - a.PrimaryKeyPlaceholder = a.PrimaryKeys - a.ForeignKeys.Reference.FieldsPlaceholder = a.ForeignKeys.Reference.Fields - return json.Marshal(a) -} - -func processPlaceholder(ph interface{}, v *[]string) error { - if ph == nil { - return nil - } - if vStr, ok := ph.(string); ok { - *v = append(*v, vStr) - return nil - } - if vSlice, ok := ph.([]interface{}); ok { - for i := range vSlice { - *v = append(*v, vSlice[i].(string)) - } - return nil - } - // Only for signalling that an error happened. The caller knows the best - // error message. - return fmt.Errorf("") -} - -// uniqueKey represents field ID and field value which then can be used for equality tests (e.g. in a map key) -type uniqueKey struct { - KeyIndex int - KeyValue interface{} -} - -// CastTable loads and casts all table rows. -// -// The result argument must necessarily be the address for a slice. The slice -// may be nil or previously allocated. -func (s *Schema) CastTable(tab table.Table, out interface{}) error { - outv := reflect.ValueOf(out) - if outv.Kind() != reflect.Ptr || outv.Elem().Kind() != reflect.Slice { - return fmt.Errorf("out argument must be a slice address") - } - iter, err := tab.Iter() - if err != nil { - return err - } - defer iter.Close() - - uniqueFieldIndexes := extractUniqueFieldIndexes(s) - uniqueCache := make(map[uniqueKey]struct{}) - - slicev := outv.Elem() - slicev = slicev.Slice(0, 0) // Trucantes the passed-in slice. - elemt := slicev.Type().Elem() - i := 0 - for iter.Next() { - i++ - elemp := reflect.New(elemt) - if err := s.CastRow(iter.Row(), elemp.Interface()); err != nil { - return err - } - for _, k := range uniqueFieldIndexes { - field := elemp.Elem().Field(k) - if _, ok := uniqueCache[uniqueKey{k, field.Interface()}]; ok { - return fmt.Errorf("field(s) '%s' duplicates in row %v", elemp.Elem().Type().Field(k).Name, i) - } - uniqueCache[uniqueKey{k, field.Interface()}] = struct{}{} - } - slicev = reflect.Append(slicev, elemp.Elem()) - slicev = slicev.Slice(0, slicev.Len()) - } - if iter.Err() != nil { - return iter.Err() - } - outv.Elem().Set(slicev.Slice(0, i)) - return nil -} - -func extractUniqueFieldIndexes(s *Schema) []int { - uniqueIndexes := make(map[int]struct{}) - for _, pk := range s.PrimaryKeys { - _, index := s.GetField(pk) - uniqueIndexes[index] = struct{}{} - } - for i := range s.Fields { - if _, ok := uniqueIndexes[i]; !ok && s.Fields[i].Constraints.Unique { - uniqueIndexes[i] = struct{}{} - } - } - keys := make([]int, 0, len(uniqueIndexes)) - for k := range uniqueIndexes { - keys = append(keys, k) - } - return keys -} - -// UncastTable uncasts each element (struct) of the passed-in slice and -func (s *Schema) UncastTable(in interface{}) ([][]string, error) { - inVal := reflect.Indirect(reflect.ValueOf(in)) - if inVal.Kind() != reflect.Slice { - return nil, fmt.Errorf("tables must be slice of structs") - } - var t [][]string - for i := 0; i < inVal.Len(); i++ { - r, err := s.UncastRow(inVal.Index(i).Interface()) - if err != nil { - return nil, err - } - t = append(t, r) - } - return t, nil -} - -// String returns an human readable version of the schema. -func (s *Schema) String() string { - var buf bytes.Buffer - pp, err := json.Marshal(s) - if err != nil { - return "" - } - buf.Write(pp) - return buf.String() -} diff --git a/vendor/github.com/frictionlessdata/tableschema-go/schema/schema_test.go b/vendor/github.com/frictionlessdata/tableschema-go/schema/schema_test.go deleted file mode 100644 index 64f532e..0000000 --- a/vendor/github.com/frictionlessdata/tableschema-go/schema/schema_test.go +++ /dev/null @@ -1,629 +0,0 @@ -package schema - -import ( - "bytes" - "fmt" - "net/http" - "net/http/httptest" - "strings" - "testing" - - "github.com/frictionlessdata/tableschema-go/table" - "github.com/matryer/is" -) - -func ExampleSchema_CastRow() { - // Lets assume we have a schema ... - s := Schema{Fields: []Field{{Name: "Name", Type: StringType}, {Name: "Age", Type: IntegerType}}} - - // And a Table. - t := table.FromSlices([]string{"Name", "Age"}, [][]string{ - {"Foo", "42"}, - {"Bar", "43"}}) - - // And we would like to process them using Go types. First we need to create a struct to - // hold the content of each row. - // The tag tableheader maps the field to the schema. If no tag is set the name of the field - // has to be the same like inside the schema. - type person struct { - MyName string `tableheader:"Name"` - Age int - } - - // Now it is a matter of iterate over the table and Cast each row. - iter, _ := t.Iter() - for iter.Next() { - var p person - s.CastRow(iter.Row(), &p) - fmt.Printf("%+v\n", p) - } - // Output: {MyName:Foo Age:42} - // {MyName:Bar Age:43} -} - -func ExampleSchema_CastTable() { - // Lets assume we have a schema ... - s := Schema{Fields: []Field{{Name: "Name", Type: StringType}, {Name: "Age", Type: IntegerType, Constraints: Constraints{Unique: true}}}} - - // And a Table. - t := table.FromSlices([]string{"Name", "Age"}, [][]string{ - {"Foo", "42"}, - {"Bar", "43"}}) - - // And we would like to process them using Go types. First we need to create a struct to - // hold the content of each row. - // The tag tableheader maps the field to the schema. If no tag is set the name of the field - // has to be the same like inside the schema. - type person struct { - MyName string `tableheader:"Name"` - Age int - } - var people []person - s.CastTable(t, &people) - fmt.Print(people) - // Output: [{Foo 42} {Bar 43}] -} - -func ExampleSchema_UncastRow() { - // Lets assume we have a schema. - s := Schema{Fields: []Field{{Name: "Name", Type: StringType}, {Name: "Age", Type: IntegerType}}} - - // And would like to create a CSV out of this list. The tag tableheader maps - // the field to the schema name. If no tag is set the name of the field - // has to be the same like inside the schema. - people := []struct { - MyName string `tableheader:"Name"` - Age int - }{{"Foo", 42}, {"Bar", 43}} - - // First create the writer and write the header. - w := table.NewStringWriter() - w.Write([]string{"Name", "Age"}) - - // Then write the list - for _, person := range people { - row, _ := s.UncastRow(person) - w.Write(row) - } - w.Flush() - fmt.Print(w.String()) - // Output: Name,Age - // Foo,42 - // Bar,43 -} - -func ExampleSchema_UncastTable() { - // Lets assume we have a schema. - s := Schema{Fields: []Field{{Name: "Name", Type: StringType}, {Name: "Age", Type: IntegerType}}} - - // And would like to create a CSV out of this list. The tag tableheader maps - // the field to the schema name. If no tag is set the name of the field - // has to be the same like inside the schema. - people := []struct { - MyName string `tableheader:"Name"` - Age int - }{{"Foo", 42}, {"Bar", 43}} - - // Then uncast the people slice into a slice of rows. - rows, _ := s.UncastTable(people) - - // Now, simply write it down. - w := table.NewStringWriter() - w.Write([]string{"Name", "Age"}) - w.WriteAll(rows) - w.Flush() - fmt.Print(w.String()) - // Output: Name,Age - // Foo,42 - // Bar,43 -} - -func TestLoadRemote(t *testing.T) { - is := is.New(t) - h := func(w http.ResponseWriter, r *http.Request) { - fmt.Fprintf(w, `{"fields": [{"name": "ID", "type": "integer"}]}`) - } - ts := httptest.NewServer(http.HandlerFunc(h)) - defer ts.Close() - got, err := LoadRemote(ts.URL) - is.NoErr(err) - - want := &Schema{Fields: []Field{asJSONField(Field{Name: "ID", Type: "integer"})}} - is.Equal(got, want) - - t.Run("Error", func(t *testing.T) { - is := is.New(t) - _, err := LoadRemote("invalidURL") - is.True(err != nil) - }) -} - -func TestRead_Sucess(t *testing.T) { - data := []struct { - Desc string - JSON string - Schema Schema - }{ - { - "OneField", - `{ - "fields":[{"name":"n","title":"ti","type":"integer","description":"desc","format":"f","trueValues":["ntrue"],"falseValues":["nfalse"]}] - }`, - Schema{ - Fields: []Field{{Name: "n", Title: "ti", Type: "integer", Description: "desc", Format: "f", TrueValues: []string{"ntrue"}, FalseValues: []string{"nfalse"}, - DecimalChar: defaultDecimalChar, GroupChar: defaultGroupChar, BareNumber: defaultBareNumber}}, - }, - }, - { - "MultipleFields", - `{ - "fields":[{"name":"n1","type":"t1","format":"f1","falseValues":[]}, {"name":"n2","type":"t2","format":"f2","trueValues":[]}] - }`, - Schema{ - Fields: []Field{ - {Name: "n1", Type: "t1", Format: "f1", TrueValues: defaultTrueValues, FalseValues: []string{}, DecimalChar: defaultDecimalChar, GroupChar: defaultGroupChar, BareNumber: defaultBareNumber}, - {Name: "n2", Type: "t2", Format: "f2", TrueValues: []string{}, FalseValues: defaultFalseValues, DecimalChar: defaultDecimalChar, GroupChar: defaultGroupChar, BareNumber: defaultBareNumber}, - }, - }, - }, - { - "PKString", - `{"fields":[{"name":"n1"}], "primaryKey":"n1"}`, - Schema{Fields: []Field{asJSONField(Field{Name: "n1"})}, PrimaryKeys: []string{"n1"}}, - }, - { - "PKSlice", - `{"fields":[{"name":"n1"}], "primaryKey":["n1"]}`, - Schema{Fields: []Field{asJSONField(Field{Name: "n1"})}, PrimaryKeys: []string{"n1"}}, - }, - { - "FKFieldsString", - `{"fields":[{"name":"n1"}], "foreignKeys":{"fields":"n1"}}`, - Schema{Fields: []Field{asJSONField(Field{Name: "n1"})}, ForeignKeys: ForeignKeys{Fields: []string{"n1"}}}, - }, - { - "FKFieldsSlice", - `{"fields":[{"name":"n1"}], "foreignKeys":{"fields":["n1"]}}`, - Schema{Fields: []Field{asJSONField(Field{Name: "n1"})}, ForeignKeys: ForeignKeys{Fields: []string{"n1"}}}, - }, - { - "FKReferenceFieldsString", - `{"fields":[{"name":"n1"}], "foreignKeys":{"reference":{"fields":"n1"}}}`, - Schema{Fields: []Field{asJSONField(Field{Name: "n1"})}, ForeignKeys: ForeignKeys{Reference: ForeignKeyReference{Fields: []string{"n1"}}}}, - }, - { - "FKReferenceFieldsSlice", - `{"fields":[{"name":"n1"}], "foreignKeys":{"reference":{"fields":["n1"]}}}`, - Schema{Fields: []Field{asJSONField(Field{Name: "n1"})}, ForeignKeys: ForeignKeys{Reference: ForeignKeyReference{Fields: []string{"n1"}}}}, - }, - } - for _, d := range data { - t.Run(d.Desc, func(t *testing.T) { - is := is.New(t) - s, err := Read(strings.NewReader(d.JSON)) - is.NoErr(err) - is.Equal(s, &d.Schema) - }) - } - t.Run("MissingValues", func(t *testing.T) { - is := is.New(t) - reader := strings.NewReader(`{"fields":[{"name":"n","type":"integer"}],"missingValues":["na"]}`) - s, err := Read(reader) - is.NoErr(err) - - f := s.Fields[0] - _, ok := f.MissingValues["na"] - is.True(ok) - }) -} - -func TestRead_Error(t *testing.T) { - data := []struct { - Desc string - JSON string - }{ - {"InvalidSchema", `{"fields":"f1"}`}, - {"EmptyDescriptor", ""}, - {"InvalidPKType", `{"fields":[{"name":"n1"}], "primaryKey":1}`}, - {"InvalidFKFieldsType", `{"fields":[{"name":"n1"}], "foreignKeys":{"fields":1}}`}, - {"InvalidFKReferenceFieldsType", `{"fields":[{"name":"n1"}], "foreignKeys":{"reference":{"fields":1}}}`}, - } - for _, d := range data { - t.Run(d.Desc, func(t *testing.T) { - is := is.New(t) - _, err := Read(strings.NewReader(d.JSON)) - is.True(err != nil) - }) - } -} - -func TestSchema_Cast(t *testing.T) { - t.Run("NoImplicitCast", func(t *testing.T) { - is := is.New(t) - t1 := struct { - Name string - Age int64 - }{} - s := Schema{Fields: []Field{{Name: "Name", Type: StringType}, {Name: "Age", Type: IntegerType}}} - is.NoErr(s.CastRow([]string{"Foo", "42"}, &t1)) - is.Equal(t1.Name, "Foo") - is.Equal(t1.Age, int64(42)) - }) - t.Run("StructWithTags", func(t *testing.T) { - is := is.New(t) - t1 := struct { - MyName string `tableheader:"Name"` - MyAge int64 `tableheader:"Age"` - }{} - s := Schema{Fields: []Field{{Name: "Name", Type: StringType}, {Name: "Age", Type: IntegerType}}} - is.NoErr(s.CastRow([]string{"Foo", "42"}, &t1)) - is.Equal(t1.MyName, "Foo") - is.Equal(t1.MyAge, int64(42)) - }) - t.Run("ImplicitCastToInt", func(t *testing.T) { - is := is.New(t) - t1 := struct{ Age int }{} - s := Schema{Fields: []Field{{Name: "Name", Type: StringType}, {Name: "Age", Type: IntegerType}}} - is.NoErr(s.CastRow([]string{"Foo", "42"}, &t1)) - is.Equal(t1.Age, 42) - }) - t.Run("Error_SchemaFieldAndStructFieldDifferentTypes", func(t *testing.T) { - is := is.New(t) - // Field is string and struct is int. - t1 := struct{ Age int }{} - s := Schema{Fields: []Field{{Name: "Age", Type: StringType}}} - is.True(s.CastRow([]string{"42"}, &t1) != nil) - }) - t.Run("Error_NotAPointerToStruct", func(t *testing.T) { - is := is.New(t) - t1 := struct{ Age int }{} - s := Schema{Fields: []Field{{Name: "Name", Type: StringType}}} - is.True(s.CastRow([]string{"Foo", "42"}, t1) != nil) - }) - t.Run("Error_CellCanNotBeCast", func(t *testing.T) { - is := is.New(t) - // Field is string and struct is int. - t1 := struct{ Age int }{} - s := Schema{Fields: []Field{{Name: "Age", Type: IntegerType}}} - is.True(s.CastRow([]string{"foo"}, &t1) != nil) - }) - t.Run("Error_CastToNil", func(t *testing.T) { - is := is.New(t) - t1 := &struct{ Age int }{} - t1 = nil - s := Schema{Fields: []Field{{Name: "Age", Type: IntegerType}}} - is.True(s.CastRow([]string{"foo"}, &t1) != nil) - }) -} - -func TestValidate_SimpleValid(t *testing.T) { - data := []struct { - Desc string - Schema Schema - }{ - {"PrimaryKey", Schema{Fields: []Field{{Name: "p"}, {Name: "i"}}, - PrimaryKeys: []string{"p"}, - ForeignKeys: ForeignKeys{ - Fields: []string{"p"}, - Reference: ForeignKeyReference{Resource: "", Fields: []string{"i"}}, - }}, - }, - } - for _, d := range data { - t.Run(d.Desc, func(t *testing.T) { - is := is.New(t) - is.NoErr(d.Schema.Validate()) - }) - } -} - -func TestValidate_Invalid(t *testing.T) { - data := []struct { - Desc string - Schema Schema - }{ - {"MissingName", Schema{Fields: []Field{{Type: IntegerType}}}}, - {"PKNonexistingField", Schema{Fields: []Field{{Name: "n1"}}, PrimaryKeys: []string{"n2"}}}, - {"FKNonexistingField", Schema{Fields: []Field{{Name: "n1"}}, - ForeignKeys: ForeignKeys{Fields: []string{"n2"}}, - }}, - {"InvalidReferences", Schema{Fields: []Field{{Name: "n1"}}, - ForeignKeys: ForeignKeys{ - Fields: []string{"n1"}, - Reference: ForeignKeyReference{Resource: "", Fields: []string{"n1", "n2"}}, - }}, - }, - } - for _, d := range data { - t.Run(d.Desc, func(t *testing.T) { - is := is.New(t) - is.True(d.Schema.Validate() != nil) - }) - } -} - -func TestWrite(t *testing.T) { - is := is.New(t) - s := Schema{ - Fields: []Field{{Name: "Foo"}, {Name: "Bar"}}, - PrimaryKeys: []string{"Foo"}, - ForeignKeys: ForeignKeys{Reference: ForeignKeyReference{Fields: []string{"Foo"}}}, - } - buf := bytes.NewBufferString("") - is.NoErr(s.Write(buf)) - - want := `{ - "fields": [ - { - "name": "Foo", - "Constraints": {} - }, - { - "name": "Bar", - "Constraints": {} - } - ], - "primaryKey": [ - "Foo" - ], - "foreignKeys": { - "reference": { - "fields": [ - "Foo" - ] - } - } -}` - - is.Equal(buf.String(), want) -} - -func TestGetField(t *testing.T) { - t.Run("HasField", func(t *testing.T) { - is := is.New(t) - s := Schema{Fields: []Field{{Name: "Foo"}, {Name: "Bar"}}} - field, pos := s.GetField("Foo") - is.Equal(pos, 0) - is.True(field != nil) - - field, pos = s.GetField("Bar") - is.Equal(pos, 1) - is.True(field != nil) - }) - t.Run("DoesNotHaveField", func(t *testing.T) { - is := is.New(t) - s := Schema{Fields: []Field{{Name: "Bez"}}} - field, pos := s.GetField("Foo") - is.Equal(pos, InvalidPosition) - is.True(field == nil) - }) -} - -func TestHasField(t *testing.T) { - t.Run("HasField", func(t *testing.T) { - is := is.New(t) - s := Schema{Fields: []Field{{Name: "Foo"}, {Name: "Bar"}}} - is.True(s.HasField("Foo")) - is.True(s.HasField("Bar")) - }) - t.Run("DoesNotHaveField", func(t *testing.T) { - is := is.New(t) - s := Schema{Fields: []Field{{Name: "Bez"}}} - is.True(!s.HasField("Bar")) - }) -} - -func TestMissingValues(t *testing.T) { - is := is.New(t) - s := Schema{ - Fields: []Field{{Name: "Foo"}}, - MissingValues: []string{"f"}, - } - row := struct { - Foo string - }{} - s.CastRow([]string{"f"}, &row) - is.Equal(row.Foo, "") -} - -type csvRow struct { - Name string -} - -func TestCastTable(t *testing.T) { - data := []struct { - desc string - got []csvRow - }{ - {"OutEmpty", []csvRow{}}, - {"OutNil", nil}, - {"OutInitialized", []csvRow{{"fooooo"}}}, - } - for _, d := range data { - t.Run(d.desc, func(t *testing.T) { - is := is.New(t) - tab := table.FromSlices( - []string{"Name"}, - [][]string{{"foo"}, {"bar"}}) - s := &Schema{Fields: []Field{{Name: "Name", Type: StringType}}} - is.NoErr(s.CastTable(tab, &d.got)) - - want := []csvRow{{"foo"}, {"bar"}} - is.Equal(want, d.got) - }) - } - t.Run("MoarData", func(t *testing.T) { - is := is.New(t) - tab := table.FromSlices( - []string{"ID", "Age", "Name"}, - [][]string{{"1", "39", "Paul"}, {"2", "23", "Jimmy"}, {"3", "36", "Jane"}, {"4", "28", "Judy"}, {"5", "37", "Iñtërnâtiônàlizætiøn"}}) - - type data struct { - ID int - Age int - Name string - } - s := &Schema{Fields: []Field{{Name: "ID", Type: IntegerType}, {Name: "Age", Type: IntegerType}, {Name: "Name", Type: StringType}}} - got := []data{} - is.NoErr(s.CastTable(tab, &got)) - - want := []data{{1, 39, "Paul"}, {2, 23, "Jimmy"}, {3, 36, "Jane"}, {4, 28, "Judy"}, {5, 37, "Iñtërnâtiônàlizætiøn"}} - is.Equal(want, got) - }) - t.Run("EmptyTable", func(t *testing.T) { - is := is.New(t) - tab := table.FromSlices([]string{}, [][]string{}) - s := &Schema{Fields: []Field{{Name: "name", Type: StringType}}} - var got []csvRow - is.NoErr(s.CastTable(tab, &got)) - is.Equal(len(got), 0) - }) - t.Run("Error_OutNotAPointerToSlice", func(t *testing.T) { - is := is.New(t) - tab := table.FromSlices([]string{"name"}, [][]string{{""}}) - s := &Schema{Fields: []Field{{Name: "name", Type: StringType}}} - is.True(s.CastTable(tab, []csvRow{}) != nil) - }) - t.Run("Error_UniqueConstrain", func(t *testing.T) { - tab := table.FromSlices( - []string{"ID", "Point"}, - [][]string{{"1", "10,11"}, {"2", "11,10"}, {"3", "10,10"}, {"4", "10,11"}}) - s := &Schema{Fields: []Field{{Name: "ID", Type: IntegerType}, {Name: "Point", Type: GeoPointType, Constraints: Constraints{Unique: true}}}} - - type data struct { - ID int - Point GeoPoint - } - got := []data{} - if err := s.CastTable(tab, &got); err == nil { - t.Fatalf("err want:err got:nil") - } - if len(got) != 0 { - t.Fatalf("len(got) want:0 got:%v", len(got)) - } - }) - t.Run("Error_PrimaryKeyAndUniqueConstrain", func(t *testing.T) { - tab := table.FromSlices( - []string{"ID", "Age", "Name"}, - [][]string{{"1", "39", "Paul"}, {"2", "23", "Jimmy"}, {"3", "36", "Jane"}, {"4", "28", "Judy"}, {"4", "37", "John"}}) - - type data struct { - ID int - Age int - Name string - } - s := &Schema{Fields: []Field{{Name: "ID", Type: IntegerType}, {Name: "Age", Type: IntegerType}, {Name: "Name", Type: StringType, Constraints: Constraints{Unique: true}}}, PrimaryKeys: []string{"ID"}} - got := []data{} - if err := s.CastTable(tab, &got); err == nil { - t.Fatalf("err want:nil got:%q", err) - } - if len(got) != 0 { - t.Fatalf("len(got) want:0 got:%v", len(got)) - } - }) -} - -func TestSchema_Uncast(t *testing.T) { - t.Run("Success", func(t *testing.T) { - is := is.New(t) - type rowType struct { - Name string - Age int - } - s := Schema{Fields: []Field{{Name: "Name", Type: StringType}, {Name: "Age", Type: IntegerType}}} - got, err := s.UncastRow(rowType{Name: "Foo", Age: 42}) - is.NoErr(err) - - want := []string{"Foo", "42"} - is.Equal(want, got) - }) - t.Run("SuccessWithTags", func(t *testing.T) { - is := is.New(t) - type rowType struct { - MyName string `tableheader:"Name"` - MyAge int `tableheader:"Age"` - } - s := Schema{Fields: []Field{{Name: "Name", Type: StringType}, {Name: "Age", Type: IntegerType}}} - got, err := s.UncastRow(rowType{MyName: "Foo", MyAge: 42}) - is.NoErr(err) - is.Equal([]string{"Foo", "42"}, got) - }) - t.Run("SuccessSchemaMoreFieldsThanStruct", func(t *testing.T) { - is := is.New(t) - s := Schema{Fields: Fields{{Name: "Age", Type: IntegerType}, {Name: "Name", Type: StringType}}} - in := csvRow{Name: "Foo"} - got, err := s.UncastRow(&in) - if err != nil { - t.Fatalf("err want:nil got:%q", err) - } - is.Equal([]string{"Foo"}, got) - }) - t.Run("SuccessStructHasMoreFieldsThanSchema", func(t *testing.T) { - is := is.New(t) - // Note: deliberately changed the order to make the test more interesting. - type rowType struct { - Age int - Name string - Bar float64 - Bez string - } - s := Schema{Fields: []Field{{Name: "Name", Type: StringType}, {Name: "Bez", Type: StringType}}} - got, err := s.UncastRow(rowType{Age: 42, Bez: "Bez", Name: "Foo"}) - is.NoErr(err) - is.Equal([]string{"Foo", "Bez"}, got) - }) - t.Run("Error_Encoding", func(t *testing.T) { - is := is.New(t) - type rowType struct { - Age string - } - s := Schema{Fields: []Field{{Name: "Age", Type: IntegerType}}} - _, err := s.UncastRow(rowType{Age: "10"}) - is.True(err != nil) - }) - t.Run("Error_NotStruct", func(t *testing.T) { - is := is.New(t) - s := Schema{Fields: []Field{{Name: "name", Type: StringType}}} - in := "string" - _, err := s.UncastRow(in) - is.True(err != nil) - }) - t.Run("Error_StructIsNil", func(t *testing.T) { - is := is.New(t) - s := Schema{Fields: []Field{{Name: "name", Type: StringType}}} - var in *csvRow - _, err := s.UncastRow(in) - is.True(err != nil) - }) -} - -func TestUncastTable(t *testing.T) { - t.Run("Simple", func(t *testing.T) { - is := is.New(t) - people := []struct { - Name string - }{{"Foo"}, {"Bar"}, {"Bez"}} - s := Schema{Fields: []Field{{Name: "Name", Type: StringType}}} - got, err := s.UncastTable(people) - is.NoErr(err) - - want := [][]string{{"Foo"}, {"Bar"}, {"Bez"}} - is.Equal(want, got) - }) - - t.Run("Error_InputIsNotASlice", func(t *testing.T) { - is := is.New(t) - s := Schema{Fields: []Field{{Name: "Name", Type: StringType}}} - _, err := s.UncastTable(10) - is.True(err != nil) - }) - t.Run("Error_ErrorEncoding", func(t *testing.T) { - is := is.New(t) - people := []struct { - Name string - }{{"Foo"}} - s := Schema{Fields: []Field{{Name: "Name", Type: IntegerType}}} - _, err := s.UncastTable(people) - is.True(err != nil) - }) -} diff --git a/vendor/github.com/frictionlessdata/tableschema-go/schema/string.go b/vendor/github.com/frictionlessdata/tableschema-go/schema/string.go deleted file mode 100644 index ce6cbbd..0000000 --- a/vendor/github.com/frictionlessdata/tableschema-go/schema/string.go +++ /dev/null @@ -1,59 +0,0 @@ -package schema - -import ( - "fmt" - "github.com/satori/go.uuid" - "net/mail" - "net/url" -) - -// Valid string formats and configuration. -const ( - stringURI = "uri" - stringEmail = "email" - stringUUID = "uuid" - stringBinary = "binary" - stringUUIDVersion = 4 -) - -func checkStringConstraints(v string, c Constraints) error { - minLength := c.MinLength - maxLength := c.MaxLength - re := c.compiledPattern - - if minLength != 0 && len(v) < minLength { - return fmt.Errorf("constraint check error: %v %v < minimum:%v", v, len(v), minLength) - } - if maxLength != 0 && len(v) > maxLength { - return fmt.Errorf("constraint check error: %v %v > maximum:%v", v, len(v), maxLength) - } - - if re != nil && !re.MatchString(v) { - return fmt.Errorf("constraint check error: %v don't fit pattern : %v ", v, c.Pattern) - } - return nil -} - -func castString(format, value string, c Constraints) (string, error) { - err := checkStringConstraints(value, c) - if err != nil { - return value, err - } - - switch format { - case stringURI: - _, err := url.ParseRequestURI(value) - return value, err - case stringEmail: - _, err := mail.ParseAddress(value) - return value, err - case stringUUID: - v, err := uuid.FromString(value) - if v.Version() != stringUUIDVersion { - return value, fmt.Errorf("invalid UUID version - got:%d want:%d", v.Version(), stringUUIDVersion) - } - return value, err - } - // NOTE: Returning the value for unknown format is in par with the python library. - return value, nil -} diff --git a/vendor/github.com/frictionlessdata/tableschema-go/schema/string_test.go b/vendor/github.com/frictionlessdata/tableschema-go/schema/string_test.go deleted file mode 100644 index 96e3722..0000000 --- a/vendor/github.com/frictionlessdata/tableschema-go/schema/string_test.go +++ /dev/null @@ -1,69 +0,0 @@ -package schema - -import ( - "regexp" - "testing" - - "github.com/matryer/is" -) - -// To be in par with the python library. -func TestCastString_URIMustRequireScheme(t *testing.T) { - is := is.New(t) - _, err := castString(stringURI, "google.com", Constraints{}) - is.True(err != nil) -} - -func TestCastString_InvalidUUIDVersion(t *testing.T) { - is := is.New(t) - // This is a uuid3: namespace DNS and python.org. - _, err := castString(stringUUID, "6fa459ea-ee8a-3ca4-894e-db77e160355e", Constraints{}) - is.True(err != nil) -} - -func TestCastString_ErrorCheckingConstraints(t *testing.T) { - data := []struct { - desc string - value string - format string - constraints Constraints - }{ - {"InvalidMinLength_UUID", "6fa459ea-ee8a-3ca4-894e-db77e160355e", stringUUID, Constraints{MinLength: 100}}, - {"InvalidMinLength_Email", "foo@bar.com", stringEmail, Constraints{MinLength: 100}}, - {"InvalidMinLength_URI", "http://google.com", stringURI, Constraints{MinLength: 100}}, - {"InvalidMaxLength_UUID", "6fa459ea-ee8a-3ca4-894e-db77e160355e", stringUUID, Constraints{MaxLength: 1}}, - {"InvalidMaxLength_Email", "foo@bar.com", stringEmail, Constraints{MaxLength: 1}}, - {"InvalidMaxLength_URI", "http://google.com", stringURI, Constraints{MaxLength: 1}}, - {"InvalidPattern_UUID", "6fa459ea-ee8a-3ca4-894e-db77e160355e", stringUUID, Constraints{compiledPattern: regexp.MustCompile("^[0-9a-f]{1}-.*"), Pattern: "^[0-9a-f]{1}-.*"}}, - {"InvalidPattern_Email", "foo@bar.com", stringEmail, Constraints{compiledPattern: regexp.MustCompile("[0-9].*"), Pattern: "[0-9].*"}}, - {"InvalidPattern_URI", "http://google.com", stringURI, Constraints{compiledPattern: regexp.MustCompile("^//.*"), Pattern: "^//.*"}}, - } - for _, d := range data { - t.Run(d.desc, func(t *testing.T) { - is := is.New(t) - _, err := castString(d.format, d.value, d.constraints) - is.True(err != nil) - }) - } -} - -func TestCastString_Success(t *testing.T) { - var data = []struct { - desc string - value string - format string - constraints Constraints - }{ - {"URI", "http://google.com", stringURI, Constraints{MinLength: 1, compiledPattern: regexp.MustCompile("^http://.*"), Pattern: "^http://.*"}}, - {"Email", "foo@bar.com", stringEmail, Constraints{MinLength: 1, compiledPattern: regexp.MustCompile(".*@.*"), Pattern: ".*@.*"}}, - {"UUID", "C56A4180-65AA-42EC-A945-5FD21DEC0538", stringUUID, Constraints{MinLength: 36, MaxLength: 36, compiledPattern: regexp.MustCompile("[0-9A-F]{8}-[0-9A-F]{4}-[0-9A-F]{4}-[0-9A-F]{4}-[0-9A-F]{12}"), Pattern: "[0-9A-F]{8}-[0-9A-F]{4}-[0-9A-F]{4}-[0-9A-F]{4}-[0-9A-F]{12}"}}, - } - for _, d := range data { - t.Run(d.desc, func(t *testing.T) { - is := is.New(t) - v, err := castString(d.format, d.value, d.constraints) - is.NoErr(err) - is.Equal(v, d.value) - }) - } -} diff --git a/vendor/github.com/frictionlessdata/tableschema-go/schema/time.go b/vendor/github.com/frictionlessdata/tableschema-go/schema/time.go deleted file mode 100644 index 9d72815..0000000 --- a/vendor/github.com/frictionlessdata/tableschema-go/schema/time.go +++ /dev/null @@ -1,41 +0,0 @@ -package schema - -import ( - "fmt" - "reflect" - "time" -) - -func castTime(format, value string, c Constraints) (time.Time, error) { - y, err := castTimeWithoutCheckConstraints(format, value) - if err != nil { - return y, err - } - var max, min time.Time - if c.Maximum != "" { - max, err = castTimeWithoutCheckConstraints(format, c.Maximum) - if err != nil { - return y, err - } - } - if c.Minimum != "" { - min, err = castTimeWithoutCheckConstraints(format, c.Minimum) - if err != nil { - return y, err - } - } - return checkConstraints(y, max, min, TimeType) -} - -func castTimeWithoutCheckConstraints(format, value string) (time.Time, error) { - return castDefaultOrCustomTime("03:04:05", format, value) -} - -func uncastTime(v interface{}) (string, error) { - value, ok := v.(time.Time) - if !ok { - return "", fmt.Errorf("invalid date - value:%v type:%v", v, reflect.ValueOf(v).Type()) - } - utc := value.In(time.UTC) - return utc.Format(time.RFC3339), nil -} diff --git a/vendor/github.com/frictionlessdata/tableschema-go/schema/time_test.go b/vendor/github.com/frictionlessdata/tableschema-go/schema/time_test.go deleted file mode 100644 index fc3c980..0000000 --- a/vendor/github.com/frictionlessdata/tableschema-go/schema/time_test.go +++ /dev/null @@ -1,76 +0,0 @@ -package schema - -import ( - "testing" - "time" - - "github.com/matryer/is" -) - -func TestCastTime(t *testing.T) { - t.Run("ValidMaximum", func(t *testing.T) { - is := is.New(t) - _, err := castTime(defaultFieldFormat, "11:45:00", Constraints{Maximum: "11:45:01"}) - is.NoErr(err) - }) - t.Run("ValidMinimum", func(t *testing.T) { - is := is.New(t) - _, err := castTime(defaultFieldFormat, "11:45:00", Constraints{Minimum: "11:44:59"}) - is.NoErr(err) - }) - t.Run("Error", func(t *testing.T) { - data := []struct { - desc string - time string - constraints Constraints - }{ - {"InvalidYear", "foo", Constraints{}}, - {"BiggerThanMaximum", "11:45:00", Constraints{Maximum: "11:44:59"}}, - {"InvalidMaximum", "11:45:00", Constraints{Maximum: "boo"}}, - {"SmallerThanMinimum", "11:45:00", Constraints{Minimum: "11:45:01"}}, - {"InvalidMinimum", "11:45:00", Constraints{Minimum: "boo"}}, - } - for _, d := range data { - t.Run(d.desc, func(t *testing.T) { - is := is.New(t) - _, err := castTime(defaultFieldFormat, d.time, d.constraints) - is.True(err != nil) - }) - } - }) -} - -func TestUncastTime(t *testing.T) { - t.Run("Success", func(t *testing.T) { - data := []struct { - desc string - value time.Time - want string - }{ - {"SimpleDate", time.Unix(1, 0), "1970-01-01T00:00:01Z"}, - } - for _, d := range data { - t.Run(d.desc, func(t *testing.T) { - is := is.New(t) - got, err := uncastTime(d.value) - is.NoErr(err) - is.Equal(d.want, got) - }) - } - }) - t.Run("Error", func(t *testing.T) { - data := []struct { - desc string - value interface{} - }{ - {"InvalidType", "Boo"}, - } - for _, d := range data { - t.Run(d.desc, func(t *testing.T) { - is := is.New(t) - _, err := uncastTime(d.value) - is.True(err != nil) - }) - } - }) -} diff --git a/vendor/github.com/frictionlessdata/tableschema-go/table/table.go b/vendor/github.com/frictionlessdata/tableschema-go/table/table.go deleted file mode 100644 index 0983369..0000000 --- a/vendor/github.com/frictionlessdata/tableschema-go/table/table.go +++ /dev/null @@ -1,137 +0,0 @@ -// Package table provides the main interfaces used to manipulate tabular data. -// To understand why we need interfaces to process tabular data, it is useful to introduce -// the concepts of the physical and the logical representation of data. -// -// The physical representation of data refers to the representation of data as text on disk, -// for example, in a CSV, JSON or XML file. This representation may have some type information (JSON, -// where the primitive types that JSON supports can be used) or not (CSV, where all data is -// represented in string form). In this project, those are going to be presented as packages that -// provide structs which implement those interfaces. For instance, csv.NewTable creates a Table -// which is backed up by a CSV. -// -// The logical representation of data refers to the "ideal" representation of the data in terms of -// primitive types, data structures, and relations, all as defined by the specification. We could say -// that the specification is about the logical representation of data. That said, functions -// exported for data processing should deal with logic representations. That functionality -// is represented by interfaces in this package. -package table - -import ( - "bytes" - "encoding/csv" -) - -// Table provides functionality to iterate and write tabular data. This is the logical -// representation and is meant to be encoding/format agnostic. -type Table interface { - // Headers returns the headers of the tabular data. - Headers() []string - - // Iter provides a convenient way to iterate over table's data. - // The iteration process always start at the beginning of the table and - // is backed by a new reading. - Iter() (Iterator, error) - - // ReadAll reads all rows from the table and return it as strings. - ReadAll() ([][]string, error) -} - -// A Writer writes rows to a table file. The idea behind the writer is to -// abstract out the physical representation of the table. Which can have -// many formats, for instance, CSV, XML and JSON -type Writer interface { - // Write writes a single row to w along with any necessary quoting. - // A record is a slice of strings with each string being one field. - Write(record []string) error - // Flush writes any buffered data to the underlying io.Writer. - // To check if an error occurred during the Flush, call Error. - Flush() - // Error reports any error that has occurred during a previous Write or Flush. - Error() error - // WriteAll writes multiple CSV records to w using Write and then calls Flush. - WriteAll(records [][]string) error -} - -// StringWriter is a simple Writer implementation which is backed up by -// an in memory bytes.Buffer. -type StringWriter struct { - csv.Writer - - content *bytes.Buffer -} - -// String returns the content that has been written so far as raw CSV. -func (s *StringWriter) String() string { - return s.content.String() -} - -// NewStringWriter returns a Writer that writes CSV to a string. -// It exports a String() method, which returns its contents. -func NewStringWriter() *StringWriter { - buf := &bytes.Buffer{} - return &StringWriter{*csv.NewWriter(buf), buf} -} - -// FromSlices creates a new SliceTable using passed-in arguments. -func FromSlices(headers []string, content [][]string) *SliceTable { - return &SliceTable{headers, content} -} - -// SliceTable offers a simple table implementation backed by slices. -type SliceTable struct { - headers []string - content [][]string -} - -// Headers returns the headers of the tabular data. -func (t *SliceTable) Headers() []string { - return t.headers -} - -// ReadAll reads all rows from the table and return it as strings. -func (t *SliceTable) ReadAll() ([][]string, error) { - return t.content, nil -} - -// Iter provides a convenient way to iterate over table's data. -// The iteration process always start at the beginning of the table and -// is backed by a new reading process. -func (t *SliceTable) Iter() (Iterator, error) { - return &sliceIterator{content: t.content}, nil -} - -type sliceIterator struct { - content [][]string - pos int -} - -func (i *sliceIterator) Next() bool { - i.pos++ - return i.pos <= len(i.content) -} -func (i *sliceIterator) Row() []string { return i.content[i.pos-1] } -func (i *sliceIterator) Err() error { return nil } -func (i *sliceIterator) Close() error { return nil } - -// Iterator is an interface which provides method to interating over tabular -// data. It is heavly inspired by bufio.Scanner. -// Iterating stops unrecoverably at EOF, the first I/O error, or a token too large to fit in the buffer. -type Iterator interface { - // Next advances the table interator to the next row, which will be available through the Cast or Row methods. - // It returns false when the iterator stops, either by reaching the end of the table or an error. - // After Next returns false, the Err method will return any error that ocurred during the iteration, except if it was io.EOF, Err - // will return nil. - // Next could automatically buffer some data, improving reading performance. It could also block, if necessary. - Next() bool - - // Row returns the most recent row fetched by a call to Next as a newly allocated string slice - // holding its fields. - Row() []string - - // Err returns nil if no errors happened during iteration, or the actual error - // otherwise. - Err() error - - // Close frees up any resources used during the iteration process. - Close() error -} diff --git a/vendor/github.com/matryer/is/.gitignore b/vendor/github.com/matryer/is/.gitignore deleted file mode 100644 index daf913b..0000000 --- a/vendor/github.com/matryer/is/.gitignore +++ /dev/null @@ -1,24 +0,0 @@ -# Compiled Object files, Static and Dynamic libs (Shared Objects) -*.o -*.a -*.so - -# Folders -_obj -_test - -# Architecture specific extensions/prefixes -*.[568vq] -[568vq].out - -*.cgo1.go -*.cgo2.c -_cgo_defun.c -_cgo_gotypes.go -_cgo_export.* - -_testmain.go - -*.exe -*.test -*.prof diff --git a/vendor/github.com/matryer/is/.travis.yml b/vendor/github.com/matryer/is/.travis.yml deleted file mode 100644 index a7efa7b..0000000 --- a/vendor/github.com/matryer/is/.travis.yml +++ /dev/null @@ -1,19 +0,0 @@ -language: go - -sudo: required - -go: - - 1.6.x - - 1.7.x - - tip - -env: - - GIMME_OS=linux GIMME_ARCH=amd64 - - GIMME_OS=darwin GIMME_ARCH=amd64 - - GIMME_OS=windows GIMME_ARCH=amd64 - -install: - - go get -d -v ./... - -script: - - go build -v ./... diff --git a/vendor/github.com/matryer/is/LICENSE b/vendor/github.com/matryer/is/LICENSE deleted file mode 100644 index 9cecc1d..0000000 --- a/vendor/github.com/matryer/is/LICENSE +++ /dev/null @@ -1,674 +0,0 @@ - GNU GENERAL PUBLIC LICENSE - Version 3, 29 June 2007 - - Copyright (C) 2007 Free Software Foundation, Inc. - Everyone is permitted to copy and distribute verbatim copies - of this license document, but changing it is not allowed. - - Preamble - - The GNU General Public License is a free, copyleft license for -software and other kinds of works. - - The licenses for most software and other practical works are designed -to take away your freedom to share and change the works. By contrast, -the GNU General Public License is intended to guarantee your freedom to -share and change all versions of a program--to make sure it remains free -software for all its users. We, the Free Software Foundation, use the -GNU General Public License for most of our software; it applies also to -any other work released this way by its authors. You can apply it to -your programs, too. - - When we speak of free software, we are referring to freedom, not -price. Our General Public Licenses are designed to make sure that you -have the freedom to distribute copies of free software (and charge for -them if you wish), that you receive source code or can get it if you -want it, that you can change the software or use pieces of it in new -free programs, and that you know you can do these things. - - To protect your rights, we need to prevent others from denying you -these rights or asking you to surrender the rights. Therefore, you have -certain responsibilities if you distribute copies of the software, or if -you modify it: responsibilities to respect the freedom of others. - - For example, if you distribute copies of such a program, whether -gratis or for a fee, you must pass on to the recipients the same -freedoms that you received. You must make sure that they, too, receive -or can get the source code. And you must show them these terms so they -know their rights. - - Developers that use the GNU GPL protect your rights with two steps: -(1) assert copyright on the software, and (2) offer you this License -giving you legal permission to copy, distribute and/or modify it. - - For the developers' and authors' protection, the GPL clearly explains -that there is no warranty for this free software. For both users' and -authors' sake, the GPL requires that modified versions be marked as -changed, so that their problems will not be attributed erroneously to -authors of previous versions. - - Some devices are designed to deny users access to install or run -modified versions of the software inside them, although the manufacturer -can do so. This is fundamentally incompatible with the aim of -protecting users' freedom to change the software. The systematic -pattern of such abuse occurs in the area of products for individuals to -use, which is precisely where it is most unacceptable. Therefore, we -have designed this version of the GPL to prohibit the practice for those -products. If such problems arise substantially in other domains, we -stand ready to extend this provision to those domains in future versions -of the GPL, as needed to protect the freedom of users. - - Finally, every program is threatened constantly by software patents. -States should not allow patents to restrict development and use of -software on general-purpose computers, but in those that do, we wish to -avoid the special danger that patents applied to a free program could -make it effectively proprietary. To prevent this, the GPL assures that -patents cannot be used to render the program non-free. - - The precise terms and conditions for copying, distribution and -modification follow. - - TERMS AND CONDITIONS - - 0. Definitions. - - "This License" refers to version 3 of the GNU General Public License. - - "Copyright" also means copyright-like laws that apply to other kinds of -works, such as semiconductor masks. - - "The Program" refers to any copyrightable work licensed under this -License. Each licensee is addressed as "you". "Licensees" and -"recipients" may be individuals or organizations. - - To "modify" a work means to copy from or adapt all or part of the work -in a fashion requiring copyright permission, other than the making of an -exact copy. The resulting work is called a "modified version" of the -earlier work or a work "based on" the earlier work. - - A "covered work" means either the unmodified Program or a work based -on the Program. - - To "propagate" a work means to do anything with it that, without -permission, would make you directly or secondarily liable for -infringement under applicable copyright law, except executing it on a -computer or modifying a private copy. Propagation includes copying, -distribution (with or without modification), making available to the -public, and in some countries other activities as well. - - To "convey" a work means any kind of propagation that enables other -parties to make or receive copies. Mere interaction with a user through -a computer network, with no transfer of a copy, is not conveying. - - An interactive user interface displays "Appropriate Legal Notices" -to the extent that it includes a convenient and prominently visible -feature that (1) displays an appropriate copyright notice, and (2) -tells the user that there is no warranty for the work (except to the -extent that warranties are provided), that licensees may convey the -work under this License, and how to view a copy of this License. If -the interface presents a list of user commands or options, such as a -menu, a prominent item in the list meets this criterion. - - 1. Source Code. - - The "source code" for a work means the preferred form of the work -for making modifications to it. "Object code" means any non-source -form of a work. - - A "Standard Interface" means an interface that either is an official -standard defined by a recognized standards body, or, in the case of -interfaces specified for a particular programming language, one that -is widely used among developers working in that language. - - The "System Libraries" of an executable work include anything, other -than the work as a whole, that (a) is included in the normal form of -packaging a Major Component, but which is not part of that Major -Component, and (b) serves only to enable use of the work with that -Major Component, or to implement a Standard Interface for which an -implementation is available to the public in source code form. A -"Major Component", in this context, means a major essential component -(kernel, window system, and so on) of the specific operating system -(if any) on which the executable work runs, or a compiler used to -produce the work, or an object code interpreter used to run it. - - The "Corresponding Source" for a work in object code form means all -the source code needed to generate, install, and (for an executable -work) run the object code and to modify the work, including scripts to -control those activities. However, it does not include the work's -System Libraries, or general-purpose tools or generally available free -programs which are used unmodified in performing those activities but -which are not part of the work. For example, Corresponding Source -includes interface definition files associated with source files for -the work, and the source code for shared libraries and dynamically -linked subprograms that the work is specifically designed to require, -such as by intimate data communication or control flow between those -subprograms and other parts of the work. - - The Corresponding Source need not include anything that users -can regenerate automatically from other parts of the Corresponding -Source. - - The Corresponding Source for a work in source code form is that -same work. - - 2. Basic Permissions. - - All rights granted under this License are granted for the term of -copyright on the Program, and are irrevocable provided the stated -conditions are met. This License explicitly affirms your unlimited -permission to run the unmodified Program. The output from running a -covered work is covered by this License only if the output, given its -content, constitutes a covered work. This License acknowledges your -rights of fair use or other equivalent, as provided by copyright law. - - You may make, run and propagate covered works that you do not -convey, without conditions so long as your license otherwise remains -in force. You may convey covered works to others for the sole purpose -of having them make modifications exclusively for you, or provide you -with facilities for running those works, provided that you comply with -the terms of this License in conveying all material for which you do -not control copyright. Those thus making or running the covered works -for you must do so exclusively on your behalf, under your direction -and control, on terms that prohibit them from making any copies of -your copyrighted material outside their relationship with you. - - Conveying under any other circumstances is permitted solely under -the conditions stated below. Sublicensing is not allowed; section 10 -makes it unnecessary. - - 3. Protecting Users' Legal Rights From Anti-Circumvention Law. - - No covered work shall be deemed part of an effective technological -measure under any applicable law fulfilling obligations under article -11 of the WIPO copyright treaty adopted on 20 December 1996, or -similar laws prohibiting or restricting circumvention of such -measures. - - When you convey a covered work, you waive any legal power to forbid -circumvention of technological measures to the extent such circumvention -is effected by exercising rights under this License with respect to -the covered work, and you disclaim any intention to limit operation or -modification of the work as a means of enforcing, against the work's -users, your or third parties' legal rights to forbid circumvention of -technological measures. - - 4. Conveying Verbatim Copies. - - You may convey verbatim copies of the Program's source code as you -receive it, in any medium, provided that you conspicuously and -appropriately publish on each copy an appropriate copyright notice; -keep intact all notices stating that this License and any -non-permissive terms added in accord with section 7 apply to the code; -keep intact all notices of the absence of any warranty; and give all -recipients a copy of this License along with the Program. - - You may charge any price or no price for each copy that you convey, -and you may offer support or warranty protection for a fee. - - 5. Conveying Modified Source Versions. - - You may convey a work based on the Program, or the modifications to -produce it from the Program, in the form of source code under the -terms of section 4, provided that you also meet all of these conditions: - - a) The work must carry prominent notices stating that you modified - it, and giving a relevant date. - - b) The work must carry prominent notices stating that it is - released under this License and any conditions added under section - 7. This requirement modifies the requirement in section 4 to - "keep intact all notices". - - c) You must license the entire work, as a whole, under this - License to anyone who comes into possession of a copy. This - License will therefore apply, along with any applicable section 7 - additional terms, to the whole of the work, and all its parts, - regardless of how they are packaged. This License gives no - permission to license the work in any other way, but it does not - invalidate such permission if you have separately received it. - - d) If the work has interactive user interfaces, each must display - Appropriate Legal Notices; however, if the Program has interactive - interfaces that do not display Appropriate Legal Notices, your - work need not make them do so. - - A compilation of a covered work with other separate and independent -works, which are not by their nature extensions of the covered work, -and which are not combined with it such as to form a larger program, -in or on a volume of a storage or distribution medium, is called an -"aggregate" if the compilation and its resulting copyright are not -used to limit the access or legal rights of the compilation's users -beyond what the individual works permit. Inclusion of a covered work -in an aggregate does not cause this License to apply to the other -parts of the aggregate. - - 6. Conveying Non-Source Forms. - - You may convey a covered work in object code form under the terms -of sections 4 and 5, provided that you also convey the -machine-readable Corresponding Source under the terms of this License, -in one of these ways: - - a) Convey the object code in, or embodied in, a physical product - (including a physical distribution medium), accompanied by the - Corresponding Source fixed on a durable physical medium - customarily used for software interchange. - - b) Convey the object code in, or embodied in, a physical product - (including a physical distribution medium), accompanied by a - written offer, valid for at least three years and valid for as - long as you offer spare parts or customer support for that product - model, to give anyone who possesses the object code either (1) a - copy of the Corresponding Source for all the software in the - product that is covered by this License, on a durable physical - medium customarily used for software interchange, for a price no - more than your reasonable cost of physically performing this - conveying of source, or (2) access to copy the - Corresponding Source from a network server at no charge. - - c) Convey individual copies of the object code with a copy of the - written offer to provide the Corresponding Source. This - alternative is allowed only occasionally and noncommercially, and - only if you received the object code with such an offer, in accord - with subsection 6b. - - d) Convey the object code by offering access from a designated - place (gratis or for a charge), and offer equivalent access to the - Corresponding Source in the same way through the same place at no - further charge. You need not require recipients to copy the - Corresponding Source along with the object code. If the place to - copy the object code is a network server, the Corresponding Source - may be on a different server (operated by you or a third party) - that supports equivalent copying facilities, provided you maintain - clear directions next to the object code saying where to find the - Corresponding Source. Regardless of what server hosts the - Corresponding Source, you remain obligated to ensure that it is - available for as long as needed to satisfy these requirements. - - e) Convey the object code using peer-to-peer transmission, provided - you inform other peers where the object code and Corresponding - Source of the work are being offered to the general public at no - charge under subsection 6d. - - A separable portion of the object code, whose source code is excluded -from the Corresponding Source as a System Library, need not be -included in conveying the object code work. - - A "User Product" is either (1) a "consumer product", which means any -tangible personal property which is normally used for personal, family, -or household purposes, or (2) anything designed or sold for incorporation -into a dwelling. In determining whether a product is a consumer product, -doubtful cases shall be resolved in favor of coverage. For a particular -product received by a particular user, "normally used" refers to a -typical or common use of that class of product, regardless of the status -of the particular user or of the way in which the particular user -actually uses, or expects or is expected to use, the product. A product -is a consumer product regardless of whether the product has substantial -commercial, industrial or non-consumer uses, unless such uses represent -the only significant mode of use of the product. - - "Installation Information" for a User Product means any methods, -procedures, authorization keys, or other information required to install -and execute modified versions of a covered work in that User Product from -a modified version of its Corresponding Source. The information must -suffice to ensure that the continued functioning of the modified object -code is in no case prevented or interfered with solely because -modification has been made. - - If you convey an object code work under this section in, or with, or -specifically for use in, a User Product, and the conveying occurs as -part of a transaction in which the right of possession and use of the -User Product is transferred to the recipient in perpetuity or for a -fixed term (regardless of how the transaction is characterized), the -Corresponding Source conveyed under this section must be accompanied -by the Installation Information. But this requirement does not apply -if neither you nor any third party retains the ability to install -modified object code on the User Product (for example, the work has -been installed in ROM). - - The requirement to provide Installation Information does not include a -requirement to continue to provide support service, warranty, or updates -for a work that has been modified or installed by the recipient, or for -the User Product in which it has been modified or installed. Access to a -network may be denied when the modification itself materially and -adversely affects the operation of the network or violates the rules and -protocols for communication across the network. - - Corresponding Source conveyed, and Installation Information provided, -in accord with this section must be in a format that is publicly -documented (and with an implementation available to the public in -source code form), and must require no special password or key for -unpacking, reading or copying. - - 7. Additional Terms. - - "Additional permissions" are terms that supplement the terms of this -License by making exceptions from one or more of its conditions. -Additional permissions that are applicable to the entire Program shall -be treated as though they were included in this License, to the extent -that they are valid under applicable law. If additional permissions -apply only to part of the Program, that part may be used separately -under those permissions, but the entire Program remains governed by -this License without regard to the additional permissions. - - When you convey a copy of a covered work, you may at your option -remove any additional permissions from that copy, or from any part of -it. (Additional permissions may be written to require their own -removal in certain cases when you modify the work.) You may place -additional permissions on material, added by you to a covered work, -for which you have or can give appropriate copyright permission. - - Notwithstanding any other provision of this License, for material you -add to a covered work, you may (if authorized by the copyright holders of -that material) supplement the terms of this License with terms: - - a) Disclaiming warranty or limiting liability differently from the - terms of sections 15 and 16 of this License; or - - b) Requiring preservation of specified reasonable legal notices or - author attributions in that material or in the Appropriate Legal - Notices displayed by works containing it; or - - c) Prohibiting misrepresentation of the origin of that material, or - requiring that modified versions of such material be marked in - reasonable ways as different from the original version; or - - d) Limiting the use for publicity purposes of names of licensors or - authors of the material; or - - e) Declining to grant rights under trademark law for use of some - trade names, trademarks, or service marks; or - - f) Requiring indemnification of licensors and authors of that - material by anyone who conveys the material (or modified versions of - it) with contractual assumptions of liability to the recipient, for - any liability that these contractual assumptions directly impose on - those licensors and authors. - - All other non-permissive additional terms are considered "further -restrictions" within the meaning of section 10. If the Program as you -received it, or any part of it, contains a notice stating that it is -governed by this License along with a term that is a further -restriction, you may remove that term. If a license document contains -a further restriction but permits relicensing or conveying under this -License, you may add to a covered work material governed by the terms -of that license document, provided that the further restriction does -not survive such relicensing or conveying. - - If you add terms to a covered work in accord with this section, you -must place, in the relevant source files, a statement of the -additional terms that apply to those files, or a notice indicating -where to find the applicable terms. - - Additional terms, permissive or non-permissive, may be stated in the -form of a separately written license, or stated as exceptions; -the above requirements apply either way. - - 8. Termination. - - You may not propagate or modify a covered work except as expressly -provided under this License. Any attempt otherwise to propagate or -modify it is void, and will automatically terminate your rights under -this License (including any patent licenses granted under the third -paragraph of section 11). - - However, if you cease all violation of this License, then your -license from a particular copyright holder is reinstated (a) -provisionally, unless and until the copyright holder explicitly and -finally terminates your license, and (b) permanently, if the copyright -holder fails to notify you of the violation by some reasonable means -prior to 60 days after the cessation. - - Moreover, your license from a particular copyright holder is -reinstated permanently if the copyright holder notifies you of the -violation by some reasonable means, this is the first time you have -received notice of violation of this License (for any work) from that -copyright holder, and you cure the violation prior to 30 days after -your receipt of the notice. - - Termination of your rights under this section does not terminate the -licenses of parties who have received copies or rights from you under -this License. If your rights have been terminated and not permanently -reinstated, you do not qualify to receive new licenses for the same -material under section 10. - - 9. Acceptance Not Required for Having Copies. - - You are not required to accept this License in order to receive or -run a copy of the Program. Ancillary propagation of a covered work -occurring solely as a consequence of using peer-to-peer transmission -to receive a copy likewise does not require acceptance. However, -nothing other than this License grants you permission to propagate or -modify any covered work. These actions infringe copyright if you do -not accept this License. Therefore, by modifying or propagating a -covered work, you indicate your acceptance of this License to do so. - - 10. Automatic Licensing of Downstream Recipients. - - Each time you convey a covered work, the recipient automatically -receives a license from the original licensors, to run, modify and -propagate that work, subject to this License. You are not responsible -for enforcing compliance by third parties with this License. - - An "entity transaction" is a transaction transferring control of an -organization, or substantially all assets of one, or subdividing an -organization, or merging organizations. If propagation of a covered -work results from an entity transaction, each party to that -transaction who receives a copy of the work also receives whatever -licenses to the work the party's predecessor in interest had or could -give under the previous paragraph, plus a right to possession of the -Corresponding Source of the work from the predecessor in interest, if -the predecessor has it or can get it with reasonable efforts. - - You may not impose any further restrictions on the exercise of the -rights granted or affirmed under this License. For example, you may -not impose a license fee, royalty, or other charge for exercise of -rights granted under this License, and you may not initiate litigation -(including a cross-claim or counterclaim in a lawsuit) alleging that -any patent claim is infringed by making, using, selling, offering for -sale, or importing the Program or any portion of it. - - 11. Patents. - - A "contributor" is a copyright holder who authorizes use under this -License of the Program or a work on which the Program is based. The -work thus licensed is called the contributor's "contributor version". - - A contributor's "essential patent claims" are all patent claims -owned or controlled by the contributor, whether already acquired or -hereafter acquired, that would be infringed by some manner, permitted -by this License, of making, using, or selling its contributor version, -but do not include claims that would be infringed only as a -consequence of further modification of the contributor version. For -purposes of this definition, "control" includes the right to grant -patent sublicenses in a manner consistent with the requirements of -this License. - - Each contributor grants you a non-exclusive, worldwide, royalty-free -patent license under the contributor's essential patent claims, to -make, use, sell, offer for sale, import and otherwise run, modify and -propagate the contents of its contributor version. - - In the following three paragraphs, a "patent license" is any express -agreement or commitment, however denominated, not to enforce a patent -(such as an express permission to practice a patent or covenant not to -sue for patent infringement). To "grant" such a patent license to a -party means to make such an agreement or commitment not to enforce a -patent against the party. - - If you convey a covered work, knowingly relying on a patent license, -and the Corresponding Source of the work is not available for anyone -to copy, free of charge and under the terms of this License, through a -publicly available network server or other readily accessible means, -then you must either (1) cause the Corresponding Source to be so -available, or (2) arrange to deprive yourself of the benefit of the -patent license for this particular work, or (3) arrange, in a manner -consistent with the requirements of this License, to extend the patent -license to downstream recipients. "Knowingly relying" means you have -actual knowledge that, but for the patent license, your conveying the -covered work in a country, or your recipient's use of the covered work -in a country, would infringe one or more identifiable patents in that -country that you have reason to believe are valid. - - If, pursuant to or in connection with a single transaction or -arrangement, you convey, or propagate by procuring conveyance of, a -covered work, and grant a patent license to some of the parties -receiving the covered work authorizing them to use, propagate, modify -or convey a specific copy of the covered work, then the patent license -you grant is automatically extended to all recipients of the covered -work and works based on it. - - A patent license is "discriminatory" if it does not include within -the scope of its coverage, prohibits the exercise of, or is -conditioned on the non-exercise of one or more of the rights that are -specifically granted under this License. You may not convey a covered -work if you are a party to an arrangement with a third party that is -in the business of distributing software, under which you make payment -to the third party based on the extent of your activity of conveying -the work, and under which the third party grants, to any of the -parties who would receive the covered work from you, a discriminatory -patent license (a) in connection with copies of the covered work -conveyed by you (or copies made from those copies), or (b) primarily -for and in connection with specific products or compilations that -contain the covered work, unless you entered into that arrangement, -or that patent license was granted, prior to 28 March 2007. - - Nothing in this License shall be construed as excluding or limiting -any implied license or other defenses to infringement that may -otherwise be available to you under applicable patent law. - - 12. No Surrender of Others' Freedom. - - If conditions are imposed on you (whether by court order, agreement or -otherwise) that contradict the conditions of this License, they do not -excuse you from the conditions of this License. If you cannot convey a -covered work so as to satisfy simultaneously your obligations under this -License and any other pertinent obligations, then as a consequence you may -not convey it at all. For example, if you agree to terms that obligate you -to collect a royalty for further conveying from those to whom you convey -the Program, the only way you could satisfy both those terms and this -License would be to refrain entirely from conveying the Program. - - 13. Use with the GNU Affero General Public License. - - Notwithstanding any other provision of this License, you have -permission to link or combine any covered work with a work licensed -under version 3 of the GNU Affero General Public License into a single -combined work, and to convey the resulting work. The terms of this -License will continue to apply to the part which is the covered work, -but the special requirements of the GNU Affero General Public License, -section 13, concerning interaction through a network will apply to the -combination as such. - - 14. Revised Versions of this License. - - The Free Software Foundation may publish revised and/or new versions of -the GNU General Public License from time to time. Such new versions will -be similar in spirit to the present version, but may differ in detail to -address new problems or concerns. - - Each version is given a distinguishing version number. If the -Program specifies that a certain numbered version of the GNU General -Public License "or any later version" applies to it, you have the -option of following the terms and conditions either of that numbered -version or of any later version published by the Free Software -Foundation. If the Program does not specify a version number of the -GNU General Public License, you may choose any version ever published -by the Free Software Foundation. - - If the Program specifies that a proxy can decide which future -versions of the GNU General Public License can be used, that proxy's -public statement of acceptance of a version permanently authorizes you -to choose that version for the Program. - - Later license versions may give you additional or different -permissions. However, no additional obligations are imposed on any -author or copyright holder as a result of your choosing to follow a -later version. - - 15. Disclaimer of Warranty. - - THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY -APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT -HOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY -OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, -THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR -PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE PROGRAM -IS WITH YOU. SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF -ALL NECESSARY SERVICING, REPAIR OR CORRECTION. - - 16. Limitation of Liability. - - IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING -WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MODIFIES AND/OR CONVEYS -THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY -GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE -USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF -DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD -PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS), -EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF -SUCH DAMAGES. - - 17. Interpretation of Sections 15 and 16. - - If the disclaimer of warranty and limitation of liability provided -above cannot be given local legal effect according to their terms, -reviewing courts shall apply local law that most closely approximates -an absolute waiver of all civil liability in connection with the -Program, unless a warranty or assumption of liability accompanies a -copy of the Program in return for a fee. - - END OF TERMS AND CONDITIONS - - How to Apply These Terms to Your New Programs - - If you develop a new program, and you want it to be of the greatest -possible use to the public, the best way to achieve this is to make it -free software which everyone can redistribute and change under these terms. - - To do so, attach the following notices to the program. It is safest -to attach them to the start of each source file to most effectively -state the exclusion of warranty; and each file should have at least -the "copyright" line and a pointer to where the full notice is found. - - {one line to give the program's name and a brief idea of what it does.} - Copyright (C) {year} {name of author} - - This program is free software: you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation, either version 3 of the License, or - (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program. If not, see . - -Also add information on how to contact you by electronic and paper mail. - - If the program does terminal interaction, make it output a short -notice like this when it starts in an interactive mode: - - {project} Copyright (C) {year} {fullname} - This program comes with ABSOLUTELY NO WARRANTY; for details type `show w'. - This is free software, and you are welcome to redistribute it - under certain conditions; type `show c' for details. - -The hypothetical commands `show w' and `show c' should show the appropriate -parts of the General Public License. Of course, your program's commands -might be different; for a GUI interface, you would use an "about box". - - You should also get your employer (if you work as a programmer) or school, -if any, to sign a "copyright disclaimer" for the program, if necessary. -For more information on this, and how to apply and follow the GNU GPL, see -. - - The GNU General Public License does not permit incorporating your program -into proprietary programs. If your program is a subroutine library, you -may consider it more useful to permit linking proprietary applications with -the library. If this is what you want to do, use the GNU Lesser General -Public License instead of this License. But first, please read -. diff --git a/vendor/github.com/matryer/is/README.md b/vendor/github.com/matryer/is/README.md deleted file mode 100644 index 472cd14..0000000 --- a/vendor/github.com/matryer/is/README.md +++ /dev/null @@ -1,30 +0,0 @@ -# is [![GoDoc](https://godoc.org/github.com/matryer/is?status.png)](http://godoc.org/github.com/matryer/is) [![Go Report Card](https://goreportcard.com/badge/github.com/matryer/is)](https://goreportcard.com/report/github.com/matryer/is) [![Build Status](https://travis-ci.org/matryer/is.svg?branch=master)](https://travis-ci.org/matryer/is) -Professional lightweight testing mini-framework for Go. - -* Easy to write and read -* [Beautifully simple API](https://godoc.org/github.com/matryer/is) with everything you need: `is.Equal`, `is.True`, `is.NoErr`, and `is.Fail` -* Use comments to add descriptions (which show up when tests fail) - -Failures are very easy to read: - -![Examples of failures](https://github.com/matryer/is/raw/master/misc/delicious-failures.png) - -### Usage - -The following code shows a range of useful ways you can use -the helper methods: - -```go -func Test(t *testing.T) { - - is := is.New(t) - - signedin, err := isSignedIn(ctx) - is.NoErr(err) // isSignedIn error - is.Equal(signedin, true) // must be signed in - - body := readBody(r) - is.True(strings.Contains(body, "Hi there")) - -} -``` diff --git a/vendor/github.com/matryer/is/is.go b/vendor/github.com/matryer/is/is.go deleted file mode 100644 index c58cf2d..0000000 --- a/vendor/github.com/matryer/is/is.go +++ /dev/null @@ -1,397 +0,0 @@ -// Package is provides a lightweight extension to the -// standard library's testing capabilities. -// -// Comments on the assertion lines are used to add -// a description. -// -// The following failing test: -// -// func Test(t *testing.T) { -// is := is.New(t) -// a, b := 1, 2 -// is.Equal(a, b) // expect to be the same -// } -// -// Will output: -// -// your_test.go:123: 1 != 2 // expect to be the same -// -// Usage -// -// The following code shows a range of useful ways you can use -// the helper methods: -// -// func Test(t *testing.T) { -// -// // always start tests with this -// is := is.New(t) -// -// signedin, err := isSignedIn(ctx) -// is.NoErr(err) // isSignedIn error -// is.Equal(signedin, true) // must be signed in -// -// body := readBody(r) -// is.OK(strings.Contains(body, "Hi there")) -// -// } -package is - -import ( - "bufio" - "bytes" - "fmt" - "io" - "os" - "path/filepath" - "reflect" - "runtime" - "strings" - "testing" -) - -// T reports when failures occur. -// testing.T implements this interface. -type T interface { - // Fail indicates that the test has failed but - // allowed execution to continue. - // Fail is called in relaxed mode (via NewRelaxed). - Fail() - // FailNow indicates that the test has failed and - // aborts the test. - // FailNow is called in strict mode (via New). - FailNow() -} - -// I is the test helper harness. -type I struct { - t T - fail func() - out io.Writer - colorful bool -} - -// New makes a new testing helper using the specified -// T through which failures will be reported. -// In strict mode, failures call T.FailNow causing the test -// to be aborted. See NewRelaxed for alternative behavior. -func New(t T) *I { - return &I{t, t.FailNow, os.Stdout, true} -} - -// NewRelaxed makes a new testing helper using the specified -// T through which failures will be reported. -// In relaxed mode, failures call T.Fail allowing -// multiple failures per test. -func NewRelaxed(t T) *I { - return &I{t, t.Fail, os.Stdout, true} -} - -func (is *I) log(args ...interface{}) { - s := is.decorate(fmt.Sprint(args...)) - fmt.Fprintf(is.out, s) - is.fail() -} - -func (is *I) logf(format string, args ...interface{}) { - is.log(fmt.Sprintf(format, args...)) -} - -// Fail immediately fails the test. -// -// func Test(t *testing.T) { -// is := is.New(t) -// is.Fail() // TODO: write this test -// } -// -// In relaxed mode, execution will continue after a call to -// Fail, but that test will still fail. -func (is *I) Fail() { - is.log("failed") -} - -// True asserts that the expression is true. The expression -// code itself will be reported if the assertion fails. -// -// func Test(t *testing.T) { -// is := is.New(t) -// val := method() -// is.True(val != nil) // val should never be nil -// } -// -// Will output: -// -// your_test.go:123: not true: val != nil -func (is *I) True(expression bool) { - if !expression { - is.log("not true: $ARGS") - } -} - -// Equal asserts that a and b are equal. -// -// func Test(t *testing.T) { -// is := is.New(t) -// a := greet("Mat") -// is.Equal(a, "Hi Mat") // greeting -// } -// -// Will output: -// -// your_test.go:123: Hey Mat != Hi Mat // greeting -func (is *I) Equal(a, b interface{}) { - if !areEqual(a, b) { - if isNil(a) || isNil(b) { - aLabel := is.valWithType(a) - bLabel := is.valWithType(b) - if isNil(a) { - aLabel = "" - } - if isNil(b) { - bLabel = "" - } - is.logf("%s != %s", aLabel, bLabel) - return - } - if reflect.ValueOf(a).Type() == reflect.ValueOf(b).Type() { - is.logf("%v != %v", a, b) - return - } - is.logf("%s != %s", is.valWithType(a), is.valWithType(b)) - } -} - -// New is a method wrapper around the New function. -// It allows you to write subtests using a fimilar -// pattern: -// -// func Test(t *testing.T) { -// is := is.New(t) -// t.Run("sub", func(t *testing.T) { -// is := is.New(t) -// // TODO: test -// }) -// } -func (is *I) New(t *testing.T) *I { - return New(t) -} - -// NewRelaxed is a method wrapper aorund the NewRelaxed -// method. It allows you to write subtests using a fimilar -// pattern: -// -// func Test(t *testing.T) { -// is := is.New(t) -// t.Run("sub", func(t *testing.T) { -// is := is.New(t) -// // TODO: test -// }) -// } -func (is *I) NewRelaxed(t *testing.T) *I { - return NewRelaxed(t) -} - -func (is *I) valWithType(v interface{}) string { - if is.colorful { - return fmt.Sprintf("%[1]s%[3]T(%[2]s%[3]v%[1]s)%[2]s", colorType, colorNormal, v) - } - return fmt.Sprintf("%[1]T(%[1]v)", v) -} - -// NoErr asserts that err is nil. -// -// func Test(t *testing.T) { -// is := is.New(t) -// val, err := getVal() -// is.NoErr(err) // getVal error -// is.OK(len(val) > 10) // val cannot be short -// } -// -// Will output: -// -// your_test.go:123: err: not found // getVal error -func (is *I) NoErr(err error) { - if err != nil { - is.logf("err: %s", err.Error()) - } -} - -// isNil gets whether the object is nil or not. -func isNil(object interface{}) bool { - if object == nil { - return true - } - value := reflect.ValueOf(object) - kind := value.Kind() - if kind >= reflect.Chan && kind <= reflect.Slice && value.IsNil() { - return true - } - return false -} - -// areEqual gets whether a equals b or not. -func areEqual(a, b interface{}) bool { - if isNil(a) || isNil(b) { - if isNil(a) && !isNil(b) { - return false - } - if !isNil(a) && isNil(b) { - return false - } - return a == b - } - if reflect.DeepEqual(a, b) { - return true - } - aValue := reflect.ValueOf(a) - bValue := reflect.ValueOf(b) - if aValue == bValue { - return true - } - return false -} - -func callerinfo() (path string, line int, ok bool) { - for i := 0; ; i++ { - _, path, line, ok = runtime.Caller(i) - if !ok { - return - } - if strings.HasSuffix(path, "is.go") { - continue - } - return path, line, true - } -} - -// loadComment gets the Go comment from the specified line -// in the specified file. -func loadComment(path string, line int) (string, bool) { - f, err := os.Open(path) - if err != nil { - return "", false - } - defer f.Close() - s := bufio.NewScanner(f) - i := 1 - for s.Scan() { - if i == line { - text := s.Text() - commentI := strings.Index(text, "//") - if commentI == -1 { - return "", false // no comment - } - text = text[commentI+2:] - text = strings.TrimSpace(text) - return text, true - } - i++ - } - return "", false -} - -// loadArguments gets the arguments from the function call -// on the specified line of the file. -func loadArguments(path string, line int) (string, bool) { - f, err := os.Open(path) - if err != nil { - return "", false - } - defer f.Close() - s := bufio.NewScanner(f) - i := 1 - for s.Scan() { - if i == line { - text := s.Text() - braceI := strings.Index(text, "(") - if braceI == -1 { - return "", false - } - text = text[braceI+1:] - cs := bufio.NewScanner(strings.NewReader(text)) - cs.Split(bufio.ScanBytes) - i := 0 - c := 1 - for cs.Scan() { - switch cs.Text() { - case ")": - c-- - case "(": - c++ - } - if c == 0 { - break - } - i++ - } - text = text[:i] - return text, true - } - i++ - } - return "", false -} - -// decorate prefixes the string with the file and line of the call site -// and inserts the final newline if needed and indentation tabs for formatting. -// this function was copied from the testing framework and modified. -func (is *I) decorate(s string) string { - path, lineNumber, ok := callerinfo() // decorate + log + public function. - file := filepath.Base(path) - if ok { - // Truncate file name at last file name separator. - if index := strings.LastIndex(file, "/"); index >= 0 { - file = file[index+1:] - } else if index = strings.LastIndex(file, "\\"); index >= 0 { - file = file[index+1:] - } - } else { - file = "???" - lineNumber = 1 - } - buf := new(bytes.Buffer) - // Every line is indented at least one tab. - buf.WriteByte('\t') - if is.colorful { - buf.WriteString(colorFile) - } - fmt.Fprintf(buf, "%s:%d: ", file, lineNumber) - if is.colorful { - buf.WriteString(colorNormal) - } - lines := strings.Split(s, "\n") - if l := len(lines); l > 1 && lines[l-1] == "" { - lines = lines[:l-1] - } - for i, line := range lines { - if i > 0 { - // Second and subsequent lines are indented an extra tab. - buf.WriteString("\n\t\t") - } - // expand arguments (if $ARGS is present) - if strings.Contains(line, "$ARGS") { - args, _ := loadArguments(path, lineNumber) - line = strings.Replace(line, "$ARGS", args, -1) - } - buf.WriteString(line) - } - comment, ok := loadComment(path, lineNumber) - if ok { - if is.colorful { - buf.WriteString(colorComment) - } - buf.WriteString(" // ") - buf.WriteString(comment) - if is.colorful { - buf.WriteString(colorNormal) - } - } - buf.WriteString("\n") - return buf.String() -} - -const ( - colorNormal = "\u001b[39m" - colorComment = "\u001b[32m" - colorFile = "\u001b[90m" - colorType = "\u001b[90m" -) diff --git a/vendor/github.com/matryer/is/is_test.go b/vendor/github.com/matryer/is/is_test.go deleted file mode 100644 index c6e5b25..0000000 --- a/vendor/github.com/matryer/is/is_test.go +++ /dev/null @@ -1,252 +0,0 @@ -package is - -import ( - "bytes" - "errors" - "fmt" - "strings" - "testing" -) - -type mockT struct { - failed bool -} - -func (m *mockT) FailNow() { - m.failed = true -} -func (m *mockT) Fail() { - m.failed = true -} - -var tests = []struct { - N string - F func(is *I) - Fail string -}{ - // Equal - { - N: "Equal(1, 1)", - F: func(is *I) { - is.Equal(1, 1) // 1 doesn't equal 2 - }, - Fail: ``, - }, - - { - N: "Equal(1, 2)", - F: func(is *I) { - is.Equal(1, 2) // 1 doesn't equal 2 - }, - Fail: `1 != 2 // 1 doesn't equal 2`, - }, - { - N: "Equal(1, nil)", - F: func(is *I) { - is.Equal(1, nil) // 1 doesn't equal nil - }, - Fail: `int(1) != // 1 doesn't equal nil`, - }, - { - N: "Equal(nil, 2)", - F: func(is *I) { - is.Equal(nil, 2) // nil doesn't equal 2 - }, - Fail: ` != int(2) // nil doesn't equal 2`, - }, - { - N: "Equal(false, false)", - F: func(is *I) { - is.Equal(false, false) // nil doesn't equal 2 - }, - Fail: ``, - }, - { - N: "Equal(int32(1), int64(1))", - F: func(is *I) { - is.Equal(int32(1), int64(1)) // nope - }, - Fail: `int32(1) != int64(1) // nope`, - }, - { - N: "Equal(map1, map2)", - F: func(is *I) { - m1 := map[string]interface{}{"value": 1} - m2 := map[string]interface{}{"value": 2} - is.Equal(m1, m2) // maps - }, - Fail: `map[value:1] != map[value:2] // maps`, - }, - { - N: "Equal(true, map2)", - F: func(is *I) { - m1 := map[string]interface{}{"value": 1} - m2 := map[string]interface{}{"value": 2} - is.Equal(m1, m2) // maps - }, - Fail: `map[value:1] != map[value:2] // maps`, - }, - { - N: "Equal(slice1, slice2)", - F: func(is *I) { - s1 := []string{"one", "two", "three"} - s2 := []string{"one", "two", "three", "four"} - is.Equal(s1, s2) // slices - }, - Fail: `[one two three] != [one two three four] // slices`, - }, - { - N: "Equal(nil, chan)", - F: func(is *I) { - var a chan string - b := make(chan string) - is.Equal(a, b) // channels - }, - Fail: ` // channels`, - }, - { - N: "Equal(nil, slice)", - F: func(is *I) { - var s1 []string - s2 := []string{"one", "two", "three", "four"} - is.Equal(s1, s2) // nil slice - }, - Fail: ` // nil slice`, - }, - - // Fail - { - N: "Fail()", - F: func(is *I) { - is.Fail() // something went wrong - }, - Fail: "failed // something went wrong", - }, - - // NoErr - { - N: "NoErr(nil)", - F: func(is *I) { - var err error - is.NoErr(err) // method shouldn't return error - }, - Fail: "", - }, - { - N: "NoErr(error)", - F: func(is *I) { - err := errors.New("nope") - is.NoErr(err) // method shouldn't return error - }, - Fail: "err: nope // method shouldn't return error", - }, - - // OK - { - N: "True(1 == 2)", - F: func(is *I) { - is.True(1 == 2) - }, - Fail: "not true: 1 == 2", - }, -} - -func TestFailures(t *testing.T) { - colorful, notColorful := true, false - testFailures(t, colorful) - testFailures(t, notColorful) -} - -func testFailures(t *testing.T, colorful bool) { - for _, test := range tests { - tt := &mockT{} - is := New(tt) - var buf bytes.Buffer - is.out = &buf - is.colorful = colorful - test.F(is) - if len(test.Fail) == 0 && tt.failed { - t.Errorf("shouldn't fail: %s", test.N) - continue - } - if len(test.Fail) > 0 && !tt.failed { - t.Errorf("didn't fail: %s", test.N) - } - if colorful { - // if colorful, we won't check the messages - // this test is run twice, one without colorful - // statements. - // see TestFailures - fmt.Print(buf.String()) - continue - } - output := buf.String() - output = strings.TrimSpace(output) - if !strings.HasSuffix(output, test.Fail) { - t.Errorf("expected `%s` to end with `%s`", output, test.Fail) - } - } -} - -func TestRelaxed(t *testing.T) { - tt := &mockT{} - is := NewRelaxed(tt) - var buf bytes.Buffer - is.out = &buf - is.colorful = false - is.NoErr(errors.New("oops")) - is.True(1 == 2) - actual := buf.String() - if !strings.Contains(actual, `oops`) { - t.Errorf("missing: oops") - } - if !strings.Contains(actual, `1 == 2`) { - t.Errorf("missing: 1 == 2") - } - if !tt.failed { - t.Errorf("didn't fail") - } -} - -func TestLoadComment(t *testing.T) { - comment, ok := loadComment("./testdata/example_test.go", 12) - if !ok { - t.Errorf("loadComment: not ok") - } - if comment != `this comment will be extracted` { - t.Errorf("loadComment: bad comment %s", comment) - } -} - -func TestLoadArguments(t *testing.T) { - arguments, ok := loadArguments("./testdata/example_test.go", 20) - if !ok { - t.Errorf("loadArguments: not ok") - } - if arguments != `a == getB()` { - t.Errorf("loadArguments: bad arguments %s", arguments) - } - - arguments, ok = loadArguments("./testdata/example_test.go", 28) - if !ok { - t.Errorf("loadArguments: not ok") - } - if arguments != `a == getB()` { - t.Errorf("loadArguments: bad arguments %s", arguments) - } - - arguments, _ = loadArguments("./testdata/example_test.go", 26) - if len(arguments) > 0 { - t.Errorf("should be no arguments: %s", arguments) - } -} - -// TestSubtests ensures subtests work as expected. -// https://github.com/matryer/is/issues/1 -func TestSubtests(t *testing.T) { - is := New(t) - t.Run("sub1", func(t *testing.T) { - is := is.New(t) - is.Equal(1+1, 2) - }) -} diff --git a/vendor/github.com/matryer/is/misc/delicious-failures.png b/vendor/github.com/matryer/is/misc/delicious-failures.png deleted file mode 100644 index b1e0d01d030c584d6e290a41c93477b458fe8808..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 277442 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 z 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 []... -``` - -if no `` arguments are passed, it simply validates the ``. - -exit-code is 1, if there are any validation errors diff --git a/vendor/github.com/santhosh-tekuri/jsonschema/cmd/jv/main.go b/vendor/github.com/santhosh-tekuri/jsonschema/cmd/jv/main.go deleted file mode 100644 index aca78f5..0000000 --- a/vendor/github.com/santhosh-tekuri/jsonschema/cmd/jv/main.go +++ /dev/null @@ -1,42 +0,0 @@ -// Copyright 2017 Santhosh Kumar Tekuri. All rights reserved. -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. - -package main - -import ( - "fmt" - "os" - - "github.com/santhosh-tekuri/jsonschema" - _ "github.com/santhosh-tekuri/jsonschema/httploader" - "github.com/santhosh-tekuri/jsonschema/loader" -) - -func main() { - if len(os.Args) == 1 { - fmt.Fprintln(os.Stderr, "jv []...") - os.Exit(1) - } - - schema, err := jsonschema.Compile(os.Args[1]) - if err != nil { - fmt.Fprintln(os.Stderr, err) - os.Exit(1) - } - - for _, f := range os.Args[2:] { - r, err := loader.Load(f) - if err != nil { - fmt.Fprintf(os.Stderr, "error in reading %q. reason: \n%v\n", f, err) - os.Exit(1) - } - - err = schema.Validate(r) - _ = r.Close() - if err != nil { - fmt.Fprintf(os.Stderr, "%q does not conform to the schema specified. reason:\n%v\n", f, err) - os.Exit(1) - } - } -} diff --git a/vendor/github.com/santhosh-tekuri/jsonschema/compiler.go b/vendor/github.com/santhosh-tekuri/jsonschema/compiler.go deleted file mode 100644 index 05eba4c..0000000 --- a/vendor/github.com/santhosh-tekuri/jsonschema/compiler.go +++ /dev/null @@ -1,492 +0,0 @@ -// Copyright 2017 Santhosh Kumar Tekuri. All rights reserved. -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. - -package jsonschema - -import ( - "encoding/json" - "fmt" - "io" - "math/big" - "regexp" - "strings" - - "github.com/santhosh-tekuri/jsonschema/formats" - "github.com/santhosh-tekuri/jsonschema/loader" -) - -// A Draft represents json-schema draft -type Draft struct { - meta *Schema - id string -} - -var latest = Draft6 - -func (draft *Draft) validateSchema(url, ptr string, v interface{}) error { - if meta := draft.meta; meta != nil { - if err := meta.validate(v); err != nil { - addContext(ptr, "", err) - finishSchemaContext(err, meta) - finishInstanceContext(err) - var instancePtr string - if ptr == "" { - instancePtr = "#" - } else { - instancePtr = "#/" + ptr - } - return &SchemaError{ - url, - &ValidationError{ - Message: fmt.Sprintf("doesn't validate with %q", meta.url+meta.ptr), - InstancePtr: instancePtr, - SchemaURL: meta.url, - SchemaPtr: "#", - Causes: []*ValidationError{err.(*ValidationError)}, - }, - } - } - } - return nil -} - -// A Compiler represents a json-schema compiler. -// -// Currently draft4 and draft6 are supported -type Compiler struct { - // Draft represents the draft used when '$schema' attribute is missing. - // - // This defaults to latest draft (currently draft6). - Draft *Draft - resources map[string]*resource -} - -// NewCompiler returns a draft4 json-schema Compiler object. -func NewCompiler() *Compiler { - return &Compiler{resources: make(map[string]*resource)} -} - -// AddResource adds in-memory resource to the compiler. -// -// Note that url must not have fragment -func (c *Compiler) AddResource(url string, r io.Reader) error { - res, err := newResource(url, r) - if err != nil { - return err - } - c.resources[res.url] = res - return nil -} - -func (c *Compiler) draft(v interface{}) (*Draft, error) { - if m, ok := v.(map[string]interface{}); ok { - if url, ok := m["$schema"]; ok { - switch url { - case "http://json-schema.org/schema#": - return latest, nil - case "http://json-schema.org/draft-06/schema#": - return Draft6, nil - case "http://json-schema.org/draft-04/schema#": - return Draft4, nil - default: - return nil, fmt.Errorf("unknown $schema %q", url) - } - } - } - if c.Draft == nil { - return latest, nil - } - return c.Draft, nil -} - -// MustCompile is like Compile but panics if the url cannot be compiled to *Schema. -// It simplifies safe initialization of global variables holding compiled Schemas. -func (c *Compiler) MustCompile(url string) *Schema { - s, err := c.Compile(url) - if err != nil { - panic(fmt.Sprintf("jsonschema: Compile(%q): %s", url, err)) - } - return s -} - -// Compile parses json-schema at given url returns, if successful, -// a Schema object that can be used to match against json. -func (c *Compiler) Compile(url string) (*Schema, error) { - base, fragment := split(url) - if _, ok := c.resources[base]; !ok { - r, err := loader.Load(base) - if err != nil { - return nil, err - } - defer r.Close() - if err := c.AddResource(base, r); err != nil { - return nil, err - } - } - r := c.resources[base] - return c.compileRef(nil, r, nil, r.url, fragment) -} - -func (c Compiler) compileRef(draft *Draft, r *resource, root map[string]interface{}, base, ref string) (*Schema, error) { - var err error - if rootFragment(ref) { - if _, ok := r.schemas["#"]; !ok { - if draft == nil { - draft, err = c.draft(r.doc) - if err != nil { - return nil, err - } - } - if err := draft.validateSchema(r.url, "", r.doc); err != nil { - return nil, err - } - s := &Schema{url: r.url, ptr: "#"} - r.schemas["#"] = s - if m, ok := r.doc.(map[string]interface{}); ok { - if _, err := c.compile(draft, r, s, base, m, m); err != nil { - return nil, err - } - } else { - if _, err := c.compile(draft, r, s, base, nil, r.doc); err != nil { - return nil, err - } - } - } - return r.schemas["#"], nil - } - - if strings.HasPrefix(ref, "#/") { - if _, ok := r.schemas[ref]; !ok { - docDraft := draft - if docDraft == nil { - docDraft = c.Draft - } - if docDraft == nil { - docDraft = latest - } - ptrBase, doc, err := r.resolvePtr(docDraft, ref) - if err != nil { - return nil, err - } - if draft == nil { - draft, err = c.draft(doc) - if err != nil { - return nil, err - } - } - if err := draft.validateSchema(r.url, strings.TrimPrefix(ref, "#/"), doc); err != nil { - return nil, err - } - r.schemas[ref] = &Schema{url: base, ptr: ref} - if _, err := c.compile(draft, r, r.schemas[ref], ptrBase, root, doc); err != nil { - return nil, err - } - } - return r.schemas[ref], nil - } - - refURL, err := resolveURL(base, ref) - if err != nil { - return nil, err - } - if rs, ok := r.schemas[refURL]; ok { - return rs, nil - } - - ids := make(map[string]map[string]interface{}) - if err := resolveIDs(draft, r.url, root, ids); err != nil { - return nil, err - } - if v, ok := ids[refURL]; ok { - if err := draft.validateSchema(r.url, "", v); err != nil { - return nil, err - } - u, f := split(refURL) - s := &Schema{url: u, ptr: f} - r.schemas[refURL] = s - if err := c.compileMap(draft, r, s, refURL, root, v); err != nil { - return nil, err - } - return s, nil - } - - base, _ = split(refURL) - if base == r.url { - return nil, fmt.Errorf("invalid ref: %q", refURL) - } - return c.Compile(refURL) -} - -func (c Compiler) compile(draft *Draft, r *resource, s *Schema, base string, root map[string]interface{}, m interface{}) (*Schema, error) { - if s == nil { - s = new(Schema) - s.url, _ = split(base) - } - switch m := m.(type) { - case bool: - s.always = &m - return s, nil - default: - return s, c.compileMap(draft, r, s, base, root, m.(map[string]interface{})) - } -} - -func (c Compiler) compileMap(draft *Draft, r *resource, s *Schema, base string, root, m map[string]interface{}) error { - var err error - - if id, ok := m[draft.id]; ok { - if base, err = resolveURL(base, id.(string)); err != nil { - return err - } - } - - if ref, ok := m["$ref"]; ok { - b, _ := split(base) - s.ref, err = c.compileRef(draft, r, root, b, ref.(string)) - if err != nil { - return err - } - // All other properties in a "$ref" object MUST be ignored - return nil - } - - if t, ok := m["type"]; ok { - switch t := t.(type) { - case string: - s.types = []string{t} - case []interface{}: - s.types = toStrings(t) - } - } - - if e, ok := m["enum"]; ok { - s.enum = e.([]interface{}) - allPrimitives := true - for _, item := range s.enum { - switch jsonType(item) { - case "object", "array": - allPrimitives = false - break - } - } - s.enumError = "enum failed" - if allPrimitives { - if len(s.enum) == 1 { - s.enumError = fmt.Sprintf("value must be %#v", s.enum[0]) - } else { - strEnum := make([]string, len(s.enum)) - for i, item := range s.enum { - strEnum[i] = fmt.Sprintf("%#v", item) - } - s.enumError = fmt.Sprintf("value must be one of %s", strings.Join(strEnum, ", ")) - } - } - } - - if not, ok := m["not"]; ok { - s.not, err = c.compile(draft, r, nil, base, root, not) - if err != nil { - return err - } - } - - loadSchemas := func(pname string) ([]*Schema, error) { - if pvalue, ok := m[pname]; ok { - pvalue := pvalue.([]interface{}) - schemas := make([]*Schema, len(pvalue)) - for i, v := range pvalue { - sch, err := c.compile(draft, r, nil, base, root, v) - if err != nil { - return nil, err - } - schemas[i] = sch - } - return schemas, nil - } - return nil, nil - } - if s.allOf, err = loadSchemas("allOf"); err != nil { - return err - } - if s.anyOf, err = loadSchemas("anyOf"); err != nil { - return err - } - if s.oneOf, err = loadSchemas("oneOf"); err != nil { - return err - } - - loadInt := func(pname string) int { - if num, ok := m[pname]; ok { - i, _ := num.(json.Number).Int64() - return int(i) - } - return -1 - } - s.minProperties, s.maxProperties = loadInt("minProperties"), loadInt("maxProperties") - - if req, ok := m["required"]; ok { - s.required = toStrings(req.([]interface{})) - } - - if props, ok := m["properties"]; ok { - props := props.(map[string]interface{}) - s.properties = make(map[string]*Schema, len(props)) - for pname, pmap := range props { - s.properties[pname], err = c.compile(draft, r, nil, base, root, pmap) - if err != nil { - return err - } - } - } - - if regexProps, ok := m["regexProperties"]; ok { - s.regexProperties = regexProps.(bool) - } - - if patternProps, ok := m["patternProperties"]; ok { - patternProps := patternProps.(map[string]interface{}) - s.patternProperties = make(map[*regexp.Regexp]*Schema, len(patternProps)) - for pattern, pmap := range patternProps { - s.patternProperties[regexp.MustCompile(pattern)], err = c.compile(draft, r, nil, base, root, pmap) - if err != nil { - return err - } - } - } - - if additionalProps, ok := m["additionalProperties"]; ok { - switch additionalProps := additionalProps.(type) { - case bool: - if !additionalProps { - s.additionalProperties = false - } - case map[string]interface{}: - s.additionalProperties, err = c.compile(draft, r, nil, base, root, additionalProps) - if err != nil { - return err - } - } - } - - if deps, ok := m["dependencies"]; ok { - deps := deps.(map[string]interface{}) - s.dependencies = make(map[string]interface{}, len(deps)) - for pname, pvalue := range deps { - switch pvalue := pvalue.(type) { - case []interface{}: - s.dependencies[pname] = toStrings(pvalue) - default: - s.dependencies[pname], err = c.compile(draft, r, nil, base, root, pvalue) - if err != nil { - return err - } - } - } - } - - s.minItems, s.maxItems = loadInt("minItems"), loadInt("maxItems") - - if unique, ok := m["uniqueItems"]; ok { - s.uniqueItems = unique.(bool) - } - - if items, ok := m["items"]; ok { - switch items := items.(type) { - case []interface{}: - s.items, err = loadSchemas("items") - if err != nil { - return err - } - if additionalItems, ok := m["additionalItems"]; ok { - switch additionalItems := additionalItems.(type) { - case bool: - s.additionalItems = additionalItems - case map[string]interface{}: - s.additionalItems, err = c.compile(draft, r, nil, base, root, additionalItems) - if err != nil { - return err - } - } - } else { - s.additionalItems = true - } - default: - s.items, err = c.compile(draft, r, nil, base, root, items) - if err != nil { - return err - } - } - } - - s.minLength, s.maxLength = loadInt("minLength"), loadInt("maxLength") - - if pattern, ok := m["pattern"]; ok { - s.pattern = regexp.MustCompile(pattern.(string)) - } - - if format, ok := m["format"]; ok { - s.formatName = format.(string) - s.format, _ = formats.Get(s.formatName) - } - - loadFloat := func(pname string) *big.Float { - if num, ok := m[pname]; ok { - r, _ := new(big.Float).SetString(string(num.(json.Number))) - return r - } - return nil - } - - s.minimum = loadFloat("minimum") - if exclusive, ok := m["exclusiveMinimum"]; ok { - if exclusive, ok := exclusive.(bool); ok { - if exclusive { - s.minimum, s.exclusiveMinimum = nil, s.minimum - } - } else { - s.exclusiveMinimum = loadFloat("exclusiveMinimum") - } - } - - s.maximum = loadFloat("maximum") - if exclusive, ok := m["exclusiveMaximum"]; ok { - if exclusive, ok := exclusive.(bool); ok { - if exclusive { - s.maximum, s.exclusiveMaximum = nil, s.maximum - } - } else { - s.exclusiveMaximum = loadFloat("exclusiveMaximum") - } - } - - s.multipleOf = loadFloat("multipleOf") - - if draft == Draft6 { - if c, ok := m["const"]; ok { - s.constant = []interface{}{c} - } - if propertyNames, ok := m["propertyNames"]; ok { - s.propertyNames, err = c.compile(draft, r, nil, base, root, propertyNames) - if err != nil { - return err - } - } - if contains, ok := m["contains"]; ok { - s.contains, err = c.compile(draft, r, nil, base, root, contains) - if err != nil { - return err - } - } - } - - return nil -} - -func toStrings(arr []interface{}) []string { - s := make([]string, len(arr)) - for i, v := range arr { - s[i] = v.(string) - } - return s -} diff --git a/vendor/github.com/santhosh-tekuri/jsonschema/doc.go b/vendor/github.com/santhosh-tekuri/jsonschema/doc.go deleted file mode 100644 index 89ea048..0000000 --- a/vendor/github.com/santhosh-tekuri/jsonschema/doc.go +++ /dev/null @@ -1,74 +0,0 @@ -// Copyright 2017 Santhosh Kumar Tekuri. All rights reserved. -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. - -/* -Package jsonschema provides json-schema compilation and validation. - -This implementation of JSON Schema, supports draft4 and draft6. -Passes all tests(including optional) in https://github.com/json-schema/JSON-Schema-Test-Suite - -An example of using this package: - - schema, err := jsonschema.Compile("schemas/purchaseOrder.json") - if err != nil { - return err - } - f, err := os.Open("purchaseOrder.json") - if err != nil { - return err - } - defer f.Close() - if err = schema.Validate(f); err != nil { - return err - } - -The schema is compiled against the version specified in `$schema` property. -If `$schema` property is missing, it uses latest draft which currently is draft6. -You can force to use draft4 when `$schema` is missing, as follows: - - compiler := jsonschema.NewCompiler() - compler.Draft = jsonschema.Draft4 - -you can also validate go value using schema.ValidateInterface(interface{}) method. -but the argument should not be user-defined struct. - -This package supports loading json-schema from filePath and fileURL. - -To load json-schema from HTTPURL, add following import: - - import _ "github.com/santhosh-tekuri/jsonschema/httploader" - -Loading from urls for other schemes (such as ftp), can be plugged in. see package jsonschema/httploader -for an example - -To load json-schema from in-memory: - - data := `{"type": "string"}` - url := "sch.json" - compiler := jsonschema.NewCompiler() - if err := compiler.AddResource(url, strings.NewReader(data)); err != nil { - return err - } - schema, err := compiler.Compile(url) - if err != nil { - return err - } - f, err := os.Open("doc.json") - if err != nil { - return err - } - defer f.Close() - if err = schema.Validate(f); err != nil { - return err - } - -This package supports json string formats: date-time, hostname, email, ip-address, ipv4, ipv6, uri, uriref, regex, -format, json-pointer, uri-template (limited validation). - -Developers can define their own formats using package jsonschema/formats. - -The ValidationError returned by Validate method contains detailed context to understand why and where the error is. - -*/ -package jsonschema diff --git a/vendor/github.com/santhosh-tekuri/jsonschema/draft4.go b/vendor/github.com/santhosh-tekuri/jsonschema/draft4.go deleted file mode 100644 index 1c98447..0000000 --- a/vendor/github.com/santhosh-tekuri/jsonschema/draft4.go +++ /dev/null @@ -1,172 +0,0 @@ -// Copyright 2017 Santhosh Kumar Tekuri. All rights reserved. -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. - -package jsonschema - -import "strings" - -// Draft4 respresents http://json-schema.org/specification-links.html#draft-4 -var Draft4 = &Draft{id: "id"} - -func init() { - c := NewCompiler() - url := "http://json-schema.org/draft-04/schema" - err := c.AddResource(url, strings.NewReader(`{ - "$schema": "http://json-schema.org/draft-04/schema#", - "description": "Core schema meta-schema", - "definitions": { - "schemaArray": { - "type": "array", - "minItems": 1, - "items": { "$ref": "#" } - }, - "positiveInteger": { - "type": "integer", - "minimum": 0 - }, - "positiveIntegerDefault0": { - "allOf": [ { "$ref": "#/definitions/positiveInteger" }, { "default": 0 } ] - }, - "simpleTypes": { - "enum": [ "array", "boolean", "integer", "null", "number", "object", "string" ] - }, - "stringArray": { - "type": "array", - "items": { "type": "string" }, - "minItems": 1, - "uniqueItems": true - } - }, - "type": "object", - "properties": { - "id": { - "type": "string", - "format": "uriref" - }, - "$schema": { - "type": "string", - "format": "uri" - }, - "title": { - "type": "string" - }, - "description": { - "type": "string" - }, - "default": {}, - "multipleOf": { - "type": "number", - "minimum": 0, - "exclusiveMinimum": true - }, - "maximum": { - "type": "number" - }, - "exclusiveMaximum": { - "type": "boolean", - "default": false - }, - "minimum": { - "type": "number" - }, - "exclusiveMinimum": { - "type": "boolean", - "default": false - }, - "maxLength": { "$ref": "#/definitions/positiveInteger" }, - "minLength": { "$ref": "#/definitions/positiveIntegerDefault0" }, - "pattern": { - "type": "string", - "format": "regex" - }, - "additionalItems": { - "anyOf": [ - { "type": "boolean" }, - { "$ref": "#" } - ], - "default": {} - }, - "items": { - "anyOf": [ - { "$ref": "#" }, - { "$ref": "#/definitions/schemaArray" } - ], - "default": {} - }, - "maxItems": { "$ref": "#/definitions/positiveInteger" }, - "minItems": { "$ref": "#/definitions/positiveIntegerDefault0" }, - "uniqueItems": { - "type": "boolean", - "default": false - }, - "maxProperties": { "$ref": "#/definitions/positiveInteger" }, - "minProperties": { "$ref": "#/definitions/positiveIntegerDefault0" }, - "required": { "$ref": "#/definitions/stringArray" }, - "additionalProperties": { - "anyOf": [ - { "type": "boolean" }, - { "$ref": "#" } - ], - "default": {} - }, - "definitions": { - "type": "object", - "additionalProperties": { "$ref": "#" }, - "default": {} - }, - "properties": { - "type": "object", - "additionalProperties": { "$ref": "#" }, - "default": {} - }, - "patternProperties": { - "type": "object", - "regexProperties": true, - "additionalProperties": { "$ref": "#" }, - "default": {} - }, - "regexProperties": { "type": "boolean" }, - "dependencies": { - "type": "object", - "additionalProperties": { - "anyOf": [ - { "$ref": "#" }, - { "$ref": "#/definitions/stringArray" } - ] - } - }, - "enum": { - "type": "array", - "minItems": 1, - "uniqueItems": true - }, - "type": { - "anyOf": [ - { "$ref": "#/definitions/simpleTypes" }, - { - "type": "array", - "items": { "$ref": "#/definitions/simpleTypes" }, - "minItems": 1, - "uniqueItems": true - } - ] - }, - "allOf": { "$ref": "#/definitions/schemaArray" }, - "anyOf": { "$ref": "#/definitions/schemaArray" }, - "oneOf": { "$ref": "#/definitions/schemaArray" }, - "not": { "$ref": "#" }, - "format": { "type": "string", "format": "format" }, - "$ref": { "type": "string" } - }, - "dependencies": { - "exclusiveMaximum": [ "maximum" ], - "exclusiveMinimum": [ "minimum" ] - }, - "default": {} - }`)) - if err != nil { - panic(err) - } - Draft4.meta = c.MustCompile(url) -} diff --git a/vendor/github.com/santhosh-tekuri/jsonschema/draft6.go b/vendor/github.com/santhosh-tekuri/jsonschema/draft6.go deleted file mode 100644 index 4d896e9..0000000 --- a/vendor/github.com/santhosh-tekuri/jsonschema/draft6.go +++ /dev/null @@ -1,170 +0,0 @@ -// Copyright 2017 Santhosh Kumar Tekuri. All rights reserved. -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. - -package jsonschema - -import "strings" - -// Draft6 respresents http://json-schema.org/specification-links.html#draft-6 -var Draft6 = &Draft{id: "$id"} - -func init() { - c := NewCompiler() - url := "http://json-schema.org/draft-06/schema" - err := c.AddResource(url, strings.NewReader(`{ - "$schema": "http://json-schema.org/draft-06/schema#", - "$id": "http://json-schema.org/draft-06/schema#", - "title": "Core schema meta-schema", - "definitions": { - "schemaArray": { - "type": "array", - "minItems": 1, - "items": { "$ref": "#" } - }, - "nonNegativeInteger": { - "type": "integer", - "minimum": 0 - }, - "nonNegativeIntegerDefault0": { - "allOf": [ - { "$ref": "#/definitions/nonNegativeInteger" }, - { "default": 0 } - ] - }, - "simpleTypes": { - "enum": [ - "array", - "boolean", - "integer", - "null", - "number", - "object", - "string" - ] - }, - "stringArray": { - "type": "array", - "items": { "type": "string" }, - "uniqueItems": true, - "default": [] - } - }, - "type": ["object", "boolean"], - "properties": { - "$id": { - "type": "string", - "format": "uri-reference" - }, - "$schema": { - "type": "string", - "format": "uri" - }, - "$ref": { - "type": "string", - "format": "uri-reference" - }, - "title": { - "type": "string" - }, - "description": { - "type": "string" - }, - "default": {}, - "multipleOf": { - "type": "number", - "exclusiveMinimum": 0 - }, - "maximum": { - "type": "number" - }, - "exclusiveMaximum": { - "type": "number" - }, - "minimum": { - "type": "number" - }, - "exclusiveMinimum": { - "type": "number" - }, - "maxLength": { "$ref": "#/definitions/nonNegativeInteger" }, - "minLength": { "$ref": "#/definitions/nonNegativeIntegerDefault0" }, - "pattern": { - "type": "string", - "format": "regex" - }, - "additionalItems": { "$ref": "#" }, - "items": { - "anyOf": [ - { "$ref": "#" }, - { "$ref": "#/definitions/schemaArray" } - ], - "default": {} - }, - "maxItems": { "$ref": "#/definitions/nonNegativeInteger" }, - "minItems": { "$ref": "#/definitions/nonNegativeIntegerDefault0" }, - "uniqueItems": { - "type": "boolean", - "default": false - }, - "contains": { "$ref": "#" }, - "maxProperties": { "$ref": "#/definitions/nonNegativeInteger" }, - "minProperties": { "$ref": "#/definitions/nonNegativeIntegerDefault0" }, - "required": { "$ref": "#/definitions/stringArray" }, - "additionalProperties": { "$ref": "#" }, - "definitions": { - "type": "object", - "additionalProperties": { "$ref": "#" }, - "default": {} - }, - "properties": { - "type": "object", - "additionalProperties": { "$ref": "#" }, - "default": {} - }, - "patternProperties": { - "type": "object", - "regexProperties": true, - "additionalProperties": { "$ref": "#" }, - "default": {} - }, - "dependencies": { - "type": "object", - "additionalProperties": { - "anyOf": [ - { "$ref": "#" }, - { "$ref": "#/definitions/stringArray" } - ] - } - }, - "propertyNames": { "$ref": "#" }, - "const": {}, - "enum": { - "type": "array", - "minItems": 1, - "uniqueItems": true - }, - "type": { - "anyOf": [ - { "$ref": "#/definitions/simpleTypes" }, - { - "type": "array", - "items": { "$ref": "#/definitions/simpleTypes" }, - "minItems": 1, - "uniqueItems": true - } - ] - }, - "format": { "type": "string", "format": "format" }, - "allOf": { "$ref": "#/definitions/schemaArray" }, - "anyOf": { "$ref": "#/definitions/schemaArray" }, - "oneOf": { "$ref": "#/definitions/schemaArray" }, - "not": { "$ref": "#" } - }, - "default": {} - }`)) - if err != nil { - panic(err) - } - Draft6.meta = c.MustCompile(url) -} diff --git a/vendor/github.com/santhosh-tekuri/jsonschema/errors.go b/vendor/github.com/santhosh-tekuri/jsonschema/errors.go deleted file mode 100644 index af1a1c5..0000000 --- a/vendor/github.com/santhosh-tekuri/jsonschema/errors.go +++ /dev/null @@ -1,122 +0,0 @@ -// Copyright 2017 Santhosh Kumar Tekuri. All rights reserved. -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. - -package jsonschema - -import ( - "fmt" - "strings" -) - -// InvalidJSONTypeError is the error type returned by ValidateInteface. -// this tells that specified go object is not valid jsonType. -type InvalidJSONTypeError string - -func (e InvalidJSONTypeError) Error() string { - return fmt.Sprintf("invalid jsonType: %s", string(e)) -} - -// SchemaError is the error type returned by Compile. -type SchemaError struct { - // SchemaURL is the url to json-schema that filed to compile. - // This is helpful, if your schema refers to external schemas - SchemaURL string - - // Err is the error that occurred during compilation. - // It could be ValidationError, because compilation validates - // given schema against the json meta-schema - Err error -} - -func (se *SchemaError) Error() string { - return fmt.Sprintf("json-schema %q compilation failed. Reason:\n%s", se.SchemaURL, se.Err) -} - -// ValidationError is the error type returned by Validate. -type ValidationError struct { - // Message describes error - Message string - - // InstancePtr is json-pointer which refers to json-fragment in json instance - // that is not valid - InstancePtr string - - // SchemaURL is the url to json-schema against which validation failed. - // This is helpful, if your schema refers to external schemas - SchemaURL string - - // SchemaPtr is json-pointer which refers to json-fragment in json schema - // that failed to satisfy - SchemaPtr string - - // Causes details the nested validation errors - Causes []*ValidationError -} - -func (ve *ValidationError) add(causes ...error) error { - for _, cause := range causes { - addContext(ve.InstancePtr, ve.SchemaPtr, cause) - ve.Causes = append(ve.Causes, cause.(*ValidationError)) - } - return ve -} - -func (ve *ValidationError) Error() string { - msg := fmt.Sprintf("I[%s] S[%s] %s", ve.InstancePtr, ve.SchemaPtr, ve.Message) - for _, c := range ve.Causes { - for _, line := range strings.Split(c.Error(), "\n") { - msg += "\n " + line - } - } - return msg -} - -func validationError(schemaPtr string, format string, a ...interface{}) *ValidationError { - return &ValidationError{fmt.Sprintf(format, a...), "", "", schemaPtr, nil} -} - -func addContext(instancePtr, schemaPtr string, err error) error { - ve := err.(*ValidationError) - ve.InstancePtr = joinPtr(instancePtr, ve.InstancePtr) - if len(ve.SchemaURL) == 0 { - ve.SchemaPtr = joinPtr(schemaPtr, ve.SchemaPtr) - } - for _, cause := range ve.Causes { - addContext(instancePtr, schemaPtr, cause) - } - return ve -} - -func finishSchemaContext(err error, s *Schema) { - ve := err.(*ValidationError) - if len(ve.SchemaURL) == 0 { - ve.SchemaURL = s.url - ve.SchemaPtr = s.ptr + "/" + ve.SchemaPtr - for _, cause := range ve.Causes { - finishSchemaContext(cause, s) - } - } -} - -func finishInstanceContext(err error) { - ve := err.(*ValidationError) - if len(ve.InstancePtr) == 0 { - ve.InstancePtr = "#" - } else { - ve.InstancePtr = "#/" + ve.InstancePtr - } - for _, cause := range ve.Causes { - finishInstanceContext(cause) - } -} - -func joinPtr(ptr1, ptr2 string) string { - if len(ptr1) == 0 { - return ptr2 - } - if len(ptr2) == 0 { - return ptr1 - } - return ptr1 + "/" + ptr2 -} diff --git a/vendor/github.com/santhosh-tekuri/jsonschema/formats/formats.go b/vendor/github.com/santhosh-tekuri/jsonschema/formats/formats.go deleted file mode 100644 index 4f47459..0000000 --- a/vendor/github.com/santhosh-tekuri/jsonschema/formats/formats.go +++ /dev/null @@ -1,217 +0,0 @@ -// Copyright 2017 Santhosh Kumar Tekuri. All rights reserved. -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. - -// Package formats provides functions to check string against format. -// -// It allows developers to register custom formats, that can be used -// in json-schema for validation. -package formats - -import ( - "net" - "net/mail" - "net/url" - "regexp" - "strconv" - "strings" - "time" -) - -// The Format type is a function, to check -// whether given string is in valid format. -type Format func(string) bool - -var formats = map[string]Format{ - "date-time": IsDateTime, - "hostname": IsHostname, - "email": IsEmail, - "ip-address": IsIPV4, - "ipv4": IsIPV4, - "ipv6": IsIPV6, - "uri": IsURI, - "uri-reference": IsURIReference, - "uriref": IsURIReference, - "uri-template": IsURIReference, - "regex": IsRegex, - "json-pointer": IsJSONPointer, -} - -func init() { - formats["format"] = IsFormat -} - -// Register registers Format object for given format name. -func Register(name string, f Format) { - formats[name] = f -} - -// Get returns Format object for given format name, if found -func Get(name string) (Format, bool) { - f, ok := formats[name] - return f, ok -} - -// IsFormat tells whether given string is a valid format that is registered -func IsFormat(s string) bool { - _, ok := formats[s] - return ok -} - -// IsDateTime tells whether given string is a valid date representation -// as defined by RFC 3339, section 5.6. -// -// Note: this is unable to parse UTC leap seconds. See https://github.com/golang/go/issues/8728. -func IsDateTime(s string) bool { - if _, err := time.Parse(time.RFC3339, s); err == nil { - return true - } - if _, err := time.Parse(time.RFC3339Nano, s); err == nil { - return true - } - return false -} - -// IsHostname tells whether given string is a valid representation -// for an Internet host name, as defined by RFC 1034, section 3.1. -// -// See https://en.wikipedia.org/wiki/Hostname#Restrictions_on_valid_host_names, for details. -func IsHostname(s string) bool { - // entire hostname (including the delimiting dots but not a trailing dot) has a maximum of 253 ASCII characters - s = strings.TrimSuffix(s, ".") - if len(s) > 253 { - return false - } - - // Hostnames are composed of series of labels concatenated with dots, as are all domain names - for _, label := range strings.Split(s, ".") { - // Each label must be from 1 to 63 characters long - if labelLen := len(label); labelLen < 1 || labelLen > 63 { - return false - } - - // labels could not start with a digit or with a hyphen - if first := s[0]; (first >= '0' && first <= '9') || (first == '-') { - return false - } - - // must not end with a hyphen - if label[len(label)-1] == '-' { - return false - } - - // labels may contain only the ASCII letters 'a' through 'z' (in a case-insensitive manner), - // the digits '0' through '9', and the hyphen ('-') - for _, c := range label { - if valid := (c >= 'a' && c <= 'z') || (c >= 'A' && c <= 'Z') || (c >= '0' && c <= '9') || (c == '-'); !valid { - return false - } - } - } - - return true -} - -// IsEmail tells whether given string is a valid Internet email address -// as defined by RFC 5322, section 3.4.1. -// -// See https://en.wikipedia.org/wiki/Email_address, for details. -func IsEmail(s string) bool { - // entire email address to be no more than 254 characters long - if len(s) > 254 { - return false - } - - // email address is generally recognized as having two parts joined with an at-sign - at := strings.LastIndexByte(s, '@') - if at == -1 { - return false - } - local := s[0:at] - domain := s[at+1:] - - // local part may be up to 64 characters long - if len(local) > 64 { - return false - } - - // domain must match the requirements for a hostname - if !IsHostname(domain) { - return false - } - - _, err := mail.ParseAddress(s) - return err == nil -} - -// IsIPV4 tells whether given string is a valid representation of an IPv4 address -// according to the "dotted-quad" ABNF syntax as defined in RFC 2673, section 3.2. -func IsIPV4(s string) bool { - groups := strings.Split(s, ".") - if len(groups) != 4 { - return false - } - for _, group := range groups { - n, err := strconv.Atoi(group) - if err != nil { - return false - } - if n < 0 || n > 255 { - return false - } - } - return true -} - -// IsIPV6 tells whether given string is a valid representation of an IPv6 address -// as defined in RFC 2373, section 2.2. -func IsIPV6(s string) bool { - if !strings.Contains(s, ":") { - return false - } - return net.ParseIP(s) != nil -} - -// IsURI tells whether given string is valid URI, according to RFC 3986. -func IsURI(s string) bool { - u, err := url.Parse(s) - return err == nil && u.IsAbs() -} - -// IsURIReference tells whether given string is a valid URI Reference -// (either a URI or a relative-reference), according to RFC 3986. -func IsURIReference(s string) bool { - _, err := url.Parse(s) - return err == nil -} - -// IsRegex tells whether given string is a valid regular expression, -// according to the ECMA 262 regular expression dialect. -// -// The implementation uses go-lang regexp package. -func IsRegex(s string) bool { - _, err := regexp.Compile(s) - return err == nil -} - -// IsJSONPointer tells whether given string is a valid JSON Pointer. -// -// Note: It returns false for JSON Pointer URI fragments. -func IsJSONPointer(s string) bool { - for _, item := range strings.Split(s, "/") { - for i := 0; i < len(item); i++ { - if item[i] == '~' { - if i == len(item)-1 { - return false - } - switch item[i+1] { - case '~', '0', '1': - // valid - default: - return false - } - } - } - } - return true -} diff --git a/vendor/github.com/santhosh-tekuri/jsonschema/formats/formats_test.go b/vendor/github.com/santhosh-tekuri/jsonschema/formats/formats_test.go deleted file mode 100644 index 19f295f..0000000 --- a/vendor/github.com/santhosh-tekuri/jsonschema/formats/formats_test.go +++ /dev/null @@ -1,137 +0,0 @@ -// Copyright 2017 Santhosh Kumar Tekuri. All rights reserved. -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. - -package formats_test - -import ( - "strings" - "testing" - - "github.com/santhosh-tekuri/jsonschema/formats" -) - -type test struct { - str string - valid bool -} - -func TestIsFormat(t *testing.T) { - tests := []test{ - {"date-time", true}, - {"palindrome", false}, - } - for i, test := range tests { - if test.valid != formats.IsFormat(test.str) { - t.Errorf("#%d: %q, valid %t, got valid %t", i, test.str, test.valid, !test.valid) - } - } -} - -func TestIsDateTime(t *testing.T) { - tests := []test{ - {"1985-04-12T23:20:50.52Z", true}, - {"1996-12-19T16:39:57-08:00", true}, - {"1990-12-31T23:59:59Z", true}, - {"1990-12-31T15:59:59-08:00", true}, - {"1937-01-01T12:00:27.87+00:20", true}, - {"06/19/1963 08:30:06 PST", false}, - {"2013-350T01:01:01", false}, - } - for i, test := range tests { - if test.valid != formats.IsDateTime(test.str) { - t.Errorf("#%d: %q, valid %t, got valid %t", i, test.str, test.valid, !test.valid) - } - } -} - -func TestIsHostname(t *testing.T) { - tests := []test{ - {"www.example.com", true}, - {strings.Repeat("a", 63) + "." + strings.Repeat("a", 63) + "." + strings.Repeat("a", 63) + "." + strings.Repeat("a", 61), true}, - {strings.Repeat("a", 63) + "." + strings.Repeat("a", 63) + "." + strings.Repeat("a", 63) + "." + strings.Repeat("a", 61) + ".", true}, - {strings.Repeat("a", 63) + "." + strings.Repeat("a", 63) + "." + strings.Repeat("a", 63) + "." + strings.Repeat("a", 62) + ".", false}, // length more than 253 characters long - {"www..com", false}, // empty label - {"-a-host-name-that-starts-with--", false}, - {"not_a_valid_host_name", false}, - {"a-vvvvvvvvvvvvvvvveeeeeeeeeeeeeeeerrrrrrrrrrrrrrrryyyyyyyyyyyyyyyy-long-host-name-component", false}, - {"www.example-.com", false}, // label ends with a hyphen - } - for i, test := range tests { - if test.valid != formats.IsHostname(test.str) { - t.Errorf("#%d: %q, valid %t, got valid %t", i, test.str, test.valid, !test.valid) - } - } -} - -func TestIsEmail(t *testing.T) { - tests := []test{ - {"joe.bloggs@example.com", true}, - {"2962", false}, // no "@" character - {strings.Repeat("a", 244) + "@google.com", false}, // more than 254 characters long - {strings.Repeat("a", 65) + "@google.com", false}, // local part more than 64 characters long - {"santhosh@-google.com", false}, // invalid domain name - } - for i, test := range tests { - if test.valid != formats.IsEmail(test.str) { - t.Errorf("#%d: %q, valid %t, got valid %t", i, test.str, test.valid, !test.valid) - } - } -} - -func TestIsIPV4(t *testing.T) { - tests := []test{ - {"192.168.0.1", true}, - {"192.168.0.test", false}, // non-integer component - {"127.0.0.0.1", false}, // too many components - {"256.256.256.256", false}, // out-of-range values - {"127.0", false}, // without 4 components - {"0x7f000001", false}, // an integer - } - for i, test := range tests { - if test.valid != formats.IsIPV4(test.str) { - t.Errorf("#%d: %q, valid %t, got valid %t", i, test.str, test.valid, !test.valid) - } - } -} - -func TestIsIPV6(t *testing.T) { - tests := []test{ - {"::1", true}, - {"192.168.0.1", false}, // is IPV4 - {"12345::", false}, // out-of-range values - {"1:1:1:1:1:1:1:1:1:1:1:1:1:1:1:1", false}, // too many components - {"::laptop", false}, // containing illegal characters - } - for i, test := range tests { - if test.valid != formats.IsIPV6(test.str) { - t.Errorf("#%d: %q, valid %t, got valid %t", i, test.str, test.valid, !test.valid) - } - } -} - -func TestIsURI(t *testing.T) { - tests := []test{ - {"http://foo.bar/?baz=qux#quux", true}, - {"//foo.bar/?baz=qux#quux", false}, // an invalid protocol-relative URI Reference - {"\\\\WINDOWS\\fileshare", false}, // an invalid URI - {"abc", false}, // an invalid URI though valid URI reference - } - for i, test := range tests { - if test.valid != formats.IsURI(test.str) { - t.Errorf("#%d: %q, valid %t, got valid %t", i, test.str, test.valid, !test.valid) - } - } -} - -func TestIsJSONPointer(t *testing.T) { - tests := []test{ - {"/foo/baz", true}, - {"/foo/baz~", false}, // ~ not escaped - } - for i, test := range tests { - if test.valid != formats.IsJSONPointer(test.str) { - t.Errorf("#%d: %q, valid %t, got valid %t", i, test.str, test.valid, !test.valid) - } - } -} diff --git a/vendor/github.com/santhosh-tekuri/jsonschema/go.test.sh b/vendor/github.com/santhosh-tekuri/jsonschema/go.test.sh deleted file mode 100755 index 88c4e8b..0000000 --- a/vendor/github.com/santhosh-tekuri/jsonschema/go.test.sh +++ /dev/null @@ -1,12 +0,0 @@ -#!/usr/bin/env bash - -set -e -echo "" > coverage.txt - -for d in $(go list ./... | grep -v vendor); do - go test -v -race -coverprofile=profile.out -covermode=atomic $d - if [ -f profile.out ]; then - cat profile.out >> coverage.txt - rm profile.out - fi -done diff --git a/vendor/github.com/santhosh-tekuri/jsonschema/httploader/httploader.go b/vendor/github.com/santhosh-tekuri/jsonschema/httploader/httploader.go deleted file mode 100644 index 5f86cf9..0000000 --- a/vendor/github.com/santhosh-tekuri/jsonschema/httploader/httploader.go +++ /dev/null @@ -1,43 +0,0 @@ -// Copyright 2017 Santhosh Kumar Tekuri. All rights reserved. -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. - -// Package httploader implements loader.Loader for http/https url. -// -// The package is typically only imported for the side effect of -// registering its Loaders. -// -// To use httploader, link this package into your program: -// import _ "github.com/santhosh-tekuri/jsonschema/httploader" -// -package httploader - -import ( - "fmt" - "io" - "net/http" - - "github.com/santhosh-tekuri/jsonschema/loader" -) - -// Client is the default HTTP Client used to Get the resource. -var Client = http.DefaultClient - -type httpLoader struct{} - -func (httpLoader) Load(url string) (io.ReadCloser, error) { - resp, err := Client.Get(url) - if err != nil { - return nil, err - } - if resp.StatusCode != http.StatusOK { - _ = resp.Body.Close() - return nil, fmt.Errorf("%s returned status code %d", url, resp.StatusCode) - } - return resp.Body, nil -} - -func init() { - loader.Register("http", httpLoader{}) - loader.Register("https", httpLoader{}) -} diff --git a/vendor/github.com/santhosh-tekuri/jsonschema/loader/loader.go b/vendor/github.com/santhosh-tekuri/jsonschema/loader/loader.go deleted file mode 100644 index f8ee551..0000000 --- a/vendor/github.com/santhosh-tekuri/jsonschema/loader/loader.go +++ /dev/null @@ -1,101 +0,0 @@ -// Copyright 2017 Santhosh Kumar Tekuri. All rights reserved. -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. - -// Package loader abstracts the reading document at given url. -// -// It allows developers to register loaders for different uri -// schemes. -package loader - -import ( - "fmt" - "io" - "net/url" - "os" - "path/filepath" - "runtime" - "strings" - "sync" -) - -// Loader is the interface that wraps the basic Load method. -// -// Load loads the document at given url and returns []byte, -// if successful. -type Loader interface { - Load(url string) (io.ReadCloser, error) -} - -type filePathLoader struct{} - -func (filePathLoader) Load(path string) (io.ReadCloser, error) { - return os.Open(path) -} - -type fileURLLoader struct{} - -func (fileURLLoader) Load(url string) (io.ReadCloser, error) { - f := strings.TrimPrefix(url, "file://") - if runtime.GOOS == "windows" { - f = strings.TrimPrefix(f, "/") - f = filepath.FromSlash(f) - } - return os.Open(f) -} - -var registry = make(map[string]Loader) -var mutex = sync.RWMutex{} - -// SchemeNotRegisteredError is the error type returned by Load function. -// It tells that no Loader is registered for that URL Scheme. -type SchemeNotRegisteredError string - -func (s SchemeNotRegisteredError) Error() string { - return fmt.Sprintf("no Loader registered for scheme %s", string(s)) -} - -// Register registers given Loader for given URI Scheme. -func Register(scheme string, loader Loader) { - mutex.Lock() - defer mutex.Unlock() - registry[scheme] = loader -} - -// UnRegister unregisters the registered loader(if any) for given URI Scheme. -func UnRegister(scheme string) { - mutex.Lock() - defer mutex.Unlock() - delete(registry, scheme) -} - -func get(s string) (Loader, error) { - mutex.RLock() - defer mutex.RUnlock() - u, err := url.Parse(s) - if err != nil { - return nil, err - } - if loader, ok := registry[u.Scheme]; ok { - return loader, nil - } - return nil, SchemeNotRegisteredError(u.Scheme) -} - -// Load loads the document at given url and returns []byte, -// if successful. -// -// If no Loader is registered against the URI Scheme, then it -// returns *SchemeNotRegisteredError -func Load(url string) (io.ReadCloser, error) { - loader, err := get(url) - if err != nil { - return nil, err - } - return loader.Load(url) -} - -func init() { - Register("", filePathLoader{}) - Register("file", fileURLLoader{}) -} diff --git a/vendor/github.com/santhosh-tekuri/jsonschema/resource.go b/vendor/github.com/santhosh-tekuri/jsonschema/resource.go deleted file mode 100644 index 0421453..0000000 --- a/vendor/github.com/santhosh-tekuri/jsonschema/resource.go +++ /dev/null @@ -1,235 +0,0 @@ -// Copyright 2017 Santhosh Kumar Tekuri. All rights reserved. -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. - -package jsonschema - -import ( - "encoding/json" - "errors" - "fmt" - "io" - "net/url" - "path/filepath" - "strconv" - "strings" -) - -type resource struct { - url string - doc interface{} - schemas map[string]*Schema -} - -// DecodeJSON decodes json document from r. -// -// Note that number is decoded into json.Number instead of as a float64 -func DecodeJSON(r io.Reader) (interface{}, error) { - decoder := json.NewDecoder(r) - decoder.UseNumber() - var doc interface{} - if err := decoder.Decode(&doc); err != nil { - return nil, err - } - if t, _ := decoder.Token(); t != nil { - return nil, fmt.Errorf("invalid character %v after top-level value", t) - } - return doc, nil -} - -func newResource(base string, r io.Reader) (*resource, error) { - if strings.IndexByte(base, '#') != -1 { - panic(fmt.Sprintf("BUG: newResource(%q)", base)) - } - doc, err := DecodeJSON(r) - if err != nil { - return nil, fmt.Errorf("parsing %q failed. Reason: %v", base, err) - } - return &resource{base, doc, make(map[string]*Schema)}, nil -} - -func resolveURL(base, ref string) (string, error) { - if ref == "" { - return base, nil - } - - refURL, err := url.Parse(ref) - if err != nil { - return "", err - } - if refURL.IsAbs() { - return normalize(ref), nil - } - - baseURL, err := url.Parse(base) - if err != nil { - return "", err - } - if baseURL.IsAbs() { - return normalize(baseURL.ResolveReference(refURL).String()), nil - } - - // filepath resolving - base, _ = split(base) - ref, fragment := split(ref) - if ref == "" { - return base + fragment, nil - } - dir, _ := filepath.Split(base) - return filepath.Join(dir, ref) + fragment, nil -} - -func (r *resource) resolvePtr(draft *Draft, ptr string) (string, interface{}, error) { - if !strings.HasPrefix(ptr, "#/") { - panic(fmt.Sprintf("BUG: resolvePtr(%q)", ptr)) - } - base := r.url - p := strings.TrimPrefix(ptr, "#/") - doc := r.doc - for _, item := range strings.Split(p, "/") { - item = strings.Replace(item, "~1", "/", -1) - item = strings.Replace(item, "~0", "~", -1) - item, err := url.PathUnescape(item) - if err != nil { - return "", nil, errors.New("unable to url unscape: " + item) - } - switch d := doc.(type) { - case map[string]interface{}: - if id, ok := d[draft.id]; ok { - if id, ok := id.(string); ok { - if base, err = resolveURL(base, id); err != nil { - return "", nil, err - } - } - } - doc = d[item] - case []interface{}: - index, err := strconv.Atoi(item) - if err != nil { - return "", nil, fmt.Errorf("invalid $ref %q, reason: %s", ptr, err) - } - if index < 0 || index >= len(d) { - return "", nil, fmt.Errorf("invalid $ref %q, reason: array index outofrange", ptr) - } - doc = d[index] - default: - return "", nil, errors.New("invalid $ref " + ptr) - } - } - return base, doc, nil -} - -func split(uri string) (string, string) { - hash := strings.IndexByte(uri, '#') - if hash == -1 { - return uri, "#" - } - return uri[0:hash], uri[hash:] -} - -func normalize(url string) string { - base, fragment := split(url) - if rootFragment(fragment) { - fragment = "#" - } - return base + fragment -} - -func rootFragment(fragment string) bool { - return fragment == "" || fragment == "#" || fragment == "#/" -} - -func resolveIDs(draft *Draft, base string, v interface{}, ids map[string]map[string]interface{}) error { - m, ok := v.(map[string]interface{}) - if !ok { - return nil - } - if id, ok := m[draft.id]; ok { - b, err := resolveURL(base, id.(string)) - if err != nil { - return err - } - base = b - ids[base] = m - } - if m, ok := m["not"]; ok { - if err := resolveIDs(draft, base, m, ids); err != nil { - return err - } - } - - for _, pname := range []string{"allOf", "anyOf", "oneOf"} { - if arr, ok := m[pname]; ok { - for _, m := range arr.([]interface{}) { - if err := resolveIDs(draft, base, m, ids); err != nil { - return err - } - } - } - } - - for _, pname := range []string{"definitions", "properties", "patternProperties"} { - if props, ok := m[pname]; ok { - for _, m := range props.(map[string]interface{}) { - if err := resolveIDs(draft, base, m, ids); err != nil { - return err - } - } - } - } - - if additionalProps, ok := m["additionalProperties"]; ok { - if additionalProps, ok := additionalProps.(map[string]interface{}); ok { - if err := resolveIDs(draft, base, additionalProps, ids); err != nil { - return err - } - } - } - - if deps, ok := m["dependencies"]; ok { - for _, pvalue := range deps.(map[string]interface{}) { - if m, ok := pvalue.(map[string]interface{}); ok { - if err := resolveIDs(draft, base, m, ids); err != nil { - return err - } - } - } - } - - if items, ok := m["items"]; ok { - switch items := items.(type) { - case map[string]interface{}: - if err := resolveIDs(draft, base, items, ids); err != nil { - return err - } - case []interface{}: - for _, item := range items { - if err := resolveIDs(draft, base, item, ids); err != nil { - return err - } - } - } - if additionalItems, ok := m["additionalItems"]; ok { - if additionalItems, ok := additionalItems.(map[string]interface{}); ok { - if err := resolveIDs(draft, base, additionalItems, ids); err != nil { - return err - } - } - } - } - - if draft == Draft6 { - if propertyNames, ok := m["propertyNames"]; ok { - if err := resolveIDs(draft, base, propertyNames, ids); err != nil { - return err - } - } - if contains, ok := m["contains"]; ok { - if err := resolveIDs(draft, base, contains, ids); err != nil { - return err - } - } - } - - return nil -} diff --git a/vendor/github.com/santhosh-tekuri/jsonschema/schema.go b/vendor/github.com/santhosh-tekuri/jsonschema/schema.go deleted file mode 100644 index ecb21a9..0000000 --- a/vendor/github.com/santhosh-tekuri/jsonschema/schema.go +++ /dev/null @@ -1,508 +0,0 @@ -// Copyright 2017 Santhosh Kumar Tekuri. All rights reserved. -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. - -package jsonschema - -import ( - "encoding/json" - "fmt" - "io" - "math/big" - "net/url" - "regexp" - "strconv" - "strings" - "unicode/utf8" - - "github.com/santhosh-tekuri/jsonschema/formats" -) - -// A Schema represents compiled version of json-schema. -type Schema struct { - url string // absolute url of the resource - ptr string // json-pointer to schema. always starts with `#` - - // type agnostic validations - always *bool // always pass/fail - ref *Schema - types []string - constant []interface{} - enum []interface{} - enumError string // error message for enum fail - not *Schema - allOf []*Schema - anyOf []*Schema - oneOf []*Schema - - // object validations - minProperties int // -1 if not specified - maxProperties int // -1 if not specified - required []string - properties map[string]*Schema - propertyNames *Schema - regexProperties bool // property names must be valid regex - patternProperties map[*regexp.Regexp]*Schema - additionalProperties interface{} // nil or false or *Schema - dependencies map[string]interface{} // value is *Schema or []string - - // array validations - minItems int // -1 if not specified - maxItems int // -1 if not specified - uniqueItems bool - items interface{} // nil or *Schema or []*Schema - additionalItems interface{} // nil or bool or *Schema - contains *Schema - - // string validations - minLength int // -1 if not specified - maxLength int // -1 if not specified - pattern *regexp.Regexp - format formats.Format - formatName string - - // number validators - minimum *big.Float - exclusiveMinimum *big.Float - maximum *big.Float - exclusiveMaximum *big.Float - multipleOf *big.Float -} - -// Compile parses json-schema at given url returns, if successful, -// a Schema object that can be used to match against json. -// -// The json-schema is validated with draft4 specification. -// Returned error can be *SchemaError -func Compile(url string) (*Schema, error) { - return NewCompiler().Compile(url) -} - -// MustCompile is like Compile but panics if the url cannot be compiled to *Schema. -// It simplifies safe initialization of global variables holding compiled Schemas. -func MustCompile(url string) *Schema { - return NewCompiler().MustCompile(url) -} - -// Validate validates the given json data, against the json-schema. -// -// Returned error can be *ValidationError. -func (s *Schema) Validate(r io.Reader) error { - doc, err := DecodeJSON(r) - if err != nil { - return err - } - return s.ValidateInterface(doc) -} - -// ValidateInterface validates given doc, against the json-schema. -// -// the doc must be the value decoded by json package using interface{} type. -// we recommend to use jsonschema.DecodeJSON(io.Reader) to decode JSON. -func (s *Schema) ValidateInterface(doc interface{}) (err error) { - defer func() { - if r := recover(); r != nil { - if _, ok := r.(InvalidJSONTypeError); ok { - err = r.(InvalidJSONTypeError) - } else { - panic(r) - } - } - }() - if err := s.validate(doc); err != nil { - finishSchemaContext(err, s) - finishInstanceContext(err) - return &ValidationError{ - Message: fmt.Sprintf("doesn't validate with %q", s.url+s.ptr), - InstancePtr: "#", - SchemaURL: s.url, - SchemaPtr: s.ptr, - Causes: []*ValidationError{err.(*ValidationError)}, - } - } - return nil -} - -// validate validates given value v with this schema. -func (s *Schema) validate(v interface{}) error { - if s.always != nil { - if !*s.always { - return validationError("", "always fail") - } - return nil - } - - if s.ref != nil { - if err := s.ref.validate(v); err != nil { - finishSchemaContext(err, s.ref) - var refURL string - if s.url == s.ref.url { - refURL = s.ref.ptr - } else { - refURL = s.ref.url + s.ref.ptr - } - return validationError("$ref", "doesn't validate with %q", refURL).add(err) - } - - // All other properties in a "$ref" object MUST be ignored - return nil - } - - if len(s.types) > 0 { - vType := jsonType(v) - matched := false - for _, t := range s.types { - if vType == t { - matched = true - break - } else if t == "integer" && vType == "number" { - if _, ok := new(big.Int).SetString(fmt.Sprint(v), 10); ok { - matched = true - break - } - } - } - if !matched { - return validationError("type", "expected %s, but got %s", strings.Join(s.types, " or "), vType) - } - } - - if len(s.constant) > 0 { - if !equals(v, s.constant[0]) { - switch jsonType(s.constant[0]) { - case "object", "array": - return validationError("const", "const failed") - default: - return validationError("const", "value must be %#v", s.constant[0]) - } - } - } - - if len(s.enum) > 0 { - matched := false - for _, item := range s.enum { - if equals(v, item) { - matched = true - break - } - } - if !matched { - return validationError("enum", s.enumError) - } - } - - if s.not != nil && s.not.validate(v) == nil { - return validationError("not", "not failed") - } - - for i, sch := range s.allOf { - if err := sch.validate(v); err != nil { - return validationError("allOf/"+strconv.Itoa(i), "allOf failed").add(err) - } - } - - if len(s.anyOf) > 0 { - matched := false - var causes []error - for i, sch := range s.anyOf { - if err := sch.validate(v); err == nil { - matched = true - break - } else { - causes = append(causes, addContext("", strconv.Itoa(i), err)) - } - } - if !matched { - return validationError("anyOf", "anyOf failed").add(causes...) - } - } - - if len(s.oneOf) > 0 { - matched := -1 - var causes []error - for i, sch := range s.oneOf { - if err := sch.validate(v); err == nil { - if matched == -1 { - matched = i - } else { - return validationError("oneOf", "valid against schemas at indexes %d and %d", matched, i) - } - } else { - causes = append(causes, addContext("", strconv.Itoa(i), err)) - } - } - if matched == -1 { - return validationError("oneOf", "oneOf failed").add(causes...) - } - } - - switch v := v.(type) { - case map[string]interface{}: - if s.minProperties != -1 && len(v) < s.minProperties { - return validationError("minProperties", "minimum %d properties allowed, but found %d properties", s.minProperties, len(v)) - } - if s.maxProperties != -1 && len(v) > s.maxProperties { - return validationError("maxProperties", "maximum %d properties allowed, but found %d properties", s.maxProperties, len(v)) - } - if len(s.required) > 0 { - var missing []string - for _, pname := range s.required { - if _, ok := v[pname]; !ok { - missing = append(missing, strconv.Quote(pname)) - } - } - if len(missing) > 0 { - return validationError("required", "missing properties: %s", strings.Join(missing, ", ")) - } - } - - var additionalProps map[string]struct{} - if s.additionalProperties != nil { - additionalProps = make(map[string]struct{}, len(v)) - for pname := range v { - additionalProps[pname] = struct{}{} - } - } - - if len(s.properties) > 0 { - for pname, pschema := range s.properties { - if pvalue, ok := v[pname]; ok { - delete(additionalProps, pname) - if err := pschema.validate(pvalue); err != nil { - return addContext(escape(pname), "properties/"+escape(pname), err) - } - } - } - } - - if s.propertyNames != nil { - for pname := range v { - if err := s.propertyNames.validate(pname); err != nil { - return addContext(escape(pname), "propertyNames", err) - } - } - } - - if s.regexProperties { - for pname := range v { - if !formats.IsRegex(pname) { - return validationError("", "patternProperty %q is not valid regex", pname) - } - } - } - for pattern, pschema := range s.patternProperties { - for pname, pvalue := range v { - if pattern.MatchString(pname) { - delete(additionalProps, pname) - if err := pschema.validate(pvalue); err != nil { - return addContext(escape(pname), "patternProperties/"+escape(pattern.String()), err) - } - } - } - } - if s.additionalProperties != nil { - if _, ok := s.additionalProperties.(bool); ok { - if len(additionalProps) != 0 { - pnames := make([]string, 0, len(additionalProps)) - for pname := range additionalProps { - pnames = append(pnames, strconv.Quote(pname)) - } - return validationError("additionalProperties", "additionalProperties %s not allowed", strings.Join(pnames, ", ")) - } - } else { - schema := s.additionalProperties.(*Schema) - for pname := range additionalProps { - if pvalue, ok := v[pname]; ok { - if err := schema.validate(pvalue); err != nil { - return addContext(escape(pname), "additionalProperties", err) - } - } - } - } - } - for dname, dvalue := range s.dependencies { - if _, ok := v[dname]; ok { - switch dvalue := dvalue.(type) { - case *Schema: - if err := dvalue.validate(v); err != nil { - return addContext("", "dependencies/"+escape(dname), err) - } - case []string: - for i, pname := range dvalue { - if _, ok := v[pname]; !ok { - return validationError("dependencies/"+escape(dname)+"/"+strconv.Itoa(i), "property %q is required, if %q property exists", pname, dname) - } - } - } - } - } - - case []interface{}: - if s.minItems != -1 && len(v) < s.minItems { - return validationError("minItems", "minimum %d items allowed, but found %d items", s.minItems, len(v)) - } - if s.maxItems != -1 && len(v) > s.maxItems { - return validationError("maxItems", "maximum %d items allowed, but found %d items", s.maxItems, len(v)) - } - if s.uniqueItems { - for i := 1; i < len(v); i++ { - for j := 0; j < i; j++ { - if equals(v[i], v[j]) { - return validationError("uniqueItems", "items at index %d and %d are equal", j, i) - } - } - } - } - switch items := s.items.(type) { - case *Schema: - for i, item := range v { - if err := items.validate(item); err != nil { - return addContext(strconv.Itoa(i), "items", err) - } - } - case []*Schema: - if additionalItems, ok := s.additionalItems.(bool); ok { - if !additionalItems && len(v) > len(items) { - return validationError("additionalItems", "only %d items are allowed, but found %d items", len(items), len(v)) - } - } - for i, item := range v { - if i < len(items) { - if err := items[i].validate(item); err != nil { - return addContext(strconv.Itoa(i), "items/"+strconv.Itoa(i), err) - } - } else if sch, ok := s.additionalItems.(*Schema); ok { - if err := sch.validate(item); err != nil { - return addContext(strconv.Itoa(i), "additionalItems", err) - } - } else { - break - } - } - } - if s.contains != nil { - matched := false - var causes []error - for i, item := range v { - if err := s.contains.validate(item); err != nil { - causes = append(causes, addContext(strconv.Itoa(i), "", err)) - } else { - matched = true - break - } - } - if !matched { - return validationError("contains", "contains failed").add(causes...) - } - } - - case string: - if s.minLength != -1 || s.maxLength != -1 { - length := utf8.RuneCount([]byte(v)) - if s.minLength != -1 && length < s.minLength { - return validationError("minLength", "length must be >= %d, but got %d", s.minLength, length) - } - if s.maxLength != -1 && length > s.maxLength { - return validationError("maxLength", "length must be <= %d, but got %d", s.maxLength, length) - } - } - if s.pattern != nil && !s.pattern.MatchString(v) { - return validationError("pattern", "does not match pattern %q", s.pattern) - } - if s.format != nil && !s.format(v) { - return validationError("format", "%q is not valid %q", v, s.formatName) - } - - case json.Number, float64, int, int32, int64: - num, _ := new(big.Float).SetString(fmt.Sprint(v)) - if s.minimum != nil && num.Cmp(s.minimum) < 0 { - return validationError("minimum", "must be >= %v but found %v", s.minimum, v) - } - if s.exclusiveMinimum != nil && num.Cmp(s.exclusiveMinimum) <= 0 { - return validationError("exclusiveMinimum", "must be > %v but found %v", s.exclusiveMinimum, v) - } - if s.maximum != nil && num.Cmp(s.maximum) > 0 { - return validationError("maximum", "must be <= %v but found %v", s.maximum, v) - } - if s.exclusiveMaximum != nil && num.Cmp(s.exclusiveMaximum) >= 0 { - return validationError("exclusiveMaximum", "must be < %v but found %v", s.exclusiveMaximum, v) - } - if s.multipleOf != nil { - if q := new(big.Float).Quo(num, s.multipleOf); !q.IsInt() { - return validationError("multipleOf", "%v not multipleOf %v", v, s.multipleOf) - } - } - } - - return nil -} - -// jsonType returns the json type of given value v. -// -// It panics if the given value is not valid json value -func jsonType(v interface{}) string { - switch v.(type) { - case nil: - return "null" - case bool: - return "boolean" - case json.Number, float64, int, int32, int64: - return "number" - case string: - return "string" - case []interface{}: - return "array" - case map[string]interface{}: - return "object" - } - panic(InvalidJSONTypeError(fmt.Sprintf("%T", v))) -} - -// equals tells if given two json values are equal or not. -func equals(v1, v2 interface{}) bool { - v1Type := jsonType(v1) - if v1Type != jsonType(v2) { - return false - } - switch v1Type { - case "array": - arr1, arr2 := v1.([]interface{}), v2.([]interface{}) - if len(arr1) != len(arr2) { - return false - } - for i := range arr1 { - if !equals(arr1[i], arr2[i]) { - return false - } - } - return true - case "object": - obj1, obj2 := v1.(map[string]interface{}), v2.(map[string]interface{}) - if len(obj1) != len(obj2) { - return false - } - for k, v1 := range obj1 { - if v2, ok := obj2[k]; ok { - if !equals(v1, v2) { - return false - } - } else { - return false - } - } - return true - case "number": - num1, _ := new(big.Float).SetString(string(v1.(json.Number))) - num2, _ := new(big.Float).SetString(string(v2.(json.Number))) - return num1.Cmp(num2) == 0 - default: - return v1 == v2 - } -} - -// escape converts given token to valid json-pointer token -func escape(token string) string { - token = strings.Replace(token, "~", "~0", -1) - token = strings.Replace(token, "/", "~1", -1) - return url.PathEscape(token) -} diff --git a/vendor/github.com/santhosh-tekuri/jsonschema/schema_test.go b/vendor/github.com/santhosh-tekuri/jsonschema/schema_test.go deleted file mode 100644 index 45a99de..0000000 --- a/vendor/github.com/santhosh-tekuri/jsonschema/schema_test.go +++ /dev/null @@ -1,336 +0,0 @@ -// Copyright 2017 Santhosh Kumar Tekuri. All rights reserved. -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. - -package jsonschema_test - -import ( - "bytes" - "crypto/tls" - "encoding/json" - "io/ioutil" - "net/http" - "net/http/httptest" - "os" - "path/filepath" - "strings" - "testing" - - "github.com/santhosh-tekuri/jsonschema" - _ "github.com/santhosh-tekuri/jsonschema/httploader" -) - -var draft4, draft6 []byte - -func init() { - var err error - draft4, err = ioutil.ReadFile("testdata/draft4.json") - if err != nil { - panic(err) - } - draft6, err = ioutil.ReadFile("testdata/draft6.json") - if err != nil { - panic(err) - } -} -func TestDraft4(t *testing.T) { - testFolder(t, "testdata/draft4", jsonschema.Draft4) -} - -func TestDraft6(t *testing.T) { - testFolder(t, "testdata/draft6", jsonschema.Draft6) -} - -type testGroup struct { - Description string - Schema json.RawMessage - Tests []struct { - Description string - Data json.RawMessage - Valid bool - } -} - -func testFolder(t *testing.T, folder string, draft *jsonschema.Draft) { - server := &http.Server{Addr: ":1234", Handler: http.FileServer(http.Dir("testdata/remotes"))} - go func() { - if err := server.ListenAndServe(); err != http.ErrServerClosed { - t.Fatal(err) - } - }() - defer server.Close() - - err := filepath.Walk(folder, func(path string, info os.FileInfo, err error) error { - if err != nil { - t.Error(err) - return nil - } - if info.IsDir() { - return nil - } - if filepath.Ext(info.Name()) != ".json" { - return nil - } - - t.Log(info.Name()) - data, err := ioutil.ReadFile(path) - if err != nil { - t.Errorf(" FAIL: %v\n", err) - return nil - } - var tg []testGroup - if err = json.Unmarshal(data, &tg); err != nil { - t.Errorf(" FAIL: %v\n", err) - return nil - } - for _, group := range tg { - t.Logf(" %s\n", group.Description) - c := jsonschema.NewCompiler() - if err := c.AddResource("http://json-schema.org/draft-04/schema", bytes.NewReader(draft4)); err != nil { - t.Errorf(" FAIL: add resource failed, reason: %v\n", err) - continue - } - if err := c.AddResource("http://json-schema.org/draft-06/schema", bytes.NewReader(draft6)); err != nil { - t.Errorf(" FAIL: add resource failed, reason: %v\n", err) - continue - } - c.Draft = draft - if err := c.AddResource("test.json", bytes.NewReader(group.Schema)); err != nil { - t.Errorf(" FAIL: add resource failed, reason: %v\n", err) - continue - } - schema, err := c.Compile("test.json") - if err != nil { - t.Errorf(" FAIL: schema compilation failed, reason: %v\n", err) - continue - } - for _, test := range group.Tests { - t.Logf(" %s\n", test.Description) - err = schema.Validate(bytes.NewReader(test.Data)) - valid := err == nil - if !valid { - for _, line := range strings.Split(err.Error(), "\n") { - t.Logf(" %s\n", line) - } - } - if test.Valid != valid { - t.Errorf(" FAIL: expected valid=%t got valid=%t\n", test.Valid, valid) - } - } - } - return nil - }) - if err != nil { - t.Fatal(err) - } - - invalidDocTests := []struct { - description string - doc string - }{ - {"non json instance", "{"}, - {"multiple json instance", "{}{}"}, - } - for _, test := range invalidDocTests { - t.Run(test.description, func(t *testing.T) { - c := jsonschema.NewCompiler() - if err := c.AddResource("test.json", strings.NewReader("{}")); err != nil { - t.Fatal(err) - } - s, err := c.Compile("test.json") - if err != nil { - t.Fatal(err) - } - if err := s.Validate(strings.NewReader(test.doc)); err != nil { - t.Log(err) - } else { - t.Error("error expected") - } - }) - } -} - -func TestInvalidSchema(t *testing.T) { - t.Run("MustCompile with panic", func(t *testing.T) { - defer func() { - if r := recover(); r == nil { - t.Error("panic expected") - } - }() - jsonschema.MustCompile("testdata/invalid_schema.json") - }) - - t.Run("MustCompile without panic", func(t *testing.T) { - defer func() { - if r := recover(); r != nil { - t.Error("panic not expected") - } - }() - jsonschema.MustCompile("testdata/customer_schema.json#/0") - }) - - t.Run("invalid json", func(t *testing.T) { - if err := jsonschema.NewCompiler().AddResource("test.json", strings.NewReader("{")); err == nil { - t.Error("error expected") - } else { - t.Log(err) - } - }) - - t.Run("multiple json", func(t *testing.T) { - if err := jsonschema.NewCompiler().AddResource("test.json", strings.NewReader("{}{}")); err == nil { - t.Error("error expected") - } else { - t.Log(err) - } - }) - - type test struct { - Description string - Schema json.RawMessage - Fragment string - } - data, err := ioutil.ReadFile("testdata/invalid_schemas.json") - if err != nil { - t.Fatal(err) - } - var tests []test - if err = json.Unmarshal(data, &tests); err != nil { - t.Fatal(err) - } - for _, test := range tests { - t.Run(test.Description, func(t *testing.T) { - c := jsonschema.NewCompiler() - url := "test.json" - if err := c.AddResource(url, bytes.NewReader(test.Schema)); err != nil { - t.Fatal(err) - } - if len(test.Fragment) > 0 { - url += test.Fragment - } - if _, err = c.Compile(url); err == nil { - t.Error("error expected") - } else { - t.Log(err) - } - }) - } -} - -func TestCompileURL(t *testing.T) { - tr := http.DefaultTransport.(*http.Transport) - if tr.TLSClientConfig == nil { - tr.TLSClientConfig = &tls.Config{} - } - tr.TLSClientConfig.InsecureSkipVerify = true - - handler := http.FileServer(http.Dir("testdata")) - httpServer := httptest.NewServer(handler) - defer httpServer.Close() - httpsServer := httptest.NewTLSServer(handler) - defer httpsServer.Close() - - abs, err := filepath.Abs("testdata") - if err != nil { - t.Error(err) - return - } - validTests := []struct { - schema, doc string - }{ - {"testdata/customer_schema.json#/0", "testdata/customer.json"}, - {"file://" + abs + "/customer_schema.json#/0", "testdata/customer.json"}, - {httpServer.URL + "/customer_schema.json#/0", "testdata/customer.json"}, - {httpsServer.URL + "/customer_schema.json#/0", "testdata/customer.json"}, - } - for i, test := range validTests { - t.Logf("valid #%d: %+v", i, test) - s, err := jsonschema.Compile(test.schema) - if err != nil { - t.Errorf("valid #%d: %v", i, err) - return - } - f, err := os.Open(test.doc) - if err != nil { - t.Errorf("valid #%d: %v", i, err) - return - } - err = s.Validate(f) - _ = f.Close() - if err != nil { - t.Errorf("valid #%d: %v", i, err) - } - } - - invalidTests := []string{ - "testdata/syntax_error.json", - "testdata/missing.json", - "file://" + abs + "/missing.json", - httpServer.URL + "/missing.json", - httpsServer.URL + "/missing.json", - } - for i, test := range invalidTests { - t.Logf("invalid #%d: %v", i, test) - if _, err := jsonschema.Compile(test); err == nil { - t.Errorf("invalid #%d: expected error", i) - } else { - t.Logf("invalid #%d: %v", i, err) - } - } -} - -func TestValidateInterface(t *testing.T) { - files := []string{ - "testdata/draft4/type.json", - "testdata/draft4/minimum.json", - "testdata/draft4/maximum.json", - } - for _, file := range files { - t.Log(filepath.Base(file)) - data, err := ioutil.ReadFile(file) - if err != nil { - t.Errorf(" FAIL: %v\n", err) - return - } - var tg []testGroup - if err = json.Unmarshal(data, &tg); err != nil { - t.Errorf(" FAIL: %v\n", err) - return - } - for _, group := range tg { - t.Logf(" %s\n", group.Description) - c := jsonschema.NewCompiler() - if err := c.AddResource("test.json", bytes.NewReader(group.Schema)); err != nil { - t.Errorf(" FAIL: add resource failed, reason: %v\n", err) - continue - } - c.Draft = jsonschema.Draft4 - schema, err := c.Compile("test.json") - if err != nil { - t.Errorf(" FAIL: schema compilation failed, reason: %v\n", err) - continue - } - for _, test := range group.Tests { - t.Logf(" %s\n", test.Description) - - decoder := json.NewDecoder(bytes.NewReader(test.Data)) - var doc interface{} - if err := decoder.Decode(&doc); err != nil { - t.Errorf(" FAIL: decode json failed, reason: %v\n", err) - continue - } - - err = schema.ValidateInterface(doc) - valid := err == nil - if !valid { - for _, line := range strings.Split(err.Error(), "\n") { - t.Logf(" %s\n", line) - } - } - if test.Valid != valid { - t.Errorf(" FAIL: expected valid=%t got valid=%t\n", test.Valid, valid) - } - } - } - } -} diff --git a/vendor/github.com/santhosh-tekuri/jsonschema/testdata/customer.json b/vendor/github.com/santhosh-tekuri/jsonschema/testdata/customer.json deleted file mode 100644 index 7bcaf11..0000000 --- a/vendor/github.com/santhosh-tekuri/jsonschema/testdata/customer.json +++ /dev/null @@ -1,12 +0,0 @@ -{ - "shipping_address": { - "street_address": "1600 Pennsylvania Avenue NW", - "city": "Washington", - "state": "DC" - }, - "billing_address": { - "street_address": "1st Street SE", - "city": "Washington", - "state": "DC" - } -} diff --git a/vendor/github.com/santhosh-tekuri/jsonschema/testdata/customer_schema.json b/vendor/github.com/santhosh-tekuri/jsonschema/testdata/customer_schema.json deleted file mode 100644 index db00584..0000000 --- a/vendor/github.com/santhosh-tekuri/jsonschema/testdata/customer_schema.json +++ /dev/null @@ -1,10 +0,0 @@ -[ - { - "$schema": "http://json-schema.org/draft-04/schema#", - "type": "object", - "properties": { - "billing_address": { "$ref": "definitions.json#/address" }, - "shipping_address": { "$ref": "definitions.json#/address" } - } - } -] diff --git a/vendor/github.com/santhosh-tekuri/jsonschema/testdata/definitions.json b/vendor/github.com/santhosh-tekuri/jsonschema/testdata/definitions.json deleted file mode 100644 index abd17ca..0000000 --- a/vendor/github.com/santhosh-tekuri/jsonschema/testdata/definitions.json +++ /dev/null @@ -1,11 +0,0 @@ -{ - "address": { - "type": "object", - "properties": { - "street_address": { "type": "string" }, - "city": { "type": "string" }, - "state": { "type": "string" } - }, - "required": ["street_address", "city", "state"] - } -} diff --git a/vendor/github.com/santhosh-tekuri/jsonschema/testdata/draft4.json b/vendor/github.com/santhosh-tekuri/jsonschema/testdata/draft4.json deleted file mode 100644 index 0381502..0000000 --- a/vendor/github.com/santhosh-tekuri/jsonschema/testdata/draft4.json +++ /dev/null @@ -1,231 +0,0 @@ -{ - "$schema": "http://json-schema.org/draft-04/schema#", - "description": "Core schema meta-schema", - "definitions": { - "schemaArray": { - "type": "array", - "minItems": 1, - "items": { - "$ref": "#" - } - }, - "positiveInteger": { - "type": "integer", - "minimum": 0 - }, - "positiveIntegerDefault0": { - "allOf": [ - { - "$ref": "#/definitions/positiveInteger" - }, - { - "default": 0 - } - ] - }, - "simpleTypes": { - "enum": [ - "array", - "boolean", - "integer", - "null", - "number", - "object", - "string" - ] - }, - "stringArray": { - "type": "array", - "items": { - "type": "string" - }, - "minItems": 1, - "uniqueItems": true - } - }, - "type": "object", - "properties": { - "id": { - "type": "string", - "format": "uriref" - }, - "$schema": { - "type": "string", - "format": "uri" - }, - "title": { - "type": "string" - }, - "description": { - "type": "string" - }, - "default": {}, - "multipleOf": { - "type": "number", - "minimum": 0, - "exclusiveMinimum": true - }, - "maximum": { - "type": "number" - }, - "exclusiveMaximum": { - "type": "boolean", - "default": false - }, - "minimum": { - "type": "number" - }, - "exclusiveMinimum": { - "type": "boolean", - "default": false - }, - "maxLength": { - "$ref": "#/definitions/positiveInteger" - }, - "minLength": { - "$ref": "#/definitions/positiveIntegerDefault0" - }, - "pattern": { - "type": "string", - "format": "regex" - }, - "additionalItems": { - "anyOf": [ - { - "type": "boolean" - }, - { - "$ref": "#" - } - ], - "default": {} - }, - "items": { - "anyOf": [ - { - "$ref": "#" - }, - { - "$ref": "#/definitions/schemaArray" - } - ], - "default": {} - }, - "maxItems": { - "$ref": "#/definitions/positiveInteger" - }, - "minItems": { - "$ref": "#/definitions/positiveIntegerDefault0" - }, - "uniqueItems": { - "type": "boolean", - "default": false - }, - "maxProperties": { - "$ref": "#/definitions/positiveInteger" - }, - "minProperties": { - "$ref": "#/definitions/positiveIntegerDefault0" - }, - "required": { - "$ref": "#/definitions/stringArray" - }, - "additionalProperties": { - "anyOf": [ - { - "type": "boolean" - }, - { - "$ref": "#" - } - ], - "default": {} - }, - "definitions": { - "type": "object", - "additionalProperties": { - "$ref": "#" - }, - "default": {} - }, - "properties": { - "type": "object", - "additionalProperties": { - "$ref": "#" - }, - "default": {} - }, - "patternProperties": { - "type": "object", - "regexProperties": true, - "additionalProperties": { - "$ref": "#" - }, - "default": {} - }, - "regexProperties": { - "type": "boolean" - }, - "dependencies": { - "type": "object", - "additionalProperties": { - "anyOf": [ - { - "$ref": "#" - }, - { - "$ref": "#/definitions/stringArray" - } - ] - } - }, - "enum": { - "type": "array", - "minItems": 1, - "uniqueItems": true - }, - "type": { - "anyOf": [ - { - "$ref": "#/definitions/simpleTypes" - }, - { - "type": "array", - "items": { - "$ref": "#/definitions/simpleTypes" - }, - "minItems": 1, - "uniqueItems": true - } - ] - }, - "allOf": { - "$ref": "#/definitions/schemaArray" - }, - "anyOf": { - "$ref": "#/definitions/schemaArray" - }, - "oneOf": { - "$ref": "#/definitions/schemaArray" - }, - "not": { - "$ref": "#" - }, - "format": { - "type": "string", - "format": "format" - }, - "$ref": { - "type": "string" - } - }, - "dependencies": { - "exclusiveMaximum": [ - "maximum" - ], - "exclusiveMinimum": [ - "minimum" - ] - }, - "default": {} -} \ No newline at end of file diff --git a/vendor/github.com/santhosh-tekuri/jsonschema/testdata/draft4/additionalItems.json b/vendor/github.com/santhosh-tekuri/jsonschema/testdata/draft4/additionalItems.json deleted file mode 100644 index abecc57..0000000 --- a/vendor/github.com/santhosh-tekuri/jsonschema/testdata/draft4/additionalItems.json +++ /dev/null @@ -1,87 +0,0 @@ -[ - { - "description": "additionalItems as schema", - "schema": { - "items": [{}], - "additionalItems": {"type": "integer"} - }, - "tests": [ - { - "description": "additional items match schema", - "data": [ null, 2, 3, 4 ], - "valid": true - }, - { - "description": "additional items do not match schema", - "data": [ null, 2, 3, "foo" ], - "valid": false - } - ] - }, - { - "description": "items is schema, no additionalItems", - "schema": { - "items": {}, - "additionalItems": false - }, - "tests": [ - { - "description": "all items match schema", - "data": [ 1, 2, 3, 4, 5 ], - "valid": true - } - ] - }, - { - "description": "array of items with no additionalItems", - "schema": { - "items": [{}, {}, {}], - "additionalItems": false - }, - "tests": [ - { - "description": "fewer number of items present", - "data": [ 1, 2 ], - "valid": true - }, - { - "description": "equal number of items present", - "data": [ 1, 2, 3 ], - "valid": true - }, - { - "description": "additional items are not permitted", - "data": [ 1, 2, 3, 4 ], - "valid": false - } - ] - }, - { - "description": "additionalItems as false without items", - "schema": {"additionalItems": false}, - "tests": [ - { - "description": - "items defaults to empty schema so everything is valid", - "data": [ 1, 2, 3, 4, 5 ], - "valid": true - }, - { - "description": "ignores non-arrays", - "data": {"foo" : "bar"}, - "valid": true - } - ] - }, - { - "description": "additionalItems are allowed by default", - "schema": {"items": [{"type": "integer"}]}, - "tests": [ - { - "description": "only the first item is validated", - "data": [1, "foo", false], - "valid": true - } - ] - } -] diff --git a/vendor/github.com/santhosh-tekuri/jsonschema/testdata/draft4/additionalProperties.json b/vendor/github.com/santhosh-tekuri/jsonschema/testdata/draft4/additionalProperties.json deleted file mode 100644 index 40831f9..0000000 --- a/vendor/github.com/santhosh-tekuri/jsonschema/testdata/draft4/additionalProperties.json +++ /dev/null @@ -1,88 +0,0 @@ -[ - { - "description": - "additionalProperties being false does not allow other properties", - "schema": { - "properties": {"foo": {}, "bar": {}}, - "patternProperties": { "^v": {} }, - "additionalProperties": false - }, - "tests": [ - { - "description": "no additional properties is valid", - "data": {"foo": 1}, - "valid": true - }, - { - "description": "an additional property is invalid", - "data": {"foo" : 1, "bar" : 2, "quux" : "boom"}, - "valid": false - }, - { - "description": "ignores non-objects", - "data": [1, 2, 3], - "valid": true - }, - { - "description": "patternProperties are not additional properties", - "data": {"foo":1, "vroom": 2}, - "valid": true - } - ] - }, - { - "description": - "additionalProperties allows a schema which should validate", - "schema": { - "properties": {"foo": {}, "bar": {}}, - "additionalProperties": {"type": "boolean"} - }, - "tests": [ - { - "description": "no additional properties is valid", - "data": {"foo": 1}, - "valid": true - }, - { - "description": "an additional valid property is valid", - "data": {"foo" : 1, "bar" : 2, "quux" : true}, - "valid": true - }, - { - "description": "an additional invalid property is invalid", - "data": {"foo" : 1, "bar" : 2, "quux" : 12}, - "valid": false - } - ] - }, - { - "description": - "additionalProperties can exist by itself", - "schema": { - "additionalProperties": {"type": "boolean"} - }, - "tests": [ - { - "description": "an additional valid property is valid", - "data": {"foo" : true}, - "valid": true - }, - { - "description": "an additional invalid property is invalid", - "data": {"foo" : 1}, - "valid": false - } - ] - }, - { - "description": "additionalProperties are allowed by default", - "schema": {"properties": {"foo": {}, "bar": {}}}, - "tests": [ - { - "description": "additional properties are allowed", - "data": {"foo": 1, "bar": 2, "quux": true}, - "valid": true - } - ] - } -] diff --git a/vendor/github.com/santhosh-tekuri/jsonschema/testdata/draft4/allOf.json b/vendor/github.com/santhosh-tekuri/jsonschema/testdata/draft4/allOf.json deleted file mode 100644 index bbb5f89..0000000 --- a/vendor/github.com/santhosh-tekuri/jsonschema/testdata/draft4/allOf.json +++ /dev/null @@ -1,112 +0,0 @@ -[ - { - "description": "allOf", - "schema": { - "allOf": [ - { - "properties": { - "bar": {"type": "integer"} - }, - "required": ["bar"] - }, - { - "properties": { - "foo": {"type": "string"} - }, - "required": ["foo"] - } - ] - }, - "tests": [ - { - "description": "allOf", - "data": {"foo": "baz", "bar": 2}, - "valid": true - }, - { - "description": "mismatch second", - "data": {"foo": "baz"}, - "valid": false - }, - { - "description": "mismatch first", - "data": {"bar": 2}, - "valid": false - }, - { - "description": "wrong type", - "data": {"foo": "baz", "bar": "quux"}, - "valid": false - } - ] - }, - { - "description": "allOf with base schema", - "schema": { - "properties": {"bar": {"type": "integer"}}, - "required": ["bar"], - "allOf" : [ - { - "properties": { - "foo": {"type": "string"} - }, - "required": ["foo"] - }, - { - "properties": { - "baz": {"type": "null"} - }, - "required": ["baz"] - } - ] - }, - "tests": [ - { - "description": "valid", - "data": {"foo": "quux", "bar": 2, "baz": null}, - "valid": true - }, - { - "description": "mismatch base schema", - "data": {"foo": "quux", "baz": null}, - "valid": false - }, - { - "description": "mismatch first allOf", - "data": {"bar": 2, "baz": null}, - "valid": false - }, - { - "description": "mismatch second allOf", - "data": {"foo": "quux", "bar": 2}, - "valid": false - }, - { - "description": "mismatch both", - "data": {"bar": 2}, - "valid": false - } - ] - }, - { - "description": "allOf simple types", - "schema": { - "allOf": [ - {"maximum": 30}, - {"minimum": 20} - ] - }, - "tests": [ - { - "description": "valid", - "data": 25, - "valid": true - }, - { - "description": "mismatch one", - "data": 35, - "valid": false - } - ] - } -] diff --git a/vendor/github.com/santhosh-tekuri/jsonschema/testdata/draft4/anyOf.json b/vendor/github.com/santhosh-tekuri/jsonschema/testdata/draft4/anyOf.json deleted file mode 100644 index a58714a..0000000 --- a/vendor/github.com/santhosh-tekuri/jsonschema/testdata/draft4/anyOf.json +++ /dev/null @@ -1,68 +0,0 @@ -[ - { - "description": "anyOf", - "schema": { - "anyOf": [ - { - "type": "integer" - }, - { - "minimum": 2 - } - ] - }, - "tests": [ - { - "description": "first anyOf valid", - "data": 1, - "valid": true - }, - { - "description": "second anyOf valid", - "data": 2.5, - "valid": true - }, - { - "description": "both anyOf valid", - "data": 3, - "valid": true - }, - { - "description": "neither anyOf valid", - "data": 1.5, - "valid": false - } - ] - }, - { - "description": "anyOf with base schema", - "schema": { - "type": "string", - "anyOf" : [ - { - "maxLength": 2 - }, - { - "minLength": 4 - } - ] - }, - "tests": [ - { - "description": "mismatch base schema", - "data": 3, - "valid": false - }, - { - "description": "one anyOf valid", - "data": "foobar", - "valid": true - }, - { - "description": "both anyOf invalid", - "data": "foo", - "valid": false - } - ] - } -] diff --git a/vendor/github.com/santhosh-tekuri/jsonschema/testdata/draft4/default.json b/vendor/github.com/santhosh-tekuri/jsonschema/testdata/draft4/default.json deleted file mode 100644 index 1762977..0000000 --- a/vendor/github.com/santhosh-tekuri/jsonschema/testdata/draft4/default.json +++ /dev/null @@ -1,49 +0,0 @@ -[ - { - "description": "invalid type for default", - "schema": { - "properties": { - "foo": { - "type": "integer", - "default": [] - } - } - }, - "tests": [ - { - "description": "valid when property is specified", - "data": {"foo": 13}, - "valid": true - }, - { - "description": "still valid when the invalid default is used", - "data": {}, - "valid": true - } - ] - }, - { - "description": "invalid string value for default", - "schema": { - "properties": { - "bar": { - "type": "string", - "minLength": 4, - "default": "bad" - } - } - }, - "tests": [ - { - "description": "valid when property is specified", - "data": {"bar": "good"}, - "valid": true - }, - { - "description": "still valid when the invalid default is used", - "data": {}, - "valid": true - } - ] - } -] diff --git a/vendor/github.com/santhosh-tekuri/jsonschema/testdata/draft4/definitions.json b/vendor/github.com/santhosh-tekuri/jsonschema/testdata/draft4/definitions.json deleted file mode 100644 index cf935a3..0000000 --- a/vendor/github.com/santhosh-tekuri/jsonschema/testdata/draft4/definitions.json +++ /dev/null @@ -1,32 +0,0 @@ -[ - { - "description": "valid definition", - "schema": {"$ref": "http://json-schema.org/draft-04/schema#"}, - "tests": [ - { - "description": "valid definition schema", - "data": { - "definitions": { - "foo": {"type": "integer"} - } - }, - "valid": true - } - ] - }, - { - "description": "invalid definition", - "schema": {"$ref": "http://json-schema.org/draft-04/schema#"}, - "tests": [ - { - "description": "invalid definition schema", - "data": { - "definitions": { - "foo": {"type": 1} - } - }, - "valid": false - } - ] - } -] diff --git a/vendor/github.com/santhosh-tekuri/jsonschema/testdata/draft4/dependencies.json b/vendor/github.com/santhosh-tekuri/jsonschema/testdata/draft4/dependencies.json deleted file mode 100644 index 7b9b16a..0000000 --- a/vendor/github.com/santhosh-tekuri/jsonschema/testdata/draft4/dependencies.json +++ /dev/null @@ -1,113 +0,0 @@ -[ - { - "description": "dependencies", - "schema": { - "dependencies": {"bar": ["foo"]} - }, - "tests": [ - { - "description": "neither", - "data": {}, - "valid": true - }, - { - "description": "nondependant", - "data": {"foo": 1}, - "valid": true - }, - { - "description": "with dependency", - "data": {"foo": 1, "bar": 2}, - "valid": true - }, - { - "description": "missing dependency", - "data": {"bar": 2}, - "valid": false - }, - { - "description": "ignores non-objects", - "data": "foo", - "valid": true - } - ] - }, - { - "description": "multiple dependencies", - "schema": { - "dependencies": {"quux": ["foo", "bar"]} - }, - "tests": [ - { - "description": "neither", - "data": {}, - "valid": true - }, - { - "description": "nondependants", - "data": {"foo": 1, "bar": 2}, - "valid": true - }, - { - "description": "with dependencies", - "data": {"foo": 1, "bar": 2, "quux": 3}, - "valid": true - }, - { - "description": "missing dependency", - "data": {"foo": 1, "quux": 2}, - "valid": false - }, - { - "description": "missing other dependency", - "data": {"bar": 1, "quux": 2}, - "valid": false - }, - { - "description": "missing both dependencies", - "data": {"quux": 1}, - "valid": false - } - ] - }, - { - "description": "multiple dependencies subschema", - "schema": { - "dependencies": { - "bar": { - "properties": { - "foo": {"type": "integer"}, - "bar": {"type": "integer"} - } - } - } - }, - "tests": [ - { - "description": "valid", - "data": {"foo": 1, "bar": 2}, - "valid": true - }, - { - "description": "no dependency", - "data": {"foo": "quux"}, - "valid": true - }, - { - "description": "wrong type", - "data": {"foo": "quux", "bar": 2}, - "valid": false - }, - { - "description": "wrong type other", - "data": {"foo": 2, "bar": "quux"}, - "valid": false - }, - { - "description": "wrong type both", - "data": {"foo": "quux", "bar": "quux"}, - "valid": false - } - ] - } -] diff --git a/vendor/github.com/santhosh-tekuri/jsonschema/testdata/draft4/enum.json b/vendor/github.com/santhosh-tekuri/jsonschema/testdata/draft4/enum.json deleted file mode 100644 index f124436..0000000 --- a/vendor/github.com/santhosh-tekuri/jsonschema/testdata/draft4/enum.json +++ /dev/null @@ -1,72 +0,0 @@ -[ - { - "description": "simple enum validation", - "schema": {"enum": [1, 2, 3]}, - "tests": [ - { - "description": "one of the enum is valid", - "data": 1, - "valid": true - }, - { - "description": "something else is invalid", - "data": 4, - "valid": false - } - ] - }, - { - "description": "heterogeneous enum validation", - "schema": {"enum": [6, "foo", [], true, {"foo": 12}]}, - "tests": [ - { - "description": "one of the enum is valid", - "data": [], - "valid": true - }, - { - "description": "something else is invalid", - "data": null, - "valid": false - }, - { - "description": "objects are deep compared", - "data": {"foo": false}, - "valid": false - } - ] - }, - { - "description": "enums in properties", - "schema": { - "type":"object", - "properties": { - "foo": {"enum":["foo"]}, - "bar": {"enum":["bar"]} - }, - "required": ["bar"] - }, - "tests": [ - { - "description": "both properties are valid", - "data": {"foo":"foo", "bar":"bar"}, - "valid": true - }, - { - "description": "missing optional property is valid", - "data": {"bar":"bar"}, - "valid": true - }, - { - "description": "missing required property is invalid", - "data": {"foo":"foo"}, - "valid": false - }, - { - "description": "missing all properties is invalid", - "data": {}, - "valid": false - } - ] - } -] diff --git a/vendor/github.com/santhosh-tekuri/jsonschema/testdata/draft4/items.json b/vendor/github.com/santhosh-tekuri/jsonschema/testdata/draft4/items.json deleted file mode 100644 index 6a4e648..0000000 --- a/vendor/github.com/santhosh-tekuri/jsonschema/testdata/draft4/items.json +++ /dev/null @@ -1,78 +0,0 @@ -[ - { - "description": "a schema given for items", - "schema": { - "items": {"type": "integer"} - }, - "tests": [ - { - "description": "valid items", - "data": [ 1, 2, 3 ], - "valid": true - }, - { - "description": "wrong type of items", - "data": [1, "x"], - "valid": false - }, - { - "description": "ignores non-arrays", - "data": {"foo" : "bar"}, - "valid": true - }, - { - "description": "JavaScript pseudo-array is valid", - "data": { - "0": "invalid", - "length": 1 - }, - "valid": true - } - ] - }, - { - "description": "an array of schemas for items", - "schema": { - "items": [ - {"type": "integer"}, - {"type": "string"} - ] - }, - "tests": [ - { - "description": "correct types", - "data": [ 1, "foo" ], - "valid": true - }, - { - "description": "wrong types", - "data": [ "foo", 1 ], - "valid": false - }, - { - "description": "incomplete array of items", - "data": [ 1 ], - "valid": true - }, - { - "description": "array with additional items", - "data": [ 1, "foo", true ], - "valid": true - }, - { - "description": "empty array", - "data": [ ], - "valid": true - }, - { - "description": "JavaScript pseudo-array is valid", - "data": { - "0": "invalid", - "1": "valid", - "length": 2 - }, - "valid": true - } - ] - } -] diff --git a/vendor/github.com/santhosh-tekuri/jsonschema/testdata/draft4/maxItems.json b/vendor/github.com/santhosh-tekuri/jsonschema/testdata/draft4/maxItems.json deleted file mode 100644 index 3b53a6b..0000000 --- a/vendor/github.com/santhosh-tekuri/jsonschema/testdata/draft4/maxItems.json +++ /dev/null @@ -1,28 +0,0 @@ -[ - { - "description": "maxItems validation", - "schema": {"maxItems": 2}, - "tests": [ - { - "description": "shorter is valid", - "data": [1], - "valid": true - }, - { - "description": "exact length is valid", - "data": [1, 2], - "valid": true - }, - { - "description": "too long is invalid", - "data": [1, 2, 3], - "valid": false - }, - { - "description": "ignores non-arrays", - "data": "foobar", - "valid": true - } - ] - } -] diff --git a/vendor/github.com/santhosh-tekuri/jsonschema/testdata/draft4/maxLength.json b/vendor/github.com/santhosh-tekuri/jsonschema/testdata/draft4/maxLength.json deleted file mode 100644 index 811d35b..0000000 --- a/vendor/github.com/santhosh-tekuri/jsonschema/testdata/draft4/maxLength.json +++ /dev/null @@ -1,33 +0,0 @@ -[ - { - "description": "maxLength validation", - "schema": {"maxLength": 2}, - "tests": [ - { - "description": "shorter is valid", - "data": "f", - "valid": true - }, - { - "description": "exact length is valid", - "data": "fo", - "valid": true - }, - { - "description": "too long is invalid", - "data": "foo", - "valid": false - }, - { - "description": "ignores non-strings", - "data": 100, - "valid": true - }, - { - "description": "two supplementary Unicode code points is long enough", - "data": "\uD83D\uDCA9\uD83D\uDCA9", - "valid": true - } - ] - } -] diff --git a/vendor/github.com/santhosh-tekuri/jsonschema/testdata/draft4/maxProperties.json b/vendor/github.com/santhosh-tekuri/jsonschema/testdata/draft4/maxProperties.json deleted file mode 100644 index d282446..0000000 --- a/vendor/github.com/santhosh-tekuri/jsonschema/testdata/draft4/maxProperties.json +++ /dev/null @@ -1,28 +0,0 @@ -[ - { - "description": "maxProperties validation", - "schema": {"maxProperties": 2}, - "tests": [ - { - "description": "shorter is valid", - "data": {"foo": 1}, - "valid": true - }, - { - "description": "exact length is valid", - "data": {"foo": 1, "bar": 2}, - "valid": true - }, - { - "description": "too long is invalid", - "data": {"foo": 1, "bar": 2, "baz": 3}, - "valid": false - }, - { - "description": "ignores non-objects", - "data": "foobar", - "valid": true - } - ] - } -] diff --git a/vendor/github.com/santhosh-tekuri/jsonschema/testdata/draft4/maximum.json b/vendor/github.com/santhosh-tekuri/jsonschema/testdata/draft4/maximum.json deleted file mode 100644 index 82718fb..0000000 --- a/vendor/github.com/santhosh-tekuri/jsonschema/testdata/draft4/maximum.json +++ /dev/null @@ -1,47 +0,0 @@ -[ - { - "description": "maximum validation", - "schema": {"maximum": 3.0}, - "tests": [ - { - "description": "below the maximum is valid", - "data": 2.6, - "valid": true - }, - { - "description": "boundary point is valid", - "data": 3.0, - "valid": true - }, - { - "description": "above the maximum is invalid", - "data": 3.5, - "valid": false - }, - { - "description": "ignores non-numbers", - "data": "x", - "valid": true - } - ] - }, - { - "description": "exclusiveMaximum validation", - "schema": { - "maximum": 3.0, - "exclusiveMaximum": true - }, - "tests": [ - { - "description": "below the maximum is still valid", - "data": 2.2, - "valid": true - }, - { - "description": "boundary point is invalid", - "data": 3.0, - "valid": false - } - ] - } -] diff --git a/vendor/github.com/santhosh-tekuri/jsonschema/testdata/draft4/minItems.json b/vendor/github.com/santhosh-tekuri/jsonschema/testdata/draft4/minItems.json deleted file mode 100644 index ed51188..0000000 --- a/vendor/github.com/santhosh-tekuri/jsonschema/testdata/draft4/minItems.json +++ /dev/null @@ -1,28 +0,0 @@ -[ - { - "description": "minItems validation", - "schema": {"minItems": 1}, - "tests": [ - { - "description": "longer is valid", - "data": [1, 2], - "valid": true - }, - { - "description": "exact length is valid", - "data": [1], - "valid": true - }, - { - "description": "too short is invalid", - "data": [], - "valid": false - }, - { - "description": "ignores non-arrays", - "data": "", - "valid": true - } - ] - } -] diff --git a/vendor/github.com/santhosh-tekuri/jsonschema/testdata/draft4/minLength.json b/vendor/github.com/santhosh-tekuri/jsonschema/testdata/draft4/minLength.json deleted file mode 100644 index 3f09158..0000000 --- a/vendor/github.com/santhosh-tekuri/jsonschema/testdata/draft4/minLength.json +++ /dev/null @@ -1,33 +0,0 @@ -[ - { - "description": "minLength validation", - "schema": {"minLength": 2}, - "tests": [ - { - "description": "longer is valid", - "data": "foo", - "valid": true - }, - { - "description": "exact length is valid", - "data": "fo", - "valid": true - }, - { - "description": "too short is invalid", - "data": "f", - "valid": false - }, - { - "description": "ignores non-strings", - "data": 1, - "valid": true - }, - { - "description": "one supplementary Unicode code point is not long enough", - "data": "\uD83D\uDCA9", - "valid": false - } - ] - } -] diff --git a/vendor/github.com/santhosh-tekuri/jsonschema/testdata/draft4/minProperties.json b/vendor/github.com/santhosh-tekuri/jsonschema/testdata/draft4/minProperties.json deleted file mode 100644 index a72c7d2..0000000 --- a/vendor/github.com/santhosh-tekuri/jsonschema/testdata/draft4/minProperties.json +++ /dev/null @@ -1,28 +0,0 @@ -[ - { - "description": "minProperties validation", - "schema": {"minProperties": 1}, - "tests": [ - { - "description": "longer is valid", - "data": {"foo": 1, "bar": 2}, - "valid": true - }, - { - "description": "exact length is valid", - "data": {"foo": 1}, - "valid": true - }, - { - "description": "too short is invalid", - "data": {}, - "valid": false - }, - { - "description": "ignores non-objects", - "data": "", - "valid": true - } - ] - } -] diff --git a/vendor/github.com/santhosh-tekuri/jsonschema/testdata/draft4/minimum.json b/vendor/github.com/santhosh-tekuri/jsonschema/testdata/draft4/minimum.json deleted file mode 100644 index 9af8ed4..0000000 --- a/vendor/github.com/santhosh-tekuri/jsonschema/testdata/draft4/minimum.json +++ /dev/null @@ -1,47 +0,0 @@ -[ - { - "description": "minimum validation", - "schema": {"minimum": 1.1}, - "tests": [ - { - "description": "above the minimum is valid", - "data": 2.6, - "valid": true - }, - { - "description": "boundary point is valid", - "data": 1.1, - "valid": true - }, - { - "description": "below the minimum is invalid", - "data": 0.6, - "valid": false - }, - { - "description": "ignores non-numbers", - "data": "x", - "valid": true - } - ] - }, - { - "description": "exclusiveMinimum validation", - "schema": { - "minimum": 1.1, - "exclusiveMinimum": true - }, - "tests": [ - { - "description": "above the minimum is still valid", - "data": 1.2, - "valid": true - }, - { - "description": "boundary point is invalid", - "data": 1.1, - "valid": false - } - ] - } -] diff --git a/vendor/github.com/santhosh-tekuri/jsonschema/testdata/draft4/multipleOf.json b/vendor/github.com/santhosh-tekuri/jsonschema/testdata/draft4/multipleOf.json deleted file mode 100644 index ca3b761..0000000 --- a/vendor/github.com/santhosh-tekuri/jsonschema/testdata/draft4/multipleOf.json +++ /dev/null @@ -1,60 +0,0 @@ -[ - { - "description": "by int", - "schema": {"multipleOf": 2}, - "tests": [ - { - "description": "int by int", - "data": 10, - "valid": true - }, - { - "description": "int by int fail", - "data": 7, - "valid": false - }, - { - "description": "ignores non-numbers", - "data": "foo", - "valid": true - } - ] - }, - { - "description": "by number", - "schema": {"multipleOf": 1.5}, - "tests": [ - { - "description": "zero is multiple of anything", - "data": 0, - "valid": true - }, - { - "description": "4.5 is multiple of 1.5", - "data": 4.5, - "valid": true - }, - { - "description": "35 is not multiple of 1.5", - "data": 35, - "valid": false - } - ] - }, - { - "description": "by small number", - "schema": {"multipleOf": 0.0001}, - "tests": [ - { - "description": "0.0075 is multiple of 0.0001", - "data": 0.0075, - "valid": true - }, - { - "description": "0.00751 is not multiple of 0.0001", - "data": 0.00751, - "valid": false - } - ] - } -] diff --git a/vendor/github.com/santhosh-tekuri/jsonschema/testdata/draft4/not.json b/vendor/github.com/santhosh-tekuri/jsonschema/testdata/draft4/not.json deleted file mode 100644 index cbb7f46..0000000 --- a/vendor/github.com/santhosh-tekuri/jsonschema/testdata/draft4/not.json +++ /dev/null @@ -1,96 +0,0 @@ -[ - { - "description": "not", - "schema": { - "not": {"type": "integer"} - }, - "tests": [ - { - "description": "allowed", - "data": "foo", - "valid": true - }, - { - "description": "disallowed", - "data": 1, - "valid": false - } - ] - }, - { - "description": "not multiple types", - "schema": { - "not": {"type": ["integer", "boolean"]} - }, - "tests": [ - { - "description": "valid", - "data": "foo", - "valid": true - }, - { - "description": "mismatch", - "data": 1, - "valid": false - }, - { - "description": "other mismatch", - "data": true, - "valid": false - } - ] - }, - { - "description": "not more complex schema", - "schema": { - "not": { - "type": "object", - "properties": { - "foo": { - "type": "string" - } - } - } - }, - "tests": [ - { - "description": "match", - "data": 1, - "valid": true - }, - { - "description": "other match", - "data": {"foo": 1}, - "valid": true - }, - { - "description": "mismatch", - "data": {"foo": "bar"}, - "valid": false - } - ] - }, - { - "description": "forbidden property", - "schema": { - "properties": { - "foo": { - "not": {} - } - } - }, - "tests": [ - { - "description": "property present", - "data": {"foo": 1, "bar": 2}, - "valid": false - }, - { - "description": "property absent", - "data": {"bar": 1, "baz": 2}, - "valid": true - } - ] - } - -] diff --git a/vendor/github.com/santhosh-tekuri/jsonschema/testdata/draft4/oneOf.json b/vendor/github.com/santhosh-tekuri/jsonschema/testdata/draft4/oneOf.json deleted file mode 100644 index 1eaa4e4..0000000 --- a/vendor/github.com/santhosh-tekuri/jsonschema/testdata/draft4/oneOf.json +++ /dev/null @@ -1,68 +0,0 @@ -[ - { - "description": "oneOf", - "schema": { - "oneOf": [ - { - "type": "integer" - }, - { - "minimum": 2 - } - ] - }, - "tests": [ - { - "description": "first oneOf valid", - "data": 1, - "valid": true - }, - { - "description": "second oneOf valid", - "data": 2.5, - "valid": true - }, - { - "description": "both oneOf valid", - "data": 3, - "valid": false - }, - { - "description": "neither oneOf valid", - "data": 1.5, - "valid": false - } - ] - }, - { - "description": "oneOf with base schema", - "schema": { - "type": "string", - "oneOf" : [ - { - "minLength": 2 - }, - { - "maxLength": 4 - } - ] - }, - "tests": [ - { - "description": "mismatch base schema", - "data": 3, - "valid": false - }, - { - "description": "one oneOf valid", - "data": "foobar", - "valid": true - }, - { - "description": "both oneOf valid", - "data": "foo", - "valid": false - } - ] - } -] diff --git a/vendor/github.com/santhosh-tekuri/jsonschema/testdata/draft4/optional/bignum.json b/vendor/github.com/santhosh-tekuri/jsonschema/testdata/draft4/optional/bignum.json deleted file mode 100644 index ccc7c17..0000000 --- a/vendor/github.com/santhosh-tekuri/jsonschema/testdata/draft4/optional/bignum.json +++ /dev/null @@ -1,107 +0,0 @@ -[ - { - "description": "integer", - "schema": {"type": "integer"}, - "tests": [ - { - "description": "a bignum is an integer", - "data": 12345678910111213141516171819202122232425262728293031, - "valid": true - } - ] - }, - { - "description": "number", - "schema": {"type": "number"}, - "tests": [ - { - "description": "a bignum is a number", - "data": 98249283749234923498293171823948729348710298301928331, - "valid": true - } - ] - }, - { - "description": "integer", - "schema": {"type": "integer"}, - "tests": [ - { - "description": "a negative bignum is an integer", - "data": -12345678910111213141516171819202122232425262728293031, - "valid": true - } - ] - }, - { - "description": "number", - "schema": {"type": "number"}, - "tests": [ - { - "description": "a negative bignum is a number", - "data": -98249283749234923498293171823948729348710298301928331, - "valid": true - } - ] - }, - { - "description": "string", - "schema": {"type": "string"}, - "tests": [ - { - "description": "a bignum is not a string", - "data": 98249283749234923498293171823948729348710298301928331, - "valid": false - } - ] - }, - { - "description": "integer comparison", - "schema": {"maximum": 18446744073709551615}, - "tests": [ - { - "description": "comparison works for high numbers", - "data": 18446744073709551600, - "valid": true - } - ] - }, - { - "description": "float comparison with high precision", - "schema": { - "maximum": 972783798187987123879878123.18878137, - "exclusiveMaximum": true - }, - "tests": [ - { - "description": "comparison works for high numbers", - "data": 972783798187987123879878123.188781371, - "valid": false - } - ] - }, - { - "description": "integer comparison", - "schema": {"minimum": -18446744073709551615}, - "tests": [ - { - "description": "comparison works for very negative numbers", - "data": -18446744073709551600, - "valid": true - } - ] - }, - { - "description": "float comparison with high precision on negative numbers", - "schema": { - "minimum": -972783798187987123879878123.18878137, - "exclusiveMinimum": true - }, - "tests": [ - { - "description": "comparison works for very negative numbers", - "data": -972783798187987123879878123.188781371, - "valid": false - } - ] - } -] diff --git a/vendor/github.com/santhosh-tekuri/jsonschema/testdata/draft4/optional/ecmascript-regex.json b/vendor/github.com/santhosh-tekuri/jsonschema/testdata/draft4/optional/ecmascript-regex.json deleted file mode 100644 index 08dc936..0000000 --- a/vendor/github.com/santhosh-tekuri/jsonschema/testdata/draft4/optional/ecmascript-regex.json +++ /dev/null @@ -1,13 +0,0 @@ -[ - { - "description": "ECMA 262 regex non-compliance", - "schema": { "format": "regex" }, - "tests": [ - { - "description": "ECMA 262 has no support for \\Z anchor from .NET", - "data": "^\\S(|(.|\\n)*\\S)\\Z", - "valid": false - } - ] - } -] diff --git a/vendor/github.com/santhosh-tekuri/jsonschema/testdata/draft4/optional/format.json b/vendor/github.com/santhosh-tekuri/jsonschema/testdata/draft4/optional/format.json deleted file mode 100644 index 80373bd..0000000 --- a/vendor/github.com/santhosh-tekuri/jsonschema/testdata/draft4/optional/format.json +++ /dev/null @@ -1,148 +0,0 @@ -[ - { - "description": "validation of date-time strings", - "schema": {"format": "date-time"}, - "tests": [ - { - "description": "a valid date-time string", - "data": "1963-06-19T08:30:06.283185Z", - "valid": true - }, - { - "description": "an invalid date-time string", - "data": "06/19/1963 08:30:06 PST", - "valid": false - }, - { - "description": "only RFC3339 not all of ISO 8601 are valid", - "data": "2013-350T01:01:01", - "valid": false - } - ] - }, - { - "description": "validation of URIs", - "schema": {"format": "uri"}, - "tests": [ - { - "description": "a valid URI", - "data": "http://foo.bar/?baz=qux#quux", - "valid": true - }, - { - "description": "an invalid protocol-relative URI Reference", - "data": "//foo.bar/?baz=qux#quux", - "valid": false - }, - { - "description": "an invalid URI", - "data": "\\\\WINDOWS\\fileshare", - "valid": false - }, - { - "description": "an invalid URI though valid URI reference", - "data": "abc", - "valid": false - } - ] - }, - { - "description": "validation of e-mail addresses", - "schema": {"format": "email"}, - "tests": [ - { - "description": "a valid e-mail address", - "data": "joe.bloggs@example.com", - "valid": true - }, - { - "description": "an invalid e-mail address", - "data": "2962", - "valid": false - } - ] - }, - { - "description": "validation of IP addresses", - "schema": {"format": "ipv4"}, - "tests": [ - { - "description": "a valid IP address", - "data": "192.168.0.1", - "valid": true - }, - { - "description": "an IP address with too many components", - "data": "127.0.0.0.1", - "valid": false - }, - { - "description": "an IP address with out-of-range values", - "data": "256.256.256.256", - "valid": false - }, - { - "description": "an IP address without 4 components", - "data": "127.0", - "valid": false - }, - { - "description": "an IP address as an integer", - "data": "0x7f000001", - "valid": false - } - ] - }, - { - "description": "validation of IPv6 addresses", - "schema": {"format": "ipv6"}, - "tests": [ - { - "description": "a valid IPv6 address", - "data": "::1", - "valid": true - }, - { - "description": "an IPv6 address with out-of-range values", - "data": "12345::", - "valid": false - }, - { - "description": "an IPv6 address with too many components", - "data": "1:1:1:1:1:1:1:1:1:1:1:1:1:1:1:1", - "valid": false - }, - { - "description": "an IPv6 address containing illegal characters", - "data": "::laptop", - "valid": false - } - ] - }, - { - "description": "validation of host names", - "schema": {"format": "hostname"}, - "tests": [ - { - "description": "a valid host name", - "data": "www.example.com", - "valid": true - }, - { - "description": "a host name starting with an illegal character", - "data": "-a-host-name-that-starts-with--", - "valid": false - }, - { - "description": "a host name containing illegal characters", - "data": "not_a_valid_host_name", - "valid": false - }, - { - "description": "a host name with a component too long", - "data": "a-vvvvvvvvvvvvvvvveeeeeeeeeeeeeeeerrrrrrrrrrrrrrrryyyyyyyyyyyyyyyy-long-host-name-component", - "valid": false - } - ] - } -] diff --git a/vendor/github.com/santhosh-tekuri/jsonschema/testdata/draft4/optional/zeroTerminatedFloats.json b/vendor/github.com/santhosh-tekuri/jsonschema/testdata/draft4/optional/zeroTerminatedFloats.json deleted file mode 100644 index 9b50ea2..0000000 --- a/vendor/github.com/santhosh-tekuri/jsonschema/testdata/draft4/optional/zeroTerminatedFloats.json +++ /dev/null @@ -1,15 +0,0 @@ -[ - { - "description": "some languages do not distinguish between different types of numeric value", - "schema": { - "type": "integer" - }, - "tests": [ - { - "description": "a float is not an integer even without fractional part", - "data": 1.0, - "valid": false - } - ] - } -] diff --git a/vendor/github.com/santhosh-tekuri/jsonschema/testdata/draft4/pattern.json b/vendor/github.com/santhosh-tekuri/jsonschema/testdata/draft4/pattern.json deleted file mode 100644 index 25e7299..0000000 --- a/vendor/github.com/santhosh-tekuri/jsonschema/testdata/draft4/pattern.json +++ /dev/null @@ -1,34 +0,0 @@ -[ - { - "description": "pattern validation", - "schema": {"pattern": "^a*$"}, - "tests": [ - { - "description": "a matching pattern is valid", - "data": "aaa", - "valid": true - }, - { - "description": "a non-matching pattern is invalid", - "data": "abc", - "valid": false - }, - { - "description": "ignores non-strings", - "data": true, - "valid": true - } - ] - }, - { - "description": "pattern is not anchored", - "schema": {"pattern": "a+"}, - "tests": [ - { - "description": "matches a substring", - "data": "xxaayy", - "valid": true - } - ] - } -] diff --git a/vendor/github.com/santhosh-tekuri/jsonschema/testdata/draft4/patternProperties.json b/vendor/github.com/santhosh-tekuri/jsonschema/testdata/draft4/patternProperties.json deleted file mode 100644 index 18586e5..0000000 --- a/vendor/github.com/santhosh-tekuri/jsonschema/testdata/draft4/patternProperties.json +++ /dev/null @@ -1,110 +0,0 @@ -[ - { - "description": - "patternProperties validates properties matching a regex", - "schema": { - "patternProperties": { - "f.*o": {"type": "integer"} - } - }, - "tests": [ - { - "description": "a single valid match is valid", - "data": {"foo": 1}, - "valid": true - }, - { - "description": "multiple valid matches is valid", - "data": {"foo": 1, "foooooo" : 2}, - "valid": true - }, - { - "description": "a single invalid match is invalid", - "data": {"foo": "bar", "fooooo": 2}, - "valid": false - }, - { - "description": "multiple invalid matches is invalid", - "data": {"foo": "bar", "foooooo" : "baz"}, - "valid": false - }, - { - "description": "ignores non-objects", - "data": 12, - "valid": true - } - ] - }, - { - "description": "multiple simultaneous patternProperties are validated", - "schema": { - "patternProperties": { - "a*": {"type": "integer"}, - "aaa*": {"maximum": 20} - } - }, - "tests": [ - { - "description": "a single valid match is valid", - "data": {"a": 21}, - "valid": true - }, - { - "description": "a simultaneous match is valid", - "data": {"aaaa": 18}, - "valid": true - }, - { - "description": "multiple matches is valid", - "data": {"a": 21, "aaaa": 18}, - "valid": true - }, - { - "description": "an invalid due to one is invalid", - "data": {"a": "bar"}, - "valid": false - }, - { - "description": "an invalid due to the other is invalid", - "data": {"aaaa": 31}, - "valid": false - }, - { - "description": "an invalid due to both is invalid", - "data": {"aaa": "foo", "aaaa": 31}, - "valid": false - } - ] - }, - { - "description": "regexes are not anchored by default and are case sensitive", - "schema": { - "patternProperties": { - "[0-9]{2,}": { "type": "boolean" }, - "X_": { "type": "string" } - } - }, - "tests": [ - { - "description": "non recognized members are ignored", - "data": { "answer 1": "42" }, - "valid": true - }, - { - "description": "recognized members are accounted for", - "data": { "a31b": null }, - "valid": false - }, - { - "description": "regexes are case sensitive", - "data": { "a_x_3": 3 }, - "valid": true - }, - { - "description": "regexes are case sensitive, 2", - "data": { "a_X_3": 3 }, - "valid": false - } - ] - } -] diff --git a/vendor/github.com/santhosh-tekuri/jsonschema/testdata/draft4/properties.json b/vendor/github.com/santhosh-tekuri/jsonschema/testdata/draft4/properties.json deleted file mode 100644 index cd1644d..0000000 --- a/vendor/github.com/santhosh-tekuri/jsonschema/testdata/draft4/properties.json +++ /dev/null @@ -1,92 +0,0 @@ -[ - { - "description": "object properties validation", - "schema": { - "properties": { - "foo": {"type": "integer"}, - "bar": {"type": "string"} - } - }, - "tests": [ - { - "description": "both properties present and valid is valid", - "data": {"foo": 1, "bar": "baz"}, - "valid": true - }, - { - "description": "one property invalid is invalid", - "data": {"foo": 1, "bar": {}}, - "valid": false - }, - { - "description": "both properties invalid is invalid", - "data": {"foo": [], "bar": {}}, - "valid": false - }, - { - "description": "doesn't invalidate other properties", - "data": {"quux": []}, - "valid": true - }, - { - "description": "ignores non-objects", - "data": [], - "valid": true - } - ] - }, - { - "description": - "properties, patternProperties, additionalProperties interaction", - "schema": { - "properties": { - "foo": {"type": "array", "maxItems": 3}, - "bar": {"type": "array"} - }, - "patternProperties": {"f.o": {"minItems": 2}}, - "additionalProperties": {"type": "integer"} - }, - "tests": [ - { - "description": "property validates property", - "data": {"foo": [1, 2]}, - "valid": true - }, - { - "description": "property invalidates property", - "data": {"foo": [1, 2, 3, 4]}, - "valid": false - }, - { - "description": "patternProperty invalidates property", - "data": {"foo": []}, - "valid": false - }, - { - "description": "patternProperty validates nonproperty", - "data": {"fxo": [1, 2]}, - "valid": true - }, - { - "description": "patternProperty invalidates nonproperty", - "data": {"fxo": []}, - "valid": false - }, - { - "description": "additionalProperty ignores property", - "data": {"bar": []}, - "valid": true - }, - { - "description": "additionalProperty validates others", - "data": {"quux": 3}, - "valid": true - }, - { - "description": "additionalProperty invalidates others", - "data": {"quux": "foo"}, - "valid": false - } - ] - } -] diff --git a/vendor/github.com/santhosh-tekuri/jsonschema/testdata/draft4/ref.json b/vendor/github.com/santhosh-tekuri/jsonschema/testdata/draft4/ref.json deleted file mode 100644 index 52cf50a..0000000 --- a/vendor/github.com/santhosh-tekuri/jsonschema/testdata/draft4/ref.json +++ /dev/null @@ -1,300 +0,0 @@ -[ - { - "description": "root pointer ref", - "schema": { - "properties": { - "foo": {"$ref": "#"} - }, - "additionalProperties": false - }, - "tests": [ - { - "description": "match", - "data": {"foo": false}, - "valid": true - }, - { - "description": "recursive match", - "data": {"foo": {"foo": false}}, - "valid": true - }, - { - "description": "mismatch", - "data": {"bar": false}, - "valid": false - }, - { - "description": "recursive mismatch", - "data": {"foo": {"bar": false}}, - "valid": false - } - ] - }, - { - "description": "relative pointer ref to object", - "schema": { - "properties": { - "foo": {"type": "integer"}, - "bar": {"$ref": "#/properties/foo"} - } - }, - "tests": [ - { - "description": "match", - "data": {"bar": 3}, - "valid": true - }, - { - "description": "mismatch", - "data": {"bar": true}, - "valid": false - } - ] - }, - { - "description": "relative pointer ref to array", - "schema": { - "items": [ - {"type": "integer"}, - {"$ref": "#/items/0"} - ] - }, - "tests": [ - { - "description": "match array", - "data": [1, 2], - "valid": true - }, - { - "description": "mismatch array", - "data": [1, "foo"], - "valid": false - } - ] - }, - { - "description": "escaped pointer ref", - "schema": { - "tilda~field": {"type": "integer"}, - "slash/field": {"type": "integer"}, - "percent%field": {"type": "integer"}, - "properties": { - "tilda": {"$ref": "#/tilda~0field"}, - "slash": {"$ref": "#/slash~1field"}, - "percent": {"$ref": "#/percent%25field"} - } - }, - "tests": [ - { - "description": "slash invalid", - "data": {"slash": "aoeu"}, - "valid": false - }, - { - "description": "tilda invalid", - "data": {"tilda": "aoeu"}, - "valid": false - }, - { - "description": "percent invalid", - "data": {"percent": "aoeu"}, - "valid": false - }, - { - "description": "slash valid", - "data": {"slash": 123}, - "valid": true - }, - { - "description": "tilda valid", - "data": {"tilda": 123}, - "valid": true - }, - { - "description": "percent valid", - "data": {"percent": 123}, - "valid": true - } - ] - }, - { - "description": "nested refs", - "schema": { - "definitions": { - "a": {"type": "integer"}, - "b": {"$ref": "#/definitions/a"}, - "c": {"$ref": "#/definitions/b"} - }, - "$ref": "#/definitions/c" - }, - "tests": [ - { - "description": "nested ref valid", - "data": 5, - "valid": true - }, - { - "description": "nested ref invalid", - "data": "a", - "valid": false - } - ] - }, - { - "description": "ref overrides any sibling keywords", - "schema": { - "definitions": { - "reffed": { - "type": "array" - } - }, - "properties": { - "foo": { - "$ref": "#/definitions/reffed", - "maxItems": 2 - } - } - }, - "tests": [ - { - "description": "ref valid", - "data": { "foo": [] }, - "valid": true - }, - { - "description": "ref valid, maxItems ignored", - "data": { "foo": [ 1, 2, 3] }, - "valid": true - }, - { - "description": "ref invalid", - "data": { "foo": "string" }, - "valid": false - } - ] - }, - { - "description": "remote ref, containing refs itself", - "schema": {"$ref": "http://json-schema.org/draft-04/schema#"}, - "tests": [ - { - "description": "remote ref valid", - "data": {"minLength": 1}, - "valid": true - }, - { - "description": "remote ref invalid", - "data": {"minLength": -1}, - "valid": false - } - ] - }, - { - "description": "property named $ref that is not a reference", - "schema": { - "properties": { - "$ref": {"type": "string"} - } - }, - "tests": [ - { - "description": "property named $ref valid", - "data": {"$ref": "a"}, - "valid": true - }, - { - "description": "property named $ref invalid", - "data": {"$ref": 2}, - "valid": false - } - ] - }, - { - "description": "Recursive references between schemas", - "schema": { - "id": "http://localhost:1234/tree", - "description": "tree of nodes", - "type": "object", - "properties": { - "meta": {"type": "string"}, - "nodes": { - "type": "array", - "items": {"$ref": "node"} - } - }, - "required": ["meta", "nodes"], - "definitions": { - "node": { - "id": "http://localhost:1234/node", - "description": "node", - "type": "object", - "properties": { - "value": {"type": "number"}, - "subtree": {"$ref": "tree"} - }, - "required": ["value"] - } - } - }, - "tests": [ - { - "description": "valid tree", - "data": { - "meta": "root", - "nodes": [ - { - "value": 1, - "subtree": { - "meta": "child", - "nodes": [ - {"value": 1.1}, - {"value": 1.2} - ] - } - }, - { - "value": 2, - "subtree": { - "meta": "child", - "nodes": [ - {"value": 2.1}, - {"value": 2.2} - ] - } - } - ] - }, - "valid": true - }, - { - "description": "invalid tree", - "data": { - "meta": "root", - "nodes": [ - { - "value": 1, - "subtree": { - "meta": "child", - "nodes": [ - {"value": "string is invalid"}, - {"value": 1.2} - ] - } - }, - { - "value": 2, - "subtree": { - "meta": "child", - "nodes": [ - {"value": 2.1}, - {"value": 2.2} - ] - } - } - ] - }, - "valid": false - } - ] - } -] diff --git a/vendor/github.com/santhosh-tekuri/jsonschema/testdata/draft4/refRemote.json b/vendor/github.com/santhosh-tekuri/jsonschema/testdata/draft4/refRemote.json deleted file mode 100644 index 8611fad..0000000 --- a/vendor/github.com/santhosh-tekuri/jsonschema/testdata/draft4/refRemote.json +++ /dev/null @@ -1,171 +0,0 @@ -[ - { - "description": "remote ref", - "schema": {"$ref": "http://localhost:1234/integer.json"}, - "tests": [ - { - "description": "remote ref valid", - "data": 1, - "valid": true - }, - { - "description": "remote ref invalid", - "data": "a", - "valid": false - } - ] - }, - { - "description": "fragment within remote ref", - "schema": {"$ref": "http://localhost:1234/subSchemas.json#/integer"}, - "tests": [ - { - "description": "remote fragment valid", - "data": 1, - "valid": true - }, - { - "description": "remote fragment invalid", - "data": "a", - "valid": false - } - ] - }, - { - "description": "ref within remote ref", - "schema": { - "$ref": "http://localhost:1234/subSchemas.json#/refToInteger" - }, - "tests": [ - { - "description": "ref within ref valid", - "data": 1, - "valid": true - }, - { - "description": "ref within ref invalid", - "data": "a", - "valid": false - } - ] - }, - { - "description": "base URI change", - "schema": { - "id": "http://localhost:1234/", - "items": { - "id": "folder/", - "items": {"$ref": "folderInteger.json"} - } - }, - "tests": [ - { - "description": "base URI change ref valid", - "data": [[1]], - "valid": true - }, - { - "description": "base URI change ref invalid", - "data": [["a"]], - "valid": false - } - ] - }, - { - "description": "base URI change - change folder", - "schema": { - "id": "http://localhost:1234/scope_change_defs1.json", - "type" : "object", - "properties": { - "list": {"$ref": "#/definitions/baz"} - }, - "definitions": { - "baz": { - "id": "folder/", - "type": "array", - "items": {"$ref": "folderInteger.json"} - } - } - }, - "tests": [ - { - "description": "number is valid", - "data": {"list": [1]}, - "valid": true - }, - { - "description": "string is invalid", - "data": {"list": ["a"]}, - "valid": false - } - ] - }, - { - "description": "base URI change - change folder in subschema", - "schema": { - "id": "http://localhost:1234/scope_change_defs2.json", - "type" : "object", - "properties": { - "list": {"$ref": "#/definitions/baz/definitions/bar"} - }, - "definitions": { - "baz": { - "id": "folder/", - "definitions": { - "bar": { - "type": "array", - "items": {"$ref": "folderInteger.json"} - } - } - } - } - }, - "tests": [ - { - "description": "number is valid", - "data": {"list": [1]}, - "valid": true - }, - { - "description": "string is invalid", - "data": {"list": ["a"]}, - "valid": false - } - ] - }, - { - "description": "root ref in remote ref", - "schema": { - "id": "http://localhost:1234/object", - "type": "object", - "properties": { - "name": {"$ref": "name.json#/definitions/orNull"} - } - }, - "tests": [ - { - "description": "string is valid", - "data": { - "name": "foo" - }, - "valid": true - }, - { - "description": "null is valid", - "data": { - "name": null - }, - "valid": true - }, - { - "description": "object is invalid", - "data": { - "name": { - "name": null - } - }, - "valid": false - } - ] - } -] diff --git a/vendor/github.com/santhosh-tekuri/jsonschema/testdata/draft4/required.json b/vendor/github.com/santhosh-tekuri/jsonschema/testdata/draft4/required.json deleted file mode 100644 index 576ef45..0000000 --- a/vendor/github.com/santhosh-tekuri/jsonschema/testdata/draft4/required.json +++ /dev/null @@ -1,44 +0,0 @@ -[ - { - "description": "required validation", - "schema": { - "properties": { - "foo": {}, - "bar": {} - }, - "required": ["foo"] - }, - "tests": [ - { - "description": "present required property is valid", - "data": {"foo": 1}, - "valid": true - }, - { - "description": "non-present required property is invalid", - "data": {"bar": 1}, - "valid": false - }, - { - "description": "ignores non-objects", - "data": 12, - "valid": true - } - ] - }, - { - "description": "required default validation", - "schema": { - "properties": { - "foo": {} - } - }, - "tests": [ - { - "description": "not required by default", - "data": {}, - "valid": true - } - ] - } -] diff --git a/vendor/github.com/santhosh-tekuri/jsonschema/testdata/draft4/santhosh.json b/vendor/github.com/santhosh-tekuri/jsonschema/testdata/draft4/santhosh.json deleted file mode 100644 index f44a979..0000000 --- a/vendor/github.com/santhosh-tekuri/jsonschema/testdata/draft4/santhosh.json +++ /dev/null @@ -1,130 +0,0 @@ -[ - { - "description": "multipleOf small value", - "schema": {"multipleOf": 0.01}, - "tests": [ - { - "description": "value is valid", - "data": 19.99, - "valid": true - } - ] - }, - { - "description": "enum with single value", - "schema": {"enum": [1]}, - "tests": [ - { - "description": "value is invalid", - "data": 5, - "valid": false - } - ] - }, - { - "description": "enum with array value", - "schema": {"enum": [[ "one", "two", "three"]]}, - "tests": [ - { - "description": "array size does not match", - "data": [ "one", "two" ], - "valid": false - } - ] - }, - { - "description": "enum with object value", - "schema": {"enum": [{ "one": 1, "two": 2, "three": 3}]}, - "tests": [ - { - "description": "object size does not match", - "data": { "one": 1 }, - "valid": false - } - ] - }, - { - "description": "enum with object having null property", - "schema": {"enum": [{ "foo": null }]}, - "tests": [ - { - "description": "valid", - "data": { "foo": null }, - "valid": true - }, - { - "description": "no props is invalid", - "data": { }, - "valid": false - }, - { - "description": "missing null prop is invalid", - "data": { "bar": null }, - "valid": false - } - ] - }, - { - "description": "enum with empty object", - "schema": {"enum": [{}]}, - "tests": [ - { - "description": "valid", - "data": {}, - "valid": true - }, - { - "description": "null prop is invalid", - "data": { "foo": null }, - "valid": false - } - ] - }, - { - "description": "$ref to $id", - "schema": { - "$schema": "http://json-schema.org/draft-04/schema#", - "type": "object", - "definitions": { - "name": { - "id": "#nm", - "type": "string" - }, - "email" : { - "id": "email.json", - "type": "string" - } - }, - "properties": { - "name": { "$ref": "#nm" }, - "email": { "$ref": "email.json"} - } - }, - "tests": [ - { - "description": "valid", - "data": { - "name": "Santhosh Kumar Tekuri", - "email": "santhosh.tekuri@gmail.com" - }, - "valid": true - }, - { - "description": "invalid1", - "data": { - "name": 0, - "email": "santhosh.tekuri@gmail.com" - }, - "valid": false - }, - { - "description": "valid", - "data": { - "name": "Santhosh Kumar Tekuri", - "email": 0 - }, - "valid": false - } - ] - } -] diff --git a/vendor/github.com/santhosh-tekuri/jsonschema/testdata/draft4/type.json b/vendor/github.com/santhosh-tekuri/jsonschema/testdata/draft4/type.json deleted file mode 100644 index 6129374..0000000 --- a/vendor/github.com/santhosh-tekuri/jsonschema/testdata/draft4/type.json +++ /dev/null @@ -1,345 +0,0 @@ -[ - { - "description": "integer type matches integers", - "schema": {"type": "integer"}, - "tests": [ - { - "description": "an integer is an integer", - "data": 1, - "valid": true - }, - { - "description": "a float is not an integer", - "data": 1.1, - "valid": false - }, - { - "description": "a string is not an integer", - "data": "foo", - "valid": false - }, - { - "description": "a string is still not an integer, even if it looks like one", - "data": "1", - "valid": false - }, - { - "description": "an object is not an integer", - "data": {}, - "valid": false - }, - { - "description": "an array is not an integer", - "data": [], - "valid": false - }, - { - "description": "a boolean is not an integer", - "data": true, - "valid": false - }, - { - "description": "null is not an integer", - "data": null, - "valid": false - } - ] - }, - { - "description": "number type matches numbers", - "schema": {"type": "number"}, - "tests": [ - { - "description": "an integer is a number", - "data": 1, - "valid": true - }, - { - "description": "a float is a number", - "data": 1.1, - "valid": true - }, - { - "description": "a string is not a number", - "data": "foo", - "valid": false - }, - { - "description": "a string is still not a number, even if it looks like one", - "data": "1", - "valid": false - }, - { - "description": "an object is not a number", - "data": {}, - "valid": false - }, - { - "description": "an array is not a number", - "data": [], - "valid": false - }, - { - "description": "a boolean is not a number", - "data": true, - "valid": false - }, - { - "description": "null is not a number", - "data": null, - "valid": false - } - ] - }, - { - "description": "string type matches strings", - "schema": {"type": "string"}, - "tests": [ - { - "description": "1 is not a string", - "data": 1, - "valid": false - }, - { - "description": "a float is not a string", - "data": 1.1, - "valid": false - }, - { - "description": "a string is a string", - "data": "foo", - "valid": true - }, - { - "description": "a string is still a string, even if it looks like a number", - "data": "1", - "valid": true - }, - { - "description": "an object is not a string", - "data": {}, - "valid": false - }, - { - "description": "an array is not a string", - "data": [], - "valid": false - }, - { - "description": "a boolean is not a string", - "data": true, - "valid": false - }, - { - "description": "null is not a string", - "data": null, - "valid": false - } - ] - }, - { - "description": "object type matches objects", - "schema": {"type": "object"}, - "tests": [ - { - "description": "an integer is not an object", - "data": 1, - "valid": false - }, - { - "description": "a float is not an object", - "data": 1.1, - "valid": false - }, - { - "description": "a string is not an object", - "data": "foo", - "valid": false - }, - { - "description": "an object is an object", - "data": {}, - "valid": true - }, - { - "description": "an array is not an object", - "data": [], - "valid": false - }, - { - "description": "a boolean is not an object", - "data": true, - "valid": false - }, - { - "description": "null is not an object", - "data": null, - "valid": false - } - ] - }, - { - "description": "array type matches arrays", - "schema": {"type": "array"}, - "tests": [ - { - "description": "an integer is not an array", - "data": 1, - "valid": false - }, - { - "description": "a float is not an array", - "data": 1.1, - "valid": false - }, - { - "description": "a string is not an array", - "data": "foo", - "valid": false - }, - { - "description": "an object is not an array", - "data": {}, - "valid": false - }, - { - "description": "an array is an array", - "data": [], - "valid": true - }, - { - "description": "a boolean is not an array", - "data": true, - "valid": false - }, - { - "description": "null is not an array", - "data": null, - "valid": false - } - ] - }, - { - "description": "boolean type matches booleans", - "schema": {"type": "boolean"}, - "tests": [ - { - "description": "an integer is not a boolean", - "data": 1, - "valid": false - }, - { - "description": "a float is not a boolean", - "data": 1.1, - "valid": false - }, - { - "description": "a string is not a boolean", - "data": "foo", - "valid": false - }, - { - "description": "an object is not a boolean", - "data": {}, - "valid": false - }, - { - "description": "an array is not a boolean", - "data": [], - "valid": false - }, - { - "description": "a boolean is a boolean", - "data": true, - "valid": true - }, - { - "description": "null is not a boolean", - "data": null, - "valid": false - } - ] - }, - { - "description": "null type matches only the null object", - "schema": {"type": "null"}, - "tests": [ - { - "description": "an integer is not null", - "data": 1, - "valid": false - }, - { - "description": "a float is not null", - "data": 1.1, - "valid": false - }, - { - "description": "a string is not null", - "data": "foo", - "valid": false - }, - { - "description": "an object is not null", - "data": {}, - "valid": false - }, - { - "description": "an array is not null", - "data": [], - "valid": false - }, - { - "description": "a boolean is not null", - "data": true, - "valid": false - }, - { - "description": "null is null", - "data": null, - "valid": true - } - ] - }, - { - "description": "multiple types can be specified in an array", - "schema": {"type": ["integer", "string"]}, - "tests": [ - { - "description": "an integer is valid", - "data": 1, - "valid": true - }, - { - "description": "a string is valid", - "data": "foo", - "valid": true - }, - { - "description": "a float is invalid", - "data": 1.1, - "valid": false - }, - { - "description": "an object is invalid", - "data": {}, - "valid": false - }, - { - "description": "an array is invalid", - "data": [], - "valid": false - }, - { - "description": "a boolean is invalid", - "data": true, - "valid": false - }, - { - "description": "null is invalid", - "data": null, - "valid": false - } - ] - } -] diff --git a/vendor/github.com/santhosh-tekuri/jsonschema/testdata/draft4/uniqueItems.json b/vendor/github.com/santhosh-tekuri/jsonschema/testdata/draft4/uniqueItems.json deleted file mode 100644 index c1f4ab9..0000000 --- a/vendor/github.com/santhosh-tekuri/jsonschema/testdata/draft4/uniqueItems.json +++ /dev/null @@ -1,79 +0,0 @@ -[ - { - "description": "uniqueItems validation", - "schema": {"uniqueItems": true}, - "tests": [ - { - "description": "unique array of integers is valid", - "data": [1, 2], - "valid": true - }, - { - "description": "non-unique array of integers is invalid", - "data": [1, 1], - "valid": false - }, - { - "description": "numbers are unique if mathematically unequal", - "data": [1.0, 1.00, 1], - "valid": false - }, - { - "description": "unique array of objects is valid", - "data": [{"foo": "bar"}, {"foo": "baz"}], - "valid": true - }, - { - "description": "non-unique array of objects is invalid", - "data": [{"foo": "bar"}, {"foo": "bar"}], - "valid": false - }, - { - "description": "unique array of nested objects is valid", - "data": [ - {"foo": {"bar" : {"baz" : true}}}, - {"foo": {"bar" : {"baz" : false}}} - ], - "valid": true - }, - { - "description": "non-unique array of nested objects is invalid", - "data": [ - {"foo": {"bar" : {"baz" : true}}}, - {"foo": {"bar" : {"baz" : true}}} - ], - "valid": false - }, - { - "description": "unique array of arrays is valid", - "data": [["foo"], ["bar"]], - "valid": true - }, - { - "description": "non-unique array of arrays is invalid", - "data": [["foo"], ["foo"]], - "valid": false - }, - { - "description": "1 and true are unique", - "data": [1, true], - "valid": true - }, - { - "description": "0 and false are unique", - "data": [0, false], - "valid": true - }, - { - "description": "unique heterogeneous types are valid", - "data": [{}, [1], true, null, 1], - "valid": true - }, - { - "description": "non-unique heterogeneous types are invalid", - "data": [{}, [1], true, null, {}, 1], - "valid": false - } - ] - } -] diff --git a/vendor/github.com/santhosh-tekuri/jsonschema/testdata/draft6.json b/vendor/github.com/santhosh-tekuri/jsonschema/testdata/draft6.json deleted file mode 100644 index 5e22683..0000000 --- a/vendor/github.com/santhosh-tekuri/jsonschema/testdata/draft6.json +++ /dev/null @@ -1,213 +0,0 @@ -{ - "$schema": "http://json-schema.org/draft-06/schema#", - "$id": "http://json-schema.org/draft-06/schema#", - "title": "Core schema meta-schema", - "definitions": { - "schemaArray": { - "type": "array", - "minItems": 1, - "items": { - "$ref": "#" - } - }, - "nonNegativeInteger": { - "type": "integer", - "minimum": 0 - }, - "nonNegativeIntegerDefault0": { - "allOf": [ - { - "$ref": "#/definitions/nonNegativeInteger" - }, - { - "default": 0 - } - ] - }, - "simpleTypes": { - "enum": [ - "array", - "boolean", - "integer", - "null", - "number", - "object", - "string" - ] - }, - "stringArray": { - "type": "array", - "items": { - "type": "string" - }, - "uniqueItems": true, - "default": [] - } - }, - "type": [ - "object", - "boolean" - ], - "properties": { - "$id": { - "type": "string", - "format": "uri-reference" - }, - "$schema": { - "type": "string", - "format": "uri" - }, - "$ref": { - "type": "string", - "format": "uri-reference" - }, - "title": { - "type": "string" - }, - "description": { - "type": "string" - }, - "default": {}, - "multipleOf": { - "type": "number", - "exclusiveMinimum": 0 - }, - "maximum": { - "type": "number" - }, - "exclusiveMaximum": { - "type": "number" - }, - "minimum": { - "type": "number" - }, - "exclusiveMinimum": { - "type": "number" - }, - "maxLength": { - "$ref": "#/definitions/nonNegativeInteger" - }, - "minLength": { - "$ref": "#/definitions/nonNegativeIntegerDefault0" - }, - "pattern": { - "type": "string", - "format": "regex" - }, - "additionalItems": { - "$ref": "#" - }, - "items": { - "anyOf": [ - { - "$ref": "#" - }, - { - "$ref": "#/definitions/schemaArray" - } - ], - "default": {} - }, - "maxItems": { - "$ref": "#/definitions/nonNegativeInteger" - }, - "minItems": { - "$ref": "#/definitions/nonNegativeIntegerDefault0" - }, - "uniqueItems": { - "type": "boolean", - "default": false - }, - "contains": { - "$ref": "#" - }, - "maxProperties": { - "$ref": "#/definitions/nonNegativeInteger" - }, - "minProperties": { - "$ref": "#/definitions/nonNegativeIntegerDefault0" - }, - "required": { - "$ref": "#/definitions/stringArray" - }, - "additionalProperties": { - "$ref": "#" - }, - "definitions": { - "type": "object", - "additionalProperties": { - "$ref": "#" - }, - "default": {} - }, - "properties": { - "type": "object", - "additionalProperties": { - "$ref": "#" - }, - "default": {} - }, - "patternProperties": { - "type": "object", - "regexProperties": true, - "additionalProperties": { - "$ref": "#" - }, - "default": {} - }, - "dependencies": { - "type": "object", - "additionalProperties": { - "anyOf": [ - { - "$ref": "#" - }, - { - "$ref": "#/definitions/stringArray" - } - ] - } - }, - "propertyNames": { - "$ref": "#" - }, - "const": {}, - "enum": { - "type": "array", - "minItems": 1, - "uniqueItems": true - }, - "type": { - "anyOf": [ - { - "$ref": "#/definitions/simpleTypes" - }, - { - "type": "array", - "items": { - "$ref": "#/definitions/simpleTypes" - }, - "minItems": 1, - "uniqueItems": true - } - ] - }, - "format": { - "type": "string", - "format": "format" - }, - "allOf": { - "$ref": "#/definitions/schemaArray" - }, - "anyOf": { - "$ref": "#/definitions/schemaArray" - }, - "oneOf": { - "$ref": "#/definitions/schemaArray" - }, - "not": { - "$ref": "#" - } - }, - "default": {} -} \ No newline at end of file diff --git a/vendor/github.com/santhosh-tekuri/jsonschema/testdata/draft6/additionalItems.json b/vendor/github.com/santhosh-tekuri/jsonschema/testdata/draft6/additionalItems.json deleted file mode 100644 index abecc57..0000000 --- a/vendor/github.com/santhosh-tekuri/jsonschema/testdata/draft6/additionalItems.json +++ /dev/null @@ -1,87 +0,0 @@ -[ - { - "description": "additionalItems as schema", - "schema": { - "items": [{}], - "additionalItems": {"type": "integer"} - }, - "tests": [ - { - "description": "additional items match schema", - "data": [ null, 2, 3, 4 ], - "valid": true - }, - { - "description": "additional items do not match schema", - "data": [ null, 2, 3, "foo" ], - "valid": false - } - ] - }, - { - "description": "items is schema, no additionalItems", - "schema": { - "items": {}, - "additionalItems": false - }, - "tests": [ - { - "description": "all items match schema", - "data": [ 1, 2, 3, 4, 5 ], - "valid": true - } - ] - }, - { - "description": "array of items with no additionalItems", - "schema": { - "items": [{}, {}, {}], - "additionalItems": false - }, - "tests": [ - { - "description": "fewer number of items present", - "data": [ 1, 2 ], - "valid": true - }, - { - "description": "equal number of items present", - "data": [ 1, 2, 3 ], - "valid": true - }, - { - "description": "additional items are not permitted", - "data": [ 1, 2, 3, 4 ], - "valid": false - } - ] - }, - { - "description": "additionalItems as false without items", - "schema": {"additionalItems": false}, - "tests": [ - { - "description": - "items defaults to empty schema so everything is valid", - "data": [ 1, 2, 3, 4, 5 ], - "valid": true - }, - { - "description": "ignores non-arrays", - "data": {"foo" : "bar"}, - "valid": true - } - ] - }, - { - "description": "additionalItems are allowed by default", - "schema": {"items": [{"type": "integer"}]}, - "tests": [ - { - "description": "only the first item is validated", - "data": [1, "foo", false], - "valid": true - } - ] - } -] diff --git a/vendor/github.com/santhosh-tekuri/jsonschema/testdata/draft6/additionalProperties.json b/vendor/github.com/santhosh-tekuri/jsonschema/testdata/draft6/additionalProperties.json deleted file mode 100644 index 40831f9..0000000 --- a/vendor/github.com/santhosh-tekuri/jsonschema/testdata/draft6/additionalProperties.json +++ /dev/null @@ -1,88 +0,0 @@ -[ - { - "description": - "additionalProperties being false does not allow other properties", - "schema": { - "properties": {"foo": {}, "bar": {}}, - "patternProperties": { "^v": {} }, - "additionalProperties": false - }, - "tests": [ - { - "description": "no additional properties is valid", - "data": {"foo": 1}, - "valid": true - }, - { - "description": "an additional property is invalid", - "data": {"foo" : 1, "bar" : 2, "quux" : "boom"}, - "valid": false - }, - { - "description": "ignores non-objects", - "data": [1, 2, 3], - "valid": true - }, - { - "description": "patternProperties are not additional properties", - "data": {"foo":1, "vroom": 2}, - "valid": true - } - ] - }, - { - "description": - "additionalProperties allows a schema which should validate", - "schema": { - "properties": {"foo": {}, "bar": {}}, - "additionalProperties": {"type": "boolean"} - }, - "tests": [ - { - "description": "no additional properties is valid", - "data": {"foo": 1}, - "valid": true - }, - { - "description": "an additional valid property is valid", - "data": {"foo" : 1, "bar" : 2, "quux" : true}, - "valid": true - }, - { - "description": "an additional invalid property is invalid", - "data": {"foo" : 1, "bar" : 2, "quux" : 12}, - "valid": false - } - ] - }, - { - "description": - "additionalProperties can exist by itself", - "schema": { - "additionalProperties": {"type": "boolean"} - }, - "tests": [ - { - "description": "an additional valid property is valid", - "data": {"foo" : true}, - "valid": true - }, - { - "description": "an additional invalid property is invalid", - "data": {"foo" : 1}, - "valid": false - } - ] - }, - { - "description": "additionalProperties are allowed by default", - "schema": {"properties": {"foo": {}, "bar": {}}}, - "tests": [ - { - "description": "additional properties are allowed", - "data": {"foo": 1, "bar": 2, "quux": true}, - "valid": true - } - ] - } -] diff --git a/vendor/github.com/santhosh-tekuri/jsonschema/testdata/draft6/allOf.json b/vendor/github.com/santhosh-tekuri/jsonschema/testdata/draft6/allOf.json deleted file mode 100644 index 00c016c..0000000 --- a/vendor/github.com/santhosh-tekuri/jsonschema/testdata/draft6/allOf.json +++ /dev/null @@ -1,145 +0,0 @@ -[ - { - "description": "allOf", - "schema": { - "allOf": [ - { - "properties": { - "bar": {"type": "integer"} - }, - "required": ["bar"] - }, - { - "properties": { - "foo": {"type": "string"} - }, - "required": ["foo"] - } - ] - }, - "tests": [ - { - "description": "allOf", - "data": {"foo": "baz", "bar": 2}, - "valid": true - }, - { - "description": "mismatch second", - "data": {"foo": "baz"}, - "valid": false - }, - { - "description": "mismatch first", - "data": {"bar": 2}, - "valid": false - }, - { - "description": "wrong type", - "data": {"foo": "baz", "bar": "quux"}, - "valid": false - } - ] - }, - { - "description": "allOf with base schema", - "schema": { - "properties": {"bar": {"type": "integer"}}, - "required": ["bar"], - "allOf" : [ - { - "properties": { - "foo": {"type": "string"} - }, - "required": ["foo"] - }, - { - "properties": { - "baz": {"type": "null"} - }, - "required": ["baz"] - } - ] - }, - "tests": [ - { - "description": "valid", - "data": {"foo": "quux", "bar": 2, "baz": null}, - "valid": true - }, - { - "description": "mismatch base schema", - "data": {"foo": "quux", "baz": null}, - "valid": false - }, - { - "description": "mismatch first allOf", - "data": {"bar": 2, "baz": null}, - "valid": false - }, - { - "description": "mismatch second allOf", - "data": {"foo": "quux", "bar": 2}, - "valid": false - }, - { - "description": "mismatch both", - "data": {"bar": 2}, - "valid": false - } - ] - }, - { - "description": "allOf simple types", - "schema": { - "allOf": [ - {"maximum": 30}, - {"minimum": 20} - ] - }, - "tests": [ - { - "description": "valid", - "data": 25, - "valid": true - }, - { - "description": "mismatch one", - "data": 35, - "valid": false - } - ] - }, - { - "description": "allOf with boolean schemas, all true", - "schema": {"allOf": [true, true]}, - "tests": [ - { - "description": "any value is valid", - "data": "foo", - "valid": true - } - ] - }, - { - "description": "allOf with boolean schemas, some false", - "schema": {"allOf": [true, false]}, - "tests": [ - { - "description": "any value is invalid", - "data": "foo", - "valid": false - } - ] - }, - { - "description": "allOf with boolean schemas, all false", - "schema": {"allOf": [false, false]}, - "tests": [ - { - "description": "any value is invalid", - "data": "foo", - "valid": false - } - ] - } -] diff --git a/vendor/github.com/santhosh-tekuri/jsonschema/testdata/draft6/anyOf.json b/vendor/github.com/santhosh-tekuri/jsonschema/testdata/draft6/anyOf.json deleted file mode 100644 index 1ea31ed..0000000 --- a/vendor/github.com/santhosh-tekuri/jsonschema/testdata/draft6/anyOf.json +++ /dev/null @@ -1,101 +0,0 @@ -[ - { - "description": "anyOf", - "schema": { - "anyOf": [ - { - "type": "integer" - }, - { - "minimum": 2 - } - ] - }, - "tests": [ - { - "description": "first anyOf valid", - "data": 1, - "valid": true - }, - { - "description": "second anyOf valid", - "data": 2.5, - "valid": true - }, - { - "description": "both anyOf valid", - "data": 3, - "valid": true - }, - { - "description": "neither anyOf valid", - "data": 1.5, - "valid": false - } - ] - }, - { - "description": "anyOf with base schema", - "schema": { - "type": "string", - "anyOf" : [ - { - "maxLength": 2 - }, - { - "minLength": 4 - } - ] - }, - "tests": [ - { - "description": "mismatch base schema", - "data": 3, - "valid": false - }, - { - "description": "one anyOf valid", - "data": "foobar", - "valid": true - }, - { - "description": "both anyOf invalid", - "data": "foo", - "valid": false - } - ] - }, - { - "description": "anyOf with boolean schemas, all true", - "schema": {"anyOf": [true, true]}, - "tests": [ - { - "description": "any value is valid", - "data": "foo", - "valid": true - } - ] - }, - { - "description": "anyOf with boolean schemas, some true", - "schema": {"anyOf": [true, false]}, - "tests": [ - { - "description": "any value is valid", - "data": "foo", - "valid": true - } - ] - }, - { - "description": "anyOf with boolean schemas, all false", - "schema": {"anyOf": [false, false]}, - "tests": [ - { - "description": "any value is invalid", - "data": "foo", - "valid": false - } - ] - } -] diff --git a/vendor/github.com/santhosh-tekuri/jsonschema/testdata/draft6/boolean_schema.json b/vendor/github.com/santhosh-tekuri/jsonschema/testdata/draft6/boolean_schema.json deleted file mode 100644 index 6d40f23..0000000 --- a/vendor/github.com/santhosh-tekuri/jsonschema/testdata/draft6/boolean_schema.json +++ /dev/null @@ -1,104 +0,0 @@ -[ - { - "description": "boolean schema 'true'", - "schema": true, - "tests": [ - { - "description": "number is valid", - "data": 1, - "valid": true - }, - { - "description": "string is valid", - "data": "foo", - "valid": true - }, - { - "description": "boolean true is valid", - "data": true, - "valid": true - }, - { - "description": "boolean false is valid", - "data": false, - "valid": true - }, - { - "description": "null is valid", - "data": null, - "valid": true - }, - { - "description": "object is valid", - "data": {"foo": "bar"}, - "valid": true - }, - { - "description": "empty object is valid", - "data": {}, - "valid": true - }, - { - "description": "array is valid", - "data": ["foo"], - "valid": true - }, - { - "description": "empty array is valid", - "data": [], - "valid": true - } - ] - }, - { - "description": "boolean schema 'false'", - "schema": false, - "tests": [ - { - "description": "number is invalid", - "data": 1, - "valid": false - }, - { - "description": "string is invalid", - "data": "foo", - "valid": false - }, - { - "description": "boolean true is invalid", - "data": true, - "valid": false - }, - { - "description": "boolean false is invalid", - "data": false, - "valid": false - }, - { - "description": "null is invalid", - "data": null, - "valid": false - }, - { - "description": "object is invalid", - "data": {"foo": "bar"}, - "valid": false - }, - { - "description": "empty object is invalid", - "data": {}, - "valid": false - }, - { - "description": "array is invalid", - "data": ["foo"], - "valid": false - }, - { - "description": "empty array is invalid", - "data": [], - "valid": false - } - ] - } -] diff --git a/vendor/github.com/santhosh-tekuri/jsonschema/testdata/draft6/const.json b/vendor/github.com/santhosh-tekuri/jsonschema/testdata/draft6/const.json deleted file mode 100644 index 0e533e0..0000000 --- a/vendor/github.com/santhosh-tekuri/jsonschema/testdata/draft6/const.json +++ /dev/null @@ -1,65 +0,0 @@ -[ - { - "description": "const validation", - "schema": {"const": 2}, - "tests": [ - { - "description": "same value is valid", - "data": 2, - "valid": true - }, - { - "description": "another value is invalid", - "data": 5, - "valid": false - }, - { - "description": "another type is invalid", - "data": "a", - "valid": false - } - ] - }, - { - "description": "const with object", - "schema": {"const": {"foo": "bar", "baz": "bax"}}, - "tests": [ - { - "description": "same object is valid", - "data": {"foo": "bar", "baz": "bax"}, - "valid": true - }, - { - "description": "same object with different property order is valid", - "data": {"baz": "bax", "foo": "bar"}, - "valid": true - }, - { - "description": "another object is invalid", - "data": {"foo": "bar"}, - "valid": false - }, - { - "description": "another type is invalid", - "data": [1, 2], - "valid": false - } - ] - }, - { - "description": "const with null", - "schema": {"const": null}, - "tests": [ - { - "description": "null is valid", - "data": null, - "valid": true - }, - { - "description": "not null is invalid", - "data": 0, - "valid": false - } - ] - } -] diff --git a/vendor/github.com/santhosh-tekuri/jsonschema/testdata/draft6/contains.json b/vendor/github.com/santhosh-tekuri/jsonschema/testdata/draft6/contains.json deleted file mode 100644 index b7ae5a2..0000000 --- a/vendor/github.com/santhosh-tekuri/jsonschema/testdata/draft6/contains.json +++ /dev/null @@ -1,95 +0,0 @@ -[ - { - "description": "contains keyword validation", - "schema": { - "contains": {"minimum": 5} - }, - "tests": [ - { - "description": "array with item matching schema (5) is valid", - "data": [3, 4, 5], - "valid": true - }, - { - "description": "array with item matching schema (6) is valid", - "data": [3, 4, 6], - "valid": true - }, - { - "description": "array with two items matching schema (5, 6) is valid", - "data": [3, 4, 5, 6], - "valid": true - }, - { - "description": "array without items matching schema is invalid", - "data": [2, 3, 4], - "valid": false - }, - { - "description": "empty array is invalid", - "data": [], - "valid": false - }, - { - "description": "not array is valid", - "data": {}, - "valid": true - } - ] - }, - { - "description": "contains keyword with const keyword", - "schema": { - "contains": { "const": 5 } - }, - "tests": [ - { - "description": "array with item 5 is valid", - "data": [3, 4, 5], - "valid": true - }, - { - "description": "array with two items 5 is valid", - "data": [3, 4, 5, 5], - "valid": true - }, - { - "description": "array without item 5 is invalid", - "data": [1, 2, 3, 4], - "valid": false - } - ] - }, - { - "description": "contains keyword with boolean schema true", - "schema": {"contains": true}, - "tests": [ - { - "description": "any non-empty array is valid", - "data": ["foo"], - "valid": true - }, - { - "description": "empty array is invalid", - "data": [], - "valid": false - } - ] - }, - { - "description": "contains keyword with boolean schema false", - "schema": {"contains": false}, - "tests": [ - { - "description": "any non-empty array is invalid", - "data": ["foo"], - "valid": false - }, - { - "description": "empty array is invalid", - "data": [], - "valid": false - } - ] - } -] diff --git a/vendor/github.com/santhosh-tekuri/jsonschema/testdata/draft6/default.json b/vendor/github.com/santhosh-tekuri/jsonschema/testdata/draft6/default.json deleted file mode 100644 index 1762977..0000000 --- a/vendor/github.com/santhosh-tekuri/jsonschema/testdata/draft6/default.json +++ /dev/null @@ -1,49 +0,0 @@ -[ - { - "description": "invalid type for default", - "schema": { - "properties": { - "foo": { - "type": "integer", - "default": [] - } - } - }, - "tests": [ - { - "description": "valid when property is specified", - "data": {"foo": 13}, - "valid": true - }, - { - "description": "still valid when the invalid default is used", - "data": {}, - "valid": true - } - ] - }, - { - "description": "invalid string value for default", - "schema": { - "properties": { - "bar": { - "type": "string", - "minLength": 4, - "default": "bad" - } - } - }, - "tests": [ - { - "description": "valid when property is specified", - "data": {"bar": "good"}, - "valid": true - }, - { - "description": "still valid when the invalid default is used", - "data": {}, - "valid": true - } - ] - } -] diff --git a/vendor/github.com/santhosh-tekuri/jsonschema/testdata/draft6/definitions.json b/vendor/github.com/santhosh-tekuri/jsonschema/testdata/draft6/definitions.json deleted file mode 100644 index cf935a3..0000000 --- a/vendor/github.com/santhosh-tekuri/jsonschema/testdata/draft6/definitions.json +++ /dev/null @@ -1,32 +0,0 @@ -[ - { - "description": "valid definition", - "schema": {"$ref": "http://json-schema.org/draft-04/schema#"}, - "tests": [ - { - "description": "valid definition schema", - "data": { - "definitions": { - "foo": {"type": "integer"} - } - }, - "valid": true - } - ] - }, - { - "description": "invalid definition", - "schema": {"$ref": "http://json-schema.org/draft-04/schema#"}, - "tests": [ - { - "description": "invalid definition schema", - "data": { - "definitions": { - "foo": {"type": 1} - } - }, - "valid": false - } - ] - } -] diff --git a/vendor/github.com/santhosh-tekuri/jsonschema/testdata/draft6/dependencies.json b/vendor/github.com/santhosh-tekuri/jsonschema/testdata/draft6/dependencies.json deleted file mode 100644 index a9b3334..0000000 --- a/vendor/github.com/santhosh-tekuri/jsonschema/testdata/draft6/dependencies.json +++ /dev/null @@ -1,162 +0,0 @@ -[ - { - "description": "dependencies", - "schema": { - "dependencies": {"bar": ["foo"]} - }, - "tests": [ - { - "description": "neither", - "data": {}, - "valid": true - }, - { - "description": "nondependant", - "data": {"foo": 1}, - "valid": true - }, - { - "description": "with dependency", - "data": {"foo": 1, "bar": 2}, - "valid": true - }, - { - "description": "missing dependency", - "data": {"bar": 2}, - "valid": false - }, - { - "description": "ignores non-objects", - "data": "foo", - "valid": true - } - ] - }, - { - "description": "dependencies with empty array", - "schema": { - "dependencies": {"bar": []} - }, - "tests": [ - { - "description": "empty object", - "data": {}, - "valid": true - }, - { - "description": "object with one property", - "data": {"bar": 2}, - "valid": true - } - ] - }, - { - "description": "multiple dependencies", - "schema": { - "dependencies": {"quux": ["foo", "bar"]} - }, - "tests": [ - { - "description": "neither", - "data": {}, - "valid": true - }, - { - "description": "nondependants", - "data": {"foo": 1, "bar": 2}, - "valid": true - }, - { - "description": "with dependencies", - "data": {"foo": 1, "bar": 2, "quux": 3}, - "valid": true - }, - { - "description": "missing dependency", - "data": {"foo": 1, "quux": 2}, - "valid": false - }, - { - "description": "missing other dependency", - "data": {"bar": 1, "quux": 2}, - "valid": false - }, - { - "description": "missing both dependencies", - "data": {"quux": 1}, - "valid": false - } - ] - }, - { - "description": "multiple dependencies subschema", - "schema": { - "dependencies": { - "bar": { - "properties": { - "foo": {"type": "integer"}, - "bar": {"type": "integer"} - } - } - } - }, - "tests": [ - { - "description": "valid", - "data": {"foo": 1, "bar": 2}, - "valid": true - }, - { - "description": "no dependency", - "data": {"foo": "quux"}, - "valid": true - }, - { - "description": "wrong type", - "data": {"foo": "quux", "bar": 2}, - "valid": false - }, - { - "description": "wrong type other", - "data": {"foo": 2, "bar": "quux"}, - "valid": false - }, - { - "description": "wrong type both", - "data": {"foo": "quux", "bar": "quux"}, - "valid": false - } - ] - }, - { - "description": "dependencies with boolean subschemas", - "schema": { - "dependencies": { - "foo": true, - "bar": false - } - }, - "tests": [ - { - "description": "object with property having schema true is valid", - "data": {"foo": 1}, - "valid": true - }, - { - "description": "object with property having schema false is invalid", - "data": {"bar": 2}, - "valid": false - }, - { - "description": "object with both properties is invalid", - "data": {"foo": 1, "bar": 2}, - "valid": false - }, - { - "description": "empty object is valid", - "data": {}, - "valid": true - } - ] - } -] diff --git a/vendor/github.com/santhosh-tekuri/jsonschema/testdata/draft6/enum.json b/vendor/github.com/santhosh-tekuri/jsonschema/testdata/draft6/enum.json deleted file mode 100644 index f124436..0000000 --- a/vendor/github.com/santhosh-tekuri/jsonschema/testdata/draft6/enum.json +++ /dev/null @@ -1,72 +0,0 @@ -[ - { - "description": "simple enum validation", - "schema": {"enum": [1, 2, 3]}, - "tests": [ - { - "description": "one of the enum is valid", - "data": 1, - "valid": true - }, - { - "description": "something else is invalid", - "data": 4, - "valid": false - } - ] - }, - { - "description": "heterogeneous enum validation", - "schema": {"enum": [6, "foo", [], true, {"foo": 12}]}, - "tests": [ - { - "description": "one of the enum is valid", - "data": [], - "valid": true - }, - { - "description": "something else is invalid", - "data": null, - "valid": false - }, - { - "description": "objects are deep compared", - "data": {"foo": false}, - "valid": false - } - ] - }, - { - "description": "enums in properties", - "schema": { - "type":"object", - "properties": { - "foo": {"enum":["foo"]}, - "bar": {"enum":["bar"]} - }, - "required": ["bar"] - }, - "tests": [ - { - "description": "both properties are valid", - "data": {"foo":"foo", "bar":"bar"}, - "valid": true - }, - { - "description": "missing optional property is valid", - "data": {"bar":"bar"}, - "valid": true - }, - { - "description": "missing required property is invalid", - "data": {"foo":"foo"}, - "valid": false - }, - { - "description": "missing all properties is invalid", - "data": {}, - "valid": false - } - ] - } -] diff --git a/vendor/github.com/santhosh-tekuri/jsonschema/testdata/draft6/exclusiveMaximum.json b/vendor/github.com/santhosh-tekuri/jsonschema/testdata/draft6/exclusiveMaximum.json deleted file mode 100644 index dc3cd70..0000000 --- a/vendor/github.com/santhosh-tekuri/jsonschema/testdata/draft6/exclusiveMaximum.json +++ /dev/null @@ -1,30 +0,0 @@ -[ - { - "description": "exclusiveMaximum validation", - "schema": { - "exclusiveMaximum": 3.0 - }, - "tests": [ - { - "description": "below the exclusiveMaximum is valid", - "data": 2.2, - "valid": true - }, - { - "description": "boundary point is invalid", - "data": 3.0, - "valid": false - }, - { - "description": "above the exclusiveMaximum is invalid", - "data": 3.5, - "valid": false - }, - { - "description": "ignores non-numbers", - "data": "x", - "valid": true - } - ] - } -] diff --git a/vendor/github.com/santhosh-tekuri/jsonschema/testdata/draft6/exclusiveMinimum.json b/vendor/github.com/santhosh-tekuri/jsonschema/testdata/draft6/exclusiveMinimum.json deleted file mode 100644 index b38d7ec..0000000 --- a/vendor/github.com/santhosh-tekuri/jsonschema/testdata/draft6/exclusiveMinimum.json +++ /dev/null @@ -1,30 +0,0 @@ -[ - { - "description": "exclusiveMinimum validation", - "schema": { - "exclusiveMinimum": 1.1 - }, - "tests": [ - { - "description": "above the exclusiveMinimum is valid", - "data": 1.2, - "valid": true - }, - { - "description": "boundary point is invalid", - "data": 1.1, - "valid": false - }, - { - "description": "below the exclusiveMinimum is invalid", - "data": 0.6, - "valid": false - }, - { - "description": "ignores non-numbers", - "data": "x", - "valid": true - } - ] - } -] diff --git a/vendor/github.com/santhosh-tekuri/jsonschema/testdata/draft6/items.json b/vendor/github.com/santhosh-tekuri/jsonschema/testdata/draft6/items.json deleted file mode 100644 index 13a6a11..0000000 --- a/vendor/github.com/santhosh-tekuri/jsonschema/testdata/draft6/items.json +++ /dev/null @@ -1,133 +0,0 @@ -[ - { - "description": "a schema given for items", - "schema": { - "items": {"type": "integer"} - }, - "tests": [ - { - "description": "valid items", - "data": [ 1, 2, 3 ], - "valid": true - }, - { - "description": "wrong type of items", - "data": [1, "x"], - "valid": false - }, - { - "description": "ignores non-arrays", - "data": {"foo" : "bar"}, - "valid": true - }, - { - "description": "JavaScript pseudo-array is valid", - "data": { - "0": "invalid", - "length": 1 - }, - "valid": true - } - ] - }, - { - "description": "an array of schemas for items", - "schema": { - "items": [ - {"type": "integer"}, - {"type": "string"} - ] - }, - "tests": [ - { - "description": "correct types", - "data": [ 1, "foo" ], - "valid": true - }, - { - "description": "wrong types", - "data": [ "foo", 1 ], - "valid": false - }, - { - "description": "incomplete array of items", - "data": [ 1 ], - "valid": true - }, - { - "description": "array with additional items", - "data": [ 1, "foo", true ], - "valid": true - }, - { - "description": "empty array", - "data": [ ], - "valid": true - }, - { - "description": "JavaScript pseudo-array is valid", - "data": { - "0": "invalid", - "1": "valid", - "length": 2 - }, - "valid": true - } - ] - }, - { - "description": "items with boolean schema (true)", - "schema": {"items": true}, - "tests": [ - { - "description": "any array is valid", - "data": [ 1, "foo", true ], - "valid": true - }, - { - "description": "empty array is valid", - "data": [], - "valid": true - } - ] - }, - { - "description": "items with boolean schema (false)", - "schema": {"items": false}, - "tests": [ - { - "description": "any non-empty array is invalid", - "data": [ 1, "foo", true ], - "valid": false - }, - { - "description": "empty array is valid", - "data": [], - "valid": true - } - ] - }, - { - "description": "items with boolean schemas", - "schema": { - "items": [true, false] - }, - "tests": [ - { - "description": "array with one item is valid", - "data": [ 1 ], - "valid": true - }, - { - "description": "array with two items is invalid", - "data": [ 1, "foo" ], - "valid": false - }, - { - "description": "empty array is valid", - "data": [], - "valid": true - } - ] - } -] diff --git a/vendor/github.com/santhosh-tekuri/jsonschema/testdata/draft6/maxItems.json b/vendor/github.com/santhosh-tekuri/jsonschema/testdata/draft6/maxItems.json deleted file mode 100644 index 3b53a6b..0000000 --- a/vendor/github.com/santhosh-tekuri/jsonschema/testdata/draft6/maxItems.json +++ /dev/null @@ -1,28 +0,0 @@ -[ - { - "description": "maxItems validation", - "schema": {"maxItems": 2}, - "tests": [ - { - "description": "shorter is valid", - "data": [1], - "valid": true - }, - { - "description": "exact length is valid", - "data": [1, 2], - "valid": true - }, - { - "description": "too long is invalid", - "data": [1, 2, 3], - "valid": false - }, - { - "description": "ignores non-arrays", - "data": "foobar", - "valid": true - } - ] - } -] diff --git a/vendor/github.com/santhosh-tekuri/jsonschema/testdata/draft6/maxLength.json b/vendor/github.com/santhosh-tekuri/jsonschema/testdata/draft6/maxLength.json deleted file mode 100644 index 811d35b..0000000 --- a/vendor/github.com/santhosh-tekuri/jsonschema/testdata/draft6/maxLength.json +++ /dev/null @@ -1,33 +0,0 @@ -[ - { - "description": "maxLength validation", - "schema": {"maxLength": 2}, - "tests": [ - { - "description": "shorter is valid", - "data": "f", - "valid": true - }, - { - "description": "exact length is valid", - "data": "fo", - "valid": true - }, - { - "description": "too long is invalid", - "data": "foo", - "valid": false - }, - { - "description": "ignores non-strings", - "data": 100, - "valid": true - }, - { - "description": "two supplementary Unicode code points is long enough", - "data": "\uD83D\uDCA9\uD83D\uDCA9", - "valid": true - } - ] - } -] diff --git a/vendor/github.com/santhosh-tekuri/jsonschema/testdata/draft6/maxProperties.json b/vendor/github.com/santhosh-tekuri/jsonschema/testdata/draft6/maxProperties.json deleted file mode 100644 index d282446..0000000 --- a/vendor/github.com/santhosh-tekuri/jsonschema/testdata/draft6/maxProperties.json +++ /dev/null @@ -1,28 +0,0 @@ -[ - { - "description": "maxProperties validation", - "schema": {"maxProperties": 2}, - "tests": [ - { - "description": "shorter is valid", - "data": {"foo": 1}, - "valid": true - }, - { - "description": "exact length is valid", - "data": {"foo": 1, "bar": 2}, - "valid": true - }, - { - "description": "too long is invalid", - "data": {"foo": 1, "bar": 2, "baz": 3}, - "valid": false - }, - { - "description": "ignores non-objects", - "data": "foobar", - "valid": true - } - ] - } -] diff --git a/vendor/github.com/santhosh-tekuri/jsonschema/testdata/draft6/maximum.json b/vendor/github.com/santhosh-tekuri/jsonschema/testdata/draft6/maximum.json deleted file mode 100644 index 8150984..0000000 --- a/vendor/github.com/santhosh-tekuri/jsonschema/testdata/draft6/maximum.json +++ /dev/null @@ -1,28 +0,0 @@ -[ - { - "description": "maximum validation", - "schema": {"maximum": 3.0}, - "tests": [ - { - "description": "below the maximum is valid", - "data": 2.6, - "valid": true - }, - { - "description": "boundary point is valid", - "data": 3.0, - "valid": true - }, - { - "description": "above the maximum is invalid", - "data": 3.5, - "valid": false - }, - { - "description": "ignores non-numbers", - "data": "x", - "valid": true - } - ] - } -] diff --git a/vendor/github.com/santhosh-tekuri/jsonschema/testdata/draft6/minItems.json b/vendor/github.com/santhosh-tekuri/jsonschema/testdata/draft6/minItems.json deleted file mode 100644 index ed51188..0000000 --- a/vendor/github.com/santhosh-tekuri/jsonschema/testdata/draft6/minItems.json +++ /dev/null @@ -1,28 +0,0 @@ -[ - { - "description": "minItems validation", - "schema": {"minItems": 1}, - "tests": [ - { - "description": "longer is valid", - "data": [1, 2], - "valid": true - }, - { - "description": "exact length is valid", - "data": [1], - "valid": true - }, - { - "description": "too short is invalid", - "data": [], - "valid": false - }, - { - "description": "ignores non-arrays", - "data": "", - "valid": true - } - ] - } -] diff --git a/vendor/github.com/santhosh-tekuri/jsonschema/testdata/draft6/minLength.json b/vendor/github.com/santhosh-tekuri/jsonschema/testdata/draft6/minLength.json deleted file mode 100644 index 3f09158..0000000 --- a/vendor/github.com/santhosh-tekuri/jsonschema/testdata/draft6/minLength.json +++ /dev/null @@ -1,33 +0,0 @@ -[ - { - "description": "minLength validation", - "schema": {"minLength": 2}, - "tests": [ - { - "description": "longer is valid", - "data": "foo", - "valid": true - }, - { - "description": "exact length is valid", - "data": "fo", - "valid": true - }, - { - "description": "too short is invalid", - "data": "f", - "valid": false - }, - { - "description": "ignores non-strings", - "data": 1, - "valid": true - }, - { - "description": "one supplementary Unicode code point is not long enough", - "data": "\uD83D\uDCA9", - "valid": false - } - ] - } -] diff --git a/vendor/github.com/santhosh-tekuri/jsonschema/testdata/draft6/minProperties.json b/vendor/github.com/santhosh-tekuri/jsonschema/testdata/draft6/minProperties.json deleted file mode 100644 index a72c7d2..0000000 --- a/vendor/github.com/santhosh-tekuri/jsonschema/testdata/draft6/minProperties.json +++ /dev/null @@ -1,28 +0,0 @@ -[ - { - "description": "minProperties validation", - "schema": {"minProperties": 1}, - "tests": [ - { - "description": "longer is valid", - "data": {"foo": 1, "bar": 2}, - "valid": true - }, - { - "description": "exact length is valid", - "data": {"foo": 1}, - "valid": true - }, - { - "description": "too short is invalid", - "data": {}, - "valid": false - }, - { - "description": "ignores non-objects", - "data": "", - "valid": true - } - ] - } -] diff --git a/vendor/github.com/santhosh-tekuri/jsonschema/testdata/draft6/minimum.json b/vendor/github.com/santhosh-tekuri/jsonschema/testdata/draft6/minimum.json deleted file mode 100644 index bd1e95b..0000000 --- a/vendor/github.com/santhosh-tekuri/jsonschema/testdata/draft6/minimum.json +++ /dev/null @@ -1,28 +0,0 @@ -[ - { - "description": "minimum validation", - "schema": {"minimum": 1.1}, - "tests": [ - { - "description": "above the minimum is valid", - "data": 2.6, - "valid": true - }, - { - "description": "boundary point is valid", - "data": 1.1, - "valid": true - }, - { - "description": "below the minimum is invalid", - "data": 0.6, - "valid": false - }, - { - "description": "ignores non-numbers", - "data": "x", - "valid": true - } - ] - } -] diff --git a/vendor/github.com/santhosh-tekuri/jsonschema/testdata/draft6/multipleOf.json b/vendor/github.com/santhosh-tekuri/jsonschema/testdata/draft6/multipleOf.json deleted file mode 100644 index ca3b761..0000000 --- a/vendor/github.com/santhosh-tekuri/jsonschema/testdata/draft6/multipleOf.json +++ /dev/null @@ -1,60 +0,0 @@ -[ - { - "description": "by int", - "schema": {"multipleOf": 2}, - "tests": [ - { - "description": "int by int", - "data": 10, - "valid": true - }, - { - "description": "int by int fail", - "data": 7, - "valid": false - }, - { - "description": "ignores non-numbers", - "data": "foo", - "valid": true - } - ] - }, - { - "description": "by number", - "schema": {"multipleOf": 1.5}, - "tests": [ - { - "description": "zero is multiple of anything", - "data": 0, - "valid": true - }, - { - "description": "4.5 is multiple of 1.5", - "data": 4.5, - "valid": true - }, - { - "description": "35 is not multiple of 1.5", - "data": 35, - "valid": false - } - ] - }, - { - "description": "by small number", - "schema": {"multipleOf": 0.0001}, - "tests": [ - { - "description": "0.0075 is multiple of 0.0001", - "data": 0.0075, - "valid": true - }, - { - "description": "0.00751 is not multiple of 0.0001", - "data": 0.00751, - "valid": false - } - ] - } -] diff --git a/vendor/github.com/santhosh-tekuri/jsonschema/testdata/draft6/not.json b/vendor/github.com/santhosh-tekuri/jsonschema/testdata/draft6/not.json deleted file mode 100644 index 98de0ed..0000000 --- a/vendor/github.com/santhosh-tekuri/jsonschema/testdata/draft6/not.json +++ /dev/null @@ -1,117 +0,0 @@ -[ - { - "description": "not", - "schema": { - "not": {"type": "integer"} - }, - "tests": [ - { - "description": "allowed", - "data": "foo", - "valid": true - }, - { - "description": "disallowed", - "data": 1, - "valid": false - } - ] - }, - { - "description": "not multiple types", - "schema": { - "not": {"type": ["integer", "boolean"]} - }, - "tests": [ - { - "description": "valid", - "data": "foo", - "valid": true - }, - { - "description": "mismatch", - "data": 1, - "valid": false - }, - { - "description": "other mismatch", - "data": true, - "valid": false - } - ] - }, - { - "description": "not more complex schema", - "schema": { - "not": { - "type": "object", - "properties": { - "foo": { - "type": "string" - } - } - } - }, - "tests": [ - { - "description": "match", - "data": 1, - "valid": true - }, - { - "description": "other match", - "data": {"foo": 1}, - "valid": true - }, - { - "description": "mismatch", - "data": {"foo": "bar"}, - "valid": false - } - ] - }, - { - "description": "forbidden property", - "schema": { - "properties": { - "foo": { - "not": {} - } - } - }, - "tests": [ - { - "description": "property present", - "data": {"foo": 1, "bar": 2}, - "valid": false - }, - { - "description": "property absent", - "data": {"bar": 1, "baz": 2}, - "valid": true - } - ] - }, - { - "description": "not with boolean schema true", - "schema": {"not": true}, - "tests": [ - { - "description": "any value is invalid", - "data": "foo", - "valid": false - } - ] - }, - { - "description": "not with boolean schema false", - "schema": {"not": false}, - "tests": [ - { - "description": "any value is valid", - "data": "foo", - "valid": true - } - ] - } -] diff --git a/vendor/github.com/santhosh-tekuri/jsonschema/testdata/draft6/oneOf.json b/vendor/github.com/santhosh-tekuri/jsonschema/testdata/draft6/oneOf.json deleted file mode 100644 index df07e0b..0000000 --- a/vendor/github.com/santhosh-tekuri/jsonschema/testdata/draft6/oneOf.json +++ /dev/null @@ -1,112 +0,0 @@ -[ - { - "description": "oneOf", - "schema": { - "oneOf": [ - { - "type": "integer" - }, - { - "minimum": 2 - } - ] - }, - "tests": [ - { - "description": "first oneOf valid", - "data": 1, - "valid": true - }, - { - "description": "second oneOf valid", - "data": 2.5, - "valid": true - }, - { - "description": "both oneOf valid", - "data": 3, - "valid": false - }, - { - "description": "neither oneOf valid", - "data": 1.5, - "valid": false - } - ] - }, - { - "description": "oneOf with base schema", - "schema": { - "type": "string", - "oneOf" : [ - { - "minLength": 2 - }, - { - "maxLength": 4 - } - ] - }, - "tests": [ - { - "description": "mismatch base schema", - "data": 3, - "valid": false - }, - { - "description": "one oneOf valid", - "data": "foobar", - "valid": true - }, - { - "description": "both oneOf valid", - "data": "foo", - "valid": false - } - ] - }, - { - "description": "oneOf with boolean schemas, all true", - "schema": {"oneOf": [true, true, true]}, - "tests": [ - { - "description": "any value is invalid", - "data": "foo", - "valid": false - } - ] - }, - { - "description": "oneOf with boolean schemas, one true", - "schema": {"oneOf": [true, false, false]}, - "tests": [ - { - "description": "any value is valid", - "data": "foo", - "valid": true - } - ] - }, - { - "description": "oneOf with boolean schemas, more than one true", - "schema": {"oneOf": [true, true, false]}, - "tests": [ - { - "description": "any value is invalid", - "data": "foo", - "valid": false - } - ] - }, - { - "description": "oneOf with boolean schemas, all false", - "schema": {"oneOf": [false, false, false]}, - "tests": [ - { - "description": "any value is invalid", - "data": "foo", - "valid": false - } - ] - } -] diff --git a/vendor/github.com/santhosh-tekuri/jsonschema/testdata/draft6/optional/bignum.json b/vendor/github.com/santhosh-tekuri/jsonschema/testdata/draft6/optional/bignum.json deleted file mode 100644 index fac275e..0000000 --- a/vendor/github.com/santhosh-tekuri/jsonschema/testdata/draft6/optional/bignum.json +++ /dev/null @@ -1,105 +0,0 @@ -[ - { - "description": "integer", - "schema": {"type": "integer"}, - "tests": [ - { - "description": "a bignum is an integer", - "data": 12345678910111213141516171819202122232425262728293031, - "valid": true - } - ] - }, - { - "description": "number", - "schema": {"type": "number"}, - "tests": [ - { - "description": "a bignum is a number", - "data": 98249283749234923498293171823948729348710298301928331, - "valid": true - } - ] - }, - { - "description": "integer", - "schema": {"type": "integer"}, - "tests": [ - { - "description": "a negative bignum is an integer", - "data": -12345678910111213141516171819202122232425262728293031, - "valid": true - } - ] - }, - { - "description": "number", - "schema": {"type": "number"}, - "tests": [ - { - "description": "a negative bignum is a number", - "data": -98249283749234923498293171823948729348710298301928331, - "valid": true - } - ] - }, - { - "description": "string", - "schema": {"type": "string"}, - "tests": [ - { - "description": "a bignum is not a string", - "data": 98249283749234923498293171823948729348710298301928331, - "valid": false - } - ] - }, - { - "description": "integer comparison", - "schema": {"maximum": 18446744073709551615}, - "tests": [ - { - "description": "comparison works for high numbers", - "data": 18446744073709551600, - "valid": true - } - ] - }, - { - "description": "float comparison with high precision", - "schema": { - "exclusiveMaximum": 972783798187987123879878123.18878137 - }, - "tests": [ - { - "description": "comparison works for high numbers", - "data": 972783798187987123879878123.188781371, - "valid": false - } - ] - }, - { - "description": "integer comparison", - "schema": {"minimum": -18446744073709551615}, - "tests": [ - { - "description": "comparison works for very negative numbers", - "data": -18446744073709551600, - "valid": true - } - ] - }, - { - "description": "float comparison with high precision on negative numbers", - "schema": { - "exclusiveMinimum": -972783798187987123879878123.18878137 - }, - "tests": [ - { - "description": "comparison works for very negative numbers", - "data": -972783798187987123879878123.188781371, - "valid": false - } - ] - } -] diff --git a/vendor/github.com/santhosh-tekuri/jsonschema/testdata/draft6/optional/ecmascript-regex.json b/vendor/github.com/santhosh-tekuri/jsonschema/testdata/draft6/optional/ecmascript-regex.json deleted file mode 100644 index 08dc936..0000000 --- a/vendor/github.com/santhosh-tekuri/jsonschema/testdata/draft6/optional/ecmascript-regex.json +++ /dev/null @@ -1,13 +0,0 @@ -[ - { - "description": "ECMA 262 regex non-compliance", - "schema": { "format": "regex" }, - "tests": [ - { - "description": "ECMA 262 has no support for \\Z anchor from .NET", - "data": "^\\S(|(.|\\n)*\\S)\\Z", - "valid": false - } - ] - } -] diff --git a/vendor/github.com/santhosh-tekuri/jsonschema/testdata/draft6/optional/format.json b/vendor/github.com/santhosh-tekuri/jsonschema/testdata/draft6/optional/format.json deleted file mode 100644 index e04fb88..0000000 --- a/vendor/github.com/santhosh-tekuri/jsonschema/testdata/draft6/optional/format.json +++ /dev/null @@ -1,261 +0,0 @@ -[ - { - "description": "validation of date-time strings", - "schema": {"format": "date-time"}, - "tests": [ - { - "description": "a valid date-time string", - "data": "1963-06-19T08:30:06.283185Z", - "valid": true - }, - { - "description": "an invalid date-time string", - "data": "06/19/1963 08:30:06 PST", - "valid": false - }, - { - "description": "only RFC3339 not all of ISO 8601 are valid", - "data": "2013-350T01:01:01", - "valid": false - } - ] - }, - { - "description": "validation of URIs", - "schema": {"format": "uri"}, - "tests": [ - { - "description": "a valid URI", - "data": "http://foo.bar/?baz=qux#quux", - "valid": true - }, - { - "description": "an invalid protocol-relative URI Reference", - "data": "//foo.bar/?baz=qux#quux", - "valid": false - }, - { - "description": "an invalid relative URI Reference", - "data": "/abc", - "valid": false - }, - { - "description": "an invalid URI", - "data": "\\\\WINDOWS\\fileshare", - "valid": false - }, - { - "description": "an invalid URI though valid URI reference", - "data": "abc", - "valid": false - } - ] - }, - { - "description": "validation of URI References", - "schema": {"format": "uri-reference"}, - "tests": [ - { - "description": "a valid URI", - "data": "http://foo.bar/?baz=qux#quux", - "valid": true - }, - { - "description": "a valid protocol-relative URI Reference", - "data": "//foo.bar/?baz=qux#quux", - "valid": true - }, - { - "description": "a valid relative URI Reference", - "data": "/abc", - "valid": true - }, - { - "description": "an invalid URI Reference", - "data": "\\\\WINDOWS\\fileshare", - "TODO:valid": false, - "valid": true - }, - { - "description": "a valid URI Reference", - "data": "abc", - "valid": true - }, - { - "description": "a valid URI fragment", - "data": "#fragment", - "valid": true - }, - { - "description": "an invalid URI fragment", - "data": "#frag\\ment", - "TODO:valid": false, - "valid": true - } - ] - }, - { - "description": "format: uri-template", - "schema": { - "format": "uri-template" - }, - "tests": [ - { - "description": "a valid uri-template", - "data": "http://example.com/dictionary/{term:1}/{term}", - "valid": true - }, - { - "description": "an invalid uri-template", - "data": "http://example.com/dictionary/{term:1}/{term", - "TODO:valid": false, - "valid": true - }, - { - "description": "a valid uri-template without variables", - "data": "http://example.com/dictionary", - "valid": true - }, - { - "description": "a valid relative uri-template", - "data": "dictionary/{term:1}/{term}", - "valid": true - } - ] - }, - { - "description": "validation of e-mail addresses", - "schema": {"format": "email"}, - "tests": [ - { - "description": "a valid e-mail address", - "data": "joe.bloggs@example.com", - "valid": true - }, - { - "description": "an invalid e-mail address", - "data": "2962", - "valid": false - } - ] - }, - { - "description": "validation of IP addresses", - "schema": {"format": "ipv4"}, - "tests": [ - { - "description": "a valid IP address", - "data": "192.168.0.1", - "valid": true - }, - { - "description": "an IP address with too many components", - "data": "127.0.0.0.1", - "valid": false - }, - { - "description": "an IP address with out-of-range values", - "data": "256.256.256.256", - "valid": false - }, - { - "description": "an IP address without 4 components", - "data": "127.0", - "valid": false - }, - { - "description": "an IP address as an integer", - "data": "0x7f000001", - "valid": false - } - ] - }, - { - "description": "validation of IPv6 addresses", - "schema": {"format": "ipv6"}, - "tests": [ - { - "description": "a valid IPv6 address", - "data": "::1", - "valid": true - }, - { - "description": "an IPv6 address with out-of-range values", - "data": "12345::", - "valid": false - }, - { - "description": "an IPv6 address with too many components", - "data": "1:1:1:1:1:1:1:1:1:1:1:1:1:1:1:1", - "valid": false - }, - { - "description": "an IPv6 address containing illegal characters", - "data": "::laptop", - "valid": false - } - ] - }, - { - "description": "validation of host names", - "schema": {"format": "hostname"}, - "tests": [ - { - "description": "a valid host name", - "data": "www.example.com", - "valid": true - }, - { - "description": "a host name starting with an illegal character", - "data": "-a-host-name-that-starts-with--", - "valid": false - }, - { - "description": "a host name containing illegal characters", - "data": "not_a_valid_host_name", - "valid": false - }, - { - "description": "a host name with a component too long", - "data": "a-vvvvvvvvvvvvvvvveeeeeeeeeeeeeeeerrrrrrrrrrrrrrrryyyyyyyyyyyyyyyy-long-host-name-component", - "valid": false - } - ] - }, - { - "description": "validation of JSON-pointers", - "schema": {"format": "json-pointer"}, - "tests": [ - { - "description": "a valid JSON-pointer", - "data": "/foo/bar~0/baz~1/%a", - "valid": true - }, - { - "description": "empty string is valid", - "data": "", - "valid": true - }, - { - "description": "/ is valid", - "data": "/", - "valid": true - }, - { - "description": "not a valid JSON-pointer (~ not escaped)", - "data": "/foo/bar~", - "valid": false - }, - { - "description": "valid JSON-pointer with empty segment", - "data": "/foo//bar", - "valid": true - }, - { - "description": "valid JSON-pointer with the last empty segment", - "data": "/foo/bar/", - "valid": true - } - ] - } -] diff --git a/vendor/github.com/santhosh-tekuri/jsonschema/testdata/draft6/optional/zeroTerminatedFloats.json b/vendor/github.com/santhosh-tekuri/jsonschema/testdata/draft6/optional/zeroTerminatedFloats.json deleted file mode 100644 index aa3355c..0000000 --- a/vendor/github.com/santhosh-tekuri/jsonschema/testdata/draft6/optional/zeroTerminatedFloats.json +++ /dev/null @@ -1,15 +0,0 @@ -[ - { - "description": "some languages do not distinguish between different types of numeric value", - "schema": { - "type": "integer" - }, - "tests": [ - { - "description": "a float without fractional part is not an integer", - "data": 1.0, - "valid": false - } - ] - } -] diff --git a/vendor/github.com/santhosh-tekuri/jsonschema/testdata/draft6/pattern.json b/vendor/github.com/santhosh-tekuri/jsonschema/testdata/draft6/pattern.json deleted file mode 100644 index 25e7299..0000000 --- a/vendor/github.com/santhosh-tekuri/jsonschema/testdata/draft6/pattern.json +++ /dev/null @@ -1,34 +0,0 @@ -[ - { - "description": "pattern validation", - "schema": {"pattern": "^a*$"}, - "tests": [ - { - "description": "a matching pattern is valid", - "data": "aaa", - "valid": true - }, - { - "description": "a non-matching pattern is invalid", - "data": "abc", - "valid": false - }, - { - "description": "ignores non-strings", - "data": true, - "valid": true - } - ] - }, - { - "description": "pattern is not anchored", - "schema": {"pattern": "a+"}, - "tests": [ - { - "description": "matches a substring", - "data": "xxaayy", - "valid": true - } - ] - } -] diff --git a/vendor/github.com/santhosh-tekuri/jsonschema/testdata/draft6/patternProperties.json b/vendor/github.com/santhosh-tekuri/jsonschema/testdata/draft6/patternProperties.json deleted file mode 100644 index b1f2d35..0000000 --- a/vendor/github.com/santhosh-tekuri/jsonschema/testdata/draft6/patternProperties.json +++ /dev/null @@ -1,141 +0,0 @@ -[ - { - "description": - "patternProperties validates properties matching a regex", - "schema": { - "patternProperties": { - "f.*o": {"type": "integer"} - } - }, - "tests": [ - { - "description": "a single valid match is valid", - "data": {"foo": 1}, - "valid": true - }, - { - "description": "multiple valid matches is valid", - "data": {"foo": 1, "foooooo" : 2}, - "valid": true - }, - { - "description": "a single invalid match is invalid", - "data": {"foo": "bar", "fooooo": 2}, - "valid": false - }, - { - "description": "multiple invalid matches is invalid", - "data": {"foo": "bar", "foooooo" : "baz"}, - "valid": false - }, - { - "description": "ignores non-objects", - "data": 12, - "valid": true - } - ] - }, - { - "description": "multiple simultaneous patternProperties are validated", - "schema": { - "patternProperties": { - "a*": {"type": "integer"}, - "aaa*": {"maximum": 20} - } - }, - "tests": [ - { - "description": "a single valid match is valid", - "data": {"a": 21}, - "valid": true - }, - { - "description": "a simultaneous match is valid", - "data": {"aaaa": 18}, - "valid": true - }, - { - "description": "multiple matches is valid", - "data": {"a": 21, "aaaa": 18}, - "valid": true - }, - { - "description": "an invalid due to one is invalid", - "data": {"a": "bar"}, - "valid": false - }, - { - "description": "an invalid due to the other is invalid", - "data": {"aaaa": 31}, - "valid": false - }, - { - "description": "an invalid due to both is invalid", - "data": {"aaa": "foo", "aaaa": 31}, - "valid": false - } - ] - }, - { - "description": "regexes are not anchored by default and are case sensitive", - "schema": { - "patternProperties": { - "[0-9]{2,}": { "type": "boolean" }, - "X_": { "type": "string" } - } - }, - "tests": [ - { - "description": "non recognized members are ignored", - "data": { "answer 1": "42" }, - "valid": true - }, - { - "description": "recognized members are accounted for", - "data": { "a31b": null }, - "valid": false - }, - { - "description": "regexes are case sensitive", - "data": { "a_x_3": 3 }, - "valid": true - }, - { - "description": "regexes are case sensitive, 2", - "data": { "a_X_3": 3 }, - "valid": false - } - ] - }, - { - "description": "patternProperties with boolean schemas", - "schema": { - "patternProperties": { - "f.*": true, - "b.*": false - } - }, - "tests": [ - { - "description": "object with property matching schema true is valid", - "data": {"foo": 1}, - "valid": true - }, - { - "description": "object with property matching schema false is invalid", - "data": {"bar": 2}, - "valid": false - }, - { - "description": "object with both properties is invalid", - "data": {"foo": 1, "bar": 2}, - "valid": false - }, - { - "description": "empty object is valid", - "data": {}, - "valid": true - } - ] - } -] diff --git a/vendor/github.com/santhosh-tekuri/jsonschema/testdata/draft6/properties.json b/vendor/github.com/santhosh-tekuri/jsonschema/testdata/draft6/properties.json deleted file mode 100644 index d56a960..0000000 --- a/vendor/github.com/santhosh-tekuri/jsonschema/testdata/draft6/properties.json +++ /dev/null @@ -1,123 +0,0 @@ -[ - { - "description": "object properties validation", - "schema": { - "properties": { - "foo": {"type": "integer"}, - "bar": {"type": "string"} - } - }, - "tests": [ - { - "description": "both properties present and valid is valid", - "data": {"foo": 1, "bar": "baz"}, - "valid": true - }, - { - "description": "one property invalid is invalid", - "data": {"foo": 1, "bar": {}}, - "valid": false - }, - { - "description": "both properties invalid is invalid", - "data": {"foo": [], "bar": {}}, - "valid": false - }, - { - "description": "doesn't invalidate other properties", - "data": {"quux": []}, - "valid": true - }, - { - "description": "ignores non-objects", - "data": [], - "valid": true - } - ] - }, - { - "description": - "properties, patternProperties, additionalProperties interaction", - "schema": { - "properties": { - "foo": {"type": "array", "maxItems": 3}, - "bar": {"type": "array"} - }, - "patternProperties": {"f.o": {"minItems": 2}}, - "additionalProperties": {"type": "integer"} - }, - "tests": [ - { - "description": "property validates property", - "data": {"foo": [1, 2]}, - "valid": true - }, - { - "description": "property invalidates property", - "data": {"foo": [1, 2, 3, 4]}, - "valid": false - }, - { - "description": "patternProperty invalidates property", - "data": {"foo": []}, - "valid": false - }, - { - "description": "patternProperty validates nonproperty", - "data": {"fxo": [1, 2]}, - "valid": true - }, - { - "description": "patternProperty invalidates nonproperty", - "data": {"fxo": []}, - "valid": false - }, - { - "description": "additionalProperty ignores property", - "data": {"bar": []}, - "valid": true - }, - { - "description": "additionalProperty validates others", - "data": {"quux": 3}, - "valid": true - }, - { - "description": "additionalProperty invalidates others", - "data": {"quux": "foo"}, - "valid": false - } - ] - }, - { - "description": "properties with boolean schema", - "schema": { - "properties": { - "foo": true, - "bar": false - } - }, - "tests": [ - { - "description": "no property present is valid", - "data": {}, - "valid": true - }, - { - "description": "only 'true' property present is valid", - "data": {"foo": 1}, - "valid": true - }, - { - "description": "only 'false' property present is invalid", - "data": {"bar": 2}, - "valid": false - }, - { - "description": "both properties present is invalid", - "data": {"foo": 1, "bar": 2}, - "valid": false - } - ] - } -] diff --git a/vendor/github.com/santhosh-tekuri/jsonschema/testdata/draft6/propertyNames.json b/vendor/github.com/santhosh-tekuri/jsonschema/testdata/draft6/propertyNames.json deleted file mode 100644 index 2804b41..0000000 --- a/vendor/github.com/santhosh-tekuri/jsonschema/testdata/draft6/propertyNames.json +++ /dev/null @@ -1,68 +0,0 @@ -[ - { - "description": "propertyNames validation", - "schema": { - "propertyNames": {"maxLength": 3} - }, - "tests": [ - { - "description": "all property names valid", - "data": { - "f": {}, - "foo": {} - }, - "valid": true - }, - { - "description": "some property names invalid", - "data": { - "foo": {}, - "foobar": {} - }, - "valid": false - }, - { - "description": "object without properties is valid", - "data": {}, - "valid": true - }, - { - "description": "non-object is valid", - "data": [], - "valid": true - } - ] - }, - { - "description": "propertyNames with boolean schema true", - "schema": {"propertyNames": true}, - "tests": [ - { - "description": "object with any properties is valid", - "data": {"foo": 1}, - "valid": true - }, - { - "description": "empty object is valid", - "data": {}, - "valid": true - } - ] - }, - { - "description": "propertyNames with boolean schema false", - "schema": {"propertyNames": false}, - "tests": [ - { - "description": "object with any properties is invalid", - "data": {"foo": 1}, - "valid": false - }, - { - "description": "empty object is valid", - "data": {}, - "valid": true - } - ] - } -] diff --git a/vendor/github.com/santhosh-tekuri/jsonschema/testdata/draft6/ref.json b/vendor/github.com/santhosh-tekuri/jsonschema/testdata/draft6/ref.json deleted file mode 100644 index 6dcf6cd..0000000 --- a/vendor/github.com/santhosh-tekuri/jsonschema/testdata/draft6/ref.json +++ /dev/null @@ -1,332 +0,0 @@ -[ - { - "description": "root pointer ref", - "schema": { - "properties": { - "foo": {"$ref": "#"} - }, - "additionalProperties": false - }, - "tests": [ - { - "description": "match", - "data": {"foo": false}, - "valid": true - }, - { - "description": "recursive match", - "data": {"foo": {"foo": false}}, - "valid": true - }, - { - "description": "mismatch", - "data": {"bar": false}, - "valid": false - }, - { - "description": "recursive mismatch", - "data": {"foo": {"bar": false}}, - "valid": false - } - ] - }, - { - "description": "relative pointer ref to object", - "schema": { - "properties": { - "foo": {"type": "integer"}, - "bar": {"$ref": "#/properties/foo"} - } - }, - "tests": [ - { - "description": "match", - "data": {"bar": 3}, - "valid": true - }, - { - "description": "mismatch", - "data": {"bar": true}, - "valid": false - } - ] - }, - { - "description": "relative pointer ref to array", - "schema": { - "items": [ - {"type": "integer"}, - {"$ref": "#/items/0"} - ] - }, - "tests": [ - { - "description": "match array", - "data": [1, 2], - "valid": true - }, - { - "description": "mismatch array", - "data": [1, "foo"], - "valid": false - } - ] - }, - { - "description": "escaped pointer ref", - "schema": { - "tilda~field": {"type": "integer"}, - "slash/field": {"type": "integer"}, - "percent%field": {"type": "integer"}, - "properties": { - "tilda": {"$ref": "#/tilda~0field"}, - "slash": {"$ref": "#/slash~1field"}, - "percent": {"$ref": "#/percent%25field"} - } - }, - "tests": [ - { - "description": "slash invalid", - "data": {"slash": "aoeu"}, - "valid": false - }, - { - "description": "tilda invalid", - "data": {"tilda": "aoeu"}, - "valid": false - }, - { - "description": "percent invalid", - "data": {"percent": "aoeu"}, - "valid": false - }, - { - "description": "slash valid", - "data": {"slash": 123}, - "valid": true - }, - { - "description": "tilda valid", - "data": {"tilda": 123}, - "valid": true - }, - { - "description": "percent valid", - "data": {"percent": 123}, - "valid": true - } - ] - }, - { - "description": "nested refs", - "schema": { - "definitions": { - "a": {"type": "integer"}, - "b": {"$ref": "#/definitions/a"}, - "c": {"$ref": "#/definitions/b"} - }, - "$ref": "#/definitions/c" - }, - "tests": [ - { - "description": "nested ref valid", - "data": 5, - "valid": true - }, - { - "description": "nested ref invalid", - "data": "a", - "valid": false - } - ] - }, - { - "description": "ref overrides any sibling keywords", - "schema": { - "definitions": { - "reffed": { - "type": "array" - } - }, - "properties": { - "foo": { - "$ref": "#/definitions/reffed", - "maxItems": 2 - } - } - }, - "tests": [ - { - "description": "ref valid", - "data": { "foo": [] }, - "valid": true - }, - { - "description": "ref valid, maxItems ignored", - "data": { "foo": [ 1, 2, 3] }, - "valid": true - }, - { - "description": "ref invalid", - "data": { "foo": "string" }, - "valid": false - } - ] - }, - { - "description": "remote ref, containing refs itself", - "schema": {"$ref": "http://json-schema.org/draft-04/schema#"}, - "tests": [ - { - "description": "remote ref valid", - "data": {"minLength": 1}, - "valid": true - }, - { - "description": "remote ref invalid", - "data": {"minLength": -1}, - "valid": false - } - ] - }, - { - "description": "property named $ref that is not a reference", - "schema": { - "properties": { - "$ref": {"type": "string"} - } - }, - "tests": [ - { - "description": "property named $ref valid", - "data": {"$ref": "a"}, - "valid": true - }, - { - "description": "property named $ref invalid", - "data": {"$ref": 2}, - "valid": false - } - ] - }, - { - "description": "$ref to boolean schema true", - "schema": { - "$ref": "#/definitions/bool", - "definitions": { - "bool": true - } - }, - "tests": [ - { - "description": "any value is valid", - "data": "foo", - "valid": true - } - ] - }, - { - "description": "$ref to boolean schema false", - "schema": { - "$ref": "#/definitions/bool", - "definitions": { - "bool": false - } - }, - "tests": [ - { - "description": "any value is invalid", - "data": "foo", - "valid": false - } - ] - }, - { - "description": "Recursive references between schemas", - "schema": { - "$id": "http://localhost:1234/tree", - "description": "tree of nodes", - "type": "object", - "properties": { - "meta": {"type": "string"}, - "nodes": { - "type": "array", - "items": {"$ref": "node"} - } - }, - "required": ["meta", "nodes"], - "definitions": { - "node": { - "$id": "http://localhost:1234/node", - "description": "node", - "type": "object", - "properties": { - "value": {"type": "number"}, - "subtree": {"$ref": "tree"} - }, - "required": ["value"] - } - } - }, - "tests": [ - { - "description": "valid tree", - "data": { - "meta": "root", - "nodes": [ - { - "value": 1, - "subtree": { - "meta": "child", - "nodes": [ - {"value": 1.1}, - {"value": 1.2} - ] - } - }, - { - "value": 2, - "subtree": { - "meta": "child", - "nodes": [ - {"value": 2.1}, - {"value": 2.2} - ] - } - } - ] - }, - "valid": true - }, - { - "description": "invalid tree", - "data": { - "meta": "root", - "nodes": [ - { - "value": 1, - "subtree": { - "meta": "child", - "nodes": [ - {"value": "string is invalid"}, - {"value": 1.2} - ] - } - }, - { - "value": 2, - "subtree": { - "meta": "child", - "nodes": [ - {"value": 2.1}, - {"value": 2.2} - ] - } - } - ] - }, - "valid": false - } - ] - } -] diff --git a/vendor/github.com/santhosh-tekuri/jsonschema/testdata/draft6/refRemote.json b/vendor/github.com/santhosh-tekuri/jsonschema/testdata/draft6/refRemote.json deleted file mode 100644 index 819d326..0000000 --- a/vendor/github.com/santhosh-tekuri/jsonschema/testdata/draft6/refRemote.json +++ /dev/null @@ -1,171 +0,0 @@ -[ - { - "description": "remote ref", - "schema": {"$ref": "http://localhost:1234/integer.json"}, - "tests": [ - { - "description": "remote ref valid", - "data": 1, - "valid": true - }, - { - "description": "remote ref invalid", - "data": "a", - "valid": false - } - ] - }, - { - "description": "fragment within remote ref", - "schema": {"$ref": "http://localhost:1234/subSchemas.json#/integer"}, - "tests": [ - { - "description": "remote fragment valid", - "data": 1, - "valid": true - }, - { - "description": "remote fragment invalid", - "data": "a", - "valid": false - } - ] - }, - { - "description": "ref within remote ref", - "schema": { - "$ref": "http://localhost:1234/subSchemas.json#/refToInteger" - }, - "tests": [ - { - "description": "ref within ref valid", - "data": 1, - "valid": true - }, - { - "description": "ref within ref invalid", - "data": "a", - "valid": false - } - ] - }, - { - "description": "base URI change", - "schema": { - "$id": "http://localhost:1234/", - "items": { - "$id": "folder/", - "items": {"$ref": "folderInteger.json"} - } - }, - "tests": [ - { - "description": "base URI change ref valid", - "data": [[1]], - "valid": true - }, - { - "description": "base URI change ref invalid", - "data": [["a"]], - "valid": false - } - ] - }, - { - "description": "base URI change - change folder", - "schema": { - "$id": "http://localhost:1234/scope_change_defs1.json", - "type" : "object", - "properties": { - "list": {"$ref": "#/definitions/baz"} - }, - "definitions": { - "baz": { - "$id": "folder/", - "type": "array", - "items": {"$ref": "folderInteger.json"} - } - } - }, - "tests": [ - { - "description": "number is valid", - "data": {"list": [1]}, - "valid": true - }, - { - "description": "string is invalid", - "data": {"list": ["a"]}, - "valid": false - } - ] - }, - { - "description": "base URI change - change folder in subschema", - "schema": { - "$id": "http://localhost:1234/scope_change_defs2.json", - "type" : "object", - "properties": { - "list": {"$ref": "#/definitions/baz/definitions/bar"} - }, - "definitions": { - "baz": { - "$id": "folder/", - "definitions": { - "bar": { - "type": "array", - "items": {"$ref": "folderInteger.json"} - } - } - } - } - }, - "tests": [ - { - "description": "number is valid", - "data": {"list": [1]}, - "valid": true - }, - { - "description": "string is invalid", - "data": {"list": ["a"]}, - "valid": false - } - ] - }, - { - "description": "root ref in remote ref", - "schema": { - "$id": "http://localhost:1234/object", - "type": "object", - "properties": { - "name": {"$ref": "name.json#/definitions/orNull"} - } - }, - "tests": [ - { - "description": "string is valid", - "data": { - "name": "foo" - }, - "valid": true - }, - { - "description": "null is valid", - "data": { - "name": null - }, - "valid": true - }, - { - "description": "object is invalid", - "data": { - "name": { - "name": null - } - }, - "valid": false - } - ] - } -] diff --git a/vendor/github.com/santhosh-tekuri/jsonschema/testdata/draft6/required.json b/vendor/github.com/santhosh-tekuri/jsonschema/testdata/draft6/required.json deleted file mode 100644 index 3082157..0000000 --- a/vendor/github.com/santhosh-tekuri/jsonschema/testdata/draft6/required.json +++ /dev/null @@ -1,60 +0,0 @@ -[ - { - "description": "required validation", - "schema": { - "properties": { - "foo": {}, - "bar": {} - }, - "required": ["foo"] - }, - "tests": [ - { - "description": "present required property is valid", - "data": {"foo": 1}, - "valid": true - }, - { - "description": "non-present required property is invalid", - "data": {"bar": 1}, - "valid": false - }, - { - "description": "ignores non-objects", - "data": 12, - "valid": true - } - ] - }, - { - "description": "required default validation", - "schema": { - "properties": { - "foo": {} - } - }, - "tests": [ - { - "description": "not required by default", - "data": {}, - "valid": true - } - ] - }, - { - "description": "required with empty array", - "schema": { - "properties": { - "foo": {} - }, - "required": [] - }, - "tests": [ - { - "description": "property not required", - "data": {}, - "valid": true - } - ] - } -] diff --git a/vendor/github.com/santhosh-tekuri/jsonschema/testdata/draft6/type.json b/vendor/github.com/santhosh-tekuri/jsonschema/testdata/draft6/type.json deleted file mode 100644 index 6129374..0000000 --- a/vendor/github.com/santhosh-tekuri/jsonschema/testdata/draft6/type.json +++ /dev/null @@ -1,345 +0,0 @@ -[ - { - "description": "integer type matches integers", - "schema": {"type": "integer"}, - "tests": [ - { - "description": "an integer is an integer", - "data": 1, - "valid": true - }, - { - "description": "a float is not an integer", - "data": 1.1, - "valid": false - }, - { - "description": "a string is not an integer", - "data": "foo", - "valid": false - }, - { - "description": "a string is still not an integer, even if it looks like one", - "data": "1", - "valid": false - }, - { - "description": "an object is not an integer", - "data": {}, - "valid": false - }, - { - "description": "an array is not an integer", - "data": [], - "valid": false - }, - { - "description": "a boolean is not an integer", - "data": true, - "valid": false - }, - { - "description": "null is not an integer", - "data": null, - "valid": false - } - ] - }, - { - "description": "number type matches numbers", - "schema": {"type": "number"}, - "tests": [ - { - "description": "an integer is a number", - "data": 1, - "valid": true - }, - { - "description": "a float is a number", - "data": 1.1, - "valid": true - }, - { - "description": "a string is not a number", - "data": "foo", - "valid": false - }, - { - "description": "a string is still not a number, even if it looks like one", - "data": "1", - "valid": false - }, - { - "description": "an object is not a number", - "data": {}, - "valid": false - }, - { - "description": "an array is not a number", - "data": [], - "valid": false - }, - { - "description": "a boolean is not a number", - "data": true, - "valid": false - }, - { - "description": "null is not a number", - "data": null, - "valid": false - } - ] - }, - { - "description": "string type matches strings", - "schema": {"type": "string"}, - "tests": [ - { - "description": "1 is not a string", - "data": 1, - "valid": false - }, - { - "description": "a float is not a string", - "data": 1.1, - "valid": false - }, - { - "description": "a string is a string", - "data": "foo", - "valid": true - }, - { - "description": "a string is still a string, even if it looks like a number", - "data": "1", - "valid": true - }, - { - "description": "an object is not a string", - "data": {}, - "valid": false - }, - { - "description": "an array is not a string", - "data": [], - "valid": false - }, - { - "description": "a boolean is not a string", - "data": true, - "valid": false - }, - { - "description": "null is not a string", - "data": null, - "valid": false - } - ] - }, - { - "description": "object type matches objects", - "schema": {"type": "object"}, - "tests": [ - { - "description": "an integer is not an object", - "data": 1, - "valid": false - }, - { - "description": "a float is not an object", - "data": 1.1, - "valid": false - }, - { - "description": "a string is not an object", - "data": "foo", - "valid": false - }, - { - "description": "an object is an object", - "data": {}, - "valid": true - }, - { - "description": "an array is not an object", - "data": [], - "valid": false - }, - { - "description": "a boolean is not an object", - "data": true, - "valid": false - }, - { - "description": "null is not an object", - "data": null, - "valid": false - } - ] - }, - { - "description": "array type matches arrays", - "schema": {"type": "array"}, - "tests": [ - { - "description": "an integer is not an array", - "data": 1, - "valid": false - }, - { - "description": "a float is not an array", - "data": 1.1, - "valid": false - }, - { - "description": "a string is not an array", - "data": "foo", - "valid": false - }, - { - "description": "an object is not an array", - "data": {}, - "valid": false - }, - { - "description": "an array is an array", - "data": [], - "valid": true - }, - { - "description": "a boolean is not an array", - "data": true, - "valid": false - }, - { - "description": "null is not an array", - "data": null, - "valid": false - } - ] - }, - { - "description": "boolean type matches booleans", - "schema": {"type": "boolean"}, - "tests": [ - { - "description": "an integer is not a boolean", - "data": 1, - "valid": false - }, - { - "description": "a float is not a boolean", - "data": 1.1, - "valid": false - }, - { - "description": "a string is not a boolean", - "data": "foo", - "valid": false - }, - { - "description": "an object is not a boolean", - "data": {}, - "valid": false - }, - { - "description": "an array is not a boolean", - "data": [], - "valid": false - }, - { - "description": "a boolean is a boolean", - "data": true, - "valid": true - }, - { - "description": "null is not a boolean", - "data": null, - "valid": false - } - ] - }, - { - "description": "null type matches only the null object", - "schema": {"type": "null"}, - "tests": [ - { - "description": "an integer is not null", - "data": 1, - "valid": false - }, - { - "description": "a float is not null", - "data": 1.1, - "valid": false - }, - { - "description": "a string is not null", - "data": "foo", - "valid": false - }, - { - "description": "an object is not null", - "data": {}, - "valid": false - }, - { - "description": "an array is not null", - "data": [], - "valid": false - }, - { - "description": "a boolean is not null", - "data": true, - "valid": false - }, - { - "description": "null is null", - "data": null, - "valid": true - } - ] - }, - { - "description": "multiple types can be specified in an array", - "schema": {"type": ["integer", "string"]}, - "tests": [ - { - "description": "an integer is valid", - "data": 1, - "valid": true - }, - { - "description": "a string is valid", - "data": "foo", - "valid": true - }, - { - "description": "a float is invalid", - "data": 1.1, - "valid": false - }, - { - "description": "an object is invalid", - "data": {}, - "valid": false - }, - { - "description": "an array is invalid", - "data": [], - "valid": false - }, - { - "description": "a boolean is invalid", - "data": true, - "valid": false - }, - { - "description": "null is invalid", - "data": null, - "valid": false - } - ] - } -] diff --git a/vendor/github.com/santhosh-tekuri/jsonschema/testdata/draft6/uniqueItems.json b/vendor/github.com/santhosh-tekuri/jsonschema/testdata/draft6/uniqueItems.json deleted file mode 100644 index c1f4ab9..0000000 --- a/vendor/github.com/santhosh-tekuri/jsonschema/testdata/draft6/uniqueItems.json +++ /dev/null @@ -1,79 +0,0 @@ -[ - { - "description": "uniqueItems validation", - "schema": {"uniqueItems": true}, - "tests": [ - { - "description": "unique array of integers is valid", - "data": [1, 2], - "valid": true - }, - { - "description": "non-unique array of integers is invalid", - "data": [1, 1], - "valid": false - }, - { - "description": "numbers are unique if mathematically unequal", - "data": [1.0, 1.00, 1], - "valid": false - }, - { - "description": "unique array of objects is valid", - "data": [{"foo": "bar"}, {"foo": "baz"}], - "valid": true - }, - { - "description": "non-unique array of objects is invalid", - "data": [{"foo": "bar"}, {"foo": "bar"}], - "valid": false - }, - { - "description": "unique array of nested objects is valid", - "data": [ - {"foo": {"bar" : {"baz" : true}}}, - {"foo": {"bar" : {"baz" : false}}} - ], - "valid": true - }, - { - "description": "non-unique array of nested objects is invalid", - "data": [ - {"foo": {"bar" : {"baz" : true}}}, - {"foo": {"bar" : {"baz" : true}}} - ], - "valid": false - }, - { - "description": "unique array of arrays is valid", - "data": [["foo"], ["bar"]], - "valid": true - }, - { - "description": "non-unique array of arrays is invalid", - "data": [["foo"], ["foo"]], - "valid": false - }, - { - "description": "1 and true are unique", - "data": [1, true], - "valid": true - }, - { - "description": "0 and false are unique", - "data": [0, false], - "valid": true - }, - { - "description": "unique heterogeneous types are valid", - "data": [{}, [1], true, null, 1], - "valid": true - }, - { - "description": "non-unique heterogeneous types are invalid", - "data": [{}, [1], true, null, {}, 1], - "valid": false - } - ] - } -] diff --git a/vendor/github.com/santhosh-tekuri/jsonschema/testdata/invalid_schema.json b/vendor/github.com/santhosh-tekuri/jsonschema/testdata/invalid_schema.json deleted file mode 100644 index b377661..0000000 --- a/vendor/github.com/santhosh-tekuri/jsonschema/testdata/invalid_schema.json +++ /dev/null @@ -1 +0,0 @@ -{ "type": 1 } \ No newline at end of file diff --git a/vendor/github.com/santhosh-tekuri/jsonschema/testdata/invalid_schemas.json b/vendor/github.com/santhosh-tekuri/jsonschema/testdata/invalid_schemas.json deleted file mode 100644 index c48a6e1..0000000 --- a/vendor/github.com/santhosh-tekuri/jsonschema/testdata/invalid_schemas.json +++ /dev/null @@ -1,268 +0,0 @@ -[ - { - "description": "must be object", - "schema": 1 - }, - { - "description": "format must be string", - "schema": { - "format": 1 - } - }, - { - "description": "unknown format", - "schema": { - "format": "palindrome" - } - }, - { - "description": "pattern must be string", - "schema": { - "pattern": 1 - } - }, - { - "description": "pattern must be regex", - "schema": { - "pattern": "(" - } - }, - { - "description": "$ref must be string", - "schema": { - "$ref": 1 - } - }, - { - "description": "patternProperties keys must be regex", - "schema": { - "patternProperties": { - "(": {} - } - } - }, - { - "description": "invalid $ref json-pointer", - "schema": { - "$ref": "#/definition/employee%1" - } - }, - { - "description": "invalid $ref url", - "schema": { - "$ref": "http:/localhost/test.json" - } - }, - { - "description": "invalid $ref ptr", - "schema": { - "$ref": "#/definition/employee" - } - }, - { - "description": "$ref to invalid schema", - "schema": { - "$ref": "#/definition/employee", - "definitions": { - "employee": { - "type": 1 - } - } - } - }, - { - "description": "draft3 is not supported", - "schema": { - "$schema": "http://json-schema.org/draft-03/schema#" - } - }, - { - "description": "does not validate with latest draft", - "schema": { - "$schema": "http://json-schema.org/schema#", - "contains": 1 - } - }, - { - "description": "$ref schema with syntax error", - "schema": { - "$ref": "testdata/syntax_error.json#" - } - }, - { - "description": "multipleOf must be greater than zero", - "schema": { - "multipleOf": 0 - } - }, - { - "description": "not compile fail", - "schema": { - "not": { - "$ref": "#/unknown" - } - } - }, - { - "description": "allOf compile fail", - "schema": { - "allOf": [ - { - "$ref": "#/unknown" - } - ] - } - }, - { - "description": "anyOf compile fail", - "schema": { - "anyOf": [ - { - "$ref": "#/unknown" - } - ] - } - }, - { - "description": "oneOf compile fail", - "schema": { - "oneOf": [ - { - "$ref": "#/unknown" - } - ] - } - }, - { - "description": "properties compile fail", - "schema": { - "properties": { - "p1": { - "$ref": "#/unknown" - } - } - } - }, - { - "description": "patternProperties compile fail", - "schema": { - "patternProperties": { - "p1": { - "$ref": "#/unknown" - } - } - } - }, - { - "description": "additionalProperties compile fail", - "schema": { - "additionalProperties": { - "$ref": "#/unknown" - } - } - }, - { - "description": "items compile fail", - "schema": { - "items": { - "$ref": "#/unknown" - } - } - }, - { - "description": "item compile fail", - "schema": { - "items": [ - { - "$ref": "#/unknown" - } - ] - } - }, - { - "description": "additionalItems compile fail", - "schema": { - "items": [{}], - "additionalItems": { - "$ref": "#/unknown" - } - } - }, - { - "description": "dependencies compile fail", - "schema": { - "dependencies": { - "p1": { - "$ref": "#/unknown" - } - } - } - }, - { - "description": "contains compile fail", - "schema": { - "contains": { - "$ref": "#/unknown" - } - } - }, - { - "description": "propertyNames compile fail", - "schema": { - "propertyNames": { - "$ref": "#/unknown" - } - } - }, - { - "description": "a:jsonpointer urlescape", - "schema": { - "propertyNames": { - "$ref": "#/unknown%" - } - } - }, - { - "description": "b:jsonpointer urlescape", - "schema": {}, - "fragment": "#/unknown%" - }, - { - "description": "jsonpointer array index", - "schema": { - "refs": [{}], - "propertyNames": { - "$ref": "#/refs/unknown" - } - } - }, - { - "description": "jsonpointer array index outofrange", - "schema": { - "refs": [{}], - "propertyNames": { - "$ref": "#/refs/5" - } - } - }, - { - "description": "schemaRef with invalid $schema", - "schema": [{"$schema":"http://json-schema.org/draft-03/schema"}], - "fragment": "#/0" - }, - { - "description": "schemaRef with wrong jsonpointer", - "schema": [{}], - "fragment": "#/1" - }, - { - "description": "schemaRef", - "schema": [1], - "fragment": "#/0" - }, - { - "description": "schemaRef wrong jsonpointer", - "schema": [{"$ref": "#/5"}], - "fragment": "#/0" - } -] \ No newline at end of file diff --git a/vendor/github.com/santhosh-tekuri/jsonschema/testdata/remotes/folder/folderInteger.json b/vendor/github.com/santhosh-tekuri/jsonschema/testdata/remotes/folder/folderInteger.json deleted file mode 100644 index dbe5c75..0000000 --- a/vendor/github.com/santhosh-tekuri/jsonschema/testdata/remotes/folder/folderInteger.json +++ /dev/null @@ -1,3 +0,0 @@ -{ - "type": "integer" -} \ No newline at end of file diff --git a/vendor/github.com/santhosh-tekuri/jsonschema/testdata/remotes/integer.json b/vendor/github.com/santhosh-tekuri/jsonschema/testdata/remotes/integer.json deleted file mode 100644 index dbe5c75..0000000 --- a/vendor/github.com/santhosh-tekuri/jsonschema/testdata/remotes/integer.json +++ /dev/null @@ -1,3 +0,0 @@ -{ - "type": "integer" -} \ No newline at end of file diff --git a/vendor/github.com/santhosh-tekuri/jsonschema/testdata/remotes/name.json b/vendor/github.com/santhosh-tekuri/jsonschema/testdata/remotes/name.json deleted file mode 100644 index 19ba093..0000000 --- a/vendor/github.com/santhosh-tekuri/jsonschema/testdata/remotes/name.json +++ /dev/null @@ -1,11 +0,0 @@ -{ - "definitions": { - "orNull": { - "anyOf": [ - {"type": "null"}, - {"$ref": "#"} - ] - } - }, - "type": "string" -} diff --git a/vendor/github.com/santhosh-tekuri/jsonschema/testdata/remotes/subSchemas.json b/vendor/github.com/santhosh-tekuri/jsonschema/testdata/remotes/subSchemas.json deleted file mode 100644 index 8b6d8f8..0000000 --- a/vendor/github.com/santhosh-tekuri/jsonschema/testdata/remotes/subSchemas.json +++ /dev/null @@ -1,8 +0,0 @@ -{ - "integer": { - "type": "integer" - }, - "refToInteger": { - "$ref": "#/integer" - } -} \ No newline at end of file diff --git a/vendor/github.com/santhosh-tekuri/jsonschema/testdata/syntax_error.json b/vendor/github.com/santhosh-tekuri/jsonschema/testdata/syntax_error.json deleted file mode 100644 index 81750b9..0000000 --- a/vendor/github.com/santhosh-tekuri/jsonschema/testdata/syntax_error.json +++ /dev/null @@ -1 +0,0 @@ -{ \ No newline at end of file diff --git a/vendor/github.com/satori/go.uuid/.travis.yml b/vendor/github.com/satori/go.uuid/.travis.yml deleted file mode 100644 index 38517e2..0000000 --- a/vendor/github.com/satori/go.uuid/.travis.yml +++ /dev/null @@ -1,15 +0,0 @@ -language: go -sudo: false -go: - - 1.2 - - 1.3 - - 1.4 - - 1.5 - - 1.6 -before_install: - - go get github.com/mattn/goveralls - - go get golang.org/x/tools/cmd/cover -script: - - $HOME/gopath/bin/goveralls -service=travis-ci -notifications: - email: false diff --git a/vendor/github.com/satori/go.uuid/LICENSE b/vendor/github.com/satori/go.uuid/LICENSE deleted file mode 100644 index 488357b..0000000 --- a/vendor/github.com/satori/go.uuid/LICENSE +++ /dev/null @@ -1,20 +0,0 @@ -Copyright (C) 2013-2016 by Maxim Bublis - -Permission is hereby granted, free of charge, to any person obtaining -a copy of this software and associated documentation files (the -"Software"), to deal in the Software without restriction, including -without limitation the rights to use, copy, modify, merge, publish, -distribute, sublicense, and/or sell copies of the Software, and to -permit persons to whom the Software is furnished to do so, subject to -the following conditions: - -The above copyright notice and this permission notice shall be -included in all copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, -EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF -MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND -NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE -LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION -OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION -WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. diff --git a/vendor/github.com/satori/go.uuid/README.md b/vendor/github.com/satori/go.uuid/README.md deleted file mode 100644 index b6aad1c..0000000 --- a/vendor/github.com/satori/go.uuid/README.md +++ /dev/null @@ -1,65 +0,0 @@ -# UUID package for Go language - -[![Build Status](https://travis-ci.org/satori/go.uuid.png?branch=master)](https://travis-ci.org/satori/go.uuid) -[![Coverage Status](https://coveralls.io/repos/github/satori/go.uuid/badge.svg?branch=master)](https://coveralls.io/github/satori/go.uuid) -[![GoDoc](http://godoc.org/github.com/satori/go.uuid?status.png)](http://godoc.org/github.com/satori/go.uuid) - -This package provides pure Go implementation of Universally Unique Identifier (UUID). Supported both creation and parsing of UUIDs. - -With 100% test coverage and benchmarks out of box. - -Supported versions: -* Version 1, based on timestamp and MAC address (RFC 4122) -* Version 2, based on timestamp, MAC address and POSIX UID/GID (DCE 1.1) -* Version 3, based on MD5 hashing (RFC 4122) -* Version 4, based on random numbers (RFC 4122) -* Version 5, based on SHA-1 hashing (RFC 4122) - -## Installation - -Use the `go` command: - - $ go get github.com/satori/go.uuid - -## Requirements - -UUID package requires Go >= 1.2. - -## Example - -```go -package main - -import ( - "fmt" - "github.com/satori/go.uuid" -) - -func main() { - // Creating UUID Version 4 - u1 := uuid.NewV4() - fmt.Printf("UUIDv4: %s\n", u1) - - // Parsing UUID from string input - u2, err := uuid.FromString("6ba7b810-9dad-11d1-80b4-00c04fd430c8") - if err != nil { - fmt.Printf("Something gone wrong: %s", err) - } - fmt.Printf("Successfully parsed: %s", u2) -} -``` - -## Documentation - -[Documentation](http://godoc.org/github.com/satori/go.uuid) is hosted at GoDoc project. - -## Links -* [RFC 4122](http://tools.ietf.org/html/rfc4122) -* [DCE 1.1: Authentication and Security Services](http://pubs.opengroup.org/onlinepubs/9696989899/chap5.htm#tagcjh_08_02_01_01) - -## Copyright - -Copyright (C) 2013-2016 by Maxim Bublis . - -UUID package released under MIT License. -See [LICENSE](https://github.com/satori/go.uuid/blob/master/LICENSE) for details. diff --git a/vendor/github.com/satori/go.uuid/benchmarks_test.go b/vendor/github.com/satori/go.uuid/benchmarks_test.go deleted file mode 100644 index b4e567f..0000000 --- a/vendor/github.com/satori/go.uuid/benchmarks_test.go +++ /dev/null @@ -1,121 +0,0 @@ -// Copyright (C) 2013-2015 by Maxim Bublis -// -// Permission is hereby granted, free of charge, to any person obtaining -// a copy of this software and associated documentation files (the -// "Software"), to deal in the Software without restriction, including -// without limitation the rights to use, copy, modify, merge, publish, -// distribute, sublicense, and/or sell copies of the Software, and to -// permit persons to whom the Software is furnished to do so, subject to -// the following conditions: -// -// The above copyright notice and this permission notice shall be -// included in all copies or substantial portions of the Software. -// -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, -// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF -// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND -// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE -// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION -// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION -// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. - -package uuid - -import ( - "testing" -) - -func BenchmarkFromBytes(b *testing.B) { - bytes := []byte{0x6b, 0xa7, 0xb8, 0x10, 0x9d, 0xad, 0x11, 0xd1, 0x80, 0xb4, 0x00, 0xc0, 0x4f, 0xd4, 0x30, 0xc8} - for i := 0; i < b.N; i++ { - FromBytes(bytes) - } -} - -func BenchmarkFromString(b *testing.B) { - s := "6ba7b810-9dad-11d1-80b4-00c04fd430c8" - for i := 0; i < b.N; i++ { - FromString(s) - } -} - -func BenchmarkFromStringUrn(b *testing.B) { - s := "urn:uuid:6ba7b810-9dad-11d1-80b4-00c04fd430c8" - for i := 0; i < b.N; i++ { - FromString(s) - } -} - -func BenchmarkFromStringWithBrackets(b *testing.B) { - s := "{6ba7b810-9dad-11d1-80b4-00c04fd430c8}" - for i := 0; i < b.N; i++ { - FromString(s) - } -} - -func BenchmarkNewV1(b *testing.B) { - for i := 0; i < b.N; i++ { - NewV1() - } -} - -func BenchmarkNewV2(b *testing.B) { - for i := 0; i < b.N; i++ { - NewV2(DomainPerson) - } -} - -func BenchmarkNewV3(b *testing.B) { - for i := 0; i < b.N; i++ { - NewV3(NamespaceDNS, "www.example.com") - } -} - -func BenchmarkNewV4(b *testing.B) { - for i := 0; i < b.N; i++ { - NewV4() - } -} - -func BenchmarkNewV5(b *testing.B) { - for i := 0; i < b.N; i++ { - NewV5(NamespaceDNS, "www.example.com") - } -} - -func BenchmarkMarshalBinary(b *testing.B) { - u := NewV4() - for i := 0; i < b.N; i++ { - u.MarshalBinary() - } -} - -func BenchmarkMarshalText(b *testing.B) { - u := NewV4() - for i := 0; i < b.N; i++ { - u.MarshalText() - } -} - -func BenchmarkUnmarshalBinary(b *testing.B) { - bytes := []byte{0x6b, 0xa7, 0xb8, 0x10, 0x9d, 0xad, 0x11, 0xd1, 0x80, 0xb4, 0x00, 0xc0, 0x4f, 0xd4, 0x30, 0xc8} - u := UUID{} - for i := 0; i < b.N; i++ { - u.UnmarshalBinary(bytes) - } -} - -func BenchmarkUnmarshalText(b *testing.B) { - bytes := []byte("6ba7b810-9dad-11d1-80b4-00c04fd430c8") - u := UUID{} - for i := 0; i < b.N; i++ { - u.UnmarshalText(bytes) - } -} - -func BenchmarkMarshalToString(b *testing.B) { - u := NewV4() - for i := 0; i < b.N; i++ { - u.String() - } -} diff --git a/vendor/github.com/satori/go.uuid/uuid.go b/vendor/github.com/satori/go.uuid/uuid.go deleted file mode 100644 index 9c7fbaa..0000000 --- a/vendor/github.com/satori/go.uuid/uuid.go +++ /dev/null @@ -1,488 +0,0 @@ -// Copyright (C) 2013-2015 by Maxim Bublis -// -// Permission is hereby granted, free of charge, to any person obtaining -// a copy of this software and associated documentation files (the -// "Software"), to deal in the Software without restriction, including -// without limitation the rights to use, copy, modify, merge, publish, -// distribute, sublicense, and/or sell copies of the Software, and to -// permit persons to whom the Software is furnished to do so, subject to -// the following conditions: -// -// The above copyright notice and this permission notice shall be -// included in all copies or substantial portions of the Software. -// -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, -// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF -// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND -// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE -// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION -// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION -// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. - -// Package uuid provides implementation of Universally Unique Identifier (UUID). -// Supported versions are 1, 3, 4 and 5 (as specified in RFC 4122) and -// version 2 (as specified in DCE 1.1). -package uuid - -import ( - "bytes" - "crypto/md5" - "crypto/rand" - "crypto/sha1" - "database/sql/driver" - "encoding/binary" - "encoding/hex" - "fmt" - "hash" - "net" - "os" - "sync" - "time" -) - -// UUID layout variants. -const ( - VariantNCS = iota - VariantRFC4122 - VariantMicrosoft - VariantFuture -) - -// UUID DCE domains. -const ( - DomainPerson = iota - DomainGroup - DomainOrg -) - -// Difference in 100-nanosecond intervals between -// UUID epoch (October 15, 1582) and Unix epoch (January 1, 1970). -const epochStart = 122192928000000000 - -// Used in string method conversion -const dash byte = '-' - -// UUID v1/v2 storage. -var ( - storageMutex sync.Mutex - storageOnce sync.Once - epochFunc = unixTimeFunc - clockSequence uint16 - lastTime uint64 - hardwareAddr [6]byte - posixUID = uint32(os.Getuid()) - posixGID = uint32(os.Getgid()) -) - -// String parse helpers. -var ( - urnPrefix = []byte("urn:uuid:") - byteGroups = []int{8, 4, 4, 4, 12} -) - -func initClockSequence() { - buf := make([]byte, 2) - safeRandom(buf) - clockSequence = binary.BigEndian.Uint16(buf) -} - -func initHardwareAddr() { - interfaces, err := net.Interfaces() - if err == nil { - for _, iface := range interfaces { - if len(iface.HardwareAddr) >= 6 { - copy(hardwareAddr[:], iface.HardwareAddr) - return - } - } - } - - // Initialize hardwareAddr randomly in case - // of real network interfaces absence - safeRandom(hardwareAddr[:]) - - // Set multicast bit as recommended in RFC 4122 - hardwareAddr[0] |= 0x01 -} - -func initStorage() { - initClockSequence() - initHardwareAddr() -} - -func safeRandom(dest []byte) { - if _, err := rand.Read(dest); err != nil { - panic(err) - } -} - -// Returns difference in 100-nanosecond intervals between -// UUID epoch (October 15, 1582) and current time. -// This is default epoch calculation function. -func unixTimeFunc() uint64 { - return epochStart + uint64(time.Now().UnixNano()/100) -} - -// UUID representation compliant with specification -// described in RFC 4122. -type UUID [16]byte - -// NullUUID can be used with the standard sql package to represent a -// UUID value that can be NULL in the database -type NullUUID struct { - UUID UUID - Valid bool -} - -// The nil UUID is special form of UUID that is specified to have all -// 128 bits set to zero. -var Nil = UUID{} - -// Predefined namespace UUIDs. -var ( - NamespaceDNS, _ = FromString("6ba7b810-9dad-11d1-80b4-00c04fd430c8") - NamespaceURL, _ = FromString("6ba7b811-9dad-11d1-80b4-00c04fd430c8") - NamespaceOID, _ = FromString("6ba7b812-9dad-11d1-80b4-00c04fd430c8") - NamespaceX500, _ = FromString("6ba7b814-9dad-11d1-80b4-00c04fd430c8") -) - -// And returns result of binary AND of two UUIDs. -func And(u1 UUID, u2 UUID) UUID { - u := UUID{} - for i := 0; i < 16; i++ { - u[i] = u1[i] & u2[i] - } - return u -} - -// Or returns result of binary OR of two UUIDs. -func Or(u1 UUID, u2 UUID) UUID { - u := UUID{} - for i := 0; i < 16; i++ { - u[i] = u1[i] | u2[i] - } - return u -} - -// Equal returns true if u1 and u2 equals, otherwise returns false. -func Equal(u1 UUID, u2 UUID) bool { - return bytes.Equal(u1[:], u2[:]) -} - -// Version returns algorithm version used to generate UUID. -func (u UUID) Version() uint { - return uint(u[6] >> 4) -} - -// Variant returns UUID layout variant. -func (u UUID) Variant() uint { - switch { - case (u[8] & 0x80) == 0x00: - return VariantNCS - case (u[8]&0xc0)|0x80 == 0x80: - return VariantRFC4122 - case (u[8]&0xe0)|0xc0 == 0xc0: - return VariantMicrosoft - } - return VariantFuture -} - -// Bytes returns bytes slice representation of UUID. -func (u UUID) Bytes() []byte { - return u[:] -} - -// Returns canonical string representation of UUID: -// xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx. -func (u UUID) String() string { - buf := make([]byte, 36) - - hex.Encode(buf[0:8], u[0:4]) - buf[8] = dash - hex.Encode(buf[9:13], u[4:6]) - buf[13] = dash - hex.Encode(buf[14:18], u[6:8]) - buf[18] = dash - hex.Encode(buf[19:23], u[8:10]) - buf[23] = dash - hex.Encode(buf[24:], u[10:]) - - return string(buf) -} - -// SetVersion sets version bits. -func (u *UUID) SetVersion(v byte) { - u[6] = (u[6] & 0x0f) | (v << 4) -} - -// SetVariant sets variant bits as described in RFC 4122. -func (u *UUID) SetVariant() { - u[8] = (u[8] & 0xbf) | 0x80 -} - -// MarshalText implements the encoding.TextMarshaler interface. -// The encoding is the same as returned by String. -func (u UUID) MarshalText() (text []byte, err error) { - text = []byte(u.String()) - return -} - -// UnmarshalText implements the encoding.TextUnmarshaler interface. -// Following formats are supported: -// "6ba7b810-9dad-11d1-80b4-00c04fd430c8", -// "{6ba7b810-9dad-11d1-80b4-00c04fd430c8}", -// "urn:uuid:6ba7b810-9dad-11d1-80b4-00c04fd430c8" -func (u *UUID) UnmarshalText(text []byte) (err error) { - if len(text) < 32 { - err = fmt.Errorf("uuid: UUID string too short: %s", text) - return - } - - t := text[:] - braced := false - - if bytes.Equal(t[:9], urnPrefix) { - t = t[9:] - } else if t[0] == '{' { - braced = true - t = t[1:] - } - - b := u[:] - - for i, byteGroup := range byteGroups { - if i > 0 && t[0] == '-' { - t = t[1:] - } else if i > 0 && t[0] != '-' { - err = fmt.Errorf("uuid: invalid string format") - return - } - - if i == 2 { - if !bytes.Contains([]byte("012345"), []byte{t[0]}) { - err = fmt.Errorf("uuid: invalid version number: %s", t[0]) - return - } - } - - if len(t) < byteGroup { - err = fmt.Errorf("uuid: UUID string too short: %s", text) - return - } - - if i == 4 && len(t) > byteGroup && - ((braced && t[byteGroup] != '}') || len(t[byteGroup:]) > 1 || !braced) { - err = fmt.Errorf("uuid: UUID string too long: %s", t) - return - } - - _, err = hex.Decode(b[:byteGroup/2], t[:byteGroup]) - - if err != nil { - return - } - - t = t[byteGroup:] - b = b[byteGroup/2:] - } - - return -} - -// MarshalBinary implements the encoding.BinaryMarshaler interface. -func (u UUID) MarshalBinary() (data []byte, err error) { - data = u.Bytes() - return -} - -// UnmarshalBinary implements the encoding.BinaryUnmarshaler interface. -// It will return error if the slice isn't 16 bytes long. -func (u *UUID) UnmarshalBinary(data []byte) (err error) { - if len(data) != 16 { - err = fmt.Errorf("uuid: UUID must be exactly 16 bytes long, got %d bytes", len(data)) - return - } - copy(u[:], data) - - return -} - -// Value implements the driver.Valuer interface. -func (u UUID) Value() (driver.Value, error) { - return u.String(), nil -} - -// Scan implements the sql.Scanner interface. -// A 16-byte slice is handled by UnmarshalBinary, while -// a longer byte slice or a string is handled by UnmarshalText. -func (u *UUID) Scan(src interface{}) error { - switch src := src.(type) { - case []byte: - if len(src) == 16 { - return u.UnmarshalBinary(src) - } - return u.UnmarshalText(src) - - case string: - return u.UnmarshalText([]byte(src)) - } - - return fmt.Errorf("uuid: cannot convert %T to UUID", src) -} - -// Value implements the driver.Valuer interface. -func (u NullUUID) Value() (driver.Value, error) { - if !u.Valid { - return nil, nil - } - // Delegate to UUID Value function - return u.UUID.Value() -} - -// Scan implements the sql.Scanner interface. -func (u *NullUUID) Scan(src interface{}) error { - if src == nil { - u.UUID, u.Valid = Nil, false - return nil - } - - // Delegate to UUID Scan function - u.Valid = true - return u.UUID.Scan(src) -} - -// FromBytes returns UUID converted from raw byte slice input. -// It will return error if the slice isn't 16 bytes long. -func FromBytes(input []byte) (u UUID, err error) { - err = u.UnmarshalBinary(input) - return -} - -// FromBytesOrNil returns UUID converted from raw byte slice input. -// Same behavior as FromBytes, but returns a Nil UUID on error. -func FromBytesOrNil(input []byte) UUID { - uuid, err := FromBytes(input) - if err != nil { - return Nil - } - return uuid -} - -// FromString returns UUID parsed from string input. -// Input is expected in a form accepted by UnmarshalText. -func FromString(input string) (u UUID, err error) { - err = u.UnmarshalText([]byte(input)) - return -} - -// FromStringOrNil returns UUID parsed from string input. -// Same behavior as FromString, but returns a Nil UUID on error. -func FromStringOrNil(input string) UUID { - uuid, err := FromString(input) - if err != nil { - return Nil - } - return uuid -} - -// Returns UUID v1/v2 storage state. -// Returns epoch timestamp, clock sequence, and hardware address. -func getStorage() (uint64, uint16, []byte) { - storageOnce.Do(initStorage) - - storageMutex.Lock() - defer storageMutex.Unlock() - - timeNow := epochFunc() - // Clock changed backwards since last UUID generation. - // Should increase clock sequence. - if timeNow <= lastTime { - clockSequence++ - } - lastTime = timeNow - - return timeNow, clockSequence, hardwareAddr[:] -} - -// NewV1 returns UUID based on current timestamp and MAC address. -func NewV1() UUID { - u := UUID{} - - timeNow, clockSeq, hardwareAddr := getStorage() - - binary.BigEndian.PutUint32(u[0:], uint32(timeNow)) - binary.BigEndian.PutUint16(u[4:], uint16(timeNow>>32)) - binary.BigEndian.PutUint16(u[6:], uint16(timeNow>>48)) - binary.BigEndian.PutUint16(u[8:], clockSeq) - - copy(u[10:], hardwareAddr) - - u.SetVersion(1) - u.SetVariant() - - return u -} - -// NewV2 returns DCE Security UUID based on POSIX UID/GID. -func NewV2(domain byte) UUID { - u := UUID{} - - timeNow, clockSeq, hardwareAddr := getStorage() - - switch domain { - case DomainPerson: - binary.BigEndian.PutUint32(u[0:], posixUID) - case DomainGroup: - binary.BigEndian.PutUint32(u[0:], posixGID) - } - - binary.BigEndian.PutUint16(u[4:], uint16(timeNow>>32)) - binary.BigEndian.PutUint16(u[6:], uint16(timeNow>>48)) - binary.BigEndian.PutUint16(u[8:], clockSeq) - u[9] = domain - - copy(u[10:], hardwareAddr) - - u.SetVersion(2) - u.SetVariant() - - return u -} - -// NewV3 returns UUID based on MD5 hash of namespace UUID and name. -func NewV3(ns UUID, name string) UUID { - u := newFromHash(md5.New(), ns, name) - u.SetVersion(3) - u.SetVariant() - - return u -} - -// NewV4 returns random generated UUID. -func NewV4() UUID { - u := UUID{} - safeRandom(u[:]) - u.SetVersion(4) - u.SetVariant() - - return u -} - -// NewV5 returns UUID based on SHA-1 hash of namespace UUID and name. -func NewV5(ns UUID, name string) UUID { - u := newFromHash(sha1.New(), ns, name) - u.SetVersion(5) - u.SetVariant() - - return u -} - -// Returns UUID based on hashing of namespace UUID and name. -func newFromHash(h hash.Hash, ns UUID, name string) UUID { - u := UUID{} - h.Write(ns[:]) - h.Write([]byte(name)) - copy(u[:], h.Sum(nil)) - - return u -} diff --git a/vendor/github.com/satori/go.uuid/uuid_test.go b/vendor/github.com/satori/go.uuid/uuid_test.go deleted file mode 100644 index aa68ac9..0000000 --- a/vendor/github.com/satori/go.uuid/uuid_test.go +++ /dev/null @@ -1,633 +0,0 @@ -// Copyright (C) 2013, 2015 by Maxim Bublis -// -// Permission is hereby granted, free of charge, to any person obtaining -// a copy of this software and associated documentation files (the -// "Software"), to deal in the Software without restriction, including -// without limitation the rights to use, copy, modify, merge, publish, -// distribute, sublicense, and/or sell copies of the Software, and to -// permit persons to whom the Software is furnished to do so, subject to -// the following conditions: -// -// The above copyright notice and this permission notice shall be -// included in all copies or substantial portions of the Software. -// -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, -// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF -// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND -// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE -// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION -// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION -// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. - -package uuid - -import ( - "bytes" - "testing" -) - -func TestBytes(t *testing.T) { - u := UUID{0x6b, 0xa7, 0xb8, 0x10, 0x9d, 0xad, 0x11, 0xd1, 0x80, 0xb4, 0x00, 0xc0, 0x4f, 0xd4, 0x30, 0xc8} - - bytes1 := []byte{0x6b, 0xa7, 0xb8, 0x10, 0x9d, 0xad, 0x11, 0xd1, 0x80, 0xb4, 0x00, 0xc0, 0x4f, 0xd4, 0x30, 0xc8} - - if !bytes.Equal(u.Bytes(), bytes1) { - t.Errorf("Incorrect bytes representation for UUID: %s", u) - } -} - -func TestString(t *testing.T) { - if NamespaceDNS.String() != "6ba7b810-9dad-11d1-80b4-00c04fd430c8" { - t.Errorf("Incorrect string representation for UUID: %s", NamespaceDNS.String()) - } -} - -func TestEqual(t *testing.T) { - if !Equal(NamespaceDNS, NamespaceDNS) { - t.Errorf("Incorrect comparison of %s and %s", NamespaceDNS, NamespaceDNS) - } - - if Equal(NamespaceDNS, NamespaceURL) { - t.Errorf("Incorrect comparison of %s and %s", NamespaceDNS, NamespaceURL) - } -} - -func TestOr(t *testing.T) { - u1 := UUID{0x00, 0xff, 0x00, 0xff, 0x00, 0xff, 0x00, 0xff, 0x00, 0xff, 0x00, 0xff, 0x00, 0xff, 0x00, 0xff} - u2 := UUID{0xff, 0x00, 0xff, 0x00, 0xff, 0x00, 0xff, 0x00, 0xff, 0x00, 0xff, 0x00, 0xff, 0x00, 0xff, 0x00} - - u := UUID{0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff} - - if !Equal(u, Or(u1, u2)) { - t.Errorf("Incorrect bitwise OR result %s", Or(u1, u2)) - } -} - -func TestAnd(t *testing.T) { - u1 := UUID{0x00, 0xff, 0x00, 0xff, 0x00, 0xff, 0x00, 0xff, 0x00, 0xff, 0x00, 0xff, 0x00, 0xff, 0x00, 0xff} - u2 := UUID{0xff, 0x00, 0xff, 0x00, 0xff, 0x00, 0xff, 0x00, 0xff, 0x00, 0xff, 0x00, 0xff, 0x00, 0xff, 0x00} - - u := UUID{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00} - - if !Equal(u, And(u1, u2)) { - t.Errorf("Incorrect bitwise AND result %s", And(u1, u2)) - } -} - -func TestVersion(t *testing.T) { - u := UUID{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00} - - if u.Version() != 1 { - t.Errorf("Incorrect version for UUID: %d", u.Version()) - } -} - -func TestSetVersion(t *testing.T) { - u := UUID{} - u.SetVersion(4) - - if u.Version() != 4 { - t.Errorf("Incorrect version for UUID after u.setVersion(4): %d", u.Version()) - } -} - -func TestVariant(t *testing.T) { - u1 := UUID{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00} - - if u1.Variant() != VariantNCS { - t.Errorf("Incorrect variant for UUID variant %d: %d", VariantNCS, u1.Variant()) - } - - u2 := UUID{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00} - - if u2.Variant() != VariantRFC4122 { - t.Errorf("Incorrect variant for UUID variant %d: %d", VariantRFC4122, u2.Variant()) - } - - u3 := UUID{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xc0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00} - - if u3.Variant() != VariantMicrosoft { - t.Errorf("Incorrect variant for UUID variant %d: %d", VariantMicrosoft, u3.Variant()) - } - - u4 := UUID{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xe0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00} - - if u4.Variant() != VariantFuture { - t.Errorf("Incorrect variant for UUID variant %d: %d", VariantFuture, u4.Variant()) - } -} - -func TestSetVariant(t *testing.T) { - u := new(UUID) - u.SetVariant() - - if u.Variant() != VariantRFC4122 { - t.Errorf("Incorrect variant for UUID after u.setVariant(): %d", u.Variant()) - } -} - -func TestFromBytes(t *testing.T) { - u := UUID{0x6b, 0xa7, 0xb8, 0x10, 0x9d, 0xad, 0x11, 0xd1, 0x80, 0xb4, 0x00, 0xc0, 0x4f, 0xd4, 0x30, 0xc8} - b1 := []byte{0x6b, 0xa7, 0xb8, 0x10, 0x9d, 0xad, 0x11, 0xd1, 0x80, 0xb4, 0x00, 0xc0, 0x4f, 0xd4, 0x30, 0xc8} - - u1, err := FromBytes(b1) - if err != nil { - t.Errorf("Error parsing UUID from bytes: %s", err) - } - - if !Equal(u, u1) { - t.Errorf("UUIDs should be equal: %s and %s", u, u1) - } - - b2 := []byte{} - - _, err = FromBytes(b2) - if err == nil { - t.Errorf("Should return error parsing from empty byte slice, got %s", err) - } -} - -func TestMarshalBinary(t *testing.T) { - u := UUID{0x6b, 0xa7, 0xb8, 0x10, 0x9d, 0xad, 0x11, 0xd1, 0x80, 0xb4, 0x00, 0xc0, 0x4f, 0xd4, 0x30, 0xc8} - b1 := []byte{0x6b, 0xa7, 0xb8, 0x10, 0x9d, 0xad, 0x11, 0xd1, 0x80, 0xb4, 0x00, 0xc0, 0x4f, 0xd4, 0x30, 0xc8} - - b2, err := u.MarshalBinary() - if err != nil { - t.Errorf("Error marshaling UUID: %s", err) - } - - if !bytes.Equal(b1, b2) { - t.Errorf("Marshaled UUID should be %s, got %s", b1, b2) - } -} - -func TestUnmarshalBinary(t *testing.T) { - u := UUID{0x6b, 0xa7, 0xb8, 0x10, 0x9d, 0xad, 0x11, 0xd1, 0x80, 0xb4, 0x00, 0xc0, 0x4f, 0xd4, 0x30, 0xc8} - b1 := []byte{0x6b, 0xa7, 0xb8, 0x10, 0x9d, 0xad, 0x11, 0xd1, 0x80, 0xb4, 0x00, 0xc0, 0x4f, 0xd4, 0x30, 0xc8} - - u1 := UUID{} - err := u1.UnmarshalBinary(b1) - if err != nil { - t.Errorf("Error unmarshaling UUID: %s", err) - } - - if !Equal(u, u1) { - t.Errorf("UUIDs should be equal: %s and %s", u, u1) - } - - b2 := []byte{} - u2 := UUID{} - - err = u2.UnmarshalBinary(b2) - if err == nil { - t.Errorf("Should return error unmarshalling from empty byte slice, got %s", err) - } -} - -func TestFromString(t *testing.T) { - u := UUID{0x6b, 0xa7, 0xb8, 0x10, 0x9d, 0xad, 0x11, 0xd1, 0x80, 0xb4, 0x00, 0xc0, 0x4f, 0xd4, 0x30, 0xc8} - - s1 := "6ba7b810-9dad-11d1-80b4-00c04fd430c8" - s2 := "{6ba7b810-9dad-11d1-80b4-00c04fd430c8}" - s3 := "urn:uuid:6ba7b810-9dad-11d1-80b4-00c04fd430c8" - - _, err := FromString("") - if err == nil { - t.Errorf("Should return error trying to parse empty string, got %s", err) - } - - u1, err := FromString(s1) - if err != nil { - t.Errorf("Error parsing UUID from string: %s", err) - } - - if !Equal(u, u1) { - t.Errorf("UUIDs should be equal: %s and %s", u, u1) - } - - u2, err := FromString(s2) - if err != nil { - t.Errorf("Error parsing UUID from string: %s", err) - } - - if !Equal(u, u2) { - t.Errorf("UUIDs should be equal: %s and %s", u, u2) - } - - u3, err := FromString(s3) - if err != nil { - t.Errorf("Error parsing UUID from string: %s", err) - } - - if !Equal(u, u3) { - t.Errorf("UUIDs should be equal: %s and %s", u, u3) - } -} - -func TestFromStringShort(t *testing.T) { - // Invalid 35-character UUID string - s1 := "6ba7b810-9dad-11d1-80b4-00c04fd430c" - - for i := len(s1); i >= 0; i-- { - _, err := FromString(s1[:i]) - if err == nil { - t.Errorf("Should return error trying to parse too short string, got %s", err) - } - } -} - -func TestFromStringLong(t *testing.T) { - // Invalid 37+ character UUID string - s := []string{ - "6ba7b810-9dad-11d1-80b4-00c04fd430c8=", - "6ba7b810-9dad-11d1-80b4-00c04fd430c8}", - "{6ba7b810-9dad-11d1-80b4-00c04fd430c8}f", - "6ba7b810-9dad-11d1-80b4-00c04fd430c800c04fd430c8", - } - - for _, str := range s { - _, err := FromString(str) - if err == nil { - t.Errorf("Should return error trying to parse too long string, passed %s", str) - } - } -} - -func TestFromStringInvalid(t *testing.T) { - // Invalid UUID string formats - s := []string{ - "6ba7b8109dad11d180b400c04fd430c8", - "6ba7b8109dad11d180b400c04fd430c86ba7b8109dad11d180b400c04fd430c8", - "urn:uuid:{6ba7b810-9dad-11d1-80b4-00c04fd430c8}", - "6ba7b8109-dad-11d1-80b4-00c04fd430c8", - "6ba7b810-9dad1-1d1-80b4-00c04fd430c8", - "6ba7b810-9dad-11d18-0b4-00c04fd430c8", - "6ba7b810-9dad-11d1-80b40-0c04fd430c8", - "6ba7b810+9dad+11d1+80b4+00c04fd430c8", - "6ba7b810-9dad11d180b400c04fd430c8", - "6ba7b8109dad-11d180b400c04fd430c8", - "6ba7b8109dad11d1-80b400c04fd430c8", - "6ba7b8109dad11d180b4-00c04fd430c8", - } - - for _, str := range s { - _, err := FromString(str) - if err == nil { - t.Errorf("Should return error trying to parse invalid string, passed %s", str) - } - } -} - -func TestFromStringOrNil(t *testing.T) { - u := FromStringOrNil("") - if u != Nil { - t.Errorf("Should return Nil UUID on parse failure, got %s", u) - } -} - -func TestFromBytesOrNil(t *testing.T) { - b := []byte{} - u := FromBytesOrNil(b) - if u != Nil { - t.Errorf("Should return Nil UUID on parse failure, got %s", u) - } -} - -func TestMarshalText(t *testing.T) { - u := UUID{0x6b, 0xa7, 0xb8, 0x10, 0x9d, 0xad, 0x11, 0xd1, 0x80, 0xb4, 0x00, 0xc0, 0x4f, 0xd4, 0x30, 0xc8} - b1 := []byte("6ba7b810-9dad-11d1-80b4-00c04fd430c8") - - b2, err := u.MarshalText() - if err != nil { - t.Errorf("Error marshaling UUID: %s", err) - } - - if !bytes.Equal(b1, b2) { - t.Errorf("Marshaled UUID should be %s, got %s", b1, b2) - } -} - -func TestUnmarshalText(t *testing.T) { - u := UUID{0x6b, 0xa7, 0xb8, 0x10, 0x9d, 0xad, 0x11, 0xd1, 0x80, 0xb4, 0x00, 0xc0, 0x4f, 0xd4, 0x30, 0xc8} - b1 := []byte("6ba7b810-9dad-11d1-80b4-00c04fd430c8") - - u1 := UUID{} - err := u1.UnmarshalText(b1) - if err != nil { - t.Errorf("Error unmarshaling UUID: %s", err) - } - - if !Equal(u, u1) { - t.Errorf("UUIDs should be equal: %s and %s", u, u1) - } - - b2 := []byte("") - u2 := UUID{} - - err = u2.UnmarshalText(b2) - if err == nil { - t.Errorf("Should return error trying to unmarshal from empty string") - } -} - -func TestValue(t *testing.T) { - u, err := FromString("6ba7b810-9dad-11d1-80b4-00c04fd430c8") - if err != nil { - t.Errorf("Error parsing UUID from string: %s", err) - } - - val, err := u.Value() - if err != nil { - t.Errorf("Error getting UUID value: %s", err) - } - - if val != u.String() { - t.Errorf("Wrong value returned, should be equal: %s and %s", val, u) - } -} - -func TestValueNil(t *testing.T) { - u := UUID{} - - val, err := u.Value() - if err != nil { - t.Errorf("Error getting UUID value: %s", err) - } - - if val != Nil.String() { - t.Errorf("Wrong value returned, should be equal to UUID.Nil: %s", val) - } -} - -func TestNullUUIDValueNil(t *testing.T) { - u := NullUUID{} - - val, err := u.Value() - if err != nil { - t.Errorf("Error getting UUID value: %s", err) - } - - if val != nil { - t.Errorf("Wrong value returned, should be nil: %s", val) - } -} - -func TestScanBinary(t *testing.T) { - u := UUID{0x6b, 0xa7, 0xb8, 0x10, 0x9d, 0xad, 0x11, 0xd1, 0x80, 0xb4, 0x00, 0xc0, 0x4f, 0xd4, 0x30, 0xc8} - b1 := []byte{0x6b, 0xa7, 0xb8, 0x10, 0x9d, 0xad, 0x11, 0xd1, 0x80, 0xb4, 0x00, 0xc0, 0x4f, 0xd4, 0x30, 0xc8} - - u1 := UUID{} - err := u1.Scan(b1) - if err != nil { - t.Errorf("Error unmarshaling UUID: %s", err) - } - - if !Equal(u, u1) { - t.Errorf("UUIDs should be equal: %s and %s", u, u1) - } - - b2 := []byte{} - u2 := UUID{} - - err = u2.Scan(b2) - if err == nil { - t.Errorf("Should return error unmarshalling from empty byte slice, got %s", err) - } -} - -func TestScanString(t *testing.T) { - u := UUID{0x6b, 0xa7, 0xb8, 0x10, 0x9d, 0xad, 0x11, 0xd1, 0x80, 0xb4, 0x00, 0xc0, 0x4f, 0xd4, 0x30, 0xc8} - s1 := "6ba7b810-9dad-11d1-80b4-00c04fd430c8" - - u1 := UUID{} - err := u1.Scan(s1) - if err != nil { - t.Errorf("Error unmarshaling UUID: %s", err) - } - - if !Equal(u, u1) { - t.Errorf("UUIDs should be equal: %s and %s", u, u1) - } - - s2 := "" - u2 := UUID{} - - err = u2.Scan(s2) - if err == nil { - t.Errorf("Should return error trying to unmarshal from empty string") - } -} - -func TestScanText(t *testing.T) { - u := UUID{0x6b, 0xa7, 0xb8, 0x10, 0x9d, 0xad, 0x11, 0xd1, 0x80, 0xb4, 0x00, 0xc0, 0x4f, 0xd4, 0x30, 0xc8} - b1 := []byte("6ba7b810-9dad-11d1-80b4-00c04fd430c8") - - u1 := UUID{} - err := u1.Scan(b1) - if err != nil { - t.Errorf("Error unmarshaling UUID: %s", err) - } - - if !Equal(u, u1) { - t.Errorf("UUIDs should be equal: %s and %s", u, u1) - } - - b2 := []byte("") - u2 := UUID{} - - err = u2.Scan(b2) - if err == nil { - t.Errorf("Should return error trying to unmarshal from empty string") - } -} - -func TestScanUnsupported(t *testing.T) { - u := UUID{} - - err := u.Scan(true) - if err == nil { - t.Errorf("Should return error trying to unmarshal from bool") - } -} - -func TestScanNil(t *testing.T) { - u := UUID{0x6b, 0xa7, 0xb8, 0x10, 0x9d, 0xad, 0x11, 0xd1, 0x80, 0xb4, 0x00, 0xc0, 0x4f, 0xd4, 0x30, 0xc8} - - err := u.Scan(nil) - if err == nil { - t.Errorf("Error UUID shouldn't allow unmarshalling from nil") - } -} - -func TestNullUUIDScanValid(t *testing.T) { - u := UUID{0x6b, 0xa7, 0xb8, 0x10, 0x9d, 0xad, 0x11, 0xd1, 0x80, 0xb4, 0x00, 0xc0, 0x4f, 0xd4, 0x30, 0xc8} - s1 := "6ba7b810-9dad-11d1-80b4-00c04fd430c8" - - u1 := NullUUID{} - err := u1.Scan(s1) - if err != nil { - t.Errorf("Error unmarshaling NullUUID: %s", err) - } - - if !u1.Valid { - t.Errorf("NullUUID should be valid") - } - - if !Equal(u, u1.UUID) { - t.Errorf("UUIDs should be equal: %s and %s", u, u1.UUID) - } -} - -func TestNullUUIDScanNil(t *testing.T) { - u := NullUUID{UUID{0x6b, 0xa7, 0xb8, 0x10, 0x9d, 0xad, 0x11, 0xd1, 0x80, 0xb4, 0x00, 0xc0, 0x4f, 0xd4, 0x30, 0xc8}, true} - - err := u.Scan(nil) - if err != nil { - t.Errorf("Error unmarshaling NullUUID: %s", err) - } - - if u.Valid { - t.Errorf("NullUUID should not be valid") - } - - if !Equal(u.UUID, Nil) { - t.Errorf("NullUUID value should be equal to Nil: %s", u) - } -} - -func TestNewV1(t *testing.T) { - u := NewV1() - - if u.Version() != 1 { - t.Errorf("UUIDv1 generated with incorrect version: %d", u.Version()) - } - - if u.Variant() != VariantRFC4122 { - t.Errorf("UUIDv1 generated with incorrect variant: %d", u.Variant()) - } - - u1 := NewV1() - u2 := NewV1() - - if Equal(u1, u2) { - t.Errorf("UUIDv1 generated two equal UUIDs: %s and %s", u1, u2) - } - - oldFunc := epochFunc - epochFunc = func() uint64 { return 0 } - - u3 := NewV1() - u4 := NewV1() - - if Equal(u3, u4) { - t.Errorf("UUIDv1 generated two equal UUIDs: %s and %s", u3, u4) - } - - epochFunc = oldFunc -} - -func TestNewV2(t *testing.T) { - u1 := NewV2(DomainPerson) - - if u1.Version() != 2 { - t.Errorf("UUIDv2 generated with incorrect version: %d", u1.Version()) - } - - if u1.Variant() != VariantRFC4122 { - t.Errorf("UUIDv2 generated with incorrect variant: %d", u1.Variant()) - } - - u2 := NewV2(DomainGroup) - - if u2.Version() != 2 { - t.Errorf("UUIDv2 generated with incorrect version: %d", u2.Version()) - } - - if u2.Variant() != VariantRFC4122 { - t.Errorf("UUIDv2 generated with incorrect variant: %d", u2.Variant()) - } -} - -func TestNewV3(t *testing.T) { - u := NewV3(NamespaceDNS, "www.example.com") - - if u.Version() != 3 { - t.Errorf("UUIDv3 generated with incorrect version: %d", u.Version()) - } - - if u.Variant() != VariantRFC4122 { - t.Errorf("UUIDv3 generated with incorrect variant: %d", u.Variant()) - } - - if u.String() != "5df41881-3aed-3515-88a7-2f4a814cf09e" { - t.Errorf("UUIDv3 generated incorrectly: %s", u.String()) - } - - u = NewV3(NamespaceDNS, "python.org") - - if u.String() != "6fa459ea-ee8a-3ca4-894e-db77e160355e" { - t.Errorf("UUIDv3 generated incorrectly: %s", u.String()) - } - - u1 := NewV3(NamespaceDNS, "golang.org") - u2 := NewV3(NamespaceDNS, "golang.org") - if !Equal(u1, u2) { - t.Errorf("UUIDv3 generated different UUIDs for same namespace and name: %s and %s", u1, u2) - } - - u3 := NewV3(NamespaceDNS, "example.com") - if Equal(u1, u3) { - t.Errorf("UUIDv3 generated same UUIDs for different names in same namespace: %s and %s", u1, u2) - } - - u4 := NewV3(NamespaceURL, "golang.org") - if Equal(u1, u4) { - t.Errorf("UUIDv3 generated same UUIDs for sane names in different namespaces: %s and %s", u1, u4) - } -} - -func TestNewV4(t *testing.T) { - u := NewV4() - - if u.Version() != 4 { - t.Errorf("UUIDv4 generated with incorrect version: %d", u.Version()) - } - - if u.Variant() != VariantRFC4122 { - t.Errorf("UUIDv4 generated with incorrect variant: %d", u.Variant()) - } -} - -func TestNewV5(t *testing.T) { - u := NewV5(NamespaceDNS, "www.example.com") - - if u.Version() != 5 { - t.Errorf("UUIDv5 generated with incorrect version: %d", u.Version()) - } - - if u.Variant() != VariantRFC4122 { - t.Errorf("UUIDv5 generated with incorrect variant: %d", u.Variant()) - } - - u = NewV5(NamespaceDNS, "python.org") - - if u.String() != "886313e1-3b8a-5372-9b90-0c9aee199e5d" { - t.Errorf("UUIDv5 generated incorrectly: %s", u.String()) - } - - u1 := NewV5(NamespaceDNS, "golang.org") - u2 := NewV5(NamespaceDNS, "golang.org") - if !Equal(u1, u2) { - t.Errorf("UUIDv5 generated different UUIDs for same namespace and name: %s and %s", u1, u2) - } - - u3 := NewV5(NamespaceDNS, "example.com") - if Equal(u1, u3) { - t.Errorf("UUIDv5 generated same UUIDs for different names in same namespace: %s and %s", u1, u2) - } - - u4 := NewV5(NamespaceURL, "golang.org") - if Equal(u1, u4) { - t.Errorf("UUIDv3 generated same UUIDs for sane names in different namespaces: %s and %s", u1, u4) - } -} From 4509da170c7405af6b842cd833e12f4dcf61c603 Mon Sep 17 00:00:00 2001 From: Daniel Fireman Date: Tue, 21 May 2019 14:35:06 -0300 Subject: [PATCH 5/8] Add dep ensure --- .travis.yml | 1 + 1 file changed, 1 insertion(+) diff --git a/.travis.yml b/.travis.yml index 98200d3..85034ee 100644 --- a/.travis.yml +++ b/.travis.yml @@ -15,6 +15,7 @@ env: - GO111MODULE=on before_install: + - dep ensure - go get github.com/mattn/goveralls script: From bde2fd08f9f21ed487ef1b5ec6e2d2273727d4f5 Mon Sep 17 00:00:00 2001 From: Daniel Fireman Date: Tue, 21 May 2019 14:57:24 -0300 Subject: [PATCH 6/8] Fix godep installation --- .travis.yml | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/.travis.yml b/.travis.yml index 85034ee..6476887 100644 --- a/.travis.yml +++ b/.travis.yml @@ -15,8 +15,11 @@ env: - GO111MODULE=on before_install: - - dep ensure + - go get github.com/tools/godep - go get github.com/mattn/goveralls +install: + - dep ensure + script: - $HOME/gopath/bin/goveralls -service=travis-ci -ignore=validator/profile_cache/*.go,examples/remote/*.go,examples/inline/*.go,examples/load_zip/*.go,examples/load/*.go,examples/zip/*.go,examples/build_package/*.go,examples/multipart/*.go From e3b117b1fccd4d704bc4d3305518d0247ceda406 Mon Sep 17 00:00:00 2001 From: Daniel Fireman Date: Tue, 21 May 2019 15:01:43 -0300 Subject: [PATCH 7/8] Fix dep installation --- .travis.yml | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/.travis.yml b/.travis.yml index 6476887..5aa5ebf 100644 --- a/.travis.yml +++ b/.travis.yml @@ -15,11 +15,9 @@ env: - GO111MODULE=on before_install: - - go get github.com/tools/godep - - go get github.com/mattn/goveralls - -install: + - curl https://raw.githubusercontent.com/golang/dep/master/install.sh | sh - dep ensure + - go get github.com/mattn/goveralls script: - $HOME/gopath/bin/goveralls -service=travis-ci -ignore=validator/profile_cache/*.go,examples/remote/*.go,examples/inline/*.go,examples/load_zip/*.go,examples/load/*.go,examples/zip/*.go,examples/build_package/*.go,examples/multipart/*.go From 73939f6dfbf8b4b1778eca9ba7dc3c364a4dff79 Mon Sep 17 00:00:00 2001 From: Daniel Fireman Date: Tue, 21 May 2019 15:10:14 -0300 Subject: [PATCH 8/8] Fix readme TOC --- README.md | 12 +++++++++++- 1 file changed, 11 insertions(+), 1 deletion(-) diff --git a/README.md b/README.md index e80141b..d721724 100644 --- a/README.md +++ b/README.md @@ -3,7 +3,17 @@ # datapackage-go A Go library for working with [Data Packages](http://specs.frictionlessdata.io/data-package/). -autoauto- [datapackage-go](#datapackage-go)auto - [Install](#install)auto - [Main Features](#main-features)auto - [Loading and validating tabular data package descriptors](#loading-and-validating-tabular-data-package-descriptors)auto - [Accessing data package resources](#accessing-data-package-resources)auto - [Loading zip bundles](#loading-zip-bundles)auto - [Creating a zip bundle with the data package.](#creating-a-zip-bundle-with-the-data-package)auto - [CSV dialect support](#csv-dialect-support)auto - [Loading multipart resources](#loading-multipart-resources)auto - [Loading non-tabular resources](#loading-non-tabular-resources)auto - [Manipulating data packages programatically](#manipulating-data-packages-programatically)autoauto +- [datapackage-go](#datapackage-go) + - [Install](#install) + - [Main Features](#main-features) + - [Loading and validating tabular data package descriptors](#loading-and-validating-tabular-data-package-descriptors) + - [Accessing data package resources](#accessing-data-package-resources) + - [Loading zip bundles](#loading-zip-bundles) + - [Creating a zip bundle with the data package.](#creating-a-zip-bundle-with-the-data-package) + - [CSV dialect support](#csv-dialect-support) + - [Loading multipart resources](#loading-multipart-resources) + - [Loading non-tabular resources](#loading-non-tabular-resources) + - [Manipulating data packages programatically](#manipulating-data-packages-programatically) ## Install