Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Feature/823 integration tests iso datetime #825

Merged
merged 5 commits into from
Dec 3, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
14 changes: 14 additions & 0 deletions api-rest/src/test/java/com/homihq/db2rest/BaseIntegrationTest.java
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
import lombok.extern.slf4j.Slf4j;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.extension.ExtendWith;
import org.junit.jupiter.params.provider.Arguments;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.autoconfigure.web.servlet.AutoConfigureMockMvc;
import org.springframework.boot.test.context.SpringBootTest;
Expand All @@ -19,6 +20,7 @@

import java.io.IOException;
import java.nio.file.Paths;
import java.util.List;

import static org.springframework.restdocs.mockmvc.MockMvcRestDocumentation.documentationConfiguration;

Expand Down Expand Up @@ -61,4 +63,16 @@ void setupEnv() {
}
}
}

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

There are many possible valid ISO date formats. We can add a few more of these also where the dialects have support out-of-the-box, and adjust test response expectations accordingly for each dialect (since many of these tests will fail without EDTF extension support in the database):

  • 1999.008 valid year and date in PostgreSQL
  • J2451187 valid Julian date in PostgreSQL
  • January 8, 99 BC valid year 99 BC in PostgreSQL
  • 040506 valid ISO 8601 Time input in PostgreSQL
  • 040506+07:30:00 valid UTF offset specified to seconds (not allowed in ISO 8601) but valid Time input in PostgreSQL
  • infinity valid special Date/Time input in PostgreSQL which is internally represented as math ∞ but displayed as infinity.
  • allballs special Date/Time input in PostgreSQL that represents new day in UTC 00:00:00.00 UTC
  • Reduced precision: 2019-12
  • Ordinal Date: 2024-336 this depends on the installation config of some DB's but it's generally supported.
  • UTC: T144515Z

Repeating intervals might also be stored? but I think this is only special DB modes and like T-SQL.

  • R5/2008-03-01T13:00:00Z/P1Y2M10DT2H30M
  • P1Y2M10DT2H30M a valid interval in PostgreSQL and others support intervals
    • time, timestamp, and interval accept an optional precision value p which specifies the number of fractional digits retained in the seconds field. By default, there is no explicit bound on precision. The allowed range of p is from 0 to 6.

These are Extended Date Time Formats, but most are not supported in regular modes with the dialects

  • 1964/2008 is a time interval with calendar year precision, beginning sometime in 1964 and ending sometime in 2008.
  • Y-170000002 is the year -170000002
  • 2001-21 is Spring, 2001 (values of 21,22,23,24 signify 'Spring', 'Summer', 'Autumn', 'Winter' and found sometimes in edge network monitoring stations and scientific datasets.
  • 2004-06-11% is a year-month-date with uncertainty and approximation.
  • 1988/.. open end time interval starting at year 1985 with year precision and open ending.
  • /1988 unknown start and ending year 1985.
  • 1950S2 represents some year between 1900 and 1999, estimated to be 1950
  • 156X-12-25 December 25 sometime during the 1560s.

ERRORS:
-1985 ISO 8601 Part 1 does not support negative years.

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Or... we can convert the above into a new issue :-) and merge your PR as-is :-)

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@thadguidry - Lets create an issue and merge the PR. Java will not be able to handle so many formats and we will have to write utils to handle every possible scenario. This can be done based on demand from users.

static List<Arguments> isoDateTimeFormats() {
return List.of(Arguments.of("2011-12-03T10:15:30"),
Arguments.of("2011-12-03T10:15:30.123"),
Arguments.of("2011-12-03T10:15:30+01:00"),
Arguments.of("2011-12-03T10:15:30-05:00"),
Arguments.of("2011-12-03T10:15:30Z"),
Arguments.of("2011-12-03T10:15:30.123Z"),
Arguments.of("2011-12-03T10:15:30.123+05:30"),
Arguments.of("2011-12-03T10:15:30+01:00[Europe/Paris]"),
Arguments.of("2011-12-03T10:15:30.123+01:00[Europe/Paris]"));
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -60,8 +60,8 @@ void create() throws Exception {
//.andDo(print())
.andExpect(status().isCreated())
.andExpect(jsonPath("$.row", equalTo(1)))
//.andExpect(jsonPath("$.keys.GENERATED_KEY").exists())
//.andExpect(jsonPath("$.keys.GENERATED_KEY", equalTo(5)))
.andExpect(jsonPath("$.keys.insert_id").exists())
.andExpect(jsonPath("$.keys.insert_id", equalTo(5)))
.andDo(document("mariadb-create-a-film"));
}

Expand Down Expand Up @@ -99,8 +99,8 @@ void createDirectorWithTSIDEnabled() throws Exception {
//.andDo(print())
.andExpect(status().isCreated())
.andExpect(jsonPath("$.row", equalTo(1)))
//.andExpect(jsonPath("$.keys.director_id").exists())
// .andExpect(jsonPath("$.keys.director_id").isNumber())
.andExpect(jsonPath("$.keys.director_id").exists())
.andExpect(jsonPath("$.keys.director_id").isNumber())
.andDo(document("mariadb-create-a-director-tsid-enabled"));
}

Expand Down Expand Up @@ -128,8 +128,8 @@ void createVanityVanWithVarcharTsIdType() throws Exception {
.andDo(print())
.andExpect(status().isCreated())
.andExpect(jsonPath("$.row", equalTo(1)))
//.andExpect(jsonPath("$.keys.vanity_van_id").exists())
//.andExpect(jsonPath("$.keys.vanity_van_id").isString())
.andExpect(jsonPath("$.keys.van_id").exists())
.andExpect(jsonPath("$.keys.van_id").isString())
.andDo(document("mariadb-create-a-vanity-van-tsid-varchar"));
}

Expand All @@ -144,7 +144,7 @@ void createFilmWithSubsetOfColumns() throws Exception {
.andExpect(status().isCreated())
.andExpect(jsonPath("$.row", equalTo(1)))
.andExpect(jsonPath("$.keys").exists())
// .andExpect(jsonPath("$.keys.GENERATED_KEY", equalTo(5)))
//.andExpect(jsonPath("$.keys.insert_id", equalTo(5)))
.andExpect(jsonPath("$.keys.insert_id").isNumber())
.andDo(document("mariadb-create-a-film"))
.andReturn();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,20 +5,24 @@
import com.fasterxml.jackson.datatype.jsr310.JavaTimeModule;
import com.homihq.db2rest.MariaDBBaseIntegrationTest;
import com.homihq.db2rest.rest.DateTimeUtil;
import com.jayway.jsonpath.JsonPath;
import org.junit.jupiter.api.ClassOrderer;
import org.junit.jupiter.api.DisplayName;
import org.junit.jupiter.api.MethodOrderer;
import org.junit.jupiter.api.Order;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.TestClassOrder;
import org.junit.jupiter.api.TestMethodOrder;
import org.junit.jupiter.params.ParameterizedTest;
import org.junit.jupiter.params.provider.MethodSource;

import java.util.HashMap;
import java.util.Map;

import static com.homihq.db2rest.jdbc.rest.RdbmsRestApi.VERSION;
import static org.hamcrest.Matchers.equalTo;
import static org.junit.jupiter.api.Assertions.assertEquals;
import static org.junit.jupiter.api.Assertions.assertTrue;
import static org.springframework.http.MediaType.APPLICATION_JSON;
import static org.springframework.restdocs.mockmvc.MockMvcRestDocumentation.document;
import static org.springframework.restdocs.mockmvc.RestDocumentationRequestBuilders.delete;
Expand Down Expand Up @@ -142,4 +146,28 @@ void deleteActorByTimeStamp() throws Exception {
.andExpect(jsonPath("$.rows", equalTo(1)))
.andDo(document("mariadb-delete-an-actor-by-timestamp"));
}

@ParameterizedTest
@MethodSource("isoDateTimeFormats")
@Order(5)
@DisplayName("Test ISO Date Time formats")
void createActorWithIsoDateTimeFormats(String isoDateTime) throws Exception {
// Prepare the request with datetime fields
Map<String, Object> actorRequestWithDateTime = new HashMap<>();
actorRequestWithDateTime.put("first_name", "Graeme");
actorRequestWithDateTime.put("last_name", "Smith");
actorRequestWithDateTime.put("last_update", isoDateTime);

var result = mockMvc.perform(post(VERSION + "/mariadb/actor")
.contentType(APPLICATION_JSON)
.accept(APPLICATION_JSON)
.content(objectMapper.writeValueAsString(actorRequestWithDateTime)))
.andExpect(status().isCreated())
.andExpect(jsonPath("$.row", equalTo(1)))
.andDo(document("mariadb-create-an-actor-with-datetime"))
.andReturn();

var pk = JsonPath.read(result.getResponse().getContentAsString(), "$.keys.insert_id");
assertTrue(deleteRow("actor", "actor_id", (int) pk));
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,9 @@
import com.fasterxml.jackson.datatype.jsr310.JavaTimeModule;
import com.homihq.db2rest.BaseIntegrationTest;
import com.homihq.db2rest.MsSQLServerContainerConfiguration;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Import;
import org.springframework.jdbc.core.JdbcTemplate;
import org.springframework.test.context.ActiveProfiles;

import static com.homihq.db2rest.jdbc.rest.RdbmsRestApi.VERSION;
Expand All @@ -17,10 +19,18 @@ class MsSQLBaseIntegrationTest extends BaseIntegrationTest {
protected static final String TEST_JSON_FOLDER = "/testdata";
protected static final String DB_NAME = "mssql";

@Autowired
private JdbcTemplate jdbcTemplate;

@WithJacksonMapper
protected ObjectMapper objectMapper = new ObjectMapper().registerModule(new JavaTimeModule());

protected String getPrefixApiUrl() {
return VERSION + "/" + DB_NAME;
}

protected boolean deleteRow(String table, String column, int id) {
var query = "DELETE FROM " + table + " WHERE " + column + " = ?";
return jdbcTemplate.update(query, id) == 1;
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,53 @@
package com.homihq.db2rest.rest.mssql;

import com.jayway.jsonpath.JsonPath;
import org.junit.jupiter.api.ClassOrderer;
import org.junit.jupiter.api.DisplayName;
import org.junit.jupiter.api.MethodOrderer;
import org.junit.jupiter.api.Order;
import org.junit.jupiter.api.TestClassOrder;
import org.junit.jupiter.api.TestMethodOrder;
import org.junit.jupiter.params.ParameterizedTest;
import org.junit.jupiter.params.provider.MethodSource;

import java.util.HashMap;
import java.util.Map;

import static com.homihq.db2rest.jdbc.rest.RdbmsRestApi.VERSION;
import static org.hamcrest.Matchers.equalTo;
import static org.junit.jupiter.api.Assertions.assertTrue;
import static org.springframework.http.MediaType.APPLICATION_JSON;
import static org.springframework.restdocs.mockmvc.MockMvcRestDocumentation.document;
import static org.springframework.restdocs.mockmvc.RestDocumentationRequestBuilders.post;
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.jsonPath;
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status;

@TestClassOrder(ClassOrderer.OrderAnnotation.class)
@Order(506)
@TestMethodOrder(MethodOrderer.OrderAnnotation.class)
class MsSQLDateTimeAllTest extends MsSQLBaseIntegrationTest {

@ParameterizedTest
@MethodSource("isoDateTimeFormats")
@Order(1)
@DisplayName("Test ISO Date Time formats")
void createActorWithIsoDateTimeFormats(String isoDateTime) throws Exception {
// Prepare the request with datetime fields
Map<String, Object> actorRequestWithDateTime = new HashMap<>();
actorRequestWithDateTime.put("first_name", "Graeme");
actorRequestWithDateTime.put("last_name", "Smith");
actorRequestWithDateTime.put("last_update", isoDateTime);

var result = mockMvc.perform(post(VERSION + "/mssql/actor")
.contentType(APPLICATION_JSON)
.accept(APPLICATION_JSON)
.content(objectMapper.writeValueAsString(actorRequestWithDateTime)))
.andExpect(status().isCreated())
.andExpect(jsonPath("$.row", equalTo(1)))
.andDo(document("mssql-create-an-actor-with-datetime"))
.andReturn();

var pk = JsonPath.read(result.getResponse().getContentAsString(), "$.keys.GENERATED_KEYS");
assertTrue(deleteRow("actor", "actor_id", (int) pk));
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -5,20 +5,24 @@
import com.fasterxml.jackson.datatype.jsr310.JavaTimeModule;
import com.homihq.db2rest.MySQLBaseIntegrationTest;
import com.homihq.db2rest.rest.DateTimeUtil;
import com.jayway.jsonpath.JsonPath;
import org.junit.jupiter.api.ClassOrderer;
import org.junit.jupiter.api.DisplayName;
import org.junit.jupiter.api.MethodOrderer;
import org.junit.jupiter.api.Order;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.TestClassOrder;
import org.junit.jupiter.api.TestMethodOrder;
import org.junit.jupiter.params.ParameterizedTest;
import org.junit.jupiter.params.provider.MethodSource;

import java.util.HashMap;
import java.util.Map;

import static com.homihq.db2rest.jdbc.rest.RdbmsRestApi.VERSION;
import static org.hamcrest.Matchers.equalTo;
import static org.junit.jupiter.api.Assertions.assertEquals;
import static org.junit.jupiter.api.Assertions.assertTrue;
import static org.springframework.http.MediaType.APPLICATION_JSON;
import static org.springframework.restdocs.mockmvc.MockMvcRestDocumentation.document;
import static org.springframework.restdocs.mockmvc.RestDocumentationRequestBuilders.delete;
Expand Down Expand Up @@ -140,4 +144,28 @@ void deleteActorByTimeStamp() throws Exception {
.andExpect(jsonPath("$.rows", equalTo(1)))
.andDo(document("mysql-delete-an-actor-by-timestamp"));
}

@ParameterizedTest
@MethodSource("isoDateTimeFormats")
@Order(5)
@DisplayName("Test ISO Date Time formats")
void createActorWithIsoDateTimeFormats(String isoDateTime) throws Exception {
// Prepare the request with datetime fields
Map<String, Object> actorRequestWithDateTime = new HashMap<>();
actorRequestWithDateTime.put("first_name", "Graeme");
actorRequestWithDateTime.put("last_name", "Smith");
actorRequestWithDateTime.put("last_update", isoDateTime);

var result = mockMvc.perform(post(VERSION + "/mysqldb/actor")
.contentType(APPLICATION_JSON)
.accept(APPLICATION_JSON)
.content(objectMapper.writeValueAsString(actorRequestWithDateTime)))
.andExpect(status().isCreated())
.andExpect(jsonPath("$.row", equalTo(1)))
.andDo(document("mysql-create-an-actor-with-datetime"))
.andReturn();

var pk = JsonPath.read(result.getResponse().getContentAsString(), "$.keys.GENERATED_KEY");
assertTrue(deleteRow("actor", "actor_id", (int) pk));
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -5,20 +5,26 @@
import com.fasterxml.jackson.datatype.jsr310.JavaTimeModule;
import com.homihq.db2rest.OracleBaseIntegrationTest;
import com.homihq.db2rest.rest.DateTimeUtil;
import com.jayway.jsonpath.JsonPath;
import org.junit.jupiter.api.ClassOrderer;
import org.junit.jupiter.api.DisplayName;
import org.junit.jupiter.api.MethodOrderer;
import org.junit.jupiter.api.Order;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.TestClassOrder;
import org.junit.jupiter.api.TestMethodOrder;
import org.junit.jupiter.params.ParameterizedTest;
import org.junit.jupiter.params.provider.Arguments;
import org.junit.jupiter.params.provider.MethodSource;

import java.util.HashMap;
import java.util.List;
import java.util.Map;

import static com.homihq.db2rest.jdbc.rest.RdbmsRestApi.VERSION;
import static org.hamcrest.Matchers.equalTo;
import static org.junit.jupiter.api.Assertions.assertEquals;
import static org.junit.jupiter.api.Assertions.assertTrue;
import static org.springframework.http.MediaType.APPLICATION_JSON;
import static org.springframework.restdocs.mockmvc.MockMvcRestDocumentation.document;
import static org.springframework.restdocs.mockmvc.RestDocumentationRequestBuilders.delete;
Expand Down Expand Up @@ -144,4 +150,30 @@ void deleteActorByTimeStamp() throws Exception {
.andExpect(jsonPath("$.rows", equalTo(1)))
.andDo(document("oracle-delete-an-actor-by-timestamp"));
}

@ParameterizedTest
@MethodSource("isoDateTimeFormats")
@Order(5)
@DisplayName("Test ISO Date Time formats")
void createActorWithIsoDateTimeFormats(String isoDateTime) throws Exception {
// Prepare the request with datetime fields
Map<String, Object> actorRequestWithDateTime = new HashMap<>();
actorRequestWithDateTime.put("first_name", "Graeme");
actorRequestWithDateTime.put("last_name", "Smith");
actorRequestWithDateTime.put("last_update", isoDateTime);
var result = mockMvc.perform(post(VERSION + "/oradb/ACTOR")
.queryParam("sequences", "actor_id:actor_sequence")
.contentType(APPLICATION_JSON)
.accept(APPLICATION_JSON)
.content(objectMapper.writeValueAsString(actorRequestWithDateTime)))
.andDo(print())
.andExpect(status().isCreated())
.andExpect(jsonPath("$.row", equalTo(1)))
.andDo(document("oracle-create-an-actor-with-datetime"))
.andReturn();

var pk = JsonPath.read(result.getResponse().getContentAsString(), "$.keys.ACTOR_ID");
assertTrue(deleteRow("actor", "actor_id", (int) pk));
}

}
Original file line number Diff line number Diff line change
Expand Up @@ -5,20 +5,24 @@
import com.fasterxml.jackson.datatype.jsr310.JavaTimeModule;
import com.homihq.db2rest.PostgreSQLBaseIntegrationTest;
import com.homihq.db2rest.rest.DateTimeUtil;
import com.jayway.jsonpath.JsonPath;
import org.junit.jupiter.api.ClassOrderer;
import org.junit.jupiter.api.DisplayName;
import org.junit.jupiter.api.MethodOrderer;
import org.junit.jupiter.api.Order;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.TestClassOrder;
import org.junit.jupiter.api.TestMethodOrder;
import org.junit.jupiter.params.ParameterizedTest;
import org.junit.jupiter.params.provider.MethodSource;

import java.util.HashMap;
import java.util.Map;

import static com.homihq.db2rest.jdbc.rest.RdbmsRestApi.VERSION;
import static org.hamcrest.Matchers.equalTo;
import static org.junit.jupiter.api.Assertions.assertEquals;
import static org.junit.jupiter.api.Assertions.assertTrue;
import static org.springframework.http.MediaType.APPLICATION_JSON;
import static org.springframework.restdocs.mockmvc.MockMvcRestDocumentation.document;
import static org.springframework.restdocs.mockmvc.RestDocumentationRequestBuilders.delete;
Expand Down Expand Up @@ -138,4 +142,30 @@ void deleteActorByTimeStamp() throws Exception {
.andExpect(jsonPath("$.rows", equalTo(1)))
.andDo(document("pg-delete-an-actor-by-timestamp"));
}

@ParameterizedTest
@MethodSource("isoDateTimeFormats")
@Order(5)
@DisplayName("Test ISO Date Time formats")
void createActorWithIsoDateTimeFormats(String isoDateTime) throws Exception {
// Prepare the request with datetime fields
Map<String, Object> actorRequestWithDateTime = new HashMap<>();
actorRequestWithDateTime.put("first_name", "Graeme");
actorRequestWithDateTime.put("last_name", "Smith");
actorRequestWithDateTime.put("last_update", isoDateTime);

var result = mockMvc.perform(post(VERSION + "/pgsqldb/actor")
.contentType(APPLICATION_JSON)
.accept(APPLICATION_JSON)
.content(objectMapper.writeValueAsString(actorRequestWithDateTime)))
.andDo(print())
.andExpect(status().isCreated())
.andExpect(jsonPath("$.row", equalTo(1)))
.andDo(document("pg-create-an-actor-with-datetime"))
.andReturn();

var pk = JsonPath.read(result.getResponse().getContentAsString(), "$.keys.actor_id");
assertTrue(deleteRow("actor", "actor_id", (int) pk));
}

}
Loading
Loading