@@ -107,6 +107,94 @@ defmodule VirtualTimeGenStateMachine do
107107 backend . sleep ( duration )
108108 end
109109
110+ @ doc """
111+ Starts a GenStateMachine with virtual time support.
112+
113+ This function injects the virtual clock into the spawned process,
114+ similar to VirtualTimeGenServer.start_link/3.
115+ """
116+ def start_link ( module , init_arg , opts \\ [ ] ) do
117+ # Extract time-related options from opts
118+ { virtual_clock , opts } = Keyword . pop ( opts , :virtual_clock )
119+ { real_time , opts } = Keyword . pop ( opts , :real_time , false )
120+
121+ # Determine which clock and backend to use
122+ # Priority: local options > global Process dictionary
123+ { final_clock , final_backend } = determine_time_config ( virtual_clock , real_time )
124+
125+ # Set virtual clock in current process before starting
126+ if final_clock do
127+ Process . put ( :virtual_clock , final_clock )
128+ end
129+
130+ Process . put ( :time_backend , final_backend )
131+
132+ # Start with the original module
133+ GenStateMachine . start_link ( module , init_arg , opts )
134+ end
135+
136+ @ doc """
137+ Starts a GenStateMachine without linking.
138+ """
139+ def start ( module , init_arg , opts \\ [ ] ) do
140+ # Extract time-related options from opts
141+ { virtual_clock , opts } = Keyword . pop ( opts , :virtual_clock )
142+ { real_time , opts } = Keyword . pop ( opts , :real_time , false )
143+
144+ # Determine which clock and backend to use
145+ { final_clock , final_backend } = determine_time_config ( virtual_clock , real_time )
146+
147+ # Set virtual clock in current process before starting
148+ if final_clock do
149+ Process . put ( :virtual_clock , final_clock )
150+ end
151+
152+ Process . put ( :time_backend , final_backend )
153+
154+ # Start with the original module
155+ GenStateMachine . start ( module , init_arg , opts )
156+ end
157+
158+ @ doc """
159+ Makes a synchronous call to a state machine.
160+ """
161+ def call ( server , request , timeout \\ 5000 ) do
162+ GenStateMachine . call ( server , request , timeout )
163+ end
164+
165+ @ doc """
166+ Sends an asynchronous cast to a state machine.
167+ """
168+ def cast ( server , request ) do
169+ GenStateMachine . cast ( server , request )
170+ end
171+
172+ @ doc """
173+ Stops a state machine.
174+ """
175+ def stop ( server , reason \\ :normal , timeout \\ :infinity ) do
176+ GenServer . stop ( server , reason , timeout )
177+ end
178+
179+ # Private helper to determine time configuration
180+ # Priority: explicit local options > global Process dictionary
181+ defp determine_time_config ( nil , false ) do
182+ # No local options - use global settings
183+ global_clock = Process . get ( :virtual_clock )
184+ global_backend = Process . get ( :time_backend , RealTimeBackend )
185+ { global_clock , global_backend }
186+ end
187+
188+ defp determine_time_config ( nil , true ) do
189+ # Explicit real_time: true - ignore global settings
190+ { nil , RealTimeBackend }
191+ end
192+
193+ defp determine_time_config ( local_clock , _ ) when is_pid ( local_clock ) do
194+ # Explicit local clock provided - use it regardless of global settings
195+ { local_clock , VirtualTimeBackend }
196+ end
197+
110198 defmacro __using__ ( opts ) do
111199 quote do
112200 use GenStateMachine , unquote ( opts )
0 commit comments