1/**************************************************************************
2 *
3 * Copyright 2014 VMware, Inc.
4 * All Rights Reserved.
5 *
6 * Permission is hereby granted, free of charge, to any person obtaining a
7 * copy of this software and associated documentation files (the
8 * "Software"), to deal in the Software without restriction, including
9 * without limitation the rights to use, copy, modify, merge, publish,
10 * distribute, sub license, and/or sell copies of the Software, and to
11 * permit persons to whom the Software is furnished to do so, subject to
12 * the following conditions:
13 *
14 * The above copyright notice and this permission notice (including the
15 * next paragraph) shall be included in all copies or substantial portions
16 * of the Software.
17 *
18 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
19 * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
20 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
21 * IN NO EVENT SHALL VMWARE AND/OR ITS SUPPLIERS BE LIABLE FOR
22 * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
23 * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
24 * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
25 *
26 **************************************************************************/
27
28#include <gtest/gtest.h>
29#include <stdint.h>
30#include <inttypes.h>
31
32#include "u_atomic.h"
33
34#ifdef _MSC_VER
35#pragma warning( disable : 28112 ) /* Accessing a local variable via an Interlocked function */
36#pragma warning( disable : 28113 ) /* A variable which is accessed via an Interlocked function must always be accessed via an Interlocked function */
37#endif
38
39template <typename T> class AtomicAssignment : public testing::Test {};
40
41using AtomicAssignmentTypes =
42   testing::Types<int, unsigned, bool,
43                  int8_t, uint8_t, int16_t, uint16_t,
44                  int32_t, uint32_t, int64_t, uint64_t>;
45
46TYPED_TEST_SUITE(AtomicAssignment, AtomicAssignmentTypes);
47
48TYPED_TEST(AtomicAssignment, Test)
49{
50   TypeParam v, r;
51   const TypeParam ones = TypeParam(-1);
52
53   p_atomic_set(&v, ones);
54   ASSERT_EQ(v, ones) << "p_atomic_set";
55
56   r = p_atomic_read(&v);
57   ASSERT_EQ(r, ones) << "p_atomic_read";
58
59   v = ones;
60   r = p_atomic_cmpxchg(&v, 0, 1);
61   ASSERT_EQ(v, ones) << "p_atomic_cmpxchg";
62   ASSERT_EQ(r, ones) << "p_atomic_cmpxchg";
63
64   r = p_atomic_cmpxchg(&v, ones, 0);
65   ASSERT_EQ(v, 0) << "p_atomic_cmpxchg";
66   ASSERT_EQ(r, ones) << "p_atomic_cmpxchg";
67}
68
69
70template <typename T> class AtomicIncrementDecrement : public testing::Test {};
71
72using AtomicIncrementDecrementTypes =
73   testing::Types<int, unsigned,
74                  int16_t, uint16_t,
75                  int32_t, uint32_t, int64_t, uint64_t>;
76
77TYPED_TEST_SUITE(AtomicIncrementDecrement, AtomicIncrementDecrementTypes);
78
79TYPED_TEST(AtomicIncrementDecrement, Test)
80{
81   TypeParam v, r;
82   bool b;
83
84   const TypeParam ones = TypeParam(-1);
85
86   v = 2;
87
88   b = p_atomic_dec_zero(&v);
89   ASSERT_EQ(v, 1) << "p_atomic_dec_zero";
90   ASSERT_FALSE(b) << "p_atomic_dec_zero";
91
92   b = p_atomic_dec_zero(&v);
93   ASSERT_EQ(v, 0) << "p_atomic_dec_zero";
94   ASSERT_TRUE(b)  << "p_atomic_dec_zero";
95
96   b = p_atomic_dec_zero(&v);
97   ASSERT_EQ(v, ones) << "p_atomic_dec_zero";
98   ASSERT_FALSE(b) << "p_atomic_dec_zero";
99
100   v = ones;
101   p_atomic_inc(&v);
102   ASSERT_EQ(v, 0) << "p_atomic_inc";
103
104   v = ones;
105   r = p_atomic_inc_return(&v);
106   ASSERT_EQ(v, 0) << "p_atomic_inc_return";
107   ASSERT_EQ(r, v) << "p_atomic_inc_return";
108
109   v = 0;
110   p_atomic_dec(&v);
111   ASSERT_EQ(v, ones) << "p_atomic_dec";
112
113   v = 0;
114   r = p_atomic_dec_return(&v);
115   ASSERT_EQ(v, ones) << "p_atomic_dec_return";
116   ASSERT_EQ(v, r) << "p_atomic_dec_return";
117}
118
119template <typename T> class AtomicAdd : public testing::Test {};
120
121using AtomicAddTypes =
122   testing::Types<int, unsigned,
123                  int8_t, uint8_t, int16_t, uint16_t,
124                  int32_t, uint32_t, int64_t, uint64_t>;
125
126TYPED_TEST_SUITE(AtomicAdd, AtomicAddTypes);
127
128TYPED_TEST(AtomicAdd, Test)
129{
130   TypeParam v, r;
131
132   v = 23;
133
134   p_atomic_add(&v, 42);
135   r = p_atomic_read(&v);
136
137   ASSERT_EQ(r, 65) << "p_atomic_add";
138}
139