1 /*
<lambda>null2  * Copyright (C) 2018 The Android Open Source Project
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file
5  * except in compliance with the License. You may obtain a copy of the License at
6  *
7  *      http://www.apache.org/licenses/LICENSE-2.0
8  *
9  * Unless required by applicable law or agreed to in writing, software distributed under the
10  * License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
11  * KIND, either express or implied. See the License for the specific language governing
12  * permissions and limitations under the License.
13  */
14 
15 package com.google.android.startop.iorap
16 
17 import android.os.ServiceManager
18 import androidx.test.filters.MediumTest
19 import org.junit.Test
20 import org.mockito.Mockito.argThat
21 import org.mockito.Mockito.eq
22 import org.mockito.Mockito.inOrder
23 import org.mockito.Mockito.spy
24 import org.mockito.Mockito.timeout
25 
26 // @Ignore("Test is disabled until iorapd is added to init and there's selinux policies for it")
27 @MediumTest
28 class IIorapIntegrationTest {
29     /**
30      * @throws ServiceManager.ServiceNotFoundException if iorapd service could not be found
31      */
32     private val iorapService: IIorap by lazy {
33         // TODO: connect to 'iorapd.stub' which doesn't actually do any work other than reply.
34         IIorap.Stub.asInterface(ServiceManager.getServiceOrThrow("iorapd"))
35 
36         // Use 'adb shell setenforce 0' otherwise this whole test fails,
37         // because the servicemanager is not allowed to hand out the binder token for iorapd.
38 
39         // TODO: implement the selinux policies for iorapd.
40     }
41 
42     // A dummy binder stub implementation is required to use with mockito#spy.
43     // Mockito overrides the methods at runtime and tracks how methods were invoked.
44     open class DummyTaskListener : ITaskListener.Stub() {
45         // Note: make parameters nullable to avoid the kotlin IllegalStateExceptions
46         // from using the mockito matchers (eq, argThat, etc).
47         override fun onProgress(requestId: RequestId?, result: TaskResult?) {
48         }
49 
50         override fun onComplete(requestId: RequestId?, result: TaskResult?) {
51         }
52     }
53 
54     private fun testAnyMethod(func: (RequestId) -> Unit) {
55         val taskListener = spy(DummyTaskListener())!!
56 
57         try {
58             iorapService.setTaskListener(taskListener)
59             // Note: Binder guarantees total order for oneway messages sent to the same binder
60             // interface, so we don't need any additional blocking here before sending later calls.
61 
62             // Every new method call should have a unique request id.
63             val requestId = RequestId.nextValueForSequence()!!
64 
65             // Apply the specific function under test.
66             func(requestId)
67 
68             // Typical mockito behavior is to allow any-order callbacks, but we want to test order.
69             val inOrder = inOrder(taskListener)
70 
71             // The "stub" behavior of iorapd is that every request immediately gets a response of
72             //   BEGAN,ONGOING,COMPLETED
73             inOrder.verify(taskListener, timeout(100))
74                 .onProgress(eq(requestId), argThat { it!!.state == TaskResult.STATE_BEGAN })
75             inOrder.verify(taskListener, timeout(100))
76                 .onProgress(eq(requestId), argThat { it!!.state == TaskResult.STATE_ONGOING })
77             inOrder.verify(taskListener, timeout(100))
78                 .onComplete(eq(requestId), argThat { it!!.state == TaskResult.STATE_COMPLETED })
79             inOrder.verifyNoMoreInteractions()
80         } finally {
81             // iorapService.setTaskListener(null)
82             // FIXME: null is broken, C++ side sees a non-null object.
83         }
84     }
85 
86     @Test
87     fun testOnPackageEvent() {
88         /*
89         testAnyMethod { requestId : RequestId ->
90             iorapService.onPackageEvent(requestId,
91                     PackageEvent.createReplaced(
92                             Uri.parse("https://www.google.com"), "com.fake.package"))
93         }
94         */
95         // FIXME: Broken for some reason. C++ side never sees this call.
96     }
97 
98     @Test
99     fun testOnAppIntentEvent() {
100         testAnyMethod { requestId: RequestId ->
101             iorapService.onAppIntentEvent(requestId, AppIntentEvent.createDefaultIntentChanged(
102                     ActivityInfo("dont care", "dont care"),
103                     ActivityInfo("dont care 2", "dont care 2")))
104         }
105     }
106 
107     @Test
108     fun testOnSystemServiceEvent() {
109         testAnyMethod { requestId: RequestId ->
110             iorapService.onSystemServiceEvent(requestId,
111                     SystemServiceEvent(SystemServiceEvent.TYPE_START))
112         }
113     }
114 
115     @Test
116     fun testOnSystemServiceUserEvent() {
117         testAnyMethod { requestId: RequestId ->
118             iorapService.onSystemServiceUserEvent(requestId,
119                     SystemServiceUserEvent(SystemServiceUserEvent.TYPE_START_USER, 0))
120         }
121     }
122 }
123