Skip to content

Commit 65bb227

Browse files
authored
Merge pull request #860 from benjeffery/bug_assert
Add tsk_bug_assert for production code assertions
2 parents 3a16d24 + 3f0f62a commit 65bb227

File tree

12 files changed

+264
-227
lines changed

12 files changed

+264
-227
lines changed

c/dev-tools/dev-cli.c

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,5 @@
11
#include <stdio.h>
22
#include <string.h>
3-
#include <assert.h>
43
#include <limits.h>
54
#include <stdarg.h>
65
#include <float.h>

c/tskit/convert.c

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -25,7 +25,6 @@
2525

2626
#include <stdio.h>
2727
#include <string.h>
28-
#include <assert.h>
2928
#include <stdbool.h>
3029
#include <stdlib.h>
3130
#include <math.h>

c/tskit/core.c

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -27,7 +27,6 @@
2727
#include <stdlib.h>
2828
#include <string.h>
2929
#include <errno.h>
30-
#include <assert.h>
3130
#include <math.h>
3231

3332
#include <kastore.h>

c/tskit/core.h

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -337,6 +337,30 @@ not be freed by client code.
337337
*/
338338
const char *tsk_strerror(int err);
339339

340+
#ifndef TSK_BUG_ASSERT_MESSAGE
341+
#define TSK_BUG_ASSERT_MESSAGE \
342+
"If you are using tskit directly please open an issue on" \
343+
" GitHub, ideally with a reproducible example." \
344+
" (https://github.com/tskit-dev/tskit/issues) If you are" \
345+
" using software that uses tskit, please report an issue" \
346+
" to that software's issue tracker, at least initially."
347+
#endif
348+
349+
/**
350+
We often wish to assert a condition that is unexpected, but using the normal `assert`
351+
means compiling without NDEBUG. This macro still asserts when NDEBUG is defined.
352+
If you are using this macro in your own software then please set TSK_BUG_ASSERT_MESSAGE
353+
to point users to your issue tracker.
354+
*/
355+
#define tsk_bug_assert(condition) \
356+
do { \
357+
if (!(condition)) { \
358+
fprintf(stderr, "Bug detected in %s at line %d. %s\n", __FILE__, __LINE__, \
359+
TSK_BUG_ASSERT_MESSAGE); \
360+
abort(); \
361+
} \
362+
} while (0)
363+
340364
void __tsk_safe_free(void **ptr);
341365
#define tsk_safe_free(pointer) __tsk_safe_free((void **) &(pointer))
342366

c/tskit/genotypes.c

Lines changed: 7 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -25,7 +25,6 @@
2525

2626
#include <stdio.h>
2727
#include <string.h>
28-
#include <assert.h>
2928
#include <stdbool.h>
3029
#include <stdlib.h>
3130

@@ -115,7 +114,7 @@ tsk_vargen_init(tsk_vargen_t *self, tsk_treeseq_t *tree_sequence, tsk_id_t *samp
115114
tsk_size_t max_alleles;
116115
tsk_id_t u;
117116

118-
assert(tree_sequence != NULL);
117+
tsk_bug_assert(tree_sequence != NULL);
119118
memset(self, 0, sizeof(tsk_vargen_t));
120119

121120
if (samples == NULL) {
@@ -299,7 +298,7 @@ tsk_vargen_update_genotypes_i8_sample_list(
299298
tsk_id_t index, stop;
300299
int ret = 0;
301300

302-
assert(derived < INT8_MAX);
301+
tsk_bug_assert(derived < INT8_MAX);
303302

304303
index = list_left[node];
305304
if (index != TSK_NULL) {
@@ -332,7 +331,7 @@ tsk_vargen_update_genotypes_i16_sample_list(
332331
tsk_id_t index, stop;
333332
int ret = 0;
334333

335-
assert(derived < INT16_MAX);
334+
tsk_bug_assert(derived < INT16_MAX);
336335

337336
index = list_left[node];
338337
if (index != TSK_NULL) {
@@ -404,8 +403,8 @@ tsk_vargen_visit_i8(tsk_vargen_t *self, tsk_id_t sample_index, tsk_id_t derived)
404403
int ret = 0;
405404
int8_t *restrict genotypes = self->variant.genotypes.i8;
406405

407-
assert(derived < INT8_MAX);
408-
assert(sample_index != -1);
406+
tsk_bug_assert(derived < INT8_MAX);
407+
tsk_bug_assert(sample_index != -1);
409408
if (genotypes[sample_index] == (int8_t) derived) {
410409
ret = TSK_ERR_INCONSISTENT_MUTATIONS;
411410
goto out;
@@ -422,8 +421,8 @@ tsk_vargen_visit_i16(tsk_vargen_t *self, tsk_id_t sample_index, tsk_id_t derived
422421
int ret = 0;
423422
int16_t *restrict genotypes = self->variant.genotypes.i16;
424423

425-
assert(derived < INT16_MAX);
426-
assert(sample_index != -1);
424+
tsk_bug_assert(derived < INT16_MAX);
425+
tsk_bug_assert(sample_index != -1);
427426
if (genotypes[sample_index] == (int16_t) derived) {
428427
ret = TSK_ERR_INCONSISTENT_MUTATIONS;
429428
goto out;

c/tskit/haplotype_matching.c

Lines changed: 33 additions & 34 deletions
Original file line numberDiff line numberDiff line change
@@ -25,7 +25,6 @@
2525
#include <stdio.h>
2626
#include <string.h>
2727
#include <stdlib.h>
28-
#include <assert.h>
2928
#include <math.h>
3029
#include <float.h>
3130

@@ -64,17 +63,17 @@ tsk_ls_hmm_check_state(tsk_ls_hmm_t *self)
6463

6564
for (j = 0; j < (tsk_id_t) self->num_transitions; j++) {
6665
if (T[j].tree_node != TSK_NULL) {
67-
assert(T_index[T[j].tree_node] == j);
66+
tsk_bug_assert(T_index[T[j].tree_node] == j);
6867
}
6968
}
70-
/* assert(self->num_transitions <= self->num_samples); */
69+
/* tsk_bug_assert(self->num_transitions <= self->num_samples); */
7170

7271
if (self->num_transitions > 0) {
7372
for (j = 0; j < (tsk_id_t) self->num_nodes; j++) {
7473
if (T_index[j] != TSK_NULL) {
75-
assert(T[T_index[j]].tree_node == j);
74+
tsk_bug_assert(T[T_index[j]].tree_node == j);
7675
}
77-
assert(self->tree.parent[j] == self->parent[j]);
76+
tsk_bug_assert(self->tree.parent[j] == self->parent[j]);
7877
}
7978
}
8079
}
@@ -315,9 +314,9 @@ tsk_ls_hmm_update_tree(tsk_ls_hmm_t *self)
315314
/* Ensure the subtree we're detaching has a transition at the root */
316315
while (T_index[u] == TSK_NULL) {
317316
u = parent[u];
318-
assert(u != TSK_NULL);
317+
tsk_bug_assert(u != TSK_NULL);
319318
}
320-
assert(self->num_transitions < self->max_transitions);
319+
tsk_bug_assert(self->num_transitions < self->max_transitions);
321320
T_index[record->edge.child] = (tsk_id_t) self->num_transitions;
322321
T[self->num_transitions].tree_node = record->edge.child;
323322
T[self->num_transitions].value = T[T_index[u]].value;
@@ -334,7 +333,7 @@ tsk_ls_hmm_update_tree(tsk_ls_hmm_t *self)
334333
/* Grafting onto a new root. */
335334
if (T_index[record->edge.parent] == TSK_NULL) {
336335
T_index[edge.parent] = (tsk_id_t) self->num_transitions;
337-
assert(self->num_transitions < self->max_transitions);
336+
tsk_bug_assert(self->num_transitions < self->max_transitions);
338337
T[self->num_transitions].tree_node = edge.parent;
339338
T[self->num_transitions].value = T[T_index[edge.child]].value;
340339
self->num_transitions++;
@@ -344,9 +343,9 @@ tsk_ls_hmm_update_tree(tsk_ls_hmm_t *self)
344343
while (T_index[u] == TSK_NULL) {
345344
u = parent[u];
346345
}
347-
assert(u != TSK_NULL);
346+
tsk_bug_assert(u != TSK_NULL);
348347
}
349-
assert(T_index[u] != -1 && T_index[edge.child] != -1);
348+
tsk_bug_assert(T_index[u] != -1 && T_index[edge.child] != -1);
350349
if (T[T_index[u]].value == T[T_index[edge.child]].value) {
351350
vt = &T[T_index[edge.child]];
352351
/* Mark the value transition as unusued */
@@ -422,7 +421,7 @@ tsk_ls_hmm_update_probabilities(
422421
while (T_index[u] == TSK_NULL) {
423422
u = parent[u];
424423
}
425-
assert(self->num_transitions < self->max_transitions);
424+
tsk_bug_assert(self->num_transitions < self->max_transitions);
426425
T_index[mut.node] = (tsk_id_t) self->num_transitions;
427426
T[self->num_transitions].tree_node = mut.node;
428427
T[self->num_transitions].value = T[T_index[u]].value;
@@ -437,7 +436,7 @@ tsk_ls_hmm_update_probabilities(
437436
v = u;
438437
while (allelic_state[v] == TSK_MISSING_DATA) {
439438
v = parent[v];
440-
assert(v != -1);
439+
tsk_bug_assert(v != -1);
441440
}
442441
match = haplotype_state == TSK_MISSING_DATA
443442
|| haplotype_state == allelic_state[v];
@@ -477,7 +476,7 @@ tsk_ls_hmm_discretise_values(tsk_ls_hmm_t *self)
477476
num_values++;
478477
}
479478
}
480-
assert(num_values > 0);
479+
tsk_bug_assert(num_values > 0);
481480

482481
qsort(values, num_values, sizeof(double), cmp_double);
483482

@@ -494,7 +493,7 @@ tsk_ls_hmm_discretise_values(tsk_ls_hmm_t *self)
494493
if (T[j].tree_node != TSK_NULL) {
495494
T[j].value_index
496495
= (tsk_id_t) tsk_search_sorted(values, num_values, T[j].value);
497-
assert(T[j].value == self->values[T[j].value_index]);
496+
tsk_bug_assert(T[j].value == self->values[T[j].value_index]);
498497
}
499498
}
500499
return ret;
@@ -516,7 +515,7 @@ get_smallest_set_bit(uint64_t v)
516515
*/
517516
uint64_t t = 1;
518517
tsk_id_t r = 0;
519-
assert(v != 0);
518+
tsk_bug_assert(v != 0);
520519

521520
while ((v & t) == 0) {
522521
t <<= 1;
@@ -534,7 +533,7 @@ get_smallest_element(const uint64_t *restrict A, size_t u, size_t num_words)
534533

535534
while (a[j] == 0) {
536535
j++;
537-
assert(j < (tsk_id_t) num_words);
536+
tsk_bug_assert(j < (tsk_id_t) num_words);
538537
}
539538
return j * 64 + get_smallest_set_bit(a[j]);
540539
}
@@ -563,7 +562,7 @@ static inline void
563562
set_fitch(uint64_t *restrict A, const tsk_id_t u, const size_t num_words, tsk_id_t state)
564563
{
565564
size_t index = ((size_t) u) * num_words + (size_t)(state / 64);
566-
assert(((size_t) state) / 64 < num_words);
565+
tsk_bug_assert(((size_t) state) / 64 < num_words);
567566
A[index] |= 1ULL << (state % 64);
568567
}
569568

@@ -641,7 +640,7 @@ compute_fitch_general(uint64_t *restrict A, const tsk_id_t *restrict left_child,
641640
const uint64_t state_word = 1ULL << (parent_state % 64);
642641
int j;
643642

644-
assert(num_words <= MAX_FITCH_WORDS);
643+
tsk_bug_assert(num_words <= MAX_FITCH_WORDS);
645644

646645
memset(a_union, 0, num_words * sizeof(*a_union));
647646
memset(a_inter, 0xff, num_words * sizeof(*a_inter));
@@ -761,15 +760,15 @@ tsk_ls_hmm_build_fitch_sets(tsk_ls_hmm_t *self)
761760
if (v != TSK_NULL) {
762761
while (T_index[v] == TSK_NULL) {
763762
v = parent[v];
764-
assert(v != TSK_NULL);
763+
tsk_bug_assert(v != TSK_NULL);
765764
}
766765
parent_state = T[T_index[v]].value_index;
767766
v = parent[u];
768767
while (T_index[v] == TSK_NULL) {
769768
compute_fitch(
770769
A, left_child, right_sib, v, parent_state, num_fitch_words);
771770
v = parent[v];
772-
assert(v != TSK_NULL);
771+
tsk_bug_assert(v != TSK_NULL);
773772
}
774773
}
775774
}
@@ -803,12 +802,12 @@ tsk_ls_hmm_redistribute_transitions(tsk_ls_hmm_t *self)
803802
for (root = self->tree.left_root; root != TSK_NULL; root = right_sib[root]) {
804803
stack[0].tree_node = root;
805804
stack[0].old_state = T_old[T_index[root]].value_index;
806-
/* assert(self->num_fitch_words == 1); */
805+
/* tsk_bug_assert(self->num_fitch_words == 1); */
807806
stack[0].new_state = get_smallest_element(A, (size_t) root, num_fitch_words);
808807
stack[0].transition_parent = 0;
809808
stack_top = 0;
810809

811-
assert(self->num_transitions < self->max_transitions);
810+
tsk_bug_assert(self->num_transitions < self->max_transitions);
812811
T_parent[self->num_transitions] = TSK_NULL;
813812
T[self->num_transitions].tree_node = stack[0].tree_node;
814813
T[self->num_transitions].value_index = stack[0].new_state;
@@ -829,7 +828,7 @@ tsk_ls_hmm_redistribute_transitions(tsk_ls_hmm_t *self)
829828
= get_smallest_element(A, (size_t) v, num_fitch_words);
830829
child_s.transition_parent = (tsk_id_t) self->num_transitions;
831830
/* Add a new transition */
832-
assert(self->num_transitions < self->max_transitions);
831+
tsk_bug_assert(self->num_transitions < self->max_transitions);
833832
T_parent[self->num_transitions] = s.transition_parent;
834833
T[self->num_transitions].tree_node = v;
835834
T[self->num_transitions].value_index = child_s.new_state;
@@ -840,7 +839,7 @@ tsk_ls_hmm_redistribute_transitions(tsk_ls_hmm_t *self)
840839
} else {
841840
/* Node that we didn't visit when moving up the tree */
842841
if (s.old_state != s.new_state) {
843-
assert(self->num_transitions < self->max_transitions);
842+
tsk_bug_assert(self->num_transitions < self->max_transitions);
844843
T_parent[self->num_transitions] = s.transition_parent;
845844
T[self->num_transitions].tree_node = v;
846845
T[self->num_transitions].value_index = s.old_state;
@@ -916,15 +915,15 @@ tsk_ls_hmm_process_site(tsk_ls_hmm_t *self, tsk_site_t *site, int8_t haplotype_s
916915
if (ret != 0) {
917916
goto out;
918917
}
919-
assert(self->num_transitions <= self->num_samples);
918+
tsk_bug_assert(self->num_transitions <= self->num_samples);
920919
normalisation_factor = self->compute_normalisation_factor(self);
921920

922921
if (normalisation_factor == 0) {
923922
ret = TSK_ERR_MATCH_IMPOSSIBLE;
924923
goto out;
925924
}
926925
for (j = 0; j < self->num_transitions; j++) {
927-
assert(T[j].tree_node != TSK_NULL);
926+
tsk_bug_assert(T[j].tree_node != TSK_NULL);
928927
x = T[j].value / normalisation_factor;
929928
T[j].value = tsk_round(x, precision);
930929
}
@@ -999,7 +998,7 @@ tsk_ls_hmm_compute_normalisation_factor_forward(tsk_ls_hmm_t *self)
999998

1000999
/* Compute the number of samples directly inheriting from each transition */
10011000
for (j = 0; j < num_transitions; j++) {
1002-
assert(T[j].tree_node != TSK_NULL);
1001+
tsk_bug_assert(T[j].tree_node != TSK_NULL);
10031002
N[j] = num_samples[T[j].tree_node];
10041003
}
10051004
for (j = 0; j < num_transitions; j++) {
@@ -1079,9 +1078,9 @@ tsk_ls_hmm_compute_normalisation_factor_viterbi(tsk_ls_hmm_t *self)
10791078

10801079
max_vt.value = -1;
10811080
max_vt.tree_node = 0; /* keep compiler happy */
1082-
assert(num_transitions > 0);
1081+
tsk_bug_assert(num_transitions > 0);
10831082
for (j = 0; j < num_transitions; j++) {
1084-
assert(T[j].tree_node != TSK_NULL);
1083+
tsk_bug_assert(T[j].tree_node != TSK_NULL);
10851084
if (T[j].value > max_vt.value) {
10861085
max_vt = T[j];
10871086
}
@@ -1481,7 +1480,7 @@ tsk_viterbi_matrix_choose_sample(
14811480
max_value = transition_values[j];
14821481
}
14831482
}
1484-
assert(u != TSK_NULL);
1483+
tsk_bug_assert(u != TSK_NULL);
14851484

14861485
while (!(node_flags[u] & TSK_NODE_IS_SAMPLE)) {
14871486
found = false;
@@ -1499,7 +1498,7 @@ tsk_viterbi_matrix_choose_sample(
14991498
}
15001499
}
15011500
/* TODO: should remove this once we're sure this is robust */
1502-
assert(found);
1501+
tsk_bug_assert(found);
15031502
}
15041503
ret = u;
15051504
out:
@@ -1551,8 +1550,8 @@ tsk_viterbi_matrix_traceback(
15511550
goto out;
15521551
}
15531552
}
1554-
assert(tree.left <= site.position);
1555-
assert(site.position < tree.right);
1553+
tsk_bug_assert(tree.left <= site.position);
1554+
tsk_bug_assert(site.position < tree.right);
15561555

15571556
/* Fill in the recombination tree */
15581557
rr_record_tmp = rr_record;
@@ -1574,7 +1573,7 @@ tsk_viterbi_matrix_traceback(
15741573
while (u != TSK_NULL && recombination_tree[u] == TSK_NULL) {
15751574
u = tree.parent[u];
15761575
}
1577-
assert(u != TSK_NULL);
1576+
tsk_bug_assert(u != TSK_NULL);
15781577
if (recombination_tree[u] == 1) {
15791578
/* Switch at the next site */
15801579
current_node = TSK_NULL;

0 commit comments

Comments
 (0)