Set encoding to UTF-8 and Fix Comparison Tests (#27)

* Fixed issue with UTF-8 encodings not being picked up from the Windows console
* Additional fixes to comparison tests
* Added tests for Integer comparisons
* Added String comparison tests
* Added timestamp comparison tests
* Renamed test files to match conventions
* Added Fractional Date Part tests
* Generated automated acceptance tests for remainder of compare() operations in TestUtils
* Checked in new Commander build
This commit is contained in:
Joshua Darnell 2020-04-27 20:23:49 -07:00 committed by GitHub
parent 59c409d37d
commit cd3fd1ab84
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
18 changed files with 5908 additions and 2232 deletions

File diff suppressed because it is too large Load Diff

View File

@ -10,6 +10,7 @@ plugins {
mainClassName = 'org.reso.commander.Main' mainClassName = 'org.reso.commander.Main'
sourceCompatibility = 1.8 sourceCompatibility = 1.8
targetCompatibility = 1.8 targetCompatibility = 1.8
compileJava.options.encoding = 'UTF-8'
repositories { repositories {
// Use jcenter for resolving your dependencies. // Use jcenter for resolving your dependencies.

Binary file not shown.

View File

@ -3,6 +3,7 @@ package org.reso.certification.stepdefs;
import com.fasterxml.jackson.databind.node.ObjectNode; import com.fasterxml.jackson.databind.node.ObjectNode;
import com.fasterxml.jackson.databind.node.POJONode; import com.fasterxml.jackson.databind.node.POJONode;
import io.cucumber.java8.En; import io.cucumber.java8.En;
import org.apache.http.HttpStatus;
import org.apache.logging.log4j.LogManager; import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger; import org.apache.logging.log4j.Logger;
import org.apache.olingo.client.api.communication.ODataClientErrorException; import org.apache.olingo.client.api.communication.ODataClientErrorException;
@ -254,20 +255,34 @@ public class WebAPIServer_1_0_2 implements En {
Then("^the server responds with a status code of (\\d+)$", (Integer assertedResponseCode) -> { Then("^the server responds with a status code of (\\d+)$", (Integer assertedResponseCode) -> {
try { try {
LOG.info("Asserted Response Code: " + assertedResponseCode + ", Server Response Code: " + getTestContainer().getResponseCode()); LOG.info("Asserted Response Code: " + assertedResponseCode + ", Server Response Code: " + getTestContainer().getResponseCode());
assertTrue(getTestContainer().getResponseCode() > 0 && assertedResponseCode > 0);
if (assertedResponseCode.intValue() != getTestContainer().getResponseCode().intValue()) { //TODO: clean up logic
if (getTestContainer().getResponseCode() != null && assertedResponseCode.intValue() != getTestContainer().getResponseCode().intValue()) {
if (getTestContainer().getODataClientErrorException() != null) { if (getTestContainer().getODataClientErrorException() != null) {
if (getTestContainer().getODataClientErrorException().getODataError().getMessage() != null) { if (getTestContainer().getODataClientErrorException().getODataError().getMessage() != null) {
LOG.error("Request failed with the following message: " LOG.error(getDefaultErrorMessage("Request failed with the following message:",
+ getTestContainer().getODataClientErrorException().getODataError().getMessage()); getTestContainer().getODataClientErrorException().getODataError().getMessage()));
} else if (getTestContainer().getODataClientErrorException().getMessage() != null) { } else if (getTestContainer().getODataClientErrorException().getMessage() != null) {
LOG.error("Request failed with the following message: " LOG.error(getDefaultErrorMessage("Request failed with the following message:",
+ getTestContainer().getODataClientErrorException().getMessage()); getTestContainer().getODataClientErrorException().getMessage()));
}
} else if (getTestContainer().getODataServerErrorException() != null) {
LOG.error(getDefaultErrorMessage("Request failed with the following message:",
getTestContainer().getODataServerErrorException().toString()));
if (getTestContainer().getODataServerErrorException().toString().contains(String.valueOf(HttpStatus.SC_INTERNAL_SERVER_ERROR))) {
getTestContainer().setResponseCode(HttpStatus.SC_INTERNAL_SERVER_ERROR);
} }
} }
//fail for all inner conditions
fail(getAssertResponseCodeErrorMessage(assertedResponseCode, getTestContainer().getResponseCode())); fail(getAssertResponseCodeErrorMessage(assertedResponseCode, getTestContainer().getResponseCode()));
} }
//if we make it through without failing, things are good
assertTrue(getTestContainer().getResponseCode() > 0 && assertedResponseCode > 0);
} catch (Exception ex) { } catch (Exception ex) {
fail(getDefaultErrorMessage(ex)); fail(getDefaultErrorMessage(ex));
} }
@ -329,11 +344,9 @@ public class WebAPIServer_1_0_2 implements En {
//iterate through response data and ensure that with data, the statement fieldName "op" assertValue is true //iterate through response data and ensure that with data, the statement fieldName "op" assertValue is true
from(getTestContainer().getResponseData()).getList(JSON_VALUE_PATH, HashMap.class).forEach(item -> { from(getTestContainer().getResponseData()).getList(JSON_VALUE_PATH, HashMap.class).forEach(item -> {
assertNotNull("ERROR: '" + fieldName + "' cannot be null!", item.get(fieldName)); fieldValue.set(item.get(fieldName) != null ? new Integer(item.get(fieldName).toString()) : null);
fieldValue.set(Integer.parseInt(item.get(fieldName).toString()));
result.set(result.get() && TestUtils.compare(fieldValue.get(), op, assertedValue)); result.set(result.get() && TestUtils.compare(fieldValue.get(), op, assertedValue));
}); });
assertTrue(result.get()); assertTrue(result.get());
} catch (Exception ex) { } catch (Exception ex) {
fail(getDefaultErrorMessage(ex)); fail(getDefaultErrorMessage(ex));

View File

@ -202,6 +202,7 @@ public class App {
if (cmd.hasOption(APP_OPTIONS.ACTIONS.GET_METADATA)) { if (cmd.hasOption(APP_OPTIONS.ACTIONS.GET_METADATA)) {
APP_OPTIONS.validateAction(cmd, APP_OPTIONS.ACTIONS.GET_METADATA); APP_OPTIONS.validateAction(cmd, APP_OPTIONS.ACTIONS.GET_METADATA);
//TODO: this isn't the metadata but the entity data model (edm), change to XML Metadata
metadata = commander.prepareEdmMetadataRequest().execute().getBody(); metadata = commander.prepareEdmMetadataRequest().execute().getBody();
getMetadataReport(metadata); getMetadataReport(metadata);

View File

@ -41,6 +41,8 @@ import java.nio.charset.StandardCharsets;
import java.util.concurrent.atomic.AtomicReference; import java.util.concurrent.atomic.AtomicReference;
import java.util.function.Function; import java.util.function.Function;
import static org.reso.commander.common.ErrorMsg.getDefaultErrorMessage;
/** /**
* Most of the work done by the WebAPI commander is done by this class. Its public methods are, therefore, * Most of the work done by the WebAPI commander is done by this class. Its public methods are, therefore,
* the ones the Client programmer is expected to use. * the ones the Client programmer is expected to use.
@ -102,15 +104,16 @@ public class Commander {
XMLReader reader = parser.getXMLReader(); XMLReader reader = parser.getXMLReader();
reader.setErrorHandler(new SimpleErrorHandler()); reader.setErrorHandler(new SimpleErrorHandler());
InputSource inputSource = new InputSource(new ByteArrayInputStream(xmlString.getBytes(StandardCharsets.UTF_8))); InputSource inputSource = new InputSource(new ByteArrayInputStream(xmlString.getBytes(StandardCharsets.UTF_8)));
inputSource.setEncoding(StandardCharsets.UTF_8.toString());
reader.parse(inputSource); reader.parse(inputSource);
return true; return true;
} catch (SAXException saxEx) { } catch (SAXException saxEx) {
if (saxEx.getMessage() != null) { if (saxEx.getMessage() != null) {
LOG.error(saxEx); LOG.error(getDefaultErrorMessage(saxEx));
} }
} catch (Exception ex) { } catch (Exception ex) {
LOG.error(ex); LOG.error(getDefaultErrorMessage("general error validating XML!"));
LOG.debug("Exception in validateXML: " + ex);
} }
return false; return false;
} }
@ -153,8 +156,7 @@ public class Commander {
JSON_FULL_METADATA = "JSON_FULL_METADATA", JSON_FULL_METADATA = "JSON_FULL_METADATA",
XML = "XML"; XML = "XML";
final ContentType DEFAULT_CONTENT_TYPE = ContentType.JSON; ContentType type = ContentType.JSON;
ContentType type = DEFAULT_CONTENT_TYPE;
if (contentType == null) { if (contentType == null) {
return type; return type;
@ -471,7 +473,8 @@ public class Commander {
//require the XML Document to be valid XML before trying to validate it with the OData validator //require the XML Document to be valid XML before trying to validate it with the OData validator
if (validateXML(xmlString)) { if (validateXML(xmlString)) {
// deserialize metadata from given file // deserialize metadata from given file
XMLMetadata metadata = client.getDeserializer(ContentType.APPLICATION_XML).toMetadata(new ByteArrayInputStream(xmlString.getBytes())); XMLMetadata metadata = client.getDeserializer(ContentType.APPLICATION_XML)
.toMetadata(new ByteArrayInputStream(xmlString.getBytes(StandardCharsets.UTF_8)));
if (metadata != null) { if (metadata != null) {
return validateMetadata(metadata); return validateMetadata(metadata);
} else { } else {

View File

@ -23,11 +23,11 @@ import java.io.IOException;
import java.io.InputStream; import java.io.InputStream;
import java.io.InputStreamReader; import java.io.InputStreamReader;
import java.net.URI; import java.net.URI;
import java.nio.charset.StandardCharsets;
import java.sql.Time; import java.sql.Time;
import java.sql.Timestamp; import java.sql.Timestamp;
import java.time.LocalDate; import java.time.LocalDate;
import java.time.OffsetDateTime; import java.time.OffsetDateTime;
import java.time.Year;
import java.util.*; import java.util.*;
import java.util.concurrent.atomic.AtomicReference; import java.util.concurrent.atomic.AtomicReference;
@ -132,17 +132,17 @@ public final class TestUtils {
boolean result = false; boolean result = false;
if (operator.contentEquals(Operators.GREATER_THAN)) { if (operator.contentEquals(Operators.GREATER_THAN)) {
result = lhs > rhs; result = lhs != null && rhs != null && lhs > rhs;
} else if (operator.contentEquals(Operators.GREATER_THAN_OR_EQUAL)) { } else if (operator.contentEquals(Operators.GREATER_THAN_OR_EQUAL)) {
result = lhs >= rhs; result = Objects.equals(lhs, rhs) || (lhs != null && rhs != null && lhs > rhs);
} else if (operator.contentEquals(Operators.EQ)) { } else if (operator.contentEquals(Operators.EQ)) {
result = lhs.equals(rhs); result = Objects.equals(lhs, rhs);
} else if (operator.contentEquals(Operators.NE)) { } else if (operator.contentEquals(Operators.NE)) {
result = !lhs.equals(rhs); result = !Objects.equals(lhs, rhs);
} else if (operator.contentEquals(Operators.LESS_THAN)) { } else if (operator.contentEquals(Operators.LESS_THAN)) {
result = lhs < rhs; result = lhs != null && rhs != null && lhs < rhs;
} else if (operator.contentEquals(Operators.LESS_THAN_OR_EQUAL)) { } else if (operator.contentEquals(Operators.LESS_THAN_OR_EQUAL)) {
result = lhs <= rhs; result = Objects.equals(lhs, rhs) || (lhs != null && rhs != null && lhs < rhs);
} }
LOG.info("Compare: " + lhs + " " + operator + " " + rhs + " ==> " + result); LOG.info("Compare: " + lhs + " " + operator + " " + rhs + " ==> " + result);
return result; return result;
@ -161,15 +161,15 @@ public final class TestUtils {
boolean result = false; boolean result = false;
if (operator.contentEquals(Operators.CONTAINS)) { if (operator.contentEquals(Operators.CONTAINS)) {
result = lhs.contains(rhs); result = Objects.equals(lhs, rhs) || (lhs != null && rhs != null && lhs.contains(rhs));
} else if (operator.contentEquals(Operators.STARTS_WITH)) { } else if (operator.contentEquals(Operators.STARTS_WITH)) {
result = lhs.startsWith(rhs); result = lhs != null && rhs != null && lhs.startsWith(rhs);
} else if (operator.contentEquals(Operators.ENDS_WITH)) { } else if (operator.contentEquals(Operators.ENDS_WITH)) {
result = lhs.endsWith(rhs); result = lhs != null && rhs != null && lhs.endsWith(rhs);
} else if (operator.contentEquals(Operators.TO_LOWER)) { } else if (operator.contentEquals(Operators.TO_LOWER)) {
result = lhs.toLowerCase().equals(rhs); result = lhs != null && lhs.toLowerCase().contentEquals(rhs);
} else if (operator.contentEquals(Operators.TO_UPPER)) { } else if (operator.contentEquals(Operators.TO_UPPER)) {
result = lhs.toUpperCase().equals(rhs); result = lhs != null && lhs.toUpperCase().contentEquals(rhs);
} }
LOG.info("Compare: \"" + lhs + "\" " + operator + " \"" + rhs + "\" ==> " + result); LOG.info("Compare: \"" + lhs + "\" " + operator + " \"" + rhs + "\" ==> " + result);
return result; return result;
@ -188,46 +188,17 @@ public final class TestUtils {
boolean result = false; boolean result = false;
if (operator.contentEquals(Operators.GREATER_THAN)) { if (operator.contentEquals(Operators.GREATER_THAN)) {
result = lhs.after(rhs); result = lhs != null && rhs != null && lhs.after(rhs);
} else if (operator.contentEquals(Operators.GREATER_THAN_OR_EQUAL)) { } else if (operator.contentEquals(Operators.GREATER_THAN_OR_EQUAL)) {
result = lhs.after(rhs) || lhs.equals(rhs); result = Objects.equals(lhs, rhs) || (lhs != null && rhs != null && lhs.after(rhs));
} else if (operator.contentEquals(Operators.EQ)) { } else if (operator.contentEquals(Operators.EQ)) {
result = lhs.equals(rhs); result = Objects.equals(lhs, rhs);
} else if (operator.contentEquals(Operators.NE)) { } else if (operator.contentEquals(Operators.NE)) {
result = !lhs.equals(rhs); result = !Objects.equals(lhs, rhs);
} else if (operator.contentEquals(Operators.LESS_THAN)) { } else if (operator.contentEquals(Operators.LESS_THAN)) {
result = lhs.before(rhs); result = lhs != null && rhs != null && lhs.before(rhs);
} else if (operator.contentEquals(Operators.LESS_THAN_OR_EQUAL)) { } else if (operator.contentEquals(Operators.LESS_THAN_OR_EQUAL)) {
result = lhs.before(rhs) || lhs.equals(rhs); result = Objects.equals(lhs, rhs) || (lhs != null && rhs != null && lhs.before(rhs));
}
LOG.info("Compare: " + lhs + " " + operator + " " + rhs + " ==> " + result);
return result;
}
/**
* Year Comparator
*
* @param lhs Year to compare
* @param op an OData binary operator to use for comparisons
* @param rhs Timestamp to compare
* @return true if lhs op rhs, false otherwise
*/
public static boolean compare(Year lhs, String op, Year rhs) {
String operator = op.toLowerCase();
boolean result = false;
if (operator.contentEquals(Operators.GREATER_THAN)) {
result = lhs.isAfter(rhs);
} else if (operator.contentEquals(Operators.GREATER_THAN_OR_EQUAL)) {
result = lhs.isAfter(rhs) || lhs.equals(rhs);
} else if (operator.contentEquals(Operators.EQ)) {
result = lhs.equals(rhs);
} else if (operator.contentEquals(Operators.NE)) {
result = !lhs.equals(rhs);
} else if (operator.contentEquals(Operators.LESS_THAN)) {
result = lhs.isBefore(rhs);
} else if (operator.contentEquals(Operators.LESS_THAN_OR_EQUAL)) {
result = lhs.isBefore(rhs) || lhs.equals(rhs);
} }
LOG.info("Compare: " + lhs + " " + operator + " " + rhs + " ==> " + result); LOG.info("Compare: " + lhs + " " + operator + " " + rhs + " ==> " + result);
return result; return result;
@ -246,17 +217,17 @@ public final class TestUtils {
boolean result = false; boolean result = false;
if (operator.contentEquals(Operators.GREATER_THAN)) { if (operator.contentEquals(Operators.GREATER_THAN)) {
result = lhs.toLocalTime().isAfter(rhs.toLocalTime()); result = lhs != null && rhs != null && lhs.toLocalTime().isAfter(rhs.toLocalTime());
} else if (operator.contentEquals(Operators.GREATER_THAN_OR_EQUAL)) { } else if (operator.contentEquals(Operators.GREATER_THAN_OR_EQUAL)) {
result = lhs.toLocalTime().isAfter(rhs.toLocalTime()) || lhs.toLocalTime().equals(rhs.toLocalTime()); result = Objects.equals(lhs, rhs) || lhs.toLocalTime().isAfter(rhs.toLocalTime()) || lhs.toLocalTime().equals(rhs.toLocalTime());
} else if (operator.contentEquals(Operators.EQ)) { } else if (operator.contentEquals(Operators.EQ)) {
result = lhs.toLocalTime().equals(rhs.toLocalTime()); result = Objects.equals(lhs, rhs) || lhs.toLocalTime().equals(rhs.toLocalTime());
} else if (operator.contentEquals(Operators.NE)) { } else if (operator.contentEquals(Operators.NE)) {
result = !lhs.toLocalTime().equals(rhs.toLocalTime()); result = !Objects.equals(lhs, rhs) || !lhs.toLocalTime().equals(rhs.toLocalTime());
} else if (operator.contentEquals(Operators.LESS_THAN)) { } else if (operator.contentEquals(Operators.LESS_THAN)) {
result = lhs.toLocalTime().isBefore(rhs.toLocalTime()); result = lhs != null && rhs != null && lhs.toLocalTime().isBefore(rhs.toLocalTime());
} else if (operator.contentEquals(Operators.LESS_THAN_OR_EQUAL)) { } else if (operator.contentEquals(Operators.LESS_THAN_OR_EQUAL)) {
result = lhs.toLocalTime().isBefore(rhs.toLocalTime()) || lhs.toLocalTime().equals(rhs.toLocalTime()); result = Objects.equals(lhs, rhs) || lhs.toLocalTime().isBefore(rhs.toLocalTime()) || lhs.toLocalTime().equals(rhs.toLocalTime());
} }
LOG.info("Compare: " + lhs + " " + operator + " " + rhs + " ==> " + result); LOG.info("Compare: " + lhs + " " + operator + " " + rhs + " ==> " + result);
return result; return result;
@ -275,17 +246,17 @@ public final class TestUtils {
boolean result = false; boolean result = false;
if (operator.contentEquals(Operators.GREATER_THAN)) { if (operator.contentEquals(Operators.GREATER_THAN)) {
result = lhs.after(rhs); result = lhs != null && lhs.after(rhs);
} else if (operator.contentEquals(Operators.GREATER_THAN_OR_EQUAL)) { } else if (operator.contentEquals(Operators.GREATER_THAN_OR_EQUAL)) {
result = lhs.after(rhs) || lhs.equals(rhs); result = Objects.equals(lhs, rhs) || (lhs != null && rhs != null && lhs.after(rhs));
} else if (operator.contentEquals(Operators.EQ)) { } else if (operator.contentEquals(Operators.EQ)) {
result = lhs.equals(rhs); result = Objects.equals(lhs, rhs);
} else if (operator.contentEquals(Operators.NE)) { } else if (operator.contentEquals(Operators.NE)) {
result = !lhs.equals(rhs); result = !Objects.equals(lhs, rhs);
} else if (operator.contentEquals(Operators.LESS_THAN)) { } else if (operator.contentEquals(Operators.LESS_THAN)) {
result = lhs.before(rhs); result = lhs != null && lhs.before(rhs);
} else if (operator.contentEquals(Operators.LESS_THAN_OR_EQUAL)) { } else if (operator.contentEquals(Operators.LESS_THAN_OR_EQUAL)) {
result = lhs.before(rhs) || lhs.equals(rhs); result = Objects.equals(lhs, rhs) || (lhs != null && rhs != null && lhs.before(rhs));
} }
LOG.info("Compare: " + lhs + " " + operator + " " + rhs + " ==> " + result); LOG.info("Compare: " + lhs + " " + operator + " " + rhs + " ==> " + result);
return result; return result;
@ -426,7 +397,7 @@ public final class TestUtils {
* @param datePart the timestamp part, "Year", "Month", "Day", etc. to try and parse * @param datePart the timestamp part, "Year", "Month", "Day", etc. to try and parse
* @param value the value to try and parse * @param value the value to try and parse
* @return the Integer portion of the date if successful, otherwise throws an Exception * @return the Integer portion of the date if successful, otherwise throws an Exception
* @exception throws an exception if value cannot be parsed into a date. * @exception EdmPrimitiveTypeException an exception if value cannot be parsed into a date.
*/ */
public static Integer getDatePart(String datePart, Object value) throws EdmPrimitiveTypeException { public static Integer getDatePart(String datePart, Object value) throws EdmPrimitiveTypeException {
LocalDate date = LocalDate.parse(parseDateFromEdmDateString(value.toString()).toString()); LocalDate date = LocalDate.parse(parseDateFromEdmDateString(value.toString()).toString());
@ -449,26 +420,29 @@ public final class TestUtils {
* @return the Integer portion of the date if successful, otherwise throws an Exception * @return the Integer portion of the date if successful, otherwise throws an Exception
*/ */
public static Integer getTimestampPart(String timestampPart, Object value) throws EdmPrimitiveTypeException { public static Integer getTimestampPart(String timestampPart, Object value) throws EdmPrimitiveTypeException {
if (timestampPart == null || value == null) return null;
//Turns nanoseconds into two most significant 2 digits for fractional comparisons //Turns nanoseconds into two most significant 2 digits for fractional comparisons
Integer ADJUSTMENT_FACTOR = 10000000; int ADJUSTMENT_FACTOR = 10000000;
OffsetDateTime offsetDateTime = OffsetDateTime.parse(value.toString()); OffsetDateTime offsetDateTime = OffsetDateTime.parse(value.toString());
if (timestampPart.equals(DateParts.YEAR)) { switch (timestampPart) {
return offsetDateTime.getYear(); case DateParts.YEAR:
} else if (timestampPart.equals(DateParts.MONTH)) { return offsetDateTime.getYear();
return offsetDateTime.getMonthValue(); case DateParts.MONTH:
} else if (timestampPart.equals(DateParts.DAY)) { return offsetDateTime.getMonthValue();
return offsetDateTime.getDayOfMonth(); case DateParts.DAY:
} else if (timestampPart.equals(DateParts.HOUR)) { return offsetDateTime.getDayOfMonth();
return offsetDateTime.getHour(); case DateParts.HOUR:
} else if (timestampPart.equals(DateParts.MINUTE)) { return offsetDateTime.getHour();
return offsetDateTime.getMinute(); case DateParts.MINUTE:
} else if (timestampPart.equals(DateParts.SECOND)) { return offsetDateTime.getMinute();
return offsetDateTime.getSecond(); case DateParts.SECOND:
} else if (timestampPart.equals(DateParts.FRACTIONAL)) { return offsetDateTime.getSecond();
return offsetDateTime.getNano() / ADJUSTMENT_FACTOR; case DateParts.FRACTIONAL:
} else { return offsetDateTime.getNano() / ADJUSTMENT_FACTOR;
return null; default:
return null;
} }
} }
@ -479,11 +453,11 @@ public final class TestUtils {
* @return the string value contained in the stream. * @return the string value contained in the stream.
*/ */
public static String convertInputStreamToString(InputStream inputStream) { public static String convertInputStreamToString(InputStream inputStream) {
InputStreamReader isReader = new InputStreamReader(inputStream);
BufferedReader reader = new BufferedReader(isReader);
StringBuilder sb = new StringBuilder();
String str;
try { try {
InputStreamReader isReader = new InputStreamReader(inputStream, StandardCharsets.UTF_8.name());
BufferedReader reader = new BufferedReader(isReader);
StringBuilder sb = new StringBuilder();
String str;
while ((str = reader.readLine()) != null) { while ((str = reader.readLine()) != null) {
sb.append(str); sb.append(str);
} }

View File

@ -75,6 +75,8 @@ public class Parameters {
public static final String public static final String
RESOURCE_NAME = "EndpointResource", RESOURCE_NAME = "EndpointResource",
DATASYSTEM_ENDPOINT = "EndpointDataSystem", DATASYSTEM_ENDPOINT = "EndpointDataSystem",
EXPAND_FIELD = "ExpandField"; EXPAND_FIELD = "ExpandField",
INTEGER_FIELD = "IntegerField";
} }
} }

View File

@ -17,7 +17,6 @@ Feature: Commander XML and Metadata Validation
When XML validation is performed on the resource data When XML validation is performed on the resource data
Then XML validation fails Then XML validation fails
####################################### #######################################
# XML Metadata Validation Tests # XML Metadata Validation Tests
####################################### #######################################
@ -31,7 +30,6 @@ Feature: Commander XML and Metadata Validation
When XML Metadata validation is performed on the resource data When XML Metadata validation is performed on the resource data
Then XML Metadata validation fails Then XML Metadata validation fails
####################################### #######################################
# Edm Validation Tests # Edm Validation Tests
####################################### #######################################
@ -43,4 +41,4 @@ Feature: Commander XML and Metadata Validation
Scenario: Edm validation fails when XML Metadata don't contain a valid service document Scenario: Edm validation fails when XML Metadata don't contain a valid service document
Given metadata were loaded from the sample resource "bad-edmx-wrong-edm-binding-target.xml" Given metadata were loaded from the sample resource "bad-edmx-wrong-edm-binding-target.xml"
When Edm validation is performed on the resource data When Edm validation is performed on the resource data
Then Edm Metadata validation fails Then Edm Metadata validation fails

View File

@ -2,24 +2,33 @@ package org.reso.commander.test.stepdefs;
import io.cucumber.java8.En; import io.cucumber.java8.En;
import org.apache.http.HttpStatus; import org.apache.http.HttpStatus;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
import org.reso.commander.certfication.containers.WebAPITestContainer; import org.reso.commander.certfication.containers.WebAPITestContainer;
import org.reso.commander.common.TestUtils; import org.reso.commander.common.TestUtils;
import org.reso.models.Settings; import org.reso.models.Settings;
import java.io.File; import java.io.File;
import java.net.URL; import java.net.URL;
import java.util.HashMap;
import java.util.concurrent.atomic.AtomicBoolean;
import java.util.concurrent.atomic.AtomicReference; import java.util.concurrent.atomic.AtomicReference;
import static io.restassured.path.json.JsonPath.from;
import static org.junit.Assert.*; import static org.junit.Assert.*;
import static org.reso.commander.common.ErrorMsg.getDefaultErrorMessage; import static org.reso.commander.common.ErrorMsg.getDefaultErrorMessage;
import static org.reso.commander.common.TestUtils.JSON_VALUE_PATH;
import static org.reso.commander.common.TestUtils.parseTimestampFromEdmDateTimeOffsetString;
public class TestWebAPITestContainer implements En { public class TestWebAPITestContainer implements En {
private static final Logger LOG = LogManager.getLogger(TestWebAPITestContainer.class);
AtomicReference<WebAPITestContainer> testContainer = new AtomicReference<>(); AtomicReference<WebAPITestContainer> testContainer = new AtomicReference<>();
public TestWebAPITestContainer() { public TestWebAPITestContainer() {
//background /*
* Background
*/
Given("^a Web API test container was created using the RESOScript \"([^\"]*)\"$", (String fileName) -> { Given("^a Web API test container was created using the RESOScript \"([^\"]*)\"$", (String fileName) -> {
try { try {
//get settings from mock RESOScript file //get settings from mock RESOScript file
@ -50,8 +59,9 @@ public class TestWebAPITestContainer implements En {
} }
}); });
/* /*
* auth settings validation * Auth settings validation
*/ */
When("^an auth token is provided in \"([^\"]*)\"$", (String clientSettingsAuthToken) -> { When("^an auth token is provided in \"([^\"]*)\"$", (String clientSettingsAuthToken) -> {
String token = Settings.resolveParametersString(clientSettingsAuthToken, getTestContainer().getSettings()); String token = Settings.resolveParametersString(clientSettingsAuthToken, getTestContainer().getSettings());
@ -82,30 +92,194 @@ public class TestWebAPITestContainer implements En {
assertNotNull(getDefaultErrorMessage("settings were not found in the Web API test container!"), assertNotNull(getDefaultErrorMessage("settings were not found in the Web API test container!"),
getTestContainer().getSettings()); getTestContainer().getSettings());
}); });
/*
* Metadata validation
*/
Then("^metadata are valid$", () -> { Then("^metadata are valid$", () -> {
getTestContainer().validateMetadata(); getTestContainer().validateMetadata();
assertTrue(getDefaultErrorMessage("getIsMetadataValid() returned false when true was expected!"), assertTrue(getDefaultErrorMessage("getIsMetadataValid() returned false when true was expected!"),
getTestContainer().hasValidMetadata()); getTestContainer().hasValidMetadata());
}); });
Then("^metadata are invalid$", () -> { Then("^metadata are invalid$", () -> {
getTestContainer().validateMetadata(); getTestContainer().validateMetadata();
assertFalse(getDefaultErrorMessage("getIsMetadataValid() returned true when false was expected!"), assertFalse(getDefaultErrorMessage("getIsMetadataValid() returned true when false was expected!"),
getTestContainer().hasValidMetadata()); getTestContainer().hasValidMetadata());
}); });
/*
* DataSystem validation
*/
When("^sample JSON data from \"([^\"]*)\" are loaded into the test container$", (String resourceName) -> { When("^sample JSON data from \"([^\"]*)\" are loaded into the test container$", (String resourceName) -> {
getTestContainer().setResponseCode(HttpStatus.SC_OK); getTestContainer().setResponseCode(HttpStatus.SC_OK);
getTestContainer().setResponseData(loadResourceAsString(resourceName)); getTestContainer().setResponseData(loadResourceAsString(resourceName));
}); });
Then("^schema validation passes for the sample DataSystem data$", () -> { Then("^schema validation passes for the sample DataSystem data$", () -> {
assertTrue(getDefaultErrorMessage("expected DataSystem to pass validation, but it failed!"), assertTrue(getDefaultErrorMessage("expected DataSystem to pass validation, but it failed!"),
getTestContainer().validateDataSystem().getIsValidDataSystem()); getTestContainer().validateDataSystem().getIsValidDataSystem());
}); });
Then("^schema validation fails for the sample DataSystem data$", () -> { Then("^schema validation fails for the sample DataSystem data$", () -> {
assertFalse(getDefaultErrorMessage("expected DataSystem to fail validation, but it passed!"), assertFalse(getDefaultErrorMessage("expected DataSystem to fail validation, but it passed!"),
getTestContainer().validateDataSystem().getIsValidDataSystem()); getTestContainer().validateDataSystem().getIsValidDataSystem());
}); });
/*
* Integer Response Testing
*/
Then("^Integer comparisons of \"([^\"]*)\" \"([^\"]*)\" (\\d+) return \"([^\"]*)\"$", (String fieldName, String op, Integer assertedValue, String expectedValue) -> {
final boolean expected = Boolean.parseBoolean(expectedValue),
result = testIntegerComparisons(fieldName, op, assertedValue);
if (expected) {
assertTrue(result);
} else {
assertFalse(result);
}
});
Then("^Integer comparisons of \"([^\"]*)\" \"([^\"]*)\" null return \"([^\"]*)\"$", (String fieldName, String op, String expectedValue) -> {
final boolean expected = Boolean.parseBoolean(expectedValue),
result = testIntegerComparisons(fieldName, op, null);
if (expected) {
assertTrue(result);
} else {
assertFalse(result);
}
});
/*
* String Response Testing
*/
Then("^String data in \"([^\"]*)\" \"([^\"]*)\" \"([^\"]*)\" returns \"([^\"]*)\"$", (String fieldName, String op, String assertedValue, String expectedValue) -> {
final boolean expected = Boolean.parseBoolean(expectedValue),
result = testStringComparisons(fieldName, op, assertedValue);
if (expected) {
assertTrue(result);
} else {
assertFalse(result);
}
});
Then("^String data in \"([^\"]*)\" \"([^\"]*)\" null returns \"([^\"]*)\"$", (String fieldName, String op, String expectedValue) -> {
final boolean expected = Boolean.parseBoolean(expectedValue),
result = testStringComparisons(fieldName, op, null);
if (expected) {
assertTrue(result);
} else {
assertFalse(result);
}
});
Then("^String data in \"([^\"]*)\" \"([^\"]*)\" equals \"([^\"]*)\"$", (String fieldName, String op, String assertedValue) -> {
assertTrue(testStringComparisons(fieldName, op, assertedValue));
});
Then("^String data in \"([^\"]*)\" \"([^\"]*)\" does not equal \"([^\"]*)\"$", (String fieldName, String op, String assertedValue) -> {
assertFalse(testStringComparisons(fieldName, op, assertedValue));
});
Then("^String data in \"([^\"]*)\" \"([^\"]*)\" is null$", (String fieldName, String op) -> {
assertFalse(testStringComparisons(fieldName, op, null));
});
/*
* Timestamp Response Testing
*/
Then("^Timestamp comparisons of \"([^\"]*)\" \"([^\"]*)\" \"([^\"]*)\" return \"([^\"]*)\"$", (String fieldName, String op, String assertedValue, String expectedValue) -> {
final boolean expected = Boolean.parseBoolean(expectedValue),
result = testTimestampComparisons(fieldName, op, assertedValue);
if (expected) {
assertTrue(result);
} else {
assertFalse(result);
}
});
Then("^Timestamp comparisons of \"([^\"]*)\" \"([^\"]*)\" null return \"([^\"]*)\"$", (String fieldName, String op, String expectedValue) -> {
final boolean expected = Boolean.parseBoolean(expectedValue),
result = testTimestampComparisons(fieldName, op, null);
if (expected) {
assertTrue(result);
} else {
assertFalse(result);
}
});
/*
* Date Part Response Testing
*/
Then("^\"([^\"]*)\" comparisons of \"([^\"]*)\" \"([^\"]*)\" (\\d+) return \"([^\"]*)\"$", (String datePart, String fieldName, String op, Integer assertedValue, String expectedValue) -> {
final boolean expected = Boolean.parseBoolean(expectedValue),
result = testDatePartComparisons(datePart, fieldName, op, assertedValue);
if (expected) {
assertTrue(result);
} else {
assertFalse(result);
}
});
Then("^\"([^\"]*)\" comparisons of \"([^\"]*)\" \"([^\"]*)\" null return \"([^\"]*)\"$", (String datePart, String fieldName, String op, String expectedValue) -> {
final boolean expected = Boolean.parseBoolean(expectedValue),
result = testDatePartComparisons(datePart, fieldName, op, null);
if (expected) {
assertTrue(result);
} else {
assertFalse(result);
}
});
}
boolean testStringComparisons(String fieldName, String op, String assertedValue) {
AtomicBoolean result = new AtomicBoolean(false);
//iterate over the items and count the number of fields with data to determine whether there are data present
from(getTestContainer().getResponseData()).getList(JSON_VALUE_PATH, HashMap.class).forEach(item -> {
result.compareAndSet(result.get(), TestUtils.compare((String)item.get(fieldName), op, assertedValue));
});
return result.get();
}
boolean testIntegerComparisons(String fieldName, String op, Integer assertedValue) {
AtomicBoolean result = new AtomicBoolean(false);
//iterate over the items and count the number of fields with data to determine whether there are data present
from(getTestContainer().getResponseData()).getList(JSON_VALUE_PATH, HashMap.class).forEach(item -> {
result.compareAndSet(result.get(), TestUtils.compare((Integer) item.get(fieldName), op, assertedValue));
});
return result.get();
}
boolean testTimestampComparisons(String fieldName, String op, String offsetDateTime) {
AtomicBoolean result = new AtomicBoolean(false);
//iterate over the items and count the number of fields with data to determine whether there are data present
from(getTestContainer().getResponseData()).getList(JSON_VALUE_PATH, HashMap.class).forEach(item -> {
try {
result.compareAndSet(result.get(), TestUtils.compare(
parseTimestampFromEdmDateTimeOffsetString((String)item.get(fieldName)), op,
parseTimestampFromEdmDateTimeOffsetString(offsetDateTime)));
} catch (Exception ex) {
fail(getDefaultErrorMessage(ex));
}
});
return result.get();
}
boolean testDatePartComparisons(String datePart, String fieldName, String op, Integer assertedValue) {
AtomicBoolean result = new AtomicBoolean(false);
from(getTestContainer().getResponseData()).getList(JSON_VALUE_PATH, HashMap.class).forEach(item -> {
try {
result.compareAndSet(result.get(), TestUtils.compare(TestUtils.getTimestampPart(datePart, item.get(fieldName)), op, assertedValue));
} catch (Exception ex) {
fail(getDefaultErrorMessage(ex));
}});
return result.get();
} }
/** /**

View File

@ -35,7 +35,7 @@ public class TestXMLAndMetadataValidation implements En {
* Background * Background
*/ */
Given("^an OData test client has been created$", () -> { Given("^an OData test client has been created$", () -> {
commander.set(Commander.Builder.class.newInstance().build()); commander.set(new Commander.Builder().build());
}); });
@ -66,7 +66,7 @@ public class TestXMLAndMetadataValidation implements En {
assertTrue(getDefaultErrorMessage("expected XML validation to succeed but it failed!"), isXMLValid.get()); assertTrue(getDefaultErrorMessage("expected XML validation to succeed but it failed!"), isXMLValid.get());
}); });
Then("^XML validation fails$", () -> { Then("^XML validation fails$", () -> {
assertFalse(getDefaultErrorMessage("expected XML validation to succeed but it failed!"), isXMLValid.get()); assertFalse(getDefaultErrorMessage("expected XML validation to fail but it succeeded!"), isXMLValid.get());
}); });

View File

@ -0,0 +1,9 @@
{
"@odata.context": "https://test.reso.org",
"value": [
{
"ListingKeyNumeric": 1,
"BedroomsTotal": null
}
]
}

View File

@ -0,0 +1,9 @@
{
"@odata.context": "https://test.reso.org",
"value": [
{
"ListingKeyNumeric": 1,
"BedroomsTotal": 5
}
]
}

View File

@ -0,0 +1,9 @@
{
"@odata.context": "https://test.reso.org",
"value": [
{
"ListingKeyNumeric": 1,
"StreetName": null
}
]
}

View File

@ -0,0 +1,9 @@
{
"@odata.context": "https://test.reso.org",
"value": [
{
"ListingKeyNumeric": 1,
"StreetName": "Main"
}
]
}

View File

@ -0,0 +1,9 @@
{
"@odata.context": "https://test.reso.org",
"value": [
{
"ListingKeyNumeric": 1,
"ModificationTimestamp": null
}
]
}

View File

@ -0,0 +1,9 @@
{
"@odata.context": "https://test.reso.org",
"value": [
{
"ListingKeyNumeric": 1,
"ModificationTimestamp": "2020-04-02T02:02:02.02Z"
}
]
}