diff --git a/.gitignore b/.gitignore index 2080c924b..44a09b4e0 100644 --- a/.gitignore +++ b/.gitignore @@ -28,4 +28,5 @@ thingweb-playground.iml package-lock.json **/package-lock.json Scripts/node_modules -Scripts/node_modules/* +**/node_modules/* +AssertionTester/Results/* diff --git a/AssertionTester/Assertions/td-action-objects.json b/AssertionTester/Assertions/td-action-objects.json new file mode 100644 index 000000000..79cc74643 --- /dev/null +++ b/AssertionTester/Assertions/td-action-objects.json @@ -0,0 +1,63 @@ +{ + "title": "td-action-objects", + "description": "The type of the members input and output MUST be serialized as a JSON object.", + "$schema ": "http://json-schema.org/draft-06/schema#", + "type": "object", + "properties": { + "actions": { + "additionalProperties": { + "$ref": "#/definitions/action_element" + } + } + }, + "required": [ + "actions" + ], + "additionalProperties": true, + "definitions": { + "action_element": { + "type": "object", + "properties": { + "input": { + "$ref": "#/definitions/dataSchema" + }, + "output": { + "$ref": "#/definitions/dataSchema" + } + }, + "required": [ + "input", "output" + ], + "additionalProperties": true + }, + "dataSchema": { + "type": "object", + "properties": { + "description": { + "type": "string" + }, + "title": { + "type": "string" + }, + "enum": { + "type": "array", + "minItems": 1, + "uniqueItems": true + }, + "const": {}, + "type": { + "type": "string", + "enum": [ + "boolean", + "integer", + "number", + "string", + "object", + "array", + "null" + ] + } + } + } + } +} \ No newline at end of file diff --git a/AssertionTester/Assertions/td-additional-contexts.json b/AssertionTester/Assertions/td-additional-contexts.json new file mode 100644 index 000000000..0acf24c7a --- /dev/null +++ b/AssertionTester/Assertions/td-additional-contexts.json @@ -0,0 +1,41 @@ +{ + "title": "td-additional-contexts", + "description": "When a single Thing Description instance involves several contexts, additional namespaces with prefixes MUST be appended to the @context array structure", + "also":["td-context"], + "$schema ": "http://json-schema.org/draft-06/schema#", + "type": "object", + "properties": { + "@context": { + "$ref": "#/definitions/context" + } + }, + "required": [ + "@context" + ], + "additionalProperties": true, + "definitions": { + "context": { + "type": "array", + "items": { + "anyOf": [{ + "$ref": "#/definitions/url" + }, + { + "type": "object" + } + ] + }, + "contains": { + "type": "string", + "enum": [ + "http://www.w3.org/ns/td" + ] + } + }, + "url": { + "type": "string", + "format": "uri", + "pattern": "(([^:/?#]+):)?(//([^/?#]*))?([^?#]*)(([^#]*))?(#(.*))?" + } + } +} \ No newline at end of file diff --git a/AssertionTester/assertionTester.js b/AssertionTester/assertionTester.js new file mode 100644 index 000000000..681b97003 --- /dev/null +++ b/AssertionTester/assertionTester.js @@ -0,0 +1,127 @@ +const fs = require('fs'); +const jsonld = require('jsonld'); +var Ajv = require('ajv'); +const Json2csvParser = require('json2csv').Parser; + +// Takes the second argument as the TD to validate + + +var storedTdAddress; + +const draftLocation = "./AssertionTester/json-schema-draft-06.json"; + +const fields = ['assertion-id', 'result']; +const json2csvParser = new Json2csvParser({ + fields +}); +var results = []; + +//console.log("argv is ", process.argv); +if (process.argv[2]) { + //console.log("there is second arg"); + if (typeof process.argv[2] === "string") { + console.log("Taking TD found at ", process.argv[2], " for validation"); + storedTdAddress = process.argv[2]; + } else { + console.error("Second argument should be string"); + throw "Argument error"; + } +} else { + console.error("There is NO second argument, put the location of the TD after the script call"); + throw "Argument error"; +} + +fs.readFile(storedTdAddress, (err, tdData) => { + if (err) { + console.error("Thing Description could not be found at ", storedTdAddress); + throw err; + }; + try { + var tdJson = JSON.parse(tdData); + console.log('JSON validation... OK'); + } catch (err) { + console.error('X JSON validation... KO:'); + console.error('> ' + err.message); + throw err; + } + + var schemaLocation = "./AssertionTester/Assertions/td-additional-contexts.json"; + //console.log(td); + + fs.readFile(draftLocation, (err, draftData) => { + if (err) { + console.error("JSON Schema Draft could not be found at ", draftLocation); + throw err; + }; + console.log("Taking Schema Draft found at ", draftLocation); + var draft = JSON.parse(draftData); + + fs.readFile(schemaLocation, (err, schemaData) => { + + if (err) { + console.error("JSON Schema could not be found at ", schemaLocation); + throw err; + }; + console.log("Taking Assertion Schema found at ", schemaLocation); + var schema = JSON.parse(schemaData); + + // Validation starts here + + var ajv = new Ajv(); // options can be passed, e.g. {allErrors: true} + ajv.addMetaSchema(draft); + ajv.addSchema(schema, 'td'); + + var valid = ajv.validate('td', tdJson); + //used to be var valid = ajv.validate('td', e.detail); + if (valid) { + console.log('JSON Schema validation... OK'); + results.push({ + "assertion-id": schema.title, + "result": "pass" + }); + + } else { + console.log('X JSON Schema validation... KO:'); + //console.log(ajv.errors); + console.log('> ' + ajv.errorsText()); + if (ajv.errorsText().indexOf("required") > -1) { + //failed because it doesnt have required thingy + results.push({ + "assertion-id": schema.title, + "result": "not-impl", + "additionalInfo": ajv.errorsText() + }); + } else { + //failed because of some other reason + results.push({ + "assertion-id": schema.title, + "result": "fail", + "additionalInfo": ajv.errorsText() + }); + } + } + + console.log(results); + var csv = json2csvParser.parse(results); + + console.log(csv); + + fs.writeFile("./AssertionTester/Results/result.json", JSON.stringify(results), function (err) { + if (err) { + return console.log(err); + } + + console.log("The result json was saved!"); + }); + + fs.writeFile("./AssertionTester/Results/result.csv", csv, function (err) { + if (err) { + return console.log(err); + } + + console.log("The result csv was saved!"); + }); + }); + + }); +}); \ No newline at end of file diff --git a/AssertionTester/json-schema-draft-06.json b/AssertionTester/json-schema-draft-06.json new file mode 100644 index 000000000..5656240b9 --- /dev/null +++ b/AssertionTester/json-schema-draft-06.json @@ -0,0 +1,154 @@ +{ + "$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": {}, + "examples": { + "type": "array", + "items": {} + }, + "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", + "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" }, + "allOf": { "$ref": "#/definitions/schemaArray" }, + "anyOf": { "$ref": "#/definitions/schemaArray" }, + "oneOf": { "$ref": "#/definitions/schemaArray" }, + "not": { "$ref": "#" } + }, + "default": {} +} diff --git a/AssertionTester/package.json b/AssertionTester/package.json new file mode 100644 index 000000000..30b321d7c --- /dev/null +++ b/AssertionTester/package.json @@ -0,0 +1,31 @@ +{ + "name": "tdplayground", + "version": "1.0.0", + "description": "validates a Thing Description stored somewhere", + "main": "playground.js", + "dependencies": { + "ajv": "^6.5.4", + "json2csv": "^4.3.1", + "jsonld": "^1.1.0" + }, + "devDependencies": {}, + "scripts": { + "test": "echo \"Error: no test specified\" && exit 1" + }, + "repository": { + "type": "git", + "url": "git+https://github.com/thingweb/thingweb-playground.git" + }, + "keywords": [ + "wot", + "td", + "playground", + "validation" + ], + "author": "Ege Korkan, Victor Charpenay", + "license": "MIT", + "bugs": { + "url": "https://github.com/thingweb/thingweb-playground/issues" + }, + "homepage": "https://github.com/thingweb/thingweb-playground#readme" +}