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

Separating server start/stop from CI test execution #2280

Merged
merged 16 commits into from
Mar 9, 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.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
28 changes: 28 additions & 0 deletions .github/actions/connectivitytests-action/action.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
name: 'Openfire Start Server'
description: 'Start CI server from distribution'
inputs:
distBaseDir:
description: 'The base directory of the Openfire installation that is to be started.'
required: false
default: './distribution/target/distribution-base'
domain:
description: 'The network name for the Openfire under test, which will be used for both the hostname as the XMPP domain name.'
required: false
default: 'example.org'
ip:
description: 'Set a hosts file for the given IP and host (or for example.com if running locally)'
required: false
default: '127.0.0.1'

runs:
using: "composite"
steps:
- name: Set up Java
uses: actions/setup-java@v4
with:
java-version: 11
distribution: zulu
- name: Build with Maven
run: |
mvn clean test --file $GITHUB_ACTION_PATH/conntest/pom.xml
shell: bash
38 changes: 38 additions & 0 deletions .github/actions/connectivitytests-action/conntest/pom.xml
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>

<groupId>org.igniterealtime.tests</groupId>
<artifactId>smack-bosh-example</artifactId>
<version>1.0</version>

<properties>
<maven.compiler.source>11</maven.compiler.source>
<maven.compiler.target>11</maven.compiler.target>
</properties>

<dependencies>
<dependency>
<groupId>org.igniterealtime.smack</groupId>
<artifactId>smack-java7</artifactId>
<version>4.3.4</version>
</dependency>
<dependency>
<groupId>org.igniterealtime.smack</groupId>
<artifactId>smack-tcp</artifactId>
<version>4.3.4</version>
</dependency>
<dependency>
<groupId>org.igniterealtime.smack</groupId>
<artifactId>smack-bosh</artifactId>
<version>4.3.4</version>
</dependency>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.12</version>
<scope>test</scope>
</dependency>
</dependencies>

</project>
Original file line number Diff line number Diff line change
@@ -0,0 +1,111 @@
import org.jivesoftware.smack.ConnectionConfiguration;
import org.jivesoftware.smack.SmackException;
import org.jivesoftware.smack.bosh.BOSHConfiguration;
import org.jivesoftware.smack.bosh.XMPPBOSHConnection;
import org.jivesoftware.smack.tcp.XMPPTCPConnection;
import org.jivesoftware.smack.tcp.XMPPTCPConnectionConfiguration;
import org.junit.Assert;
import org.junit.Test;

public class ConnectivityTest
{
/**
* Verifies that a few connections can be established and used to authenticate over BOSH.
*/
@Test
public void testBoshConnections() throws Exception
{
// Setup test fixture.
final BOSHConfiguration config = BOSHConfiguration.builder()
.setFile("/http-bind/")
.setXmppDomain("example.org")
.setHost("localhost")
.setPort(7070)
.setUseHttps(false)
.setSecurityMode(ConnectionConfiguration.SecurityMode.disabled)
.build();
final int iterations = 50;

// For some reason, the first connection on a freshly started instance on CI seems to fail. This attempts to work
// around that problem by ignoring the first connection attempt.
final XMPPBOSHConnection warmupCon = new XMPPBOSHConnection(config);
warmupCon.connect();
try {
warmupCon.login("john", "secret");
} catch (Throwable e) {
System.out.println("Warm-up connection failed with error message: " + e.getMessage());
} finally {
warmupCon.disconnect();
}

// Execute system under test.
int result = 0;
for (int i=0; i<iterations; i++) {
final XMPPBOSHConnection con = new XMPPBOSHConnection(config);
con.connect();
try {
con.login("john", "secret");
if (con.isAuthenticated()) {
result++;
}
} catch (Throwable e) {
// This will prevent the result from being incremented, which will cause the test to fail.
e.printStackTrace();
} finally {
con.disconnect();
}
}

// Verify result.
Assert.assertEquals("Expected all BOSH connection attempts to result in an authenticated session, but not all did.", iterations, result);
}

/**
* Verifies that a few connections can be established and used to authenticate over TCP.
*/
@Test
public void testTCPConnections() throws Exception
{
// Setup test fixture.
final XMPPTCPConnectionConfiguration config = XMPPTCPConnectionConfiguration.builder()
.setXmppDomain("example.org")
.setHost("localhost")
.setPort(5222)
.setSecurityMode(ConnectionConfiguration.SecurityMode.disabled)
.build();
final int iterations = 50;

// For some reason, the first connection on a freshly started instance on CI seems to fail. This attempts to work
// around that problem by ignoring the first connection attempt.
final XMPPTCPConnection warmupCon = new XMPPTCPConnection(config);
warmupCon.connect();
try {
warmupCon.login("john", "secret");
} catch (Throwable e) {
System.out.println("Warm-up connection failed with error message: " + e.getMessage());
} finally {
warmupCon.disconnect();
}

// Execute system under test.
int result = 0;
for (int i=0; i<iterations; i++) {
final XMPPTCPConnection con = new XMPPTCPConnection(config);
con.connect();
try {
con.login("john", "secret");
if (con.isAuthenticated()) {
result++;
}
} catch (Throwable e) {
// This will prevent the result from being incremented, which will cause the test to fail.
e.printStackTrace();
} finally {
con.disconnect();
}
}

// Verify result.
Assert.assertEquals("Expected all TCP connection attempts to result in an authenticated session, but not all did.", iterations, result);
}
}
34 changes: 34 additions & 0 deletions .github/actions/startserver-action/action.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
name: 'Openfire Start Server'
description: 'Start CI server from distribution'
inputs:
distBaseDir:
description: 'The base directory of the Openfire installation that is to be started.'
required: false
default: './distribution/target/distribution-base'
domain:
description: 'The network name for the Openfire under test, which will be used for both the hostname as the XMPP domain name.'
required: false
default: 'example.org'
ip:
description: 'Set a hosts file for the given IP and host (or for example.com if running locally)'
required: false
default: '127.0.0.1'

runs:
using: "composite"
steps:
- name: Set GitHub Path
run: echo "$GITHUB_ACTION_PATH" >> $GITHUB_PATH
shell: bash
env:
GITHUB_ACTION_PATH: ${{ github.action_path }}
- name: Set up Java
uses: actions/setup-java@v4
with:
java-version: 11
distribution: zulu
- name: Set JAVA_HOME to use Java 11
run: echo "JAVA_HOME=$(echo $JAVA_HOME_11_X64)" >> $GITHUB_ENV
shell: bash
- run: startCIServer.sh -i ${{ inputs.ip }} -h ${{ inputs.domain }} -b ${{ inputs.distBaseDir }}
shell: bash
73 changes: 73 additions & 0 deletions .github/actions/startserver-action/startCIServer.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,73 @@
#!/usr/bin/env bash
# Starts an Openfire server (used in Continuous integration testing)
set -euo pipefail

HOST='example.org'

usage()
{
echo "Usage: $0 [-i IPADDRESS] [-h HOST] [-b BASEDIR]"
echo " -i: Set a hosts file for the given IP and host (or for example.com if running locally). Reverted at exit."
echo " -h: The network name for the Openfire under test, which will be used for both the hostname as the XMPP domain name (default: example.org)"
echo " -b: The base directory of the distribution that is to be started"
exit 2
}

while getopts h:i:b: OPTION "$@"; do
case $OPTION in
h)
HOST="${OPTARG}"
;;
i)
IPADDRESS="${OPTARG}"
;;
b)
BASEDIR="${OPTARG}"
;;
\? ) usage;;
: ) usage;;
* ) usage;;
esac
done

function setHostsFile {
if [[ -n "${IPADDRESS-}" ]]; then
echo "Setting hosts file for local running. This may prompt for sudo."
sudo /bin/sh -c "echo \"$IPADDRESS $HOST\" >> /etc/hosts"
fi
}

function launchOpenfire {
declare -r OPENFIRE_SHELL_SCRIPT="${BASEDIR}/bin/openfire.sh"

if [[ ! -f "${OPENFIRE_SHELL_SCRIPT}" ]]; then
echo "Unable to find Openfire distribution in ${BASEDIR} (this file did not exist: ${OPENFIRE_SHELL_SCRIPT} )"
exit 1
fi

# Ensure script is executable
chmod +x "${OPENFIRE_SHELL_SCRIPT}"

# Replace standard config with demoboot config
rm -f ${BASEDIR}/conf/openfire.xml
cp ${BASEDIR}/conf/openfire-demoboot.xml \
${BASEDIR}/conf/openfire.xml

# Replace the default XMPP domain name ('example.org') that's in the demoboot config with the configured domain name.
sed -i -e 's/example.org/'"${HOST}"'/g' ${BASEDIR}/conf/openfire.xml

echo "Starting Openfire…"
"${OPENFIRE_SHELL_SCRIPT}" &

# Wait 120 seconds for Openfire to open up the web interface and
# assume Openfire is fully operational once that happens (not sure if
# this assumption is correct).
echo "Waiting for Openfire…"
timeout 120 bash -c 'until printf "" 2>>/dev/null >>/dev/tcp/$0/$1; do sleep 0.3; done' localhost 7070
}

if [[ -n "${IPADDRESS-}" ]]; then
setHostsFile
fi

launchOpenfire
22 changes: 22 additions & 0 deletions .github/actions/stopserver-action/action.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
name: 'Openfire Stop Server'
description: 'Stops an Openfire server (used in Continuous integration testing)'
inputs:
domain:
description: 'The network name for the Openfire under test, which will be used for both the hostname as the XMPP domain name'
required: false
default: 'example.org'
ip:
description: 'Set a hosts file for the given IP and host (or for example.com if running locally)'
required: false
default: '127.0.0.1'

runs:
using: "composite"
steps:
- name: Set GitHub Path
run: echo "$GITHUB_ACTION_PATH" >> $GITHUB_PATH
shell: bash
env:
GITHUB_ACTION_PATH: ${{ github.action_path }}
- run: stopCIServer.sh -i ${{ inputs.ip }} -h ${{ inputs.domain }}
shell: bash
36 changes: 36 additions & 0 deletions .github/actions/stopserver-action/stopCIServer.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
#!/usr/bin/env bash
# Stops an Openfire server (used in Continuous integration testing)
set -euo pipefail

HOST='example.org'

usage()
{
echo "Usage: $0 [-i IPADDRESS] [-h HOST]"
echo " -i: Set a hosts file for the given IP and host (or for example.com if running locally). Reverted at exit."
echo " -h: The network name for the Openfire under test, which will be used for both the hostname as the XMPP domain name."

exit 2
}

while getopts h:i: OPTION "$@"; do
case $OPTION in
h)
HOST="${OPTARG}"
;;
i)
IPADDRESS="${OPTARG}"
;;
\? ) usage;;
: ) usage;;
* ) usage;;
esac
done

if [[ -n "${IPADDRESS-}" ]]; then
echo "Resetting hosts file after local running. This may prompt for sudo."
sudo sed -i'.original' "/$IPADDRESS $HOST/d" /etc/hosts
fi

echo "Stopping Openfire"
pkill -f openfire.lib #TODO: Can this be made more future-proof against changes in the start script?