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.
5 #include "mojo/edk/system/options_validation.h"
10 #include "mojo/public/c/system/macros.h"
11 #include "testing/gtest/include/gtest/gtest.h"
17 // Declare a test options struct just as we do in actual public headers.
19 typedef uint32_t TestOptionsFlags
;
21 static_assert(MOJO_ALIGNOF(int64_t) == 8, "int64_t has weird alignment");
22 struct MOJO_ALIGNAS(8) TestOptions
{
24 TestOptionsFlags flags
;
28 static_assert(sizeof(TestOptions
) == 16, "TestOptions has wrong size");
30 const uint32_t kSizeOfTestOptions
= static_cast<uint32_t>(sizeof(TestOptions
));
32 TEST(OptionsValidationTest
, Valid
) {
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
));
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
));
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
));
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
));
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
));
82 TEST(OptionsValidationTest
, Invalid
) {
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
;
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
97 TEST(OptionsValidationTest
, InvalidDeath
) {
98 const char kMemoryCheckFailedRegex
[] = "Check failed";
101 EXPECT_DEATH_IF_SUPPORTED(
102 { UserOptionsReader
<TestOptions
> reader((NullUserPointer())); },
103 kMemoryCheckFailedRegex
);
106 EXPECT_DEATH_IF_SUPPORTED(
108 UserOptionsReader
<TestOptions
> reader(
109 MakeUserPointer(reinterpret_cast<const TestOptions
*>(1)));
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(
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
));
125 kMemoryCheckFailedRegex
);
129 } // namespace system