1 package com.google.sample.oboe.manualtest; 2 3 import android.content.Context; 4 import android.content.Intent; 5 import android.os.Build; 6 import android.text.method.ScrollingMovementMethod; 7 import android.util.AttributeSet; 8 import android.util.Log; 9 import android.view.LayoutInflater; 10 import android.view.View; 11 import android.widget.Button; 12 import android.widget.LinearLayout; 13 import android.widget.TextView; 14 15 import java.text.DateFormat; 16 import java.text.SimpleDateFormat; 17 import java.util.Calendar; 18 import java.util.Date; 19 20 /** 21 * Run an automated test from a UI, gather logs, 22 * and display a summary. 23 */ 24 public class AutomatedTestRunner extends LinearLayout implements Runnable { 25 26 private Button mStartButton; 27 private Button mStopButton; 28 private Button mShareButton; 29 private TextView mAutoTextView; 30 private TextView mSingleTestIndex; 31 private StringBuffer mFailedSummary; 32 private StringBuffer mSummary; 33 private int mTestCount; 34 private int mPassCount; 35 private int mFailCount; 36 private TestAudioActivity mActivity; 37 38 private Thread mAutoThread; 39 private volatile boolean mThreadEnabled; 40 private CachedTextViewLog mCachedTextView; 41 AutomatedTestRunner(Context context)42 public AutomatedTestRunner(Context context) { 43 super(context); 44 initializeViews(context); 45 } 46 AutomatedTestRunner(Context context, AttributeSet attrs)47 public AutomatedTestRunner(Context context, AttributeSet attrs) { 48 super(context, attrs); 49 initializeViews(context); 50 } 51 AutomatedTestRunner(Context context, AttributeSet attrs, int defStyle)52 public AutomatedTestRunner(Context context, 53 AttributeSet attrs, 54 int defStyle) { 55 super(context, attrs, defStyle); 56 initializeViews(context); 57 } 58 getActivity()59 public TestAudioActivity getActivity() { 60 return mActivity; 61 } 62 setActivity(TestAudioActivity activity)63 public void setActivity(TestAudioActivity activity) { 64 this.mActivity = activity; 65 mCachedTextView = new CachedTextViewLog(activity, mAutoTextView); 66 } 67 68 /** 69 * Inflates the views in the layout. 70 * 71 * @param context 72 * the current context for the view. 73 */ initializeViews(Context context)74 private void initializeViews(Context context) { 75 LayoutInflater inflater = (LayoutInflater) context 76 .getSystemService(Context.LAYOUT_INFLATER_SERVICE); 77 inflater.inflate(R.layout.auto_test_runner, this); 78 79 mStartButton = (Button) findViewById(R.id.button_start); 80 mStartButton.setOnClickListener( new OnClickListener() { 81 @Override 82 public void onClick(View v) { 83 startTest(); 84 } 85 }); 86 87 mStopButton = (Button) findViewById(R.id.button_stop); 88 mStopButton.setOnClickListener( new OnClickListener() { 89 @Override 90 public void onClick(View v) { 91 stopTest(); 92 } 93 }); 94 95 mShareButton = (Button) findViewById(R.id.button_share); 96 mShareButton.setOnClickListener( new OnClickListener() { 97 @Override 98 public void onClick(View v) { 99 shareResult(); 100 mShareButton.setEnabled(true); 101 } 102 }); 103 mShareButton.setEnabled(false); 104 105 mSingleTestIndex = (TextView) findViewById(R.id.single_test_index); 106 107 mAutoTextView = (TextView) findViewById(R.id.text_log); 108 mAutoTextView.setMovementMethod(new ScrollingMovementMethod()); 109 } 110 updateStartStopButtons(boolean running)111 private void updateStartStopButtons(boolean running) { 112 mStartButton.setEnabled(!running); 113 mStopButton.setEnabled(running); 114 } 115 getTestCount()116 public int getTestCount() { 117 return mTestCount; 118 } 119 isThreadEnabled()120 public boolean isThreadEnabled() { 121 return mThreadEnabled; 122 } 123 appendFailedSummary(String text)124 public void appendFailedSummary(String text) { 125 mFailedSummary.append(text); 126 } appendSummary(String text)127 public void appendSummary(String text) { 128 mSummary.append(text); 129 } 130 incrementFailCount()131 public void incrementFailCount() { 132 mFailCount++; 133 } incrementPassCount()134 public void incrementPassCount() { 135 mPassCount++; 136 } incrementTestCount()137 public void incrementTestCount() { 138 mTestCount++; 139 } 140 141 // Write to scrollable TextView log(final String text)142 public void log(final String text) { 143 if (text == null) return; 144 Log.d(TestAudioActivity.TAG, "LOG - " + text); 145 mCachedTextView.append(text + "\n"); 146 } 147 148 // Flush any logs that are stuck in the cache. flushLog()149 public void flushLog() { 150 mCachedTextView.flush(); 151 } 152 logClear()153 private void logClear() { 154 mCachedTextView.clear(); 155 } 156 startAutoThread()157 private void startAutoThread() { 158 mThreadEnabled = true; 159 mAutoThread = new Thread(this); 160 mAutoThread.start(); 161 } 162 stopAutoThread()163 private void stopAutoThread() { 164 try { 165 if (mAutoThread != null) { 166 log("Disable background test thread."); 167 new RuntimeException("Disable background test thread.").printStackTrace(); 168 mThreadEnabled = false; 169 mAutoThread.interrupt(); 170 mAutoThread.join(100); 171 mAutoThread = null; 172 } 173 } catch (InterruptedException e) { 174 e.printStackTrace(); 175 } 176 } 177 updateTestIndex()178 private void updateTestIndex() { 179 CharSequence chars = mSingleTestIndex.getText(); 180 String text = chars.toString(); 181 int testIndex = -1; 182 String trimmed = chars.toString().trim(); 183 if (trimmed.length() > 0) { 184 try { 185 testIndex = Integer.parseInt(text); 186 } catch (NumberFormatException e) { 187 mActivity.showErrorToast("Badly formated callback size: " + text); 188 mSingleTestIndex.setText(""); 189 } 190 } 191 mActivity.setSingleTestIndex(testIndex); 192 } 193 startTest()194 protected void startTest() { 195 updateTestIndex(); 196 updateStartStopButtons(true); 197 startAutoThread(); 198 } 199 stopTest()200 public void stopTest() { 201 stopAutoThread(); 202 } 203 204 // Only call from UI thread. onTestFinished()205 public void onTestFinished() { 206 updateStartStopButtons(false); 207 mShareButton.setEnabled(true); 208 } 209 getTimestampString()210 public static String getTimestampString() { 211 DateFormat df = new SimpleDateFormat("yyyyMMdd-HHmmss"); 212 Date now = Calendar.getInstance().getTime(); 213 return df.format(now); 214 } 215 216 // Share text from log via GMail, Drive or other method. shareResult()217 public void shareResult() { 218 Intent sharingIntent = new Intent(android.content.Intent.ACTION_SEND); 219 sharingIntent.setType("text/plain"); 220 221 String subjectText = "OboeTester-" + mActivity.getTestName() 222 + "-" + Build.MANUFACTURER 223 + "-" + Build.MODEL 224 + "-" + getTimestampString(); 225 subjectText = subjectText.replace(' ', '-'); 226 sharingIntent.putExtra(android.content.Intent.EXTRA_SUBJECT, subjectText); 227 228 String shareBody = mAutoTextView.getText().toString(); 229 sharingIntent.putExtra(android.content.Intent.EXTRA_TEXT, shareBody); 230 231 mActivity.startActivity(Intent.createChooser(sharingIntent, "Share using:")); 232 } 233 234 @Override run()235 public void run() { 236 logClear(); 237 log("=== STARTED at " + new Date()); 238 log(mActivity.getTestName()); 239 log(MainActivity.getVersiontext()); 240 log(Build.MANUFACTURER + ", " + Build.MODEL + ", " + Build.PRODUCT); 241 log(Build.DISPLAY); 242 mFailedSummary = new StringBuffer(); 243 mSummary = new StringBuffer(); 244 appendFailedSummary("Summary\n"); 245 mTestCount = 0; 246 mPassCount = 0; 247 mFailCount = 0; 248 try { 249 mActivity.runTest(); 250 log("Tests finished without exception."); 251 } catch(Exception e) { 252 log("EXCEPTION: " + e.getMessage()); 253 } finally { 254 mActivity.stopTest(); 255 if (mThreadEnabled) { 256 log("\n==== SUMMARY ========"); 257 log(mSummary.toString()); 258 if (mFailCount > 0) { 259 log("These tests FAILED:"); 260 log(mFailedSummary.toString()); 261 log("------------"); 262 } else if (mPassCount > 0) { 263 log("All " + mPassCount + " tests PASSED."); 264 } else { 265 log("No tests were run!"); 266 } 267 int skipped = mTestCount - (mPassCount + mFailCount); 268 log(mPassCount + " passed. " 269 + mFailCount + " failed. " 270 + skipped + " skipped. "); 271 log("== FINISHED at " + new Date()); 272 } else { 273 log("== TEST STOPPED =="); 274 } 275 flushLog(); 276 mActivity.runOnUiThread(new Runnable() { 277 @Override 278 public void run() { 279 onTestFinished(); 280 } 281 }); 282 } 283 } 284 285 } 286