/*
 * Copyright 2023 Google, Inc.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions are
 * met: redistributions of source code must retain the above copyright
 * notice, this list of conditions and the following disclaimer;
 * redistributions in binary form must reproduce the above copyright
 * notice, this list of conditions and the following disclaimer in the
 * documentation and/or other materials provided with the distribution;
 * neither the name of the copyright holders nor the names of its
 * contributors may be used to endorse or promote products derived from
 * this software without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 */

#include <gtest/gtest.h>
#include <vector>

#include "base/addr_range.hh"
#include "base/gtest/logging.hh"
#include "mem/backdoor.hh"
#include "mem/backdoor_manager.hh"

namespace gem5
{
namespace backdoor_manager_test
{
const std::vector<AddrRange> kOriginalRange({AddrRange(0x0, 0x1000)});
const std::vector<AddrRange> kRemappedRange({AddrRange(0x1000, 0x2000)});

class BackdoorManagerTest : public BackdoorManager, public ::testing::Test
{
  public:
    BackdoorManagerTest() : BackdoorManager(kOriginalRange, kRemappedRange)
    {
    }
};

TEST_F(BackdoorManagerTest, BasicRemapTest)
{
    /**
     * The backdoor range is remappedRanges[0], and should be reverted into
     * originalRanges[0].
     */
    AddrRange pkt_range = originalRanges[0];

    uint8_t *ptr = nullptr;
    MemBackdoor remapped_backdoor(remappedRanges[0], ptr,
                                  MemBackdoor::Flags::Readable);
    MemBackdoorPtr reverted_backdoor =
        getRevertedBackdoor(&remapped_backdoor, pkt_range);

    EXPECT_EQ(reverted_backdoor->range(), originalRanges[0]);
    EXPECT_EQ(reverted_backdoor->ptr(), ptr);
    ASSERT_EQ(backdoorLists[0].size(), 1);
    EXPECT_EQ(backdoorLists[0].begin()->get(), reverted_backdoor);

    /**
     * After the target backdoor is invalidated, the new created backdoor should
     * be freed and removed from the backdoor list.
     */
    remapped_backdoor.invalidate();
    EXPECT_EQ(backdoorLists[0].size(), 0);
}

TEST_F(BackdoorManagerTest, ShrinkTest)
{
    AddrRange pkt_range = originalRanges[0];

    /**
     * The backdoor range is larger than the address remapper's address range.
     * Backdoor is expected to be shrinked.
     */
    Addr diff = 0x1000;
    AddrRange remapped_backdoor_range(
        remappedRanges[0].start() - diff,  // 0x0
        remappedRanges[0].end() + diff);   // 0x3000

    uint8_t *ptr = nullptr;
    MemBackdoor remapped_backdoor(remapped_backdoor_range, ptr,
                                  MemBackdoor::Flags::Readable);
    MemBackdoorPtr reverted_backdoor =
        getRevertedBackdoor(&remapped_backdoor, pkt_range);

    EXPECT_EQ(reverted_backdoor->range(), originalRanges[0]);
    EXPECT_EQ(reverted_backdoor->ptr(), ptr + diff);

    remapped_backdoor.invalidate();
}

TEST_F(BackdoorManagerTest, ReuseTest)
{
    /**
     * The two packets have different address range, but both contained in the
     * original address range.
     */
    Addr mid = originalRanges[0].start() + originalRanges[0].size() / 2;
    AddrRange pkt_range_0 = AddrRange(originalRanges[0].start(), mid);
    AddrRange pkt_range_1 = AddrRange(mid, originalRanges[0].end());

    /**
     * The address range of the backdoor covers the whole address range, so
     * both packets can be fulfilled by this backdoor.
     */
    uint8_t *ptr = nullptr;
    MemBackdoor remapped_backdoor(remappedRanges[0], ptr,
                                  MemBackdoor::Flags::Readable);
    /**
     * For the first packet, a new backdoor should be constructed.
     */
    MemBackdoorPtr reverted_backdoor_0 =
        getRevertedBackdoor(&remapped_backdoor, pkt_range_0);
    EXPECT_EQ(backdoorLists[0].size(), 1);

    /**
     * For the second packet, it should return the same backdoor as previous
     * one, and no new backdoor should be constructed.
     */
    MemBackdoorPtr reverted_backdoor_1 =
        getRevertedBackdoor(&remapped_backdoor, pkt_range_1);
    EXPECT_EQ(reverted_backdoor_0, reverted_backdoor_1);
    EXPECT_EQ(backdoorLists[0].size(), 1);

    remapped_backdoor.invalidate();
}

}  // namespace backdoor_manager_test
}  // namespace gem5
