Skip to content

Commit d85b416

Browse files
committed
test: Improved CloudConnectionEndpointsTest
Signed-off-by: Nicola Timeus <nicola.timeus@eurotech.com>
1 parent d9285a6 commit d85b416

5 files changed

Lines changed: 168 additions & 129 deletions

File tree

kura/test/org.eclipse.kura.rest.cloudconnection.provider.test/META-INF/MANIFEST.MF

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -25,4 +25,5 @@ Import-Package: com.google.gson;version="2.9.0",
2525
Fragment-Host: org.eclipse.kura.rest.cloudconnection.provider
2626
Require-Bundle: org.eclipse.kura.http.server.manager;bundle-version="1.1.0",
2727
org.eclipse.kura.broker.artemis.core;bundle-version="1.2.0",
28-
org.eclipse.kura.broker.artemis.simple.mqtt;bundle-version="1.1.0"
28+
org.eclipse.kura.broker.artemis.simple.mqtt;bundle-version="1.1.0",
29+
moquette-broker

kura/test/org.eclipse.kura.rest.cloudconnection.provider.test/src/main/java/org/eclipse/kura/internal/rest/cloudconnection/provider/test/CloudConnectionEndpointsTest.java

Lines changed: 166 additions & 48 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*******************************************************************************
2-
* Copyright (c) 2023, 2025 Eurotech and/or its affiliates and others
2+
* Copyright (c) 2023, 2026 Eurotech and/or its affiliates and others
33
*
44
* This program and the accompanying materials are made
55
* available under the terms of the Eclipse Public License 2.0
@@ -12,43 +12,64 @@
1212
******************************************************************************/
1313
package org.eclipse.kura.internal.rest.cloudconnection.provider.test;
1414

15+
import static org.junit.Assert.assertEquals;
16+
import static org.junit.Assert.assertTrue;
1517
import static org.junit.Assert.fail;
1618

1719
import java.util.Arrays;
1820
import java.util.Collection;
1921
import java.util.Collections;
22+
import java.util.HashMap;
2023
import java.util.HashSet;
24+
import java.util.Map;
2125
import java.util.Optional;
26+
import java.util.Properties;
2227
import java.util.Scanner;
2328
import java.util.concurrent.TimeUnit;
29+
import java.util.function.Predicate;
30+
import java.util.function.Supplier;
31+
32+
import io.moquette.broker.Server;
2433

2534
import org.eclipse.kura.KuraException;
2635
import org.eclipse.kura.cloudconnection.CloudConnectionConstants;
2736
import org.eclipse.kura.cloudconnection.factory.CloudConnectionFactory;
37+
import org.eclipse.kura.configuration.ComponentConfiguration;
38+
import org.eclipse.kura.configuration.ConfigurableComponent;
2839
import org.eclipse.kura.configuration.ConfigurationService;
2940
import org.eclipse.kura.core.testutil.requesthandler.AbstractRequestHandlerTest;
3041
import org.eclipse.kura.core.testutil.requesthandler.MqttTransport;
3142
import org.eclipse.kura.core.testutil.requesthandler.RestTransport;
3243
import org.eclipse.kura.core.testutil.requesthandler.Transport;
3344
import org.eclipse.kura.core.testutil.requesthandler.Transport.MethodSpec;
3445
import org.eclipse.kura.core.testutil.service.ServiceUtil;
46+
import org.eclipse.kura.data.DataTransportService;
3547
import org.eclipse.kura.internal.rest.cloudconnection.provider.dto.CloudConnectionFactoryPidAndCloudEndpointPid;
3648
import org.eclipse.kura.internal.rest.cloudconnection.provider.dto.CloudEndpointPidRequest;
3749
import org.eclipse.kura.internal.rest.cloudconnection.provider.dto.PidAndFactoryPidAndCloudEndpointPid;
3850
import org.eclipse.kura.rest.configuration.api.PidAndFactoryPid;
3951
import org.eclipse.kura.rest.configuration.api.PidSet;
4052
import org.eclipse.kura.rest.configuration.api.UpdateComponentConfigurationRequest;
53+
import org.junit.After;
54+
import org.junit.Before;
4155
import org.junit.BeforeClass;
4256
import org.junit.Test;
4357
import org.junit.runner.RunWith;
4458
import org.junit.runners.Parameterized;
59+
import org.slf4j.Logger;
60+
import org.slf4j.LoggerFactory;
4561

4662
import com.google.gson.Gson;
63+
import com.google.gson.JsonObject;
64+
import com.google.gson.JsonPrimitive;
4765

4866
@RunWith(Parameterized.class)
4967
public class CloudConnectionEndpointsTest extends AbstractRequestHandlerTest {
5068

51-
private static final String CLOUD_ENDPOINT_INSTANCE_TEST = "org.eclipse.kura.cloud.CloudService-test";
69+
private static final Logger logger = LoggerFactory.getLogger(CloudConnectionEndpointsTest.class);
70+
71+
private static final String CLOUD_SERVICE_FACTORY_PID = "org.eclipse.kura.cloud.CloudService";
72+
private static final String MQTT_DATA_TRANSPORT_STACK_COMPONENT_PREFIX = "org.eclipse.kura.core.data.transport.mqtt.MqttDataTransport";
5273

5374
private static final String MQTT_APP_ID = "CLD-V1";
5475

@@ -72,18 +93,6 @@ public class CloudConnectionEndpointsTest extends AbstractRequestHandlerTest {
7293
private UpdateComponentConfigurationRequest updateComponentConfigurationRequest;
7394
private CloudEndpointPidRequest cloudEndpointPidRequest;
7495

75-
private static final String EXPECTED_GET_STACK_COMPONENT_PIDS_RESPONSE = new Scanner(
76-
CloudConnectionEndpointsTest.class.getResourceAsStream("/getStackComponentPidsResponse.json"), "UTF-8")
77-
.useDelimiter("\\A").next().replace(" ", "");
78-
79-
private static final String UPDATE_COMPONENT_CONFIGURATION_REQUEST = new Scanner(
80-
CloudConnectionEndpointsTest.class.getResourceAsStream("/updateConfigurationRequest.json"), "UTF-8")
81-
.useDelimiter("\\A").next().replace(" ", "");
82-
83-
private static final String EXPECTED_IS_ENDPOINT_CONNECTED_RESPONSE = new Scanner(
84-
CloudConnectionEndpointsTest.class.getResourceAsStream("/isConnectedResponse.json"), "UTF-8")
85-
.useDelimiter("\\A").next().replace(" ", "");
86-
8796
@Parameterized.Parameters(name = "{0}")
8897
public static Collection<Transport> transports() {
8998
return Arrays.asList(new MqttTransport(MQTT_APP_ID), new RestTransport(REST_APP_ID));
@@ -101,9 +110,30 @@ public static void setup() {
101110
TimeUnit.SECONDS);
102111
cloudConnectionFactory = ServiceUtil.trackService(CloudConnectionFactory.class, Optional.empty()).get(30,
103112
TimeUnit.SECONDS);
104-
cloudConnectionFactory.createConfiguration(CLOUD_ENDPOINT_INSTANCE_TEST);
113+
114+
final Server server = new Server();
115+
116+
final Properties properties = new Properties();
117+
properties.put("port", "6666");
118+
properties.put("host", "0.0.0.0");
119+
120+
server.startServer(properties);
105121
} catch (Exception e) {
106-
fail("Unable to create the test CloudEndpoint");
122+
fail("Test setup failed");
123+
}
124+
}
125+
126+
@Before
127+
public void createTestCloudStack() {
128+
givenExistingCloudEndpoint(testCloudInstancePid());
129+
}
130+
131+
@After
132+
public void deleteTestCloudStack() {
133+
try {
134+
cloudConnectionFactory.deleteConfiguration(testCloudInstancePid());
135+
} catch (final Exception e) {
136+
logger.warn("failed to delete test cloud instance during cleanup", e);
107137
}
108138
}
109139

@@ -118,20 +148,40 @@ public void shouldGetCloudComponentInstances() {
118148

119149
@Test
120150
public void shouldGetStackComponentPids() {
121-
givenCloudConnectionFactoryPidAndCloudEndpointPid("org.eclipse.kura.cloud.CloudService",
122-
CLOUD_ENDPOINT_INSTANCE_TEST);
151+
givenCloudConnectionFactoryPidAndCloudEndpointPid(CLOUD_SERVICE_FACTORY_PID, testCloudInstancePid());
123152

124153
whenRequestIsPerformed(new MethodSpec(METHOD_SPEC_POST), "/cloudEndpoint/stackComponentPids",
125154
gson.toJson(this.cloudConnectionFactoryPidAndCloudEndpointPid));
126155

127156
thenRequestSucceeds();
128-
thenResponseBodyEqualsJson(EXPECTED_GET_STACK_COMPONENT_PIDS_RESPONSE);
157+
thenResponseJsonArraySizeIs("pids", 3);
158+
thenResponseJsonArrayContains("pids", "org.eclipse.kura.cloud.CloudService-" + testCloudInstancesSuffix());
159+
thenResponseJsonArrayContains("pids",
160+
"org.eclipse.kura.core.data.transport.mqtt.MqttDataTransport-" + testCloudInstancesSuffix());
161+
thenResponseJsonArrayContains("pids", "org.eclipse.kura.data.DataService-" + testCloudInstancesSuffix());
162+
163+
}
164+
165+
private void thenResponseJsonArraySizeIs(final String property, final int size) {
166+
final JsonObject response = gson.fromJson(
167+
expectResponse().getBody().orElseThrow(() -> new IllegalStateException("body is missing")),
168+
JsonObject.class);
169+
170+
assertEquals(size, response.get(property).getAsJsonArray().size());
171+
}
172+
173+
private void thenResponseJsonArrayContains(final String property, final String value) {
174+
final JsonObject response = gson.fromJson(
175+
expectResponse().getBody().orElseThrow(() -> new IllegalStateException("body is missing")),
176+
JsonObject.class);
177+
178+
assertTrue(response.get(property).getAsJsonArray().contains(new JsonPrimitive(value)));
129179
}
130180

131181
@Test
132182
public void shouldCreateCloudEndpoint() {
133-
givenCloudConnectionFactoryPidAndCloudEndpointPid("org.eclipse.kura.cloud.CloudService",
134-
"org.eclipse.kura.cloud.CloudService-createTest" + this.getTransportType());
183+
givenCloudConnectionFactoryPidAndCloudEndpointPid(CLOUD_SERVICE_FACTORY_PID,
184+
"org.eclipse.kura.cloud.CloudService-createTest" + testCloudInstancesSuffix());
135185

136186
whenRequestIsPerformed(new MethodSpec(METHOD_SPEC_POST), "/cloudEndpoint",
137187
gson.toJson(this.cloudConnectionFactoryPidAndCloudEndpointPid));
@@ -141,9 +191,7 @@ public void shouldCreateCloudEndpoint() {
141191

142192
@Test
143193
public void shouldDeleteCloudEndpoint() {
144-
givenExistingCloudEndpoint("org.eclipse.kura.cloud.CloudService-toDelete" + this.getTransportType());
145-
givenCloudConnectionFactoryPidAndCloudEndpointPid("org.eclipse.kura.cloud.CloudService",
146-
"org.eclipse.kura.cloud.CloudService-toDelete" + this.getTransportType());
194+
givenCloudConnectionFactoryPidAndCloudEndpointPid(CLOUD_SERVICE_FACTORY_PID, testCloudInstancePid());
147195

148196
whenRequestIsPerformed(new MethodSpec(METHOD_SPEC_DELETE, MQTT_METHOD_SPEC_DEL), "/cloudEndpoint",
149197
gson.toJson(this.cloudConnectionFactoryPidAndCloudEndpointPid));
@@ -162,8 +210,8 @@ public void shouldGetCloudComponentFactories() {
162210

163211
@Test
164212
public void shouldCreatePublisherInstance() {
165-
givenPidAndFactoryPidAndCloudEndpointPid("test-pub-" + this.getTransportType(),
166-
"org.eclipse.kura.cloud.publisher.CloudPublisher", CLOUD_ENDPOINT_INSTANCE_TEST);
213+
givenPidAndFactoryPidAndCloudEndpointPid("test-pub-" + testCloudInstancesSuffix(),
214+
"org.eclipse.kura.cloud.publisher.CloudPublisher", testCloudInstancePid());
167215

168216
whenRequestIsPerformed(new MethodSpec(METHOD_SPEC_POST), "/pubSub",
169217
gson.toJson(this.pidAndFactoryPidAndCloudEndpointPid));
@@ -173,8 +221,8 @@ public void shouldCreatePublisherInstance() {
173221

174222
@Test
175223
public void shouldCreateSubscriberInstance() {
176-
givenPidAndFactoryPidAndCloudEndpointPid("test-sub-" + this.getTransportType(),
177-
"org.eclipse.kura.cloud.subscriber.CloudSubscriber", CLOUD_ENDPOINT_INSTANCE_TEST);
224+
givenPidAndFactoryPidAndCloudEndpointPid("test-sub-" + testCloudInstancesSuffix(),
225+
"org.eclipse.kura.cloud.subscriber.CloudSubscriber", testCloudInstancePid());
178226

179227
whenRequestIsPerformed(new MethodSpec(METHOD_SPEC_POST), "/pubSub",
180228
gson.toJson(this.pidAndFactoryPidAndCloudEndpointPid));
@@ -184,9 +232,9 @@ public void shouldCreateSubscriberInstance() {
184232

185233
@Test
186234
public void shouldDeletePublisherInstance() {
187-
givenPubSubInstance("pub-to-delete-" + this.getTransportType(),
188-
"org.eclipse.kura.cloud.publisher.CloudPublisher", CLOUD_ENDPOINT_INSTANCE_TEST);
189-
givenPid("pub-to-delete-" + this.getTransportType());
235+
givenPubSubInstance("pub-to-delete-" + testCloudInstancesSuffix(),
236+
"org.eclipse.kura.cloud.publisher.CloudPublisher", testCloudInstancePid());
237+
givenPid("pub-to-delete-" + testCloudInstancesSuffix());
190238
whenRequestIsPerformed(new MethodSpec(METHOD_SPEC_DELETE, MQTT_METHOD_SPEC_DEL), "/pubSub",
191239
gson.toJson(this.pidAndFactoryPid));
192240

@@ -195,9 +243,9 @@ public void shouldDeletePublisherInstance() {
195243

196244
@Test
197245
public void shouldDeleteSubscriberInstance() {
198-
givenPubSubInstance("sub-to-delete-" + this.getTransportType(),
199-
"org.eclipse.kura.cloud.subscriber.CloudSubscriber", CLOUD_ENDPOINT_INSTANCE_TEST);
200-
givenPid("sub-to-delete-" + this.getTransportType());
246+
givenPubSubInstance("sub-to-delete-" + testCloudInstancesSuffix(),
247+
"org.eclipse.kura.cloud.subscriber.CloudSubscriber", testCloudInstancePid());
248+
givenPid("sub-to-delete-" + testCloudInstancesSuffix());
201249

202250
whenRequestIsPerformed(new MethodSpec(METHOD_SPEC_DELETE, MQTT_METHOD_SPEC_DEL), "/pubSub",
203251
gson.toJson(this.pidAndFactoryPid));
@@ -207,8 +255,9 @@ public void shouldDeleteSubscriberInstance() {
207255

208256
@Test
209257
public void shouldGetConfigurations() {
210-
givenPidSet(CLOUD_ENDPOINT_INSTANCE_TEST, "org.eclipse.kura.core.data.transport.mqtt.MqttDataTransport-test", //
211-
"org.eclipse.kura.data.DataService-test");
258+
givenPidSet(CLOUD_SERVICE_FACTORY_PID + '-' + testCloudInstancesSuffix(),
259+
"org.eclipse.kura.core.data.transport.mqtt.MqttDataTransport-" + testCloudInstancesSuffix(), //
260+
"org.eclipse.kura.data.DataService-" + testCloudInstancesSuffix());
212261

213262
whenRequestIsPerformed(new MethodSpec(METHOD_SPEC_POST), "/configurations", gson.toJson(this.pidSet));
214263

@@ -218,8 +267,29 @@ public void shouldGetConfigurations() {
218267

219268
@Test
220269
public void shouldUpdateStackComponentConfigurations() {
221-
222-
givenUpdateComponentConfigurationRequest(UPDATE_COMPONENT_CONFIGURATION_REQUEST);
270+
givenUpdateComponentConfigurationRequest("{" + //
271+
"\"configs\": [" + //
272+
"{" + //
273+
"\"pid\": \"org.eclipse.kura.core.data.transport.mqtt.MqttDataTransport-" + testCloudInstancesSuffix()
274+
+ "\"," + //
275+
"\"properties\": {" + //
276+
"\"broker-url\": {" + //
277+
"\"type\": \"STRING\"," + //
278+
"\"value\": \"mqtt://test.mosquitto.org:1883\"" + //
279+
"}," + //
280+
"\"topic.context.account-name\": {" + //
281+
"\"type\": \"STRING\"," + //
282+
"\"value\": \"account-name-testX2\"" + //
283+
"}," + //
284+
"\"client-id\": {" + //
285+
"\"type\": \"STRING\"," + //
286+
"\"value\": \"foobar\"" + //
287+
"}" + //
288+
"}" + //
289+
"}" + //
290+
"]," + //
291+
"\"takeSnapshot\" : true" + //
292+
"}");
223293

224294
whenRequestIsPerformed(new MethodSpec(METHOD_SPEC_PUT), "/configurations",
225295
gson.toJson(this.updateComponentConfigurationRequest));
@@ -229,7 +299,7 @@ public void shouldUpdateStackComponentConfigurations() {
229299

230300
@Test
231301
public void shouldConnectEndpoint() {
232-
givenCloudEndpointPidRequest(CLOUD_ENDPOINT_INSTANCE_TEST);
302+
givenCloudEndpointPidRequest(testCloudInstancePid());
233303

234304
whenRequestIsPerformed(new MethodSpec(METHOD_SPEC_POST), "/cloudEndpoint/connect",
235305
gson.toJson(this.cloudEndpointPidRequest));
@@ -239,7 +309,7 @@ public void shouldConnectEndpoint() {
239309

240310
@Test
241311
public void shouldDisconnectEndpoint() {
242-
givenCloudEndpointPidRequest(CLOUD_ENDPOINT_INSTANCE_TEST);
312+
givenCloudEndpointPidRequest(testCloudInstancePid());
243313

244314
whenRequestIsPerformed(new MethodSpec(METHOD_SPEC_POST), "/cloudEndpoint/disconnect",
245315
gson.toJson(this.cloudEndpointPidRequest));
@@ -249,13 +319,13 @@ public void shouldDisconnectEndpoint() {
249319

250320
@Test
251321
public void shouldCheckEndpointStatus() {
252-
givenCloudEndpointPidRequest(CLOUD_ENDPOINT_INSTANCE_TEST);
322+
givenCloudEndpointPidRequest(testCloudInstancePid());
253323

254324
whenRequestIsPerformed(new MethodSpec(METHOD_SPEC_POST), "/cloudEndpoint/isConnected",
255325
gson.toJson(this.cloudEndpointPidRequest));
256326

257327
thenRequestSucceeds();
258-
thenResponseBodyEqualsJson(EXPECTED_IS_ENDPOINT_CONNECTED_RESPONSE);
328+
thenResponseBodyEqualsJson("{\"connected\": false}");
259329
}
260330

261331
private void givenCloudEndpointPidRequest(String pid) {
@@ -291,9 +361,48 @@ private void givenExistingCloudEndpoint(String cloudEndpointPid) {
291361
try {
292362
cloudConnectionFactory.createConfiguration(cloudEndpointPid);
293363

294-
} catch (KuraException e) {
295-
e.printStackTrace();
296-
fail("Unable to create the test CloudService");
364+
final String mqttDataTransportPid = cloudEndpointPid.replace(CLOUD_SERVICE_FACTORY_PID,
365+
MQTT_DATA_TRANSPORT_STACK_COMPONENT_PREFIX);
366+
367+
final DataTransportService dataTransportService = ServiceUtil.trackService(DataTransportService.class,
368+
Optional.of("(kura.service.pid=" + mqttDataTransportPid + ")")).get(30, TimeUnit.SECONDS);
369+
370+
await(() -> {
371+
try {
372+
return configurationService.getComponentConfiguration(mqttDataTransportPid) != null;
373+
} catch (Exception e) {
374+
return false;
375+
}
376+
}, 5, TimeUnit.SECONDS);
377+
378+
logger.info("Test MqttDataTransport with pid {} found...", mqttDataTransportPid);
379+
380+
final Map<String, Object> prioperties = new HashMap<>();
381+
prioperties.put("client-id", "testClientId");
382+
prioperties.put("broker-url", "mqtt://localhost:6666");
383+
384+
configurationService.updateConfiguration(mqttDataTransportPid, prioperties);
385+
386+
await(() -> dataTransportService.getClientId() != null, 5, TimeUnit.SECONDS);
387+
388+
} catch (Exception e) {
389+
final String message = "Unable to create the test CloudService with pid: " + cloudEndpointPid;
390+
logger.warn(message, e);
391+
fail(message);
392+
}
393+
}
394+
395+
private void await(final Supplier<Boolean> predicate, final long duration, final TimeUnit timeUnit)
396+
throws InterruptedException {
397+
398+
final long deadline = System.nanoTime() + timeUnit.toNanos(duration);
399+
400+
while (!predicate.get() && System.nanoTime() < deadline) {
401+
Thread.sleep(100);
402+
}
403+
404+
if (!predicate.get()) {
405+
fail("condition did not occur");
297406
}
298407
}
299408

@@ -302,10 +411,19 @@ private void givenPubSubInstance(String pid, String factoryPid, String cloudEndp
302411
configurationService.createFactoryConfiguration(factoryPid, pid, Collections.singletonMap(
303412
CloudConnectionConstants.CLOUD_ENDPOINT_SERVICE_PID_PROP_NAME.value(), cloudEndpointPid), true);
304413
} catch (KuraException e) {
305-
e.printStackTrace();
306-
fail("Unable to create pubSub instance");
414+
final String message = "Unable to create pubSub instance";
415+
logger.warn(message, e);
416+
fail(message);
307417
}
308418

309419
}
310420

311-
}
421+
private String testCloudInstancesSuffix() {
422+
return "test" + System.identityHashCode(this);
423+
}
424+
425+
private String testCloudInstancePid() {
426+
return "org.eclipse.kura.cloud.CloudService-" + testCloudInstancesSuffix();
427+
}
428+
429+
}

kura/test/org.eclipse.kura.rest.cloudconnection.provider.test/src/main/resources/getStackComponentPidsResponse.json

Lines changed: 0 additions & 7 deletions
This file was deleted.

0 commit comments

Comments
 (0)