| /* |
| * Copyright (C) 2013 DroidDriver committers |
| * |
| * Licensed under the Apache License, Version 2.0 (the "License"); |
| * you may not use this file except in compliance with the License. |
| * You may obtain a copy of the License at |
| * |
| * http://www.apache.org/licenses/LICENSE-2.0 |
| * |
| * Unless required by applicable law or agreed to in writing, software |
| * distributed under the License is distributed on an "AS IS" BASIS, |
| * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
| * See the License for the specific language governing permissions and |
| * limitations under the License. |
| */ |
| |
| package io.appium.droiddriver.runner; |
| |
| import android.app.Activity; |
| import android.os.Build; |
| import android.os.Bundle; |
| import android.test.AndroidTestRunner; |
| import android.test.InstrumentationTestRunner; |
| import android.test.suitebuilder.TestMethod; |
| import android.util.Log; |
| |
| import com.android.internal.util.Predicate; |
| |
| import junit.framework.AssertionFailedError; |
| import junit.framework.Test; |
| import junit.framework.TestListener; |
| |
| import java.lang.annotation.Annotation; |
| import java.util.ArrayList; |
| import java.util.HashSet; |
| import java.util.List; |
| import java.util.Set; |
| |
| import io.appium.droiddriver.helpers.DroidDrivers; |
| import io.appium.droiddriver.util.ActivityUtils; |
| import io.appium.droiddriver.util.ActivityUtils.Supplier; |
| import io.appium.droiddriver.util.InstrumentationUtils; |
| import io.appium.droiddriver.util.Logs; |
| |
| /** |
| * Adds activity watcher to InstrumentationTestRunner. |
| * |
| * @deprecated Use android.support.test.runner.AndroidJUnitRunner instead. |
| */ |
| @Deprecated |
| public class TestRunner extends InstrumentationTestRunner { |
| private final Set<Activity> activities = new HashSet<Activity>(); |
| private final AndroidTestRunner androidTestRunner = new AndroidTestRunner(); |
| private volatile Activity runningActivity; |
| |
| /** |
| * Returns an {@link AndroidTestRunner} that is shared by this and super, such |
| * that we can add custom {@link TestListener}s. |
| */ |
| @Override |
| protected AndroidTestRunner getAndroidTestRunner() { |
| return androidTestRunner; |
| } |
| |
| /** |
| * {@inheritDoc} |
| * <p> |
| * Initializes {@link InstrumentationUtils}. |
| */ |
| @Override |
| public void onCreate(Bundle arguments) { |
| InstrumentationUtils.init(this, arguments); |
| super.onCreate(arguments); |
| } |
| |
| /** |
| * {@inheritDoc} |
| * <p> |
| * Adds a {@link TestListener} that finishes all created activities. |
| */ |
| @Override |
| public void onStart() { |
| getAndroidTestRunner().addTestListener(new TestListener() { |
| @Override |
| public void endTest(Test test) { |
| // Try to finish activity on best-effort basis - TestListener should |
| // not throw. |
| final Activity[] activitiesCopy; |
| synchronized (activities) { |
| if (activities.isEmpty()) { |
| return; |
| } |
| activitiesCopy = activities.toArray(new Activity[activities.size()]); |
| } |
| |
| try { |
| InstrumentationUtils.runOnMainSyncWithTimeout(new Runnable() { |
| @Override |
| public void run() { |
| for (Activity activity : activitiesCopy) { |
| if (!activity.isFinishing()) { |
| try { |
| Logs.log(Log.INFO, "Stopping activity: " + activity); |
| activity.finish(); |
| } catch (Throwable e) { |
| Logs.log(Log.ERROR, e, "Failed to stop activity"); |
| } |
| } |
| } |
| } |
| }); |
| } catch (Throwable e) { |
| Logs.log(Log.ERROR, e); |
| } |
| |
| // We've done what we can. Clear activities if any are left. |
| synchronized (activities) { |
| activities.clear(); |
| runningActivity = null; |
| } |
| } |
| |
| @Override |
| public void addError(Test arg0, Throwable arg1) {} |
| |
| @Override |
| public void addFailure(Test arg0, AssertionFailedError arg1) {} |
| |
| @Override |
| public void startTest(Test arg0) {} |
| }); |
| |
| ActivityUtils.setRunningActivitySupplier(new Supplier<Activity>() { |
| @Override |
| public Activity get() { |
| return runningActivity; |
| } |
| }); |
| |
| super.onStart(); |
| } |
| |
| // Overrides InstrumentationTestRunner |
| List<Predicate<TestMethod>> getBuilderRequirements() { |
| List<Predicate<TestMethod>> requirements = new ArrayList<Predicate<TestMethod>>(); |
| requirements.add(new Predicate<TestMethod>() { |
| @Override |
| public boolean apply(TestMethod arg0) { |
| MinSdkVersion minSdkVersion = getAnnotation(arg0, MinSdkVersion.class); |
| if (minSdkVersion != null && minSdkVersion.value() > Build.VERSION.SDK_INT) { |
| Logs.logfmt(Log.INFO, "filtered %s#%s: MinSdkVersion=%d", arg0.getEnclosingClassname(), |
| arg0.getName(), minSdkVersion.value()); |
| return false; |
| } |
| |
| UseUiAutomation useUiAutomation = getAnnotation(arg0, UseUiAutomation.class); |
| if (useUiAutomation != null && !DroidDrivers.hasUiAutomation()) { |
| Logs.logfmt(Log.INFO, |
| "filtered %s#%s: Has @UseUiAutomation, but ro.build.version.sdk=%d", |
| arg0.getEnclosingClassname(), arg0.getName(), Build.VERSION.SDK_INT); |
| return false; |
| } |
| return true; |
| } |
| |
| private <T extends Annotation> T getAnnotation(TestMethod testMethod, Class<T> clazz) { |
| T annotation = testMethod.getAnnotation(clazz); |
| if (annotation == null) { |
| annotation = testMethod.getEnclosingClass().getAnnotation(clazz); |
| } |
| return annotation; |
| } |
| }); |
| return requirements; |
| } |
| |
| @Override |
| public void callActivityOnDestroy(Activity activity) { |
| super.callActivityOnDestroy(activity); |
| synchronized (activities) { |
| activities.remove(activity); |
| } |
| } |
| |
| @Override |
| public void callActivityOnCreate(Activity activity, Bundle bundle) { |
| super.callActivityOnCreate(activity, bundle); |
| synchronized (activities) { |
| activities.add(activity); |
| } |
| } |
| |
| @Override |
| public void callActivityOnResume(Activity activity) { |
| super.callActivityOnResume(activity); |
| runningActivity = activity; |
| } |
| |
| @Override |
| public void callActivityOnPause(Activity activity) { |
| super.callActivityOnPause(activity); |
| if (activity == runningActivity) { |
| runningActivity = null; |
| } |
| } |
| } |