/**
* This Source Code Form is subject to the terms of the Mozilla Public License,
* v. 2.0. If a copy of the MPL was not distributed with this file, You can
* obtain one at http://mozilla.org/MPL/2.0/. OpenMRS is also distributed under
* the terms of the Healthcare Disclaimer located at http://openmrs.org/license.
*
* Copyright (C) OpenMRS Inc. OpenMRS is a registered trademark and the OpenMRS
* graphic logo is a trademark of OpenMRS Inc.
*/
package org.openmrs.module.webservices.rest.doc;
import java.sql.Connection;
import java.sql.DatabaseMetaData;
import java.sql.ResultSet;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import org.dbunit.database.DatabaseConnection;
import org.junit.Assert;
import org.junit.Before;
import org.junit.Test;
import org.openmrs.GlobalProperty;
import org.openmrs.api.context.Context;
import org.openmrs.module.webservices.docs.swagger.Operation;
import org.openmrs.module.webservices.docs.swagger.Parameter;
import org.openmrs.module.webservices.docs.swagger.Path;
import org.openmrs.module.webservices.docs.swagger.SwaggerSpecification;
import org.openmrs.module.webservices.docs.swagger.SwaggerSpecificationCreator;
import org.openmrs.module.webservices.rest.web.RestConstants;
import org.openmrs.module.webservices.rest.web.api.RestService;
import org.openmrs.web.test.BaseModuleWebContextSensitiveTest;
public class SwaggerSpecificationCreatorTest extends BaseModuleWebContextSensitiveTest {
Map<String, Integer> beforeCounts;
public Map<String, Integer> getRowCounts() throws Exception {
Map<String, Integer> ret = new HashMap<String, Integer>();
Connection con = this.getConnection();
DatabaseMetaData metaData = con.getMetaData();
DatabaseConnection dbcon = new DatabaseConnection(con);
ResultSet rs = metaData.getTables(null, "PUBLIC", "%", null);
while (rs.next()) {
String tableName = rs.getString(3);
ret.put(tableName, dbcon.getRowCount(tableName));
}
return ret;
}
@Before
public void init() throws Exception {
// init REST
Context.getService(RestService.class).initialize();
Context.getAdministrationService().saveGlobalProperty(
new GlobalProperty(RestConstants.SWAGGER_QUIET_DOCS_GLOBAL_PROPERTY_NAME, "true"));
// ensure GP is written to database before we count the rows
Context.flushSession();
beforeCounts = getRowCounts();
}
@Test
public void checkNoDatabaseChanges() throws Exception {
SwaggerSpecificationCreator ssc = new SwaggerSpecificationCreator("/v1/");
ssc.BuildJSON();
Map<String, Integer> afterCounts = getRowCounts();
Assert.assertEquals("Ensure no tables are created or destroyed", beforeCounts.size(), afterCounts.size());
Assert.assertTrue("Ensure that no data was added or removed from any tables",
ensureCountsEqual(beforeCounts, afterCounts));
}
private boolean ensureCountsEqual(Map<String, Integer> beforeCounts, Map<String, Integer> afterCounts) throws Exception {
for (String key : beforeCounts.keySet()) {
if (beforeCounts.get(key) != afterCounts.get(key)) {
System.err.println("The " + key + " table has a different number of rows (" + beforeCounts.get(key)
+ " before, " + afterCounts.get(key) + " after).");
return false;
}
}
return true;
}
// makes sure that every operation has a unique operationId
@Test
public void checkOperationIdsSet() throws Exception {
List<String> operationIds = new ArrayList<String>();
SwaggerSpecificationCreator ssc = new SwaggerSpecificationCreator("/v1/");
ssc.BuildJSON();
SwaggerSpecification spec = ssc.getSwaggerSpecification();
for (Path p : spec.getPaths().getPaths().values()) {
for (Operation o : p.getOperations().values()) {
Assert.assertFalse("Ensure each operation has a unique ID", operationIds.contains(o.getOperationId()));
operationIds.add(o.getOperationId());
}
}
}
// makes sure that every GET operation has the "v" parameter
@Test
public void checkRepresentationParamExists() throws Exception {
List<String> operationIds = new ArrayList<String>();
SwaggerSpecificationCreator ssc = new SwaggerSpecificationCreator("/v1/");
ssc.BuildJSON();
SwaggerSpecification spec = ssc.getSwaggerSpecification();
for (Path p : spec.getPaths().getPaths().values()) {
for (Operation o : p.getOperations().values()) {
if (o.getName().equals("get")) {
Assert.assertTrue("Ensure each GET operation has the 'v' query parameter",
operationHasRepresentationParam(o));
}
}
}
}
private boolean operationHasRepresentationParam(Operation o) {
boolean ret = false;
for (Parameter p : o.getParameters()) {
if (p.getName().equals("v")) {
ret = !ret;
}
}
return ret;
}
// make sure each operation that supports paging has the limit and startIndex parameters
@Test
public void checkPagingParamsExist() throws Exception {
SwaggerSpecificationCreator ssc = new SwaggerSpecificationCreator("/v1/");
ssc.BuildJSON();
SwaggerSpecification spec = ssc.getSwaggerSpecification();
for (Path p : spec.getPaths().getPaths().values()) {
for (Operation o : p.getOperations().values()) {
if (o.getOperationId().matches("^getAll[A-Z].*")) {
Assert.assertTrue("Ensure each operation that supports paging has both paging parameters",
operationHasPagingParams(o));
}
}
}
}
private boolean operationHasPagingParams(Operation o) {
boolean limit = false, startIndex = false;
for (Parameter p : o.getParameters()) {
if (p.getName().equals("limit")) {
limit = !limit;
} else if (p.getName().equals("startIndex")) {
startIndex = !startIndex;
}
}
return limit && startIndex;
}
}