From 2bad2edf797c9fefb1facd2a63c69cce34a0e635 Mon Sep 17 00:00:00 2001 From: Mateusz Piekos Date: Sat, 7 Jul 2012 18:49:10 +0200 Subject: Added WhiteboardClient with passing simple unit test diff --git a/Swiften/SConscript b/Swiften/SConscript index 120186f..9c9d246 100644 --- a/Swiften/SConscript +++ b/Swiften/SConscript @@ -207,6 +207,7 @@ if env["SCONS_STAGE"] == "build" : "Whiteboard/OutgoingWhiteboardSession.cpp", "Whiteboard/WhiteboardSessionManager.cpp", "Whiteboard/WhiteboardServer.cpp", + "Whiteboard/WhiteboardClient.cpp", "Whiteboard/Elements/Color.cpp", "Whiteboard/WhiteboardTransformer.cpp", ] @@ -405,6 +406,7 @@ if env["SCONS_STAGE"] == "build" : File("TLS/UnitTest/CertificateTest.cpp"), File("VCards/UnitTest/VCardManagerTest.cpp"), File("Whiteboard/UnitTest/WhiteboardServerTest.cpp"), + File("Whiteboard/UnitTest/WhiteboardClientTest.cpp"), ]) # Generate the Swiften header diff --git a/Swiften/Whiteboard/UnitTest/WhiteboardClientTest.cpp b/Swiften/Whiteboard/UnitTest/WhiteboardClientTest.cpp new file mode 100644 index 0000000..f6f8249 --- /dev/null +++ b/Swiften/Whiteboard/UnitTest/WhiteboardClientTest.cpp @@ -0,0 +1,101 @@ +/* + * Copyright (c) 2012 Mateusz Piękos + * Licensed under the simplified BSD license. + * See Documentation/Licenses/BSD-simplified.txt for more information. + */ + + +#include +#include + +#include +#include +#include +#include + +using namespace Swift; + +class WhiteboardClientTest : public CppUnit::TestFixture { + CPPUNIT_TEST_SUITE(WhiteboardClientTest); + CPPUNIT_TEST(testNoninterrupedSynchronization); + CPPUNIT_TEST_SUITE_END(); +public: + void testNoninterrupedSynchronization() { + WhiteboardClient client; + WhiteboardInsertOperation::ref serverOp; + serverOp = createInsertOperation("0", ""); + serverOp->setPos(0); + std::pair pairResult = client.handleServerOperationReceived(serverOp); + CPPUNIT_ASSERT_EQUAL(serverOp, boost::dynamic_pointer_cast(pairResult.first)); + CPPUNIT_ASSERT_EQUAL(WhiteboardOperation::ref(), pairResult.second); + + WhiteboardInsertOperation::ref clientOp; + clientOp = createInsertOperation("a", "0"); + clientOp->setPos(1); + clientOp->setOrigin(WhiteboardOperation::Local); + WhiteboardEllipseElement::ref aElement = boost::make_shared(0,0,0,0); + clientOp->setElement(aElement); + WhiteboardInsertOperation::ref result = boost::dynamic_pointer_cast(client.handleLocalOperationReceived(clientOp)); + CPPUNIT_ASSERT_EQUAL(clientOp, boost::dynamic_pointer_cast(result)); + CPPUNIT_ASSERT_EQUAL(aElement, boost::dynamic_pointer_cast(result->getElement())); + + + clientOp = createInsertOperation("b", "a"); + clientOp->setPos(2); + clientOp->setOrigin(WhiteboardOperation::Local); + WhiteboardEllipseElement::ref bElement = boost::make_shared(0,0,0,0); + clientOp->setElement(bElement); + CPPUNIT_ASSERT_EQUAL(WhiteboardOperation::ref(), client.handleLocalOperationReceived(clientOp)); + + serverOp = createInsertOperation("c", "0"); + serverOp->setPos(1); + serverOp->setOrigin(WhiteboardOperation::Other); + WhiteboardEllipseElement::ref cElement = boost::make_shared(0,0,0,0); + serverOp->setElement(cElement); + pairResult = client.handleServerOperationReceived(serverOp); + result = boost::dynamic_pointer_cast(pairResult.first); + CPPUNIT_ASSERT_EQUAL(3, result->getPos()); + CPPUNIT_ASSERT_EQUAL(cElement, boost::dynamic_pointer_cast(result->getElement())); + CPPUNIT_ASSERT_EQUAL(std::string("b"), result->getParentID()); + CPPUNIT_ASSERT_EQUAL(WhiteboardOperation::ref(), pairResult.second); + + serverOp = createInsertOperation("d", "c"); + serverOp->setPos(2); + serverOp->setOrigin(WhiteboardOperation::Other); + WhiteboardEllipseElement::ref dElement = boost::make_shared(0,0,0,0); + serverOp->setElement(dElement); + pairResult = client.handleServerOperationReceived(serverOp); + result = boost::dynamic_pointer_cast(pairResult.first); + CPPUNIT_ASSERT_EQUAL(4, result->getPos()); + CPPUNIT_ASSERT_EQUAL(dElement, boost::dynamic_pointer_cast(result->getElement())); + CPPUNIT_ASSERT_EQUAL(std::string("c"), result->getParentID()); + CPPUNIT_ASSERT_EQUAL(WhiteboardOperation::ref(), pairResult.second); + + serverOp = createInsertOperation("a", "d"); + serverOp->setPos(1); + serverOp->setOrigin(WhiteboardOperation::Other); + pairResult = client.handleServerOperationReceived(serverOp); + result = boost::dynamic_pointer_cast(pairResult.second); + CPPUNIT_ASSERT_EQUAL(WhiteboardOperation::ref(), pairResult.first); + CPPUNIT_ASSERT_EQUAL(std::string("b"), result->getID()); + CPPUNIT_ASSERT_EQUAL(bElement, boost::dynamic_pointer_cast(result->getElement())); + CPPUNIT_ASSERT_EQUAL(std::string("a"), result->getParentID()); + CPPUNIT_ASSERT_EQUAL(WhiteboardOperation::Other, result->getOrigin()); + + serverOp = createInsertOperation("b", "a"); + serverOp->setPos(2); + serverOp->setOrigin(WhiteboardOperation::Other); + pairResult = client.handleServerOperationReceived(serverOp); + CPPUNIT_ASSERT_EQUAL(WhiteboardOperation::ref(), pairResult.first); + CPPUNIT_ASSERT_EQUAL(WhiteboardOperation::ref(), pairResult.second); + } + + WhiteboardInsertOperation::ref createInsertOperation(std::string id, std::string parent) { + WhiteboardInsertOperation::ref operation = boost::make_shared(); + operation->setParentID(parent); + operation->setID(id); + return operation; + } +}; + +CPPUNIT_TEST_SUITE_REGISTRATION(WhiteboardClientTest); diff --git a/Swiften/Whiteboard/WhiteboardClient.cpp b/Swiften/Whiteboard/WhiteboardClient.cpp new file mode 100644 index 0000000..6b352f5 --- /dev/null +++ b/Swiften/Whiteboard/WhiteboardClient.cpp @@ -0,0 +1,91 @@ +/* + * Copyright (c) 2012 Mateusz Piękos + * Licensed under the simplified BSD license. + * See Documentation/Licenses/BSD-simplified.txt for more information. + */ + +#include +#include + +namespace Swift { + WhiteboardOperation::ref WhiteboardClient::handleLocalOperationReceived(WhiteboardOperation::ref operation) { + localOperations_.push_back(operation); + if (lastSentOperationID_.empty()) + { + lastSentOperationID_ = operation->getID(); + return operation; + } + return WhiteboardOperation::ref(); + } + + std::pair WhiteboardClient::handleServerOperationReceived(WhiteboardOperation::ref operation) { + serverOperations_.push_back(operation); + WhiteboardOperation::ref clientOp; + WhiteboardOperation::ref serverOp; + if (localOperations_.empty()) {// || localOperations_.back()->getID() == operation->getParentID()) { + localOperations_.push_back(operation); + clientOp = operation; + } else if (lastSentOperationID_ == operation->getID()) { + std::list::iterator it; + for (it = bridge_.begin(); it != bridge_.end(); ++it) { + if ((*it)->getParentID() == lastSentOperationID_) { + lastSentOperationID_ = (*it)->getID(); + serverOperations_.push_back(*it); + serverOp = *it; + serverOp->setOrigin(WhiteboardOperation::Other); + break; + } + } + } else { + if (bridge_.size() > 0 && bridge_.front()->getParentID() == operation->getParentID()) { + std::list::iterator it = bridge_.begin(); + std::pair opPair; + WhiteboardInsertOperation::ref temp; + opPair = WhiteboardTransformer::transform(boost::dynamic_pointer_cast(*it), boost::dynamic_pointer_cast(operation)); + temp = opPair.first; + + *it = opPair.second; + std::string previousID = (*it)->getID(); + ++it; + for (; it != bridge_.end(); ++it) { + opPair = WhiteboardTransformer::transform(boost::dynamic_pointer_cast(*it), temp); + temp = opPair.first; + *it = opPair.second; + (*it)->setParentID(previousID); + previousID = (*it)->getID(); + } + temp->setParentID(localOperations_.back()->getID()); + localOperations_.push_back(temp); + clientOp = temp; + } else { + std::list::reverse_iterator it; + std::pair opPair; + WhiteboardInsertOperation::ref temp = boost::dynamic_pointer_cast(operation); + bool end = false; + for (it = localOperations_.rbegin(); it != localOperations_.rend(); ++it) { + while ((*it)->getParentID() == temp->getParentID()) { + opPair = WhiteboardTransformer::transform(boost::dynamic_pointer_cast(*it), temp); + if (bridge_.size() > 0) { + opPair.second->setParentID(bridge_.back()->getID()); + } + temp = opPair.first; + bridge_.push_back(opPair.second); + if (it == localOperations_.rbegin()) { + localOperations_.push_back(temp); + clientOp = temp; + end = true; + break; + } else { + --it; + } + } + if (end) { + break; + } + } + } + } + + return std::pair(clientOp, serverOp); + } +} diff --git a/Swiften/Whiteboard/WhiteboardClient.h b/Swiften/Whiteboard/WhiteboardClient.h new file mode 100644 index 0000000..f781e6f --- /dev/null +++ b/Swiften/Whiteboard/WhiteboardClient.h @@ -0,0 +1,31 @@ +/* + * Copyright (c) 2012 Mateusz Piękos + * Licensed under the simplified BSD license. + * See Documentation/Licenses/BSD-simplified.txt for more information. + */ + +#pragma once + +#include +#include +#include + +namespace Swift { + class WhiteboardClient { + public: + /*! + * @return Operation to send + */ + WhiteboardOperation::ref handleLocalOperationReceived(WhiteboardOperation::ref operation); + /*! + * @return pair.first-element to handle locally, pair.second-element to send to server + */ + std::pair handleServerOperationReceived(WhiteboardOperation::ref operation); + + private: + std::list localOperations_; + std::list serverOperations_; + std::list bridge_; + std::string lastSentOperationID_; + }; +} -- cgit v0.10.2-6-g49f6