diff --git a/.github/CONTRIBUTING.md b/.github/CONTRIBUTING.md new file mode 100644 index 00000000..e0bf6764 --- /dev/null +++ b/.github/CONTRIBUTING.md @@ -0,0 +1,183 @@ +# Contributing to json_schema + +Looking to contribute something to the json_schema library? __Here's how you can help.__ + ++ __[Coding Standards](#coding-standards)__ + + [General Formatting Guidelines](#general-formatting-guidelines) ++ __[Using the Issue Tracker](#using-the-issue-tracker)__ + + [Reporting Bugs](#bug-reports) + + [Feature Requests](#feature-requests) + + [Submitting Pull Requests](#pull-requests) ++ __[Developer Workflow](#developer-workflow)__ + + + + +## Coding standards + +A lot can be gained by writing code in a consistent way. Moreover, always remember that code is written and +maintained by _people_. Ensure your code is descriptive, well commented, and approachable by others. + +__ALWAYS__ adhere to the [Dart Style Guide]. _Please take the time to read it if you have never done so._ + +  + + +### General formatting guidelines + ++ __AVOID__ lines longer than 120 characters. ++ __AVOID__ using `dartfmt` as an excuse to ignore good judgement about + whether your code is readable and approachable by others. + +  +  + + + +## Using the issue tracker + +The issue tracker is the preferred channel for [bug reports](#bug-reports) and [feature requests](#feature-requests), +but __please follow the guidelines:__ + + + __Fill out the template we've provided.__ + + + __Be Professional__ + + Please __do not__ derail or troll issues. Keep the discussion on topic and respect the opinions of others. + + + __Not that Professional__ + + Feel free to include _relevant_ animated gifs to drive home your message / request. + +  + + +### Bug reports + +A bug is a _demonstrable problem_ that is caused by the code in the repository. + +_Good bug reports are extremely helpful - thank you!__ + +__Guidelines for bug reports:__ + +1. __Search for existing issues.__ Duplicate issues can become cumbersome, and you'd help us out a lot by first + checking if someone else has reported the same issue. Moreover, the issue may have already been resolved with a + fix available. + +2. __Record a screencast of yourself reproducing the issue__. + 1. Be sure the problem exists in json_schema's code by building a + reduced test case that one of the reviewers can pull locally + and test out. + +3. __Share as much information as possible.__ Include operating system and version, browser and version, etc. where appropriate. + +Always include steps to reproduce the bug. + +__Example Bug Report:__ + +> Short and descriptive example bug report title +> +> A summary of the issue and the browser/OS environment in which it occurs. If +> suitable, include the steps required to reproduce the bug. +> +> 1. This is the first step +> 2. This is the second step +> 3. Further steps, etc. +> +> `` - a link to branch with the reduced test case +> +> Any other information you want to share that is relevant to the issue being +> reported. This might include the lines of code that you have identified as +> causing the bug, and potential solutions (and your opinions on their +> merits). + +  + + +### Feature requests + +Feature requests are welcome. But take a moment to find out whether your idea fits with the scope and aims of the +project. It's up to *you* to make a strong case to convince the `json_schema` team of the merits of this feature. +Please provide as much detail and context as possible. + +  + + +### Pull requests + +Good pull requests - patches, improvements, new features - are a fantastic help. They should remain focused in scope +and avoid containing unrelated commits. + +__Please ask first__ before embarking on any significant pull request (e.g. implementing features, refactoring code, +porting to a different language), otherwise you risk spending a lot of time working on something that the project's +lead developers might not want to merge into the project. + +Please adhere to the [Dart Style Guide] for all changes contained in your pull requests. + +Adhering to the following process is the best way to get your work included in the project: + +1. [Fork](http://help.github.com/fork-a-repo/) the project, clone your fork, + and configure the remotes: + + ```bash + # Navigate to the directory where you store repos locally + cd ~/your-local-git-repo-spot + # Clone your fork of the repo into the current directory + git clone git@github.com:/json_schema + # Navigate to the newly cloned directory + cd ~/your-local-git-repo-spot/json_schema + # Assign the repo you forked from to a remote called "upstream" + git remote add upstream git@github.com:Workiva/json_schema + ``` + +2. If you cloned a while ago, get the latest changes from upstream: + + ```bash + git checkout master + git pull upstream master + ``` + +3. Create a new topic branch that will contain your feature, change, or fix: + + ```bash + git checkout -b + ``` + +4. Commit your changes in logical chunks. Please adhere to these + [git commit message guidelines](#git-commit-message-standards) or your code is unlikely be merged into the master + branch. Optionally, you can use Git's [interactive rebase](https://help.github.com/articles/interactive-rebase) + feature to tidy up your commits before making them public. + +5. Write tests for your changes. + 1. There are no exceptions. + 2. If you're having trouble, reach out in your PR about how to best go about testing your changes. + +6. If you have merge conflicts, locally merge the upstream master branch into your topic branch: + + ```bash + git pull upstream master + ``` + +7. Push your topic branch up to your fork: + + ```bash + git push origin + ``` + +8. [Open a Pull Request](https://help.github.com/articles/using-pull-requests/) + with a clear title and description - following all the [issue guidelines](#using-the-issue-tracker) listed above. + +  +  + + +## Developer Workflow + +The `json_schema` developer workflow couldn't be any more simple! + +When you're ready to run the tests... run: + +```bash +pub run dart_dev test +``` + + +[Dart Style Guide]: https://www.dartlang.org/guides/language/effective-dart/style \ No newline at end of file diff --git a/.github/ISSUE_TEMPLATE.md b/.github/ISSUE_TEMPLATE.md new file mode 100644 index 00000000..f5db4250 --- /dev/null +++ b/.github/ISSUE_TEMPLATE.md @@ -0,0 +1,28 @@ + + + +## Type + +## Details + + + +## Possible Solution + + + + + +## Steps to Reproduce + +1. +2. +3. + +## Your Environment + +* Version: +* Browser name / VM and version: +* Operating System and version: + +> __FYI:__ @michaelcarter-wf \ No newline at end of file diff --git a/.github/PULL_REQUEST_TEMPLATE.md b/.github/PULL_REQUEST_TEMPLATE.md new file mode 100644 index 00000000..e2bcab9f --- /dev/null +++ b/.github/PULL_REQUEST_TEMPLATE.md @@ -0,0 +1,16 @@ +## Ultimate problem: + + +## How it was fixed: + + +## Testing suggestions: + + +## Potential areas of regression: + + + +--- + +> __FYA:__ @michaelcarter-wf \ No newline at end of file diff --git a/.gitignore b/.gitignore index 0de029e4..aff650d8 100644 --- a/.gitignore +++ b/.gitignore @@ -1,18 +1,17 @@ *.~*~ +.idea/ .packages -packages -build/ -.pub/ .project +.pub/ +*.dart.js *.iml *.ipr *.iws -.idea/ -*.dart.js *.js_ *.js.deps *.js.map -# custom +build/ +coverage +packages pubspec.lock -# end diff --git a/.travis.yml b/.travis.yml index 2e9f3e76..43be0792 100644 --- a/.travis.yml +++ b/.travis.yml @@ -2,5 +2,11 @@ language: dart sudo: false dart: - stable - - dev -script: ./tool/travis.sh \ No newline at end of file +script: + - pub get --packages-dir + - pub run dependency_validator --ignore dart_style,coverage + - pub run dart_dev format --check + - pub run dart_dev analyze + - pub run dart_dev test + - pub run dart_dev coverage --no-html + - bash <(curl -s https://codecov.io/bash) -f coverage/coverage.lcov \ No newline at end of file diff --git a/CHANGELOG.md b/CHANGELOG.md index b90af2e1..3567e43d 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,3 +1,9 @@ +## 1.0.8 + +* Code cleanup +* Strong mode +* Switch build tools to dart_dev + ## 1.0.7 * Update dependency constraint on the `args` package. diff --git a/LICENSE b/LICENSE index fe33dee2..9f3f33ef 100644 --- a/LICENSE +++ b/LICENSE @@ -1,4 +1,4 @@ -Copyright 2013-2017 Workiva Inc. +Copyright 2013-2018 Workiva Inc. Licensed under the Boost Software License (the "License"); you may not use this file except in compliance with the License. diff --git a/README.md b/README.md index 6539a3fa..d9cbcc82 100644 --- a/README.md +++ b/README.md @@ -2,7 +2,7 @@ A *dart:io* dependent library for validating json instances against json schema (version Draft 04) -![Build Status](https://travis-ci.org/patefacio/json_schema.svg) +![Build Status](https://travis-ci.org/workiva/json_schema.svg) # How To Validate diff --git a/bin/gensamples.dart b/bin/gensamples.dart index b032e1b8..2917ebef 100644 --- a/bin/gensamples.dart +++ b/bin/gensamples.dart @@ -1,11 +1,48 @@ +// Copyright 2013-2018 Workiva Inc. +// +// Licensed under the Boost Software License (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.boost.org/LICENSE_1_0.txt +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// +// This software or document includes material copied from or derived +// from JSON-Schema-Test-Suite (https://github.com/json-schema-org/JSON-Schema-Test-Suite), +// Copyright (c) 2012 Julian Berman, which is licensed under the following terms: +// +// Copyright (c) 2012 Julian Berman +// +// 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. + import 'dart:io'; import 'package:path/path.dart'; import 'package:json_schema/json_schema.dart'; import 'package:json_schema/schema_dot.dart'; main() { - var sourcePath = join(dirname(dirname(absolute(Platform.script.toFilePath()))), - 'dot_samples', 'schemas'); + var sourcePath = join(dirname(dirname(absolute(Platform.script.toFilePath()))), 'dot_samples', 'schemas'); var outPath = join(dirname(sourcePath), 'schemaout'); new Directory(sourcePath).listSync().forEach((jsonFile) { var fname = jsonFile.path; @@ -13,20 +50,16 @@ main() { var dotFilename = join(outPath, '$base.dot'); var pngOut = join(outPath, '$base.png'); - Schema.createSchemaFromUrl(fname) - .then((schema) { - new File(dotFilename).writeAsStringSync(createDot(schema)); - }) - .then((_) { - - Process.run('dot', ['-Tpng', '-o$pngOut', dotFilename]) - .then((ProcessResult processResult) { - if(processResult.exitCode == 0) { - print("Finished running dot -Tpng -o$pngOut $fname"); - } else { - print("FAILED: running dot -Tpng -o$pngOut $fname"); - } - }); + Schema.createSchemaFromUrl(fname).then((schema) { + new File(dotFilename).writeAsStringSync(createDot(schema)); + }).then((_) { + Process.run('dot', ['-Tpng', '-o$pngOut', dotFilename]).then((ProcessResult processResult) { + if (processResult.exitCode == 0) { + print("Finished running dot -Tpng -o$pngOut $fname"); + } else { + print("FAILED: running dot -Tpng -o$pngOut $fname"); + } }); + }); }); -} \ No newline at end of file +} diff --git a/bin/schemadot.dart b/bin/schemadot.dart index bc099288..9e6102d8 100644 --- a/bin/schemadot.dart +++ b/bin/schemadot.dart @@ -1,4 +1,41 @@ #!/usr/bin/env dart +// Copyright 2013-2018 Workiva Inc. +// +// Licensed under the Boost Software License (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.boost.org/LICENSE_1_0.txt +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// +// This software or document includes material copied from or derived +// from JSON-Schema-Test-Suite (https://github.com/json-schema-org/JSON-Schema-Test-Suite), +// Copyright (c) 2012 Julian Berman, which is licensed under the following terms: +// +// Copyright (c) 2012 Julian Berman +// +// 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. /// /// Usage: schemadot --in-uri INPUT_JSON_URI --out-file OUTPUT_FILE @@ -11,7 +48,6 @@ import 'dart:async'; import 'dart:convert' as convert; import 'dart:io'; -import 'dart:math'; import 'package:args/args.dart'; import 'package:json_schema/json_schema.dart'; import 'package:json_schema/schema_dot.dart'; @@ -33,7 +69,7 @@ program. If [out-file] provided, output is written to the file, otherwise written to stdout. '''); - print(_parser.getUsage()); + print(_parser.usage); } //! Method to parse command line options. @@ -41,7 +77,6 @@ the file, otherwise written to stdout. Map _parseArgs(List args) { ArgResults argResults; Map result = {}; - List remaining = []; _parser = new ArgParser(); try { @@ -53,18 +88,8 @@ Display this help screen abbr: 'h', defaultsTo: false); - _parser.addOption('in-uri', - help: '', - defaultsTo: null, - allowMultiple: false, - abbr: 'i', - allowed: null); - _parser.addOption('out-file', - help: '', - defaultsTo: null, - allowMultiple: false, - abbr: 'o', - allowed: null); + _parser.addOption('in-uri', help: '', defaultsTo: null, allowMultiple: false, abbr: 'i', allowed: null); + _parser.addOption('out-file', help: '', defaultsTo: null, allowMultiple: false, abbr: 'o', allowed: null); _parser.addOption('log-level', help: r''' Select log level from: @@ -116,15 +141,13 @@ Select log level from: final _logger = new Logger('schemadot'); main(List args) { - Logger.root.onRecord.listen( - (LogRecord r) => print("${r.loggerName} [${r.level}]:\t${r.message}")); + Logger.root.onRecord.listen((LogRecord r) => print("${r.loggerName} [${r.level}]:\t${r.message}")); Logger.root.level = Level.OFF; Map argResults = _parseArgs(args); Map options = argResults['options']; - List positionals = argResults['rest']; + try { - if (options["in-uri"] == null) - throw new ArgumentError("option: in-uri is required"); + if (options["in-uri"] == null) throw new ArgumentError("option: in-uri is required"); } on ArgumentError catch (e) { print(e); _usage(); @@ -139,8 +162,7 @@ main(List args) { new HttpClient() .getUrl(uri) .then((HttpClientRequest request) => request.close()) - .then((HttpClientResponse response) => - response.transform(new convert.Utf8Decoder()).join()) + .then((HttpClientResponse response) => response.transform(new convert.Utf8Decoder()).join()) .then((text) { completer.complete(text); }); diff --git a/codegen/json_schema.ebisu_dart.dart b/codegen/json_schema.ebisu_dart.dart deleted file mode 100644 index 068ee0bb..00000000 --- a/codegen/json_schema.ebisu_dart.dart +++ /dev/null @@ -1,354 +0,0 @@ -import "dart:io"; -import "package:path/path.dart" as path; -import "package:ebisu/ebisu_dart_meta.dart"; -import "package:ebisu/ebisu.dart"; -import "package:logging/logging.dart"; - -String _topDir; - -void main() { - Logger.root.onRecord.listen((LogRecord r) => - print("${r.loggerName} [${r.level}]:\t${r.message}")); - String here = path.absolute(Platform.script.toFilePath()); - _topDir = path.dirname(path.dirname(here)); - useDartFormatter = true; - System ebisu = system('json_schema') - ..pubSpec.homepage = 'https://github.com/patefacio/json_schema' - ..pubSpec.version = '1.0.7' - ..pubSpec.doc = 'Provide support for validating instances against json schema' - ..rootPath = '$_topDir' - ..doc = 'Json Schema related functionality' - ..testLibraries = [ - library('test_invalid_schemas') - ..includesLogger = true - ..imports = [ - 'io', '"dart:convert" as convert', '"package:path/path.dart" as path', - 'package:json_schema/json_schema.dart', - ], - library('test_validation') - ..includesLogger = true - ..imports = [ - 'io', '"dart:convert" as convert', '"package:path/path.dart" as path', - 'package:json_schema/json_schema.dart', - ], - ] - ..scripts = [ - script('schemadot') - ..imports = [ - 'package:json_schema/json_schema.dart', - 'package:json_schema/schema_dot.dart', - '"dart:convert" as convert', - 'math', - 'async', - ] - ..doc = ''' - -Usage: schemadot --in-uri INPUT_JSON_URI --out-file OUTPUT_FILE - -Given an input uri [in-uri] processes content of uri as -json schema and generates input file for Graphviz dot -program. If [out-file] provided, output is written to -the file, otherwise written to stdout. -''' - ..args = [ - scriptArg('in_uri') - ..isRequired = true - ..abbr = 'i', - scriptArg('out_file') - ..abbr = 'o', - ] - ] - ..libraries = [ - library('schema_dot') - ..doc = 'Functionality to create Graphviz input dot file from schema' - ..imports = [ - 'package:json_schema/json_schema.dart', - 'convert', - 'async', - ] - ..classes = [ - class_('schema_node') - ..doc = 'Represents one node in the schema diagram' - ..members = [ - member('schema') - ..doc = 'Referenced schema this node portrays' - ..type = 'Schema', - member('links') - ..doc = 'List of links (resulting in graph edge) from this node to another' - ..type = 'List' - ] - ], - library('json_schema') - ..doc = 'Support for validating json instances against a json schema' - ..includesLogger = true - ..enums = [ - enum_('schema_type') - ..isSnakeString = true - ..hasCustom = true - ..values = [ - id('array'), id('boolean'), id('integer'), - id('number'), id('null'), id('object'), - id('string') - ] - ] - ..imports = [ - 'io', - 'math', - '"dart:convert" as convert', - '"package:path/path.dart" as PATH', - 'async', - ] - ..parts = [ - part('schema') - ..classes = [ - class_('schema') - ..defaultMemberAccess = RO - ..ctorCustoms = [ '_fromRootMap', '_fromMap' ] - ..doc = ''' -Constructed with a json schema, either as string or Map. Validation of -the schema itself is done on construction. Any errors in the schema -result in a FormatException being thrown. -''' - ..members = [ - member('root') - ..type = 'Schema' - ..ctors = [ '_fromMap' ], - member('schema_map') - ..type = 'Map' - ..classInit = '{}' - ..ctors = [ '_fromRootMap', '_fromMap' ], - member('path') - ..ctorInit = "'#'" - ..ctors = [ '_fromMap' ], - - member('multiple_of') - ..type = 'num', - member('maximum') - ..type = 'num', - member('exclusive_maximum') - ..type = 'bool' - ..access = IA, - member('minimum') - ..type = 'num', - member('exclusive_minimum') - ..type = 'bool' - ..access = IA, - member('max_length') - ..type = 'int', - member('min_length') - ..type = 'int', - member('pattern') - ..type = 'RegExp', - - // Validation keywords for any instance - member('enum_values') - ..type = 'List' - ..classInit = '[]', - member('all_of') - ..type = 'List' - ..classInit = '[]', - member('any_of') - ..type = 'List' - ..classInit = '[]', - member('one_of') - ..type = 'List' - ..classInit = '[]', - member('not_schema') - ..type = 'Schema', - member('definitions') - ..type = 'Map' - ..classInit = '{}', - - // Meta-data - member('id') - ..type = 'Uri', - member('ref'), - member('description'), - member('title'), - - member('schema_type_list') - ..type = 'List', - member('items') - ..doc = 'To match all items to a schema' - ..type = 'Schema', - member('items_list') - ..doc = 'To match each item in array to a schema' - ..type = 'List', - member('additional_items') - ..type = 'dynamic', - member('max_items') - ..type = 'int', - member('min_items') - ..type = 'int', - member('unique_items') - ..type = 'bool' - ..classInit = 'false', - - member('required_properties') - ..type = 'List', - member('max_properties') - ..type = 'int', - member('min_properties') - ..type = 'int' - ..classInit = '0', - member('properties') - ..type = 'Map' - ..classInit = '{}', - member('additional_properties') - ..type = 'bool', - member('additional_properties_schema') - ..type = 'Schema', - member('pattern_properties') - ..type = 'Map' - ..classInit = '{}', - - member('schema_dependencies') - ..type = 'Map' - ..classInit = '{}', - member('property_dependencies') - ..type = 'Map>' - ..classInit = '{}', - - member('default_value') - ..type = 'dynamic', - - member('ref_map') - ..doc = 'Map of path to schema object' - ..type = 'Map' - ..classInit = '{}', - member('schema_refs') - ..doc = 'For schemas with \$ref maps path of schema to \$ref path' - ..type = 'Map' - ..access = IA - ..classInit = '{}', - member('schema_assignments') - ..doc = 'Assignments to call for resolution upon end of parse' - ..type = 'List' - ..classInit = '[]' - ..access = IA, - member('free_form_map') - ..doc = 'Maps any non-key top level property to its original value' - ..type = 'Map' - ..classInit = '{}' - ..access = IA, - member('this_completer') - ..type = 'Completer' - ..classInit = 'new Completer()' - ..access = IA, - member('retrieval_requests') - ..type = 'List>' - ..init = [] - ..access = IA, - member('paths_encountered') - ..doc = 'Set of strings to gaurd against path cycles' - ..type = 'Set' - ..classInit = 'new Set()' - ..access = IA, - member('format') - ..doc = 'Support for optional formats (date-time, uri, email, ipv6, hostname)' - ..access = IA, - ] - ], - part('validator') - ..variables = [ - variable('email_re') - ..isPublic = false - ..type = 'RegExp' - ..init = "new RegExp(\n" - r''' - r'^[_A-Za-z0-9-\+]+(\.[_A-Za-z0-9-]+)*' - r'@' - r'[A-Za-z0-9-]+(\.[A-Za-z0-9]+)*(\.[A-Za-z]{2,})$' -''' - ")", - variable('default_email_validator') - ..type = 'var' - ..isPublic = false - ..init = '(String email) => _emailRe.firstMatch(email) != null', - variable('email_validator') - ..isPublic = false - ..type = 'var' - ..init = '_defaultEmailValidator', - variable('ipv4_re') - ..isPublic = false - ..type = 'RegExp' - ..init = "new RegExp(\n" - r''' - r'^(\d|[1-9]\d|1\d\d|2([0-4]\d|5[0-5]))\.' - r'(\d|[1-9]\d|1\d\d|2([0-4]\d|5[0-5]))\.' - r'(\d|[1-9]\d|1\d\d|2([0-4]\d|5[0-5]))\.' - r'(\d|[1-9]\d|1\d\d|2([0-4]\d|5[0-5]))$' -''' - ")", - variable('ipv6_re') - ..isPublic = false - ..type = 'RegExp' - ..init = "new RegExp(\n" - r''' - r'(^([0-9a-f]{1,4}:){1,1}(:[0-9a-f]{1,4}){1,6}$)|' - r'(^([0-9a-f]{1,4}:){1,2}(:[0-9a-f]{1,4}){1,5}$)|' - r'(^([0-9a-f]{1,4}:){1,3}(:[0-9a-f]{1,4}){1,4}$)|' - r'(^([0-9a-f]{1,4}:){1,4}(:[0-9a-f]{1,4}){1,3}$)|' - r'(^([0-9a-f]{1,4}:){1,5}(:[0-9a-f]{1,4}){1,2}$)|' - r'(^([0-9a-f]{1,4}:){1,6}(:[0-9a-f]{1,4}){1,1}$)|' - r'(^(([0-9a-f]{1,4}:){1,7}|:):$)|' - r'(^:(:[0-9a-f]{1,4}){1,7}$)|' - r'(^((([0-9a-f]{1,4}:){6})(25[0-5]|2[0-4]\d|[0-1]?\d?\d)(\.(25[0-5]|2[0-4]\d|[0-1]?\d?\d)){3})$)|' - r'(^(([0-9a-f]{1,4}:){5}[0-9a-f]{1,4}:(25[0-5]|2[0-4]\d|[0-1]?\d?\d)(\.(25[0-5]|2[0-4]\d|[0-1]?\d?\d)){3})$)|' - r'(^([0-9a-f]{1,4}:){5}:[0-9a-f]{1,4}:(25[0-5]|2[0-4]\d|[0-1]?\d?\d)(\.(25[0-5]|2[0-4]\d|[0-1]?\d?\d)){3}$)|' - r'(^([0-9a-f]{1,4}:){1,1}(:[0-9a-f]{1,4}){1,4}:(25[0-5]|2[0-4]\d|[0-1]?\d?\d)(\.(25[0-5]|2[0-4]\d|[0-1]?\d?\d)){3}$)|' - r'(^([0-9a-f]{1,4}:){1,2}(:[0-9a-f]{1,4}){1,3}:(25[0-5]|2[0-4]\d|[0-1]?\d?\d)(\.(25[0-5]|2[0-4]\d|[0-1]?\d?\d)){3}$)|' - r'(^([0-9a-f]{1,4}:){1,3}(:[0-9a-f]{1,4}){1,2}:(25[0-5]|2[0-4]\d|[0-1]?\d?\d)(\.(25[0-5]|2[0-4]\d|[0-1]?\d?\d)){3}$)|' - r'(^([0-9a-f]{1,4}:){1,4}(:[0-9a-f]{1,4}){1,1}:(25[0-5]|2[0-4]\d|[0-1]?\d?\d)(\.(25[0-5]|2[0-4]\d|[0-1]?\d?\d)){3}$)|' - r'(^(([0-9a-f]{1,4}:){1,5}|:):(25[0-5]|2[0-4]\d|[0-1]?\d?\d)(\.(25[0-5]|2[0-4]\d|[0-1]?\d?\d)){3}$)|' - r'(^:(:[0-9a-f]{1,4}){1,5}:(25[0-5]|2[0-4]\d|[0-1]?\d?\d)(\.(25[0-5]|2[0-4]\d|[0-1]?\d?\d)){3}$)' -''' - ")", - variable('default_uri_validator') - ..type = 'var' - ..isPublic = false - ..init = ''' -(String uri) { - try { - final result = Uri.parse(uri); - if(result.path.startsWith('//')) return false; - return true; - } catch(e) { - return false; - } -}''', - variable('hostname_re') - ..isPublic = false - ..type = 'RegExp' - ..init = "new RegExp(\n" - r''' - r'^(?=.{1,255}$)' - r'[0-9A-Za-z](?:(?:[0-9A-Za-z]|-){0,61}[0-9A-Za-z])?' - r'(?:\.[0-9A-Za-z](?:(?:[0-9A-Za-z]|-){0,61}[0-9A-Za-z])?)*\.?$' -''' - ")", - variable('uri_validator') - ..isPublic = false - ..type = 'var' - ..init = '_defaultUriValidator', - ] - ..classes = [ - class_('validator') - ..defaultMemberAccess = IA - ..doc = 'Initialized with schema, validates instances against it' - ..members = [ - member('root_schema') - ..type = 'Schema' - ..ctors = [''], - member('errors') - ..type = 'List' - ..access = RO - ..classInit = '[]', - member('report_multiple_errors') - ..type = 'bool', - ], - ] - ] - ]; - ebisu.generate(); -} diff --git a/example/from_json/movie_sample.dart b/example/from_json/movie_sample.dart index d2eac747..b57d4fb8 100644 --- a/example/from_json/movie_sample.dart +++ b/example/from_json/movie_sample.dart @@ -1,4 +1,41 @@ #!/usr/bin/env dart +// Copyright 2013-2018 Workiva Inc. +// +// Licensed under the Boost Software License (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.boost.org/LICENSE_1_0.txt +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// +// This software or document includes material copied from or derived +// from JSON-Schema-Test-Suite (https://github.com/json-schema-org/JSON-Schema-Test-Suite), +// Copyright (c) 2012 Julian Berman, which is licensed under the following terms: +// +// Copyright (c) 2012 Julian Berman +// +// 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. import "package:json_schema/json_schema.dart"; import "package:logging/logging.dart"; @@ -13,54 +50,44 @@ main() { // Define schema in code ////////////////////////////////////////////////////////////////////// var movieSchema = { - "title" : "movie data", - "additionalProperties" : false, - "required" : [ "movies" ], - "properties" : { - "movies" : { r"$ref" : "#/definitions/movie_map" } + "title": "movie data", + "additionalProperties": false, + "required": ["movies"], + "properties": { + "movies": {r"$ref": "#/definitions/movie_map"} }, - "definitions" : { - "movie" : { + "definitions": { + "movie": { "additionalProperties": false, - "required" : [ "title", "year_made", "rating" ], + "required": ["title", "year_made", "rating"], "properties": { - "title" : { "type" : "string" }, - "year_made" : { "type" : "integer" }, - "rating" : { "type" : "integer" } + "title": {"type": "string"}, + "year_made": {"type": "integer"}, + "rating": {"type": "integer"} } }, - "movie_map" : { + "movie_map": { "type": "object", - "additionalProperties": { r"$ref": "#/definitions/movie" }, + "additionalProperties": {r"$ref": "#/definitions/movie"}, "default": {} } } }; var movies = { - "movies" : { - "the mission" : { - "title":"The Mission", - "year_made":1986, - "rating":5 - }, - "troll 2" : { - "title":"Troll 2", - "year_made":1990, - "rating":2 - } + "movies": { + "the mission": {"title": "The Mission", "year_made": 1986, "rating": 5}, + "troll 2": {"title": "Troll 2", "year_made": 1990, "rating": 2} } }; - Schema.createSchema(movieSchema) - .then((schema) { - var validator = new Validator(schema); - bool validates = validator.validate(movies); - if(!validates) { - print("Errors: ${validator.errors}"); - } else { - print('$movies:\nvalidates!'); - } - }); - + Schema.createSchema(movieSchema).then((schema) { + var validator = new Validator(schema); + bool validates = validator.validate(movies); + if (!validates) { + print("Errors: ${validator.errors}"); + } else { + print('$movies:\nvalidates!'); + } + }); } diff --git a/example/from_json/validate_json_from_data.dart b/example/from_json/validate_json_from_data.dart index 6640c080..38d032ee 100644 --- a/example/from_json/validate_json_from_data.dart +++ b/example/from_json/validate_json_from_data.dart @@ -1,30 +1,61 @@ #!/usr/bin/env dart +// Copyright 2013-2018 Workiva Inc. +// +// Licensed under the Boost Software License (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.boost.org/LICENSE_1_0.txt +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// +// This software or document includes material copied from or derived +// from JSON-Schema-Test-Suite (https://github.com/json-schema-org/JSON-Schema-Test-Suite), +// Copyright (c) 2012 Julian Berman, which is licensed under the following terms: +// +// Copyright (c) 2012 Julian Berman +// +// 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. import "package:json_schema/json_schema.dart"; import "package:logging/logging.dart"; main() { - - Logger.root.onRecord.listen((LogRecord rec) => - print('${rec.level.name}: ${rec.time}: ${rec.message}')); + Logger.root.onRecord.listen((LogRecord rec) => print('${rec.level.name}: ${rec.time}: ${rec.message}')); Logger.root.level = Level.SHOUT; ////////////////////////////////////////////////////////////////////// // Define schema in code ////////////////////////////////////////////////////////////////////// - var mustBeIntegerSchema = { - "type" : "integer" - }; + var mustBeIntegerSchema = {"type": "integer"}; var n = 3; var decimals = 3.14; var str = 'hi'; - Schema.createSchema(mustBeIntegerSchema) - .then((schema) { - print('$n => ${schema.validate(n)}'); - print('$decimals => ${schema.validate(decimals)}'); - print('$str => ${schema.validate(str)}'); - }); - + Schema.createSchema(mustBeIntegerSchema).then((schema) { + print('$n => ${schema.validate(n)}'); + print('$decimals => ${schema.validate(decimals)}'); + print('$str => ${schema.validate(str)}'); + }); } diff --git a/example/from_url/validate_instance_from_url.dart b/example/from_url/validate_instance_from_url.dart index a9a29345..67b4d0ca 100644 --- a/example/from_url/validate_instance_from_url.dart +++ b/example/from_url/validate_instance_from_url.dart @@ -1,45 +1,76 @@ #!/usr/bin/env dart +// Copyright 2013-2018 Workiva Inc. +// +// Licensed under the Boost Software License (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.boost.org/LICENSE_1_0.txt +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// +// This software or document includes material copied from or derived +// from JSON-Schema-Test-Suite (https://github.com/json-schema-org/JSON-Schema-Test-Suite), +// Copyright (c) 2012 Julian Berman, which is licensed under the following terms: +// +// Copyright (c) 2012 Julian Berman +// +// 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. import "dart:convert" as convert; import "package:json_schema/json_schema.dart"; import "package:logging/logging.dart"; main() { - - Logger.root.onRecord.listen((LogRecord rec) => - print('${rec.level.name}: ${rec.time}: ${rec.message}')); + Logger.root.onRecord.listen((LogRecord rec) => print('${rec.level.name}: ${rec.time}: ${rec.message}')); Logger.root.level = Level.SHOUT; ////////////////////////////////////////////////////////////////////// // Pull in schema from web ////////////////////////////////////////////////////////////////////// String url = "http://json-schema.org/draft-04/schema"; - Schema.createSchemaFromUrl(url) - .then((Schema schema) { - - // TODO: Figure out the redirect issues here - if(false) { - print('''Does schema validate itself? - ${schema.validate(schema.schemaMap)}'''); - } + Schema.createSchemaFromUrl(url).then((Schema schema) { + // TODO: Figure out the redirect issues here + // if(false) { + // print('''Does schema validate itself? + // ${schema.validate(schema.schemaMap)}'''); + // } - var validSchema = { "type" : "integer" }; - print('''Does schema validate valid schema $validSchema? + var validSchema = {"type": "integer"}; + print('''Does schema validate valid schema $validSchema? ${schema.validate(validSchema)}'''); - var invalidSchema = { "type" : "nibble" }; - print('''Does schema validate invalid schema $invalidSchema? + var invalidSchema = {"type": "nibble"}; + print('''Does schema validate invalid schema $invalidSchema? ${schema.validate(invalidSchema)}'''); - - }); + }); ////////////////////////////////////////////////////////////////////// // Pull in schema from file in current directory ////////////////////////////////////////////////////////////////////// url = "grades_schema.json"; - Schema.createSchemaFromUrl(url) - .then((schema) { - var grades = convert.JSON.decode(''' + Schema.createSchemaFromUrl(url).then((schema) { + var grades = convert.JSON.decode(''' { "semesters": [ { @@ -64,7 +95,7 @@ main() { ] }'''); - print('''Does grades schema validate $grades + print('''Does grades schema validate $grades ${schema.validate(grades)}'''); - }); + }); } diff --git a/lib/json_schema.dart b/lib/json_schema.dart index a5fcd994..ed498459 100644 --- a/lib/json_schema.dart +++ b/lib/json_schema.dart @@ -1,3 +1,41 @@ +// Copyright 2013-2018 Workiva Inc. +// +// Licensed under the Boost Software License (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.boost.org/LICENSE_1_0.txt +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// +// This software or document includes material copied from or derived +// from JSON-Schema-Test-Suite (https://github.com/json-schema-org/JSON-Schema-Test-Suite), +// Copyright (c) 2012 Julian Berman, which is licensed under the following terms: +// +// Copyright (c) 2012 Julian Berman +// +// 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. + /// Support for validating json instances against a json schema library json_schema.json_schema; @@ -31,8 +69,7 @@ class SchemaType implements Comparable { static const SchemaType STRING = const SchemaType._(6); - static List get values => - const [ARRAY, BOOLEAN, INTEGER, NUMBER, NULL, OBJECT, STRING]; + static List get values => const [ARRAY, BOOLEAN, INTEGER, NUMBER, NULL, OBJECT, STRING]; final int value; diff --git a/lib/schema_dot.dart b/lib/schema_dot.dart index 90d8c9d2..487bcdc0 100644 --- a/lib/schema_dot.dart +++ b/lib/schema_dot.dart @@ -1,3 +1,41 @@ +// Copyright 2013-2018 Workiva Inc. +// +// Licensed under the Boost Software License (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.boost.org/LICENSE_1_0.txt +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// +// This software or document includes material copied from or derived +// from JSON-Schema-Test-Suite (https://github.com/json-schema-org/JSON-Schema-Test-Suite), +// Copyright (c) 2012 Julian Berman, which is licensed under the following terms: +// +// Copyright (c) 2012 Julian Berman +// +// 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. + /// Functionality to create Graphviz input dot file from schema library json_schema.schema_dot; @@ -51,14 +89,11 @@ class SchemaNode { var schemaTypeList = schema.schemaTypeList; if (schemaTypeList == null) { if (schema.oneOf.length > 0) { - result = - "oneOf:${schema.oneOf.map((schema) => schemaType(schema)).toList()}"; + result = "oneOf:${schema.oneOf.map((schema) => schemaType(schema)).toList()}"; } else if (schema.anyOf.length > 0) { - result = - "anyOf:${schema.anyOf.map((schema) => schemaType(schema)).toList()}"; + result = "anyOf:${schema.anyOf.map((schema) => schemaType(schema)).toList()}"; } else if (schema.allOf.length > 0) { - result = - "allOf:${schema.allOf.map((schema) => schemaType(schema)).toList()}"; + result = "allOf:${schema.allOf.map((schema) => schemaType(schema)).toList()}"; } else if (schema.defaultValue != null) { result = "default=${schema.defaultValue}"; } else if (schema.ref != null) { @@ -151,8 +186,7 @@ class SchemaNode { schema.anyOf.forEach((anyOfSchema) { String port = "${i++}"; makeSchemaLink(port, schema, anyOfSchema); - anyOf.add(wrap(abbreviatedString("${schemaType(anyOfSchema)}", 30), - color: 'grey', port: port)); + anyOf.add(wrap(abbreviatedString("${schemaType(anyOfSchema)}", 30), color: 'grey', port: port)); }); } return anyOf; @@ -166,8 +200,7 @@ class SchemaNode { schema.oneOf.forEach((oneOfSchema) { String port = "${i++}"; makeSchemaLink(port, schema, oneOfSchema); - oneOf.add(wrap(abbreviatedString("${schemaType(oneOfSchema)}", 30), - color: 'grey', port: port)); + oneOf.add(wrap(abbreviatedString("${schemaType(oneOfSchema)}", 30), color: 'grey', port: port)); }); } return oneOf; @@ -181,8 +214,7 @@ class SchemaNode { schema.allOf.forEach((allOfSchema) { String port = "${i++}"; makeSchemaLink(port, schema, allOfSchema); - allOf.add(wrap(abbreviatedString("${schemaType(allOfSchema)}", 30), - color: 'grey', port: port)); + allOf.add(wrap(abbreviatedString("${schemaType(allOfSchema)}", 30), color: 'grey', port: port)); }); } return allOf; @@ -213,9 +245,7 @@ class SchemaNode { makeSchemaPort(String port, Schema schema) => '"${schema.path}":"$port"'; makeSchemaLink(String port, Schema src, Schema target) { - if (schemaShown(target)) - links.add( - '${makeSchemaPort(port, src)} -> ${makeSchemaPort("@path", target)}'); + if (schemaShown(target)) links.add('${makeSchemaPort(port, src)} -> ${makeSchemaPort("@path", target)}'); } List get additionalPropertiesSchema { @@ -225,8 +255,7 @@ class SchemaNode { result.add(wrap('Additional Properties', color: 'lemonchiffon')); String port = "mustBe"; makeSchemaLink(port, schema, other); - result.add(wrapRowDistinct('Must Be: ', - abbreviatedString(schemaType(other).toString(), 30), port)); + result.add(wrapRowDistinct('Must Be: ', abbreviatedString(schemaType(other).toString(), 30), port)); } return result; } @@ -242,14 +271,11 @@ class SchemaNode { String port = "@$prop"; if (schemaShown(propertySchema)) { makeSchemaLink(port, schema, propertySchema); - } else if (propertySchema.items is Schema && - schemaShown(propertySchema.items)) { + } else if (propertySchema.items is Schema && schemaShown(propertySchema.items)) { makeSchemaLink(port, schema, propertySchema.items); } props.add(wrapRowDistinct( - "$requiredPrefix$prop", - abbreviatedString(schemaType(propertySchema).toString(), 30), - port)); + "$requiredPrefix$prop", abbreviatedString(schemaType(propertySchema).toString(), 30), port)); }); } return props; @@ -258,8 +284,8 @@ class SchemaNode { List get definitionEntries { List definitions = []; if (schema.definitions.length > 0) { - definitions.add( - 'Definitions'); + definitions + .add('Definitions'); var sortedDefinitions = new List.from(schema.definitions.keys)..sort(); sortedDefinitions.forEach((key) { definitions.add(wrapRowDistinct(key, '', "${schema.path}@$key")); @@ -275,13 +301,9 @@ class SchemaNode { String wrapRowDistinct(String first, String second, [String port = '']) => '$first$first$second'; - String get title => schema.title != null - ? abbreviatedString("title=${schema.title}", 30) - : null; + String get title => schema.title != null ? abbreviatedString("title=${schema.title}", 30) : null; - String get description => schema.description != null - ? abbreviatedString("descr=${schema.description}", 30) - : null; + String get description => schema.description != null ? abbreviatedString("descr=${schema.description}", 30) : null; String abbreviatedString(String s, [int len = 15]) { if (s == null) return s; diff --git a/lib/src/json_schema/schema.dart b/lib/src/json_schema/schema.dart index 82700714..3fcf953f 100644 --- a/lib/src/json_schema/schema.dart +++ b/lib/src/json_schema/schema.dart @@ -1,3 +1,41 @@ +// Copyright 2013-2018 Workiva Inc. +// +// Licensed under the Boost Software License (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.boost.org/LICENSE_1_0.txt +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// +// This software or document includes material copied from or derived +// from JSON-Schema-Test-Suite (https://github.com/json-schema-org/JSON-Schema-Test-Suite), +// Copyright (c) 2012 Julian Berman, which is licensed under the following terms: +// +// Copyright (c) 2012 Julian Berman +// +// 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. + part of json_schema.json_schema; /// Constructed with a json schema, either as string or Map. Validation of @@ -75,10 +113,7 @@ class Schema { request.followRedirects = true; return request.close(); }).then((HttpClientResponse response) { - return response - .transform(new convert.Utf8Decoder()) - .join() - .then((schemaText) { + return response.transform(new convert.Utf8Decoder()).join().then((schemaText) { Map map = convert.JSON.decode(schemaText); return createSchema(map); }); @@ -88,15 +123,13 @@ class Schema { .readAsString() .then((text) => createSchema(convert.JSON.decode(text))); } else { - throw new FormatException( - "Url schemd must be http, file, or empty: $schemaUrl"); + throw new FormatException("Url schemd must be http, file, or empty: $schemaUrl"); } } /// Create a schema from a [data] /// Typically [data] is result of JSON.decode(jsonSchemaString) - static Future createSchema(Map data) => - new Schema._fromRootMap(data)._thisCompleter.future; + static Future createSchema(Map data) => new Schema._fromRootMap(data)._thisCompleter.future; /// Validate [instance] against this schema bool validate(dynamic instance) => new Validator(this).validate(instance); @@ -104,8 +137,7 @@ class Schema { bool get exclusiveMaximum => _exclusiveMaximum == null || _exclusiveMaximum; bool get exclusiveMinimum => _exclusiveMinimum == null || _exclusiveMinimum; - bool propertyRequired(String property) => - _requiredProperties != null && _requiredProperties.contains(property); + bool propertyRequired(String property) => _requiredProperties != null && _requiredProperties.contains(property); /// Given path, follow all references to an end path pointing to schema String endPath(String path) { @@ -124,20 +156,13 @@ class Schema { return _refMap[path]; } - FormatException _boolError(String key, dynamic instance) => - _error("$key must be boolean: $instance"); - FormatException _numError(String key, dynamic instance) => - _error("$key must be num: $instance"); - FormatException _intError(String key, dynamic instance) => - _error("$key must be int: $instance"); - FormatException _stringError(String key, dynamic instance) => - _error("$key must be string: $instance"); - FormatException _objectError(String key, dynamic instance) => - _error("$key must be object: $instance"); - FormatException _arrayError(String key, dynamic instance) => - _error("$key must be array: $instance"); - FormatException _schemaError(String key, dynamic instance) => - _error("$key must be valid schema object: $instance"); + FormatException _boolError(String key, dynamic instance) => _error("$key must be boolean: $instance"); + FormatException _numError(String key, dynamic instance) => _error("$key must be num: $instance"); + FormatException _intError(String key, dynamic instance) => _error("$key must be int: $instance"); + FormatException _stringError(String key, dynamic instance) => _error("$key must be string: $instance"); + FormatException _objectError(String key, dynamic instance) => _error("$key must be object: $instance"); + FormatException _arrayError(String key, dynamic instance) => _error("$key must be array: $instance"); + FormatException _schemaError(String key, dynamic instance) => _error("$key must be valid schema object: $instance"); FormatException _error(String msg) { msg = "$_path: $msg"; @@ -188,10 +213,8 @@ class Schema { _exclusiveMinimum = value; } - _getMaxLength(dynamic value) => - _maxLength = _requireNonNegativeInt('maxLength', value); - _getMinLength(dynamic value) => - _minLength = _requireNonNegativeInt('minLength', value); + _getMaxLength(dynamic value) => _maxLength = _requireNonNegativeInt('maxLength', value); + _getMinLength(dynamic value) => _minLength = _requireNonNegativeInt('minLength', value); _getPattern(dynamic value) { if (value is! String) throw _stringError("pattern", value); @@ -209,10 +232,8 @@ class Schema { _getProperties(dynamic value) { if (value is Map) { - value.forEach((property, subSchema) => _makeSchema( - "$_path/properties/$property", - subSchema, - (rhs) => _properties[property] = rhs)); + value.forEach((property, subSchema) => + _makeSchema("$_path/properties/$property", subSchema, (rhs) => _properties[property] = rhs)); } else { throw _objectError("properties", value); } @@ -225,8 +246,7 @@ class Schema { int index = 0; _itemsList = new List(value.length); for (int i = 0; i < value.length; i++) { - _makeSchema( - "$_path/items/${index++}", value[i], (rhs) => _itemsList[i] = rhs); + _makeSchema("$_path/items/${index++}", value[i], (rhs) => _itemsList[i] = rhs); } } else { throw _error("items must be object or array: $value"); @@ -237,17 +257,14 @@ class Schema { if (value is bool) { _additionalItems = value; } else if (value is Map) { - _makeSchema( - "$_path/additionalItems", value, (rhs) => _additionalItems = rhs); + _makeSchema("$_path/additionalItems", value, (rhs) => _additionalItems = rhs); } else { throw _error("additionalItems must be boolean or object: $value"); } } - _getMaxItems(dynamic value) => - _maxItems = _requireNonNegativeInt('maxItems', value); - _getMinItems(dynamic value) => - _minItems = _requireNonNegativeInt('minItems', value); + _getMaxItems(dynamic value) => _maxItems = _requireNonNegativeInt('maxItems', value); + _getMinItems(dynamic value) => _minItems = _requireNonNegativeInt('minItems', value); _getUniqueItems(dynamic value) { if (value is! bool) throw _boolError("uniqueItems", value); _uniqueItems = value; @@ -255,50 +272,42 @@ class Schema { _getRequired(dynamic value) { if (value is! List) throw _arrayError("required", value); - if (value.length == 0) - throw _error("required must be a non-empty array: $value"); + if (value.length == 0) throw _error("required must be a non-empty array: $value"); _requiredProperties = new List.from(value); } - _getMaxProperties(dynamic value) => - _maxProperties = _requireNonNegativeInt('maxProperties', value); - _getMinProperties(dynamic value) => - _minProperties = _requireNonNegativeInt('minProperties', value); + _getMaxProperties(dynamic value) => _maxProperties = _requireNonNegativeInt('maxProperties', value); + _getMinProperties(dynamic value) => _minProperties = _requireNonNegativeInt('minProperties', value); _getAdditionalProperties(dynamic value) { if (value is bool) { _additionalProperties = value; } else if (value is Map) { - _makeSchema("$_path/additionalProperties", value, - (rhs) => _additionalPropertiesSchema = rhs); + _makeSchema("$_path/additionalProperties", value, (rhs) => _additionalPropertiesSchema = rhs); } else { - throw _error( - "additionalProperties must be a bool or valid schema object: $value"); + throw _error("additionalProperties must be a bool or valid schema object: $value"); } } _getPatternProperties(dynamic value) { if (value is! Map) throw _objectError("patternProperties", value); - value.forEach((k, v) => _makeSchema("$_path/patternProperties/$k", v, - (rhs) => _patternProperties[new RegExp(k)] = rhs)); + value.forEach( + (k, v) => _makeSchema("$_path/patternProperties/$k", v, (rhs) => _patternProperties[new RegExp(k)] = rhs)); } _getDependencies(dynamic value) { if (value is Map) { value.forEach((k, v) { if (v is Map) { - _makeSchema("$_path/dependencies/$k", v, - (rhs) => _schemaDependencies[k] = rhs); + _makeSchema("$_path/dependencies/$k", v, (rhs) => _schemaDependencies[k] = rhs); } else if (v is List) { - if (v.length == 0) - throw _error("property dependencies must be non-empty array"); + if (v.length == 0) throw _error("property dependencies must be non-empty array"); Set uniqueDeps = new Set(); v.forEach((propDep) { if (propDep is! String) throw _stringError("propertyDependency", v); - if (uniqueDeps.contains(propDep)) - throw _error("property dependencies must be unique: $v"); + if (uniqueDeps.contains(propDep)) throw _error("property dependencies must be unique: $v"); _propertyDependencies.putIfAbsent(k, () => []).add(propDep); uniqueDeps.add(propDep); @@ -314,13 +323,11 @@ class Schema { _getEnum(dynamic value) { if (value is List) { - if (value.length == 0) - throw _error("enum must be a non-empty array: $value"); + if (value.length == 0) throw _error("enum must be a non-empty array: $value"); int i = 0; value.forEach((v) { for (int j = i + 1; j < value.length; j++) { - if (_jsonEqual(value[i], value[j])) - throw _error("enum values must be unique: $value [$i]==[$j]"); + if (_jsonEqual(value[i], value[j])) throw _error("enum values must be unique: $value [$i]==[$j]"); } i++; _enumValues.add(v); @@ -352,12 +359,9 @@ class Schema { } } - _getAllOf(dynamic value) => - _requireListOfSchema("allOf", value, (schema) => _allOf.add(schema)); - _getAnyOf(dynamic value) => - _requireListOfSchema("anyOf", value, (schema) => _anyOf.add(schema)); - _getOneOf(dynamic value) => - _requireListOfSchema("oneOf", value, (schema) => _oneOf.add(schema)); + _getAllOf(dynamic value) => _requireListOfSchema("allOf", value, (schema) => _allOf.add(schema)); + _getAnyOf(dynamic value) => _requireListOfSchema("anyOf", value, (schema) => _anyOf.add(schema)); + _getOneOf(dynamic value) => _requireListOfSchema("oneOf", value, (schema) => _oneOf.add(schema)); _getNot(dynamic value) { if (value is Map) { _makeSchema("$_path/not", value, (rhs) => _notSchema = rhs); @@ -368,8 +372,7 @@ class Schema { _getDefinitions(dynamic value) { if (value is Map) { - value.forEach((k, v) => _makeSchema( - "$_path/definitions/$k", v, (rhs) => _definitions[k] = rhs)); + value.forEach((k, v) => _makeSchema("$_path/definitions/$k", v, (rhs) => _definitions[k] = rhs)); } else { throw _objectError("definition", value); } @@ -380,8 +383,7 @@ class Schema { _ref = value; if (_ref.length == 0) throw _error("\$ref must be non-empty string"); if (_ref[0] != '#') { - var refSchemaFuture = createSchemaFromUrl(_ref) - .then((schema) => _addSchema(_ref, schema)); + var refSchemaFuture = createSchemaFromUrl(_ref).then((schema) => _addSchema(_ref, schema)); _retrievalRequests.add(refSchemaFuture); } } else { @@ -413,8 +415,7 @@ class Schema { } _getTitle(dynamic value) => _title = _requireString("title", value); - _getDescription(dynamic value) => - _description = _requireString("description", value); + _getDescription(dynamic value) => _description = _requireString("description", value); _getDefault(dynamic value) => _defaultValue = value; _getFormat(dynamic value) { _format = _requireString("format", value); @@ -473,18 +474,14 @@ class Schema { } }); - if (_exclusiveMinimum != null && _minimum == null) - throw _error("exclusiveMinimum requires minimum"); + if (_exclusiveMinimum != null && _minimum == null) throw _error("exclusiveMinimum requires minimum"); - if (_exclusiveMaximum != null && _maximum == null) - throw _error("exclusiveMaximum requires maximum"); + if (_exclusiveMaximum != null && _maximum == null) throw _error("exclusiveMaximum requires maximum"); if (_root == this) { _schemaAssignments.forEach((assignment) => assignment()); if (_retrievalRequests.isNotEmpty) { - Future - .wait(_retrievalRequests) - .then((_) => _thisCompleter.complete(_resolvePath('#'))); + Future.wait(_retrievalRequests).then((_) => _thisCompleter.complete(_resolvePath('#'))); } else { _thisCompleter.complete(_resolvePath('#')); } @@ -512,8 +509,7 @@ class Schema { } String _endPath(String path) { - if (_pathsEncountered.contains(path)) - throw _error("Encountered path cycle ${_pathsEncountered}, adding $path"); + if (_pathsEncountered.contains(path)) throw _error("Encountered path cycle ${_pathsEncountered}, adding $path"); var referredTo = _schemaRefs[path]; if (referredTo == null) { @@ -529,8 +525,7 @@ class Schema { Schema result = _refMap[path]; if (result == null) { var schema = _freeFormMap[path]; - if (schema is! Map) - throw _schemaError("free-form property $original at $path", schema); + if (schema is! Map) throw _schemaError("free-form property $original at $path", schema); return new Schema._fromMap(_root, schema, path); } return result; @@ -552,8 +547,7 @@ class Schema { return false; } - static String _normalizePath(String path) => - path.replaceAll('~', '~0').replaceAll('/', '~1').replaceAll('%', '%25'); + static String _normalizePath(String path) => path.replaceAll('~', '~0').replaceAll('/', '~1').replaceAll('%', '%25'); Schema _createSubSchema(dynamic schemaDefinition, String path) { assert(!_schemaRefs.containsKey(path)); diff --git a/lib/src/json_schema/validator.dart b/lib/src/json_schema/validator.dart index 93e3528c..5dedd7df 100644 --- a/lib/src/json_schema/validator.dart +++ b/lib/src/json_schema/validator.dart @@ -1,3 +1,41 @@ +// Copyright 2013-2018 Workiva Inc. +// +// Licensed under the Boost Software License (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.boost.org/LICENSE_1_0.txt +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// +// This software or document includes material copied from or derived +// from JSON-Schema-Test-Suite (https://github.com/json-schema-org/JSON-Schema-Test-Suite), +// Copyright (c) 2012 Julian Berman, which is licensed under the following terms: +// +// Copyright (c) 2012 Julian Berman +// +// 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. + part of json_schema.json_schema; /// Initialized with schema, validates instances against it @@ -10,8 +48,7 @@ class Validator { /// Validate the [instance] against the this validator's schema bool validate(dynamic instance, [bool reportMultipleErrors = false]) { - _logger - .info("Validating ${instance.runtimeType}:$instance on ${_rootSchema}"); + _logger.info("Validating ${instance.runtimeType}:$instance on ${_rootSchema}"); _reportMultipleErrors = reportMultipleErrors; _errors = []; @@ -194,8 +231,7 @@ class Validator { void _validateAnyOf(Schema schema, instance) { if (!schema._anyOf.any((s) => new Validator(s).validate(instance))) { - _err( - "${schema._path}/anyOf: anyOf violated ($instance, ${schema._anyOf})"); + _err("${schema._path}/anyOf: anyOf violated ($instance, ${schema._anyOf})"); } } @@ -226,8 +262,7 @@ class Validator { break; case 'uri': { - var isValid = - (_uriValidator != null) ? _uriValidator : _defaultUriValidator; + var isValid = (_uriValidator != null) ? _uriValidator : _defaultUriValidator; if (!isValid(instance)) { _err("'uri' format not accepted $instance"); @@ -236,9 +271,7 @@ class Validator { break; case 'email': { - var isValid = (_emailValidator != null) - ? _emailValidator - : _defaultEmailValidator; + var isValid = (_emailValidator != null) ? _emailValidator : _defaultEmailValidator; if (!isValid(instance)) { _err("'email' format not accepted $instance"); @@ -274,8 +307,7 @@ class Validator { } void _objectPropertyValidation(Schema schema, Map instance) { - bool propMustValidate = - schema._additionalProperties != null && !schema._additionalProperties; + bool propMustValidate = schema._additionalProperties != null && !schema._additionalProperties; instance.forEach((k, v) { bool propCovered = false; @@ -329,27 +361,22 @@ class Validator { int minProps = schema._minProperties; int maxProps = schema._maxProperties; if (numProps < minProps) { - _err( - "${schema._path}: minProperties violated (${numProps} < ${minProps})"); + _err("${schema._path}: minProperties violated (${numProps} < ${minProps})"); } else if (maxProps != null && numProps > maxProps) { - _err( - "${schema._path}: maxProperties violated (${numProps} > ${maxProps})"); + _err("${schema._path}: maxProperties violated (${numProps} > ${maxProps})"); } if (schema._requiredProperties != null) { schema._requiredProperties.forEach((prop) { if (!instance.containsKey(prop)) { - _err( - "${schema._path}: required prop missing: ${prop} from $instance"); + _err("${schema._path}: required prop missing: ${prop} from $instance"); } }); } _objectPropertyValidation(schema, instance); - if (schema._propertyDependencies != null) - _propertyDependenciesValidation(schema, instance); + if (schema._propertyDependencies != null) _propertyDependenciesValidation(schema, instance); - if (schema._schemaDependencies != null) - _schemaDependenciesValidation(schema, instance); + if (schema._schemaDependencies != null) _schemaDependenciesValidation(schema, instance); } void _validate(Schema schema, dynamic instance) { @@ -385,8 +412,7 @@ class Validator { RegExp _emailRe = new RegExp(r'^[_A-Za-z0-9-\+]+(\.[_A-Za-z0-9-]+)*' r'@' r'[A-Za-z0-9-]+(\.[A-Za-z0-9]+)*(\.[A-Za-z]{2,})$'); -var _defaultEmailValidator = - (String email) => _emailRe.firstMatch(email) != null; +var _defaultEmailValidator = (String email) => _emailRe.firstMatch(email) != null; var _emailValidator = _defaultEmailValidator; RegExp _ipv4Re = new RegExp(r'^(\d|[1-9]\d|1\d\d|2([0-4]\d|5[0-5]))\.' r'(\d|[1-9]\d|1\d\d|2([0-4]\d|5[0-5]))\.' @@ -419,6 +445,7 @@ bool _defaultUriValidatorImpl(String uri) { return false; } } + RegExp _hostnameRe = new RegExp(r'^(?=.{1,255}$)' r'[0-9A-Za-z](?:(?:[0-9A-Za-z]|-){0,61}[0-9A-Za-z])?' r'(?:\.[0-9A-Za-z](?:(?:[0-9A-Za-z]|-){0,61}[0-9A-Za-z])?)*\.?$'); diff --git a/pubspec.yaml b/pubspec.yaml index 277557b6..a6c04bd0 100644 --- a/pubspec.yaml +++ b/pubspec.yaml @@ -1,39 +1,24 @@ name: json_schema version: 1.0.7 -author: Daniel Davidson -homepage: https://github.com/patefacio/json_schema + +authors: + - Michael Carter + - Daniel Davidson + +homepage: https://github.com/workiva/json_schema description: > Provide support for validating instances against json schema environment: - sdk: '>=1.8.2 <2.0.0' + sdk: ">=1.8.2 <2.0.0" dependencies: - -# custom - - path: "^1.3.0" - logging: ">=0.9.3<0.12.0" args: ">=0.11.0 <2.0.0" - -# end + logging: ">=0.9.3<0.12.0" + path: "^1.3.0" dev_dependencies: - -# custom - - test: "^0.12.13" - yaml: "^2.1.0" coverage: ">=0.7.6" - -# end - -dependency_overrides: -# custom - -# end - -transformers: - -# custom -# end - + dart_dev: any + dart_style: any + dependency_validator: ^1.0.0 + test: "^0.12.13" diff --git a/smithy.yaml b/smithy.yaml new file mode 100644 index 00000000..b9debae5 --- /dev/null +++ b/smithy.yaml @@ -0,0 +1,12 @@ +project: dart +language: dart + +# dart 1.24.2 +runner_image: drydock-prod.workiva.net/workiva/smithy-runner-generator:179735 + +script: + - pub get + +artifacts: + build: + - ./pubspec.lock \ No newline at end of file diff --git a/test/cover.dart b/test/cover.dart deleted file mode 100644 index b8bfca76..00000000 --- a/test/cover.dart +++ /dev/null @@ -1,33 +0,0 @@ -import 'dart:io'; -import 'package:logging/logging.dart'; -import 'package:coverage/coverage.dart'; -import 'runner.dart' as runner; -import 'package:path/path.dart'; - - -main() async { - Logger.root.level = Level.OFF; - Logger.root.onRecord.listen((LogRecord rec) { - print('${rec.level.name}: ${rec.time}: ${rec.message}'); - }); - - final results = await runAndCollect('runner.dart'); - - final untested = {}; - results['coverage'].forEach((var entry) { - final source = entry['source']; - if(!source.contains('package:json_schema')) return; - print(source); - final hits = entry['hits']; - final hitCount = hits.length/2; - for(int i=0; i []).add(lineNumber); - } - } - }); - - print(untested); -} diff --git a/test/run.sh b/test/run.sh deleted file mode 100755 index ce81fbd9..00000000 --- a/test/run.sh +++ /dev/null @@ -1,3 +0,0 @@ -#!/bin/bash -dart tool/hop_runner.dart analyze_lib -dart test/runner.dart diff --git a/test/runner.dart b/test/runner.dart deleted file mode 100644 index 5614b9dc..00000000 --- a/test/runner.dart +++ /dev/null @@ -1,13 +0,0 @@ -import 'package:logging/logging.dart'; -import 'test_invalid_schemas.dart' as test_invalid_schemas; -import 'test_validation.dart' as test_validation; - -void main() { - Logger.root.level = Level.OFF; - Logger.root.onRecord.listen((LogRecord rec) { - print('${rec.level.name}: ${rec.time}: ${rec.message}'); - }); - - test_invalid_schemas.main(null); - test_validation.main(null); -} diff --git a/test/test_invalid_schemas.dart b/test/test_invalid_schemas.dart deleted file mode 100644 index b349c70c..00000000 --- a/test/test_invalid_schemas.dart +++ /dev/null @@ -1,65 +0,0 @@ -library json_schema.test_invalid_schemas; - -import 'dart:convert' as convert; -import 'dart:io'; -import 'package:json_schema/json_schema.dart'; -import 'package:logging/logging.dart'; -import 'package:path/path.dart' as path; -import 'package:test/test.dart'; - -// custom - -// end - -final Logger _logger = new Logger('test_invalid_schemas'); - -// custom -// end - -void main([List args]) { - if (args?.isEmpty ?? false) { - Logger.root.onRecord.listen( - (LogRecord r) => print("${r.loggerName} [${r.level}]:\t${r.message}")); - Logger.root.level = Level.OFF; - } -// custom
- - String here = - path.dirname(path.dirname(path.absolute(Platform.script.toFilePath()))); - - Directory testSuiteFolder = new Directory("${here}/test/invalid_schemas"); - - testSuiteFolder.listSync().forEach((testEntry) { - String shortName = path.basename(testEntry.path); - group("Invalid schema: ${shortName}", () { - if (testEntry is File) { - List tests = - convert.JSON.decode((testEntry as File).readAsStringSync()); - tests.forEach((testObject) { - var schemaData = testObject["schema"]; - var description = testObject["description"]; - test(description, () { - var gotException = (e) { - _logger.info("Caught expected $e"); - if (!(e is FormatException)) { - _logger.info('${shortName} wtf it is a ${e.runtimeType}'); - } - expect(e is FormatException, true); - }; - var ensureInvalid = expectAsync(gotException); - - try { - Schema.createSchema(schemaData).then(ensureInvalid); - } on FormatException catch (e) { - ensureInvalid(e); - } catch (e) { - ensureInvalid(e); - } - }); - }); - } - }); - }); - -// end
-} diff --git a/test/test_validation.dart b/test/test_validation.dart deleted file mode 100644 index 5865c1ab..00000000 --- a/test/test_validation.dart +++ /dev/null @@ -1,93 +0,0 @@ -library json_schema.test_validation; - -import 'dart:convert' as convert; -import 'dart:io'; -import 'package:json_schema/json_schema.dart'; -import 'package:logging/logging.dart'; -import 'package:path/path.dart' as path; -import 'package:test/test.dart'; - -// custom -// end - -final Logger _logger = new Logger('test_validation'); - -// custom -// end - -void main([List args]) { - if (args?.isEmpty ?? false) { - Logger.root.onRecord.listen( - (LogRecord r) => print("${r.loggerName} [${r.level}]:\t${r.message}")); - Logger.root.level = Level.OFF; - } -// custom
- - //////////////////////////////////////////////////////////////////////// - // Uncomment to see logging of excpetions - // Logger.root.onRecord.listen((LogRecord r) => - // print("${r.loggerName} [${r.level}]:\t${r.message}")); - - Logger.root.level = Level.OFF; - - String here = - path.dirname(path.dirname(path.absolute(Platform.script.toFilePath()))); - - Directory testSuiteFolder = new Directory( - "${here}/test/JSON-Schema-Test-Suite/tests/draft4/invalidSchemas"); - - testSuiteFolder = - new Directory("${here}/test/JSON-Schema-Test-Suite/tests/draft4"); - - var optionals = - new Directory(path.joinAll([testSuiteFolder.path, 'optional'])); - - var all = testSuiteFolder.listSync()..addAll(optionals.listSync()); - - all.forEach((testEntry) { - if (testEntry is File) { - group("Validations ${path.basename(testEntry.path)}", () { - // TODO: add these back or get replacements - // Skip these for now - reason shown - if ([ - 'refRemote.json', // seems to require webserver running to vend files - ].contains(path.basename(testEntry.path))) return; - - List tests = - convert.JSON.decode((testEntry as File).readAsStringSync()); - tests.forEach((testEntry) { - var schemaData = testEntry["schema"]; - var description = testEntry["description"]; - List validationTests = testEntry["tests"]; - - validationTests.forEach((validationTest) { - String validationDescription = validationTest["description"]; - test("${description} : ${validationDescription}", () { - var instance = validationTest["data"]; - bool validationResult; - bool expectedResult = validationTest["valid"]; - var checkResult = - expectAsync(() => expect(validationResult, expectedResult)); - Schema.createSchema(schemaData).then((schema) { - validationResult = schema.validate(instance); - checkResult(); - }); - }); - }); - }); - }); - } - }); - - test("Schema self validation", () { - // Pull in the official schema, verify description and then ensure - // that the schema satisfies the schema for schemas - String url = "http://json-schema.org/draft-04/schema"; - Schema.createSchemaFromUrl(url).then((schema) { - expect(schema.schemaMap["description"], "Core schema meta-schema"); - expect(schema.validate(schema.schemaMap), true); - }); - }); - -// end
-} diff --git a/test/unit/vm/generated_runner_test.dart b/test/unit/vm/generated_runner_test.dart new file mode 100644 index 00000000..43425ec9 --- /dev/null +++ b/test/unit/vm/generated_runner_test.dart @@ -0,0 +1,13 @@ +@TestOn('vm') +library test.unit.vm.generated_runner_test; + +// Generated by `pub run dart_dev gen-test-runner -d test/unit/vm -e Environment.vm --no-genHtml` + +import './json_schema/invalid_schemas_test.dart' as json_schema_invalid_schemas_test; +import './json_schema/validation_test.dart' as json_schema_validation_test; +import 'package:test/test.dart'; + +void main() { + json_schema_invalid_schemas_test.main(); + json_schema_validation_test.main(); +} \ No newline at end of file diff --git a/test/unit/vm/json_schema/invalid_schemas_test.dart b/test/unit/vm/json_schema/invalid_schemas_test.dart new file mode 100644 index 00000000..306cb0fd --- /dev/null +++ b/test/unit/vm/json_schema/invalid_schemas_test.dart @@ -0,0 +1,88 @@ +// Copyright 2013-2018 Workiva Inc. +// +// Licensed under the Boost Software License (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.boost.org/LICENSE_1_0.txt +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// +// This software or document includes material copied from or derived +// from JSON-Schema-Test-Suite (https://github.com/json-schema-org/JSON-Schema-Test-Suite), +// Copyright (c) 2012 Julian Berman, which is licensed under the following terms: +// +// Copyright (c) 2012 Julian Berman +// +// 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. + +library json_schema.test_invalid_schemas; + +import 'dart:convert' as convert; +import 'dart:io'; +import 'package:json_schema/json_schema.dart'; +import 'package:logging/logging.dart'; +import 'package:path/path.dart' as path; +import 'package:test/test.dart'; + +final Logger _logger = new Logger('test_invalid_schemas'); + +void main([List args]) { + if (args?.isEmpty ?? false) { + Logger.root.onRecord.listen((LogRecord r) => print("${r.loggerName} [${r.level}]:\t${r.message}")); + Logger.root.level = Level.OFF; + } + + Directory testSuiteFolder = new Directory("./test/invalid_schemas"); + + testSuiteFolder.listSync().forEach((testEntry) { + String shortName = path.basename(testEntry.path); + group("Invalid schema: ${shortName}", () { + if (testEntry is File) { + List tests = convert.JSON.decode((testEntry as File).readAsStringSync()); + tests.forEach((testObject) { + var schemaData = testObject["schema"]; + var description = testObject["description"]; + test(description, () { + var gotException = (e) { + _logger.info("Caught expected $e"); + if (!(e is FormatException)) { + _logger.info('${shortName} wtf it is a ${e.runtimeType}'); + } + expect(e is FormatException, true); + }; + var ensureInvalid = expectAsync1(gotException); + + try { + Schema.createSchema(schemaData).then(ensureInvalid); + } on FormatException catch (e) { + ensureInvalid(e); + } catch (e) { + ensureInvalid(e); + } + }); + }); + } + }); + }); +} diff --git a/test/unit/vm/json_schema/validation_test.dart b/test/unit/vm/json_schema/validation_test.dart new file mode 100644 index 00000000..b34b6b1b --- /dev/null +++ b/test/unit/vm/json_schema/validation_test.dart @@ -0,0 +1,122 @@ +// Copyright 2013-2018 Workiva Inc. +// +// Licensed under the Boost Software License (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.boost.org/LICENSE_1_0.txt +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// +// This software or document includes material copied from or derived +// from JSON-Schema-Test-Suite (https://github.com/json-schema-org/JSON-Schema-Test-Suite), +// Copyright (c) 2012 Julian Berman, which is licensed under the following terms: +// +// Copyright (c) 2012 Julian Berman +// +// 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. + +library json_schema.test_validation; + +import 'dart:convert' as convert; +import 'dart:io'; +import 'package:json_schema/json_schema.dart'; +import 'package:logging/logging.dart'; +import 'package:path/path.dart' as path; +import 'package:test/test.dart'; + +// custom +// end + +final Logger _logger = new Logger('test_validation'); + +// custom +// end + +void main([List args]) { + if (args?.isEmpty ?? false) { + Logger.root.onRecord.listen((LogRecord r) => print("${r.loggerName} [${r.level}]:\t${r.message}")); + Logger.root.level = Level.OFF; + } +// custom
+ + //////////////////////////////////////////////////////////////////////// + // Uncomment to see logging of exceptions + // Logger.root.onRecord.listen((LogRecord r) => + // print("${r.loggerName} [${r.level}]:\t${r.message}")); + + Logger.root.level = Level.OFF; + + Directory testSuiteFolder = new Directory("./test/JSON-Schema-Test-Suite/tests/draft4/invalidSchemas"); + + testSuiteFolder = new Directory("./test/JSON-Schema-Test-Suite/tests/draft4"); + + var optionals = new Directory(path.joinAll([testSuiteFolder.path, 'optional'])); + + var all = testSuiteFolder.listSync()..addAll(optionals.listSync()); + + all.forEach((testEntry) { + if (testEntry is File) { + group("Validations ${path.basename(testEntry.path)}", () { + // TODO: add these back or get replacements + // Skip these for now - reason shown + if ([ + 'refRemote.json', // seems to require webserver running to vend files + ].contains(path.basename(testEntry.path))) return; + + List tests = convert.JSON.decode((testEntry as File).readAsStringSync()); + tests.forEach((testEntry) { + var schemaData = testEntry["schema"]; + var description = testEntry["description"]; + List validationTests = testEntry["tests"]; + + validationTests.forEach((validationTest) { + String validationDescription = validationTest["description"]; + test("${description} : ${validationDescription}", () { + var instance = validationTest["data"]; + bool validationResult; + bool expectedResult = validationTest["valid"]; + var checkResult = expectAsync0(() => expect(validationResult, expectedResult)); + Schema.createSchema(schemaData).then((schema) { + validationResult = schema.validate(instance); + checkResult(); + }); + }); + }); + }); + }); + } + }); + + test("Schema self validation", () { + // Pull in the official schema, verify description and then ensure + // that the schema satisfies the schema for schemas + String url = "http://json-schema.org/draft-04/schema"; + Schema.createSchemaFromUrl(url).then((schema) { + expect(schema.schemaMap["description"], "Core schema meta-schema"); + expect(schema.validate(schema.schemaMap), true); + }); + }); + +// end
+} diff --git a/tool/dev.dart b/tool/dev.dart new file mode 100644 index 00000000..c3c60449 --- /dev/null +++ b/tool/dev.dart @@ -0,0 +1,68 @@ +// Copyright 2013-2018 Workiva Inc. +// +// Licensed under the Boost Software License (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.boost.org/LICENSE_1_0.txt +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// +// This software or document includes material copied from or derived +// from JSON-Schema-Test-Suite (https://github.com/json-schema-org/JSON-Schema-Test-Suite), +// Copyright (c) 2012 Julian Berman, which is licensed under the following terms: +// +// Copyright (c) 2012 Julian Berman +// +// 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. + +import 'package:dart_dev/dart_dev.dart' show dev, config, TestRunnerConfig, Environment; + +main(List args) async { + config.analyze + ..entryPoints = const ['bin/', 'lib/', 'test/', 'tool/'] + ..fatalWarnings = true + ..strong = true; + + config.copyLicense.directories = const ['bin/', 'example/', 'lib/', 'test/', 'tool/']; + + config.coverage..reportOn = ['lib/']; + + config.format + ..lineLength = 120 + ..paths = const ['bin/', 'dot_samples/', 'example', 'lib/', 'test/', 'tool/']; + + config.format.exclude = const [ + 'test/unit/generated_runner_test.dart', + 'test/unit/browser/generated_runner_test.dart', + 'test/unit/vm/generated_runner_test.dart', + ]; + + config.genTestRunner.configs = [ + new TestRunnerConfig(directory: 'test/unit/vm', env: Environment.vm, filename: 'generated_runner_test'), + ]; + + config.test.unitTests = const ['test/unit/vm/generated_runner_test.dart']; + + await dev(args); +} diff --git a/tool/travis.sh b/tool/travis.sh deleted file mode 100755 index adc8fc76..00000000 --- a/tool/travis.sh +++ /dev/null @@ -1,14 +0,0 @@ -#!/bin/bash - -# Fast fail the script on failures. -set -e - -# Skipping this until at least we have a dev release that aligns with dart_style version -# $(dirname -- "$0")/ensure_dartfmt.sh - -# Run the tests. -dart test/runner.dart - -# Run the build.dart file - just to make sure it works -$(dirname $(readlink -f `which dart`))/dartanalyzer lib/*.dart test/*.dart -