Date comparisons through REQ-WA103-QO24, fractional seconds comparisons
This commit is contained in:
parent
d412f0bdd4
commit
521920a1f8
Binary file not shown.
1500
generic.resoscript
1500
generic.resoscript
File diff suppressed because it is too large
Load Diff
|
@ -244,4 +244,84 @@ Feature: Web API Server 1.0.2 Certification
|
||||||
Then the server responds with a status code of 200
|
Then the server responds with a status code of 200
|
||||||
And the response is valid JSON
|
And the response is valid JSON
|
||||||
And the response has results
|
And the response has results
|
||||||
And DateTimeOffset data in "Parameter_TimestampField" is sorted in "desc" order
|
And DateTimeOffset data in "Parameter_TimestampField" is sorted in "desc" order
|
||||||
|
|
||||||
|
@REQ-WA103-QO18.1 @gold @2.4.4 @filterability-endorsement
|
||||||
|
Scenario: Query Support: $filter: Date: year
|
||||||
|
When a GET request is made to the resolved Url in "REQ-WA103-QO18.1"
|
||||||
|
Then the server responds with a status code of 200
|
||||||
|
And the response is valid JSON
|
||||||
|
And the response has results
|
||||||
|
And "year" data in Date Field "Parameter_DateField" "eq" "Parameter_YearValue"
|
||||||
|
|
||||||
|
@REQ-WA103-QO18.2 @gold @2.4.4 @filterability-endorsement
|
||||||
|
Scenario: Query Support: $filter: Date: year comparison with timestamp
|
||||||
|
When a GET request is made to the resolved Url in "REQ-WA103-QO18.2"
|
||||||
|
Then the server responds with a status code of 200
|
||||||
|
And the response is valid JSON
|
||||||
|
And the response has results
|
||||||
|
And "year" data in Timestamp Field "Parameter_TimestampField" "eq" "Parameter_YearValue"
|
||||||
|
|
||||||
|
@REQ-WA103-QO19.1 @gold @2.4.4 @filterability-endorsement
|
||||||
|
Scenario: Query Support: $filter: Date: month
|
||||||
|
When a GET request is made to the resolved Url in "REQ-WA103-QO19.1"
|
||||||
|
Then the server responds with a status code of 200
|
||||||
|
And the response is valid JSON
|
||||||
|
And the response has results
|
||||||
|
And "month" data in Date Field "Parameter_DateField" "eq" "Parameter_MonthValue"
|
||||||
|
|
||||||
|
@REQ-WA103-QO19.2 @gold @2.4.4 @filterability-endorsement
|
||||||
|
Scenario: Query Support: $filter: Date: month comparison with timestamp
|
||||||
|
When a GET request is made to the resolved Url in "REQ-WA103-QO19.2"
|
||||||
|
Then the server responds with a status code of 200
|
||||||
|
And the response is valid JSON
|
||||||
|
And the response has results
|
||||||
|
And "month" data in Timestamp Field "Parameter_TimestampField" "eq" "Parameter_MonthValue"
|
||||||
|
|
||||||
|
@REQ-WA103-QO20.1 @gold @2.4.4 @filterability-endorsement
|
||||||
|
Scenario: Query Support: $filter: Date: day
|
||||||
|
When a GET request is made to the resolved Url in "REQ-WA103-QO20.1"
|
||||||
|
Then the server responds with a status code of 200
|
||||||
|
And the response is valid JSON
|
||||||
|
And the response has results
|
||||||
|
And "day" data in Date Field "Parameter_DateField" "eq" "Parameter_DayValue"
|
||||||
|
|
||||||
|
@REQ-WA103-QO20.2 @gold @2.4.4 @filterability-endorsement
|
||||||
|
Scenario: Query Support: $filter: Date: day comparison with timestamp
|
||||||
|
When a GET request is made to the resolved Url in "REQ-WA103-QO20.2"
|
||||||
|
Then the server responds with a status code of 200
|
||||||
|
And the response is valid JSON
|
||||||
|
And the response has results
|
||||||
|
And "day" data in Timestamp Field "Parameter_TimestampField" "eq" "Parameter_DayValue"
|
||||||
|
|
||||||
|
@REQ-WA103-QO21 @gold @2.4.4 @filterability-endorsement
|
||||||
|
Scenario: Query Support: $filter: Date: hour comparison with timestamp
|
||||||
|
When a GET request is made to the resolved Url in "REQ-WA103-QO21"
|
||||||
|
Then the server responds with a status code of 200
|
||||||
|
And the response is valid JSON
|
||||||
|
And the response has results
|
||||||
|
And "hour" data in Timestamp Field "Parameter_TimestampField" "eq" "Parameter_HourValue"
|
||||||
|
|
||||||
|
@REQ-WA103-QO22 @gold @2.4.4 @filterability-endorsement
|
||||||
|
Scenario: Query Support: $filter: Date: minute comparison with timestamp
|
||||||
|
When a GET request is made to the resolved Url in "REQ-WA103-QO22"
|
||||||
|
Then the server responds with a status code of 200
|
||||||
|
And the response is valid JSON
|
||||||
|
And the response has results
|
||||||
|
And "minute" data in Timestamp Field "Parameter_TimestampField" "gt" "Parameter_MinuteValue"
|
||||||
|
|
||||||
|
@REQ-WA103-QO23 @gold @2.4.4 @filterability-endorsement
|
||||||
|
Scenario: Query Support: $filter: Date: second comparison with timestamp
|
||||||
|
When a GET request is made to the resolved Url in "REQ-WA103-QO23"
|
||||||
|
Then the server responds with a status code of 200
|
||||||
|
And the response is valid JSON
|
||||||
|
And the response has results
|
||||||
|
And "second" data in Timestamp Field "Parameter_TimestampField" "lt" "Parameter_SecondValue"
|
||||||
|
|
||||||
|
@REQ-WA103-QO24 @gold @2.4.4 @filterability-endorsement
|
||||||
|
Scenario: Query Support: $filter: Date: fractional seconds comparison with timestamp
|
||||||
|
When a GET request is made to the resolved Url in "REQ-WA103-QO24"
|
||||||
|
Then the server responds with a status code of 200
|
||||||
|
And the response is valid JSON
|
||||||
|
And the response has results
|
||||||
|
And "fractional" data in Timestamp Field "Parameter_TimestampField" "lt" "Parameter_FractionalValue"
|
|
@ -28,7 +28,7 @@ import java.io.*;
|
||||||
import java.net.URI;
|
import java.net.URI;
|
||||||
import java.sql.Time;
|
import java.sql.Time;
|
||||||
import java.sql.Timestamp;
|
import java.sql.Timestamp;
|
||||||
import java.time.Instant;
|
import java.time.*;
|
||||||
import java.util.*;
|
import java.util.*;
|
||||||
import java.util.concurrent.atomic.AtomicBoolean;
|
import java.util.concurrent.atomic.AtomicBoolean;
|
||||||
import java.util.concurrent.atomic.AtomicInteger;
|
import java.util.concurrent.atomic.AtomicInteger;
|
||||||
|
@ -500,6 +500,11 @@ public class WebAPIServer_1_0_2 implements En {
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Year comparison glue
|
||||||
|
*/
|
||||||
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Timestamp comparison glue
|
* Timestamp comparison glue
|
||||||
*/
|
*/
|
||||||
|
@ -592,6 +597,60 @@ public class WebAPIServer_1_0_2 implements En {
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
|
And("^\"([^\"]*)\" data in Date Field \"([^\"]*)\" \"([^\"]*)\" \"([^\"]*)\"$", (String stringDatePart, String parameterFieldName, String op, String parameterAssertedValue) -> {
|
||||||
|
String fieldName = Settings.resolveParametersString(parameterFieldName, settings);
|
||||||
|
AtomicReference<Integer> fieldValue = new AtomicReference<>();
|
||||||
|
AtomicInteger assertedValue = new AtomicInteger();
|
||||||
|
AtomicReference<String> datePart = new AtomicReference<>(stringDatePart.toLowerCase());
|
||||||
|
|
||||||
|
try {
|
||||||
|
assertedValue.set(Integer.parseInt(Settings.resolveParametersString(parameterAssertedValue, settings)));
|
||||||
|
LOG.info("Asserted value is: " + assertedValue.get());
|
||||||
|
|
||||||
|
from(responseData.get()).getList(JSON_VALUE_PATH, HashMap.class).forEach(item -> {
|
||||||
|
try {
|
||||||
|
fieldValue.set(Utils.getDatePart(datePart.get(), item.get(fieldName)));
|
||||||
|
assertTrue(Utils.compare(fieldValue.get(), op, assertedValue.get()));
|
||||||
|
} catch (Exception ex){
|
||||||
|
//fail();
|
||||||
|
LOG.error("ERROR: exception thrown." + ex);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
} catch (Exception ex) {
|
||||||
|
fail();
|
||||||
|
LOG.error("ERROR: exception thrown." + ex);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Year comparison from Timestamp Field
|
||||||
|
* TODO: consolidate with Year comparison with Date Field
|
||||||
|
*/
|
||||||
|
And("^\"([^\"]*)\" data in Timestamp Field \"([^\"]*)\" \"([^\"]*)\" \"([^\"]*)\"$", (String stringDatePart, String parameterFieldName, String op, String parameterAssertedValue) -> {
|
||||||
|
String fieldName = Settings.resolveParametersString(parameterFieldName, settings);
|
||||||
|
AtomicReference<Integer> fieldValue = new AtomicReference<>();
|
||||||
|
AtomicReference<Integer> assertedValue = new AtomicReference<>();
|
||||||
|
AtomicReference<String> datePart = new AtomicReference<>(stringDatePart.toLowerCase());
|
||||||
|
|
||||||
|
try {
|
||||||
|
assertedValue.set(Integer.parseInt(Settings.resolveParametersString(parameterAssertedValue, settings)));
|
||||||
|
LOG.info("Asserted value is: " + assertedValue.get().toString());
|
||||||
|
|
||||||
|
from(responseData.get()).getList(JSON_VALUE_PATH, HashMap.class).forEach(item -> {
|
||||||
|
try {
|
||||||
|
fieldValue.set(Utils.getTimestampPart(datePart.get(), item.get(fieldName).toString()));
|
||||||
|
assertTrue(Utils.compare(fieldValue.get(), op, assertedValue.get()));
|
||||||
|
} catch (Exception ex){
|
||||||
|
fail();
|
||||||
|
LOG.error("ERROR: exception thrown." + ex);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
} catch (Exception ex) {
|
||||||
|
fail();
|
||||||
|
LOG.error("ERROR: exception thrown." + ex);
|
||||||
|
}
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -609,6 +668,17 @@ public class WebAPIServer_1_0_2 implements En {
|
||||||
LESS_THAN_OR_EQUAL = "le";
|
LESS_THAN_OR_EQUAL = "le";
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private static class DateParts {
|
||||||
|
private static final String
|
||||||
|
YEAR = "year",
|
||||||
|
MONTH = "month",
|
||||||
|
DAY = "day",
|
||||||
|
HOUR = "hour",
|
||||||
|
MINUTE = "minute",
|
||||||
|
SECOND = "second",
|
||||||
|
FRACTIONAL = "fractional";
|
||||||
|
}
|
||||||
|
|
||||||
private static class Utils {
|
private static class Utils {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -708,6 +778,34 @@ public class WebAPIServer_1_0_2 implements En {
|
||||||
return 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
|
||||||
|
*/
|
||||||
|
private 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);
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Time Comparator
|
* Time Comparator
|
||||||
* @param lhs Time to compare
|
* @param lhs Time to compare
|
||||||
|
@ -860,6 +958,57 @@ public class WebAPIServer_1_0_2 implements En {
|
||||||
return EdmDateTimeOffset.getInstance().valueOfString(edmDateTimeOffsetString, true, null, null, null, null, Date.class);
|
return EdmDateTimeOffset.getInstance().valueOfString(edmDateTimeOffsetString, true, null, null, null, null, Date.class);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/***
|
||||||
|
* Tries to parse datePart from the given Object value
|
||||||
|
* @param datePart the timestamp part, "Year", "Month", "Day", etc. 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
|
||||||
|
* @exception throws an exception if value cannot be parsed into a date.
|
||||||
|
*/
|
||||||
|
private static Integer getDatePart(String datePart, Object value) throws EdmPrimitiveTypeException {
|
||||||
|
LocalDate date = LocalDate.parse(parseDateFromEdmDateString(value.toString()).toString());
|
||||||
|
switch (datePart) {
|
||||||
|
case DateParts.YEAR:
|
||||||
|
return date.getYear();
|
||||||
|
case DateParts.MONTH:
|
||||||
|
return date.getMonthValue();
|
||||||
|
case DateParts.DAY:
|
||||||
|
return date.getDayOfMonth();
|
||||||
|
default:
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/***
|
||||||
|
* Tries to parse datePart from the given Object value
|
||||||
|
* @param timestampPart the timestamp part, "Year", "Month", "Day", etc. 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
|
||||||
|
*/
|
||||||
|
private static Integer getTimestampPart(String timestampPart, Object value) throws EdmPrimitiveTypeException {
|
||||||
|
//Turns nanoseconds into two most significant 2 digits for fractional comparisons
|
||||||
|
Integer ADJUSTMENT_FACTOR = 10000000;
|
||||||
|
OffsetDateTime offsetDateTime = OffsetDateTime.parse(value.toString());
|
||||||
|
|
||||||
|
if (timestampPart.equals(DateParts.YEAR)) {
|
||||||
|
return offsetDateTime.getYear();
|
||||||
|
} else if (timestampPart.equals(DateParts.MONTH)) {
|
||||||
|
return offsetDateTime.getMonthValue();
|
||||||
|
} else if (timestampPart.equals(DateParts.DAY)) {
|
||||||
|
return offsetDateTime.getDayOfMonth();
|
||||||
|
} else if (timestampPart.equals(DateParts.HOUR)) {
|
||||||
|
return offsetDateTime.getHour();
|
||||||
|
} else if (timestampPart.equals(DateParts.MINUTE)) {
|
||||||
|
return offsetDateTime.getMinute();
|
||||||
|
} else if (timestampPart.equals(DateParts.SECOND)) {
|
||||||
|
return offsetDateTime.getSecond();
|
||||||
|
} else if (timestampPart.equals(DateParts.FRACTIONAL)) {
|
||||||
|
return offsetDateTime.getNano() / ADJUSTMENT_FACTOR;
|
||||||
|
} else {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Converts the given inputStream to a string.
|
* Converts the given inputStream to a string.
|
||||||
* @param inputStream the input stream to convert.
|
* @param inputStream the input stream to convert.
|
||||||
|
|
Loading…
Reference in New Issue