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