1//===-- tsan_clock_test.cpp -----------------------------------------------===//
2//
3// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4// See https://llvm.org/LICENSE.txt for license information.
5// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6//
7//===----------------------------------------------------------------------===//
8//
9// This file is a part of ThreadSanitizer (TSan), a race detector.
10//
11//===----------------------------------------------------------------------===//
12#include "tsan_vector_clock.h"
13
14#include "gtest/gtest.h"
15#include "tsan_rtl.h"
16
17namespace __tsan {
18
19TEST(VectorClock, GetSet) {
20 // Compiler won't ensure alignment on stack.
21 VectorClock *vc = New<VectorClock>();
22 for (uptr i = 0; i < kThreadSlotCount; i++)
23 ASSERT_EQ(vc->Get(static_cast<Sid>(i)), kEpochZero);
24 for (uptr i = 0; i < kThreadSlotCount; i++)
25 vc->Set(static_cast<Sid>(i), static_cast<Epoch>(i));
26 for (uptr i = 0; i < kThreadSlotCount; i++)
27 ASSERT_EQ(vc->Get(static_cast<Sid>(i)), static_cast<Epoch>(i));
28 vc->Reset();
29 for (uptr i = 0; i < kThreadSlotCount; i++)
30 ASSERT_EQ(vc->Get(static_cast<Sid>(i)), kEpochZero);
31 DestroyAndFree(vc);
32}
33
34TEST(VectorClock, VectorOps) {
35 VectorClock *vc1 = New<VectorClock>();
36 VectorClock *vc2 = nullptr;
37 VectorClock *vc3 = nullptr;
38
39 vc1->Acquire(vc2);
40 for (uptr i = 0; i < kThreadSlotCount; i++)
41 ASSERT_EQ(vc1->Get(static_cast<Sid>(i)), kEpochZero);
42 vc1->Release(&vc2);
43 EXPECT_NE(vc2, nullptr);
44 vc1->Acquire(vc2);
45 for (uptr i = 0; i < kThreadSlotCount; i++)
46 ASSERT_EQ(vc1->Get(static_cast<Sid>(i)), kEpochZero);
47
48 for (uptr i = 0; i < kThreadSlotCount; i++) {
49 vc1->Set(static_cast<Sid>(i), static_cast<Epoch>(i));
50 vc2->Set(static_cast<Sid>(i), static_cast<Epoch>(kThreadSlotCount - i));
51 }
52 vc1->Acquire(vc2);
53 for (uptr i = 0; i < kThreadSlotCount; i++) {
54 ASSERT_EQ(vc1->Get(static_cast<Sid>(i)),
55 static_cast<Epoch>(i < kThreadSlotCount / 2 ? kThreadSlotCount - i
56 : i));
57 ASSERT_EQ(vc2->Get(static_cast<Sid>(i)),
58 static_cast<Epoch>(kThreadSlotCount - i));
59 }
60 vc2->ReleaseStore(&vc3);
61 for (uptr i = 0; i < kThreadSlotCount; i++) {
62 ASSERT_EQ(vc3->Get(static_cast<Sid>(i)),
63 static_cast<Epoch>(kThreadSlotCount - i));
64 ASSERT_EQ(vc2->Get(static_cast<Sid>(i)),
65 static_cast<Epoch>(kThreadSlotCount - i));
66 }
67
68 vc1->Reset();
69 vc2->Reset();
70 for (uptr i = 0; i < kThreadSlotCount; i++) {
71 vc1->Set(static_cast<Sid>(i), static_cast<Epoch>(i));
72 vc2->Set(static_cast<Sid>(i), static_cast<Epoch>(kThreadSlotCount - i));
73 }
74 vc1->ReleaseAcquire(&vc2);
75 for (uptr i = 0; i < kThreadSlotCount; i++) {
76 Epoch expect =
77 static_cast<Epoch>(i < kThreadSlotCount / 2 ? kThreadSlotCount - i : i);
78 ASSERT_EQ(vc1->Get(static_cast<Sid>(i)), expect);
79 ASSERT_EQ(vc2->Get(static_cast<Sid>(i)), expect);
80 }
81
82 vc1->Reset();
83 vc2->Reset();
84 for (uptr i = 0; i < kThreadSlotCount; i++) {
85 vc1->Set(static_cast<Sid>(i), static_cast<Epoch>(i));
86 vc2->Set(static_cast<Sid>(i), static_cast<Epoch>(kThreadSlotCount - i));
87 }
88 vc1->ReleaseStoreAcquire(&vc2);
89 for (uptr i = 0; i < kThreadSlotCount; i++) {
90 ASSERT_EQ(vc1->Get(static_cast<Sid>(i)),
91 static_cast<Epoch>(i < kThreadSlotCount / 2 ? kThreadSlotCount - i
92 : i));
93 ASSERT_EQ(vc2->Get(static_cast<Sid>(i)), static_cast<Epoch>(i));
94 }
95
96 DestroyAndFree(vc1);
97 DestroyAndFree(vc2);
98 DestroyAndFree(vc3);
99}
100
101} // namespace __tsan
102

source code of compiler-rt/lib/tsan/tests/unit/tsan_vector_clock_test.cpp