element_detection_unittest.cc 3.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102
  1. // Copyright 2017 The Chromium Authors. All rights reserved.
  2. // Use of this source code is governed by a BSD-style license that can be
  3. // found in the LICENSE file.
  4. #include "components/zucchini/element_detection.h"
  5. #include <map>
  6. #include <vector>
  7. #include "base/bind.h"
  8. #include "components/zucchini/buffer_view.h"
  9. #include "testing/gtest/include/gtest/gtest.h"
  10. namespace zucchini {
  11. namespace {
  12. // This test uses a mock archive format where regions are determined by their
  13. // consecutive byte values rather than parsing real executables.
  14. //
  15. // 0 - Padding or raw data (not mapped to an executable).
  16. // 1 - A Win32x86 executable.
  17. // 2 - A Win32x64 executable.
  18. //
  19. // So an example archive file of;
  20. // 0 1 1 1 0 1 1 0 0 2 2 2 2
  21. // contains (in order left to right):
  22. // - One padding byte
  23. // - Three byte Win32x86 executable
  24. // - One padding byte
  25. // - Two byte Win32x86 executable
  26. // - Two padding bytes
  27. // - Four byte Win32x64 executable
  28. class ElementDetectionTest : public ::testing::Test {
  29. protected:
  30. using ElementVector = std::vector<Element>;
  31. using ExeTypeMap = std::map<uint8_t, ExecutableType>;
  32. ElementDetectionTest()
  33. : exe_map_({{1, kExeTypeWin32X86}, {2, kExeTypeWin32X64}}) {}
  34. ElementVector TestElementFinder(std::vector<uint8_t> buffer) {
  35. ConstBufferView image(buffer.data(), buffer.size());
  36. ElementFinder finder(
  37. image,
  38. base::BindRepeating(
  39. [](ExeTypeMap exe_map, ConstBufferView image,
  40. ConstBufferView region) -> absl::optional<Element> {
  41. EXPECT_GE(region.begin(), image.begin());
  42. EXPECT_LE(region.end(), image.end());
  43. EXPECT_GE(region.size(), 0U);
  44. if (region[0] != 0) {
  45. offset_t length = 1;
  46. while (length < region.size() && region[length] == region[0])
  47. ++length;
  48. return Element{{0, length}, exe_map[region[0]]};
  49. }
  50. return absl::nullopt;
  51. },
  52. exe_map_, image));
  53. std::vector<Element> elements;
  54. for (auto element = finder.GetNext(); element; element = finder.GetNext()) {
  55. elements.push_back(*element);
  56. }
  57. return elements;
  58. }
  59. // Translation map from mock archive bytes to actual types used in Zucchini.
  60. ExeTypeMap exe_map_;
  61. };
  62. TEST_F(ElementDetectionTest, ElementFinderEmpty) {
  63. std::vector<uint8_t> buffer(10, 0);
  64. ElementFinder finder(
  65. ConstBufferView(buffer.data(), buffer.size()),
  66. base::BindRepeating([](ConstBufferView image) -> absl::optional<Element> {
  67. return absl::nullopt;
  68. }));
  69. EXPECT_EQ(absl::nullopt, finder.GetNext());
  70. }
  71. TEST_F(ElementDetectionTest, ElementFinder) {
  72. EXPECT_EQ(ElementVector(), TestElementFinder({}));
  73. EXPECT_EQ(ElementVector(), TestElementFinder({0, 0}));
  74. EXPECT_EQ(ElementVector({{{0, 2}, kExeTypeWin32X86}}),
  75. TestElementFinder({1, 1}));
  76. EXPECT_EQ(
  77. ElementVector({{{0, 2}, kExeTypeWin32X86}, {{2, 2}, kExeTypeWin32X64}}),
  78. TestElementFinder({1, 1, 2, 2}));
  79. EXPECT_EQ(ElementVector({{{1, 2}, kExeTypeWin32X86}}),
  80. TestElementFinder({0, 1, 1, 0}));
  81. EXPECT_EQ(
  82. ElementVector({{{1, 2}, kExeTypeWin32X86}, {{3, 3}, kExeTypeWin32X64}}),
  83. TestElementFinder({0, 1, 1, 2, 2, 2}));
  84. EXPECT_EQ(
  85. ElementVector({{{1, 2}, kExeTypeWin32X86}, {{4, 3}, kExeTypeWin32X64}}),
  86. TestElementFinder({0, 1, 1, 0, 2, 2, 2}));
  87. }
  88. } // namespace
  89. } // namespace zucchini