Skip to content

Commit d3d4379

Browse files
author
awalsh128
committed
Several changes to testing.
1 parent 741330a commit d3d4379

File tree

8 files changed

+289
-23
lines changed

8 files changed

+289
-23
lines changed

.vscode/settings.json

Lines changed: 15 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -2,8 +2,6 @@
22
"C_Cpp.clang_format_style": "file",
33
"C_Cpp.clang_format_fallbackStyle": "none",
44
"C_Cpp.default.configurationProvider": "ms-vscode.cmake-tools",
5-
"C_Cpp.dimInactiveRegions": false,
6-
75
// sudo apt install clang-format; which clang-format
86
"clang-format.executable": "/usr/bin/clang-format",
97
"clang-format.language.c.enable": true,
@@ -13,19 +11,27 @@
1311
"editor.suggest.insertMode": "replace",
1412
"editor.semanticHighlighting.enabled": true
1513
},
16-
1714
"cmake.configureSettings": {
18-
"CMAKE_BUILD_TYPE": "${buildType}"
15+
"CMAKE_BUILD_TYPE": "${buildType}",
16+
"BUILD_TESTS": true,
17+
"BUILD_WEBSITE": true,
18+
"BUILD_BENCHMARKS": true,
19+
"BUILD_EXAMPLES": true,
1920
},
2021
"cmake.loggingLevel": "trace",
2122
"cmake.sourceDirectory": "${workspaceFolder}/.",
22-
23-
"editor.rulers": [80],
23+
"editor.rulers": [
24+
80
25+
],
2426
"editor.formatOnSave": true,
2527
"editor.tabSize": 2,
2628
"editor.insertSpaces": true,
2729
"editor.detectIndentation": false,
28-
30+
"[python]": {
31+
"editor.tabSize": 4,
32+
"editor.insertSpaces": true,
33+
"editor.detectIndentation": false,
34+
},
2935
"files.associations": {
3036
"type_traits": "cpp",
3137
"array": "cpp",
@@ -89,6 +95,5 @@
8995
"thread": "cpp",
9096
"list": "cpp",
9197
"unordered_set": "cpp"
92-
},
93-
"C_Cpp.errorSquiggles": "Disabled"
94-
}
98+
}
99+
}

CMakeLists.txt

Lines changed: 13 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -12,17 +12,28 @@ project(fluentcpp
1212

1313
# HEADER-END
1414

15+
include(assets/scripts/functions.cmake)
16+
17+
option(RUN_TESTS, "Run unit and benchmark tests." OFF)
18+
option(BUILD_WEBSITE "Build Doxygen and product website." OFF)
19+
option(RUN_BENCHMARKS "Run benchmark tests." OFF)
20+
option(BUILD_EXAMPLES "Build code examples using the product." OFF)
21+
1522
# Make the src directory available for include lookup.
1623
include_directories(src)
1724

1825
add_subdirectory(src)
1926

2027
# Must live in the top level file or tests won't be found.
28+
# Options are evaluated in the subdirectory CMake file.
2129
include(CTest) # Automatically invokes enable_testing()
2230
add_subdirectory(tests)
2331

24-
if(CMAKE_BUILD_TYPE MATCHES Release)
32+
if (BUILD_EXAMPLES)
2533
add_subdirectory(examples)
34+
endif()
35+
36+
if(BUILD_WEBSITE)
2637
add_subdirectory(assets/artwork) # Distribute artwork first.
2738
add_subdirectory(assets/doxygen) # Build API website.
28-
endif(CMAKE_BUILD_TYPE MATCHES Release)
39+
endif()

tests/CMakeLists.txt

Lines changed: 38 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -2,18 +2,45 @@ include(FetchContent)
22

33
message(STATUS "Building tests.")
44

5-
FetchContent_Declare(
6-
Catch2
7-
GIT_REPOSITORY https://github.com/catchorg/Catch2.git
8-
GIT_TAG v3.0.0-preview3)
5+
if (BUILD_TESTS)
96

10-
FetchContent_MakeAvailable(Catch2)
7+
FetchContent_Declare(
8+
Catch2
9+
GIT_REPOSITORY https://github.com/catchorg/Catch2.git
10+
GIT_TAG v3.0.0-preview3)
1111

12-
file(GLOB TEST_FILES *.h *.cpp)
12+
FetchContent_MakeAvailable(Catch2)
1313

14-
add_executable(query_tests ${TEST_FILES})
14+
add_executable(tests tests.cpp)
15+
# Catch2 provides a main function as executable entry point.
16+
# Private since there is no need to surface these libraries in the binary.
17+
target_link_libraries(tests PUBLIC Catch2 Catch2WithMain fluentcpp)
18+
add_test(NAME tests COMMAND tests)
1519

16-
# Catch2 provides a main function as executable entry point.
17-
# Private since there is no need to surface these libraries in the binary.
18-
target_link_libraries(query_tests PUBLIC Catch2 Catch2WithMain fluentcpp)
19-
add_test(NAME tests COMMAND query_tests)
20+
endif()
21+
22+
if (BUILD_BENCHMARKS)
23+
24+
FetchContent_Declare(
25+
googlebenchmark
26+
GIT_REPOSITORY https://github.com/google/benchmark.git
27+
GIT_TAG master)
28+
29+
FetchContent_Declare(
30+
googletest
31+
GIT_REPOSITORY https://github.com/google/googletest.git
32+
GIT_TAG release-1.11.0)
33+
34+
FetchContent_MakeAvailable(googletest googlebenchmark)
35+
36+
add_executable(benchmarks benchmarks.cpp)
37+
target_link_libraries(benchmarks PUBLIC benchmark::benchmark fluentcpp)
38+
add_test(NAME benchmarks COMMAND tests)
39+
40+
py3_build(benchmarks_delta.py)
41+
42+
file(COPY benchmark.sh
43+
DESTINATION ${CMAKE_CURRENT_BINARY_DIR}
44+
USE_SOURCE_PERMISSIONS)
45+
46+
endif()

tests/benchmark.sh

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
#!/bin/bash
2+
3+
set -e
4+
5+
./benchmarks --benchmark_out=benchmarks_results.json --benchmark_out_format=json
6+
./benchmarks_delta.py benchmarks_results.json

tests/benchmarks.cpp

Lines changed: 49 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,49 @@
1+
#include "query.h"
2+
3+
#include <benchmark/benchmark.h>
4+
#include <chrono>
5+
#include <random>
6+
#include <thread>
7+
#include <vector>
8+
9+
#define RANGE_LOW 1 << 10
10+
#define RANGE_HIGH 1 << 26
11+
12+
namespace {
13+
14+
std::vector<int> CreateSequence(size_t size) {
15+
std::vector<int> sequence;
16+
sequence.reserve(size);
17+
for (int i = 0; i < size; i++) {
18+
sequence.push_back(std::rand());
19+
}
20+
return sequence;
21+
}
22+
23+
static void BM_Select_int_Std(benchmark::State &state) {
24+
for (auto _ : state) {
25+
state.PauseTiming();
26+
auto items = CreateSequence(state.range(0));
27+
state.ResumeTiming();
28+
std::vector<int> result;
29+
result.reserve(items.size());
30+
std::transform(
31+
items.begin(), items.end(), std::back_inserter(result),
32+
[](auto x) { return x + 1; });
33+
}
34+
}
35+
BENCHMARK(BM_Select_int_Std)->Range(RANGE_LOW, RANGE_HIGH);
36+
37+
static void BM_Select_int_FCpp(benchmark::State &state) {
38+
for (auto _ : state) {
39+
state.PauseTiming();
40+
auto items = CreateSequence(state.range(0));
41+
state.ResumeTiming();
42+
fcpp::query(std::move(items)).select([](auto x) { return x + 1; });
43+
}
44+
}
45+
BENCHMARK(BM_Select_int_FCpp)->Range(RANGE_LOW, RANGE_HIGH);
46+
47+
} // namespace
48+
49+
BENCHMARK_MAIN();

tests/benchmarks_delta.py

Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,40 @@
1+
#!/usr/bin/env python3
2+
3+
import json
4+
import sys
5+
6+
7+
def delta_pct(x, y):
8+
return '%.2f' % ((x - y) / y)
9+
10+
11+
def from_json(filepath):
12+
results = json.load(open(filepath))
13+
timings = dict()
14+
lines = list()
15+
16+
for benchmark in results['benchmarks']:
17+
fqname = benchmark['name']
18+
name_path, size = fqname.split('/')
19+
_, fname, type, competitor = name_path.split('_')
20+
key = (fname, type, size)
21+
timing = timings.get(key, dict())
22+
timing[competitor.lower()] = int(benchmark['cpu_time'])
23+
timings[key] = timing
24+
25+
for key, values in timings.items():
26+
print(values)
27+
delta = delta_pct(values['std'], values['fcpp'])
28+
fname, type, size = key
29+
lines.append(f'{fname} {type} {size} {delta}')
30+
31+
return lines
32+
33+
34+
def main(argv):
35+
lines = from_json(argv[0])
36+
print('\n'.join(lines))
37+
38+
39+
if __name__ == '__main__':
40+
main(sys.argv[1:])

tests/scratch.cpp

Lines changed: 128 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,128 @@
1+
2+
// class ValueGenerator {
3+
// private:
4+
// std::uniform_int_distribution<char> char_dist_;
5+
// std::uniform_real_distribution<> double_dist_;
6+
// std::uniform_int_distribution<> int_dist_;
7+
// std::uniform_real_distribution<> int64_dist_;
8+
// std::default_random_engine engine_;
9+
10+
// public:
11+
// ValueGenerator()
12+
// : char_dist_(
13+
// std::numeric_limits<char>::min(),
14+
// std::numeric_limits<char>::max()),
15+
// double_dist_(0.0, 1.0),
16+
// int_dist_(
17+
// std::numeric_limits<int>::min(),
18+
// std::numeric_limits<int>::max()),
19+
// int64_dist_(
20+
// std::numeric_limits<int64_t>::min(),
21+
// std::numeric_limits<int64_t>::max()) {}
22+
23+
// template <typename T>
24+
// T get() {
25+
// return T();
26+
// }
27+
28+
// template <>
29+
// char get<char>() {
30+
// return char_dist_(engine_);
31+
// }
32+
// template <>
33+
// double get<double>() {
34+
// return double_dist_(engine_);
35+
// }
36+
37+
// template <>
38+
// int get<int>() {
39+
// return int_dist_(engine_);
40+
// }
41+
42+
// template <>
43+
// int64_t get<int64_t>() {
44+
// return int64_dist_(engine_);
45+
// }
46+
47+
// template <>
48+
// std::string get<std::string>() {
49+
// int length = get<int>() % 500;
50+
// std::string value;
51+
// value.reserve(length);
52+
// for (int i = 0; i < 0; ++i) {
53+
// value[i] = get_char();
54+
// }
55+
// return value;
56+
// }
57+
58+
// template <typename V>
59+
// std::vector<V> get<std::vector<V>>() {
60+
// int length = get<int>() % 500;
61+
// std::vector<V> value;
62+
// value.reserve(length);
63+
// for (int i = 0; i < 0; ++i) {
64+
// value[i] = get<V>();
65+
// }
66+
// return value;
67+
// }
68+
69+
// template <>
70+
// FlatPrimaryObject get<FlatPrimaryObject>() {
71+
// return {gen.get(), gen.get(), gen.get(), gen.get()};
72+
// }
73+
74+
// template <>
75+
// FlatDerivedObject get<FlatDerivedObject>() {
76+
// return {gen.get(), gen.get(), gen.get(), gen.get(), gen.get(),
77+
// gen.get()};
78+
// }
79+
80+
// template <>
81+
// FlatUserDefinedObject get<FlatUserDefinedObject>() {
82+
// return {gen.get(), gen.get(), gen.get(), gen.get(),
83+
// gen.get(), gen.get(), gen.get()};
84+
// }
85+
86+
// template <>
87+
// NestedObject get<NestedObject>() {
88+
// return {gen.get(), gen.get(), gen.get(), gen.get(),
89+
// gen.get(), gen.get(), gen.get(), gen.get()};
90+
// }
91+
// }
92+
93+
// struct FlatPrimaryObject {
94+
// int int_val;
95+
// int64_t int64_val;
96+
// double double_val;
97+
// int64_t int64_val2;
98+
// };
99+
100+
// struct FlatDerivedObject {
101+
// std::string string_val;
102+
// int int_val;
103+
// int64_t int64_val;
104+
// double double_val;
105+
// int64_t int64_val2;
106+
// std::string string_val2;
107+
// };
108+
109+
// struct FlatUserDefinedObject {
110+
// std::vector<int> int_vec_val;
111+
// int int_val;
112+
// int64_t int64_val;
113+
// std::vector<std::string> vec_string_val;
114+
// double double_val;
115+
// FlatPrimaryObject flat_primary_val;
116+
// std::string string_val2;
117+
// };
118+
119+
// struct NestedObject {
120+
// std::vector<FlatUserDefinedObject> flat_userdef_vec_val;
121+
// int int_val;
122+
// FlatUserDefinedObject flat_userdef_val;
123+
// int64_t int64_val;
124+
// std::vector<std::string> vec_string_val;
125+
// FlatDerivedObject flat_deriv_val;
126+
// double double_val;
127+
// FlatPrimaryObject flat_primary_val;
128+
// };
File renamed without changes.

0 commit comments

Comments
 (0)