1 // Copyright (c) 2011-present, Facebook, Inc. All rights reserved.
2 // This source code is licensed under both the GPLv2 (found in the
3 // COPYING file in the root directory) and Apache 2.0 License
4 // (found in the LICENSE.Apache file in the root directory).
15 #include "rocksdb/rocksdb_namespace.h"
16 #include "rocksdb/slice.h"
19 // empty in release build
20 #define TEST_KILL_RANDOM_WITH_WEIGHT(kill_point, rocksdb_kill_odds_weight)
21 #define TEST_KILL_RANDOM(kill_point)
24 namespace ROCKSDB_NAMESPACE
{
26 // To avoid crashing always at some frequently executed codepaths (during
27 // kill random test), use this factor to reduce odds
29 #define REDUCE_ODDS2 4
31 // A class used to pass when a kill point is reached.
34 // This is only set from db_stress.cc and for testing only.
35 // If non-zero, kill at various points in source code with probability 1/this
36 int rocksdb_kill_odds
= 0;
37 // If kill point has a prefix on this list, will skip killing.
38 std::vector
<std::string
> rocksdb_kill_exclude_prefixes
;
39 // Kill the process with probability 1/odds for testing.
40 void TestKillRandom(std::string kill_point
, int odds
,
41 const std::string
& srcfile
, int srcline
);
43 static KillPoint
* GetInstance();
46 #define TEST_KILL_RANDOM_WITH_WEIGHT(kill_point, rocksdb_kill_odds_weight) \
48 KillPoint::GetInstance()->TestKillRandom( \
49 kill_point, rocksdb_kill_odds_weight, __FILE__, __LINE__); \
51 #define TEST_KILL_RANDOM(kill_point) TEST_KILL_RANDOM_WITH_WEIGHT(kill_point, 1)
52 } // namespace ROCKSDB_NAMESPACE
57 #define TEST_SYNC_POINT(x)
58 #define TEST_IDX_SYNC_POINT(x, index)
59 #define TEST_SYNC_POINT_CALLBACK(x, y)
60 #define INIT_SYNC_POINT_SINGLETONS()
63 namespace ROCKSDB_NAMESPACE
{
65 // This class provides facility to reproduce race conditions deterministically
67 // Developer could specify sync points in the codebase via TEST_SYNC_POINT.
68 // Each sync point represents a position in the execution stream of a thread.
69 // In the unit test, 'Happens After' relationship among sync points could be
70 // setup via SyncPoint::LoadDependency, to reproduce a desired interleave of
72 // Refer to (DBTest,TransactionLogIteratorRace), for an example use case.
76 static SyncPoint
* GetInstance();
78 SyncPoint(const SyncPoint
&) = delete;
79 SyncPoint
& operator=(const SyncPoint
&) = delete;
82 struct SyncPointPair
{
83 std::string predecessor
;
84 std::string successor
;
87 // call once at the beginning of a test to setup the dependency between
89 void LoadDependency(const std::vector
<SyncPointPair
>& dependencies
);
91 // call once at the beginning of a test to setup the dependency between
92 // sync points and setup markers indicating the successor is only enabled
93 // when it is processed on the same thread as the predecessor.
94 // When adding a marker, it implicitly adds a dependency for the marker pair.
95 void LoadDependencyAndMarkers(const std::vector
<SyncPointPair
>& dependencies
,
96 const std::vector
<SyncPointPair
>& markers
);
98 // The argument to the callback is passed through from
99 // TEST_SYNC_POINT_CALLBACK(); nullptr if TEST_SYNC_POINT or
100 // TEST_IDX_SYNC_POINT was used.
101 void SetCallBack(const std::string
& point
,
102 const std::function
<void(void*)>& callback
);
104 // Clear callback function by point
105 void ClearCallBack(const std::string
& point
);
107 // Clear all call back functions.
108 void ClearAllCallBacks();
110 // enable sync point processing (disabled on startup)
111 void EnableProcessing();
113 // disable sync point processing
114 void DisableProcessing();
116 // remove the execution trace of all sync points
119 // triggered by TEST_SYNC_POINT, blocking execution until all predecessors
121 // And/or call registered callback function, with argument `cb_arg`
122 void Process(const Slice
& point
, void* cb_arg
= nullptr);
124 // template gets length of const string at compile time,
125 // avoiding strlen() at runtime
126 template <size_t kLen
>
127 void Process(const char (&point
)[kLen
], void* cb_arg
= nullptr) {
128 static_assert(kLen
> 0, "Must not be empty");
129 assert(point
[kLen
- 1] == '\0');
130 Process(Slice(point
, kLen
- 1), cb_arg
);
133 // TODO: it might be useful to provide a function that blocks until all
134 // sync points are cleared.
136 // We want this to be public so we can
137 // subclass the implementation
146 // Sets up sync points to mock direct IO instead of actually issuing direct IO
147 // to the file system.
148 void SetupSyncPointsToMockDirectIO();
149 } // namespace ROCKSDB_NAMESPACE
151 // Use TEST_SYNC_POINT to specify sync points inside code base.
152 // Sync points can have happens-after dependency on other sync points,
153 // configured at runtime via SyncPoint::LoadDependency. This could be
154 // utilized to re-produce race conditions between threads.
155 // See TransactionLogIteratorRace in db_test.cc for an example use case.
156 // TEST_SYNC_POINT is no op in release build.
157 #define TEST_SYNC_POINT(x) \
158 ROCKSDB_NAMESPACE::SyncPoint::GetInstance()->Process(x)
159 #define TEST_IDX_SYNC_POINT(x, index) \
160 ROCKSDB_NAMESPACE::SyncPoint::GetInstance()->Process(x + \
161 std::to_string(index))
162 #define TEST_SYNC_POINT_CALLBACK(x, y) \
163 ROCKSDB_NAMESPACE::SyncPoint::GetInstance()->Process(x, y)
164 #define INIT_SYNC_POINT_SINGLETONS() \
165 (void)ROCKSDB_NAMESPACE::SyncPoint::GetInstance();
168 // Callback sync point for any read IO errors that should be ignored by
169 // the fault injection framework
170 // Disable in release mode
172 #define IGNORE_STATUS_IF_ERROR(_status_)
174 #define IGNORE_STATUS_IF_ERROR(_status_) \
176 if (!_status_.ok()) { \
177 TEST_SYNC_POINT("FaultInjectionIgnoreError"); \