// Copyright 2013 Google LLC
//
// 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 Google LLC 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.

// Unittests for OMAP related functions.

#ifdef HAVE_CONFIG_H
#include <config.h>  // Must come first
#endif

#include "common/windows/omap.h"

#include "breakpad_googletest_includes.h"

namespace google_breakpad {

// Equality operators for ContainerEq. These must be outside of the anonymous
// namespace in order for them to be found.
bool operator==(const MappedRange& mr1, const MappedRange& mr2) {
  return mr1.rva_original == mr2.rva_original &&
      mr1.rva_transformed == mr2.rva_transformed &&
      mr1.length == mr2.length &&
      mr1.injected == mr2.injected &&
      mr1.removed == mr2.removed;
}
bool operator==(const EndpointIndex& ei1, const EndpointIndex& ei2) {
  return ei1.endpoint == ei2.endpoint && ei1.index == ei2.index;
}

// Pretty printers for more meaningful error messages. Also need to be outside
// the anonymous namespace.
std::ostream& operator<<(std::ostream& os, const MappedRange& mr) {
  os << "MappedRange(rva_original=" << mr.rva_original
     << ", rva_transformed=" << mr.rva_transformed
     << ", length=" << mr.length
     << ", injected=" << mr.injected
     << ", removed=" << mr.removed << ")";
  return os;
}
std::ostream& operator<<(std::ostream& os, const EndpointIndex& ei) {
  os << "EndpointIndex(endpoint=" << ei.endpoint
     << ", index=" << ei.index << ")";
  return os;
}
std::ostream& operator<<(std::ostream& os, const AddressRange& ar) {
  os << "AddressRange(rva=" << ar.rva << ", length=" << ar.length << ")";
  return os;
}

namespace {

OMAP CreateOmap(DWORD rva, DWORD rvaTo) {
  OMAP o = { rva, rvaTo };
  return o;
}

MappedRange CreateMappedRange(DWORD rva_original,
                              DWORD rva_transformed,
                              DWORD length,
                              DWORD injected,
                              DWORD removed) {
  MappedRange mr = { rva_original, rva_transformed, length, injected, removed };
  return mr;
}

EndpointIndex CreateEndpointIndex(DWORD endpoint, size_t index) {
  EndpointIndex ei = { endpoint, index };
  return ei;
}

//              (C is removed)
// Original   :  A B C D E F G H
// Transformed:  A B D F E * H1 G1 G2 H2
//              (* is injected, G is copied, H is split)
// A is implied.

// Layout of the original image.
const AddressRange B(100, 15);
const AddressRange C(B.end(), 10);
const AddressRange D(C.end(), 25);
const AddressRange E(D.end(), 10);
const AddressRange F(E.end(), 40);
const AddressRange G(F.end(), 3);
const AddressRange H(G.end(), 7);

// Layout of the transformed image.
const AddressRange Bt(100, 15);
const AddressRange Dt(Bt.end(), 20);  // D is shortened.
const AddressRange Ft(Dt.end(), F.length);
const AddressRange Et(Ft.end(), E.length);
const AddressRange injected(Et.end(), 5);
const AddressRange H1t(injected.end(), 4);  // H is split.
const AddressRange G1t(H1t.end(), G.length);  // G is copied.
const AddressRange G2t(G1t.end(), G.length);  // G is copied.
const AddressRange H2t(G2t.end(), 3);  // H is split.

class BuildImageMapTest : public testing::Test {
 public:
  static const DWORD kInvalidAddress = 0xFFFFFFFF;

  void InitOmapData() {
    omap_data.length_original = H.end();

    // Build the OMAPTO vector (from transformed to original).
    omap_data.omap_to.push_back(CreateOmap(Bt.rva, B.rva));
    omap_data.omap_to.push_back(CreateOmap(Dt.rva, D.rva));
    omap_data.omap_to.push_back(CreateOmap(Ft.rva, F.rva));
    omap_data.omap_to.push_back(CreateOmap(Et.rva, E.rva));
    omap_data.omap_to.push_back(CreateOmap(injected.rva, kInvalidAddress));
    omap_data.omap_to.push_back(CreateOmap(H1t.rva, H.rva));
    omap_data.omap_to.push_back(CreateOmap(G1t.rva, G.rva));
    omap_data.omap_to.push_back(CreateOmap(G2t.rva, G.rva));
    omap_data.omap_to.push_back(CreateOmap(H2t.rva, H.rva + H1t.length));
    omap_data.omap_to.push_back(CreateOmap(H2t.end(), kInvalidAddress));

    // Build the OMAPFROM vector (from original to transformed).
    omap_data.omap_from.push_back(CreateOmap(B.rva, Bt.rva));
    omap_data.omap_from.push_back(CreateOmap(C.rva, kInvalidAddress));
    omap_data.omap_from.push_back(CreateOmap(D.rva, Dt.rva));
    omap_data.omap_from.push_back(CreateOmap(E.rva, Et.rva));
    omap_data.omap_from.push_back(CreateOmap(F.rva, Ft.rva));
    omap_data.omap_from.push_back(CreateOmap(G.rva, G1t.rva));
    omap_data.omap_from.push_back(CreateOmap(H.rva, H1t.rva));
    omap_data.omap_from.push_back(CreateOmap(H.rva + H1t.length, H2t.rva));
    omap_data.omap_from.push_back(CreateOmap(H.end(), kInvalidAddress));
  }

  OmapData omap_data;
};

}  // namespace

TEST_F(BuildImageMapTest, EmptyImageMapOnEmptyOmapData) {
  ASSERT_EQ(0u, omap_data.omap_from.size());
  ASSERT_EQ(0u, omap_data.omap_to.size());
  ASSERT_EQ(0u, omap_data.length_original);

  ImageMap image_map;
  BuildImageMap(omap_data, &image_map);
  EXPECT_EQ(0u, image_map.mapping.size());
  EXPECT_EQ(0u, image_map.endpoint_index_map.size());
}

TEST_F(BuildImageMapTest, ImageMapIsCorrect) {
  InitOmapData();
  ASSERT_LE(0u, omap_data.omap_from.size());
  ASSERT_LE(0u, omap_data.omap_to.size());
  ASSERT_LE(0u, omap_data.length_original);

  ImageMap image_map;
  BuildImageMap(omap_data, &image_map);
  EXPECT_LE(9u, image_map.mapping.size());
  EXPECT_LE(9u, image_map.endpoint_index_map.size());

  Mapping mapping;
  mapping.push_back(CreateMappedRange(0, 0, B.rva, 0, 0));
  // C is removed, and it originally comes immediately after B.
  mapping.push_back(CreateMappedRange(B.rva, Bt.rva, B.length, 0, C.length));
  // D is shortened by a length of 5.
  mapping.push_back(CreateMappedRange(D.rva, Dt.rva, Dt.length, 0, 5));
  // The injected content comes immediately after E in the transformed image.
  mapping.push_back(CreateMappedRange(E.rva, Et.rva, E.length, injected.length,
                                      0));
  mapping.push_back(CreateMappedRange(F.rva, Ft.rva, F.length, 0, 0));
  // G is copied so creates two entries.
  mapping.push_back(CreateMappedRange(G.rva, G1t.rva, G.length, 0, 0));
  mapping.push_back(CreateMappedRange(G.rva, G2t.rva, G.length, 0, 0));
  // H is split, so create two entries.
  mapping.push_back(CreateMappedRange(H.rva, H1t.rva, H1t.length, 0, 0));
  mapping.push_back(CreateMappedRange(H.rva + H1t.length, H2t.rva, H2t.length,
                                      0, 0));
  EXPECT_THAT(mapping,
              testing::ContainerEq(image_map.mapping));

  EndpointIndexMap endpoint_index_map;
  endpoint_index_map.push_back(CreateEndpointIndex(0, 0));
  endpoint_index_map.push_back(CreateEndpointIndex(B.rva, 1));
  endpoint_index_map.push_back(CreateEndpointIndex(D.rva, 2));
  endpoint_index_map.push_back(CreateEndpointIndex(E.rva, 3));
  endpoint_index_map.push_back(CreateEndpointIndex(F.rva, 4));
  // G is duplicated so 2 ranges map back to it, hence the skip from 5 to 7.
  endpoint_index_map.push_back(CreateEndpointIndex(G.rva, 5));
  // H is split so we expect 2 endpoints to show up attributed to it.
  endpoint_index_map.push_back(CreateEndpointIndex(H.rva, 7));
  endpoint_index_map.push_back(CreateEndpointIndex(H.rva + H1t.length, 8));
  endpoint_index_map.push_back(CreateEndpointIndex(H.end(), 9));
  EXPECT_THAT(endpoint_index_map,
              testing::ContainerEq(image_map.endpoint_index_map));
}

namespace {

class MapAddressRangeTest : public BuildImageMapTest {
 public:
  typedef BuildImageMapTest Super;
  virtual void SetUp() {
    Super::SetUp();
    InitOmapData();
    BuildImageMap(omap_data, &image_map);
  }

  ImageMap image_map;

 private:
  using BuildImageMapTest::InitOmapData;
  using BuildImageMapTest::omap_data;
};

}  // namespace

TEST_F(MapAddressRangeTest, EmptyImageMapReturnsIdentity) {
  ImageMap im;
  AddressRangeVector mapped_ranges;
  AddressRange ar(0, 1024);
  MapAddressRange(im, ar, &mapped_ranges);
  EXPECT_EQ(1u, mapped_ranges.size());
  EXPECT_EQ(ar, mapped_ranges[0]);
}

TEST_F(MapAddressRangeTest, MapOutOfImage) {
  AddressRangeVector mapped_ranges;
  MapAddressRange(image_map, AddressRange(H.end() + 10, 10), &mapped_ranges);
  EXPECT_EQ(0u, mapped_ranges.size());
}

TEST_F(MapAddressRangeTest, MapIdentity) {
  AddressRangeVector mapped_ranges;
  MapAddressRange(image_map, B, &mapped_ranges);
  EXPECT_EQ(1u, mapped_ranges.size());
  EXPECT_THAT(mapped_ranges, testing::ElementsAre(B));
}

TEST_F(MapAddressRangeTest, MapReorderedContiguous) {
  AddressRangeVector mapped_ranges;

  AddressRange DEF(D.rva, F.end() - D.rva);
  MapAddressRange(image_map, DEF, &mapped_ranges);
  EXPECT_EQ(1u, mapped_ranges.size());

  AddressRange DFEt(Dt.rva, Et.end() - Dt.rva);
  EXPECT_THAT(mapped_ranges, testing::ElementsAre(DFEt));
}

TEST_F(MapAddressRangeTest, MapEmptySingle) {
  AddressRangeVector mapped_ranges;
  MapAddressRange(image_map, AddressRange(D.rva, 0), &mapped_ranges);
  EXPECT_EQ(1u, mapped_ranges.size());
  EXPECT_THAT(mapped_ranges, testing::ElementsAre(AddressRange(Dt.rva, 0)));
}

TEST_F(MapAddressRangeTest, MapEmptyCopied) {
  AddressRangeVector mapped_ranges;
  MapAddressRange(image_map, AddressRange(G.rva, 0), &mapped_ranges);
  EXPECT_EQ(2u, mapped_ranges.size());
  EXPECT_THAT(mapped_ranges, testing::ElementsAre(AddressRange(G1t.rva, 0),
                                                  AddressRange(G2t.rva, 0)));
}

TEST_F(MapAddressRangeTest, MapCopiedContiguous) {
  AddressRangeVector mapped_ranges;
  MapAddressRange(image_map, G, &mapped_ranges);
  EXPECT_EQ(1u, mapped_ranges.size());
  EXPECT_THAT(mapped_ranges, testing::ElementsAre(
      AddressRange(G1t.rva, G2t.end() - G1t.rva)));
}

TEST_F(MapAddressRangeTest, MapSplitDiscontiguous) {
  AddressRangeVector mapped_ranges;
  MapAddressRange(image_map, H, &mapped_ranges);
  EXPECT_EQ(2u, mapped_ranges.size());
  EXPECT_THAT(mapped_ranges, testing::ElementsAre(H1t, H2t));
}

TEST_F(MapAddressRangeTest, MapInjected) {
  AddressRangeVector mapped_ranges;

  AddressRange EFGH(E.rva, H.end() - E.rva);
  MapAddressRange(image_map, EFGH, &mapped_ranges);
  EXPECT_EQ(1u, mapped_ranges.size());

  AddressRange FEHGGHt(Ft.rva, H2t.end() - Ft.rva);
  EXPECT_THAT(mapped_ranges, testing::ElementsAre(FEHGGHt));
}

TEST_F(MapAddressRangeTest, MapRemovedEntirely) {
  AddressRangeVector mapped_ranges;
  MapAddressRange(image_map, C, &mapped_ranges);
  EXPECT_EQ(0u, mapped_ranges.size());
}

TEST_F(MapAddressRangeTest, MapRemovedPartly) {
  AddressRangeVector mapped_ranges;
  MapAddressRange(image_map, D, &mapped_ranges);
  EXPECT_EQ(1u, mapped_ranges.size());
  EXPECT_THAT(mapped_ranges, testing::ElementsAre(Dt));
}

TEST_F(MapAddressRangeTest, MapFull) {
  AddressRangeVector mapped_ranges;

  AddressRange AH(0, H.end());
  MapAddressRange(image_map, AH, &mapped_ranges);
  EXPECT_EQ(1u, mapped_ranges.size());

  AddressRange AHt(0, H2t.end());
  EXPECT_THAT(mapped_ranges, testing::ElementsAre(AHt));
}

}  // namespace google_breakpad
