Quellcodebibliothek Statistik Leitseite products/Sources/formale Sprachen/C/LibreOffice/o3tl/qa/   (Office von Apache Version 25.8.3.2©)  Datei vom 5.10.2025 mit Größe 10 kB image not shown  

Quelle  test-lru_map.cxx   Sprache: C

 
/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
/*
 * This file is part of the LibreOffice project.
 *
 * This Source Code Form is subject to the terms of the Mozilla Public
 * License, v. 2.0. If a copy of the MPL was not distributed with this
 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
 *
 */


#include <cppunit/TestAssert.h>
#include <cppunit/TestFixture.h>
#include <cppunit/extensions/HelperMacros.h>

#include <o3tl/lru_map.hxx>

#include <o3tl/hash_combine.hxx>

using namespace ::o3tl;

class lru_map_test : public CppUnit::TestFixture
{
public:
    void testBaseUsage();
    void testReplaceKey();
    void testReplaceValue();
    void testLruRemoval();
    void testCustomHash();
    void testRemoveIf();
    void testChangeMaxSize();
    void testCustomItemSize();

    CPPUNIT_TEST_SUITE(lru_map_test);
    CPPUNIT_TEST(testBaseUsage);
    CPPUNIT_TEST(testReplaceKey);
    CPPUNIT_TEST(testReplaceValue);
    CPPUNIT_TEST(testLruRemoval);
    CPPUNIT_TEST(testCustomHash);
    CPPUNIT_TEST(testRemoveIf);
    CPPUNIT_TEST(testChangeMaxSize);
    CPPUNIT_TEST(testCustomItemSize);
    CPPUNIT_TEST_SUITE_END();
};

void lru_map_test::testBaseUsage()
{
    o3tl::lru_map<intint> lru(10);
    lru.insert(std::make_pair<intint>(1, 1));

    std::pair<intint> pair;
    for (int i = 2; i < 7; i++)
    {
        pair.first = pair.second = i;
        lru.insert(pair);
    }

    CPPUNIT_ASSERT_EQUAL(size_t(6), lru.size());

    o3tl::lru_map<intint>::const_iterator it;

    it = lru.find(2);
    CPPUNIT_ASSERT(it != lru.end());
    CPPUNIT_ASSERT_EQUAL(2, it->second);

    it = lru.find(5);
    CPPUNIT_ASSERT(it != lru.end());
    CPPUNIT_ASSERT_EQUAL(5, it->second);

    it = lru.find(0);
    CPPUNIT_ASSERT(bool(it == lru.end()));
}

void lru_map_test::testReplaceValue()
{
    o3tl::lru_map<intint> lru(2);
    // check if map is empty
    CPPUNIT_ASSERT_EQUAL(size_t(0), lru.size());

    // check if inserting entry with same key replaces the value

    // inserting new entry
    lru.insert(std::make_pair<intint>(1, 2));
    CPPUNIT_ASSERT_EQUAL(size_t(1), lru.size());
    CPPUNIT_ASSERT_EQUAL(2, lru.find(1)->second);

    // inserting new entry with key that already exists
    lru.insert(std::make_pair<intint>(1, 4));
    CPPUNIT_ASSERT_EQUAL(size_t(1), lru.size());
    CPPUNIT_ASSERT_EQUAL(4, lru.find(1)->second);

    // inserting new entry
    lru.insert(std::make_pair<intint>(2, 200));
    CPPUNIT_ASSERT_EQUAL(size_t(2), lru.size());
    CPPUNIT_ASSERT_EQUAL(4, lru.find(1)->second);
    CPPUNIT_ASSERT_EQUAL(200, lru.find(2)->second);

    // check if insert with same key, moves the entry back of the lru queue

    // inserting new entry with key that already exists
    lru.insert(std::make_pair<intint>(1, 6));
    // inserting new entry, lru removed
    lru.insert(std::make_pair<intint>(3, 300));

    CPPUNIT_ASSERT_EQUAL(size_t(2), lru.size());
    CPPUNIT_ASSERT_EQUAL(6, lru.find(1)->second);
    CPPUNIT_ASSERT_EQUAL(300, lru.find(3)->second);
}

void lru_map_test::testReplaceKey()
{
    o3tl::lru_map<intint> lru(2);

    // inserting new entry
    lru.insert(std::make_pair<intint>(1, 100));
    CPPUNIT_ASSERT_EQUAL(size_t(1), lru.size());
    CPPUNIT_ASSERT_EQUAL(100, lru.find(1)->second);
    CPPUNIT_ASSERT(bool(lru.find(2) == lru.end()));
    CPPUNIT_ASSERT(bool(lru.find(3) == lru.end()));

    // inserting new entry
    lru.insert(std::make_pair<intint>(2, 200));
    CPPUNIT_ASSERT_EQUAL(size_t(2), lru.size());
    CPPUNIT_ASSERT_EQUAL(100, lru.find(1)->second);
    CPPUNIT_ASSERT_EQUAL(200, lru.find(2)->second);
    CPPUNIT_ASSERT(bool(lru.find(3) == lru.end()));

    // inserting new entry, lru entry is removed
    lru.insert(std::make_pair<intint>(3, 300));
    CPPUNIT_ASSERT_EQUAL(size_t(2), lru.size());
    CPPUNIT_ASSERT(bool(lru.find(1) == lru.end()));
    CPPUNIT_ASSERT_EQUAL(200, lru.find(2)->second);
    CPPUNIT_ASSERT_EQUAL(300, lru.find(3)->second);

    // inserting new entry, lru entry is removed
    std::pair<intint> pair(4, 400);
    lru.insert(pair);
    CPPUNIT_ASSERT_EQUAL(size_t(2), lru.size());
    CPPUNIT_ASSERT(bool(lru.find(1) == lru.end()));
    CPPUNIT_ASSERT(bool(lru.find(2) == lru.end()));
    CPPUNIT_ASSERT_EQUAL(300, lru.find(3)->second);
    CPPUNIT_ASSERT_EQUAL(400, lru.find(4)->second);
}

void lru_map_test::testLruRemoval()
{
    o3tl::lru_map<intint> lru(5);
    CPPUNIT_ASSERT_EQUAL(size_t(0), lru.size());

    // fill up...
    lru.insert(std::make_pair<intint>(1, 100));
    lru.insert(std::make_pair<intint>(2, 200));
    lru.insert(std::make_pair<intint>(3, 300));
    lru.insert(std::make_pair<intint>(4, 400));
    lru.insert(std::make_pair<intint>(5, 500));
    CPPUNIT_ASSERT_EQUAL(size_t(5), lru.size());
    CPPUNIT_ASSERT_EQUAL(100, lru.find(1)->second);
    CPPUNIT_ASSERT_EQUAL(200, lru.find(2)->second);
    CPPUNIT_ASSERT_EQUAL(300, lru.find(3)->second);
    CPPUNIT_ASSERT_EQUAL(400, lru.find(4)->second);
    CPPUNIT_ASSERT_EQUAL(500, lru.find(5)->second);

    // add one more entry - lru entry should be removed
    lru.insert(std::make_pair<intint>(6, 600));

    CPPUNIT_ASSERT_EQUAL(size_t(5), lru.size());
    CPPUNIT_ASSERT_EQUAL(200, lru.find(2)->second);
    CPPUNIT_ASSERT_EQUAL(300, lru.find(3)->second);
    CPPUNIT_ASSERT_EQUAL(400, lru.find(4)->second);
    CPPUNIT_ASSERT_EQUAL(500, lru.find(5)->second);
    CPPUNIT_ASSERT_EQUAL(600, lru.find(6)->second);

    // access the lru entry to put it at the back of the lru queue
    lru.find(2);
    // add new entry - lru entry should be removed
    lru.insert(std::make_pair<intint>(7, 700));

    CPPUNIT_ASSERT_EQUAL(size_t(5), lru.size());
    CPPUNIT_ASSERT_EQUAL(200, lru.find(2)->second);
    CPPUNIT_ASSERT_EQUAL(400, lru.find(4)->second);
    CPPUNIT_ASSERT_EQUAL(500, lru.find(5)->second);
    CPPUNIT_ASSERT_EQUAL(600, lru.find(6)->second);
    CPPUNIT_ASSERT_EQUAL(700, lru.find(7)->second);
}

namespace
{
struct TestClassKey
{
    int mA;
    int mB;

    TestClassKey(int a, int b)
        : mA(a)
        , mB(b)
    {
    }

    bool operator==(TestClassKey const& aOther) const { return mA == aOther.mA && mB == aOther.mB; }
};

struct TestClassKeyHashFunction
{
    std::size_t operator()(TestClassKey const& aKey) const
    {
        std::size_t seed = 0;
        o3tl::hash_combine(seed, aKey.mA);
        o3tl::hash_combine(seed, aKey.mB);
        return seed;
    }
};
}

void lru_map_test::testCustomHash()
{
    // check lru_map with custom hash function
    o3tl::lru_map<TestClassKey, int, TestClassKeyHashFunction> lru(2);
    CPPUNIT_ASSERT_EQUAL(size_t(0), lru.size());

    lru.insert(std::make_pair<TestClassKey, int>(TestClassKey(1, 1), 2));
    CPPUNIT_ASSERT_EQUAL(size_t(1), lru.size());

    lru.insert(std::make_pair<TestClassKey, int>(TestClassKey(1, 1), 7));
    CPPUNIT_ASSERT_EQUAL(size_t(1), lru.size());

    lru.insert(std::make_pair<TestClassKey, int>(TestClassKey(1, 2), 9));
    CPPUNIT_ASSERT_EQUAL(size_t(2), lru.size());

    CPPUNIT_ASSERT(bool(lru.end() == lru.find(TestClassKey(0, 0)))); // non existent
    CPPUNIT_ASSERT_EQUAL(7, lru.find(TestClassKey(1, 1))->second);
    CPPUNIT_ASSERT_EQUAL(9, lru.find(TestClassKey(1, 2))->second);

    lru.insert(std::make_pair<TestClassKey, int>(TestClassKey(2, 1), 13));

    CPPUNIT_ASSERT_EQUAL(size_t(2), lru.size());

    CPPUNIT_ASSERT(bool(lru.end() == lru.find(TestClassKey(1, 1))));
    CPPUNIT_ASSERT_EQUAL(9, lru.find(TestClassKey(1, 2))->second);
    CPPUNIT_ASSERT_EQUAL(13, lru.find(TestClassKey(2, 1))->second);
}

void lru_map_test::testRemoveIf()
{
    typedef o3tl::lru_map<intint> IntMap;
    typedef IntMap::key_value_pair_t IntMapPair;
    struct limit_except : public std::exception
    {
    };

    IntMap lru(6);
    int i = 0;
    for (; i < 8; i++)
        lru.insert({ i, i });
    CPPUNIT_ASSERT_EQUAL(size_t(6), lru.size());
    // now contains 7..2

    // remove everything < 4 from the back
    try
    {
        lru.remove_if([](IntMapPair const& rPair) {
            if (rPair.first >= 4)
                throw limit_except();
            return true;
        });
        CPPUNIT_ASSERT(false); // not reached
    }
    catch (limit_except&)
    {
        // contains 7..4
        CPPUNIT_ASSERT_EQUAL(size_t(4), lru.size());
    }

    // remove all even numbers
    lru.remove_if([](IntMapPair const& rPair) { return (0 == rPair.first % 2); });
    CPPUNIT_ASSERT_EQUAL(size_t(2), lru.size());
    // contains 7, 5

    lru.insert({ 5, 5 });
    // contains 5, 7

    i = 5;
    for (auto& rPair : lru)
    {
        CPPUNIT_ASSERT_EQUAL(i, rPair.first);
        i += 2;
    }

    // remove the first item
    lru.remove_if([](IntMapPair const& rPair) { return (rPair.first == 5); });
    CPPUNIT_ASSERT_EQUAL(size_t(1), lru.size());

    // remove the only item
    lru.remove_if([](IntMapPair const& rPair) { return (rPair.first == 7); });
    CPPUNIT_ASSERT_EQUAL(size_t(0), lru.size());
}

void lru_map_test::testChangeMaxSize()
{
    o3tl::lru_map<intint> lru(3);
    CPPUNIT_ASSERT_EQUAL(size_t(0), lru.size());
    lru.insert({ 0, 0 });
    lru.insert({ 1, 1 });
    lru.insert({ 2, 2 });
    CPPUNIT_ASSERT_EQUAL(size_t(3), lru.size());
    lru.setMaxSize(1);
    CPPUNIT_ASSERT_EQUAL(size_t(1), lru.size());
}

void lru_map_test::testCustomItemSize()
{
    struct cost_is_value
    {
        size_t operator()(int i) { return i; };
    };
    o3tl::lru_map<intint, std::hash<int>, std::equal_to<int>, cost_is_value> lru(5);
    lru.insert({ 1, 1 });
    lru.insert({ 2, 2 });
    // Adding this one will remove the first one, since then the total
    // cost would be 6, more than the maximum 5.
    lru.insert({ 3, 3 });
    CPPUNIT_ASSERT_EQUAL(size_t(2), lru.size());
    CPPUNIT_ASSERT_EQUAL(size_t(5), lru.total_size());
    // Drop the last item.
    lru.remove_if([](std::pair<intint> i) { return i.first == 3; });
    CPPUNIT_ASSERT_EQUAL(size_t(1), lru.size());
    CPPUNIT_ASSERT_EQUAL(size_t(2), lru.total_size());
    // This should drop everything except for keeping this one (an exception that
    // keeps the last item inserted regardless of limit).
    lru.insert({ 4, 4 });
    CPPUNIT_ASSERT_EQUAL(size_t(1), lru.size());
    CPPUNIT_ASSERT_EQUAL(size_t(4), lru.total_size());
    lru.clear();
    CPPUNIT_ASSERT_EQUAL(size_t(0), lru.size());
    CPPUNIT_ASSERT_EQUAL(size_t(0), lru.total_size());
}

CPPUNIT_TEST_SUITE_REGISTRATION(lru_map_test);

/* vim:set shiftwidth=4 softtabstop=4 expandtab: */

Messung V0.5
C=94 H=93 G=93

¤ Dauer der Verarbeitung: 0.4 Sekunden  ¤

*© Formatika GbR, Deutschland






Wurzel

Suchen

Beweissystem der NASA

Beweissystem Isabelle

NIST Cobol Testsuite

Cephes Mathematical Library

Wiener Entwicklungsmethode

Haftungshinweis

Die Informationen auf dieser Webseite wurden nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit, noch Qualität der bereit gestellten Informationen zugesichert.

Bemerkung:

Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.