roleClient:actionSendRequest:response=server.process()# Message can be lost:# 1. Request never sent# 2. Request sent, server processes, response lost# 3. Success (both ways)
Automatic simulation of:
Network failures
Process crashes
Timeouts
Ephemeral vs Durable State
@state(ephemeral=['cache'])roleServer:actionInit:self.disk_data=0# Durableself.cache=0# EphemeralactionProcess:self.disk_data=self.disk_data+1self.cache=self.cache+1# If crash here:# - disk_data preserved# - cache reset to 0
---
# Example 0078: Crash on Yield (Implicit Fault Injection)# FizzBee's key differentiator - automatic crash fault injection# Demonstrates: crash_on_yield, implicit fault injection at yield points# Default is true - crashes can happen at yield pointsoptions:
max_actions: 3 crash_on_yield: true---
# This example shows FizzBee's automatic fault injection# At each yield point (between statements in serial blocks),# the model checker explores the possibility of a crashaction Init:
step1_done= False
step2_done= False
step3_done= False
# Serial action has yield points between statementsaction MultiStepOperation:
require not step3_done
# Yield point 1 (after this statement)step1_done= True
# Yield point 2 (after this statement)step2_done= True
# Yield point 3 (after this statement)step3_done= True
# Model checker automatically explores:# - Normal execution (all steps complete)# - Crash after step1 (step1_done=True, others False)# - Crash after step2 (step1&2 done, step3 False)# - etc.# Safety: if step3 done, earlier steps must be donealways assertion StepsOrdered:
if step3_done:
return step1_done and step2_done
if step2_done:
return step1_done
return True
atomic action NoOp:
pass
---
# Example 0079: Disable Crash on Yield# Turning off implicit fault injection# Demonstrates: crash_on_yield: false, comparing with/without crashes# Disable crash fault injectionoptions:
max_actions: 3 crash_on_yield: false---
# With crash_on_yield: false, the model checker does NOT# explore crash scenarios at yield points.# Useful for: testing happy path, performance modeling,# or when crashes are explicitly modeledaction Init:
step1_done= False
step2_done= False
step3_done= False
completed= False
fair action MultiStepOperation:
require not completed
# No crash injected after thisstep1_done= True
# No crash injected after thisstep2_done= True
# No crash injected after thisstep3_done= True
completed= True
# With crash_on_yield: false and fair action,# the operation will eventually completeeventually always assertion EventuallyCompletes:
return completed
atomic action NoOp:
pass
# Example 0080: Role Crash with Ephemeral State# Simulating process crashes with state loss# Demonstrates: role crashes, ephemeral vs durable state, recovery# Cache is ephemeral (lost on crash), disk_data is durable@state(ephemeral=['cache'])role Server:
action Init:
self.disk_data =0# Durable (persists across crashes) self.cache =0# Ephemeral (lost on crash) self.requests =0 action ProcessRequest:
require self.requests < 2# Update disk first, then cache self.disk_data = self.disk_data + 1 self.requests = self.requests + 1# Update cache after disk self.cache = self.cache + 1# If crash happens between disk and cache updates,# cache is reset to 0 (ephemeral)# but disk_data is preserved (durable)action Init:
server= Server()# Safety: disk_data reflects durable statealways assertion DiskDataPersists:
return server.disk_data >=0# Safety: cache can be behind disk_data after crashalways assertion CacheMayBeBehind:
return server.cache <= server.disk_data
atomic action NoOp:
if server.requests >= 2:
pass
Expected result (from fizz):
StateSpaceOptions: options:{max_actions:100 max_concurrent_actions:2}
Nodes: 3158, queued: 0
Skipping dotfile generation. Too many Nodes: 3158
Valid Nodes: 3158 Unique states: 2752
IsLive: true
PASSED: Model checker completed successfully