/* * nextpnr -- Next Generation Place and Route * * Copyright (C) 2018 Serge Bazanski * * Permission to use, copy, modify, and/or distribute this software for any * purpose with or without fee is hereby granted, provided that the above * copyright notice and this permission notice appear in all copies. * * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. * */ #include "gtest/gtest.h" #include "nextpnr.h" #include "quadtree.h" USING_NEXTPNR_NAMESPACE using QT = QuadTree; class QuadTreeTest : public ::testing::Test { protected: virtual void SetUp() { qt_ = new QT(QT::BoundingBox(0, 0, width_, height_)); } virtual void TearDown() { delete qt_; } int width_ = 100; int height_ = 100; QT *qt_; }; // Test that we're doing bound checking correctly. TEST_F(QuadTreeTest, insert_bound_checking) { ASSERT_TRUE(qt_->insert(QT::BoundingBox(10, 10, 20, 20), 10)); ASSERT_TRUE(qt_->insert(QT::BoundingBox(0, 0, 100, 100), 10)); ASSERT_FALSE(qt_->insert(QT::BoundingBox(10, 10, 101, 20), 10)); ASSERT_FALSE(qt_->insert(QT::BoundingBox(-1, 10, 101, 20), 10)); ASSERT_FALSE(qt_->insert(QT::BoundingBox(-1, -1, 20, 20), 10)); } // Test whether we are not losing any elements. TEST_F(QuadTreeTest, insert_count) { auto rng = NEXTPNR_NAMESPACE::DeterministicRNG(); // Add 10000 random rectangles. for (unsigned int i = 0; i < 10000; i++) { int x0 = rng.rng(width_); int y0 = rng.rng(height_); int w = rng.rng(width_ - x0); int h = rng.rng(width_ - y0); int x1 = x0 + w; int y1 = y0 + h; ASSERT_TRUE(qt_->insert(QT::BoundingBox(x0, y0, x1, y1), i)); ASSERT_EQ(qt_->size(), i + 1); } // Add 100000 random points. for (unsigned int i = 0; i < 100000; i++) { int x0 = rng.rng(width_); int y0 = rng.rng(height_); int x1 = x0; int y1 = y0; ASSERT_TRUE(qt_->insert(QT::BoundingBox(x0, y0, x1, y1), i)); ASSERT_EQ(qt_->size(), i + 10001); } } // Test that we can insert and retrieve the same element. TEST_F(QuadTreeTest, insert_retrieve_same) { auto rng = NEXTPNR_NAMESPACE::DeterministicRNG(); // Add 10000 small random rectangles. rng.rngseed(0); for (int i = 0; i < 10000; i++) { int x0 = rng.rng(width_); int y0 = rng.rng(height_); int w = rng.rng(width_ - x0); int h = rng.rng(width_ - y0); int x1 = x0 + w / 4; int y1 = y0 + h / 4; ASSERT_TRUE(qt_->insert(QT::BoundingBox(x0, y0, x1, y1), i)); } // Restart RNG, make sure we get the same rectangles back. rng.rngseed(0); for (int i = 0; i < 10000; i++) { int x0 = rng.rng(width_); int y0 = rng.rng(height_); int w = rng.rng(width_ - x0); int h = rng.rng(width_ - y0); int x1 = x0 + w / 4; int y1 = y0 + h / 4; // try to find something in the middle of the square int x = (x1 - x0) / 2 + x0; int y = (y1 - y0) / 2 + y0; auto res = qt_->get(x, y); // Somewhat arbirary test to make sure we don't return obscene // amounts of data. ASSERT_LT(res.size(), 200UL); bool found = false; for (auto elem : res) { // Is this what we're looking for? if (elem == i) { found = true; break; } } ASSERT_TRUE(found); } }