1/*
2 * Copyright (C) 2008 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.mms.ui;
18
19import android.content.Intent;
20import android.graphics.drawable.Drawable;
21import android.test.ActivityInstrumentationTestCase2;
22import android.test.suitebuilder.annotation.LargeTest;
23import android.util.Log;
24import android.view.ActionProvider;
25import android.view.ContextMenu.ContextMenuInfo;
26import android.view.MenuItem;
27import android.view.SubMenu;
28import android.view.View;
29import android.view.ViewStub;
30import android.widget.Button;
31import android.widget.ImageButton;
32import android.widget.EditText;
33import android.widget.TextView;
34
35import com.android.mms.R;
36import com.android.mms.ui.ComposeMessageActivity;
37import com.android.mms.ui.RecipientsEditor;
38
39import java.io.FileInputStream;
40import java.util.ArrayList;
41import java.util.Random;
42
43/**
44 * Test threads with thousands of messages
45 * NOTE: you first have to put the unix words file on the device:
46 *    example: adb push ~/words /data/data/com.android.mms/files
47 * and then push a file that contains a comma separated list of numbers to send to.
48 *    example: adb push ~/recipients /data/data/com.android.mms/files
49 *
50 */
51public class LongThreadTest
52extends ActivityInstrumentationTestCase2<ComposeMessageActivity> {
53
54    private RecipientsEditor mRecipientsEditor;
55    private EditText mTextEditor;
56    private EditText mSubjectTextEditor;    // Text editor for MMS subject
57    static final String TAG = "LongThreadTest";
58    private ArrayList<String> mWords;
59    private ArrayList<String> mRecipients;
60    private int mWordCount;
61    private Random mRandom = new Random();
62    private ComposeMessageActivity mActivity;
63
64    public LongThreadTest() {
65        super(ComposeMessageActivity.class);
66    }
67
68    @Override
69    protected void setUp() throws Exception {
70        super.setUp();
71
72        mActivity = getActivity();
73        ViewStub stub = (ViewStub)mActivity.findViewById(R.id.recipients_editor_stub);
74        if (stub != null) {
75            View stubView = stub.inflate();
76            mRecipientsEditor = (RecipientsEditor) stubView.findViewById(R.id.recipients_editor);
77        } else {
78            mRecipientsEditor = (RecipientsEditor)mActivity.findViewById(R.id.recipients_editor);
79            mRecipientsEditor.setVisibility(View.VISIBLE);
80        }
81        mTextEditor = (EditText)mActivity.findViewById(R.id.embedded_text_editor);
82        mSubjectTextEditor = (EditText)mActivity.findViewById(R.id.subject);
83
84        // Read in dictionary of words
85        mWords = new ArrayList<String>(98568);      // count of words in words file
86        StringBuilder sb = new StringBuilder();
87        try {
88            Log.v(TAG, "Loading dictionary of words");
89            FileInputStream words = mActivity.openFileInput("words");
90            int c;
91            while ((c = words.read()) != -1) {
92                if (c == '\r' || c == '\n') {
93                    String word = sb.toString().trim();
94                    if (word.length() > 0) {
95                        mWords.add(word);
96                    }
97                    sb.setLength(0);
98                } else {
99                    sb.append((char)c);
100                }
101            }
102            words.close();
103            mWordCount = mWords.size();
104            Log.v(TAG, "Loaded dictionary word count: " + mWordCount);
105        } catch (Exception e) {
106            Log.e(TAG, "can't open words file at /data/data/com.android.mms/files/words");
107            return;
108        }
109
110        // Read in list of recipients
111        mRecipients = new ArrayList<String>();
112        try {
113            Log.v(TAG, "Loading recipients");
114            FileInputStream recipients = mActivity.openFileInput("recipients");
115            int c;
116            while ((c = recipients.read()) != -1) {
117                if (c == '\r' || c == '\n' || c == ',') {
118                    String recipient = sb.toString().trim();
119                    if (recipient.length() > 0) {
120                        mRecipients.add(recipient);
121                    }
122                    sb.setLength(0);
123                } else {
124                    sb.append((char)c);
125                }
126            }
127            recipients.close();
128            Log.v(TAG, "Loaded recipients: " + mRecipients.size());
129        } catch (Exception e) {
130            Log.e(TAG, "can't open recipients file at /data/data/com.android.mms/files/recipients");
131            return;
132        }
133    }
134
135    private String generateMessage() {
136        int wordsInMessage = mRandom.nextInt(9) + 1;   // up to 10 words in the message
137        StringBuilder msg = new StringBuilder();
138        for (int i = 0; i < wordsInMessage; i++) {
139            msg.append(mWords.get(mRandom.nextInt(mWordCount)) + " ");
140        }
141        return msg.toString();
142    }
143
144    private class AddSubjectMenuItem implements MenuItem {
145        private static final int MENU_ADD_SUBJECT = 0;
146
147        public char getAlphabeticShortcut() {
148            // TODO Auto-generated method stub
149            return 0;
150        }
151
152        public int getGroupId() {
153            // TODO Auto-generated method stub
154            return 0;
155        }
156
157        public Drawable getIcon() {
158            // TODO Auto-generated method stub
159            return null;
160        }
161
162        public Intent getIntent() {
163            // TODO Auto-generated method stub
164            return null;
165        }
166
167        public int getItemId() {
168            return MENU_ADD_SUBJECT;
169        }
170
171        public ContextMenuInfo getMenuInfo() {
172            // TODO Auto-generated method stub
173            return null;
174        }
175
176        public char getNumericShortcut() {
177            // TODO Auto-generated method stub
178            return 0;
179        }
180
181        public int getOrder() {
182            // TODO Auto-generated method stub
183            return 0;
184        }
185
186        public SubMenu getSubMenu() {
187            // TODO Auto-generated method stub
188            return null;
189        }
190
191        public CharSequence getTitle() {
192            // TODO Auto-generated method stub
193            return null;
194        }
195
196        public CharSequence getTitleCondensed() {
197            // TODO Auto-generated method stub
198            return null;
199        }
200
201        public boolean hasSubMenu() {
202            // TODO Auto-generated method stub
203            return false;
204        }
205
206        public boolean isCheckable() {
207            // TODO Auto-generated method stub
208            return false;
209        }
210
211        public boolean isChecked() {
212            // TODO Auto-generated method stub
213            return false;
214        }
215
216        public boolean isEnabled() {
217            // TODO Auto-generated method stub
218            return false;
219        }
220
221        public boolean isVisible() {
222            // TODO Auto-generated method stub
223            return false;
224        }
225
226        public MenuItem setAlphabeticShortcut(char alphaChar) {
227            // TODO Auto-generated method stub
228            return null;
229        }
230
231        public MenuItem setCheckable(boolean checkable) {
232            // TODO Auto-generated method stub
233            return null;
234        }
235
236        public MenuItem setChecked(boolean checked) {
237            // TODO Auto-generated method stub
238            return null;
239        }
240
241        public MenuItem setEnabled(boolean enabled) {
242            // TODO Auto-generated method stub
243            return null;
244        }
245
246        public MenuItem setIcon(Drawable icon) {
247            // TODO Auto-generated method stub
248            return null;
249        }
250
251        public MenuItem setIcon(int iconRes) {
252            // TODO Auto-generated method stub
253            return null;
254        }
255
256        public MenuItem setIntent(Intent intent) {
257            // TODO Auto-generated method stub
258            return null;
259        }
260
261        public MenuItem setNumericShortcut(char numericChar) {
262            // TODO Auto-generated method stub
263            return null;
264        }
265
266        public MenuItem setOnMenuItemClickListener(
267                OnMenuItemClickListener menuItemClickListener) {
268            // TODO Auto-generated method stub
269            return null;
270        }
271
272        public MenuItem setShortcut(char numericChar, char alphaChar) {
273            // TODO Auto-generated method stub
274            return null;
275        }
276
277        public MenuItem setTitle(CharSequence title) {
278            // TODO Auto-generated method stub
279            return null;
280        }
281
282        public MenuItem setTitle(int title) {
283            // TODO Auto-generated method stub
284            return null;
285        }
286
287        public MenuItem setTitleCondensed(CharSequence title) {
288            // TODO Auto-generated method stub
289            return null;
290        }
291
292        public MenuItem setVisible(boolean visible) {
293            // TODO Auto-generated method stub
294            return null;
295        }
296
297        public void setShowAsAction(int actionEnum) {
298            // TODO Auto-generated method stub
299
300        }
301
302        @Override
303        public MenuItem setActionView(View view) {
304            // TODO Auto-generated method stub
305            return null;
306        }
307
308        @Override
309        public View getActionView() {
310            // TODO Auto-generated method stub
311            return null;
312        }
313
314        @Override
315        public MenuItem setActionView(int resId) {
316            // TODO Auto-generated method stub
317            return null;
318        }
319
320        @Override
321        public MenuItem setShowAsActionFlags(int actionEnum) {
322            // TODO Auto-generated method stub
323            return null;
324        }
325
326        @Override
327        public boolean expandActionView() {
328            // TODO Auto-generated method stub
329            return false;
330        }
331
332        @Override
333        public boolean collapseActionView() {
334            // TODO Auto-generated method stub
335            return false;
336        }
337
338        @Override
339        public boolean isActionViewExpanded() {
340            return false;
341        }
342
343        @Override
344        public MenuItem setOnActionExpandListener(OnActionExpandListener listener) {
345            // TODO Auto-generated method stub
346            return null;
347        }
348
349        @Override
350        public MenuItem setActionProvider(ActionProvider actionProvider) {
351            // TODO Auto-generated method stub
352            return null;
353        }
354
355        @Override
356        public ActionProvider getActionProvider() {
357            // TODO Auto-generated method stub
358            return null;
359        }
360
361    }
362
363    private abstract class MessageRunnable implements Runnable {
364        protected String mRecipient;
365
366        public void setRecipient(String recipient) {
367            mRecipient = recipient;
368        }
369    }
370
371    private MessageRunnable mSendSmsMessage = new MessageRunnable() {
372        public void run() {
373            // only on the first message will there be a recipients editor
374            if (mRecipientsEditor.getVisibility() == View.VISIBLE) {
375                mRecipientsEditor.setText(mRecipient);
376            }
377            mTextEditor.setText(generateMessage());
378            final ComposeMessageActivity a = getActivity();
379            ImageButton send = (ImageButton)mActivity.findViewById(R.id.send_button_sms);
380            send.performClick();
381        }
382    };
383
384    private MessageRunnable mSendMmsMessage = new MessageRunnable() {
385        public void run() {
386            // only on the first message will there be a recipients editor
387            if (mRecipientsEditor.getVisibility() == View.VISIBLE) {
388                mRecipientsEditor.setText(mRecipient);
389            }
390            // Add a subject
391            final ComposeMessageActivity a = getActivity();
392            MenuItem item = new AddSubjectMenuItem();
393            mActivity.onOptionsItemSelected(item);
394            mSubjectTextEditor.setText(generateMessage());
395
396            mTextEditor.setText(generateMessage());
397            Button send = (Button)mActivity.findViewById(R.id.send_button);
398            send.performClick();
399        }
400    };
401
402    /**
403     * Send a flurry of SMS and MMS messages
404     */
405    @LargeTest
406    public void testSendManyMessages() throws Throwable {
407        // BTW, sending 50 messages brings up the "Sending too many messages" alert so
408        // backing down to a smaller number.
409        final int MAXSEND = 30;
410        final int MSG_PER_RECIPIENT = MAXSEND / mRecipients.size();
411        final int MMS_FREQ = Math.min(MSG_PER_RECIPIENT / 10, 1);
412
413        final ComposeMessageActivity a = getActivity();
414        for (String recipient : mRecipients) {
415            mActivity.runOnUiThread(new Runnable() {
416                public void run() {
417                    a.initialize(null, 0);
418                    a.loadMessageContent();
419                }
420            });
421
422            for (int i = 0; i < MSG_PER_RECIPIENT; i++) {
423                Log.v(TAG, "Sending msg: " + i);
424                if (i % MMS_FREQ == 0) {
425                    mSendMmsMessage.setRecipient(recipient);
426                    runTestOnUiThread(mSendMmsMessage);
427                } else {
428                    mSendSmsMessage.setRecipient(recipient);
429                    runTestOnUiThread(mSendSmsMessage);
430                }
431                Thread.sleep(5000);     // wait 5 seconds between messages
432            }
433        }
434        assertTrue(true);
435    }
436}
437