1// Copyright 2013 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/data_pipe.h"
6
7#include <stddef.h>
8#include <stdint.h>
9
10#include <limits>
11
12#include "mojo/system/constants.h"
13#include "testing/gtest/include/gtest/gtest.h"
14
15namespace mojo {
16namespace system {
17namespace {
18
19const uint32_t kSizeOfCreateOptions =
20    static_cast<uint32_t>(sizeof(MojoCreateDataPipeOptions));
21
22// Does a cursory sanity check of |validated_options|. Calls
23// |ValidateCreateOptions()| on already-validated options. The validated options
24// should be valid, and the revalidated copy should be the same.
25void RevalidateCreateOptions(
26    const MojoCreateDataPipeOptions& validated_options) {
27  EXPECT_EQ(kSizeOfCreateOptions, validated_options.struct_size);
28  // Nothing to check for flags.
29  EXPECT_GT(validated_options.element_num_bytes, 0u);
30  EXPECT_GT(validated_options.capacity_num_bytes, 0u);
31  EXPECT_EQ(0u,
32            validated_options.capacity_num_bytes %
33                validated_options.element_num_bytes);
34
35  MojoCreateDataPipeOptions revalidated_options = {};
36  EXPECT_EQ(MOJO_RESULT_OK,
37            DataPipe::ValidateCreateOptions(MakeUserPointer(&validated_options),
38                                            &revalidated_options));
39  EXPECT_EQ(validated_options.struct_size, revalidated_options.struct_size);
40  EXPECT_EQ(validated_options.element_num_bytes,
41            revalidated_options.element_num_bytes);
42  EXPECT_EQ(validated_options.capacity_num_bytes,
43            revalidated_options.capacity_num_bytes);
44  EXPECT_EQ(validated_options.flags, revalidated_options.flags);
45}
46
47// Checks that a default-computed capacity is correct. (Does not duplicate the
48// checks done by |RevalidateCreateOptions()|.)
49void CheckDefaultCapacity(const MojoCreateDataPipeOptions& validated_options) {
50  EXPECT_LE(validated_options.capacity_num_bytes,
51            kDefaultDataPipeCapacityBytes);
52  EXPECT_GT(validated_options.capacity_num_bytes +
53                validated_options.element_num_bytes,
54            kDefaultDataPipeCapacityBytes);
55}
56
57// Tests valid inputs to |ValidateCreateOptions()|.
58TEST(DataPipeTest, ValidateCreateOptionsValid) {
59  // Default options.
60  {
61    MojoCreateDataPipeOptions validated_options = {};
62    EXPECT_EQ(
63        MOJO_RESULT_OK,
64        DataPipe::ValidateCreateOptions(NullUserPointer(), &validated_options));
65    RevalidateCreateOptions(validated_options);
66    CheckDefaultCapacity(validated_options);
67  }
68
69  // Size member, but nothing beyond.
70  {
71    MojoCreateDataPipeOptions options = {
72        offsetof(MojoCreateDataPipeOptions, flags)  // |struct_size|.
73    };
74    MojoCreateDataPipeOptions validated_options = {};
75    EXPECT_EQ(MOJO_RESULT_OK,
76              DataPipe::ValidateCreateOptions(MakeUserPointer(&options),
77                                              &validated_options));
78    RevalidateCreateOptions(validated_options);
79    CheckDefaultCapacity(validated_options);
80  }
81
82  // Different flags.
83  MojoCreateDataPipeOptionsFlags flags_values[] = {
84      MOJO_CREATE_DATA_PIPE_OPTIONS_FLAG_NONE,
85      MOJO_CREATE_DATA_PIPE_OPTIONS_FLAG_MAY_DISCARD};
86  for (size_t i = 0; i < arraysize(flags_values); i++) {
87    const MojoCreateDataPipeOptionsFlags flags = flags_values[i];
88
89    // Flags member, but nothing beyond.
90    {
91      MojoCreateDataPipeOptions options = {
92          // |struct_size|.
93          offsetof(MojoCreateDataPipeOptions, element_num_bytes),
94          flags  // |flags|.
95      };
96      MojoCreateDataPipeOptions validated_options = {};
97      EXPECT_EQ(MOJO_RESULT_OK,
98                DataPipe::ValidateCreateOptions(MakeUserPointer(&options),
99                                                &validated_options));
100      RevalidateCreateOptions(validated_options);
101      EXPECT_EQ(options.flags, validated_options.flags);
102      CheckDefaultCapacity(validated_options);
103    }
104
105    // Different capacities (size 1).
106    for (uint32_t capacity = 1; capacity <= 100 * 1000 * 1000; capacity *= 10) {
107      MojoCreateDataPipeOptions options = {
108          kSizeOfCreateOptions,  // |struct_size|.
109          flags,                 // |flags|.
110          1,                     // |element_num_bytes|.
111          capacity               // |capacity_num_bytes|.
112      };
113      MojoCreateDataPipeOptions validated_options = {};
114      EXPECT_EQ(MOJO_RESULT_OK,
115                DataPipe::ValidateCreateOptions(MakeUserPointer(&options),
116                                                &validated_options))
117          << capacity;
118      RevalidateCreateOptions(validated_options);
119      EXPECT_EQ(options.flags, validated_options.flags);
120      EXPECT_EQ(options.element_num_bytes, validated_options.element_num_bytes);
121      EXPECT_EQ(options.capacity_num_bytes,
122                validated_options.capacity_num_bytes);
123    }
124
125    // Small sizes.
126    for (uint32_t size = 1; size < 100; size++) {
127      // Different capacities.
128      for (uint32_t elements = 1; elements <= 1000 * 1000; elements *= 10) {
129        MojoCreateDataPipeOptions options = {
130            kSizeOfCreateOptions,  // |struct_size|.
131            flags,                 // |flags|.
132            size,                  // |element_num_bytes|.
133            size * elements        // |capacity_num_bytes|.
134        };
135        MojoCreateDataPipeOptions validated_options = {};
136        EXPECT_EQ(MOJO_RESULT_OK,
137                  DataPipe::ValidateCreateOptions(MakeUserPointer(&options),
138                                                  &validated_options))
139            << size << ", " << elements;
140        RevalidateCreateOptions(validated_options);
141        EXPECT_EQ(options.flags, validated_options.flags);
142        EXPECT_EQ(options.element_num_bytes,
143                  validated_options.element_num_bytes);
144        EXPECT_EQ(options.capacity_num_bytes,
145                  validated_options.capacity_num_bytes);
146      }
147
148      // Default capacity.
149      {
150        MojoCreateDataPipeOptions options = {
151            kSizeOfCreateOptions,  // |struct_size|.
152            flags,                 // |flags|.
153            size,                  // |element_num_bytes|.
154            0                      // |capacity_num_bytes|.
155        };
156        MojoCreateDataPipeOptions validated_options = {};
157        EXPECT_EQ(MOJO_RESULT_OK,
158                  DataPipe::ValidateCreateOptions(MakeUserPointer(&options),
159                                                  &validated_options))
160            << size;
161        RevalidateCreateOptions(validated_options);
162        EXPECT_EQ(options.flags, validated_options.flags);
163        EXPECT_EQ(options.element_num_bytes,
164                  validated_options.element_num_bytes);
165        CheckDefaultCapacity(validated_options);
166      }
167
168      // No capacity field.
169      {
170        MojoCreateDataPipeOptions options = {
171            // |struct_size|.
172            offsetof(MojoCreateDataPipeOptions, capacity_num_bytes),
173            flags,  // |flags|.
174            size    // |element_num_bytes|.
175        };
176        MojoCreateDataPipeOptions validated_options = {};
177        EXPECT_EQ(MOJO_RESULT_OK,
178                  DataPipe::ValidateCreateOptions(MakeUserPointer(&options),
179                                                  &validated_options))
180            << size;
181        RevalidateCreateOptions(validated_options);
182        EXPECT_EQ(options.flags, validated_options.flags);
183        EXPECT_EQ(options.element_num_bytes,
184                  validated_options.element_num_bytes);
185        CheckDefaultCapacity(validated_options);
186      }
187    }
188
189    // Larger sizes.
190    for (uint32_t size = 100; size <= 100 * 1000; size *= 10) {
191      // Capacity of 1000 elements.
192      {
193        MojoCreateDataPipeOptions options = {
194            kSizeOfCreateOptions,  // |struct_size|.
195            flags,                 // |flags|.
196            size,                  // |element_num_bytes|.
197            1000 * size            // |capacity_num_bytes|.
198        };
199        MojoCreateDataPipeOptions validated_options = {};
200        EXPECT_EQ(MOJO_RESULT_OK,
201                  DataPipe::ValidateCreateOptions(MakeUserPointer(&options),
202                                                  &validated_options))
203            << size;
204        RevalidateCreateOptions(validated_options);
205        EXPECT_EQ(options.flags, validated_options.flags);
206        EXPECT_EQ(options.element_num_bytes,
207                  validated_options.element_num_bytes);
208        EXPECT_EQ(options.capacity_num_bytes,
209                  validated_options.capacity_num_bytes);
210      }
211
212      // Default capacity.
213      {
214        MojoCreateDataPipeOptions options = {
215            kSizeOfCreateOptions,  // |struct_size|.
216            flags,                 // |flags|.
217            size,                  // |element_num_bytes|.
218            0                      // |capacity_num_bytes|.
219        };
220        MojoCreateDataPipeOptions validated_options = {};
221        EXPECT_EQ(MOJO_RESULT_OK,
222                  DataPipe::ValidateCreateOptions(MakeUserPointer(&options),
223                                                  &validated_options))
224            << size;
225        RevalidateCreateOptions(validated_options);
226        EXPECT_EQ(options.flags, validated_options.flags);
227        EXPECT_EQ(options.element_num_bytes,
228                  validated_options.element_num_bytes);
229        CheckDefaultCapacity(validated_options);
230      }
231
232      // No capacity field.
233      {
234        MojoCreateDataPipeOptions options = {
235            // |struct_size|.
236            offsetof(MojoCreateDataPipeOptions, capacity_num_bytes),
237            flags,  // |flags|.
238            size    // |element_num_bytes|.
239        };
240        MojoCreateDataPipeOptions validated_options = {};
241        EXPECT_EQ(MOJO_RESULT_OK,
242                  DataPipe::ValidateCreateOptions(MakeUserPointer(&options),
243                                                  &validated_options))
244            << size;
245        RevalidateCreateOptions(validated_options);
246        EXPECT_EQ(options.flags, validated_options.flags);
247        EXPECT_EQ(options.element_num_bytes,
248                  validated_options.element_num_bytes);
249        CheckDefaultCapacity(validated_options);
250      }
251    }
252  }
253}
254
255TEST(DataPipeTest, ValidateCreateOptionsInvalid) {
256  // Invalid |struct_size|.
257  {
258    MojoCreateDataPipeOptions options = {
259        1,                                        // |struct_size|.
260        MOJO_CREATE_DATA_PIPE_OPTIONS_FLAG_NONE,  // |flags|.
261        1,                                        // |element_num_bytes|.
262        0                                         // |capacity_num_bytes|.
263    };
264    MojoCreateDataPipeOptions unused;
265    EXPECT_EQ(
266        MOJO_RESULT_INVALID_ARGUMENT,
267        DataPipe::ValidateCreateOptions(MakeUserPointer(&options), &unused));
268  }
269
270  // Unknown |flags|.
271  {
272    MojoCreateDataPipeOptions options = {
273        kSizeOfCreateOptions,  // |struct_size|.
274        ~0u,                   // |flags|.
275        1,                     // |element_num_bytes|.
276        0                      // |capacity_num_bytes|.
277    };
278    MojoCreateDataPipeOptions unused;
279    EXPECT_EQ(
280        MOJO_RESULT_UNIMPLEMENTED,
281        DataPipe::ValidateCreateOptions(MakeUserPointer(&options), &unused));
282  }
283
284  // Invalid |element_num_bytes|.
285  {
286    MojoCreateDataPipeOptions options = {
287        kSizeOfCreateOptions,                     // |struct_size|.
288        MOJO_CREATE_DATA_PIPE_OPTIONS_FLAG_NONE,  // |flags|.
289        0,                                        // |element_num_bytes|.
290        1000                                      // |capacity_num_bytes|.
291    };
292    MojoCreateDataPipeOptions unused;
293    EXPECT_EQ(
294        MOJO_RESULT_INVALID_ARGUMENT,
295        DataPipe::ValidateCreateOptions(MakeUserPointer(&options), &unused));
296  }
297  // |element_num_bytes| too big.
298  {
299    MojoCreateDataPipeOptions options = {
300        kSizeOfCreateOptions,                     // |struct_size|.
301        MOJO_CREATE_DATA_PIPE_OPTIONS_FLAG_NONE,  // |flags|.
302        std::numeric_limits<uint32_t>::max(),     // |element_num_bytes|.
303        std::numeric_limits<uint32_t>::max()      // |capacity_num_bytes|.
304    };
305    MojoCreateDataPipeOptions unused;
306    EXPECT_EQ(
307        MOJO_RESULT_RESOURCE_EXHAUSTED,
308        DataPipe::ValidateCreateOptions(MakeUserPointer(&options), &unused));
309  }
310  {
311    MojoCreateDataPipeOptions options = {
312        kSizeOfCreateOptions,                         // |struct_size|.
313        MOJO_CREATE_DATA_PIPE_OPTIONS_FLAG_NONE,      // |flags|.
314        std::numeric_limits<uint32_t>::max() - 1000,  // |element_num_bytes|.
315        std::numeric_limits<uint32_t>::max() - 1000   // |capacity_num_bytes|.
316    };
317    MojoCreateDataPipeOptions unused;
318    EXPECT_EQ(
319        MOJO_RESULT_RESOURCE_EXHAUSTED,
320        DataPipe::ValidateCreateOptions(MakeUserPointer(&options), &unused));
321  }
322
323  // Invalid |capacity_num_bytes|.
324  {
325    MojoCreateDataPipeOptions options = {
326        kSizeOfCreateOptions,                     // |struct_size|.
327        MOJO_CREATE_DATA_PIPE_OPTIONS_FLAG_NONE,  // |flags|.
328        2,                                        // |element_num_bytes|.
329        1                                         // |capacity_num_bytes|.
330    };
331    MojoCreateDataPipeOptions unused;
332    EXPECT_EQ(
333        MOJO_RESULT_INVALID_ARGUMENT,
334        DataPipe::ValidateCreateOptions(MakeUserPointer(&options), &unused));
335  }
336  {
337    MojoCreateDataPipeOptions options = {
338        kSizeOfCreateOptions,                     // |struct_size|.
339        MOJO_CREATE_DATA_PIPE_OPTIONS_FLAG_NONE,  // |flags|.
340        2,                                        // |element_num_bytes|.
341        111                                       // |capacity_num_bytes|.
342    };
343    MojoCreateDataPipeOptions unused;
344    EXPECT_EQ(
345        MOJO_RESULT_INVALID_ARGUMENT,
346        DataPipe::ValidateCreateOptions(MakeUserPointer(&options), &unused));
347  }
348  {
349    MojoCreateDataPipeOptions options = {
350        kSizeOfCreateOptions,                     // |struct_size|.
351        MOJO_CREATE_DATA_PIPE_OPTIONS_FLAG_NONE,  // |flags|.
352        5,                                        // |element_num_bytes|.
353        104                                       // |capacity_num_bytes|.
354    };
355    MojoCreateDataPipeOptions unused;
356    EXPECT_EQ(
357        MOJO_RESULT_INVALID_ARGUMENT,
358        DataPipe::ValidateCreateOptions(MakeUserPointer(&options), &unused));
359  }
360  // |capacity_num_bytes| too big.
361  {
362    MojoCreateDataPipeOptions options = {
363        kSizeOfCreateOptions,                     // |struct_size|.
364        MOJO_CREATE_DATA_PIPE_OPTIONS_FLAG_NONE,  // |flags|.
365        8,                                        // |element_num_bytes|.
366        0xffff0000                                // |capacity_num_bytes|.
367    };
368    MojoCreateDataPipeOptions unused;
369    EXPECT_EQ(
370        MOJO_RESULT_RESOURCE_EXHAUSTED,
371        DataPipe::ValidateCreateOptions(MakeUserPointer(&options), &unused));
372  }
373}
374
375}  // namespace
376}  // namespace system
377}  // namespace mojo
378