25
25
#include <stdio.h>
26
26
#include <stdlib.h>
27
27
#include <string.h>
28
+ #include <signal.h>
28
29
#include <mongoc/mongoc-util-private.h>
29
30
#if !defined(_WIN32 )
30
31
#include <sys/types.h>
@@ -112,6 +113,43 @@ static BSON_ONCE_FUN (_test_suite_ensure_mutex_once)
112
113
}
113
114
114
115
116
+ static void
117
+ _handle_signal (int signum )
118
+ {
119
+ const char * s = "\nProcess was interrupted by the delivery of a signal.\n" ;
120
+ const char * sigstr ;
121
+ switch (signum ) {
122
+ case SIGABRT :
123
+ sigstr = "SIGABRT - Abnormal termination" ;
124
+ break ;
125
+ case SIGINT :
126
+ sigstr = "SIGINT - Interrupted" ;
127
+ break ;
128
+ case SIGTERM :
129
+ sigstr = "SIGTERM - Termination requested" ;
130
+ break ;
131
+ case SIGSEGV :
132
+ sigstr = "SIGSEGV - Access violation" ;
133
+ break ;
134
+ default :
135
+ sigstr = "(Unknown signal delivered)" ;
136
+ }
137
+ #ifdef BSON_OS_UNIX
138
+ /* On POSIX these APIs are signal-safe */
139
+ write (STDERR_FILENO , s , strlen (s ));
140
+ write (STDERR_FILENO , " " , 2 );
141
+ write (STDERR_FILENO , sigstr , strlen (sigstr ));
142
+ write (STDERR_FILENO , "\n" , 1 );
143
+ fsync (STDERR_FILENO );
144
+ #else
145
+ /* On Windows these APIs are signal-safe */
146
+ fprintf (stderr , "\n%s\n %s\n" , s , sigstr );
147
+ fflush (stderr );
148
+ #endif
149
+ _Exit (signum );
150
+ }
151
+
152
+
115
153
void
116
154
TestSuite_Init (TestSuite * suite , const char * name , int argc , char * * argv )
117
155
{
@@ -125,8 +163,14 @@ TestSuite_Init (TestSuite *suite, const char *name, int argc, char **argv)
125
163
suite -> flags = 0 ;
126
164
suite -> prgname = bson_strdup (argv [0 ]);
127
165
suite -> silent = false;
166
+ suite -> ctest_run = NULL ;
128
167
_mongoc_array_init (& suite -> match_patterns , sizeof (char * ));
129
168
169
+ suite -> prev_sigabrt = signal (SIGABRT , _handle_signal );
170
+ suite -> prev_sigint = signal (SIGINT , _handle_signal );
171
+ suite -> prev_sigterm = signal (SIGTERM , _handle_signal );
172
+ suite -> prev_sigsegv = signal (SIGSEGV , _handle_signal );
173
+
130
174
for (i = 1 ; i < argc ; i ++ ) {
131
175
if (0 == strcmp ("-d" , argv [i ])) {
132
176
suite -> flags |= TEST_DEBUGOUTPUT ;
@@ -165,6 +209,16 @@ TestSuite_Init (TestSuite *suite, const char *name, int argc, char **argv)
165
209
} else if ((0 == strcmp ("-s" , argv [i ])) ||
166
210
(0 == strcmp ("--silent" , argv [i ]))) {
167
211
suite -> silent = true;
212
+ } else if ((0 == strcmp ("--ctest-run" , argv [i ]))) {
213
+ if (suite -> ctest_run ) {
214
+ test_error ("'--ctest-run' can only be specified once" );
215
+ }
216
+ if (argc - 1 == i ) {
217
+ test_error ("'--ctest-run' requires an argument" );
218
+ }
219
+ suite -> flags |= TEST_NOFORK ;
220
+ suite -> silent = true;
221
+ suite -> ctest_run = bson_strdup (argv [++ i ]);
168
222
} else if ((0 == strcmp ("-l" , argv [i ])) ||
169
223
(0 == strcmp ("--match" , argv [i ]))) {
170
224
char * val ;
@@ -180,6 +234,10 @@ TestSuite_Init (TestSuite *suite, const char *name, int argc, char **argv)
180
234
}
181
235
}
182
236
237
+ if (suite -> match_patterns .len != 0 && suite -> ctest_run != NULL ) {
238
+ test_error ("'--ctest-run' cannot be specified with '-l' or '--match'" );
239
+ }
240
+
183
241
if (test_framework_getenv_bool ("MONGOC_TEST_VALGRIND" )) {
184
242
suite -> flags |= TEST_VALGRIND ;
185
243
}
@@ -559,6 +617,10 @@ TestSuite_RunTest (TestSuite *suite, /* IN */
559
617
560
618
for (i = 0 ; i < test -> num_checks ; i ++ ) {
561
619
if (!test -> checks [i ]()) {
620
+ if (suite -> ctest_run ) {
621
+ /* Write a marker that tells CTest that we are skipping this test */
622
+ test_msg ("@@ctest-skipped@@" );
623
+ }
562
624
if (!suite -> silent ) {
563
625
bson_string_append_printf (
564
626
buf ,
@@ -667,6 +729,8 @@ TestSuite_PrintHelp (TestSuite *suite) /* IN */
667
729
"first error).\n"
668
730
" -l, --match PATTERN Run test by name, e.g. \"/Client/command\" or "
669
731
"\"/Client/*\". May be repeated.\n"
732
+ " --ctest-run TEST Run only the named TEST for CTest\n"
733
+ " integration.\n"
670
734
" -s, --silent Suppress all output.\n"
671
735
" -F FILENAME Write test results (JSON) to FILENAME.\n"
672
736
" -d Print debug output (useful if a test hangs).\n"
@@ -878,6 +942,11 @@ test_matches (TestSuite *suite, Test *test)
878
942
{
879
943
int i ;
880
944
945
+ if (suite -> ctest_run ) {
946
+ /* We only want exactly the named test */
947
+ return strcmp (test -> name , suite -> ctest_run ) == 0 ;
948
+ }
949
+
881
950
/* If no match patterns were provided, then assume all match. */
882
951
if (suite -> match_patterns .len == 0 ) {
883
952
return true;
@@ -909,6 +978,14 @@ TestSuite_RunAll (TestSuite *suite /* IN */)
909
978
}
910
979
}
911
980
981
+ if (suite -> ctest_run ) {
982
+ /* We should have matched *at most* one test */
983
+ ASSERT (count <= 1 );
984
+ if (count == 0 ) {
985
+ test_error ("No such test '%s'" , suite -> ctest_run );
986
+ }
987
+ }
988
+
912
989
for (test = suite -> tests ; test ; test = test -> next ) {
913
990
if (test_matches (suite , test )) {
914
991
status += TestSuite_RunTest (suite , test , & count );
@@ -1001,12 +1078,18 @@ TestSuite_Destroy (TestSuite *suite)
1001
1078
1002
1079
free (suite -> name );
1003
1080
free (suite -> prgname );
1081
+ free (suite -> ctest_run );
1004
1082
for (i = 0 ; i < suite -> match_patterns .len ; i ++ ) {
1005
1083
char * val = _mongoc_array_index (& suite -> match_patterns , char * , i );
1006
1084
bson_free (val );
1007
1085
}
1008
1086
1009
1087
_mongoc_array_destroy (& suite -> match_patterns );
1088
+
1089
+ signal (SIGABRT , suite -> prev_sigabrt );
1090
+ signal (SIGINT , suite -> prev_sigint );
1091
+ signal (SIGTERM , suite -> prev_sigterm );
1092
+ signal (SIGSEGV , suite -> prev_sigsegv );
1010
1093
}
1011
1094
1012
1095
0 commit comments