Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to write unit tests that tests concurrency invariants

There are other questions about this issue, but I'm trying to figure how to approach unit testing something like this:

 public class Semaphore extends Lock {
        private AtomicInteger semaphore = new AtomicInteger(0);
        public synchronized boolean available() {
                return semaphore.intValue() == 0;
        }
        public synchronized void acquire() {
            semaphore.incrementAndGet();

        }
        public synchronized void release() {
            semaphore.decrementAndGet();
        }
    }

This is my homespun locking mechanism (just for learning purposes). How would I test the thread safety of this? I know that there are no guarantees when it comes to unit testing concurrent code, but how would I even go about writing a unit test that ATTEMPTS to test the obvious invariants inherent in this locking mechanism?

like image 526
LuxuryMode Avatar asked Jan 31 '12 22:01

LuxuryMode


People also ask

How do you test concurrency issues?

Process for concurrency testing :Create high and low-level scenarios for concurrent testing. Keep ready different platforms for testing. Creating the environment for testing. Now, two or more testers can start the test by performing the same task at the same times.

What is AAA pattern in unit testing?

Arrange/Act/Assert (AAA) is a pattern for organizing unit tests. It breaks tests down into three clear and distinct steps: Arrange: Perform the setup and initialization required for the test. Act: Take action(s) required for the test. Assert: Verify the outcome(s) of the test.

Do JUnit tests run in parallel?

Once parallel test execution property is enabled, the JUnit Jupiter engine will execute tests in parallel according to the provided configuration with declared synchronization mechanisms.

When writing unit tests it is usually the practice to follow the AAA principle arrange act and assert?

It breaks each test down into three parts – Arrange, Act, and Assert – where each part is a step leading to the next. The arrange step sets up the test's input values. The act step prompts the primary function being tested. And finally, the assert step verifies that the output of the function is what was expected.


1 Answers

I guess I'll answer my own question since I did some research. There's a great framework called MultithreadedTC. It allows you to set up tests like so:

public class SafeSemaphoreTest extends MultithreadedTestCase {

    private SafeSemaphore semaphore;
    AtomicInteger ai = new AtomicInteger(0);

    @Override
    public void initialize() {
        semaphore = new SafeSemaphore();
    }


    public void thread1() throws InterruptedException {

        assertTick(0);

        semaphore.acquire();
        waitForTick(2);
        assertTick(2);

        semaphore.acquire();
        assertEquals(semaphore.getValue(), 2);
        assertEquals(semaphore.getValue()==3, false);
        semaphore.release();
        semaphore.release();

    }

    public void thread2() throws InterruptedException {
        waitForTick(1);
        assertTick(1);
        assertEquals(semaphore.available(), false);
        waitForTick(3);
        assertTick(3);
        assertEquals(semaphore.available(), true);

    }

}

where the waitForTick(int) calls make the current Thread block until the tick is reached. There was even some development to make this a bit more modern for better JUnit integration: http://janvanbesien.blogspot.com/2009/06/modernizing-multithreadedtc-junit-4.html

like image 185
LuxuryMode Avatar answered Sep 25 '22 14:09

LuxuryMode