| Index: remoting/android/javatests/src/org/chromium/chromoting/EventTest.java
|
| diff --git a/remoting/android/javatests/src/org/chromium/chromoting/EventTest.java b/remoting/android/javatests/src/org/chromium/chromoting/EventTest.java
|
| new file mode 100644
|
| index 0000000000000000000000000000000000000000..d6b9ebf646880b0e682d3032f163056d81acbc04
|
| --- /dev/null
|
| +++ b/remoting/android/javatests/src/org/chromium/chromoting/EventTest.java
|
| @@ -0,0 +1,184 @@
|
| +// Copyright 2016 The Chromium Authors. All rights reserved.
|
| +// Use of this source code is governed by a BSD-style license that can be
|
| +// found in the LICENSE file.
|
| +
|
| +package org.chromium.chromoting;
|
| +
|
| +import android.test.InstrumentationTestCase;
|
| +import android.test.suitebuilder.annotation.MediumTest;
|
| +import android.test.suitebuilder.annotation.SmallTest;
|
| +
|
| +import org.chromium.base.test.util.Feature;
|
| +
|
| +/**
|
| + * Tests for {@link Event}.
|
| + */
|
| +public class EventTest extends InstrumentationTestCase {
|
| + @SmallTest
|
| + @Feature({"Chromoting"})
|
| + public static void testBasicScenario() {
|
| + Event.Executor<Void> event = new Event.Executor<>();
|
| + final Counter callTimes = new Counter();
|
| + int eventId1 = event.add(new Event.ParameterRunnable<Void>() {
|
| + @Override
|
| + public void run(Void nil) {
|
| + callTimes.increment();
|
| + }
|
| + });
|
| + int eventId2 = event.add(new Event.ParameterRunnable<Void>() {
|
| + @Override
|
| + public void run(Void nil) {
|
| + callTimes.increment();
|
| + }
|
| + });
|
| + int eventId3 = event.add(new Event.ParameterRunnable<Void>() {
|
| + @Override
|
| + public void run(Void nil) {
|
| + // Should not reach.
|
| + assertTrue(false);
|
| + callTimes.increment();
|
| + }
|
| + });
|
| + assertTrue(eventId1 >= 0);
|
| + assertTrue(eventId2 >= 0);
|
| + assertTrue(eventId3 >= 0);
|
| + assertTrue(event.remove(eventId3));
|
| + for (int i = 0; i < 100; i++) {
|
| + assertEquals(event.raise(null), 2);
|
| + assertEquals(callTimes.get(), (i + 1) << 1);
|
| + }
|
| + assertTrue(event.remove(eventId1));
|
| + assertTrue(event.remove(eventId2));
|
| + assertFalse(event.remove(eventId3));
|
| + }
|
| +
|
| + private static class MultithreadingTestRunner extends Thread {
|
| + private final Event.Executor<Void> mEvent;
|
| + private final Pointer<Boolean> mError;
|
| +
|
| + public MultithreadingTestRunner(Event.Executor<Void> event,
|
| + Pointer<Boolean> error) {
|
| + Preconditions.notNull(event);
|
| + Preconditions.notNull(error);
|
| + mEvent = event;
|
| + mError = error;
|
| + }
|
| +
|
| + @Override
|
| + public void run() {
|
| + for (int i = 0; i < 100; i++) {
|
| + final Pointer<Boolean> called = new Pointer<>();
|
| + int id = mEvent.add(new Event.ParameterRunnable<Void>() {
|
| + @Override
|
| + public void run(Void nil) {
|
| + called.set(true);
|
| + }
|
| + });
|
| + if (id < 0) {
|
| + mError.set(true);
|
| + }
|
| + for (int j = 0; j < 100; j++) {
|
| + called.set(false);
|
| + if (mEvent.raise(null) <= 0) {
|
| + mError.set(true);
|
| + }
|
| + if (!called.get()) {
|
| + mError.set(true);
|
| + }
|
| + }
|
| + if (!mEvent.remove(id)) {
|
| + mError.set(true);
|
| + }
|
| + }
|
| + }
|
| + }
|
| +
|
| + @MediumTest
|
| + @Feature({"Chromoting"})
|
| + public static void testMultithreading() {
|
| + Event.Executor<Void> event = new Event.Executor<>();
|
| + final int threadCount = 10;
|
| + final Pointer<Boolean> error = new Pointer<>();
|
| + Thread[] threads = new Thread[threadCount];
|
| + for (int i = 0; i < threadCount; i++) {
|
| + threads[i] = new MultithreadingTestRunner(event, error);
|
| + threads[i].start();
|
| + }
|
| + for (int i = 0; i < threadCount; i++) {
|
| + try {
|
| + threads[i].join();
|
| + } catch (InterruptedException exception) {
|
| + assertTrue(false);
|
| + }
|
| + }
|
| + assertNull(error.get());
|
| + }
|
| +
|
| + @SmallTest
|
| + @Feature({"Chromoting"})
|
| + public static void testWeakReferred() {
|
| + Event.Executor<Void> event = new Event.Executor<>();
|
| + final Pointer<Boolean> called = new Pointer<>();
|
| + Event.ParameterRunnable<Void> runnable =
|
| + new Event.ParameterRunnable<Void>() {
|
| + @Override
|
| + public void run(Void nil) {
|
| + called.set(true);
|
| + }
|
| + };
|
| + assertTrue(event.addWeakReferred(runnable));
|
| + // When runnable is referred, it should be called.
|
| + for (int i = 0; i < 100; i++) {
|
| + assertEquals(event.raise(null), 1);
|
| + assertTrue(called.get());
|
| + called.set(false);
|
| + }
|
| + assertTrue(event.attached());
|
| +
|
| + // When runnable is not referred anymore, it would be eventually GCed and removed from event
|
| + // queue.
|
| + runnable = null;
|
| + final int round = 100;
|
| + int i = 0;
|
| + for (i = 0; i < round; i++) {
|
| + System.runFinalization();
|
| + System.gc();
|
| + event.raise(null);
|
| + if (!called.get()) {
|
| + break;
|
| + }
|
| + called.set(false);
|
| + }
|
| + assertTrue(i < round);
|
| + assertFalse(event.attached());
|
| + }
|
| +
|
| + @SmallTest
|
| + @Feature({"Chromoting"})
|
| + public static void testSelfRemovable() {
|
| + Event.Executor<Void> event = new Event.Executor<>();
|
| + final Pointer<Boolean> called = new Pointer<>();
|
| + final Pointer<Boolean> nextReturn = new Pointer<>();
|
| + nextReturn.set(true);
|
| + event.addSelfRemovable(new Event.ParameterCallback<Boolean, Void>() {
|
| + @Override
|
| + public Boolean run(Void nil) {
|
| + called.set(true);
|
| + return nextReturn.get();
|
| + }
|
| + });
|
| + assertEquals(event.raise(null), 1);
|
| + assertTrue(called.get());
|
| + assertTrue(event.attached());
|
| + called.set(false);
|
| + nextReturn.set(false);
|
| + assertEquals(event.raise(null), 1);
|
| + assertTrue(called.get());
|
| + assertFalse(event.attached());
|
| + called.set(false);
|
| + nextReturn.set(true);
|
| + assertEquals(event.raise(null), 0);
|
| + assertFalse(called.get());
|
| + assertFalse(event.attached());
|
| + }
|
| +}
|
|
|