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   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 
     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 
     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 
    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