mirror of
https://gitflic.ru/project/openide/openide.git
synced 2026-09-27 10:03:11 +07:00
add test for multi-thread execution
This commit is contained in:
@@ -0,0 +1,170 @@
|
||||
/*
|
||||
* Copyright 2000-2017 JetBrains s.r.o.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package com.intellij.util.concurrency;
|
||||
|
||||
import com.intellij.openapi.Disposable;
|
||||
import com.intellij.openapi.util.Disposer;
|
||||
import org.junit.Assert;
|
||||
import org.junit.Test;
|
||||
|
||||
import java.util.concurrent.CountDownLatch;
|
||||
import java.util.concurrent.atomic.AtomicBoolean;
|
||||
import java.util.concurrent.atomic.AtomicReference;
|
||||
import java.util.function.BooleanSupplier;
|
||||
import java.util.function.Consumer;
|
||||
|
||||
/**
|
||||
* @author Sergey.Malenkov
|
||||
*/
|
||||
public class InvokerTest {
|
||||
@Test
|
||||
public void testValidOnEDT() {
|
||||
Disposable parent = InvokerTest::dispose;
|
||||
testValidThread(parent, new Invoker.EDT(parent));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testValidBgPool() {
|
||||
Disposable parent = InvokerTest::dispose;
|
||||
testValidThread(parent, new Invoker.BackgroundPool(parent));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testValidBgThread() {
|
||||
Disposable parent = InvokerTest::dispose;
|
||||
testValidThread(parent, new Invoker.BackgroundThread(parent));
|
||||
}
|
||||
|
||||
private static void testValidThread(Disposable parent, Invoker invoker) {
|
||||
CountDownLatch latch = new CountDownLatch(1);
|
||||
test(parent, invoker, latch, error -> countDown(latch, 0, error, "task on invalid thread", invoker::isValidThread));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testInvokeLaterOnEDT() {
|
||||
Disposable parent = InvokerTest::dispose;
|
||||
testInvokeLater(parent, new Invoker.EDT(parent));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testInvokeLaterOnBgPool() {
|
||||
Disposable parent = InvokerTest::dispose;
|
||||
testInvokeLater(parent, new Invoker.BackgroundPool(parent));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testInvokeLaterOnBgThread() {
|
||||
Disposable parent = InvokerTest::dispose;
|
||||
testInvokeLater(parent, new Invoker.BackgroundThread(parent));
|
||||
}
|
||||
|
||||
private static void testInvokeLater(Disposable parent, Invoker invoker) {
|
||||
CountDownLatch latch = new CountDownLatch(1);
|
||||
test(parent, invoker, latch, error -> {
|
||||
AtomicBoolean current = new AtomicBoolean(false);
|
||||
invoker.invokeLater(() -> countDown(latch, 100, error, "task is not done before subtask", current::get));
|
||||
current.set(true);
|
||||
});
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testInvokeLaterIfNeededOnEDT() {
|
||||
Disposable parent = InvokerTest::dispose;
|
||||
testInvokeLaterIfNeeded(parent, new Invoker.EDT(parent));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testInvokeLaterIfNeededOnBgPool() {
|
||||
Disposable parent = InvokerTest::dispose;
|
||||
testInvokeLaterIfNeeded(parent, new Invoker.BackgroundPool(parent));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testInvokeLaterIfNeededOnBgThread() {
|
||||
Disposable parent = InvokerTest::dispose;
|
||||
testInvokeLaterIfNeeded(parent, new Invoker.BackgroundThread(parent));
|
||||
}
|
||||
|
||||
private static void testInvokeLaterIfNeeded(Disposable parent, Invoker invoker) {
|
||||
CountDownLatch latch = new CountDownLatch(1);
|
||||
test(parent, invoker, latch, error -> {
|
||||
AtomicBoolean current = new AtomicBoolean(true);
|
||||
invoker.invokeLaterIfNeeded(() -> countDown(latch, 100, error, "task is done before subtask", current::get));
|
||||
current.set(false);
|
||||
});
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testQueueOnEDT() {
|
||||
Disposable parent = InvokerTest::dispose;
|
||||
testQueue(parent, new Invoker.EDT(parent), true);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testQueueOnBgPool() {
|
||||
Disposable parent = InvokerTest::dispose;
|
||||
testQueue(parent, new Invoker.BackgroundPool(parent), false);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testQueueOnBgThread() {
|
||||
Disposable parent = InvokerTest::dispose;
|
||||
testQueue(parent, new Invoker.BackgroundThread(parent), true);
|
||||
}
|
||||
|
||||
private static void testQueue(Disposable parent, Invoker invoker, boolean ordered) {
|
||||
CountDownLatch latch = new CountDownLatch(2);
|
||||
test(parent, invoker, latch, error -> {
|
||||
long first = ordered ? 2 : 1;
|
||||
invoker.invokeLater(() -> countDown(latch, 100, error, "unexpected task order", () -> first == latch.getCount()));
|
||||
long second = ordered ? 1 : 2;
|
||||
invoker.invokeLater(() -> countDown(latch, 0, error, "unexpected task order", () -> second == latch.getCount()));
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
private static void test(Disposable parent, Invoker invoker, CountDownLatch latch, Consumer<AtomicReference<String>> consumer) {
|
||||
AtomicReference<String> error = new AtomicReference<>();
|
||||
invoker.invokeLater(() -> consumer.accept(error));
|
||||
String message;
|
||||
try {
|
||||
latch.await();
|
||||
message = error.get();
|
||||
}
|
||||
catch (InterruptedException ignore) {
|
||||
message = "interrupted exception";
|
||||
}
|
||||
finally {
|
||||
Disposer.dispose(parent);
|
||||
}
|
||||
if (message != null) Assert.fail(message + " @ " + invoker);
|
||||
}
|
||||
|
||||
private static void countDown(CountDownLatch latch, long ms, AtomicReference<String> error, String message, BooleanSupplier success) {
|
||||
try {
|
||||
if (ms > 0) Thread.sleep(ms);
|
||||
}
|
||||
catch (InterruptedException ignore) {
|
||||
}
|
||||
finally {
|
||||
if (!success.getAsBoolean()) error.set(message);
|
||||
latch.countDown();
|
||||
}
|
||||
}
|
||||
|
||||
private static void dispose() {
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user