package com.samknows.measurement.TestRunner; import android.content.Context; import android.os.Looper; import com.samknows.libcore.SKPorting; import com.samknows.measurement.CachingStorage; import com.samknows.measurement.SKApplication; import com.samknows.measurement.environment.PassiveMetricCollector; import com.samknows.measurement.schedule.condition.ConditionGroupResult; import com.samknows.measurement.schedule.ScheduleConfig; import com.samknows.measurement.schedule.TestDescription; import com.samknows.measurement.SK2AppSettings; import com.samknows.measurement.statemachine.state.StateEnum; import com.samknows.measurement.statemachine.StateResponseCode; import com.samknows.measurement.statemachine.Transition; import com.samknows.measurement.storage.DBHelper; import com.samknows.measurement.storage.TestBatch; import com.samknows.measurement.Storage; import java.util.ArrayList; import java.util.HashMap; import java.util.List; import org.json.JSONObject; /* * This class is used to run the the tests when they are executed manually * as a continuous test. * The class is simply created, started, and stopped. * Test results are not reported while the tests are running. */ public class ContinuousTestRunner extends SKTestRunner implements Runnable { private static final String JSON_SUBMISSION_TYPE = "continuous_testing"; private Context mContext; private StateEnum mPreviousState; final PassiveMetricCollector mPassiveMetricCollector; private final TestContext mTestContext; private ScheduleConfig mConfig; private final DBHelper mDBHelper; public ContinuousTestRunner(SKTestRunnerObserver observer) { super(observer); mTestContext = TestContext.createBackgroundTestContext(mContext); mContext = SKApplication.getAppInstance().getApplicationContext(); mPassiveMetricCollector = new PassiveMetricCollector(mContext, mTestContext); mDBHelper = new DBHelper(mContext); } // Start continuous testing public void startTestRunning_RunInBackground() { new Thread(this).start(); } public void stopTestRunning() { super.setStateChangeToUIHandler(TestRunnerState.STOPPING); isExecutingContinuous = false; } /* * Execute continuous testing: * check for config file * start data collectors * run init tests * while(not stopped) * run tests * submit data */ @Override public void run() { super.setStateChangeToUIHandler(TestRunnerState.STARTING); Looper.prepare(); StateResponseCode response; SK2AppSettings appSettings = SK2AppSettings.getSK2AppSettingsInstance(); mPreviousState = appSettings.getState(); StateEnum state = StateEnum.EXECUTE_QUEUE; appSettings.saveState(state); try { response = Transition.createState(state, mContext).executeState(); } catch (Exception e) { SKPorting.sAssertE(this, "fail to execute " + state + " "); } Storage storage = CachingStorage.getInstance(); mConfig = storage.loadScheduleConfig(); if (mConfig == null) { onEnd(); throw new NullPointerException("null schedule config!"); } isExecutingContinuous = true; super.setStateChangeToUIHandler(TestRunnerState.EXECUTING); // // Change required 29/04/2014 - always enforce that we run a closest target test FIRST for a continuous test! // Code very similar to this is in ManualTestRunner.java. // If we don't do this, then the continuous tests always fail unless you have *first* // already remembered to run a manual test! mConfig.forManualOrContinuousTestEnsureClosestTargetIsRunAtStart(mConfig.continuous_tests); mPassiveMetricCollector.startCollectors(mConfig.dataCollectors); while (isExecutingContinuous()) { executeBatch(); try { state = StateEnum.SUBMIT_RESULTS_ANONYMOUS; response = Transition.createState(state, mContext).executeState(); } catch (Exception e) { SKPorting.sAssertE(this, "fail to execute " + state + " "); } // // And after first pass-through, remove the closest target test so we don't // // keep running it - this is different to iOS, where we run it every time. // if (mConfig.continuous_tests.size() > 0) { // if (mConfig.continuous_tests.get(0).type.equals(SKConstants.TEST_TYPE_CLOSEST_TARGET)) { // mConfig.continuous_tests.remove(0); // } // } } mPassiveMetricCollector.stopCollectors(); super.setStateChangeToUIHandler(TestRunnerState.STOPPED); onEnd(); } private void executeBatch() { TestContext tc = mTestContext; long startTime = System.currentTimeMillis(); List<JSONObject> testsResults = new ArrayList<>(); HashMap<String, Object> batch = new HashMap<>(); TestExecutor te = new TestExecutor(tc); batch.put(TestBatch.JSON_DTIME, startTime); batch.put(TestBatch.JSON_RUNMANUALLY, "0"); ConditionGroupResult tr = new ConditionGroupResult(); for (TestDescription td : mConfig.continuous_tests) { te.executeTest(td, tr); List<JSONObject> theResult = com.samknows.measurement.storage.StorageTestResult.testOutput(te.getExecutingTest(), td.type); if (theResult != null) { testsResults.addAll(theResult); } } List<JSONObject> passiveMetrics = mPassiveMetricCollector.collectMetricsIntoResultsContainer(te.getResultsContainer()); long batchId = mDBHelper.insertTestBatch(new JSONObject(batch), testsResults, passiveMetrics); te.save(JSON_SUBMISSION_TYPE, batchId); } private void onEnd() { SK2AppSettings appSettings = SK2AppSettings.getSK2AppSettingsInstance(); appSettings.saveState(mPreviousState); } // // Properties and methods to get and modify the execution status of continuous testing // private static boolean isExecutingContinuous = false; public boolean isExecutingContinuous() { return isExecutingContinuous; } }