1 /* 2 * Copyright (C) 2024 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 package com.android.adservices.shared.testing.concurrency; 17 18 import static org.junit.Assert.assertThrows; 19 20 import org.junit.Before; 21 import org.junit.Test; 22 23 import java.util.List; 24 import java.util.concurrent.atomic.AtomicInteger; 25 26 /** Base test for classes that extend ResultTestSyncCallback. */ 27 public abstract class IResultSyncCallbackTestCase< 28 R, CB extends IResultSyncCallback<R> & FreezableToString> 29 extends IBinderSyncCallbackTestCase<CB> { 30 31 private static final AtomicInteger sNextId = new AtomicInteger(); 32 33 // Must be set on @Before otherwise OutcomeReceiverForTestsTest would fail on R 34 protected CB mCallback; 35 36 /** Gets a new, unique result object, preferably with a user-friendly string representation. */ newResult()37 protected abstract R newResult(); 38 39 @Before setFixtures()40 public final void setFixtures() { 41 mCallback = newCallback(mDefaultSettings); 42 mLog.v("setFixtures(): mCallback=%s", mCallback); 43 } 44 45 /** 46 * Gets a unique id. 47 * 48 * <p>Useful to make sure {@link #newResult()} return unique objects. 49 */ getNextUniqueId()50 protected final int getNextUniqueId() { 51 return sNextId.incrementAndGet(); 52 } 53 54 @Override callCallback(CB callback)55 protected String callCallback(CB callback) { 56 R result = newResult(); 57 callback.injectResult(result); 58 return "injectResult(" + result + ")"; 59 } 60 61 @Test testNewResult()62 public final void testNewResult() { 63 R result1 = newResult(); 64 expect.withMessage("1st result").that(result1).isNotNull(); 65 66 R result2 = newResult(); 67 expect.withMessage("2nd result").that(result2).isNotNull(); 68 expect.withMessage("2nd result").that(result2).isNotSameInstanceAs(result1); 69 } 70 71 @Test testInjectResult_assertResultReceived()72 public final void testInjectResult_assertResultReceived() throws Exception { 73 assertInitialState(mCallback); 74 R injectedResult = newResult(); 75 76 runAsync(INJECTION_TIMEOUT_MS, () -> mCallback.injectResult(injectedResult)); 77 R receivedResult = mCallback.assertResultReceived(); 78 79 expect.withMessage("%s.assertResultReceived()", mCallback) 80 .that(receivedResult) 81 .isSameInstanceAs(injectedResult); 82 expect.withMessage("%s.isCalled() after injectResult()", mCallback) 83 .that(mCallback.isCalled()) 84 .isTrue(); 85 R gottenResult = mCallback.getResult(); 86 expect.withMessage("%s.getResult()", mCallback) 87 .that(gottenResult) 88 .isSameInstanceAs(injectedResult); 89 expect.withMessage("%s.getResults() after injectResult()", mCallback) 90 .that(mCallback.getResults()) 91 .containsExactly(injectedResult); 92 expect.withMessage("toString() after injectResult()") 93 .that(mCallback.toString()) 94 .contains("result=" + injectedResult); 95 } 96 97 @Test testInjectNullResult_assertResultReceived()98 public final void testInjectNullResult_assertResultReceived() throws Exception { 99 assertInitialState(mCallback); 100 R injectedResult = null; 101 102 runAsync(INJECTION_TIMEOUT_MS, () -> mCallback.injectResult(injectedResult)); 103 R receivedResult = mCallback.assertResultReceived(); 104 105 expect.withMessage("%s.assertResultReceived()", mCallback).that(receivedResult).isNull(); 106 expect.withMessage("%s.isCalled() after injectResult()", mCallback) 107 .that(mCallback.isCalled()) 108 .isTrue(); 109 110 assertGetResultMethods(mCallback, "after injectResult()", injectedResult); 111 } 112 113 @Test testInjectResult_assertCalled()114 public final void testInjectResult_assertCalled() throws Exception { 115 assertInitialState(mCallback); 116 R injectedResult = newResult(); 117 118 runAsync(INJECTION_TIMEOUT_MS, () -> mCallback.injectResult(injectedResult)); 119 mCallback.assertCalled(); 120 121 assertGetResultMethods(mCallback, "after injectResult()", injectedResult); 122 } 123 124 @Test testInjectNullResult_assertCalled()125 public final void testInjectNullResult_assertCalled() throws Exception { 126 assertInitialState(mCallback); 127 R injectedResult = null; 128 129 runAsync(INJECTION_TIMEOUT_MS, () -> mCallback.injectResult(injectedResult)); 130 mCallback.assertCalled(); 131 132 assertGetResultMethods(mCallback, "after injectResult()", injectedResult); 133 } 134 135 @Test testInjectResult_calledTwice()136 public final void testInjectResult_calledTwice() throws Exception { 137 R firstResult = newResult(); 138 mCallback.injectResult(firstResult); 139 R secondResult = newResult(); 140 mCallback.injectResult(secondResult); 141 142 R assertReceivedResult = mCallback.assertResultReceived(); 143 144 expect.withMessage("%s.assertResultReceived()", mCallback) 145 .that(assertReceivedResult) 146 .isSameInstanceAs(firstResult); 147 148 assertGetResultMethods( 149 mCallback, "after 2 injectResult() calls", firstResult, secondResult); 150 } 151 152 @Test testInjectResult_calledTwice_firstWasNull()153 public final void testInjectResult_calledTwice_firstWasNull() throws Exception { 154 R firstResult = null; 155 mCallback.injectResult(firstResult); 156 R secondResult = newResult(); 157 mCallback.injectResult(secondResult); 158 159 R assertReceivedResult = mCallback.assertResultReceived(); 160 161 expect.withMessage("%s.assertResultReceived()", mCallback) 162 .that(assertReceivedResult) 163 .isSameInstanceAs(firstResult); 164 165 assertGetResultMethods( 166 mCallback, "after 2 injectResult() calls", firstResult, secondResult); 167 } 168 169 @Test testGetResults_immutable()170 public final void testGetResults_immutable() throws Exception { 171 List<R> results = mCallback.getResults(); 172 expect.withMessage("%s.getResults() initially", mCallback).that(results).isEmpty(); 173 174 assertThrows(UnsupportedOperationException.class, () -> results.add(newResult())); 175 176 expect.withMessage("%s.getResults() after", mCallback) 177 .that(mCallback.getResults()) 178 .isEmpty(); 179 } 180 181 @Test testToString_containsResults()182 public final void testToString_containsResults() throws Exception { 183 // Initial state 184 String toString = mCallback.toString(); 185 expect.withMessage("toString()").that(toString).contains("(no result yet)"); 186 187 // 1st call 188 R firstResult = newResult(); 189 mCallback.injectResult(firstResult); 190 toString = mCallback.toString(); 191 expect.withMessage("toString()").that(toString).contains("result=" + firstResult); 192 expect.withMessage("toString()").that(toString).contains("results=[" + firstResult + "]"); 193 194 // 2nd call 195 R secondResult = newResult(); 196 mCallback.injectResult(secondResult); 197 toString = mCallback.toString(); 198 expect.withMessage("toString()").that(toString).contains("result=" + firstResult); 199 expect.withMessage("toString()") 200 .that(toString) 201 .contains("results=[" + firstResult + ", " + secondResult + "]"); 202 } 203 assertGetResultMethodsWhenNoResult(CB callback, String when)204 protected final void assertGetResultMethodsWhenNoResult(CB callback, String when) { 205 expect.withMessage("%s.getResult() %s", callback, when).that(callback.getResult()).isNull(); 206 expect.withMessage("%s.getResults() %s", callback, when) 207 .that(callback.getResults()) 208 .isEmpty(); 209 } 210 211 @SafeVarargs assertGetResultMethods(CB callback, String when, R... expectedResults)212 protected final void assertGetResultMethods(CB callback, String when, R... expectedResults) { 213 expect.withMessage("%s.getResult() %s", callback, when) 214 .that(callback.getResult()) 215 .isSameInstanceAs(expectedResults[0]); 216 expect.withMessage("%s.getResults() %s", callback, when) 217 .that(callback.getResults()) 218 .containsExactly(expectedResults) 219 .inOrder(); 220 } 221 assertInitialState(CB callback)222 private void assertInitialState(CB callback) { 223 assertGetResultMethodsWhenNoResult(callback, "initially"); 224 } 225 } 226