Package tripleplay.syncdb

Source Code of tripleplay.syncdb.SyncDBTest$TestServer

//
// Triple Play - utilities for use in PlayN-based games
// Copyright (c) 2011-2014, Three Rings Design, Inc. - All rights reserved.
// http://github.com/threerings/tripleplay/blob/master/LICENSE

package tripleplay.syncdb;

import java.util.HashMap;
import java.util.Map;

import react.RMap;
import react.RSet;
import react.Value;

import playn.core.Platform;
import playn.core.StubPlatform;
import playn.core.util.Callback;

import com.google.common.collect.ImmutableMap;
import com.google.common.collect.Sets;

import org.junit.*;
import static org.junit.Assert.*;

public class SyncDBTest
{
    public static class TestDB extends SyncDB {
        public final Value<Boolean> trueBool = value(
            "trueBool", false, Codec.BOOLEAN, Resolver.TRUE);
        public final Value<Boolean> falseBool = value(
            "falseBool", true, Codec.BOOLEAN, Resolver.FALSE);
        public final Value<Integer> maxInt = value("maxInt", 0, Codec.INT, Resolver.INTMAX);
        public final Value<Long> maxLong = value("maxLong", 0L, Codec.LONG, Resolver.INTMAX);
        public final Value<String> serverString = value(
            "serverString", null, Codec.STRING, Resolver.SERVER);
        public final RSet<String> unionSet = set("unionSet", Codec.STRING, SetResolver.UNION);
        public final RSet<String> interSet = set(
            "interSet", Codec.STRING, SetResolver.INTERSECTION);
        public final RSet<String> serverSet = set("serverSet", Codec.STRING, SetResolver.SERVER);
        public final RMap<String,Integer> maxMap = map(
            "maxMap", Codec.STRING, Codec.INT, Resolver.INTMAX);

        public TestDB () {
            this(testPlatform());
        }

        public TestDB (Platform platform) {
            super(platform);
        }

        @Override public TestDB clone () {
            return new TestDB(_platform);
        }

        public void assertEquals (TestDB other) {
            Assert.assertEquals(trueBool, other.trueBool);
            Assert.assertEquals(falseBool, other.falseBool);
            Assert.assertEquals(maxInt, other.maxInt);
            Assert.assertEquals(maxLong, other.maxLong);
            Assert.assertEquals(serverString, other.serverString);
            Assert.assertEquals(unionSet, other.unionSet);
            Assert.assertEquals(interSet, other.interSet);
            Assert.assertEquals(serverSet, other.serverSet);
            Assert.assertEquals(maxMap, other.maxMap);
        }
    }

    @Test public void testSimpleSync () {
        Protocol.Session session = testSession();
        TestDB one = new TestDB(), two = new TestDB();

        one.trueBool.update(true);
        one.maxInt.update(42);
        one.maxLong.update(400L);
        one.serverString.update("foo");
        one.unionSet.add("one");
        one.unionSet.add("two");
        one.unionSet.add("three");
        one.interSet.add("four");
        one.serverSet.add("five");

        session.sync(one);
        session.sync(two);
        one.assertEquals(two);

        // make sure we have no lingering modifications
        assertEquals(0, one.getMods().size());
        assertEquals(0, two.getMods().size());
    }

    @Test public void testModsWhileSyncing () {
        final TestDB one = new TestDB(), two = new TestDB();
        Protocol.Session session = new Protocol.Session(new TestServer()) {
            @Override protected void onSyncSuccess (SyncDB db, Map<String,Integer> mods,
                                                    Protocol.Response rsp) {
                // simulate a concurrent modification by modifying values in one just before we
                // note that our sync has completed
                if (rsp.cleanSync) {
                    one.maxInt.update(50); // modify a property that was part of the sync
                    one.maxLong.update(400L); // and modify a property that was not part of the sync
                }
                super.onSyncSuccess(db, mods, rsp);
            }
            @Override protected void onSyncFailure (SyncDB db, Throwable cause) {
                System.err.println("Sync failure " + cause);
            }
        };

        one.trueBool.update(true);
        one.maxInt.update(42);
        one.serverString.update("foo");

        session.sync(one);
        session.sync(two);
        // one.assertEquals(two); // they won't be equal as we modified 'one' concurrently

        // make sure the concurrent modifications in DB one did not get wiped out
        assertEquals(Sets.newHashSet("maxInt", "maxLong"), one.getMods().keySet());
        assertEquals(0, two.getMods().size());
    }

    @Test public void testMaxing () {
        Protocol.Session session = testSession();
        TestDB one = new TestDB(), two = new TestDB();

        // start with some synced changes
        one.maxInt.update(42);
        one.maxLong.update(60L);
        session.sync(one);
        session.sync(two);

        // now make conflicting changes to both client one and two and resync
        one.maxInt.update(40);
        one.maxLong.update(65L);
        two.maxInt.update(45);
        two.maxLong.update(30L);
        session.sync(one); // this will go through no questions asked
        session.sync(two); // this will sync one's changes into two and overwrite some of one's
                           // changes with the merged data from two
        session.sync(one); // this will sync two's merged data back to one

        one.assertEquals(two);
        assertEquals(45, one.maxInt.get().intValue());
        assertEquals(65L, one.maxLong.get().longValue());

        // make sure we have no lingering modifications
        assertEquals(0, one.getMods().size());
        assertEquals(0, two.getMods().size());
    }

    @Test public void testUseServer () {
        Protocol.Session session = testSession();
        TestDB one = new TestDB(), two = new TestDB();

        // start with some synced changes
        one.serverString.update("foo");
        session.sync(one);
        session.sync(two);

        // now make conflicting changes to both client one and two and resync
        one.serverString.update("bar");
        two.serverString.update("baz");
        session.sync(one); // this will go through no questions asked
        session.sync(two); // this will sync one's changes into two

        one.assertEquals(two);
        assertEquals("bar", two.serverString.get());

        // make sure we have no lingering modifications
        assertEquals(0, one.getMods().size());
        assertEquals(0, two.getMods().size());
    }

    @Test public void testSets () {
        Protocol.Session session = testSession();
        TestDB one = new TestDB(), two = new TestDB();

        // start with some synced changes
        one.unionSet.add("one");
        one.unionSet.add("two");
        one.interSet.add("1");
        one.interSet.add("2");
        one.serverSet.add("a");
        one.serverSet.add("b");
        session.sync(one);
        session.sync(two);

        // now make conflicting changes to both client one and two and resync
        one.unionSet.add("three");
        two.unionSet.add("four");
        one.interSet.remove("1");
        two.interSet.add("3");
        one.serverSet.add("c");
        two.serverSet.remove("b");
        session.sync(one); // this will go through no questions asked
        session.sync(two); // this will sync one's changes into two and overwrite some of one's
                           // changes with the merged data from two
        session.sync(one); // this will sync two's merged data back to one

        one.assertEquals(two);
        assertEquals(Sets.newHashSet("one", "two", "three", "four"), two.unionSet);
        assertEquals(Sets.newHashSet("2"), two.interSet);
        assertEquals(Sets.newHashSet("a", "b", "c"), two.serverSet);

        // make sure we reread our data from storage properly
        one.assertEquals(one.clone());

        // make sure we have no lingering modifications
        assertEquals(0, one.getMods().size());
        assertEquals(0, two.getMods().size());
    }

    @Test public void testMap () {
        Protocol.Session session = testSession();
        TestDB one = new TestDB(), two = new TestDB();

        // start with some synced changes
        one.maxMap.put("one", 1);
        one.maxMap.put("two", 2);
        session.sync(one);
        session.sync(two);

        // now make conflicting changes to both client one and two and resync
        one.maxMap.put("three", 3);
        one.maxMap.put("four", 4);
        one.maxMap.remove("one");
        two.maxMap.put("four", 44);
        session.sync(one); // this will go through no questions asked
        session.sync(two); // this will sync one's changes into two and overwrite some of one's
                           // changes with the merged data from two
        session.sync(one); // this will sync two's merged data back to one

        one.assertEquals(two);
        assertEquals(ImmutableMap.of("two", 2, "three", 3, "four", 44), two.maxMap);

        // make sure we reread our data from storage properly
        one.assertEquals(one.clone());

        // make sure we have no lingering modifications
        assertEquals(0, one.getMods().size());
        assertEquals(0, two.getMods().size());
    }

    protected void makeTestChanges2 (TestDB db) {
        db.trueBool.update(false);
        db.maxInt.update(60);
        db.maxLong.update(1000L);
        db.serverString.update("bar");
        db.unionSet.remove("one");
        db.unionSet.add("five");
        db.interSet.add("one");
        db.serverSet.add("six");
    }

    protected static class Datum {
        public final int version;
        public final String value;
        public Datum (int version, String value) {
            this.version = version;
            this.value = value;
        }
    }

    protected static class TestServer implements Protocol.Server {
        @Override public void sendSync (int version, Map<String,String> delta,
                                        Callback<Protocol.Response> onResponse) {
            if (version > _version) {
                throw new IllegalStateException("So impossible! " + version + " > " + _version);
            } else if (version < _version) {
                onResponse.onSuccess(needSync(version));
            } else if (delta.size() == 0) {
                onResponse.onSuccess(new Protocol.Response(_version));
            } else {
                _version += 1;
                for (Map.Entry<String,String> entry : delta.entrySet()) {
                    _data.put(entry.getKey(), new Datum(_version, entry.getValue()));
                }
                onResponse.onSuccess(new Protocol.Response(_version));
            }
        }

        protected Protocol.Response needSync (int clientVers) {
            Map<String,String> delta = new HashMap<String,String>();
            for (Map.Entry<String,Datum> entry : _data.entrySet()) {
                Datum d = entry.getValue();
                if (d.version > clientVers) delta.put(entry.getKey(), d.value);
            }
            return new Protocol.Response(_version, delta);
        }

        protected int _version;
        protected Map<String,Datum> _data = new HashMap<String,Datum>();
    }

    protected static Protocol.Session testSession () {
        return new Protocol.Session(new TestServer()) {
            @Override protected void onSyncFailure (SyncDB db, Throwable cause) {
                System.err.println("Sync failure " + cause);
            }
        };
    }

    protected static Platform testPlatform () {
        return new StubPlatform();
    }
}
TOP

Related Classes of tripleplay.syncdb.SyncDBTest$TestServer

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.