| Index: mojo/public/cpp/bindings/tests/bounds_checker_unittest.cc
|
| diff --git a/mojo/public/cpp/bindings/tests/bounds_checker_unittest.cc b/mojo/public/cpp/bindings/tests/bounds_checker_unittest.cc
|
| new file mode 100644
|
| index 0000000000000000000000000000000000000000..2c25396292b23009414e79a9e47e7e6bed730e4e
|
| --- /dev/null
|
| +++ b/mojo/public/cpp/bindings/tests/bounds_checker_unittest.cc
|
| @@ -0,0 +1,211 @@
|
| +// Copyright 2014 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 <limits>
|
| +
|
| +#include "mojo/public/cpp/bindings/lib/bindings_serialization.h"
|
| +#include "mojo/public/cpp/bindings/lib/bounds_checker.h"
|
| +#include "mojo/public/cpp/system/core.h"
|
| +#include "testing/gtest/include/gtest/gtest.h"
|
| +
|
| +namespace mojo {
|
| +namespace test {
|
| +namespace {
|
| +
|
| +const void* ToPtr(uintptr_t ptr) {
|
| + return reinterpret_cast<const void*>(ptr);
|
| +}
|
| +
|
| +bool AreEqualVectors(const std::vector<uintptr_t>& actual_values,
|
| + const uintptr_t* expected_values,
|
| + size_t expected_value_count) {
|
| + if (actual_values.size() != expected_value_count)
|
| + return false;
|
| +
|
| + for (size_t i = 0; i < expected_value_count; ++i) {
|
| + if (actual_values[i] != expected_values[i])
|
| + return false;
|
| + }
|
| + return true;
|
| +}
|
| +
|
| +#ifdef NDEBUG
|
| +TEST(BoundsCheckerTest, MemoryRangeOverflow) {
|
| + internal::BoundsChecker
|
| + checker(ToPtr(std::numeric_limits<uintptr_t>::max() - 3000), 5000, 0);
|
| +
|
| + EXPECT_FALSE(checker.IsWithinBounds(
|
| + ToPtr(std::numeric_limits<uintptr_t>::max() - 3000), 1));
|
| + EXPECT_FALSE(checker.ClaimMemory(
|
| + ToPtr(std::numeric_limits<uintptr_t>::max() - 3000), 1));
|
| +}
|
| +#endif
|
| +
|
| +TEST(BoundsCheckerTest, IsWithinBounds) {
|
| + {
|
| + internal::BoundsChecker checker(ToPtr(1234), 100, 0);
|
| +
|
| + // Basics.
|
| + EXPECT_FALSE(checker.IsWithinBounds(ToPtr(100), 5));
|
| + EXPECT_FALSE(checker.IsWithinBounds(ToPtr(1230), 50));
|
| + EXPECT_TRUE(checker.IsWithinBounds(ToPtr(1234), 5));
|
| + EXPECT_TRUE(checker.IsWithinBounds(ToPtr(1240), 50));
|
| + EXPECT_TRUE(checker.IsWithinBounds(ToPtr(1234), 100));
|
| + EXPECT_FALSE(checker.IsWithinBounds(ToPtr(1234), 200));
|
| + EXPECT_FALSE(checker.IsWithinBounds(ToPtr(1240), 100));
|
| + EXPECT_FALSE(checker.IsWithinBounds(ToPtr(2234), 5));
|
| +
|
| + // Should return false for empty ranges.
|
| + EXPECT_FALSE(checker.IsWithinBounds(ToPtr(0), 0));
|
| + EXPECT_FALSE(checker.IsWithinBounds(ToPtr(1200), 0));
|
| + EXPECT_FALSE(checker.IsWithinBounds(ToPtr(1234), 0));
|
| + EXPECT_FALSE(checker.IsWithinBounds(ToPtr(1240), 0));
|
| + EXPECT_FALSE(checker.IsWithinBounds(ToPtr(2234), 0));
|
| + }
|
| +
|
| + {
|
| + // The valid memory range is empty.
|
| + internal::BoundsChecker checker(ToPtr(1234), 0, 0);
|
| +
|
| + EXPECT_FALSE(checker.IsWithinBounds(ToPtr(1234), 1));
|
| + EXPECT_FALSE(checker.IsWithinBounds(ToPtr(1234), 0));
|
| + }
|
| +
|
| + {
|
| + internal::BoundsChecker
|
| + checker(ToPtr(std::numeric_limits<uintptr_t>::max() - 2000), 1000, 0);
|
| +
|
| + // Test overflow.
|
| + EXPECT_FALSE(checker.IsWithinBounds(
|
| + ToPtr(std::numeric_limits<uintptr_t>::max() - 1500), 4000));
|
| + EXPECT_FALSE(checker.IsWithinBounds(
|
| + ToPtr(std::numeric_limits<uintptr_t>::max() - 1500),
|
| + std::numeric_limits<uint32_t>::max()));
|
| +
|
| + // This should be fine.
|
| + EXPECT_TRUE(checker.IsWithinBounds(
|
| + ToPtr(std::numeric_limits<uintptr_t>::max() - 1500), 200));
|
| + }
|
| +}
|
| +
|
| +TEST(BoundsCheckerTest, ClaimHandle) {
|
| + {
|
| + internal::BoundsChecker checker(ToPtr(0), 0, 10);
|
| +
|
| + // Basics.
|
| + EXPECT_TRUE(checker.ClaimHandle(Handle(0)));
|
| + EXPECT_FALSE(checker.ClaimHandle(Handle(0)));
|
| +
|
| + EXPECT_TRUE(checker.ClaimHandle(Handle(9)));
|
| + EXPECT_FALSE(checker.ClaimHandle(Handle(10)));
|
| +
|
| + // Should return true for invalid handle.
|
| + EXPECT_TRUE(
|
| + checker.ClaimHandle(Handle(internal::kEncodedInvalidHandleValue)));
|
| + EXPECT_TRUE(
|
| + checker.ClaimHandle(Handle(internal::kEncodedInvalidHandleValue)));
|
| + }
|
| +
|
| + {
|
| + // No handle to claim.
|
| + internal::BoundsChecker checker(ToPtr(0), 0, 0);
|
| +
|
| + EXPECT_FALSE(checker.ClaimHandle(Handle(0)));
|
| +
|
| + // Should still return true for invalid handle.
|
| + EXPECT_TRUE(
|
| + checker.ClaimHandle(Handle(internal::kEncodedInvalidHandleValue)));
|
| + }
|
| +}
|
| +
|
| +TEST(BoundsCheckerTest, ClaimMemory) {
|
| + {
|
| + internal::BoundsChecker checker(ToPtr(1000), 2000, 0);
|
| +
|
| + // Basics.
|
| + EXPECT_FALSE(checker.ClaimMemory(ToPtr(500), 100));
|
| + EXPECT_FALSE(checker.ClaimMemory(ToPtr(800), 300));
|
| + EXPECT_TRUE(checker.ClaimMemory(ToPtr(1000), 100));
|
| + EXPECT_FALSE(checker.ClaimMemory(ToPtr(1099), 100));
|
| + EXPECT_TRUE(checker.ClaimMemory(ToPtr(1100), 200));
|
| + EXPECT_FALSE(checker.ClaimMemory(ToPtr(2000), 1001));
|
| + EXPECT_TRUE(checker.ClaimMemory(ToPtr(2000), 1000));
|
| + EXPECT_FALSE(checker.ClaimMemory(ToPtr(3000), 1));
|
| +
|
| + // Test that we cannot claim a range that overlaps an existing one.
|
| + EXPECT_TRUE(checker.ClaimMemory(ToPtr(1400), 200));
|
| + // The same range.
|
| + EXPECT_FALSE(checker.ClaimMemory(ToPtr(1400), 200));
|
| + // Inclusion.
|
| + EXPECT_FALSE(checker.ClaimMemory(ToPtr(1450), 100));
|
| + // The head overlaps an existing range.
|
| + EXPECT_FALSE(checker.ClaimMemory(ToPtr(1450), 200));
|
| + // The tail overlaps an existing range.
|
| + EXPECT_FALSE(checker.ClaimMemory(ToPtr(1350), 200));
|
| + }
|
| +
|
| + {
|
| + // No memory to claim.
|
| + internal::BoundsChecker checker(ToPtr(10000), 0, 0);
|
| +
|
| + EXPECT_FALSE(checker.ClaimMemory(ToPtr(10000), 1));
|
| + EXPECT_FALSE(checker.ClaimMemory(ToPtr(10000), 0));
|
| + }
|
| +
|
| + {
|
| + internal::BoundsChecker checker(ToPtr(1000), 2000, 0);
|
| +
|
| + // Test the internal state of claimed ranges.
|
| + EXPECT_TRUE(checker.ClaimMemory(ToPtr(2150), 50));
|
| + EXPECT_EQ(2u, checker.GetClaimedRangesForTesting().size());
|
| +
|
| + EXPECT_TRUE(checker.ClaimMemory(ToPtr(2350), 50));
|
| + EXPECT_EQ(4u, checker.GetClaimedRangesForTesting().size());
|
| +
|
| + EXPECT_TRUE(checker.ClaimMemory(ToPtr(2250), 50));
|
| + uintptr_t expected_values1[] = {2150, 2200, 2250, 2300, 2350, 2400};
|
| + EXPECT_TRUE(AreEqualVectors(checker.GetClaimedRangesForTesting(),
|
| + expected_values1, 6u));
|
| +
|
| + EXPECT_TRUE(checker.ClaimMemory(ToPtr(2300), 25));
|
| + uintptr_t expected_values2[] = {2150, 2200, 2250, 2325, 2350, 2400};
|
| + EXPECT_TRUE(AreEqualVectors(checker.GetClaimedRangesForTesting(),
|
| + expected_values2, 6u));
|
| +
|
| + EXPECT_TRUE(checker.ClaimMemory(ToPtr(2050), 100));
|
| + uintptr_t expected_values3[] = {2050, 2200, 2250, 2325, 2350, 2400};
|
| + EXPECT_TRUE(AreEqualVectors(checker.GetClaimedRangesForTesting(),
|
| + expected_values3, 6u));
|
| +
|
| + EXPECT_TRUE(checker.ClaimMemory(ToPtr(2200), 50));
|
| + uintptr_t expected_values4[] = {2050, 2325, 2350, 2400};
|
| + EXPECT_TRUE(AreEqualVectors(checker.GetClaimedRangesForTesting(),
|
| + expected_values4, 4u));
|
| +
|
| + EXPECT_TRUE(checker.ClaimMemory(ToPtr(2325), 25));
|
| + uintptr_t expected_values5[] = {2050, 2400};
|
| + EXPECT_TRUE(AreEqualVectors(checker.GetClaimedRangesForTesting(),
|
| + expected_values5, 2u));
|
| + }
|
| +
|
| + {
|
| + internal::BoundsChecker
|
| + checker(ToPtr(std::numeric_limits<uintptr_t>::max() - 1000), 500, 0);
|
| +
|
| + // Test overflow.
|
| + EXPECT_FALSE(checker.ClaimMemory(
|
| + ToPtr(std::numeric_limits<uintptr_t>::max() - 750), 4000));
|
| + EXPECT_FALSE(checker.ClaimMemory(
|
| + ToPtr(std::numeric_limits<uintptr_t>::max() - 750),
|
| + std::numeric_limits<uint32_t>::max()));
|
| +
|
| + // This should be fine.
|
| + EXPECT_TRUE(checker.ClaimMemory(
|
| + ToPtr(std::numeric_limits<uintptr_t>::max() - 750), 200));
|
| + }
|
| +}
|
| +
|
| +} // namespace
|
| +} // namespace test
|
| +} // namespace mojo
|
|
|