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 
17 package com.android.mms.ui;
18 
19 import android.content.Intent;
20 import android.graphics.drawable.Drawable;
21 import android.test.ActivityInstrumentationTestCase2;
22 import android.test.suitebuilder.annotation.LargeTest;
23 import android.util.Log;
24 import android.view.ActionProvider;
25 import android.view.ContextMenu.ContextMenuInfo;
26 import android.view.MenuItem;
27 import android.view.SubMenu;
28 import android.view.View;
29 import android.view.ViewStub;
30 import android.widget.Button;
31 import android.widget.ImageButton;
32 import android.widget.EditText;
33 import android.widget.TextView;
34 
35 import com.android.mms.R;
36 import com.android.mms.ui.ComposeMessageActivity;
37 import com.android.mms.ui.RecipientsEditor;
38 
39 import java.io.FileInputStream;
40 import java.util.ArrayList;
41 import 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  */
51 public class LongThreadTest
52 extends 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 
LongThreadTest()64     public LongThreadTest() {
65         super(ComposeMessageActivity.class);
66     }
67 
68     @Override
setUp()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 
generateMessage()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 
getAlphabeticShortcut()147         public char getAlphabeticShortcut() {
148             // TODO Auto-generated method stub
149             return 0;
150         }
151 
getGroupId()152         public int getGroupId() {
153             // TODO Auto-generated method stub
154             return 0;
155         }
156 
getIcon()157         public Drawable getIcon() {
158             // TODO Auto-generated method stub
159             return null;
160         }
161 
getIntent()162         public Intent getIntent() {
163             // TODO Auto-generated method stub
164             return null;
165         }
166 
getItemId()167         public int getItemId() {
168             return MENU_ADD_SUBJECT;
169         }
170 
getMenuInfo()171         public ContextMenuInfo getMenuInfo() {
172             // TODO Auto-generated method stub
173             return null;
174         }
175 
getNumericShortcut()176         public char getNumericShortcut() {
177             // TODO Auto-generated method stub
178             return 0;
179         }
180 
getOrder()181         public int getOrder() {
182             // TODO Auto-generated method stub
183             return 0;
184         }
185 
getSubMenu()186         public SubMenu getSubMenu() {
187             // TODO Auto-generated method stub
188             return null;
189         }
190 
getTitle()191         public CharSequence getTitle() {
192             // TODO Auto-generated method stub
193             return null;
194         }
195 
getTitleCondensed()196         public CharSequence getTitleCondensed() {
197             // TODO Auto-generated method stub
198             return null;
199         }
200 
hasSubMenu()201         public boolean hasSubMenu() {
202             // TODO Auto-generated method stub
203             return false;
204         }
205 
isCheckable()206         public boolean isCheckable() {
207             // TODO Auto-generated method stub
208             return false;
209         }
210 
isChecked()211         public boolean isChecked() {
212             // TODO Auto-generated method stub
213             return false;
214         }
215 
isEnabled()216         public boolean isEnabled() {
217             // TODO Auto-generated method stub
218             return false;
219         }
220 
isVisible()221         public boolean isVisible() {
222             // TODO Auto-generated method stub
223             return false;
224         }
225 
setAlphabeticShortcut(char alphaChar)226         public MenuItem setAlphabeticShortcut(char alphaChar) {
227             // TODO Auto-generated method stub
228             return null;
229         }
230 
setCheckable(boolean checkable)231         public MenuItem setCheckable(boolean checkable) {
232             // TODO Auto-generated method stub
233             return null;
234         }
235 
setChecked(boolean checked)236         public MenuItem setChecked(boolean checked) {
237             // TODO Auto-generated method stub
238             return null;
239         }
240 
setEnabled(boolean enabled)241         public MenuItem setEnabled(boolean enabled) {
242             // TODO Auto-generated method stub
243             return null;
244         }
245 
setIcon(Drawable icon)246         public MenuItem setIcon(Drawable icon) {
247             // TODO Auto-generated method stub
248             return null;
249         }
250 
setIcon(int iconRes)251         public MenuItem setIcon(int iconRes) {
252             // TODO Auto-generated method stub
253             return null;
254         }
255 
setIntent(Intent intent)256         public MenuItem setIntent(Intent intent) {
257             // TODO Auto-generated method stub
258             return null;
259         }
260 
setNumericShortcut(char numericChar)261         public MenuItem setNumericShortcut(char numericChar) {
262             // TODO Auto-generated method stub
263             return null;
264         }
265 
setOnMenuItemClickListener( OnMenuItemClickListener menuItemClickListener)266         public MenuItem setOnMenuItemClickListener(
267                 OnMenuItemClickListener menuItemClickListener) {
268             // TODO Auto-generated method stub
269             return null;
270         }
271 
setShortcut(char numericChar, char alphaChar)272         public MenuItem setShortcut(char numericChar, char alphaChar) {
273             // TODO Auto-generated method stub
274             return null;
275         }
276 
setTitle(CharSequence title)277         public MenuItem setTitle(CharSequence title) {
278             // TODO Auto-generated method stub
279             return null;
280         }
281 
setTitle(int title)282         public MenuItem setTitle(int title) {
283             // TODO Auto-generated method stub
284             return null;
285         }
286 
setTitleCondensed(CharSequence title)287         public MenuItem setTitleCondensed(CharSequence title) {
288             // TODO Auto-generated method stub
289             return null;
290         }
291 
setVisible(boolean visible)292         public MenuItem setVisible(boolean visible) {
293             // TODO Auto-generated method stub
294             return null;
295         }
296 
setShowAsAction(int actionEnum)297         public void setShowAsAction(int actionEnum) {
298             // TODO Auto-generated method stub
299 
300         }
301 
302         @Override
setActionView(View view)303         public MenuItem setActionView(View view) {
304             // TODO Auto-generated method stub
305             return null;
306         }
307 
308         @Override
getActionView()309         public View getActionView() {
310             // TODO Auto-generated method stub
311             return null;
312         }
313 
314         @Override
setActionView(int resId)315         public MenuItem setActionView(int resId) {
316             // TODO Auto-generated method stub
317             return null;
318         }
319 
320         @Override
setShowAsActionFlags(int actionEnum)321         public MenuItem setShowAsActionFlags(int actionEnum) {
322             // TODO Auto-generated method stub
323             return null;
324         }
325 
326         @Override
expandActionView()327         public boolean expandActionView() {
328             // TODO Auto-generated method stub
329             return false;
330         }
331 
332         @Override
collapseActionView()333         public boolean collapseActionView() {
334             // TODO Auto-generated method stub
335             return false;
336         }
337 
338         @Override
isActionViewExpanded()339         public boolean isActionViewExpanded() {
340             return false;
341         }
342 
343         @Override
setOnActionExpandListener(OnActionExpandListener listener)344         public MenuItem setOnActionExpandListener(OnActionExpandListener listener) {
345             // TODO Auto-generated method stub
346             return null;
347         }
348 
349         @Override
setActionProvider(ActionProvider actionProvider)350         public MenuItem setActionProvider(ActionProvider actionProvider) {
351             // TODO Auto-generated method stub
352             return null;
353         }
354 
355         @Override
getActionProvider()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 
setRecipient(String recipient)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
testSendManyMessages()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