17add67b949163f981b785a8c23de89d6b17fff93Kevin Jin/* 27add67b949163f981b785a8c23de89d6b17fff93Kevin Jin * Copyright (C) 2013 DroidDriver committers 37add67b949163f981b785a8c23de89d6b17fff93Kevin Jin * 47add67b949163f981b785a8c23de89d6b17fff93Kevin Jin * Licensed under the Apache License, Version 2.0 (the "License"); 57add67b949163f981b785a8c23de89d6b17fff93Kevin Jin * you may not use this file except in compliance with the License. 67add67b949163f981b785a8c23de89d6b17fff93Kevin Jin * You may obtain a copy of the License at 77add67b949163f981b785a8c23de89d6b17fff93Kevin Jin * 87add67b949163f981b785a8c23de89d6b17fff93Kevin Jin * http://www.apache.org/licenses/LICENSE-2.0 97add67b949163f981b785a8c23de89d6b17fff93Kevin Jin * 107add67b949163f981b785a8c23de89d6b17fff93Kevin Jin * Unless required by applicable law or agreed to in writing, software 117add67b949163f981b785a8c23de89d6b17fff93Kevin Jin * distributed under the License is distributed on an "AS IS" BASIS, 127add67b949163f981b785a8c23de89d6b17fff93Kevin Jin * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 137add67b949163f981b785a8c23de89d6b17fff93Kevin Jin * See the License for the specific language governing permissions and 147add67b949163f981b785a8c23de89d6b17fff93Kevin Jin * limitations under the License. 157add67b949163f981b785a8c23de89d6b17fff93Kevin Jin */ 167add67b949163f981b785a8c23de89d6b17fff93Kevin Jin 177add67b949163f981b785a8c23de89d6b17fff93Kevin Jinpackage com.google.android.droiddriver.runner; 187add67b949163f981b785a8c23de89d6b17fff93Kevin Jin 197add67b949163f981b785a8c23de89d6b17fff93Kevin Jinimport android.app.Activity; 200c2c0d1f1d7e1198a4e513f8b8ac2149518844abKevin Jinimport android.os.Build; 217add67b949163f981b785a8c23de89d6b17fff93Kevin Jinimport android.os.Bundle; 227add67b949163f981b785a8c23de89d6b17fff93Kevin Jinimport android.test.AndroidTestRunner; 237add67b949163f981b785a8c23de89d6b17fff93Kevin Jinimport android.test.InstrumentationTestRunner; 240c2c0d1f1d7e1198a4e513f8b8ac2149518844abKevin Jinimport android.test.suitebuilder.TestMethod; 257add67b949163f981b785a8c23de89d6b17fff93Kevin Jinimport android.util.Log; 267add67b949163f981b785a8c23de89d6b17fff93Kevin Jin 270c2c0d1f1d7e1198a4e513f8b8ac2149518844abKevin Jinimport com.android.internal.util.Predicate; 28115eb39036a7a4e500dc94b57975a5693861f654Tony Wickhamimport com.google.android.droiddriver.util.ActivityUtils; 297add67b949163f981b785a8c23de89d6b17fff93Kevin Jinimport com.google.android.droiddriver.util.Logs; 30b18bb64ed9513bedf8222e6915abb5164e9108f9Kevin Jinimport com.google.common.base.Supplier; 310c2c0d1f1d7e1198a4e513f8b8ac2149518844abKevin Jinimport com.google.common.collect.Lists; 327add67b949163f981b785a8c23de89d6b17fff93Kevin Jinimport com.google.common.collect.Sets; 337add67b949163f981b785a8c23de89d6b17fff93Kevin Jin 347add67b949163f981b785a8c23de89d6b17fff93Kevin Jinimport junit.framework.AssertionFailedError; 357add67b949163f981b785a8c23de89d6b17fff93Kevin Jinimport junit.framework.Test; 367add67b949163f981b785a8c23de89d6b17fff93Kevin Jinimport junit.framework.TestListener; 377add67b949163f981b785a8c23de89d6b17fff93Kevin Jin 38df778b5b087c324e1078c6ba692d0aff4f940ac9Kevin Jinimport java.lang.annotation.Annotation; 397add67b949163f981b785a8c23de89d6b17fff93Kevin Jinimport java.util.Iterator; 400c2c0d1f1d7e1198a4e513f8b8ac2149518844abKevin Jinimport java.util.List; 417add67b949163f981b785a8c23de89d6b17fff93Kevin Jinimport java.util.Set; 427add67b949163f981b785a8c23de89d6b17fff93Kevin Jin 437add67b949163f981b785a8c23de89d6b17fff93Kevin Jin/** 447add67b949163f981b785a8c23de89d6b17fff93Kevin Jin * Adds activity watcher to InstrumentationTestRunner. 457add67b949163f981b785a8c23de89d6b17fff93Kevin Jin */ 467add67b949163f981b785a8c23de89d6b17fff93Kevin Jinpublic class TestRunner extends InstrumentationTestRunner { 477add67b949163f981b785a8c23de89d6b17fff93Kevin Jin private final Set<Activity> activities = Sets.newIdentityHashSet(); 487add67b949163f981b785a8c23de89d6b17fff93Kevin Jin private final AndroidTestRunner androidTestRunner = new AndroidTestRunner(); 49b18bb64ed9513bedf8222e6915abb5164e9108f9Kevin Jin private Activity runningActivity; 507add67b949163f981b785a8c23de89d6b17fff93Kevin Jin 517add67b949163f981b785a8c23de89d6b17fff93Kevin Jin /** 527add67b949163f981b785a8c23de89d6b17fff93Kevin Jin * Returns an {@link AndroidTestRunner} that is shared by this and super, such 537add67b949163f981b785a8c23de89d6b17fff93Kevin Jin * that we can add custom {@link TestListener}s. 547add67b949163f981b785a8c23de89d6b17fff93Kevin Jin */ 557add67b949163f981b785a8c23de89d6b17fff93Kevin Jin @Override 567add67b949163f981b785a8c23de89d6b17fff93Kevin Jin protected AndroidTestRunner getAndroidTestRunner() { 577add67b949163f981b785a8c23de89d6b17fff93Kevin Jin return androidTestRunner; 587add67b949163f981b785a8c23de89d6b17fff93Kevin Jin } 597add67b949163f981b785a8c23de89d6b17fff93Kevin Jin 607add67b949163f981b785a8c23de89d6b17fff93Kevin Jin /** 617add67b949163f981b785a8c23de89d6b17fff93Kevin Jin * {@inheritDoc} 627add67b949163f981b785a8c23de89d6b17fff93Kevin Jin * <p> 637add67b949163f981b785a8c23de89d6b17fff93Kevin Jin * Adds a {@link TestListener} that finishes all created activities. 647add67b949163f981b785a8c23de89d6b17fff93Kevin Jin */ 657add67b949163f981b785a8c23de89d6b17fff93Kevin Jin @Override 667add67b949163f981b785a8c23de89d6b17fff93Kevin Jin public void onStart() { 677add67b949163f981b785a8c23de89d6b17fff93Kevin Jin getAndroidTestRunner().addTestListener(new TestListener() { 687add67b949163f981b785a8c23de89d6b17fff93Kevin Jin @Override 697add67b949163f981b785a8c23de89d6b17fff93Kevin Jin public void endTest(Test test) { 707add67b949163f981b785a8c23de89d6b17fff93Kevin Jin runOnMainSync(new Runnable() { 717add67b949163f981b785a8c23de89d6b17fff93Kevin Jin @Override 727add67b949163f981b785a8c23de89d6b17fff93Kevin Jin public void run() { 737add67b949163f981b785a8c23de89d6b17fff93Kevin Jin Iterator<Activity> iterator = activities.iterator(); 747add67b949163f981b785a8c23de89d6b17fff93Kevin Jin while (iterator.hasNext()) { 757add67b949163f981b785a8c23de89d6b17fff93Kevin Jin Activity activity = iterator.next(); 767add67b949163f981b785a8c23de89d6b17fff93Kevin Jin iterator.remove(); 777add67b949163f981b785a8c23de89d6b17fff93Kevin Jin if (!activity.isFinishing()) { 787add67b949163f981b785a8c23de89d6b17fff93Kevin Jin try { 796316362de61fca700d7d5a455ad5c0ac9717c365Kevin Jin Logs.log(Log.INFO, "Stopping activity: " + activity); 807add67b949163f981b785a8c23de89d6b17fff93Kevin Jin activity.finish(); 817add67b949163f981b785a8c23de89d6b17fff93Kevin Jin } catch (RuntimeException e) { 826316362de61fca700d7d5a455ad5c0ac9717c365Kevin Jin Logs.log(Log.ERROR, e, "Failed to stop activity"); 837add67b949163f981b785a8c23de89d6b17fff93Kevin Jin } 847add67b949163f981b785a8c23de89d6b17fff93Kevin Jin } 857add67b949163f981b785a8c23de89d6b17fff93Kevin Jin } 867add67b949163f981b785a8c23de89d6b17fff93Kevin Jin } 877add67b949163f981b785a8c23de89d6b17fff93Kevin Jin }); 887add67b949163f981b785a8c23de89d6b17fff93Kevin Jin } 897add67b949163f981b785a8c23de89d6b17fff93Kevin Jin 907add67b949163f981b785a8c23de89d6b17fff93Kevin Jin @Override 917add67b949163f981b785a8c23de89d6b17fff93Kevin Jin public void addError(Test arg0, Throwable arg1) {} 927add67b949163f981b785a8c23de89d6b17fff93Kevin Jin 937add67b949163f981b785a8c23de89d6b17fff93Kevin Jin @Override 947add67b949163f981b785a8c23de89d6b17fff93Kevin Jin public void addFailure(Test arg0, AssertionFailedError arg1) {} 957add67b949163f981b785a8c23de89d6b17fff93Kevin Jin 967add67b949163f981b785a8c23de89d6b17fff93Kevin Jin @Override 977add67b949163f981b785a8c23de89d6b17fff93Kevin Jin public void startTest(Test arg0) {} 987add67b949163f981b785a8c23de89d6b17fff93Kevin Jin }); 99b18bb64ed9513bedf8222e6915abb5164e9108f9Kevin Jin 100b18bb64ed9513bedf8222e6915abb5164e9108f9Kevin Jin ActivityUtils.setRunningActivitySupplier(new Supplier<Activity>() { 101b18bb64ed9513bedf8222e6915abb5164e9108f9Kevin Jin @Override 102b18bb64ed9513bedf8222e6915abb5164e9108f9Kevin Jin public Activity get() { 103b18bb64ed9513bedf8222e6915abb5164e9108f9Kevin Jin return runningActivity; 104b18bb64ed9513bedf8222e6915abb5164e9108f9Kevin Jin } 105b18bb64ed9513bedf8222e6915abb5164e9108f9Kevin Jin }); 106b18bb64ed9513bedf8222e6915abb5164e9108f9Kevin Jin 1077add67b949163f981b785a8c23de89d6b17fff93Kevin Jin super.onStart(); 1087add67b949163f981b785a8c23de89d6b17fff93Kevin Jin } 1097add67b949163f981b785a8c23de89d6b17fff93Kevin Jin 1100c2c0d1f1d7e1198a4e513f8b8ac2149518844abKevin Jin // Overrides InstrumentationTestRunner 1110c2c0d1f1d7e1198a4e513f8b8ac2149518844abKevin Jin List<Predicate<TestMethod>> getBuilderRequirements() { 1120c2c0d1f1d7e1198a4e513f8b8ac2149518844abKevin Jin List<Predicate<TestMethod>> requirements = Lists.newArrayList(); 1130c2c0d1f1d7e1198a4e513f8b8ac2149518844abKevin Jin requirements.add(new Predicate<TestMethod>() { 1140c2c0d1f1d7e1198a4e513f8b8ac2149518844abKevin Jin @Override 1150c2c0d1f1d7e1198a4e513f8b8ac2149518844abKevin Jin public boolean apply(TestMethod arg0) { 116df778b5b087c324e1078c6ba692d0aff4f940ac9Kevin Jin MinSdkVersion minSdkVersion = getAnnotation(arg0, MinSdkVersion.class); 117df778b5b087c324e1078c6ba692d0aff4f940ac9Kevin Jin if (minSdkVersion != null && minSdkVersion.value() > Build.VERSION.SDK_INT) { 118df778b5b087c324e1078c6ba692d0aff4f940ac9Kevin Jin Logs.logfmt(Log.INFO, "filtered %s#%s: MinSdkVersion=%d", arg0.getEnclosingClassname(), 119df778b5b087c324e1078c6ba692d0aff4f940ac9Kevin Jin arg0.getName(), minSdkVersion.value()); 120df778b5b087c324e1078c6ba692d0aff4f940ac9Kevin Jin return false; 121df778b5b087c324e1078c6ba692d0aff4f940ac9Kevin Jin } 122df778b5b087c324e1078c6ba692d0aff4f940ac9Kevin Jin 123df778b5b087c324e1078c6ba692d0aff4f940ac9Kevin Jin UseUiAutomation useUiAutomation = getAnnotation(arg0, UseUiAutomation.class); 124df778b5b087c324e1078c6ba692d0aff4f940ac9Kevin Jin if (useUiAutomation != null && Build.VERSION.SDK_INT < Build.VERSION_CODES.JELLY_BEAN_MR2) { 125df778b5b087c324e1078c6ba692d0aff4f940ac9Kevin Jin Logs.logfmt(Log.INFO, 126df778b5b087c324e1078c6ba692d0aff4f940ac9Kevin Jin "filtered %s#%s: Has @UseUiAutomation, but ro.build.version.sdk=%d", 127df778b5b087c324e1078c6ba692d0aff4f940ac9Kevin Jin arg0.getEnclosingClassname(), arg0.getName(), Build.VERSION.SDK_INT); 128df778b5b087c324e1078c6ba692d0aff4f940ac9Kevin Jin return false; 1290c2c0d1f1d7e1198a4e513f8b8ac2149518844abKevin Jin } 130df778b5b087c324e1078c6ba692d0aff4f940ac9Kevin Jin return true; 131df778b5b087c324e1078c6ba692d0aff4f940ac9Kevin Jin } 132df778b5b087c324e1078c6ba692d0aff4f940ac9Kevin Jin 133df778b5b087c324e1078c6ba692d0aff4f940ac9Kevin Jin private <T extends Annotation> T getAnnotation(TestMethod testMethod, Class<T> clazz) { 134df778b5b087c324e1078c6ba692d0aff4f940ac9Kevin Jin T annotation = testMethod.getAnnotation(clazz); 135df778b5b087c324e1078c6ba692d0aff4f940ac9Kevin Jin if (annotation == null) { 136df778b5b087c324e1078c6ba692d0aff4f940ac9Kevin Jin annotation = testMethod.getEnclosingClass().getAnnotation(clazz); 1370c2c0d1f1d7e1198a4e513f8b8ac2149518844abKevin Jin } 138df778b5b087c324e1078c6ba692d0aff4f940ac9Kevin Jin return annotation; 1390c2c0d1f1d7e1198a4e513f8b8ac2149518844abKevin Jin } 1400c2c0d1f1d7e1198a4e513f8b8ac2149518844abKevin Jin }); 1410c2c0d1f1d7e1198a4e513f8b8ac2149518844abKevin Jin return requirements; 1420c2c0d1f1d7e1198a4e513f8b8ac2149518844abKevin Jin } 1430c2c0d1f1d7e1198a4e513f8b8ac2149518844abKevin Jin 1447add67b949163f981b785a8c23de89d6b17fff93Kevin Jin @Override 1457add67b949163f981b785a8c23de89d6b17fff93Kevin Jin public void callActivityOnDestroy(Activity activity) { 1467add67b949163f981b785a8c23de89d6b17fff93Kevin Jin super.callActivityOnDestroy(activity); 1477add67b949163f981b785a8c23de89d6b17fff93Kevin Jin activities.remove(activity); 1487add67b949163f981b785a8c23de89d6b17fff93Kevin Jin } 1497add67b949163f981b785a8c23de89d6b17fff93Kevin Jin 1507add67b949163f981b785a8c23de89d6b17fff93Kevin Jin @Override 1517add67b949163f981b785a8c23de89d6b17fff93Kevin Jin public void callActivityOnCreate(Activity activity, Bundle bundle) { 1527add67b949163f981b785a8c23de89d6b17fff93Kevin Jin super.callActivityOnCreate(activity, bundle); 1537add67b949163f981b785a8c23de89d6b17fff93Kevin Jin activities.add(activity); 1547add67b949163f981b785a8c23de89d6b17fff93Kevin Jin } 155115eb39036a7a4e500dc94b57975a5693861f654Tony Wickham 156115eb39036a7a4e500dc94b57975a5693861f654Tony Wickham @Override 157115eb39036a7a4e500dc94b57975a5693861f654Tony Wickham public void callActivityOnResume(Activity activity) { 158115eb39036a7a4e500dc94b57975a5693861f654Tony Wickham super.callActivityOnResume(activity); 159b18bb64ed9513bedf8222e6915abb5164e9108f9Kevin Jin runningActivity = activity; 160115eb39036a7a4e500dc94b57975a5693861f654Tony Wickham } 161115eb39036a7a4e500dc94b57975a5693861f654Tony Wickham 162115eb39036a7a4e500dc94b57975a5693861f654Tony Wickham @Override 163115eb39036a7a4e500dc94b57975a5693861f654Tony Wickham public void callActivityOnPause(Activity activity) { 164115eb39036a7a4e500dc94b57975a5693861f654Tony Wickham super.callActivityOnPause(activity); 165115eb39036a7a4e500dc94b57975a5693861f654Tony Wickham if (activity == ActivityUtils.getRunningActivity()) { 166b18bb64ed9513bedf8222e6915abb5164e9108f9Kevin Jin runningActivity = null; 167115eb39036a7a4e500dc94b57975a5693861f654Tony Wickham } 168115eb39036a7a4e500dc94b57975a5693861f654Tony Wickham } 1697add67b949163f981b785a8c23de89d6b17fff93Kevin Jin} 170