1 /* 2 * Copyright (C) 2021 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 android.car.test.mocks; 18 19 import static com.google.common.truth.Truth.assertThat; 20 21 import static org.mockito.Mockito.spy; 22 import static org.mockito.Mockito.when; 23 24 import org.junit.Before; 25 import org.junit.Test; 26 27 import java.util.concurrent.ArrayBlockingQueue; 28 import java.util.concurrent.BlockingQueue; 29 import java.util.concurrent.TimeUnit; 30 import java.util.concurrent.atomic.AtomicBoolean; 31 32 public final class SyncAnswerTest { 33 34 private static final long TIMEOUT_MS = 1_000L; 35 36 private SlowServiceInitializer mSlowServiceInitializer; 37 38 private SlowService mSlowService; 39 40 private BlockingExceptionLogger mExceptionLogger; 41 42 @Before setUp()43 public void setUp() { 44 mExceptionLogger = new BlockingExceptionLogger(); 45 mSlowServiceInitializer = spy(new SlowServiceInitializer()); 46 mSlowService = new SlowService(mSlowServiceInitializer, mExceptionLogger); 47 } 48 49 @Test testForException()50 public void testForException() throws Exception { 51 Exception expected = new Exception("expected"); 52 SyncAnswer<Boolean> syncException = SyncAnswer.forException(expected); 53 when(mSlowServiceInitializer.initialize()).thenAnswer(syncException); 54 55 mSlowService.asyncSlowTask(); 56 syncException.await(TIMEOUT_MS); 57 58 assertThat(mExceptionLogger.mExceptionReceiver.poll(3, TimeUnit.SECONDS)).isSameInstanceAs( 59 expected); 60 } 61 62 @Test testForReturn()63 public void testForReturn() throws Exception { 64 SyncAnswer<Boolean> syncInitialized = SyncAnswer.forReturn(true); 65 when(mSlowServiceInitializer.initialize()).thenAnswer(syncInitialized); 66 67 mSlowService.asyncSlowTask(); 68 syncInitialized.await(TIMEOUT_MS); 69 70 assertThat(mSlowServiceInitializer.isInitialized()).isTrue(); 71 } 72 73 private static final class BlockingExceptionLogger { 74 75 final BlockingQueue<Exception> mExceptionReceiver = new ArrayBlockingQueue<>(1); 76 logException(Exception exception)77 void logException(Exception exception) { 78 mExceptionReceiver.offer(exception); 79 } 80 } 81 82 private static final class SlowServiceInitializer { 83 84 private final AtomicBoolean mInitialized = new AtomicBoolean(false); 85 initialize()86 boolean initialize() { 87 mInitialized.set(true); 88 return true; 89 } 90 isInitialized()91 boolean isInitialized() { 92 return mInitialized.get(); 93 } 94 } 95 96 private static final class SlowService { 97 98 private final SlowServiceInitializer mSlowServiceDelegate; 99 100 private final BlockingExceptionLogger mExceptionLogger; 101 SlowService(SlowServiceInitializer slowServiceDelegate, BlockingExceptionLogger exceptionLogger)102 SlowService(SlowServiceInitializer slowServiceDelegate, 103 BlockingExceptionLogger exceptionLogger) { 104 mSlowServiceDelegate = slowServiceDelegate; 105 mExceptionLogger = exceptionLogger; 106 } 107 asyncSlowTask()108 void asyncSlowTask() { 109 new Thread(() -> { 110 try { 111 mSlowServiceDelegate.initialize(); 112 } catch (Exception expected) { 113 mExceptionLogger.logException(expected); 114 } 115 }, getClass().getName() + "#asyncSlowTask").start(); 116 } 117 } 118 } 119 120 121