From b492eae3b74de8a1258ec4331f61ec4ea124826e Mon Sep 17 00:00:00 2001 From: "deanm@google.com" Date: Fri, 29 Aug 2008 09:45:09 +0000 Subject: Import upstream atomicop tests. git-svn-id: svn://svn.chromium.org/chrome/trunk/src@1522 0039d316-1c4b-4281-b951-d872f2087c98 --- base/atomicops_unittest.cc | 229 +++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 229 insertions(+) create mode 100644 base/atomicops_unittest.cc (limited to 'base/atomicops_unittest.cc') diff --git a/base/atomicops_unittest.cc b/base/atomicops_unittest.cc new file mode 100644 index 0000000..a7aa092 --- /dev/null +++ b/base/atomicops_unittest.cc @@ -0,0 +1,229 @@ +// Copyright (c) 2006-2008 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "base/atomicops.h" +#include "testing/gtest/include/gtest/gtest.h" + +template +static void TestAtomicIncrement() { + // For now, we just test single threaded execution + + // use a guard value to make sure the NoBarrier_AtomicIncrement doesn't go + // outside the expected address bounds. This is in particular to + // test that some future change to the asm code doesn't cause the + // 32-bit NoBarrier_AtomicIncrement doesn't do the wrong thing on 64-bit + // machines. + struct { + AtomicType prev_word; + AtomicType count; + AtomicType next_word; + } s; + + AtomicType prev_word_value, next_word_value; + memset(&prev_word_value, 0xFF, sizeof(AtomicType)); + memset(&next_word_value, 0xEE, sizeof(AtomicType)); + + s.prev_word = prev_word_value; + s.count = 0; + s.next_word = next_word_value; + + EXPECT_EQ(base::subtle::NoBarrier_AtomicIncrement(&s.count, 1), 1); + EXPECT_EQ(s.count, 1); + EXPECT_EQ(s.prev_word, prev_word_value); + EXPECT_EQ(s.next_word, next_word_value); + + EXPECT_EQ(base::subtle::NoBarrier_AtomicIncrement(&s.count, 2), 3); + EXPECT_EQ(s.count, 3); + EXPECT_EQ(s.prev_word, prev_word_value); + EXPECT_EQ(s.next_word, next_word_value); + + EXPECT_EQ(base::subtle::NoBarrier_AtomicIncrement(&s.count, 3), 6); + EXPECT_EQ(s.count, 6); + EXPECT_EQ(s.prev_word, prev_word_value); + EXPECT_EQ(s.next_word, next_word_value); + + EXPECT_EQ(base::subtle::NoBarrier_AtomicIncrement(&s.count, -3), 3); + EXPECT_EQ(s.count, 3); + EXPECT_EQ(s.prev_word, prev_word_value); + EXPECT_EQ(s.next_word, next_word_value); + + EXPECT_EQ(base::subtle::NoBarrier_AtomicIncrement(&s.count, -2), 1); + EXPECT_EQ(s.count, 1); + EXPECT_EQ(s.prev_word, prev_word_value); + EXPECT_EQ(s.next_word, next_word_value); + + EXPECT_EQ(base::subtle::NoBarrier_AtomicIncrement(&s.count, -1), 0); + EXPECT_EQ(s.count, 0); + EXPECT_EQ(s.prev_word, prev_word_value); + EXPECT_EQ(s.next_word, next_word_value); + + EXPECT_EQ(base::subtle::NoBarrier_AtomicIncrement(&s.count, -1), -1); + EXPECT_EQ(s.count, -1); + EXPECT_EQ(s.prev_word, prev_word_value); + EXPECT_EQ(s.next_word, next_word_value); + + EXPECT_EQ(base::subtle::NoBarrier_AtomicIncrement(&s.count, -4), -5); + EXPECT_EQ(s.count, -5); + EXPECT_EQ(s.prev_word, prev_word_value); + EXPECT_EQ(s.next_word, next_word_value); + + EXPECT_EQ(base::subtle::NoBarrier_AtomicIncrement(&s.count, 5), 0); + EXPECT_EQ(s.count, 0); + EXPECT_EQ(s.prev_word, prev_word_value); + EXPECT_EQ(s.next_word, next_word_value); +} + + +#define NUM_BITS(T) (sizeof(T) * 8) + + +template +static void TestCompareAndSwap() { + AtomicType value = 0; + AtomicType prev = base::subtle::NoBarrier_CompareAndSwap(&value, 0, 1); + EXPECT_EQ(1, value); + EXPECT_EQ(0, prev); + + // Use test value that has non-zero bits in both halves, more for testing + // 64-bit implementation on 32-bit platforms. + const AtomicType k_test_val = (GG_ULONGLONG(1) << + (NUM_BITS(AtomicType) - 2)) + 11; + value = k_test_val; + prev = base::subtle::NoBarrier_CompareAndSwap(&value, 0, 5); + EXPECT_EQ(k_test_val, value); + EXPECT_EQ(k_test_val, prev); + + value = k_test_val; + prev = base::subtle::NoBarrier_CompareAndSwap(&value, k_test_val, 5); + EXPECT_EQ(5, value); + EXPECT_EQ(k_test_val, prev); +} + + +template +static void TestAtomicExchange() { + AtomicType value = 0; + AtomicType new_value = base::subtle::NoBarrier_AtomicExchange(&value, 1); + EXPECT_EQ(1, value); + EXPECT_EQ(0, new_value); + + // Use test value that has non-zero bits in both halves, more for testing + // 64-bit implementation on 32-bit platforms. + const AtomicType k_test_val = (GG_ULONGLONG(1) << + (NUM_BITS(AtomicType) - 2)) + 11; + value = k_test_val; + new_value = base::subtle::NoBarrier_AtomicExchange(&value, k_test_val); + EXPECT_EQ(k_test_val, value); + EXPECT_EQ(k_test_val, new_value); + + value = k_test_val; + new_value = base::subtle::NoBarrier_AtomicExchange(&value, 5); + EXPECT_EQ(5, value); + EXPECT_EQ(k_test_val, new_value); +} + + +template +static void TestAtomicIncrementBounds() { + // Test at rollover boundary between int_max and int_min + AtomicType test_val = (GG_ULONGLONG(1) << + (NUM_BITS(AtomicType) - 1)); + AtomicType value = -1 ^ test_val; + AtomicType new_value = base::subtle::NoBarrier_AtomicIncrement(&value, 1); + EXPECT_EQ(test_val, value); + EXPECT_EQ(value, new_value); + + base::subtle::NoBarrier_AtomicIncrement(&value, -1); + EXPECT_EQ(-1 ^ test_val, value); + + // Test at 32-bit boundary for 64-bit atomic type. + test_val = GG_ULONGLONG(1) << (NUM_BITS(AtomicType) / 2); + value = test_val - 1; + new_value = base::subtle::NoBarrier_AtomicIncrement(&value, 1); + EXPECT_EQ(test_val, value); + EXPECT_EQ(value, new_value); + + base::subtle::NoBarrier_AtomicIncrement(&value, -1); + EXPECT_EQ(test_val - 1, value); +} + +// This is a simple sanity check that values are correct. Not testing +// atomicity +template +static void TestStore() { + const AtomicType kVal1 = static_cast(0xa5a5a5a5a5a5a5a5LL); + const AtomicType kVal2 = static_cast(-1); + + AtomicType value; + + base::subtle::NoBarrier_Store(&value, kVal1); + EXPECT_EQ(kVal1, value); + base::subtle::NoBarrier_Store(&value, kVal2); + EXPECT_EQ(kVal2, value); + + base::subtle::Acquire_Store(&value, kVal1); + EXPECT_EQ(kVal1, value); + base::subtle::Acquire_Store(&value, kVal2); + EXPECT_EQ(kVal2, value); + + base::subtle::Release_Store(&value, kVal1); + EXPECT_EQ(kVal1, value); + base::subtle::Release_Store(&value, kVal2); + EXPECT_EQ(kVal2, value); +} + +// This is a simple sanity check that values are correct. Not testing +// atomicity +template +static void TestLoad() { + const AtomicType kVal1 = static_cast(0xa5a5a5a5a5a5a5a5LL); + const AtomicType kVal2 = static_cast(-1); + + AtomicType value; + + value = kVal1; + EXPECT_EQ(kVal1, base::subtle::NoBarrier_Load(&value)); + value = kVal2; + EXPECT_EQ(kVal2, base::subtle::NoBarrier_Load(&value)); + + value = kVal1; + EXPECT_EQ(kVal1, base::subtle::Acquire_Load(&value)); + value = kVal2; + EXPECT_EQ(kVal2, base::subtle::Acquire_Load(&value)); + + value = kVal1; + EXPECT_EQ(kVal1, base::subtle::Release_Load(&value)); + value = kVal2; + EXPECT_EQ(kVal2, base::subtle::Release_Load(&value)); +} + +TEST(AtomicOpsTest, Inc) { + TestAtomicIncrement(); + TestAtomicIncrement(); +} + +TEST(AtomicOpsTest, CompareAndSwap) { + TestCompareAndSwap(); + TestCompareAndSwap(); +} + +TEST(AtomicOpsTest, Exchange) { + TestAtomicExchange(); + TestAtomicExchange(); +} + +TEST(AtomicOpsTest, IncrementBounds) { + TestAtomicIncrementBounds(); + TestAtomicIncrementBounds(); +} + +TEST(AtomicOpsTest, Store) { + TestStore(); + TestStore(); +} + +TEST(AtomicOpsTest, Load) { + TestLoad(); + TestLoad(); +} -- cgit v1.1