15d3207ac2713386ed61c6ca8f0356e8f093a62e1Paul Duffin/*
25d3207ac2713386ed61c6ca8f0356e8f093a62e1Paul Duffin * Copyright (C) 2014 Google, Inc.
35d3207ac2713386ed61c6ca8f0356e8f093a62e1Paul Duffin *
45d3207ac2713386ed61c6ca8f0356e8f093a62e1Paul Duffin * Licensed under the Apache License, Version 2.0 (the "License");
55d3207ac2713386ed61c6ca8f0356e8f093a62e1Paul Duffin * you may not use this file except in compliance with the License.
65d3207ac2713386ed61c6ca8f0356e8f093a62e1Paul Duffin * You may obtain a copy of the License at
75d3207ac2713386ed61c6ca8f0356e8f093a62e1Paul Duffin *
85d3207ac2713386ed61c6ca8f0356e8f093a62e1Paul Duffin * http://www.apache.org/licenses/LICENSE-2.0
95d3207ac2713386ed61c6ca8f0356e8f093a62e1Paul Duffin *
105d3207ac2713386ed61c6ca8f0356e8f093a62e1Paul Duffin * Unless required by applicable law or agreed to in writing, software
115d3207ac2713386ed61c6ca8f0356e8f093a62e1Paul Duffin * distributed under the License is distributed on an "AS IS" BASIS,
125d3207ac2713386ed61c6ca8f0356e8f093a62e1Paul Duffin * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
135d3207ac2713386ed61c6ca8f0356e8f093a62e1Paul Duffin * See the License for the specific language governing permissions and
145d3207ac2713386ed61c6ca8f0356e8f093a62e1Paul Duffin * limitations under the License.
155d3207ac2713386ed61c6ca8f0356e8f093a62e1Paul Duffin */
165d3207ac2713386ed61c6ca8f0356e8f093a62e1Paul Duffinpackage dagger.producers.internal;
175d3207ac2713386ed61c6ca8f0356e8f093a62e1Paul Duffin
185d3207ac2713386ed61c6ca8f0356e8f093a62e1Paul Duffinimport com.google.common.util.concurrent.Futures;
195d3207ac2713386ed61c6ca8f0356e8f093a62e1Paul Duffinimport com.google.common.util.concurrent.ListenableFuture;
205d3207ac2713386ed61c6ca8f0356e8f093a62e1Paul Duffinimport com.google.common.util.concurrent.SettableFuture;
215d3207ac2713386ed61c6ca8f0356e8f093a62e1Paul Duffinimport dagger.producers.Producer;
225d3207ac2713386ed61c6ca8f0356e8f093a62e1Paul Duffinimport dagger.producers.monitoring.ProducerMonitor;
2387182e06b8f6ec9a11ed6ebcaf74444e79b18ae2Paul Duffinimport dagger.producers.monitoring.ProducerToken;
2487182e06b8f6ec9a11ed6ebcaf74444e79b18ae2Paul Duffinimport dagger.producers.monitoring.ProductionComponentMonitor;
255d3207ac2713386ed61c6ca8f0356e8f093a62e1Paul Duffinimport java.util.concurrent.ExecutionException;
2687182e06b8f6ec9a11ed6ebcaf74444e79b18ae2Paul Duffinimport javax.inject.Provider;
2787182e06b8f6ec9a11ed6ebcaf74444e79b18ae2Paul Duffinimport org.mockito.Mock;
2887182e06b8f6ec9a11ed6ebcaf74444e79b18ae2Paul Duffinimport org.mockito.Mockito;
2987182e06b8f6ec9a11ed6ebcaf74444e79b18ae2Paul Duffinimport org.mockito.MockitoAnnotations;
305d3207ac2713386ed61c6ca8f0356e8f093a62e1Paul Duffinimport org.junit.Before;
315d3207ac2713386ed61c6ca8f0356e8f093a62e1Paul Duffinimport org.junit.Test;
325d3207ac2713386ed61c6ca8f0356e8f093a62e1Paul Duffinimport org.junit.runner.RunWith;
335d3207ac2713386ed61c6ca8f0356e8f093a62e1Paul Duffinimport org.junit.runners.JUnit4;
345d3207ac2713386ed61c6ca8f0356e8f093a62e1Paul Duffin
355d3207ac2713386ed61c6ca8f0356e8f093a62e1Paul Duffinimport static com.google.common.truth.Truth.assertThat;
365d3207ac2713386ed61c6ca8f0356e8f093a62e1Paul Duffinimport static org.junit.Assert.fail;
3787182e06b8f6ec9a11ed6ebcaf74444e79b18ae2Paul Duffinimport static org.mockito.Mockito.any;
385d3207ac2713386ed61c6ca8f0356e8f093a62e1Paul Duffinimport static org.mockito.Mockito.verify;
395d3207ac2713386ed61c6ca8f0356e8f093a62e1Paul Duffinimport static org.mockito.Mockito.verifyNoMoreInteractions;
4087182e06b8f6ec9a11ed6ebcaf74444e79b18ae2Paul Duffinimport static org.mockito.Mockito.when;
415d3207ac2713386ed61c6ca8f0356e8f093a62e1Paul Duffin
425d3207ac2713386ed61c6ca8f0356e8f093a62e1Paul Duffin/**
435d3207ac2713386ed61c6ca8f0356e8f093a62e1Paul Duffin * Tests {@link AbstractProducer}.
445d3207ac2713386ed61c6ca8f0356e8f093a62e1Paul Duffin */
455d3207ac2713386ed61c6ca8f0356e8f093a62e1Paul Duffin@RunWith(JUnit4.class)
465d3207ac2713386ed61c6ca8f0356e8f093a62e1Paul Duffinpublic class AbstractProducerTest {
4787182e06b8f6ec9a11ed6ebcaf74444e79b18ae2Paul Duffin  @Mock private ProductionComponentMonitor componentMonitor;
4887182e06b8f6ec9a11ed6ebcaf74444e79b18ae2Paul Duffin  private ProducerMonitor monitor;
4987182e06b8f6ec9a11ed6ebcaf74444e79b18ae2Paul Duffin  private Provider<ProductionComponentMonitor> componentMonitorProvider;
505d3207ac2713386ed61c6ca8f0356e8f093a62e1Paul Duffin
515d3207ac2713386ed61c6ca8f0356e8f093a62e1Paul Duffin  @Before
525d3207ac2713386ed61c6ca8f0356e8f093a62e1Paul Duffin  public void initMocks() {
535d3207ac2713386ed61c6ca8f0356e8f093a62e1Paul Duffin    MockitoAnnotations.initMocks(this);
5487182e06b8f6ec9a11ed6ebcaf74444e79b18ae2Paul Duffin    monitor = Mockito.mock(ProducerMonitor.class, Mockito.CALLS_REAL_METHODS);
5587182e06b8f6ec9a11ed6ebcaf74444e79b18ae2Paul Duffin    when(componentMonitor.producerMonitorFor(any(ProducerToken.class))).thenReturn(monitor);
5687182e06b8f6ec9a11ed6ebcaf74444e79b18ae2Paul Duffin    componentMonitorProvider =
5787182e06b8f6ec9a11ed6ebcaf74444e79b18ae2Paul Duffin        new Provider<ProductionComponentMonitor>() {
5887182e06b8f6ec9a11ed6ebcaf74444e79b18ae2Paul Duffin          @Override
5987182e06b8f6ec9a11ed6ebcaf74444e79b18ae2Paul Duffin          public ProductionComponentMonitor get() {
6087182e06b8f6ec9a11ed6ebcaf74444e79b18ae2Paul Duffin            return componentMonitor;
6187182e06b8f6ec9a11ed6ebcaf74444e79b18ae2Paul Duffin          }
6287182e06b8f6ec9a11ed6ebcaf74444e79b18ae2Paul Duffin        };
635d3207ac2713386ed61c6ca8f0356e8f093a62e1Paul Duffin  }
645d3207ac2713386ed61c6ca8f0356e8f093a62e1Paul Duffin
655d3207ac2713386ed61c6ca8f0356e8f093a62e1Paul Duffin  @Test
665d3207ac2713386ed61c6ca8f0356e8f093a62e1Paul Duffin  public void get_nullPointerException() {
6787182e06b8f6ec9a11ed6ebcaf74444e79b18ae2Paul Duffin    Producer<Object> producer = new DelegateProducer<>(componentMonitorProvider, null);
685d3207ac2713386ed61c6ca8f0356e8f093a62e1Paul Duffin    try {
695d3207ac2713386ed61c6ca8f0356e8f093a62e1Paul Duffin      producer.get();
705d3207ac2713386ed61c6ca8f0356e8f093a62e1Paul Duffin      fail();
715d3207ac2713386ed61c6ca8f0356e8f093a62e1Paul Duffin    } catch (NullPointerException expected) {
725d3207ac2713386ed61c6ca8f0356e8f093a62e1Paul Duffin    }
735d3207ac2713386ed61c6ca8f0356e8f093a62e1Paul Duffin  }
745d3207ac2713386ed61c6ca8f0356e8f093a62e1Paul Duffin
755d3207ac2713386ed61c6ca8f0356e8f093a62e1Paul Duffin  @Test public void get() throws Exception {
765d3207ac2713386ed61c6ca8f0356e8f093a62e1Paul Duffin    Producer<Integer> producer =
7787182e06b8f6ec9a11ed6ebcaf74444e79b18ae2Paul Duffin        new AbstractProducer<Integer>(componentMonitorProvider, null) {
785d3207ac2713386ed61c6ca8f0356e8f093a62e1Paul Duffin          int i = 0;
795d3207ac2713386ed61c6ca8f0356e8f093a62e1Paul Duffin
805d3207ac2713386ed61c6ca8f0356e8f093a62e1Paul Duffin          @Override
8187182e06b8f6ec9a11ed6ebcaf74444e79b18ae2Paul Duffin          public ListenableFuture<Integer> compute(ProducerMonitor unusedMonitor) {
825d3207ac2713386ed61c6ca8f0356e8f093a62e1Paul Duffin            return Futures.immediateFuture(i++);
835d3207ac2713386ed61c6ca8f0356e8f093a62e1Paul Duffin          }
845d3207ac2713386ed61c6ca8f0356e8f093a62e1Paul Duffin        };
855d3207ac2713386ed61c6ca8f0356e8f093a62e1Paul Duffin    assertThat(producer.get().get()).isEqualTo(0);
865d3207ac2713386ed61c6ca8f0356e8f093a62e1Paul Duffin    assertThat(producer.get().get()).isEqualTo(0);
875d3207ac2713386ed61c6ca8f0356e8f093a62e1Paul Duffin    assertThat(producer.get().get()).isEqualTo(0);
885d3207ac2713386ed61c6ca8f0356e8f093a62e1Paul Duffin  }
895d3207ac2713386ed61c6ca8f0356e8f093a62e1Paul Duffin
905d3207ac2713386ed61c6ca8f0356e8f093a62e1Paul Duffin  @Test
915d3207ac2713386ed61c6ca8f0356e8f093a62e1Paul Duffin  public void monitor_success() throws Exception {
925d3207ac2713386ed61c6ca8f0356e8f093a62e1Paul Duffin    SettableFuture<Integer> delegateFuture = SettableFuture.create();
9387182e06b8f6ec9a11ed6ebcaf74444e79b18ae2Paul Duffin    Producer<Integer> producer = new DelegateProducer<>(componentMonitorProvider, delegateFuture);
945d3207ac2713386ed61c6ca8f0356e8f093a62e1Paul Duffin
955d3207ac2713386ed61c6ca8f0356e8f093a62e1Paul Duffin    ListenableFuture<Integer> future = producer.get();
965d3207ac2713386ed61c6ca8f0356e8f093a62e1Paul Duffin    assertThat(future.isDone()).isFalse();
9787182e06b8f6ec9a11ed6ebcaf74444e79b18ae2Paul Duffin    verify(monitor).addCallbackTo(any(ListenableFuture.class));
985d3207ac2713386ed61c6ca8f0356e8f093a62e1Paul Duffin    delegateFuture.set(-42);
995d3207ac2713386ed61c6ca8f0356e8f093a62e1Paul Duffin    assertThat(future.get()).isEqualTo(-42);
1005d3207ac2713386ed61c6ca8f0356e8f093a62e1Paul Duffin    verify(monitor).succeeded(-42);
1015d3207ac2713386ed61c6ca8f0356e8f093a62e1Paul Duffin    verifyNoMoreInteractions(monitor);
1025d3207ac2713386ed61c6ca8f0356e8f093a62e1Paul Duffin  }
1035d3207ac2713386ed61c6ca8f0356e8f093a62e1Paul Duffin
1045d3207ac2713386ed61c6ca8f0356e8f093a62e1Paul Duffin  @Test
1055d3207ac2713386ed61c6ca8f0356e8f093a62e1Paul Duffin  public void monitor_failure() throws Exception {
1065d3207ac2713386ed61c6ca8f0356e8f093a62e1Paul Duffin    SettableFuture<Integer> delegateFuture = SettableFuture.create();
10787182e06b8f6ec9a11ed6ebcaf74444e79b18ae2Paul Duffin    Producer<Integer> producer = new DelegateProducer<>(componentMonitorProvider, delegateFuture);
1085d3207ac2713386ed61c6ca8f0356e8f093a62e1Paul Duffin
1095d3207ac2713386ed61c6ca8f0356e8f093a62e1Paul Duffin    ListenableFuture<Integer> future = producer.get();
1105d3207ac2713386ed61c6ca8f0356e8f093a62e1Paul Duffin    assertThat(future.isDone()).isFalse();
11187182e06b8f6ec9a11ed6ebcaf74444e79b18ae2Paul Duffin    verify(monitor).addCallbackTo(any(ListenableFuture.class));
1125d3207ac2713386ed61c6ca8f0356e8f093a62e1Paul Duffin    Throwable t = new RuntimeException("monkey");
1135d3207ac2713386ed61c6ca8f0356e8f093a62e1Paul Duffin    delegateFuture.setException(t);
1145d3207ac2713386ed61c6ca8f0356e8f093a62e1Paul Duffin    try {
1155d3207ac2713386ed61c6ca8f0356e8f093a62e1Paul Duffin      future.get();
1165d3207ac2713386ed61c6ca8f0356e8f093a62e1Paul Duffin      fail();
1175d3207ac2713386ed61c6ca8f0356e8f093a62e1Paul Duffin    } catch (ExecutionException e) {
1185d3207ac2713386ed61c6ca8f0356e8f093a62e1Paul Duffin      assertThat(e.getCause()).isSameAs(t);
1195d3207ac2713386ed61c6ca8f0356e8f093a62e1Paul Duffin    }
1205d3207ac2713386ed61c6ca8f0356e8f093a62e1Paul Duffin    verify(monitor).failed(t);
1215d3207ac2713386ed61c6ca8f0356e8f093a62e1Paul Duffin    verifyNoMoreInteractions(monitor);
1225d3207ac2713386ed61c6ca8f0356e8f093a62e1Paul Duffin  }
1235d3207ac2713386ed61c6ca8f0356e8f093a62e1Paul Duffin
12487182e06b8f6ec9a11ed6ebcaf74444e79b18ae2Paul Duffin  @Test(expected = NullPointerException.class)
1255d3207ac2713386ed61c6ca8f0356e8f093a62e1Paul Duffin  public void monitor_null() throws Exception {
12687182e06b8f6ec9a11ed6ebcaf74444e79b18ae2Paul Duffin    new DelegateProducer<>(null, Futures.immediateFuture(42));
1275d3207ac2713386ed61c6ca8f0356e8f093a62e1Paul Duffin  }
1285d3207ac2713386ed61c6ca8f0356e8f093a62e1Paul Duffin
1295d3207ac2713386ed61c6ca8f0356e8f093a62e1Paul Duffin  static final class DelegateProducer<T> extends AbstractProducer<T> {
1305d3207ac2713386ed61c6ca8f0356e8f093a62e1Paul Duffin    private final ListenableFuture<T> delegate;
1315d3207ac2713386ed61c6ca8f0356e8f093a62e1Paul Duffin
13287182e06b8f6ec9a11ed6ebcaf74444e79b18ae2Paul Duffin    DelegateProducer(
13387182e06b8f6ec9a11ed6ebcaf74444e79b18ae2Paul Duffin        Provider<ProductionComponentMonitor> componentMonitorProvider,
13487182e06b8f6ec9a11ed6ebcaf74444e79b18ae2Paul Duffin        ListenableFuture<T> delegate) {
13587182e06b8f6ec9a11ed6ebcaf74444e79b18ae2Paul Duffin      super(componentMonitorProvider, null);
1365d3207ac2713386ed61c6ca8f0356e8f093a62e1Paul Duffin      this.delegate = delegate;
1375d3207ac2713386ed61c6ca8f0356e8f093a62e1Paul Duffin    }
1385d3207ac2713386ed61c6ca8f0356e8f093a62e1Paul Duffin
1395d3207ac2713386ed61c6ca8f0356e8f093a62e1Paul Duffin    @Override
14087182e06b8f6ec9a11ed6ebcaf74444e79b18ae2Paul Duffin    public ListenableFuture<T> compute(ProducerMonitor unusedMonitor) {
1415d3207ac2713386ed61c6ca8f0356e8f093a62e1Paul Duffin      return delegate;
1425d3207ac2713386ed61c6ca8f0356e8f093a62e1Paul Duffin    }
1435d3207ac2713386ed61c6ca8f0356e8f093a62e1Paul Duffin  }
1445d3207ac2713386ed61c6ca8f0356e8f093a62e1Paul Duffin}
145