package com.sas.unravl.assertions;
import com.fasterxml.jackson.databind.JsonNode;
import com.fasterxml.jackson.databind.node.ObjectNode;
import com.sas.unravl.ApiCall;
import com.sas.unravl.UnRAVL;
import com.sas.unravl.UnRAVLException;
import com.sas.unravl.annotations.UnRAVLAssertionPlugin;
import com.sas.unravl.util.Json;
/**
* StatusAssertion asserts that the API call returned an HTTP status code that
* matches the specification. There are three possible forms for this assertion:
*
* <pre>
* { "status" : int }
* { "status" : [ int, int, ..., int ] }
* { "status" : "<em>pattern</em>" }
* </pre>
*
* In the first form, the status must match the given int value exactly. <br>
* Example: <code>{ "status" : 200 }</code>
* <p>
* In the second, the HTTP status code must match one of the int values. The int
* values must be greater than or equal to 100 and less than 600. <br>
* Example: <code>{ "status" : 200, 201, 204 }</code>
* </p>
* <p>
* In the third, the string representation of the status code must regular
* expression pattern. This is the "default" assertion. <br>
* Example: <code>{ "status" : "2.." }</code>
* </p>
* <p>
* If an UnRAVL script has no "status" assertion, an implicit assertion of <br>
* <code>{ "status" : "2.." }</code><br>
* is applied, which matches all 200-level status codes.
* </p>
*
* @author David.Biesack@sas.com
*
*/
@UnRAVLAssertionPlugin("status")
public class StatusAssertion extends BaseUnRAVLAssertion {
@Override
public void check(UnRAVL current, ObjectNode assertion, Stage when,
ApiCall call) throws UnRAVLAssertionException, UnRAVLException {
super.check(current, assertion, when, call);
int httpStatus = call.getHttpStatus();
boolean found = false;
JsonNode statusCodes = Json.firstFieldValue(assertion);
if (statusCodes.isTextual()) {
found |= check(statusCodes.textValue(), httpStatus);
} else if (statusCodes.isArray()) {
for (JsonNode j : Json.array(statusCodes))
found |= check(j, httpStatus);
} else
found = check(statusCodes, httpStatus);
if (!found)
throw new UnRAVLAssertionException("Actual HTTP status code "
+ httpStatus + " did not match the expected status, "
+ statusCodes);
return;
}
private boolean check(String pattern, int httpStatus)
throws UnRAVLAssertionException {
return Integer.toString(httpStatus).matches(pattern);
}
private boolean check(JsonNode j, int httpStatus) throws UnRAVLException {
if (j.isInt()) {
int expected = j.intValue();
if (j.intValue() >= 100 && j.intValue() < 600)
return expected == httpStatus;
}
throw new UnRAVLException(
"status assertion must use integer values between 100 and 599");
}
}