• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2017 The Guava 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 com.google.common.util.concurrent;
18 
19 import static com.google.common.truth.Truth.assertThat;
20 import static com.google.common.truth.Truth.assertWithMessage;
21 import static com.google.common.util.concurrent.MoreExecutors.shutdownAndAwaitTermination;
22 import static com.google.common.util.concurrent.Uninterruptibles.awaitUninterruptibly;
23 import static java.util.concurrent.Executors.newSingleThreadExecutor;
24 import static java.util.concurrent.TimeUnit.SECONDS;
25 
26 import com.google.common.util.concurrent.ClosingFuture.ClosingCallable;
27 import com.google.common.util.concurrent.ClosingFuture.DeferredCloser;
28 import com.google.common.util.concurrent.ClosingFuture.ValueAndCloser;
29 import com.google.common.util.concurrent.ClosingFuture.ValueAndCloserConsumer;
30 import java.io.Closeable;
31 import java.util.concurrent.CountDownLatch;
32 import java.util.concurrent.ExecutionException;
33 import java.util.concurrent.Executor;
34 import java.util.concurrent.ExecutorService;
35 
36 /**
37  * Tests for {@link ClosingFuture} that exercise {@link
38  * ClosingFuture#finishToValueAndCloser(ValueAndCloserConsumer, Executor)}.
39  */
40 public class ClosingFutureFinishToValueAndCloserTest extends AbstractClosingFutureTest {
41   private final ExecutorService finishToValueAndCloserExecutor = newSingleThreadExecutor();
42   private volatile ValueAndCloser<?> valueAndCloser;
43 
44   @Override
tearDown()45   protected void tearDown() throws Exception {
46     super.tearDown();
47     assertWithMessage("finishToValueAndCloserExecutor was shut down")
48         .that(shutdownAndAwaitTermination(finishToValueAndCloserExecutor, 10, SECONDS))
49         .isTrue();
50   }
51 
testFinishToValueAndCloser_throwsIfCalledTwice()52   public void testFinishToValueAndCloser_throwsIfCalledTwice() throws Exception {
53     ClosingFuture<Closeable> closingFuture =
54         ClosingFuture.submit(
55             new ClosingCallable<Closeable>() {
56               @Override
57               public Closeable call(DeferredCloser closer) throws Exception {
58                 return closer.eventuallyClose(mockCloseable, executor);
59               }
60             },
61             executor);
62     closingFuture.finishToValueAndCloser(
63         new NoOpValueAndCloserConsumer<>(), finishToValueAndCloserExecutor);
64     try {
65       closingFuture.finishToValueAndCloser(
66           new NoOpValueAndCloserConsumer<>(), finishToValueAndCloserExecutor);
67       fail("should have thrown");
68     } catch (IllegalStateException expected) {
69     }
70   }
71 
testFinishToValueAndCloser_throwsAfterCallingFinishToFuture()72   public void testFinishToValueAndCloser_throwsAfterCallingFinishToFuture() throws Exception {
73     ClosingFuture<Closeable> closingFuture =
74         ClosingFuture.submit(
75             new ClosingCallable<Closeable>() {
76               @Override
77               public Closeable call(DeferredCloser closer) throws Exception {
78                 return closer.eventuallyClose(mockCloseable, executor);
79               }
80             },
81             executor);
82     FluentFuture<Closeable> unused = closingFuture.finishToFuture();
83     try {
84       closingFuture.finishToValueAndCloser(
85           new NoOpValueAndCloserConsumer<>(), finishToValueAndCloserExecutor);
86       fail("should have thrown");
87     } catch (IllegalStateException expected) {
88     }
89   }
90 
91   @Override
getFinalValue(ClosingFuture<T> closingFuture)92   <T> T getFinalValue(ClosingFuture<T> closingFuture) throws ExecutionException {
93     return finishToValueAndCloser(closingFuture).get();
94   }
95 
96   @Override
assertFinallyFailsWithException(ClosingFuture<?> closingFuture)97   void assertFinallyFailsWithException(ClosingFuture<?> closingFuture) {
98     assertThatFutureFailsWithException(closingFuture.statusFuture());
99     ValueAndCloser<?> valueAndCloser = finishToValueAndCloser(closingFuture);
100     try {
101       valueAndCloser.get();
102       fail();
103     } catch (ExecutionException expected) {
104       assertThat(expected).hasCauseThat().isSameInstanceAs(exception);
105     }
106     valueAndCloser.closeAsync();
107   }
108 
109   @Override
assertBecomesCanceled(ClosingFuture<?> closingFuture)110   void assertBecomesCanceled(ClosingFuture<?> closingFuture) throws ExecutionException {
111     assertThatFutureBecomesCancelled(closingFuture.statusFuture());
112   }
113 
114   @Override
waitUntilClosed(ClosingFuture<?> closingFuture)115   void waitUntilClosed(ClosingFuture<?> closingFuture) {
116     if (valueAndCloser != null) {
117       valueAndCloser.closeAsync();
118     }
119     super.waitUntilClosed(closingFuture);
120   }
121 
122   @Override
cancelFinalStepAndWait(ClosingFuture<TestCloseable> closingFuture)123   void cancelFinalStepAndWait(ClosingFuture<TestCloseable> closingFuture) {
124     assertThat(closingFuture.cancel(false)).isTrue();
125     ValueAndCloser<?> unused = finishToValueAndCloser(closingFuture);
126     waitUntilClosed(closingFuture);
127     futureCancelled.countDown();
128   }
129 
finishToValueAndCloser(ClosingFuture<V> closingFuture)130   private <V> ValueAndCloser<V> finishToValueAndCloser(ClosingFuture<V> closingFuture) {
131     final CountDownLatch valueAndCloserSet = new CountDownLatch(1);
132     closingFuture.finishToValueAndCloser(
133         new ValueAndCloserConsumer<V>() {
134           @Override
135           public void accept(ValueAndCloser<V> valueAndCloser) {
136             ClosingFutureFinishToValueAndCloserTest.this.valueAndCloser = valueAndCloser;
137             valueAndCloserSet.countDown();
138           }
139         },
140         finishToValueAndCloserExecutor);
141     assertWithMessage("valueAndCloser was set")
142         .that(awaitUninterruptibly(valueAndCloserSet, 10, SECONDS))
143         .isTrue();
144     @SuppressWarnings("unchecked")
145     ValueAndCloser<V> valueAndCloserWithType = (ValueAndCloser<V>) valueAndCloser;
146     return valueAndCloserWithType;
147   }
148 }
149