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.producers.Producer; 29 import dagger.producers.internal.AbstractProducer; 30 import dagger.producers.internal.CancellableProducer; 31 import dagger.producers.monitoring.ProducerMonitor; 32 import dagger.producers.monitoring.ProducerToken; 33 import dagger.producers.monitoring.ProductionComponentMonitor; 34 import java.util.concurrent.ExecutionException; 35 import java.util.concurrent.Executor; 36 import javax.inject.Provider; 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 // TODO(beder): Use Providers.of when available. 59 executorProvider = 60 new Provider<Executor>() { 61 @Override 62 public Executor get() { 63 return MoreExecutors.directExecutor(); 64 } 65 }; 66 componentMonitorProvider = 67 new Provider<ProductionComponentMonitor>() { 68 @Override 69 public ProductionComponentMonitor get() { 70 return componentMonitor; 71 } 72 }; 73 } 74 75 @Test noArgMethod()76 public void noArgMethod() throws Exception { 77 ProducerToken token = ProducerToken.create(SimpleProducerModule_StrFactory.class); 78 Producer<String> producer = 79 SimpleProducerModule_StrFactory.create(executorProvider, componentMonitorProvider); 80 assertThat(producer.get().get()).isEqualTo("str"); 81 InOrder order = inOrder(componentMonitor, monitor); 82 order.verify(componentMonitor).producerMonitorFor(token); 83 order.verify(monitor).methodStarting(); 84 order.verify(monitor).methodFinished(); 85 order.verify(monitor).succeeded("str"); 86 order.verifyNoMoreInteractions(); 87 } 88 89 @Test singleArgMethod()90 public void singleArgMethod() throws Exception { 91 SettableFuture<Integer> intFuture = SettableFuture.create(); 92 CancellableProducer<Integer> intProducer = producerOfFuture(intFuture); 93 Producer<String> producer = 94 SimpleProducerModule_StrWithArgFactory.create( 95 executorProvider, componentMonitorProvider, intProducer); 96 assertThat(producer.get().isDone()).isFalse(); 97 intFuture.set(42); 98 assertThat(producer.get().get()).isEqualTo("str with arg"); 99 } 100 101 @Test successMonitor()102 public void successMonitor() throws Exception { 103 ProducerToken token = ProducerToken.create(SimpleProducerModule_SettableFutureStrFactory.class); 104 105 SettableFuture<String> strFuture = SettableFuture.create(); 106 @SuppressWarnings("FutureReturnValueIgnored") 107 SettableFuture<SettableFuture<String>> strFutureFuture = SettableFuture.create(); 108 CancellableProducer<SettableFuture<String>> strFutureProducer = 109 producerOfFuture(strFutureFuture); 110 Producer<String> producer = 111 SimpleProducerModule_SettableFutureStrFactory.create( 112 executorProvider, componentMonitorProvider, strFutureProducer); 113 assertThat(producer.get().isDone()).isFalse(); 114 115 InOrder order = inOrder(componentMonitor, monitor); 116 order.verify(componentMonitor).producerMonitorFor(token); 117 118 strFutureFuture.set(strFuture); 119 order.verify(monitor).methodStarting(); 120 order.verify(monitor).methodFinished(); 121 assertThat(producer.get().isDone()).isFalse(); 122 123 strFuture.set("monkey"); 124 assertThat(producer.get().get()).isEqualTo("monkey"); 125 order.verify(monitor).succeeded("monkey"); 126 127 order.verifyNoMoreInteractions(); 128 } 129 130 @Test failureMonitor()131 public void failureMonitor() throws Exception { 132 ProducerToken token = ProducerToken.create(SimpleProducerModule_SettableFutureStrFactory.class); 133 134 SettableFuture<String> strFuture = SettableFuture.create(); 135 @SuppressWarnings("FutureReturnValueIgnored") 136 SettableFuture<SettableFuture<String>> strFutureFuture = SettableFuture.create(); 137 CancellableProducer<SettableFuture<String>> strFutureProducer = 138 producerOfFuture(strFutureFuture); 139 Producer<String> producer = 140 SimpleProducerModule_SettableFutureStrFactory.create( 141 executorProvider, componentMonitorProvider, strFutureProducer); 142 assertThat(producer.get().isDone()).isFalse(); 143 144 InOrder order = inOrder(componentMonitor, monitor); 145 order.verify(componentMonitor).producerMonitorFor(token); 146 147 strFutureFuture.set(strFuture); 148 order.verify(monitor).methodStarting(); 149 order.verify(monitor).methodFinished(); 150 assertThat(producer.get().isDone()).isFalse(); 151 152 Throwable t = new RuntimeException("monkey"); 153 strFuture.setException(t); 154 try { 155 producer.get().get(); 156 fail(); 157 } catch (ExecutionException e) { 158 assertThat(e).hasCauseThat().isSameInstanceAs(t); 159 order.verify(monitor).failed(t); 160 } 161 162 order.verifyNoMoreInteractions(); 163 } 164 165 @Test failureMonitorDueToThrowingProducer()166 public void failureMonitorDueToThrowingProducer() throws Exception { 167 ProducerToken token = ProducerToken.create(SimpleProducerModule_ThrowingProducerFactory.class); 168 169 Producer<String> producer = 170 SimpleProducerModule_ThrowingProducerFactory.create( 171 executorProvider, componentMonitorProvider); 172 assertThat(producer.get().isDone()).isTrue(); 173 174 InOrder order = inOrder(componentMonitor, monitor); 175 order.verify(componentMonitor).producerMonitorFor(token); 176 177 order.verify(monitor).methodStarting(); 178 order.verify(monitor).methodFinished(); 179 180 try { 181 producer.get().get(); 182 fail(); 183 } catch (ExecutionException e) { 184 order.verify(monitor).failed(e.getCause()); 185 } 186 187 order.verifyNoMoreInteractions(); 188 } 189 190 @Test(expected = NullPointerException.class) nullComponentMonitorProvider()191 public void nullComponentMonitorProvider() throws Exception { 192 SimpleProducerModule_StrFactory.create(executorProvider, null); 193 } 194 producerOfFuture(final ListenableFuture<T> future)195 private static <T> CancellableProducer<T> producerOfFuture(final ListenableFuture<T> future) { 196 return new AbstractProducer<T>() { 197 @Override 198 public ListenableFuture<T> compute() { 199 return future; 200 } 201 }; 202 } 203 } 204