Skip to content

Commit

Permalink
tests will validate the composite swagger against the schema (Azure#823)
Browse files Browse the repository at this point in the history
* tests will validate the composite swagger against the schema

* updated tests to ensure that the documents in the composite documents actually exist.
  • Loading branch information
amarzavery authored Dec 21, 2016
1 parent e3eedae commit a2e06bb
Show file tree
Hide file tree
Showing 4 changed files with 126 additions and 40 deletions.
6 changes: 6 additions & 0 deletions .vscode/settings.json
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,12 @@
"/**/examples/*.json"
],
"url": "https://raw.githubusercontent.com/Azure/autorest/master/schema/example-schema.json"
},
{
"fileMatch": [
"/**/composite*.json"
],
"url": "https://raw.githubusercontent.com/Azure/autorest/master/schema/composite-swagger.json"
}
]
}
2 changes: 1 addition & 1 deletion LICENSE
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
The MIT License (MIT)

Copyright (c) 2015 Microsoft
Copyright (c) 2016 Microsoft

Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
Expand Down
8 changes: 3 additions & 5 deletions package.json
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
{
"name": "azure-rest-specs-tests",
"name": "azure-rest-api-specs-tests",
"private": true,
"author": {
"name": "Microsoft Corporation",
Expand All @@ -8,11 +8,9 @@
},
"version": "0.1.0",
"description": "Tests for Azure REST API Specifications",
"engines": {
"node": ">= 0.8.26"
},
"license": "MIT",
"dependencies": {
"async": "^2.1.4",
"glob": "^5.0.14",
"lodash": "^3.10.1",
"request": "^2.61.0",
Expand All @@ -30,6 +28,6 @@
"url": "http://github.com/azure/azure-rest-api-specs/issues"
},
"scripts": {
"test": "mocha"
"test": "mocha -t 10000"
}
}
150 changes: 116 additions & 34 deletions test/test.js
Original file line number Diff line number Diff line change
@@ -1,24 +1,38 @@
// Copyright (c) Microsoft Corporation. All rights reserved.
// Licensed under the MIT License. See License in the project root for license information.

'use strict';
var assert = require("assert"),
fs = require('fs'),
glob = require('glob'),
path = require('path'),
_ = require('lodash'),
z = require('z-schema'),
request = require('request'),
util = require('util');
fs = require('fs'),
glob = require('glob'),
path = require('path'),
_ = require('lodash'),
z = require('z-schema'),
request = require('request'),
async = require('async'),
util = require('util');

var extensionSwaggerSchemaUrl = "https://raw.githubusercontent.com/Azure/autorest/master/schema/swagger-extensions.json";
var swaggerSchemaUrl = "http://json.schemastore.org/swagger-2.0";
var swaggerSchemaAltUrl = "http://swagger.io/v2/schema.json";
var schemaUrl = "http://json-schema.org/draft-04/schema";
var exampleSchemaUrl = "https://raw.githubusercontent.com/Azure/autorest/master/schema/example-schema.json";
var swaggerSchema;
var extensionSwaggerSchema;
var schema4;
var exampleSchema;
var compositeSchemaUrl = "https://raw.githubusercontent.com/Azure/autorest/master/schema/composite-swagger.json";

var swaggerSchema, extensionSwaggerSchema, schema4, exampleSchema, compositeSchema,
globPath, compositeGlobPath, swaggers, compositeSwaggers, validator;

globPath = path.join(__dirname, '../', '/**/swagger/*.json');
swaggers = _(glob.sync(globPath));

var globPath = path.join(__dirname, '../', '/**/swagger/*.json');
var swaggers = _(glob.sync(globPath));
// Useful when debugging a test for a particular swagger.
// Just update the regex. That will return an array of filtered items.
// swaggers = swaggers.filter(function(item) {
// return (item.match(/.*arm-redis.*/ig) !== null);
// })

compositeGlobPath = path.join(__dirname, '../', '/**/composite*.json');
compositeSwaggers = _(glob.sync(compositeGlobPath));

// Remove byte order marker. This catches EF BB BF (the UTF-8 BOM)
// because the buffer-to-string conversion in `fs.readFile()`
Expand All @@ -33,43 +47,111 @@ function stripBOM(content) {
return content;
}

describe('Azure Swagger Schema Validation', function() {
before(function(done) {
request({url: extensionSwaggerSchemaUrl, json:true}, function (error, response, extensionSwaggerSchemaBody) {
describe('Azure Swagger Schema Validation', function () {
before(function (done) {
request({ url: extensionSwaggerSchemaUrl, json: true }, function (error, response, extensionSwaggerSchemaBody) {
request({ url: swaggerSchemaAltUrl, json: true }, function (error, response, swaggerSchemaBody) {
request({ url: exampleSchemaUrl, json: true }, function (error, response, exampleSchemaBody) {
extensionSwaggerSchema = extensionSwaggerSchemaBody;
swaggerSchema = swaggerSchemaBody;
exampleSchema = exampleSchemaBody;
done();
request({ url: compositeSchemaUrl, json: true }, function (error, response, compositeSchemaBody) {
extensionSwaggerSchema = extensionSwaggerSchemaBody;
swaggerSchema = swaggerSchemaBody;
exampleSchema = exampleSchemaBody;
compositeSchema = compositeSchemaBody;
validator = new z({ breakOnFirstError: false });
validator.setRemoteReference(swaggerSchemaUrl, swaggerSchema);
validator.setRemoteReference(exampleSchemaUrl, exampleSchema);
validator.setRemoteReference(compositeSchemaUrl, compositeSchema);
done();
});
});
});
});
});

_(swaggers).each(function(swagger){
it(swagger + ' should be valid Swagger', function(done){
fs.readFile(swagger, 'utf8', function(err, data) {
if(err) { done(err); }

var parsedData = JSON.parse(stripBOM(data));
_(swaggers).each(function (swagger) {
it(swagger + ' should be a valid Swagger document.', function (done) {
fs.readFile(swagger, 'utf8', function (err, data) {
if (err) { done(err); }
var parsedData;
try {
parsedData = JSON.parse(stripBOM(data));
} catch (err) {
throw new Error("swagger " + swagger + " is an invalid JSON. " + util.inspect(err, { depth: null }));
}

if (parsedData.documents && util.isArray(parsedData.documents)) {
console.log(util.format('Skipping the test for \'%s\' document as it seems to be a composite swagger doc.', swagger));
done();
}
var validator = new z({
breakOnFirstError: false
});
validator.setRemoteReference(swaggerSchemaUrl, swaggerSchema);
validator.setRemoteReference(exampleSchemaUrl, exampleSchema);
var valid = validator.validate(JSON.parse(stripBOM(data)), extensionSwaggerSchema);
var valid = validator.validate(parsedData, extensionSwaggerSchema);
if (!valid) {
var error = validator.getLastErrors();
throw new Error("Schema validation failed: " + JSON.stringify(error, null, "\t"));
var error = validator.getLastErrors();
throw new Error("Schema validation failed: " + util.inspect(error, { depth: null }));
}
assert(valid === true);
done();
});
});
}).value();

_(compositeSwaggers).each(function (compositeSwagger) {
it('composite: ' + compositeSwagger + ' should be a valid Composite Swagger document.', function (done) {
fs.readFile(compositeSwagger, 'utf8', function (err, data) {
if (err) { done(err); }
var parsedData;
try {
parsedData = JSON.parse(stripBOM(data));
} catch (err) {
throw new Error("compositeSwagger " + compositeSwagger + " is an invalid JSON. " + util.inspect(err, { depth: null }));
}
var valid = validator.validate(parsedData, compositeSchema);
if (!valid) {
var error = validator.getLastErrors();
throw new Error("Schema validation for Composite Swagger failed: " + util.inspect(error, { depth: null }));
}
assert(valid === true);
var compositeSwaggerDir = path.dirname(compositeSwagger);
var messages = [];
if (parsedData.documents && parsedData.documents.length > 0) {
async.eachSeries(parsedData.documents, function (docUrl, loopCallback) {
//construct the absolue path if the item in the documents array is a relative path
if (!path.isAbsolute(docUrl) && !docUrl.startsWith('http')) {
docUrl = path.join(compositeSwaggerDir, docUrl);
}
//make a request if it is a url
if (docUrl.startsWith('http')) {
request({ url: docUrl, json: true }, function (error, response, responseBody) {
if (error) {
messages.push('An error occurred while accessing the swagger doc ' +
docUrl + ' from the documents list. The error is ' + util.inspect(error, { depth: null }));
}
if (response.statusCode !== 200) {
messages.push('\'File Not Found\': error occurred while accessing the swagger doc ' +
docUrl + ' from the documents list. The received statusCode is: \'' + response.statusCode + '\'.');
}
loopCallback();
});
} else {
//check whether the file exists
if (!fs.existsSync(docUrl)) {
messages.push('\'File Not Found\': error occurred while accessing the swagger doc ' +
docUrl + ' from the documents list on the host filesystem.');
}
loopCallback();
}
}, function (err) {
if (err) {
throw err;
}
if (messages.length > 0) {
throw new Error(JSON.stringify(messages));
}
done();
});
} else {
done();
}
});
});
}).value();
});

0 comments on commit a2e06bb

Please sign in to comment.