// Copyright 2017 The Chromium Authors. All rights reserved. // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. #include "components/zucchini/element_detection.h" #include #include #include "base/bind.h" #include "components/zucchini/buffer_view.h" #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 class ElementDetectionTest : public ::testing::Test { protected: using ElementVector = std::vector; using ExeTypeMap = std::map; ElementDetectionTest() : exe_map_({{1, kExeTypeWin32X86}, {2, kExeTypeWin32X64}}) {} ElementVector TestElementFinder(std::vector buffer) { ConstBufferView image(buffer.data(), buffer.size()); ElementFinder finder( image, base::BindRepeating( [](ExeTypeMap exe_map, ConstBufferView image, ConstBufferView region) -> absl::optional { 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 absl::nullopt; }, exe_map_, image)); std::vector 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_F(ElementDetectionTest, ElementFinderEmpty) { std::vector buffer(10, 0); ElementFinder finder( ConstBufferView(buffer.data(), buffer.size()), base::BindRepeating([](ConstBufferView image) -> absl::optional { return absl::nullopt; })); EXPECT_EQ(absl::nullopt, finder.GetNext()); } TEST_F(ElementDetectionTest, ElementFinder) { EXPECT_EQ(ElementVector(), TestElementFinder({})); EXPECT_EQ(ElementVector(), TestElementFinder({0, 0})); EXPECT_EQ(ElementVector({{{0, 2}, kExeTypeWin32X86}}), TestElementFinder({1, 1})); EXPECT_EQ( ElementVector({{{0, 2}, kExeTypeWin32X86}, {{2, 2}, kExeTypeWin32X64}}), TestElementFinder({1, 1, 2, 2})); EXPECT_EQ(ElementVector({{{1, 2}, kExeTypeWin32X86}}), TestElementFinder({0, 1, 1, 0})); EXPECT_EQ( ElementVector({{{1, 2}, kExeTypeWin32X86}, {{3, 3}, kExeTypeWin32X64}}), TestElementFinder({0, 1, 1, 2, 2, 2})); EXPECT_EQ( ElementVector({{{1, 2}, kExeTypeWin32X86}, {{4, 3}, kExeTypeWin32X64}}), TestElementFinder({0, 1, 1, 0, 2, 2, 2})); } } // namespace } // namespace zucchini