Project

General

Profile

Feature #9285

Allow remote access to Event Semaphores and Mutexes

Added by Tomasz Domin over 1 year ago. Updated over 1 year ago.

Status:
Closed
Priority:
Normal
Assignee:
Start date:
Due date:
% Done:

100%

billable:
No
vendor_id:
GCD
case_num:
version_reported:
version_resolved:
reviewer:
production:
No
env_name:
topics:

Related issues

Related to Testing - Support #9270: design and implement an approach for executing multi-session 4GL testcases Closed

History

#1 Updated by Tomasz Domin over 1 year ago

The goal of the task is to expose API to allow external tools to access Harness Mutexes and Semaphores in order to synchronize and communicate in parallel tests scenarios.

#2 Updated by Tomasz Domin over 1 year ago

The initial idea is to expose a TCP socket and allow external apps to lock/unlock resources with a simple protocol initially defined in #9270

Harness would expose a TCP socket on a predefined port after providing a dedicated command line option to allow clients to connect.
Each connected client would start a new Driver thread that would become a new actor in test scenario, thus interact/synchronize with a test plan.

The protocol would be text based and optimized for ABL sockets.
Communication would be split into messages, both up- and downstream in following format:
  • six characters constituting a header, in the first version of protocol that would six ascii digits providing a number of bytes of an actual message
  • actual message as ascii string.
Additional rules would apply:
  • Client would connect to the socket and would send a request, and getting response back with possible blocking waiting for resources.
  • Every command from client is a request with two possible responses OK or ERROR from Harness server
  • Commands may have parameters, parameters are separated from command name and each other by vertical bar ( | ) sign - ASCII code 124.
  • Semaphores are identified by name as defined in Harness Testcase
  • Executing command may block client test execution e.g. resource is allocated and needs to be released
  • Disconnection from server should be treated as an unconditional error

Examples:

000002OK
000005ERROR
000021ERRORWith description
000011POSTEStest1

Note there is no newline between messages, so message stream would like following (upstream and downstream):

000018POSTES|test1|false000016WAITES|sem1|1800000016WAITES|sem2|1800
000002OK|000002OK|000025ERROR|Timeout waiting for semaphore

The protocol allows controlling Harness Mutexes and Semaphores with following commands - please see Harness Documentation for more information about functionality of related test
  • POSTES|<name>|<reset> - Post event semaphore, <reset> can be true/false
  • RESETES|<name> - Reset Event Semaphore
  • WAITES|<name>|<timeout> - Wait Event Semaphore identified by name up to <timeout> seconds - this may block
  • ACQUIREMTX|<name> - Acquire mutex identified by name - this may block indefinitely
  • RELEASEMTX|<name> - Release mutex identified by name

#3 Updated by Tomasz Domin over 1 year ago

  • Related to Support #9270: design and implement an approach for executing multi-session 4GL testcases added

#4 Updated by Tomasz Domin over 1 year ago

In order to allow a proper binding of a remote test to Harness reporting I need to add two more messages:
  • TESTSET|<name> - set Harness TestSet name
  • TEST|<name> - set Harness Test name

#5 Updated by Tomasz Domin over 1 year ago

  • % Done changed from 0 to 80

Tomasz Domin wrote:

In order to allow a proper binding of a remote test to Harness reporting I need to add two more messages:
  • TESTSET|<name> - set Harness TestSet name
  • TEST|<name> - set Harness Test name

Actually TESTSET is not needed anymore, as Remote Server is bound to a TestSet by definition.

Implemented and testing.
A sample session emulated with netcat:


(for a in "000021TEST|cross_session_03" "000024ACQUIREMTX|xsessionmutex" "000024RELEASEMTX|xsessionmutex" ; do echo -n $a; sleep 1; done;) | netcat -N localhost 8889
000002OK000002OK000002OK

#6 Updated by Tomasz Domin over 1 year ago

In order to activate Remote Access a following target needs to be specified in Harness TestPlan or in TestSet:

   <target type="remote" port="8889" threads="4" />

That starts a Remote Access Server that waits on port 8889 for external commands and allows for up to 4 clients connections.
Note that in case of TestSets running in parallel each TestSet needs a different Remote Access port.

#7 Updated by Tomasz Domin over 1 year ago

  • Assignee set to Tomasz Domin
  • Status changed from New to WIP

#8 Updated by Tomasz Domin over 1 year ago

Marian - what is a progress of ABL part ?

#9 Updated by Marian Edu over 1 year ago

Tomasz Domin wrote:

Marian - what is a progress of ABL part ?

We're testing that locally with a 'echo' server implementation right now, I will push that in testcases tomorrow morning first thing.

#10 Updated by Marian Edu over 1 year ago

Marian Edu wrote:

Tomasz Domin wrote:

Marian - what is a progress of ABL part ?

We're testing that locally with a 'echo' server implementation right now, I will push that in testcases tomorrow morning first thing.

I've pushed the Harness API 4GL code on testcases. Only thing that is probably going to be used in test cases is support.harness.HarnessApi, apart the Connect method (port, [host = localhost]) there are only SendMessage methods that are merely overloads for sending a 'harness message' with optional timeout - default to no time-out. The method return is void - either completes with no error (OK response) or it will throw - when harness response is ERROR or time-out specified and passed.

Otherwise we have a mockup server and client UI implemented in 4GL in support/harness/test that we've used to test the whole thing, hope I've got the specs correctly but please let me know if there is anything wrong with it.

#11 Updated by Tomasz Domin over 1 year ago

Marian Edu wrote:

We're testing that locally with a 'echo' server implementation right now, I will push that in testcases tomorrow morning first thing.

Otherwise we have a mockup server and client UI implemented in 4GL in support/harness/test that we've used to test the whole thing, hope I've got the specs correctly but please let me know if there is anything wrong with it.

Marian - what is support.harness.protocol.* referred in client ?
I tried to build client with FWD to connect it with Harness and I failed Caused by: java.lang.ClassNotFoundException: Can not find class for accessing Connect [OO_METH_VOID] @243:24 (107374183429)

#12 Updated by Marian Edu over 1 year ago

Tomasz Domin wrote:

Marian - what is support.harness.protocol.* referred in client ?

That seems to have been a left over from previous refactor, the APPBuilder kinda hidden it under analyse-suspend preprocessor directives :(

Removed those from test client/server and added the convert file list.

I tried to build client with FWD to connect it with Harness and I failed Caused by: java.lang.ClassNotFoundException: Can not find class for accessing Connect [OO_METH_VOID] @243:24 (107374183429)

That doesn't seem to be related to the bad 'using' statements mentioned before although it just might, don't know how conversion handle bad wildcard 'using' statements although those were not really used.

#13 Updated by Tomasz Domin over 1 year ago

Marian Edu wrote:

Tomasz Domin wrote:

Removed those from test client/server and added the convert file list.

I tried to build client with FWD to connect it with Harness and I failed Caused by: java.lang.ClassNotFoundException: Can not find class for accessing Connect [OO_METH_VOID] @243:24 (107374183429)

That doesn't seem to be related to the bad 'using' statements mentioned before although it just might, don't know how conversion handle bad wildcard 'using' statements although those were not really used.

Marian, are you able to build harnessClient.w with FWD ? I am still getting the error as above.

#14 Updated by Tomasz Domin over 1 year ago

Tomasz Domin wrote:

Marian, are you able to build harnessClient.w with FWD ? I am still getting the error as above.

I had to modify code in a following way (and I am still getting the third error):

=== modified file 'support/harness/HarnessApi.cls'
--- old/support/harness/HarnessApi.cls    2024-12-31 12:54:35 +0000
+++ new/support/harness/HarnessApi.cls    2025-01-08 20:38:06 +0000
@@ -23,10 +23,10 @@
     define public event OnDisconnect void ().

     method public void Connect(harnessPort as integer):
-        this-object:Connect(harnessPort, ?).
+        this-object:Connect2(harnessPort, ?).
     end method.

-    method public void Connect(harnessPort as integer, harnessHost as character):
+    method public void Connect2(harnessPort as integer, harnessHost as character):
         harnessConn = new HarnessConnection().   
         harnessConn:OnDisconnect:Subscribe(onConnectionDisconnect).
         harnessConn:Connect(harnessPort, harnessHost). 

=== modified file 'support/harness/test/harnessClient.w'
--- old/support/harness/test/harnessClient.w    2025-01-06 17:57:11 +0000
+++ new/support/harness/test/harnessClient.w    2025-01-08 20:40:34 +0000
@@ -239,6 +239,7 @@

 on choose of connectButton 
     do:
+        define variable harnessPort as integer no-undo.
         if valid-object(harnessApi) and harnessApi:Connected then 
         do:
             run disconnect.
@@ -250,8 +251,10 @@
                 harnessApi = new HarnessApi().
                 harnessApi:OnDisconnect:Subscribe('onDisconnect').
             end.
-                
-            harnessApi:Connect(portFillIn:input-value) no-error.
+            
+            harnessPort = portFillIn:input-value.    
+            
+            harnessApi:Connect(harnessPort) no-error.

             if harnessApi:Connected then 
             do:

There is conversion problem for code referring to OO class methods in trunk/15631, not sure if that is a regression. Not sure if I am describing that correctly but there are at least three issues:
  1. There is a problem with overloaded class methods - when looking for exact match the first one is selected - in this case Connect(harnessPort as integer, harnessHost as character):, so I had to rename overloaded method.
  2. when looking for class method for expression harnessApi:Connect(portFillIn:input-value) it looks for connect(Widget) instead of connect(integer)
  3. when conversion succeeds it seems modes are missing in converted code for one of constructors: error: no suitable method found for newInstance(Class<HarnessMessage>,object<HarnessCommand>,character)
    [javac] harnessMsg.assign(ObjectOps.newInstance(HarnessMessage.class, HarnessCommand.getEnum(defaultFrameFrame.widgetCommandComboBox().getScreenValue()), (character)defaultFrameFrame.widgetResourceNameFillIn().inputValue()));

#15 Updated by Marian Edu over 1 year ago

There are definitively issues in conversion, nevertheless I've changed the 4GL code to help the converter pickup the right method (widget input-value data type doesn't seem to be inferred from the data type). Committed rev #1685 that seems to convert right and the converted code has no errors, can't tell if it's correct or not nor if it's actually working but the conversion errors are gone.

#16 Updated by Tomasz Domin over 1 year ago

Marian Edu wrote:

There are definitively issues in conversion, nevertheless I've changed the 4GL code to help the converter pickup the right method (widget input-value data type doesn't seem to be inferred from the data type). Committed rev #1685 that seems to convert right and the converted code has no errors, can't tell if it's correct or not nor if it's actually working but the conversion errors are gone.

Marian, I've pushed updated sources to xfer repository: Committed revision 1689.
Note I've updated build_ablunit.xml to allow two sessions of ant pct running in parallel - for that to happen I had to allow redefinition of a temporary directory.

#17 Updated by Tomasz Domin over 1 year ago

  • % Done changed from 80 to 100

I've pushed changes to java code to task branch harness/9270a to be reviewed together with #9270 changes.

The final list of supported commands:

POSTES|<name>|<reset> - Post event semaphore, <reset> can be true/false
RESETES|<name> - Reset Event Semaphore
WAITES|<name>|<timeout> - Wait Event Semaphore identified by name up to <timeout> seconds - this may block
ACQUIREMTX|<name> - Acquire mutex identified by name - this may block indefinitely
RELEASEMTX|<name> - Release mutex identified by name
TEST|<name> - set Harness Test name

#18 Updated by Tomasz Domin over 1 year ago

I've added Harness ABL remote API to harness project and refactored it in the way, that harness if needed should be checked out into testcases as testcases/support/harness.

#19 Updated by Marian Edu over 1 year ago

Tomasz Domin wrote:

I've added Harness ABL remote API to harness project and refactored it in the way, that harness if needed should be checked out into testcases as testcases/support/harness.

Hi Tomasz, I'm not sure if testcases is the right place to have that 4GL code but alas is the only repository we have access to and beside we are going to need it in testcases :)

I did updated the project to pick-up your changes, I see there are two additional message types added and you like to have specific methods for each action - on top of the more generic SendMessage, no problem with that. In the message body I see you've added | as separator between command and body data, no problem with that either only I think the constructor that takes raw data as input should be updated to take that into account, update the substring to skip the | separator - use 2 instead of 1 on the substring call on line #48 of HarnessMessage.

#20 Updated by Tomasz Domin over 1 year ago

Marian Edu wrote:

Tomasz Domin wrote:

I've added Harness ABL remote API to harness project and refactored it in the way, that harness if needed should be checked out into testcases as testcases/support/harness.

Hi Tomasz, I'm not sure if testcases is the right place to have that 4GL code but alas is the only repository we have access to and beside we are going to need it in testcases :)

Thank you Marian
My idea is to move 4GL Harness ABL API code to harness project and then include harness project optionally in testcases project (via link or checkout) with a directory structure like this:

-testcases
--support
---harness
----abl <- here to put 4GL Harness ABL API, classes would be in @support.harness.abl@ package
----example <- here to put 4GL Harness ABL based example tests

Note I didnt want to change PROPATH of testcases project.
What do you think ?

I have a question where to put tests that require harness inside testcases project, as I think there are too much folders in root of testcases project. There is already a folder called flushing_and_triggers.

#21 Updated by Tomasz Domin over 1 year ago

  • Status changed from WIP to Review

#22 Updated by Tomasz Domin over 1 year ago

  • Status changed from Review to Test

The feature has been reviewed and accepted in task #9270
I've added description of the Harness Remote Protocol and feature usage into Documentation revision 26

#23 Updated by Greg Shah over 1 year ago

  • Status changed from Test to Closed

I've reviewed the docs and made some minor edits.

Also available in: Atom PDF