Home | History | Annotate | Download | only in wtf
      1 /*
      2  * Copyright (C) 2011 Apple Inc. All rights reserved.
      3  *
      4  * Redistribution and use in source and binary forms, with or without
      5  * modification, are permitted provided that the following conditions
      6  * are met:
      7  * 1. Redistributions of source code must retain the above copyright
      8  *    notice, this list of conditions and the following disclaimer.
      9  * 2. Redistributions in binary form must reproduce the above copyright
     10  *    notice, this list of conditions and the following disclaimer in the
     11  *    documentation and/or other materials provided with the distribution.
     12  *
     13  * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS''
     14  * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
     15  * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
     16  * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS
     17  * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
     18  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
     19  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
     20  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
     21  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
     22  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
     23  * THE POSSIBILITY OF SUCH DAMAGE.
     24  */
     25 
     26 #include "config.h"
     27 
     28 #include "wtf/CheckedArithmetic.h"
     29 #include <gtest/gtest.h>
     30 
     31 namespace {
     32 
     33 #define CheckedArithmeticTest(type, coerceLiteral, MixedSignednessTest) \
     34     TEST(WTF, Checked_##type) \
     35     { \
     36         Checked<type, RecordOverflow> value; \
     37         EXPECT_EQ(coerceLiteral(0), value.unsafeGet()); \
     38         EXPECT_EQ(std::numeric_limits<type>::max(), (value + std::numeric_limits<type>::max()).unsafeGet()); \
     39         EXPECT_EQ(std::numeric_limits<type>::max(), (std::numeric_limits<type>::max() + value).unsafeGet()); \
     40         EXPECT_EQ(std::numeric_limits<type>::min(), (value + std::numeric_limits<type>::min()).unsafeGet()); \
     41         EXPECT_EQ(std::numeric_limits<type>::min(), (std::numeric_limits<type>::min() + value).unsafeGet()); \
     42         EXPECT_EQ(coerceLiteral(0), (value * coerceLiteral(0)).unsafeGet()); \
     43         EXPECT_EQ(coerceLiteral(0), (coerceLiteral(0) * value).unsafeGet()); \
     44         EXPECT_EQ(coerceLiteral(0), (value * value).unsafeGet()); \
     45         EXPECT_EQ(coerceLiteral(0), (value - coerceLiteral(0)).unsafeGet()); \
     46         EXPECT_EQ(coerceLiteral(0), (coerceLiteral(0) - value).unsafeGet()); \
     47         EXPECT_EQ(coerceLiteral(0), (value - value).unsafeGet()); \
     48         EXPECT_EQ(coerceLiteral(0), (value++).unsafeGet()); \
     49         EXPECT_EQ(coerceLiteral(1), (value--).unsafeGet()); \
     50         EXPECT_EQ(coerceLiteral(1), (++value).unsafeGet()); \
     51         EXPECT_EQ(coerceLiteral(0), (--value).unsafeGet()); \
     52         EXPECT_EQ(coerceLiteral(10), (value += coerceLiteral(10)).unsafeGet()); \
     53         EXPECT_EQ(coerceLiteral(10), value.unsafeGet()); \
     54         EXPECT_EQ(coerceLiteral(100), (value *= coerceLiteral(10)).unsafeGet()); \
     55         EXPECT_EQ(coerceLiteral(100), value.unsafeGet()); \
     56         EXPECT_EQ(coerceLiteral(0), (value -= coerceLiteral(100)).unsafeGet()); \
     57         EXPECT_EQ(coerceLiteral(0), value.unsafeGet()); \
     58         value = 10; \
     59         EXPECT_EQ(coerceLiteral(10), value.unsafeGet()); \
     60         EXPECT_EQ(coerceLiteral(0), (value - coerceLiteral(10)).unsafeGet()); \
     61         EXPECT_EQ(coerceLiteral(10), value.unsafeGet()); \
     62         value = std::numeric_limits<type>::min(); \
     63         EXPECT_EQ(true, (Checked<type, RecordOverflow>(value - coerceLiteral(1))).hasOverflowed()); \
     64         EXPECT_EQ(true, !((value--).hasOverflowed())); \
     65         EXPECT_EQ(true, value.hasOverflowed()); \
     66         value = std::numeric_limits<type>::max(); \
     67         EXPECT_EQ(true, !value.hasOverflowed()); \
     68         EXPECT_EQ(true, (Checked<type, RecordOverflow>(value + coerceLiteral(1))).hasOverflowed()); \
     69         EXPECT_EQ(true, !(value++).hasOverflowed()); \
     70         EXPECT_EQ(true, value.hasOverflowed()); \
     71         value = std::numeric_limits<type>::max(); \
     72         EXPECT_EQ(true, (value += coerceLiteral(1)).hasOverflowed()); \
     73         EXPECT_EQ(true, value.hasOverflowed()); \
     74         value = 10; \
     75         type _value = 0; \
     76         EXPECT_EQ(true, CheckedState::DidNotOverflow == (value * Checked<type, RecordOverflow>(0)).safeGet(_value)); \
     77         _value = 0; \
     78         EXPECT_EQ(true, CheckedState::DidNotOverflow == (Checked<type, RecordOverflow>(0) * value).safeGet(_value)); \
     79         _value = 0; \
     80         EXPECT_EQ(true, CheckedState::DidOverflow == (value * Checked<type, RecordOverflow>(std::numeric_limits<type>::max())).safeGet(_value)); \
     81         _value = 0; \
     82         EXPECT_EQ(true, CheckedState::DidOverflow == (Checked<type, RecordOverflow>(std::numeric_limits<type>::max()) * value).safeGet(_value)); \
     83         value = 0; \
     84         _value = 0; \
     85         EXPECT_EQ(true, CheckedState::DidNotOverflow == (value * Checked<type, RecordOverflow>(std::numeric_limits<type>::max())).safeGet(_value)); \
     86         _value = 0; \
     87         EXPECT_EQ(true, CheckedState::DidNotOverflow == (Checked<type, RecordOverflow>(std::numeric_limits<type>::max()) * value).safeGet(_value)); \
     88         value = 1; \
     89         _value = 0; \
     90         EXPECT_EQ(true, CheckedState::DidNotOverflow == (value * Checked<type, RecordOverflow>(std::numeric_limits<type>::max())).safeGet(_value)); \
     91         _value = 0; \
     92         EXPECT_EQ(true, CheckedState::DidNotOverflow == (Checked<type, RecordOverflow>(std::numeric_limits<type>::max()) * value).safeGet(_value)); \
     93         _value = 0; \
     94         value = 0; \
     95         EXPECT_EQ(true, CheckedState::DidNotOverflow == (value * Checked<type, RecordOverflow>(std::numeric_limits<type>::max())).safeGet(_value)); \
     96         _value = 0; \
     97         EXPECT_EQ(true, CheckedState::DidNotOverflow == (Checked<type, RecordOverflow>(std::numeric_limits<type>::max()) * (type)0).safeGet(_value)); \
     98         _value = 0; \
     99         value = 1; \
    100         EXPECT_EQ(true, CheckedState::DidNotOverflow == (value * Checked<type, RecordOverflow>(std::numeric_limits<type>::max())).safeGet(_value)); \
    101         _value = 0; \
    102         EXPECT_EQ(true, CheckedState::DidNotOverflow == (Checked<type, RecordOverflow>(std::numeric_limits<type>::max()) * (type)1).safeGet(_value)); \
    103         _value = 0; \
    104         value = 2; \
    105         EXPECT_EQ(true, CheckedState::DidOverflow == (value * Checked<type, RecordOverflow>(std::numeric_limits<type>::max())).safeGet(_value)); \
    106         _value = 0; \
    107         EXPECT_EQ(true, CheckedState::DidOverflow == (Checked<type, RecordOverflow>(std::numeric_limits<type>::max()) * (type)2).safeGet(_value)); \
    108         value = 10; \
    109         EXPECT_EQ(true, (value * Checked<type, RecordOverflow>(std::numeric_limits<type>::max())).hasOverflowed()); \
    110         MixedSignednessTest(EXPECT_EQ(coerceLiteral(0), (value + -10).unsafeGet())); \
    111         MixedSignednessTest(EXPECT_EQ(0U, (value - 10U).unsafeGet())); \
    112         MixedSignednessTest(EXPECT_EQ(coerceLiteral(0), (-10 + value).unsafeGet())); \
    113         MixedSignednessTest(EXPECT_EQ(0U, (10U - value).unsafeGet())); \
    114         value = std::numeric_limits<type>::min(); \
    115         MixedSignednessTest(EXPECT_EQ(true, (Checked<type, RecordOverflow>(value - 1)).hasOverflowed())); \
    116         MixedSignednessTest(EXPECT_EQ(true, !(value--).hasOverflowed())); \
    117         MixedSignednessTest(EXPECT_EQ(true, value.hasOverflowed())); \
    118         value = std::numeric_limits<type>::max(); \
    119         MixedSignednessTest(EXPECT_EQ(true, !value.hasOverflowed())); \
    120         MixedSignednessTest(EXPECT_EQ(true, (Checked<type, RecordOverflow>(value + 1)).hasOverflowed())); \
    121         MixedSignednessTest(EXPECT_EQ(true, !(value++).hasOverflowed())); \
    122         MixedSignednessTest(EXPECT_EQ(true, value.hasOverflowed())); \
    123         value = std::numeric_limits<type>::max(); \
    124         MixedSignednessTest(EXPECT_EQ(true, (value += 1).hasOverflowed())); \
    125         MixedSignednessTest(EXPECT_EQ(true, value.hasOverflowed())); \
    126         value = std::numeric_limits<type>::min(); \
    127         MixedSignednessTest(EXPECT_EQ(true, (value - 1U).hasOverflowed())); \
    128         MixedSignednessTest(EXPECT_EQ(true, !(value--).hasOverflowed())); \
    129         MixedSignednessTest(EXPECT_EQ(true, value.hasOverflowed())); \
    130         value = std::numeric_limits<type>::max(); \
    131         MixedSignednessTest(EXPECT_EQ(true, !value.hasOverflowed())); \
    132         MixedSignednessTest(EXPECT_EQ(true, (Checked<type, RecordOverflow>(value + 1U)).hasOverflowed())); \
    133         MixedSignednessTest(EXPECT_EQ(true, !(value++).hasOverflowed())); \
    134         MixedSignednessTest(EXPECT_EQ(true, value.hasOverflowed())); \
    135         value = std::numeric_limits<type>::max(); \
    136         MixedSignednessTest(EXPECT_EQ(true, (value += 1U).hasOverflowed())); \
    137         MixedSignednessTest(EXPECT_EQ(true, value.hasOverflowed())); \
    138     }
    139 
    140 #define CoerceLiteralToUnsigned(x) x##U
    141 #define CoerceLiteralNop(x) x
    142 #define AllowMixedSignednessTest(x) x
    143 #define IgnoreMixedSignednessTest(x)
    144 CheckedArithmeticTest(int8_t, CoerceLiteralNop, IgnoreMixedSignednessTest)
    145 CheckedArithmeticTest(int16_t, CoerceLiteralNop, IgnoreMixedSignednessTest)
    146 CheckedArithmeticTest(int32_t, CoerceLiteralNop, AllowMixedSignednessTest)
    147 CheckedArithmeticTest(uint32_t, CoerceLiteralToUnsigned, AllowMixedSignednessTest)
    148 CheckedArithmeticTest(int64_t, CoerceLiteralNop, IgnoreMixedSignednessTest)
    149 CheckedArithmeticTest(uint64_t, CoerceLiteralToUnsigned, IgnoreMixedSignednessTest)
    150 
    151 } // namespace
    152