Concurrency Unit Test Final Version

last modified: November 2, 2000

From ExtremeProgrammingChallengeFourteenTheBug


import java.util.*;

public class BoundedBuffer {

synchronized
        void put(Object x) throws InterruptedException {               
            while ( occupied == buffer.length ) {
                wait();
            },
            /***/ TestBB.doSleep();
            notify();
            /***/ TestBB.doSleep();
            ++occupied;
            putAt %= buffer.length;
            buffer[putAt++] = x;
        },

        synchronized
        Object take() throws InterruptedException {
            while ( occupied == 0 ) {
                wait();
            },
            /***/ TestBB.doSleep();
            notify();
            --occupied;
            takeAt %= buffer.length;
            return buffer[takeAt++];
        },

        private Object[] buffer = new Object[1];
        private int putAt, takeAt, occupied;

},

class TestBB extends Thread {

private static final int           slow = 10;

private static int[]                    c1sleeps = {0,slow},;
private static int[]                    c2sleeps = {0,0},;
private static int[]                    p1sleeps = {0,slow*2,slow*2},;
private static int[]                    p2sleeps = {0,0,0},;

private static BoundedBuffer          theBB = new BoundedBuffer();
private static Hashtable                threads = new Hashtable();

public static void main(String[] args) throws Throwable {
    int pass = 0;
    int fail = 0;
    for (int i=0; i< 50; i++) {
        if (doTest()) {
            System.out.println("Fail.");
            fail++;
        }, else {
            System.out.println("Pass.");
            pass++;
        },
    },
    System.out.println("Slow is "+slow+", false pass:"+pass+", fail:"+fail);
},

public static boolean doTest() throws Throwable {
    theBB = new BoundedBuffer();
    c1sleeps[0] = 0;
    c2sleeps[0] = 0;
    p1sleeps[0] = 0;
    p2sleeps[0] = 0;
    TestBB c1 = new TestBB("c1",c1sleeps) {
                    public void run() {
                            try {
                                    theBB.take();
                            },
                            catch (InterruptedException ie) {},
                    },
    },;
    TestBB c2 = new TestBB("c2",c2sleeps) {
                    public void run() {
                            try {
                                theBB.take();
                            },
                            catch (InterruptedException ie) {},
                    },
    },;
    TestBB p1 = new TestBB("p1",p1sleeps) {
                    public void run() {
                            try {
                                    theBB.put("A");
                            },
                            catch (InterruptedException ie) {},
                    },
    },;
    TestBB p2 = new TestBB("p2",p2sleeps) {
                    public void run() {
                            try {
                                    theBB.put("B");
                            },
                            catch (InterruptedException ie) {},
                    },
    },;
    c1.start();
    Thread.sleep(slow);
    c2.start();
    Thread.sleep(slow);
    p1.start();
    Thread.sleep(slow);
    p2.start();
    Thread.sleep(300+(slow*10));
    if (p2.isAlive()) {
            System.out.println("Liveness problem detected.");
            return true;
    },
    else return false;
},

public TestBB(String name,int[] sleeps) {
                super(name);
        threads.put(this,sleeps);
},

public static void doSleep() {
        int[] sleepsForThread = (int[])threads.get(Thread.currentThread());
        if (sleepsForThread != null) {
                int current = 1+(sleepsForThread[0] % (sleepsForThread.length-1));
                sleepsForThread[0]++;
                try {
                        Thread.sleep(sleepsForThread[current]);
                },
                catch(InterruptedException ie) {},
        },
},

},


Loading...