Package org.jpox.util

Source Code of org.jpox.util.ReadWriteLockTest

/*
* The terms of the JPOX License are distributed with the software documentation.
*/

package org.jpox.util;

import java.util.Random;

import org.jpox.util.ReadWriteLock;

import junit.framework.Assert;
import junit.framework.TestCase;


/**
* Tests the functionality of a {@link ReadWriteLock}.
*
* @author <a href="mailto:mmartin5@austin.rr.com">Mike Martin</a>
*/

public class ReadWriteLockTest extends TestCase
{
    private static final int MAX_TEST_TIME = 30;
    private static final int NUM_TEST_THREADS = 10;
    private static final int NUM_OUTER_ITERATIONS = 500;
    private static final int NUM_INNER_ITERATIONS = 2500;
    private static final int YIELD_FREQUENCY = 250;

    private Throwable threadFailure;


    /**
     * Used by the JUnit framework to construct tests.  Normally, programmers
     * would never explicitly use this constructor.
     *
     * @param name   Name of the <tt>TestCase</tt>.
     */

    public ReadWriteLockTest(String name)
    {
        super(name);
    }


    public void testBasicFunction() throws Throwable
    {
        ThreadGroup group = new ThreadGroup("ReadWriteLockTest");
        Thread[] threads = new Thread[NUM_TEST_THREADS];
        ReadWriteLock rwl = new ReadWriteLock();
        Object[] objs = new Object[1];

        /*
         * Create and start all the threads running the test.
         */
        for (int i = 0; i < NUM_TEST_THREADS; ++i)
            threads[i] = new Thread(group, new TestThread(new Random(i), rwl, objs), "Test thread #" + i);

        threadFailure = null;

        for (int i = 0; i < NUM_TEST_THREADS; ++i)
            threads[i].start();

        /*
         * Wait up to MAX_TEST_TIME seconds for all threads to finish.  Any
         * longer is assumed to be a failure.
         */
        long startTime = System.currentTimeMillis();
        int runningThreads;

        do
        {
            runningThreads = group.enumerate(threads);

            for (int i = 0; i < runningThreads; ++i)
            {
                threads[i].join(250);

                if (System.currentTimeMillis() - startTime > MAX_TEST_TIME * 1000)
                {
                    for (int j = 0; j < runningThreads; ++j)
                        threads[j].interrupt();

                    fail("Test has taken more than " + MAX_TEST_TIME + " seconds; it is assumed to be deadlocked");
                }
            }
        } while (runningThreads > 0);

        /*
         * If any thread threw an exception, rethrow the last one that
         * occurred.
         */
        if (threadFailure != null)
            throw threadFailure;
    }


    private class TestThread implements Runnable
    {
        private final Random rnd;
        private final ReadWriteLock rwl;
        private final Object[] objs;

        public TestThread(Random rnd, ReadWriteLock rwl, Object[] objs)
        {
            this.rnd = rnd;
            this.rwl = rwl;
            this.objs = objs;
        }


        public void run()
        {
            try
            {
                /*
                 * Test various legal and illegal nested locking patterns
                 * repeatedly in a random order.
                 */
                final String[] lockPatterns =
                    {
                        /* Legal patterns */
                        "R", "W",
                        "RR", "WR", "WW",
                        "RRR", "WRR", "WWR", "WWW",

                        /* Illegal patterns */
                        "RW", "RRW", "RRRW", "RRRRW"
                    };

                for (int i = 0; i < NUM_OUTER_ITERATIONS && threadFailure == null; ++i)
                {
                    String pattern = lockPatterns[rnd.nextInt(lockPatterns.length)];
                    boolean isLegalPattern = pattern.indexOf("RW") == -1;

                    try
                    {
                        tryPattern(pattern);

                        if (!isLegalPattern)
                            fail("Illegal nested lock sequence " + pattern + " should have thrown an IllegalStateException");
                    }
                    catch (IllegalStateException e)
                    {
                        if (isLegalPattern)
                            throw e;
                    }
                }
            }
            catch (Throwable t)
            {
                threadFailure = t;
            }
        }


        private void tryPattern(String lockPattern) throws InterruptedException
        {
            boolean isWriteLock = lockPattern.charAt(0) == 'W';

            if (isWriteLock)
                rwl.writeLock();
            else
                rwl.readLock();

            try
            {
                Object obj;

                /*
                 * If writing, assign a new value to the array, else read the
                 * existing value.
                 */
                if (isWriteLock)
                {
                    obj = this;
                    objs[0] = obj;
                }
                else
                    obj = objs[0];

                /*
                 * Assert that the current value doesn't change over many
                 * successive accesses.  Occasionally yield to other threads.
                 */
                for (int i = 0; i < NUM_INNER_ITERATIONS; ++i)
                {
                    Assert.assertSame(obj, objs[0]);

                    if (i % YIELD_FREQUENCY == 0)
                        Thread.yield();
                }

                /*
                 * If the pattern calls for nested locks, recurse.
                 */
                if (lockPattern.length() > 1)
                    tryPattern(lockPattern.substring(1));
            }
            finally
            {
                rwl.unlock();
            }
        }
    }
}
TOP

Related Classes of org.jpox.util.ReadWriteLockTest

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.