blob: b1e6194e0c92c25785946162e942c3bf5a6bd1d2 [file] [log] [blame]
/*
* Copyright (C) 2018 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 com.google.android.startop.iorap
import android.os.ServiceManager
import androidx.test.filters.MediumTest
import org.junit.Test
import org.mockito.Mockito.argThat
import org.mockito.Mockito.eq
import org.mockito.Mockito.inOrder
import org.mockito.Mockito.spy
import org.mockito.Mockito.timeout
// @Ignore("Test is disabled until iorapd is added to init and there's selinux policies for it")
@MediumTest
class IIorapIntegrationTest {
/**
* @throws ServiceManager.ServiceNotFoundException if iorapd service could not be found
*/
private val iorapService: IIorap by lazy {
// TODO: connect to 'iorapd.stub' which doesn't actually do any work other than reply.
IIorap.Stub.asInterface(ServiceManager.getServiceOrThrow("iorapd"))
// Use 'adb shell setenforce 0' otherwise this whole test fails,
// because the servicemanager is not allowed to hand out the binder token for iorapd.
// TODO: implement the selinux policies for iorapd.
}
// A dummy binder stub implementation is required to use with mockito#spy.
// Mockito overrides the methods at runtime and tracks how methods were invoked.
open class DummyTaskListener : ITaskListener.Stub() {
// Note: make parameters nullable to avoid the kotlin IllegalStateExceptions
// from using the mockito matchers (eq, argThat, etc).
override fun onProgress(requestId: RequestId?, result: TaskResult?) {
}
override fun onComplete(requestId: RequestId?, result: TaskResult?) {
}
}
private fun testAnyMethod(func: (RequestId) -> Unit) {
val taskListener = spy(DummyTaskListener())!!
try {
iorapService.setTaskListener(taskListener)
// Note: Binder guarantees total order for oneway messages sent to the same binder
// interface, so we don't need any additional blocking here before sending later calls.
// Every new method call should have a unique request id.
val requestId = RequestId.nextValueForSequence()!!
// Apply the specific function under test.
func(requestId)
// Typical mockito behavior is to allow any-order callbacks, but we want to test order.
val inOrder = inOrder(taskListener)
// The "stub" behavior of iorapd is that every request immediately gets a response of
// BEGAN,ONGOING,COMPLETED
inOrder.verify(taskListener, timeout(100))
.onProgress(eq(requestId), argThat { it!!.state == TaskResult.STATE_BEGAN })
inOrder.verify(taskListener, timeout(100))
.onProgress(eq(requestId), argThat { it!!.state == TaskResult.STATE_ONGOING })
inOrder.verify(taskListener, timeout(100))
.onComplete(eq(requestId), argThat { it!!.state == TaskResult.STATE_COMPLETED })
inOrder.verifyNoMoreInteractions()
} finally {
// iorapService.setTaskListener(null)
// FIXME: null is broken, C++ side sees a non-null object.
}
}
@Test
fun testOnPackageEvent() {
/*
testAnyMethod { requestId : RequestId ->
iorapService.onPackageEvent(requestId,
PackageEvent.createReplaced(
Uri.parse("https://www.google.com"), "com.fake.package"))
}
*/
// FIXME: Broken for some reason. C++ side never sees this call.
}
@Test
fun testOnAppIntentEvent() {
testAnyMethod { requestId: RequestId ->
iorapService.onAppIntentEvent(requestId, AppIntentEvent.createDefaultIntentChanged(
ActivityInfo("dont care", "dont care"),
ActivityInfo("dont care 2", "dont care 2")))
}
}
@Test
fun testOnSystemServiceEvent() {
testAnyMethod { requestId: RequestId ->
iorapService.onSystemServiceEvent(requestId,
SystemServiceEvent(SystemServiceEvent.TYPE_START))
}
}
@Test
fun testOnSystemServiceUserEvent() {
testAnyMethod { requestId: RequestId ->
iorapService.onSystemServiceUserEvent(requestId,
SystemServiceUserEvent(SystemServiceUserEvent.TYPE_START_USER, 0))
}
}
}