Remove build server specific timing from dynamodb and ruuvigateway (#15472)

* Remove build server specific timing from dynamodb and ruuvigateway

There should be no difference between running tests on your own PC or on a build server.
The ruuvigateway tests always fail for me during parallel builds due to its unrealistic timing.

Signed-off-by: Wouter Born <github@maindrain.net>
This commit is contained in:
Wouter Born 2023-08-23 20:54:50 +02:00 committed by GitHub
parent 7b90fbe162
commit fef05c3322
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
4 changed files with 51 additions and 81 deletions

View File

@ -96,26 +96,13 @@ public class BaseIntegrationTest extends JavaTest {
static { static {
ComponentContext context = Mockito.mock(ComponentContext.class); ComponentContext context = Mockito.mock(ComponentContext.class);
BundleContext bundleContext = Mockito.mock(BundleContext.class); BundleContext bundleContext = Mockito.mock(BundleContext.class);
Hashtable<String, Object> properties = new Hashtable<String, Object>(); Hashtable<String, Object> properties = new Hashtable<>();
properties.put("measurementSystem", SIUnits.MEASUREMENT_SYSTEM_NAME); properties.put("measurementSystem", SIUnits.MEASUREMENT_SYSTEM_NAME);
when(context.getProperties()).thenReturn(properties); when(context.getProperties()).thenReturn(properties);
when(context.getBundleContext()).thenReturn(bundleContext); when(context.getBundleContext()).thenReturn(bundleContext);
UNIT_PROVIDER = new I18nProviderImpl(context); UNIT_PROVIDER = new I18nProviderImpl(context);
} }
/**
* Whether tests are run in Continuous Integration environment, i.e. Jenkins or Travis CI
*
* Travis CI is detected using CI environment variable, see https://docs.travis-ci.com/user/environment-variables/
* Jenkins CI is detected using JENKINS_HOME environment variable
*
* @return
*/
protected static boolean isRunningInCI() {
String jenkinsHome = System.getenv("JENKINS_HOME");
return "true".equals(System.getenv("CI")) || (jenkinsHome != null && !jenkinsHome.isBlank());
}
private static boolean credentialsSet() { private static boolean credentialsSet() {
String access = System.getProperty("DYNAMODBTEST_ACCESS"); String access = System.getProperty("DYNAMODBTEST_ACCESS");
String secret = System.getProperty("DYNAMODBTEST_SECRET"); String secret = System.getProperty("DYNAMODBTEST_SECRET");
@ -135,10 +122,9 @@ public class BaseIntegrationTest extends JavaTest {
@Override @Override
protected void waitForAssert(Runnable runnable) { protected void waitForAssert(Runnable runnable) {
// Longer timeouts and slower polling with real dynamodb // Use longer timeouts and slower polling with real dynamodb when credentials are set.
// Non-CI tests against local server are with lower timeout. // Otherwise, test against a local server with lower timeouts.
waitForAssert(runnable, hasFakeServer() ? isRunningInCI() ? 30_000L : 10_000L : 120_000L, waitForAssert(runnable, hasFakeServer() ? 30_000L : 120_000L, hasFakeServer() ? 500 : 1000L);
hasFakeServer() ? 500 : 1000L);
} }
@BeforeAll @BeforeAll

View File

@ -13,7 +13,7 @@
package org.openhab.persistence.dynamodb.internal; package org.openhab.persistence.dynamodb.internal;
import static org.junit.jupiter.api.Assertions.*; import static org.junit.jupiter.api.Assertions.*;
import static org.junit.jupiter.api.Assumptions.*; import static org.junit.jupiter.api.Assumptions.assumeTrue;
import java.math.BigDecimal; import java.math.BigDecimal;
import java.util.ArrayList; import java.util.ArrayList;
@ -305,8 +305,6 @@ public class TestComplexItemsWithDifferentStateTypesTest extends BaseIntegration
@Test @Test
public void testGroupDummyItem() { public void testGroupDummyItem() {
// Do not want to slow down CI runs
assumeFalse(isRunningInCI());
// only with the fast local server // only with the fast local server
assumeTrue(hasFakeServer()); assumeTrue(hasFakeServer());
try { try {

View File

@ -114,17 +114,4 @@ public class MqttOSGiTest extends JavaOSGiTest {
protected CompletableFuture<Boolean> publish(String topic, String message) { protected CompletableFuture<Boolean> publish(String topic, String message) {
return brokerConnection.publish(topic, message.getBytes(StandardCharsets.UTF_8), 1, true); return brokerConnection.publish(topic, message.getBytes(StandardCharsets.UTF_8), 1, true);
} }
/**
* Whether tests are run in Continuous Integration environment, i.e. Jenkins or Travis CI
*
* Travis CI is detected using CI environment variable, see https://docs.travis-ci.com/us>
* Jenkins CI is detected using JENKINS_HOME environment variable
*
* @return
*/
protected boolean isRunningInCI() {
String jenkinsHome = System.getenv("JENKINS_HOME");
return "true".equals(System.getenv("CI")) || (jenkinsHome != null && !jenkinsHome.isBlank());
}
} }

View File

@ -15,7 +15,8 @@ package org.openhab.binding.mqtt.ruuvigateway;
import static org.hamcrest.CoreMatchers.is; import static org.hamcrest.CoreMatchers.is;
import static org.hamcrest.MatcherAssert.assertThat; import static org.hamcrest.MatcherAssert.assertThat;
import static org.junit.jupiter.api.Assertions.*; import static org.junit.jupiter.api.Assertions.*;
import static org.mockito.Mockito.*; import static org.mockito.ArgumentMatchers.any;
import static org.mockito.Mockito.when;
import static org.openhab.binding.mqtt.ruuvigateway.internal.RuuviGatewayBindingConstants.*; import static org.openhab.binding.mqtt.ruuvigateway.internal.RuuviGatewayBindingConstants.*;
import static org.openhab.core.library.unit.MetricPrefix.HECTO; import static org.openhab.core.library.unit.MetricPrefix.HECTO;
@ -65,7 +66,6 @@ import org.openhab.binding.mqtt.ruuvigateway.internal.RuuviGatewayBindingConstan
import org.openhab.binding.mqtt.ruuvigateway.internal.discovery.RuuviGatewayDiscoveryService; import org.openhab.binding.mqtt.ruuvigateway.internal.discovery.RuuviGatewayDiscoveryService;
import org.openhab.binding.mqtt.ruuvigateway.internal.handler.RuuviTagHandler; import org.openhab.binding.mqtt.ruuvigateway.internal.handler.RuuviTagHandler;
import org.openhab.core.config.core.Configuration; import org.openhab.core.config.core.Configuration;
import org.openhab.core.config.discovery.DiscoveryResult;
import org.openhab.core.i18n.UnitProvider; import org.openhab.core.i18n.UnitProvider;
import org.openhab.core.io.transport.mqtt.MqttBrokerConnection; import org.openhab.core.io.transport.mqtt.MqttBrokerConnection;
import org.openhab.core.io.transport.mqtt.MqttConnectionObserver; import org.openhab.core.io.transport.mqtt.MqttConnectionObserver;
@ -329,32 +329,29 @@ public class RuuviGatewayTest extends MqttOSGiTest {
String accelerationZStandardGravity, String batteryVolt, int dataFormat, String humidityPercent, String accelerationZStandardGravity, String batteryVolt, int dataFormat, String humidityPercent,
int measurementSequenceNumber, int movementCounter, String pressurePascal, String txPowerDecibelMilliwatts, int measurementSequenceNumber, int movementCounter, String pressurePascal, String txPowerDecibelMilliwatts,
String rssiDecibelMilliwatts, Instant ts, Instant gwts, String gwMac) { String rssiDecibelMilliwatts, Instant ts, Instant gwts, String gwMac) {
assertEquals(new QuantityType<Temperature>(new BigDecimal(temperatureCelsius), SIUnits.CELSIUS), assertEquals(new QuantityType<>(new BigDecimal(temperatureCelsius), SIUnits.CELSIUS),
channelStateGetter.apply(CHANNEL_ID_TEMPERATURE)); channelStateGetter.apply(CHANNEL_ID_TEMPERATURE));
assertEquals( assertEquals(new QuantityType<>(new BigDecimal(accelerationXStandardGravity), Units.STANDARD_GRAVITY),
new QuantityType<Acceleration>(new BigDecimal(accelerationXStandardGravity), Units.STANDARD_GRAVITY),
channelStateGetter.apply(CHANNEL_ID_ACCELERATIONX)); channelStateGetter.apply(CHANNEL_ID_ACCELERATIONX));
assertEquals( assertEquals(new QuantityType<>(new BigDecimal(accelerationYStandardGravity), Units.STANDARD_GRAVITY),
new QuantityType<Acceleration>(new BigDecimal(accelerationYStandardGravity), Units.STANDARD_GRAVITY),
channelStateGetter.apply(CHANNEL_ID_ACCELERATIONY)); channelStateGetter.apply(CHANNEL_ID_ACCELERATIONY));
assertEquals( assertEquals(new QuantityType<>(new BigDecimal(accelerationZStandardGravity), Units.STANDARD_GRAVITY),
new QuantityType<Acceleration>(new BigDecimal(accelerationZStandardGravity), Units.STANDARD_GRAVITY),
channelStateGetter.apply(CHANNEL_ID_ACCELERATIONZ)); channelStateGetter.apply(CHANNEL_ID_ACCELERATIONZ));
assertEquals(new QuantityType<ElectricPotential>(new BigDecimal(batteryVolt), Units.VOLT), assertEquals(new QuantityType<>(new BigDecimal(batteryVolt), Units.VOLT),
channelStateGetter.apply(CHANNEL_ID_BATTERY)); channelStateGetter.apply(CHANNEL_ID_BATTERY));
assertEquals(new DecimalType(dataFormat), channelStateGetter.apply(CHANNEL_ID_DATA_FORMAT)); assertEquals(new DecimalType(dataFormat), channelStateGetter.apply(CHANNEL_ID_DATA_FORMAT));
assertEquals(new QuantityType<Dimensionless>(new BigDecimal(humidityPercent), Units.PERCENT), assertEquals(new QuantityType<>(new BigDecimal(humidityPercent), Units.PERCENT),
channelStateGetter.apply(CHANNEL_ID_HUMIDITY)); channelStateGetter.apply(CHANNEL_ID_HUMIDITY));
assertEquals(new DecimalType(new BigDecimal(measurementSequenceNumber)), assertEquals(new DecimalType(new BigDecimal(measurementSequenceNumber)),
channelStateGetter.apply(CHANNEL_ID_MEASUREMENT_SEQUENCE_NUMBER)); channelStateGetter.apply(CHANNEL_ID_MEASUREMENT_SEQUENCE_NUMBER));
assertEquals(new DecimalType(new BigDecimal(movementCounter)), assertEquals(new DecimalType(new BigDecimal(movementCounter)),
channelStateGetter.apply(CHANNEL_ID_MOVEMENT_COUNTER)); channelStateGetter.apply(CHANNEL_ID_MOVEMENT_COUNTER));
assertEquals(new QuantityType<Pressure>(new BigDecimal(pressurePascal), SIUnits.PASCAL), assertEquals(new QuantityType<>(new BigDecimal(pressurePascal), SIUnits.PASCAL),
channelStateGetter.apply(CHANNEL_ID_PRESSURE)); channelStateGetter.apply(CHANNEL_ID_PRESSURE));
assertEquals(new QuantityType<Power>(new BigDecimal(txPowerDecibelMilliwatts), Units.DECIBEL_MILLIWATTS), assertEquals(new QuantityType<>(new BigDecimal(txPowerDecibelMilliwatts), Units.DECIBEL_MILLIWATTS),
channelStateGetter.apply(CHANNEL_ID_TX_POWER)); channelStateGetter.apply(CHANNEL_ID_TX_POWER));
assertEquals(new QuantityType<Power>(new BigDecimal(rssiDecibelMilliwatts), Units.DECIBEL_MILLIWATTS), assertEquals(new QuantityType<>(new BigDecimal(rssiDecibelMilliwatts), Units.DECIBEL_MILLIWATTS),
channelStateGetter.apply(CHANNEL_ID_RSSI)); channelStateGetter.apply(CHANNEL_ID_RSSI));
assertEquals(new DateTimeType(ts.atZone(ZoneId.of("UTC"))), channelStateGetter.apply(CHANNEL_ID_TS)); assertEquals(new DateTimeType(ts.atZone(ZoneId.of("UTC"))), channelStateGetter.apply(CHANNEL_ID_TS));
assertEquals(new DateTimeType(gwts.atZone(ZoneId.of("UTC"))), channelStateGetter.apply(CHANNEL_ID_GWTS)); assertEquals(new DateTimeType(gwts.atZone(ZoneId.of("UTC"))), channelStateGetter.apply(CHANNEL_ID_GWTS));
@ -414,16 +411,18 @@ public class RuuviGatewayTest extends MqttOSGiTest {
@SuppressWarnings("null") @SuppressWarnings("null")
@Test @Test
public void testDiscovery() { public void testDiscovery() {
scheduler.execute(() -> publish(BASE_TOPIC_RUUVI + "/mygwid/DE:AD:BE:EF:BB:02", scheduler.execute(() -> publish(BASE_TOPIC_RUUVI + "/mygwid/DE:AD:BE:EF:BB:02", """
"{" + " \"gw_mac\": \"DE:AD:BE:EF:00\"," + " \"rssi\": -82," + " \"aoa\": []," {\
+ " \"gwts\": \"1659365432\"," + " \"ts\": \"1659365222\"," "gw_mac": "DE:AD:BE:EF:00",\
+ " \"data\": \"0201061BFF99040512FC5394C37C0004FFFC040CAC364200CDCBB8334C884F\"," "rssi": -82,\
+ " \"coords\": \"\" }")); "aoa": [],\
"gwts": "1659365432",\
"ts": "1659365222",\
"data": "0201061BFF99040512FC5394C37C0004FFFC040CAC364200CDCBB8334C884F",\
"coords": "" }"""));
waitForAssert(() -> { waitForAssert(() -> {
assertEquals(2, inbox.getAll().size(), inbox.getAll().toString()); assertEquals(2, inbox.getAll().size(), inbox.getAll().toString());
var discovered = new HashSet<DiscoveryResult>(); var discovered = new HashSet<>(inbox.getAll());
discovered.addAll(inbox.getAll());
for (var result : discovered) { for (var result : discovered) {
assertEquals(THING_TYPE_BEACON, result.getThingTypeUID()); assertEquals(THING_TYPE_BEACON, result.getThingTypeUID());
assertEquals("topic", result.getRepresentationProperty()); assertEquals("topic", result.getRepresentationProperty());
@ -431,10 +430,10 @@ public class RuuviGatewayTest extends MqttOSGiTest {
assertNotNull(topic); assertNotNull(topic);
assertTrue( assertTrue(
// published in this test // published in this test
topic.equals((BASE_TOPIC_RUUVI + "/mygwid/DE:AD:BE:EF:BB:02")) (BASE_TOPIC_RUUVI + "/mygwid/DE:AD:BE:EF:BB:02").equals(topic)
// published in beforeEach // published in beforeEach
|| result.getProperties().get("topic") || (BASE_TOPIC_RUUVI + "/mygwid/DE:AD:BE:EF:AA:00")
.equals((BASE_TOPIC_RUUVI + "/mygwid/DE:AD:BE:EF:AA:00"))); .equals(result.getProperties().get("topic")));
} }
}); });
} }
@ -445,8 +444,7 @@ public class RuuviGatewayTest extends MqttOSGiTest {
// with quickTimeout=false, heartbeat is effectively disabled. Thing will not "timeout" and go OFFLINE // with quickTimeout=false, heartbeat is effectively disabled. Thing will not "timeout" and go OFFLINE
// with quickTimeout=true, timeout happens very fast. In CI we use infinite timeout and trigger timeout manually // with quickTimeout=true, timeout happens very fast. In CI we use infinite timeout and trigger timeout manually
Thing ruuviThing = createRuuviThing("mygwid", BASE_TOPIC_RUUVI + "/mygwid/DE:AD:BE:EF:BB:02", Thing ruuviThing = createRuuviThing("mygwid", BASE_TOPIC_RUUVI + "/mygwid/DE:AD:BE:EF:BB:02", 9_000_000);
quickTimeout ? (isRunningInCI() ? 9_000_000 : 100) : 9_000_000);
// Link all channels to freshly created items // Link all channels to freshly created items
ruuviThing.getChannels().stream().map(Channel::getUID).forEach(this::linkChannelToAutogeneratedItem); ruuviThing.getChannels().stream().map(Channel::getUID).forEach(this::linkChannelToAutogeneratedItem);
@ -470,9 +468,7 @@ public class RuuviGatewayTest extends MqttOSGiTest {
List<ThingStatusInfo> statusUpdates = statusSubscriber.statusUpdates.get(ruuviThing.getUID()); List<ThingStatusInfo> statusUpdates = statusSubscriber.statusUpdates.get(ruuviThing.getUID());
assertNotNull(statusUpdates); assertNotNull(statusUpdates);
if (quickTimeout) { if (quickTimeout) {
if (isRunningInCI()) {
triggerTimeoutHandling(ruuviThing); triggerTimeoutHandling(ruuviThing);
}
waitForAssert(() -> { waitForAssert(() -> {
assertThingStatus(statusUpdates, statusUpdateIndex.get(), ThingStatus.OFFLINE, assertThingStatus(statusUpdates, statusUpdateIndex.get(), ThingStatus.OFFLINE,
ThingStatusDetail.COMMUNICATION_ERROR, "No valid data received for some time"); ThingStatusDetail.COMMUNICATION_ERROR, "No valid data received for some time");
@ -485,11 +481,15 @@ public class RuuviGatewayTest extends MqttOSGiTest {
// publish some valid data ("valid case" test vector from // publish some valid data ("valid case" test vector from
// https://docs.ruuvi.com/communication/bluetooth-advertisements/data-format-5-rawv2) // https://docs.ruuvi.com/communication/bluetooth-advertisements/data-format-5-rawv2)
scheduler.execute(() -> publish(BASE_TOPIC_RUUVI + "/mygwid/DE:AD:BE:EF:BB:02", scheduler.execute(() -> publish(BASE_TOPIC_RUUVI + "/mygwid/DE:AD:BE:EF:BB:02", """
"{" + " \"gw_mac\": \"DE:AD:BE:EF:00\"," + " \"rssi\": -82," + " \"aoa\": []," {\
+ " \"gwts\": \"1659365432\"," + " \"ts\": \"1659365222\"," "gw_mac": "DE:AD:BE:EF:00",\
+ " \"data\": \"0201061BFF99040512FC5394C37C0004FFFC040CAC364200CDCBB8334C884F\"," "rssi": -82,\
+ " \"coords\": \"\" }")); "aoa": [],\
"gwts": "1659365432",\
"ts": "1659365222",\
"data": "0201061BFF99040512FC5394C37C0004FFFC040CAC364200CDCBB8334C884F",\
"coords": "" }"""));
waitForAssert(() -> { waitForAssert(() -> {
assertThingStatus(statusUpdates, statusUpdateIndex.get(), ThingStatus.ONLINE); assertThingStatus(statusUpdates, statusUpdateIndex.get(), ThingStatus.ONLINE);
@ -517,9 +517,7 @@ public class RuuviGatewayTest extends MqttOSGiTest {
}); });
if (quickTimeout) { if (quickTimeout) {
if (isRunningInCI()) {
triggerTimeoutHandling(ruuviThing); triggerTimeoutHandling(ruuviThing);
}
waitForAssert(() -> { waitForAssert(() -> {
assertThingStatus(statusUpdates, statusUpdateIndex.get(), ThingStatus.OFFLINE, assertThingStatus(statusUpdates, statusUpdateIndex.get(), ThingStatus.OFFLINE,
ThingStatusDetail.COMMUNICATION_ERROR, "No valid data received for some time"); ThingStatusDetail.COMMUNICATION_ERROR, "No valid data received for some time");
@ -532,11 +530,15 @@ public class RuuviGatewayTest extends MqttOSGiTest {
// Another mqtt update (("minimum values" test vector from // Another mqtt update (("minimum values" test vector from
// https://docs.ruuvi.com/communication/bluetooth-advertisements/data-format-5-rawv2) // https://docs.ruuvi.com/communication/bluetooth-advertisements/data-format-5-rawv2)
scheduler.execute(() -> publish(BASE_TOPIC_RUUVI + "/mygwid/DE:AD:BE:EF:BB:02", scheduler.execute(() -> publish(BASE_TOPIC_RUUVI + "/mygwid/DE:AD:BE:EF:BB:02", """
"{" + " \"gw_mac\": \"DE:AD:BE:EF:00\"," + " \"rssi\": -66," + " \"aoa\": []," {\
+ " \"gwts\": \"1659365431\"," + " \"ts\": \"1659365221\"," "gw_mac": "DE:AD:BE:EF:00",\
+ " \"data\": \"0201061BFF9904058001000000008001800180010000000000CBB8334C884F\"," "rssi": -66,\
+ " \"coords\": \"\" }")); "aoa": [],\
"gwts": "1659365431",\
"ts": "1659365221",\
"data": "0201061BFF9904058001000000008001800180010000000000CBB8334C884F",\
"coords": "" }"""));
if (quickTimeout) { if (quickTimeout) {
// With quick timeout we were previously offline, so now we should be back online // With quick timeout we were previously offline, so now we should be back online
// with valid channels. // with valid channels.
@ -566,10 +568,7 @@ public class RuuviGatewayTest extends MqttOSGiTest {
); );
}); });
// ...after which timeout will happen again
if (isRunningInCI()) {
triggerTimeoutHandling(ruuviThing); triggerTimeoutHandling(ruuviThing);
}
waitForAssert(() -> { waitForAssert(() -> {
assertThingStatus(statusUpdates, statusUpdateIndex.get(), ThingStatus.OFFLINE, assertThingStatus(statusUpdates, statusUpdateIndex.get(), ThingStatus.OFFLINE,
ThingStatusDetail.COMMUNICATION_ERROR, "No valid data received for some time"); ThingStatusDetail.COMMUNICATION_ERROR, "No valid data received for some time");