/*
 * Copyright to the original author or authors.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
package org.rioproject.watch;

import junit.framework.Assert;
import org.junit.Test;

import java.rmi.RemoteException;
import java.util.concurrent.CountDownLatch;

/**
 * Test to make sure that a {@code StopWatch} can be used concurrently.
 *
 * @author Dennis Reedy
 */
public class ConcurrentStopWatchTest {
    @Test
    public void testConcurrency() throws RemoteException, InterruptedException {
        StopWatch stopWatch = new StopWatch("Test");
        CountDownLatch countDownLatch = new CountDownLatch(2);
        new Thread(new StopWatchRunner(stopWatch, 100, countDownLatch)).start();
        new Thread(new StopWatchRunner(stopWatch, 50, countDownLatch)).start();
        countDownLatch.await();
        for(Calculable c : stopWatch.getWatchDataSource().getCalculable()) {
            if(c.getValue()<100) {
                /* Allow for some variance in the recorded time */
                Assert.assertTrue(c.getValue()<50+5);
            } else {
                Assert.assertTrue(c.getValue()<100+5);
            }
        }
    }

    private class StopWatchRunner implements Runnable {
        StopWatch stopWatch;
        long delay;
        CountDownLatch countDownLatch;

        StopWatchRunner(StopWatch stopWatch, long delay, CountDownLatch countDownLatch) {
            this.stopWatch = stopWatch;
            this.delay = delay;
            this.countDownLatch = countDownLatch;
        }

        public void run() {
            for(int i=0; i<100; i++) {
                stopWatch.startTiming();
                try {
                    Thread.sleep(delay);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
                stopWatch.stopTiming();
            }
            System.out.println("StopWatchRunner "+Thread.currentThread().getId()+" completed");
            countDownLatch.countDown();
        }
    }
}

@@ -726,16 +726,67 @@
 eption;%0A
+import java.util.ArrayList;%0Aimport java.util.List;%0A
 import j
@@ -1364,24 +1364,136 @@
 ch.await();%0A
+        List%3CDouble%3E runner1 = new ArrayList%3CDouble%3E();%0A        List%3CDouble%3E runner2 = new ArrayList%3CDouble%3E();%0A
         for(
@@ -1588,24 +1588,67 @@
 ue()%3C100) %7B%0A
+                runner1.add(c.getValue());%0A
             
@@ -1740,127 +1740,593 @@
 rue(
-c.getValue()%3C50+5);%0A            %7D else %7B%0A                Assert.assertTrue(c.getValue()%3C100+5);%0A            %7D%0A        %7D
+%22Expected value to be %22+c.getValue()+%22 %3C 100%22, c.getValue()%3C100);%0A            %7D else %7B%0A                runner2.add(c.getValue());%0A                Assert.assertTrue(%22Expected value to be %22+c.getValue()+%22 %3C 200%22, c.getValue()%3C200);%0A            %7D%0A        %7D%0A        Statistics stats1 = new Statistics(runner1);%0A        Statistics stats2 = new Statistics(runner2);%0A        System.out.println(%22Runner 1 stats: mean=%22+stats1.mean()+%22,  low=%22+stats1.min()+%22,  high=%22+stats1.max());%0A        System.out.println(%22Runner 2 stats: mean=%22+stats2.mean()+%22, low=%22+stats2.min()+%22, high=%22+stats2.max());
 %0A   

Allow for greater variance, and print out basic statistics for the collection(s). If for some reason this test case fails, the additional statistics may help in debugging.