1package io.flutter.embedding.engine.dart;
3import static android.os.Looper.getMainLooper;
4import static junit.framework.TestCase.assertEquals;
5import static junit.framework.TestCase.assertNotNull;
6import static junit.framework.TestCase.assertTrue;
7import static org.junit.Assert.assertArrayEquals;
8import static org.mockito.ArgumentMatchers.any;
9import static org.mockito.ArgumentMatchers.anyInt;
10import static org.mockito.ArgumentMatchers.eq;
11import static org.mockito.Mockito.mock;
12import static org.mockito.Mockito.never;
13import static org.mockito.Mockito.times;
14import static org.mockito.Mockito.verify;
15import static org.robolectric.Shadows.shadowOf;
17import androidx.test.ext.junit.runners.AndroidJUnit4;
18import io.flutter.embedding.engine.FlutterJNI;
19import io.flutter.embedding.engine.dart.DartMessenger.DartMessengerTaskQueue;
20import io.flutter.plugin.common.BinaryMessenger;
21import io.flutter.plugin.common.BinaryMessenger.BinaryMessageHandler;
22import java.nio.ByteBuffer;
23import java.util.LinkedList;
24import java.util.Random;
25import java.util.concurrent.CountDownLatch;
26import java.util.concurrent.ExecutorService;
27import java.util.concurrent.Executors;
29import org.junit.runner.RunWith;
30import org.mockito.ArgumentCaptor;
31import org.mockito.Mockito;
32import org.robolectric.annotation.Config;
35@RunWith(AndroidJUnit4.class)
37 SynchronousTaskQueue synchronousTaskQueue =
new SynchronousTaskQueue();
39 private static class ReportingUncaughtExceptionHandler
40 implements Thread.UncaughtExceptionHandler {
41 public Throwable latestException;
44 public void uncaughtException(Thread t, Throwable
e) {
49 private static class SynchronousTaskQueue
implements DartMessengerTaskQueue {
50 public void dispatch(Runnable runnable) {
59 final Thread currentThread = Thread.currentThread();
60 final Thread.UncaughtExceptionHandler savedHandler =
61 currentThread.getUncaughtExceptionHandler();
62 final ReportingUncaughtExceptionHandler reportingHandler =
63 new ReportingUncaughtExceptionHandler();
64 currentThread.setUncaughtExceptionHandler(reportingHandler);
70 Mockito.doThrow(AssertionError.class)
71 .when(throwingHandler)
76 assertNotNull(reportingHandler.latestException);
77 assertTrue(reportingHandler.latestException instanceof AssertionError);
78 currentThread.setUncaughtExceptionHandler(savedHandler);
87 final String channel =
"foobar";
88 final boolean[] wasDirect = {
false};
89 final BinaryMessenger.BinaryMessageHandler handler =
91 wasDirect[0] =
message.isDirect();
95 final ByteBuffer
message = ByteBuffer.allocateDirect(4 * 2);
102 assertTrue(wasDirect[0]);
111 final String channel =
"foobar";
112 final ByteBuffer[] byteBuffers = {
null};
113 final int bufferSize = 4 * 2;
114 final BinaryMessenger.BinaryMessageHandler handler =
117 assertEquals(bufferSize, byteBuffers[0].limit());
121 final ByteBuffer
message = ByteBuffer.allocateDirect(bufferSize);
128 assertNotNull(byteBuffers[0]);
129 assertTrue(byteBuffers[0].isDirect());
130 assertEquals(0, byteBuffers[0].limit());
138 final ByteBuffer
message = ByteBuffer.allocateDirect(4 * 2);
139 final String channel =
"foobar";
145 final ByteBuffer[] byteBuffers = {
null};
146 BinaryMessenger.BinaryReply
callback =
148 assertTrue(reply.isDirect());
149 byteBuffers[0] = reply;
153 assertEquals(0, byteBuffers[0].limit());
161 final String channel =
"foobar";
162 messenger.
send(channel,
null,
null);
163 verify(fakeFlutterJni,
times(1)).dispatchEmptyPlatformMessage(
eq(
"foobar"),
eq(1));
164 messenger.
send(channel,
null,
null);
165 verify(fakeFlutterJni,
times(1)).dispatchEmptyPlatformMessage(
eq(
"foobar"),
eq(2));
174 String channel =
"foobar";
175 BinaryMessenger.BinaryMessageHandler handler =
176 (ByteBuffer
message, BinaryMessenger.BinaryReply reply) -> {
180 final ByteBuffer
message = ByteBuffer.allocateDirect(4 * 2);
181 final int replyId = 1;
182 final long messageData = 1234;
184 verify(fakeFlutterJni).cleanupMessageData(
eq(messageData));
193 String channel =
"foobar";
194 BinaryMessenger.BinaryMessageHandler handler =
195 (ByteBuffer
message, BinaryMessenger.BinaryReply reply) -> {
196 throw new RuntimeException(
"hello");
199 final ByteBuffer
message = ByteBuffer.allocateDirect(4 * 2);
200 final int replyId = 1;
201 final long messageData = 1234;
204 verify(fakeFlutterJni).cleanupMessageData(
eq(messageData));
212 final String channel =
"foobar";
213 final ByteBuffer
message = ByteBuffer.allocateDirect(4 * 2);
214 final int replyId = 1;
215 final long messageData = 1234;
218 shadowOf(getMainLooper()).idle();
219 verify(fakeFlutterJni).invokePlatformMessageEmptyResponseCallback(replyId);
228 final String channel =
"foobar";
229 final ByteBuffer
message = ByteBuffer.allocateDirect(4 * 2);
230 final int replyId = 1;
231 final long messageData = 1234;
233 messenger.enableBufferingIncomingMessages();
236 shadowOf(getMainLooper()).idle();
237 verify(fakeFlutterJni, never()).invokePlatformMessageEmptyResponseCallback(
eq(replyId));
239 final BinaryMessenger.BinaryMessageHandler handler =
240 (ByteBuffer msg, BinaryMessenger.BinaryReply reply) -> {
241 reply.reply(ByteBuffer.wrap(
"done".getBytes()));
245 shadowOf(getMainLooper()).idle();
246 verify(fakeFlutterJni, never()).invokePlatformMessageEmptyResponseCallback(
eq(replyId));
248 final ArgumentCaptor<ByteBuffer> response = ArgumentCaptor.forClass(ByteBuffer.class);
249 verify(fakeFlutterJni)
250 .invokePlatformMessageResponseCallback(anyInt(), response.capture(), anyInt());
251 assertArrayEquals(
"done".getBytes(), response.getValue().array());
256 throws InterruptedException {
260 final String channel =
"foobar";
261 final ByteBuffer
message = ByteBuffer.allocateDirect(4 * 2);
262 final int replyId = 1;
263 final long messageData = 1234;
265 messenger.enableBufferingIncomingMessages();
267 shadowOf(getMainLooper()).idle();
268 verify(fakeFlutterJni, never()).invokePlatformMessageEmptyResponseCallback(replyId);
271 shadowOf(getMainLooper()).idle();
272 verify(fakeFlutterJni).invokePlatformMessageEmptyResponseCallback(replyId);
281 final String channel =
"foobar";
282 final ByteBuffer
message = ByteBuffer.allocateDirect(4 * 2);
283 final int replyId = 1;
284 final long messageData = 1234;
286 messenger.enableBufferingIncomingMessages();
289 shadowOf(getMainLooper()).idle();
290 verify(fakeFlutterJni, never()).invokePlatformMessageEmptyResponseCallback(
eq(replyId));
292 final BinaryMessenger.BinaryMessageHandler handler =
293 (ByteBuffer msg, BinaryMessenger.BinaryReply reply) -> {
294 reply.reply(ByteBuffer.wrap(
"done".getBytes()));
298 shadowOf(getMainLooper()).idle();
299 verify(fakeFlutterJni, never()).invokePlatformMessageEmptyResponseCallback(
eq(replyId));
301 final ArgumentCaptor<ByteBuffer> response = ArgumentCaptor.forClass(ByteBuffer.class);
302 verify(fakeFlutterJni)
303 .invokePlatformMessageResponseCallback(anyInt(), response.capture(), anyInt());
304 assertArrayEquals(
"done".getBytes(), response.getValue().array());
310 shadowOf(getMainLooper()).idle();
311 verify(fakeFlutterJni).invokePlatformMessageEmptyResponseCallback(replyId);
318 final ExecutorService taskQueuePool = Executors.newFixedThreadPool(4);
320 final int count = 5000;
321 final LinkedList<Integer> ints =
new LinkedList<>();
322 Random rand =
new Random();
328 Thread.sleep(rand.nextInt(10));
329 }
catch (InterruptedException ex) {
330 System.out.println(ex.toString());
334 taskQueuePool.execute(
338 Thread.sleep(rand.nextInt(10));
339 }
catch (InterruptedException ex) {
340 System.out.println(ex.toString());
344 CountDownLatch latch =
new CountDownLatch(1);
350 assertEquals(
count, ints.size());
351 for (
int i = 0;
i <
count - 1; ++
i) {
352 assertEquals((
int) ints.get(
i), (
int) (ints.get(
i + 1)) - 1);
static SkISize times(const SkISize &size, float factor)
static bool eq(const SkM44 &a, const SkM44 &b, float tol)
void emptyResponseWhenHandlerIsNotSet()
void replyIdIncrementsOnNullReply()
void givesDirectByteBuffer()
void directByteBufferLimitZeroAfterUsage()
void emptyResponseWhenHandlerIsUnregistered()
void testSerialTaskQueue()
void directByteBufferLimitZeroAfterReply()
void cleansUpMessageData()
void cleansUpMessageDataOnError()
void disableBufferingTriggersEmptyResponseForPendingMessages()
void buffersResponseWhenHandlerIsNotSet()
void setMessageHandler( @NonNull String channel, @Nullable BinaryMessenger.BinaryMessageHandler handler)
void handleMessageFromDart( @NonNull String channel, @Nullable ByteBuffer message, int replyId, long messageData)
TaskQueue makeBackgroundTaskQueue(TaskQueueOptions options)
void send(@NonNull String channel, @NonNull ByteBuffer message)
void handlePlatformMessageResponse(int replyId, @Nullable ByteBuffer reply)
void disableBufferingIncomingMessages()
FlKeyEvent uint64_t FlKeyResponderAsyncCallback callback
void dispatch(@NonNull Runnable runnable)
SIT bool any(const Vec< 1, T > &x)