tests[ChronoShare]: Create integrated tests for ChronoShare
Change-Id: If3f2a803b41dedb060971d07d9564e9ec5f77f4b
diff --git a/tests/integrated-tests/chronoshare.cpp b/tests/integrated-tests/chronoshare.cpp
new file mode 100644
index 0000000..415f24d
--- /dev/null
+++ b/tests/integrated-tests/chronoshare.cpp
@@ -0,0 +1,281 @@
+/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
+/**
+ * Copyright (c) 2013-2017 Regents of the University of California.
+ *
+ * This file is part of ndn-cxx library (NDN C++ library with eXperimental eXtensions).
+ *
+ * ndn-cxx library is free software: you can redistribute it and/or modify it under the
+ * terms of the GNU Lesser General Public License as published by the Free Software
+ * Foundation, either version 3 of the License, or (at your option) any later version.
+ *
+ * ndn-cxx library is distributed in the hope that it will be useful, but WITHOUT ANY
+ * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A
+ * PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details.
+ *
+ * You should have received copies of the GNU General Public License and GNU Lesser
+ * General Public License along with ndn-cxx, e.g., in COPYING.md file. If not, see
+ * <http://www.gnu.org/licenses/>.
+ *
+ * See AUTHORS.md for complete list of ndn-cxx authors and contributors.
+ */
+#define BOOST_TEST_MAIN 1
+#define BOOST_TEST_DYN_LINK 1
+#define BOOST_TEST_MODULE ChronoShare Integrated Tests (ChronoShare)
+
+#include "gui/chronosharegui.hpp"
+#include "test-common.hpp"
+#include "dummy-forwarder.hpp"
+
+#include <boost/make_shared.hpp>
+#include <boost/test/unit_test.hpp>
+#include <boost/bind.hpp>
+#include <boost/filesystem.hpp>
+#include <boost/filesystem/fstream.hpp>
+#include <boost/lexical_cast.hpp>
+#include <thread>
+#include <chrono>
+
+namespace ndn {
+namespace chronoshare {
+namespace tests {
+
+using namespace std;
+namespace fs = boost::filesystem;
+
+_LOG_INIT(Test.Integrated.ChronoShare);
+
+class ChronoShareFixture : public IdentityManagementFixture
+{
+public:
+ ChronoShareFixture()
+ : forwarder(m_io, m_keyChain)
+ , folder("sharefolder")
+ , dir1(fs::path(fs::path(UNIT_TEST_CONFIG_PATH) / "sharefolder1"))
+ , dir2(fs::path(fs::path(UNIT_TEST_CONFIG_PATH) / "sharefolder2"))
+ , argc(0)
+ {
+
+ if (fs::exists(dir1)) {
+ fs::remove_all(dir1);
+ }
+
+ if (fs::exists(dir2)) {
+ fs::remove_all(dir2);
+ }
+
+ fs::create_directory(dir1);
+ fs::create_directory(dir2);
+ }
+
+ ~ChronoShareFixture()
+ {
+ //delete app;
+ // cleanup
+ if (fs::exists(dir1)) {
+ fs::remove_all(dir1);
+ }
+
+ // cleanup
+ if (fs::exists(dir2)) {
+ fs::remove_all(dir2);
+ }
+ }
+
+ void
+ advanceClocks(std::chrono::seconds delay)
+ {
+ std::chrono::milliseconds step = delay;
+ step /= 50;
+ for (int i = 0; i < 50; ++i) {
+ std::this_thread::sleep_for(step);
+ m_io.poll();
+ m_io.reset();
+ }
+ }
+
+ void
+ create_file(const fs::path& ph, const std::string& contents)
+ {
+ std::ofstream f(ph.string().c_str());
+ if (!f) {
+ abort();
+ }
+ if (!contents.empty()) {
+ f << contents;
+ }
+ }
+
+ void
+ run()
+ {
+ std::this_thread::sleep_for(std::chrono::seconds(5));
+
+ _LOG_DEBUG("======created files===========");
+ create_file(dir1 / folder / "test.txt", "hello");
+
+ std::this_thread::sleep_for(std::chrono::seconds(10));
+
+
+ BOOST_REQUIRE_MESSAGE(fs::exists(dir2 / folder / "test.txt"), "user1 failed to notify user2 about test.txt");
+ BOOST_CHECK_EQUAL(fs::file_size(dir1 / folder / "test.txt"), fs::file_size(dir2 / folder / "test.txt"));
+
+
+ fs::path subdir1 = dir1 / folder / "sub";
+ fs::path subdir2 = dir2 / folder / "sub";
+ fs::create_directory(subdir1);
+ for (int i = 0; i < 10; i++) {
+ string filename = boost::lexical_cast<string>(i);
+ create_file(subdir1 / filename.c_str(), boost::lexical_cast<string>(i));
+ }
+
+ std::this_thread::sleep_for(std::chrono::seconds(10));
+ for (int i = 0; i < 10; i++) {
+ string filename = boost::lexical_cast<string>(i);
+ BOOST_REQUIRE_MESSAGE(fs::exists(subdir2 / filename), "user1 failed to notify user2 about"<< filename);
+ }
+
+ //=========check copy file to sub directory==========
+ fs::create_directory(dir1 / folder / "sub1");
+ fs::path subsubdir1 = dir1 / folder / "sub1" / "sub2";
+ fs::path subsubdir2 = dir2 / folder / "sub1" / "sub2";
+ fs::copy_directory(subdir1, subsubdir1);
+ for (int i = 0; i < 5; i++) {
+ string filename = boost::lexical_cast<string>(i);
+ fs::copy(subdir1 / filename.c_str(), subsubdir1 / filename.c_str());
+ }
+
+ std::this_thread::sleep_for(std::chrono::seconds(10));
+ // test.txt
+ // sub/0..9
+ // sub1/sub2/0..4
+ for (int i = 0; i < 5; i++) {
+ string filename = boost::lexical_cast<string>(i);
+ BOOST_REQUIRE_MESSAGE(fs::exists(subsubdir2 / filename), "user1 failed to notify user2 about"<< filename);
+ }
+
+ // =============== check remove files =========================
+ for (int i = 0; i < 7; i++) {
+ string filename = boost::lexical_cast<string>(i);
+ fs::remove(subdir1 / filename.c_str());
+ }
+
+ std::this_thread::sleep_for(std::chrono::seconds(10));
+ // test.txt
+ // sub/7..9
+ // sub1/sub2/0..4
+ for (int i = 0; i < 10; i++) {
+ string filename = boost::lexical_cast<string>(i);
+ if (i < 7)
+ BOOST_REQUIRE_MESSAGE(!fs::exists(subdir2 / filename), "user1 failed to notify user2 about"<< filename);
+ else
+ BOOST_REQUIRE_MESSAGE(fs::exists(subdir2 / filename), "user1 failed to notify user2 about"<< filename);
+ }
+
+ // =================== check remove files again, remove the whole dir this time
+ // ===================
+ // before remove check
+ for (int i = 0; i < 5; i++) {
+ string filename = boost::lexical_cast<string>(i);
+ BOOST_REQUIRE_MESSAGE(fs::exists(subsubdir2 / filename), "user1 failed to notify user2 about"<< filename);
+ }
+ fs::remove_all(subsubdir1);
+
+ std::this_thread::sleep_for(std::chrono::seconds(10));
+ // test.txt
+ // sub/7..9
+ BOOST_REQUIRE_MESSAGE(!fs::exists(subsubdir2), "user1 failed to notify user2 about sub1/sub2");
+
+ // =================== check rename files =======================
+ for (int i = 7; i < 10; i++) {
+ string filename = boost::lexical_cast<string>(i);
+ fs::rename(subdir1 / filename.c_str(), dir1 / folder / filename.c_str());
+ }
+ std::this_thread::sleep_for(std::chrono::seconds(10));
+ // test.txt
+ // 7
+ // 8
+ // 9
+ // sub
+ for (int i = 7; i < 10; i++) {
+ string filename = boost::lexical_cast<string>(i);
+
+ BOOST_REQUIRE_MESSAGE(!fs::exists(subdir2 / filename), "user1 failed to notify user2 about"<< filename);
+ BOOST_REQUIRE_MESSAGE(fs::exists(dir2 / folder / filename), "user1 failed to notify user2 about"<< filename);
+ }
+
+ create_file(dir1 / folder / "add-removal-check.txt", "add-removal-check");
+ std::this_thread::sleep_for(std::chrono::seconds(4));
+ BOOST_REQUIRE_MESSAGE(fs::exists(dir2 / folder / "add-removal-check.txt"),
+ "user1 failed to notify user2 about add-removal-check.txt");
+
+ fs::remove(dir1 / folder / "add-removal-check.txt");
+ std::this_thread::sleep_for(std::chrono::seconds(4));
+ BOOST_REQUIRE_MESSAGE(!fs::exists(dir2 / folder / "add-removal-check.txt"),
+ "user1 failed to notify user2 about add-removal-check.txt");
+
+ create_file(dir1 / folder / "add-removal-check.txt", "add-removal-check");
+ std::this_thread::sleep_for(std::chrono::seconds(4));
+ BOOST_REQUIRE_MESSAGE(fs::exists(dir2 / folder / "add-removal-check.txt"),
+ "user1 failed to notify user2 about add-removal-check.txt");
+
+ fs::remove(dir1 / folder / "add-removal-check.txt");
+ std::this_thread::sleep_for(std::chrono::seconds(4));
+ BOOST_REQUIRE_MESSAGE(!fs::exists(dir2 / folder / "add-removal-check.txt"),
+ "user1 failed to notify user2 about add-removal-check.txt");
+
+ create_file(dir1 / folder / "add-removal-check.txt", "add-removal-check");
+ std::this_thread::sleep_for(std::chrono::seconds(4));
+ BOOST_REQUIRE_MESSAGE(fs::exists(dir2 / folder / "add-removal-check.txt"),
+ "user1 failed to notify user2 about add-removal-check.txt");
+
+ fs::remove(dir1 / folder / "add-removal-check.txt");
+ std::this_thread::sleep_for(std::chrono::seconds(4));
+ BOOST_REQUIRE_MESSAGE(!fs::exists(dir2 / folder / "add-removal-check.txt"),
+ "user1 failed to notify user2 about add-removal-check.txt");
+
+ _LOG_DEBUG("======finish thread===========");
+ }
+
+public:
+ DummyForwarder forwarder;
+ std::string folder;
+ fs::path dir1;
+ fs::path dir2;
+
+ int argc;
+ //TestApp* app;
+};
+
+BOOST_FIXTURE_TEST_SUITE(TestChronoShare, ChronoShareFixture)
+
+BOOST_AUTO_TEST_CASE(Chronoshare)
+{
+ QApplication app(argc, nullptr);
+
+ // do not quit when last window closes
+ app.setQuitOnLastWindowClosed(false);
+ // invoke gui
+ ndn::chronoshare::ChronoShareGui gui1(QString::fromStdString(dir1.generic_string()),
+ QString::fromStdString("user1"),
+ QString::fromStdString("sharefolder"));
+
+ // invoke gui
+ ndn::chronoshare::ChronoShareGui gui2(QString::fromStdString(dir2.generic_string()),
+ QString::fromStdString("user2"),
+ QString::fromStdString("sharefolder"));
+
+ QTimer::singleShot(95000, &app, SLOT(quit()));
+
+ _LOG_DEBUG("run thread");
+ std::thread workThread(boost::bind(&ChronoShareFixture::run, this));
+
+ app.exec();
+ workThread.join();
+ _LOG_DEBUG("thread finished");
+}
+
+BOOST_AUTO_TEST_SUITE_END()
+
+} // namespace tests
+} // namespace chronoshare
+} // namespace ndn
diff --git a/tests/integrated-tests/fs-watcher.t.cpp b/tests/integrated-tests/fs-watcher.cpp
similarity index 95%
rename from tests/integrated-tests/fs-watcher.t.cpp
rename to tests/integrated-tests/fs-watcher.cpp
index 05f9764..c29da56 100644
--- a/tests/integrated-tests/fs-watcher.t.cpp
+++ b/tests/integrated-tests/fs-watcher.cpp
@@ -17,6 +17,9 @@
*
* See AUTHORS.md for complete list of ChronoShare authors and contributors.
*/
+#define BOOST_TEST_MAIN 1
+#define BOOST_TEST_DYN_LINK 1
+#define BOOST_TEST_MODULE ChronoShare Integrated Tests (FsWatcher)
#include "fs-watcher.hpp"
#include "test-common.hpp"
@@ -32,8 +35,7 @@
#include <iostream>
#include <thread>
#include <set>
-
-#include "fs-watcher.t.hpp"
+#include <QtWidgets>
using namespace std;
namespace fs = boost::filesystem;
@@ -44,14 +46,6 @@
namespace chronoshare {
namespace tests {
-fsWatcherApp::fsWatcherApp(int& argc, char** argv)
- : QCoreApplication(argc, argv)
-{
- connect(this, SIGNAL(stopApp()), this, SLOT(quit()), Qt::QueuedConnection);
-}
-
-fsWatcherApp::~fsWatcherApp() = default;
-
class TestFSWatcherFixture : public IdentityManagementFixture
{
public:
@@ -115,19 +109,21 @@
void
run()
{
- app = new fsWatcherApp(argc, nullptr);
+ QApplication app(argc, nullptr);
new FsWatcher(m_io, dir.string().c_str(),
std::bind(&TestFSWatcherFixture::onChange, this, std::ref(files), _1),
std::bind(&TestFSWatcherFixture::onDelete, this, std::ref(files), _1),
- app);
- app->exec();
+ &app);
+
+ QTimer::singleShot(21000, &app, SLOT(quit()));
+ app.exec();
}
public:
fs::path dir;
set<string> files;
int argc;
- fsWatcherApp* app;
+ //fsWatcherApp* app;
};
BOOST_FIXTURE_TEST_SUITE(TestFsWatcher, TestFSWatcherFixture)
@@ -255,7 +251,7 @@
this->advanceClocks(std::chrono::seconds(2));
BOOST_CHECK(files.find("add-removal-check.txt") == files.end());
- emit app->stopApp();
+ //emit app->stopApp();
workThread.join();
}
diff --git a/tests/integrated-tests/fs-watcher.t.hpp b/tests/integrated-tests/fs-watcher.t.hpp
deleted file mode 100644
index 40c524b..0000000
--- a/tests/integrated-tests/fs-watcher.t.hpp
+++ /dev/null
@@ -1,42 +0,0 @@
-/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
-/**
- * Copyright (c) 2013-2017, Regents of the University of California.
- *
- * This file is part of ChronoShare, a decentralized file sharing application over NDN.
- *
- * ChronoShare is free software: you can redistribute it and/or modify it under the terms
- * of the GNU General Public License as published by the Free Software Foundation, either
- * version 3 of the License, or (at your option) any later version.
- *
- * ChronoShare is distributed in the hope that it will be useful, but WITHOUT ANY
- * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A
- * PARTICULAR PURPOSE. See the GNU General Public License for more details.
- *
- * You should have received copies of the GNU General Public License along with
- * ChronoShare, e.g., in COPYING.md file. If not, see <http://www.gnu.org/licenses/>.
- *
- * See AUTHORS.md for complete list of ChronoShare authors and contributors.
- */
-
-#include <QtWidgets>
-
-namespace ndn {
-namespace chronoshare {
-namespace tests {
-
-class fsWatcherApp : public QCoreApplication
-{
-Q_OBJECT
-
-signals:
- void
- stopApp();
-
-public:
- fsWatcherApp(int& argc, char** argv);
- ~fsWatcherApp();
-};
-
-} // namespace tests
-} // namespace chronoshare
-} // namespace ndn
diff --git a/tests/integrated-tests/wscript b/tests/integrated-tests/wscript
new file mode 100644
index 0000000..3898a81
--- /dev/null
+++ b/tests/integrated-tests/wscript
@@ -0,0 +1,15 @@
+from waflib import Utils
+
+top = '..'
+
+def build(bld):
+
+ for i in bld.path.ant_glob(['*.cpp']):
+ name = str(i)[str.rfind(str(i),'/'):-len(".cpp")]
+ bld(features='qt5 cxx cxxprogram',
+ target=name,
+ source=[i],
+ use='chronoshare core-objects adhoc http_server chronoshare_gui boost-tests-base QT5CORE QT5WIDGETS',
+ includes='..',
+ defines=['UNIT_TEST_CONFIG_PATH=\"%s/tmp-files/\"' % (bld.bldnode)],
+ install_path=None)