package uk.ac.cam.db538.securesms.storage; import java.io.IOException; import java.util.ArrayList; import uk.ac.cam.db538.securesms.CustomAsserts; import uk.ac.cam.db538.securesms.Encryption; import uk.ac.cam.db538.securesms.Encryption.WrongKeyException; import uk.ac.cam.db538.securesms.data.LowLevel; import uk.ac.cam.db538.securesms.storage.Conversation; import uk.ac.cam.db538.securesms.storage.Storage; import uk.ac.cam.db538.securesms.storage.StorageFileException; import uk.ac.cam.db538.securesms.storage.MessageData; import uk.ac.cam.db538.securesms.storage.MessageDataPart; import junit.framework.TestCase; public class MessagePart_Test extends TestCase { protected void setUp() throws Exception { super.setUp(); Common.clearStorageFile(); } protected void tearDown() throws Exception { super.tearDown(); } private boolean deliveredPart = true; private String messageBody = "Testing body"; private byte[] messageBodyData = messageBody.getBytes(); private short messageBodyLength = (short) messageBodyData.length; private long indexNext = 12L; private void setData(MessageDataPart msgPart) { msgPart.setDeliveredPart(deliveredPart); msgPart.setMessageBody(messageBodyData); msgPart.setIndexNext(indexNext); } private void checkData(MessageDataPart msgPart) { assertEquals(deliveredPart, msgPart.getDeliveredPart()); assertEquals(msgPart.getMessageBody().length, messageBodyLength); CustomAsserts.assertArrayEquals(msgPart.getMessageBody(), messageBodyData); assertEquals(indexNext, msgPart.getIndexNext()); } public void testConstruction() throws StorageFileException, IOException { // Check that it is assigned to a proper message, etc... Conversation conv = Conversation.createConversation(); MessageData msg = MessageData.createMessageData(conv); ArrayList<MessageDataPart> list = new ArrayList<MessageDataPart>(2); MessageDataPart msgPart1 = MessageDataPart.createMessageDataPart(); MessageDataPart msgPart2 = MessageDataPart.createMessageDataPart(); list.add(msgPart1); list.add(msgPart2); msg.assignMessageDataParts(list); assertSame(msg.getFirstMessageDataPart(), msgPart1); assertNotSame(msg.getFirstMessageDataPart(), msgPart2); assertTrue(Common.checkStructure()); // Check that the data is saved properly setData(msgPart1); msgPart1.saveToFile(); long index = msgPart1.getEntryIndex(); // force it to be re-read MessageDataPart.forceClearCache(); msgPart1 = MessageDataPart.getMessageDataPart(index); checkData(msgPart1); } public void testIndices() throws StorageFileException, IOException { // INDICES OUT OF BOUNDS MessageDataPart msgPart = MessageDataPart.createMessageDataPart(); // indexNext try { msgPart.setIndexNext(0x0100000000L); assertTrue(false); } catch (IndexOutOfBoundsException ex) { } try { msgPart.setIndexNext(-1L); assertTrue(false); } catch (IndexOutOfBoundsException ex) { } } public void testCreateData() throws StorageFileException, IOException, WrongKeyException { // compute expected values byte flags = 0; flags |= (deliveredPart) ? 0x80 : 0x00; // generate data MessageDataPart msgPart = MessageDataPart.createMessageDataPart(); setData(msgPart); msgPart.saveToFile(); // get the generated data byte[] dataEncrypted = Storage.getDatabase().getEntry(msgPart.getEntryIndex()); // chunk length assertEquals(dataEncrypted.length, Storage.CHUNK_SIZE); // decrypt the encoded part byte[] dataPlain = Encryption.decryptSymmetric(dataEncrypted, Encryption.retreiveEncryptionKey()); // check the data assertEquals(dataPlain[0], flags); assertEquals(LowLevel.getUnsignedShort(dataPlain, 1), messageBodyLength); CustomAsserts.assertArrayEquals(LowLevel.cutData(dataPlain, 3, messageBodyLength), messageBodyData); assertEquals(LowLevel.getUnsignedInt(dataPlain, Storage.ENCRYPTED_ENTRY_SIZE - 4), indexNext); } public void testParseData() throws StorageFileException, IOException { MessageDataPart msgPart = MessageDataPart.createMessageDataPart(); long index = msgPart.getEntryIndex(); // prepare stuff byte flags = 0; flags |= (deliveredPart) ? 0x80 : 0x00; // create plain data byte[] dataPlain = new byte[Storage.ENCRYPTED_ENTRY_SIZE]; dataPlain[0] = flags; System.arraycopy(LowLevel.getBytesUnsignedShort(messageBodyLength), 0, dataPlain, 1, 2); System.arraycopy(LowLevel.wrapData(messageBodyData, 140), 0, dataPlain, 3, 140); System.arraycopy(LowLevel.getBytesUnsignedInt(indexNext), 0, dataPlain, Storage.ENCRYPTED_ENTRY_SIZE - 4, 4); // encrypt it byte[] dataEncrypted = Encryption.encryptSymmetric(dataPlain, Encryption.retreiveEncryptionKey()); // inject it into the file Storage.getDatabase().setEntry(index, dataEncrypted); // have it parsed MessageDataPart.forceClearCache(); msgPart = MessageDataPart.getMessageDataPart(index); // check the indices checkData(msgPart); } }