1/*
2 * Copyright (C) 2015 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 *      http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17package com.android.messaging.datamodel.action;
18
19import android.content.pm.ProviderInfo;
20import android.database.Cursor;
21import android.net.Uri;
22import android.test.mock.MockContentProvider;
23import android.test.suitebuilder.annotation.SmallTest;
24
25import com.android.messaging.BugleTestCase;
26import com.android.messaging.FakeContext;
27import com.android.messaging.FakeFactory;
28import com.android.messaging.datamodel.BugleDatabaseOperations;
29import com.android.messaging.datamodel.DataModel;
30import com.android.messaging.datamodel.DatabaseWrapper;
31import com.android.messaging.datamodel.FakeDataModel;
32import com.android.messaging.datamodel.MessagingContentProvider;
33import com.android.messaging.datamodel.action.ActionTestHelpers.StubActionService;
34import com.android.messaging.datamodel.action.ActionTestHelpers.StubActionService.StubActionServiceCallLog;
35import com.android.messaging.datamodel.action.GetOrCreateConversationAction.GetOrCreateConversationActionListener;
36import com.android.messaging.datamodel.action.GetOrCreateConversationAction.GetOrCreateConversationActionMonitor;
37import com.android.messaging.datamodel.data.ParticipantData;
38import com.android.messaging.datamodel.data.TestDataFactory;
39import com.android.messaging.sms.MmsUtils;
40
41import org.mockito.Mock;
42
43import java.util.ArrayList;
44
45@SmallTest
46public class GetOrCreateConversationActionTest extends BugleTestCase {
47
48    @Mock GetOrCreateConversationActionListener mockListener;
49
50    public void testGetOrCreateConversation() {
51        final DatabaseWrapper db = DataModel.get().getDatabase();
52
53        final ArrayList<String> recipients = new ArrayList<String>();
54        recipients.add("5551234567");
55        recipients.add("5551234568");
56
57        // Generate a list of partially formed participants
58        final ArrayList<ParticipantData> participants = new
59                ArrayList<ParticipantData>();
60
61
62        for (final String recipient : recipients) {
63            participants.add(ParticipantData.getFromRawPhoneBySystemLocale(recipient));
64        }
65
66        // Test that we properly stubbed the SMS provider to return a thread id
67        final long threadId = MmsUtils.getOrCreateThreadId(mContext, recipients);
68        assertEquals(TestDataFactory.SMS_MMS_THREAD_ID_CURSOR_VALUE, threadId);
69
70        final String blankId = BugleDatabaseOperations.getExistingConversation(db, threadId, false);
71        assertNull("Conversation already exists", blankId);
72
73        ArrayList<StubActionServiceCallLog> calls = mService.getCalls();
74
75        GetOrCreateConversationActionMonitor monitor =
76                GetOrCreateConversationAction.getOrCreateConversation(participants, null,
77                        mockListener);
78
79        assertEquals("Failed to start service once for action", calls.size(), 1);
80        assertTrue("Action not GetOrCreateConversationAction", calls.get(0).action instanceof
81                GetOrCreateConversationAction);
82
83        GetOrCreateConversationAction action = (GetOrCreateConversationAction)
84                calls.get(0).action;
85
86        Object result = action.executeAction();
87
88        assertTrue(result instanceof String);
89
90        // Make sure that we created a new conversation
91        assertEquals(TestDataFactory.NUM_TEST_CONVERSATIONS+1, Integer.parseInt((String)result));
92
93        // Now get the conversation that we just created again
94        monitor = GetOrCreateConversationAction.getOrCreateConversation(participants, null,
95                        mockListener);
96
97        calls = mService.getCalls();
98        assertEquals("Failed to start service for second action", calls.size(), 2);
99        assertTrue("Action not GetOrCreateConversationAction", calls.get(1).action instanceof
100                GetOrCreateConversationAction);
101        action = (GetOrCreateConversationAction)calls.get(1).action;
102        result = action.executeAction();
103
104        assertTrue(result instanceof String);
105
106        final String conversationId = (String) result;
107
108        // Make sure that we found the same conversation id
109        assertEquals(TestDataFactory.NUM_TEST_CONVERSATIONS+1, Integer.parseInt((String)result));
110
111        final ArrayList<ParticipantData> conversationParticipants =
112                BugleDatabaseOperations.getParticipantsForConversation(db, conversationId);
113
114        assertEquals("Participant count mismatch", recipients.size(),
115                conversationParticipants.size());
116        for(final ParticipantData participant : conversationParticipants) {
117            assertTrue(recipients.contains(participant.getSendDestination()));
118        }
119
120        final Uri conversationParticipantsUri =
121                MessagingContentProvider.buildConversationParticipantsUri(conversationId);
122        final Cursor cursor = mContext.getContentResolver().query(conversationParticipantsUri,
123                ParticipantData.ParticipantsQuery.PROJECTION, null, null, null);
124
125        int countSelf = 0;
126        while(cursor.moveToNext()) {
127            final ParticipantData participant = ParticipantData.getFromCursor(cursor);
128            if (participant.isSelf()) {
129                countSelf++;
130            } else {
131                assertTrue(recipients.contains(participant.getSendDestination()));
132            }
133        }
134        cursor.close();
135        assertEquals("Expect one self participant in conversations", 1, countSelf);
136        assertEquals("Cursor count mismatch", recipients.size(), cursor.getCount() - countSelf);
137
138        final String realId = BugleDatabaseOperations.getExistingConversation(db, threadId, false);
139        assertEquals("Conversation already exists", realId, conversationId);
140    }
141
142    private FakeContext mContext;
143    private StubActionService mService;
144
145    @Override
146    public void setUp() throws Exception {
147        super.setUp();
148
149        mContext = new FakeContext(getTestContext());
150
151        final MockContentProvider mockProvider = new MockContentProvider() {
152            @Override
153            public Cursor query(final Uri uri, final String[] projection, final String selection,
154                    final String[] selectionArgs, final String sortOrder) {
155                return TestDataFactory.getSmsMmsThreadIdCursor();
156            }
157        };
158
159        mContext.addContentProvider("mms-sms", mockProvider);
160        final MessagingContentProvider provider = new MessagingContentProvider();
161        final ProviderInfo providerInfo = new ProviderInfo();
162        providerInfo.authority = MessagingContentProvider.AUTHORITY;
163        provider.attachInfo(mContext, providerInfo);
164        mContext.addContentProvider(MessagingContentProvider.AUTHORITY, provider);
165
166        mService = new StubActionService();
167        final FakeDataModel fakeDataModel = new FakeDataModel(mContext)
168            .withActionService(mService);
169        FakeFactory.registerWithFakeContext(getTestContext(), mContext)
170                .withDataModel(fakeDataModel);
171        provider.setDatabaseForTest(fakeDataModel.getDatabase());
172    }
173}
174