Files
JIMRI/java/test/jmri/util/ThreadingUtilTest.java
2026-06-17 14:00:51 +02:00

218 lines
6.4 KiB
Java

package jmri.util;
import org.junit.jupiter.api.*;
import static org.junit.jupiter.api.Assertions.assertEquals;
import static org.junit.jupiter.api.Assertions.assertFalse;
import static org.junit.jupiter.api.Assertions.assertNotNull;
import static org.junit.jupiter.api.Assertions.assertNull;
import static org.junit.jupiter.api.Assertions.assertTrue;
/**
* Tests for ThreadingUtil class
*
* @author Bob Jacobsen Copyright 2015, 2020
*/
public class ThreadingUtilTest {
private volatile boolean done;
@Test
public void testToLayout() {
done = false;
ThreadingUtil.runOnLayout( ()-> {
done = true;
} );
assertTrue(done);
}
@Test
public void testThreadGroup() {
ThreadGroup tg = ThreadingUtil.getJmriThreadGroup();
assertNotNull(tg);
assertEquals( "JMRI", tg.getName());
assertEquals(tg, ThreadingUtil.getJmriThreadGroup());
}
@Test
public void testThreadStartEnd() throws InterruptedException {
ThreadingUtil.getJmriThreadGroup(); // just used to create the group
Thread t = ThreadingUtil.newThread(() -> {}); // create and run quick
t.join();
}
private Object testRef = null;
@Test
public void testToGuiWarn() {
// if (!java.lang.management.ManagementFactory
// .getThreadMXBean().isObjectMonitorUsageSupported())
// log.info("This JVM doesn't support object monitor tracking");
// if (!java.lang.management.ManagementFactory
// .getThreadMXBean().isSynchronizerUsageSupported())
// log.info("This JVM doesn't support synchronized lock tracking");
final Object lockedThing = new Object();
done = false;
synchronized (lockedThing) {
// first, run something that also wants the lock
new Thread(() -> {
synchronized (lockedThing) {
testRef = lockedThing;
}
}).start();
ThreadingUtil.runOnGUI( ()-> {
done = true;
assertNull(testRef); // due to lock
} );
JUnitUtil.waitFor( ()->{ return done; }, "GUI thread complete");
assertNull(testRef); // due to lock
}
JUnitUtil.waitFor( ()->{ return testRef != null; }, "Locked thread complete");
}
@Test
public void testThreadingNesting() {
done = false;
Thread t = new Thread(
new Runnable() {
@Override
public void run() {
// now on another thread
// switch back to Layout thread
ThreadingUtil.runOnLayout( ()-> {
// on layout thread, confirm
assertTrue( ThreadingUtil.isLayoutThread(), "on Layout thread");
// mark done so we know
done = true;
} );
}
}
);
t.setName("Thread Nesting Test Thread");
t.start();
// wait for separate thread to do it's work before confirming test
JUnitUtil.waitFor( ()->{ return done; }, "Separate thread complete");
}
@Test
public void testThreadingNestingToSwing() {
done = false;
javax.swing.SwingUtilities.invokeLater(
new Runnable() {
@Override
public void run() {
// now on Swing thread
// switch back to Layout thread
ThreadingUtil.runOnLayout( ()-> {
// on layout thread, confirm
assertTrue( ThreadingUtil.isLayoutThread(), "on Layout thread");
// mark done so we known
done = true;
} );
}
}
);
// wait for separate thread to do it's work before confirming test
JUnitUtil.waitFor( ()->{ return done; }, "Separate thread complete");
}
@Test
public void testThreadingDelayGUI() {
done = false;
ThreadingUtil.runOnGUIDelayed( ()-> {
done = true;
}, 200 );
// ensure not done now
assertFalse(done);
// wait for separate thread to do it's work before confirming test
JUnitUtil.waitFor( ()->{ return done; }, "Delayed operation complete");
}
@Test
public void testThreadingRunOnGUIwithReturn() {
done = false;
Integer value = ThreadingUtil.runOnGUIwithReturn( ()-> {
done = true;
return 21;
});
assertTrue(done);
assertEquals(Integer.valueOf(21), value);
}
@Test
public void testThreadingDelayLayout() {
done = false;
ThreadingUtil.runOnLayoutDelayed( ()-> {
done = true;
}, 200 );
// ensure not done now
assertFalse(done);
// wait for separate thread to do it's work before confirming test
JUnitUtil.waitFor( ()->{ return done; }, "Delayed oepration complete");
}
@Test
public void testThreadingTests() {
ThreadingUtil.runOnLayout( ()-> {
ThreadingUtil.requireLayoutThread(log);
} );
ThreadingUtil.runOnGUI( ()-> {
ThreadingUtil.requireGuiThread(log);
} );
assertTrue(JUnitAppender.verifyNoBacklog());
ThreadingUtil.requireGuiThread(log);
JUnitAppender.assertWarnMessage("Call not on GUI thread");
ThreadingUtil.requireLayoutThread(log);
JUnitAppender.assertWarnMessage("Call not on Layout thread");
ThreadingUtil.requireGuiThread(log);
ThreadingUtil.requireLayoutThread(log);
assertTrue(JUnitAppender.verifyNoBacklog());
}
/**
* Show how to query state of _current_ thread
*/
@Test
public void testSelfState() {
// To run the tests, this thread has to be running, not waiting
assertTrue(ThreadingUtil.canThreadRun(Thread.currentThread()));
assertFalse(ThreadingUtil.isThreadWaiting(Thread.currentThread()));
}
@BeforeEach
public void setUp() {
jmri.util.JUnitUtil.setUp();
}
@AfterEach
public void tearDown() {
jmri.util.JUnitUtil.tearDown();
}
private static final org.slf4j.Logger log = org.slf4j.LoggerFactory.getLogger(ThreadingUtilTest.class);
}