@ParameterizedTest
    @MethodSource("arguments")
    public void outgoingTest(final ServerSettings localServerSettings, final ServerSettings remoteServerSettings)
        throws Exception
    {
        final ExpectedOutcome expected = ExpectedOutcome.generateExpectedOutcome(localServerSettings, remoteServerSettings);
        AbstractRemoteServerDummy.log("Executing test:\n - Local Server (Initiator, Openfire, System under test) Settings: " + localServerSettings + "\n - Remote Server (Recipient, dummy/mock server) Settings: " + remoteServerSettings + "\nExpected outcome: " + expected.getConnectionState());

        JiveGlobals.setProperty("xmpp.domain", Fixtures.XMPP_DOMAIN);
        JiveGlobals.setProperty("xmpp.server.session.initialise-timeout", Long.toString(1));

        try {
            AbstractRemoteServerDummy.log("Setup fixture: (start setting up fixture)");
            // Setup test fixture.

            // Remote server TLS policy.
            remoteReceivingServerDummy.setEncryptionPolicy(remoteServerSettings.encryptionPolicy);

            // Remote server dialback
            remoteReceivingServerDummy.setDisableDialback(!remoteServerSettings.dialbackSupported);

            // Remote server certificate state
            switch (remoteServerSettings.certificateState) {
                case INVALID:
                    remoteReceivingServerDummy.setUseExpiredEndEntityCertificate(true);
                    // Intended fall-through
                case VALID:
                    remoteReceivingServerDummy.preparePKIX();

                    // Install in local server's truststore.
                    final X509Certificate[] chain = remoteReceivingServerDummy.getGeneratedPKIX().getCertificateChain();
                    final X509Certificate caCert = chain[chain.length-1];
                    trustStore.installCertificate("unit-test", KeystoreTestUtils.toPemFormat(caCert));
                    break;
                case MISSING:
                    break;
                default:
                    throw new IllegalStateException("Unsupported remote certificate state");
            }

            // Local server TLS policy.
            JiveGlobals.setProperty(ConnectionSettings.Server.TLS_POLICY, localServerSettings.encryptionPolicy.toString());

            // Local server dialback.
            JiveGlobals.setProperty(ConnectionSettings.Server.DIALBACK_ENABLED, localServerSettings.dialbackSupported ? "true" : "false");

            // Local server certificate state
            switch (localServerSettings.certificateState) {
                case MISSING:
                    // Do not install domain certificate.
                    break;
                case INVALID:
                    // Insert an expired certificate into the identity store
                    identityStore.installCertificate(Fixtures.expiredX509Certificate, Fixtures.privateKeyForExpiredCert, "");
                    break;
                case VALID:
                    // Adds a valid certificate into identity store
                    identityStore.getStore().setKeyEntry( "selfsignedkey", FIXTURE_VALID_KEY, "secret".toCharArray(), FIXTURE_VALID_CERTIFICATE_CHAIN);
                    break;
            }

            final DomainPair domainPair = new DomainPair(Fixtures.XMPP_DOMAIN, RemoteReceivingServerDummy.XMPP_DOMAIN);
            final int port = remoteReceivingServerDummy.getPort();
            AbstractRemoteServerDummy.log("Setup fixture: (done with setting up fixture)");

            // Execute system under test.
            AbstractRemoteServerDummy.log("Execute system under test: (start with execution)");
            final LocalOutgoingServerSession result = LocalOutgoingServerSession.createOutgoingSession(domainPair, port);
            AbstractRemoteServerDummy.log("Execute system under test: (done with execution)");

            // Verify results
            AbstractRemoteServerDummy.log("Verify results (start)");
            AbstractRemoteServerDummy.log("Expect: " + expected.getConnectionState() + ", Result: " + result);
            switch (expected.getConnectionState())
            {
                case NO_CONNECTION:
                    assertNull(result);
                    break;
                case NON_ENCRYPTED_WITH_DIALBACK_AUTH:
                    assertNotNull(result);
                    assertFalse(result.isClosed());
                    assertFalse(result.isEncrypted());
                    assertTrue(result.isAuthenticated());
                    assertEquals(ServerSession.AuthenticationMethod.DIALBACK, result.getAuthenticationMethod());
                    break;
                case ENCRYPTED_WITH_DIALBACK_AUTH:
                    assertNotNull(result);
                    assertFalse(result.isClosed());
                    assertTrue(result.isEncrypted());
                    assertTrue(result.isAuthenticated());
                    assertEquals(ServerSession.AuthenticationMethod.DIALBACK, result.getAuthenticationMethod());
                    assertEquals( "TLSv1.3", result.getConnection().getTLSProtocolName().get());
                    break;
                case ENCRYPTED_WITH_SASLEXTERNAL_AUTH:
                    assertNotNull(result);
                    assertFalse(result.isClosed());
                    assertTrue(result.isEncrypted());
                    assertTrue(result.isAuthenticated());
                    assertEquals(ServerSession.AuthenticationMethod.SASL_EXTERNAL, result.getAuthenticationMethod());
                    assertEquals( "TLSv1.3", result.getConnection().getTLSProtocolName().get());
                    break;
            }
            AbstractRemoteServerDummy.log("Verify results (done)");
        } finally {
            // Teardown test fixture.
            AbstractRemoteServerDummy.log("Teardown test fixture (start)");
            trustStore.delete("unit-test");
            AbstractRemoteServerDummy.log("Teardown test fixture (start)");
        }
    }
Unit test in which Openfire initiates an outgoing server-to-server connection.

This test is parameterized, meaning that the configuration of both the local server and the remote mock server is
passed as an argument to this method. These configurations are used to both initialize and execute the test, but
also to calculate the expected outcome of the test, given the provided configuration. This expected outcome is
asserted by the test implementation

@param localServerSettings Server settings for the system under test (the 'local' server).
@param remoteServerSettings Server settings for the mock server that is used as a peer in this test.
xmppserver/src/test/java/org/jivesoftware/openfire/session/LocalOutgoingServerSessionTest.java