// Copyright 2016 Yahoo Inc. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root. #include #include #include #include #include #include #include namespace storage { struct JudyArrayTest : public CppUnit::TestFixture { void testIterating(); void testDualArrayFunctions(); void testComparing(); void testSize(); void testStress(); CPPUNIT_TEST_SUITE(JudyArrayTest); CPPUNIT_TEST(testIterating); CPPUNIT_TEST(testDualArrayFunctions); CPPUNIT_TEST(testSize); CPPUNIT_TEST(testStress); CPPUNIT_TEST_SUITE_END(); }; CPPUNIT_TEST_SUITE_REGISTRATION(JudyArrayTest); namespace { std::vector > getJudyArrayContents(const JudyArray& array) { std::vector > vals; for (JudyArray::const_iterator it = array.begin(); it != array.end(); ++it) { vals.push_back(std::make_pair(it.key(), it.value())); } return vals; } } void JudyArrayTest::testIterating() { JudyArray array; // Test that things are sane for empty document CPPUNIT_ASSERT_EQUAL(array.begin(), array.end()); // Add some values using namespace boost::assign; std::vector > values = map_list_of(3,2)(5,12)(15,8)(13,10)(7,6)(9,4); for (uint32_t i=0; i > foundVals = getJudyArrayContents(array); CPPUNIT_ASSERT_EQUAL(values, foundVals); { // Test that we can alter through non-const iterator JudyArray::iterator it = array.begin(); ++it; ++it; it.setValue(20); CPPUNIT_ASSERT_EQUAL((JudyArray::key_type) 7, it.key()); CPPUNIT_ASSERT_EQUAL((JudyArray::data_type) 20, array[7]); it.remove(); CPPUNIT_ASSERT_EQUAL((JudyArray::size_type) 5, getJudyArrayContents(array).size()); CPPUNIT_ASSERT_EQUAL(array.end(), array.find(7)); values.erase(values.begin() + 2); CPPUNIT_ASSERT_EQUAL(values, getJudyArrayContents(array)); // And that we can continue iterating after removing. ++it; CPPUNIT_ASSERT_EQUAL((JudyArray::key_type) 9, it.key()); CPPUNIT_ASSERT_EQUAL((JudyArray::data_type) 4, array[9]); } { // Test printing of iterators JudyArray::ConstIterator cit = array.begin(); CPPUNIT_ASSERT_MATCH_REGEX( "^ConstIterator\\(Key: 3, Valp: 0x[0-9a-f]{1,16}, Val: 2\\)$", cit.toString()); JudyArray::Iterator it = array.end(); CPPUNIT_ASSERT_MATCH_REGEX( "^Iterator\\(Key: 0, Valp: 0\\)$", it.toString()); } } void JudyArrayTest::testDualArrayFunctions() { JudyArray array1; JudyArray array2; // Add values to array1 using namespace boost::assign; std::vector > values1 = map_list_of(3,2)(5,12)(15,8)(13,10)(7,6)(9,4); for (uint32_t i=0; i > values2 = map_list_of(4,5)(9,40); for (uint32_t i=0; i std::string toString(const T& m) { std::cerr << "#"; std::ostringstream ost; ost << m; return ost.str(); } } void JudyArrayTest::testStress() { // Do a lot of random stuff to both judy array and std::map. Ensure equal // behaviour JudyArray judyArray; typedef std::map StdMap; StdMap stdMap; boost::rand48 rnd(55); for (uint32_t checkpoint=0; checkpoint<50; ++checkpoint) { for (uint32_t opnr=0; opnr<500; ++opnr) { int optype = rnd() % 100; if (optype < 30) { // Insert JudyArray::key_type key(rnd() % 500); JudyArray::key_type value(rnd()); judyArray.insert(key, value); stdMap[key] = value; //std::pair result // = stdMap.insert(std::make_pair(key, value)); //if (!result.second) result.first->second = value; } else if (optype < 50) { // operator[] JudyArray::key_type key(rnd() % 500); JudyArray::key_type value(rnd()); judyArray[key] = value; stdMap[key] = value; } else if (optype < 70) { // erase() JudyArray::key_type key(rnd() % 500); CPPUNIT_ASSERT_EQUAL_MSG( toString(judyArray) + toString(stdMap), stdMap.erase(key), judyArray.erase(key)); } else if (optype < 75) { // size() CPPUNIT_ASSERT_EQUAL_MSG( toString(judyArray) + toString(stdMap), stdMap.size(), judyArray.size()); } else if (optype < 78) { // empty() CPPUNIT_ASSERT_EQUAL_MSG( toString(judyArray) + toString(stdMap), stdMap.empty(), judyArray.empty()); } else { // find() JudyArray::key_type key(rnd() % 500); JudyArray::iterator it = judyArray.find(key); StdMap::iterator it2 = stdMap.find(key); CPPUNIT_ASSERT_EQUAL_MSG( toString(judyArray) + toString(stdMap), it2 == stdMap.end(), it == judyArray.end()); if (it != judyArray.end()) { CPPUNIT_ASSERT_EQUAL_MSG( toString(judyArray) + toString(stdMap), it.key(), it2->first); CPPUNIT_ASSERT_EQUAL_MSG( toString(judyArray) + toString(stdMap), it.value(), it2->second); } } } // Ensure judy array contents is equal to std::map's at this point StdMap tmpMap; for (JudyArray::const_iterator it = judyArray.begin(); it != judyArray.end(); ++it) { tmpMap[it.key()] = it.value(); } CPPUNIT_ASSERT_EQUAL(stdMap, tmpMap); } } } // storage