OrchestratedInstrumentationListener.java
/*
* Copyright (C) 2016 The Android Open Source Project
*
* 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 androidx.test.orchestrator.instrumentationlistener;
import static androidx.test.orchestrator.listeners.OrchestrationListenerManager.KEY_TEST_EVENT;
import android.app.Service;
import android.content.ComponentName;
import android.content.Context;
import android.content.Intent;
import android.content.ServiceConnection;
import android.os.Bundle;
import android.os.IBinder;
import android.os.RemoteException;
import android.util.Log;
import androidx.test.orchestrator.callback.OrchestratorCallback;
import androidx.test.orchestrator.junit.BundleJUnitUtils;
import androidx.test.orchestrator.listeners.OrchestrationListenerManager.TestEvent;
import org.junit.runner.Description;
import org.junit.runner.Result;
import org.junit.runner.notification.Failure;
import org.junit.runner.notification.RunListener;
/**
* A {@link RunListener} for the orchestrated instrumentation to communicate information back to the
* {@link androidx.test.orchestrator.OrchestratorService}. Not to be attached to {@link
* androidx.test.orchestrator.AndroidTestOrchestrator} itself.
*/
public final class OrchestratedInstrumentationListener extends RunListener {
private static final String TAG = "OrchestrationListener";
private static final String ORCHESTRATOR_PACKAGE = "androidx.test.orchestrator";
private static final String ODO_SERVICE_PACKAGE =
"androidx.test.orchestrator.OrchestratorService";
private final OnConnectListener listener;
OrchestratorCallback odoCallback;
/** Interface to notify when the listener has connected to the orchestrator. */
public interface OnConnectListener {
void onOrchestratorConnect();
}
public OrchestratedInstrumentationListener(OnConnectListener listener) {
super();
this.listener = listener;
}
private final ServiceConnection connection =
new ServiceConnection() {
@Override
public void onServiceConnected(ComponentName className, IBinder service) {
odoCallback = OrchestratorCallback.Stub.asInterface(service);
Log.i(TAG, "OrchestrationListener connected to service");
listener.onOrchestratorConnect();
}
@Override
public void onServiceDisconnected(ComponentName className) {
odoCallback = null;
Log.i(TAG, "OrchestrationListener disconnected from service");
}
};
public void connect(Context context) {
Intent intent = new Intent(ODO_SERVICE_PACKAGE);
intent.setPackage(ORCHESTRATOR_PACKAGE);
if (!context.bindService(intent, connection, Service.BIND_AUTO_CREATE)) {
throw new RuntimeException("Cannot connect to " + ODO_SERVICE_PACKAGE);
}
}
@Override
public void testRunStarted(Description description) {
try {
sendTestNotification(
TestEvent.TEST_RUN_STARTED, BundleJUnitUtils.getBundleFromDescription(description));
} catch (RemoteException e) {
Log.e(TAG, "Unable to send TestRunStarted Status to Orchestrator", e);
}
}
@Override
public void testRunFinished(Result result) {
try {
sendTestNotification(
TestEvent.TEST_RUN_FINISHED, BundleJUnitUtils.getBundleFromResult(result));
} catch (RemoteException e) {
Log.e(TAG, "Unable to send TestRunFinished Status to Orchestrator", e);
}
}
@Override
public void testStarted(Description description) {
try {
sendTestNotification(
TestEvent.TEST_STARTED, BundleJUnitUtils.getBundleFromDescription(description));
} catch (RemoteException e) {
Log.e(TAG, "Unable to send TestStarted Status to Orchestrator", e);
}
}
@Override
public void testFinished(Description description) {
try {
sendTestNotification(
TestEvent.TEST_FINISHED, BundleJUnitUtils.getBundleFromDescription(description));
} catch (RemoteException e) {
Log.e(TAG, "Unable to send TestFinished Status to Orchestrator", e);
}
}
@Override
public void testFailure(Failure failure) {
try {
sendTestNotification(TestEvent.TEST_FAILURE, BundleJUnitUtils.getBundleFromFailure(failure));
} catch (RemoteException e) {
throw new IllegalStateException("Unable to send TestFailure status, terminating", e);
}
}
@Override
public void testAssumptionFailure(Failure failure) {
try {
sendTestNotification(
TestEvent.TEST_ASSUMPTION_FAILURE, BundleJUnitUtils.getBundleFromFailure(failure));
} catch (RemoteException e) {
throw new IllegalStateException(
"Unable to send TestAssumptionFailure status, terminating", e);
}
}
@Override
public void testIgnored(Description description) {
try {
sendTestNotification(
TestEvent.TEST_IGNORED, BundleJUnitUtils.getBundleFromDescription(description));
} catch (RemoteException e) {
Log.e(TAG, "Unable to send TestIgnored Status to Orchestrator", e);
}
}
public void sendTestNotification(TestEvent type, Bundle bundle) throws RemoteException {
if (null == odoCallback) {
throw new IllegalStateException("Unable to send notification, callback is null");
}
bundle.putString(KEY_TEST_EVENT, type.toString());
odoCallback.sendTestNotification(bundle);
}
public void addTests(Description description) {
if (description.isEmpty()) {
return;
}
if (description.isTest()) {
addTest(description.getClassName() + "#" + description.getMethodName());
} else {
for (Description child : description.getChildren()) {
addTests(child);
}
}
}
public void addTest(String test) {
if (null == odoCallback) {
throw new IllegalStateException("Unable to send test, callback is null");
}
try {
odoCallback.addTest(test);
} catch (RemoteException e) {
Log.e(TAG, "Unable to send test", e);
}
}
}