@@ -268,3 +268,87 @@ def test_init_chat_ollama_format():
268
268
"dummy_input" , ["output" ], node_config = node_config_with_schema
269
269
)
270
270
assert node2 .llm_model .format == "dummy_schema_json"
271
+
272
+ import time
273
+ import json
274
+ from requests .exceptions import Timeout
275
+
276
+ # New dummy chain classes and dummy llms for testing invoke_with_timeout and ChatBedrock behavior.
277
+ class DummySlowChain :
278
+ """A dummy chain that simulates a slow response by returning quickly but using patched time."""
279
+ def invoke (self , inputs ):
280
+ return "response"
281
+
282
+ class DummyChainException :
283
+ """A dummy chain that simulates an exception during invoke."""
284
+ def invoke (self , inputs ):
285
+ raise Exception ("dummy error" )
286
+
287
+ class DummyChatBedrock :
288
+ """A dummy ChatBedrock chain that returns a predefined answer. It should be used when output_parser is None."""
289
+ def __call__ (self , * args , ** kwargs ):
290
+ return {"content" : "bedrock answer" }
291
+
292
+ def __or__ (self , other ):
293
+ return self
294
+
295
+ # New tests to increase test coverage.
296
+ def test_invoke_with_timeout_exceeded (dummy_node ):
297
+ """
298
+ Test that invoke_with_timeout raises a Timeout exception when the chain.invoke
299
+ takes longer than the specified timeout.
300
+ """
301
+ # Set dummy_node.timeout to a known value (from dummy_node, timeout=1 is used)
302
+ original_time = time .time
303
+ # Create a list of times such that the first call returns start_time,
304
+ # and the next call returns start_time + timeout + 1.
305
+ call_times = [100 , 100 + dummy_node .timeout + 1 ]
306
+ def fake_time ():
307
+ return call_times .pop (0 ) if call_times else original_time ()
308
+ time_time_backup = time .time
309
+ time .time = fake_time
310
+ try :
311
+ with pytest .raises (Timeout ):
312
+ dummy_node .invoke_with_timeout (DummySlowChain (), {"key" : "value" }, dummy_node .timeout )
313
+ finally :
314
+ time .time = time_time_backup
315
+
316
+ def test_invoke_with_timeout_exception_propagates (dummy_node ):
317
+ """
318
+ Test that invoke_with_timeout properly propagates exceptions raised by the chain.invoke call.
319
+ """
320
+ with pytest .raises (Exception ) as excinfo :
321
+ dummy_node .invoke_with_timeout (DummyChainException (), {"key" : "value" }, dummy_node .timeout )
322
+ assert "dummy error" in str (excinfo .value )
323
+
324
+ @pytest .mark .parametrize ("content_key" , ["relevant_chunks" , "parsed_doc" , "doc" , "content" ])
325
+ def test_process_with_alternative_content_keys (dummy_node_for_process , content_key ):
326
+ """
327
+ Test that process() successfully uses alternative content keys.
328
+ """
329
+ state = {"user_prompt" : "What is the answer?" , content_key : "Alternative content" }
330
+ dummy_node_for_process .chain = DummyChain ()
331
+ dummy_node_for_process .invoke_with_timeout = lambda chain , inputs , timeout : chain .invoke (inputs )
332
+ result_state = dummy_node_for_process .process (state )
333
+ assert result_state ["output" ] == {"content" : "successful answer" }
334
+
335
+ def test_execute_single_chunk_with_bedrock ():
336
+ """
337
+ Test execute() for the single chunk branch using a DummyChatBedrock instance.
338
+ This verifies that if the llm_model is a ChatBedrock, no output_parser is applied.
339
+ """
340
+ node_config = {"llm_model" : DummyChatBedrock (), "verbose" : False , "timeout" : 480 }
341
+ node = GenerateAnswerNode ("dummy_input & doc" , ["output" ], node_config = node_config )
342
+ node .logger = DummyLogger ()
343
+ node .get_input_keys = lambda state : ["dummy_input" , "doc" ]
344
+ state = {"dummy_input" : "What is the answer?" , "doc" : ["Only one chunk bedrock" ]}
345
+
346
+ # simulate a simple chain invocation (in the single-chunk branch)
347
+ def fake_invoke_with_timeout (chain , inputs , timeout ):
348
+ if "question" in inputs :
349
+ return {"content" : "bedrock answer" }
350
+ return {"content" : "unexpected response" }
351
+
352
+ node .invoke_with_timeout = fake_invoke_with_timeout
353
+ output_state = node .execute (state )
354
+ assert output_state ["output" ] == {"content" : "bedrock answer" }
0 commit comments