1 #include <fstream> 2 #include <sstream> 3 #include <cstdio> 4 #include <cxxtest/TestSuite.h> 5 #include <libgeodecomp/geometry/streak.h> 6 #include <libgeodecomp/misc/apitraits.h> 7 #include <libgeodecomp/storage/grid.h> 8 #include <libgeodecomp/storage/displacedgrid.h> 9 #include <libgeodecomp/misc/testcell.h> 10 11 #define GRIDWIDTH 4 12 #define GRIDHEIGHT 5 13 14 double edge = 0; 15 16 class MyDummyCell 17 { 18 public: 19 class API : 20 public LibGeoDecomp::APITraits::HasSoA 21 {}; 22 23 explicit MyDummyCell(const int x = 0, const double y = 0, const char z = 0) : x(x)24 x(x), 25 y(y), 26 z(z) 27 {} 28 29 inline bool operator==(const MyDummyCell& other) 30 { 31 return 32 (x == other.x) && 33 (y == other.y) && 34 (z == other.z); 35 } 36 37 int x; 38 double y; 39 char z; 40 }; 41 42 LIBFLATARRAY_REGISTER_SOA(MyDummyCell, ((int)(x))((double)(y))((char)(z)) ) 43 44 using namespace LibGeoDecomp; 45 46 namespace LibGeoDecomp { 47 48 /* 49 * testGrid is 50 * x=0 x=3 51 * y=0 200 201 202 203 52 * 204 205 206 207 53 * 208 209 210 211 54 * 212 213 214 215 55 * y=4 216 217 218 219 56 */ 57 class GridTest : public CxxTest::TestSuite 58 { 59 Grid<TestCell<2> > *testGrid; 60 61 public: 62 setUp()63 void setUp() 64 { 65 testGrid = new Grid<TestCell<2> >(Coord<2>(GRIDWIDTH, GRIDHEIGHT)); 66 67 int num = 200; 68 for (int y = 0; y < testGrid->getDimensions().y(); y++) { 69 for (int x = 0; x < testGrid->getDimensions().x(); x++) { 70 (*testGrid)[Coord<2>(x, y)] = 71 TestCell<2>(Coord<2>(x, y), testGrid->getDimensions()); 72 (*testGrid)[Coord<2>(x, y)].testValue = num++; 73 } 74 } 75 } 76 tearDown()77 void tearDown() 78 { 79 delete testGrid; 80 } 81 testDefaultConstructor()82 void testDefaultConstructor() 83 { 84 Grid<TestCell<2> > g; 85 TS_ASSERT_EQUALS(0, (int)g.getDimensions().x()); 86 TS_ASSERT_EQUALS(0, (int)g.getDimensions().y()); 87 } 88 testCopyConstructorFromGridBase()89 void testCopyConstructorFromGridBase() 90 { 91 Grid<int> a; 92 Grid<int> b(Coord<2>(10, 5), 5); 93 GridBase<int, 2>& base = b; 94 a = Grid<int>(base); 95 TS_ASSERT_EQUALS(a, b); 96 } 97 testConstructorDefaultInit()98 void testConstructorDefaultInit() 99 { 100 Grid<double> g(Coord<2>(10, 12), 14.16, 47.11); 101 TS_ASSERT_EQUALS(Coord<2>(10, 12), g.getDimensions()); 102 TS_ASSERT_EQUALS(14.16, g[5][6]); 103 TS_ASSERT_EQUALS(47.11, g[Coord<2>(-1, -1)]); 104 } 105 testMultiDimensionalConstructor()106 void testMultiDimensionalConstructor() 107 { 108 Coord<3> dim(3, 4, 5); 109 Grid<double, Topologies::Torus<3>::Topology > g(dim); 110 g.getEdgeCell() = -1; 111 g[Coord<3>(2, 1, 1)] = 1; 112 g[Coord<3>(-1, 27, -2)] = 5; 113 114 TS_ASSERT_EQUALS(dim, g.getDimensions()); 115 TS_ASSERT_EQUALS(-1, g.getEdgeCell()); 116 TS_ASSERT_EQUALS(1, g[Coord<3>(-1, 1, 1)]); 117 TS_ASSERT_EQUALS(5, g[Coord<3>(2, 3, 3)]); 118 } 119 testOperatorEqual1()120 void testOperatorEqual1() 121 { 122 int width = testGrid->getDimensions().x(); 123 int height = testGrid->getDimensions().y(); 124 double deltaTemp = 42.0; 125 Coord<2> changedCoord(0, 4); 126 127 Grid<TestCell<2> > other(Coord<2>(width, height)); 128 TS_ASSERT(!other[4][2].isValid); 129 for(int x = 0; x < width; x++) 130 for(int y = 0; y < height; y++) 131 other.cellMatrix[y][x] = testGrid->cellMatrix[y][x]; 132 133 TS_ASSERT(*testGrid == other); 134 135 other[changedCoord].testValue += deltaTemp; 136 TS_ASSERT_EQUALS( 137 other[changedCoord].testValue, 138 (*testGrid)[changedCoord].testValue + deltaTemp); 139 TS_ASSERT(*testGrid != other); 140 } 141 testOperatorEqual2()142 void testOperatorEqual2() 143 { 144 Grid<TestCell<2> > a(Coord<2>(0, 0)); 145 Grid<TestCell<2> > b(Coord<2>(0, 0)); 146 TS_ASSERT_EQUALS(a, b); 147 } 148 testCopyConstructor()149 void testCopyConstructor() 150 { 151 Grid<int> a1(Coord<2>(200, 100)); 152 for (int i = 0; i < 100; i++) { 153 for (int j = 0; j < 200; j++) { 154 a1[Coord<2>(j, i)] = i * 200 + j; 155 } 156 } 157 158 Grid<int> a2; 159 a2 = a1; 160 TS_ASSERT_EQUALS(a1, a1); 161 TS_ASSERT_EQUALS(a1, a2); 162 163 a2[Coord<2>(0, 0)] = 4711; 164 TS_ASSERT_DIFFERS(a1, a2); 165 } 166 testOperatorSquareBracketsOfCoord()167 void testOperatorSquareBracketsOfCoord() 168 { 169 (*testGrid)[Coord<2>(2, 3)].testValue = 47; 170 TS_ASSERT_EQUALS((*testGrid)[Coord<2>(2, 3)].testValue, 47); 171 (*testGrid)[Coord<2>(2, 3)].testValue = 11; 172 TS_ASSERT_EQUALS((*testGrid)[Coord<2>(2, 3)].testValue, 11); 173 } 174 testResize()175 void testResize() 176 { 177 Grid<int> g(Coord<2>(64, 20)); 178 TS_ASSERT_EQUALS(Coord<2>(64, 20), g.getDimensions()); 179 g.resize(Coord<2>(12, 34)); 180 TS_ASSERT_EQUALS(Coord<2>(12, 34), g.getDimensions()); 181 } 182 testGetNeighborhood()183 void testGetNeighborhood() 184 { 185 CoordMap<TestCell<2> > hood = testGrid->getNeighborhood(Coord<2>(1,2)); 186 187 TS_ASSERT_EQUALS(hood[Coord<2>( 0, -1)].testValue, 205); 188 189 TS_ASSERT_EQUALS(hood[Coord<2>(-1, 0)].testValue, 208); 190 TS_ASSERT_EQUALS(hood[Coord<2>( 0, 0)].testValue, 209); 191 TS_ASSERT_EQUALS(hood[Coord<2>( 1, 0)].testValue, 210); 192 193 TS_ASSERT_EQUALS(hood[Coord<2>( 0, 1)].testValue, 213); 194 } 195 testGetNeighborhoodReferenceReturn()196 void testGetNeighborhoodReferenceReturn() 197 { 198 CoordMap<TestCell<2> > hood = testGrid->getNeighborhood(Coord<2>(1,2)); 199 /* We need to use absolute coordinates for testGrid, but relative 200 * coordinates for the neighbourhood map "hood" 201 */ 202 203 TS_ASSERT_EQUALS((*testGrid)[Coord<2>(1,1)], hood[Coord<2>( 0,-1)]) 204 205 TS_ASSERT_EQUALS((*testGrid)[Coord<2>(0,2)], hood[Coord<2>(-1, 0)]) 206 TS_ASSERT_EQUALS((*testGrid)[Coord<2>(1,2)], hood[Coord<2>( 0, 0)]) 207 TS_ASSERT_EQUALS((*testGrid)[Coord<2>(2,2)], hood[Coord<2>( 1, 0)]) 208 209 TS_ASSERT_EQUALS((*testGrid)[Coord<2>(1,3)], hood[Coord<2>( 0, 1)]) 210 } 211 testGetNeighborhoodInUpperRightCorner()212 void testGetNeighborhoodInUpperRightCorner() 213 { 214 CoordMap<TestCell<2> > hood = testGrid->getNeighborhood(Coord<2>(GRIDWIDTH-1, 0)); 215 216 TS_ASSERT_EQUALS(hood[Coord<2>( 0, -1)].testValue, 217 TestCell<2>::defaultValue()); 218 219 TS_ASSERT_EQUALS(hood[Coord<2>(-1, 0)].testValue, 202); 220 TS_ASSERT_EQUALS(hood[Coord<2>( 0, 0)].testValue, 203); 221 TS_ASSERT_EQUALS(hood[Coord<2>( 1, 0)].testValue, 222 TestCell<2>::defaultValue()); 223 224 TS_ASSERT_EQUALS(hood[Coord<2>( 0, 1)].testValue, 207); 225 } 226 testGetSetManyCells()227 void testGetSetManyCells() 228 { 229 TestCell<2> cells[2]; 230 testGrid->get(Streak<2>(Coord<2>(1, 3), 3), cells); 231 232 for (int i = 0; i < 2; ++i) { 233 TS_ASSERT_EQUALS(cells[i], testGrid->get(Coord<2>(i + 1, 3))); 234 } 235 236 for (int i = 0; i < 2; ++i) { 237 cells[i].testValue = i + 1234; 238 } 239 testGrid->set(Streak<2>(Coord<2>(1, 3), 3), cells); 240 241 for (int i = 0; i < 2; ++i) { 242 TS_ASSERT_EQUALS(cells[i], testGrid->get(Coord<2>(i + 1, 3))); 243 } 244 } 245 testToString()246 void testToString() 247 { 248 Grid<int> fooBar(Coord<2>(3, 2), 4711); 249 // set edge cell... 250 fooBar[Coord<2>(-1, -1)] = 2701; 251 // ...and two others 252 fooBar[Coord<2>( 1, 0)] = 19; 253 fooBar[Coord<2>( 2, 1)] = 81; 254 std::string expected = 255 "Grid<2>(\n" 256 "boundingBox: CoordBox<2>(origin: (0, 0), dimensions: (3, 2))\n" 257 "edgeCell:\n" 258 "2701\n" 259 "Coord(0, 0):\n" 260 "4711\n" 261 "Coord(1, 0):\n" 262 "19\n" 263 "Coord(2, 0):\n" 264 "4711\n" 265 "Coord(0, 1):\n" 266 "4711\n" 267 "Coord(1, 1):\n" 268 "4711\n" 269 "Coord(2, 1):\n" 270 "81\n" 271 ")"; 272 TS_ASSERT_EQUALS(fooBar.toString(), expected); 273 } 274 testEdgeCell()275 void testEdgeCell() 276 { 277 Grid<int> fooBar(Coord<2>(12, 34), 56, 78); 278 TS_ASSERT_EQUALS(fooBar.edgeCell, 78); 279 TS_ASSERT_EQUALS(fooBar[Coord<2>(-1, -1)], 78); 280 281 fooBar[Coord<2>(-1, -1)] = 90; 282 TS_ASSERT_EQUALS(fooBar.edgeCell, 90); 283 TS_ASSERT_EQUALS(fooBar[Coord<2>(-1, -1)], 90); 284 285 fooBar.edgeCell = 10; 286 TS_ASSERT_EQUALS(fooBar.edgeCell, 10); 287 TS_ASSERT_EQUALS(fooBar[Coord<2>(-1, -1)], 10); 288 } 289 testFill2D()290 void testFill2D() 291 { 292 CoordBox<2> insert(Coord<2>(10, 20), Coord<2>(4, 7)); 293 Coord<2> dim(40, 70); 294 295 Grid<int> g(dim, -1); 296 g.fill(insert, 2); 297 298 299 for (int y = 0; y < dim.y(); ++y) { 300 for (int x = 0; x < dim.x(); ++x) { 301 Coord<2> c = Coord<2>(x, y); 302 int expected = -1; 303 if (insert.inBounds(c)) { 304 expected = 2; 305 } 306 307 TS_ASSERT_EQUALS(expected, g[c]); 308 } 309 } 310 } 311 testFill3D()312 void testFill3D() 313 { 314 CoordBox<3> insert(Coord<3>(10, 20, 15), Coord<3>(4, 7, 5)); 315 Coord<3> dim(40, 70, 30); 316 317 Grid<int, Topologies::Cube<3>::Topology> g(dim, -1); 318 g.fill(insert, 2); 319 320 321 for (int z = 0; z < dim.z(); ++z) { 322 for (int y = 0; y < dim.y(); ++y) { 323 for (int x = 0; x < dim.x(); ++x) { 324 Coord<3> c = Coord<3>(x, y, z); 325 int expected = -1; 326 if (insert.inBounds(c)) { 327 expected = 2; 328 } 329 330 TS_ASSERT_EQUALS(expected, g[c]); 331 } 332 } 333 } 334 } 335 testDefaultTopology()336 void testDefaultTopology() 337 { 338 Grid<int> g(Coord<2>(3, 4), 10, 11); 339 // in-bounds accesses 340 TS_ASSERT_EQUALS(g[Coord<2>( 0, 0)], 10); 341 TS_ASSERT_EQUALS(g[Coord<2>( 2, 0)], 10); 342 TS_ASSERT_EQUALS(g[Coord<2>( 0, 3)], 10); 343 TS_ASSERT_EQUALS(g[Coord<2>( 2, 3)], 10); 344 345 // out-of-bounds accesses should yield edge cell 346 TS_ASSERT_EQUALS(g[Coord<2>( 0, 4)], 11); 347 TS_ASSERT_EQUALS(g[Coord<2>( 0, -1)], 11); 348 TS_ASSERT_EQUALS(g[Coord<2>( 3, 0)], 11); 349 TS_ASSERT_EQUALS(g[Coord<2>(-1, 0)], 11); 350 } 351 trans(const int & x,const int & dimension)352 inline int trans(const int& x, const int& dimension) 353 { 354 return (x + dimension) % dimension; 355 } 356 testTorusTopology()357 void testTorusTopology() 358 { 359 Grid<int, Topologies::Torus<2>::Topology> g(Coord<2>(3, 4), 0, -1); 360 for (int y = 0; y < 4; ++y) { 361 for (int x = 0; x < 3; ++x) { 362 g[Coord<2>(x, y)] = y * 10 + x; 363 } 364 } 365 366 // in-bounds accesses 367 TS_ASSERT_EQUALS(g[Coord<2>( 0, 0)], 0); 368 TS_ASSERT_EQUALS(g[Coord<2>( 2, 0)], 2); 369 TS_ASSERT_EQUALS(g[Coord<2>( 0, 3)], 30); 370 TS_ASSERT_EQUALS(g[Coord<2>( 2, 3)], 32); 371 372 // out-of-bounds accesses should not yield edge cell 373 TS_ASSERT_EQUALS(g[Coord<2>( 0, 4)], 0); 374 TS_ASSERT_EQUALS(g[Coord<2>( 0, -1)], 30); 375 TS_ASSERT_EQUALS(g[Coord<2>( 3, 0)], 0); 376 TS_ASSERT_EQUALS(g[Coord<2>(-1, 0)], 2); 377 TS_ASSERT_EQUALS(g[Coord<2>(47, 69)], 12); 378 } 379 testFill3d()380 void testFill3d() 381 { 382 Coord<3> dim(3, 4, 5); 383 Grid<int, Topologies::Cube<3>::Topology> g(dim, 47, 11); 384 TS_ASSERT_EQUALS(g[Coord<3>(-1, 0, 0)], 11); 385 386 for (int z=0; z < dim.z(); ++z) { 387 for (int y=0; y < dim.y(); ++y) { 388 for (int x=0; x < dim.x(); ++x) { 389 TS_ASSERT_EQUALS(g[Coord<3>(x, y, z)], 47); 390 } 391 } 392 } 393 } 394 testCompare()395 void testCompare() 396 { 397 Coord<2> dim(5, 4); 398 Grid<int> g1(dim, 4); 399 Grid<int> g2(dim, 9); 400 DisplacedGrid<int> g3(CoordBox<2>(Coord<2>(), dim), 4); 401 DisplacedGrid<int> g4(CoordBox<2>(Coord<2>(), dim), 9); 402 DisplacedGrid<int> g5(CoordBox<2>(Coord<2>(), Coord<2>(5, 5)), 9); 403 404 TS_ASSERT(g1 != g2); 405 TS_ASSERT(g1 == g3); 406 TS_ASSERT(g1 != g4); 407 TS_ASSERT(g1 != g5); 408 409 TS_ASSERT(g2 != g3); 410 TS_ASSERT(g2 == g4); 411 TS_ASSERT(g2 != g5); 412 } 413 testLoadSaveMember()414 void testLoadSaveMember() 415 { 416 // basic setup: 417 Selector<MyDummyCell> xSelector(&MyDummyCell::x, "x"); 418 Selector<MyDummyCell> ySelector(&MyDummyCell::y, "y"); 419 Selector<MyDummyCell> zSelector(&MyDummyCell::z, "z"); 420 421 Coord<2> dim(40, 20); 422 Grid<MyDummyCell, Topologies::Cube<2>::Topology> grid(dim); 423 for (int y = 0; y < dim.y(); ++y) { 424 for (int x = 0; x < dim.x(); ++x) { 425 grid[Coord<2>(x, y)] = MyDummyCell(x, y, 13); 426 } 427 } 428 429 Region<2> region; 430 region << Streak<2>(Coord<2>( 0, 0), 10) 431 << Streak<2>(Coord<2>(10, 10), 20) 432 << Streak<2>(Coord<2>(30, 19), 40); 433 434 std::vector<int > xVector(region.size(), -1); 435 std::vector<double> yVector(region.size(), -1); 436 std::vector<char > zVector(region.size(), -1); 437 438 grid.saveMember(&xVector[0], xSelector, region); 439 grid.saveMember(&yVector[0], ySelector, region); 440 grid.saveMember(&zVector[0], zSelector, region); 441 442 Region<2>::Iterator cursor = region.begin(); 443 444 // test whether grid data is accurately copied back: 445 for (std::size_t i = 0; i < region.size(); ++i) { 446 TS_ASSERT_EQUALS(xVector[i], cursor->x()); 447 TS_ASSERT_EQUALS(yVector[i], cursor->y()); 448 TS_ASSERT_EQUALS(zVector[i], 13); 449 ++cursor; 450 } 451 452 // modify vectors and copy back to grid: 453 for (std::size_t i = 0; i < region.size(); ++i) { 454 xVector[i] = 1000 + i; 455 yVector[i] = 2000 + i; 456 zVector[i] = i; 457 } 458 459 grid.loadMember(&xVector[0], xSelector, region); 460 grid.loadMember(&yVector[0], ySelector, region); 461 grid.loadMember(&zVector[0], zSelector, region); 462 463 int counter = 0; 464 for (Region<2>::Iterator i = region.begin(); i != region.end(); ++i) { 465 TS_ASSERT_EQUALS(grid[*i], MyDummyCell(1000 + counter, 2000 + counter, counter)); 466 ++counter; 467 } 468 } 469 }; 470 471 } 472