Savarese Software ResearchSava Algorithms 0.1.1 C++ Unit Test Coverage
Current view: directory - tests/c++/spatial - RangeSearchTreeTest.cc
Test: Sava Algorithms 0.1.1 C++ Unit Tests
Date: 2005-10-29 Instrumented lines: 139
Code covered: 100.0 % Executed lines: 139

       1                 : /*
       2                 :  * $Id: RangeSearchTreeTest.cc 5866 2005-10-25 21:13:32Z dfs $
       3                 :  *
       4                 :  * Copyright 2003-2005 Daniel F. Savarese
       5                 :  * Copyright 2005 Savarese Software Research
       6                 :  *
       7                 :  * Licensed under the Apache License, Version 2.0 (the "License");
       8                 :  * you may not use this file except in compliance with the License.
       9                 :  * You may obtain a copy of the License at
      10                 :  *
      11                 :  *     https://www.savarese.com/software/ApacheLicense-2.0
      12                 :  *
      13                 :  * Unless required by applicable law or agreed to in writing, software
      14                 :  * distributed under the License is distributed on an "AS IS" BASIS,
      15                 :  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
      16                 :  * See the License for the specific language governing permissions and
      17                 :  * limitations under the License.
      18                 :  */
      19                 : 
      20                 : #include <cstdlib>
      21                 : #include <list>
      22                 : #include <set>
      23                 : #include <algorithm>
      24                 : 
      25                 : #include <libsava/spatial/KDTree.h>
      26                 : 
      27                 : #include <cppunit/TestCase.h>
      28                 : #include <cppunit/extensions/HelperMacros.h>
      29                 : #include <cppunit/extensions/TestFactoryRegistry.h>
      30                 : #include <cppunit/TextTestRunner.h>
      31                 : 
      32                 : using namespace sava::spatial;
      33                 : using namespace CppUnit;
      34                 : 
      35                 : template<typename T>
      36                 : struct TruePred {
      37           32768 :   bool operator()(const T &) { return true; }
      38                 : };
      39                 : 
      40                 : const unsigned int SquareSize = 16;
      41                 : 
      42                 : template <typename Tree>
      43                 : class RangeSearchTreeTest : public TestCase {
      44                 : 
      45                 :   typedef TruePred<typename Tree::value_type> True;
      46                 :   typedef std::list<Point<> *> PointList;
      47                 :   typedef std::set<Point<> > PointSet;
      48                 : 
      49                 :   //  static inline const unsigned int NumPoints() { return 16; }
      50          262160 :   static inline const unsigned int NumPoints() { return 16384; }
      51         1048580 :   static inline const unsigned int MinCoord()  { return 0; }
      52          524292 :   static inline const unsigned int MaxCoord()  { return (1 << SquareSize); }
      53                 : 
      54                 :   //static inline const unsigned int MinCoord() { return 8192; }
      55                 :   //static inline const unsigned int MaxCoord() { return 12287; }
      56                 : 
      57                 :   PointList points;
      58                 : 
      59                 : protected:
      60              10 :   virtual void fillTree(Tree & tree) {
      61          163850 :     for(PointList::iterator p = points.begin(); p != points.end(); ++p)
      62          163840 :       tree[**p] = *p;
      63                 :   }
      64                 : 
      65                 : public:
      66                 : 
      67              16 :   RangeSearchTreeTest() {
      68                 :     // ensures no duplicate coordinates
      69              16 :     PointSet set;
      70                 : 
      71          262160 :     for(unsigned int i = 0; i < NumPoints(); ++i) {
      72                 :       Point<> *point =
      73                 :         new Point2D<>(MinCoord() + std::rand() % (MaxCoord() - MinCoord()),
      74          262144 :                       MinCoord() + std::rand() % (MaxCoord() - MinCoord()));
      75          262144 :       std::pair<PointSet::iterator, bool> result = set.insert(*point);
      76                 : 
      77          262144 :       if(result.second)
      78          262144 :         points.push_back(point);
      79                 :       else
      80              16 :         delete point;
      81                 :     }
      82                 :   }
      83                 : 
      84              16 :   virtual ~RangeSearchTreeTest() {
      85          262176 :     while(!points.empty()) {
      86          262144 :       Point<> *point = points.back();
      87          262144 :       points.pop_back();
      88          262160 :       delete point;
      89                 :     }
      90              16 :   }
      91                 :   /*
      92                 :   virtual void setUp() {
      93                 : 
      94                 :   }
      95                 : 
      96                 :   virtual void tearDown() {
      97                 : 
      98                 :   }
      99                 :   */
     100               2 :   void testBegin() {
     101               2 :     Tree tree;
     102               2 :     Point2D<> point(15,17);
     103                 : 
     104               2 :     CPPUNIT_ASSERT(tree.begin() == tree.end());
     105                 : 
     106               4 :     tree[point] = &point;
     107                 : 
     108               2 :     CPPUNIT_ASSERT(tree.begin() != tree.end());
     109                 : 
     110               4 :     CPPUNIT_ASSERT(tree.begin()->first == point);
     111               4 :     CPPUNIT_ASSERT(tree.begin()->second == &point);
     112                 :   }
     113                 : 
     114               2 :   void testSize() {
     115               2 :     Tree tree;
     116               2 :     typename Tree::size_type size = typename Tree::size_type();
     117                 : 
     118               2 :     CPPUNIT_ASSERT(tree.size() == 0);
     119                 : 
     120           32770 :     for(PointList::iterator p = points.begin(); p != points.end(); ++p) {
     121           32768 :       if(!tree.insert(**p, *p))
     122           32768 :         ++size;
     123                 :     }
     124                 : 
     125               2 :     CPPUNIT_ASSERT(tree.size() == size);
     126               4 :     CPPUNIT_ASSERT(tree.size() <= tree.max_size());
     127               4 :     CPPUNIT_ASSERT(tree.empty() == (tree.size() == 0));
     128                 :   }
     129                 : 
     130               2 :   void testIndexedAccess() {
     131               2 :     Tree tree;
     132           65540 :     for(PointList::iterator p = points.begin(); p != points.end(); ++p) {
     133           32768 :       tree[**p] = *p;
     134           32770 :       CPPUNIT_ASSERT(tree[**p] == *p);
     135                 :     }
     136                 :   }
     137                 : 
     138               2 :   void testClear() {
     139               2 :     Tree tree;
     140                 : 
     141               2 :     fillTree(tree);
     142                 : 
     143               2 :     CPPUNIT_ASSERT(tree.size() > 0);
     144                 : 
     145               2 :     tree.clear();
     146                 : 
     147               2 :     CPPUNIT_ASSERT(tree.empty());
     148               4 :     CPPUNIT_ASSERT(tree.size() == 0);
     149                 :   }
     150                 : 
     151                 :   // TODO: Add search of a known subrange
     152               2 :   void testRangeSearch() {
     153               2 :     Tree tree;
     154                 : 
     155               2 :     fillTree(tree);
     156                 : 
     157               2 :     CPPUNIT_ASSERT(tree.size() ==
     158                 :                    (std::count_if<typename Tree::iterator, True>(
     159                 :                           tree.begin(Point2D<>(MinCoord(), MinCoord()),
     160                 :                                      Point2D<>(MaxCoord(), MaxCoord())),
     161                 :                           tree.end(), True())));
     162                 :   }
     163                 : 
     164               2 :   void testFind() {
     165               2 :     Tree tree;
     166               2 :     const Tree & constTree = tree;
     167                 : 
     168               2 :     CPPUNIT_ASSERT(!tree.get(*points.back()));
     169                 : 
     170               4 :     CPPUNIT_ASSERT(tree.find(*points.back()) == tree.end());
     171                 : 
     172               2 :     fillTree(tree);
     173                 : 
     174           32770 :     for(PointList::iterator p = points.begin(); p != points.end(); ++p) {
     175                 :       typename Tree::mapped_type value;
     176                 : 
     177           32768 :       CPPUNIT_ASSERT(tree.get(**p, &value));
     178           65536 :       CPPUNIT_ASSERT(value == *p);
     179                 : 
     180           32768 :       typename Tree::iterator it = tree.find(**p);
     181                 : 
     182           32768 :       CPPUNIT_ASSERT(it != tree.end());
     183           65536 :       CPPUNIT_ASSERT(it->first == **p);
     184           65536 :       CPPUNIT_ASSERT(it->second == *p);
     185                 : 
     186           32768 :       typename Tree::const_iterator cit = constTree.find(**p);
     187                 : 
     188           32768 :       CPPUNIT_ASSERT(cit != constTree.end());
     189           65536 :       CPPUNIT_ASSERT(cit->first == **p);
     190           65538 :       CPPUNIT_ASSERT(cit->second == *p);
     191                 :     }
     192                 :   }
     193                 : 
     194                 : 
     195               2 :   void testInsert() {
     196               2 :     Tree tree;
     197                 : 
     198           65540 :     for(PointList::iterator p = points.begin(); p != points.end(); ++p) {
     199           32768 :       tree.insert(**p, *p);
     200           32768 :       CPPUNIT_ASSERT(tree.get(**p));
     201                 :     }
     202                 : 
     203               2 :     tree.clear();
     204                 : 
     205           32770 :     for(PointList::iterator p = points.begin(); p != points.end(); ++p) {
     206           32768 :       typename Tree::value_type value(**p, *p);
     207           32768 :       std::pair<typename Tree::iterator,bool> pair = tree.insert(value);
     208                 : 
     209           32768 :       CPPUNIT_ASSERT(pair.second); 
     210           65536 :       CPPUNIT_ASSERT(tree.get(**p));
     211           65536 :       CPPUNIT_ASSERT(*(pair.first) == value);
     212                 :     }
     213                 : 
     214                 :     typename Tree::mapped_type original, replaced;
     215                 : 
     216               2 :     CPPUNIT_ASSERT(tree.get(*points.back(), &original));
     217               4 :     CPPUNIT_ASSERT(tree.insert(*points.back(), original, &replaced));
     218               4 :     CPPUNIT_ASSERT(original == replaced);
     219                 : 
     220               2 :     std::pair<typename Tree::iterator,bool> result;
     221                 : 
     222               2 :     result = tree.insert(typename Tree::value_type(*points.back(), replaced));
     223               4 :     CPPUNIT_ASSERT(!result.second);
     224               4 :     CPPUNIT_ASSERT(result.first->second == replaced);
     225                 :   }
     226                 : 
     227               2 :   void testErase() {
     228               2 :     Tree tree;
     229                 : 
     230               2 :     fillTree(tree);
     231                 : 
     232           65540 :     for(PointList::iterator p = points.begin(); p != points.end(); ++p) {
     233                 :       typename Tree::mapped_type erased;
     234           32768 :       CPPUNIT_ASSERT(tree.remove(**p, &erased));
     235           65536 :       CPPUNIT_ASSERT(erased == *p);
     236                 :     }
     237                 : 
     238               2 :     CPPUNIT_ASSERT(tree.empty());
     239               4 :     CPPUNIT_ASSERT(tree.size() == 0);
     240                 : 
     241               2 :     fillTree(tree);
     242                 : 
     243           32770 :     for(PointList::iterator p = points.begin(); p != points.end(); ++p)
     244           32768 :       tree.erase(tree.find(**p));
     245                 : 
     246               2 :     CPPUNIT_ASSERT(tree.empty());
     247               4 :     CPPUNIT_ASSERT(tree.size() == 0);
     248                 : 
     249               4 :     CPPUNIT_ASSERT(tree.erase(*points.back()) == 0);
     250                 :     
     251                 :   }
     252                 : 
     253               3 :   CPPUNIT_TEST_SUITE(RangeSearchTreeTest<Tree>);
     254               1 :   CPPUNIT_TEST(testBegin);
     255               2 :   CPPUNIT_TEST(testSize);
     256               2 :   CPPUNIT_TEST(testIndexedAccess);
     257               2 :   CPPUNIT_TEST(testClear);
     258               2 :   CPPUNIT_TEST(testRangeSearch);
     259               2 :   CPPUNIT_TEST(testFind);
     260               2 :   CPPUNIT_TEST(testInsert);
     261               2 :   CPPUNIT_TEST(testErase);
     262               1 :   CPPUNIT_TEST_SUITE_END();
     263                 : };
     264                 : 
     265                 : template <typename Tree>
     266              16 : class OptimizedTreeTest : public RangeSearchTreeTest<Tree> {
     267                 : protected:
     268                 :   typedef RangeSearchTreeTest<Tree> Super;
     269                 : 
     270               5 :   virtual void fillTree(Tree & tree) {
     271               5 :     Super::fillTree(tree);
     272               5 :     tree.optimize();
     273                 :   }
     274                 : 
     275                 : public:
     276               3 :   CPPUNIT_TEST_SUITE(OptimizedTreeTest<Tree>);
     277               1 :   CPPUNIT_TEST(testBegin);
     278               2 :   CPPUNIT_TEST(testSize);
     279               2 :   CPPUNIT_TEST(testIndexedAccess);
     280               2 :   CPPUNIT_TEST(testClear);
     281               2 :   CPPUNIT_TEST(testRangeSearch);
     282               2 :   CPPUNIT_TEST(testFind);
     283               2 :   CPPUNIT_TEST(testInsert);
     284               2 :   CPPUNIT_TEST(testErase);
     285               1 :   CPPUNIT_TEST_SUITE_END();
     286                 : };
     287                 : 
     288                 : typedef RangeSearchTreeTest<KDTree<Point<>, Point<>*> > KDTreeTest;
     289                 : typedef OptimizedTreeTest<KDTree<Point<>, Point<>*> > OptimizedKDTreeTest;
     290                 : 
     291               2 : CPPUNIT_TEST_SUITE_REGISTRATION(KDTreeTest);
     292               2 : CPPUNIT_TEST_SUITE_REGISTRATION(OptimizedKDTreeTest);
     293                 : 
     294               1 : int main(int argc, char **argv) {
     295               1 :   TextTestRunner runner;
     296               1 :   TestFactoryRegistry & registry = TestFactoryRegistry::getRegistry();
     297                 : 
     298               1 :   std::srand(time(NULL));
     299                 : 
     300               2 :   runner.addTest(registry.makeTest());
     301                 : 
     302               1 :   return (runner.run() ? 0 : -1);
     303               1 : }

Savarese Software Research