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 17 package com.android.adservices.shared.testing; 18 19 import android.util.Log; 20 21 import com.android.adservices.shared.testing.concurrency.DeviceSideSyncCallback; 22 import com.android.adservices.shared.testing.concurrency.SyncCallbackFactory; 23 import com.android.adservices.shared.testing.concurrency.SyncCallbackSettings; 24 import com.android.adservices.shared.testing.mockito.MockitoHelper; 25 26 import org.mockito.invocation.InvocationOnMock; 27 import org.mockito.stubbing.Answer; 28 29 /** 30 * {@code SyncCallback} to be used when setting Mockito expectations with an {@link Answer}. 31 * 32 * @param <T> return type of the method being "answered". 33 */ 34 public final class AnswerSyncCallback<T> extends DeviceSideSyncCallback implements Answer<T> { 35 36 private static final String TAG = AnswerSyncCallback.class.getSimpleName(); 37 38 @Nullable private final T mAnswer; 39 @Nullable private final Throwable mFailure; 40 AnswerSyncCallback(T answer, Throwable failure, int numberOfExpectedCalls)41 private AnswerSyncCallback(T answer, Throwable failure, int numberOfExpectedCalls) { 42 this( 43 answer, 44 failure, 45 SyncCallbackFactory.newSettingsBuilder() 46 .setExpectedNumberCalls(numberOfExpectedCalls) 47 .build()); 48 } 49 AnswerSyncCallback(T answer, Throwable failure, SyncCallbackSettings settings)50 private AnswerSyncCallback(T answer, Throwable failure, SyncCallbackSettings settings) { 51 super(settings); 52 mAnswer = answer; 53 mFailure = failure; 54 } 55 56 /** 57 * Convenience method for {@link #forVoidAnswers(SyncCallbackSettings)} using a {@link 58 * SyncCallbackSettings settings} that expects just 1 call. 59 */ forSingleVoidAnswer()60 public static AnswerSyncCallback<Void> forSingleVoidAnswer() { 61 return new AnswerSyncCallback<Void>( 62 /* answer= */ null, /* failure= */ null, /* numberOfExpectedCalls= */ 1); 63 } 64 65 /** 66 * Convenience method for {@link #forAnswers(SyncCallbackSettings)} using a {@link 67 * SyncCallbackSettings settings} that expects just 1 call. 68 */ forSingleAnswer(A answer)69 public static <A> AnswerSyncCallback<A> forSingleAnswer(A answer) { 70 return new AnswerSyncCallback<A>( 71 answer, /* failure= */ null, /* numberOfExpectedCalls= */ 1); 72 } 73 74 /** 75 * Convenience method for {@link #forVoidAnswers(SyncCallbackSettings)} using a {@link 76 * SyncCallbackSettings settings} that expects {@code numberOfExpectedCalls} calls. 77 */ forMultipleVoidAnswers(int numberOfExpectedCalls)78 public static AnswerSyncCallback<Void> forMultipleVoidAnswers(int numberOfExpectedCalls) { 79 return new AnswerSyncCallback<>( 80 /* answer= */ null, /* failure= */ null, numberOfExpectedCalls); 81 } 82 83 /** 84 * Convenience method for {@link #forAnswers(SyncCallbackSettings)} using a {@link 85 * SyncCallbackSettings settings} that expects {@code numberOfExpectedCalls} calls. 86 */ forMultipleAnswers( A answer, int numberOfExpectedCalls)87 public static <A> AnswerSyncCallback<A> forMultipleAnswers( 88 A answer, int numberOfExpectedCalls) { 89 return new AnswerSyncCallback<A>(answer, /* failure= */ null, numberOfExpectedCalls); 90 } 91 92 /** 93 * Factory method for answers that return {@code Void} and take a generic {@link 94 * SyncCallbackSettings}. 95 */ forVoidAnswers(SyncCallbackSettings settings)96 public static AnswerSyncCallback<Void> forVoidAnswers(SyncCallbackSettings settings) { 97 return new AnswerSyncCallback<>(/* answer= */ null, /* failure= */ null, settings); 98 } 99 100 /** Factory method for answers that return non-{@code Void}. */ forAnswers(A answer, SyncCallbackSettings settings)101 public static <A> AnswerSyncCallback<A> forAnswers(A answer, SyncCallbackSettings settings) { 102 return new AnswerSyncCallback<A>(answer, /* failure= */ null, settings); 103 } 104 105 /** 106 * Factory method for {@link Answer}s that should thrown an exception. 107 * 108 * @param clazz type of the object that should be returned by the {@link Answer} 109 * @param failure exception that will be thrown. 110 */ forSingleFailure(Class<A> clazz, Throwable failure)111 public static <A> AnswerSyncCallback<A> forSingleFailure(Class<A> clazz, Throwable failure) { 112 return new AnswerSyncCallback<A>( 113 /* answer= */ null, failure, /* numberOfExpectedCalls= */ 1); 114 } 115 116 @Override answer(InvocationOnMock invocation)117 public T answer(InvocationOnMock invocation) throws Throwable { 118 super.internalSetCalled(MockitoHelper.toString(invocation)); 119 if (mFailure != null) { 120 Log.v(TAG, "Throwing '" + mFailure + "' on " + invocation); 121 throw mFailure; 122 } 123 Log.v(TAG, "Answering '" + mAnswer + "' on " + invocation); 124 return mAnswer; 125 } 126 } 127