1
+ #define _DEFAULT_SOURCE
1
2
#include "fd_solfuzz.h"
2
3
#include <errno.h>
4
+ #include <dirent.h>
3
5
#include <fcntl.h>
4
6
#include <sys/types.h>
5
7
#include <sys/stat.h>
6
8
#include <unistd.h>
7
9
#include "../fd_runtime.h"
8
10
#include "../../../ballet/nanopb/pb_firedancer.h"
9
11
12
+ static int fail_fast ;
13
+ static int error_occurred ;
14
+
10
15
/* run_test runs a test.
11
16
Return 1 on success, 0 on failure. */
12
17
static int
13
- run_test ( fd_solfuzz_runner_t * runner ,
14
- char const * path ) {
18
+ run_test1 ( fd_solfuzz_runner_t * runner ,
19
+ char const * path ) {
15
20
16
21
/* Read file content to memory */
17
22
18
23
int file = open ( path , O_RDONLY );
24
+ if ( FD_UNLIKELY ( file < 0 ) ) {
25
+ FD_LOG_WARNING (( "open(%s) failed: (%i-%s)" , path , errno , fd_io_strerror ( errno ) ));
26
+ return 0 ;
27
+ }
19
28
struct stat st ;
20
29
if ( FD_UNLIKELY ( 0 != fstat ( file , & st ) ) ) {
21
- FD_LOG_WARNING (( "fstat(%s): %s " , path , fd_io_strerror ( errno ) ));
30
+ FD_LOG_WARNING (( "fstat(%s) failed: (%i-%s) " , path , errno , fd_io_strerror ( errno ) ));
22
31
return 0 ;
23
32
}
24
33
ulong file_sz = (ulong )st .st_size ;
@@ -53,6 +62,142 @@ run_test( fd_solfuzz_runner_t * runner,
53
62
return ok ;
54
63
}
55
64
65
+ static int
66
+ run_test ( fd_solfuzz_runner_t * runner ,
67
+ char const * path ) {
68
+ ulong frames_used_pre_test = runner -> spad -> frame_free ;
69
+ ulong mem_used_pre_test = runner -> spad -> mem_used ;
70
+
71
+ fd_spad_push ( runner -> spad );
72
+ int ok = !!run_test1 ( runner , path );
73
+ fd_spad_pop ( runner -> spad );
74
+
75
+ ulong frames_used_post_test = runner -> spad -> frame_free ;
76
+ ulong mem_used_post_test = runner -> spad -> mem_used ;
77
+
78
+ FD_TEST ( frames_used_pre_test == frames_used_post_test );
79
+ FD_TEST ( mem_used_pre_test == mem_used_post_test );
80
+ return ok ;
81
+ }
82
+
83
+ /* Recursive dir walk function, follows symlinks */
84
+
85
+ typedef int (* visit_path )( void * ctx , char const * path );
86
+
87
+ static int
88
+ recursive_walk1 ( DIR * dir ,
89
+ char path [ PATH_MAX ],
90
+ ulong path_len ,
91
+ visit_path visit ,
92
+ void * visit_ctx ) {
93
+ struct dirent * entry ;
94
+ errno = 0 ;
95
+ while (( entry = readdir ( dir ) )) {
96
+ path [ path_len ] = '\0' ;
97
+ if ( FD_LIKELY ( !strcmp ( entry -> d_name , "." ) || !strcmp ( entry -> d_name , ".." ) ) ) continue ;
98
+
99
+ ulong child_len = strlen ( entry -> d_name );
100
+ if ( FD_UNLIKELY ( path_len + 1 + child_len + 1 > PATH_MAX ) ) {
101
+ FD_LOG_WARNING (( "Ignoring overlong path name: %s/%s" , path , entry -> d_name ));
102
+ continue ;
103
+ }
104
+
105
+ char * p = path + path_len ;
106
+ p = fd_cstr_append_char ( p , '/' );
107
+ p = fd_cstr_append_text ( p , entry -> d_name , child_len );
108
+ fd_cstr_fini ( p );
109
+ ulong sub_path_len = (ulong )( p - path );
110
+
111
+ DIR * subdir = NULL ;
112
+ char * suffix ;
113
+ if ( entry -> d_type == DT_DIR ) {
114
+ subdir = opendir ( path );
115
+ if ( FD_UNLIKELY ( !subdir ) ) {
116
+ FD_LOG_WARNING (( "opendir(%s) failed: (%i-%s)" , path , errno , fd_io_strerror ( errno ) ));
117
+ continue ;
118
+ }
119
+ as_dir :
120
+ recursive_walk1 ( subdir , path , sub_path_len , visit , visit_ctx );
121
+ closedir ( subdir );
122
+ } else if ( entry -> d_type == DT_REG ) {
123
+ as_file :
124
+ suffix = strstr ( entry -> d_name , ".fix" );
125
+ if ( !suffix || suffix [4 ]!= '\0' ) continue ;
126
+ if ( !visit ( visit_ctx , path ) ) break ;
127
+ } else if ( entry -> d_type == DT_LNK ) {
128
+ subdir = opendir ( path );
129
+ if ( subdir ) {
130
+ goto as_dir ;
131
+ } else {
132
+ if ( FD_UNLIKELY ( errno != ENOTDIR ) ) {
133
+ FD_LOG_WARNING (( "opendir(%s) failed: (%i-%s)" , path , errno , fd_io_strerror ( errno ) ));
134
+ continue ;
135
+ }
136
+ goto as_file ;
137
+ }
138
+ }
139
+ }
140
+ return 1 ;
141
+ }
142
+
143
+ static int
144
+ recursive_walk ( char const * path ,
145
+ visit_path visit ,
146
+ void * visit_ctx ) {
147
+ char path1 [ PATH_MAX ];
148
+ ulong path_len = strlen ( path );
149
+ if ( FD_UNLIKELY ( path_len >=PATH_MAX ) ) {
150
+ FD_LOG_WARNING (( "Ignoring overlong path name: %s" , path ));
151
+ return 0 ;
152
+ }
153
+ fd_cstr_fini ( fd_cstr_append_text ( fd_cstr_init ( path1 ), path , path_len ) );
154
+ DIR * root_dir = opendir ( path1 );
155
+ if ( FD_UNLIKELY ( !root_dir ) ) {
156
+ FD_LOG_WARNING (( "opendir(%s) failed: (%i-%s)" , path , errno , fd_io_strerror ( errno ) ));
157
+ return 0 ;
158
+ }
159
+ int ok = recursive_walk1 ( root_dir , path1 , path_len , visit , visit_ctx );
160
+ closedir ( root_dir );
161
+ return ok ;
162
+ }
163
+
164
+ /* Single-threaded mode: execute synchronously while walking dir */
165
+
166
+ static int
167
+ visit_sync ( void * ctx ,
168
+ char const * path ) {
169
+ fd_solfuzz_runner_t * runner = ctx ;
170
+ int ok = run_test ( runner , path );
171
+ if ( !ok ) {
172
+ error_occurred = 1 ;
173
+ if ( fail_fast ) return 0 ;
174
+ }
175
+ return 1 ;
176
+ }
177
+
178
+ static void
179
+ run_single_threaded ( fd_solfuzz_runner_t * runner ,
180
+ int argc ,
181
+ char * * argv ) {
182
+ for ( int j = 1 ; j < argc ; j ++ ) {
183
+ int ok = recursive_walk ( argv [ j ], visit_sync , runner );
184
+ if ( !ok ) {
185
+ FD_LOG_WARNING (( "Stopping early" ));
186
+ }
187
+ }
188
+ }
189
+
190
+ /* Multi-threaded mode: fan out tasks to bank of tiles */
191
+
192
+ FD_FN_UNUSED static void
193
+ run_multi_threaded ( fd_solfuzz_runner_t * * runners ,
194
+ ulong worker_cnt ,
195
+ int argc ,
196
+ char * * argv ) {
197
+ (void )runners ; (void )worker_cnt ; (void )argc ; (void )argv ;
198
+ FD_LOG_WARNING (( "Multi-threaded mode not implemented yet" ));
199
+ }
200
+
56
201
int
57
202
main ( int argc ,
58
203
char * * argv ) {
@@ -74,29 +219,45 @@ main( int argc,
74
219
}
75
220
if ( FD_UNLIKELY ( !wksp ) ) return 255 ;
76
221
77
- fd_solfuzz_runner_t * runner = fd_solfuzz_runner_new ( wksp , wksp_tag );
78
- FD_TEST ( runner );
222
+ /* Run strategy: If the application was launched with one tile
223
+ (default), run everything on the current tile. If more than one
224
+ tile is detected, use the first tile (recommended floating) to walk
225
+ the file system, use all other tiles to execute fuzz vectors. */
226
+ ulong worker_cnt = fd_tile_cnt ();
227
+ if ( worker_cnt > 1UL ) worker_cnt -- ;
79
228
80
- ulong fail_cnt = 0UL ;
81
- for ( int j = 1 ; j < argc ; j ++ ) {
82
- ulong frames_used_pre_test = runner -> spad -> frame_free ;
83
- ulong mem_used_pre_test = runner -> spad -> mem_used ;
84
-
85
- fd_spad_push ( runner -> spad );
86
- fail_cnt += !run_test ( runner , argv [j ] );
87
- fd_spad_pop ( runner -> spad );
88
-
89
- ulong frames_used_post_test = runner -> spad -> frame_free ;
90
- ulong mem_used_post_test = runner -> spad -> mem_used ;
229
+ /* Allocate runners */
230
+ int exit_code = 255 ;
231
+ fd_solfuzz_runner_t * * runners = fd_wksp_alloc_laddr ( wksp , alignof(void * ), worker_cnt * sizeof (void * ), 1UL );
232
+ if ( FD_UNLIKELY ( !runners ) ) { FD_LOG_WARNING (( "init failed" )); goto exit ; }
233
+ fd_memset ( runners , 0 , worker_cnt * sizeof (void * ) );
234
+ for ( ulong i = 0UL ; i < worker_cnt ; i ++ ) {
235
+ runners [i ] = fd_solfuzz_runner_new ( wksp , wksp_tag );
236
+ if ( FD_UNLIKELY ( !runners [i ] ) ) { FD_LOG_WARNING (( "init failed (creating worker %lu)" , i )); goto exit ; }
237
+ }
91
238
92
- FD_TEST ( frames_used_pre_test == frames_used_post_test );
93
- FD_TEST ( mem_used_pre_test == mem_used_post_test );
239
+ /* Run strategy */
240
+ //if( fd_tile_cnt()==1 ) {
241
+ run_single_threaded ( runners [0 ], argc , argv );
242
+ //} else {
243
+ // run_multi_threaded( runners, worker_cnt, argc, argv );
244
+ //}
245
+ if ( error_occurred ) {
246
+ if ( fail_fast ) exit_code = 255 ;
247
+ else exit_code = 1 ;
248
+ } else {
249
+ exit_code = 0 ;
94
250
}
95
251
96
- fd_solfuzz_runner_delete ( runner );
252
+ exit :
253
+ /* Undo all wksp allocs */
254
+ for ( ulong i = 0UL ; runners && i < worker_cnt ; i ++ ) {
255
+ if ( runners [i ] ) fd_solfuzz_runner_delete ( runners [i ] );
256
+ }
257
+ fd_wksp_free_laddr ( runners );
97
258
if ( wksp_name ) fd_wksp_detach ( wksp );
98
259
else fd_wksp_demand_paged_delete ( wksp );
99
260
100
261
fd_halt ();
101
- return fail_cnt > 0UL ;
262
+ return exit_code ;
102
263
}
0 commit comments