Update To 11.40.268.0
[platform/framework/web/crosswalk.git] / src / components / devtools_bridge / test / android / javatests / src / org / chromium / components / devtools_bridge / SignalingThreadMock.java
1 // Copyright 2014 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4
5 package org.chromium.components.devtools_bridge;
6
7 import java.util.concurrent.BlockingQueue;
8 import java.util.concurrent.Callable;
9 import java.util.concurrent.ExecutionException;
10 import java.util.concurrent.ExecutorService;
11 import java.util.concurrent.Executors;
12 import java.util.concurrent.LinkedBlockingDeque;
13 import java.util.concurrent.ScheduledExecutorService;
14 import java.util.concurrent.ScheduledFuture;
15 import java.util.concurrent.TimeUnit;
16 import java.util.concurrent.atomic.AtomicInteger;
17
18 /**
19  * Convinience class for tests. Like WebRTC threads supports posts
20  * and synchronous invokes.
21  */
22 class SignalingThreadMock {
23     // TODO: use scaleTimeout when natives for org.chromium.base get available.
24     private static final int EXECUTION_TIME_LIMIT_MS = 5000;
25
26     private final AtomicInteger mInvokationCounter = new AtomicInteger(0);
27     private final ExecutorService mExecutor = Executors.newSingleThreadExecutor();
28     private final ScheduledExecutorService mWatchDogExecutor =
29             Executors.newSingleThreadScheduledExecutor();
30     private ScheduledFuture<?> mWatchDogFuture;
31     private final Thread mThread;
32     private final BlockingQueue<Runnable> mExecutionQueue = new LinkedBlockingDeque<Runnable>();
33
34     public SignalingThreadMock() {
35         mThread = new Thread() {
36             @Override
37             public void run() {
38                 try {
39                     runExecutionLoop();
40                 } catch (InterruptedException e) {
41                     // Normal finish.
42                 }
43             }
44         };
45         mThread.start();
46     }
47
48     private void runExecutionLoop() throws InterruptedException {
49         while (true) {
50             mExecutionQueue.take().run();
51         }
52     }
53
54     public void invoke(final Runnable runnable) {
55         try {
56             invoke(new TestUtils.RunnableAdapter(runnable));
57         } catch (Exception e) {
58             throw new RuntimeException(e);
59         }
60     }
61
62     public <T> T invoke(final Callable<T> callable) throws Exception {
63         if (isOnThread()) return callable.call();
64
65         try {
66             return new InvokeWrapper<T>(callable).invoke();
67         } catch (InterruptedException e) {
68             throw new RuntimeException(e);
69         } catch (ExecutionException e) {
70             throw (Exception) e.getCause();
71         }
72     }
73
74     public void post(Runnable runnable) {
75         boolean success = mExecutionQueue.offer(new PostWrapper(runnable));
76         assert success;
77     }
78
79     public void dispose() {
80         mWatchDogExecutor.shutdown();
81         mThread.interrupt();
82         try {
83             mThread.join();
84         } catch (InterruptedException e) {
85             Thread.currentThread().interrupt();
86         }
87     }
88
89     public boolean isOnThread() {
90         return Thread.currentThread() == mThread;
91     }
92
93     private void onStartedExecution(final int index, final Exception timeoutException) {
94         mWatchDogFuture = mWatchDogExecutor.schedule(new Runnable() {
95             @Override
96             public void run() {
97                 throw new RuntimeException(
98                         "Time limit on " + Integer.toString(index) + " invocation",
99                         timeoutException);
100             }
101         }, EXECUTION_TIME_LIMIT_MS, TimeUnit.MILLISECONDS);
102     }
103
104     private void onFinishedExecution() {
105         mWatchDogFuture.cancel(false);
106     }
107
108     private abstract class WrapperBase implements Runnable {
109         private final int mIndex;
110         private final Exception mTimeoutException;
111
112         protected WrapperBase() {
113             mIndex = mInvokationCounter.incrementAndGet();
114             mTimeoutException = new Exception("Timeout exception");
115         }
116
117         @Override
118         public final void run() {
119             onStartedExecution(mIndex, mTimeoutException);
120             try {
121                 runWrapped();
122             } finally {
123                 onFinishedExecution();
124             }
125         }
126
127         protected abstract void runWrapped();
128     }
129
130     private class InvokeWrapper<T> extends WrapperBase {
131         private final Callable<T> mWrapped;
132         private final TestUtils.InvokeHelper<T> mHelper = new TestUtils.InvokeHelper<T>();
133
134         public InvokeWrapper(Callable<T> wrapped) {
135             mWrapped = wrapped;
136         }
137
138         @Override
139         protected void runWrapped() {
140             mHelper.runOnTargetThread(mWrapped);
141         }
142
143         public T invoke() throws Exception {
144             boolean success = mExecutionQueue.offer(this);
145             assert success;
146             return mHelper.takeResult();
147         }
148     }
149
150     private class PostWrapper extends WrapperBase {
151         private final Runnable mWrapped;
152
153         public PostWrapper(Runnable wrapped) {
154             mWrapped = wrapped;
155         }
156
157         @Override
158         protected void runWrapped() {
159             mWrapped.run();
160         }
161     }
162 }