Package org.rioproject.impl.watch

Source Code of org.rioproject.impl.watch.WatchDataSourceImplTest$RemoteWDR

/*
* Copyright 2008 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.impl.watch;

import junit.framework.Assert;
import net.jini.config.Configuration;
import net.jini.config.EmptyConfiguration;
import net.jini.export.Exporter;
import net.jini.jeri.BasicILFactory;
import net.jini.jeri.BasicJeriExporter;
import net.jini.jeri.tcp.TcpServerEndpoint;
import org.junit.Test;
import org.rioproject.impl.config.DynamicConfiguration;

import java.rmi.*;
import java.rmi.server.ExportException;
import java.util.*;

import org.rioproject.impl.watch.WatchDataReplicatorProxy;
import org.rioproject.impl.watch.WatchDataSourceImpl;
import org.rioproject.watch.*;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;


/**
* The class tests the <code>WatchDataSourceImpl</code> class against its
* javadoc specification. The class tests the public constructors, methods,
* and fields declared in <code>WatchDataSourceImpl</code>.
*/
public class WatchDataSourceImplTest {
    static final Logger logger = LoggerFactory.getLogger("org.rioproject.watch");
    /**
     * The set of possible boolean values.
     */
    private static final Boolean[] booleanAxis =
            new Boolean[] {Boolean.FALSE, Boolean.TRUE};


    /**
     * Tests the <code>DEFAULT_COLLECTION_SIZE</code> field.
     */
    @Test public void testFields() {
        Assert.assertTrue(WatchDataSourceImpl.DEFAULT_COLLECTION_SIZE > 0);
        Assert.assertTrue(WatchDataSourceImpl.MAX_COLLECTION_SIZE > 0);
        Assert.assertTrue(WatchDataSourceImpl.MAX_COLLECTION_SIZE
                          >= WatchDataSourceImpl.DEFAULT_COLLECTION_SIZE);
    }

    /**
     * Tests the
     * <code>WatchDataSourceImpl(String, Configuration)</code>
     * constructor.
     *
     * @throws RemoteException if the test fails
     */
    @Test public void testConstructor() throws RemoteException {
        final int DCS = WatchDataSourceImpl.DEFAULT_COLLECTION_SIZE;
        final int MCS = WatchDataSourceImpl.MAX_COLLECTION_SIZE;
        final String[] ids = new String[] {"watch", ""};
        final WatchDataReplicator[] wdrs = new WatchDataReplicator[] {
                new LoggingWatchDataReplicator(), null};
        final Integer[] collectionSizes = ArrayUtils.asObjects(new int[] {
                -1, 0, 1, 10, 1000, 9999, 10000, 10001, 20000, 666});
        Object[][] combinations = ArrayUtils.combinations(new Object[][] {
                ids, wdrs, collectionSizes});
        for (Object[] combination : combinations) {
            String id = (String) combination[0];
            WatchDataReplicator wdr = (WatchDataReplicator) combination[1];
            int collectionSize = (Integer) combination[2];
            DynamicConfiguration config = new DynamicConfiguration();
            if (collectionSize != 666) {
                config.setEntry("org.rioproject.watch",
                                "collectionSize",
                                collectionSize);
            }
            WatchDataSourceImpl impl = new WatchDataSourceImpl(id, config);
            boolean added = impl.addWatchDataReplicator(wdr);
            if(wdr!=null)
                Assert.assertTrue("Expected to add "+wdr.getClass().getName(),
                                  added);
            else
                Assert.assertFalse("Expected to not add a null WatchDataReplicator",
                                   added);

            Assert.assertSame(id, impl.getID());
            if (wdr == null) {
                Assert.assertNotNull(impl.getWatchDataReplicators());
                Assert.assertTrue(impl.getWatchDataReplicators().length==0);
            } else {
                Assert.assertSame(wdr, impl.getWatchDataReplicators()[0]);
            }
            if (collectionSize == 666 || collectionSize < 1
                || collectionSize > MCS) {
                Assert.assertEquals(DCS, impl.getMaxSize());
            } else {
                Assert.assertEquals(collectionSize, impl.getMaxSize());
            }

            Assert.assertNull(impl.getProxy());
            assertAddCalculableWorks(impl,
                                     Math.min(Math.max(collectionSize, 0), 10),
                                     true);

            impl.close();
        }

        try {
            new WatchDataSourceImpl(null, new DynamicConfiguration());
            Assert.fail("IllegalArgumentException expected but not thrown");
        } catch (IllegalArgumentException e) {
        }
        try {
            new WatchDataSourceImpl("watch", null);
            Assert.fail("IllegalArgumentException expected but not thrown");
        } catch (IllegalArgumentException e) {
        }
        try {
            new WatchDataSourceImpl(null, null);
            Assert.fail("IllegalArgumentException expected but not thrown");
        } catch (IllegalArgumentException e) {
        }
    }

    /**
     * Tests the <code>export()</code> method.
     *
     ** @throws Exception if the test fails
     */
    @Test public void testExport() throws Exception {
        final int N = 3;
        Integer[] counts = new Integer[N];
        for (int i = 0; i < N; i++) {
            counts[i] = i;
        }
        Object[][] combinations = ArrayUtils.combinations(new Object[][] {
                counts, counts, booleanAxis});
        int i = 0;
        while (i < combinations.length) {
            int exportCount = (Integer) combinations[i][0];
            int unexportCount = (Integer) combinations[i][1];
            boolean force = (Boolean) combinations[i][2];

            LoggingWatchDataSourceImpl impl = new LoggingWatchDataSourceImpl(
                "watch", null, EmptyConfiguration.INSTANCE);

            List<WatchDataSource> proxies = new ArrayList<WatchDataSource>();
            for (int j = 0; j < exportCount; j++) {
                proxies.add(impl.export());
            }
            for (int j = 0; j < unexportCount; j++) {
                impl.unexport(force);
            }
            if (exportCount > 0 && unexportCount == 0 ) {
                Assert.assertNotNull(impl.getProxy());
            } else {
                Assert.assertNull(impl.getProxy());
            }

            WatchDataSource proxy = impl.export();

            Assert.assertNotNull(proxy);
            assertValidProxy(proxy, impl);
            Assert.assertSame(proxy, impl.getProxy());
            if (proxies.size() > 0) {
                assertAllSame(proxies);
                if (unexportCount == 0) {
                    Assert.assertSame(proxies.get(0), proxy);
                } else {
                    Assert.assertNotSame(proxies.get(0), proxy);
                }
            }
            assertAddCalculableWorks(impl, 10, true);

            impl.close();
            i++;
        }
    }

    /**
     * Tests the <code>unexport()</code> method.
     *
     * @throws Exception if the test fails
     */
    @Test public void testUnexport() throws Exception {
        final int N = 3;
        Integer[] counts = new Integer[N];
        for (int i = 0; i < N; i++) {
            counts[i] = i;
        }
        Object[][] combinations = ArrayUtils.combinations(new Object[][] {
                counts, counts, booleanAxis});
        for (Object[] combination : combinations) {
            int exportCount = (Integer) combination[0];
            int unexportCount = (Integer) combination[1];
            boolean force = (Boolean) combination[2];

            LoggingWatchDataSourceImpl impl = new LoggingWatchDataSourceImpl(
                "watch", null, EmptyConfiguration.INSTANCE);

            List<WatchDataSource> proxies = new ArrayList<WatchDataSource>();
            for (int j = 0; j < exportCount; j++) {
                proxies.add(impl.export());
            }
            for (int j = 0; j < unexportCount; j++) {
                impl.unexport(force);
            }
            if (exportCount > 0 && unexportCount == 0) {
                Assert.assertNotNull(impl.getProxy());
            } else {
                Assert.assertNull(impl.getProxy());
            }

            impl.unexport(force);

            Assert.assertNull(impl.getProxy());
            if (proxies.size() > 0) {
                assertAllSame(proxies);
                assertInvalidProxy(proxies.get(0), impl);
            }
            assertAddCalculableWorks(impl, 10, true);

            impl.close();
        }
    }

    /**
     * Tests the <code>getProxy()</code> method.
     *
     * @throws Exception if the test fails
     */
    @Test public void testGetProxy() throws Exception {
        final int N = 5;
        Integer[] counts = new Integer[N];
        for (int i = 0; i < N; i++) {
            counts[i] = i;
        }
        Object[][] combinations = ArrayUtils.combinations(new Object[][] {
                counts, counts, booleanAxis});
        for (Object[] combination : combinations) {
            int exportCount = (Integer) combination[0];
            int unexportCount = (Integer) combination[1];
            boolean force = (Boolean) combination[2];

            LoggingWatchDataSourceImpl impl = new LoggingWatchDataSourceImpl(
                "watch", null, EmptyConfiguration.INSTANCE);

            for (int j = 0; j < exportCount; j++) {
                impl.export();
            }
            for (int j = 0; j < unexportCount; j++) {
                impl.unexport(force);
            }

            if (exportCount > 0 && unexportCount == 0) {
                Assert.assertNotNull(impl.getProxy());
                assertValidProxy(impl.getProxy(), impl);
            } else {
                Assert.assertNull(impl.getProxy());
            }

            impl.close();
        }
    }

    /**
     * Tests the <code>getID()</code> method.
     *
     * @throws Exception if the test fails
     */
    @Test public void testGetID() throws Exception {
        WatchDataSourceImpl impl = new WatchDataSourceImpl();
        impl.setID("watch");
        Assert.assertEquals("watch", impl.getID());

        impl.setID("aaa");
        Assert.assertEquals("aaa", impl.getID());

        impl.close();
    }

    /**
     * Tests the <code>setID(String)</code> method.
     *
     * @throws Exception if the test fails
     */
    @Test public void testSetID() throws Exception {
        WatchDataSourceImpl impl = new WatchDataSourceImpl();
        impl.setID("aaa");
        Assert.assertEquals("aaa", impl.getID());

        impl.setID("");
        Assert.assertEquals("", impl.getID());

        try {
            impl.setID("bbb");
            impl.setID(null);
            Assert.fail("IllegalArgumentException expected but not thrown");
        } catch (IllegalArgumentException e) {
        }
        Assert.assertEquals("bbb", impl.getID());

        impl.close();
    }

    /**
     * Tests the <code>getOffset()</code> method.
     * @noinspection UNUSED_SYMBOL

    private void testGetOffset() throws Exception {
        WatchDataSourceImpl impl = new WatchDataSourceImpl(
                "watch", null, EmptyConfiguration.INSTANCE);

        final int DCS = WatchDataSourceImpl.DEFAULT_COLLECTION_SIZE;
        for (int i = 0; i < DCS; i++) {
            impl.addCalculable(new Calculable());
        }
        DataSourceMonitor mon = new DataSourceMonitor(impl);
        mon.waitFor(DCS);

        for (int i = 0; i < 10; i++) {
            impl.addCalculable(new Calculable());
            mon.waitFor(DCS + i + 1);
        }

        impl.close();
    }
    */
    /**
     * Tests the <code>getMaxSize()</code> method.
     *
     * @throws Exception if the test fails
     */
    @Test public void testGetSize() throws Exception {
        final int DCS = WatchDataSourceImpl.DEFAULT_COLLECTION_SIZE;

        {   // Default initial size
            WatchDataSourceImpl impl = new WatchDataSourceImpl();
            impl.setID("watch");
            impl.setConfiguration(EmptyConfiguration.INSTANCE);

            // Non-modified
            Assert.assertEquals(DCS, impl.getMaxSize());

            // Modified
            impl.setMaxSize(DCS + 10);
            Assert.assertEquals(DCS + 10, impl.getMaxSize());

            impl.close();
        }

        {   // Non-default initial size
            DynamicConfiguration config = new DynamicConfiguration();
            config.setEntry("org.rioproject.watch", "collectionSize",
                            DCS + 15);
            WatchDataSourceImpl impl = new WatchDataSourceImpl();
            impl.setID("watch");
            impl.setConfiguration(config);
            impl.initialize();

            // Non-modified
            Assert.assertEquals(DCS + 15, impl.getMaxSize());

            // Modified
            impl.setMaxSize(DCS + 20);
            Assert.assertEquals(DCS + 20, impl.getMaxSize());

            impl.close();
        }
    }

    /**
     * Tests the <code>setMaxSize(int)</code> method.
     *
     * @throws Exception if the test fails
     */
    @Test public void testSetSize() throws Exception {
        final int DCS = WatchDataSourceImpl.DEFAULT_COLLECTION_SIZE;
        final int MCS = WatchDataSourceImpl.MAX_COLLECTION_SIZE;
        final int[] sizes = new int[] {-100, -2, -1, 0, 1, 2, DCS,
                MCS - 1, MCS, MCS + 1, MCS + 5};
        for (int size : sizes) {
            WatchDataSourceImpl impl = new WatchDataSourceImpl();
            impl.setID("watch");
            impl.setConfiguration(EmptyConfiguration.INSTANCE);
            // TODO: Change when fixed
            if (size < -1) {
                try {
                    impl.setMaxSize(size);
                    Assert.fail("IndexOutOfBoundsException expected"
                                + " but not thrown");
                } catch (IndexOutOfBoundsException e) {
                }
            } else {
                impl.setMaxSize(size);
                Assert.assertEquals(size, impl.getMaxSize());
            }
            impl.close();
        }
    }

    /**
     * Tests the <code>clear()</code> method.
     *
     * @throws Exception if the test fails
     */
    @Test public void testClear() throws Exception {
        final int DCS = WatchDataSourceImpl.DEFAULT_COLLECTION_SIZE;
        WatchDataSourceImpl impl = new WatchDataSourceImpl();
        impl.setID("watch");
        impl.setConfiguration(EmptyConfiguration.INSTANCE);

        for (int j = 0; j < DCS; j++) {
            impl.addCalculable(new Calculable());
        }
        DataSourceMonitor mon = new DataSourceMonitor(impl);
        mon.waitFor(DCS);
        int expected = Math.min(DCS, DCS);
        Assert.assertEquals(expected, impl.getCalculable().length);

        impl.clear();
        Assert.assertEquals(0, impl.getCalculable().length);

        impl.close();
    }

    /**
     * Tests the <code>getCurrentSize()</code> method.
     *
     * @throws Exception if the test fails
     */
    @Test public void testGetCurrentSize() throws Exception {
        final int DCS = WatchDataSourceImpl.DEFAULT_COLLECTION_SIZE;
        WatchDataSourceImpl impl = new WatchDataSourceImpl();
        impl.setID("watch");
        impl.setConfiguration(EmptyConfiguration.INSTANCE);

        for (int j = 0; j < DCS; j++) {
            impl.addCalculable(new Calculable());
        }
        DataSourceMonitor mon = new DataSourceMonitor(impl);
        mon.waitFor(DCS);

        int expected = Math.min(DCS, DCS);
        Assert.assertEquals(expected, impl.getCurrentSize());

        impl.close();
    }

    /**
     * Tests the <code>addCalculable(Calculable)</code> method.
     *
     * @throws Exception if the test fails
     */
    @Test public void testAddCalculable() throws Exception {
        doTestAddCalculable(LoggingWatchDataReplicator.class.getName());
        doTestAddCalculable(RemoteWDR.class.getName());
    }

    private void doTestAddCalculable(String wdrClass) throws Exception {
        final int DCS = WatchDataSourceImpl.DEFAULT_COLLECTION_SIZE;
        final int MCS = WatchDataSourceImpl.MAX_COLLECTION_SIZE;
        final Integer[] collectionSizes = ArrayUtils.asObjects(new int[] {1, DCS, MCS});
        Object[][] combinations = ArrayUtils.combinations(new Object[][] {collectionSizes, booleanAxis});
        for (Object[] combination : combinations) {
            int collectionSize = (Integer) combination[0];
            boolean nullCalculable = (Boolean) combination[1];
            final int[] counts = new int[]{0,
                                           1,
                                           collectionSize - 1,
                                           collectionSize,
                                           collectionSize + 1,
                                           collectionSize + 10};
            for (int count : counts) {
                LoggingWatchDataReplicator wdr;
                if(wdrClass.equals(RemoteWDR.class.getName()))
                    wdr = new RemoteWDR();
                else
                    wdr = new LoggingWatchDataReplicator();
                DynamicConfiguration config = new DynamicConfiguration();
                config.setEntry("org.rioproject.watch", "collectionSize", collectionSize);

                WatchDataSourceImpl impl = new WatchDataSourceImpl();
                impl.setID("watch");
                impl.setConfiguration(config);
                if(wdrClass.equals(RemoteWDR.class.getName()))
                    impl.addWatchDataReplicator(((RemoteWDR)wdr).getWatchDataReplicator());
                else
                    impl.addWatchDataReplicator(wdr);
                impl.initialize();

                /*System.out.println(
                    "WDS max size=" + impl.getMaxSize() + ", " +
                    "configured to be=" + collectionSize + ", " +
                    "count is=" + count);*/

                List<Calculable> expected = new ArrayList<Calculable>();
                for (int k = 0; k < count; k++) {
                    Calculable c = new Calculable();
                    impl.addCalculable(c);
                    expected.add(c);
                }

                if (nullCalculable) {
                    try {
                        impl.addCalculable(null);
                        Assert.fail("IllegalArgumentException expected but not thrown");
                    } catch (IllegalArgumentException e) {
                    }
                } else {
                    Calculable c = new Calculable();
                    impl.addCalculable(c);
                    expected.add(c);
                }

                long waited = 0;
                if(wdrClass.equals(RemoteWDR.class.getName())) {
                    int maxIterations = 10000;
                    int iteration = 0;
                    long current = System.currentTimeMillis();
                    while(expected.size()!=wdr.calculables().size() && iteration<maxIterations) {
                        Utils.sleep(1);
                        iteration++;
                    }
                    waited = System.currentTimeMillis()-current;
                }
                // Replicator should have all the data
                System.out.println(
                    "WDS size=" + impl.getCurrentSize() + ", " +
                    "Replicator ("+wdrClass.substring(wdrClass.indexOf("$")+1,wdrClass.length())+") " +
                    "size=" + wdr.calculables().size() +", expected size=" + expected.size()+
                    (waited==0?"":", waited="+waited+" ms"));
                Assert.assertEquals(expected.size(), wdr.calculables().size());
                Utils.assertEqualContents(expected, wdr.calculables());               

                // Data source should contain the tail
                int off = Math.max(expected.size() - collectionSize, 0);
                expected = expected.subList(off, expected.size());
                Calculable[] res = impl.getCalculable();
                Utils.assertSameContents(expected, Arrays.asList(res));

                impl.close();

                if(wdrClass.equals(RemoteWDR.class.getName()))
                    wdr.close();
            }
        }
    }

    /**
     * Tests the <code>getWatchDataReplicator()</code> method.
     *
     * @throws Exception if the test fails
     */
    @Test public void testGetWatchDataReplicator() throws Exception {
        WatchDataReplicator wdr1 = new LoggingWatchDataReplicator();
        WatchDataSourceImpl impl = new WatchDataSourceImpl();
        impl.setID("watch");
        impl.setConfiguration(new DynamicConfiguration());
        impl.addWatchDataReplicator(wdr1);
        Assert.assertSame(wdr1, impl.getWatchDataReplicators()[0]);

        WatchDataReplicator wdr2 = new LoggingWatchDataReplicator();
        impl.addWatchDataReplicator(wdr2);
        Assert.assertEquals(2, impl.getWatchDataReplicators().length);
        Assert.assertSame(wdr2, impl.getWatchDataReplicators()[1]);

        impl.close();
    }

    /**
     * Tests the <code>addWatchDataReplicator(WatchDataReplicator)</code> method.
     *
     * @throws Exception if the test fails
     */
    @Test public void testAddWatchDataReplicator() throws Exception {
        WatchDataSourceImpl impl = new WatchDataSourceImpl();
        impl.setID("watch");
        impl.setConfiguration(new DynamicConfiguration());

        WatchDataReplicator wdr1 = new LoggingWatchDataReplicator();
        impl.addWatchDataReplicator(wdr1);
        Assert.assertSame(wdr1, impl.getWatchDataReplicators()[0]);

        WatchDataReplicator wdr2 = new LoggingWatchDataReplicator();
        impl.addWatchDataReplicator(wdr2);
        Assert.assertSame(wdr2, impl.getWatchDataReplicators()[1]);

        impl.addWatchDataReplicator(null);
        Assert.assertNotNull(impl.getWatchDataReplicators());
        Assert.assertTrue(impl.getWatchDataReplicators().length==2);

        impl.close();
    }

    /**
     * Tests the <code>getCalculable()</code> method.
     *
     * @throws Exception if the test fails
     */
    @Test public void testGetCalculable1() throws Exception {
        final int DCS = WatchDataSourceImpl.DEFAULT_COLLECTION_SIZE;
        WatchDataSourceImpl impl = new WatchDataSourceImpl();
        impl.setID("watch");
        impl.setConfiguration(EmptyConfiguration.INSTANCE);
        List<Calculable> expected = new ArrayList<Calculable>();
        for (int j = 0; j < DCS; j++) {
            Calculable c = new Calculable();
            impl.addCalculable(c);
            expected.add(c);
        }
        DataSourceMonitor mon = new DataSourceMonitor(impl);
        mon.waitFor(DCS);

        int off = Math.max(expected.size() - DCS, 0);
        expected = expected.subList(off, expected.size());
        Calculable[] res = impl.getCalculable();
        Utils.assertSameContents(expected, Arrays.asList(res));

        impl.close();
    }

    /**
     * Tests the <code>getLastCalculable()<code> method.
     *
     * @throws Exception if the test fails
     */
    @Test public void testGetLastCalculable1() throws Exception {
        final int DCS = WatchDataSourceImpl.DEFAULT_COLLECTION_SIZE;
        WatchDataSourceImpl impl = new WatchDataSourceImpl();
        impl.setID("watch");
        impl.setConfiguration(EmptyConfiguration.INSTANCE);
        Calculable expected = null;
        for (int j = 0; j < DCS; j++) {
            Calculable c = new Calculable();
            impl.addCalculable(c);
            expected = c;
        }
        DataSourceMonitor mon = new DataSourceMonitor(impl);
        mon.waitFor(DCS);

        Assert.assertSame(expected, impl.getLastCalculable());

        impl.close();
    }

    /**
     * Tests the <code>getThresholdValues()<code> method.
     *
     * @throws Exception if the test fails
     */
    @Test public void testGetThresholdValues() throws Exception {
        WatchDataSourceImpl impl = new WatchDataSourceImpl();
        impl.setID("watch");
        impl.setConfiguration(EmptyConfiguration.INSTANCE);
        ThresholdValues tv = impl.getThresholdValues();
        Assert.assertNotNull(tv);

        tv = new ThresholdValues();
        impl.setThresholdValues(tv);
        Assert.assertSame(tv, impl.getThresholdValues());

        impl.close();
    }

    /**
     * Tests the <code>getShresholdValues<code> method.
     *
     * @throws Exception if the test fails
     */
    @Test public void testSetThresholdValues() throws Exception {
        WatchDataSourceImpl impl = new WatchDataSourceImpl();
        impl.setID("watch");
        impl.setConfiguration(EmptyConfiguration.INSTANCE);

        ThresholdValues tv = new ThresholdValues();
        impl.setThresholdValues(tv);
        Assert.assertSame(tv, impl.getThresholdValues());

        // TODO: Change when fixed
        impl.setThresholdValues(null);
        Assert.assertSame(tv, impl.getThresholdValues());

        impl.close();
    }

    /**
     * Tests the <code>close()<code> method.
     *
     * @throws Exception if the test fails
     */
    @Test public void testClose() throws Exception {
        final int N = 3;
        Integer[] counts = new Integer[N];
        for (int i = 0; i < N; i++) {
            counts[i] = i;
        }
        Object[][] combinations = ArrayUtils.combinations(new Object[][] {
                counts, counts, counts});
        for (Object[] combination : combinations) {
            int exportCount = (Integer) combination[0];
            int unexportCount = (Integer) combination[1];
            int closeCount = (Integer) combination[2];

            LoggingWatchDataReplicator watchDataReplicator = new LoggingWatchDataReplicator();
            LoggingWatchDataSourceImpl impl = new LoggingWatchDataSourceImpl(
                "watch", watchDataReplicator, EmptyConfiguration.INSTANCE);
            // TODO: Without this sleep the writer thread often
            // TODO: starts after close() is called, therefore
            // TODO: close() does not really stop the writer
            // TODO: thread
            Utils.sleep(200);

            WatchDataSource proxy = null;
            for (int j = 0; j < exportCount; j++) {
                proxy = impl.export();
            }
            for (int j = 0; j < unexportCount; j++) {
                impl.unexport(true);
            }
            for (int j = 0; j < closeCount; j++) {
                impl.close();
            }

            impl.close();

            // The previous proxy (if any) should be unexported
            if (proxy != null) {
                assertInvalidProxy(proxy, impl);
            }
            // The data source must have no proxy
            Assert.assertNull(impl.getProxy());
            // Adding should not work
            assertAddCalculableWorks(impl, 10, false);
            // close() should close and clear the WatchDataReplicators
            Assert.assertEquals(0, impl.getWatchDataReplicators().length);
            checkLog(watchDataReplicator.log(), "close()");
        }
    }

    /**
     * Tests the <code>getView()</code> method.
     *
     * @throws Exception if the test fails
     */
    @Test public void testGetView() throws Exception {
        WatchDataSourceImpl impl = new WatchDataSourceImpl();
        impl.setID("watch");
        impl.setConfiguration(EmptyConfiguration.INSTANCE);
        Assert.assertEquals(null, impl.getView());

        impl.setView("abcd");
        Assert.assertEquals("abcd", impl.getView());

        impl.close();
    }

    /**
     * Tests the <code>setView(String)</code> method.
     *
     * @throws Exception if the test fails
     */
    @Test public void testSetView() throws Exception {
        WatchDataSourceImpl impl = new WatchDataSourceImpl();
        impl.setID("watch");
        impl.setConfiguration(EmptyConfiguration.INSTANCE);

        impl.setView("abcd");
        Assert.assertEquals("abcd", impl.getView());

        impl.setView("");
        Assert.assertEquals("", impl.getView());

        impl.setView(null);
        Assert.assertEquals(null, impl.getView());

        impl.close();
    }

    /**
     * Tests the <code>getProxyVerifier()</code> method.
     *
     * @throws Exception if the test fails
     */
    @Test
    public void testGetProxyVerifier() throws Exception {
        final int N = 3;
        Integer[] counts = new Integer[N];
        for (int i = 0; i < N; i++) {
            counts[i] = i;
        }
        Object[][] combinations = ArrayUtils.combinations(new Object[][] {
                counts, counts});
        for (Object[] combination : combinations) {
            int exportCount = (Integer) combination[0];
            int unexportCount = (Integer) combination[1];

            WatchDataSourceImpl impl = new WatchDataSourceImpl();
            impl.setID("watch");
            impl.setConfiguration(EmptyConfiguration.INSTANCE);

            for (int j = 0; j < exportCount; j++) {
                impl.export();
            }
            for (int j = 0; j < unexportCount; j++) {
                impl.unexport(true);
            }

            if (exportCount == 0 || unexportCount > 0) {
                // TODO: Is this correct? IllegalStateException is better
                try {
                    impl.getProxyVerifier();
                    Assert.fail("IllegalArgumentException expected"
                                + " but not thrown");
                } catch (IllegalArgumentException e) {
                }
            } else {
                Assert.assertNotNull(impl.getProxyVerifier());
            }

            impl.close();
        }
    }

    /**
     * The class extends <code>WatchDataSourceImpl</code> and logs most
     * <code>WatchDataSource</code> method calls into a string buffer.
     */
    private class LoggingWatchDataSourceImpl extends WatchDataSourceImpl {

        private StringBuffer log = new StringBuffer();

        public LoggingWatchDataSourceImpl(String id,
                                          WatchDataReplicator wdr,
                                          Configuration config) {
            super();
            setID(id);
            setConfiguration(config);
            addWatchDataReplicator(wdr);
        }

        public StringBuffer log() {
            return log;
        }

        public String getID() {
            log.append("getID()");
            return super.getID();
        }

        public void setMaxSize(int size) {
            log.append("setMaxSize(").append(size).append(")");
            super.setMaxSize(size);
        }

        public int getMaxSize() {
            log.append("getMaxSize()");
            return super.getMaxSize();
        }

        public void clear() {
            log.append("clear()");
            super.clear();
        }

        public int getCurrentSize() {
            log.append("getCurrentSize()");
            return super.getCurrentSize();
        }

        public Calculable[] getCalculable() {
            log.append("getCalculable()");
            return super.getCalculable();
        }

        public Calculable getLastCalculable() {
            log.append("getLastCalculable()");
            return super.getLastCalculable();
        }

        public ThresholdValues getThresholdValues() {
            log.append("getThresholdValues()");
            return super.getThresholdValues();
        }

        public void close() {
            log.append("close()");
            super.close();
        }

        public void setView(String view) {
            log.append("setView(").append(view).append(")");
            super.setView(view);
        }

        public String getView() {
            log.append("getView()");
            return super.getView();
        }
    }

    /*
     * Asserts that a given object is a actually a proxy to a given
     * implementation object.
     */
    private void assertValidProxy(WatchDataSource proxy,
                                  LoggingWatchDataSourceImpl impl)
            throws RemoteException {
        impl.log().delete(0, impl.log().length());
        proxy.clear();
        proxy.getCalculable();
        proxy.getCurrentSize();
        proxy.getID();
        proxy.getLastCalculable();
        proxy.getMaxSize();
        proxy.getThresholdValues();
        proxy.getView();
        //proxy.setMaxSize(1);
        proxy.setView("aaa");
        checkLog(impl.log, "clear()"
                           + "getCalculable()"
                           //+ "getCalculable(0,1)"
                           //+ "getCalculable(watch,0,1)"
                           + "getCurrentSize()"
                           + "getID()"
                           + "getLastCalculable()"
                           + "getMaxSize()"
                           + "getThresholdValues()"
                           + "getView()"
                           //+ "setMaxSize(1)"
                           + "setView(aaa)");
    }

    /*
     * Asserts that a given object is not a working proxy
     * (e.g. closed proxy) to a given implementation object.
     */
    private void assertInvalidProxy(WatchDataSource proxy,
                                    LoggingWatchDataSourceImpl impl)
            throws RemoteException {
        impl.log().delete(0, impl.log().length());
        try {
            proxy.getID();
            Assert.fail("Exception expected but not thrown");
        } catch (NoSuchObjectException e) {
        } catch (ConnectException e) {
        } catch (ConnectIOException e) {           
        }
        checkLog(impl.log(), "");
    }


    /**
     * The class provides an implementation of the <code>WatchDataReplicator</code>
     * interface that logs <code>close()</code> method calls into a string
     * buffer and stores samples passed to the <code>addCalculable()</code> method
     * in a list.
     */
    private class LoggingWatchDataReplicator implements WatchDataReplicator {
        private StringBuffer log = new StringBuffer();
        protected List<Calculable> calculables = new ArrayList<Calculable>();

        public LoggingWatchDataReplicator() {
        }

        public StringBuffer log() {
            return log;
        }

        public List calculables() {
            return calculables;
        }

        public void close() {
            log.append("close()");
        }

        public void addCalculable(Calculable calculable) {           
            calculables.add(calculable);
        }
    }

    private class RemoteWDR extends LoggingWatchDataReplicator implements RemoteWatchDataReplicator {
        Exporter exporter;

        public RemoteWDR() {
            super();
        }

        WatchDataReplicator getWatchDataReplicator() throws ExportException {
            exporter = new BasicJeriExporter(TcpServerEndpoint.getInstance(0),
                                             new BasicILFactory(),
                                             false,
                                             true);
            RemoteWatchDataReplicator backend = (RemoteWatchDataReplicator)exporter.export(this);
            return WatchDataReplicatorProxy.getInstance(backend, UUID.randomUUID());
        }

        public void replicate(Calculable c) {
            addCalculable(c);
        }

        public void bulkReplicate(Collection<Calculable> c)  {
            calculables.addAll(c);
        }

        @Override
        public void close() {
            exporter.unexport(true);
            super.close();
        }
    }

    /*
     * Checks that a given string buffer (used as a log) holds a given
     * string, and clears the string buffer.
     */
    private void checkLog(StringBuffer log, String s) {
        Assert.assertEquals(s, log.toString());
        log.delete(0, log.length());
    }


    /*
     * Asserts that all objects in a given collection are same.
     */
    private void assertAllSame(Collection collection) {
        if (collection.isEmpty()) {
            return;
        }
        Iterator i = collection.iterator();
        Object obj = i.next();
        while (i.hasNext()) {
            Assert.assertSame(obj, i.next());
        }
    }

    /*
     * Asserts that the <code>addCalculable</code> method really works for
     * the current state of a given data source, that is, calculables get
     * into the history. The method verifies this by calling
     * <code>addCalculable</code> the specified number of times and
     * checking the history.
     *
     * @param ds    the data source to verify
     * @param count the required number of calls to <code>addCalculable</code>
     * @param works specifies whether <code>addCalculable</code> should
     *              work or not
     */
    private void assertAddCalculableWorks(WatchDataSource ds,
                                          int count,
                                          boolean works) throws RemoteException {
        ds.clear();
        List<Calculable> expected = new ArrayList<Calculable>();
        Calculable expectedLast = null;
        for (int j = 0; j < count; j++) {
            Calculable c = new Calculable();
            ds.addCalculable(c);
            if (works) {
                expected.add(c);
                expectedLast = c;
            }
        }

        DataSourceMonitor detector = new DataSourceMonitor(ds);
        detector.waitFor(works ? count : 0);

        List calculables = Arrays.asList(ds.getCalculable());
        Utils.assertSameContents(expected, calculables);
        Assert.assertEquals(expected.size(), ds.getCurrentSize());
        Assert.assertSame(expectedLast, ds.getLastCalculable());
        ds.clear();
    }
}
TOP

Related Classes of org.rioproject.impl.watch.WatchDataSourceImplTest$RemoteWDR

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.