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 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