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