blob: 2bc7bb9cdacbd527e65d5f0b70140656a2f1f316 [file] [log] [blame]
Brad Ebinger12ec7f22016-05-05 10:40:57 -07001/*
2 * Copyright (C) 2016 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License
15 */
16
17package com.android;
18
Brad Ebingera68a4972020-01-30 17:31:23 -080019import static org.mockito.Mockito.spy;
20
Brad Ebinger12ec7f22016-05-05 10:40:57 -070021import android.os.Handler;
Brad Ebinger32925b82016-12-02 13:01:49 -080022import android.os.Looper;
Sanket Padawed9a427e2017-06-08 12:03:07 -070023import android.util.Log;
Brad Ebinger12ec7f22016-05-05 10:40:57 -070024
Brad Ebingera15005b2020-04-29 15:20:38 -070025import com.android.internal.telephony.PhoneConfigurationManager;
26
Sarah Chine04784a2022-10-31 20:32:34 -070027import org.junit.After;
28import org.junit.Before;
tom hsu0b59d292022-09-29 23:49:21 +080029import org.junit.Rule;
30import org.mockito.junit.MockitoJUnit;
31import org.mockito.junit.MockitoRule;
Brad Ebinger12ec7f22016-05-05 10:40:57 -070032
Sarah Chine04784a2022-10-31 20:32:34 -070033import java.lang.reflect.Field;
34import java.util.HashMap;
35import java.util.Iterator;
36import java.util.LinkedList;
Brad Ebinger12ec7f22016-05-05 10:40:57 -070037import java.util.concurrent.CountDownLatch;
Brad Ebinger63b6f5a2020-10-27 11:43:35 -070038import java.util.concurrent.Executor;
Brad Ebinger12ec7f22016-05-05 10:40:57 -070039import java.util.concurrent.TimeUnit;
40
41/**
42 * Helper class to load Mockito Resources into a test.
43 */
44public class TelephonyTestBase {
tom hsu0b59d292022-09-29 23:49:21 +080045 @Rule public final MockitoRule mocks = MockitoJUnit.rule();
Brad Ebinger12ec7f22016-05-05 10:40:57 -070046
Brad Ebinger792729e2019-12-09 16:12:57 -080047 protected TestContext mContext;
Brad Ebinger12ec7f22016-05-05 10:40:57 -070048
Sarah Chine04784a2022-10-31 20:32:34 -070049 private final HashMap<InstanceKey, Object> mOldInstances = new HashMap<>();
50 private final LinkedList<InstanceKey> mInstanceKeys = new LinkedList<>();
51
52 @Before
Brad Ebinger12ec7f22016-05-05 10:40:57 -070053 public void setUp() throws Exception {
Brad Ebinger32925b82016-12-02 13:01:49 -080054 if (Looper.myLooper() == null) {
55 Looper.prepare();
56 }
Tomasz Wasilczyk1c8068b2024-10-29 15:10:04 -070057
58 mContext = spy(new TestContext());
Brad Ebinger12ec7f22016-05-05 10:40:57 -070059 }
60
Sarah Chine04784a2022-10-31 20:32:34 -070061 @After
Brad Ebinger12ec7f22016-05-05 10:40:57 -070062 public void tearDown() throws Exception {
Brad Ebingera15005b2020-04-29 15:20:38 -070063 // Ensure there are no static references to handlers after test completes.
64 PhoneConfigurationManager.unregisterAllMultiSimConfigChangeRegistrants();
Sarah Chine04784a2022-10-31 20:32:34 -070065 restoreInstances();
Brad Ebinger12ec7f22016-05-05 10:40:57 -070066 }
67
Brad Ebinger63b6f5a2020-10-27 11:43:35 -070068 protected final boolean waitForExecutorAction(Executor executor, long timeoutMillis) {
69 final CountDownLatch lock = new CountDownLatch(1);
Brad Ebinger63b6f5a2020-10-27 11:43:35 -070070 executor.execute(() -> {
Brad Ebinger63b6f5a2020-10-27 11:43:35 -070071 lock.countDown();
72 });
73 while (lock.getCount() > 0) {
74 try {
75 return lock.await(timeoutMillis, TimeUnit.MILLISECONDS);
76 } catch (InterruptedException e) {
77 // do nothing
78 }
79 }
80 return true;
81 }
82
Brad Ebinger12ec7f22016-05-05 10:40:57 -070083 protected final void waitForHandlerAction(Handler h, long timeoutMillis) {
84 final CountDownLatch lock = new CountDownLatch(1);
85 h.post(lock::countDown);
86 while (lock.getCount() > 0) {
87 try {
88 lock.await(timeoutMillis, TimeUnit.MILLISECONDS);
89 } catch (InterruptedException e) {
90 // do nothing
91 }
92 }
93 }
94
95 protected final void waitForHandlerActionDelayed(Handler h, long timeoutMillis, long delayMs) {
96 final CountDownLatch lock = new CountDownLatch(1);
97 h.postDelayed(lock::countDown, delayMs);
98 while (lock.getCount() > 0) {
99 try {
100 lock.await(timeoutMillis, TimeUnit.MILLISECONDS);
101 } catch (InterruptedException e) {
102 // do nothing
103 }
104 }
105 }
Sanket Padawed9a427e2017-06-08 12:03:07 -0700106
107 protected void waitForMs(long ms) {
108 try {
109 Thread.sleep(ms);
110 } catch (InterruptedException e) {
111 Log.e("TelephonyTestBase", "InterruptedException while waiting: " + e);
112 }
113 }
Brad Ebinger792729e2019-12-09 16:12:57 -0800114
Sarah Chine04784a2022-10-31 20:32:34 -0700115 protected synchronized void replaceInstance(final Class c, final String instanceName,
116 final Object obj, final Object newValue)
117 throws Exception {
118 Field field = c.getDeclaredField(instanceName);
119 field.setAccessible(true);
120
121 InstanceKey key = new InstanceKey(c, instanceName, obj);
122 if (!mOldInstances.containsKey(key)) {
123 mOldInstances.put(key, field.get(obj));
124 mInstanceKeys.add(key);
125 }
126 field.set(obj, newValue);
127 }
128
129 private synchronized void restoreInstances() throws Exception {
130 Iterator<InstanceKey> it = mInstanceKeys.descendingIterator();
131
132 while (it.hasNext()) {
133 InstanceKey key = it.next();
134 Field field = key.mClass.getDeclaredField(key.mInstName);
135 field.setAccessible(true);
136 field.set(key.mObj, mOldInstances.get(key));
137 }
138
139 mInstanceKeys.clear();
140 mOldInstances.clear();
141 }
142
143 private static class InstanceKey {
144 public final Class mClass;
145 public final String mInstName;
146 public final Object mObj;
147 InstanceKey(final Class c, final String instName, final Object obj) {
148 mClass = c;
149 mInstName = instName;
150 mObj = obj;
151 }
152
153 @Override
154 public int hashCode() {
155 return (mClass.getName().hashCode() * 31 + mInstName.hashCode()) * 31;
156 }
157
158 @Override
159 public boolean equals(Object obj) {
160 if (obj == null || obj.getClass() != getClass()) {
161 return false;
162 }
163
164 InstanceKey other = (InstanceKey) obj;
165 return (other.mClass == mClass && other.mInstName.equals(mInstName)
166 && other.mObj == mObj);
167 }
168 }
169
Brad Ebinger792729e2019-12-09 16:12:57 -0800170 protected TestContext getTestContext() {
171 return mContext;
172 }
Brad Ebinger12ec7f22016-05-05 10:40:57 -0700173}