blob: e977aa77190cf0b731d119797bff78468cbe7bcf [file] [log] [blame]
/*
* Copyright (C) 2015 The Android Open Source Project
*
* 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 com.android.messaging.datamodel.action;
import android.content.ContentProvider;
import android.content.pm.ProviderInfo;
import android.database.Cursor;
import android.net.Uri;
import android.test.suitebuilder.annotation.SmallTest;
import android.text.TextUtils;
import com.android.messaging.BugleTestCase;
import com.android.messaging.FakeContext;
import com.android.messaging.FakeFactory;
import com.android.messaging.datamodel.BugleDatabaseOperations;
import com.android.messaging.datamodel.DataModel;
import com.android.messaging.datamodel.DatabaseHelper;
import com.android.messaging.datamodel.DatabaseHelper.ConversationColumns;
import com.android.messaging.datamodel.DatabaseWrapper;
import com.android.messaging.datamodel.FakeDataModel;
import com.android.messaging.datamodel.MediaScratchFileProvider;
import com.android.messaging.datamodel.MessagingContentProvider;
import com.android.messaging.datamodel.action.ActionTestHelpers.StubActionService;
import com.android.messaging.datamodel.action.ActionTestHelpers.StubActionService.StubActionServiceCallLog;
import com.android.messaging.datamodel.action.ReadDraftDataAction.ReadDraftDataActionListener;
import com.android.messaging.datamodel.data.MessageData;
import com.android.messaging.datamodel.data.MessagePartData;
import com.android.messaging.datamodel.data.ParticipantData;
import com.android.messaging.util.ContentType;
import org.mockito.Mock;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.util.ArrayList;
@SmallTest
public class ReadWriteDraftMessageActionTest extends BugleTestCase {
@Mock ReadDraftDataActionListener mockListener;
// TODO: Add test cases
// 1. Make sure drafts can include attachments and multiple parts
// 2. Make sure attachments get cleaned up appropriately
// 3. Make sure messageId and partIds not reused (currently each draft is a new message).
public void testWriteDraft() {
final String draftMessage = "draftMessage";
final long threadId = 1234567;
final boolean senderBlocked = false;
final String participantNumber = "5551234567";
final DatabaseWrapper db = DataModel.get().getDatabase();
final String conversationId = getOrCreateConversation(db, participantNumber, threadId,
senderBlocked);
final String selfId = getOrCreateSelfId(db);
// Should clear/stub DB
final ArrayList<StubActionServiceCallLog> calls = mService.getCalls();
final MessageData message = MessageData.createDraftSmsMessage(conversationId, selfId,
draftMessage);
WriteDraftMessageAction.writeDraftMessage(conversationId, message);
assertEquals("Failed to start service once for action", calls.size(), 1);
assertTrue("Action not SaveDraftMessageAction",
calls.get(0).action instanceof WriteDraftMessageAction);
final Action save = calls.get(0).action;
final Object result = save.executeAction();
assertTrue("Expect row number string as result", result instanceof String);
final String messageId = (String) result;
// Should check DB
final MessageData actual = BugleDatabaseOperations.readMessage(db, messageId);
assertNotNull("Database missing draft", actual);
assertEquals("Draft text changed", draftMessage, actual.getMessageText());
}
private static String getOrCreateSelfId(final DatabaseWrapper db) {
db.beginTransaction();
final String selfId = BugleDatabaseOperations.getOrCreateParticipantInTransaction(db,
ParticipantData.getSelfParticipant(ParticipantData.DEFAULT_SELF_SUB_ID));
db.setTransactionSuccessful();
db.endTransaction();
return selfId;
}
private static String getOrCreateConversation(final DatabaseWrapper db,
final String participantNumber, final long threadId, final boolean senderBlocked) {
final ArrayList<ParticipantData> participants =
new ArrayList<ParticipantData>();
participants.add(ParticipantData.getFromRawPhoneBySystemLocale(participantNumber));
final String conversationId = BugleDatabaseOperations.getOrCreateConversation(db, threadId,
senderBlocked, participants, false, false, null);
assertNotNull("No conversation", conversationId);
return conversationId;
}
public void testReadDraft() {
final Object data = "data";
final String draftMessage = "draftMessage";
final long threadId = 1234567;
final boolean senderBlocked = false;
final String participantNumber = "5552345678";
final DatabaseWrapper db = DataModel.get().getDatabase();
final String conversationId = getOrCreateConversation(db, participantNumber, threadId,
senderBlocked);
final String selfId = getOrCreateSelfId(db);
// Should clear/stub DB
final ArrayList<StubActionServiceCallLog> calls = mService.getCalls();
final MessageData message = MessageData.createDraftSmsMessage(conversationId, selfId,
draftMessage);
BugleDatabaseOperations.updateDraftMessageData(db, conversationId, message,
BugleDatabaseOperations.UPDATE_MODE_ADD_DRAFT);
final ActionMonitor monitor =
ReadDraftDataAction.readDraftData(conversationId, null, data, mockListener);
assertEquals("Unexpected number of calls to service", 1, calls.size());
assertTrue("Action not of type ReadDraftMessageAction",
calls.get(0).action instanceof ReadDraftDataAction);
final Action read = calls.get(0).action;
final Object result = read.executeAction();
assertTrue(result instanceof ReadDraftDataAction.DraftData);
final ReadDraftDataAction.DraftData draft = (ReadDraftDataAction.DraftData) result;
assertEquals("Draft message text differs", draftMessage, draft.message.getMessageText());
assertEquals("Draft self differs", selfId, draft.message.getSelfId());
assertEquals("Draft conversation differs", conversationId,
draft.conversation.getConversationId());
}
public void testReadDraftForNewConversation() {
final Object data = "data";
long threadId = 1234567;
final boolean senderBlocked = false;
long phoneNumber = 5557654567L;
final String notConversationId = "ThisIsNotValidConversationId";
final DatabaseWrapper db = DataModel.get().getDatabase();
final String selfId = getOrCreateSelfId(db);
// Unless set a new conversation should have a null draft message
final MessageData blank = BugleDatabaseOperations.readDraftMessageData(db,
notConversationId, selfId);
assertNull(blank);
String conversationId = null;
do {
conversationId = BugleDatabaseOperations.getExistingConversation(db,
threadId, senderBlocked);
threadId++;
phoneNumber++;
}
while(!TextUtils.isEmpty(conversationId));
final ArrayList<ParticipantData> participants =
new ArrayList<ParticipantData>();
participants.add(ParticipantData.getFromRawPhoneBySystemLocale(Long.toString(phoneNumber)));
conversationId = BugleDatabaseOperations.getOrCreateConversation(db, threadId,
senderBlocked, participants, false, false, null);
assertNotNull("No conversation", conversationId);
final MessageData actual = BugleDatabaseOperations.readDraftMessageData(db, conversationId,
selfId);
assertNull(actual);
// Should clear/stub DB
final ArrayList<StubActionServiceCallLog> calls = mService.getCalls();
final ActionMonitor monitor =
ReadDraftDataAction.readDraftData(conversationId, null, data, mockListener);
assertEquals("Unexpected number of calls to service", 1, calls.size());
assertTrue("Action not of type ReadDraftMessageAction",
calls.get(0).action instanceof ReadDraftDataAction);
final Action read = calls.get(0).action;
final Object result = read.executeAction();
assertTrue(result instanceof ReadDraftDataAction.DraftData);
final ReadDraftDataAction.DraftData draft = (ReadDraftDataAction.DraftData) result;
assertEquals("Draft message text differs", "", draft.message.getMessageText());
assertEquals("Draft self differs", selfId, draft.message.getSelfId());
assertEquals("Draft conversation differs", conversationId,
draft.conversation.getConversationId());
}
public void testWriteAndReadDraft() {
final Object data = "data";
final String draftMessage = "draftMessage";
final DatabaseWrapper db = DataModel.get().getDatabase();
final Cursor conversations = db.query(DatabaseHelper.CONVERSATIONS_TABLE,
new String[] { ConversationColumns._ID, ConversationColumns.CURRENT_SELF_ID }, null,
null, null /* groupBy */, null /* having */, null /* orderBy */);
if (conversations.moveToFirst()) {
final String conversationId = conversations.getString(0);
final String selfId = getOrCreateSelfId(db);
// Should clear/stub DB
final ArrayList<StubActionServiceCallLog> calls = mService.getCalls();
final MessageData message = MessageData.createDraftSmsMessage(conversationId, selfId,
draftMessage);
WriteDraftMessageAction.writeDraftMessage(conversationId, message);
assertEquals("Failed to start service once for action", calls.size(), 1);
assertTrue("Action not SaveDraftMessageAction",
calls.get(0).action instanceof WriteDraftMessageAction);
final Action save = calls.get(0).action;
Object result = save.executeAction();
assertTrue("Expect row number string as result", result instanceof String);
// Should check DB
final ActionMonitor monitor =
ReadDraftDataAction.readDraftData(conversationId, null, data,
mockListener);
assertEquals("Expect two calls queued", 2, calls.size());
assertTrue("Expect action", calls.get(1).action instanceof ReadDraftDataAction);
final Action read = calls.get(1).action;
result = read.executeAction();
assertTrue(result instanceof ReadDraftDataAction.DraftData);
final ReadDraftDataAction.DraftData draft = (ReadDraftDataAction.DraftData) result;
assertEquals("Draft message text differs", draftMessage, draft.message.getMessageText());
// The conversation's self id is used as the draft's self id.
assertEquals("Draft self differs", conversations.getString(1),
draft.message.getSelfId());
assertEquals("Draft conversation differs", conversationId,
draft.conversation.getConversationId());
} else {
fail("No conversations in database");
}
}
public void testUpdateDraft() {
final String initialMessage = "initialMessage";
final String draftMessage = "draftMessage";
final long threadId = 1234567;
final boolean senderBlocked = false;
final String participantNumber = "5553456789";
final DatabaseWrapper db = DataModel.get().getDatabase();
final String conversationId = getOrCreateConversation(db, participantNumber, threadId,
senderBlocked);
final String selfId = getOrCreateSelfId(db);
final ArrayList<StubActionServiceCallLog> calls = mService.getCalls();
// Insert initial message
MessageData initial = MessageData.createDraftSmsMessage(conversationId, selfId,
initialMessage);
BugleDatabaseOperations.updateDraftMessageData(db, conversationId, initial,
BugleDatabaseOperations.UPDATE_MODE_ADD_DRAFT);
initial = BugleDatabaseOperations.readDraftMessageData(db,
conversationId, selfId);
assertEquals("Initial text mismatch", initialMessage, initial.getMessageText());
// Now update the draft
final MessageData message = MessageData.createDraftSmsMessage(conversationId, selfId,
draftMessage);
WriteDraftMessageAction.writeDraftMessage(conversationId, message);
assertEquals("Failed to start service once for action", calls.size(), 1);
assertTrue("Action not SaveDraftMessageAction",
calls.get(0).action instanceof WriteDraftMessageAction);
final Action save = calls.get(0).action;
final Object result = save.executeAction();
assertTrue("Expect row number string as result", result instanceof String);
// Check DB
final MessageData actual = BugleDatabaseOperations.readDraftMessageData(db,
conversationId, selfId);
assertNotNull("Database missing draft", actual);
assertEquals("Draft text mismatch", draftMessage, actual.getMessageText());
assertNull("Draft messageId should be null", actual.getMessageId());
}
public void testBugleDatabaseDraftOperations() {
final String initialMessage = "initialMessage";
final String draftMessage = "draftMessage";
final long threadId = 1234599;
final boolean senderBlocked = false;
final String participantNumber = "5553456798";
final String subject = "subject here";
final DatabaseWrapper db = DataModel.get().getDatabase();
final String conversationId = getOrCreateConversation(db, participantNumber, threadId,
senderBlocked);
final String selfId = getOrCreateSelfId(db);
final String text = "This is some text";
final Uri mOutputUri = MediaScratchFileProvider.buildMediaScratchSpaceUri("txt");
OutputStream outputStream = null;
try {
outputStream = mContext.getContentResolver().openOutputStream(mOutputUri);
outputStream.write(text.getBytes());
} catch (final FileNotFoundException e) {
fail("Cannot open output file");
} catch (final IOException e) {
fail("Cannot write output file");
}
final MessageData initial =
MessageData.createDraftMmsMessage(conversationId, selfId, initialMessage, subject);
initial.addPart(MessagePartData.createMediaMessagePart(ContentType.MULTIPART_MIXED,
mOutputUri, 0, 0));
final String initialMessageId = BugleDatabaseOperations.updateDraftMessageData(db,
conversationId, initial, BugleDatabaseOperations.UPDATE_MODE_ADD_DRAFT);
assertNotNull(initialMessageId);
final MessageData initialDraft = BugleDatabaseOperations.readMessage(db, initialMessageId);
assertNotNull(initialDraft);
int cnt = 0;
for(final MessagePartData part : initialDraft.getParts()) {
if (part.isAttachment()) {
assertEquals(part.getContentUri(), mOutputUri);
} else {
assertEquals(part.getText(), initialMessage);
}
cnt++;
}
assertEquals("Wrong number of parts", 2, cnt);
InputStream inputStream = null;
try {
inputStream = mContext.getContentResolver().openInputStream(mOutputUri);
final byte[] buffer = new byte[256];
final int read = inputStream.read(buffer);
assertEquals(read, text.getBytes().length);
} catch (final FileNotFoundException e) {
fail("Cannot open input file");
} catch (final IOException e) {
fail("Cannot read input file");
}
final String moreText = "This is some more text";
final Uri mAnotherUri = MediaScratchFileProvider.buildMediaScratchSpaceUri("txt");
outputStream = null;
try {
outputStream = mContext.getContentResolver().openOutputStream(mAnotherUri);
outputStream.write(moreText.getBytes());
} catch (final FileNotFoundException e) {
fail("Cannot open output file");
} catch (final IOException e) {
fail("Cannot write output file");
}
final MessageData another =
MessageData.createDraftMmsMessage(conversationId, selfId, draftMessage, subject);
another.addPart(MessagePartData.createMediaMessagePart(ContentType.MMS_MULTIPART_MIXED,
mAnotherUri, 0, 0));
final String anotherMessageId = BugleDatabaseOperations.updateDraftMessageData(db,
conversationId, another, BugleDatabaseOperations.UPDATE_MODE_ADD_DRAFT);
assertNotNull(anotherMessageId);
final MessageData anotherDraft = BugleDatabaseOperations.readMessage(db, anotherMessageId);
assertNotNull(anotherDraft);
cnt = 0;
for(final MessagePartData part : anotherDraft.getParts()) {
if (part.isAttachment()) {
assertEquals(part.getContentUri(), mAnotherUri);
} else {
assertEquals(part.getText(), draftMessage);
}
cnt++;
}
assertEquals("Wrong number of parts", 2, cnt);
inputStream = null;
try {
inputStream = mContext.getContentResolver().openInputStream(mOutputUri);
assertNull("Original draft content should have been deleted", inputStream);
} catch (final FileNotFoundException e) {
}
inputStream = null;
try {
inputStream = mContext.getContentResolver().openInputStream(mAnotherUri);
final byte[] buffer = new byte[256];
final int read = inputStream.read(buffer);
assertEquals(read, moreText.getBytes().length);
} catch (final FileNotFoundException e) {
fail("Cannot open input file");
} catch (final IOException e) {
fail("Cannot read input file");
}
final MessageData last = null;
final String lastPartId = BugleDatabaseOperations.updateDraftMessageData(db,
conversationId, last, BugleDatabaseOperations.UPDATE_MODE_ADD_DRAFT);
assertNull(lastPartId);
inputStream = null;
try {
inputStream = mContext.getContentResolver().openInputStream(mAnotherUri);
assertNull("Original draft content should have been deleted", inputStream);
} catch (final FileNotFoundException e) {
}
}
private StubActionService mService;
@Override
public void setUp() throws Exception {
super.setUp();
final FakeContext context = new FakeContext(getTestContext());
final ContentProvider bugleProvider = new MessagingContentProvider();
final ProviderInfo bugleProviderInfo = new ProviderInfo();
bugleProviderInfo.authority = MessagingContentProvider.AUTHORITY;
bugleProvider.attachInfo(mContext, bugleProviderInfo);
context.addContentProvider(MessagingContentProvider.AUTHORITY, bugleProvider);
final ContentProvider mediaProvider = new MediaScratchFileProvider();
final ProviderInfo mediaProviderInfo = new ProviderInfo();
mediaProviderInfo.authority = MediaScratchFileProvider.AUTHORITY;
mediaProvider.attachInfo(mContext, mediaProviderInfo);
context.addContentProvider(MediaScratchFileProvider.AUTHORITY, mediaProvider);
mService = new StubActionService();
final FakeDataModel fakeDataModel = new FakeDataModel(context)
.withActionService(mService);
FakeFactory.registerWithFakeContext(getTestContext(), context)
.withDataModel(fakeDataModel);
}
}