Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[3.8.x] JT400 tests can not be run in parallel #6018 #6022

Merged
merged 1 commit into from
Apr 23, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
47 changes: 25 additions & 22 deletions integration-tests/jt400/README.adoc
Original file line number Diff line number Diff line change
Expand Up @@ -88,6 +88,31 @@ CRTDTAQ DTAQ(LIBRARY/TESTKEYED) SEQ(*KEYED) KEYLEN(20) MAXLEN(100)
CRTDTAQ DTAQ(LIBRARY/TESTLIFO) SEQ(*LIFO) MAXLEN(100)
```

==== Synchronization for parallel executions

The tests do not work by default for parallel executions.
For parallel scenario, the locking file has to be provided.

You can create such file by running

```
QSH CMD('touch #file_lock_path')
for example QSH CMD('touch /home/#username/cq_jt400_lock')
```

How to provide a locking file:

```
export JT400_LOCK_FILE=#file_lock_path
```

or for Windows:

```
$Env:JT400_LOCK_FILE="#file_lock_path"
```
*If locking file is not provided, tests may fail their executions in parallel mode*

==== Using different object names

If your test object names are different from the default ones, you can override default values via environmental variable
Expand All @@ -109,27 +134,5 @@ $Env:JT400_LIFO_QUEUE="#lifoqueue_if_not_TESTLIFO.DTAQe"
$Env:JT400_KEYED_QUEUE="#lkeyedqueue_if_not_TESTKEYED.DTAQ"
$Env:JT400_MESSAGE_QUEUE="#messagequeue_if_not_TESTMSGQ.MSGQ"
$Env:JT400_MESSAGE_REPLYTO_QUEUE="#messagequeueinquiry_if_not_REPLYMSGQ.MSGQ"
$Env:JT400_USER_SPACE="#userspace_if_not_PROGCALL"
```

=== Clear queues after unexpected failures

If tests finishes without unexpected failure, tests are taking care of clearing the data.
In some cases data might stay written into the real server if test fails unexpectedly.
This state should might alter following executions.

To force full clear (of each queue) can be achieved by add ing parameter
```
-Dcq.jt400.clear-all=true
```
Be aware that with `-Dcq.jt400.clear-all=true`, the tests can not successfully finish in parallel run.

Usage of clear queues parameter is *strongly* suggested during development


==== Parallel runs and locking

Simple locking mechanism is implemented for the test to allow parallel executions.

Whenever test is started, new entry is written into keyed data queue `JT400_KEYED_QUEUE` with the key `cq.jt400.global-lock` and entry is removed after the run.
Tests are able to clear this lock even if previous execution fails unexpectedly.
Original file line number Diff line number Diff line change
Expand Up @@ -14,12 +14,6 @@
## See the License for the specific language governing permissions and
## limitations under the License.
## ---------------------------------------------------------------------------
#quarkus.test.flat-class-path = ${quarkus.test.flat-class-path}

# workaround for mocked tests, should be solvable by excluding mocked java files from compilation of skip-mock-tests profile
# I can not make it work though, but to not block the native support by this, I'm setting flat path to true for all tests
quarkus.test.flat-class-path = true

#jt400 server connection information
cq.jt400.url=${JT400_URL:system}
cq.jt400.username=${JT400_USERNAME:username}
Expand All @@ -31,4 +25,6 @@ cq.jt400.user-space=${JT400_USER_SPACE:PROGCALL}
cq.jt400.message-queue=${JT400_MESSAGE_QUEUE:TESTMSGQ.MSGQ}
cq.jt400.message-replyto-queue=${JT400_MESSAGE_REPLYTO_QUEUE:REPLYMSGQ.MSGQ}
cq.jt400.keyed-queue=${JT400_KEYED_QUEUE:TESTKEYED.DTAQ}
cq.jt400.lifo-queue=${JT400_LIFO_QUEUE:TESTLIFO.DTAQ}
cq.jt400.lifo-queue=${JT400_LIFO_QUEUE:TESTLIFO.DTAQ}

cq.jt400.lock-file=${JT400_LOCK_FILE}
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,6 @@
import org.awaitility.Awaitility;
import org.hamcrest.Matchers;
import org.jboss.logging.Logger;
import org.junit.jupiter.api.AfterAll;
import org.junit.jupiter.api.BeforeAll;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.condition.EnabledIfEnvironmentVariable;
Expand All @@ -41,33 +40,42 @@ public class Jt400Test {

private final int MSG_LENGTH = 20;
//tests may be executed in parallel, therefore the timeout is a little bigger in case the test has to wait for another one
private final int WAIT_IN_SECONDS = 20;
private static final int WAIT_IN_SECONDS = 30;

@BeforeAll
public static void beforeAll() throws Exception {
//lock execution
getClientHelper().lock();

//for development purposes
// logQueues();

//lock execution
Jt400TestResource.CLIENT_HELPER.lock();
}

@AfterAll
public static void afterAll() throws Exception {
getClientHelper().unlock();
//clear al data in advance to be sure that there is no data in the queues
//it is not possible to clear data after the run because of CPF2451 Message queue REPLYMSGQ is allocated to another job
//wait is required also because of CPF2451, usually takes ~20 seconds to release connections to a reply queue
Awaitility.await().pollInterval(1, TimeUnit.SECONDS).atMost(WAIT_IN_SECONDS, TimeUnit.SECONDS).until(
() -> {
try {
return getClientHelper().clear();
} catch (Exception e) {
LOGGER.debug("Clear failed because of: " + e.getMessage());
return false;
}
},
Matchers.is(true));
}

private static void logQueues() throws Exception {
StringBuilder sb = new StringBuilder("\n");
sb.append("**********************************************************");
sb.append("************************************************************");
sb.append(getClientHelper().dumpQueues());
sb.append("\n**********************************************************\n");
LOGGER.info(sb.toString());
}

@Test
public void testDataQueue() {
LOGGER.debug("** testDataQueue() ** has started ");
LOGGER.debug("**** testDataQueue() ** has started ");

String msg = RandomStringUtils.randomAlphanumeric(MSG_LENGTH).toLowerCase(Locale.ROOT);
String answer = "Hello From DQ: " + msg;
Expand All @@ -91,7 +99,7 @@ public void testDataQueue() {

@Test
public void testDataQueueBinary() throws Exception {
LOGGER.debug("** testDataQueueBinary() ** has started ");
LOGGER.debug("**** testDataQueueBinary() ** has started ");
String msg = RandomStringUtils.randomAlphanumeric(MSG_LENGTH).toLowerCase(Locale.ROOT);
String answer = "Hello (bin) " + msg;

Expand All @@ -118,7 +126,7 @@ public void testDataQueueBinary() throws Exception {

@Test
public void testKeyedDataQueue() {
LOGGER.debug("** testKeyedDataQueue() ** has started ");
LOGGER.debug("**** testKeyedDataQueue() ** has started ");
String msg1 = RandomStringUtils.randomAlphanumeric(MSG_LENGTH).toLowerCase(Locale.ROOT);
String msg2 = RandomStringUtils.randomAlphanumeric(MSG_LENGTH).toLowerCase(Locale.ROOT);
String answer1 = "Hello From KDQ: " + msg1;
Expand Down Expand Up @@ -170,7 +178,7 @@ public void testKeyedDataQueue() {

@Test
public void testMessageQueue() throws Exception {
LOGGER.debug("** testMessageQueue() ** has started ");
LOGGER.debug("**** testMessageQueue() ** has started ");
//write
String msg = RandomStringUtils.randomAlphanumeric(MSG_LENGTH).toLowerCase(Locale.ROOT);
String answer = "Hello from MQ: " + msg;
Expand Down Expand Up @@ -205,19 +213,20 @@ public void testMessageQueue() throws Exception {

@Test
public void testInquiryMessageQueue() throws Exception {
LOGGER.debug("** testInquiryMessageQueue() **: has started ");
LOGGER.debug("**** testInquiryMessageQueue() **: has started ");

String msg = RandomStringUtils.randomAlphanumeric(10).toLowerCase(Locale.ROOT);
String replyMsg = "reply to: " + msg;

LOGGER.debug("testInquiryMessageQueue: writing " + msg);
getClientHelper().registerForRemoval(Jt400TestResource.RESOURCE_TYPE.replyToQueueu, msg);
getClientHelper().registerForRemoval(Jt400TestResource.RESOURCE_TYPE.replyToQueueu, replyMsg);

//sending a message using the same client as component
getClientHelper().sendInquiry(msg);

LOGGER.debug("testInquiryMessageQueue: message " + msg + " written via client");
//register deletion of the message in case some following task fails
QueuedMessage queuedMessage = getClientHelper().peekReplyToQueueMessage(msg);
if (queuedMessage != null) {
getClientHelper().registerForRemoval(Jt400TestResource.RESOURCE_TYPE.replyToQueueu, queuedMessage.getKey());
LOGGER.debug("testInquiryMessageQueue: message confirmed by peek: " + msg);
}

Expand All @@ -227,6 +236,7 @@ public void testInquiryMessageQueue() throws Exception {
.post("/jt400/inquiryMessageSetExpected")
.then()
.statusCode(204);

//start route before sending message (and wait for start)
Awaitility.await().atMost(WAIT_IN_SECONDS, TimeUnit.SECONDS).until(
() -> RestAssured.get("/jt400/route/start/inquiryRoute")
Expand All @@ -237,7 +247,7 @@ public void testInquiryMessageQueue() throws Exception {
LOGGER.debug("testInquiryMessageQueue: inquiry route started");

//await to be processed
Awaitility.await().pollInterval(1, TimeUnit.SECONDS).atMost(20, TimeUnit.SECONDS).until(
Awaitility.await().pollInterval(1, TimeUnit.SECONDS).atMost(WAIT_IN_SECONDS, TimeUnit.SECONDS).until(
() -> RestAssured.get("/jt400/inquiryMessageProcessed")
.then()
.statusCode(200)
Expand Down
Loading
Loading