diff --git a/app/src/test/java/com/etesync/syncadapter/journalmanager/AuthenticatorTest.java b/app/src/test/java/com/etesync/syncadapter/journalmanager/AuthenticatorTest.java deleted file mode 100644 index a37e2751..00000000 --- a/app/src/test/java/com/etesync/syncadapter/journalmanager/AuthenticatorTest.java +++ /dev/null @@ -1,54 +0,0 @@ -/* - * Copyright © 2013 – 2015 Ricki Hirner (bitfire web engineering). - * All rights reserved. This program and the accompanying materials - * are made available under the terms of the GNU Public License v3.0 - * which accompanies this distribution, and is available at - * http://www.gnu.org/licenses/gpl.html - */ - -package com.etesync.syncadapter.journalmanager; - -import com.etesync.syncadapter.HttpClient; -import com.etesync.syncadapter.utils.Base64; - -import org.apache.commons.codec.Charsets; -import org.junit.After; -import org.junit.Before; -import org.junit.Test; - -import java.io.IOException; - -import okhttp3.HttpUrl; -import okhttp3.OkHttpClient; - -import static org.junit.Assert.assertEquals; -import static org.junit.Assert.assertNotEquals; - -public class AuthenticatorTest { - private OkHttpClient httpClient; - private HttpUrl remote; - - @Before - public void setUp() throws IOException { - httpClient = HttpClient.create(null); - remote = HttpUrl.parse("http://localhost:8000"); // FIXME: hardcode for now, should make configureable - } - - @After - public void tearDown() throws IOException { - } - - @Test - public void testAuthToken() throws IOException, Exceptions.HttpException { - JournalAuthenticator journalAuthenticator = new JournalAuthenticator(httpClient, remote); - String authToken = journalAuthenticator.getAuthToken(Helpers.USER, Helpers.PASSWORD); - assertNotEquals(authToken.length(), 0); - } - - @Test(expected=Exceptions.UnauthorizedException.class) - public void testNoUser() throws Exceptions.IntegrityException, Exceptions.VersionTooNewException, IOException, Exceptions.HttpException { - JournalAuthenticator journalAuthenticator = new JournalAuthenticator(httpClient, remote); - String authToken = journalAuthenticator.getAuthToken(Helpers.USER, "BadPassword"); - assertNotEquals(authToken.length(), 0); - } -} diff --git a/app/src/test/java/com/etesync/syncadapter/journalmanager/AuthenticatorTest.kt b/app/src/test/java/com/etesync/syncadapter/journalmanager/AuthenticatorTest.kt new file mode 100644 index 00000000..58a9ca2d --- /dev/null +++ b/app/src/test/java/com/etesync/syncadapter/journalmanager/AuthenticatorTest.kt @@ -0,0 +1,58 @@ +/* + * Copyright © 2013 – 2015 Ricki Hirner (bitfire web engineering). + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the GNU Public License v3.0 + * which accompanies this distribution, and is available at + * http://www.gnu.org/licenses/gpl.html + */ + +package com.etesync.syncadapter.journalmanager + +import com.etesync.syncadapter.HttpClient +import com.etesync.syncadapter.utils.Base64 + +import org.apache.commons.codec.Charsets +import org.junit.After +import org.junit.Before +import org.junit.Test + +import java.io.IOException + +import okhttp3.HttpUrl +import okhttp3.OkHttpClient + +import org.junit.Assert.assertEquals +import org.junit.Assert.assertNotEquals + +class AuthenticatorTest { + private var httpClient: OkHttpClient? = null + private var remote: HttpUrl? = null + + @Before + @Throws(IOException::class) + fun setUp() { + httpClient = HttpClient.create(null) + remote = HttpUrl.parse("http://localhost:8000") // FIXME: hardcode for now, should make configureable + } + + @After + @Throws(IOException::class) + fun tearDown() { + } + + @Test + @Throws(IOException::class, Exceptions.HttpException::class) + fun testAuthToken() { + val journalAuthenticator = JournalAuthenticator(httpClient!!, remote!!) + val authToken = journalAuthenticator.getAuthToken(Helpers.USER, Helpers.PASSWORD) + assertNotEquals(authToken!!.length.toLong(), 0) + } + + @Test(expected = Exceptions.UnauthorizedException::class) + @Throws(Exceptions.IntegrityException::class, Exceptions.VersionTooNewException::class, IOException::class, Exceptions.HttpException::class) + fun testNoUser() { + val journalAuthenticator = JournalAuthenticator(httpClient!!, remote!!) + val authToken = journalAuthenticator.getAuthToken(Helpers.USER, "BadPassword") + assertNotEquals(authToken!!.length.toLong(), 0) + } +} diff --git a/app/src/test/java/com/etesync/syncadapter/journalmanager/EncryptionTest.java b/app/src/test/java/com/etesync/syncadapter/journalmanager/EncryptionTest.java deleted file mode 100644 index 5ea6018f..00000000 --- a/app/src/test/java/com/etesync/syncadapter/journalmanager/EncryptionTest.java +++ /dev/null @@ -1,87 +0,0 @@ -/* - * Copyright © 2013 – 2015 Ricki Hirner (bitfire web engineering). - * All rights reserved. This program and the accompanying materials - * are made available under the terms of the GNU Public License v3.0 - * which accompanies this distribution, and is available at - * http://www.gnu.org/licenses/gpl.html - */ - -package com.etesync.syncadapter.journalmanager; - -import com.etesync.syncadapter.utils.Base64; - -import org.apache.commons.codec.Charsets; -import org.junit.After; -import org.junit.Before; -import org.junit.Test; -import org.spongycastle.util.encoders.Hex; - -import java.io.IOException; - -import static org.junit.Assert.assertArrayEquals; -import static org.junit.Assert.assertEquals; - -public class EncryptionTest { - @Before - public void setUp() throws IOException { - } - - @After - public void tearDown() throws IOException { - } - - @Test - public void testDerivePassword() { - String key = Crypto.deriveKey(Helpers.USER, Helpers.PASSWORD); - assertEquals(key, Helpers.keyBase64); - } - - @Test - public void testCryptoV1() throws Exceptions.IntegrityException, Exceptions.GenericCryptoException { - Crypto.CryptoManager cryptoManager = new Crypto.CryptoManager(1, Helpers.keyBase64, "TestSaltShouldBeJournalId"); - - String clearText = "This Is Some Test Cleartext."; - byte[] cipher = cryptoManager.encrypt(clearText.getBytes(Charsets.UTF_8)); - assertEquals(clearText, new String(cryptoManager.decrypt(cipher), Charsets.UTF_8)); - - String expected = "Lz+HUFzh1HdjxuGdQrBwBG1IzHT0ug6mO8fwePSbXtc="; - assertEquals(expected, Base64.encodeToString(cryptoManager.hmac("Some test data".getBytes(Charsets.UTF_8)), Base64.NO_WRAP)); - } - - @Test - public void testCryptoV2() throws Exceptions.IntegrityException, Exceptions.GenericCryptoException { - Crypto.CryptoManager cryptoManager = new Crypto.CryptoManager(2, Helpers.keyBase64, "TestSaltShouldBeJournalId"); - - String clearText = "This Is Some Test Cleartext."; - byte[] cipher = cryptoManager.encrypt(clearText.getBytes(Charsets.UTF_8)); - assertEquals(clearText, new String(cryptoManager.decrypt(cipher), Charsets.UTF_8)); - - String expected = "XQ/A0gentOaE98R9wzf3zEIAHj4OH1GF8J4C6JiJupo="; - assertEquals(expected, Base64.encodeToString(cryptoManager.hmac("Some test data".getBytes(Charsets.UTF_8)), Base64.NO_WRAP)); - } - - @Test(expected=Exceptions.VersionTooNewException.class) - public void testCryptoVersionTooNew() throws Exceptions.IntegrityException, Exceptions.VersionTooNewException { - new Crypto.CryptoManager(120, Helpers.keyBase64, "TestSaltShouldBeJournalId"); - } - - @Test(expected=Exceptions.IntegrityException.class) - public void testCryptoVersionOutOfRange() throws Exceptions.IntegrityException, Exceptions.VersionTooNewException { - new Crypto.CryptoManager(999, Helpers.keyBase64, "TestSaltShouldBeJournalId"); - } - - @Test - public void testAsymCrypto() throws Exceptions.IntegrityException, Exceptions.GenericCryptoException { - Crypto.AsymmetricKeyPair keyPair = Crypto.generateKeyPair(); - Crypto.AsymmetricCryptoManager cryptoManager = new Crypto.AsymmetricCryptoManager(keyPair); - - byte[] clearText = "This Is Some Test Cleartext.".getBytes(Charsets.UTF_8); - byte[] cipher = cryptoManager.encrypt(keyPair.getPublicKey(), clearText); - byte[] clearText2 = cryptoManager.decrypt(cipher); - assertArrayEquals(clearText, clearText2); - - // Mostly for coverage. Make sure it's the expected sha256 value. - assertEquals("ca978112ca1bbdcafac231b39a23dc4da786eff8147c4e72b9807785afee48bb", - Hex.toHexString(Crypto.AsymmetricCryptoManager.Companion.getKeyFingerprint("a".getBytes(Charsets.UTF_8))).toLowerCase()); - } -} diff --git a/app/src/test/java/com/etesync/syncadapter/journalmanager/EncryptionTest.kt b/app/src/test/java/com/etesync/syncadapter/journalmanager/EncryptionTest.kt new file mode 100644 index 00000000..1ca9de6f --- /dev/null +++ b/app/src/test/java/com/etesync/syncadapter/journalmanager/EncryptionTest.kt @@ -0,0 +1,94 @@ +/* + * Copyright © 2013 – 2015 Ricki Hirner (bitfire web engineering). + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the GNU Public License v3.0 + * which accompanies this distribution, and is available at + * http://www.gnu.org/licenses/gpl.html + */ + +package com.etesync.syncadapter.journalmanager + +import com.etesync.syncadapter.utils.Base64 + +import org.apache.commons.codec.Charsets +import org.junit.After +import org.junit.Before +import org.junit.Test +import org.spongycastle.util.encoders.Hex + +import java.io.IOException + +import org.junit.Assert.assertArrayEquals +import org.junit.Assert.assertEquals + +class EncryptionTest { + @Before + @Throws(IOException::class) + fun setUp() { + } + + @After + @Throws(IOException::class) + fun tearDown() { + } + + @Test + fun testDerivePassword() { + val key = Crypto.deriveKey(Helpers.USER, Helpers.PASSWORD) + assertEquals(key, Helpers.keyBase64) + } + + @Test + @Throws(Exceptions.IntegrityException::class, Exceptions.GenericCryptoException::class) + fun testCryptoV1() { + val cryptoManager = Crypto.CryptoManager(1, Helpers.keyBase64, "TestSaltShouldBeJournalId") + + val clearText = "This Is Some Test Cleartext." + val cipher = cryptoManager.encrypt(clearText.toByteArray(Charsets.UTF_8)) + assertEquals(clearText, String(cryptoManager.decrypt(cipher!!)!!, Charsets.UTF_8)) + + val expected = "Lz+HUFzh1HdjxuGdQrBwBG1IzHT0ug6mO8fwePSbXtc=" + assertEquals(expected, Base64.encodeToString(cryptoManager.hmac("Some test data".toByteArray(Charsets.UTF_8)), Base64.NO_WRAP)) + } + + @Test + @Throws(Exceptions.IntegrityException::class, Exceptions.GenericCryptoException::class) + fun testCryptoV2() { + val cryptoManager = Crypto.CryptoManager(2, Helpers.keyBase64, "TestSaltShouldBeJournalId") + + val clearText = "This Is Some Test Cleartext." + val cipher = cryptoManager.encrypt(clearText.toByteArray(Charsets.UTF_8)) + assertEquals(clearText, String(cryptoManager.decrypt(cipher!!)!!, Charsets.UTF_8)) + + val expected = "XQ/A0gentOaE98R9wzf3zEIAHj4OH1GF8J4C6JiJupo=" + assertEquals(expected, Base64.encodeToString(cryptoManager.hmac("Some test data".toByteArray(Charsets.UTF_8)), Base64.NO_WRAP)) + } + + @Test(expected = Exceptions.VersionTooNewException::class) + @Throws(Exceptions.IntegrityException::class, Exceptions.VersionTooNewException::class) + fun testCryptoVersionTooNew() { + Crypto.CryptoManager(120, Helpers.keyBase64, "TestSaltShouldBeJournalId") + } + + @Test(expected = Exceptions.IntegrityException::class) + @Throws(Exceptions.IntegrityException::class, Exceptions.VersionTooNewException::class) + fun testCryptoVersionOutOfRange() { + Crypto.CryptoManager(999, Helpers.keyBase64, "TestSaltShouldBeJournalId") + } + + @Test + @Throws(Exceptions.IntegrityException::class, Exceptions.GenericCryptoException::class) + fun testAsymCrypto() { + val keyPair = Crypto.generateKeyPair() + val cryptoManager = Crypto.AsymmetricCryptoManager(keyPair!!) + + val clearText = "This Is Some Test Cleartext.".toByteArray(Charsets.UTF_8) + val cipher = cryptoManager.encrypt(keyPair.publicKey, clearText) + val clearText2 = cryptoManager.decrypt(cipher!!) + assertArrayEquals(clearText, clearText2) + + // Mostly for coverage. Make sure it's the expected sha256 value. + assertEquals("ca978112ca1bbdcafac231b39a23dc4da786eff8147c4e72b9807785afee48bb", + Hex.toHexString(Crypto.AsymmetricCryptoManager.getKeyFingerprint("a".toByteArray(Charsets.UTF_8))).toLowerCase()) + } +} diff --git a/app/src/test/java/com/etesync/syncadapter/journalmanager/Helpers.java b/app/src/test/java/com/etesync/syncadapter/journalmanager/Helpers.java deleted file mode 100644 index 364e4375..00000000 --- a/app/src/test/java/com/etesync/syncadapter/journalmanager/Helpers.java +++ /dev/null @@ -1,8 +0,0 @@ -package com.etesync.syncadapter.journalmanager; - -class Helpers { - static final String USER = "test@localhost"; - static final String USER2 = "test2@localhost"; - static final String PASSWORD = "SomePassword"; - static final String keyBase64 = "Gpn6j6WJ/9JJbVkWhmEfZjlqSps5rwEOzjUOO0rqufvb4vtT4UfRgx0uMivuGwjF7/8Y1z1glIASX7Oz/4l2jucgf+lAzg2oTZFodWkXRZCDmFa7c9a8/04xIs7koFmUH34Rl9XXW6V2/GDVigQhQU8uWnrGo795tupoNQMbtB8RgMX5GyuxR55FvcybHpYBbwrDIsKvXcBxWFEscdNU8zyeq3yjvDo/W/y24dApW3mnNo7vswoL2rpkZj3dqw=="; -} diff --git a/app/src/test/java/com/etesync/syncadapter/journalmanager/Helpers.kt b/app/src/test/java/com/etesync/syncadapter/journalmanager/Helpers.kt new file mode 100644 index 00000000..53e49e5a --- /dev/null +++ b/app/src/test/java/com/etesync/syncadapter/journalmanager/Helpers.kt @@ -0,0 +1,8 @@ +package com.etesync.syncadapter.journalmanager + +internal object Helpers { + val USER = "test@localhost" + val USER2 = "test2@localhost" + val PASSWORD = "SomePassword" + val keyBase64 = "Gpn6j6WJ/9JJbVkWhmEfZjlqSps5rwEOzjUOO0rqufvb4vtT4UfRgx0uMivuGwjF7/8Y1z1glIASX7Oz/4l2jucgf+lAzg2oTZFodWkXRZCDmFa7c9a8/04xIs7koFmUH34Rl9XXW6V2/GDVigQhQU8uWnrGo795tupoNQMbtB8RgMX5GyuxR55FvcybHpYBbwrDIsKvXcBxWFEscdNU8zyeq3yjvDo/W/y24dApW3mnNo7vswoL2rpkZj3dqw==" +} diff --git a/app/src/test/java/com/etesync/syncadapter/journalmanager/ServiceTest.java b/app/src/test/java/com/etesync/syncadapter/journalmanager/ServiceTest.java deleted file mode 100644 index c09ae06a..00000000 --- a/app/src/test/java/com/etesync/syncadapter/journalmanager/ServiceTest.java +++ /dev/null @@ -1,271 +0,0 @@ -/* - * Copyright © 2013 – 2015 Ricki Hirner (bitfire web engineering). - * All rights reserved. This program and the accompanying materials - * are made available under the terms of the GNU Public License v3.0 - * which accompanies this distribution, and is available at - * http://www.gnu.org/licenses/gpl.html - */ - -package com.etesync.syncadapter.journalmanager; - -import com.etesync.syncadapter.App; -import com.etesync.syncadapter.HttpClient; -import com.etesync.syncadapter.model.CollectionInfo; - -import org.apache.commons.codec.Charsets; -import org.junit.After; -import org.junit.Before; -import org.junit.Test; - -import java.io.IOException; -import java.util.LinkedList; -import java.util.List; - -import okhttp3.HttpUrl; -import okhttp3.MediaType; -import okhttp3.OkHttpClient; -import okhttp3.Request; -import okhttp3.RequestBody; -import okhttp3.Response; -import okio.BufferedSink; - -import static org.junit.Assert.assertArrayEquals; -import static org.junit.Assert.assertEquals; -import static org.junit.Assert.assertNotNull; -import static org.junit.Assert.assertNull; - -public class ServiceTest { - private OkHttpClient httpClient; - private HttpUrl remote; - private String authToken; - - @Before - public void setUp() throws Exception { - httpClient = HttpClient.create(null); - remote = HttpUrl.parse("http://localhost:8000"); // FIXME: hardcode for now, should make configureable - JournalAuthenticator journalAuthenticator = new JournalAuthenticator(httpClient, remote); - authToken = journalAuthenticator.getAuthToken(Helpers.USER, Helpers.PASSWORD); - - httpClient = HttpClient.create(null, App.log, null, authToken); - - /* Reset */ - Request request = new Request.Builder() - .post(new RequestBody() { - @Override - public MediaType contentType() { - return null; - } - - @Override - public void writeTo(BufferedSink sink) throws IOException { - - } - }) - .url(remote.newBuilder().addEncodedPathSegments("reset/").build()) - .build(); - Response response = httpClient.newCall(request).execute(); - if (!response.isSuccessful()) { - throw new Exception("Failed resetting"); - } - } - - @After - public void tearDown() throws IOException { - } - - @Test - public void testSyncSimple() throws IOException, Exceptions.HttpException, Exceptions.GenericCryptoException, Exceptions.IntegrityException { - Exception caught; - JournalManager journalManager = new JournalManager(httpClient, remote); - CollectionInfo info = CollectionInfo.defaultForServiceType(CollectionInfo.Type.ADDRESS_BOOK); - info.uid = JournalManager.Journal.genUid(); - info.displayName = "Test"; - Crypto.CryptoManager crypto = new Crypto.CryptoManager(info.version, Helpers.keyBase64, info.uid); - JournalManager.Journal journal = new JournalManager.Journal(crypto, info.toJson(), info.uid); - journalManager.create(journal); - - // Try pushing the same journal (uid clash) - try { - caught = null; - journalManager.create(journal); - } catch (Exceptions.HttpException e) { - caught = e; - } - assertNotNull(caught); - - List journals = journalManager.list(); - assertEquals(journals.size(), 1); - CollectionInfo info2 = CollectionInfo.fromJson(journals.get(0).getContent(crypto)); - assertEquals(info2.displayName, info.displayName); - - // Update journal - info.displayName = "Test 2"; - journal = new JournalManager.Journal(crypto, info.toJson(), info.uid); - journalManager.update(journal); - - journals = journalManager.list(); - assertEquals(journals.size(), 1); - info2 = CollectionInfo.fromJson(journals.get(0).getContent(crypto)); - assertEquals(info2.displayName, info.displayName); - - // Delete journal - journalManager.delete(journal); - - journals = journalManager.list(); - assertEquals(journals.size(), 0); - - // Bad HMAC - info.uid = JournalManager.Journal.genUid(); - journal = new JournalManager.Journal(crypto, info.toJson(), info.uid); - info.displayName = "Test 3"; - //// We assume this doesn't update the hmac. - journal.setContent(crypto, info.toJson()); - journalManager.create(journal); - - try { - caught = null; - for (JournalManager.Journal journal1 : journalManager.list()) { - Crypto.CryptoManager crypto1 = new Crypto.CryptoManager(info.version, Helpers.keyBase64, journal1.getUid()); - journal1.verify(crypto1); - } - } catch (Exceptions.IntegrityException e) { - caught = e; - } - assertNotNull(caught); - } - - - @Test - public void testSyncEntry() throws IOException, Exceptions.HttpException, Exceptions.GenericCryptoException, Exceptions.IntegrityException { - Exception caught; - JournalManager journalManager = new JournalManager(httpClient, remote); - CollectionInfo info = CollectionInfo.defaultForServiceType(CollectionInfo.Type.ADDRESS_BOOK); - info.uid = JournalManager.Journal.genUid(); - info.displayName = "Test"; - Crypto.CryptoManager crypto = new Crypto.CryptoManager(info.version, Helpers.keyBase64, info.uid); - JournalManager.Journal journal = new JournalManager.Journal(crypto, info.toJson(), info.uid); - journalManager.create(journal); - - JournalEntryManager journalEntryManager = new JournalEntryManager(httpClient, remote, info.uid); - JournalEntryManager.Entry previousEntry = null; - JournalEntryManager.Entry entry = new JournalEntryManager.Entry(); - entry.update(crypto, "Content", previousEntry); - - List entries = new LinkedList<>(); - - entries.add(entry); - journalEntryManager.create(entries, null); - previousEntry = entry; - - entries.clear(); - JournalEntryManager.Entry entry2 = new JournalEntryManager.Entry(); - entry2.update(crypto, "Content", previousEntry); - entries.add(entry2); - - // Pushing a correct entries without the last parameter - try { - caught = null; - journalEntryManager.create(entries, null); - } catch (Exceptions.HttpException e) { - caught = e; - } - assertNotNull(caught); - - // Adding a second entry - journalEntryManager.create(entries, previousEntry.getUid()); - previousEntry = entry2; - - entries.clear(); - entries.add(entry); - entries.add(entry2); - - // Check last works: - entries = journalEntryManager.list(crypto, entry.getUid(), 0); - assertEquals(entries.size(), 1); - entries = journalEntryManager.list(crypto, entry2.getUid(), 0); - assertEquals(entries.size(), 0); - - // Corrupt the journal and verify we catch it - entries.clear(); - entry2 = new JournalEntryManager.Entry(); - entry2.update(crypto, "Content", null); - entries.add(entry2); - - journalEntryManager.create(entries, previousEntry.getUid()); - - try { - caught = null; - journalEntryManager.list(crypto, null, 0); - } catch (Exceptions.IntegrityException e) { - caught = e; - } - assertNotNull(caught); - } - - - @Test - public void testUserInfo() throws IOException, Exceptions.HttpException, Exceptions.GenericCryptoException, Exceptions.IntegrityException { - Crypto.CryptoManager cryptoManager = new Crypto.CryptoManager(Constants.CURRENT_VERSION, Helpers.keyBase64, "userInfo"); - UserInfoManager.UserInfo userInfo, userInfo2; - UserInfoManager manager = new UserInfoManager(httpClient, remote); - - // Get when there's nothing - userInfo = manager.get(Helpers.USER); - assertNull(userInfo); - - // Create - userInfo = UserInfoManager.UserInfo.generate(cryptoManager, Helpers.USER); - manager.create(userInfo); - - // Get - userInfo2 = manager.get(Helpers.USER); - assertNotNull(userInfo2); - assertArrayEquals(userInfo.getContent(cryptoManager), userInfo2.getContent(cryptoManager)); - - // Update - userInfo.setContent(cryptoManager, "test".getBytes(Charsets.UTF_8)); - manager.update(userInfo); - userInfo2 = manager.get(Helpers.USER); - assertNotNull(userInfo2); - assertArrayEquals(userInfo.getContent(cryptoManager), userInfo2.getContent(cryptoManager)); - - // Delete - manager.delete(userInfo); - userInfo = manager.get(Helpers.USER); - assertNull(userInfo); - } - - - @Test - public void testJournalMember() throws IOException, Exceptions.HttpException, Exceptions.GenericCryptoException, Exceptions.IntegrityException { - Exception caught; - JournalManager journalManager = new JournalManager(httpClient, remote); - CollectionInfo info = CollectionInfo.defaultForServiceType(CollectionInfo.Type.ADDRESS_BOOK); - info.uid = JournalManager.Journal.genUid(); - info.displayName = "Test"; - Crypto.CryptoManager crypto = new Crypto.CryptoManager(info.version, Helpers.keyBase64, info.uid); - JournalManager.Journal journal = new JournalManager.Journal(crypto, info.toJson(), info.uid); - journalManager.create(journal); - - assertEquals(journalManager.listMembers(journal).size(), 0); - - // Test inviting ourselves - JournalManager.Member member = new JournalManager.Member(Helpers.USER, "test".getBytes(Charsets.UTF_8)); - try { - caught = null; - journalManager.addMember(journal, member); - } catch (Exceptions.HttpException e) { - caught = e; - } - assertNotNull(caught); - - JournalManager.Member member2 = new JournalManager.Member(Helpers.USER2, "test".getBytes(Charsets.UTF_8)); - journalManager.addMember(journal, member2); - assertEquals(journalManager.listMembers(journal).size(), 1); - - // Uninviting user - journalManager.deleteMember(journal, member2); - - assertEquals(journalManager.listMembers(journal).size(), 0); - } -} diff --git a/app/src/test/java/com/etesync/syncadapter/journalmanager/ServiceTest.kt b/app/src/test/java/com/etesync/syncadapter/journalmanager/ServiceTest.kt new file mode 100644 index 00000000..5ba11cfa --- /dev/null +++ b/app/src/test/java/com/etesync/syncadapter/journalmanager/ServiceTest.kt @@ -0,0 +1,282 @@ +/* + * Copyright © 2013 – 2015 Ricki Hirner (bitfire web engineering). + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the GNU Public License v3.0 + * which accompanies this distribution, and is available at + * http://www.gnu.org/licenses/gpl.html + */ + +package com.etesync.syncadapter.journalmanager + +import com.etesync.syncadapter.App +import com.etesync.syncadapter.HttpClient +import com.etesync.syncadapter.model.CollectionInfo + +import org.apache.commons.codec.Charsets +import org.junit.After +import org.junit.Before +import org.junit.Test + +import java.io.IOException +import java.util.LinkedList + +import okhttp3.HttpUrl +import okhttp3.MediaType +import okhttp3.OkHttpClient +import okhttp3.Request +import okhttp3.RequestBody +import okhttp3.Response +import okio.BufferedSink + +import org.junit.Assert.assertArrayEquals +import org.junit.Assert.assertEquals +import org.junit.Assert.assertNotNull +import org.junit.Assert.assertNull + +class ServiceTest { + private var httpClient: OkHttpClient? = null + private var remote: HttpUrl? = null + private var authToken: String? = null + + @Before + @Throws(Exception::class) + fun setUp() { + httpClient = HttpClient.create(null) + remote = HttpUrl.parse("http://localhost:8000") // FIXME: hardcode for now, should make configureable + val journalAuthenticator = JournalAuthenticator(httpClient!!, remote!!) + authToken = journalAuthenticator.getAuthToken(Helpers.USER, Helpers.PASSWORD) + + httpClient = HttpClient.create(null, App.log, null, authToken!!) + + /* Reset */ + val request = Request.Builder() + .post(object : RequestBody() { + override fun contentType(): MediaType? { + return null + } + + @Throws(IOException::class) + override fun writeTo(sink: BufferedSink) { + + } + }) + .url(remote!!.newBuilder().addEncodedPathSegments("reset/").build()) + .build() + val response = httpClient!!.newCall(request).execute() + if (!response.isSuccessful) { + throw Exception("Failed resetting") + } + } + + @After + @Throws(IOException::class) + fun tearDown() { + } + + @Test + @Throws(IOException::class, Exceptions.HttpException::class, Exceptions.GenericCryptoException::class, Exceptions.IntegrityException::class) + fun testSyncSimple() { + var caught: Exception? + val journalManager = JournalManager(httpClient!!, remote!!) + val info = CollectionInfo.defaultForServiceType(CollectionInfo.Type.ADDRESS_BOOK) + info.uid = JournalManager.Journal.genUid() + info.displayName = "Test" + val crypto = Crypto.CryptoManager(info.version, Helpers.keyBase64, info.uid) + var journal = JournalManager.Journal(crypto, info.toJson(), info.uid) + journalManager.create(journal) + + // Try pushing the same journal (uid clash) + try { + caught = null + journalManager.create(journal) + } catch (e: Exceptions.HttpException) { + caught = e + } + + assertNotNull(caught) + + var journals: List = journalManager.list() + assertEquals(journals.size.toLong(), 1) + var info2 = CollectionInfo.fromJson(journals[0].getContent(crypto)) + assertEquals(info2.displayName, info.displayName) + + // Update journal + info.displayName = "Test 2" + journal = JournalManager.Journal(crypto, info.toJson(), info.uid) + journalManager.update(journal) + + journals = journalManager.list() + assertEquals(journals.size.toLong(), 1) + info2 = CollectionInfo.fromJson(journals[0].getContent(crypto)) + assertEquals(info2.displayName, info.displayName) + + // Delete journal + journalManager.delete(journal) + + journals = journalManager.list() + assertEquals(journals.size.toLong(), 0) + + // Bad HMAC + info.uid = JournalManager.Journal.genUid() + journal = JournalManager.Journal(crypto, info.toJson(), info.uid) + info.displayName = "Test 3" + //// We assume this doesn't update the hmac. + journal.setContent(crypto, info.toJson()) + journalManager.create(journal) + + try { + caught = null + for (journal1 in journalManager.list()) { + val crypto1 = Crypto.CryptoManager(info.version, Helpers.keyBase64, journal1.uid!!) + journal1.verify(crypto1) + } + } catch (e: Exceptions.IntegrityException) { + caught = e + } + + assertNotNull(caught) + } + + + @Test + @Throws(IOException::class, Exceptions.HttpException::class, Exceptions.GenericCryptoException::class, Exceptions.IntegrityException::class) + fun testSyncEntry() { + var caught: Exception? + val journalManager = JournalManager(httpClient!!, remote!!) + val info = CollectionInfo.defaultForServiceType(CollectionInfo.Type.ADDRESS_BOOK) + info.uid = JournalManager.Journal.genUid() + info.displayName = "Test" + val crypto = Crypto.CryptoManager(info.version, Helpers.keyBase64, info.uid) + val journal = JournalManager.Journal(crypto, info.toJson(), info.uid) + journalManager.create(journal) + + val journalEntryManager = JournalEntryManager(httpClient!!, remote!!, info.uid) + var previousEntry: JournalEntryManager.Entry? = null + val entry = JournalEntryManager.Entry() + entry.update(crypto, "Content", previousEntry) + + var entries: MutableList = LinkedList() + var retEntries: List + + entries.add(entry) + journalEntryManager.create(entries, null) + previousEntry = entry + + entries.clear() + var entry2 = JournalEntryManager.Entry() + entry2.update(crypto, "Content", previousEntry) + entries.add(entry2) + + // Pushing a correct entries without the last parameter + try { + caught = null + journalEntryManager.create(entries, null) + } catch (e: Exceptions.HttpException) { + caught = e + } + + assertNotNull(caught) + + // Adding a second entry + journalEntryManager.create(entries, previousEntry.uid) + previousEntry = entry2 + + entries.clear() + entries.add(entry) + entries.add(entry2) + + // Check last works: + retEntries = journalEntryManager.list(crypto, entry.uid, 0) + assertEquals(retEntries.size.toLong(), 1) + retEntries = journalEntryManager.list(crypto, entry2.uid, 0) + assertEquals(retEntries.size.toLong(), 0) + + // Corrupt the journal and verify we catch it + entries.clear() + entry2 = JournalEntryManager.Entry() + entry2.update(crypto, "Content", null) + entries.add(entry2) + + journalEntryManager.create(entries, previousEntry.uid) + + try { + caught = null + journalEntryManager.list(crypto, null, 0) + } catch (e: Exceptions.IntegrityException) { + caught = e + } + + assertNotNull(caught) + } + + + @Test + @Throws(IOException::class, Exceptions.HttpException::class, Exceptions.GenericCryptoException::class, Exceptions.IntegrityException::class) + fun testUserInfo() { + val cryptoManager = Crypto.CryptoManager(Constants.CURRENT_VERSION, Helpers.keyBase64, "userInfo") + var userInfo: UserInfoManager.UserInfo? + var userInfo2: UserInfoManager.UserInfo? + val manager = UserInfoManager(httpClient!!, remote!!) + + // Get when there's nothing + userInfo = manager[Helpers.USER] + assertNull(userInfo) + + // Create + userInfo = UserInfoManager.UserInfo.generate(cryptoManager, Helpers.USER) + manager.create(userInfo) + + // Get + userInfo2 = manager[Helpers.USER] + assertNotNull(userInfo2) + assertArrayEquals(userInfo.getContent(cryptoManager), userInfo2!!.getContent(cryptoManager)) + + // Update + userInfo.setContent(cryptoManager, "test".toByteArray(Charsets.UTF_8)) + manager.update(userInfo) + userInfo2 = manager[Helpers.USER] + assertNotNull(userInfo2) + assertArrayEquals(userInfo.getContent(cryptoManager), userInfo2!!.getContent(cryptoManager)) + + // Delete + manager.delete(userInfo) + userInfo = manager[Helpers.USER] + assertNull(userInfo) + } + + + @Test + @Throws(IOException::class, Exceptions.HttpException::class, Exceptions.GenericCryptoException::class, Exceptions.IntegrityException::class) + fun testJournalMember() { + var caught: Exception? + val journalManager = JournalManager(httpClient!!, remote!!) + val info = CollectionInfo.defaultForServiceType(CollectionInfo.Type.ADDRESS_BOOK) + info.uid = JournalManager.Journal.genUid() + info.displayName = "Test" + val crypto = Crypto.CryptoManager(info.version, Helpers.keyBase64, info.uid) + val journal = JournalManager.Journal(crypto, info.toJson(), info.uid) + journalManager.create(journal) + + assertEquals(journalManager.listMembers(journal).size.toLong(), 0) + + // Test inviting ourselves + val member = JournalManager.Member(Helpers.USER, "test".toByteArray(Charsets.UTF_8)) + try { + caught = null + journalManager.addMember(journal, member) + } catch (e: Exceptions.HttpException) { + caught = e + } + + assertNotNull(caught) + + val member2 = JournalManager.Member(Helpers.USER2, "test".toByteArray(Charsets.UTF_8)) + journalManager.addMember(journal, member2) + assertEquals(journalManager.listMembers(journal).size.toLong(), 1) + + // Uninviting user + journalManager.deleteMember(journal, member2) + + assertEquals(journalManager.listMembers(journal).size.toLong(), 0) + } +}