/**
  *  \file u/t_game_proxy_drawingproxy.cpp
  *  \brief Test for game::proxy::DrawingProxy
  */

#include "game/proxy/drawingproxy.hpp"

#include "t_game_proxy.hpp"
#include "game/game.hpp"
#include "game/map/drawingcontainer.hpp"
#include "game/map/universe.hpp"
#include "game/test/root.hpp"
#include "game/test/sessionthread.hpp"
#include "game/test/waitindicator.hpp"
#include "game/turn.hpp"

using game::test::SessionThread;
using game::test::WaitIndicator;
using game::proxy::DrawingProxy;
using game::map::Point;
using game::map::Drawing;
using game::map::DrawingContainer;

namespace {
    class StatusReceiver {
     public:
        StatusReceiver(DrawingProxy& proxy)
            : conn_update(proxy.sig_update.add(this, &StatusReceiver::onUpdate)),
              m_status()
            { }

        const DrawingProxy::Status_t& get() const
            { return m_status; }

     private:
        void onUpdate(const DrawingProxy::Status_t& st)
            { m_status = st; }

        afl::base::SignalConnection conn_update;
        DrawingProxy::Status_t m_status;
    };

    void prepare(SessionThread& h)
    {
        afl::base::Ptr<game::Game> g = new game::Game();
        h.session().setGame(g);
    }

    void addMarker(SessionThread& h, int x, int y, uint8_t color)
    {
        Drawing* d = new Drawing(game::map::Point(x, y), Drawing::MarkerDrawing);
        d->setColor(color);
        h.session().getGame()->currentTurn().universe().drawings().addNew(d);
    }

    void addLine(SessionThread& h, int x, int y, int x2, int y2, uint8_t color, util::Atom_t tag)
    {
        Drawing* d = new Drawing(game::map::Point(x, y), Drawing::LineDrawing);
        d->setColor(color);
        d->setTag(tag);
        d->setPos2(Point(x2, y2));
        h.session().getGame()->currentTurn().universe().drawings().addNew(d);
    }
}

/** Test behaviour on empty session.
    A: create empty session. Create DrawingProxy. Call some methods. Query status.
    E: no crash. Status reports empty. */
void
TestGameProxyDrawingProxy::testEmpty()
{
    SessionThread h;
    WaitIndicator ind;
    DrawingProxy testee(h.gameSender(), ind);

    // Some dummy calls
    TS_ASSERT_THROWS_NOTHING(testee.create(Point(2000, 2000), Drawing::MarkerDrawing));
    TS_ASSERT_THROWS_NOTHING(testee.setPos(Point(2000, 2020)));

    // Querying should yield nothing
    DrawingProxy::Status_t st;
    TS_ASSERT_THROWS_NOTHING(testee.getStatus(ind, st));
    TS_ASSERT(!st.isValid());
}

/** Test creating a marker.
    A: create session with turn. Create DrawingProxy. Create and populate a marker.
    E: marker created; correct status reported. Verify all stages. */
void
TestGameProxyDrawingProxy::testCreateMarker()
{
    SessionThread h;
    WaitIndicator ind;
    prepare(h);
    DrawingProxy testee(h.gameSender(), ind);
    StatusReceiver recv(testee);

    // Create and configure a marker
    testee.create(Point(2100, 2200), Drawing::MarkerDrawing);
    testee.setMarkerKind(3);
    testee.setColor(4, false);
    testee.setComment("hi");
    testee.setTag(7777, false);
    testee.setPos(Point(2200, 2300));

    // Verify that correct update is eventually received
    h.sync();
    ind.processQueue();
    TS_ASSERT(recv.get().isValid());
    TS_ASSERT_EQUALS(recv.get().get()->getType(), Drawing::MarkerDrawing);
    TS_ASSERT_EQUALS(recv.get().get()->getPos(), Point(2200, 2300));
    TS_ASSERT_EQUALS(recv.get().get()->getColor(), 4);
    TS_ASSERT_EQUALS(recv.get().get()->getMarkerKind(), 3);
    TS_ASSERT_EQUALS(recv.get().get()->getComment(), "hi");
    TS_ASSERT_EQUALS(recv.get().get()->getTag(), 7777U);

    // Explicitly query
    DrawingProxy::Status_t st;
    TS_ASSERT_THROWS_NOTHING(testee.getStatus(ind, st));
    TS_ASSERT(st.isValid());
    TS_ASSERT_EQUALS(st.get()->getType(), Drawing::MarkerDrawing);
    TS_ASSERT_EQUALS(st.get()->getPos(), Point(2200, 2300));
    TS_ASSERT_EQUALS(st.get()->getColor(), 4);
    TS_ASSERT_EQUALS(st.get()->getMarkerKind(), 3);
    TS_ASSERT_EQUALS(st.get()->getComment(), "hi");
    TS_ASSERT_EQUALS(st.get()->getTag(), 7777U);

    // Verify that marker is present
    DrawingContainer::Iterator_t it = h.session().getGame()->currentTurn().universe().drawings().begin();
    TS_ASSERT(*it);
    TS_ASSERT_EQUALS((*it)->getType(), Drawing::MarkerDrawing);
    TS_ASSERT_EQUALS((*it)->getPos(), Point(2200, 2300));
    TS_ASSERT_EQUALS((*it)->getColor(), 4);
    TS_ASSERT_EQUALS((*it)->getMarkerKind(), 3);
    TS_ASSERT_EQUALS((*it)->getComment(), "hi");
    TS_ASSERT_EQUALS((*it)->getTag(), 7777U);

    // Finish; verify that report is invalidated
    testee.finish();
    h.sync();
    ind.processQueue();
    TS_ASSERT(!recv.get().isValid());
}

/** Test creating lines.
    A: create session with turn. Create DrawingProxy. Create multiple lines.
    E: verify result. */
void
TestGameProxyDrawingProxy::testCreateLines()
{
    SessionThread h;
    WaitIndicator ind;
    prepare(h);
    DrawingProxy testee(h.gameSender(), ind);

    // Create some lines
    //   (2000,2000) -> (2000,2010), color 4
    testee.create(Point(2000, 2000), Drawing::LineDrawing);
    testee.setColor(4, false);
    testee.setPos2(Point(2000, 2010));
    //   (2000,2010) -> (2000,2020), color 4
    testee.continueLine();
    testee.setPos2(Point(2000, 2020));
    //   (2000,2020) -> (2000,2030), color 5
    testee.continueLine();
    testee.setColor(5, false);
    testee.setPos2(Point(2000, 2030));
    //   (2000,2030) -> (2000,2030), color 5 [ignored segment]
    testee.continueLine();
    //   (2000,2030) -> (2000,2040), color 5
    testee.continueLine();
    testee.setPos2(Point(2000, 2040));

    // Verify
    h.sync();
    ind.processQueue();

    DrawingContainer::Iterator_t it = h.session().getGame()->currentTurn().universe().drawings().begin();
    TS_ASSERT(*it);
    TS_ASSERT_EQUALS((**it).getPos(),   Point(2000, 2000));
    TS_ASSERT_EQUALS((**it).getPos2(),  Point(2000, 2010));
    TS_ASSERT_EQUALS((**it).getColor(), 4);

    ++it;
    TS_ASSERT(*it);
    TS_ASSERT_EQUALS((**it).getPos(),   Point(2000, 2010));
    TS_ASSERT_EQUALS((**it).getPos2(),  Point(2000, 2020));
    TS_ASSERT_EQUALS((**it).getColor(), 4);

    ++it;
    TS_ASSERT(*it);
    TS_ASSERT_EQUALS((**it).getPos(),   Point(2000, 2020));
    TS_ASSERT_EQUALS((**it).getPos2(),  Point(2000, 2030));
    TS_ASSERT_EQUALS((**it).getColor(), 5);

    ++it;
    TS_ASSERT(*it);
    TS_ASSERT_EQUALS((**it).getPos(),   Point(2000, 2030));
    TS_ASSERT_EQUALS((**it).getPos2(),  Point(2000, 2040));
    TS_ASSERT_EQUALS((**it).getColor(), 5);

    ++it;
    TS_ASSERT(!*it);
}

/** Test creating rectangels.
    A: create session with turn. Create DrawingProxy. Create a rectangle.
    E: verify result. */
void
TestGameProxyDrawingProxy::testCreateRectangle()
{
    SessionThread h;
    WaitIndicator ind;
    prepare(h);
    DrawingProxy testee(h.gameSender(), ind);

    // Create and verify initial state
    testee.create(Point(1500, 1600), Drawing::RectangleDrawing);
    DrawingProxy::Status_t st;
    TS_ASSERT_THROWS_NOTHING(testee.getStatus(ind, st));
    TS_ASSERT(st.isValid());
    TS_ASSERT_EQUALS(st.get()->getPos(), Point(1500, 1600));
    TS_ASSERT_EQUALS(st.get()->getPos2(), Point(1500, 1600));

    // Finish it
    testee.setPos2(Point(1700, 1800));
    testee.finish();

    // Verify
    h.sync();
    ind.processQueue();

    DrawingContainer::Iterator_t it = h.session().getGame()->currentTurn().universe().drawings().begin();
    TS_ASSERT(*it);
    TS_ASSERT_EQUALS((**it).getPos(),   Point(1500, 1600));
    TS_ASSERT_EQUALS((**it).getPos2(),  Point(1700, 1800));
    TS_ASSERT_EQUALS((**it).getType(),  Drawing::RectangleDrawing);
}

/** Test creating rectangels.
    A: create session with turn. Create DrawingProxy. Create a circle.
    E: verify result. */
void
TestGameProxyDrawingProxy::testCreateCircle()
{
    SessionThread h;
    WaitIndicator ind;
    prepare(h);
    DrawingProxy testee(h.gameSender(), ind);

    // Create
    testee.create(Point(1300, 1400), Drawing::CircleDrawing);
    testee.setCircleRadius(20);
    testee.changeCircleRadius(50);
    testee.finish();

    // Verify
    h.sync();
    ind.processQueue();

    DrawingContainer::Iterator_t it = h.session().getGame()->currentTurn().universe().drawings().begin();
    TS_ASSERT(*it);
    TS_ASSERT_EQUALS((**it).getPos(),          Point(1300, 1400));
    TS_ASSERT_EQUALS((**it).getCircleRadius(), 70);
    TS_ASSERT_EQUALS((**it).getType(),         Drawing::CircleDrawing);
}

/** Test selectNearestVisibleDrawing().
    A: create session with turn and some drawings. Create DrawingProxy. Call selectNearestVisibleDrawing().
    E: verify correct drawing is selected. */
void
TestGameProxyDrawingProxy::testFindNearest()
{
    SessionThread h;
    WaitIndicator ind;
    prepare(h);
    addMarker(h, 1000, 1000, 1);
    addMarker(h, 1000, 1010, 2);
    addMarker(h, 1000, 1020, 3);
    addMarker(h, 1000, 1030, 4);

    DrawingProxy testee(h.gameSender(), ind);
    StatusReceiver recv(testee);

    // Select marker, unsuccessfully
    testee.selectNearestVisibleDrawing(Point(2000, 2000), 10, afl::base::Nothing);
    h.sync();
    ind.processQueue();
    TS_ASSERT(!recv.get().isValid());

    // Select marker, successfully
    testee.selectNearestVisibleDrawing(Point(1000, 1011), 10, afl::base::Nothing);
    h.sync();
    ind.processQueue();
    TS_ASSERT(recv.get().isValid());
    TS_ASSERT_EQUALS(recv.get().get()->getColor(), 2);

    // Select again, unsuccessfully. This does not change anything.
    testee.selectNearestVisibleDrawing(Point(2000, 2000), 10, afl::base::Nothing);
    h.sync();
    ind.processQueue();
    TS_ASSERT(recv.get().isValid());
    TS_ASSERT_EQUALS(recv.get().get()->getColor(), 2);

    // Select again, successfully
    testee.selectNearestVisibleDrawing(Point(1000, 1019), 10, afl::base::Nothing);
    h.sync();
    ind.processQueue();
    TS_ASSERT(recv.get().isValid());
    TS_ASSERT_EQUALS(recv.get().get()->getColor(), 3);
}

/** Test erase().
    A: create session with turn and some drawings. Create DrawingProxy. Call selectNearestVisibleDrawing(), then erase().
    E: verify correct result. */
void
TestGameProxyDrawingProxy::testErase()
{
    SessionThread h;
    WaitIndicator ind;
    prepare(h);
    addMarker(h, 1000, 1000, 1);
    addMarker(h, 1000, 1010, 2);
    addMarker(h, 1000, 1020, 3);

    DrawingProxy testee(h.gameSender(), ind);
    StatusReceiver recv(testee);

    // Select and erase
    testee.selectNearestVisibleDrawing(Point(1000, 1011), 10, afl::base::Nothing);
    testee.erase(false);

    // Verify
    h.sync();
    ind.processQueue();
    TS_ASSERT(!recv.get().isValid());

    DrawingContainer::Iterator_t it = h.session().getGame()->currentTurn().universe().drawings().begin();
    TS_ASSERT(*it);
    TS_ASSERT_EQUALS((**it).getColor(), 1);
    ++it;
    TS_ASSERT(*it);
    TS_ASSERT_EQUALS((**it).getColor(), 3);
    ++it;
    TS_ASSERT(!*it);
}

/** Test setColor() for adjacent lines.
    A: create session with turn and some lines. Create DrawingProxy. Call selectNearestVisibleDrawing(). Call setColor(adjacent=true).
    E: verify correct result. */
void
TestGameProxyDrawingProxy::testColorAdjacent()
{
    SessionThread h;
    WaitIndicator ind;
    prepare(h);
    addLine(h, 1000, 1000, 1000, 1010, 4, 500);
    addLine(h, 1000, 1010, 1000, 1020, 6, 501);
    addLine(h, 1000, 1020, 1000, 1030, 7, 502);

    // Action
    DrawingProxy testee(h.gameSender(), ind);
    testee.selectNearestVisibleDrawing(Point(1005, 1015), 10, afl::base::Nothing);
    testee.setColor(9, true);

    // Verify
    h.sync();
    ind.processQueue();
    DrawingContainer::Iterator_t it = h.session().getGame()->currentTurn().universe().drawings().begin();
    for (int i = 0; i < 3; ++i) {
        TS_ASSERT(*it);
        TS_ASSERT_EQUALS((**it).getColor(), 9);
        ++it;
    }
    TS_ASSERT(!*it);
}

/** Test setTag() for adjacent lines.
    A: create session with turn and some lines. Create DrawingProxy. Call selectNearestVisibleDrawing(). Call setTag(adjacent=true).
    E: verify correct result. */
void
TestGameProxyDrawingProxy::testTagAdjacent()
{
    SessionThread h;
    WaitIndicator ind;
    prepare(h);
    addLine(h, 1000, 1000, 1000, 1010, 4, 500);
    addLine(h, 1000, 1010, 1000, 1020, 6, 501);
    addLine(h, 1000, 1020, 1000, 1030, 7, 502);

    // Action
    DrawingProxy testee(h.gameSender(), ind);
    testee.selectNearestVisibleDrawing(Point(1005, 1015), 10, afl::base::Nothing);
    testee.setTag(600, true);

    // Verify
    h.sync();
    ind.processQueue();
    DrawingContainer::Iterator_t it = h.session().getGame()->currentTurn().universe().drawings().begin();
    for (int i = 0; i < 3; ++i) {
        TS_ASSERT(*it);
        TS_ASSERT_EQUALS((**it).getTag(), 600U);
        ++it;
    }
    TS_ASSERT(!*it);
}

/** Test erase() for adjacent lines.
    A: create session with turn and some lines. Create DrawingProxy. Call selectNearestVisibleDrawing(). Call erase(adjacent=true).
    E: verify correct result. */
void
TestGameProxyDrawingProxy::testEraseAdjacent()
{
    SessionThread h;
    WaitIndicator ind;
    prepare(h);
    addLine(h, 1000, 1000, 1000, 1010, 4, 500);
    addLine(h, 1000, 1010, 1000, 1020, 6, 501);
    addLine(h, 1000, 1020, 1000, 1030, 7, 502);

    // Action
    DrawingProxy testee(h.gameSender(), ind);
    testee.selectNearestVisibleDrawing(Point(1005, 1015), 10, afl::base::Nothing);
    testee.erase(true);

    // Verify
    h.sync();
    ind.processQueue();
    DrawingContainer::Iterator_t it = h.session().getGame()->currentTurn().universe().drawings().begin();
    TS_ASSERT(!*it);
}

/** Test parallel usage.
    A: create a session. Create two DrawingProxy instances and observe both. Create a drawing with one, erase it with the other.
    E: verify correct status updates. */
void
TestGameProxyDrawingProxy::testParallel()
{
    SessionThread h;
    WaitIndicator ind;
    prepare(h);

    DrawingProxy p1(h.gameSender(), ind);
    DrawingProxy p2(h.gameSender(), ind);
    StatusReceiver r1(p1);
    StatusReceiver r2(p2);

    // Create a circle and verify
    p1.create(Point(1500, 1500), Drawing::CircleDrawing);
    p1.setCircleRadius(200);
    h.sync();
    ind.processQueue();

    TS_ASSERT(r1.get().isValid());
    TS_ASSERT_EQUALS(r1.get().get()->getCircleRadius(), 200);
    TS_ASSERT(!r2.get().isValid());

    // Select circle with second instance
    p2.selectNearestVisibleDrawing(Point(1700, 1500), 10, afl::base::Nothing);
    h.sync();
    ind.processQueue();

    TS_ASSERT(r1.get().isValid());
    TS_ASSERT_EQUALS(r1.get().get()->getCircleRadius(), 200);
    TS_ASSERT(r2.get().isValid());
    TS_ASSERT_EQUALS(r2.get().get()->getCircleRadius(), 200);

    // Modify tag with second instance
    p2.setTag(7777, false);
    h.sync();
    ind.processQueue();

    TS_ASSERT(r1.get().isValid());
    TS_ASSERT_EQUALS(r1.get().get()->getTag(), 7777U);
    TS_ASSERT(r2.get().isValid());
    TS_ASSERT_EQUALS(r2.get().get()->getTag(), 7777U);

    // Erase with second instance
    p2.erase(false);
    h.sync();
    ind.processQueue();

    TS_ASSERT(!r1.get().isValid());
    TS_ASSERT(!r2.get().isValid());
}

/** Test selectMarkerAt().
    A: create session with turn and some markers. Create DrawingProxy. Call selectMarkerAt().
    E: verify correct drawing is selected. */
void
TestGameProxyDrawingProxy::testSelectMarker()
{
    SessionThread h;
    WaitIndicator ind;
    prepare(h);
    addMarker(h, 1000, 1000, 1);
    addMarker(h, 1000, 1010, 2);

    DrawingProxy testee(h.gameSender(), ind);
    StatusReceiver recv(testee);

    // Select marker, unsuccessfully
    testee.selectMarkerAt(Point(2000, 2000), afl::base::Nothing);
    h.sync();
    ind.processQueue();
    TS_ASSERT(!recv.get().isValid());

    // Select marker, successfully
    testee.selectMarkerAt(Point(1000, 1000), afl::base::Nothing);
    h.sync();
    ind.processQueue();
    TS_ASSERT(recv.get().isValid());
    TS_ASSERT_EQUALS(recv.get().get()->getColor(), 1);

    // Select other marker, successfully
    testee.selectMarkerAt(Point(1000, 1010), afl::base::Nothing);
    h.sync();
    ind.processQueue();
    TS_ASSERT(recv.get().isValid());
    TS_ASSERT_EQUALS(recv.get().get()->getColor(), 2);
}

/** Test setTagName.
    A: create session with turn and a marker. Create DrawingProxy. Call setTagName() with different parameters.
    E: verify correct values set */
void
TestGameProxyDrawingProxy::testSetTagName()
{
    SessionThread h;
    WaitIndicator ind;
    prepare(h);
    addMarker(h, 1000, 1000, 1);

    // Create and set number
    DrawingProxy testee(h.gameSender(), ind);
    testee.selectMarkerAt(Point(1000, 1000), afl::base::Nothing);
    testee.setTagName("17", false);
    h.sync();
    ind.processQueue();

    // Verify
    DrawingContainer::Iterator_t it = h.session().getGame()->currentTurn().universe().drawings().begin();
    TS_ASSERT(*it);
    TS_ASSERT_EQUALS((**it).getTag(), 17U);

    // Try a string
    testee.setTagName("foo", false);
    h.sync();
    ind.processQueue();
    TS_ASSERT(*it);
    TS_ASSERT_DIFFERS((**it).getTag(), 0U);
    TS_ASSERT_EQUALS(h.session().world().atomTable().getStringFromAtom((**it).getTag()), "foo");

    // Try empty
    testee.setTagName("", false);
    h.sync();
    ind.processQueue();
    TS_ASSERT(*it);
    TS_ASSERT_EQUALS((**it).getTag(), 0U);
}

/** Test packTagList.
    A: create session with turn and a some markers. Create DrawingProxy. Call getTagList().
    E: verify result */
void
TestGameProxyDrawingProxy::testPackTagList()
{
    SessionThread h;
    WaitIndicator ind;
    prepare(h);
    util::AtomTable& tab = h.session().world().atomTable();
    addLine(h, 1000, 1000, 1010, 1010, 7, 1);
    addLine(h, 1000, 1000, 1010, 1010, 7, 20);
    addLine(h, 1000, 1000, 1010, 1010, 7, tab.getAtomFromString("hi"));
    addLine(h, 1000, 1000, 1010, 1010, 7, tab.getAtomFromString("hi"));
    addLine(h, 1000, 1000, 1010, 1010, 7, tab.getAtomFromString("what"));
    addLine(h, 1000, 1000, 1010, 1010, 7, 3);

    // Retrieve result
    DrawingProxy testee(h.gameSender(), ind);
    util::StringList list;
    testee.getTagList(ind, list);

    // Verify
    list.sortAlphabetically();
    TS_ASSERT_EQUALS(list.size(), 5U);

    int32_t k;
    String_t s;
    TS_ASSERT(list.get(0, k, s));
    TS_ASSERT_EQUALS(k, 1);
    TS_ASSERT_EQUALS(s, "1");

    TS_ASSERT(list.get(1, k, s));
    TS_ASSERT_EQUALS(k, 20);
    TS_ASSERT_EQUALS(s, "20");

    TS_ASSERT(list.get(2, k, s));
    TS_ASSERT_EQUALS(k, 3);
    TS_ASSERT_EQUALS(s, "3");

    TS_ASSERT(list.get(3, k, s));
    TS_ASSERT_EQUALS(s, "hi");

    TS_ASSERT(list.get(4, k, s));
    TS_ASSERT_EQUALS(s, "what");
}

/** Test packTagList on empty universe.
    A: create session. Create DrawingProxy. Call getTagList().
    E: result must be empty */
void
TestGameProxyDrawingProxy::testPackTagListEmpty()
{
    SessionThread h;
    WaitIndicator ind;
    prepare(h);

    DrawingProxy testee(h.gameSender(), ind);
    util::StringList list;
    testee.getTagList(ind, list);

    TS_ASSERT_EQUALS(list.size(), 0U);
}

/** Test creating a canned marker.
    A: create session with turn and root. Create DrawingProxy. Create and populate a canned marker.
    E: marker created; correct status reported. */
void
TestGameProxyDrawingProxy::testCreateCannedMarker()
{
    SessionThread h;
    WaitIndicator ind;
    prepare(h);

    // Need a root for this test for configuration.
    // Hardwire the configuration here to be independant from changing defaults.
    afl::base::Ptr<game::Root> r = game::test::makeRoot(game::HostVersion()).asPtr();
    r->userConfiguration().setOption("chart.marker4", "5,7,x", game::config::ConfigurationOption::User);
    h.session().setRoot(r);

    DrawingProxy testee(h.gameSender(), ind);
    StatusReceiver recv(testee);

    // Create and configure a marker
    testee.createCannedMarker(Point(1111, 2222), 4);

    // Verify that correct update is eventually received
    h.sync();
    ind.processQueue();
    TS_ASSERT(recv.get().isValid());
    TS_ASSERT_EQUALS(recv.get().get()->getType(), Drawing::MarkerDrawing);
    TS_ASSERT_EQUALS(recv.get().get()->getPos(), Point(1111, 2222));
    TS_ASSERT_EQUALS(recv.get().get()->getColor(), 7);
    TS_ASSERT_EQUALS(recv.get().get()->getMarkerKind(), 5);

    // Verify that marker is present
    DrawingContainer::Iterator_t it = h.session().getGame()->currentTurn().universe().drawings().begin();
    TS_ASSERT(*it);
    TS_ASSERT_EQUALS((*it)->getType(), Drawing::MarkerDrawing);
    TS_ASSERT_EQUALS((*it)->getPos(), Point(1111, 2222));
    TS_ASSERT_EQUALS((*it)->getColor(), 7);
    TS_ASSERT_EQUALS((*it)->getMarkerKind(), 5);
}

/** Test queueing.
    A: create session with turn. Create DrawingProxy. Create a circle. Call setCircleRadius repeatedly.
    E: verify result: circle eventually settles at the last radius given. */
void
TestGameProxyDrawingProxy::testQueueing()
{
    SessionThread h;
    WaitIndicator ind;
    prepare(h);
    DrawingProxy testee(h.gameSender(), ind);

    // Create
    testee.create(Point(1300, 1400), Drawing::CircleDrawing);
    for (int i = 1; i < 20; ++i) {
        testee.setCircleRadius(10*i);
    }

    // Verify
    for (int i = 1; i < 20; ++i) {
        h.sync();
        ind.processQueue();
    }

    DrawingContainer::Iterator_t it = h.session().getGame()->currentTurn().universe().drawings().begin();
    TS_ASSERT(*it);
    TS_ASSERT_EQUALS((**it).getPos(),          Point(1300, 1400));
    TS_ASSERT_EQUALS((**it).getCircleRadius(), 190);
    TS_ASSERT_EQUALS((**it).getType(),         Drawing::CircleDrawing);
}
