Skip to content

Commit

Permalink
test: make elastic tests independent of the time
Browse files Browse the repository at this point in the history
Some of the tests of the elastic repository depend on the time when they are executed.
This commit introduces a TimeProvider class that is used to provide the same date for both the data put in ES and the tests themselves.

(cherry picked from commit 94b9e2a)
  • Loading branch information
phiz71 committed Jan 17, 2025
1 parent d95972c commit 4dbabda
Show file tree
Hide file tree
Showing 10 changed files with 165 additions and 112 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -22,27 +22,27 @@
import io.reactivex.rxjava3.core.Single;
import io.vertx.core.buffer.Buffer;
import jakarta.annotation.PostConstruct;
import java.time.Instant;
import java.time.ZoneId;
import java.time.format.DateTimeFormatter;
import java.time.temporal.ChronoUnit;
import java.util.List;
import java.util.Map;
import org.apache.commons.lang.StringUtils;

public class DatabaseHydrator {

private static final DateTimeFormatter FORMATTER_WITH_DASH = DateTimeFormatter.ofPattern("yyyy-MM-dd").withZone(ZoneId.systemDefault());
private static final DateTimeFormatter FORMATTER_WITH_DOT = DateTimeFormatter.ofPattern("yyyy.MM.dd").withZone(ZoneId.systemDefault());

Client client;
FreeMarkerComponent freeMarkerComponent;
String elasticMajorVersion;
private final TimeProvider timeProvider;

public DatabaseHydrator(Client client, FreeMarkerComponent freeMarkerComponent, String elasticsearchVersion) {
public DatabaseHydrator(
Client client,
FreeMarkerComponent freeMarkerComponent,
String elasticsearchVersion,
TimeProvider timeProvider
) {
this.client = client;
this.freeMarkerComponent = freeMarkerComponent;
this.elasticMajorVersion = elasticsearchVersion.split("\\.")[0];
this.timeProvider = timeProvider;
}

@PostConstruct
Expand Down Expand Up @@ -83,27 +83,20 @@ private Completable createTemplate(List<String> types) {
}

private List<Buffer> prepareData(List<String> types) {
final Instant now = Instant.now();
final Instant yesterday = now.minus(1, ChronoUnit.DAYS);

final String dateToday = FORMATTER_WITH_DASH.format(now);
final String dateYesterday = FORMATTER_WITH_DASH.format(yesterday);

final String todayWithDot = FORMATTER_WITH_DOT.format(now);
final String yesterdayWithDot = FORMATTER_WITH_DOT.format(yesterday);

return types
.stream()
.map(type -> {
Map<String, Object> data = Map.ofEntries(
Map.entry("dateToday", dateToday),
Map.entry("dateYesterday", dateYesterday),
Map.entry("indexNameToday", indexTemplate(type, todayWithDot)),
Map.entry("indexNameTodayEntrypoint", indexTemplate(type, todayWithDot, "entrypoint")),
Map.entry("indexNameTodayEndpoint", indexTemplate(type, todayWithDot, "endpoint")),
Map.entry("indexNameYesterday", indexTemplate(type, yesterdayWithDot)),
Map.entry("indexNameYesterdayEntrypoint", indexTemplate(type, yesterdayWithDot, "entrypoint")),
Map.entry("indexNameYesterdayEndpoint", indexTemplate(type, yesterdayWithDot, "endpoint"))
Map.entry("dateToday", this.timeProvider.getDateToday()),
Map.entry("dateYesterday", this.timeProvider.getDateYesterday()),
Map.entry("dateTimeToday", this.timeProvider.getDateTimeToday()),
Map.entry("dateTimeYesterday", this.timeProvider.getDateTimeYesterday()),
Map.entry("indexNameToday", indexTemplate(type, this.timeProvider.getTodayWithDot())),
Map.entry("indexNameTodayEntrypoint", indexTemplate(type, this.timeProvider.getTodayWithDot(), "entrypoint")),
Map.entry("indexNameTodayEndpoint", indexTemplate(type, this.timeProvider.getTodayWithDot(), "endpoint")),
Map.entry("indexNameYesterday", indexTemplate(type, this.timeProvider.getYesterdayWithDot())),
Map.entry("indexNameYesterdayEntrypoint", indexTemplate(type, this.timeProvider.getYesterdayWithDot(), "entrypoint")),
Map.entry("indexNameYesterdayEndpoint", indexTemplate(type, this.timeProvider.getYesterdayWithDot(), "endpoint"))
);
var filename = type + ".ftl";
return freeMarkerComponent.generateFromTemplate(filename, data);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -64,8 +64,13 @@ public Vertx vertx() {
}

@Bean
public DatabaseHydrator databaseHydrator(Client client, FreeMarkerComponent freeMarkerComponent) {
return new DatabaseHydrator(client, freeMarkerComponent, elasticsearchVersion);
public TimeProvider timeProvider() {
return new TimeProvider();
}

@Bean
public DatabaseHydrator databaseHydrator(Client client, FreeMarkerComponent freeMarkerComponent, TimeProvider timeProvider) {
return new DatabaseHydrator(client, freeMarkerComponent, elasticsearchVersion, timeProvider);
}

@Bean
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,58 @@
/*
* Copyright © 2015 The Gravitee team (http://gravitee.io)
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package io.gravitee.repository.elasticsearch;

import java.time.Instant;
import java.time.ZoneId;
import java.time.format.DateTimeFormatter;
import java.time.temporal.ChronoUnit;
import lombok.Getter;

@Getter
public class TimeProvider {

private static final DateTimeFormatter DATE_TIME_FORMATTER_WITH_DASH = DateTimeFormatter
.ofPattern("yyyy-MM-dd'T'HH:mm:ss.SSSxxx")
.withZone(ZoneId.systemDefault());
private static final DateTimeFormatter DATE_FORMATTER_WITH_DASH = DateTimeFormatter
.ofPattern("yyyy-MM-dd")
.withZone(ZoneId.systemDefault());
private static final DateTimeFormatter DATE_FORMATTER_WITH_DOT = DateTimeFormatter
.ofPattern("yyyy.MM.dd")
.withZone(ZoneId.systemDefault());

private final Instant now;
private final String dateToday;
private final String dateYesterday;
private final String dateTimeToday;
private final String dateTimeYesterday;
private final String todayWithDot;
private final String yesterdayWithDot;

public TimeProvider() {
now = Instant.now().minus(30, ChronoUnit.MINUTES);
final Instant yesterday = now.minus(1, ChronoUnit.DAYS);

dateToday = DATE_FORMATTER_WITH_DASH.format(now);
dateYesterday = DATE_FORMATTER_WITH_DASH.format(yesterday);

dateTimeToday = DATE_TIME_FORMATTER_WITH_DASH.format(now);
dateTimeYesterday = DATE_TIME_FORMATTER_WITH_DASH.format(yesterday);

todayWithDot = DATE_FORMATTER_WITH_DOT.format(now);
yesterdayWithDot = DATE_FORMATTER_WITH_DOT.format(yesterday);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -192,7 +192,7 @@ public void testCountWithTwoApis() throws Exception {
);

assertThat(response).isNotNull();
assertThat(response.getCount()).isEqualTo(4);
assertThat(response.getCount()).isEqualTo(7);
}

@Test
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -21,15 +21,19 @@

import io.gravitee.repository.common.query.QueryContext;
import io.gravitee.repository.elasticsearch.AbstractElasticsearchRepositoryTest;
import io.gravitee.repository.elasticsearch.TimeProvider;
import io.gravitee.repository.healthcheck.v4.model.ApiFieldPeriod;
import io.gravitee.repository.healthcheck.v4.model.AverageHealthCheckResponseTimeOvertimeQuery;
import io.gravitee.repository.healthcheck.v4.model.HealthCheckLogQuery;
import io.gravitee.repository.management.api.search.builder.PageableBuilder;
import jakarta.annotation.PostConstruct;
import java.time.Duration;
import java.time.Instant;
import java.time.LocalDateTime;
import java.time.ZoneId;
import java.time.ZoneOffset;
import java.time.ZonedDateTime;
import java.time.format.DateTimeFormatter;
import java.time.temporal.ChronoUnit;
import java.util.Date;
import java.util.List;
Expand All @@ -55,13 +59,22 @@ class HealthCheckElasticsearchRepositoryTest extends AbstractElasticsearchReposi
@Autowired
private HealthCheckElasticsearchRepository repository;

@Autowired
private TimeProvider timeProvider;

private Instant now;

@PostConstruct
public void init() {
now = timeProvider.getNow();
}

@Nested
class AverageResponseTime {

@Test
void should_return_average_response_time_grouped_by_endpoint() {
// Given
var now = Instant.now();
var from = now.minus(Duration.ofDays(1)).truncatedTo(ChronoUnit.DAYS);
var to = from.plus(Duration.ofDays(1));

Expand All @@ -78,7 +91,6 @@ void should_return_average_response_time_grouped_by_endpoint() {
@Test
void should_return_average_response_time_grouped_by_gateway() {
// Given
var now = Instant.now();
var from = now.minus(Duration.ofDays(1)).truncatedTo(ChronoUnit.DAYS);
var to = from.plus(Duration.ofDays(1));

Expand All @@ -99,7 +111,6 @@ class AverageResponseTimeOverTime {
@Test
void should_return_average_response_time_overtime() {
// Given
var now = Instant.now();
var from = now.truncatedTo(ChronoUnit.DAYS);
var to = from.plus(Duration.ofDays(1));
Duration interval = Duration.ofMinutes(10);
Expand All @@ -115,14 +126,20 @@ void should_return_average_response_time_overtime() {
// Then
long nbBuckets = Duration.between(from, to).dividedBy(interval);

var nowDateTime = now.truncatedTo(ChronoUnit.MINUTES).atOffset(ZoneOffset.UTC);
int minuteNow = nowDateTime.getMinute();
minuteNow = (minuteNow / 10) * 10;

DateTimeFormatter timeFormatter = DateTimeFormatter.ofPattern("HH:mm:ss.SSS'Z'").withZone(ZoneOffset.UTC);
String expectedTime = timeFormatter.format(nowDateTime.withMinute(minuteNow));

assertThat(requireNonNull(responseTime).buckets().entrySet())
.hasSize((int) nbBuckets + 1)
.haveExactly(1, bucketOfTimeHaveValue("17:20:00.000Z", 7L))
.haveExactly(1, bucketOfTimeHaveValue("17:30:00.000Z", 8L));
.haveExactly(1, bucketOfTimeHaveValue(expectedTime, 7L));
}

private static Condition<Map.Entry<String, Long>> bucketOfTimeHaveValue(String timeSuffix, long value) {
return bucket(key -> key.endsWith(timeSuffix), d -> d == value, "entre for '%s' with value %d".formatted(timeSuffix, value));
return bucket(key -> key.endsWith(timeSuffix), d -> d == value, "entry for '%s' with value %d".formatted(timeSuffix, value));
}

private static Condition<Map.Entry<String, Long>> bucket(
Expand All @@ -140,7 +157,6 @@ class SearchLogs {
@Test
void should_return_health_check_logs() {
// Given
var now = Instant.now();
var from = now.truncatedTo(ChronoUnit.DAYS);
var to = from.plus(Duration.ofDays(1));

Expand All @@ -162,13 +178,7 @@ void should_return_health_check_logs() {
.containsExactly(
new io.gravitee.repository.healthcheck.v4.model.HealthCheckLog(
"AVsGgxUsooztmMPf1gOp",
LocalDateTime
.now()
.withHour(15)
.withMinute(28)
.withSecond(20)
.truncatedTo(ChronoUnit.SECONDS)
.toInstant(ZoneOffset.UTC),
now.truncatedTo(ChronoUnit.SECONDS),
"bf19088c-f2c7-4fec-9908-8cf2c75fece4",
"other",
"gw2",
Expand All @@ -194,13 +204,7 @@ void should_return_health_check_logs() {
),
new io.gravitee.repository.healthcheck.v4.model.HealthCheckLog(
"AVsGg7GYooztmMPf1gO2",
LocalDateTime
.now()
.withHour(17)
.withMinute(29)
.withSecond(10)
.truncatedTo(ChronoUnit.SECONDS)
.toInstant(ZoneOffset.UTC),
now.truncatedTo(ChronoUnit.SECONDS),
"bf19088c-f2c7-4fec-9908-8cf2c75fece4",
"default",
"gw1",
Expand Down Expand Up @@ -243,7 +247,6 @@ class Availability {
@Test
void should_return_rate_of_availability_grouped_by_endpoint() {
// Given
var now = Instant.now();
var from = now.minus(Duration.ofDays(1)).truncatedTo(ChronoUnit.DAYS);
var to = from.plus(Duration.ofDays(1));

Expand All @@ -270,7 +273,6 @@ void should_return_rate_of_availability_grouped_by_endpoint() {
@Test
void should_return_rate_of_availability_grouped_by_gateway() {
// Given
var now = Instant.now();
var from = now.minus(Duration.ofDays(1)).truncatedTo(ChronoUnit.DAYS);
var to = from.plus(Duration.ofDays(1));

Expand Down
Loading

0 comments on commit 4dbabda

Please sign in to comment.