• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 
TEST(OptionsValidationTest,Valid)32 TEST(OptionsValidationTest, Valid) {
33   const TestOptions kOptions1 = {
34     kSizeOfTestOptions
35   };
36 
37   EXPECT_TRUE(IsOptionsStructPointerAndSizeValid<TestOptions>(&kOptions1));
38   EXPECT_TRUE(HAS_OPTIONS_STRUCT_MEMBER(TestOptions, flags, &kOptions1));
39   EXPECT_TRUE(HAS_OPTIONS_STRUCT_MEMBER(TestOptions, member1, &kOptions1));
40   EXPECT_TRUE(HAS_OPTIONS_STRUCT_MEMBER(TestOptions, member2, &kOptions1));
41 
42   const TestOptions kOptions2 = {
43     static_cast<uint32_t>(offsetof(TestOptions, struct_size) + sizeof(uint32_t))
44   };
45   EXPECT_TRUE(IsOptionsStructPointerAndSizeValid<TestOptions>(&kOptions2));
46   EXPECT_FALSE(HAS_OPTIONS_STRUCT_MEMBER(TestOptions, flags, &kOptions2));
47   EXPECT_FALSE(HAS_OPTIONS_STRUCT_MEMBER(TestOptions, member1, &kOptions2));
48   EXPECT_FALSE(HAS_OPTIONS_STRUCT_MEMBER(TestOptions, member2, &kOptions2));
49 
50   const TestOptions kOptions3 = {
51     static_cast<uint32_t>(offsetof(TestOptions, flags) + sizeof(uint32_t))
52   };
53   EXPECT_TRUE(IsOptionsStructPointerAndSizeValid<TestOptions>(&kOptions3));
54   EXPECT_TRUE(HAS_OPTIONS_STRUCT_MEMBER(TestOptions, flags, &kOptions3));
55   EXPECT_FALSE(HAS_OPTIONS_STRUCT_MEMBER(TestOptions, member1, &kOptions3));
56   EXPECT_FALSE(HAS_OPTIONS_STRUCT_MEMBER(TestOptions, member2, &kOptions3));
57 
58   MOJO_ALIGNAS(8) char buf[sizeof(TestOptions) + 100] = {};
59   TestOptions* options = reinterpret_cast<TestOptions*>(buf);
60   options->struct_size = kSizeOfTestOptions + 1;
61   EXPECT_TRUE(IsOptionsStructPointerAndSizeValid<TestOptions>(options));
62   EXPECT_TRUE(HAS_OPTIONS_STRUCT_MEMBER(TestOptions, flags, options));
63   EXPECT_TRUE(HAS_OPTIONS_STRUCT_MEMBER(TestOptions, member1, options));
64   EXPECT_TRUE(HAS_OPTIONS_STRUCT_MEMBER(TestOptions, member2, options));
65 
66   options->struct_size = kSizeOfTestOptions + 4;
67   EXPECT_TRUE(IsOptionsStructPointerAndSizeValid<TestOptions>(options));
68   EXPECT_TRUE(HAS_OPTIONS_STRUCT_MEMBER(TestOptions, flags, options));
69   EXPECT_TRUE(HAS_OPTIONS_STRUCT_MEMBER(TestOptions, member1, options));
70   EXPECT_TRUE(HAS_OPTIONS_STRUCT_MEMBER(TestOptions, member2, options));
71 }
72 
TEST(OptionsValidationTest,Invalid)73 TEST(OptionsValidationTest, Invalid) {
74   // Null:
75   EXPECT_FALSE(IsOptionsStructPointerAndSizeValid<TestOptions>(NULL));
76 
77   // Unaligned:
78   EXPECT_FALSE(IsOptionsStructPointerAndSizeValid<TestOptions>(
79                    reinterpret_cast<const void*>(1)));
80   EXPECT_FALSE(IsOptionsStructPointerAndSizeValid<TestOptions>(
81                    reinterpret_cast<const void*>(4)));
82 
83   // Size too small:
84   for (size_t i = 0; i < sizeof(uint32_t); i++) {
85     TestOptions options = {static_cast<uint32_t>(i)};
86     EXPECT_FALSE(IsOptionsStructPointerAndSizeValid<TestOptions>(&options))
87         << i;
88   }
89 }
90 
TEST(OptionsValidationTest,CheckFlags)91 TEST(OptionsValidationTest, CheckFlags) {
92   const TestOptions kOptions1 = {kSizeOfTestOptions, 0};
93   EXPECT_TRUE(AreOptionsFlagsAllKnown<TestOptions>(&kOptions1, 0u));
94   EXPECT_TRUE(AreOptionsFlagsAllKnown<TestOptions>(&kOptions1, 1u));
95   EXPECT_TRUE(AreOptionsFlagsAllKnown<TestOptions>(&kOptions1, 3u));
96   EXPECT_TRUE(AreOptionsFlagsAllKnown<TestOptions>(&kOptions1, 7u));
97   EXPECT_TRUE(AreOptionsFlagsAllKnown<TestOptions>(&kOptions1, ~0u));
98 
99   const TestOptions kOptions2 = {kSizeOfTestOptions, 1};
100   EXPECT_FALSE(AreOptionsFlagsAllKnown<TestOptions>(&kOptions2, 0u));
101   EXPECT_TRUE(AreOptionsFlagsAllKnown<TestOptions>(&kOptions2, 1u));
102   EXPECT_TRUE(AreOptionsFlagsAllKnown<TestOptions>(&kOptions2, 3u));
103   EXPECT_TRUE(AreOptionsFlagsAllKnown<TestOptions>(&kOptions2, 7u));
104   EXPECT_TRUE(AreOptionsFlagsAllKnown<TestOptions>(&kOptions2, ~0u));
105 
106   const TestOptions kOptions3 = {kSizeOfTestOptions, 2};
107   EXPECT_FALSE(AreOptionsFlagsAllKnown<TestOptions>(&kOptions3, 0u));
108   EXPECT_FALSE(AreOptionsFlagsAllKnown<TestOptions>(&kOptions3, 1u));
109   EXPECT_TRUE(AreOptionsFlagsAllKnown<TestOptions>(&kOptions3, 3u));
110   EXPECT_TRUE(AreOptionsFlagsAllKnown<TestOptions>(&kOptions3, 7u));
111   EXPECT_TRUE(AreOptionsFlagsAllKnown<TestOptions>(&kOptions3, ~0u));
112 
113   const TestOptions kOptions4 = {kSizeOfTestOptions, 5};
114   EXPECT_FALSE(AreOptionsFlagsAllKnown<TestOptions>(&kOptions4, 0u));
115   EXPECT_FALSE(AreOptionsFlagsAllKnown<TestOptions>(&kOptions4, 1u));
116   EXPECT_FALSE(AreOptionsFlagsAllKnown<TestOptions>(&kOptions4, 3u));
117   EXPECT_TRUE(AreOptionsFlagsAllKnown<TestOptions>(&kOptions4, 7u));
118   EXPECT_TRUE(AreOptionsFlagsAllKnown<TestOptions>(&kOptions4, ~0u));
119 }
120 
TEST(OptionsValidationTest,ValidateOptionsStructPointerSizeAndFlags)121 TEST(OptionsValidationTest, ValidateOptionsStructPointerSizeAndFlags) {
122   const TestOptions kDefaultOptions = {kSizeOfTestOptions, 1u, 123u, 456u};
123 
124   // Valid cases:
125 
126   // "Normal":
127   {
128     const TestOptions kOptions = {kSizeOfTestOptions, 0u, 12u, 34u};
129     TestOptions validated_options = kDefaultOptions;
130     EXPECT_EQ(MOJO_RESULT_OK,
131               ValidateOptionsStructPointerSizeAndFlags<TestOptions>(
132                   &kOptions, 3u, &validated_options));
133     EXPECT_EQ(kDefaultOptions.struct_size, validated_options.struct_size);
134     // Copied |flags|.
135     EXPECT_EQ(kOptions.flags, validated_options.flags);
136     // Didn't touch subsequent members.
137     EXPECT_EQ(kDefaultOptions.member1, validated_options.member1);
138     EXPECT_EQ(kDefaultOptions.member2, validated_options.member2);
139   }
140 
141   // Doesn't actually have |flags|:
142   {
143     const TestOptions kOptions = {
144       static_cast<uint32_t>(sizeof(uint32_t)), 0u, 12u, 34u
145     };
146     TestOptions validated_options = kDefaultOptions;
147     EXPECT_EQ(MOJO_RESULT_OK,
148               ValidateOptionsStructPointerSizeAndFlags<TestOptions>(
149                   &kOptions, 3u, &validated_options));
150     EXPECT_EQ(kDefaultOptions.struct_size, validated_options.struct_size);
151     // Didn't copy |flags|.
152     EXPECT_EQ(kDefaultOptions.flags, validated_options.flags);
153     // Didn't touch subsequent members.
154     EXPECT_EQ(kDefaultOptions.member1, validated_options.member1);
155     EXPECT_EQ(kDefaultOptions.member2, validated_options.member2);
156   }
157 
158   // Invalid cases:
159 
160   // Unaligned:
161   {
162     TestOptions validated_options = kDefaultOptions;
163     EXPECT_EQ(MOJO_RESULT_INVALID_ARGUMENT,
164               ValidateOptionsStructPointerSizeAndFlags<TestOptions>(
165                   reinterpret_cast<const TestOptions*>(1), 3u,
166                   &validated_options));
167   }
168 
169   // |struct_size| too small:
170   {
171     const TestOptions kOptions = {1u, 0u, 12u, 34u};
172     TestOptions validated_options = kDefaultOptions;
173     EXPECT_EQ(MOJO_RESULT_INVALID_ARGUMENT,
174               ValidateOptionsStructPointerSizeAndFlags<TestOptions>(
175                   &kOptions, 3u, &validated_options));
176   }
177 
178   // Unknown |flag|:
179   {
180     const TestOptions kOptions = {kSizeOfTestOptions, 5u, 12u, 34u};
181     TestOptions validated_options = kDefaultOptions;
182     EXPECT_EQ(MOJO_RESULT_UNIMPLEMENTED,
183               ValidateOptionsStructPointerSizeAndFlags<TestOptions>(
184                   &kOptions, 3u, &validated_options));
185   }
186 }
187 
188 }  // namespace
189 }  // namespace system
190 }  // namespace mojo
191