From c2e8ecfdffc8487c7c166297317e5a5ae5d64ae4 Mon Sep 17 00:00:00 2001 From: TheOneWithTheBraid Date: Wed, 18 Jan 2023 11:45:55 +0100 Subject: [PATCH] refactor: migrate integration tests to more stable setup Signed-off-by: TheOneWithTheBraid Signed-off-by: The one with the braid --- .gitlab-ci.yml | 13 +- ...ntegration-create-environment-variables.sh | 8 + scripts/integration-prepare-homeserver.sh | 44 ++++- scripts/test_driver.sh | 4 +- test_driver/matrixsdk_test.dart | 156 ++++++++++-------- test_driver/test_config.dart | 43 ++++- 6 files changed, 178 insertions(+), 90 deletions(-) create mode 100755 scripts/integration-create-environment-variables.sh diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml index 8597ccd2..66351838 100644 --- a/.gitlab-ci.yml +++ b/.gitlab-ci.yml @@ -76,23 +76,26 @@ e2ee_test: DOCKER_DRIVER: overlay2 # Disable TLS since we're running inside local network. DOCKER_TLS_CERTDIR: "" + HOMESERVER: docker dependencies: [] parallel: matrix: - - HOMESERVER: + - HOMESERVER_IMPLEMENTATION: - synapse - dendrite - conduit before_script: - scripts/integration-prepare-alpine.sh - # create Synapse instance - - scripts/integration-server-$HOMESERVER.sh + # deploy homeserver instance + - scripts/integration-server-$HOMESERVER_IMPLEMENTATION.sh + script: + # create test user environment variables + - source scripts/integration-create-environment-variables.sh # properly set the homeserver IP and create test users - scripts/integration-prepare-homeserver.sh # setup OLM - scripts/prepare.sh - script: - - ./scripts/test_driver.sh + - scripts/test_driver.sh timeout: 10m dry-run: diff --git a/scripts/integration-create-environment-variables.sh b/scripts/integration-create-environment-variables.sh new file mode 100755 index 00000000..e9ca0d3a --- /dev/null +++ b/scripts/integration-create-environment-variables.sh @@ -0,0 +1,8 @@ +#!/usr/bin/env bash + +export USER1_NAME="alice" +export USER1_PW="AliceInWonderland" +export USER2_NAME="bob" +export USER2_PW="JoWirSchaffenDas" +export USER3_NAME="trudy" +export USER3_PW="HaveIBeenPwned" diff --git a/scripts/integration-prepare-homeserver.sh b/scripts/integration-prepare-homeserver.sh index b29d62aa..903fb20d 100755 --- a/scripts/integration-prepare-homeserver.sh +++ b/scripts/integration-prepare-homeserver.sh @@ -1,18 +1,44 @@ #!/usr/bin/env bash -IP_ADDRESS="$(drill docker | grep -m 1 -P "\d+\.\d+\.\d+.\d+" | awk -F ' ' '{print $NF}')" +if [ -z $HOMESERVER ]; then + echo "Please ensure HOMESERVER environment variable is set to the IP or hostname of the homeserver." + exit 1 +fi +if [ -z $USER1_NAME ]; then + echo "Please ensure USER1_NAME environment variable is set to first user name." + exit 1 +fi +if [ -z $USER1_PW ]; then + echo "Please ensure USER1_PW environment variable is set to first user password." + exit 1 +fi +if [ -z $USER2_NAME ]; then + echo "Please ensure USER2_NAME environment variable is set to second user name." + exit 1 +fi +if [ -z $USER2_PW ]; then + echo "Please ensure USER2_PW environment variable is set to second user password." + exit 1 +fi +if [ -z $USER3_NAME ]; then + echo "Please ensure USER3_NAME environment variable is set to third user name." + exit 1 +fi +if [ -z $USER3_PW ]; then + echo "Please ensure USER3_PW environment variable is set to third user password." + exit 1 +fi -echo "Homeserver IP found at $IP_ADDRESS." +echo "Waiting for homeserver to be available... (GET http://$HOMESERVER/_matrix/client/v3/login)" -echo "Waiting for homeserver to be available..." - -while ! curl -XGET "http://$IP_ADDRESS/_matrix/client/v3/login" >/dev/null 2>/dev/null; do +while ! curl -XGET "http://$HOMESERVER/_matrix/client/v3/login" >/dev/null 2>/dev/null; do sleep 2 done + echo "Homeserver is up." -sed -i "s/localhost/$IP_ADDRESS/g" test_driver/test_config.dart +# create users -curl -fS --retry 3 -XPOST -d '{"username":"alice", "password":"AliceInWonderland", "inhibit_login":true, "auth": {"type":"m.login.dummy"}}' "http://$IP_ADDRESS/_matrix/client/r0/register" -curl -fS --retry 3 -XPOST -d '{"username":"bob", "password":"JoWirSchaffenDas", "inhibit_login":true, "auth": {"type":"m.login.dummy"}}' "http://$IP_ADDRESS/_matrix/client/r0/register" -curl -fS --retry 3 -XPOST -d '{"username":"trudy", "password":"HaveIBeenPwned", "inhibit_login":true, "auth": {"type":"m.login.dummy"}}' "http://$IP_ADDRESS/_matrix/client/r0/register" +curl -fS --retry 3 -XPOST -d '{"username":"'"$USER1_NAME"'", "password":"'"$USER1_PW"'", "inhibit_login":true, "auth": {"type":"m.login.dummy"}}' "http://$HOMESERVER/_matrix/client/r0/register" +curl -fS --retry 3 -XPOST -d '{"username":"'"$USER2_NAME"'", "password":"'"$USER2_PW"'", "inhibit_login":true, "auth": {"type":"m.login.dummy"}}' "http://$HOMESERVER/_matrix/client/r0/register" +curl -fS --retry 3 -XPOST -d '{"username":"'"$USER3_NAME"'", "password":"'"$USER3_PW"'", "inhibit_login":true, "auth": {"type":"m.login.dummy"}}' "http://$HOMESERVER/_matrix/client/r0/register" diff --git a/scripts/test_driver.sh b/scripts/test_driver.sh index 98788a14..00a6405f 100755 --- a/scripts/test_driver.sh +++ b/scripts/test_driver.sh @@ -1,6 +1,6 @@ #!/bin/sh -e if which flutter >/dev/null; then - flutter pub run test_driver/matrixsdk_test.dart -p vm + flutter --no-version-check test test_driver/matrixsdk_test.dart --dart-define=HOMESERVER=$HOMESERVER --dart-define=USER1_NAME=$USER1_NAME --dart-define=USER2_NAME=$USER2_NAME --dart-define=USER3_NAME=$USER3_NAME --dart-define=USER1_PW=$USER1_PW --dart-define=USER2_PW=$USER2_PW --dart-define=USER3_PW=$USER3_PW else - dart pub run test_driver/matrixsdk_test.dart -p vm + dart run -D HOMESERVER=$HOMESERVER -D USER1_NAME=$USER1_NAME -D USER2_NAME=$USER2_NAME -D USER3_NAME=$USER3_NAME -D USER1_PW=$USER1_PW -D USER2_PW=$USER2_PW -D USER3_PW=$USER3_PW test_driver/matrixsdk_test.dart -p vm fi diff --git a/test_driver/matrixsdk_test.dart b/test_driver/matrixsdk_test.dart index 7bad6680..72e1dde1 100644 --- a/test_driver/matrixsdk_test.dart +++ b/test_driver/matrixsdk_test.dart @@ -44,22 +44,27 @@ void main() => group('Integration tests', () { olm.Account(); Logs().i('[LibOlm] Enabled'); + final homeserverUri = Uri.parse(homeserver); + Logs().i('++++ Using homeserver $homeserverUri ++++'); + Logs().i('++++ Login Alice at ++++'); testClientA = Client('TestClientA', databaseBuilder: getDatabase); - await testClientA.checkHomeserver(Uri.parse(TestUser.homeserver)); - await testClientA.login(LoginType.mLoginPassword, - identifier: AuthenticationUserIdentifier( - user: TestUser.username.localpart!), - password: TestUser.password); + await testClientA.checkHomeserver(homeserverUri); + await testClientA.login( + LoginType.mLoginPassword, + identifier: AuthenticationUserIdentifier(user: Users.user1.name), + password: Users.user1.password, + ); expect(testClientA.encryptionEnabled, true); Logs().i('++++ Login Bob ++++'); testClientB = Client('TestClientB', databaseBuilder: getDatabase); - await testClientB.checkHomeserver(Uri.parse(TestUser.homeserver)); - await testClientB.login(LoginType.mLoginPassword, - identifier: AuthenticationUserIdentifier( - user: TestUser.username2.localpart!), - password: TestUser.password2); + await testClientB.checkHomeserver(homeserverUri); + await testClientB.login( + LoginType.mLoginPassword, + identifier: AuthenticationUserIdentifier(user: Users.user2.name), + password: Users.user2.password, + ); expect(testClientB.encryptionEnabled, true); Logs().i('++++ (Alice) Leave all rooms ++++'); @@ -86,32 +91,32 @@ void main() => group('Integration tests', () { } Logs().i('++++ Check if own olm device is verified by default ++++'); - expect(testClientA.userDeviceKeys, contains(TestUser.username)); - expect(testClientA.userDeviceKeys[TestUser.username]!.deviceKeys, + expect(testClientA.userDeviceKeys, contains(testClientA.userID)); + expect(testClientA.userDeviceKeys[testClientA.userID]!.deviceKeys, contains(testClientA.deviceID)); expect( - testClientA.userDeviceKeys[TestUser.username]! + testClientA.userDeviceKeys[testClientA.userID]! .deviceKeys[testClientA.deviceID!]!.verified, isTrue); expect( - !testClientA.userDeviceKeys[TestUser.username]! + !testClientA.userDeviceKeys[testClientA.userID]! .deviceKeys[testClientA.deviceID!]!.blocked, isTrue); - expect(testClientB.userDeviceKeys, contains(TestUser.username2)); - expect(testClientB.userDeviceKeys[TestUser.username2]!.deviceKeys, + expect(testClientB.userDeviceKeys, contains(testClientB.userID)); + expect(testClientB.userDeviceKeys[testClientB.userID]!.deviceKeys, contains(testClientB.deviceID)); expect( - testClientB.userDeviceKeys[TestUser.username2]! + testClientB.userDeviceKeys[testClientB.userID]! .deviceKeys[testClientB.deviceID!]!.verified, isTrue); expect( - !testClientB.userDeviceKeys[TestUser.username2]! + !testClientB.userDeviceKeys[testClientB.userID]! .deviceKeys[testClientB.deviceID!]!.blocked, isTrue); Logs().i('++++ (Alice) Create room and invite Bob ++++'); await testClientA.startDirectChat( - TestUser.username2, + testClientB.userID!, enableEncryption: false, ); await Future.delayed(Duration(seconds: 1)); @@ -132,52 +137,52 @@ void main() => group('Integration tests', () { expect( room.client.encryption!.keyManager .getOutboundGroupSession(room.id), - null); + isNull); Logs().i('++++ (Alice) Check known olm devices ++++'); - expect(testClientA.userDeviceKeys, contains(TestUser.username2)); - expect(testClientA.userDeviceKeys[TestUser.username2]!.deviceKeys, + expect(testClientA.userDeviceKeys, contains(testClientB.userID)); + expect(testClientA.userDeviceKeys[testClientB.userID]!.deviceKeys, contains(testClientB.deviceID)); expect( - testClientA.userDeviceKeys[TestUser.username2]! + testClientA.userDeviceKeys[testClientB.userID]! .deviceKeys[testClientB.deviceID!]!.verified, isFalse); expect( - testClientA.userDeviceKeys[TestUser.username2]! + testClientA.userDeviceKeys[testClientB.userID]! .deviceKeys[testClientB.deviceID!]!.blocked, isFalse); - expect(testClientB.userDeviceKeys, contains(TestUser.username)); - expect(testClientB.userDeviceKeys[TestUser.username]!.deviceKeys, + expect(testClientB.userDeviceKeys, contains(testClientA.userID)); + expect(testClientB.userDeviceKeys[testClientA.userID]!.deviceKeys, contains(testClientA.deviceID)); expect( - testClientB.userDeviceKeys[TestUser.username]! + testClientB.userDeviceKeys[testClientA.userID]! .deviceKeys[testClientA.deviceID!]!.verified, isFalse); expect( - testClientB.userDeviceKeys[TestUser.username]! + testClientB.userDeviceKeys[testClientA.userID]! .deviceKeys[testClientA.deviceID!]!.blocked, isFalse); await Future.wait([ testClientA.updateUserDeviceKeys(), testClientB.updateUserDeviceKeys(), ]); - await testClientA.userDeviceKeys[TestUser.username2]! + await testClientA.userDeviceKeys[testClientB.userID]! .deviceKeys[testClientB.deviceID!]! .setVerified(true); Logs().i('++++ Check if own olm device is verified by default ++++'); - expect(testClientA.userDeviceKeys, contains(TestUser.username)); - expect(testClientA.userDeviceKeys[TestUser.username]!.deviceKeys, + expect(testClientA.userDeviceKeys, contains(testClientA.userID)); + expect(testClientA.userDeviceKeys[testClientA.userID]!.deviceKeys, contains(testClientA.deviceID)); expect( - testClientA.userDeviceKeys[TestUser.username]! + testClientA.userDeviceKeys[testClientA.userID]! .deviceKeys[testClientA.deviceID!]!.verified, isTrue); - expect(testClientB.userDeviceKeys, contains(TestUser.username2)); - expect(testClientB.userDeviceKeys[TestUser.username2]!.deviceKeys, + expect(testClientB.userDeviceKeys, contains(testClientB.userID)); + expect(testClientB.userDeviceKeys[testClientB.userID]!.deviceKeys, contains(testClientB.deviceID)); expect( - testClientB.userDeviceKeys[TestUser.username2]! + testClientB.userDeviceKeys[testClientB.userID]! .deviceKeys[testClientB.deviceID!]!.verified, isTrue); @@ -196,13 +201,15 @@ void main() => group('Integration tests', () { .getInboundGroupSession(room.id, currentSessionIdA, '') != null);*/ expect( - testClientA.encryption!.olmManager - .olmSessions[testClientB.identityKey]!.length, - 1); + testClientA.encryption!.olmManager + .olmSessions[testClientB.identityKey]!.length, + olmLengthMatcher, + ); expect( - testClientB.encryption!.olmManager - .olmSessions[testClientA.identityKey]!.length, - 1); + testClientB.encryption!.olmManager + .olmSessions[testClientA.identityKey]!.length, + olmLengthMatcher, + ); expect( testClientA.encryption!.olmManager .olmSessions[testClientB.identityKey]!.first.sessionId, @@ -221,13 +228,15 @@ void main() => group('Integration tests', () { await room.sendTextEvent(testMessage2); await Future.delayed(Duration(seconds: 5)); expect( - testClientA.encryption!.olmManager - .olmSessions[testClientB.identityKey]!.length, - 1); + testClientA.encryption!.olmManager + .olmSessions[testClientB.identityKey]!.length, + olmLengthMatcher, + ); expect( - testClientB.encryption!.olmManager - .olmSessions[testClientA.identityKey]!.length, - 1); + testClientB.encryption!.olmManager + .olmSessions[testClientA.identityKey]!.length, + olmLengthMatcher, + ); expect( testClientA.encryption!.olmManager .olmSessions[testClientB.identityKey]!.first.sessionId, @@ -253,13 +262,14 @@ void main() => group('Integration tests', () { await inviteRoom.sendTextEvent(testMessage3); await Future.delayed(Duration(seconds: 5)); expect( - testClientA.encryption!.olmManager - .olmSessions[testClientB.identityKey]!.length, - 1); + testClientA.encryption!.olmManager + .olmSessions[testClientB.identityKey]!.length, + olmLengthMatcher, + ); expect( testClientB.encryption!.olmManager .olmSessions[testClientA.identityKey]!.length, - 1); + olmLengthMatcher); expect( room.client.encryption!.keyManager .getOutboundGroupSession(room.id)! @@ -289,18 +299,19 @@ void main() => group('Integration tests', () { Logs().i('++++ Login Bob in another client ++++'); final testClientC = Client('TestClientC', databaseBuilder: getDatabase); - await testClientC.checkHomeserver(Uri.parse(TestUser.homeserver)); + await testClientC.checkHomeserver(homeserverUri); // We can't sign in using the displayname, since that breaks e2ee on dendrite: https://github.com/matrix-org/dendrite/issues/2914 - await testClientC.login(LoginType.mLoginPassword, - identifier: AuthenticationUserIdentifier( - user: TestUser.username2.localpart!), - password: TestUser.password2); + await testClientC.login( + LoginType.mLoginPassword, + identifier: AuthenticationUserIdentifier(user: Users.user2.name), + password: Users.user2.password, + ); await Future.delayed(Duration(seconds: 3)); Logs().i( "++++ (Alice) Send again encrypted message: '$testMessage4' ++++"); await room.sendTextEvent(testMessage4); - await Future.delayed(Duration(seconds: 5)); + await Future.delayed(Duration(seconds: 7)); expect( testClientA.encryption!.olmManager .olmSessions[testClientB.identityKey]!.length, @@ -317,11 +328,11 @@ void main() => group('Integration tests', () { expect( testClientA.encryption!.olmManager .olmSessions[testClientC.identityKey]!.length, - 1); + olmLengthMatcher); expect( testClientC.encryption!.olmManager .olmSessions[testClientA.identityKey]!.length, - 1); + olmLengthMatcher); expect( testClientA.encryption!.olmManager .olmSessions[testClientC.identityKey]!.first.sessionId, @@ -352,13 +363,15 @@ void main() => group('Integration tests', () { await room.sendTextEvent(testMessage6); await Future.delayed(Duration(seconds: 5)); expect( - testClientA.encryption!.olmManager - .olmSessions[testClientB.identityKey]!.length, - 1); + testClientA.encryption!.olmManager + .olmSessions[testClientB.identityKey]!.length, + olmLengthMatcher, + ); expect( - testClientB.encryption!.olmManager - .olmSessions[testClientA.identityKey]!.length, - 1); + testClientB.encryption!.olmManager + .olmSessions[testClientA.identityKey]!.length, + olmLengthMatcher, + ); expect( testClientA.encryption!.olmManager .olmSessions[testClientB.identityKey]!.first.sessionId, @@ -366,7 +379,7 @@ void main() => group('Integration tests', () { .olmSessions[testClientA.identityKey]!.first.sessionId); // This does not work on conduit because of a server bug: https://gitlab.com/famedly/conduit/-/issues/325 - if (Platform.environment['HOMESERVER'] != 'conduit') { + if (Platform.environment['HOMESERVER_IMPLEMENTATION'] != 'conduit') { expect( room.client.encryption!.keyManager .getOutboundGroupSession(room.id)! @@ -406,3 +419,14 @@ void main() => group('Integration tests', () { return; }); }, timeout: Timeout(Duration(minutes: 6))); + +Object get olmLengthMatcher { + return + // workarounding weird Dendrite bug + Platform.environment['HOMESERVER_IMPLEMENTATION'] != 'dendrite' + ? 1 + : predicate( + [1, 2].contains, + 'is either 1 or two', + ); +} diff --git a/test_driver/test_config.dart b/test_driver/test_config.dart index fecb94ff..8af999e9 100644 --- a/test_driver/test_config.dart +++ b/test_driver/test_config.dart @@ -1,9 +1,36 @@ -class TestUser { - static const String homeserver = 'http://localhost'; - static const String username = '@alice:famedlysdk.test'; - static const String username2 = '@bob:famedlysdk.test'; - static const String displayname = 'Alice'; - static const String displayname2 = 'Bob'; - static const String password = 'AliceInWonderland'; - static const String password2 = 'JoWirSchaffenDas'; +abstract class Users { + const Users._(); + + static const user1 = User( + String.fromEnvironment( + 'USER1_NAME', + defaultValue: 'alice', + ), + String.fromEnvironment( + 'USER1_PW', + defaultValue: 'AliceInWonderland', + ), + ); + static const user2 = User( + String.fromEnvironment( + 'USER2_NAME', + defaultValue: 'bob', + ), + String.fromEnvironment( + 'USER2_PW', + defaultValue: 'JoWirSchaffenDas', + ), + ); } + +class User { + final String name; + final String password; + + const User(this.name, this.password); +} + +const homeserver = 'http://${const String.fromEnvironment( + 'HOMESERVER', + defaultValue: 'localhost', +)}';