Skip to content

Commit 2bcce7f

Browse files
xiaoxmengfacebook-github-bot
authored andcommitted
Add testvalue test facility for velox (#2101)
Summary: Add testvalue test facility for velox which can help to capture and manipulate the production internal state for unit test purpose. Pull Request resolved: #2101 Reviewed By: mbasmanova Differential Revision: D38118388 Pulled By: xiaoxmeng fbshipit-source-id: 40409af4f0b627ba30ed5aab96914a247ab94db3
1 parent be7ca7b commit 2bcce7f

File tree

6 files changed

+479
-0
lines changed

6 files changed

+479
-0
lines changed

velox/common/CMakeLists.txt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,3 +19,4 @@ add_subdirectory(memory)
1919
add_subdirectory(process)
2020
add_subdirectory(serialization)
2121
add_subdirectory(time)
22+
add_subdirectory(testutil)

velox/common/testutil/CMakeLists.txt

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
# Copyright (c) Facebook, Inc. and its affiliates.
2+
#
3+
# Licensed under the Apache License, Version 2.0 (the "License");
4+
# you may not use this file except in compliance with the License.
5+
# You may obtain a copy of the License at
6+
#
7+
# http://www.apache.org/licenses/LICENSE-2.0
8+
#
9+
# Unless required by applicable law or agreed to in writing, software
10+
# distributed under the License is distributed on an "AS IS" BASIS,
11+
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12+
# See the License for the specific language governing permissions and
13+
# limitations under the License.
14+
15+
add_library(velox_test_util TestValue.cpp)
16+
target_link_libraries(velox_test_util velox_common_base)
17+
18+
if(${VELOX_BUILD_TESTING})
19+
add_subdirectory(tests)
20+
endif()

velox/common/testutil/TestValue.cpp

Lines changed: 67 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,67 @@
1+
/*
2+
* Copyright (c) Facebook, Inc. and its affiliates.
3+
*
4+
* Licensed under the Apache License, Version 2.0 (the "License");
5+
* you may not use this file except in compliance with the License.
6+
* You may obtain a copy of the License at
7+
*
8+
* http://www.apache.org/licenses/LICENSE-2.0
9+
*
10+
* Unless required by applicable law or agreed to in writing, software
11+
* distributed under the License is distributed on an "AS IS" BASIS,
12+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
* See the License for the specific language governing permissions and
14+
* limitations under the License.
15+
*/
16+
17+
#include "velox/common/testutil/TestValue.h"
18+
19+
namespace facebook::velox::common::testutil {
20+
21+
std::mutex TestValue::mutex_;
22+
bool TestValue::enabled_ = false;
23+
std::unordered_map<std::string, TestValue::Callback> TestValue::injectionMap_;
24+
25+
#ifndef NDEBUG
26+
void TestValue::enable() {
27+
std::lock_guard<std::mutex> l(mutex_);
28+
enabled_ = true;
29+
}
30+
31+
void TestValue::disable() {
32+
std::lock_guard<std::mutex> l(mutex_);
33+
enabled_ = false;
34+
}
35+
36+
bool TestValue::enabled() {
37+
std::lock_guard<std::mutex> l(mutex_);
38+
return enabled_;
39+
}
40+
41+
void TestValue::clear(const std::string& injectionPoint) {
42+
std::lock_guard<std::mutex> l(mutex_);
43+
injectionMap_.erase(injectionPoint);
44+
}
45+
46+
void TestValue::adjust(const std::string& injectionPoint, void* testData) {
47+
Callback injectionCb;
48+
{
49+
std::lock_guard<std::mutex> l(mutex_);
50+
if (!enabled_ || injectionMap_.count(injectionPoint) == 0) {
51+
return;
52+
}
53+
injectionCb = injectionMap_[injectionPoint];
54+
}
55+
injectionCb(testData);
56+
}
57+
#else
58+
void TestValue::enable() {}
59+
void TestValue::disable() {}
60+
bool TestValue::enabled() {
61+
return false;
62+
}
63+
void TestValue::clear(const std::string& injectionPoint) {}
64+
void TestValue::adjust(const std::string& injectionPoint, void* testData) {}
65+
#endif
66+
67+
} // namespace facebook::velox::common::testutil

velox/common/testutil/TestValue.h

Lines changed: 111 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,111 @@
1+
/*
2+
* Copyright (c) Facebook, Inc. and its affiliates.
3+
*
4+
* Licensed under the Apache License, Version 2.0 (the "License");
5+
* you may not use this file except in compliance with the License.
6+
* You may obtain a copy of the License at
7+
*
8+
* http://www.apache.org/licenses/LICENSE-2.0
9+
*
10+
* Unless required by applicable law or agreed to in writing, software
11+
* distributed under the License is distributed on an "AS IS" BASIS,
12+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
* See the License for the specific language governing permissions and
14+
* limitations under the License.
15+
*/
16+
#pragma once
17+
18+
#include <mutex>
19+
#include <string>
20+
#include <unordered_map>
21+
22+
#include "velox/common/base/Exceptions.h"
23+
24+
namespace facebook::velox::common::testutil {
25+
26+
/// The test facility used to inject callback hook in production execution point
27+
/// to get, change and verify various internal execution state for unit test.
28+
/// The hook injected in production code path will be opt out in release build
29+
/// and only be executed in debug build. Please follow the example in
30+
/// TestValueTest.cpp for use.
31+
class TestValue {
32+
public:
33+
/// Enable the test value injection.
34+
static void enable();
35+
/// Disable the test value injection.
36+
static void disable();
37+
/// Check if the test value injection is enabled or not.
38+
static bool enabled();
39+
40+
/// Invoked by the test code to register a callback hook at the specified
41+
/// execution point. 'injectionPoint' is a string to identify the execution
42+
/// point which could be formed by concatenating namespace, class name, method
43+
/// name plus optional actual action within a method. 'injectionCb' is the
44+
/// injected callback hook.
45+
template <typename T>
46+
static void set(
47+
const std::string& injectionPoint,
48+
std::function<void(T*)> injectionCb);
49+
50+
/// Invoked by the test code to unregister a callback hook at the specified
51+
/// execution point.
52+
static void clear(const std::string& injectionPoint);
53+
54+
/// Invoked by the production code to try to invoke the test callback hook
55+
/// with 'testData' if there is one registered at the specified execution
56+
/// point. 'testData' can capture the production execution state.
57+
static void adjust(const std::string& injectionPoint, void* testData);
58+
59+
private:
60+
using Callback = std::function<void(void*)>;
61+
62+
static std::mutex mutex_;
63+
static bool enabled_;
64+
static std::unordered_map<std::string, Callback> injectionMap_;
65+
};
66+
67+
class ScopedTestValue {
68+
public:
69+
template <typename T>
70+
ScopedTestValue(const std::string& point, std::function<void(T*)> callback)
71+
: point_(point) {
72+
VELOX_CHECK_NOT_NULL(callback);
73+
VELOX_CHECK(!point_.empty());
74+
TestValue::set<T>(point_, std::move(callback));
75+
}
76+
~ScopedTestValue() {
77+
TestValue::clear(point_);
78+
}
79+
80+
private:
81+
const std::string point_;
82+
};
83+
84+
#ifndef NDEBUG
85+
template <typename T>
86+
void TestValue::set(
87+
const std::string& injectionPoint,
88+
std::function<void(T*)> injectionCb) {
89+
std::lock_guard<std::mutex> l(mutex_);
90+
if (!enabled_) {
91+
return;
92+
}
93+
injectionMap_[injectionPoint] = [injectionCb](void* testData) {
94+
T* typedData = static_cast<T*>(testData);
95+
injectionCb(typedData);
96+
};
97+
}
98+
#else
99+
template <typename T>
100+
void TestValue::set(
101+
const std::string& injectionPoint,
102+
std::function<void(T*)> injectionCb) {}
103+
#endif
104+
105+
#define VELOX_CONCAT(x, y) __##x##y
106+
#define VELOX_VARNAME(x) VELOX_CONCAT(x, Obj)
107+
108+
#define SCOPED_TESTVALUE_SET(point, ...) \
109+
ScopedTestValue VELOX_VARNAME(__LINE__)(point, ##__VA_ARGS__)
110+
111+
} // namespace facebook::velox::common::testutil
Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
# Copyright (c) Facebook, Inc. and its affiliates.
2+
#
3+
# Licensed under the Apache License, Version 2.0 (the "License");
4+
# you may not use this file except in compliance with the License.
5+
# You may obtain a copy of the License at
6+
#
7+
# http://www.apache.org/licenses/LICENSE-2.0
8+
#
9+
# Unless required by applicable law or agreed to in writing, software
10+
# distributed under the License is distributed on an "AS IS" BASIS,
11+
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12+
# See the License for the specific language governing permissions and
13+
# limitations under the License.
14+
include(GoogleTest)
15+
add_executable(velox_test_util_test TestValueTest.cpp)
16+
gtest_add_tests(velox_test_util_test "" AUTO)
17+
18+
target_link_libraries(velox_test_util_test velox_test_util velox_exception
19+
gtest gtest_main)

0 commit comments

Comments
 (0)