[PATCH 2/3] mds:Interval tree

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



Hi
  This patch part provides unit test cases for interval tree
implementation. It provides usage scenarios and test cases for
 interval tree implemantation.

           Tests include:
           - testing addInterval interface
           - testing removeInterval interfaces
           - testing with various template parameters

     Signed-off-by: Jojy George Varghese <jvarghese@xxxxxxxxxxxxxxxxxx>

thanks,
-Jojy
From b69b11eccbc3d0f9204db0cfc0a51ad7a16bcb0f Mon Sep 17 00:00:00 2001
From: Jojy George Varghese <jvarghese@xxxxxxxxxxxxxxxxxx>
Date: Tue, 11 Oct 2011 23:26:13 -0700
Subject: [PATCH][ 2/3] mds: Unit tests for interval tree
              Provides usage scenarios and test cases for
 interval tree implementation.

	Tests include:
            - testing addInterval interface
            - testing removeInterval interfaces
            - testing with various template parameters

Signed-off-by: Jojy George Varghese <jvarghese@xxxxxxxxxxxxxxxxxx>
---
 src/test/TestIntervalTree.cc |  487 ++++++++++++++++++++++++++++++++++++++++++
 1 files changed, 487 insertions(+), 0 deletions(-)
 create mode 100644 src/test/TestIntervalTree.cc

diff --git a/src/test/TestIntervalTree.cc b/src/test/TestIntervalTree.cc
new file mode 100644
index 0000000..d6d113b
--- /dev/null
+++ b/src/test/TestIntervalTree.cc
@@ -0,0 +1,487 @@
+// -*-#define dbg(lvl)\ mode:C++; tab-width:8; c-basic-offset:2; indent-tabs-mode:t -*- 
+// vim: ts=8 sw=2 smarttab
+
+#include <cstdio>
+#include <iostream>
+
+#include "mds/IntervalTree.h"
+
+
+#define ARRAY_SIZE(a)\
+	sizeof(a)/sizeof(a[0])
+
+using namespace std;
+
+struct String {
+  String(const string& s):str(s)
+  {
+  }
+
+  bool operator <(const String& rhs) const
+  {
+    return str < rhs.str;
+  }
+
+  bool operator ==(const String& rhs) const
+  {
+    return str == rhs.str;
+  }
+ 
+  friend ostream& operator<<(ostream& out, const String& );
+
+  string toString() const
+  {
+    return str;
+  }
+
+  string str;
+};
+
+
+struct LockHolder {
+  LockHolder(char nm):
+  name(nm)
+  {
+  }
+  char name;
+
+  bool operator <(const LockHolder& rhs) const
+  {
+    return name < rhs.name; 
+  }
+  bool operator ==(const LockHolder& rhs) const
+  {
+    return(name == rhs.name); 
+  }
+  string toString() const
+  {
+    return std::string(&name, 1);
+  }
+
+  friend ostream& operator<<(ostream& out, const LockHolder& );
+ 
+};
+
+struct Node {
+  typedef int value_type;
+
+
+  Node(value_type s, value_type e): left(s), right(e)
+  {
+  }
+
+
+  std::string toString() const
+  {
+    char buff[50];
+    memset(buff, 0, 50);
+    snprintf(buff, 50, "left:%d, right:%d", left, right);
+
+    return buff;
+  }
+
+
+  bool operator== (const Node& rhs) const
+  {
+    return((this->left == rhs.left) && (this->right == rhs.right));
+  }
+
+  bool operator< (const Node& rhs) const
+  {
+    return left <rhs.left;
+  }
+
+  friend ostream& operator<<(ostream& out, const Node& );
+ 
+
+  value_type left;
+  value_type right;
+};
+
+ostream& operator<< (ostream& out,  const LockHolder& t )
+{
+    out << t.toString();
+    return out;
+}
+
+
+ostream& operator<< (ostream& out, const String& t )
+{
+    out << t.toString();
+    return out;
+}
+
+
+ostream& operator<< (ostream& out, const Node& t )
+{
+    out << t.toString();
+    return out;
+}
+
+template<typename T>
+bool popNode(std::list<T>& result, const T& n)
+{
+  if(result.front() == n) {
+    result.pop_front();
+    return true;
+  }
+  return false;
+}
+
+template<typename T>
+bool hasNode(std::list<T>& result, const T& n)
+{
+  typename std::list<T>::iterator itr = find(result.begin(), result.end(), n);
+  return (itr != result.end());
+}
+
+template<typename T>
+void printResultSet(std::list<T>& result)
+{
+#ifdef DEBUG
+  typename std::list<T>::iterator i, iEnd = result.end();
+  for(i = result.begin(); i != iEnd; ++i){
+    std::cout << "result ::{" << (*i)<< "} " << std::endl; 
+  }
+#endif
+}
+
+template<typename T, typename U>
+void printTree(IntervalTree<T,U> &tree)
+{
+#ifdef DEBUG
+  std::cout  << "============= tree ============" << std::endl;
+  tree.printTree(std::cout);
+  std::cout << "============= ============" << std::endl;
+#endif
+}
+
+void testLocks()
+{
+  // 1. Create new lock and acquire lock from 1-10
+  IntervalTree<int, LockHolder> tree;
+  LockHolder lockA('A');
+  tree.addInterval(1, 10, lockA);
+
+  printTree(tree);
+  std::list<LockHolder> result;
+
+  {
+    result = tree.getIntervalSet(1,10);
+    assert(result.size() == 1);
+
+    printResultSet(result);
+  }
+
+  // Create new lock and acquire from 3-15
+  LockHolder lockB('B');
+  tree.addInterval(3, 15, lockB);
+
+  {
+    result = tree.getIntervalSet(1,15);
+    assert(result.size() == 2);
+  }
+
+  // Release all  locks  from 3-10
+  tree.removeInterval(3,10);
+
+  // Query the whole range
+  result = tree.getIntervalSet(1,15);
+
+  assert(result.size() == 2 && (result.front() == 'A') );
+  result.pop_front();
+  assert(result.front() == 'B');
+
+
+  // Query the range held by only A
+  result = tree.getIntervalSet(1,5);
+  assert(result.front().name == 'A');
+
+  // Query the range held by none
+  result = tree.getIntervalSet(4,9);
+  printResultSet(result);
+  assert(!result.size());
+
+  // Again acquire lock B from 3-15
+  tree.addInterval(3, 15, lockB);
+  result = tree.getIntervalSet(1,15);
+  assert(result.size() ==2);
+
+
+  // Query the range held by only B
+  result = tree.getIntervalSet(4,10);
+  assert((result.size() ==1) && (result.front().name == 'B'));
+
+
+  // Again acquire lock A from 3-10
+  tree.addInterval(3, 10, lockA);
+  result = tree.getIntervalSet(3,10);
+  assert(result.size() ==2);
+
+  // Release only  locks held by B from 3-10	
+  tree.removeInterval(3,10, lockB);
+
+
+  // Query interval just released by B
+  result = tree.getIntervalSet(3,9);
+  assert((result.size() ==1) && (result.front().name == 'A'));
+
+
+  // Query interval now partially owned by B
+  result = tree.getIntervalSet(3,12);
+  assert(result.size() ==2);
+
+
+  // Add one more lock between 4-8
+  LockHolder lockC('C');
+  tree.addInterval(4, 8, lockC);
+
+  printTree(tree);
+
+  // Query the interval shared by A,B,C
+  result = tree.getIntervalSet(3,12);
+  assert(result.size() ==3);
+
+
+  // Query the intervals shared by A, C
+  result = tree.getIntervalSet(3, 6);
+  assert(result.size() == 2 && (result.front() == 'A') );
+  result.pop_front();
+  assert(result.front() == 'C');
+
+  // Add one more lock between 2-4
+  LockHolder lockD('D');
+  tree.addInterval(2, 4, lockD);
+
+  // Query the intervals owned by A.B,C,D
+  result = tree.getIntervalSet(2, 11);
+  assert(result.size () == 4);
+  assert(popNode(result, lockA) && popNode(result, lockB) &&  popNode(result, lockC) && popNode(result, lockD));
+
+}
+
+
+void testBoundaries()
+{
+  // 1. Create new lock and acquire lock from 1-10
+  IntervalTree<int, LockHolder> tree;
+  LockHolder lockA('A');
+  tree.addInterval(1, 10, lockA);
+
+  // 2. Create lock B on the edge
+  LockHolder lockB('B');
+  tree.addInterval(10, 15, lockB);
+
+  //3. Query the edge
+  std::list<LockHolder> result = tree.getIntervalSet(10, 10);
+  printResultSet(result);
+  assert((result.size() == 1) && (result.front() == 'B'));
+}
+
+void testRemoveFromMiddle()
+{
+  // 1. Create new lock and acquire lock from 1-10
+  IntervalTree<int, LockHolder> tree;
+  LockHolder lockA('A');
+  tree.addInterval(1, 10, lockA);
+
+  // 2. Create lock B on the edge
+  LockHolder lockB('B');
+  tree.addInterval(10, 15, lockB);
+
+  // 3. Remove all locks from 6-12
+  tree.removeInterval(6, 12);
+
+  //4.  Query the removed interval
+  std::list<LockHolder> result = tree.getIntervalSet(6, 11);
+  assert(result.size() == 0);
+
+  //5. Query the interval locked by A
+  result = tree.getIntervalSet(2, 5);
+  assert((result.size() == 1) && (result.front() == 'A'));
+}
+
+
+void testIntervalQuery()
+{
+  int arr[][2] ={
+
+    {1888,1971},
+    {1874,1951},
+    {1843,1907},
+    {1779,1828},
+    {1756,1791},
+    {1585, 1672}
+
+  };
+
+  Node a(1888, 1971);
+  Node b(1874, 1951);
+  Node c(1843, 1907);
+  Node d(1779, 1828);
+  Node e(1756, 1791);
+  Node f(1585, 1672);
+
+  IntervalTree<int,Node> tree;
+  for(size_t i=0; i < ARRAY_SIZE(arr); i++) {
+    Node nd (arr[i][0], arr[i][1]);
+    tree.addInterval( arr[i][0], arr[i][1], nd);
+  }
+
+
+  std::list<Node> result = tree.getIntervalSet(1843, 1874);
+  assert(result.size() == 1 && (result.front() == c));
+
+  result = tree.getIntervalSet(1873, 1974);
+  assert(result.size() == 3);
+  assert(popNode(result, c) && popNode(result,b) && popNode(result,a));
+
+
+  result = tree.getIntervalSet(1910, 1910);
+  assert(result.size() == 2);
+  assert(popNode(result, b) &&  popNode(result,a));
+
+  result = tree.getIntervalSet(1829, 1842);
+  assert(result.size() == 0); 
+
+  result = tree.getIntervalSet(1829, 1845);
+  assert(result.size() == 1);
+  assert(popNode(result, c)); 
+}
+
+void testRemoveInterval()
+{
+  int arr[][2] ={
+
+    {1888,1971},
+    {1874,1951},
+    {1843,1907},
+    {1779,1828},
+    {1756,1791},
+    {1585, 1672}
+
+  };
+
+  Node a(1888, 1971);
+  Node b(1874, 1951);
+  Node c(1843, 1907);
+  Node d(1779, 1828);
+  Node e(1756, 1791);
+  Node f(1585, 1672);
+
+  IntervalTree<int,Node> tree;
+  for(size_t i=0; i < ARRAY_SIZE(arr); i++) {
+    Node nd (arr[i][0], arr[i][1]);
+    tree.addInterval( arr[i][0], arr[i][1], nd);
+  }
+
+  printTree(tree);
+  std::list<Node> result; 
+
+  {
+    tree.removeInterval(1951, 1972, a); 
+    result = tree.getIntervalSet(1960, 1970);
+    assert(result.size() == 0);
+  }
+
+  {
+    result = tree.getIntervalSet(1890, 1900);
+    assert(result.size() == 3);
+    assert(popNode(result, c) && popNode(result, b) && popNode(result, a));
+  }
+
+  {
+    tree.removeInterval(1875, 1890, c); 
+    result = tree.getIntervalSet(1877, 1889);
+    assert(!hasNode(result, c));
+  }
+
+  {
+    result = tree.getIntervalSet(1906, 1910);
+    assert(result.size() == 3);
+    assert(hasNode(result, a));
+    assert(hasNode(result, b));
+    assert(hasNode(result, c));
+  }
+
+}
+
+void testStringIntervals()
+{
+  IntervalTree<char, String> tree;
+
+  tree.addInterval('a', 'c', string("ac"));
+  tree.addInterval('a', 'f', string("af"));
+  tree.addInterval('d', 'k', string("dk"));
+  tree.addInterval('d', 'l', string("dl"));
+  tree.addInterval('d', 'o', string("do"));
+  tree.addInterval('t', 'z', string("tz"));
+
+  printTree(tree);
+  std::list<String> result;
+
+  {
+    result = tree.getIntervalSet('b', 'g');
+    assert(result.size() == 5);
+    assert(!hasNode(result, String(string("tz"))));
+  }
+
+  {
+    result = tree.getIntervalSet('k', 'z');
+    assert(result.size() == 3);
+    assert(hasNode(result, String(string("dl"))));
+    assert(hasNode(result, String(string("do"))));
+    assert(hasNode(result, String(string("tz"))));
+
+    printResultSet(result);
+  }
+
+}
+
+void testNames()
+{  
+  IntervalTree<char, string> tree;
+
+  tree.addInterval('j', 'y', string("jojy"));
+  tree.addInterval('b', 'n', string("brian"));
+  tree.addInterval('e', 's', string("sage"));
+  tree.addInterval('f', 'g', string("gregsf"));
+  tree.addInterval('h', 'y', string("yehudah"));
+
+  printTree(tree);
+
+  std::list<string> result;
+  {
+    result = tree.getIntervalSet('b', 'y');
+    assert(result.size() == 5);
+
+    printResultSet(result);
+  }
+  
+  { 
+    result = tree.getIntervalSet('j', 'm');
+    assert(!hasNode(result, string("gregsf")));
+
+    printResultSet(result);
+  }
+
+  {
+    tree.removeAll("jojy");
+
+    result = tree.getIntervalSet('b', 'z');
+    assert(!hasNode(result, string("jojy")));
+
+    printResultSet(result);
+  }
+}
+
+int main()
+{ 
+  testIntervalQuery();  
+  testRemoveInterval(); 
+  testLocks();
+  testRemoveFromMiddle();
+  testBoundaries();
+  testStringIntervals();
+  testNames();
+}
-- 
1.7.0.4


[Index of Archives]     [CEPH Users]     [Ceph Large]     [Information on CEPH]     [Linux BTRFS]     [Linux USB Devel]     [Video for Linux]     [Linux Audio Users]     [Yosemite News]     [Linux Kernel]     [Linux SCSI]
  Powered by Linux