1/*
2 * Copyright (C) 2014 Google, Inc.
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 */
16package dagger.producers.internal;
17
18import com.google.common.util.concurrent.Futures;
19import com.google.common.util.concurrent.ListenableFuture;
20import com.google.common.util.concurrent.SettableFuture;
21import dagger.producers.Producer;
22import dagger.producers.monitoring.ProducerMonitor;
23import dagger.producers.monitoring.ProducerToken;
24import dagger.producers.monitoring.ProductionComponentMonitor;
25import java.util.concurrent.ExecutionException;
26import javax.inject.Provider;
27import org.mockito.Mock;
28import org.mockito.Mockito;
29import org.mockito.MockitoAnnotations;
30import org.junit.Before;
31import org.junit.Test;
32import org.junit.runner.RunWith;
33import org.junit.runners.JUnit4;
34
35import static com.google.common.truth.Truth.assertThat;
36import static org.junit.Assert.fail;
37import static org.mockito.Mockito.any;
38import static org.mockito.Mockito.verify;
39import static org.mockito.Mockito.verifyNoMoreInteractions;
40import static org.mockito.Mockito.when;
41
42/**
43 * Tests {@link AbstractProducer}.
44 */
45@RunWith(JUnit4.class)
46public class AbstractProducerTest {
47  @Mock private ProductionComponentMonitor componentMonitor;
48  private ProducerMonitor monitor;
49  private Provider<ProductionComponentMonitor> componentMonitorProvider;
50
51  @Before
52  public void initMocks() {
53    MockitoAnnotations.initMocks(this);
54    monitor = Mockito.mock(ProducerMonitor.class, Mockito.CALLS_REAL_METHODS);
55    when(componentMonitor.producerMonitorFor(any(ProducerToken.class))).thenReturn(monitor);
56    componentMonitorProvider =
57        new Provider<ProductionComponentMonitor>() {
58          @Override
59          public ProductionComponentMonitor get() {
60            return componentMonitor;
61          }
62        };
63  }
64
65  @Test
66  public void get_nullPointerException() {
67    Producer<Object> producer = new DelegateProducer<>(componentMonitorProvider, null);
68    try {
69      producer.get();
70      fail();
71    } catch (NullPointerException expected) {
72    }
73  }
74
75  @Test public void get() throws Exception {
76    Producer<Integer> producer =
77        new AbstractProducer<Integer>(componentMonitorProvider, null) {
78          int i = 0;
79
80          @Override
81          public ListenableFuture<Integer> compute(ProducerMonitor unusedMonitor) {
82            return Futures.immediateFuture(i++);
83          }
84        };
85    assertThat(producer.get().get()).isEqualTo(0);
86    assertThat(producer.get().get()).isEqualTo(0);
87    assertThat(producer.get().get()).isEqualTo(0);
88  }
89
90  @Test
91  public void monitor_success() throws Exception {
92    SettableFuture<Integer> delegateFuture = SettableFuture.create();
93    Producer<Integer> producer = new DelegateProducer<>(componentMonitorProvider, delegateFuture);
94
95    ListenableFuture<Integer> future = producer.get();
96    assertThat(future.isDone()).isFalse();
97    verify(monitor).addCallbackTo(any(ListenableFuture.class));
98    delegateFuture.set(-42);
99    assertThat(future.get()).isEqualTo(-42);
100    verify(monitor).succeeded(-42);
101    verifyNoMoreInteractions(monitor);
102  }
103
104  @Test
105  public void monitor_failure() throws Exception {
106    SettableFuture<Integer> delegateFuture = SettableFuture.create();
107    Producer<Integer> producer = new DelegateProducer<>(componentMonitorProvider, delegateFuture);
108
109    ListenableFuture<Integer> future = producer.get();
110    assertThat(future.isDone()).isFalse();
111    verify(monitor).addCallbackTo(any(ListenableFuture.class));
112    Throwable t = new RuntimeException("monkey");
113    delegateFuture.setException(t);
114    try {
115      future.get();
116      fail();
117    } catch (ExecutionException e) {
118      assertThat(e.getCause()).isSameAs(t);
119    }
120    verify(monitor).failed(t);
121    verifyNoMoreInteractions(monitor);
122  }
123
124  @Test(expected = NullPointerException.class)
125  public void monitor_null() throws Exception {
126    new DelegateProducer<>(null, Futures.immediateFuture(42));
127  }
128
129  static final class DelegateProducer<T> extends AbstractProducer<T> {
130    private final ListenableFuture<T> delegate;
131
132    DelegateProducer(
133        Provider<ProductionComponentMonitor> componentMonitorProvider,
134        ListenableFuture<T> delegate) {
135      super(componentMonitorProvider, null);
136      this.delegate = delegate;
137    }
138
139    @Override
140    public ListenableFuture<T> compute(ProducerMonitor unusedMonitor) {
141      return delegate;
142    }
143  }
144}
145