summaryrefslogtreecommitdiffstats
path: root/mfbt/tests/TestAtomics.cpp
diff options
context:
space:
mode:
Diffstat (limited to '')
-rw-r--r--mfbt/tests/TestAtomics.cpp274
1 files changed, 274 insertions, 0 deletions
diff --git a/mfbt/tests/TestAtomics.cpp b/mfbt/tests/TestAtomics.cpp
new file mode 100644
index 0000000000..7d333d37c1
--- /dev/null
+++ b/mfbt/tests/TestAtomics.cpp
@@ -0,0 +1,274 @@
+/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* vim: set ts=8 sts=2 et sw=2 tw=80: */
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+#include "mozilla/Assertions.h"
+#include "mozilla/Atomics.h"
+
+#include <stdint.h>
+
+using mozilla::Atomic;
+using mozilla::MemoryOrdering;
+using mozilla::Relaxed;
+using mozilla::ReleaseAcquire;
+using mozilla::SequentiallyConsistent;
+
+#define A(a, b) MOZ_RELEASE_ASSERT(a, b)
+
+template <typename T, MemoryOrdering Order>
+static void TestTypeWithOrdering() {
+ Atomic<T, Order> atomic(5);
+ A(atomic == 5, "Atomic variable did not initialize");
+
+ // Test atomic increment
+ A(++atomic == T(6), "Atomic increment did not work");
+ A(atomic++ == T(6), "Atomic post-increment did not work");
+ A(atomic == T(7), "Atomic post-increment did not work");
+
+ // Test atomic decrement
+ A(--atomic == 6, "Atomic decrement did not work");
+ A(atomic-- == 6, "Atomic post-decrement did not work");
+ A(atomic == 5, "Atomic post-decrement did not work");
+
+ // Test other arithmetic.
+ T result;
+ result = (atomic += T(5));
+ A(atomic == T(10), "Atomic += did not work");
+ A(result == T(10), "Atomic += returned the wrong value");
+ result = (atomic -= T(3));
+ A(atomic == T(7), "Atomic -= did not work");
+ A(result == T(7), "Atomic -= returned the wrong value");
+
+ // Test assignment
+ result = (atomic = T(5));
+ A(atomic == T(5), "Atomic assignment failed");
+ A(result == T(5), "Atomic assignment returned the wrong value");
+
+ // Test logical operations.
+ result = (atomic ^= T(2));
+ A(atomic == T(7), "Atomic ^= did not work");
+ A(result == T(7), "Atomic ^= returned the wrong value");
+ result = (atomic ^= T(4));
+ A(atomic == T(3), "Atomic ^= did not work");
+ A(result == T(3), "Atomic ^= returned the wrong value");
+ result = (atomic |= T(8));
+ A(atomic == T(11), "Atomic |= did not work");
+ A(result == T(11), "Atomic |= returned the wrong value");
+ result = (atomic |= T(8));
+ A(atomic == T(11), "Atomic |= did not work");
+ A(result == T(11), "Atomic |= returned the wrong value");
+ result = (atomic &= T(12));
+ A(atomic == T(8), "Atomic &= did not work");
+ A(result == T(8), "Atomic &= returned the wrong value");
+
+ // Test exchange.
+ atomic = T(30);
+ result = atomic.exchange(42);
+ A(atomic == T(42), "Atomic exchange did not work");
+ A(result == T(30), "Atomic exchange returned the wrong value");
+
+ // Test CAS.
+ atomic = T(1);
+ bool boolResult = atomic.compareExchange(0, 2);
+ A(!boolResult, "CAS should have returned false.");
+ A(atomic == T(1), "CAS shouldn't have done anything.");
+
+ boolResult = atomic.compareExchange(1, 42);
+ A(boolResult, "CAS should have succeeded.");
+ A(atomic == T(42), "CAS should have changed atomic's value.");
+}
+
+template <typename T, MemoryOrdering Order>
+static void TestPointerWithOrdering() {
+ T array1[10];
+ Atomic<T*, Order> atomic(array1);
+ A(atomic == array1, "Atomic variable did not initialize");
+
+ // Test atomic increment
+ A(++atomic == array1 + 1, "Atomic increment did not work");
+ A(atomic++ == array1 + 1, "Atomic post-increment did not work");
+ A(atomic == array1 + 2, "Atomic post-increment did not work");
+
+ // Test atomic decrement
+ A(--atomic == array1 + 1, "Atomic decrement did not work");
+ A(atomic-- == array1 + 1, "Atomic post-decrement did not work");
+ A(atomic == array1, "Atomic post-decrement did not work");
+
+ // Test other arithmetic operations
+ T* result;
+ result = (atomic += 2);
+ A(atomic == array1 + 2, "Atomic += did not work");
+ A(result == array1 + 2, "Atomic += returned the wrong value");
+ result = (atomic -= 1);
+ A(atomic == array1 + 1, "Atomic -= did not work");
+ A(result == array1 + 1, "Atomic -= returned the wrong value");
+
+ // Test stores
+ result = (atomic = array1);
+ A(atomic == array1, "Atomic assignment did not work");
+ A(result == array1, "Atomic assignment returned the wrong value");
+
+ // Test exchange
+ atomic = array1 + 2;
+ result = atomic.exchange(array1);
+ A(atomic == array1, "Atomic exchange did not work");
+ A(result == array1 + 2, "Atomic exchange returned the wrong value");
+
+ atomic = array1;
+ bool boolResult = atomic.compareExchange(array1 + 1, array1 + 2);
+ A(!boolResult, "CAS should have returned false.");
+ A(atomic == array1, "CAS shouldn't have done anything.");
+
+ boolResult = atomic.compareExchange(array1, array1 + 3);
+ A(boolResult, "CAS should have succeeded.");
+ A(atomic == array1 + 3, "CAS should have changed atomic's value.");
+}
+
+enum EnumType {
+ EnumType_0 = 0,
+ EnumType_1 = 1,
+ EnumType_2 = 2,
+ EnumType_3 = 3
+};
+
+template <MemoryOrdering Order>
+static void TestEnumWithOrdering() {
+ Atomic<EnumType, Order> atomic(EnumType_2);
+ A(atomic == EnumType_2, "Atomic variable did not initialize");
+
+ // Test assignment
+ EnumType result;
+ result = (atomic = EnumType_3);
+ A(atomic == EnumType_3, "Atomic assignment failed");
+ A(result == EnumType_3, "Atomic assignment returned the wrong value");
+
+ // Test exchange.
+ atomic = EnumType_1;
+ result = atomic.exchange(EnumType_2);
+ A(atomic == EnumType_2, "Atomic exchange did not work");
+ A(result == EnumType_1, "Atomic exchange returned the wrong value");
+
+ // Test CAS.
+ atomic = EnumType_1;
+ bool boolResult = atomic.compareExchange(EnumType_0, EnumType_2);
+ A(!boolResult, "CAS should have returned false.");
+ A(atomic == EnumType_1, "CAS shouldn't have done anything.");
+
+ boolResult = atomic.compareExchange(EnumType_1, EnumType_3);
+ A(boolResult, "CAS should have succeeded.");
+ A(atomic == EnumType_3, "CAS should have changed atomic's value.");
+}
+
+enum class EnumClass : uint32_t {
+ Value0 = 0,
+ Value1 = 1,
+ Value2 = 2,
+ Value3 = 3
+};
+
+template <MemoryOrdering Order>
+static void TestEnumClassWithOrdering() {
+ Atomic<EnumClass, Order> atomic(EnumClass::Value2);
+ A(atomic == EnumClass::Value2, "Atomic variable did not initialize");
+
+ // Test assignment
+ EnumClass result;
+ result = (atomic = EnumClass::Value3);
+ A(atomic == EnumClass::Value3, "Atomic assignment failed");
+ A(result == EnumClass::Value3, "Atomic assignment returned the wrong value");
+
+ // Test exchange.
+ atomic = EnumClass::Value1;
+ result = atomic.exchange(EnumClass::Value2);
+ A(atomic == EnumClass::Value2, "Atomic exchange did not work");
+ A(result == EnumClass::Value1, "Atomic exchange returned the wrong value");
+
+ // Test CAS.
+ atomic = EnumClass::Value1;
+ bool boolResult =
+ atomic.compareExchange(EnumClass::Value0, EnumClass::Value2);
+ A(!boolResult, "CAS should have returned false.");
+ A(atomic == EnumClass::Value1, "CAS shouldn't have done anything.");
+
+ boolResult = atomic.compareExchange(EnumClass::Value1, EnumClass::Value3);
+ A(boolResult, "CAS should have succeeded.");
+ A(atomic == EnumClass::Value3, "CAS should have changed atomic's value.");
+}
+
+template <MemoryOrdering Order>
+static void TestBoolWithOrdering() {
+ Atomic<bool, Order> atomic(false);
+ A(atomic == false, "Atomic variable did not initialize");
+
+ // Test assignment
+ bool result;
+ result = (atomic = true);
+ A(atomic == true, "Atomic assignment failed");
+ A(result == true, "Atomic assignment returned the wrong value");
+
+ // Test exchange.
+ atomic = false;
+ result = atomic.exchange(true);
+ A(atomic == true, "Atomic exchange did not work");
+ A(result == false, "Atomic exchange returned the wrong value");
+
+ // Test CAS.
+ atomic = false;
+ bool boolResult = atomic.compareExchange(true, false);
+ A(!boolResult, "CAS should have returned false.");
+ A(atomic == false, "CAS shouldn't have done anything.");
+
+ boolResult = atomic.compareExchange(false, true);
+ A(boolResult, "CAS should have succeeded.");
+ A(atomic == true, "CAS should have changed atomic's value.");
+}
+
+template <typename T>
+static void TestType() {
+ TestTypeWithOrdering<T, SequentiallyConsistent>();
+ TestTypeWithOrdering<T, ReleaseAcquire>();
+ TestTypeWithOrdering<T, Relaxed>();
+}
+
+template <typename T>
+static void TestPointer() {
+ TestPointerWithOrdering<T, SequentiallyConsistent>();
+ TestPointerWithOrdering<T, ReleaseAcquire>();
+ TestPointerWithOrdering<T, Relaxed>();
+}
+
+static void TestEnum() {
+ TestEnumWithOrdering<SequentiallyConsistent>();
+ TestEnumWithOrdering<ReleaseAcquire>();
+ TestEnumWithOrdering<Relaxed>();
+
+ TestEnumClassWithOrdering<SequentiallyConsistent>();
+ TestEnumClassWithOrdering<ReleaseAcquire>();
+ TestEnumClassWithOrdering<Relaxed>();
+}
+
+static void TestBool() {
+ TestBoolWithOrdering<SequentiallyConsistent>();
+ TestBoolWithOrdering<ReleaseAcquire>();
+ TestBoolWithOrdering<Relaxed>();
+}
+
+#undef A
+
+int main() {
+ TestType<uint32_t>();
+ TestType<int32_t>();
+ TestType<uint64_t>();
+ TestType<int64_t>();
+ TestType<intptr_t>();
+ TestType<uintptr_t>();
+ TestPointer<int>();
+ TestPointer<float>();
+ TestPointer<uint16_t*>();
+ TestPointer<uint32_t*>();
+ TestEnum();
+ TestBool();
+ return 0;
+}