1 /* 2 * Copyright (C) 2015 The Dagger Authors. 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 dagger.functional.producers; 18 19 import static com.google.common.truth.Truth.assertThat; 20 import static org.junit.Assert.fail; 21 import static org.mockito.ArgumentMatchers.any; 22 import static org.mockito.Mockito.inOrder; 23 import static org.mockito.Mockito.when; 24 25 import com.google.common.util.concurrent.ListenableFuture; 26 import com.google.common.util.concurrent.MoreExecutors; 27 import com.google.common.util.concurrent.SettableFuture; 28 import dagger.internal.Provider; 29 import dagger.producers.Producer; 30 import dagger.producers.internal.AbstractProducer; 31 import dagger.producers.internal.CancellableProducer; 32 import dagger.producers.monitoring.ProducerMonitor; 33 import dagger.producers.monitoring.ProducerToken; 34 import dagger.producers.monitoring.ProductionComponentMonitor; 35 import java.util.concurrent.ExecutionException; 36 import java.util.concurrent.Executor; 37 import org.junit.Before; 38 import org.junit.Test; 39 import org.junit.runner.RunWith; 40 import org.junit.runners.JUnit4; 41 import org.mockito.InOrder; 42 import org.mockito.Mock; 43 import org.mockito.Mockito; 44 import org.mockito.MockitoAnnotations; 45 46 @RunWith(JUnit4.class) 47 public class ProducerFactoryTest { 48 @Mock private ProductionComponentMonitor componentMonitor; 49 private ProducerMonitor monitor; 50 private Provider<Executor> executorProvider; 51 private Provider<ProductionComponentMonitor> componentMonitorProvider; 52 53 @Before setUpMocks()54 public void setUpMocks() { 55 MockitoAnnotations.initMocks(this); 56 monitor = Mockito.mock(ProducerMonitor.class, Mockito.CALLS_REAL_METHODS); 57 when(componentMonitor.producerMonitorFor(any(ProducerToken.class))).thenReturn(monitor); 58 executorProvider = 59 new Provider<Executor>() { 60 @Override 61 public Executor get() { 62 return MoreExecutors.directExecutor(); 63 } 64 }; 65 componentMonitorProvider = 66 new Provider<ProductionComponentMonitor>() { 67 @Override 68 public ProductionComponentMonitor get() { 69 return componentMonitor; 70 } 71 }; 72 } 73 74 @Test noArgMethod()75 public void noArgMethod() throws Exception { 76 ProducerToken token = ProducerToken.create(SimpleProducerModule_StrFactory.class); 77 Producer<String> producer = 78 SimpleProducerModule_StrFactory.create(executorProvider, componentMonitorProvider); 79 assertThat(producer.get().get()).isEqualTo("str"); 80 InOrder order = inOrder(componentMonitor, monitor); 81 order.verify(componentMonitor).producerMonitorFor(token); 82 order.verify(monitor).methodStarting(); 83 order.verify(monitor).methodFinished(); 84 order.verify(monitor).succeeded("str"); 85 order.verifyNoMoreInteractions(); 86 } 87 88 @Test singleArgMethod()89 public void singleArgMethod() throws Exception { 90 SettableFuture<Integer> intFuture = SettableFuture.create(); 91 CancellableProducer<Integer> intProducer = producerOfFuture(intFuture); 92 Producer<String> producer = 93 SimpleProducerModule_StrWithArgFactory.create( 94 executorProvider, componentMonitorProvider, intProducer); 95 assertThat(producer.get().isDone()).isFalse(); 96 intFuture.set(42); 97 assertThat(producer.get().get()).isEqualTo("str with arg"); 98 } 99 100 @Test successMonitor()101 public void successMonitor() throws Exception { 102 ProducerToken token = ProducerToken.create(SimpleProducerModule_SettableFutureStrFactory.class); 103 104 SettableFuture<String> strFuture = SettableFuture.create(); 105 @SuppressWarnings("FutureReturnValueIgnored") 106 SettableFuture<SettableFuture<String>> strFutureFuture = SettableFuture.create(); 107 CancellableProducer<SettableFuture<String>> strFutureProducer = 108 producerOfFuture(strFutureFuture); 109 Producer<String> producer = 110 SimpleProducerModule_SettableFutureStrFactory.create( 111 executorProvider, componentMonitorProvider, strFutureProducer); 112 assertThat(producer.get().isDone()).isFalse(); 113 114 InOrder order = inOrder(componentMonitor, monitor); 115 order.verify(componentMonitor).producerMonitorFor(token); 116 117 strFutureFuture.set(strFuture); 118 order.verify(monitor).methodStarting(); 119 order.verify(monitor).methodFinished(); 120 assertThat(producer.get().isDone()).isFalse(); 121 122 strFuture.set("monkey"); 123 assertThat(producer.get().get()).isEqualTo("monkey"); 124 order.verify(monitor).succeeded("monkey"); 125 126 order.verifyNoMoreInteractions(); 127 } 128 129 @Test failureMonitor()130 public void failureMonitor() throws Exception { 131 ProducerToken token = ProducerToken.create(SimpleProducerModule_SettableFutureStrFactory.class); 132 133 SettableFuture<String> strFuture = SettableFuture.create(); 134 @SuppressWarnings("FutureReturnValueIgnored") 135 SettableFuture<SettableFuture<String>> strFutureFuture = SettableFuture.create(); 136 CancellableProducer<SettableFuture<String>> strFutureProducer = 137 producerOfFuture(strFutureFuture); 138 Producer<String> producer = 139 SimpleProducerModule_SettableFutureStrFactory.create( 140 executorProvider, componentMonitorProvider, strFutureProducer); 141 assertThat(producer.get().isDone()).isFalse(); 142 143 InOrder order = inOrder(componentMonitor, monitor); 144 order.verify(componentMonitor).producerMonitorFor(token); 145 146 strFutureFuture.set(strFuture); 147 order.verify(monitor).methodStarting(); 148 order.verify(monitor).methodFinished(); 149 assertThat(producer.get().isDone()).isFalse(); 150 151 Throwable t = new RuntimeException("monkey"); 152 strFuture.setException(t); 153 try { 154 producer.get().get(); 155 fail(); 156 } catch (ExecutionException e) { 157 assertThat(e).hasCauseThat().isSameInstanceAs(t); 158 order.verify(monitor).failed(t); 159 } 160 161 order.verifyNoMoreInteractions(); 162 } 163 164 @Test failureMonitorDueToThrowingProducer()165 public void failureMonitorDueToThrowingProducer() throws Exception { 166 ProducerToken token = ProducerToken.create(SimpleProducerModule_ThrowingProducerFactory.class); 167 168 Producer<String> producer = 169 SimpleProducerModule_ThrowingProducerFactory.create( 170 executorProvider, componentMonitorProvider); 171 assertThat(producer.get().isDone()).isTrue(); 172 173 InOrder order = inOrder(componentMonitor, monitor); 174 order.verify(componentMonitor).producerMonitorFor(token); 175 176 order.verify(monitor).methodStarting(); 177 order.verify(monitor).methodFinished(); 178 179 try { 180 producer.get().get(); 181 fail(); 182 } catch (ExecutionException e) { 183 order.verify(monitor).failed(e.getCause()); 184 } 185 186 order.verifyNoMoreInteractions(); 187 } 188 189 @Test(expected = NullPointerException.class) nullComponentMonitorProvider()190 public void nullComponentMonitorProvider() throws Exception { 191 SimpleProducerModule_StrFactory.create(executorProvider, null); 192 } 193 producerOfFuture(final ListenableFuture<T> future)194 private static <T> CancellableProducer<T> producerOfFuture(final ListenableFuture<T> future) { 195 return new AbstractProducer<T>() { 196 @Override 197 public ListenableFuture<T> compute() { 198 return future; 199 } 200 }; 201 } 202 } 203