Skip to content
This repository has been archived by the owner on Nov 4, 2024. It is now read-only.

Commit

Permalink
Merge pull request #953 from galasa-dev/mcobbett-gherkin-3270-termina…
Browse files Browse the repository at this point in the history
…ls-scenario-outline

3270 terminals disconnect and re-connect between scenarios
  • Loading branch information
techcobweb authored Jul 10, 2024
2 parents 58d433a + 5af8326 commit cddd9e6
Show file tree
Hide file tree
Showing 15 changed files with 129 additions and 34 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -17,15 +17,19 @@ NOTE, the spacing and capitalisation must be exact at this time. We will try to

There are 4 flavours to the "given a terminal". you can specify an ID for a terminal so that a feature file can operate multiple terminals in the same feature file. You can also specify a zOS image tag to influence which image the terminal connects to.

The default ID is A and the default tag is PRIMARY.
The default ID is `A` and the default tag is `PRIMARY`.

In all the following statements, where you see `terminal` you can leave as default ID of A or code `terminal B` to point to a different terminal.
In all the following statements, where you see `terminal` you can leave as default ID of `A` or code `terminal B` to point to a different terminal.

### Move Cursor

`AND move terminal cursor to field "xxxxxx"`

Where xxxxxx is the text in an protected or unprotected field on the screen.
Where `xxxxxx` is the text in an protected or unprotected field on the screen.

`AND move terminal A cursor to field "xxxxxx"`

As above, but for the terminal with an id of `A`

### Terminal keys

Expand All @@ -35,26 +39,39 @@ Where xxxxxx is the text in an protected or unprotected field on the screen.

`AND press terminal key ENTER`

`AND press terminal key PFxx` where xx is the PF number
`AND press terminal key PFxx` where `xx` is the PF number

`AND press terminal A key ENTER` where `A` is the id of the terminal to use.

### Type something

`AND type "xxxxxx" on terminal` where xxxxx is what you want to type where the cursor is
`AND type "xxxxxx" on terminal` where `xxxxx` is what you want to type where the cursor is

`AND type "xxxxxx" on terminal A` where `A` is the id of the terminal to use.

`AND type "xxxxxx" on terminal in field labelled "yyyyyy"` where `xxxxxx` is the what you want to type, `yyyyyy` is the field label. WARNING, this will move the cursor. It will locate ANY text `yyyyyy` and then press TAB and then type.

`AND type "xxxxxx" on terminal in field labelled "yyyyyy"` where xxxxxx is the what you want to type, yyyyyy is the field label. WARNING, this will move the cursor. It will locate ANY text yyyyyy and then press TAB and then type.
`AND type "xxxxxx" on terminal A in field labelled "yyyyyy"` where `A` is the id of the terminal to use.

### Wait for the keyboard to unlock

`AND wait for terminal keyboard`

`AND wait for terminal A keyboard`

### Wait for text on the screen

`THEN wait for "xxxxxx" in any terminal field`

This will wait for the text to appear on the screen on any screen update. WARNING, the keyboard may not be unlocked when this statement finishes.

`THEN wait for "xxxxxx" in any terminal A field` where `A` is the id of the terminal to use.

### Check single text on screen

`THEN check "xxxxxx" appears only once on terminal`

This will search the screen for text xxxxxx and ensure it occurs once. This is immediate, will not wait for updates.
This will search the screen for text `xxxxxx` and ensure it occurs once. This is immediate, will not wait for updates.

`THEN check "xxxxxx" appears only once on terminal A` where `A` is the id of the terminal to use.

Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ plugins {

description = 'Galasa zOS 3270 Terminal Manager'

version = '0.34.0'
version = '0.36.0'

dependencies {
api project(':galasa-managers-zos-parent:dev.galasa.zos3270.common')
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,8 @@
import dev.galasa.framework.spi.IGherkinManager;
import dev.galasa.framework.spi.IManager;
import dev.galasa.framework.spi.ResourceUnavailableException;
import dev.galasa.framework.spi.Result;
import dev.galasa.framework.spi.language.GalasaMethod;
import dev.galasa.framework.spi.language.GalasaTest;
import dev.galasa.ipnetwork.IIpHost;
import dev.galasa.textscan.spi.ITextScannerManagerSpi;
Expand Down Expand Up @@ -97,7 +99,30 @@ public void initialise(@NotNull IFramework framework, @NotNull List<IManager> al
}

}


@Override
public Result endOfTestMethod(@NotNull GalasaMethod galasaMethod, @NotNull Result currentResult, Throwable currentException)
throws ManagerException {

super.endOfTestMethod(galasaMethod, currentResult, currentException);

if (galasaMethod.isGherkin()) {
// The end of a test method in gherkin equates to the end of the scenario.
// So we need to free up terminals so their state doesn't leech into the next scenario.
// A scenario equates to a java method.
disconnectAllTerminals();
}

return currentResult;
}

private void disconnectAllTerminals() throws Zos3270ManagerException {
for( Zos3270TerminalImpl terminal: terminals) {
if (terminal.isConnected()) {
disconnectTerminal(terminal);
}
}
}

@Override
public List<String> extraBundles(@NotNull IFramework framework) throws ManagerException {
Expand Down Expand Up @@ -207,14 +232,20 @@ public void provisionStart() throws ManagerException, ResourceUnavailableExcepti
public void provisionStop() {
logger.trace("Disconnecting terminals");
for (Zos3270TerminalImpl terminal : terminals) {
try {
terminal.writeRasOutput();
terminal.flushTerminalCache();
terminal.disconnect();
} catch (TerminalInterruptedException e) {
logger.warn("Thread interrupted whilst disconnecting terminals", e);
Thread.currentThread().interrupt();
}
disconnectTerminal(terminal);
}
}

private void disconnectTerminal(Zos3270TerminalImpl terminal) {
String terminalId = terminal.getId();
logger.info("Disconnecting terminal "+terminalId);
try {
terminal.writeRasOutput();
terminal.flushTerminalCache();
terminal.disconnect();
} catch (TerminalInterruptedException e) {
logger.warn("Thread interrupted whilst disconnecting terminals", e);
Thread.currentThread().interrupt();
}
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,9 @@ public void allocateTerminal(IGherkinExecutable executable, Map<String,Object> t
}

Zos3270TerminalImpl terminal = this.gerkinCoordinator.getTerminal(terminalId);
if (terminal == null ) {
throw new Zos3270ManagerException("Unable to get terminal "+terminalId);
}
if (!terminal.isConnected()) {
throw new Zos3270ManagerException("Terminal '" + terminalId + "' is not connected");
}
Expand Down
Original file line number Diff line number Diff line change
@@ -1,39 +1,44 @@
package dev.galasa.zos3270.internal.gherkin;

import java.util.HashMap;
import java.util.*;

import dev.galasa.ManagerException;
import dev.galasa.framework.spi.AbstractManager;
import dev.galasa.framework.spi.IGherkinExecutable;
import dev.galasa.framework.spi.IStatementOwner;
import dev.galasa.framework.spi.language.gherkin.GherkinMethod;
import dev.galasa.framework.spi.language.gherkin.GherkinTest;
import dev.galasa.zos3270.Zos3270ManagerException;
import dev.galasa.zos3270.internal.Zos3270ManagerImpl;
import dev.galasa.zos3270.spi.Zos3270TerminalImpl;

public class Gherkin3270Coordinator {

// The manager that this Coordinator is a facade of.
private final Zos3270ManagerImpl manager;

private final GherkinTest test;

// The gherkin test is essentially a feature.
private final GherkinTest feature;

// This coordinator keeps a reference of the terminals using the id that the gherkin scenario uses,
// which is different to the underlying terminal id.
// This is a mapping of the gherkin terminal id key to the terminal itself.
private final HashMap<String, Zos3270TerminalImpl> terminals = new HashMap<>();
private final HashMap<String, String> terminalImageTags = new HashMap<>();

public Gherkin3270Coordinator(Zos3270ManagerImpl manager, GherkinTest gherkinTest) {
this.manager = manager;
this.test = gherkinTest;
this.feature = gherkinTest;
}

public boolean registerStatements() throws ManagerException {
//*** Do we have any statements we need to support
if (!manager.registerStatements(this.test, getStatementOwners())) {
if (!manager.registerStatements(this.feature, getStatementOwners())) {
return false;
}
return true;
}


public IStatementOwner[] getStatementOwners() {
return new IStatementOwner[] {
new Gherkin3270GivenTerminal(this, this.manager),
Expand All @@ -48,8 +53,9 @@ public IStatementOwner[] getStatementOwners() {
new Gherkin3270TypeInField(this, this.manager)};
}

protected Zos3270TerminalImpl getTerminal(String id) {
return this.terminals.get(id);
protected Zos3270TerminalImpl getTerminal(String id) throws Zos3270ManagerException {
Zos3270TerminalImpl terminal = this.terminals.get(id);
return terminal ;
}

protected void registerTerminal(String id, Zos3270TerminalImpl terminal, String imageTag) {
Expand All @@ -59,10 +65,16 @@ protected void registerTerminal(String id, Zos3270TerminalImpl terminal, String

public void provisionGenerate() throws Zos3270ManagerException {
// Provision any terminals that are Given
for(IGherkinExecutable executable : this.test.getAllExecutables()) {
Object owner = executable.getOwner();
if (owner instanceof Gherkin3270GivenTerminal) {
((Gherkin3270GivenTerminal)owner).provision(executable);
List<GherkinMethod> methods = this.feature.getMethods();
for( GherkinMethod method : methods ) {

List<IGherkinExecutable> executables = method.getExecutables();
for(IGherkinExecutable executable : executables) {
Object owner = executable.getOwner();

if (owner instanceof Gherkin3270GivenTerminal) {
((Gherkin3270GivenTerminal)owner).provision(executable);
}
}
}
}
Expand All @@ -71,7 +83,6 @@ protected String getImageTagForTerminal(String id) {
return this.terminalImageTags.get(id);
}


public static String defaultTerminaId(String id) {
return AbstractManager.defaultString(id, "A").toUpperCase();
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,9 @@ public void typeUsername(IGherkinExecutable executable, Map<String,Object> testV
String credentialsId = AbstractManager.nulled(groups.get(0));

Zos3270TerminalImpl terminal = this.gerkinCoordinator.getTerminal(terminalId);
if (terminal == null ) {
throw new Zos3270ManagerException("Unable to get terminal "+terminalId);
}
if (!terminal.isConnected()) {
throw new Zos3270ManagerException("Terminal '" + terminalId + "' is not connected");
}
Expand Down Expand Up @@ -69,6 +72,9 @@ public void typePassword(IGherkinExecutable executable, Map<String,Object> testV
String credentialsId = AbstractManager.nulled(groups.get(0));

Zos3270TerminalImpl terminal = this.gerkinCoordinator.getTerminal(terminalId);
if (terminal == null ) {
throw new Zos3270ManagerException("Unable to get terminal "+terminalId);
}
if (!terminal.isConnected()) {
throw new Zos3270ManagerException("Terminal '" + terminalId + "' is not connected");
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@
import dev.galasa.zos3270.Zos3270ManagerException;
import dev.galasa.zos3270.common.screens.TerminalSize;
import dev.galasa.zos3270.internal.Zos3270ManagerImpl;
import dev.galasa.zos3270.spi.NetworkException;
import dev.galasa.zos3270.spi.Zos3270TerminalImpl;

public class Gherkin3270GivenTerminal implements IStatementOwner {
Expand All @@ -41,8 +42,13 @@ public void allocateTerminal(IGherkinExecutable executable, Map<String,Object> t
if (terminal == null) {
throw new Zos3270ManagerException("Terminal '" + terminalId + "' was not provisioned!");
}

if (!terminal.isConnected()) {
throw new Zos3270ManagerException("Terminal '" + terminalId + "' is not connected to the host system");
try {
terminal.connect();
} catch (NetworkException ex ) {
throw new Zos3270ManagerException("Cannot connect terminal to host system.",ex);
}
}
}

Expand All @@ -59,6 +65,6 @@ public void provision(IGherkinExecutable executable) throws Zos3270ManagerExcept
newTerminal = this.manager.generateTerminal(imageTag, true, terminalSize, alternateSize);
this.gerkinCoordinator.registerTerminal(terminalId, newTerminal, imageTag);
logger.info("zOS 3270 Terminal id '" + terminalId + "' as been provisioned for image tag '" + imageTag + "'");
}
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,9 @@ public void allocateTerminal(IGherkinExecutable executable, Map<String,Object> t


Zos3270TerminalImpl terminal = this.gerkinCoordinator.getTerminal(terminalId);
if (terminal == null ) {
throw new Zos3270ManagerException("Unable to get terminal "+terminalId);
}
if (!terminal.isConnected()) {
throw new Zos3270ManagerException("Terminal '" + terminalId + "' is not connected");
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,9 @@ public void pressBasicKey(IGherkinExecutable executable, Map<String,Object> test
String key = groups.get(1);

Zos3270TerminalImpl terminal = this.gerkinCoordinator.getTerminal(terminalId);
if (terminal == null ) {
throw new Zos3270ManagerException("Unable to get terminal "+terminalId);
}
if (!terminal.isConnected()) {
throw new Zos3270ManagerException("Terminal '" + terminalId + "' is not connected");
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,9 @@ public void pressPfKey(IGherkinExecutable executable, Map<String,Object> testVar
String key = groups.get(1);

Zos3270TerminalImpl terminal = this.gerkinCoordinator.getTerminal(terminalId);
if (terminal == null ) {
throw new Zos3270ManagerException("Unable to get terminal "+terminalId);
}
if (!terminal.isConnected()) {
throw new Zos3270ManagerException("Terminal '" + terminalId + "' is not connected");
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -32,12 +32,15 @@ public void allocateTerminal(IGherkinExecutable executable, Map<String,Object> t
List<String> groups = executable.getRegexGroups();

String terminalId = Gherkin3270Coordinator.defaultTerminaId(groups.get(1));
String text = groups.get(0);
String text = groups.get(0);
if (text.isEmpty()) {
return;
}

Zos3270TerminalImpl terminal = this.gerkinCoordinator.getTerminal(terminalId);
if (terminal == null ) {
throw new Zos3270ManagerException("Unable to get terminal "+terminalId);
}
if (!terminal.isConnected()) {
throw new Zos3270ManagerException("Terminal '" + terminalId + "' is not connected");
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,9 @@ public void allocateTerminal(IGherkinExecutable executable, Map<String,Object> t
}

Zos3270TerminalImpl terminal = this.gerkinCoordinator.getTerminal(terminalId);
if (terminal == null ) {
throw new Zos3270ManagerException("Unable to get terminal "+terminalId);
}
if (!terminal.isConnected()) {
throw new Zos3270ManagerException("Terminal '" + terminalId + "' is not connected");
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,9 @@ public void allocateTerminal(IGherkinExecutable executable, Map<String,Object> t
String terminalId = Gherkin3270Coordinator.defaultTerminaId(groups.get(0));

Zos3270TerminalImpl terminal = this.gerkinCoordinator.getTerminal(terminalId);
if (terminal == null ) {
throw new Zos3270ManagerException("Unable to get terminal "+terminalId);
}
if (!terminal.isConnected()) {
throw new Zos3270ManagerException("Terminal '" + terminalId + "' is not connected");
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,9 @@ public void allocateTerminal(IGherkinExecutable executable, Map<String,Object> t
}

Zos3270TerminalImpl terminal = this.gerkinCoordinator.getTerminal(terminalId);
if (terminal == null ) {
throw new Zos3270ManagerException("Unable to get terminal "+terminalId);
}
if (!terminal.isConnected()) {
throw new Zos3270ManagerException("Terminal '" + terminalId + "' is not connected");
}
Expand Down
2 changes: 1 addition & 1 deletion release.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -520,7 +520,7 @@ managers:
codecoverage: false

- artifact: dev.galasa.zos3270.manager
version: 0.34.0
version: 0.36.0
obr: true
mvp: true
bom: true
Expand Down

0 comments on commit cddd9e6

Please sign in to comment.