YugabyteDB (2.13.0.0-b42, bfc6a6643e7399ac8a0e81d06a3ee6d6571b33ab)

Coverage Report

Created: 2022-03-09 17:30

/Users/deen/code/yugabyte-db/src/yb/util/once-test.cc
Line
Count
Source
1
// Licensed to the Apache Software Foundation (ASF) under one
2
// or more contributor license agreements.  See the NOTICE file
3
// distributed with this work for additional information
4
// regarding copyright ownership.  The ASF licenses this file
5
// to you under the Apache License, Version 2.0 (the
6
// "License"); you may not use this file except in compliance
7
// with the License.  You may obtain a copy of the License at
8
//
9
//   http://www.apache.org/licenses/LICENSE-2.0
10
//
11
// Unless required by applicable law or agreed to in writing,
12
// software distributed under the License is distributed on an
13
// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
14
// KIND, either express or implied.  See the License for the
15
// specific language governing permissions and limitations
16
// under the License.
17
//
18
// The following only applies to changes made to this file as part of YugaByte development.
19
//
20
// Portions Copyright (c) YugaByte, Inc.
21
//
22
// Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except
23
// in compliance with the License.  You may obtain a copy of the License at
24
//
25
// http://www.apache.org/licenses/LICENSE-2.0
26
//
27
// Unless required by applicable law or agreed to in writing, software distributed under the License
28
// is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
29
// or implied.  See the License for the specific language governing permissions and limitations
30
// under the License.
31
//
32
#include <vector>
33
34
#include <gtest/gtest.h>
35
36
#include "yb/util/once.h"
37
#include "yb/util/test_macros.h"
38
#include "yb/util/thread.h"
39
40
using std::vector;
41
using strings::Substitute;
42
43
namespace yb {
44
45
namespace {
46
47
struct Thing {
48
  explicit Thing(bool should_fail)
49
    : should_fail_(should_fail),
50
3
      value_(0) {
51
3
  }
52
53
9
  Status Init() {
54
9
    return once_.Init(&Thing::InitOnce, this);
55
9
  }
56
57
3
  Status InitOnce() {
58
3
    if (should_fail_) {
59
1
      return STATUS(IllegalState, "Whoops!");
60
1
    }
61
2
    value_ = 1;
62
2
    return Status::OK();
63
2
  }
64
65
  const bool should_fail_;
66
  int value_;
67
  YBOnceDynamic once_;
68
};
69
70
} // anonymous namespace
71
72
1
TEST(TestOnce, YBOnceDynamicTest) {
73
1
  {
74
1
    Thing t(false);
75
1
    ASSERT_EQ(0, t.value_);
76
1
    ASSERT_FALSE(t.once_.initted());
77
78
3
    for (int i = 0; i < 2; i++) {
79
2
      ASSERT_OK(t.Init());
80
2
      ASSERT_EQ(1, t.value_);
81
2
      ASSERT_TRUE(t.once_.initted());
82
2
    }
83
1
  }
84
85
1
  {
86
1
    Thing t(true);
87
3
    for (int i = 0; i < 2; i++) {
88
2
      ASSERT_TRUE(t.Init().IsIllegalState());
89
2
      ASSERT_EQ(0, t.value_);
90
2
      ASSERT_TRUE(t.once_.initted());
91
2
    }
92
1
  }
93
1
}
94
95
10
static void InitOrGetInitted(Thing* t, int i) {
96
10
  if (i % 2 == 0) {
97
5
    LOG(INFO) << "Thread " << i << " initting";
98
5
    ASSERT_OK(t->Init());
99
5
  } else {
100
5
    LOG(INFO) << "Thread " << i << " value: " << t->once_.initted();
101
5
  }
102
10
}
103
104
1
TEST(TestOnce, YBOnceDynamicThreadSafeTest) {
105
1
  Thing thing(false);
106
107
  // The threads will read and write to thing.once_.initted. If access to
108
  // it is not synchronized, TSAN will flag the access as data races.
109
1
  vector<scoped_refptr<Thread> > threads;
110
11
  for (int i = 0; i < 10; i++) {
111
10
    scoped_refptr<Thread> t;
112
10
    ASSERT_OK(Thread::Create("test", Substitute("thread $0", i),
113
10
                             &InitOrGetInitted, &thing, i, &t));
114
10
    threads.push_back(t);
115
10
  }
116
117
10
  for (const scoped_refptr<Thread>& t : threads) {
118
10
    t->Join();
119
10
  }
120
1
}
121
122
} // namespace yb