Adding nsync for NLSR
diff --git a/nsync/tests/main.cc b/nsync/tests/main.cc
new file mode 100644
index 0000000..6b0a14a
--- /dev/null
+++ b/nsync/tests/main.cc
@@ -0,0 +1,13 @@
+/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil -*- */
+/*
+ * Copyright (c) 2013, Regents of the University of California
+ *
+ * BSD license, See the LICENSE file for more information
+ *
+ * Author: Alexander Afanasyev <alexander.afanasyev@ucla.edu>
+ */
+
+#define BOOST_TEST_MAIN 1
+#define BOOST_TEST_DYN_LINK 1
+
+#include <boost/test/unit_test.hpp>
diff --git a/nsync/tests/test_data_fetch_and_publish.cc b/nsync/tests/test_data_fetch_and_publish.cc
new file mode 100644
index 0000000..c1eb5df
--- /dev/null
+++ b/nsync/tests/test_data_fetch_and_publish.cc
@@ -0,0 +1,111 @@
+/* -*- Mode: C++; c-file-style: "gnu"; indent-tabs-mode:nil -*- */
+/*
+ * Copyright (c) 2012 University of California, Los Angeles
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation;
+ *
+ * This program 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 a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ *
+ * Author: Zhenkai Zhu <zhenkai@cs.ucla.edu>
+ *         Chaoyi Bian <bcy@pku.edu.cn>
+ *	   Alexander Afanasyev <alexander.afanasyev@ucla.edu>
+ */
+
+/*
+#include <boost/test/unit_test.hpp>
+#include <boost/test/output_test_stream.hpp> 
+#include <map>
+using boost::test_tools::output_test_stream;
+
+#include <boost/make_shared.hpp>
+
+#include "sync-ccnx-wrapper.h"
+#include "sync-app-data-fetch.h"
+#include "sync-app-data-publish.h"
+
+using namespace Sync;
+using namespace std;
+using namespace boost;
+
+class TestStructApp {
+public:
+  map<string, string> data;
+  void set(string str1, string str2) {
+    data.insert(make_pair(str1, str2));
+  }
+
+  void erase(string str1, string str2) {
+    data.erase(str1);
+  }
+
+  string toString(){
+    map<string, string>::iterator it = data.begin(); 
+    string str = "";
+    for (; it != data.end(); ++it){
+      str += "<";
+      str += it->first;
+      str += "|";
+      str += it->second;
+      str += ">";
+    }
+    return str;
+  }
+
+};
+
+BOOST_AUTO_TEST_CASE (AppDataPublishAndFetchTest)
+{
+  TestStructApp foo;
+  TestStructApp bar;
+	
+  string interest = "/april/fool";
+  string seq[5] = {"0", "1", "2", "3", "4" };
+  string str[5] = {"panda", "express", "tastes", "so", "good"};
+
+  for (int i = 0; i < 5; i++) {
+    foo.set(interest + "/" + "0/" + seq[i], str[i]);
+  }
+
+  boost::function<void (string, string)> setFunc =
+    bind(&TestStructApp::set, &bar, _1, _2);
+
+  shared_ptr<CcnxWrapper> handle(new CcnxWrapper());
+
+  AppDataFetch fetcher(handle, setFunc);
+  AppDataPublish publisher(handle);
+
+  for (int i = 1; i <= 5; i++) {
+    publisher.publishData(interest, 0, str[i - 1], 5);
+  }
+
+  BOOST_CHECK_EQUAL(publisher.getNextSeq(interest, 0), 5);
+  BOOST_CHECK_EQUAL(publisher.getRecentData(interest, 0), str[4]);
+
+  fetcher.onUpdate (interest, SeqNo (0,4), SeqNo (0,-1));
+  // give time for ccnd to react
+  sleep(1);
+  BOOST_CHECK_EQUAL(foo.toString(), bar.toString());
+
+
+  boost::function<void (string, string)> eraseFunc =
+    bind(&TestStructApp::erase, &bar, _1, _2);
+  fetcher.setDataCallback(eraseFunc);
+
+  fetcher.onUpdate (interest, SeqNo (0,4), SeqNo (0,-1));
+  // give time for ccnd to react
+  sleep(1);
+  TestStructApp poo;
+
+  BOOST_CHECK_EQUAL(poo.toString(), bar.toString());
+
+}
+*/
diff --git a/nsync/tests/test_digest.cc b/nsync/tests/test_digest.cc
new file mode 100644
index 0000000..4815919
--- /dev/null
+++ b/nsync/tests/test_digest.cc
@@ -0,0 +1,104 @@
+/* -*- Mode: C++; c-file-style: "gnu"; indent-tabs-mode:nil -*- */
+/*
+ * Copyright (c) 2012 University of California, Los Angeles
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation;
+ *
+ * This program 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 a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ *
+ * Author: Zhenkai Zhu <zhenkai@cs.ucla.edu>
+ *         Chaoyi Bian <bcy@pku.edu.cn>
+ *	   Alexander Afanasyev <alexander.afanasyev@ucla.edu>
+ */
+
+#include <boost/test/unit_test.hpp>
+#include <boost/test/output_test_stream.hpp> 
+using boost::test_tools::output_test_stream;
+
+#include "sync-digest.h"
+#include <iostream>
+#include <sstream>
+
+using namespace Sync;
+using namespace Sync::Error;
+using namespace std;
+using namespace boost;
+
+BOOST_AUTO_TEST_SUITE(DigestTests)
+
+BOOST_AUTO_TEST_CASE (BasicTest)
+{
+  Digest d0;
+  BOOST_REQUIRE (d0.empty ());
+}
+
+BOOST_AUTO_TEST_CASE (DigestGenerationTest)
+{
+  Digest d1;
+  BOOST_CHECK_NO_THROW (d1 << "1\n");
+
+  // without explicit finalizing, Digest will not be complete and printing out will cause assert
+  BOOST_CHECK (d1.empty ());
+
+  // fix hash
+  d1.finalize ();
+  
+  BOOST_CHECK_NO_THROW (d1.getHash ());
+  BOOST_CHECK (!d1.empty ());
+  BOOST_CHECK (d1 == d1);
+
+  BOOST_CHECK_THROW (d1 << "2", DigestCalculationError);
+  
+  output_test_stream output;
+  BOOST_CHECK_NO_THROW (output << d1);
+  // BOOST_CHECK (output.check_length (40, false) );
+  // BOOST_CHECK (output.is_equal ("e5fa44f2b31c1fb553b6021e7360d07d5d91ff5e", true)); // for sha1
+	BOOST_CHECK (output.check_length (64, false) );
+	BOOST_CHECK (output.is_equal ("4355a46b19d348dc2f57c046f8ef63d4538ebb936000f3c9ee954a27460dd865", true)); // for sha256
+}
+
+BOOST_AUTO_TEST_CASE (DigestComparison)
+{
+  Digest d1;
+  BOOST_CHECK_NO_THROW (d1 << "1\n");
+  // BOOST_CHECK_THROW (d1 == d1, DigestCalculationError);
+  BOOST_CHECK_NO_THROW (d1.finalize ());
+  BOOST_CHECK (d1 == d1);
+  
+  Digest d2;
+  BOOST_CHECK_NO_THROW (d2 << "2\n");
+  BOOST_CHECK_NO_THROW (d2.finalize ());
+  BOOST_CHECK (d1 != d2);
+  
+  Digest d3;
+  // istringstream is (string ("e5fa44f2b31c1fb553b6021e7360d07d5d91ff5e")); // real sha-1 for "1\n"
+	istringstream is (string ("4355a46b19d348dc2f57c046f8ef63d4538ebb936000f3c9ee954a27460dd865")); // real sha256 for "1\n"
+  BOOST_CHECK_NO_THROW (is >> d3);
+  BOOST_CHECK (!d3.empty ());
+  BOOST_CHECK (d3 == d1);
+  BOOST_CHECK (d3 != d2);
+
+  istringstream is2 (string ("25fa44f2b31c1fb553b6021e7360d07d5d91ff5e")); // some fake hash
+  BOOST_CHECK_THROW (is2 >> d3, DigestCalculationError); // >> can be used only once
+
+  Digest d4;
+  BOOST_CHECK_THROW (is2 >> d4, DigestCalculationError); // is2 is now empty. empty >> is not allowed
+
+  istringstream is3 (string ("25fa44f2b31c1fb553b6021e7360d07d5d91ff5e")); // some fake hash
+  BOOST_CHECK_NO_THROW (is3 >> d4);
+  
+  BOOST_CHECK (d4 != d1);
+  BOOST_CHECK (d4 != d2);
+  BOOST_CHECK (d4 != d3);
+}
+
+BOOST_AUTO_TEST_SUITE_END()
diff --git a/nsync/tests/test_interest_table.cc b/nsync/tests/test_interest_table.cc
new file mode 100644
index 0000000..9f31551
--- /dev/null
+++ b/nsync/tests/test_interest_table.cc
@@ -0,0 +1,46 @@
+/* -*- Mode: C++; c-file-style: "gnu"; indent-tabs-mode:nil -*- */
+/*
+ * Copyright (c) 2012 University of California, Los Angeles
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation;
+ *
+ * This program 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 a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ *
+ * Author: Zhenkai Zhu <zhenkai@cs.ucla.edu>
+ *         Chaoyi Bian <bcy@pku.edu.cn>
+ *	   Alexander Afanasyev <alexander.afanasyev@ucla.edu>
+ */
+
+#include <boost/test/unit_test.hpp>
+#include <boost/test/output_test_stream.hpp> 
+#include <map>
+using boost::test_tools::output_test_stream;
+
+#include <boost/make_shared.hpp>
+
+#include "sync-interest-table.h"
+
+using namespace Sync;
+using namespace std;
+using namespace boost;
+
+BOOST_AUTO_TEST_CASE (InterestTableTest)
+{
+  // Alex: test is broken due to changes in SyncInterestTable
+  cerr << "InterestTableTest is broken" << endl;
+  
+  // SyncInterestTable *table = 0;
+  // BOOST_CHECK_NO_THROW (table = new SyncInterestTable ());
+
+  // BOOST_CHECK_NO_THROW (delete table);
+}
+
diff --git a/nsync/tests/test_leaf.cc b/nsync/tests/test_leaf.cc
new file mode 100644
index 0000000..49afcc5
--- /dev/null
+++ b/nsync/tests/test_leaf.cc
@@ -0,0 +1,108 @@
+/* -*- Mode: C++; c-file-style: "gnu"; indent-tabs-mode:nil -*- */
+/*
+ * Copyright (c) 2012 University of California, Los Angeles
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation;
+ *
+ * This program 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 a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ *
+ * Author: Zhenkai Zhu <zhenkai@cs.ucla.edu>
+ *         Chaoyi Bian <bcy@pku.edu.cn>
+ *	   Alexander Afanasyev <alexander.afanasyev@ucla.edu>
+ */
+
+#include <boost/test/unit_test.hpp>
+#include <boost/test/output_test_stream.hpp> 
+using boost::test_tools::output_test_stream;
+
+#include <boost/make_shared.hpp>
+
+#include "sync-full-leaf.h"
+#include "sync-diff-leaf.h"
+#include "sync-std-name-info.h"
+
+using namespace Sync;
+using namespace std;
+using namespace boost;
+
+BOOST_AUTO_TEST_SUITE(LeafTests)
+
+BOOST_AUTO_TEST_CASE (LeafBase)
+{
+  NameInfoConstPtr name = StdNameInfo::FindOrCreate ("/test/name");
+  BOOST_CHECK (name != 0);
+
+  // find the same name
+  BOOST_CHECK (name.get () == StdNameInfo::FindOrCreate ("/test/name").get ());
+  BOOST_CHECK_EQUAL (name.use_count (), 1);
+
+  BOOST_CHECK_NO_THROW (DiffLeaf x (name, SeqNo (12)));
+  BOOST_CHECK_EQUAL (name.use_count (), 1);
+  
+  BOOST_CHECK_NO_THROW (DiffLeaf x (name));
+  BOOST_CHECK_EQUAL (name.use_count (), 1);
+
+  DiffLeaf updateLeaf (name, SeqNo (12));
+  BOOST_CHECK_EQUAL (name.use_count (), 2);
+
+  DiffLeaf removeLeaf (name);
+  BOOST_CHECK_EQUAL (name.use_count (), 3);
+
+  BOOST_CHECK_EQUAL (updateLeaf.getOperation (), UPDATE);
+  BOOST_CHECK_EQUAL (updateLeaf.getSeq ().getSession (), 0);
+  BOOST_CHECK_EQUAL (updateLeaf.getSeq ().getSeq (), 12);
+  
+  BOOST_CHECK_EQUAL (removeLeaf.getOperation (), REMOVE);
+  BOOST_CHECK_EQUAL (removeLeaf.getSeq ().getSession (), 0);
+  BOOST_CHECK_EQUAL (removeLeaf.getSeq ().getSeq (), 0);
+  
+  BOOST_REQUIRE_NO_THROW (FullLeaf x (name, SeqNo (12)));
+  FullLeaf fullLeaf (name, SeqNo (12));
+  BOOST_CHECK_EQUAL (name.use_count (), 4);
+}
+
+BOOST_AUTO_TEST_CASE (LeafDigest)
+{
+  BOOST_CHECK_EQUAL (StdNameInfo::FindOrCreate ("/test/name").use_count (), 1);
+  NameInfoConstPtr name = StdNameInfo::FindOrCreate ("/test/name");
+  FullLeaf fullLeaf (name, SeqNo (12));
+
+  // fullLeafDigest = hash ( hash(name), hash (session, seqNo) )
+  
+  // Digest manualDigest;
+
+  // Digest manualNameDigest;
+  // manualNameDigest << "/test/name";
+  // manualNameDigest.finalize ();
+
+  // Digest manualSeqNoDigest;
+  // manualSeqNoDigest << 0 << 13;
+  // manualSeqNoDigest.finalize ();
+
+  // manualDigest << manualNameDigest << manualSeqNoDigest;
+  // manualDigest.finalize ();
+
+  // cout << manualDigest << "\n\n";
+
+  output_test_stream output;
+  output << fullLeaf.getDigest ();
+  // BOOST_CHECK (output.is_equal ("991f8cf6262dfe0f519c63f6e9b92fe69e741a9b", true)); // for sha1
+	BOOST_CHECK (output.is_equal ("526d63e6e1f05f97502fd500a1729c4907f3841483ae4561b7e6307c40188f35", true)); // for sha256
+
+  fullLeaf.setSeq (SeqNo (13));
+  output << fullLeaf.getDigest ();
+  BOOST_CHECK (!output.is_equal ("991f8cf6262dfe0f519c63f6e9b92fe69e741a9b", false));
+  // BOOST_CHECK (output.is_equal ("585a8687ab41d5c29f86e5906c8f188ddca816b3", true)); // for sha1
+	BOOST_CHECK (output.is_equal ("39fefe65b3e1021776c07d3a9a3023c6c7cdf12724ee7f3a98b813b22f46d5ec", true)); // for sha256
+}
+
+BOOST_AUTO_TEST_SUITE_END()
diff --git a/nsync/tests/test_pit.cc b/nsync/tests/test_pit.cc
new file mode 100644
index 0000000..5e48180
--- /dev/null
+++ b/nsync/tests/test_pit.cc
@@ -0,0 +1,77 @@
+/* -*- Mode: C++; c-file-style: "gnu"; indent-tabs-mode:nil -*- */
+/*
+ * Copyright (c) 2012 University of California, Los Angeles
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation;
+ *
+ * This program 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 a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ *
+ * Author: Zhenkai Zhu <zhenkai@cs.ucla.edu>
+ *         Chaoyi Bian <bcy@pku.edu.cn>
+ *	   Alexander Afanasyev <alexander.afanasyev@ucla.edu>
+ */
+
+#include <boost/test/unit_test.hpp>
+#include <boost/test/output_test_stream.hpp> 
+using boost::test_tools::output_test_stream;
+#include <vector>
+
+#include <boost/make_shared.hpp>
+
+#include "sync-interest-table.h"
+#include "sync-logging.h"
+
+using namespace Sync;
+using namespace std;
+using namespace boost;
+
+// string sitToString(SyncInterestTable *sit) {
+//   vector<string> ent = sit->fetchAll();
+//   sort(ent.begin(), ent.end());
+//   string str = "";
+//   while(!ent.empty()){
+//     str += ent.back();
+//     ent.pop_back();
+//   }
+//   return str;
+// }
+
+BOOST_AUTO_TEST_CASE (SyncInterestTableTest)
+{
+  cerr << "SyncInterestTableTest is broken" << endl;
+  
+  // INIT_LOGGERS ();
+  // INIT_LOGGER ("Test.Pit");
+
+  // SyncInterestTable sit;
+  // sit.insert("/ucla.edu/0");
+  // sit.insert("/ucla.edu/1");
+  // string str = sitToString(&sit);
+  // BOOST_CHECK_EQUAL(str, "/ucla.edu/1/ucla.edu/0");
+
+  // str = sitToString(&sit);
+  // BOOST_CHECK_EQUAL(str, "");
+
+  // _LOG_DEBUG ("Adding 0 and 1");
+  // sit.insert("/ucla.edu/0");
+  // sit.insert("/ucla.edu/1");
+  // sleep(2);
+  // _LOG_DEBUG ("Adding 0 and 2");
+  // sit.insert("/ucla.edu/0");
+  // sit.insert("/ucla.edu/2");
+  // sleep(3);
+  // _LOG_DEBUG ("Checking");
+  // str = sitToString(&sit);
+  // BOOST_CHECK_EQUAL(str, "/ucla.edu/2/ucla.edu/0");
+}
+
+
diff --git a/nsync/tests/test_scheduler.cc.tmp b/nsync/tests/test_scheduler.cc.tmp
new file mode 100644
index 0000000..0d67417
--- /dev/null
+++ b/nsync/tests/test_scheduler.cc.tmp
@@ -0,0 +1,178 @@
+/* -*- Mode: C++; c-file-style: "gnu"; indent-tabs-mode:nil -*- */
+/*
+ * Copyright (c) 2012 University of California, Los Angeles
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation;
+ *
+ * This program 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 a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ *
+ * Author: Zhenkai Zhu <zhenkai@cs.ucla.edu>
+ *         Chaoyi Bian <bcy@pku.edu.cn>
+ *	   Alexander Afanasyev <alexander.afanasyev@ucla.edu>
+ */
+
+#include <boost/test/unit_test.hpp>
+#include <boost/test/output_test_stream.hpp> 
+#include <map>
+using boost::test_tools::output_test_stream;
+
+#include <boost/make_shared.hpp>
+#include "sync-scheduler.h"
+#include "sync-logic.h"
+
+using namespace Sync;
+using namespace std;
+using namespace boost;
+
+
+
+// void funcUpdate (const std::string &, const SeqNo &newSeq, const SeqNo &oldSeq)
+// {
+//   cout << "funcUpdate\n";
+// }
+
+// void funcRemove (const std::string &)
+// {
+//   cout << "funcRemove\n";
+// }
+
+enum SCHEDULE_LABELS
+  {
+    TEST_LABEL,
+    ANOTHER_LABEL
+  };
+
+struct SchedulerFixture
+{
+  SchedulerFixture ()
+    : counter (0)
+  {}
+
+  int counter;
+  
+  Scheduler *scheduler;
+
+  void everySecond ()
+  {
+    // cout << "." << flush;
+    counter ++;
+
+    if (counter < 9)
+    scheduler->schedule (boost::posix_time::milliseconds (100),
+                         boost::bind (&SchedulerFixture::everySecond, this),
+                         TEST_LABEL);
+  }
+
+  void setCounterFive ()
+  {
+    counter = 5;
+  }
+
+  void setCounterThree ()
+  {
+    counter = 3;
+  }
+};
+
+
+#ifdef _DEBUG
+
+BOOST_FIXTURE_TEST_SUITE (SchedulerTestSuite, SchedulerFixture)
+
+BOOST_AUTO_TEST_CASE (BasicTest)
+{
+  BOOST_CHECK_NO_THROW (scheduler = new Scheduler ());
+
+  scheduler->schedule (posix_time::milliseconds (100),
+                       bind (&SchedulerFixture::everySecond, this),
+                       TEST_LABEL);
+
+  sleep (1);
+  // cout << counter << endl;
+  BOOST_CHECK_EQUAL (counter, 9); // generally, should be 9
+
+  scheduler->schedule (posix_time::seconds (2),
+		       bind (&SchedulerFixture::setCounterFive, this),
+                       TEST_LABEL);
+
+  this_thread::sleep (posix_time::milliseconds (400)); // just in case
+
+  scheduler->schedule (posix_time::milliseconds (600),
+		       bind (&SchedulerFixture::setCounterThree, this),
+                       TEST_LABEL);
+
+  this_thread::sleep (posix_time::milliseconds (500));
+  BOOST_CHECK_EQUAL (counter, 9); // still 9
+  
+  this_thread::sleep (posix_time::milliseconds (200));
+  BOOST_CHECK_EQUAL (counter, 3);
+
+  this_thread::sleep (posix_time::milliseconds (1000));
+  BOOST_CHECK_EQUAL (counter, 5);
+
+  scheduler->schedule (posix_time::milliseconds (100),
+		       bind (&SchedulerFixture::setCounterThree, this),
+                       ANOTHER_LABEL);
+  this_thread::sleep (posix_time::milliseconds (50));
+  scheduler->cancel (ANOTHER_LABEL);
+  this_thread::sleep (posix_time::milliseconds (150));
+  BOOST_CHECK_EQUAL (counter, 5);
+  
+  BOOST_CHECK_NO_THROW (delete scheduler);
+}
+
+BOOST_AUTO_TEST_SUITE_END ()
+
+
+void funcUpdate( const std::string &/*prefix*/, const SeqNo &/*newSeq*/, const SeqNo &/*oldSeq*/ )
+{
+}
+
+void funcPass( const std::vector<MissingDataInfo> &v)
+{
+}
+
+void funcRemove( const std::string &/*prefix*/ )
+{
+}
+
+BOOST_AUTO_TEST_CASE (SyncLogicSchedulerTest)
+{  
+  SyncLogic *logic = 0;
+  BOOST_CHECK_NO_THROW (logic = new SyncLogic ("/prefix", funcPass, funcRemove));
+  this_thread::sleep (posix_time::milliseconds (100));
+
+  Scheduler &scheduler = logic->getScheduler ();
+  BOOST_CHECK_EQUAL (scheduler.getEventsSize (), 1);
+
+  BOOST_CHECK_NO_THROW (logic->respondSyncInterest ("/prefix/e5fa44f2b31c1fb553b6021e7360d07d5d91ff5e")); 
+  BOOST_CHECK_EQUAL (scheduler.getEventsSize (), 2);
+
+  this_thread::sleep (posix_time::milliseconds (100)); // max waiting time
+  BOOST_CHECK_EQUAL (scheduler.getEventsSize (), 1);
+
+  BOOST_CHECK_NO_THROW (logic->respondSyncInterest ("/prefix/e5fa44f2b31c1fb553b6021e7360d07d5d91ff5e")); 
+  BOOST_CHECK_NO_THROW (logic->respondSyncInterest ("/prefix/e5fa44f2b31c1fb553b6021e7360d07d5d91ff5e")); 
+  BOOST_CHECK_NO_THROW (logic->respondSyncInterest ("/prefix/e5fa44f2b31c1fb553b6021e7360d07d5d91ff5e")); 
+  BOOST_CHECK_NO_THROW (logic->respondSyncInterest ("/prefix/e5fa44f2b31c1fb553b6021e7360d07d5d91ff5e"));
+  BOOST_CHECK_EQUAL (scheduler.getEventsSize (), 5);  
+
+  this_thread::sleep (posix_time::milliseconds (19)); // min waiting time is 20
+  BOOST_CHECK_EQUAL (scheduler.getEventsSize (), 5);  
+
+  this_thread::sleep (posix_time::milliseconds (100)); // max waiting time
+  BOOST_CHECK_EQUAL (scheduler.getEventsSize (), 1);
+  
+  BOOST_CHECK_NO_THROW (delete logic);
+}
+
+#endif
diff --git a/nsync/tests/test_socket.cc b/nsync/tests/test_socket.cc
new file mode 100644
index 0000000..60a87f3
--- /dev/null
+++ b/nsync/tests/test_socket.cc
@@ -0,0 +1,399 @@
+/* -*- Mode: C++; c-file-style: "gnu"; indent-tabs-mode:nil -*- */
+/*
+ * Copyright (c) 2012 University of California, Los Angeles
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation;
+ *
+ * This program 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 a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ *
+ * Author: Zhenkai Zhu <zhenkai@cs.ucla.edu>
+ *         Chaoyi Bian <bcy@pku.edu.cn>
+ *	   Alexander Afanasyev <alexander.afanasyev@ucla.edu>
+ */
+
+#include <boost/test/unit_test.hpp>
+#include <boost/test/output_test_stream.hpp> 
+using boost::test_tools::output_test_stream;
+
+#include <boost/make_shared.hpp>
+#include <boost/date_time/posix_time/posix_time.hpp>
+
+#include "sync-logging.h"
+#include "sync-socket.h"
+#include <ndn-cpp-dev/security/validator-null.hpp>
+
+extern "C" {
+#include <unistd.h>
+}
+
+using namespace Sync;
+using namespace std;
+using namespace boost;
+
+INIT_LOGGER ("Test.AppSocket");
+
+#define PRINT 
+//std::cout << "Line: " << __LINE__ << std::endl;
+
+class TestSocketApp {
+public:
+  TestSocketApp()
+    : sum(0)
+  {}
+
+  map<ndn::Name, string> data;
+  void set(const ndn::shared_ptr<const ndn::Data>& dataPacket) {
+    // _LOG_FUNCTION (this << ", " << str1);
+    ndn::Name dataName(dataPacket->getName());
+    string str2(reinterpret_cast<const char*>(dataPacket->getContent().value()), dataPacket->getContent().value_size());
+    data.insert(make_pair(dataName, str2));
+    // cout << str1 << ", " << str2 << endl;
+  }
+
+  void set(ndn::Name name, const char * buf, int len) {
+    string str2(buf, len);
+    data.insert(make_pair(name, str2));
+  }
+  
+  void setNum(const ndn::shared_ptr<const ndn::Data>& dataPacket) {
+    int n = dataPacket->getContent().value_size() / 4;
+    uint32_t *numbers = new uint32_t [n];
+    memcpy(numbers, dataPacket->getContent().value(), dataPacket->getContent().value_size());
+    for (int i = 0; i < n; i++) {
+      sum += numbers[i];
+    }
+    delete numbers;
+
+  }
+
+  void setNum(ndn::Name name, const char * buf, int len) {
+    int n = len / 4;
+    int *numbers = new int [n];
+    memcpy(numbers, buf, len);
+    for (int i = 0; i < n; i++) {
+      sum += numbers[i];
+    }
+    delete numbers;
+  }
+
+  uint32_t sum;
+
+  void fetchAll(const vector<MissingDataInfo> &v, SyncSocket *socket) {
+    int n = v.size();
+
+    PRINT
+
+    for (int i = 0; i < n; i++) {
+      for(SeqNo s = v[i].low; s <= v[i].high; ++s) {
+        //PRINT
+        socket->fetchData(v[i].prefix, s, bind(&TestSocketApp::set, this, _1));
+      }
+    }
+  }
+
+  void fetchNumbers(const vector<MissingDataInfo> &v, SyncSocket *socket) {
+    int n = v.size();
+
+    PRINT
+
+    // std::cout << "In fetchNumbers. size of v is:  " << n << std::endl;
+    for (int i = 0; i < n; i++) {
+      // std::cout << "In fetchNumbers. v[i].low is (" <<v[i].low.getSession() <<", " << v[i].low.getSeq() << ") v[i].high is ("<<v[i].high.getSession() <<", " <<v[i].high.getSeq()<<")" << std::endl;
+      for(SeqNo s = v[i].low; s <= v[i].high; ++s) {
+        PRINT
+        socket->fetchData(v[i].prefix, s, bind(&TestSocketApp::setNum, this, _1));
+      }
+    }
+  }
+
+  void pass(const string &prefix) {
+  }
+
+  string toString(){
+    map<ndn::Name, string>::iterator it = data.begin(); 
+    string str = "\n";
+    for (; it != data.end(); ++it){
+      str += "<";
+      str += it->first.toUri();
+      str += "|";
+      str += it->second;
+      str += ">";
+      str += "\n";
+    }
+
+    return str;
+  }
+
+};
+
+class TestSet1{
+public:
+  TestSet1(ndn::shared_ptr<boost::asio::io_service> ioService)
+    : m_validator(new ndn::ValidatorNull())
+    , m_face1(new ndn::Face(ioService))
+    , m_face2(new ndn::Face(ioService))
+    , m_face3(new ndn::Face(ioService))
+    , m_p1("/irl.cs.ucla.edu")
+    , m_p2("/yakshi.org")
+    , m_p3("/google.com")
+    , m_syncPrefix("/let/us/sync")
+  {}
+
+  void
+  createSyncSocket1()
+  {
+    _LOG_DEBUG ("s1");
+    m_s1 = make_shared<SyncSocket>(m_syncPrefix, m_validator, m_face1, 
+                                   bind(&TestSocketApp::fetchAll, &m_a1, _1, _2), 
+                                   bind(&TestSocketApp::pass, &m_a1, _1));
+  }
+
+  void
+  createSyncSocket2()
+  {
+    _LOG_DEBUG ("s2");
+    m_s2 = make_shared<SyncSocket>(m_syncPrefix, m_validator, m_face2, 
+                                   bind(&TestSocketApp::fetchAll, &m_a2, _1, _2), 
+                                   bind(&TestSocketApp::pass, &m_a2, _1));
+  }
+  
+  void
+  createSyncSocket3()
+  {
+    _LOG_DEBUG ("s3");
+    m_s3 = make_shared<SyncSocket>(m_syncPrefix, m_validator, m_face3, 
+                                   bind(&TestSocketApp::fetchAll, &m_a3, _1, _2), 
+                                   bind(&TestSocketApp::pass, &m_a3, _1));
+  }
+
+  void
+  publishSocket1(uint32_t session, string data)
+  {
+    _LOG_DEBUG ("s1 publish");
+    m_s1->publishData (m_p1, session, data.c_str(), data.size(), 1000); 
+  }
+
+  void
+  publishSocket2(uint32_t session, string data)
+  {
+    _LOG_DEBUG ("s2 publish");
+    m_s2->publishData (m_p2, session, data.c_str(), data.size(), 1000); 
+  }
+
+  void
+  publishSocket3(uint32_t session, string data)
+  {
+    _LOG_DEBUG ("s3 publish");
+    m_s3->publishData (m_p3, session, data.c_str(), data.size(), 1000); 
+  }
+
+  void
+  setSocket1(string suffix, string data)
+  {
+    _LOG_DEBUG ("a1 set");
+    ndn::Name name = m_p1;
+    name.append(suffix);
+    m_a1.set (name, data.c_str(), data.size()); 
+  }
+
+  void
+  setSocket2(string suffix, string data)
+  {
+    _LOG_DEBUG ("a2 set");
+    ndn::Name name = m_p2;
+    name.append(suffix);
+    m_a2.set (name, data.c_str(), data.size()); 
+  }
+
+  void
+  setSocket3(string suffix, string data)
+  {
+    _LOG_DEBUG ("a3 set");
+    ndn::Name name = m_p3;
+    name.append(suffix);
+    m_a3.set (name, data.c_str(), data.size()); 
+  }
+
+  void
+  check(int round)
+  { 
+    BOOST_CHECK_EQUAL(m_a1.toString(), m_a2.toString());
+    BOOST_CHECK_EQUAL(m_a2.toString(), m_a3.toString());
+  }
+
+  void
+  done()
+  {
+    m_s1.reset();
+    m_s2.reset();
+    m_s3.reset();
+  }
+
+
+  TestSocketApp m_a1, m_a2, m_a3;
+  ndn::shared_ptr<ndn::ValidatorNull> m_validator;
+  ndn::shared_ptr<ndn::Face> m_face1, m_face2, m_face3;
+  ndn::Name m_p1, m_p2, m_p3;
+  ndn::shared_ptr<SyncSocket> m_s1, m_s2, m_s3;
+  ndn::Name m_syncPrefix;
+};
+
+class TestSet2{
+public:
+  TestSet2(ndn::shared_ptr<boost::asio::io_service> ioService)
+    : m_validator(new ndn::ValidatorNull())
+    , m_face1(new ndn::Face(ioService))
+    , m_face2(new ndn::Face(ioService))
+    , m_p1("/xiaonei.com")
+    , m_p2("/mitbbs.com")
+    , m_syncPrefix("/this/is/the/prefix")
+  {}
+
+  void
+  createSyncSocket1()
+  {
+    _LOG_DEBUG ("s1");
+    m_s1 = make_shared<SyncSocket>(m_syncPrefix, m_validator, m_face1, 
+                                   bind(&TestSocketApp::fetchNumbers, &m_a1, _1, _2), 
+                                   bind(&TestSocketApp::pass, &m_a1, _1));
+  }
+
+  void
+  createSyncSocket2()
+  {
+    _LOG_DEBUG ("s2");
+    m_s2 = make_shared<SyncSocket>(m_syncPrefix, m_validator, m_face2, 
+                                   bind(&TestSocketApp::fetchNumbers, &m_a2, _1, _2), 
+                                   bind(&TestSocketApp::pass, &m_a2, _1));
+  }
+  
+  void
+  publishSocket1(uint32_t session, string data)
+  {
+    _LOG_DEBUG ("s1 publish");
+    m_s1->publishData (m_p1, session, data.c_str(), data.size(), 1000); 
+  }
+
+  void
+  publishSocket2(uint32_t session, string data)
+  {
+    _LOG_DEBUG ("s2 publish");
+    m_s2->publishData (m_p2, session, data.c_str(), data.size(), 1000); 
+  }
+
+  void
+  setSocket1(const char* ptr, size_t size)
+  {
+    _LOG_DEBUG ("a1 setNum");
+    m_a1.setNum (m_p1, ptr, size); 
+  }
+
+  void
+  setSocket2(const char* ptr, size_t size)
+  {
+    _LOG_DEBUG ("a2 setNum");
+    m_a2.setNum (m_p2, ptr, size); 
+  }
+
+  void
+  check(int num)
+  { 
+    _LOG_DEBUG ("codnum " << num);
+    _LOG_DEBUG ("a1 sum " << m_a1.sum);
+    _LOG_DEBUG ("a2 sum " << m_a2.sum);
+
+    BOOST_CHECK(m_a1.sum == m_a2.sum && m_a1.sum == num);
+  }
+
+  void
+  done()
+  {
+    m_s1.reset();
+    m_s2.reset();
+  }
+
+  TestSocketApp m_a1, m_a2;
+  ndn::shared_ptr<ndn::ValidatorNull> m_validator;
+  ndn::shared_ptr<ndn::Face> m_face1, m_face2;
+  ndn::Name m_p1, m_p2;
+  ndn::shared_ptr<SyncSocket> m_s1, m_s2;
+  ndn::Name m_syncPrefix;
+};
+
+BOOST_AUTO_TEST_CASE (AppSocketTest1)
+{
+  INIT_LOGGERS ();
+
+  ndn::shared_ptr<boost::asio::io_service> ioService = ndn::make_shared<boost::asio::io_service>();
+  ndn::Scheduler scheduler(*ioService);
+  TestSet1 testSet1(ioService);
+
+  scheduler.scheduleEvent(ndn::time::seconds(0.00), ndn::bind(&TestSet1::createSyncSocket1, &testSet1));
+  scheduler.scheduleEvent(ndn::time::seconds(0.05), ndn::bind(&TestSet1::createSyncSocket2, &testSet1));
+  scheduler.scheduleEvent(ndn::time::seconds(0.10), ndn::bind(&TestSet1::createSyncSocket3, &testSet1));
+  string data0 = "Very funny Scotty, now beam down my clothes";
+  scheduler.scheduleEvent(ndn::time::seconds(0.15), ndn::bind(&TestSet1::publishSocket1, &testSet1, 0, data0));
+  scheduler.scheduleEvent(ndn::time::seconds(1.15), ndn::bind(&TestSet1::setSocket1, &testSet1, "/0/0", data0));
+  scheduler.scheduleEvent(ndn::time::seconds(1.16), ndn::bind(&TestSet1::check, &testSet1, 1)); 
+  string data1 = "Yes, give me that ketchup";
+  string data2 = "Don't look conspicuous, it draws fire";
+  scheduler.scheduleEvent(ndn::time::seconds(1.17), ndn::bind(&TestSet1::publishSocket1, &testSet1, 0, data1));
+  scheduler.scheduleEvent(ndn::time::seconds(1.18), ndn::bind(&TestSet1::publishSocket1, &testSet1, 0, data2));
+  scheduler.scheduleEvent(ndn::time::seconds(2.15), ndn::bind(&TestSet1::setSocket1, &testSet1, "/0/1", data1));
+  scheduler.scheduleEvent(ndn::time::seconds(2.16), ndn::bind(&TestSet1::setSocket1, &testSet1, "/0/2", data2));
+  scheduler.scheduleEvent(ndn::time::seconds(2.17), ndn::bind(&TestSet1::check, &testSet1, 2));
+  string data3 = "You surf the Internet, I surf the real world";
+  string data4 = "I got a fortune cookie once that said 'You like Chinese food'";
+  string data5 = "Real men wear pink. Why? Because their wives make them";
+  scheduler.scheduleEvent(ndn::time::seconds(3.18), ndn::bind(&TestSet1::publishSocket3, &testSet1, 0, data3));
+  scheduler.scheduleEvent(ndn::time::seconds(3.20), ndn::bind(&TestSet1::publishSocket2, &testSet1, 0, data4));
+  scheduler.scheduleEvent(ndn::time::seconds(3.21), ndn::bind(&TestSet1::publishSocket2, &testSet1, 0, data5));
+  scheduler.scheduleEvent(ndn::time::seconds(4.21), ndn::bind(&TestSet1::setSocket3, &testSet1, "/0/0", data3));
+  scheduler.scheduleEvent(ndn::time::seconds(4.22), ndn::bind(&TestSet1::setSocket2, &testSet1, "/0/0", data4));
+  scheduler.scheduleEvent(ndn::time::seconds(4.23), ndn::bind(&TestSet1::setSocket2, &testSet1, "/0/1", data5));
+  scheduler.scheduleEvent(ndn::time::seconds(4.30), ndn::bind(&TestSet1::check, &testSet1, 3));
+  // not sure weither this is simultanous data generation from multiple sources
+  _LOG_DEBUG ("Simultaneous publishing");
+  string data6 = "Shakespeare says: 'Prose before hos.'";
+  string data7 = "Pick good people, talent never wears out";
+  scheduler.scheduleEvent(ndn::time::seconds(5.50), ndn::bind(&TestSet1::publishSocket1, &testSet1, 0, data6));
+  scheduler.scheduleEvent(ndn::time::seconds(5.50), ndn::bind(&TestSet1::publishSocket2, &testSet1, 0, data7));
+  scheduler.scheduleEvent(ndn::time::seconds(6.80), ndn::bind(&TestSet1::setSocket1, &testSet1, "/0/3", data6));
+  scheduler.scheduleEvent(ndn::time::seconds(6.80), ndn::bind(&TestSet1::setSocket2, &testSet1, "/0/2", data7));
+  scheduler.scheduleEvent(ndn::time::seconds(6.90), ndn::bind(&TestSet1::check, &testSet1, 4));
+  scheduler.scheduleEvent(ndn::time::seconds(7.00), ndn::bind(&TestSet1::done, &testSet1));
+
+  ioService->run();
+}
+
+BOOST_AUTO_TEST_CASE (AppSocketTest2)
+{
+  ndn::shared_ptr<boost::asio::io_service> ioService = ndn::make_shared<boost::asio::io_service>();
+  ndn::Scheduler scheduler(*ioService);
+  TestSet2 testSet2(ioService);
+
+  scheduler.scheduleEvent(ndn::time::seconds(0.00), ndn::bind(&TestSet2::createSyncSocket1, &testSet2));
+  scheduler.scheduleEvent(ndn::time::seconds(0.05), ndn::bind(&TestSet2::createSyncSocket2, &testSet2));
+  uint32_t num[5] = {0, 1, 2, 3, 4};
+  string data0((const char *) num, sizeof(num));
+  scheduler.scheduleEvent(ndn::time::seconds(0.10), ndn::bind(&TestSet2::publishSocket1, &testSet2, 0, data0));
+  scheduler.scheduleEvent(ndn::time::seconds(0.15), ndn::bind(&TestSet2::setSocket1, &testSet2, (const char *) num, sizeof (num)));
+  scheduler.scheduleEvent(ndn::time::seconds(1.00), ndn::bind(&TestSet2::check, &testSet2, 10));
+  uint32_t newNum[5] = {9, 7, 2, 1, 1};
+  string data1((const char *) newNum, sizeof(newNum));
+  scheduler.scheduleEvent(ndn::time::seconds(1.10), ndn::bind(&TestSet2::publishSocket2, &testSet2, 0, data1));
+  scheduler.scheduleEvent(ndn::time::seconds(1.15), ndn::bind(&TestSet2::setSocket2, &testSet2, (const char *) newNum, sizeof (newNum)));
+  scheduler.scheduleEvent(ndn::time::seconds(2.00), ndn::bind(&TestSet2::check, &testSet2, 30));
+  scheduler.scheduleEvent(ndn::time::seconds(7.00), ndn::bind(&TestSet2::done, &testSet2));
+
+  ioService->run();
+}
diff --git a/nsync/tests/test_state.cc.outdated b/nsync/tests/test_state.cc.outdated
new file mode 100644
index 0000000..35fc79c
--- /dev/null
+++ b/nsync/tests/test_state.cc.outdated
@@ -0,0 +1,294 @@
+/* -*- Mode: C++; c-file-style: "gnu"; indent-tabs-mode:nil -*- */
+/*
+ * Copyright (c) 2012 University of California, Los Angeles
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation;
+ *
+ * This program 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 a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ *
+ * Author: Zhenkai Zhu <zhenkai@cs.ucla.edu>
+ *         Chaoyi Bian <bcy@pku.edu.cn>
+ *	   Alexander Afanasyev <alexander.afanasyev@ucla.edu>
+ */
+
+#define BOOST_TEST_DYN_LINK 1
+#define BOOST_TEST_NO_MAIN 1
+// #define BOOST_TEST_MODULE StateTests
+#include <boost/test/unit_test.hpp>
+#include <boost/test/output_test_stream.hpp> 
+using boost::test_tools::output_test_stream;
+
+#include <boost/make_shared.hpp>
+#include <boost/date_time/posix_time/posix_time.hpp>
+
+#include "sync-std-name-info.h"
+#include "sync-full-state.h"
+#include "sync-diff-state.h"
+
+using namespace Sync;
+using namespace std;
+using namespace boost;
+
+BOOST_AUTO_TEST_SUITE(StateTests)
+
+BOOST_AUTO_TEST_CASE (FullStateTest)
+{
+  BOOST_CHECK_NO_THROW (FullState ());
+  FullState state;
+  BOOST_CHECK_EQUAL (state.getLeaves ().size (), 0);
+
+  output_test_stream output;
+  output << state.getTimeFromLastUpdate ();
+  BOOST_CHECK (output.is_equal ("not-a-date-time", true));
+
+  NameInfoConstPtr name = StdNameInfo::FindOrCreate ("/test/name");
+  BOOST_CHECK_NO_THROW (state.update (name, SeqNo (12)));
+  BOOST_CHECK_NO_THROW (state.update (name, SeqNo (12)));
+  BOOST_CHECK_NO_THROW (state.update (name, SeqNo (12)));
+  BOOST_CHECK_EQUAL (state.getLeaves ().size (), 1);
+  BOOST_CHECK_EQUAL ((*state.getLeaves ().begin ())->getSeq ().getSeq (), 12);
+
+  BOOST_CHECK_NO_THROW (state.update (name, SeqNo (13)));
+  BOOST_CHECK_EQUAL ((*state.getLeaves ().begin ())->getSeq ().getSeq (), 13);
+
+  BOOST_CHECK_NO_THROW (state.remove (name));
+  BOOST_CHECK_EQUAL (state.getLeaves ().size (), 0);
+
+  BOOST_CHECK_EQUAL (state.getTimeFromLastUpdate ().total_milliseconds (), 0);
+}
+
+BOOST_AUTO_TEST_CASE (DiffStateTest)
+{
+  BOOST_CHECK_NO_THROW (DiffState ());
+  DiffState state;
+  BOOST_CHECK_EQUAL (state.getLeaves ().size (), 0);
+
+  NameInfoConstPtr name = StdNameInfo::FindOrCreate ("/test/name");
+  BOOST_CHECK_NO_THROW (state.update (name, SeqNo (12)));
+  BOOST_CHECK_NO_THROW (state.update (name, SeqNo (12)));
+  BOOST_CHECK_NO_THROW (state.update (name, SeqNo (12)));
+  BOOST_CHECK_EQUAL (state.getLeaves ().size (), 1);
+  BOOST_CHECK_EQUAL ((*state.getLeaves ().begin ())->getSeq ().getSeq (), 12);
+
+  BOOST_CHECK_NO_THROW (state.update (name, SeqNo (13)));
+  BOOST_CHECK_EQUAL ((*state.getLeaves ().begin ())->getSeq ().getSeq (), 13);
+
+  BOOST_CHECK_NO_THROW (state.remove (name));
+  BOOST_CHECK_EQUAL (state.getLeaves ().size (), 1);
+  BOOST_CHECK_EQUAL ((*state.getLeaves ().begin ())->getSeq ().getSeq (), 0);
+}
+
+BOOST_AUTO_TEST_CASE (FullStateDigestTest)
+{
+  FullState state;
+  BOOST_CHECK_EQUAL (state.getLeaves ().size (), 0);
+
+  NameInfoConstPtr name3 = StdNameInfo::FindOrCreate ("3");
+  NameInfoConstPtr name2 = StdNameInfo::FindOrCreate ("2");
+  NameInfoConstPtr name1 = StdNameInfo::FindOrCreate ("1");
+
+  state.update (name1, SeqNo (10));
+  DigestConstPtr digest1 = state.getDigest ();
+
+  state.update (name2, SeqNo (12));
+  DigestConstPtr digest2 = state.getDigest ();
+
+  BOOST_CHECK (digest1.get () != digest2.get ());
+  BOOST_CHECK (!digest1->empty ());
+  BOOST_CHECK (!digest2->empty ());
+
+  state.update (name3, SeqNo (8));
+  DigestConstPtr digest3 = state.getDigest ();
+
+  BOOST_CHECK (digest1.get () != digest2.get ());
+  BOOST_CHECK (digest2.get () != digest3.get ());
+  BOOST_CHECK (digest1.get () != digest3.get ());
+
+  BOOST_CHECK (*digest1 != *digest2);
+  BOOST_CHECK (*digest2 != *digest3);
+  BOOST_CHECK (*digest1 != *digest3);
+
+  // removing elements. Digest should get reverted to digest1
+  state.remove (name2);
+  state.remove (name3);
+  DigestConstPtr digest4 = state.getDigest ();
+  BOOST_CHECK (*digest1 == *digest4);
+
+  name2.reset (); // force destructor
+  name3.reset (); // force destructor
+  name3 = StdNameInfo::FindOrCreate ("3"); // this will enforce different (larger) hashing ID of name
+  name2 = StdNameInfo::FindOrCreate ("2"); // this will enforce different (larger) hashing ID of name
+  
+  // adding in different order
+  state.update (name3, SeqNo (8));
+  state.update (name2, SeqNo (12));
+  DigestConstPtr digest5 = state.getDigest ();
+  BOOST_CHECK (*digest5 == *digest3);
+}
+
+BOOST_AUTO_TEST_CASE (FullStateXml)
+{
+  FullState state;
+
+  NameInfoConstPtr name3 = StdNameInfo::FindOrCreate ("3");
+  NameInfoConstPtr name2 = StdNameInfo::FindOrCreate ("2");
+  NameInfoConstPtr name1 = StdNameInfo::FindOrCreate ("1");
+
+  state.update (name1, SeqNo (10));
+  state.update (name2, SeqNo (12));
+  state.update (name3, SeqNo (8));  
+
+  string xml1 = "<state>"
+    "<item><name>1</name><seq><session>0</session><seqno>10</seqno></seq></item>"
+    "<item><name>2</name><seq><session>0</session><seqno>12</seqno></seq></item>"
+    "<item><name>3</name><seq><session>0</session><seqno>8</seqno></seq></item>"
+    "</state>";
+  {
+  ostringstream os;
+  os << state;
+  string s = os.str ();
+  // cout << s << endl; 
+  erase_all (s, "\n");
+  BOOST_CHECK_EQUAL (s, xml1);
+  }
+  
+  state.remove (name2);
+  string xml2 = "<state>"
+    "<item><name>1</name><seq><session>0</session><seqno>10</seqno></seq></item>"
+    "<item><name>3</name><seq><session>0</session><seqno>8</seqno></seq></item>"
+    "</state>";
+  {
+  ostringstream os;
+  os << state;
+  string s = os.str ();
+  erase_all (s, "\n");
+  BOOST_CHECK_EQUAL (s, xml2);
+  }
+
+  FullState state2;
+  istringstream xml1_is (xml1);
+  BOOST_CHECK_NO_THROW (xml1_is >> state2);
+  {
+  ostringstream os;
+  os << state2;
+  string xml1_test = os.str ();
+  erase_all (xml1_test, "\n");
+  BOOST_CHECK_EQUAL (xml1_test, xml1);
+  }
+  
+  istringstream xml2_is ("<state><item action=\"remove\"><name>2</name></item></state>");
+  BOOST_CHECK_NO_THROW (xml2_is >> state2);
+  
+  {
+  ostringstream os;
+  os << state2;
+  string xml2_test = os.str ();
+  erase_all (xml2_test, "\n");
+  BOOST_CHECK_EQUAL (xml2_test, xml2);
+  }
+}
+
+BOOST_AUTO_TEST_CASE (DiffStateXml)
+{
+  DiffState state;
+
+  NameInfoConstPtr name3 = StdNameInfo::FindOrCreate ("3");
+  NameInfoConstPtr name2 = StdNameInfo::FindOrCreate ("2");
+  NameInfoConstPtr name1 = StdNameInfo::FindOrCreate ("1");
+
+  state.update (name1, SeqNo (10));
+  state.update (name2, SeqNo (12));
+  state.update (name3, SeqNo (8));  
+
+  string xml1 = "<state>"
+    "<item action=\"update\"><name>1</name><seq><session>0</session><seqno>10</seqno></seq></item>"
+    "<item action=\"update\"><name>2</name><seq><session>0</session><seqno>12</seqno></seq></item>"
+    "<item action=\"update\"><name>3</name><seq><session>0</session><seqno>8</seqno></seq></item>"
+    "</state>";
+  {
+  ostringstream os;
+  os << state;
+  string xml1_test = os.str ();
+  erase_all (xml1_test, "\n");
+  BOOST_CHECK_EQUAL (xml1_test, xml1);
+  }
+  
+  state.remove (name2);
+  string xml2 = "<state>"
+    "<item action=\"update\"><name>1</name><seq><session>0</session><seqno>10</seqno></seq></item>"
+    "<item action=\"remove\"><name>2</name></item>"
+    "<item action=\"update\"><name>3</name><seq><session>0</session><seqno>8</seqno></seq></item>"
+    "</state>";
+  {
+  ostringstream os;
+  os << state;
+  string xml2_test = os.str ();
+  erase_all (xml2_test, "\n");
+  BOOST_CHECK_EQUAL (xml2_test, xml2);
+  }
+
+  ////////////  ////////////  ////////////  ////////////  ////////////  ////////////
+  
+  DiffState state2;
+  istringstream xml1_is (xml1);
+  BOOST_CHECK_NO_THROW (xml1_is >> state2);
+  
+  {
+  ostringstream os;
+  os << state2;
+  string xml1_test = os.str ();
+  erase_all (xml1_test, "\n");
+  BOOST_CHECK_EQUAL (xml1_test, xml1);
+  }
+
+  istringstream xml2_is ("<state><item action=\"remove\"><name>2</name></item></state>");
+  BOOST_CHECK_NO_THROW (xml2_is >> state2);
+  
+  {
+  ostringstream os;
+  os << state2;
+  string xml2_test = os.str ();
+  erase_all (xml2_test, "\n");
+  BOOST_CHECK_EQUAL (xml2_test, xml2);
+  }
+
+}
+
+BOOST_AUTO_TEST_CASE (DiffStateDiffTest)
+{
+  DiffStatePtr root = make_shared<DiffState> ();
+
+  DiffStatePtr head = make_shared<DiffState> ();
+  root->setNext (head);
+  
+  head->update (StdNameInfo::FindOrCreate ("3"), SeqNo (1));
+  head->remove (StdNameInfo::FindOrCreate ("1"));
+  
+  DiffStatePtr tail = make_shared<DiffState> ();
+  head->setNext (tail);
+
+  tail->update (StdNameInfo::FindOrCreate ("3"), SeqNo (2));  
+
+  {
+  ostringstream os;
+  os << *root->diff ();
+  string diffState = os.str ();
+  erase_all (diffState, "\n");
+  BOOST_CHECK_EQUAL (diffState,
+                     "<state>"
+                     "<item action=\"remove\"><name>1</name></item>"
+                     "<item action=\"update\"><name>3</name><seq><session>0</session><seqno>2</seqno></seq></item>"
+                     "</state>");
+  }
+}
+
+BOOST_AUTO_TEST_SUITE_END()
diff --git a/nsync/tests/test_sync_logic.cc b/nsync/tests/test_sync_logic.cc
new file mode 100644
index 0000000..d2444e7
--- /dev/null
+++ b/nsync/tests/test_sync_logic.cc
@@ -0,0 +1,179 @@
+/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil -*- */
+/*
+ * Copyright (c) 2012 University of California, Los Angeles
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation;
+ *
+ * This program 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 a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ *
+ * Author: Zhenkai Zhu <zhenkai@cs.ucla.edu>
+ *         Chaoyi Bian <bcy@pku.edu.cn>
+ *	   Alexander Afanasyev <alexander.afanasyev@ucla.edu>
+ */
+
+#include <boost/test/unit_test.hpp>
+#include <boost/test/output_test_stream.hpp> 
+#include <map>
+using boost::test_tools::output_test_stream;
+
+#include <boost/make_shared.hpp>
+
+#include <ndn-cpp-dev/security/validator-null.hpp>
+#include "sync-logic.h"
+#include "sync-seq-no.h"
+
+using namespace std;
+using namespace boost;
+using namespace Sync;
+
+struct Handler
+{
+  string instance;
+  
+  Handler (const string &_instance)
+  : instance (_instance)
+  {
+  }
+
+  void wrapper (const vector<MissingDataInfo> &v) {
+    int n = v.size();
+    for (int i = 0; i < n; i++) {
+      onUpdate (v[i].prefix, v[i].high, v[i].low);
+    }
+  }
+
+  void onUpdate (const string &p/*prefix*/, const SeqNo &seq/*newSeq*/, const SeqNo &oldSeq/*oldSeq*/)
+  {
+    m_map[p] = seq.getSeq ();
+    
+    // cout << instance << "\t";
+    // if (!oldSeq.isValid ())
+    //   cout << "Inserted: " << p << " (" << seq << ")" << endl;
+    // else
+    //   cout << "Updated: " << p << "  ( " << oldSeq << ".." << seq << ")" << endl;
+  }
+
+  void onRemove (const string &p/*prefix*/)
+  {
+    // cout << instance << "\tRemoved: " << p << endl;
+    m_map.erase (p);
+  }
+
+  map<string, uint32_t> m_map;
+};
+
+class TestCore
+{
+public:
+  TestCore(ndn::shared_ptr<boost::asio::io_service> ioService)
+    : m_ioService(ioService)
+  {
+    m_l[0] = 0;
+    m_l[1] = 0;
+    
+    m_validator = ndn::make_shared<ndn::ValidatorNull>();
+  }
+  
+  ~TestCore()
+  {
+    if(m_l[0] != 0)
+      delete m_l[0];
+
+    if(m_l[1] != 0)
+      delete m_l[1];
+  }
+
+  void
+  finish()
+  {
+  }
+  
+  void
+  createSyncLogic(int index, 
+                  ndn::shared_ptr<Handler> h)
+  { 
+    m_faces[index] = ndn::make_shared<ndn::Face>(m_ioService);
+    m_l[index] = new SyncLogic(ndn::Name("/bcast"), 
+                               m_validator, m_faces[index], 
+                               bind (&Handler::wrapper, &*h, _1), 
+                               bind (&Handler::onRemove, &*h, _1)); 
+  }
+
+  void
+  getOldDigestForOne()
+  {
+    m_oldDigest = m_l[0]->getRootDigest();
+  }
+  
+  void
+  getNewDigestForOne()
+  {
+    m_newDigest = m_l[0]->getRootDigest();
+  }
+
+  void
+  addLocalNamesForOne(ndn::Name name, uint64_t session, uint64_t seq)
+  {
+    m_l[0]->addLocalNames(name, session, seq);
+  }
+
+  void
+  removeForOne(ndn::Name name)
+  {
+    m_l[0]->remove(name);
+  }
+  
+  void
+  checkDigest()
+  {
+    BOOST_CHECK(m_oldDigest != m_newDigest);
+  }
+
+
+public:
+  ndn::shared_ptr<boost::asio::io_service> m_ioService;
+  SyncLogic* m_l[2];
+  ndn::shared_ptr<ndn::Face> m_faces[2];
+  ndn::shared_ptr<ndn::ValidatorNull> m_validator;
+  string m_oldDigest;
+  string m_newDigest;
+};
+
+void
+checkMapSize(ndn::shared_ptr<Handler> h, int size)
+{ BOOST_CHECK_EQUAL (h->m_map.size (), size); }
+
+
+BOOST_AUTO_TEST_CASE (SyncLogicTest)
+{
+  ndn::shared_ptr<boost::asio::io_service> ioService = ndn::make_shared<boost::asio::io_service>();
+  ndn::Scheduler scheduler(*ioService);
+  TestCore testCore(ioService);
+
+  ndn::shared_ptr<Handler> h1 = ndn::make_shared<Handler>("1");
+  ndn::shared_ptr<Handler> h2 = ndn::make_shared<Handler>("2");
+
+  scheduler.scheduleEvent(ndn::time::seconds(0), ndn::bind(&TestCore::createSyncLogic, &testCore, 0, h1));
+  scheduler.scheduleEvent(ndn::time::seconds(0.1), ndn::bind(&TestCore::getOldDigestForOne, &testCore));
+  scheduler.scheduleEvent(ndn::time::seconds(0.2), ndn::bind(&TestCore::addLocalNamesForOne, &testCore, "/one", 1, 2));
+  scheduler.scheduleEvent(ndn::time::seconds(0.3), ndn::bind(&checkMapSize, h1, 0));
+  scheduler.scheduleEvent(ndn::time::seconds(0.4), ndn::bind(&TestCore::createSyncLogic, &testCore, 1, h2));
+  scheduler.scheduleEvent(ndn::time::seconds(0.5), ndn::bind(&checkMapSize, h1, 0));
+  scheduler.scheduleEvent(ndn::time::seconds(0.6), ndn::bind(&checkMapSize, h2, 1));
+  scheduler.scheduleEvent(ndn::time::seconds(0.7), ndn::bind(&TestCore::removeForOne, &testCore, "/one"));
+  scheduler.scheduleEvent(ndn::time::seconds(0.8), ndn::bind(&TestCore::getNewDigestForOne, &testCore));
+  scheduler.scheduleEvent(ndn::time::seconds(0.9), ndn::bind(&TestCore::checkDigest, &testCore));
+  scheduler.scheduleEvent(ndn::time::seconds(1.0), ndn::bind(&TestCore::finish, &testCore));
+  
+  ioService->run();
+
+}