Changeset 185708 in webkit


Ignore:
Timestamp:
Jun 18, 2015, 10:58:22 AM (10 years ago)
Author:
mark.lam@apple.com
Message:

Refactor CheckedArithmeticOperations.cpp to use templates instead of macros.
https://bugs.webkit.org/show_bug.cgi?id=146103

Reviewed by Anders Carlsson.

Presently, the tests in CheckedArithmeticOperations.cpp are all implemented as
part of a large macro. This makes them harder to:

  1. write: no editor help with indentations, have to add trailing '\'s, inconvenient to add line breaks and comments.
  1. read: no chroma coding / syntax highlighting.
  1. debug: compile time errors are reported as being on the single line where the macro is used.

Refactoring the tests to use C++ templates solves all these issues.

  • TestWebKitAPI/Tests/WTF/CheckedArithmeticOperations.cpp:

(TestWebKitAPI::CheckedArithmeticTester::run):
(TestWebKitAPI::AllowMixedSignednessTest::run):
(TestWebKitAPI::IgnoreMixedSignednessTest::run):
(TestWebKitAPI::CoerceLiteralToUnsigned::coerce):
(TestWebKitAPI::CoerceLiteralNop::coerce):

Location:
trunk/Tools
Files:
2 edited

Legend:

Unmodified
Added
Removed
  • trunk/Tools/ChangeLog

    r185701 r185708  
     12015-06-18  Mark Lam  <mark.lam@apple.com>
     2
     3        Refactor CheckedArithmeticOperations.cpp to use templates instead of macros.
     4        https://bugs.webkit.org/show_bug.cgi?id=146103
     5
     6        Reviewed by Anders Carlsson.
     7
     8        Presently, the tests in CheckedArithmeticOperations.cpp are all implemented as
     9        part of a large macro.  This makes them harder to:
     10
     11        1. write: no editor help with indentations, have to add trailing '\'s,
     12           inconvenient to add line breaks and comments.
     13
     14        2. read: no chroma coding / syntax highlighting.
     15
     16        3. debug: compile time errors are reported as being on the single line where
     17           the macro is used.
     18
     19        Refactoring the tests to use C++ templates solves all these issues.
     20
     21        * TestWebKitAPI/Tests/WTF/CheckedArithmeticOperations.cpp:
     22        (TestWebKitAPI::CheckedArithmeticTester::run):
     23        (TestWebKitAPI::AllowMixedSignednessTest::run):
     24        (TestWebKitAPI::IgnoreMixedSignednessTest::run):
     25        (TestWebKitAPI::CoerceLiteralToUnsigned::coerce):
     26        (TestWebKitAPI::CoerceLiteralNop::coerce):
     27
    1282015-06-18  Christophe Dumez  <ch.dumez@sisa.samsung.com>
    229
  • trunk/Tools/TestWebKitAPI/Tests/WTF/CheckedArithmeticOperations.cpp

    r145759 r185708  
    11/*
    2  * Copyright (C) 2011 Apple Inc. All rights reserved.
     2 * Copyright (C) 2011, 2015 Apple Inc. All rights reserved.
    33 *
    44 * Redistribution and use in source and binary forms, with or without
     
    2929namespace TestWebKitAPI {
    3030
    31 #define CheckedArithmeticTest(type, coerceLiteral, MixedSignednessTest) \
     31#define CheckedArithmeticTest(type, Coercer, MixedSignednessTester) \
    3232    TEST(WTF, Checked_##type) \
    3333    { \
    34         Checked<type, RecordOverflow> value; \
    35         EXPECT_EQ(coerceLiteral(0), value.unsafeGet()); \
    36         EXPECT_EQ(std::numeric_limits<type>::max(), (value + std::numeric_limits<type>::max()).unsafeGet()); \
    37         EXPECT_EQ(std::numeric_limits<type>::max(), (std::numeric_limits<type>::max() + value).unsafeGet()); \
    38         EXPECT_EQ(std::numeric_limits<type>::min(), (value + std::numeric_limits<type>::min()).unsafeGet()); \
    39         EXPECT_EQ(std::numeric_limits<type>::min(), (std::numeric_limits<type>::min() + value).unsafeGet()); \
    40         EXPECT_EQ(coerceLiteral(0), (value * coerceLiteral(0)).unsafeGet()); \
    41         EXPECT_EQ(coerceLiteral(0), (coerceLiteral(0) * value).unsafeGet()); \
    42         EXPECT_EQ(coerceLiteral(0), (value * value).unsafeGet()); \
    43         EXPECT_EQ(coerceLiteral(0), (value - coerceLiteral(0)).unsafeGet()); \
    44         EXPECT_EQ(coerceLiteral(0), (coerceLiteral(0) - value).unsafeGet()); \
    45         EXPECT_EQ(coerceLiteral(0), (value - value).unsafeGet()); \
    46         EXPECT_EQ(coerceLiteral(0), (value++).unsafeGet()); \
    47         EXPECT_EQ(coerceLiteral(1), (value--).unsafeGet()); \
    48         EXPECT_EQ(coerceLiteral(1), (++value).unsafeGet()); \
    49         EXPECT_EQ(coerceLiteral(0), (--value).unsafeGet()); \
    50         EXPECT_EQ(coerceLiteral(10), (value += coerceLiteral(10)).unsafeGet()); \
    51         EXPECT_EQ(coerceLiteral(10), value.unsafeGet()); \
    52         EXPECT_EQ(coerceLiteral(100), (value *= coerceLiteral(10)).unsafeGet()); \
    53         EXPECT_EQ(coerceLiteral(100), value.unsafeGet()); \
    54         EXPECT_EQ(coerceLiteral(0), (value -= coerceLiteral(100)).unsafeGet()); \
    55         EXPECT_EQ(coerceLiteral(0), value.unsafeGet()); \
    56         value = 10; \
    57         EXPECT_EQ(coerceLiteral(10), value.unsafeGet()); \
    58         EXPECT_EQ(coerceLiteral(0), (value - coerceLiteral(10)).unsafeGet()); \
    59         EXPECT_EQ(coerceLiteral(10), value.unsafeGet()); \
    60         value = std::numeric_limits<type>::min(); \
    61         EXPECT_EQ(true, (Checked<type, RecordOverflow>(value - coerceLiteral(1))).hasOverflowed()); \
    62         EXPECT_EQ(true, !((value--).hasOverflowed())); \
    63         EXPECT_EQ(true, value.hasOverflowed()); \
    64         value = std::numeric_limits<type>::max(); \
    65         EXPECT_EQ(true, !value.hasOverflowed()); \
    66         EXPECT_EQ(true, (Checked<type, RecordOverflow>(value + coerceLiteral(1))).hasOverflowed()); \
    67         EXPECT_EQ(true, !(value++).hasOverflowed()); \
    68         EXPECT_EQ(true, value.hasOverflowed()); \
    69         value = std::numeric_limits<type>::max(); \
    70         EXPECT_EQ(true, (value += coerceLiteral(1)).hasOverflowed()); \
    71         EXPECT_EQ(true, value.hasOverflowed()); \
    72         value = 10; \
    73         type _value = 0; \
    74         EXPECT_EQ(true, CheckedState::DidNotOverflow == (value * Checked<type, RecordOverflow>(0)).safeGet(_value)); \
    75         _value = 0; \
    76         EXPECT_EQ(true, CheckedState::DidNotOverflow == (Checked<type, RecordOverflow>(0) * value).safeGet(_value)); \
    77         _value = 0; \
    78         EXPECT_EQ(true, CheckedState::DidOverflow == (value * Checked<type, RecordOverflow>(std::numeric_limits<type>::max())).safeGet(_value)); \
    79         _value = 0; \
    80         EXPECT_EQ(true, CheckedState::DidOverflow == (Checked<type, RecordOverflow>(std::numeric_limits<type>::max()) * value).safeGet(_value)); \
    81         value = 0; \
    82         _value = 0; \
    83         EXPECT_EQ(true, CheckedState::DidNotOverflow == (value * Checked<type, RecordOverflow>(std::numeric_limits<type>::max())).safeGet(_value)); \
    84         _value = 0; \
    85         EXPECT_EQ(true, CheckedState::DidNotOverflow == (Checked<type, RecordOverflow>(std::numeric_limits<type>::max()) * value).safeGet(_value)); \
    86         value = 1; \
    87         _value = 0; \
    88         EXPECT_EQ(true, CheckedState::DidNotOverflow == (value * Checked<type, RecordOverflow>(std::numeric_limits<type>::max())).safeGet(_value)); \
    89         _value = 0; \
    90         EXPECT_EQ(true, CheckedState::DidNotOverflow == (Checked<type, RecordOverflow>(std::numeric_limits<type>::max()) * value).safeGet(_value)); \
    91         _value = 0; \
    92         value = 0; \
    93         EXPECT_EQ(true, CheckedState::DidNotOverflow == (value * Checked<type, RecordOverflow>(std::numeric_limits<type>::max())).safeGet(_value)); \
    94         _value = 0; \
    95         EXPECT_EQ(true, CheckedState::DidNotOverflow == (Checked<type, RecordOverflow>(std::numeric_limits<type>::max()) * (type)0).safeGet(_value)); \
    96         _value = 0; \
    97         value = 1; \
    98         EXPECT_EQ(true, CheckedState::DidNotOverflow == (value * Checked<type, RecordOverflow>(std::numeric_limits<type>::max())).safeGet(_value)); \
    99         _value = 0; \
    100         EXPECT_EQ(true, CheckedState::DidNotOverflow == (Checked<type, RecordOverflow>(std::numeric_limits<type>::max()) * (type)1).safeGet(_value)); \
    101         _value = 0; \
    102         value = 2; \
    103         EXPECT_EQ(true, CheckedState::DidOverflow == (value * Checked<type, RecordOverflow>(std::numeric_limits<type>::max())).safeGet(_value)); \
    104         _value = 0; \
    105         EXPECT_EQ(true, CheckedState::DidOverflow == (Checked<type, RecordOverflow>(std::numeric_limits<type>::max()) * (type)2).safeGet(_value)); \
    106         value = 10; \
    107         EXPECT_EQ(true, (value * Checked<type, RecordOverflow>(std::numeric_limits<type>::max())).hasOverflowed()); \
    108         MixedSignednessTest(EXPECT_EQ(coerceLiteral(0), (value + -10).unsafeGet())); \
    109         MixedSignednessTest(EXPECT_EQ(0U, (value - 10U).unsafeGet())); \
    110         MixedSignednessTest(EXPECT_EQ(coerceLiteral(0), (-10 + value).unsafeGet())); \
    111         MixedSignednessTest(EXPECT_EQ(0U, (10U - value).unsafeGet())); \
    112         value = std::numeric_limits<type>::min(); \
    113         MixedSignednessTest(EXPECT_EQ(true, (Checked<type, RecordOverflow>(value - 1)).hasOverflowed())); \
    114         MixedSignednessTest(EXPECT_EQ(true, !(value--).hasOverflowed())); \
    115         MixedSignednessTest(EXPECT_EQ(true, value.hasOverflowed())); \
    116         value = std::numeric_limits<type>::max(); \
    117         MixedSignednessTest(EXPECT_EQ(true, !value.hasOverflowed())); \
    118         MixedSignednessTest(EXPECT_EQ(true, (Checked<type, RecordOverflow>(value + 1)).hasOverflowed())); \
    119         MixedSignednessTest(EXPECT_EQ(true, !(value++).hasOverflowed())); \
    120         MixedSignednessTest(EXPECT_EQ(true, value.hasOverflowed())); \
    121         value = std::numeric_limits<type>::max(); \
    122         MixedSignednessTest(EXPECT_EQ(true, (value += 1).hasOverflowed())); \
    123         MixedSignednessTest(EXPECT_EQ(true, value.hasOverflowed())); \
    124         value = std::numeric_limits<type>::min(); \
    125         MixedSignednessTest(EXPECT_EQ(true, (value - 1U).hasOverflowed())); \
    126         MixedSignednessTest(EXPECT_EQ(true, !(value--).hasOverflowed())); \
    127         MixedSignednessTest(EXPECT_EQ(true, value.hasOverflowed())); \
    128         value = std::numeric_limits<type>::max(); \
    129         MixedSignednessTest(EXPECT_EQ(true, !value.hasOverflowed())); \
    130         MixedSignednessTest(EXPECT_EQ(true, (Checked<type, RecordOverflow>(value + 1U)).hasOverflowed())); \
    131         MixedSignednessTest(EXPECT_EQ(true, !(value++).hasOverflowed())); \
    132         MixedSignednessTest(EXPECT_EQ(true, value.hasOverflowed())); \
    133         value = std::numeric_limits<type>::max(); \
    134         MixedSignednessTest(EXPECT_EQ(true, (value += 1U).hasOverflowed())); \
    135         MixedSignednessTest(EXPECT_EQ(true, value.hasOverflowed())); \
     34        typedef Coercer<type> CoercerType; \
     35        typedef MixedSignednessTester<type, CoercerType> MixedSignednessTesterType; \
     36        CheckedArithmeticTester<type, CoercerType, MixedSignednessTesterType>(); \
    13637    }
     38   
     39#define coerceLiteral(x) Coerser::coerce(x)
     40   
     41template <typename type, typename Coerser, typename MixedSignednessTester>
     42class CheckedArithmeticTester {
     43public:
     44    static void run()
     45    {
     46        Checked<type, RecordOverflow> value;
     47        EXPECT_EQ(coerceLiteral(0), value.unsafeGet());
     48        EXPECT_EQ(std::numeric_limits<type>::max(), (value + std::numeric_limits<type>::max()).unsafeGet());
     49        EXPECT_EQ(std::numeric_limits<type>::max(), (std::numeric_limits<type>::max() + value).unsafeGet());
     50        EXPECT_EQ(std::numeric_limits<type>::min(), (value + std::numeric_limits<type>::min()).unsafeGet());
     51        EXPECT_EQ(std::numeric_limits<type>::min(), (std::numeric_limits<type>::min() + value).unsafeGet());
    13752
    138 #define CoerceLiteralToUnsigned(x) x##U
    139 #define CoerceLiteralNop(x) x
    140 #define AllowMixedSignednessTest(x) x
    141 #define IgnoreMixedSignednessTest(x)
     53        EXPECT_EQ(coerceLiteral(0), (value * coerceLiteral(0)).unsafeGet());
     54        EXPECT_EQ(coerceLiteral(0), (coerceLiteral(0) * value).unsafeGet());
     55        EXPECT_EQ(coerceLiteral(0), (value * value).unsafeGet());
     56        EXPECT_EQ(coerceLiteral(0), (value - coerceLiteral(0)).unsafeGet());
     57        EXPECT_EQ(coerceLiteral(0), (coerceLiteral(0) - value).unsafeGet());
     58        EXPECT_EQ(coerceLiteral(0), (value - value).unsafeGet());
     59        EXPECT_EQ(coerceLiteral(0), (value++).unsafeGet());
     60        EXPECT_EQ(coerceLiteral(1), (value--).unsafeGet());
     61        EXPECT_EQ(coerceLiteral(1), (++value).unsafeGet());
     62        EXPECT_EQ(coerceLiteral(0), (--value).unsafeGet());
     63        EXPECT_EQ(coerceLiteral(10), (value += coerceLiteral(10)).unsafeGet());
     64        EXPECT_EQ(coerceLiteral(10), value.unsafeGet());
     65        EXPECT_EQ(coerceLiteral(100), (value *= coerceLiteral(10)).unsafeGet());
     66        EXPECT_EQ(coerceLiteral(100), value.unsafeGet());
     67        EXPECT_EQ(coerceLiteral(0), (value -= coerceLiteral(100)).unsafeGet());
     68        EXPECT_EQ(coerceLiteral(0), value.unsafeGet());
     69        value = 10;
     70        EXPECT_EQ(coerceLiteral(10), value.unsafeGet());
     71        EXPECT_EQ(coerceLiteral(0), (value - coerceLiteral(10)).unsafeGet());
     72        EXPECT_EQ(coerceLiteral(10), value.unsafeGet());
     73
     74        value = std::numeric_limits<type>::min();
     75        EXPECT_EQ(true, (Checked<type, RecordOverflow>(value - coerceLiteral(1))).hasOverflowed());
     76        EXPECT_EQ(true, !((value--).hasOverflowed()));
     77        EXPECT_EQ(true, value.hasOverflowed());
     78        value = std::numeric_limits<type>::max();
     79        EXPECT_EQ(true, !value.hasOverflowed());
     80        EXPECT_EQ(true, (Checked<type, RecordOverflow>(value + coerceLiteral(1))).hasOverflowed());
     81        EXPECT_EQ(true, !(value++).hasOverflowed());
     82        EXPECT_EQ(true, value.hasOverflowed());
     83        value = std::numeric_limits<type>::max();
     84        EXPECT_EQ(true, (value += coerceLiteral(1)).hasOverflowed());
     85        EXPECT_EQ(true, value.hasOverflowed());
     86
     87        value = 10;
     88        type _value = 0;
     89        EXPECT_EQ(true, CheckedState::DidNotOverflow == (value * Checked<type, RecordOverflow>(0)).safeGet(_value));
     90        _value = 0;
     91        EXPECT_EQ(true, CheckedState::DidNotOverflow == (Checked<type, RecordOverflow>(0) * value).safeGet(_value));
     92        _value = 0;
     93        EXPECT_EQ(true, CheckedState::DidOverflow == (value * Checked<type, RecordOverflow>(std::numeric_limits<type>::max())).safeGet(_value));
     94        _value = 0;
     95        EXPECT_EQ(true, CheckedState::DidOverflow == (Checked<type, RecordOverflow>(std::numeric_limits<type>::max()) * value).safeGet(_value));
     96        value = 0;
     97        _value = 0;
     98        EXPECT_EQ(true, CheckedState::DidNotOverflow == (value * Checked<type, RecordOverflow>(std::numeric_limits<type>::max())).safeGet(_value));
     99        _value = 0;
     100        EXPECT_EQ(true, CheckedState::DidNotOverflow == (Checked<type, RecordOverflow>(std::numeric_limits<type>::max()) * value).safeGet(_value));
     101        value = 1;
     102        _value = 0;
     103        EXPECT_EQ(true, CheckedState::DidNotOverflow == (value * Checked<type, RecordOverflow>(std::numeric_limits<type>::max())).safeGet(_value));
     104        _value = 0;
     105        EXPECT_EQ(true, CheckedState::DidNotOverflow == (Checked<type, RecordOverflow>(std::numeric_limits<type>::max()) * value).safeGet(_value));
     106        _value = 0;
     107        value = 0;
     108        EXPECT_EQ(true, CheckedState::DidNotOverflow == (value * Checked<type, RecordOverflow>(std::numeric_limits<type>::max())).safeGet(_value));
     109        _value = 0;
     110        EXPECT_EQ(true, CheckedState::DidNotOverflow == (Checked<type, RecordOverflow>(std::numeric_limits<type>::max()) * (type)0).safeGet(_value));
     111        _value = 0;
     112        value = 1;
     113        EXPECT_EQ(true, CheckedState::DidNotOverflow == (value * Checked<type, RecordOverflow>(std::numeric_limits<type>::max())).safeGet(_value));
     114        _value = 0;
     115        EXPECT_EQ(true, CheckedState::DidNotOverflow == (Checked<type, RecordOverflow>(std::numeric_limits<type>::max()) * (type)1).safeGet(_value));
     116        _value = 0;
     117        value = 2;
     118        EXPECT_EQ(true, CheckedState::DidOverflow == (value * Checked<type, RecordOverflow>(std::numeric_limits<type>::max())).safeGet(_value));
     119        _value = 0;
     120        EXPECT_EQ(true, CheckedState::DidOverflow == (Checked<type, RecordOverflow>(std::numeric_limits<type>::max()) * (type)2).safeGet(_value));
     121        value = 10;
     122        EXPECT_EQ(true, (value * Checked<type, RecordOverflow>(std::numeric_limits<type>::max())).hasOverflowed());
     123
     124        MixedSignednessTester::run();
     125    }
     126};
     127
     128template <typename type, typename Coerser>
     129class AllowMixedSignednessTest {
     130public:
     131    static void run()
     132    {
     133        Checked<type, RecordOverflow> value;
     134        value = 10;
     135
     136        EXPECT_EQ(coerceLiteral(0), (value + -10).unsafeGet());
     137        EXPECT_EQ(0U, (value - 10U).unsafeGet());
     138        EXPECT_EQ(coerceLiteral(0), (-10 + value).unsafeGet());
     139        EXPECT_EQ(0U, (10U - value).unsafeGet());
     140        value = std::numeric_limits<type>::min();
     141        EXPECT_EQ(true, (Checked<type, RecordOverflow>(value - 1)).hasOverflowed());
     142        EXPECT_EQ(true, !(value--).hasOverflowed());
     143        EXPECT_EQ(true, value.hasOverflowed());
     144        value = std::numeric_limits<type>::max();
     145        EXPECT_EQ(true, !value.hasOverflowed());
     146        EXPECT_EQ(true, (Checked<type, RecordOverflow>(value + 1)).hasOverflowed());
     147        EXPECT_EQ(true, !(value++).hasOverflowed());
     148        EXPECT_EQ(true, value.hasOverflowed());
     149        value = std::numeric_limits<type>::max();
     150        EXPECT_EQ(true, (value += 1).hasOverflowed());
     151        EXPECT_EQ(true, value.hasOverflowed());
     152        value = std::numeric_limits<type>::min();
     153        EXPECT_EQ(true, (value - 1U).hasOverflowed());
     154        EXPECT_EQ(true, !(value--).hasOverflowed());
     155        EXPECT_EQ(true, value.hasOverflowed());
     156        value = std::numeric_limits<type>::max();
     157        EXPECT_EQ(true, !value.hasOverflowed());
     158        EXPECT_EQ(true, (Checked<type, RecordOverflow>(value + 1U)).hasOverflowed());
     159        EXPECT_EQ(true, !(value++).hasOverflowed());
     160        EXPECT_EQ(true, value.hasOverflowed());
     161        value = std::numeric_limits<type>::max();
     162        EXPECT_EQ(true, (value += 1U).hasOverflowed());
     163        EXPECT_EQ(true, value.hasOverflowed());
     164    }
     165};
     166
     167template <typename type, typename Coerser>
     168class IgnoreMixedSignednessTest {
     169public:
     170    static void run() { }
     171};
     172
     173template <typename type> class CoerceLiteralToUnsigned {
     174public:
     175    static unsigned coerce(type x) { return static_cast<unsigned>(x); }
     176};
     177   
     178template <typename type> class CoerceLiteralNop {
     179public:
     180    static type coerce(type x) { return x; }
     181};
     182
    142183CheckedArithmeticTest(int8_t, CoerceLiteralNop, IgnoreMixedSignednessTest)
    143184CheckedArithmeticTest(int16_t, CoerceLiteralNop, IgnoreMixedSignednessTest)
Note: See TracChangeset for help on using the changeset viewer.