1 //===-- tsan_mutexset_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_mutexset.h"
13 #include "gtest/gtest.h"
14 
15 namespace __tsan {
16 
Expect(const MutexSet & mset,uptr i,u64 id,bool write,u64 epoch,int count)17 static void Expect(const MutexSet &mset, uptr i, u64 id, bool write, u64 epoch,
18     int count) {
19   MutexSet::Desc d = mset.Get(i);
20   EXPECT_EQ(id, d.id);
21   EXPECT_EQ(write, d.write);
22   EXPECT_EQ(epoch, d.epoch);
23   EXPECT_EQ(count, d.count);
24 }
25 
TEST(MutexSet,Basic)26 TEST(MutexSet, Basic) {
27   MutexSet mset;
28   EXPECT_EQ(mset.Size(), (uptr)0);
29 
30   mset.Add(1, true, 2);
31   EXPECT_EQ(mset.Size(), (uptr)1);
32   Expect(mset, 0, 1, true, 2, 1);
33   mset.Del(1, true);
34   EXPECT_EQ(mset.Size(), (uptr)0);
35 
36   mset.Add(3, true, 4);
37   mset.Add(5, false, 6);
38   EXPECT_EQ(mset.Size(), (uptr)2);
39   Expect(mset, 0, 3, true, 4, 1);
40   Expect(mset, 1, 5, false, 6, 1);
41   mset.Del(3, true);
42   EXPECT_EQ(mset.Size(), (uptr)1);
43   mset.Del(5, false);
44   EXPECT_EQ(mset.Size(), (uptr)0);
45 }
46 
TEST(MutexSet,DoubleAdd)47 TEST(MutexSet, DoubleAdd) {
48   MutexSet mset;
49   mset.Add(1, true, 2);
50   EXPECT_EQ(mset.Size(), (uptr)1);
51   Expect(mset, 0, 1, true, 2, 1);
52 
53   mset.Add(1, true, 2);
54   EXPECT_EQ(mset.Size(), (uptr)1);
55   Expect(mset, 0, 1, true, 2, 2);
56 
57   mset.Del(1, true);
58   EXPECT_EQ(mset.Size(), (uptr)1);
59   Expect(mset, 0, 1, true, 2, 1);
60 
61   mset.Del(1, true);
62   EXPECT_EQ(mset.Size(), (uptr)0);
63 }
64 
TEST(MutexSet,DoubleDel)65 TEST(MutexSet, DoubleDel) {
66   MutexSet mset;
67   mset.Add(1, true, 2);
68   EXPECT_EQ(mset.Size(), (uptr)1);
69   mset.Del(1, true);
70   EXPECT_EQ(mset.Size(), (uptr)0);
71   mset.Del(1, true);
72   EXPECT_EQ(mset.Size(), (uptr)0);
73 }
74 
TEST(MutexSet,Remove)75 TEST(MutexSet, Remove) {
76   MutexSet mset;
77   mset.Add(1, true, 2);
78   mset.Add(1, true, 2);
79   mset.Add(3, true, 4);
80   mset.Add(3, true, 4);
81   EXPECT_EQ(mset.Size(), (uptr)2);
82 
83   mset.Remove(1);
84   EXPECT_EQ(mset.Size(), (uptr)1);
85   Expect(mset, 0, 3, true, 4, 2);
86 }
87 
TEST(MutexSet,Full)88 TEST(MutexSet, Full) {
89   MutexSet mset;
90   for (uptr i = 0; i < MutexSet::kMaxSize; i++) {
91     mset.Add(i, true, i + 1);
92   }
93   EXPECT_EQ(mset.Size(), MutexSet::kMaxSize);
94   for (uptr i = 0; i < MutexSet::kMaxSize; i++) {
95     Expect(mset, i, i, true, i + 1, 1);
96   }
97 
98   for (uptr i = 0; i < MutexSet::kMaxSize; i++) {
99     mset.Add(i, true, i + 1);
100   }
101   EXPECT_EQ(mset.Size(), MutexSet::kMaxSize);
102   for (uptr i = 0; i < MutexSet::kMaxSize; i++) {
103     Expect(mset, i, i, true, i + 1, 2);
104   }
105 }
106 
TEST(MutexSet,Overflow)107 TEST(MutexSet, Overflow) {
108   MutexSet mset;
109   for (uptr i = 0; i < MutexSet::kMaxSize; i++) {
110     mset.Add(i, true, i + 1);
111     mset.Add(i, true, i + 1);
112   }
113   mset.Add(100, true, 200);
114   EXPECT_EQ(mset.Size(), MutexSet::kMaxSize);
115   for (uptr i = 0; i < MutexSet::kMaxSize; i++) {
116     if (i == 0)
117       Expect(mset, i, MutexSet::kMaxSize - 1,
118              true, MutexSet::kMaxSize, 2);
119     else if (i == MutexSet::kMaxSize - 1)
120       Expect(mset, i, 100, true, 200, 1);
121     else
122       Expect(mset, i, i, true, i + 1, 2);
123   }
124 }
125 
126 }  // namespace __tsan
127