Package org.cometd.oort

Source Code of org.cometd.oort.OortObjectTest

/*
* Copyright (c) 2008-2014 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.cometd.oort;

import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.concurrent.CountDownLatch;
import java.util.concurrent.TimeUnit;

import org.cometd.bayeux.server.BayeuxServer;
import org.cometd.bayeux.server.ServerChannel;
import org.cometd.bayeux.server.ServerMessage;
import org.cometd.bayeux.server.ServerSession;
import org.cometd.client.BayeuxClient;
import org.eclipse.jetty.server.Server;
import org.junit.Assert;
import org.junit.Test;

public class OortObjectTest extends AbstractOortObjectTest
{
    public OortObjectTest(String serverTransport)
    {
        super(serverTransport);
    }

    @Test
    public void testShareObject() throws Exception
    {
        String name = "test";
        OortObject.Factory<Map<String, Object>> factory = OortObjectFactories.forMap();
        OortObject<Map<String, Object>> oortObject1 = new OortObject<Map<String, Object>>(oort1, name, factory);
        OortObject<Map<String, Object>> oortObject2 = new OortObject<Map<String, Object>>(oort2, name, factory);
        startOortObjects(oortObject1, oortObject2);

        final String key1 = "key1";
        final String value1 = "value1";
        final CountDownLatch objectLatch1 = new CountDownLatch(1);
        oortObject1.addListener(new OortObject.Listener.Adapter<Map<String, Object>>()
        {
            @Override
            public void onUpdated(OortObject.Info<Map<String, Object>> oldInfo, OortObject.Info<Map<String, Object>> newInfo)
            {
                Assert.assertTrue(newInfo.isLocal());
                Assert.assertNotNull(oldInfo);
                Assert.assertTrue(oldInfo.getObject().isEmpty());
                Assert.assertNotSame(oldInfo, newInfo);
                Assert.assertEquals(value1, newInfo.getObject().get(key1));
                objectLatch1.countDown();
            }
        });

        // The other OortObject listens to receive the object
        final CountDownLatch objectLatch2 = new CountDownLatch(1);
        oortObject2.addListener(new OortObject.Listener.Adapter<Map<String, Object>>()
        {
            public void onUpdated(OortObject.Info< Map <String, Object>> oldInfo, OortObject.Info<Map<String, Object>> newInfo)
            {
                Assert.assertFalse(newInfo.isLocal());
                Assert.assertNotNull(oldInfo);
                Assert.assertTrue(oldInfo.getObject().isEmpty());
                Assert.assertNotSame(oldInfo, newInfo);
                Assert.assertEquals(value1, newInfo.getObject().get(key1));
                objectLatch2.countDown();
            }
        });

        // Change the object and share the change
        Map<String, Object> object1 = factory.newObject(null);
        object1.put(key1, value1);
        oortObject1.setAndShare(object1);

        Assert.assertTrue(objectLatch1.await(5, TimeUnit.SECONDS));
        Assert.assertTrue(objectLatch2.await(5, TimeUnit.SECONDS));

        Assert.assertEquals(value1, oortObject1.getInfo(oort1.getURL()).getObject().get(key1));
        Assert.assertTrue(oortObject1.getInfo(oort2.getURL()).getObject().isEmpty());

        Assert.assertTrue(oortObject2.getInfo(oort2.getURL()).getObject().isEmpty());
        Assert.assertEquals(object1, oortObject2.getInfo(oort1.getURL()).getObject());

        Map<String, Object> objectAtOort2 = oortObject2.merge(OortObjectMergers.<String, Object>mapUnion());
        Assert.assertEquals(object1, objectAtOort2);
    }

    @Test
    public void testLocalObjectIsPushedWhenNodeJoins() throws Exception
    {
        String name = "test";
        OortObject.Factory<Map<String, Object>> factory = OortObjectFactories.forMap();
        OortObject<Map<String, Object>> oortObject1 = new OortObject<Map<String, Object>>(oort1, name, factory);
        OortObject<Map<String, Object>> oortObject2 = new OortObject<Map<String, Object>>(oort2, name, factory);
        startOortObjects(oortObject1, oortObject2);

        Map<String, Object> object1 = factory.newObject(null);
        String key1 = "key1";
        String value1 = "value1";
        object1.put(key1, value1);
        oortObject1.setAndShare(object1);

        Map<String, Object> object2 = factory.newObject(null);
        String key2 = "key2";
        String value2 = "value2";
        object2.put(key2, value2);
        oortObject2.setAndShare(object2);

        // Wait for shared objects to synchronize
        Thread.sleep(1000);

        // Connect node3
        Server server3 = startServer(0);
        Oort oort3 = startOort(server3);
        OortComet oortComet31 = oort3.observeComet(oort1.getURL());
        Assert.assertTrue(oortComet31.waitFor(5000, BayeuxClient.State.CONNECTED));
        OortComet oortComet32 = oort3.observeComet(oort2.getURL());
        Assert.assertTrue(oortComet32.waitFor(5000, BayeuxClient.State.CONNECTED));

        OortObject<Map<String, Object>> oortObject3 = new OortObject<Map<String, Object>>(oort3, name, factory);
        OortObjectInitialListener<Map<String, Object>> initialListener = new OortObjectInitialListener<Map<String, Object>>(2);
        oortObject3.addListener(initialListener);
        CometSubscriptionListener subscriptionListener = new CometSubscriptionListener(oortObject1.getChannelName(), 2);
        oort1.getBayeuxServer().addListener(subscriptionListener);
        oort2.getBayeuxServer().addListener(subscriptionListener);
        oortObject3.start();
        Assert.assertTrue(subscriptionListener.await(5, TimeUnit.SECONDS));
        Assert.assertTrue(initialListener.await(5, TimeUnit.SECONDS));

        Map<String, Object> object3 = factory.newObject(null);
        String key3 = "key3";
        String value3 = "value3";
        object3.put(key3, value3);
        final CountDownLatch objectsLatch = new CountDownLatch(3);
        OortObject.Listener.Adapter<Map<String, Object>> objectListener = new OortObject.Listener.Adapter<Map<String, Object>>()
        {
            @Override
            public void onUpdated(OortObject.Info<Map<String, Object>> oldInfo, OortObject.Info<Map<String, Object>> newInfo)
            {
                objectsLatch.countDown();
            }
        };
        oortObject1.addListener(objectListener);
        oortObject2.addListener(objectListener);
        oortObject3.addListener(objectListener);
        oortObject3.setAndShare(object3);
        Assert.assertTrue(objectsLatch.await(5, TimeUnit.SECONDS));

        OortObject.Merger<Map<String, Object>, Map<String, Object>> merger = OortObjectMergers.mapUnion();
        Map<String, Object> objectAtOort1 = oortObject1.merge(merger);
        Assert.assertEquals(3, objectAtOort1.size());
        Map<String, Object> objectAtOort2 = oortObject2.merge(merger);
        Assert.assertEquals(3, objectAtOort2.size());
        Map<String, Object> objectAtOort3 = oortObject3.merge(merger);
        Assert.assertEquals(3, objectAtOort3.size());

        oortObject3.stop();
    }

    @Test
    public void testLocalObjectIsRemovedWhenNodeLeaves() throws Exception
    {
        String name = "test";
        OortObject.Factory<Map<String, Object>> factory = OortObjectFactories.forMap();
        OortObject<Map<String, Object>> oortObject1 = new OortObject<Map<String, Object>>(oort1, name, factory);
        OortObject<Map<String, Object>> oortObject2 = new OortObject<Map<String, Object>>(oort2, name, factory);
        startOortObjects(oortObject1, oortObject2);

        Map<String, Object> object1 = factory.newObject(null);
        String key1 = "key1";
        String value1 = "value1";
        object1.put(key1, value1);
        oortObject1.setAndShare(object1);

        Map<String, Object> object2 = factory.newObject(null);
        String key2 = "key2";
        String value2 = "value2";
        object2.put(key2, value2);
        oortObject2.setAndShare(object2);

        // Wait for shared objects to synchronize
        Thread.sleep(1000);

        CountDownLatch latch = new CountDownLatch(1);
        oort2.addCometListener(new CometLeftListener(latch));
        stopOort(oort1);
        Assert.assertTrue(latch.await(5, TimeUnit.SECONDS));

        Map<String, Object> objectAtOort2 = oortObject2.merge(OortObjectMergers.<String, Object>mapUnion());
        Assert.assertEquals(object2, objectAtOort2);
    }

    @Test
    public void testIterationOverInfos() throws Exception
    {
        String name = "test";
        OortObject.Factory<Map<String, Object>> factory = OortObjectFactories.forMap();
        OortObject<Map<String, Object>> oortObject1 = new OortObject<Map<String, Object>>(oort1, name, factory);
        OortObject<Map<String, Object>> oortObject2 = new OortObject<Map<String, Object>>(oort2, name, factory);
        startOortObjects(oortObject1, oortObject2);

        Map<String, Object> object1 = factory.newObject(null);
        String key1 = "key1";
        String value1 = "value1";
        object1.put(key1, value1);
        oortObject1.setAndShare(object1);

        Map<String, Object> object2 = factory.newObject(null);
        String key2 = "key2";
        String value2 = "value2";
        object2.put(key2, value2);
        oortObject2.setAndShare(object2);

        // Wait for shared objects to synchronize
        Thread.sleep(1000);

        List<OortObject.Info<Map<String, Object>>> infos = new ArrayList<OortObject.Info<Map<String, Object>>>();
        for (OortObject.Info<Map<String, Object>> info : oortObject1)
            infos.add(info);
        Assert.assertEquals(2, infos.size());
        for (OortObject.Info<Map<String, Object>> info : infos)
        {
            Map<String, Object> data = info.getObject();
            if (data.containsKey(key1))
                Assert.assertEquals(oort1.getURL(), info.getOortURL());
            else if (data.containsKey(key2))
                Assert.assertEquals(oort2.getURL(), info.getOortURL());
        }
    }

    @Test
    public void testNonCompositeObject() throws Exception
    {
        String name = "test";
        OortObject.Factory<Long> factory = OortObjectFactories.forLong(0);
        OortObject<Long> oortObject1 = new OortObject<Long>(oort1, name, factory);
        OortObject<Long> oortObject2 = new OortObject<Long>(oort2, name, factory);
        startOortObjects(oortObject1, oortObject2);

        final CountDownLatch latch1 = new CountDownLatch(2);
        OortObject.Listener<Long> objectListener1 = new OortObject.Listener.Adapter<Long>()
        {
            @Override
            public void onUpdated(OortObject.Info<Long> oldInfo, OortObject.Info<Long> newInfo)
            {
                latch1.countDown();
            }
        };
        oortObject1.addListener(objectListener1);
        oortObject2.addListener(objectListener1);
        long value1 = 2;
        oortObject1.setAndShare(value1);
        Assert.assertTrue(latch1.await(5, TimeUnit.SECONDS));

        final CountDownLatch latch2 = new CountDownLatch(2);
        OortObject.Listener<Long> objectListener2 = new OortObject.Listener.Adapter<Long>()
        {
            @Override
            public void onUpdated(OortObject.Info<Long> oldInfo, OortObject.Info<Long> newInfo)
            {
                latch2.countDown();
            }
        };
        oortObject1.addListener(objectListener2);
        oortObject2.addListener(objectListener2);
        long value2 = 3;
        oortObject2.setAndShare(value2);
        Assert.assertTrue(latch2.await(5, TimeUnit.SECONDS));

        long sum = oortObject1.merge(OortObjectMergers.longSum());
        Assert.assertEquals(value1 + value2, sum);
    }

    @Test
    public void testStaleUpdateIsDiscarded() throws Exception
    {
        String name = "test";
        OortObject.Factory<Long> factory = OortObjectFactories.forLong(0);
        final OortObject<Long> oortObject1 = new OortObject<Long>(oort1, name, factory);
        OortObject<Long> oortObject2 = new OortObject<Long>(oort2, name, factory);
        startOortObjects(oortObject1, oortObject2);

        final CountDownLatch latch1 = new CountDownLatch(2);
        OortObject.Listener<Long> objectListener1 = new OortObject.Listener.Adapter<Long>()
        {
            @Override
            public void onUpdated(OortObject.Info<Long> oldInfo, OortObject.Info<Long> newInfo)
            {
                latch1.countDown();
            }
        };
        oortObject1.addListener(objectListener1);
        oortObject2.addListener(objectListener1);
        long value1 = 1;
        oortObject1.setAndShare(value1);
        Assert.assertTrue(latch1.await(5, TimeUnit.SECONDS));

        // Update "concurrently": the concurrence will be simulated
        final long delay = 1000;
        final long value2 = 2;
        final long value3 = 3;
        oort2.getBayeuxServer().addExtension(new BayeuxServer.Extension.Adapter()
        {
            @Override
            public boolean rcv(ServerSession from, final ServerMessage.Mutable message)
            {
                if (oortObject1.getChannelName().equals(message.getChannel()))
                {
                    Map<String, Object> data = message.getDataAsMap();
                    if (data != null)
                    {
                        if (value2 == ((Number)data.get(OortObject.Info.OBJECT_FIELD)).longValue())
                        {
                            new Thread()
                            {
                                public void run()
                                {
                                    try
                                    {
                                        sleep(delay);
                                        ServerChannel channel = oort2.getBayeuxServer().getChannel(message.getChannel());
                                        channel.publish(oort2.getOortSession(), message);
                                    }
                                    catch (InterruptedException ignored)
                                    {
                                    }
                                }
                            }.start();
                            return false;
                        }
                    }
                }
                return true;
            }
        });
        Assert.assertEquals(value1, (long)oortObject1.setAndShare(value2));
        Assert.assertEquals(value2, (long)oortObject1.setAndShare(value3));

        Thread.sleep(2 * delay);

        long valueAtNode2 = oortObject2.getInfo(oort1.getURL()).getObject();
        Assert.assertEquals(value3, valueAtNode2);
    }
}
TOP

Related Classes of org.cometd.oort.OortObjectTest

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.