3 * Licensed to the Apache Software Foundation (ASF) under one
4 * or more contributor license agreements. See the NOTICE file
5 * distributed with this work for additional information
6 * regarding copyright ownership. The ASF licenses this file
7 * to you under the Apache License, Version 2.0 (the
8 * "License"); you may not use this file except in compliance
9 * with the License. You may obtain a copy of the License at
11 * http://www.apache.org/licenses/LICENSE-2.0
13 * Unless required by applicable law or agreed to in writing, software
14 * distributed under the License is distributed on an "AS IS" BASIS,
15 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16 * See the License for the specific language governing permissions and
17 * limitations under the License.
19 package org
.apache
.hadoop
.hbase
;
21 import java
.io
.IOException
;
22 import java
.util
.HashSet
;
23 import java
.util
.List
;
25 import java
.util
.concurrent
.ExecutionException
;
26 import java
.util
.concurrent
.Future
;
28 import org
.apache
.hadoop
.conf
.Configuration
;
29 import org
.slf4j
.Logger
;
30 import org
.slf4j
.LoggerFactory
;
32 public abstract class MultithreadedTestUtil
{
34 private static final Logger LOG
=
35 LoggerFactory
.getLogger(MultithreadedTestUtil
.class);
37 public static class TestContext
{
38 private final Configuration conf
;
39 private Throwable err
= null;
40 private boolean stopped
= false;
41 private int threadDoneCount
= 0;
42 private Set
<TestThread
> testThreads
= new HashSet
<>();
44 public TestContext(Configuration configuration
) {
45 this.conf
= configuration
;
48 protected Configuration
getConf() {
52 public synchronized boolean shouldRun() {
53 return !stopped
&& err
== null;
56 public void addThread(TestThread t
) {
60 public void startThreads() {
61 for (TestThread t
: testThreads
) {
66 public void waitFor(long millis
) throws Exception
{
67 long endTime
= System
.currentTimeMillis() + millis
;
69 long left
= endTime
- System
.currentTimeMillis();
77 private synchronized void checkException() throws Exception
{
79 throw new RuntimeException("Deferred", err
);
83 public synchronized void threadFailed(Throwable t
) {
84 if (err
== null) err
= t
;
85 LOG
.error("Failed!", err
);
89 public synchronized void threadDone() {
93 public void setStopFlag(boolean s
) throws Exception
{
99 public void stop() throws Exception
{
100 synchronized (this) {
103 for (TestThread t
: testThreads
) {
111 * A thread that can be added to a test context, and properly
112 * passes exceptions through.
114 public static abstract class TestThread
extends Thread
{
115 protected final TestContext ctx
;
116 protected boolean stopped
;
118 public TestThread(TestContext ctx
) {
126 } catch (Throwable t
) {
132 public abstract void doWork() throws Exception
;
134 protected void stopTestThread() {
140 * A test thread that performs a repeating operation.
142 public static abstract class RepeatingTestThread
extends TestThread
{
143 public RepeatingTestThread(TestContext ctx
) {
148 public final void doWork() throws Exception
{
150 while (ctx
.shouldRun() && !stopped
) {
158 public abstract void doAnAction() throws Exception
;
159 public void workDone() throws IOException
{}
163 * Verify that no assertions have failed inside a future.
164 * Used for unit tests that spawn threads. E.g.,
167 * List<Future<Void>> results = Lists.newArrayList();
168 * Future<Void> f = executor.submit(new Callable<Void> {
169 * public Void call() {
170 * assertTrue(someMethod());
174 * assertOnFutures(results);
176 * @param threadResults A list of futures
177 * @throws InterruptedException If interrupted when waiting for a result
178 * from one of the futures
179 * @throws ExecutionException If an exception other than AssertionError
180 * occurs inside any of the futures
182 public static void assertOnFutures(List
<Future
<?
>> threadResults
)
183 throws InterruptedException
, ExecutionException
{
184 for (Future
<?
> threadResult
: threadResults
) {
187 } catch (ExecutionException e
) {
188 if (e
.getCause() instanceof AssertionError
) {
189 throw (AssertionError
) e
.getCause();