From 5c9281bc7e8f3704bef2c92d895838997050a80f Mon Sep 17 00:00:00 2001 From: Benoit Marty Date: Wed, 18 May 2022 12:23:28 +0200 Subject: [PATCH 1/3] Ensure calling 'fail()' is not caught by the Exception handler --- .../java/org/matrix/android/sdk/Util.kt | 44 ++++++++++++++ .../sdk/internal/crypto/E2eeSanityTests.kt | 5 +- .../crypto/gossiping/KeyShareTests.kt | 14 ++--- .../crypto/gossiping/WithHeldTests.kt | 59 ++++++++++--------- 4 files changed, 83 insertions(+), 39 deletions(-) create mode 100644 matrix-sdk-android/src/androidTest/java/org/matrix/android/sdk/Util.kt diff --git a/matrix-sdk-android/src/androidTest/java/org/matrix/android/sdk/Util.kt b/matrix-sdk-android/src/androidTest/java/org/matrix/android/sdk/Util.kt new file mode 100644 index 0000000000..2970dec29a --- /dev/null +++ b/matrix-sdk-android/src/androidTest/java/org/matrix/android/sdk/Util.kt @@ -0,0 +1,44 @@ +/* + * Copyright (c) 2022 New Vector Ltd + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.matrix.android.sdk + +import junit.framework.TestCase.fail + +/** + * Will fail the test if invoking [block] is not throwing a Throwable. + * + * @param message the failure message, if the block does not throw any Throwable + * @param failureBlock a Lambda to be able to do extra check on the thrown Throwable + * @param block the block to test + */ +internal suspend fun mustFail( + message: String = "must fail", + failureBlock: ((Throwable) -> Unit)? = null, + block: suspend () -> Unit, +) { + val isSuccess = try { + block.invoke() + true + } catch (throwable: Throwable) { + failureBlock?.invoke(throwable) + false + } + + if (isSuccess) { + fail(message) + } +} diff --git a/matrix-sdk-android/src/androidTest/java/org/matrix/android/sdk/internal/crypto/E2eeSanityTests.kt b/matrix-sdk-android/src/androidTest/java/org/matrix/android/sdk/internal/crypto/E2eeSanityTests.kt index 38597269cb..552936971f 100644 --- a/matrix-sdk-android/src/androidTest/java/org/matrix/android/sdk/internal/crypto/E2eeSanityTests.kt +++ b/matrix-sdk-android/src/androidTest/java/org/matrix/android/sdk/internal/crypto/E2eeSanityTests.kt @@ -62,6 +62,7 @@ import org.matrix.android.sdk.common.RetryTestRule import org.matrix.android.sdk.common.SessionTestParams import org.matrix.android.sdk.common.TestConstants import org.matrix.android.sdk.common.TestMatrixCallback +import org.matrix.android.sdk.mustFail import java.util.concurrent.CountDownLatch @RunWith(JUnit4::class) @@ -525,10 +526,8 @@ class E2eeSanityTests : InstrumentedTest { // Confirm we can decrypt one but not the other testHelper.runBlockingTest { - try { + mustFail(message = "Should not be able to decrypt event") { newBobSession.cryptoService().decryptEvent(firstEventNewBobPov.root, "") - fail("Should not be able to decrypt event") - } catch (_: MXCryptoError) { } } diff --git a/matrix-sdk-android/src/androidTest/java/org/matrix/android/sdk/internal/crypto/gossiping/KeyShareTests.kt b/matrix-sdk-android/src/androidTest/java/org/matrix/android/sdk/internal/crypto/gossiping/KeyShareTests.kt index 1bd2a46381..895f95aeac 100644 --- a/matrix-sdk-android/src/androidTest/java/org/matrix/android/sdk/internal/crypto/gossiping/KeyShareTests.kt +++ b/matrix-sdk-android/src/androidTest/java/org/matrix/android/sdk/internal/crypto/gossiping/KeyShareTests.kt @@ -21,7 +21,6 @@ import androidx.test.ext.junit.runners.AndroidJUnit4 import androidx.test.filters.LargeTest import junit.framework.TestCase.assertNotNull import junit.framework.TestCase.assertTrue -import junit.framework.TestCase.fail import org.amshove.kluent.internal.assertEquals import org.junit.Assert import org.junit.Assert.assertNull @@ -47,6 +46,7 @@ import org.matrix.android.sdk.common.CryptoTestHelper import org.matrix.android.sdk.common.RetryTestRule import org.matrix.android.sdk.common.SessionTestParams import org.matrix.android.sdk.common.TestConstants +import org.matrix.android.sdk.mustFail @RunWith(AndroidJUnit4::class) @FixMethodOrder(MethodSorters.JVM) @@ -95,12 +95,10 @@ class KeyShareTests : InstrumentedTest { assertNotNull(receivedEvent) assert(receivedEvent!!.isEncrypted()) - try { - commonTestHelper.runBlockingTest { + commonTestHelper.runBlockingTest { + mustFail { aliceSession2.cryptoService().decryptEvent(receivedEvent.root, "foo") } - fail("should fail") - } catch (failure: Throwable) { } val outgoingRequestsBefore = aliceSession2.cryptoService().getOutgoingRoomKeyRequests() @@ -168,12 +166,10 @@ class KeyShareTests : InstrumentedTest { } } - try { - commonTestHelper.runBlockingTest { + commonTestHelper.runBlockingTest { + mustFail { aliceSession2.cryptoService().decryptEvent(receivedEvent.root, "foo") } - fail("should fail") - } catch (failure: Throwable) { } // Mark the device as trusted diff --git a/matrix-sdk-android/src/androidTest/java/org/matrix/android/sdk/internal/crypto/gossiping/WithHeldTests.kt b/matrix-sdk-android/src/androidTest/java/org/matrix/android/sdk/internal/crypto/gossiping/WithHeldTests.kt index 1c3c6c46e7..13133b726c 100644 --- a/matrix-sdk-android/src/androidTest/java/org/matrix/android/sdk/internal/crypto/gossiping/WithHeldTests.kt +++ b/matrix-sdk-android/src/androidTest/java/org/matrix/android/sdk/internal/crypto/gossiping/WithHeldTests.kt @@ -42,6 +42,7 @@ import org.matrix.android.sdk.common.MockOkHttpInterceptor import org.matrix.android.sdk.common.RetryTestRule import org.matrix.android.sdk.common.SessionTestParams import org.matrix.android.sdk.common.TestConstants +import org.matrix.android.sdk.mustFail @RunWith(AndroidJUnit4::class) @FixMethodOrder(MethodSorters.JVM) @@ -96,17 +97,19 @@ class WithHeldTests : InstrumentedTest { // ============================= // Bob should not be able to decrypt because the keys is withheld - try { - // .. might need to wait a bit for stability? - testHelper.runBlockingTest { + // .. might need to wait a bit for stability? + testHelper.runBlockingTest { + mustFail( + message = "This session should not be able to decrypt", + failureBlock = { failure -> + val type = (failure as MXCryptoError.Base).errorType + val technicalMessage = failure.technicalMessage + Assert.assertEquals("Error should be withheld", MXCryptoError.ErrorType.KEYS_WITHHELD, type) + Assert.assertEquals("Cause should be unverified", WithHeldCode.UNVERIFIED.value, technicalMessage) + } + ) { bobUnverifiedSession.cryptoService().decryptEvent(eventBobPOV.root, "") } - Assert.fail("This session should not be able to decrypt") - } catch (failure: Throwable) { - val type = (failure as MXCryptoError.Base).errorType - val technicalMessage = failure.technicalMessage - Assert.assertEquals("Error should be withheld", MXCryptoError.ErrorType.KEYS_WITHHELD, type) - Assert.assertEquals("Cause should be unverified", WithHeldCode.UNVERIFIED.value, technicalMessage) } // Let's see if the reply we got from bob first session is unverified @@ -137,17 +140,18 @@ class WithHeldTests : InstrumentedTest { } // Previous message should still be undecryptable (partially withheld session) - try { - // .. might need to wait a bit for stability? - testHelper.runBlockingTest { + // .. might need to wait a bit for stability? + testHelper.runBlockingTest { + mustFail( + message = "This session should not be able to decrypt", + failureBlock = { failure -> + val type = (failure as MXCryptoError.Base).errorType + val technicalMessage = failure.technicalMessage + Assert.assertEquals("Error should be withheld", MXCryptoError.ErrorType.KEYS_WITHHELD, type) + Assert.assertEquals("Cause should be unverified", WithHeldCode.UNVERIFIED.value, technicalMessage) + }) { bobUnverifiedSession.cryptoService().decryptEvent(eventBobPOV.root, "") } - Assert.fail("This session should not be able to decrypt") - } catch (failure: Throwable) { - val type = (failure as MXCryptoError.Base).errorType - val technicalMessage = failure.technicalMessage - Assert.assertEquals("Error should be withheld", MXCryptoError.ErrorType.KEYS_WITHHELD, type) - Assert.assertEquals("Cause should be unverified", WithHeldCode.UNVERIFIED.value, technicalMessage) } testHelper.signOutAndClose(aliceSession) @@ -190,17 +194,18 @@ class WithHeldTests : InstrumentedTest { // Previous message should still be undecryptable (partially withheld session) val eventBobPOV = bobSession.getRoom(testData.roomId)?.getTimelineEvent(eventId) - try { - // .. might need to wait a bit for stability? - testHelper.runBlockingTest { + // .. might need to wait a bit for stability? + testHelper.runBlockingTest { + mustFail( + message = "This session should not be able to decrypt", + failureBlock = { failure -> + val type = (failure as MXCryptoError.Base).errorType + val technicalMessage = failure.technicalMessage + Assert.assertEquals("Error should be withheld", MXCryptoError.ErrorType.KEYS_WITHHELD, type) + Assert.assertEquals("Cause should be unverified", WithHeldCode.NO_OLM.value, technicalMessage) + }) { bobSession.cryptoService().decryptEvent(eventBobPOV!!.root, "") } - Assert.fail("This session should not be able to decrypt") - } catch (failure: Throwable) { - val type = (failure as MXCryptoError.Base).errorType - val technicalMessage = failure.technicalMessage - Assert.assertEquals("Error should be withheld", MXCryptoError.ErrorType.KEYS_WITHHELD, type) - Assert.assertEquals("Cause should be unverified", WithHeldCode.NO_OLM.value, technicalMessage) } // Ensure that alice has marked the session to be shared with bob From 328d8348519e13a9cf63763aada5eff696877742 Mon Sep 17 00:00:00 2001 From: Benoit Marty Date: Wed, 18 May 2022 13:09:58 +0200 Subject: [PATCH 2/3] changelog --- changelog.d/6089.misc | 1 + 1 file changed, 1 insertion(+) create mode 100644 changelog.d/6089.misc diff --git a/changelog.d/6089.misc b/changelog.d/6089.misc new file mode 100644 index 0000000000..19b951c1a3 --- /dev/null +++ b/changelog.d/6089.misc @@ -0,0 +1 @@ +Test: Ensure calling 'fail()' is not caught by the catch block From 99d4bbe74bb75f0af8834d70cb24df488fcbc438 Mon Sep 17 00:00:00 2001 From: Benoit Marty Date: Wed, 18 May 2022 14:12:44 +0200 Subject: [PATCH 3/3] Fix bad copyright --- .../src/androidTest/java/org/matrix/android/sdk/Util.kt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/matrix-sdk-android/src/androidTest/java/org/matrix/android/sdk/Util.kt b/matrix-sdk-android/src/androidTest/java/org/matrix/android/sdk/Util.kt index 2970dec29a..5e2c2ba25f 100644 --- a/matrix-sdk-android/src/androidTest/java/org/matrix/android/sdk/Util.kt +++ b/matrix-sdk-android/src/androidTest/java/org/matrix/android/sdk/Util.kt @@ -1,5 +1,5 @@ /* - * Copyright (c) 2022 New Vector Ltd + * Copyright (c) 2022 The Matrix.org Foundation C.I.C. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License.