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 |