| OLD | NEW |
| (Empty) |
| 1 // Copyright 2014 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 | |
| 5 #include "mojo/system/options_validation.h" | |
| 6 | |
| 7 #include <stddef.h> | |
| 8 #include <stdint.h> | |
| 9 | |
| 10 #include "mojo/public/c/system/macros.h" | |
| 11 #include "testing/gtest/include/gtest/gtest.h" | |
| 12 | |
| 13 namespace mojo { | |
| 14 namespace system { | |
| 15 namespace { | |
| 16 | |
| 17 // Declare a test options struct just as we do in actual public headers. | |
| 18 | |
| 19 typedef uint32_t TestOptionsFlags; | |
| 20 | |
| 21 MOJO_COMPILE_ASSERT(MOJO_ALIGNOF(int64_t) == 8, int64_t_has_weird_alignment); | |
| 22 struct MOJO_ALIGNAS(8) TestOptions { | |
| 23 uint32_t struct_size; | |
| 24 TestOptionsFlags flags; | |
| 25 uint32_t member1; | |
| 26 uint32_t member2; | |
| 27 }; | |
| 28 MOJO_COMPILE_ASSERT(sizeof(TestOptions) == 16, TestOptions_has_wrong_size); | |
| 29 | |
| 30 const uint32_t kSizeOfTestOptions = static_cast<uint32_t>(sizeof(TestOptions)); | |
| 31 | |
| 32 TEST(OptionsValidationTest, Valid) { | |
| 33 { | |
| 34 const TestOptions kOptions = {kSizeOfTestOptions}; | |
| 35 UserOptionsReader<TestOptions> reader(MakeUserPointer(&kOptions)); | |
| 36 EXPECT_TRUE(reader.is_valid()); | |
| 37 EXPECT_TRUE(OPTIONS_STRUCT_HAS_MEMBER(TestOptions, flags, reader)); | |
| 38 EXPECT_TRUE(OPTIONS_STRUCT_HAS_MEMBER(TestOptions, member1, reader)); | |
| 39 EXPECT_TRUE(OPTIONS_STRUCT_HAS_MEMBER(TestOptions, member2, reader)); | |
| 40 } | |
| 41 { | |
| 42 const TestOptions kOptions = {static_cast<uint32_t>( | |
| 43 offsetof(TestOptions, struct_size) + sizeof(uint32_t))}; | |
| 44 UserOptionsReader<TestOptions> reader(MakeUserPointer(&kOptions)); | |
| 45 EXPECT_TRUE(reader.is_valid()); | |
| 46 EXPECT_FALSE(OPTIONS_STRUCT_HAS_MEMBER(TestOptions, flags, reader)); | |
| 47 EXPECT_FALSE(OPTIONS_STRUCT_HAS_MEMBER(TestOptions, member1, reader)); | |
| 48 EXPECT_FALSE(OPTIONS_STRUCT_HAS_MEMBER(TestOptions, member2, reader)); | |
| 49 } | |
| 50 | |
| 51 { | |
| 52 const TestOptions kOptions = { | |
| 53 static_cast<uint32_t>(offsetof(TestOptions, flags) + sizeof(uint32_t))}; | |
| 54 UserOptionsReader<TestOptions> reader(MakeUserPointer(&kOptions)); | |
| 55 EXPECT_TRUE(reader.is_valid()); | |
| 56 EXPECT_TRUE(OPTIONS_STRUCT_HAS_MEMBER(TestOptions, flags, reader)); | |
| 57 EXPECT_FALSE(OPTIONS_STRUCT_HAS_MEMBER(TestOptions, member1, reader)); | |
| 58 EXPECT_FALSE(OPTIONS_STRUCT_HAS_MEMBER(TestOptions, member2, reader)); | |
| 59 } | |
| 60 { | |
| 61 MOJO_ALIGNAS(8) char buf[sizeof(TestOptions) + 100] = {}; | |
| 62 TestOptions* options = reinterpret_cast<TestOptions*>(buf); | |
| 63 options->struct_size = kSizeOfTestOptions + 1; | |
| 64 UserOptionsReader<TestOptions> reader(MakeUserPointer(options)); | |
| 65 EXPECT_TRUE(reader.is_valid()); | |
| 66 EXPECT_TRUE(OPTIONS_STRUCT_HAS_MEMBER(TestOptions, flags, reader)); | |
| 67 EXPECT_TRUE(OPTIONS_STRUCT_HAS_MEMBER(TestOptions, member1, reader)); | |
| 68 EXPECT_TRUE(OPTIONS_STRUCT_HAS_MEMBER(TestOptions, member2, reader)); | |
| 69 } | |
| 70 { | |
| 71 MOJO_ALIGNAS(8) char buf[sizeof(TestOptions) + 100] = {}; | |
| 72 TestOptions* options = reinterpret_cast<TestOptions*>(buf); | |
| 73 options->struct_size = kSizeOfTestOptions + 4; | |
| 74 UserOptionsReader<TestOptions> reader(MakeUserPointer(options)); | |
| 75 EXPECT_TRUE(reader.is_valid()); | |
| 76 EXPECT_TRUE(OPTIONS_STRUCT_HAS_MEMBER(TestOptions, flags, reader)); | |
| 77 EXPECT_TRUE(OPTIONS_STRUCT_HAS_MEMBER(TestOptions, member1, reader)); | |
| 78 EXPECT_TRUE(OPTIONS_STRUCT_HAS_MEMBER(TestOptions, member2, reader)); | |
| 79 } | |
| 80 } | |
| 81 | |
| 82 TEST(OptionsValidationTest, Invalid) { | |
| 83 // Size too small: | |
| 84 for (size_t i = 0; i < sizeof(uint32_t); i++) { | |
| 85 TestOptions options = {static_cast<uint32_t>(i)}; | |
| 86 UserOptionsReader<TestOptions> reader(MakeUserPointer(&options)); | |
| 87 EXPECT_FALSE(reader.is_valid()) << i; | |
| 88 } | |
| 89 } | |
| 90 | |
| 91 // These test invalid arguments that should cause death if we're being paranoid | |
| 92 // about checking arguments (which we would want to do if, e.g., we were in a | |
| 93 // true "kernel" situation, but we might not want to do otherwise for | |
| 94 // performance reasons). Probably blatant errors like passing in null pointers | |
| 95 // (for required pointer arguments) will still cause death, but perhaps not | |
| 96 // predictably. | |
| 97 TEST(OptionsValidationTest, InvalidDeath) { | |
| 98 const char kMemoryCheckFailedRegex[] = "Check failed"; | |
| 99 | |
| 100 // Null: | |
| 101 EXPECT_DEATH_IF_SUPPORTED( | |
| 102 { UserOptionsReader<TestOptions> reader((NullUserPointer())); }, | |
| 103 kMemoryCheckFailedRegex); | |
| 104 | |
| 105 // Unaligned: | |
| 106 EXPECT_DEATH_IF_SUPPORTED( | |
| 107 { | |
| 108 UserOptionsReader<TestOptions> reader( | |
| 109 MakeUserPointer(reinterpret_cast<const TestOptions*>(1))); | |
| 110 }, | |
| 111 kMemoryCheckFailedRegex); | |
| 112 // Note: The current implementation checks the size only after checking the | |
| 113 // alignment versus that required for the |uint32_t| size, so it won't die in | |
| 114 // the expected way if you pass, e.g., 4. So we have to manufacture a valid | |
| 115 // pointer at an offset of alignment 4. | |
| 116 EXPECT_DEATH_IF_SUPPORTED( | |
| 117 { | |
| 118 uint32_t buffer[100] = {}; | |
| 119 TestOptions* options = (reinterpret_cast<uintptr_t>(buffer) % 8 == 0) | |
| 120 ? reinterpret_cast<TestOptions*>(&buffer[1]) | |
| 121 : reinterpret_cast<TestOptions*>(&buffer[0]); | |
| 122 options->struct_size = static_cast<uint32_t>(sizeof(TestOptions)); | |
| 123 UserOptionsReader<TestOptions> reader(MakeUserPointer(options)); | |
| 124 }, | |
| 125 kMemoryCheckFailedRegex); | |
| 126 } | |
| 127 | |
| 128 } // namespace | |
| 129 } // namespace system | |
| 130 } // namespace mojo | |
| OLD | NEW |