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/memory.h"
      6 
      7 #include <stddef.h>
      8 #include <stdint.h>
      9 
     10 #include <limits>
     11 
     12 #include "mojo/public/c/system/macros.h"
     13 #include "testing/gtest/include/gtest/gtest.h"
     14 
     15 namespace mojo {
     16 namespace system {
     17 namespace {
     18 
     19 TEST(MemoryTest, Valid) {
     20   char my_char;
     21   int32_t my_int32;
     22   int64_t my_int64_array[5] = {};  // Zero initialize.
     23 
     24   UserPointer<char> my_char_ptr(&my_char);
     25   UserPointer<int32_t> my_int32_ptr(&my_int32);
     26   UserPointer<int64_t> my_int64_array_ptr(my_int64_array);
     27 
     28   // |UserPointer<>::IsNull()|:
     29   EXPECT_FALSE(my_char_ptr.IsNull());
     30   EXPECT_FALSE(my_int32_ptr.IsNull());
     31   EXPECT_FALSE(my_int64_array_ptr.IsNull());
     32 
     33   // |UserPointer<>::Put()| and |UserPointer<>::Get()|:
     34   my_char_ptr.Put('x');
     35   EXPECT_EQ('x', my_char);
     36   EXPECT_EQ('x', my_char_ptr.Get());
     37   my_int32_ptr.Put(123);
     38   EXPECT_EQ(123, my_int32);
     39   EXPECT_EQ(123, my_int32_ptr.Get());
     40   my_int64_array_ptr.Put(456);
     41   EXPECT_EQ(456, my_int64_array[0]);
     42   EXPECT_EQ(456, my_int64_array_ptr.Get());
     43 
     44   // |UserPointer<>::At()|, etc.:
     45   my_int64_array_ptr.At(3).Put(789);
     46   EXPECT_EQ(789, my_int64_array[3]);
     47   {
     48     // Copy construction:
     49     UserPointer<int64_t> other(my_int64_array_ptr.At(3));
     50     EXPECT_FALSE(other.IsNull());
     51     EXPECT_EQ(789, other.Get());
     52 
     53     // Assignment:
     54     other = my_int64_array_ptr;
     55     EXPECT_FALSE(other.IsNull());
     56     EXPECT_EQ(456, other.Get());
     57 
     58     // Assignment to |NullUserPointer()|:
     59     other = NullUserPointer();
     60     EXPECT_TRUE(other.IsNull());
     61 
     62     // |MakeUserPointer()|:
     63     other = MakeUserPointer(&my_int64_array[1]);
     64     other.Put(-123);
     65     EXPECT_EQ(-123, my_int64_array_ptr.At(1).Get());
     66   }
     67 
     68   // "const" |UserPointer<>|:
     69   {
     70     // Explicit constructor from |NullUserPointer()|:
     71     UserPointer<const char> other((NullUserPointer()));
     72     EXPECT_TRUE(other.IsNull());
     73 
     74     // Conversion to "const":
     75     other = my_char_ptr;
     76     EXPECT_EQ('x', other.Get());
     77   }
     78 
     79   // Default constructor:
     80   {
     81     UserPointer<int32_t> other;
     82     EXPECT_TRUE(other.IsNull());
     83 
     84     other = my_int32_ptr;
     85     other.Put(-456);
     86     EXPECT_EQ(-456, my_int32_ptr.Get());
     87   }
     88 
     89   // |UserPointer<>::CheckArray()|:
     90   my_int64_array_ptr.CheckArray(5);
     91 
     92   // |UserPointer<>::GetArray()|:
     93   {
     94     // From a "const" |UserPointer<>| (why not?):
     95     UserPointer<const int64_t> other(my_int64_array_ptr);
     96     int64_t array[3] = {1, 2, 3};
     97     other.At(1).GetArray(array, 3);
     98     EXPECT_EQ(-123, array[0]);
     99     EXPECT_EQ(0, array[1]);
    100     EXPECT_EQ(789, array[2]);
    101   }
    102 
    103   // |UserPointer<>::PutArray()|:
    104   {
    105     const int64_t array[2] = {654, 321};
    106     my_int64_array_ptr.At(3).PutArray(array, 2);
    107     EXPECT_EQ(0, my_int64_array[2]);
    108     EXPECT_EQ(654, my_int64_array[3]);
    109     EXPECT_EQ(321, my_int64_array[4]);
    110   }
    111 
    112   // |UserPointer<>::Reader|:
    113   {
    114     UserPointer<int64_t>::Reader reader(my_int64_array_ptr, 5);
    115     EXPECT_EQ(456, reader.GetPointer()[0]);
    116     EXPECT_EQ(321, reader.GetPointer()[4]);
    117   }
    118 
    119   // Non-const to const:
    120   {
    121     UserPointer<const int64_t>::Reader reader(my_int64_array_ptr.At(3), 1);
    122     const int64_t* ptr = reader.GetPointer();
    123     EXPECT_EQ(654, *ptr);
    124   }
    125 
    126   // |UserPointer<>::Writer|:
    127   {
    128     UserPointer<int64_t>::Writer writer(my_int64_array_ptr.At(2), 1);
    129     int64_t* ptr = writer.GetPointer();
    130     *ptr = 1234567890123LL;
    131     writer.Commit();
    132     EXPECT_EQ(1234567890123LL, my_int64_array[2]);
    133   }
    134 
    135   // |UserPointer<>::ReaderWriter|:
    136   {
    137     UserPointer<int32_t>::ReaderWriter reader_writer(my_int32_ptr, 1);
    138     int32_t* ptr = reader_writer.GetPointer();
    139     EXPECT_EQ(-456, *ptr);
    140     *ptr = 42;
    141     reader_writer.Commit();
    142     EXPECT_EQ(42, my_int32);
    143   }
    144 
    145   // |UserPointer<>::ReinterpretCast<>|:
    146   // (This assumes little-endian, etc.)
    147   {
    148     UserPointer<const char> other(my_int32_ptr.ReinterpretCast<char>());
    149     EXPECT_EQ(42, other.Get());
    150     EXPECT_EQ(0, other.At(1).Get());
    151     EXPECT_EQ(0, other.At(2).Get());
    152     EXPECT_EQ(0, other.At(3).Get());
    153   }
    154 
    155   // |UserPointer<>::GetPointerValue()|:
    156   {
    157     UserPointer<int32_t> other;
    158     EXPECT_EQ(0u, other.GetPointerValue());
    159     other = my_int32_ptr;
    160     EXPECT_EQ(reinterpret_cast<uintptr_t>(&my_int32), other.GetPointerValue());
    161   }
    162 }
    163 
    164 TEST(MemoryTest, InvalidDeath) {
    165   const char kMemoryCheckFailedRegex[] = "Check failed";
    166 
    167   // Note: |Check...()| are defined to be "best effort" checks (and may always
    168   // return true). Thus these tests of invalid cases only reflect the current
    169   // implementation.
    170 
    171   // These tests depend on |int32_t| and |int64_t| having nontrivial alignment.
    172   static_assert(MOJO_ALIGNOF(int32_t) != 1,
    173                 "int32_t does not require nontrivial alignment");
    174   static_assert(MOJO_ALIGNOF(int64_t) != 1,
    175                 "int64_t does not require nontrivial alignment");
    176 
    177   // Null:
    178   {
    179     UserPointer<char> ptr(nullptr);
    180     char array[5] = {};
    181     EXPECT_DEATH_IF_SUPPORTED(ptr.Check(), kMemoryCheckFailedRegex);
    182     EXPECT_DEATH_IF_SUPPORTED(ptr.Get(), kMemoryCheckFailedRegex);
    183     EXPECT_DEATH_IF_SUPPORTED(ptr.Put('x'), kMemoryCheckFailedRegex);
    184     EXPECT_DEATH_IF_SUPPORTED(ptr.CheckArray(5), kMemoryCheckFailedRegex);
    185     EXPECT_DEATH_IF_SUPPORTED(ptr.GetArray(array, 5), kMemoryCheckFailedRegex);
    186     EXPECT_DEATH_IF_SUPPORTED(ptr.PutArray(array, 5), kMemoryCheckFailedRegex);
    187   }
    188   {
    189     UserPointer<int32_t> ptr(nullptr);
    190     int32_t array[5] = {};
    191     EXPECT_DEATH_IF_SUPPORTED(ptr.Check(), kMemoryCheckFailedRegex);
    192     EXPECT_DEATH_IF_SUPPORTED(ptr.Get(), kMemoryCheckFailedRegex);
    193     EXPECT_DEATH_IF_SUPPORTED(ptr.Put(123), kMemoryCheckFailedRegex);
    194     EXPECT_DEATH_IF_SUPPORTED(ptr.CheckArray(5), kMemoryCheckFailedRegex);
    195     EXPECT_DEATH_IF_SUPPORTED(ptr.GetArray(array, 5), kMemoryCheckFailedRegex);
    196     EXPECT_DEATH_IF_SUPPORTED(ptr.PutArray(array, 5), kMemoryCheckFailedRegex);
    197   }
    198   {
    199     UserPointer<int64_t> ptr(nullptr);
    200     int64_t array[5] = {};
    201     EXPECT_DEATH_IF_SUPPORTED(ptr.Check(), kMemoryCheckFailedRegex);
    202     EXPECT_DEATH_IF_SUPPORTED(ptr.Get(), kMemoryCheckFailedRegex);
    203     EXPECT_DEATH_IF_SUPPORTED(ptr.Put(123), kMemoryCheckFailedRegex);
    204     EXPECT_DEATH_IF_SUPPORTED(ptr.CheckArray(5), kMemoryCheckFailedRegex);
    205     EXPECT_DEATH_IF_SUPPORTED(ptr.GetArray(array, 5), kMemoryCheckFailedRegex);
    206     EXPECT_DEATH_IF_SUPPORTED(ptr.PutArray(array, 5), kMemoryCheckFailedRegex);
    207   }
    208   // Also check a const pointer:
    209   {
    210     UserPointer<const int32_t> ptr(nullptr);
    211     int32_t array[5] = {};
    212     EXPECT_DEATH_IF_SUPPORTED(ptr.Check(), kMemoryCheckFailedRegex);
    213     EXPECT_DEATH_IF_SUPPORTED(ptr.Get(), kMemoryCheckFailedRegex);
    214     EXPECT_DEATH_IF_SUPPORTED(ptr.CheckArray(5), kMemoryCheckFailedRegex);
    215     EXPECT_DEATH_IF_SUPPORTED(ptr.GetArray(array, 5), kMemoryCheckFailedRegex);
    216   }
    217 
    218   // Unaligned:
    219   {
    220     int32_t x[10];
    221     UserPointer<int32_t> ptr(
    222         reinterpret_cast<int32_t*>(reinterpret_cast<uintptr_t>(x) + 1));
    223     int32_t array[5] = {};
    224     EXPECT_DEATH_IF_SUPPORTED(ptr.Check(), kMemoryCheckFailedRegex);
    225     EXPECT_DEATH_IF_SUPPORTED(ptr.Get(), kMemoryCheckFailedRegex);
    226     EXPECT_DEATH_IF_SUPPORTED(ptr.Put(123), kMemoryCheckFailedRegex);
    227     EXPECT_DEATH_IF_SUPPORTED(ptr.CheckArray(5), kMemoryCheckFailedRegex);
    228     EXPECT_DEATH_IF_SUPPORTED(ptr.GetArray(array, 5), kMemoryCheckFailedRegex);
    229     EXPECT_DEATH_IF_SUPPORTED(ptr.PutArray(array, 5), kMemoryCheckFailedRegex);
    230   }
    231   {
    232     int64_t x[10];
    233     UserPointer<int64_t> ptr(
    234         reinterpret_cast<int64_t*>(reinterpret_cast<uintptr_t>(x) + 1));
    235     int64_t array[5] = {};
    236     EXPECT_DEATH_IF_SUPPORTED(ptr.Check(), kMemoryCheckFailedRegex);
    237     EXPECT_DEATH_IF_SUPPORTED(ptr.Get(), kMemoryCheckFailedRegex);
    238     EXPECT_DEATH_IF_SUPPORTED(ptr.Put(123), kMemoryCheckFailedRegex);
    239     EXPECT_DEATH_IF_SUPPORTED(ptr.CheckArray(5), kMemoryCheckFailedRegex);
    240     EXPECT_DEATH_IF_SUPPORTED(ptr.GetArray(array, 5), kMemoryCheckFailedRegex);
    241     EXPECT_DEATH_IF_SUPPORTED(ptr.PutArray(array, 5), kMemoryCheckFailedRegex);
    242   }
    243   // Also check a const pointer:
    244   {
    245     int32_t x[10];
    246     UserPointer<const int32_t> ptr(
    247         reinterpret_cast<const int32_t*>(reinterpret_cast<uintptr_t>(x) + 1));
    248     int32_t array[5] = {};
    249     EXPECT_DEATH_IF_SUPPORTED(ptr.Check(), kMemoryCheckFailedRegex);
    250     EXPECT_DEATH_IF_SUPPORTED(ptr.Get(), kMemoryCheckFailedRegex);
    251     EXPECT_DEATH_IF_SUPPORTED(ptr.CheckArray(5), kMemoryCheckFailedRegex);
    252     EXPECT_DEATH_IF_SUPPORTED(ptr.GetArray(array, 5), kMemoryCheckFailedRegex);
    253   }
    254 
    255   // Count too big:
    256   {
    257     const size_t kTooBig =
    258         std::numeric_limits<size_t>::max() / sizeof(int32_t) + 1;
    259     int32_t x = 0;
    260     UserPointer<int32_t> ptr(&x);
    261     EXPECT_DEATH_IF_SUPPORTED(ptr.CheckArray(kTooBig), kMemoryCheckFailedRegex);
    262     EXPECT_DEATH_IF_SUPPORTED(ptr.GetArray(&x, kTooBig),
    263                               kMemoryCheckFailedRegex);
    264     EXPECT_DEATH_IF_SUPPORTED(ptr.PutArray(&x, kTooBig),
    265                               kMemoryCheckFailedRegex);
    266   }
    267   {
    268     const size_t kTooBig =
    269         std::numeric_limits<size_t>::max() / sizeof(int64_t) + 1;
    270     int64_t x = 0;
    271     UserPointer<int64_t> ptr(&x);
    272     EXPECT_DEATH_IF_SUPPORTED(ptr.CheckArray(kTooBig), kMemoryCheckFailedRegex);
    273     EXPECT_DEATH_IF_SUPPORTED(ptr.GetArray(&x, kTooBig),
    274                               kMemoryCheckFailedRegex);
    275     EXPECT_DEATH_IF_SUPPORTED(ptr.PutArray(&x, kTooBig),
    276                               kMemoryCheckFailedRegex);
    277   }
    278   // Also check a const pointer:
    279   {
    280     const size_t kTooBig =
    281         std::numeric_limits<size_t>::max() / sizeof(int32_t) + 1;
    282     int32_t x = 0;
    283     UserPointer<const int32_t> ptr(&x);
    284     EXPECT_DEATH_IF_SUPPORTED(ptr.CheckArray(kTooBig), kMemoryCheckFailedRegex);
    285     EXPECT_DEATH_IF_SUPPORTED(ptr.GetArray(&x, kTooBig),
    286                               kMemoryCheckFailedRegex);
    287   }
    288 
    289   // TODO(vtl): Tests for |UserPointer{Reader,Writer,ReaderWriter}|.
    290 }
    291 
    292 }  // namespace
    293 }  // namespace system
    294 }  // namespace mojo
    295