@@ -835,7 +835,7 @@ fn fs_sym_name(command : FsSymCommand) -> String {
835835
836836///|
837837// Labels used as coverage diagnostics:
838- // The file-system example in the blog uses labels to make sure generated
838+ // The file-system example uses labels to make sure generated
839839// programs cover meaningful behaviors, not just arbitrary command names. These
840840// labels identify multi-open scenarios, successful reads, closed-handle writes,
841841// and busy reads.
@@ -954,7 +954,7 @@ fn fs_unknown_handle_probe_spec() -> @quickcheck_statemachine.StateMachine[
954954// exist, reified at execution time, and still satisfy the pure model. The
955955// required labels assert that the scenario covers both multiple open handles and
956956// at least one successful read.
957- test "qsm blog filesystem open-write-read examples pass with symbolic handles" {
957+ test "qsm filesystem open-write-read examples pass with symbolic handles" {
958958 let root = fs_root_dir ()
959959 let z = fs_dir (["z" ])
960960 let a = fs_file (root , "a" )
@@ -980,7 +980,29 @@ test "qsm blog filesystem open-write-read examples pass with symbolic handles" {
980980 "OpenTwo" , "SuccessfulRead" ,
981981 ]),
982982 )
983- assert_eq (summary .commands_run, commands .length ())
983+ inspect (summary .commands_run, content = "12" )
984+ inspect (
985+ @debug .to_string (summary .labels),
986+ content = "[\" OpenTwo\" , \" SuccessfulRead\" ]" ,
987+ )
988+ inspect (
989+ @quickcheck_statemachine .format_commands (summary .commands),
990+ content = (
991+ #| 0: FsSymOpen({ dir: { parts: [] }, name: "a" }) -> FsSymSucceeded(FsSymHandle({ id: 0 }))
992+ #| 1: FsSymOpen({ dir: { parts: [] }, name: "b" }) -> FsSymSucceeded(FsSymHandle({ id: 1 }))
993+ #| 2: FsSymWrite(Symbolic({ id: 0 }), "Hi") -> FsSymSucceeded(FsSymUnit)
994+ #| 3: FsSymWrite(Symbolic({ id: 1 }), "Bye") -> FsSymSucceeded(FsSymUnit)
995+ #| 4: FsSymClose(Symbolic({ id: 0 })) -> FsSymSucceeded(FsSymUnit)
996+ #| 5: FsSymRead({ dir: { parts: [] }, name: "a" }) -> FsSymSucceeded(FsSymText("Hi"))
997+ #| 6: FsSymClose(Symbolic({ id: 1 })) -> FsSymSucceeded(FsSymUnit)
998+ #| 7: FsSymRead({ dir: { parts: [] }, name: "b" }) -> FsSymSucceeded(FsSymText("Bye"))
999+ #| 8: FsSymMkDir({ parts: ["z"] }) -> FsSymSucceeded(FsSymUnit)
1000+ #| 9: FsSymOpen({ dir: { parts: ["z"] }, name: "b" }) -> FsSymSucceeded(FsSymHandle({ id: 2 }))
1001+ #| 10: FsSymClose(Symbolic({ id: 2 })) -> FsSymSucceeded(FsSymUnit)
1002+ #| 11: FsSymRead({ dir: { parts: ["z"] }, name: "b" }) -> FsSymSucceeded(FsSymText(""))
1003+ #|
1004+ ),
1005+ )
9841006}
9851007
9861008///|
@@ -989,7 +1011,7 @@ test "qsm blog filesystem open-write-read examples pass with symbolic handles" {
9891011// introduced that variable. The property checks that generation exhausts its
9901012// retries and reports a deadlock at step zero instead of producing a program
9911013// that would fail later during reification.
992- test "qsm blog precondition rejects handles that were never created" {
1014+ test "qsm precondition rejects handles that were never created" {
9931015 let result = @quickcheck_statemachine .check (
9941016 fs_unknown_handle_probe_spec (),
9951017 config = case_config (max_commands = 1 , max_tries = 3 ),
@@ -1000,9 +1022,12 @@ test "qsm blog precondition rejects handles that were never created" {
10001022 ) else {
10011023 fail ("expected unknown handle to exhaust generation attempts" )
10021024 }
1003- assert_eq (step_index , 0 )
1004- assert_eq (model .created_handles.length (), 0 )
1005- assert_eq (commands .length (), 0 )
1025+ inspect (step_index , content = "0" )
1026+ inspect (
1027+ @debug .to_string (model ),
1028+ content = "{ dirs: [{ parts: [] }], files: [], handles: [], created_handles: [] }" ,
1029+ )
1030+ inspect (@quickcheck_statemachine .format_commands (commands ), content = "" )
10061031}
10071032
10081033///|
@@ -1012,7 +1037,7 @@ test "qsm blog precondition rejects handles that were never created" {
10121037// the intentionally liberal precondition: closed-handle writes remain legal test
10131038// commands so the model can verify the expected `HandleClosed` response and the
10141039// label can record that coverage.
1015- test "qsm blog precondition still allows closed handle errors" {
1040+ test "qsm precondition still allows closed handle errors" {
10161041 let root = fs_root_dir ()
10171042 let a = fs_file (root , "a" )
10181043 let commands : Array [FsSymCommand ] = [
@@ -1026,7 +1051,23 @@ test "qsm blog precondition still allows closed handle errors" {
10261051 "ClosedHandleWrite" ,
10271052 ]),
10281053 )
1029- assert_eq (summary .commands_run, 3 )
1054+ inspect (summary .commands_run, content = "3" )
1055+ inspect (@debug .to_string (summary .labels), content = "[\" ClosedHandleWrite\" ]" )
1056+ inspect (
1057+ @quickcheck_statemachine .format_history (summary .history),
1058+ content = (
1059+ #| Invocation(
1060+ #| pid={ id: 0 },
1061+ #| command=FsOpen({ dir: { parts: [] }, name: "a" }),
1062+ #| )
1063+ #| Response(pid={ id: 0 }, response=FsSucceeded(FsHandle(0)))
1064+ #| Invocation(pid={ id: 1 }, command=FsClose(0))
1065+ #| Response(pid={ id: 1 }, response=FsSucceeded(FsUnit))
1066+ #| Invocation(pid={ id: 2 }, command=FsWrite(0, "late write"))
1067+ #| Response(pid={ id: 2 }, response=FsFailed(FsHandleClosed))
1068+ #|
1069+ ),
1070+ )
10301071}
10311072
10321073///|
@@ -1036,7 +1077,7 @@ test "qsm blog precondition still allows closed handle errors" {
10361077// The property verifies that the postcondition catches this mismatch and that
10371078// the recorded history contains the full three-command prefix needed to explain
10381079// the failure.
1039- test "qsm blog filesystem catches missing busy read check" {
1080+ test "qsm filesystem catches missing busy read check" {
10401081 let root = fs_root_dir ()
10411082 let a = fs_file (root , "a" )
10421083 let commands : Array [FsSymCommand ] = [
@@ -1057,17 +1098,50 @@ test "qsm blog filesystem catches missing busy read check" {
10571098 model ~,
10581099 next_model ~,
10591100 history ~,
1101+ logic ~,
10601102 ..
10611103 )
10621104 ) else {
10631105 fail ("expected busy read mismatch" )
10641106 }
1065- assert_eq (step_index , 2 )
1066- assert_true (command is FsRead (_ ))
1067- assert_true (response is FsSucceeded (FsText ("Hi" )))
1068- assert_true (fs_postcondition (model , command , response ).eval () == false )
1069- assert_true (next_model == model )
1070- assert_eq (@quickcheck_statemachine .make_operations (history ).length (), 3 )
1071- assert_eq (model .handles.length (), 1 )
1072- assert_true (model .handles[0 ].file == a )
1107+ inspect (
1108+ "\{ step_index } : \{ @debug .to_string (command )} -> \{ @debug .to_string (response )} , postcondition=\{ fs_postcondition (model , command , response ).eval ()} " ,
1109+ content = (
1110+ #| 2: FsRead({ dir: { parts: [] }, name: "a" }) -> FsSucceeded(FsText("Hi")), postcondition=false
1111+ ),
1112+ )
1113+ inspect (
1114+ @debug .to_string (model ),
1115+ content = (
1116+ #| {
1117+ #| dirs: [{ parts: [] }],
1118+ #| files: [{ file: { dir: { parts: [] }, name: "a" }, content: "Hi" }],
1119+ #| handles: [{ handle: 0, file: { dir: { parts: [] }, name: "a" } }],
1120+ #| next_handle: 1,
1121+ #| }
1122+ ),
1123+ )
1124+ inspect (next_model == model , content = "true" )
1125+ inspect (
1126+ @quickcheck_statemachine .format_history (history ),
1127+ content = (
1128+ #| Invocation(
1129+ #| pid={ id: 0 },
1130+ #| command=FsOpen({ dir: { parts: [] }, name: "a" }),
1131+ #| )
1132+ #| Response(pid={ id: 0 }, response=FsSucceeded(FsHandle(0)))
1133+ #| Invocation(pid={ id: 1 }, command=FsWrite(0, "Hi"))
1134+ #| Response(pid={ id: 1 }, response=FsSucceeded(FsUnit))
1135+ #| Invocation(
1136+ #| pid={ id: 2 },
1137+ #| command=FsRead({ dir: { parts: [] }, name: "a" }),
1138+ #| )
1139+ #| Response(pid={ id: 2 }, response=FsSucceeded(FsText("Hi")))
1140+ #|
1141+ ),
1142+ )
1143+ inspect (
1144+ @quickcheck_statemachine .format_counterexample (logic .counterexample ()),
1145+ content = "filesystem response matches model" ,
1146+ )
10731147}
0 commit comments