Home | History | Annotate | Download | only in system
      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
    131