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/edk/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 static_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 static_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 |