This is an automated email from the ASF dual-hosted git repository. jamesnetherton pushed a commit to branch main in repository https://gitbox.apache.org/repos/asf/camel-quarkus.git
The following commit(s) were added to refs/heads/main by this push: new b44944782e jt400 mock coverage + native fixes b44944782e is described below commit b44944782e5bb223c698b256ef19c4a0c0bb37ac Author: JiriOndrusek <ondrusek.j...@gmail.com> AuthorDate: Tue Feb 27 11:58:28 2024 +0100 jt400 mock coverage + native fixes --- .../component/jt400/deployment/Jt400Processor.java | 37 ++++++ integration-tests/jt400/pom.xml | 33 +++++ .../main/java/com/ibm/as400/access/MockAS400.java | 61 +++++++++ .../com/ibm/as400/access/MockAS400ImplRemote.java} | 23 ++-- .../com/ibm/as400/access/MockAS400Server.java} | 27 ++-- .../java/com/ibm/as400/access/MockDataStream.java} | 34 +++-- .../com/ibm/as400/access/MockSocketContainer.java | 77 +++++++++++ .../com/ibm/as400/access/MockedResponses.java} | 27 ++-- .../java/com/ibm/as400/access/ReplyDQCommon.java} | 28 ++-- .../com/ibm/as400/access/ReplyDQReadNormal.java | 54 ++++++++ .../access/ReplyDQRequestAttributesNormal.java} | 53 ++++++-- .../java/com/ibm/as400/access/ReplyOk.java} | 11 +- .../com/ibm/as400/access/ReplyRCCallProgram.java | 70 ++++++++++ .../as400/access/ReplyRCExchangeAttributes.java} | 21 ++- .../quarkus/component/jt400/it/Jt400Producers.java | 62 +++++++++ .../quarkus/component/jt400/it/Jt400Resource.java | 122 +++++++++++++++++- .../jt400/it/MockAS400ConnectionPool.java | 71 +++++++++++ .../src/main/resources/application.properties | 17 +++ .../jt400/it/{Jt400IT.java => Jt400MockIT.java} | 4 +- .../quarkus/component/jt400/it/Jt400MockTest.java | 142 +++++++++++++++++++++ 20 files changed, 886 insertions(+), 88 deletions(-) diff --git a/extensions/jt400/deployment/src/main/java/org/apache/camel/quarkus/component/jt400/deployment/Jt400Processor.java b/extensions/jt400/deployment/src/main/java/org/apache/camel/quarkus/component/jt400/deployment/Jt400Processor.java index 12d43daaa8..702d7e3983 100644 --- a/extensions/jt400/deployment/src/main/java/org/apache/camel/quarkus/component/jt400/deployment/Jt400Processor.java +++ b/extensions/jt400/deployment/src/main/java/org/apache/camel/quarkus/component/jt400/deployment/Jt400Processor.java @@ -18,16 +18,26 @@ package org.apache.camel.quarkus.component.jt400.deployment; import java.util.ArrayList; import java.util.List; +import java.util.regex.Pattern; +import com.ibm.as400.access.ConvTable; +import com.ibm.as400.access.NLSImplNative; +import io.quarkus.deployment.annotations.BuildProducer; import io.quarkus.deployment.annotations.BuildStep; +import io.quarkus.deployment.builditem.CombinedIndexBuildItem; import io.quarkus.deployment.builditem.FeatureBuildItem; +import io.quarkus.deployment.builditem.IndexDependencyBuildItem; +import io.quarkus.deployment.builditem.nativeimage.ReflectiveClassBuildItem; import io.quarkus.deployment.builditem.nativeimage.RuntimeInitializedClassBuildItem; +import org.jboss.jandex.DotName; +import org.jboss.jandex.IndexView; import org.jboss.logging.Logger; class Jt400Processor { private static final Logger LOG = Logger.getLogger(Jt400Processor.class); private static final String FEATURE = "camel-jt400"; + private static final DotName CONV_TABLE_NAME = DotName.createSimple(ConvTable.class.getName()); @BuildStep FeatureBuildItem feature() { @@ -40,4 +50,31 @@ class Jt400Processor { items.add(new RuntimeInitializedClassBuildItem("com.ibm.as400.access.CredentialVault")); return items; } + + @BuildStep + void reflectiveClasses(BuildProducer<ReflectiveClassBuildItem> reflectiveClassesProducer, + CombinedIndexBuildItem combinedIndex) { + IndexView index = combinedIndex.getIndex(); + + reflectiveClassesProducer.produce(ReflectiveClassBuildItem.builder(NLSImplNative.class).build()); + + Pattern pattern = Pattern.compile("com.ibm.as400.access.*Remote"); + index.getKnownClasses().stream() + .filter(c -> pattern.matcher(c.name().toString()).matches()) + .map(c -> ReflectiveClassBuildItem.builder(c.name().toString()).build()) + .forEach(reflectiveClassesProducer::produce); + + combinedIndex.getIndex() + .getAllKnownSubclasses(CONV_TABLE_NAME) + .stream() + .map(c -> ReflectiveClassBuildItem.builder(c.name().toString()).build()) + .forEach(reflectiveClassesProducer::produce); + + } + + @BuildStep + IndexDependencyBuildItem registerDependencyForIndex() { + return new IndexDependencyBuildItem("net.sf.jt400", "jt400", "java11"); + } + } diff --git a/integration-tests/jt400/pom.xml b/integration-tests/jt400/pom.xml index 91a001285e..eaef839185 100644 --- a/integration-tests/jt400/pom.xml +++ b/integration-tests/jt400/pom.xml @@ -30,6 +30,22 @@ <name>Camel Quarkus :: Integration Tests :: JT400</name> <description>Integration tests for Camel Quarkus JT400 extension</description> + <properties> + <quarkus.test.flat-class-path>true</quarkus.test.flat-class-path> + </properties> + + <build> + <resources> + <resource> + <directory>src/main/resources</directory> + <filtering>true</filtering> + <includes> + <include>application.properties</include> + </includes> + </resource> + </resources> + </build> + <dependencies> <dependency> <groupId>org.apache.camel.quarkus</groupId> @@ -39,6 +55,10 @@ <groupId>io.quarkus</groupId> <artifactId>quarkus-resteasy</artifactId> </dependency> + <dependency> + <groupId>io.quarkus</groupId> + <artifactId>quarkus-resteasy-jackson</artifactId> + </dependency> <!-- test dependencies --> <dependency> @@ -105,6 +125,19 @@ </dependency> </dependencies> </profile> + <profile> + <!-- Mock tests require flat classpath, which are enabled by default. + This profile disables flat classpath--> + <id>skip-mock-tests</id> + <activation> + <property> + <name>skip-mock-tests</name> + </property> + </activation> + <properties> + <quarkus.test.flat-class-path>false</quarkus.test.flat-class-path> + </properties> + </profile> </profiles> </project> diff --git a/integration-tests/jt400/src/main/java/com/ibm/as400/access/MockAS400.java b/integration-tests/jt400/src/main/java/com/ibm/as400/access/MockAS400.java new file mode 100644 index 0000000000..f690086d83 --- /dev/null +++ b/integration-tests/jt400/src/main/java/com/ibm/as400/access/MockAS400.java @@ -0,0 +1,61 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You 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 com.ibm.as400.access; + +import java.io.IOException; + +public class MockAS400 extends AS400 { + + private final MockAS400ImplRemote as400ImplRemote; + + public MockAS400(MockAS400ImplRemote as400ImplRemote) { + this.as400ImplRemote = as400ImplRemote; + } + + @Override + public AS400Impl getImpl() { + return as400ImplRemote; + } + + @Override + public int getCcsid() { + //ConvTable37 depends on this value + return 37; + } + + @Override + public boolean isConnected(int service) { + //always connected + return true; + } + + @Override + public void connectService(int service, int overridePort) throws AS400SecurityException, IOException { + //connection to real i server is ignored + setSignonInfo(-1, -1, "username"); + } + + @Override + synchronized void signon(boolean keepConnection) throws AS400SecurityException, IOException { + //do nothing + } + + @Override + public int getVRM() throws AS400SecurityException, IOException { + return 1; + } +} diff --git a/integration-tests/jt400/src/test/java/org/apache/camel/quarkus/component/jt400/it/Jt400Test.java b/integration-tests/jt400/src/main/java/com/ibm/as400/access/MockAS400ImplRemote.java similarity index 66% copy from integration-tests/jt400/src/test/java/org/apache/camel/quarkus/component/jt400/it/Jt400Test.java copy to integration-tests/jt400/src/main/java/com/ibm/as400/access/MockAS400ImplRemote.java index 1bf9069224..09553ebae6 100644 --- a/integration-tests/jt400/src/test/java/org/apache/camel/quarkus/component/jt400/it/Jt400Test.java +++ b/integration-tests/jt400/src/main/java/com/ibm/as400/access/MockAS400ImplRemote.java @@ -14,20 +14,19 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package org.apache.camel.quarkus.component.jt400.it; +package com.ibm.as400.access; -import io.quarkus.test.junit.QuarkusTest; -import io.restassured.RestAssured; -import org.junit.jupiter.api.Test; +import java.io.IOException; -@QuarkusTest -public class Jt400Test { +public class MockAS400ImplRemote extends AS400ImplRemote { - @Test - public void loadComponentJt400() { - /* A simple autogenerated test */ - RestAssured.get("/jt400/load/component/jt400") - .then() - .statusCode(200); + AS400Server getConnection(int service, boolean forceNewConnection, + boolean skipSignonServer) throws AS400SecurityException, IOException { + return new MockAS400Server(this); + } + + @Override + public String getNLV() { + return "012345678901234567890123456789"; } } diff --git a/integration-tests/jt400/src/test/java/org/apache/camel/quarkus/component/jt400/it/Jt400Test.java b/integration-tests/jt400/src/main/java/com/ibm/as400/access/MockAS400Server.java similarity index 62% copy from integration-tests/jt400/src/test/java/org/apache/camel/quarkus/component/jt400/it/Jt400Test.java copy to integration-tests/jt400/src/main/java/com/ibm/as400/access/MockAS400Server.java index 1bf9069224..07a25a91cb 100644 --- a/integration-tests/jt400/src/test/java/org/apache/camel/quarkus/component/jt400/it/Jt400Test.java +++ b/integration-tests/jt400/src/main/java/com/ibm/as400/access/MockAS400Server.java @@ -14,20 +14,23 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package org.apache.camel.quarkus.component.jt400.it; +package com.ibm.as400.access; -import io.quarkus.test.junit.QuarkusTest; -import io.restassured.RestAssured; -import org.junit.jupiter.api.Test; +import java.io.IOException; -@QuarkusTest -public class Jt400Test { +public class MockAS400Server extends AS400NoThreadServer { - @Test - public void loadComponentJt400() { - /* A simple autogenerated test */ - RestAssured.get("/jt400/load/component/jt400") - .then() - .statusCode(200); + MockAS400Server(AS400ImplRemote system) throws IOException { + super(system, 1, new MockSocketContainer(), "job/String/something"); } + + @Override + public DataStream sendAndReceive(DataStream requestStream) throws IOException { + if (!MockedResponses.isEmpty()) { + return MockedResponses.removeFirst(); + } + + return null; + } + } diff --git a/integration-tests/jt400/src/test/java/org/apache/camel/quarkus/component/jt400/it/Jt400Test.java b/integration-tests/jt400/src/main/java/com/ibm/as400/access/MockDataStream.java similarity index 66% copy from integration-tests/jt400/src/test/java/org/apache/camel/quarkus/component/jt400/it/Jt400Test.java copy to integration-tests/jt400/src/main/java/com/ibm/as400/access/MockDataStream.java index 1bf9069224..7cfa53721b 100644 --- a/integration-tests/jt400/src/test/java/org/apache/camel/quarkus/component/jt400/it/Jt400Test.java +++ b/integration-tests/jt400/src/main/java/com/ibm/as400/access/MockDataStream.java @@ -14,20 +14,30 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package org.apache.camel.quarkus.component.jt400.it; +package com.ibm.as400.access; -import io.quarkus.test.junit.QuarkusTest; -import io.restassured.RestAssured; -import org.junit.jupiter.api.Test; +public class MockDataStream extends DataStream { + MockDataStream() { + super(30); + } + + @Override + int getCorrelation() { + return 0; + } + + @Override + int getLength() { + return 0; + } + + @Override + void setCorrelation(int correlation) { + + } -@QuarkusTest -public class Jt400Test { + @Override + void setLength(int len) { - @Test - public void loadComponentJt400() { - /* A simple autogenerated test */ - RestAssured.get("/jt400/load/component/jt400") - .then() - .statusCode(200); } } diff --git a/integration-tests/jt400/src/main/java/com/ibm/as400/access/MockSocketContainer.java b/integration-tests/jt400/src/main/java/com/ibm/as400/access/MockSocketContainer.java new file mode 100644 index 0000000000..39a1516520 --- /dev/null +++ b/integration-tests/jt400/src/main/java/com/ibm/as400/access/MockSocketContainer.java @@ -0,0 +1,77 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You 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 com.ibm.as400.access; + +import java.io.ByteArrayInputStream; +import java.io.ByteArrayOutputStream; +import java.io.IOException; +import java.io.InputStream; +import java.io.OutputStream; +import java.net.Socket; +import java.net.SocketException; + +public class MockSocketContainer extends SocketContainer { + + ByteArrayOutputStream bOutput = new ByteArrayOutputStream(50); + + byte[] _data = new byte[50]; + + public MockSocketContainer() { + + // https://github.com/IBM/JTOpen/blob/98e74fae6d212563a1558abce60ea5c73fcfc0c0/src/main/java/com/ibm/as400/access/ClientAccessDataStream.java#L70 + _data[6] = (byte) 0xE0; + + //sets length to 49 + _data[1] = 0; + _data[2] = 0; + _data[3] = '1'; + + _data[4] = 0; + _data[5] = 0; + _data[7] = 0; + } + + @Override + void setProperties(Socket socket, String serviceName, String systemName, int port, SSLOptions options) throws IOException { + + } + + @Override + void close() throws IOException { + + } + + @Override + InputStream getInputStream() throws IOException { + return new ByteArrayInputStream(_data); + } + + @Override + OutputStream getOutputStream() throws IOException { + return bOutput; + } + + @Override + void setSoTimeout(int timeout) throws SocketException { + + } + + @Override + int getSoTimeout() throws SocketException { + return 0; + } +} diff --git a/integration-tests/jt400/src/test/java/org/apache/camel/quarkus/component/jt400/it/Jt400Test.java b/integration-tests/jt400/src/main/java/com/ibm/as400/access/MockedResponses.java similarity index 65% copy from integration-tests/jt400/src/test/java/org/apache/camel/quarkus/component/jt400/it/Jt400Test.java copy to integration-tests/jt400/src/main/java/com/ibm/as400/access/MockedResponses.java index 1bf9069224..392b98ddc1 100644 --- a/integration-tests/jt400/src/test/java/org/apache/camel/quarkus/component/jt400/it/Jt400Test.java +++ b/integration-tests/jt400/src/main/java/com/ibm/as400/access/MockedResponses.java @@ -14,20 +14,23 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package org.apache.camel.quarkus.component.jt400.it; +package com.ibm.as400.access; -import io.quarkus.test.junit.QuarkusTest; -import io.restassured.RestAssured; -import org.junit.jupiter.api.Test; +import java.util.LinkedList; -@QuarkusTest -public class Jt400Test { +public class MockedResponses { - @Test - public void loadComponentJt400() { - /* A simple autogenerated test */ - RestAssured.get("/jt400/load/component/jt400") - .then() - .statusCode(200); + private static LinkedList<DataStream> responses = new LinkedList<>(); + + public static void add(DataStream dataStream) { + responses.add(dataStream); + } + + public static DataStream removeFirst() { + return responses.removeFirst(); + } + + public static boolean isEmpty() { + return responses.isEmpty(); } } diff --git a/integration-tests/jt400/src/test/java/org/apache/camel/quarkus/component/jt400/it/Jt400Test.java b/integration-tests/jt400/src/main/java/com/ibm/as400/access/ReplyDQCommon.java similarity index 63% copy from integration-tests/jt400/src/test/java/org/apache/camel/quarkus/component/jt400/it/Jt400Test.java copy to integration-tests/jt400/src/main/java/com/ibm/as400/access/ReplyDQCommon.java index 1bf9069224..4517d3189a 100644 --- a/integration-tests/jt400/src/test/java/org/apache/camel/quarkus/component/jt400/it/Jt400Test.java +++ b/integration-tests/jt400/src/main/java/com/ibm/as400/access/ReplyDQCommon.java @@ -14,20 +14,24 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package org.apache.camel.quarkus.component.jt400.it; +package com.ibm.as400.access; -import io.quarkus.test.junit.QuarkusTest; -import io.restassured.RestAssured; -import org.junit.jupiter.api.Test; +public class ReplyDQCommon extends DQCommonReplyDataStream { -@QuarkusTest -public class Jt400Test { + private final int hashCode; - @Test - public void loadComponentJt400() { - /* A simple autogenerated test */ - RestAssured.get("/jt400/load/component/jt400") - .then() - .statusCode(200); + public ReplyDQCommon(int hashCode) { + this.hashCode = hashCode; + } + + @Override + public int hashCode() { + return hashCode; + } + + @Override + int getRC() { + //because of https://github.com/IBM/JTOpen/blob/main/src/main/java/com/ibm/as400/access/BaseDataQueueImplRemote.java#L332 + return 0xF000; } } diff --git a/integration-tests/jt400/src/main/java/com/ibm/as400/access/ReplyDQReadNormal.java b/integration-tests/jt400/src/main/java/com/ibm/as400/access/ReplyDQReadNormal.java new file mode 100644 index 0000000000..66f4e9cbf6 --- /dev/null +++ b/integration-tests/jt400/src/main/java/com/ibm/as400/access/ReplyDQReadNormal.java @@ -0,0 +1,54 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You 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 com.ibm.as400.access; + +import java.nio.charset.StandardCharsets; + +public class ReplyDQReadNormal extends DQReadNormalReplyDataStream { + + private final int hashCode; + private final String senderInformation; + private final String entry; + private final String key; + + public ReplyDQReadNormal(int hashCode, String senderInformation, String entry, String key) { + this.hashCode = hashCode; + this.senderInformation = senderInformation; + this.entry = entry; + this.key = key; + } + + @Override + public int hashCode() { + return hashCode; + } + + @Override + byte[] getSenderInformation() { + return senderInformation.getBytes(StandardCharsets.UTF_8); + } + + @Override + byte[] getEntry() { + return entry.getBytes(StandardCharsets.UTF_8); + } + + @Override + byte[] getKey() { + return key.getBytes(StandardCharsets.UTF_8); + } +} diff --git a/integration-tests/jt400/src/test/java/org/apache/camel/quarkus/component/jt400/it/Jt400Test.java b/integration-tests/jt400/src/main/java/com/ibm/as400/access/ReplyDQRequestAttributesNormal.java similarity index 50% rename from integration-tests/jt400/src/test/java/org/apache/camel/quarkus/component/jt400/it/Jt400Test.java rename to integration-tests/jt400/src/main/java/com/ibm/as400/access/ReplyDQRequestAttributesNormal.java index 1bf9069224..81cd5613a1 100644 --- a/integration-tests/jt400/src/test/java/org/apache/camel/quarkus/component/jt400/it/Jt400Test.java +++ b/integration-tests/jt400/src/main/java/com/ibm/as400/access/ReplyDQRequestAttributesNormal.java @@ -14,20 +14,49 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package org.apache.camel.quarkus.component.jt400.it; +package com.ibm.as400.access; -import io.quarkus.test.junit.QuarkusTest; -import io.restassured.RestAssured; -import org.junit.jupiter.api.Test; +public class ReplyDQRequestAttributesNormal extends DQRequestAttributesNormalReplyDataStream { -@QuarkusTest -public class Jt400Test { + private final int keyLength; - @Test - public void loadComponentJt400() { - /* A simple autogenerated test */ - RestAssured.get("/jt400/load/component/jt400") - .then() - .statusCode(200); + public ReplyDQRequestAttributesNormal(int keyLength) { + this.keyLength = keyLength; + } + + @Override + public int hashCode() { + return 0x8001; + } + + @Override + int getType() { + //required for keyed + return 2; + } + + @Override + int getMaxEntryLength() { + return 1; + } + + @Override + boolean getSaveSenderInformation() { + return false; + } + + @Override + boolean getForceToAuxiliaryStorage() { + return false; + } + + @Override + byte[] getDescription() { + return new byte[5]; + } + + @Override + int getKeyLength() { + return keyLength; } } diff --git a/integration-tests/jt400/src/test/java/org/apache/camel/quarkus/component/jt400/it/Jt400IT.java b/integration-tests/jt400/src/main/java/com/ibm/as400/access/ReplyOk.java similarity index 82% copy from integration-tests/jt400/src/test/java/org/apache/camel/quarkus/component/jt400/it/Jt400IT.java copy to integration-tests/jt400/src/main/java/com/ibm/as400/access/ReplyOk.java index 11e65bf29a..f9569479e0 100644 --- a/integration-tests/jt400/src/test/java/org/apache/camel/quarkus/component/jt400/it/Jt400IT.java +++ b/integration-tests/jt400/src/main/java/com/ibm/as400/access/ReplyOk.java @@ -14,11 +14,12 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package org.apache.camel.quarkus.component.jt400.it; +package com.ibm.as400.access; -import io.quarkus.test.junit.QuarkusIntegrationTest; - -@QuarkusIntegrationTest -class Jt400IT extends Jt400Test { +public class ReplyOk extends DQRequestAttributesNormalReplyDataStream { + @Override + public int hashCode() { + return 0x8000; + } } diff --git a/integration-tests/jt400/src/main/java/com/ibm/as400/access/ReplyRCCallProgram.java b/integration-tests/jt400/src/main/java/com/ibm/as400/access/ReplyRCCallProgram.java new file mode 100644 index 0000000000..1be991acdd --- /dev/null +++ b/integration-tests/jt400/src/main/java/com/ibm/as400/access/ReplyRCCallProgram.java @@ -0,0 +1,70 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You 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 com.ibm.as400.access; + +import java.nio.charset.StandardCharsets; + +public class ReplyRCCallProgram extends RCCallProgramReplyDataStream { + + public ReplyRCCallProgram() { + } + + @Override + int getRC() { + //success + return 0x0000; + } + + @Override + void getParameterList(ProgramParameter[] parameterList) { + //skip + byte[] str = "hello".repeat(50).getBytes(StandardCharsets.UTF_8); + //lengths are encoded in the string + // int lengthDataReturned = BinaryConverter.byteArrayToInt(data, 152); + // int lengthMessageReturned = BinaryConverter.byteArrayToInt(data, 160); + // int lengthHelpReturned = BinaryConverter.byteArrayToInt(data, 168); + str[150] = 0; + str[151] = 0; + str[152] = 0; + str[153] = 0; + str[154] = 0; + str[155] = 1; + str[156] = 0; + str[157] = 0; + str[158] = 0; + str[159] = 0; + str[160] = 0; + str[161] = 0; + str[162] = 0; + str[163] = 0; + str[164] = 0; + str[165] = 0; + str[166] = 0; + str[167] = 1; + str[168] = 0; + str[169] = 0; + str[170] = 0; + str[171] = 0; + str[172] = 0; + str[173] = 0; + str[174] = 0; + str[175] = 1; + str[176] = 0; + + parameterList[0].setOutputData(str); + } +} diff --git a/integration-tests/jt400/src/test/java/org/apache/camel/quarkus/component/jt400/it/Jt400IT.java b/integration-tests/jt400/src/main/java/com/ibm/as400/access/ReplyRCExchangeAttributes.java similarity index 67% copy from integration-tests/jt400/src/test/java/org/apache/camel/quarkus/component/jt400/it/Jt400IT.java copy to integration-tests/jt400/src/main/java/com/ibm/as400/access/ReplyRCExchangeAttributes.java index 11e65bf29a..6f45c84792 100644 --- a/integration-tests/jt400/src/test/java/org/apache/camel/quarkus/component/jt400/it/Jt400IT.java +++ b/integration-tests/jt400/src/main/java/com/ibm/as400/access/ReplyRCExchangeAttributes.java @@ -14,11 +14,24 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package org.apache.camel.quarkus.component.jt400.it; +package com.ibm.as400.access; -import io.quarkus.test.junit.QuarkusIntegrationTest; +public class ReplyRCExchangeAttributes extends RCExchangeAttributesReplyDataStream { -@QuarkusIntegrationTest -class Jt400IT extends Jt400Test { + @Override + int getRC() { + //successful return code + return 0x0000; + } + @Override + int getCCSID() { + //ConvTable37 depends on this value + return 37; + } + + // Server datastream level. + int getDSLevel() { + return 1; + } } diff --git a/integration-tests/jt400/src/main/java/org/apache/camel/quarkus/component/jt400/it/Jt400Producers.java b/integration-tests/jt400/src/main/java/org/apache/camel/quarkus/component/jt400/it/Jt400Producers.java new file mode 100644 index 0000000000..2043d2028f --- /dev/null +++ b/integration-tests/jt400/src/main/java/org/apache/camel/quarkus/component/jt400/it/Jt400Producers.java @@ -0,0 +1,62 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You 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 org.apache.camel.quarkus.component.jt400.it; + +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import java.util.concurrent.CopyOnWriteArrayList; + +import com.ibm.as400.access.AS400ConnectionPool; +import com.ibm.as400.access.MockAS400; +import com.ibm.as400.access.MockAS400ImplRemote; +import jakarta.enterprise.context.ApplicationScoped; +import jakarta.enterprise.inject.Produces; +import jakarta.inject.Named; + +public class Jt400Producers { + + @Produces + @ApplicationScoped + @Named("collected-data") + public Map<String, List<String>> collectedData() { + Map<String, List<String>> result = new HashMap<>(); + result.put("queue", new CopyOnWriteArrayList<>()); + return result; + } + + //-------------------------- mocked backend ------------------------------------------------ + + @Produces + @ApplicationScoped + MockAS400ImplRemote produceMockAS400ImplRemote() { + return new MockAS400ImplRemote(); + } + + @Produces + @ApplicationScoped + MockAS400 produceMockAS400(MockAS400ImplRemote as400ImplRemote) { + return new MockAS400(as400ImplRemote); + } + + @Produces + @ApplicationScoped + @Named("mockPool") + AS400ConnectionPool produceConnectionPool(MockAS400 mockAS400) { + return new MockAS400ConnectionPool(mockAS400); + } +} diff --git a/integration-tests/jt400/src/main/java/org/apache/camel/quarkus/component/jt400/it/Jt400Resource.java b/integration-tests/jt400/src/main/java/org/apache/camel/quarkus/component/jt400/it/Jt400Resource.java index d066206f20..fd65e7950a 100644 --- a/integration-tests/jt400/src/main/java/org/apache/camel/quarkus/component/jt400/it/Jt400Resource.java +++ b/integration-tests/jt400/src/main/java/org/apache/camel/quarkus/component/jt400/it/Jt400Resource.java @@ -16,35 +16,145 @@ */ package org.apache.camel.quarkus.component.jt400.it; +import java.util.Map; + +import com.ibm.as400.access.DataStream; +import com.ibm.as400.access.MockAS400ImplRemote; +import com.ibm.as400.access.MockedResponses; +import com.ibm.as400.access.ReplyDQCommon; +import com.ibm.as400.access.ReplyDQReadNormal; +import com.ibm.as400.access.ReplyDQRequestAttributesNormal; +import com.ibm.as400.access.ReplyOk; +import com.ibm.as400.access.ReplyRCCallProgram; +import com.ibm.as400.access.ReplyRCExchangeAttributes; import jakarta.enterprise.context.ApplicationScoped; import jakarta.inject.Inject; +import jakarta.ws.rs.Consumes; import jakarta.ws.rs.GET; +import jakarta.ws.rs.POST; import jakarta.ws.rs.Path; +import jakarta.ws.rs.PathParam; import jakarta.ws.rs.Produces; import jakarta.ws.rs.core.MediaType; import jakarta.ws.rs.core.Response; import org.apache.camel.CamelContext; +import org.apache.camel.ConsumerTemplate; +import org.apache.camel.Exchange; +import org.apache.camel.ProducerTemplate; +import org.apache.camel.component.jt400.Jt400Endpoint; import org.jboss.logging.Logger; @Path("/jt400") @ApplicationScoped public class Jt400Resource { + public enum ReplyType { + DQReadNormal, ok, DQRequestAttributesNormal, DQCommonReply, RCExchangeAttributesReply, RCCallProgramReply + } + private static final Logger LOG = Logger.getLogger(Jt400Resource.class); private static final String COMPONENT_JT400 = "jt400"; + @Inject CamelContext context; - @Path("/load/component/jt400") + @Inject + ProducerTemplate producerTemplate; + + @Inject + ConsumerTemplate consumerTemplate; + + @Inject + MockAS400ImplRemote as400ImplRemote; + + @Path("/keyedDataQueue/read") @GET @Produces(MediaType.TEXT_PLAIN) - public Response loadComponentJt400() throws Exception { - /* This is an autogenerated test */ - if (context.getComponent(COMPONENT_JT400) != null) { + public Response keyedDataQueueRead() { + + Exchange ex = consumerTemplate.receive( + "jt400://username:password@system/qsys.lib/MSGOUTDQ.DTAQ?connectionPool=#mockPool&keyed=true&format=binary&searchKey=MYKEY&searchType=GE"); + + return Response.ok().entity(ex.getIn().getBody(String.class)).build(); + } + + @Path("/keyedDataQueue/write/{key}") + @POST + @Consumes(MediaType.TEXT_PLAIN) + @Produces(MediaType.TEXT_PLAIN) + public Response keyedDataQueueWrite(@PathParam("key") String key, String data) throws Exception { + + Object ex = producerTemplate.requestBodyAndHeader( + "jt400://username:password@system/qsys.lib/MSGINDQ.DTAQ?connectionPool=#mockPool&keyed=true", + data, + Jt400Endpoint.KEY, + key); + return Response.ok().entity(ex).build(); + } + + @Path("/messageQueue/read") + @GET + @Produces(MediaType.TEXT_PLAIN) + public Response messageQueueRead() throws InterruptedException { + Exchange ex = consumerTemplate.receive( + "jt400://username:password@system/qsys.lib/MSGOUTQ.MSGQ?connectionPool=#mockPool&readTimeout=100"); + if (ex.getIn().getBody() != null) { + //reurn ok,because something is returned (the message contains 1 char, which is not correctly converted) return Response.ok().build(); } - LOG.warnf("Could not load [%s] from the Camel context", COMPONENT_JT400); - return Response.status(500, COMPONENT_JT400 + " could not be loaded from the Camel context").build(); + + return Response.serverError().build(); + } + + @Path("/messageQueue/write/{key}") + @POST + @Consumes(MediaType.TEXT_PLAIN) + @Produces(MediaType.TEXT_PLAIN) + public Response messageQueueWrite(@PathParam("key") String key, String data) throws Exception { + + Object ex = producerTemplate.requestBodyAndHeader( + "jt400://username:password@system/qsys.lib/MSGINQ.MSGQ?connectionPool=#mockPool", + data, + Jt400Endpoint.KEY, + key); + return Response.ok().entity(ex).build(); } + + @Path("/programCall") + @POST + @Consumes(MediaType.TEXT_PLAIN) + @Produces(MediaType.APPLICATION_JSON) + public Response programCall() throws Exception { + + Object ex = producerTemplate.requestBody( + "jt400://GRUPO:ATWORK@server/QSYS.LIB/assets.LIB/compute.PGM?connectionPool=#mockPool&outputFieldsIdx=1&fieldsLength=10,10,512", + new String[] { "par1", "par2" }); + return Response.ok().entity(ex).build(); + } + + @Path("/put/mockResponse") + @POST + @Consumes(MediaType.APPLICATION_JSON) + public Response putMockResponse( + Map params) throws Exception { + DataStream dataStream = switch (ReplyType.valueOf((String) params.get("replyType"))) { + case DQReadNormal -> new ReplyDQReadNormal((Integer) params.get("hashCode"), + (String) params.get("senderInformation"), + (String) params.get("entry"), + (String) params.get("key")); + case ok -> new ReplyOk(); + case DQCommonReply -> new ReplyDQCommon( + (Integer) params.get("hashCode")); + case DQRequestAttributesNormal -> new ReplyDQRequestAttributesNormal( + (Integer) params.get("keyLength")); + case RCExchangeAttributesReply -> new ReplyRCExchangeAttributes(); + case RCCallProgramReply -> new ReplyRCCallProgram(); + }; + + MockedResponses.add(dataStream); + + return Response.ok().build(); + } + } diff --git a/integration-tests/jt400/src/main/java/org/apache/camel/quarkus/component/jt400/it/MockAS400ConnectionPool.java b/integration-tests/jt400/src/main/java/org/apache/camel/quarkus/component/jt400/it/MockAS400ConnectionPool.java new file mode 100644 index 0000000000..00cef3dc94 --- /dev/null +++ b/integration-tests/jt400/src/main/java/org/apache/camel/quarkus/component/jt400/it/MockAS400ConnectionPool.java @@ -0,0 +1,71 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You 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 org.apache.camel.quarkus.component.jt400.it; + +import java.util.Locale; + +import com.ibm.as400.access.AS400; +import com.ibm.as400.access.AS400ConnectionPool; +import com.ibm.as400.access.ConnectionPoolException; +import com.ibm.as400.access.MockAS400; + +/** + * Mock {@code AS400ConnectionPool} implementation, useful in unit testing JT400 endpoints. + */ +public class MockAS400ConnectionPool extends AS400ConnectionPool { + + private static final long serialVersionUID = -7473444280370756827L; + + private final MockAS400 mockAS400; + + public MockAS400ConnectionPool(MockAS400 mockAS400) { + this.mockAS400 = mockAS400; + setRunMaintenance(false); + setThreadUsed(false); + } + + @Deprecated + @Override + public AS400 getConnection(String systemName, String userID, int service) { + throw new UnsupportedOperationException(); + } + + @Override + public AS400 getConnection(String systemName, String userID, String password) { + return mockAS400; + } + + @Override + public AS400 getConnection(String systemName, String userID, String password, int service) throws ConnectionPoolException { + return getConnection(systemName, userID, password); + } + + @Override + public AS400 getConnection(String systemName, String userID, String password, int service, Locale locale) + throws ConnectionPoolException { + return getConnection(systemName, userID, password, locale); + } + + @Override + public AS400 getConnection(String systemName, String userID, String password, Locale locale) + throws ConnectionPoolException { + AS400 connection = getConnection(systemName, userID, password); + connection.setLocale(locale); + return connection; + } + +} diff --git a/integration-tests/jt400/src/main/resources/application.properties b/integration-tests/jt400/src/main/resources/application.properties new file mode 100644 index 0000000000..b1e3fa4668 --- /dev/null +++ b/integration-tests/jt400/src/main/resources/application.properties @@ -0,0 +1,17 @@ +## --------------------------------------------------------------------------- +## Licensed to the Apache Software Foundation (ASF) under one or more +## contributor license agreements. See the NOTICE file distributed with +## this work for additional information regarding copyright ownership. +## The ASF licenses this file to You 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. +## --------------------------------------------------------------------------- +quarkus.test.flat-class-path = ${quarkus.test.flat-class-path} \ No newline at end of file diff --git a/integration-tests/jt400/src/test/java/org/apache/camel/quarkus/component/jt400/it/Jt400IT.java b/integration-tests/jt400/src/test/java/org/apache/camel/quarkus/component/jt400/it/Jt400MockIT.java similarity index 84% rename from integration-tests/jt400/src/test/java/org/apache/camel/quarkus/component/jt400/it/Jt400IT.java rename to integration-tests/jt400/src/test/java/org/apache/camel/quarkus/component/jt400/it/Jt400MockIT.java index 11e65bf29a..7bd64e0e2d 100644 --- a/integration-tests/jt400/src/test/java/org/apache/camel/quarkus/component/jt400/it/Jt400IT.java +++ b/integration-tests/jt400/src/test/java/org/apache/camel/quarkus/component/jt400/it/Jt400MockIT.java @@ -17,8 +17,10 @@ package org.apache.camel.quarkus.component.jt400.it; import io.quarkus.test.junit.QuarkusIntegrationTest; +import org.junit.jupiter.api.condition.DisabledIfSystemProperty; @QuarkusIntegrationTest -class Jt400IT extends Jt400Test { +@DisabledIfSystemProperty(named = "skip-mock-tests", matches = "true") +class Jt400MockIT extends Jt400MockTest { } diff --git a/integration-tests/jt400/src/test/java/org/apache/camel/quarkus/component/jt400/it/Jt400MockTest.java b/integration-tests/jt400/src/test/java/org/apache/camel/quarkus/component/jt400/it/Jt400MockTest.java new file mode 100644 index 0000000000..dcb4615b38 --- /dev/null +++ b/integration-tests/jt400/src/test/java/org/apache/camel/quarkus/component/jt400/it/Jt400MockTest.java @@ -0,0 +1,142 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You 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 org.apache.camel.quarkus.component.jt400.it; + +import java.util.HashMap; +import java.util.Map; + +import io.quarkus.test.junit.QuarkusTest; +import io.restassured.RestAssured; +import io.restassured.http.ContentType; +import org.apache.camel.util.CollectionHelper; +import org.hamcrest.Matchers; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.condition.DisabledIfSystemProperty; + +@QuarkusTest +@DisabledIfSystemProperty(named = "skip-mock-tests", matches = "true") + +public class Jt400MockTest { + + @Test + public void testReadKeyedDataQueue() { + prepareMockReply(Jt400Resource.ReplyType.ok); + prepareMockReply(Jt400Resource.ReplyType.DQRequestAttributesNormal, CollectionHelper.mapOf("keyLength", 5)); + prepareMockReply(Jt400Resource.ReplyType.ok); + prepareMockReply(Jt400Resource.ReplyType.DQReadNormal, 0x8003, "mocked jt400", "Hello from mocked jt400!", "MYKEY"); + + RestAssured.get("/jt400/keyedDataQueue/read") + .then() + .statusCode(200) + .body(Matchers.equalTo("Hello from mocked jt400!")); + } + + @Test + public void testWriteKeyedDataQueue() { + prepareMockReply(Jt400Resource.ReplyType.ok); + prepareMockReply(Jt400Resource.ReplyType.DQRequestAttributesNormal, CollectionHelper.mapOf("keyLength", 7)); + prepareMockReply(Jt400Resource.ReplyType.ok); + prepareMockReply(Jt400Resource.ReplyType.DQCommonReply, CollectionHelper.mapOf("hashCode", 0x8002)); + + RestAssured.given() + .body("Written in mocked jt400!") + .post("/jt400/keyedDataQueue/write/testKey") + .then() + .statusCode(200) + .body(Matchers.equalTo("Written in mocked jt400!")); + } + + @Test + public void testReadMessageQueue() { + prepareMockReply(Jt400Resource.ReplyType.RCExchangeAttributesReply); + prepareMockReply(Jt400Resource.ReplyType.RCExchangeAttributesReply); + prepareMockReply(Jt400Resource.ReplyType.RCCallProgramReply); + + RestAssured.get("/jt400/messageQueue/read") + .then() + .statusCode(200); + } + + @Test + public void testWriteMessageQueue() { + prepareMockReply(Jt400Resource.ReplyType.RCExchangeAttributesReply); + prepareMockReply(Jt400Resource.ReplyType.RCExchangeAttributesReply); + prepareMockReply(Jt400Resource.ReplyType.RCCallProgramReply); + + RestAssured.given() + .body("Written in mocked jt400!") + .post("/jt400/messageQueue/write/testKey") + .then() + .statusCode(200) + .body(Matchers.equalTo("Written in mocked jt400!")); + } + + @Test + public void testProgramCall() { + prepareMockReply(Jt400Resource.ReplyType.RCExchangeAttributesReply); + prepareMockReply(Jt400Resource.ReplyType.RCExchangeAttributesReply); + prepareMockReply(Jt400Resource.ReplyType.RCCallProgramReply); + + RestAssured.given() + .body("Written in mocked jt400!") + .post("/jt400/programCall") + .then() + .statusCode(200) + .body(Matchers.both(Matchers.not(Matchers.containsString("par1"))).and( + Matchers.containsString("par2"))); + } + + private void prepareMockReply(Jt400Resource.ReplyType replyType, + Integer hashCode, + String senderInformation, + String entry, + String key) { + //prepare mock data + RestAssured.given() + .contentType(ContentType.JSON) + .body(CollectionHelper.mapOf("replyType", replyType.name(), + "hashCode", hashCode, + "senderInformation", senderInformation, + "entry", entry, + "key", key)) + .post("/jt400/put/mockResponse") + .then() + .statusCode(200); + } + + private void prepareMockReply(Jt400Resource.ReplyType replyType) { + //prepare mock data + RestAssured.given() + .body(CollectionHelper.mapOf("replyType", replyType.name())) + .contentType(ContentType.JSON) + .post("/jt400/put/mockResponse") + .then() + .statusCode(200); + } + + private void prepareMockReply(Jt400Resource.ReplyType replyType, Map<String, Object> data) { + Map<String, Object> request = new HashMap<>(data); + request.put("replyType", replyType.name()); + //prepare mock data + RestAssured.given() + .body(request) + .contentType(ContentType.JSON) + .post("/jt400/put/mockResponse") + .then() + .statusCode(200); + } +}