aboutsummaryrefslogtreecommitdiff
path: root/java/android/OlmLibSdk/olm-sdk/src/androidTest
diff options
context:
space:
mode:
Diffstat (limited to 'java/android/OlmLibSdk/olm-sdk/src/androidTest')
-rw-r--r--java/android/OlmLibSdk/olm-sdk/src/androidTest/java/org/matrix/olm/OlmAccountTest.java420
-rw-r--r--java/android/OlmLibSdk/olm-sdk/src/androidTest/java/org/matrix/olm/OlmGroupSessionTest.java443
-rw-r--r--java/android/OlmLibSdk/olm-sdk/src/androidTest/java/org/matrix/olm/OlmSessionTest.java641
-rw-r--r--java/android/OlmLibSdk/olm-sdk/src/androidTest/java/org/matrix/olm/OlmUtilityTest.java124
-rw-r--r--java/android/OlmLibSdk/olm-sdk/src/androidTest/java/org/matrix/olm/TestHelper.java90
5 files changed, 1718 insertions, 0 deletions
diff --git a/java/android/OlmLibSdk/olm-sdk/src/androidTest/java/org/matrix/olm/OlmAccountTest.java b/java/android/OlmLibSdk/olm-sdk/src/androidTest/java/org/matrix/olm/OlmAccountTest.java
new file mode 100644
index 0000000..2c2711d
--- /dev/null
+++ b/java/android/OlmLibSdk/olm-sdk/src/androidTest/java/org/matrix/olm/OlmAccountTest.java
@@ -0,0 +1,420 @@
+/*
+ * Copyright 2016 OpenMarket 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.olm;
+
+import android.content.Context;
+import android.support.test.runner.AndroidJUnit4;
+import android.text.TextUtils;
+import android.util.Log;
+
+import org.json.JSONException;
+import org.json.JSONObject;
+import org.junit.After;
+import org.junit.AfterClass;
+import org.junit.Before;
+import org.junit.BeforeClass;
+import org.junit.FixMethodOrder;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.junit.runners.MethodSorters;
+
+import java.io.FileInputStream;
+import java.io.FileNotFoundException;
+import java.io.FileOutputStream;
+import java.io.IOException;
+import java.io.ObjectInputStream;
+import java.io.ObjectOutputStream;
+
+import static android.support.test.InstrumentationRegistry.getInstrumentation;
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertNotNull;
+import static org.junit.Assert.assertNull;
+import static org.junit.Assert.assertTrue;
+
+@RunWith(AndroidJUnit4.class)
+@FixMethodOrder(MethodSorters.NAME_ASCENDING)
+public class OlmAccountTest {
+ private static final String LOG_TAG = "OlmAccountTest";
+ private static final int GENERATION_ONE_TIME_KEYS_NUMBER = 50;
+
+ private static OlmAccount mOlmAccount;
+ private static OlmManager mOlmManager;
+ private boolean mIsAccountCreated;
+ private final String FILE_NAME = "SerialTestFile";
+
+ @BeforeClass
+ public static void setUpClass(){
+ // enable UTF-8 specific conversion for pre Marshmallow(23) android versions,
+ // due to issue described here: https://github.com/eclipsesource/J2V8/issues/142
+ boolean isSpecificUtf8ConversionEnabled = android.os.Build.VERSION.SDK_INT < 23;
+
+ // load native lib
+ mOlmManager = new OlmManager(isSpecificUtf8ConversionEnabled);
+
+ String olmLibVersion = mOlmManager.getOlmLibVersion();
+ assertNotNull(olmLibVersion);
+ String olmSdkVersion = mOlmManager.getSdkOlmVersion();
+ assertNotNull(olmLibVersion);
+ Log.d(LOG_TAG, "## setUpClass(): Versions - Android Olm SDK = "+olmSdkVersion+" Olm lib ="+olmLibVersion);
+ }
+
+ @AfterClass
+ public static void tearDownClass() {
+ // TBD
+ }
+
+ @Before
+ public void setUp() {
+ if(mIsAccountCreated) {
+ assertNotNull(mOlmAccount);
+ }
+ }
+
+ @After
+ public void tearDown() {
+ // TBD
+ }
+
+ /**
+ * Basic test: creation and release.
+ */
+ @Test
+ public void test01CreateReleaseAccount() {
+ try {
+ mOlmAccount = new OlmAccount();
+ } catch (OlmException e) {
+ e.printStackTrace();
+ }
+ assertNotNull(mOlmAccount);
+
+ mOlmAccount.releaseAccount();
+ assertTrue(0 == mOlmAccount.getOlmAccountId());
+ }
+
+ @Test
+ public void test02CreateAccount() {
+ try {
+ mOlmAccount = new OlmAccount();
+ } catch (OlmException e) {
+ e.printStackTrace();
+ }
+ assertNotNull(mOlmAccount);
+ mIsAccountCreated = true;
+ }
+
+ @Test
+ public void test04GetOlmAccountId() {
+ long olmNativeInstance = mOlmAccount.getOlmAccountId();
+ Log.d(LOG_TAG,"## testGetOlmAccountId olmNativeInstance="+olmNativeInstance);
+ assertTrue(0!=olmNativeInstance);
+ }
+
+ /**
+ * Test if {@link OlmAccount#identityKeys()} returns a JSON object
+ * that contains the following keys: {@link OlmAccount#JSON_KEY_FINGER_PRINT_KEY}
+ * and {@link OlmAccount#JSON_KEY_IDENTITY_KEY}
+ */
+ @Test
+ public void test05IdentityKeys() {
+ JSONObject identityKeysJson = mOlmAccount.identityKeys();
+ assertNotNull(identityKeysJson);
+ Log.d(LOG_TAG,"## testIdentityKeys Keys="+identityKeysJson);
+
+ // is JSON_KEY_FINGER_PRINT_KEY present?
+ String fingerPrintKey = TestHelper.getFingerprintKey(identityKeysJson);
+ assertTrue("fingerprint key missing",!TextUtils.isEmpty(fingerPrintKey));
+
+ // is JSON_KEY_IDENTITY_KEY present?
+ String identityKey = TestHelper.getIdentityKey(identityKeysJson);
+ assertTrue("identity key missing",!TextUtils.isEmpty(identityKey));
+ }
+
+ //****************************************************
+ //***************** ONE TIME KEYS TESTS **************
+ //****************************************************
+ @Test
+ public void test06MaxOneTimeKeys() {
+ long maxOneTimeKeys = mOlmAccount.maxOneTimeKeys();
+ Log.d(LOG_TAG,"## testMaxOneTimeKeys(): maxOneTimeKeys="+maxOneTimeKeys);
+
+ assertTrue(maxOneTimeKeys>0);
+ }
+
+ /**
+ * Test one time keys generation.
+ */
+ @Test
+ public void test07GenerateOneTimeKeys() {
+ int retValue = mOlmAccount.generateOneTimeKeys(GENERATION_ONE_TIME_KEYS_NUMBER);
+ assertTrue(0==retValue);
+ }
+
+ /**
+ * Test the generated amount of one time keys = GENERATION_ONE_TIME_KEYS_NUMBER.
+ */
+ @Test
+ public void test08OneTimeKeysJsonFormat() {
+ int oneTimeKeysCount = 0;
+ JSONObject generatedKeysJsonObj;
+ JSONObject oneTimeKeysJson = mOlmAccount.oneTimeKeys();
+ assertNotNull(oneTimeKeysJson);
+
+ try {
+ generatedKeysJsonObj = oneTimeKeysJson.getJSONObject(OlmAccount.JSON_KEY_ONE_TIME_KEY);
+ assertTrue(OlmAccount.JSON_KEY_ONE_TIME_KEY +" object is missing", null!=generatedKeysJsonObj);
+
+ // test the count of the generated one time keys:
+ oneTimeKeysCount = generatedKeysJsonObj.length();
+
+ assertTrue("Expected count="+GENERATION_ONE_TIME_KEYS_NUMBER+" found="+oneTimeKeysCount,GENERATION_ONE_TIME_KEYS_NUMBER==oneTimeKeysCount);
+
+ } catch (JSONException e) {
+ assertTrue("Exception MSg="+e.getMessage(), false);
+ }
+ }
+
+ @Test
+ public void test10RemoveOneTimeKeysForSession() {
+ OlmSession olmSession = null;
+ try {
+ olmSession = new OlmSession();
+ } catch (OlmException e) {
+ assertTrue("Exception Msg="+e.getMessage(), false);
+ }
+ long sessionId = olmSession.getOlmSessionId();
+ assertTrue(0 != sessionId);
+
+ int sessionRetCode = mOlmAccount.removeOneTimeKeysForSession(olmSession);
+ // test against no matching keys
+ assertTrue(1 == sessionRetCode);
+
+ olmSession.releaseSession();
+ sessionId = olmSession.getOlmSessionId();
+ assertTrue("sessionRetCode="+sessionRetCode,0 == sessionId);
+ }
+
+ @Test
+ public void test11MarkOneTimeKeysAsPublished() {
+ int retCode = mOlmAccount.markOneTimeKeysAsPublished();
+ // if OK => retCode=0
+ assertTrue(0 == retCode);
+ }
+
+ @Test
+ public void test12SignMessage() {
+ String clearMsg = "String to be signed by olm";
+ String signedMsg = mOlmAccount.signMessage(clearMsg);
+ assertNotNull(signedMsg);
+ // additional tests are performed in test01VerifyEd25519Signing()
+ }
+
+
+ // ********************************************************
+ // ************* SERIALIZATION TEST ***********************
+ // ********************************************************
+
+ @Test
+ public void test13Serialization() {
+ FileOutputStream fileOutput;
+ ObjectOutputStream objectOutput;
+ OlmAccount accountRef = null;
+ OlmAccount accountDeserial;
+
+ try {
+ accountRef = new OlmAccount();
+ } catch (OlmException e) {
+ assertTrue(e.getMessage(),false);
+ }
+
+ int retValue = accountRef.generateOneTimeKeys(GENERATION_ONE_TIME_KEYS_NUMBER);
+ assertTrue(0==retValue);
+
+ // get keys references
+ JSONObject identityKeysRef = accountRef.identityKeys();
+ JSONObject oneTimeKeysRef = accountRef.oneTimeKeys();
+ assertNotNull(identityKeysRef);
+ assertNotNull(oneTimeKeysRef);
+
+ try {
+ Context context = getInstrumentation().getContext();
+ //context.getFilesDir();
+ fileOutput = context.openFileOutput(FILE_NAME, Context.MODE_PRIVATE);
+
+ // serialize account
+ objectOutput = new ObjectOutputStream(fileOutput);
+ objectOutput.writeObject(accountRef);
+ objectOutput.flush();
+ objectOutput.close();
+
+ // deserialize account
+ FileInputStream fileInput = context.openFileInput(FILE_NAME);
+ ObjectInputStream objectInput = new ObjectInputStream(fileInput);
+ accountDeserial = (OlmAccount) objectInput.readObject();
+ objectInput.close();
+ assertNotNull(accountDeserial);
+
+ // get de-serialized keys
+ JSONObject identityKeysDeserial = accountDeserial.identityKeys();
+ JSONObject oneTimeKeysDeserial = accountDeserial.oneTimeKeys();
+ assertNotNull(identityKeysDeserial);
+ assertNotNull(oneTimeKeysDeserial);
+
+ // compare identity keys
+ assertTrue(identityKeysDeserial.toString().equals(identityKeysRef.toString()));
+
+ // compare onetime keys
+ assertTrue(oneTimeKeysDeserial.toString().equals(oneTimeKeysRef.toString()));
+
+ accountRef.releaseAccount();
+ accountDeserial.releaseAccount();
+ }
+ catch (FileNotFoundException e) {
+ Log.e(LOG_TAG, "## test13Serialization(): Exception FileNotFoundException Msg=="+e.getMessage());
+ }
+ catch (ClassNotFoundException e) {
+ Log.e(LOG_TAG, "## test13Serialization(): Exception ClassNotFoundException Msg==" + e.getMessage());
+ }
+ catch (IOException e) {
+ Log.e(LOG_TAG, "## test13Serialization(): Exception IOException Msg==" + e.getMessage());
+ }
+ /*catch (OlmException e) {
+ Log.e(LOG_TAG, "## test13Serialization(): Exception OlmException Msg==" + e.getMessage());
+ }*/
+ catch (Exception e) {
+ Log.e(LOG_TAG, "## test13Serialization(): Exception Msg==" + e.getMessage());
+ }
+ }
+
+
+ // ****************************************************
+ // *************** SANITY CHECK TESTS *****************
+ // ****************************************************
+
+ @Test
+ public void test14GenerateOneTimeKeysError() {
+ // keys number = 0 => no error
+ int retValue = mOlmAccount.generateOneTimeKeys(0);
+ assertTrue(0==retValue);
+
+ // keys number = negative value
+ retValue = mOlmAccount.generateOneTimeKeys(-50);
+ assertTrue(-1==retValue);
+ }
+
+ @Test
+ public void test15RemoveOneTimeKeysForSessionError() {
+ OlmAccount olmAccount = null;
+ try {
+ olmAccount = new OlmAccount();
+ } catch (OlmException e) {
+ assertTrue(e.getMessage(),false);
+ }
+
+ int sessionRetCode = olmAccount.removeOneTimeKeysForSession(null);
+ // test against no matching keys
+ assertTrue(-1 == sessionRetCode);
+
+ olmAccount.releaseAccount();
+ }
+
+ @Test
+ public void test16SignMessageError() {
+ OlmAccount olmAccount = null;
+ try {
+ olmAccount = new OlmAccount();
+ } catch (OlmException e) {
+ assertTrue(e.getMessage(),false);
+ }
+ String signedMsg = olmAccount.signMessage(null);
+ assertNull(signedMsg);
+
+ olmAccount.releaseAccount();
+ }
+
+ /**
+ * Create multiple accounts and check that identity keys are still different.
+ * This test validates random series are provide enough random values.
+ */
+ @Test
+ public void test17MultipleAccountCreation() {
+ try {
+ OlmAccount account1 = new OlmAccount();
+ OlmAccount account2 = new OlmAccount();
+ OlmAccount account3 = new OlmAccount();
+ OlmAccount account4 = new OlmAccount();
+ OlmAccount account5 = new OlmAccount();
+ OlmAccount account6 = new OlmAccount();
+ OlmAccount account7 = new OlmAccount();
+ OlmAccount account8 = new OlmAccount();
+ OlmAccount account9 = new OlmAccount();
+ OlmAccount account10 = new OlmAccount();
+
+ JSONObject identityKeysJson1 = account1.identityKeys();
+ JSONObject identityKeysJson2 = account2.identityKeys();
+ JSONObject identityKeysJson3 = account3.identityKeys();
+ JSONObject identityKeysJson4 = account4.identityKeys();
+ JSONObject identityKeysJson5 = account5.identityKeys();
+ JSONObject identityKeysJson6 = account6.identityKeys();
+ JSONObject identityKeysJson7 = account7.identityKeys();
+ JSONObject identityKeysJson8 = account8.identityKeys();
+ JSONObject identityKeysJson9 = account9.identityKeys();
+ JSONObject identityKeysJson10 = account10.identityKeys();
+
+ String identityKey1 = TestHelper.getIdentityKey(identityKeysJson1);
+ String identityKey2 = TestHelper.getIdentityKey(identityKeysJson2);
+ assertFalse(identityKey1.equals(identityKey2));
+
+ String identityKey3 = TestHelper.getIdentityKey(identityKeysJson3);
+ assertFalse(identityKey2.equals(identityKey3));
+
+ String identityKey4 = TestHelper.getIdentityKey(identityKeysJson4);
+ assertFalse(identityKey3.equals(identityKey4));
+
+ String identityKey5 = TestHelper.getIdentityKey(identityKeysJson5);
+ assertFalse(identityKey4.equals(identityKey5));
+
+ String identityKey6 = TestHelper.getIdentityKey(identityKeysJson6);
+ assertFalse(identityKey5.equals(identityKey6));
+
+ String identityKey7 = TestHelper.getIdentityKey(identityKeysJson7);
+ assertFalse(identityKey6.equals(identityKey7));
+
+ String identityKey8 = TestHelper.getIdentityKey(identityKeysJson8);
+ assertFalse(identityKey7.equals(identityKey8));
+
+ String identityKey9 = TestHelper.getIdentityKey(identityKeysJson9);
+ assertFalse(identityKey8.equals(identityKey9));
+
+ String identityKey10 = TestHelper.getIdentityKey(identityKeysJson10);
+ assertFalse(identityKey9.equals(identityKey10));
+
+ account1.releaseAccount();
+ account2.releaseAccount();
+ account3.releaseAccount();
+ account4.releaseAccount();
+ account5.releaseAccount();
+ account6.releaseAccount();
+ account7.releaseAccount();
+ account8.releaseAccount();
+ account9.releaseAccount();
+ account10.releaseAccount();
+
+ } catch (OlmException e) {
+ assertTrue(e.getMessage(),false);
+ }
+ }
+}
diff --git a/java/android/OlmLibSdk/olm-sdk/src/androidTest/java/org/matrix/olm/OlmGroupSessionTest.java b/java/android/OlmLibSdk/olm-sdk/src/androidTest/java/org/matrix/olm/OlmGroupSessionTest.java
new file mode 100644
index 0000000..6e12463
--- /dev/null
+++ b/java/android/OlmLibSdk/olm-sdk/src/androidTest/java/org/matrix/olm/OlmGroupSessionTest.java
@@ -0,0 +1,443 @@
+/*
+ * Copyright 2016 OpenMarket 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.olm;
+
+import android.content.Context;
+import android.support.test.runner.AndroidJUnit4;
+import android.text.TextUtils;
+import android.util.Log;
+
+import org.junit.BeforeClass;
+import org.junit.FixMethodOrder;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.junit.runners.MethodSorters;
+
+
+import java.io.FileInputStream;
+import java.io.FileNotFoundException;
+import java.io.FileOutputStream;
+import java.io.IOException;
+import java.io.ObjectInputStream;
+import java.io.ObjectOutputStream;
+
+import static android.support.test.InstrumentationRegistry.getInstrumentation;
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertNotNull;
+import static org.junit.Assert.assertTrue;
+
+@RunWith(AndroidJUnit4.class)
+@FixMethodOrder(MethodSorters.NAME_ASCENDING)
+public class OlmGroupSessionTest {
+ private static final String LOG_TAG = "OlmSessionTest";
+ private final String FILE_NAME_SERIAL_OUT_SESSION = "SerialOutGroupSession";
+ private final String FILE_NAME_SERIAL_IN_SESSION = "SerialInGroupSession";
+
+ private static OlmManager mOlmManager;
+ private static OlmOutboundGroupSession mAliceOutboundGroupSession;
+ private static String mAliceSessionIdentifier;
+ private static long mAliceMessageIndex;
+ private static final String CLEAR_MESSAGE1 = "Hello!";
+ private static String mAliceToBobMessage;
+ private static OlmInboundGroupSession mBobInboundGroupSession;
+ private static String mAliceOutboundSessionKey;
+ private static String mBobSessionIdentifier;
+ private static String mBobDecryptedMessage;
+
+ @BeforeClass
+ public static void setUpClass(){
+
+ // enable UTF-8 specific conversion for pre Marshmallow(23) android versions,
+ // due to issue described here: https://github.com/eclipsesource/J2V8/issues/142
+ boolean isSpecificUtf8ConversionEnabled = android.os.Build.VERSION.SDK_INT < 23;
+
+ // load native lib
+ mOlmManager = new OlmManager(isSpecificUtf8ConversionEnabled);
+
+ String version = mOlmManager.getOlmLibVersion();
+ assertNotNull(version);
+ Log.d(LOG_TAG, "## setUpClass(): lib version="+version);
+ }
+
+ /**
+ * Basic test:
+ * - alice creates an outbound group session
+ * - bob creates an inbound group session with alice's outbound session key
+ * - alice encrypts a message with its session
+ * - bob decrypts the encrypted message with its session
+ * - decrypted message is identical to original alice message
+ */
+ @Test
+ public void test01CreateOutboundSession() {
+ // alice creates OUTBOUND GROUP SESSION
+ try {
+ mAliceOutboundGroupSession = new OlmOutboundGroupSession();
+ } catch (OlmException e) {
+ assertTrue("Exception in OlmOutboundGroupSession, Exception code=" + e.getExceptionCode(), false);
+ }
+ }
+
+ @Test
+ public void test02GetOutboundGroupSessionIdentifier() {
+ // test session ID
+ mAliceSessionIdentifier = mAliceOutboundGroupSession.sessionIdentifier();
+ assertNotNull(mAliceSessionIdentifier);
+ assertTrue(mAliceSessionIdentifier.length() > 0);
+ }
+
+ @Test
+ public void test03GetOutboundGroupSessionKey() {
+ // test session Key
+ mAliceOutboundSessionKey = mAliceOutboundGroupSession.sessionKey();
+ assertNotNull(mAliceOutboundSessionKey);
+ assertTrue(mAliceOutboundSessionKey.length() > 0);
+ }
+
+ @Test
+ public void test04GetOutboundGroupMessageIndex() {
+ // test message index before any encryption
+ mAliceMessageIndex = mAliceOutboundGroupSession.messageIndex();
+ assertTrue(0 == mAliceMessageIndex);
+ }
+
+ @Test
+ public void test05OutboundGroupEncryptMessage() {
+ // alice encrypts a message to bob
+ mAliceToBobMessage = mAliceOutboundGroupSession.encryptMessage(CLEAR_MESSAGE1);
+ assertFalse(TextUtils.isEmpty(mAliceToBobMessage));
+
+ // test message index after encryption is incremented
+ mAliceMessageIndex = mAliceOutboundGroupSession.messageIndex();
+ assertTrue(1 == mAliceMessageIndex);
+ }
+
+ @Test
+ public void test06CreateInboundGroupSession() {
+ // bob creates INBOUND GROUP SESSION with alice outbound key
+ try {
+ mBobInboundGroupSession = new OlmInboundGroupSession(mAliceOutboundSessionKey);
+ } catch (OlmException e) {
+ assertTrue("Exception in bob OlmInboundGroupSession, Exception code=" + e.getExceptionCode(), false);
+ }
+ }
+
+ @Test
+ public void test08GetInboundGroupSessionIdentifier() {
+ // check both session identifiers are equals
+ mBobSessionIdentifier = mBobInboundGroupSession.sessionIdentifier();
+ assertFalse(TextUtils.isEmpty(mBobSessionIdentifier));
+ }
+
+ @Test
+ public void test09SessionIdentifiersAreIdentical() {
+ // check both session identifiers are equals: alice vs bob
+ assertTrue(mAliceSessionIdentifier.equals(mBobSessionIdentifier));
+ }
+
+ @Test
+ public void test10InboundDecryptMessage() {
+ // test decrypted message
+ mBobDecryptedMessage = mBobInboundGroupSession.decryptMessage(mAliceToBobMessage);
+ assertFalse(TextUtils.isEmpty(mBobDecryptedMessage));
+ }
+
+ @Test
+ public void test11InboundDecryptedMessageIdentical() {
+ // test decrypted message
+ assertTrue(mBobDecryptedMessage.equals(CLEAR_MESSAGE1));
+ }
+
+ @Test
+ public void test12ReleaseOutboundSession() {
+ // release group sessions
+ mAliceOutboundGroupSession.releaseSession();
+ }
+
+ @Test
+ public void test13ReleaseInboundSession() {
+ // release group sessions
+ mBobInboundGroupSession.releaseSession();
+ }
+
+ @Test
+ public void test14CheckUnreleaseedCount() {
+ assertTrue(0==mAliceOutboundGroupSession.getUnreleasedCount());
+ assertTrue(0==mBobInboundGroupSession.getUnreleasedCount());
+ }
+
+ @Test
+ public void test15SerializeOutboundSession() {
+ OlmOutboundGroupSession outboundGroupSessionRef=null;
+ OlmOutboundGroupSession outboundGroupSessionSerial;
+
+ // create one OUTBOUND GROUP SESSION
+ try {
+ outboundGroupSessionRef = new OlmOutboundGroupSession();
+ } catch (OlmException e) {
+ assertTrue("Exception in OlmOutboundGroupSession, Exception code=" + e.getExceptionCode(), false);
+ }
+ assertNotNull(outboundGroupSessionRef);
+
+
+ // serialize alice session
+ Context context = getInstrumentation().getContext();
+ try {
+ FileOutputStream fileOutput = context.openFileOutput(FILE_NAME_SERIAL_OUT_SESSION, Context.MODE_PRIVATE);
+ ObjectOutputStream objectOutput = new ObjectOutputStream(fileOutput);
+ objectOutput.writeObject(outboundGroupSessionRef);
+ objectOutput.flush();
+ objectOutput.close();
+
+ // deserialize session
+ FileInputStream fileInput = context.openFileInput(FILE_NAME_SERIAL_OUT_SESSION);
+ ObjectInputStream objectInput = new ObjectInputStream(fileInput);
+ outboundGroupSessionSerial = (OlmOutboundGroupSession) objectInput.readObject();
+ assertNotNull(outboundGroupSessionSerial);
+ objectInput.close();
+
+ // get sessions keys
+ String sessionKeyRef = outboundGroupSessionRef.sessionKey();
+ String sessionKeySerial = outboundGroupSessionSerial.sessionKey();
+ assertFalse(TextUtils.isEmpty(sessionKeyRef));
+ assertFalse(TextUtils.isEmpty(sessionKeySerial));
+
+ // session keys comparison
+ assertTrue(sessionKeyRef.equals(sessionKeySerial));
+
+ // get sessions IDs
+ String sessionIdRef = outboundGroupSessionRef.sessionIdentifier();
+ String sessionIdSerial = outboundGroupSessionSerial.sessionIdentifier();
+ assertFalse(TextUtils.isEmpty(sessionIdRef));
+ assertFalse(TextUtils.isEmpty(sessionIdSerial));
+
+ // session IDs comparison
+ assertTrue(sessionIdRef.equals(sessionIdSerial));
+
+ outboundGroupSessionRef.releaseSession();
+ outboundGroupSessionSerial.releaseSession();
+
+ assertTrue(0==outboundGroupSessionRef.getUnreleasedCount());
+ assertTrue(0==outboundGroupSessionSerial.getUnreleasedCount());
+ } catch (FileNotFoundException e) {
+ Log.e(LOG_TAG, "## test15SerializeOutboundSession(): Exception FileNotFoundException Msg=="+e.getMessage());
+ } catch (ClassNotFoundException e) {
+ Log.e(LOG_TAG, "## test15SerializeOutboundSession(): Exception ClassNotFoundException Msg==" + e.getMessage());
+ } catch (OlmException e) {
+ Log.e(LOG_TAG, "## test15SerializeOutboundSession(): Exception OlmException Msg==" + e.getMessage());
+ } catch (IOException e) {
+ Log.e(LOG_TAG, "## test15SerializeOutboundSession(): Exception IOException Msg==" + e.getMessage());
+ } catch (Exception e) {
+ Log.e(LOG_TAG, "## test15SerializeOutboundSession(): Exception Msg==" + e.getMessage());
+ }
+ }
+
+ @Test
+ public void test16SerializeInboundSession() {
+ OlmOutboundGroupSession aliceOutboundGroupSession=null;
+ OlmInboundGroupSession bobInboundGroupSessionRef=null;
+ OlmInboundGroupSession bobInboundGroupSessionSerial;
+
+ // alice creates OUTBOUND GROUP SESSION
+ try {
+ aliceOutboundGroupSession = new OlmOutboundGroupSession();
+ } catch (OlmException e) {
+ assertTrue("Exception in OlmOutboundGroupSession, Exception code=" + e.getExceptionCode(), false);
+ }
+ assertNotNull(aliceOutboundGroupSession);
+
+ // get the session key from the outbound group session
+ String sessionKeyRef = aliceOutboundGroupSession.sessionKey();
+ assertNotNull(sessionKeyRef);
+
+ // bob creates INBOUND GROUP SESSION
+ try {
+ bobInboundGroupSessionRef = new OlmInboundGroupSession(sessionKeyRef);
+ } catch (OlmException e) {
+ assertTrue("Exception in OlmInboundGroupSession, Exception code=" + e.getExceptionCode(), false);
+ }
+ assertNotNull(bobInboundGroupSessionRef);
+
+
+ // serialize alice session
+ Context context = getInstrumentation().getContext();
+ try {
+ FileOutputStream fileOutput = context.openFileOutput(FILE_NAME_SERIAL_IN_SESSION, Context.MODE_PRIVATE);
+ ObjectOutputStream objectOutput = new ObjectOutputStream(fileOutput);
+ objectOutput.writeObject(bobInboundGroupSessionRef);
+ objectOutput.flush();
+ objectOutput.close();
+
+ // deserialize session
+ FileInputStream fileInput = context.openFileInput(FILE_NAME_SERIAL_IN_SESSION);
+ ObjectInputStream objectInput = new ObjectInputStream(fileInput);
+ bobInboundGroupSessionSerial = (OlmInboundGroupSession)objectInput.readObject();
+ assertNotNull(bobInboundGroupSessionSerial);
+ objectInput.close();
+
+ // get sessions IDs
+ String aliceSessionId = aliceOutboundGroupSession.sessionIdentifier();
+ String sessionIdRef = bobInboundGroupSessionRef.sessionIdentifier();
+ String sessionIdSerial = bobInboundGroupSessionSerial.sessionIdentifier();
+ assertFalse(TextUtils.isEmpty(aliceSessionId));
+ assertFalse(TextUtils.isEmpty(sessionIdRef));
+ assertFalse(TextUtils.isEmpty(sessionIdSerial));
+
+ // session IDs comparison
+ assertTrue(aliceSessionId.equals(sessionIdSerial));
+ assertTrue(sessionIdRef.equals(sessionIdSerial));
+
+ aliceOutboundGroupSession.releaseSession();
+ bobInboundGroupSessionRef.releaseSession();
+ bobInboundGroupSessionSerial.releaseSession();
+
+ assertTrue(0==aliceOutboundGroupSession.getUnreleasedCount());
+ assertTrue(0==bobInboundGroupSessionRef.getUnreleasedCount());
+ assertTrue(0==bobInboundGroupSessionSerial.getUnreleasedCount());
+ } catch (FileNotFoundException e) {
+ Log.e(LOG_TAG, "## test16SerializeInboundSession(): Exception FileNotFoundException Msg=="+e.getMessage());
+ } catch (ClassNotFoundException e) {
+ Log.e(LOG_TAG, "## test16SerializeInboundSession(): Exception ClassNotFoundException Msg==" + e.getMessage());
+ } catch (OlmException e) {
+ Log.e(LOG_TAG, "## test16SerializeInboundSession(): Exception OlmException Msg==" + e.getMessage());
+ } catch (IOException e) {
+ Log.e(LOG_TAG, "## test16SerializeInboundSession(): Exception IOException Msg==" + e.getMessage());
+ } catch (Exception e) {
+ Log.e(LOG_TAG, "## test16SerializeInboundSession(): Exception Msg==" + e.getMessage());
+ }
+ }
+
+ /**
+ * Create multiple outbound group sessions and check that session Keys are different.
+ * This test validates random series are provide enough random values.
+ */
+ @Test
+ public void test17MultipleOutboundSession() {
+ OlmOutboundGroupSession outboundGroupSession1;
+ OlmOutboundGroupSession outboundGroupSession2;
+ OlmOutboundGroupSession outboundGroupSession3;
+ OlmOutboundGroupSession outboundGroupSession4;
+ OlmOutboundGroupSession outboundGroupSession5;
+ OlmOutboundGroupSession outboundGroupSession6;
+ OlmOutboundGroupSession outboundGroupSession7;
+ OlmOutboundGroupSession outboundGroupSession8;
+
+ try {
+ outboundGroupSession1 = new OlmOutboundGroupSession();
+ outboundGroupSession2 = new OlmOutboundGroupSession();
+ outboundGroupSession3 = new OlmOutboundGroupSession();
+ outboundGroupSession4 = new OlmOutboundGroupSession();
+ outboundGroupSession5 = new OlmOutboundGroupSession();
+ outboundGroupSession6 = new OlmOutboundGroupSession();
+ outboundGroupSession7 = new OlmOutboundGroupSession();
+ outboundGroupSession8 = new OlmOutboundGroupSession();
+
+ // get the session key from the outbound group sessions
+ String sessionKey1 = outboundGroupSession1.sessionKey();
+ String sessionKey2 = outboundGroupSession2.sessionKey();
+ assertFalse(sessionKey1.equals(sessionKey2));
+
+ String sessionKey3 = outboundGroupSession3.sessionKey();
+ assertFalse(sessionKey2.equals(sessionKey3));
+
+ String sessionKey4 = outboundGroupSession4.sessionKey();
+ assertFalse(sessionKey3.equals(sessionKey4));
+
+ String sessionKey5 = outboundGroupSession5.sessionKey();
+ assertFalse(sessionKey4.equals(sessionKey5));
+
+ String sessionKey6 = outboundGroupSession6.sessionKey();
+ assertFalse(sessionKey5.equals(sessionKey6));
+
+ String sessionKey7 = outboundGroupSession7.sessionKey();
+ assertFalse(sessionKey6.equals(sessionKey7));
+
+ String sessionKey8 = outboundGroupSession8.sessionKey();
+ assertFalse(sessionKey7.equals(sessionKey8));
+
+ // get the session IDs from the outbound group sessions
+ String sessionId1 = outboundGroupSession1.sessionIdentifier();
+ String sessionId2 = outboundGroupSession2.sessionIdentifier();
+ assertFalse(sessionId1.equals(sessionId2));
+
+ String sessionId3 = outboundGroupSession3.sessionKey();
+ assertFalse(sessionId2.equals(sessionId3));
+
+ String sessionId4 = outboundGroupSession4.sessionKey();
+ assertFalse(sessionId3.equals(sessionId4));
+
+ String sessionId5 = outboundGroupSession5.sessionKey();
+ assertFalse(sessionId4.equals(sessionId5));
+
+ String sessionId6 = outboundGroupSession6.sessionKey();
+ assertFalse(sessionId5.equals(sessionId6));
+
+ String sessionId7 = outboundGroupSession7.sessionKey();
+ assertFalse(sessionId6.equals(sessionId7));
+
+ String sessionId8 = outboundGroupSession8.sessionKey();
+ assertFalse(sessionId7.equals(sessionId8));
+
+ outboundGroupSession1.releaseSession();
+ outboundGroupSession2.releaseSession();
+ outboundGroupSession3.releaseSession();
+ outboundGroupSession4.releaseSession();
+ outboundGroupSession5.releaseSession();
+ outboundGroupSession6.releaseSession();
+ outboundGroupSession7.releaseSession();
+ outboundGroupSession8.releaseSession();
+
+ assertTrue(0==outboundGroupSession1.getUnreleasedCount());
+ assertTrue(0==outboundGroupSession2.getUnreleasedCount());
+ assertTrue(0==outboundGroupSession3.getUnreleasedCount());
+ assertTrue(0==outboundGroupSession4.getUnreleasedCount());
+ assertTrue(0==outboundGroupSession5.getUnreleasedCount());
+ assertTrue(0==outboundGroupSession6.getUnreleasedCount());
+ assertTrue(0==outboundGroupSession7.getUnreleasedCount());
+ assertTrue(0==outboundGroupSession8.getUnreleasedCount());
+ } catch (OlmException e) {
+ assertTrue("Exception in OlmOutboundGroupSession, Exception code=" + e.getExceptionCode(), false);
+ }
+ }
+
+ /**
+ * Specific test for the following run time error:
+ * "JNI DETECTED ERROR IN APPLICATION: input is not valid Modified UTF-8: illegal start byte 0xf0 in call to NewStringUTF".<br>
+ * When the msg to decrypt contain emojis, depending on the android platform, the NewStringUTF() behaves differently and
+ * can even crash.
+ * This issue is described in details here: https://github.com/eclipsesource/J2V8/issues/142
+ */
+ @Test
+ public void test18TestBadCharacterCrashInDecrypt() {
+ OlmInboundGroupSession bobInboundGroupSession=null;
+
+ // values taken from a "real life" crash case
+ String sessionKeyRef = "AgAAAAycZE6AekIctJWYxd2AWLOY15YmxZODm/WkgbpWkyycp6ytSp/R+wo84jRrzBNWmv6ySLTZ9R0EDOk9VI2eZyQ6Efdwyo1mAvrWvTkZl9yALPdkOIVHywyG65f1SNiLrnsln3hgsT1vUrISGyKtsljoUgQpr3JDPEhD0ilAi63QBjhnGCW252b+7nF+43rb6O6lwm93LaVwe2341Gdp6EkhTUvetALezEqDOtKN00wVqAbq0RQAnUJIowxHbMswg+FyoR1K1oCjnVEoF23O9xlAn5g1XtuBZP3moJlR2lwsBA";
+ String msgToDecryptWithEmoji = "AwgNEpABpjs+tYF+0y8bWtzAgYAC3N55p5cPJEEiGPU1kxIHSY7f2aG5Fj4wmcsXUkhDv0UePj922kgf+Q4dFsPHKq2aVA93n8DJAQ/FRfcM98B9E6sKCZ/PsCF78uBvF12Aaq9D3pUHBopdd7llUfVq29d5y6ZwX5VDoqV2utsATkKjXYV9CbfZuvvBMQ30ZLjEtyUUBJDY9K4FxEFcULytA/IkVnATTG9ERuLF/yB6ukSFR+iUWRYAmtuOuU0k9BvaqezbGqNoK5Grlkes+dYX6/0yUObumcw9/iAI";
+
+ // bob creates INBOUND GROUP SESSION
+ try {
+ bobInboundGroupSession = new OlmInboundGroupSession(sessionKeyRef);
+ } catch (OlmException e) {
+ assertTrue("Exception in test18TestBadCharacterCrashInDecrypt, Exception code=" + e.getExceptionCode(), false);
+ }
+
+ String decryptedMessage = bobInboundGroupSession.decryptMessage(msgToDecryptWithEmoji);
+ assertNotNull(decryptedMessage);
+ }
+
+}
+
diff --git a/java/android/OlmLibSdk/olm-sdk/src/androidTest/java/org/matrix/olm/OlmSessionTest.java b/java/android/OlmLibSdk/olm-sdk/src/androidTest/java/org/matrix/olm/OlmSessionTest.java
new file mode 100644
index 0000000..1aeb3fb
--- /dev/null
+++ b/java/android/OlmLibSdk/olm-sdk/src/androidTest/java/org/matrix/olm/OlmSessionTest.java
@@ -0,0 +1,641 @@
+/*
+ * Copyright 2016 OpenMarket 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.olm;
+
+import android.content.Context;
+import android.support.test.runner.AndroidJUnit4;
+import android.util.Log;
+
+import org.json.JSONObject;
+import org.junit.BeforeClass;
+import org.junit.FixMethodOrder;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.junit.runners.MethodSorters;
+
+import java.io.FileInputStream;
+import java.io.FileNotFoundException;
+import java.io.FileOutputStream;
+import java.io.IOException;
+import java.io.ObjectInputStream;
+import java.io.ObjectOutputStream;
+
+import static android.support.test.InstrumentationRegistry.getInstrumentation;
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertNotNull;
+import static org.junit.Assert.assertTrue;
+
+@RunWith(AndroidJUnit4.class)
+@FixMethodOrder(MethodSorters.NAME_ASCENDING)
+public class OlmSessionTest {
+ private static final String LOG_TAG = "OlmSessionTest";
+ private final String INVALID_PRE_KEY = "invalid PRE KEY hu hu!";
+ private final String FILE_NAME_SERIAL_SESSION = "SerialSession";
+ private final int ONE_TIME_KEYS_NUMBER = 4;
+
+ private static OlmManager mOlmManager;
+
+ @BeforeClass
+ public static void setUpClass(){
+ // enable UTF-8 specific conversion for pre Marshmallow(23) android versions,
+ // due to issue described here: https://github.com/eclipsesource/J2V8/issues/142
+ boolean isSpecificUtf8ConversionEnabled = android.os.Build.VERSION.SDK_INT < 23;
+
+ // load native lib
+ mOlmManager = new OlmManager(isSpecificUtf8ConversionEnabled);
+
+ String version = mOlmManager.getOlmLibVersion();
+ assertNotNull(version);
+ Log.d(LOG_TAG, "## setUpClass(): lib version="+version);
+ }
+
+ /**
+ * Basic test:
+ * - alice creates an account
+ * - bob creates an account
+ * - alice creates an outbound session with bob (bobIdentityKey & bobOneTimeKey)
+ * - alice encrypts a message with its session
+ * - bob creates an inbound session based on alice's encrypted message
+ * - bob decrypts the encrypted message with its session
+ */
+ @Test
+ public void test01AliceToBob() {
+ final int ONE_TIME_KEYS_NUMBER = 5;
+ String bobIdentityKey = null;
+ String bobOneTimeKey=null;
+ OlmAccount bobAccount = null;
+ OlmAccount aliceAccount = null;
+
+ // ALICE & BOB ACCOUNTS CREATION
+ try {
+ aliceAccount = new OlmAccount();
+ bobAccount = new OlmAccount();
+ } catch (OlmException e) {
+ assertTrue(e.getMessage(),false);
+ }
+
+ // test accounts creation
+ assertTrue(0!=bobAccount.getOlmAccountId());
+ assertTrue(0!=aliceAccount.getOlmAccountId());
+
+ // get bob identity key
+ JSONObject bobIdentityKeysJson = bobAccount.identityKeys();
+ bobIdentityKey = TestHelper.getIdentityKey(bobIdentityKeysJson);
+ assertTrue(null!=bobIdentityKey);
+
+ // get bob one time keys
+ assertTrue(0==bobAccount.generateOneTimeKeys(ONE_TIME_KEYS_NUMBER));
+ JSONObject bobOneTimeKeysJsonObj = bobAccount.oneTimeKeys();
+ bobOneTimeKey = TestHelper.getOneTimeKey(bobOneTimeKeysJsonObj,1);
+ assertNotNull(bobOneTimeKey);
+
+ // CREATE ALICE SESSION
+ OlmSession aliceSession = null;
+ try {
+ aliceSession = new OlmSession();
+ } catch (OlmException e) {
+ assertTrue("Exception Msg="+e.getMessage(), false);
+ }
+ assertTrue(0!=aliceSession.getOlmSessionId());
+
+ // CREATE ALICE OUTBOUND SESSION and encrypt message to bob
+ assertNotNull(aliceSession.initOutboundSessionWithAccount(aliceAccount, bobIdentityKey, bobOneTimeKey));
+ String clearMsg = "Heloo bob , this is alice!";
+ OlmMessage encryptedMsgToBob = aliceSession.encryptMessage(clearMsg);
+ assertNotNull(encryptedMsgToBob);
+ assertNotNull(encryptedMsgToBob.mCipherText);
+ Log.d(LOG_TAG,"## test01AliceToBob(): encryptedMsg="+encryptedMsgToBob.mCipherText);
+
+ // CREATE BOB INBOUND SESSION and decrypt message from alice
+ OlmSession bobSession = null;
+ try {
+ bobSession = new OlmSession();
+ } catch (OlmException e) {
+ assertTrue("Exception Msg="+e.getMessage(), false);
+ }
+ assertTrue(0!=bobSession.getOlmSessionId());
+ assertTrue(0==bobSession.initInboundSessionWithAccount(bobAccount, encryptedMsgToBob.mCipherText));
+ String decryptedMsg = bobSession.decryptMessage(encryptedMsgToBob);
+ assertNotNull(decryptedMsg);
+
+ // MESSAGE COMPARISON: decrypted vs encrypted
+ assertTrue(clearMsg.equals(decryptedMsg));
+
+ // clean objects..
+ assertTrue(0==bobAccount.removeOneTimeKeysForSession(bobSession));
+
+ // release accounts
+ bobAccount.releaseAccount();
+ aliceAccount.releaseAccount();
+ assertTrue(0==bobAccount.getUnreleasedCount());
+ assertTrue(0==aliceAccount.getUnreleasedCount());
+
+ // release sessions
+ bobSession.releaseSession();
+ aliceSession.releaseSession();
+ assertTrue(0==bobSession.getUnreleasedCount());
+ assertTrue(0==aliceSession.getUnreleasedCount());
+ }
+
+
+ /**
+ * Same as test01AliceToBob but with bob who's encrypting messages
+ * to alice and alice decrypt them.<br>
+ * - alice creates an account
+ * - bob creates an account
+ * - alice creates an outbound session with bob (bobIdentityKey & bobOneTimeKey)
+ * - alice encrypts a message with its own session
+ * - bob creates an inbound session based on alice's encrypted message
+ * - bob decrypts the encrypted message with its own session
+ * - bob encrypts messages with its own session
+ * - alice decrypts bob's messages with its own message
+ * - alice encrypts a message
+ * - bob decrypts the encrypted message
+ */
+ @Test
+ public void test02AliceToBobBackAndForth() {
+ String bobIdentityKey;
+ String bobOneTimeKey;
+ OlmAccount aliceAccount = null;
+ OlmAccount bobAccount = null;
+
+ // creates alice & bob accounts
+ try {
+ aliceAccount = new OlmAccount();
+ bobAccount = new OlmAccount();
+ } catch (OlmException e) {
+ assertTrue(e.getMessage(),false);
+ }
+
+ // test accounts creation
+ assertTrue(0!=bobAccount.getOlmAccountId());
+ assertTrue(0!=aliceAccount.getOlmAccountId());
+
+ // get bob identity key
+ JSONObject bobIdentityKeysJson = bobAccount.identityKeys();
+ bobIdentityKey = TestHelper.getIdentityKey(bobIdentityKeysJson);
+ assertTrue(null!=bobIdentityKey);
+
+ // get bob one time keys
+ assertTrue(0==bobAccount.generateOneTimeKeys(ONE_TIME_KEYS_NUMBER));
+ JSONObject bobOneTimeKeysJsonObj = bobAccount.oneTimeKeys();
+ bobOneTimeKey = TestHelper.getOneTimeKey(bobOneTimeKeysJsonObj,1);
+ assertNotNull(bobOneTimeKey);
+
+ // CREATE ALICE SESSION
+ OlmSession aliceSession = null;
+ try {
+ aliceSession = new OlmSession();
+ } catch (OlmException e) {
+ assertTrue("Exception Msg="+e.getMessage(), false);
+ }
+ assertTrue(0!=aliceSession.getOlmSessionId());
+
+ // CREATE ALICE OUTBOUND SESSION and encrypt message to bob
+ assertNotNull(aliceSession.initOutboundSessionWithAccount(aliceAccount, bobIdentityKey, bobOneTimeKey));
+ String helloClearMsg = "Hello I'm Alice!";
+
+ OlmMessage encryptedAliceToBobMsg1 = aliceSession.encryptMessage(helloClearMsg);
+ assertNotNull(encryptedAliceToBobMsg1);
+ assertNotNull(encryptedAliceToBobMsg1.mCipherText);
+
+ // CREATE BOB INBOUND SESSION and decrypt message from alice
+ OlmSession bobSession = null;
+ try {
+ bobSession = new OlmSession();
+ } catch (OlmException e) {
+ assertTrue("Exception Msg="+e.getMessage(), false);
+ }
+ assertTrue(0!=bobSession.getOlmSessionId());
+ assertTrue(0==bobSession.initInboundSessionWithAccount(bobAccount, encryptedAliceToBobMsg1.mCipherText));
+
+ // DECRYPT MESSAGE FROM ALICE
+ String decryptedMsg01 = bobSession.decryptMessage(encryptedAliceToBobMsg1);
+ assertNotNull(decryptedMsg01);
+
+ // MESSAGE COMPARISON: decrypted vs encrypted
+ assertTrue(helloClearMsg.equals(decryptedMsg01));
+
+ // BACK/FORTH MESSAGE COMPARISON
+ String clearMsg1 = "Hello I'm Bob!";
+ String clearMsg2 = "Isn't life grand?";
+ String clearMsg3 = "Let's go to the opera.";
+
+ // bob encrypts messages
+ OlmMessage encryptedMsg1 = bobSession.encryptMessage(clearMsg1);
+ assertNotNull(encryptedMsg1);
+ OlmMessage encryptedMsg2 = bobSession.encryptMessage(clearMsg2);
+ assertNotNull(encryptedMsg2);
+ OlmMessage encryptedMsg3 = bobSession.encryptMessage(clearMsg3);
+ assertNotNull(encryptedMsg3);
+
+ // alice decrypts bob's messages
+ String decryptedMsg1 = aliceSession.decryptMessage(encryptedMsg1);
+ assertNotNull(decryptedMsg1);
+ String decryptedMsg2 = aliceSession.decryptMessage(encryptedMsg2);
+ assertNotNull(decryptedMsg2);
+ String decryptedMsg3 = aliceSession.decryptMessage(encryptedMsg3);
+ assertNotNull(decryptedMsg3);
+
+ // comparison tests
+ assertTrue(clearMsg1.equals(decryptedMsg1));
+ assertTrue(clearMsg2.equals(decryptedMsg2));
+ assertTrue(clearMsg3.equals(decryptedMsg3));
+
+ // and one more from alice to bob
+ clearMsg1 = "another message from Alice to Bob!!";
+ encryptedMsg1 = aliceSession.encryptMessage(clearMsg1);
+ assertNotNull(encryptedMsg1);
+ decryptedMsg1 = bobSession.decryptMessage(encryptedMsg1);
+ assertNotNull(decryptedMsg1);
+ assertTrue(clearMsg1.equals(decryptedMsg1));
+
+ // comparison test
+ assertTrue(clearMsg1.equals(decryptedMsg1));
+
+ // clean objects..
+ assertTrue(0==bobAccount.removeOneTimeKeysForSession(bobSession));
+ bobAccount.releaseAccount();
+ aliceAccount.releaseAccount();
+ assertTrue(0==bobAccount.getUnreleasedCount());
+ assertTrue(0==aliceAccount.getUnreleasedCount());
+
+ bobSession.releaseSession();
+ aliceSession.releaseSession();
+ assertTrue(0==bobSession.getUnreleasedCount());
+ assertTrue(0==aliceSession.getUnreleasedCount());
+ }
+
+
+ @Test
+ public void test03AliceBobSessionId() {
+ // creates alice & bob accounts
+ OlmAccount aliceAccount = null;
+ OlmAccount bobAccount = null;
+ try {
+ aliceAccount = new OlmAccount();
+ bobAccount = new OlmAccount();
+ } catch (OlmException e) {
+ assertTrue(e.getMessage(),false);
+ }
+
+ // test accounts creation
+ assertTrue(0!=bobAccount.getOlmAccountId());
+ assertTrue(0!=aliceAccount.getOlmAccountId());
+
+ // CREATE ALICE SESSION
+
+ OlmSession aliceSession = null;
+ try {
+ aliceSession = new OlmSession();
+ } catch (OlmException e) {
+ assertTrue("Exception Msg="+e.getMessage(), false);
+ }
+ assertTrue(0!=aliceSession.getOlmSessionId());
+
+ // CREATE ALICE SESSION
+ OlmSession bobSession = null;
+ try {
+ bobSession = new OlmSession();
+ } catch (OlmException e) {
+ e.printStackTrace();
+ }
+ assertTrue(0!=bobSession.getOlmSessionId());
+
+ String aliceSessionId = aliceSession.sessionIdentifier();
+ assertNotNull(aliceSessionId);
+
+ String bobSessionId = bobSession.sessionIdentifier();
+ assertNotNull(bobSessionId);
+
+ // must be the same for both ends of the conversation
+ assertTrue(aliceSessionId.equals(bobSessionId));
+
+ aliceAccount.releaseAccount();
+ bobAccount.releaseAccount();
+ assertTrue(0==aliceAccount.getUnreleasedCount());
+ assertTrue(0==bobAccount.getUnreleasedCount());
+
+ bobSession.releaseSession();
+ aliceSession.releaseSession();
+ assertTrue(0==bobSession.getUnreleasedCount());
+ assertTrue(0==aliceSession.getUnreleasedCount());
+ }
+
+ @Test
+ public void test04MatchInboundSession() {
+ OlmAccount aliceAccount=null, bobAccount=null;
+ OlmSession aliceSession = null, bobSession = null;
+
+ // ACCOUNTS CREATION
+ try {
+ aliceAccount = new OlmAccount();
+ bobAccount = new OlmAccount();
+ } catch (OlmException e) {
+ assertTrue(e.getMessage(), false);
+ }
+
+ // CREATE ALICE SESSION
+ try {
+ aliceSession = new OlmSession();
+ bobSession = new OlmSession();
+ } catch (OlmException e) {
+ assertTrue("Exception Msg=" + e.getMessage(), false);
+ }
+
+ // get bob/luke identity key
+ JSONObject bobIdentityKeysJson = bobAccount.identityKeys();
+ JSONObject aliceIdentityKeysJson = aliceAccount.identityKeys();
+ String bobIdentityKey = TestHelper.getIdentityKey(bobIdentityKeysJson);
+ String aliceIdentityKey = TestHelper.getIdentityKey(aliceIdentityKeysJson);
+
+ // get bob/luke one time keys
+ assertTrue(0 == bobAccount.generateOneTimeKeys(ONE_TIME_KEYS_NUMBER));
+ assertTrue(0 == aliceAccount.generateOneTimeKeys(ONE_TIME_KEYS_NUMBER));
+ JSONObject bobOneTimeKeysJsonObj = bobAccount.oneTimeKeys();
+ String bobOneTimeKey1 = TestHelper.getOneTimeKey(bobOneTimeKeysJsonObj, 1);
+
+ // create alice inbound session for bob
+ assertTrue(0==aliceSession.initOutboundSessionWithAccount(aliceAccount, bobIdentityKey, bobOneTimeKey1));
+
+ String aliceClearMsg = "hello helooo to bob!";
+ OlmMessage encryptedAliceToBobMsg1 = aliceSession.encryptMessage(aliceClearMsg);
+ assertFalse(bobSession.matchesInboundSession(encryptedAliceToBobMsg1.mCipherText));
+
+ // init bob session with alice PRE KEY
+ assertTrue(0==bobSession.initInboundSessionWithAccount(bobAccount, encryptedAliceToBobMsg1.mCipherText));
+
+ // test matchesInboundSession() and matchesInboundSessionFrom()
+ assertTrue(bobSession.matchesInboundSession(encryptedAliceToBobMsg1.mCipherText));
+ assertTrue(bobSession.matchesInboundSessionFrom(aliceIdentityKey, encryptedAliceToBobMsg1.mCipherText));
+ // following requires olm native lib new version with https://github.com/matrix-org/olm-backup/commit/7e9f3bebb8390f975a76c0188ce4cb460fe6692e
+ //assertTrue(false==bobSession.matchesInboundSessionFrom(bobIdentityKey, encryptedAliceToBobMsg1.mCipherText));
+
+ // release objects
+ assertTrue(0==bobAccount.removeOneTimeKeysForSession(bobSession));
+ aliceAccount.releaseAccount();
+ bobAccount.releaseAccount();
+ assertTrue(0==aliceAccount.getUnreleasedCount());
+ assertTrue(0==bobAccount.getUnreleasedCount());
+
+ aliceSession.releaseSession();
+ bobSession.releaseSession();
+ assertTrue(0==aliceSession.getUnreleasedCount());
+ assertTrue(0==bobSession.getUnreleasedCount());
+ }
+
+ // ********************************************************
+ // ************* SERIALIZATION TEST ***********************
+ // ********************************************************
+ /**
+ * Same as {@link #test02AliceToBobBackAndForth()}, but alice's session
+ * is serialized and de-serialized before performing the final
+ * comparison (encrypt vs )
+ */
+ @Test
+ public void test05SessionSerialization() {
+ final int ONE_TIME_KEYS_NUMBER = 1;
+ String bobIdentityKey;
+ String bobOneTimeKey;
+ OlmAccount aliceAccount = null;
+ OlmAccount bobAccount = null;
+ OlmSession aliceSessionDeserial = null;
+
+ // creates alice & bob accounts
+ try {
+ aliceAccount = new OlmAccount();
+ bobAccount = new OlmAccount();
+ } catch (OlmException e) {
+ assertTrue(e.getMessage(),false);
+ }
+
+ // test accounts creation
+ assertTrue(0!=bobAccount.getOlmAccountId());
+ assertTrue(0!=aliceAccount.getOlmAccountId());
+
+ // get bob identity key
+ JSONObject bobIdentityKeysJson = bobAccount.identityKeys();
+ bobIdentityKey = TestHelper.getIdentityKey(bobIdentityKeysJson);
+ assertTrue(null!=bobIdentityKey);
+
+ // get bob one time keys
+ assertTrue(0==bobAccount.generateOneTimeKeys(ONE_TIME_KEYS_NUMBER));
+ JSONObject bobOneTimeKeysJsonObj = bobAccount.oneTimeKeys();
+ bobOneTimeKey = TestHelper.getOneTimeKey(bobOneTimeKeysJsonObj,1);
+ assertNotNull(bobOneTimeKey);
+
+ // CREATE ALICE SESSION
+ OlmSession aliceSession = null;
+ try {
+ aliceSession = new OlmSession();
+ } catch (OlmException e) {
+ assertTrue("Exception Msg="+e.getMessage(), false);
+ }
+ assertTrue(0!=aliceSession.getOlmSessionId());
+
+ // CREATE ALICE OUTBOUND SESSION and encrypt message to bob
+ assertNotNull(aliceSession.initOutboundSessionWithAccount(aliceAccount, bobIdentityKey, bobOneTimeKey));
+ String helloClearMsg = "Hello I'm Alice!";
+
+ OlmMessage encryptedAliceToBobMsg1 = aliceSession.encryptMessage(helloClearMsg);
+ assertNotNull(encryptedAliceToBobMsg1);
+ assertNotNull(encryptedAliceToBobMsg1.mCipherText);
+
+ // CREATE BOB INBOUND SESSION and decrypt message from alice
+ OlmSession bobSession = null;
+ try {
+ bobSession = new OlmSession();
+ } catch (OlmException e) {
+ assertTrue("Exception Msg="+e.getMessage(), false);
+ }
+ assertTrue(0!=bobSession.getOlmSessionId());
+ assertTrue(0==bobSession.initInboundSessionWithAccount(bobAccount, encryptedAliceToBobMsg1.mCipherText));
+
+ // DECRYPT MESSAGE FROM ALICE
+ String decryptedMsg01 = bobSession.decryptMessage(encryptedAliceToBobMsg1);
+ assertNotNull(decryptedMsg01);
+
+ // MESSAGE COMPARISON: decrypted vs encrypted
+ assertTrue(helloClearMsg.equals(decryptedMsg01));
+
+ // BACK/FORTH MESSAGE COMPARISON
+ String clearMsg1 = "Hello I'm Bob!";
+ String clearMsg2 = "Isn't life grand?";
+ String clearMsg3 = "Let's go to the opera.";
+
+ // bob encrypts messages
+ OlmMessage encryptedMsg1 = bobSession.encryptMessage(clearMsg1);
+ assertNotNull(encryptedMsg1);
+ OlmMessage encryptedMsg2 = bobSession.encryptMessage(clearMsg2);
+ assertNotNull(encryptedMsg2);
+ OlmMessage encryptedMsg3 = bobSession.encryptMessage(clearMsg3);
+ assertNotNull(encryptedMsg3);
+
+ // serialize alice session
+ Context context = getInstrumentation().getContext();
+ try {
+ FileOutputStream fileOutput = context.openFileOutput(FILE_NAME_SERIAL_SESSION, Context.MODE_PRIVATE);
+ ObjectOutputStream objectOutput = new ObjectOutputStream(fileOutput);
+ objectOutput.writeObject(aliceSession);
+ objectOutput.flush();
+ objectOutput.close();
+
+ // deserialize session
+ FileInputStream fileInput = context.openFileInput(FILE_NAME_SERIAL_SESSION);
+ ObjectInputStream objectInput = new ObjectInputStream(fileInput);
+ aliceSessionDeserial = (OlmSession) objectInput.readObject();
+ objectInput.close();
+
+ // test deserialize return value
+ assertNotNull(aliceSessionDeserial);
+
+ // de-serialized alice session decrypts bob's messages
+ String decryptedMsg1 = aliceSessionDeserial.decryptMessage(encryptedMsg1);
+ assertNotNull(decryptedMsg1);
+ String decryptedMsg2 = aliceSessionDeserial.decryptMessage(encryptedMsg2);
+ assertNotNull(decryptedMsg2);
+ String decryptedMsg3 = aliceSessionDeserial.decryptMessage(encryptedMsg3);
+ assertNotNull(decryptedMsg3);
+
+ // comparison tests
+ assertTrue(clearMsg1.equals(decryptedMsg1));
+ assertTrue(clearMsg2.equals(decryptedMsg2));
+ assertTrue(clearMsg3.equals(decryptedMsg3));
+
+ // clean objects..
+ assertTrue(0==bobAccount.removeOneTimeKeysForSession(bobSession));
+ bobAccount.releaseAccount();
+ aliceAccount.releaseAccount();
+ assertTrue(0==bobAccount.getUnreleasedCount());
+ assertTrue(0==aliceAccount.getUnreleasedCount());
+
+ bobSession.releaseSession();
+ aliceSession.releaseSession();
+ aliceSessionDeserial.releaseSession();
+ assertTrue(0==bobSession.getUnreleasedCount());
+ assertTrue(0==aliceSession.getUnreleasedCount());
+ assertTrue(0==aliceSessionDeserial.getUnreleasedCount());
+ }
+ catch (FileNotFoundException e) {
+ Log.e(LOG_TAG, "## test03SessionSerialization(): Exception FileNotFoundException Msg=="+e.getMessage());
+ }
+ catch (ClassNotFoundException e) {
+ Log.e(LOG_TAG, "## test03SessionSerialization(): Exception ClassNotFoundException Msg==" + e.getMessage());
+ }
+ catch (IOException e) {
+ Log.e(LOG_TAG, "## test03SessionSerialization(): Exception IOException Msg==" + e.getMessage());
+ }
+ /*catch (OlmException e) {
+ Log.e(LOG_TAG, "## test03SessionSerialization(): Exception OlmException Msg==" + e.getMessage());
+ }*/
+ catch (Exception e) {
+ Log.e(LOG_TAG, "## test03SessionSerialization(): Exception Msg==" + e.getMessage());
+ }
+ }
+
+
+ // ****************************************************
+ // *************** SANITY CHECK TESTS *****************
+ // ****************************************************
+
+ @Test
+ public void test06SanityCheckErrors() {
+ final int ONE_TIME_KEYS_NUMBER = 5;
+ OlmAccount bobAccount = null;
+ OlmAccount aliceAccount = null;
+
+ // ALICE & BOB ACCOUNTS CREATION
+ try {
+ aliceAccount = new OlmAccount();
+ bobAccount = new OlmAccount();
+ } catch (OlmException e) {
+ assertTrue(e.getMessage(), false);
+ }
+
+ // get bob identity key
+ JSONObject bobIdentityKeysJson = bobAccount.identityKeys();
+ String bobIdentityKey = TestHelper.getIdentityKey(bobIdentityKeysJson);
+ assertTrue(null != bobIdentityKey);
+
+ // get bob one time keys
+ assertTrue(0 == bobAccount.generateOneTimeKeys(ONE_TIME_KEYS_NUMBER));
+ JSONObject bobOneTimeKeysJsonObj = bobAccount.oneTimeKeys();
+ assertNotNull(bobOneTimeKeysJsonObj);
+ String bobOneTimeKey = TestHelper.getOneTimeKey(bobOneTimeKeysJsonObj,1);
+ assertNotNull(bobOneTimeKey);
+
+ // CREATE ALICE SESSION
+ OlmSession aliceSession = null;
+ try {
+ aliceSession = new OlmSession();
+ } catch (OlmException e) {
+ assertTrue("Exception Msg=" + e.getMessage(), false);
+ }
+
+ // SANITY CHECK TESTS FOR: initOutboundSessionWithAccount()
+ assertTrue(-1==aliceSession.initOutboundSessionWithAccount(null, bobIdentityKey, bobOneTimeKey));
+ assertTrue(-1==aliceSession.initOutboundSessionWithAccount(aliceAccount, null, bobOneTimeKey));
+ assertTrue(-1==aliceSession.initOutboundSessionWithAccount(aliceAccount, bobIdentityKey, null));
+ assertTrue(-1==aliceSession.initOutboundSessionWithAccount(null, null, null));
+
+ // init properly
+ assertTrue(0==aliceSession.initOutboundSessionWithAccount(aliceAccount, bobIdentityKey, bobOneTimeKey));
+
+ // SANITY CHECK TESTS FOR: encryptMessage()
+ assertTrue(null==aliceSession.encryptMessage(null));
+
+ // encrypt properly
+ OlmMessage encryptedMsgToBob = aliceSession.encryptMessage("A message for bob");
+ assertNotNull(encryptedMsgToBob);
+
+ // SANITY CHECK TESTS FOR: initInboundSessionWithAccount()
+ OlmSession bobSession = null;
+ try {
+ bobSession = new OlmSession();
+ assertTrue(-1==bobSession.initInboundSessionWithAccount(null, encryptedMsgToBob.mCipherText));
+ assertTrue(-1==bobSession.initInboundSessionWithAccount(bobAccount, null));
+ assertTrue(-1==bobSession.initInboundSessionWithAccount(bobAccount, INVALID_PRE_KEY));
+ // init properly
+ assertTrue(0==bobSession.initInboundSessionWithAccount(bobAccount, encryptedMsgToBob.mCipherText));
+ } catch (OlmException e) {
+ assertTrue("Exception Msg="+e.getMessage(), false);
+ }
+
+ // SANITY CHECK TESTS FOR: decryptMessage()
+ String decryptedMsg = aliceSession.decryptMessage(null);
+ assertTrue(null==decryptedMsg);
+
+ // SANITY CHECK TESTS FOR: matchesInboundSession()
+ assertTrue(!aliceSession.matchesInboundSession(null));
+
+ // SANITY CHECK TESTS FOR: matchesInboundSessionFrom()
+ assertTrue(!aliceSession.matchesInboundSessionFrom(null,null));
+
+ // release objects
+ assertTrue(0==bobAccount.removeOneTimeKeysForSession(bobSession));
+ aliceAccount.releaseAccount();
+ bobAccount.releaseAccount();
+ assertTrue(0==aliceAccount.getUnreleasedCount());
+ assertTrue(0==bobAccount.getUnreleasedCount());
+
+ aliceSession.releaseSession();
+ bobSession.releaseSession();
+ assertTrue(0==aliceSession.getUnreleasedCount());
+ assertTrue(0==bobSession.getUnreleasedCount());
+ }
+
+}
diff --git a/java/android/OlmLibSdk/olm-sdk/src/androidTest/java/org/matrix/olm/OlmUtilityTest.java b/java/android/OlmLibSdk/olm-sdk/src/androidTest/java/org/matrix/olm/OlmUtilityTest.java
new file mode 100644
index 0000000..3006344
--- /dev/null
+++ b/java/android/OlmLibSdk/olm-sdk/src/androidTest/java/org/matrix/olm/OlmUtilityTest.java
@@ -0,0 +1,124 @@
+/*
+ * Copyright 2016 OpenMarket 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.olm;
+
+import android.support.test.runner.AndroidJUnit4;
+import android.text.TextUtils;
+import android.util.Log;
+
+import org.json.JSONObject;
+import org.junit.BeforeClass;
+import org.junit.FixMethodOrder;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.junit.runners.MethodSorters;
+
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertNotNull;
+import static org.junit.Assert.assertTrue;
+
+@RunWith(AndroidJUnit4.class)
+@FixMethodOrder(MethodSorters.NAME_ASCENDING)
+public class OlmUtilityTest {
+ private static final String LOG_TAG = "OlmAccountTest";
+ private static final int GENERATION_ONE_TIME_KEYS_NUMBER = 50;
+
+ private static OlmManager mOlmManager;
+
+ @BeforeClass
+ public static void setUpClass(){
+ // enable UTF-8 specific conversion for pre Marshmallow(23) android versions,
+ // due to issue described here: https://github.com/eclipsesource/J2V8/issues/142
+ boolean isSpecificUtf8ConversionEnabled = android.os.Build.VERSION.SDK_INT < 23;
+
+ // load native lib
+ mOlmManager = new OlmManager(isSpecificUtf8ConversionEnabled);
+
+ String version = mOlmManager.getOlmLibVersion();
+ assertNotNull(version);
+ Log.d(LOG_TAG, "## setUpClass(): lib version="+version);
+ }
+
+ /**
+ * Test the signing API
+ */
+ @Test
+ public void test01VerifyEd25519Signing() {
+ String fingerPrintKey = null;
+ StringBuffer errorMsg = new StringBuffer();
+ String message = "{\"algorithms\":[\"m.megolm.v1.aes-sha2\",\"m.olm.v1.curve25519-aes-sha2\"],\"device_id\":\"YMBYCWTWCG\",\"keys\":{\"curve25519:YMBYCWTWCG\":\"KZFa5YUXV2EOdhK8dcGMMHWB67stdgAP4+xwiS69mCU\",\"ed25519:YMBYCWTWCG\":\"0cEgQJJqjgtXUGp4ZXQQmh36RAxwxr8HJw2E9v1gvA0\"},\"user_id\":\"@mxBob14774891254276b253f42-f267-43ec-bad9-767142bfea30:localhost:8480\"}";
+ OlmAccount account = null;
+
+ // create account
+ try {
+ account = new OlmAccount();
+ } catch (OlmException e) {
+ assertTrue(e.getMessage(),false);
+ }
+ assertNotNull(account);
+
+ // sign message
+ String messageSignature = account.signMessage(message);
+ assertNotNull(messageSignature);
+
+ // get identities key (finger print key)
+ JSONObject identityKeysJson = account.identityKeys();
+ assertNotNull(identityKeysJson);
+ fingerPrintKey = TestHelper.getFingerprintKey(identityKeysJson);
+ assertTrue("fingerprint key missing",!TextUtils.isEmpty(fingerPrintKey));
+
+ // instantiate utility object
+ OlmUtility utility = new OlmUtility();
+
+ // verify signature
+ errorMsg.append("init with anything");
+ boolean isVerified = utility.verifyEd25519Signature(messageSignature, fingerPrintKey, message, errorMsg);
+ assertTrue(isVerified);
+ assertTrue(String.valueOf(errorMsg).isEmpty());
+
+ // check a bad signature is detected => errorMsg = BAD_MESSAGE_MAC
+ String badSignature = "Bad signature Bad signature Bad signature..";
+ isVerified = utility.verifyEd25519Signature(badSignature, fingerPrintKey, message, errorMsg);
+ assertFalse(isVerified);
+ assertFalse(String.valueOf(errorMsg).isEmpty());
+
+ // check bad fingerprint size => errorMsg = INVALID_BASE64
+ String badSizeFingerPrintKey = fingerPrintKey.substring(fingerPrintKey.length()/2);
+ isVerified = utility.verifyEd25519Signature(messageSignature, badSizeFingerPrintKey, message, errorMsg);
+ assertFalse(isVerified);
+ assertFalse(String.valueOf(errorMsg).isEmpty());
+
+ utility.releaseUtility();
+ assertTrue(0==utility.getUnreleasedCount());
+
+ account.releaseAccount();
+ assertTrue(0==account.getUnreleasedCount());
+ }
+
+
+ @Test
+ public void test02sha256() {
+ OlmUtility utility = new OlmUtility();
+ String msgToHash = "The quick brown fox jumps over the lazy dog";
+
+ String hashResult = utility.sha256(msgToHash);
+ assertFalse(TextUtils.isEmpty(hashResult));
+
+ utility.releaseUtility();
+ assertTrue(0==utility.getUnreleasedCount());
+ }
+}
diff --git a/java/android/OlmLibSdk/olm-sdk/src/androidTest/java/org/matrix/olm/TestHelper.java b/java/android/OlmLibSdk/olm-sdk/src/androidTest/java/org/matrix/olm/TestHelper.java
new file mode 100644
index 0000000..363ab7a
--- /dev/null
+++ b/java/android/OlmLibSdk/olm-sdk/src/androidTest/java/org/matrix/olm/TestHelper.java
@@ -0,0 +1,90 @@
+/*
+ * Copyright 2016 OpenMarket 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.olm;
+
+import org.json.JSONException;
+import org.json.JSONObject;
+
+import java.util.Iterator;
+
+import static org.junit.Assert.assertNotNull;
+import static org.junit.Assert.assertTrue;
+
+/**
+ * Helper class providing helper methods used in the Olm Android SDK unit tests.
+ */
+public class TestHelper {
+
+ /**
+ * Return the identity key {@link OlmAccount#JSON_KEY_IDENTITY_KEY} from the JSON object.
+ * @param aIdentityKeysObj JSON result of {@link OlmAccount#identityKeys()}
+ * @return identity key string if operation succeed, null otherwise
+ */
+ static public String getIdentityKey(JSONObject aIdentityKeysObj){
+ String idKey = null;
+
+ try {
+ idKey = aIdentityKeysObj.getString(OlmAccount.JSON_KEY_IDENTITY_KEY);
+ } catch (JSONException e) {
+ assertTrue("Exception MSg=" + e.getMessage(), false);
+ }
+ return idKey;
+ }
+
+ /**
+ * Return the fingerprint key {@link OlmAccount#JSON_KEY_FINGER_PRINT_KEY} from the JSON object.
+ * @param aIdentityKeysObj JSON result of {@link OlmAccount#identityKeys()}
+ * @return fingerprint key string if operation succeed, null otherwise
+ */
+ static public String getFingerprintKey(JSONObject aIdentityKeysObj){
+ String fingerprintKey = null;
+
+ try {
+ fingerprintKey = aIdentityKeysObj.getString(OlmAccount.JSON_KEY_FINGER_PRINT_KEY);
+ } catch (JSONException e) {
+ assertTrue("Exception MSg=" + e.getMessage(), false);
+ }
+ return fingerprintKey;
+ }
+
+ /**
+ * Return the first one time key from the JSON object.
+ * @param aIdentityKeysObj JSON result of {@link OlmAccount#oneTimeKeys()}
+ * @param aKeyPosition the position of the key to be retrieved
+ * @return one time key string if operation succeed, null otherwise
+ */
+ static public String getOneTimeKey(JSONObject aIdentityKeysObj, int aKeyPosition) {
+ String firstOneTimeKey = null;
+ int i=0;
+
+ try {
+ JSONObject generatedKeys = aIdentityKeysObj.getJSONObject(OlmAccount.JSON_KEY_ONE_TIME_KEY);
+ assertNotNull(OlmAccount.JSON_KEY_ONE_TIME_KEY + " object is missing", generatedKeys);
+
+ Iterator<String> generatedKeysIt = generatedKeys.keys();
+ while(i<aKeyPosition) {
+ if (generatedKeysIt.hasNext()) {
+ firstOneTimeKey = generatedKeys.getString(generatedKeysIt.next());
+ i++;
+ }
+ }
+ } catch (JSONException e) {
+ assertTrue("Exception Msg=" + e.getMessage(), false);
+ }
+ return firstOneTimeKey;
+ }
+}