kurbatov / firmata4j

Firmata client written in Java.
MIT License
87 stars 45 forks source link

fix(firmata-device): shutdown the executor when device stops #39

Closed kurbatov closed 4 years ago

kurbatov commented 4 years ago

Fixes #38

centic9 commented 4 years ago

Thanks for the quick update, changes look good as far as I see.

BTW, I use something like the following in an abstract base class for all tests to verify that no unexpected threads leak anywhere:

    @Before
    public void setUp() throws InterruptedException {
        waitForThreads();
    }

    @After
    public void tearDownBase() throws InterruptedException {
        waitForThreads();
    }

    protected void waitForThreads() throws InterruptedException {
        // ensure that none of our threads are left running during shutdown
        waitForThreadToFinishSubstring("Scheduler");
        waitForThreadToFinishSubstring("qtp");
        waitForThreadToFinishSubstring("firmata");
        waitForThreadToFinishSubstring("EventThread");
    }

    private void waitForThreadToFinishSubstring(String contains) throws InterruptedException {
        waitForThreadToFinishSubstring(contains, 10_000);
        assertNoThreadLeft("Thread which contains '" + contains + "' was still running after 10 seconds", contains);
    }

    public static void assertNoThreadLeft(final String error, final String startsWith) {
        int count = Thread.currentThread().getThreadGroup().activeCount();

        Thread[] threads = new Thread[count];
        Thread.currentThread().getThreadGroup().enumerate(threads);

        for (Thread t : threads) {
            if (t != null && t.getName().startsWith(startsWith)) {
                // first take a thread-dump to report the state before we stop threads
                final String dump = new ThreadDump(true, true).toString();

                // try to stop the thread to make other tests succeed again afterwards
                AbstractPipedModule.stopThread(t.getName());

                log.severe("ThreadDump: " + dump);

                // report the problem:
                fail(error + ": " + t);
            }
        }
    }

    public static void waitForThreadToFinishSubstring(final String name, final long timeout) throws InterruptedException {
        int count = Thread.currentThread().getThreadGroup().activeCount();

        Thread[] threads = new Thread[count];
        Thread.currentThread().getThreadGroup().enumerate(threads);

        for (Thread t : threads) {
            if (t != null && t.getName().contains(name)) {
                t.join(timeout);
            }
        }
    }