Skip to content

Commit c0a74d9

Browse files
committed
Switch opcua tests to test containers.
Relates to #1410. Checked in MiloTestContainer which creates on-the-fly container based on static configuration. Signed-off-by: Łukasz Dywicki <[email protected]>
1 parent 9410635 commit c0a74d9

File tree

5 files changed

+160
-20
lines changed

5 files changed

+160
-20
lines changed

plc4j/drivers/opcua/Dockerfile.test

+6
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
FROM eclipse-temurin:17
2+
3+
ADD "target/milo-testcontainer/*.jar" "/opt/milo/"
4+
ADD "target/test-classes/org/eclipse/milo" "/opt/milo/org/eclipse/milo"
5+
6+
CMD java -cp '/opt/milo/*:/opt/milo/' org.eclipse.milo.examples.server.TestMiloServer

plc4j/drivers/opcua/pom.xml

+35
Original file line numberDiff line numberDiff line change
@@ -69,6 +69,23 @@
6969
</execution>
7070
</executions>
7171
</plugin>
72+
<plugin>
73+
<groupId>org.apache.maven.plugins</groupId>
74+
<artifactId>maven-dependency-plugin</artifactId>
75+
<executions>
76+
<execution>
77+
<id>copy-milo-dependencies</id>
78+
<goals>
79+
<goal>copy-dependencies</goal>
80+
</goals>
81+
<phase>test-compile</phase>
82+
<configuration>
83+
<includeArtifactIds>server-examples</includeArtifactIds>
84+
<outputDirectory>${project.build.directory}/milo-testcontainer</outputDirectory>
85+
</configuration>
86+
</execution>
87+
</executions>
88+
</plugin>
7289
<plugin>
7390
<groupId>org.apache.felix</groupId>
7491
<artifactId>maven-bundle-plugin</artifactId>
@@ -186,6 +203,24 @@
186203
<type>test-jar</type>
187204
<scope>test</scope>
188205
</dependency>
206+
<dependency>
207+
<groupId>org.testcontainers</groupId>
208+
<artifactId>testcontainers</artifactId>
209+
<version>1.20.0</version>
210+
<scope>test</scope>
211+
</dependency>
212+
<dependency>
213+
<groupId>org.testcontainers</groupId>
214+
<artifactId>junit-jupiter</artifactId>
215+
<version>1.20.0</version>
216+
<scope>test</scope>
217+
</dependency>
218+
<dependency>
219+
<groupId>com.google.cloud.tools</groupId>
220+
<artifactId>jib-core</artifactId>
221+
<version>0.22.0</version>
222+
<scope>test</scope>
223+
</dependency>
189224
</dependencies>
190225

191226
<dependencyManagement>
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,49 @@
1+
/*
2+
* Licensed to the Apache Software Foundation (ASF) under one
3+
* or more contributor license agreements. See the NOTICE file
4+
* distributed with this work for additional information
5+
* regarding copyright ownership. The ASF licenses this file
6+
* to you under the Apache License, Version 2.0 (the
7+
* "License"); you may not use this file except in compliance
8+
* with the License. You may obtain a copy of the License at
9+
*
10+
* http://www.apache.org/licenses/LICENSE-2.0
11+
*
12+
* Unless required by applicable law or agreed to in writing,
13+
* software distributed under the License is distributed on an
14+
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
15+
* KIND, either express or implied. See the License for the
16+
* specific language governing permissions and limitations
17+
* under the License.
18+
*/
19+
20+
package org.apache.plc4x.java.opcua;
21+
22+
import java.nio.file.Path;
23+
import java.nio.file.Paths;
24+
import org.slf4j.Logger;
25+
import org.slf4j.LoggerFactory;
26+
import org.testcontainers.containers.GenericContainer;
27+
import org.testcontainers.containers.wait.strategy.Wait;
28+
import org.testcontainers.images.builder.ImageFromDockerfile;
29+
30+
public class MiloTestContainer extends GenericContainer<MiloTestContainer> {
31+
32+
private final static Logger logger = LoggerFactory.getLogger(MiloTestContainer.class);
33+
34+
public MiloTestContainer() {
35+
super(inlineImage());
36+
37+
waitingFor(Wait.forLogMessage("Server started\\s*", 1));
38+
addFixedExposedPort(12686, 12686);
39+
}
40+
41+
private static ImageFromDockerfile inlineImage() {
42+
Path absolutePath = Paths.get(".").toAbsolutePath();
43+
logger.info("Building milo server image from {}", absolutePath);
44+
return new ImageFromDockerfile("plc4x-milo-test", false)
45+
.withBuildImageCmdModifier(cmd -> cmd.withNoCache(true))
46+
.withDockerfile(absolutePath.resolve("Dockerfile.test"));
47+
}
48+
49+
}

plc4j/drivers/opcua/src/test/java/org/apache/plc4x/java/opcua/OpcuaPlcDriverTest.java

+37-20
Original file line numberDiff line numberDiff line change
@@ -62,17 +62,29 @@
6262
import java.nio.file.Paths;
6363
import java.util.concurrent.ExecutionException;
6464
import java.util.stream.Stream;
65+
import org.testcontainers.containers.GenericContainer;
66+
import org.testcontainers.containers.output.Slf4jLogConsumer;
67+
import org.testcontainers.containers.wait.strategy.Wait;
68+
import org.testcontainers.images.builder.ImageFromDockerfile;
69+
import org.testcontainers.jib.JibImage;
70+
import org.testcontainers.junit.jupiter.Container;
71+
import org.testcontainers.junit.jupiter.Testcontainers;
6572

6673
import static java.util.Map.entry;
6774
import static org.assertj.core.api.Assertions.assertThat;
6875
import static org.assertj.core.api.Assertions.fail;
6976

77+
@Testcontainers(disabledWithoutDocker = true)
7078
@DisableOnJenkinsFlag
71-
@Disabled("This test regularly fails the build, it needs to be generally fixed.")
7279
public class OpcuaPlcDriverTest {
7380

7481
private static final Logger LOGGER = LoggerFactory.getLogger(OpcuaPlcDriverTest.class);
7582

83+
@Container
84+
public static final GenericContainer milo = new MiloTestContainer()
85+
//.withCreateContainerCmdModifier(cmd -> cmd.withHostName("test-opcua-server"))
86+
.withReuse(true);
87+
7688
// Read only variables of milo example server of version 3.6
7789
private static final String BOOL_IDENTIFIER_READ_WRITE = "ns=2;s=HelloWorld/ScalarTypes/Boolean";
7890
private static final String BYTE_IDENTIFIER_READ_WRITE = "ns=2;s=HelloWorld/ScalarTypes/Byte";
@@ -123,50 +135,55 @@ public class OpcuaPlcDriverTest {
123135
//Restricted
124136
public static final String STRING_IDENTIFIER_ONLY_ADMIN_READ_WRITE = "ns=2;s=HelloWorld/OnlyAdminCanRead/String";
125137

126-
// Address of local milo server
127-
private final String miloLocalAddress = "127.0.0.1:12686/milo";
138+
// Address of local milo server, since it comes from test container its hostname and port is not static
139+
private final String miloLocalAddress = "%s:%d/milo";
128140
//Tcp pattern of OPC UA
129141
private final String opcPattern = "opcua:tcp://";
130142

131143
private final String paramSectionDivider = "?";
132144
private final String paramDivider = "&";
133145

134-
private final String tcpConnectionAddress = opcPattern + miloLocalAddress;
135-
136-
private final List<String> connectionStringValidSet = List.of(tcpConnectionAddress);
137-
private final List<String> connectionStringCorruptedSet = List.of();
138-
139146
private final String discoveryValidParamTrue = "discovery=true";
140147
private final String discoveryValidParamFalse = "discovery=false";
141148
private final String discoveryCorruptedParamWrongValueNum = "discovery=1";
142149
private final String discoveryCorruptedParamWrongName = "diskovery=false";
143150

151+
private String tcpConnectionAddress;
152+
private List<String> connectionStringValidSet;
153+
144154
final List<String> discoveryParamValidSet = List.of(discoveryValidParamTrue, discoveryValidParamFalse);
145155
List<String> discoveryParamCorruptedSet = List.of(discoveryCorruptedParamWrongValueNum, discoveryCorruptedParamWrongName);
146156

147157
private static TestMiloServer exampleServer;
148158

159+
@BeforeEach
160+
public void startUp() {
161+
//System.out.println(milo.getMappedPort(12686));
162+
tcpConnectionAddress = String.format(opcPattern + miloLocalAddress, milo.getHost(), milo.getMappedPort(12686));
163+
connectionStringValidSet = List.of(tcpConnectionAddress);
164+
}
165+
149166
@BeforeAll
150167
public static void setup() throws Exception {
151168
// When switching JDK versions from a newer to an older version,
152169
// this can cause the server to not start correctly.
153170
// Deleting the directory makes sure the key-store is initialized correctly.
154-
Path securityBaseDir = Paths.get(System.getProperty("java.io.tmpdir"), "server", "security");
155-
try {
156-
Files.delete(securityBaseDir);
157-
} catch (Exception e) {
158-
// Ignore this ...
159-
}
160-
161-
exampleServer = new TestMiloServer();
162-
exampleServer.startup().get();
171+
// Path securityBaseDir = Paths.get(System.getProperty("java.io.tmpdir"), "server", "security");
172+
// try {
173+
// Files.delete(securityBaseDir);
174+
// } catch (Exception e) {
175+
// // Ignore this ...
176+
// }
177+
//
178+
// exampleServer = new TestMiloServer();
179+
// exampleServer.startup().get();
163180
}
164181

165182
@AfterAll
166183
public static void tearDown() throws Exception {
167-
if (exampleServer != null) {
168-
exampleServer.shutdown().get();
169-
}
184+
// if (exampleServer != null) {
185+
// exampleServer.shutdown().get();
186+
// }
170187
}
171188

172189
@Nested

plc4j/drivers/opcua/src/test/java/org/eclipse/milo/examples/server/TestMiloServer.java

+33
Original file line numberDiff line numberDiff line change
@@ -28,12 +28,17 @@
2828
import java.nio.file.Path;
2929
import java.nio.file.Paths;
3030
import java.security.KeyPair;
31+
import java.security.Security;
3132
import java.security.cert.X509Certificate;
3233
import java.util.ArrayList;
3334
import java.util.LinkedHashSet;
3435
import java.util.List;
3536
import java.util.Set;
3637
import java.util.concurrent.CompletableFuture;
38+
import java.util.concurrent.ExecutionException;
39+
import java.util.concurrent.TimeUnit;
40+
import java.util.concurrent.TimeoutException;
41+
import org.bouncycastle.jce.provider.BouncyCastleProvider;
3742
import org.eclipse.milo.opcua.sdk.server.OpcUaServer;
3843
import org.eclipse.milo.opcua.sdk.server.api.config.OpcUaServerConfig;
3944
import org.eclipse.milo.opcua.sdk.server.identity.CompositeValidator;
@@ -52,6 +57,7 @@
5257
import org.eclipse.milo.opcua.stack.core.types.enumerated.MessageSecurityMode;
5358
import org.eclipse.milo.opcua.stack.core.types.structured.BuildInfo;
5459
import org.eclipse.milo.opcua.stack.core.util.CertificateUtil;
60+
import org.eclipse.milo.opcua.stack.core.util.NonceUtil;
5561
import org.eclipse.milo.opcua.stack.core.util.SelfSignedCertificateGenerator;
5662
import org.eclipse.milo.opcua.stack.core.util.SelfSignedHttpsCertificateBuilder;
5763
import org.eclipse.milo.opcua.stack.server.EndpointConfiguration;
@@ -69,6 +75,32 @@ public class TestMiloServer {
6975
private final OpcUaServer server;
7076
private final ExampleNamespace exampleNamespace;
7177

78+
static {
79+
// Required for SecurityPolicy.Aes256_Sha256_RsaPss
80+
Security.addProvider(new BouncyCastleProvider());
81+
82+
try {
83+
NonceUtil.blockUntilSecureRandomSeeded(10, TimeUnit.SECONDS);
84+
} catch (ExecutionException | InterruptedException | TimeoutException e) {
85+
e.printStackTrace();
86+
System.exit(-1);
87+
}
88+
}
89+
90+
public static void main(String[] args) throws Exception {
91+
TestMiloServer server = new TestMiloServer();
92+
93+
server.startup().thenAccept(srv -> {
94+
System.out.println("Server started");
95+
}).get();
96+
97+
final CompletableFuture<Void> future = new CompletableFuture<>();
98+
99+
Runtime.getRuntime().addShutdownHook(new Thread(() -> future.complete(null)));
100+
101+
future.get();
102+
}
103+
72104
public TestMiloServer() throws Exception {
73105
Path securityTempDir = Paths.get(System.getProperty("java.io.tmpdir"), "server", "security");
74106
Files.createDirectories(securityTempDir);
@@ -168,6 +200,7 @@ private Set<EndpointConfiguration> createEndpointConfigurations(X509Certificate
168200
bindAddresses.add("0.0.0.0");
169201

170202
Set<String> hostnames = new LinkedHashSet<>();
203+
hostnames.add("localhost");
171204
hostnames.add(HostnameUtil.getHostname());
172205
hostnames.addAll(HostnameUtil.getHostnames("0.0.0.0"));
173206

0 commit comments

Comments
 (0)