package mobisocial.musubi.service; import java.util.Arrays; import java.util.Date; import java.util.HashSet; import java.util.Random; import mobisocial.crypto.IBHashedIdentity.Authority; import mobisocial.crypto.IBIdentity; import mobisocial.musubi.encoding.MessageEncoder; import mobisocial.musubi.encoding.OutgoingMessage; import mobisocial.musubi.identity.UnverifiedIdentityProvider; import mobisocial.musubi.model.MEncodedMessage; import mobisocial.musubi.model.MIdentity; import mobisocial.musubi.model.MSignatureUserKey; import mobisocial.musubi.model.helpers.EncodedMessageManager; import mobisocial.musubi.model.helpers.IdentitiesManager; import mobisocial.musubi.model.helpers.MessageTransportManager; import mobisocial.musubi.model.helpers.UserKeyManager; import mobisocial.musubi.util.Util; import mobisocial.test.MockMusubiAppContext; import android.content.Intent; import android.database.sqlite.SQLiteOpenHelper; import android.os.IBinder; import android.test.ServiceTestCase; public class AMQPServiceTest extends ServiceTestCase<AMQPService> { UnverifiedIdentityProvider mIdp = new UnverifiedIdentityProvider(); public AMQPServiceTest() { super(AMQPService.class); } @Override protected void setUp() throws Exception { super.setUp(); setContext(new MockMusubiAppContext(getContext())); } public void testStartable() { Intent startIntent = new Intent(); startIntent.setClass(getContext(), AMQPService.class); startService(startIntent); } public void testDefaultDatabaseBindable() { Intent startIntent = new Intent(); startIntent.setClass(getContext(), AMQPService.class); bindService(startIntent); } public void testCustomDatabaseBindable() { Intent startIntent = new Intent(); startIntent.setClass(getContext(), AMQPService.class); IBinder service = bindService(startIntent); @SuppressWarnings("unused") AMQPService amqpService = ((AMQPService.AMQPServiceBinder)service).getService(); } boolean waitForConnection(AMQPService amqpService, long millis) throws InterruptedException { long start = new Date().getTime(); for(;;) { if(new Date().getTime() - start > millis) break; //success if(amqpService.isConnectionReady()) return true; Thread.sleep(1000); } return false; } public void testConnectSuccessful() throws InterruptedException { Intent startIntent = new Intent(); startIntent.setClass(getContext(), AMQPService.class); IBinder service = bindService(startIntent); AMQPService amqpService = ((AMQPService.AMQPServiceBinder)service).getService(); //allow 20 seconds to connect assertTrue(waitForConnection(amqpService, 20 * 1000)); } Random r = new Random(); final HashSet<String> usedNames = new HashSet<String>(); String randomUniquePrincipal() { for(;;) { int length = r.nextInt(16); StringBuilder sb = new StringBuilder(); for(int i = 0; i < length; ++i) { char c = (char) ('a' + r.nextInt('z' - 'a')); sb.append(c); } sb.append("@gmail.com"); String result = sb.toString(); if(usedNames.contains(result)) continue; usedNames.add(result); return result; } } public void testSendAtoBwithBFirst() throws Exception { MockMusubiAppContext c0 = new MockMusubiAppContext(getContext()); //set up identity and signature user secret final SQLiteOpenHelper dbh0 = c0.getDatabaseSource(); final IBIdentity me = new IBIdentity(Authority.Email, randomUniquePrincipal(), 0); long myDeviceName0 = r.nextLong(); IdentitiesManager idm0 = new IdentitiesManager(dbh0); MessageTransportManager mtm0 = new MessageTransportManager(dbh0, mIdp.getEncryptionScheme(), mIdp.getSignatureScheme(), myDeviceName0); MIdentity myid0 = mtm0.addClaimedIdentity(me); myid0.owned_ = true; myid0.principal_ = me.principal_; idm0.updateIdentity(myid0); UserKeyManager sm0 = new UserKeyManager(mIdp.getEncryptionScheme(), mIdp.getSignatureScheme(), dbh0); MSignatureUserKey sigKey = new MSignatureUserKey(); sigKey.identityId_ = myid0.id_; IBIdentity required_key = me.at(mtm0.getSignatureTime(myid0)); sigKey.userKey_ = mIdp.syncGetSignatureKey(required_key).key_; sigKey.when_ = required_key.temporalFrame_; sm0.insertSignatureUserKey(sigKey); setContext(c0); Intent startIntent0 = new Intent(); startIntent0.setClass(c0, AMQPService.class); IBinder service0 = bindService(startIntent0); AMQPService amqpService0 = ((AMQPService.AMQPServiceBinder)service0).getService(); @SuppressWarnings("unused") EncodedMessageManager emm0 = new EncodedMessageManager(dbh0); //pick the other identity final IBIdentity you = new IBIdentity(Authority.Email, randomUniquePrincipal(), 0); //set up the background service instance AMQPListener listener = new AMQPListener(getContext(), mIdp, you); //make up a message OutgoingMessage om = new OutgoingMessage(); om.data_ = new byte[32]; r.nextBytes(om.data_); om.app_ = new byte[32]; r.nextBytes(om.app_); om.fromIdentity_ = idm0.getOwnedIdentities().get(1); om.recipients_ = new MIdentity[] { mtm0.addClaimedIdentity(you) }; om.hash_ = Util.sha256(om.data_); //encode the message, implicitly inserts it, so amqp should now be able //to get access to it MessageEncoder encoder = new MessageEncoder(mtm0); MEncodedMessage encodedOutgoing; try { encodedOutgoing = encoder.processMessage(om); } catch (Exception e) { throw e; } c0.getContentResolver().notifyChange(MusubiService.PREPARED_ENCODED, null); //allow 20 seconds to connect and it will automatically send messages //when the connection is established assertTrue(waitForConnection(amqpService0, 20 * 1000)); MEncodedMessage encodedIncoming = listener.waitForNthMessage(1, 20 * 1000); assertNotNull(encodedIncoming); assertTrue(Arrays.equals(encodedOutgoing.encoded_, encodedIncoming.encoded_)); listener.destroy(); } public void testSendAtoBwithAFirst() throws Exception { UnverifiedIdentityProvider idp = new UnverifiedIdentityProvider(); MockMusubiAppContext c0 = new MockMusubiAppContext(getContext()); //set up identity and signature user secret final SQLiteOpenHelper dbh0 = c0.getDatabaseSource(); final IBIdentity me = new IBIdentity(Authority.Email, randomUniquePrincipal(), 0); long myDeviceName0 = r.nextLong(); IdentitiesManager idm0 = new IdentitiesManager(dbh0); MessageTransportManager mtm0 = new MessageTransportManager(dbh0, idp.getEncryptionScheme(), idp.getSignatureScheme(), myDeviceName0); MIdentity myid0 = mtm0.addClaimedIdentity(me); myid0.owned_ = true; myid0.principal_ = me.principal_; idm0.updateIdentity(myid0); UserKeyManager sm0 = new UserKeyManager(mIdp.getEncryptionScheme(), mIdp.getSignatureScheme(), dbh0); MSignatureUserKey sigKey = new MSignatureUserKey(); sigKey.identityId_ = myid0.id_; IBIdentity required_key = me.at(mtm0.getSignatureTime(myid0)); sigKey.userKey_ = idp.syncGetSignatureKey(required_key).key_; sigKey.when_ = required_key.temporalFrame_; sm0.insertSignatureUserKey(sigKey); setContext(c0); Intent startIntent0 = new Intent(); startIntent0.setClass(c0, AMQPService.class); IBinder service0 = bindService(startIntent0); AMQPService amqpService0 = ((AMQPService.AMQPServiceBinder)service0).getService(); @SuppressWarnings("unused") EncodedMessageManager emm0 = new EncodedMessageManager(dbh0); //pick the other identity final IBIdentity you = new IBIdentity(Authority.Email, randomUniquePrincipal(), 0); //make up a message OutgoingMessage om = new OutgoingMessage(); om.data_ = new byte[32]; r.nextBytes(om.data_); om.app_ = new byte[32]; r.nextBytes(om.app_); om.fromIdentity_ = idm0.getOwnedIdentities().get(1); om.recipients_ = new MIdentity[] { mtm0.addClaimedIdentity(you) }; om.hash_ = Util.sha256(om.data_); //encode the message, implicitly inserts it, so amqp should now be able //to get access to it MessageEncoder encoder = new MessageEncoder(mtm0); MEncodedMessage encodedOutgoing; try { encodedOutgoing = encoder.processMessage(om); } catch (Exception e) { throw e; } c0.getContentResolver().notifyChange(MusubiService.PREPARED_ENCODED, null); //allow 20 seconds to connect and it will automatically send messages //when the connection is established assertTrue(waitForConnection(amqpService0, 20 * 1000)); //set up the background service instance AMQPListener listener = new AMQPListener(getContext(), idp, you); MEncodedMessage encodedIncoming = listener.waitForNthMessage(1, 20 * 1000); assertNotNull(encodedIncoming); assertTrue(Arrays.equals(encodedOutgoing.encoded_, encodedIncoming.encoded_)); listener.destroy(); } public void testExactlyTwoMessages() throws Exception { UnverifiedIdentityProvider idp = new UnverifiedIdentityProvider(); MockMusubiAppContext c0 = new MockMusubiAppContext(getContext()); //set up identity and signature user secret final SQLiteOpenHelper dbh0 = c0.getDatabaseSource(); final IBIdentity me = new IBIdentity(Authority.Email, randomUniquePrincipal(), 0); long myDeviceName0 = r.nextLong(); IdentitiesManager idm0 = new IdentitiesManager(dbh0); MessageTransportManager mtm0 = new MessageTransportManager(dbh0, idp.getEncryptionScheme(), idp.getSignatureScheme(), myDeviceName0); MIdentity myid0 = mtm0.addClaimedIdentity(me); myid0.owned_ = true; myid0.principal_ = me.principal_; idm0.updateIdentity(myid0); UserKeyManager sm0 = new UserKeyManager(mIdp.getEncryptionScheme(), mIdp.getSignatureScheme(), dbh0); MSignatureUserKey sigKey = new MSignatureUserKey(); sigKey.identityId_ = myid0.id_; IBIdentity required_key = me.at(mtm0.getSignatureTime(myid0)); sigKey.userKey_ = idp.syncGetSignatureKey(required_key).key_; sigKey.when_ = required_key.temporalFrame_; sm0.insertSignatureUserKey(sigKey); setContext(c0); Intent startIntent0 = new Intent(); startIntent0.setClass(c0, AMQPService.class); IBinder service0 = bindService(startIntent0); AMQPService amqpService0 = ((AMQPService.AMQPServiceBinder)service0).getService(); @SuppressWarnings("unused") EncodedMessageManager emm0 = new EncodedMessageManager(dbh0); //pick the other identity final IBIdentity you = new IBIdentity(Authority.Email, randomUniquePrincipal(), 0); //make up a message OutgoingMessage om = new OutgoingMessage(); om.data_ = new byte[32]; r.nextBytes(om.data_); om.app_ = new byte[32]; r.nextBytes(om.app_); om.fromIdentity_ = idm0.getOwnedIdentities().get(1); om.recipients_ = new MIdentity[] { mtm0.addClaimedIdentity(you) }; om.hash_ = Util.sha256(om.data_); //encode the message, implicitly inserts it MessageEncoder encoder = new MessageEncoder(mtm0); MEncodedMessage encodedOutgoing; try { encodedOutgoing = encoder.processMessage(om); } catch (Exception e) { throw e; } //encoded message available c0.getContentResolver().notifyChange(MusubiService.PREPARED_ENCODED, null); //allow 20 seconds to connect and it will automatically send messages //when the connection is established assertTrue(waitForConnection(amqpService0, 20 * 1000)); //set up the background service instance AMQPListener listener = new AMQPListener(getContext(), idp, you); MEncodedMessage encodedIncoming = listener.waitForNthMessage(1, 20 * 1000); assertNotNull(encodedIncoming); assertTrue(Arrays.equals(encodedOutgoing.encoded_, encodedIncoming.encoded_)); //make up a message OutgoingMessage omB = new OutgoingMessage(); omB.data_ = new byte[32]; r.nextBytes(omB.data_); omB.app_ = new byte[32]; r.nextBytes(om.app_); omB.fromIdentity_ = idm0.getOwnedIdentities().get(1); omB.recipients_ = new MIdentity[] { mtm0.addClaimedIdentity(you) }; omB.hash_ = Util.sha256(omB.data_); //encode the message, implicitly inserts it, so amqp should now be able //to get access to it MEncodedMessage encodedOutgoingB; try { encodedOutgoingB = encoder.processMessage(omB); } catch (Exception e) { throw e; } c0.getContentResolver().notifyChange(MusubiService.PREPARED_ENCODED, null); MEncodedMessage encodedIncomingB = listener.waitForNthMessage(2, 20 * 1000); assertNotNull(encodedIncomingB); assertTrue(Arrays.equals(encodedOutgoingB.encoded_, encodedIncomingB.encoded_)); listener.destroy(); } }