Home | History | Annotate | Download | only in monitoring
      1 /*
      2  * Copyright (C) 2015 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  */
     16 package producerstest.monitoring;
     17 
     18 import com.google.common.base.Throwables;
     19 import com.google.common.collect.ImmutableList;
     20 import com.google.common.util.concurrent.ListenableFuture;
     21 import com.google.common.util.concurrent.MoreExecutors;
     22 import com.google.common.util.concurrent.SettableFuture;
     23 import dagger.producers.monitoring.ProducerMonitor;
     24 import dagger.producers.monitoring.ProducerToken;
     25 import dagger.producers.monitoring.ProductionComponentMonitor;
     26 import java.util.LinkedHashMap;
     27 import java.util.Map;
     28 import java.util.concurrent.ExecutionException;
     29 import org.junit.Before;
     30 import org.junit.Test;
     31 import org.junit.runner.RunWith;
     32 import org.junit.runners.JUnit4;
     33 import org.mockito.InOrder;
     34 import org.mockito.Mock;
     35 import org.mockito.MockitoAnnotations;
     36 
     37 import static com.google.common.truth.Truth.assertThat;
     38 import static org.junit.Assert.fail;
     39 import static org.mockito.Mockito.any;
     40 import static org.mockito.Mockito.inOrder;
     41 import static org.mockito.Mockito.mock;
     42 import static org.mockito.Mockito.verifyNoMoreInteractions;
     43 import static org.mockito.Mockito.when;
     44 
     45 /** Tests for production components using monitoring. */
     46 @RunWith(JUnit4.class)
     47 public final class MonitoringTest {
     48   @Mock private ProductionComponentMonitor.Factory componentMonitorFactory;
     49   @Mock private StringStub server1;
     50   @Mock private StringStub server2;
     51   private SettableFuture<String> server1Future;
     52   private SettableFuture<String> server2Future;
     53   private FakeProductionComponentMonitor componentMonitor;
     54 
     55   @Before
     56   public void setUp() {
     57     MockitoAnnotations.initMocks(this);
     58     componentMonitor = new FakeProductionComponentMonitor();
     59     when(componentMonitorFactory.create(any())).thenReturn(componentMonitor);
     60     server1Future = SettableFuture.create();
     61     server2Future = SettableFuture.create();
     62     when(server1.run(any(String.class))).thenReturn(server1Future);
     63     when(server2.run(any(String.class))).thenReturn(server2Future);
     64   }
     65 
     66   @Test
     67   public void basicMonitoring() throws Exception {
     68     MonitoredComponent component =
     69         DaggerMonitoredComponent.builder()
     70             .executor(MoreExecutors.directExecutor())
     71             .monitoringModule(new MonitoringModule(componentMonitorFactory))
     72             .stubModule(new StubModule(server1, server2))
     73             .build();
     74     ListenableFuture<String> output = component.output();
     75     assertThat(componentMonitor.monitors).hasSize(3);
     76     ImmutableList<Map.Entry<ProducerToken, ProducerMonitor>> entries =
     77         ImmutableList.copyOf(componentMonitor.monitors.entrySet());
     78     assertThat(entries.get(0).getKey().toString()).contains("CallServer2");
     79     assertThat(entries.get(1).getKey().toString()).contains("CallServer1");
     80     assertThat(entries.get(2).getKey().toString()).contains("RequestData");
     81 
     82     ProducerMonitor callServer2Monitor = entries.get(0).getValue();
     83     ProducerMonitor callServer1Monitor = entries.get(1).getValue();
     84     ProducerMonitor requestDataMonitor = entries.get(2).getValue();
     85 
     86     InOrder inOrder = inOrder(requestDataMonitor, callServer1Monitor, callServer2Monitor);
     87     inOrder.verify(requestDataMonitor).methodStarting();
     88     inOrder.verify(requestDataMonitor).methodFinished();
     89     inOrder.verify(requestDataMonitor).succeeded("Hello, World!");
     90     inOrder.verify(callServer1Monitor).methodStarting();
     91     inOrder.verify(callServer1Monitor).methodFinished();
     92     verifyNoMoreInteractions(requestDataMonitor, callServer1Monitor, callServer2Monitor);
     93 
     94     server1Future.set("server 1 response");
     95     inOrder.verify(callServer1Monitor).succeeded("server 1 response");
     96     inOrder.verify(callServer2Monitor).methodStarting();
     97     inOrder.verify(callServer2Monitor).methodFinished();
     98     verifyNoMoreInteractions(requestDataMonitor, callServer1Monitor, callServer2Monitor);
     99 
    100     server2Future.set("server 2 response");
    101     inOrder.verify(callServer2Monitor).succeeded("server 2 response");
    102     verifyNoMoreInteractions(requestDataMonitor, callServer1Monitor, callServer2Monitor);
    103     assertThat(output.get()).isEqualTo("server 2 response");
    104   }
    105 
    106   @Test
    107   public void basicMonitoringWithFailure() throws Exception {
    108     MonitoredComponent component =
    109         DaggerMonitoredComponent.builder()
    110             .executor(MoreExecutors.directExecutor())
    111             .monitoringModule(new MonitoringModule(componentMonitorFactory))
    112             .stubModule(new StubModule(server1, server2))
    113             .build();
    114     ListenableFuture<String> output = component.output();
    115     assertThat(componentMonitor.monitors).hasSize(3);
    116     ImmutableList<Map.Entry<ProducerToken, ProducerMonitor>> entries =
    117         ImmutableList.copyOf(componentMonitor.monitors.entrySet());
    118     assertThat(entries.get(0).getKey().toString()).contains("CallServer2");
    119     assertThat(entries.get(1).getKey().toString()).contains("CallServer1");
    120     assertThat(entries.get(2).getKey().toString()).contains("RequestData");
    121 
    122     ProducerMonitor callServer2Monitor = entries.get(0).getValue();
    123     ProducerMonitor callServer1Monitor = entries.get(1).getValue();
    124     ProducerMonitor requestDataMonitor = entries.get(2).getValue();
    125 
    126     InOrder inOrder = inOrder(requestDataMonitor, callServer1Monitor, callServer2Monitor);
    127     inOrder.verify(requestDataMonitor).methodStarting();
    128     inOrder.verify(requestDataMonitor).methodFinished();
    129     inOrder.verify(requestDataMonitor).succeeded("Hello, World!");
    130     inOrder.verify(callServer1Monitor).methodStarting();
    131     inOrder.verify(callServer1Monitor).methodFinished();
    132     verifyNoMoreInteractions(requestDataMonitor, callServer1Monitor, callServer2Monitor);
    133 
    134     RuntimeException cause = new RuntimeException("monkey");
    135     server1Future.setException(cause);
    136     inOrder.verify(callServer1Monitor).failed(cause);
    137     inOrder.verify(callServer2Monitor).failed(any(Throwable.class));
    138     verifyNoMoreInteractions(requestDataMonitor, callServer1Monitor, callServer2Monitor);
    139     try {
    140       output.get();
    141       fail();
    142     } catch (ExecutionException e) {
    143       assertThat(Throwables.getRootCause(e)).isSameAs(cause);
    144     }
    145   }
    146 
    147   private static final class FakeProductionComponentMonitor implements ProductionComponentMonitor {
    148     final Map<ProducerToken, ProducerMonitor> monitors = new LinkedHashMap<>();
    149 
    150     @Override
    151     public ProducerMonitor producerMonitorFor(ProducerToken token) {
    152       ProducerMonitor monitor = mock(ProducerMonitor.class);
    153       monitors.put(token, monitor);
    154       return monitor;
    155     }
    156   }
    157 }
    158