@@ -483,6 +483,8 @@ def run_tests(
483
483
):
484
484
print (f"Diff between { name1 } and { name2 } : vimdiff { file1 } { file2 } " )
485
485
486
+ return (failed == 0 ) and (skipped == 0 ) and (passed > 0 )
487
+
486
488
487
489
@app .command (help = f"Convert Context and/or Fixture messages to human-readable format." )
488
490
def decode_protobufs (
@@ -711,7 +713,7 @@ def debug_mismatches(
711
713
):
712
714
os .remove (files [j ])
713
715
714
- run_tests (
716
+ return run_tests (
715
717
input = globals .inputs_dir ,
716
718
reference_shared_library = reference_shared_library ,
717
719
default_harness_ctx = default_harness_ctx ,
@@ -1033,5 +1035,157 @@ def exec_fixtures(
1033
1035
print (f"Skipped tests: { skipped_tests } " )
1034
1036
1035
1037
1038
+ @app .command (
1039
+ help = f"""
1040
+ Set up environment for debugging a mismatch from FuzzCorp
1041
+ """
1042
+ )
1043
+ def create_env (
1044
+ reference_shared_library : Path = typer .Option (
1045
+ Path (os .getenv ("SOLFUZZ_TARGET" , "impl/lib/libsolfuzz_agave_v2.0.so" )),
1046
+ "--solana-target" ,
1047
+ "-s" ,
1048
+ help = "Solana (or ground truth) shared object (.so) target file path" ,
1049
+ ),
1050
+ default_harness_ctx : str = typer .Option (
1051
+ "InstrHarness" ,
1052
+ "--default-harness-type" ,
1053
+ "-h" ,
1054
+ help = f"Harness type to use for Context protobufs" ,
1055
+ ),
1056
+ shared_libraries : List [Path ] = typer .Option (
1057
+ [Path (os .getenv ("FIREDANCER_TARGET" , "impl/lib/libsolfuzz_firedancer.so" ))],
1058
+ "--target" ,
1059
+ "-t" ,
1060
+ help = "Shared object (.so) target file paths (pairs with --keep-passing)."
1061
+ f" Targets must have required function entrypoints defined" ,
1062
+ ),
1063
+ output_dir : Path = typer .Option (
1064
+ Path ("debug_mismatch" ),
1065
+ "--output-dir" ,
1066
+ "-o" ,
1067
+ help = f"Output directory for messages" ,
1068
+ ),
1069
+ repro_urls : str = typer .Option (
1070
+ "" , "--repro-urls" , "-u" , help = "Comma-delimited list of FuzzCorp mismatch links"
1071
+ ),
1072
+ section_names : str = typer .Option (
1073
+ "" ,
1074
+ "--section-names" ,
1075
+ "-n" ,
1076
+ help = "Comma-delimited list of FuzzCorp section names" ,
1077
+ ),
1078
+ fuzzcorp_url : str = typer .Option (
1079
+ os .getenv (
1080
+ "FUZZCORP_URL" ,
1081
+ "https://api.dev.fuzzcorp.asymmetric.re/uglyweb/firedancer-io/solfuzz/bugs/" ,
1082
+ ),
1083
+ "--fuzzcorp-url" ,
1084
+ "-f" ,
1085
+ help = "Comma-delimited list of FuzzCorp section names" ,
1086
+ ),
1087
+ log_level : int = typer .Option (
1088
+ 5 ,
1089
+ "--log-level" ,
1090
+ "-l" ,
1091
+ help = "FD logging level" ,
1092
+ ),
1093
+ randomize_output_buffer : bool = typer .Option (
1094
+ False ,
1095
+ "--randomize-output-buffer" ,
1096
+ "-r" ,
1097
+ help = "Randomizes bytes in output buffer before shared library execution" ,
1098
+ ),
1099
+ num_processes : int = typer .Option (
1100
+ 4 , "--num-processes" , "-p" , help = "Number of processes to use"
1101
+ ),
1102
+ section_limit : int = typer .Option (
1103
+ 0 , "--section-limit" , "-l" , help = "Limit number of fixture per section"
1104
+ ),
1105
+ firedancer_repo_path : Path = typer .Option (
1106
+ os .getenv ("FIREDANCER_DIR" ),
1107
+ "--firedancer-repo" ,
1108
+ "-fd" ,
1109
+ help = "Path to firedancer repository" ,
1110
+ ),
1111
+ test_vectors_repos_path : Path = typer .Option (
1112
+ os .getenv ("TEST_VECTORS_DIR" ),
1113
+ "--test-vectors-repo" ,
1114
+ "-tv" ,
1115
+ help = "Path to test-vectors repository" ,
1116
+ ),
1117
+ ):
1118
+ lists = [
1119
+ f"{ file .parent .name } /{ file .name } "
1120
+ for file in firedancer_repo_path .glob (
1121
+ "contrib/test/test-vectors-fixtures/*fixtures*/*list"
1122
+ )
1123
+ ]
1124
+
1125
+ max_width = max (len (option ) for option in lists ) + 2
1126
+
1127
+ print ("Select correct list for mismatch:" )
1128
+ for i , option in enumerate (lists , start = 1 ):
1129
+ print (f"{ i } . { option } " .ljust (max_width ), end = "\t " )
1130
+ if i % 4 == 0 :
1131
+ print ()
1132
+
1133
+ if len (lists ) % 4 != 0 :
1134
+ print ()
1135
+
1136
+ while True :
1137
+ try :
1138
+ choice = int (input ("Enter the list of your choice: " ))
1139
+ if 1 <= choice <= len (lists ):
1140
+ selected_option = lists [choice - 1 ]
1141
+ break
1142
+ else :
1143
+ print (f"Please enter a number between 1 and { len (lists )} ." )
1144
+ except ValueError :
1145
+ print ("Invalid input. Please enter a number." )
1146
+
1147
+ print (f"Adding fixture to: { selected_option } " )
1148
+ list_path = glob (
1149
+ str (firedancer_repo_path )
1150
+ + f"/contrib/test/test-vectors-fixtures/{ selected_option } "
1151
+ )[0 ]
1152
+
1153
+ passed = debug_mismatches (
1154
+ reference_shared_library = reference_shared_library ,
1155
+ default_harness_ctx = default_harness_ctx ,
1156
+ shared_libraries = shared_libraries ,
1157
+ output_dir = output_dir ,
1158
+ repro_urls = repro_urls ,
1159
+ section_names = section_names ,
1160
+ fuzzcorp_url = fuzzcorp_url ,
1161
+ log_level = log_level ,
1162
+ randomize_output_buffer = randomize_output_buffer ,
1163
+ num_processes = num_processes ,
1164
+ section_limit = section_limit ,
1165
+ )
1166
+
1167
+ if passed :
1168
+ print ("All fixtures already pass" )
1169
+ typer .Exit (code = 1 )
1170
+
1171
+ failures = glob (str (output_dir ) + "/test_results/failed_protobufs/*" )
1172
+
1173
+ for failure in failures :
1174
+ with open (list_path , "r" ) as file :
1175
+ lines = file .readlines ()
1176
+
1177
+ last_line = lines [- 1 ].strip ()
1178
+
1179
+ failure_path = os .path .dirname (last_line ) + "/" + os .path .basename (failure )
1180
+ with open (list_path , "a" ) as file :
1181
+ file .write (failure_path + "\n " )
1182
+ print (f"\n Added { os .path .basename (failure )} to { list_path } " )
1183
+
1184
+ failure_test_vector_path = failure_path .replace (
1185
+ "dump/test-vectors" , str (test_vectors_repos_path )
1186
+ )
1187
+ shutil .copy2 (failure , os .path .dirname (failure_test_vector_path ))
1188
+
1189
+
1036
1190
if __name__ == "__main__" :
1037
1191
app ()
0 commit comments