Skip to content

Commit 5809c70

Browse files
committed
Add test_asan to makefile, fix many issues detected by sanitizers. Currently the sanitizers only work with clang
1 parent b12fe4d commit 5809c70

9 files changed

+42
-16
lines changed

Makefile

+4
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,10 @@ test_openmp:
66
meson setup -Dbuild_tests=true -Duse_openmp=true --warnlevel 2 --werror --buildtype release builddir
77
cd builddir && ninja
88

9+
test_asan:
10+
meson setup -Dbuild_tests=true -Duse_openmp=true -Db_sanitize=address,undefined -Dfatal_sanitizers=true -Db_lundef=false --warnlevel 2 --werror --buildtype debugoptimized builddir
11+
cd builddir && ninja
12+
913
bench:
1014
meson setup -Dbuild_benchmarks=true --warnlevel 2 --werror --buildtype release builddir
1115
cd builddir && ninja

meson.build

+5
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,11 @@ if get_option('build_ippbench')
1818
ipplink = ['-lipps', '-lippcore']
1919
endif
2020

21+
# Essentially '-Werror' for the sanitizers; all problems become fatal with this set
22+
if get_option('fatal_sanitizers')
23+
add_project_arguments([ '-fno-sanitize-recover=all' ], language: 'cpp')
24+
endif
25+
2126
# Add google vqsort to benchmarks:
2227
benchvq = false
2328
if get_option('build_vqsortbench')

meson_options.txt

+2-1
Original file line numberDiff line numberDiff line change
@@ -10,4 +10,5 @@ option('use_openmp', type : 'boolean', value : false,
1010
description : 'Use OpenMP to accelerate key-value sort (default: "false").')
1111
option('lib_type', type : 'string', value : 'shared',
1212
description : 'Library type: shared or static (default: "shared").')
13-
13+
option('fatal_sanitizers', type : 'boolean', value : 'false',
14+
description : 'If sanitizers are enabled, should all issues be considered fatal? (default: "false").')

src/xss-common-qsort.h

+3
Original file line numberDiff line numberDiff line change
@@ -715,6 +715,9 @@ xss_qselect(T *arr, arrsize_t k, arrsize_t arrsize, bool hasnan)
715715
Comparator<vtype, true>,
716716
Comparator<vtype, false>>::type;
717717

718+
// Exit early if no work would be done
719+
if (arrsize <= 1) return;
720+
718721
arrsize_t index_first_elem = 0;
719722
arrsize_t index_last_elem = arrsize - 1;
720723

tests/test-keyvalue.cpp

+13-6
Original file line numberDiff line numberDiff line change
@@ -14,8 +14,8 @@ class simdkvsort : public ::testing::Test {
1414
public:
1515
simdkvsort()
1616
{
17-
std::iota(arrsize.begin(), arrsize.end(), 1);
18-
std::iota(arrsize_long.begin(), arrsize_long.end(), 1);
17+
std::iota(arrsize.begin(), arrsize.end(), 0);
18+
std::iota(arrsize_long.begin(), arrsize_long.end(), 0);
1919
#ifdef XSS_USE_OPENMP
2020
// These extended tests are only needed for the OpenMP logic
2121
arrsize_long.push_back(10'000);
@@ -63,6 +63,9 @@ bool is_kv_sorted(
6363
{
6464
auto cmp_eq = compare<T1, std::equal_to<T1>>();
6565

66+
// Always true for arrays of zero length
67+
if (size == 0) return true;
68+
6669
// First check keys are exactly identical
6770
for (size_t i = 0; i < size; i++) {
6871
if (!cmp_eq(keys_comp[i], keys_ref[i])) { return false; }
@@ -237,7 +240,7 @@ TYPED_TEST_P(simdkvsort, test_kvselect_ascending)
237240
for (auto type : this->arrtype) {
238241
bool hasnan = is_nan_test(type);
239242
for (auto size : this->arrsize) {
240-
size_t k = rand() % size;
243+
size_t k = size != 0 ? rand() % size : 0;
241244

242245
std::vector<T1> key = get_array<T1>(type, size);
243246
std::vector<T2> val = get_array<T2>(type, size);
@@ -250,6 +253,7 @@ TYPED_TEST_P(simdkvsort, test_kvselect_ascending)
250253
// Test select by using it as part of partial_sort
251254
x86simdsort::keyvalue_select(
252255
key.data(), val.data(), k, size, hasnan, false);
256+
if (size == 0) continue;
253257
IS_ARR_PARTITIONED<T1>(key, k, key_bckp[k], type);
254258
xss::scalar::keyvalue_qsort(
255259
key.data(), val.data(), k, hasnan, false);
@@ -281,7 +285,7 @@ TYPED_TEST_P(simdkvsort, test_kvselect_descending)
281285
for (auto type : this->arrtype) {
282286
bool hasnan = is_nan_test(type);
283287
for (auto size : this->arrsize) {
284-
size_t k = rand() % size;
288+
size_t k = size != 0 ? rand() % size : 0;
285289

286290
std::vector<T1> key = get_array<T1>(type, size);
287291
std::vector<T2> val = get_array<T2>(type, size);
@@ -294,6 +298,7 @@ TYPED_TEST_P(simdkvsort, test_kvselect_descending)
294298
// Test select by using it as part of partial_sort
295299
x86simdsort::keyvalue_select(
296300
key.data(), val.data(), k, size, hasnan, true);
301+
if (size == 0) continue;
297302
IS_ARR_PARTITIONED<T1>(key, k, key_bckp[k], type, true);
298303
xss::scalar::keyvalue_qsort(
299304
key.data(), val.data(), k, hasnan, true);
@@ -324,14 +329,15 @@ TYPED_TEST_P(simdkvsort, test_kvpartial_sort_ascending)
324329
for (auto type : this->arrtype) {
325330
bool hasnan = is_nan_test(type);
326331
for (auto size : this->arrsize) {
327-
size_t k = rand() % size;
332+
size_t k = size != 0 ? rand() % size : 0;
328333

329334
std::vector<T1> key = get_array<T1>(type, size);
330335
std::vector<T2> val = get_array<T2>(type, size);
331336
std::vector<T1> key_bckp = key;
332337
std::vector<T2> val_bckp = val;
333338
x86simdsort::keyvalue_partial_sort(
334339
key.data(), val.data(), k, size, hasnan, false);
340+
if (size == 0) continue;
335341
xss::scalar::keyvalue_qsort(
336342
key_bckp.data(), val_bckp.data(), size, hasnan, false);
337343

@@ -361,14 +367,15 @@ TYPED_TEST_P(simdkvsort, test_kvpartial_sort_descending)
361367
for (auto type : this->arrtype) {
362368
bool hasnan = is_nan_test(type);
363369
for (auto size : this->arrsize) {
364-
size_t k = rand() % size;
370+
size_t k = size != 0 ? rand() % size : 0;
365371

366372
std::vector<T1> key = get_array<T1>(type, size);
367373
std::vector<T2> val = get_array<T2>(type, size);
368374
std::vector<T1> key_bckp = key;
369375
std::vector<T2> val_bckp = val;
370376
x86simdsort::keyvalue_partial_sort(
371377
key.data(), val.data(), k, size, hasnan, true);
378+
if (size == 0) continue;
372379
xss::scalar::keyvalue_qsort(
373380
key_bckp.data(), val_bckp.data(), size, hasnan, true);
374381

tests/test-objqsort.cpp

+1-1
Original file line numberDiff line numberDiff line change
@@ -25,7 +25,7 @@ class simdobjsort : public ::testing::Test {
2525
public:
2626
simdobjsort()
2727
{
28-
std::iota(arrsize.begin(), arrsize.end(), 1);
28+
std::iota(arrsize.begin(), arrsize.end(), 0);
2929
arrtype = {"random",
3030
"constant",
3131
"sorted",

tests/test-qsort-common.h

+1
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,7 @@ inline bool is_nan_test(std::string type)
2929
template <typename T>
3030
void IS_SORTED(std::vector<T> sorted, std::vector<T> arr, std::string type)
3131
{
32+
if (arr.size() == 0) return;
3233
if (memcmp(arr.data(), sorted.data(), arr.size() * sizeof(T)) != 0) {
3334
REPORT_FAIL("Array not sorted", arr.size(), type, -1);
3435
}

tests/test-qsort.cpp

+12-8
Original file line numberDiff line numberDiff line change
@@ -10,8 +10,8 @@ class simdsort : public ::testing::Test {
1010
public:
1111
simdsort()
1212
{
13-
std::iota(arrsize.begin(), arrsize.end(), 1);
14-
std::iota(arrsize_long.begin(), arrsize_long.end(), 1);
13+
std::iota(arrsize.begin(), arrsize.end(), 0);
14+
std::iota(arrsize_long.begin(), arrsize_long.end(), 0);
1515
#ifdef XSS_USE_OPENMP
1616
// These extended tests are only needed for the OpenMP logic
1717
arrsize_long.push_back(10'000);
@@ -123,7 +123,7 @@ TYPED_TEST_P(simdsort, test_qselect_ascending)
123123
for (auto type : this->arrtype) {
124124
bool hasnan = is_nan_test(type);
125125
for (auto size : this->arrsize) {
126-
size_t k = rand() % size;
126+
size_t k = size != 0 ? rand() % size : 0;
127127
std::vector<TypeParam> basearr = get_array<TypeParam>(type, size);
128128

129129
// Ascending order
@@ -134,6 +134,7 @@ TYPED_TEST_P(simdsort, test_qselect_ascending)
134134
sortedarr.end(),
135135
compare<TypeParam, std::less<TypeParam>>());
136136
x86simdsort::qselect(arr.data(), k, arr.size(), hasnan);
137+
if (size == 0) continue;
137138
IS_ARR_PARTITIONED(arr, k, sortedarr[k], type);
138139

139140
arr.clear();
@@ -147,7 +148,7 @@ TYPED_TEST_P(simdsort, test_qselect_descending)
147148
for (auto type : this->arrtype) {
148149
bool hasnan = is_nan_test(type);
149150
for (auto size : this->arrsize) {
150-
size_t k = rand() % size;
151+
size_t k = size != 0 ? rand() % size : 0;
151152
std::vector<TypeParam> basearr = get_array<TypeParam>(type, size);
152153

153154
// Descending order
@@ -158,6 +159,7 @@ TYPED_TEST_P(simdsort, test_qselect_descending)
158159
sortedarr.end(),
159160
compare<TypeParam, std::greater<TypeParam>>());
160161
x86simdsort::qselect(arr.data(), k, arr.size(), hasnan, true);
162+
if (size == 0) continue;
161163
IS_ARR_PARTITIONED(arr, k, sortedarr[k], type, true);
162164

163165
arr.clear();
@@ -171,14 +173,15 @@ TYPED_TEST_P(simdsort, test_argselect)
171173
for (auto type : this->arrtype) {
172174
bool hasnan = is_nan_test(type);
173175
for (auto size : this->arrsize) {
174-
size_t k = rand() % size;
176+
size_t k = size != 0 ? rand() % size : 0;
175177
std::vector<TypeParam> arr = get_array<TypeParam>(type, size);
176178
std::vector<TypeParam> sortedarr = arr;
177179
std::sort(sortedarr.begin(),
178180
sortedarr.end(),
179181
compare<TypeParam, std::less<TypeParam>>());
180182
auto arg
181183
= x86simdsort::argselect(arr.data(), k, arr.size(), hasnan);
184+
if (size == 0) continue;
182185
IS_ARG_PARTITIONED(arr, arg, sortedarr[k], k, type);
183186
arr.clear();
184187
sortedarr.clear();
@@ -191,7 +194,7 @@ TYPED_TEST_P(simdsort, test_partial_qsort_ascending)
191194
for (auto type : this->arrtype) {
192195
bool hasnan = is_nan_test(type);
193196
for (auto size : this->arrsize) {
194-
size_t k = rand() % size;
197+
size_t k = size != 0 ? rand() % size : 0;
195198
std::vector<TypeParam> basearr = get_array<TypeParam>(type, size);
196199

197200
// Ascending order
@@ -201,6 +204,7 @@ TYPED_TEST_P(simdsort, test_partial_qsort_ascending)
201204
sortedarr.end(),
202205
compare<TypeParam, std::less<TypeParam>>());
203206
x86simdsort::partial_qsort(arr.data(), k, arr.size(), hasnan);
207+
if (size == 0) continue;
204208
IS_ARR_PARTIALSORTED(arr, k, sortedarr, type);
205209

206210
arr.clear();
@@ -214,8 +218,7 @@ TYPED_TEST_P(simdsort, test_partial_qsort_descending)
214218
for (auto type : this->arrtype) {
215219
bool hasnan = is_nan_test(type);
216220
for (auto size : this->arrsize) {
217-
// k should be at least 1
218-
size_t k = std::max((size_t)1, rand() % size);
221+
size_t k = size != 0 ? rand() % size : 0;
219222
std::vector<TypeParam> basearr = get_array<TypeParam>(type, size);
220223

221224
// Descending order
@@ -225,6 +228,7 @@ TYPED_TEST_P(simdsort, test_partial_qsort_descending)
225228
sortedarr.end(),
226229
compare<TypeParam, std::greater<TypeParam>>());
227230
x86simdsort::partial_qsort(arr.data(), k, arr.size(), hasnan, true);
231+
if (size == 0) continue;
228232
IS_ARR_PARTIALSORTED(arr, k, sortedarr, type);
229233

230234
arr.clear();

utils/rand_array.h

+1
Original file line numberDiff line numberDiff line change
@@ -70,6 +70,7 @@ static std::vector<T> get_array(std::string arrtype,
7070
T max = xss::fp::max<T>())
7171
{
7272
std::vector<T> arr;
73+
if (arrsize == 0) return arr;
7374
if (arrtype == "random") {
7475
arr = get_uniform_rand_array<T>(arrsize, max, min);
7576
}

0 commit comments

Comments
 (0)