aboutsummaryrefslogtreecommitdiff
path: root/element_detection_unittest.cc
diff options
context:
space:
mode:
authorCalder Kitagawa <ckitagawa@google.com>2018-04-24 13:54:46 +0000
committerEdward Lesmes <ehmaldonado@google.com>2021-07-23 22:09:53 +0000
commit05b1b6a1d8cfe2960959ff0ea3ecf96c4f198c54 (patch)
treec73343189a18e17ada847085bd27d0053e49d3ab /element_detection_unittest.cc
parent451ff5de400706acdfcfdb9bf28ca6d4c0670b81 (diff)
downloadzucchini-05b1b6a1d8cfe2960959ff0ea3ecf96c4f198c54.tar.gz
[Zucchini] Update ExecutableType values.
This change has some pros and some cons: Pros: - Human readable ExecType in patch/hex dumps as the ASCII is meaningful. - Can be done at next to no cost at compile time. - Assigning new values regardless of order of appearance in the enum is more flexible. No more concern over invalidating old patches as values will be more or less permanent once this change goes in. Cons: - Checking if an ExecutableType is valid requires O(n) time where n is the number of supported Exec types using a cast. Alternatively, we could maintain a sorted list of these types in memory to check against in O(log(n)) or could use a set but this is more memory. Overall not a huge deal since we only support ~9 types but it is worth understanding the tradeoffs. - Enums don't enforce value reuse so it is possible although highly unlikely we introduce a repeated value. However, given the use of the switch case casting requiring unique values this is very unlikely. Bug: 834932 Change-Id: I7bc14ea7b4434e60bb0dafa47178fb2c2c12dc7f Reviewed-on: https://chromium-review.googlesource.com/1020446 Commit-Queue: Calder Kitagawa <ckitagawa@google.com> Reviewed-by: Samuel Huang <huangs@chromium.org> Cr-Commit-Position: refs/heads/master@{#553083} NOKEYCHECK=True GitOrigin-RevId: da4335f0d27c7fa14f6897ffeb0833d424860f7e
Diffstat (limited to 'element_detection_unittest.cc')
-rw-r--r--element_detection_unittest.cc91
1 files changed, 57 insertions, 34 deletions
diff --git a/element_detection_unittest.cc b/element_detection_unittest.cc
index 2200c0b..6dbfa3f 100644
--- a/element_detection_unittest.cc
+++ b/element_detection_unittest.cc
@@ -11,14 +11,65 @@
#include "testing/gtest/include/gtest/gtest.h"
namespace zucchini {
-
namespace {
+// This test uses a mock archive format where regions are determined by their
+// consecutive byte values rather than parsing real executables.
+//
+// 0 - Padding or raw data (not mapped to an executable).
+// 1 - A Win32x86 executable.
+// 2 - A Win32x64 executable.
+//
+// So an example archive file of;
+// 0 1 1 1 0 1 1 0 0 2 2 2 2
+// contains (in order left to right):
+// - One padding byte
+// - Three byte Win32x86 executable
+// - One padding byte
+// - Two byte Win32x86 executable
+// - Two padding bytes
+// - Four byte Win32x64 executable
-using ElementVector = std::vector<Element>;
+class ElementDetectionTest : public ::testing::Test {
+ protected:
+ using ElementVector = std::vector<Element>;
+ using ExeTypeMap = std::map<uint8_t, ExecutableType>;
-} // namespace
+ ElementDetectionTest()
+ : exe_map_({{1, kExeTypeWin32X86}, {2, kExeTypeWin32X64}}) {}
+
+ ElementVector TestElementFinder(std::vector<uint8_t> buffer) {
+ ConstBufferView image(buffer.data(), buffer.size());
+
+ ElementFinder finder(
+ image,
+ base::BindRepeating(
+ [](ExeTypeMap exe_map, ConstBufferView image,
+ ConstBufferView region) -> base::Optional<Element> {
+ EXPECT_GE(region.begin(), image.begin());
+ EXPECT_LE(region.end(), image.end());
+ EXPECT_GE(region.size(), 0U);
+
+ if (region[0] != 0) {
+ offset_t length = 1;
+ while (length < region.size() && region[length] == region[0])
+ ++length;
+ return Element{{0, length}, exe_map[region[0]]};
+ }
+ return base::nullopt;
+ },
+ exe_map_, image));
+ std::vector<Element> elements;
+ for (auto element = finder.GetNext(); element; element = finder.GetNext()) {
+ elements.push_back(*element);
+ }
+ return elements;
+ }
+
+ // Translation map from mock archive bytes to actual types used in Zucchini.
+ ExeTypeMap exe_map_;
+};
-TEST(ElementDetectionTest, ElementFinderEmpty) {
+TEST_F(ElementDetectionTest, ElementFinderEmpty) {
std::vector<uint8_t> buffer(10, 0);
ElementFinder finder(
ConstBufferView(buffer.data(), buffer.size()),
@@ -28,36 +79,7 @@ TEST(ElementDetectionTest, ElementFinderEmpty) {
EXPECT_EQ(base::nullopt, finder.GetNext());
}
-ElementVector TestElementFinder(std::vector<uint8_t> buffer) {
- ConstBufferView image(buffer.data(), buffer.size());
-
- ElementFinder finder(
- image,
- base::BindRepeating(
- [](ConstBufferView image,
- ConstBufferView region) -> base::Optional<Element> {
- EXPECT_GE(region.begin(), image.begin());
- EXPECT_LE(region.end(), image.end());
- EXPECT_GE(region.size(), 0U);
-
- if (region[0] != 0) {
- offset_t length = 1;
- while (length < region.size() && region[length] == region[0])
- ++length;
- return Element{{0, length},
- static_cast<ExecutableType>(region[0])};
- }
- return base::nullopt;
- },
- image));
- std::vector<Element> elements;
- for (auto element = finder.GetNext(); element; element = finder.GetNext()) {
- elements.push_back(*element);
- }
- return elements;
-}
-
-TEST(ElementDetectionTest, ElementFinder) {
+TEST_F(ElementDetectionTest, ElementFinder) {
EXPECT_EQ(ElementVector(), TestElementFinder({}));
EXPECT_EQ(ElementVector(), TestElementFinder({0, 0}));
EXPECT_EQ(ElementVector({{{0, 2}, kExeTypeWin32X86}}),
@@ -75,4 +97,5 @@ TEST(ElementDetectionTest, ElementFinder) {
TestElementFinder({0, 1, 1, 0, 2, 2, 2}));
}
+} // namespace
} // namespace zucchini