# -*- coding: utf-8 -*- """ Unit tests for ThinkingParser - FSM-based parser for thinking blocks in streaming responses. Tests cover: - Parser state transitions (PRE_CONTENT -> IN_THINKING -> STREAMING) - Tag detection at response start - "Cautious" buffering for split tags - Different handling modes (as_reasoning_content, remove, pass, strip_tags) - Edge cases and error handling """ import pytest from unittest.mock import patch from kiro.thinking_parser import ( ThinkingParser, ThinkingParseResult, ParserState, ) class TestParserStateEnum: """Tests for ParserState enum.""" def test_pre_content_value(self): """ What it does: Verifies PRE_CONTENT enum value. Purpose: Ensure PRE_CONTENT is 0 (initial state). """ print("Checking PRE_CONTENT enum value...") assert ParserState.PRE_CONTENT == 0 def test_in_thinking_value(self): """ What it does: Verifies IN_THINKING enum value. Purpose: Ensure IN_THINKING is 1. """ print("Checking IN_THINKING enum value...") assert ParserState.IN_THINKING == 1 def test_streaming_value(self): """ What it does: Verifies STREAMING enum value. Purpose: Ensure STREAMING is 2. """ print("Checking STREAMING enum value...") assert ParserState.STREAMING == 2 class TestThinkingParseResult: """Tests for ThinkingParseResult dataclass.""" def test_default_values(self): """ What it does: Verifies default values of ThinkingParseResult. Purpose: Ensure all fields have correct defaults. """ print("Creating ThinkingParseResult with defaults...") result = ThinkingParseResult() print(f"Comparing: Expected None, Got {result.thinking_content}") assert result.thinking_content is None assert result.regular_content is None assert result.is_first_thinking_chunk is False assert result.is_last_thinking_chunk is False assert result.state_changed is False def test_custom_values(self): """ What it does: Verifies custom values in ThinkingParseResult. Purpose: Ensure all fields can be set. """ print("Creating ThinkingParseResult with custom values...") result = ThinkingParseResult( thinking_content="thinking", regular_content="regular", is_first_thinking_chunk=True, is_last_thinking_chunk=True, state_changed=True ) print(f"Comparing thinking_content: Expected 'thinking', Got '{result.thinking_content}'") assert result.thinking_content == "thinking" assert result.regular_content == "regular" assert result.is_first_thinking_chunk is True assert result.is_last_thinking_chunk is True assert result.state_changed is True class TestThinkingParserInitialization: """Tests for ThinkingParser initialization.""" def test_default_initialization(self): """ What it does: Verifies default initialization of ThinkingParser. Purpose: Ensure parser starts in PRE_CONTENT state with empty buffers. """ print("Creating ThinkingParser with defaults...") parser = ThinkingParser() print(f"Comparing state: Expected PRE_CONTENT, Got {parser.state}") assert parser.state == ParserState.PRE_CONTENT assert parser.initial_buffer == "" assert parser.thinking_buffer == "" assert parser.open_tag is None assert parser.close_tag is None assert parser.is_first_thinking_chunk is True assert parser._thinking_block_found is False def test_custom_handling_mode(self): """ What it does: Verifies custom handling_mode parameter. Purpose: Ensure handling_mode can be overridden. """ print("Creating ThinkingParser with custom handling_mode...") parser = ThinkingParser(handling_mode="remove") print(f"Comparing handling_mode: Expected 'remove', Got '{parser.handling_mode}'") assert parser.handling_mode == "remove" def test_custom_open_tags(self): """ What it does: Verifies custom open_tags parameter. Purpose: Ensure open_tags can be overridden. """ print("Creating ThinkingParser with custom open_tags...") custom_tags = ["", ""] parser = ThinkingParser(open_tags=custom_tags) print(f"Comparing open_tags: Expected {custom_tags}, Got {parser.open_tags}") assert parser.open_tags == custom_tags def test_custom_initial_buffer_size(self): """ What it does: Verifies custom initial_buffer_size parameter. Purpose: Ensure initial_buffer_size can be overridden. """ print("Creating ThinkingParser with custom initial_buffer_size...") parser = ThinkingParser(initial_buffer_size=50) print(f"Comparing initial_buffer_size: Expected 50, Got {parser.initial_buffer_size}") assert parser.initial_buffer_size == 50 def test_max_tag_length_calculated(self): """ What it does: Verifies max_tag_length is calculated from open_tags. Purpose: Ensure cautious buffering uses correct buffer size. """ print("Creating ThinkingParser and checking max_tag_length...") parser = ThinkingParser(open_tags=["", ""]) # max_tag_length = max(len(tag) for tag in open_tags) * 2 # len("") = 10, so max_tag_length = 20 expected = 20 print(f"Comparing max_tag_length: Expected {expected}, Got {parser.max_tag_length}") assert parser.max_tag_length == expected class TestThinkingParserFeedPreContent: """Tests for ThinkingParser.feed() in PRE_CONTENT state.""" def test_empty_content_returns_empty_result(self): """ What it does: Verifies empty content returns empty result. Purpose: Ensure empty string doesn't change state. """ print("Feeding empty content...") parser = ThinkingParser() result = parser.feed("") print(f"Comparing result: Expected empty result") assert result.thinking_content is None assert result.regular_content is None assert result.state_changed is False assert parser.state == ParserState.PRE_CONTENT def test_detects_thinking_tag(self): """ What it does: Verifies tag detection. Purpose: Ensure parser transitions to IN_THINKING on tag detection. """ print("Feeding content with tag...") parser = ThinkingParser() result = parser.feed("Hello") print(f"Comparing state: Expected IN_THINKING, Got {parser.state}") assert parser.state == ParserState.IN_THINKING assert parser.open_tag == "" assert parser.close_tag == "" assert result.state_changed is True assert parser._thinking_block_found is True def test_detects_think_tag(self): """ What it does: Verifies tag detection. Purpose: Ensure parser detects alternative tag format. """ print("Feeding content with tag...") parser = ThinkingParser() result = parser.feed("Hello") print(f"Comparing open_tag: Expected '', Got '{parser.open_tag}'") assert parser.state == ParserState.IN_THINKING assert parser.open_tag == "" assert parser.close_tag == "" def test_detects_reasoning_tag(self): """ What it does: Verifies tag detection. Purpose: Ensure parser detects reasoning tag format. """ print("Feeding content with tag...") parser = ThinkingParser() result = parser.feed("Hello") print(f"Comparing open_tag: Expected '', Got '{parser.open_tag}'") assert parser.state == ParserState.IN_THINKING assert parser.open_tag == "" assert parser.close_tag == "" def test_detects_thought_tag(self): """ What it does: Verifies tag detection. Purpose: Ensure parser detects thought tag format. """ print("Feeding content with tag...") parser = ThinkingParser() result = parser.feed("Hello") print(f"Comparing open_tag: Expected '', Got '{parser.open_tag}'") assert parser.state == ParserState.IN_THINKING assert parser.open_tag == "" assert parser.close_tag == "" def test_strips_leading_whitespace_for_tag_detection(self): """ What it does: Verifies leading whitespace is stripped for tag detection. Purpose: Ensure tags with leading whitespace are detected. """ print("Feeding content with leading whitespace...") parser = ThinkingParser() result = parser.feed(" \n\nHello") print(f"Comparing state: Expected IN_THINKING, Got {parser.state}") assert parser.state == ParserState.IN_THINKING assert parser.open_tag == "" def test_buffers_partial_tag(self): """ What it does: Verifies partial tag is buffered. Purpose: Ensure parser waits for complete tag. """ print("Feeding partial tag...") parser = ThinkingParser() result = parser.feed("Hello") print(f"After second chunk: state={parser.state}") assert parser.state == ParserState.IN_THINKING assert parser.open_tag == "" def test_no_tag_transitions_to_streaming(self): """ What it does: Verifies transition to STREAMING when no tag found. Purpose: Ensure regular content is passed through. """ print("Feeding content without thinking tag...") parser = ThinkingParser() result = parser.feed("Hello, this is regular content without any thinking tags.") print(f"Comparing state: Expected STREAMING, Got {parser.state}") assert parser.state == ParserState.STREAMING assert result.state_changed is True assert result.regular_content == "Hello, this is regular content without any thinking tags." def test_buffer_exceeds_limit_transitions_to_streaming(self): """ What it does: Verifies transition to STREAMING when buffer exceeds limit. Purpose: Ensure parser doesn't buffer indefinitely. """ print("Feeding content that exceeds buffer limit...") parser = ThinkingParser(initial_buffer_size=10) result = parser.feed("This is a long content that exceeds the buffer limit") print(f"Comparing state: Expected STREAMING, Got {parser.state}") assert parser.state == ParserState.STREAMING assert result.state_changed is True class TestThinkingParserFeedInThinking: """Tests for ThinkingParser.feed() in IN_THINKING state.""" def test_accumulates_thinking_content(self): """ What it does: Verifies thinking content is accumulated. Purpose: Ensure content inside thinking block is captured. """ print("Feeding thinking content...") parser = ThinkingParser() parser.feed("") # Feed more content result = parser.feed("This is thinking content") print(f"Comparing thinking_buffer: Got '{parser.thinking_buffer}'") # Content is in buffer due to cautious sending assert "This is thinking content" in parser.thinking_buffer or result.thinking_content def test_detects_closing_tag(self): """ What it does: Verifies closing tag detection. Purpose: Ensure parser transitions to STREAMING on closing tag. """ print("Feeding content with closing tag...") parser = ThinkingParser() parser.feed("Hello") result = parser.feed("World") print(f"Comparing state: Expected STREAMING, Got {parser.state}") assert parser.state == ParserState.STREAMING assert result.is_last_thinking_chunk is True assert result.state_changed is True def test_regular_content_after_closing_tag(self): """ What it does: Verifies regular content after closing tag. Purpose: Ensure content after closing tag is returned as regular_content. """ print("Feeding content with closing tag and regular content...") parser = ThinkingParser() parser.feed("Thinking") result = parser.feed("Regular content") print(f"Comparing regular_content: Got '{result.regular_content}'") assert result.regular_content == "Regular content" def test_strips_whitespace_after_closing_tag(self): """ What it does: Verifies whitespace is stripped after closing tag. Purpose: Ensure leading newlines after closing tag are removed. """ print("Feeding content with whitespace after closing tag...") parser = ThinkingParser() parser.feed("Thinking") result = parser.feed("\n\nRegular content") print(f"Comparing regular_content: Got '{result.regular_content}'") assert result.regular_content == "Regular content" def test_cautious_buffering(self): """ What it does: Verifies cautious buffering keeps last max_tag_length chars. Purpose: Ensure closing tag is not split across chunks. """ print("Testing cautious buffering...") parser = ThinkingParser(open_tags=[""]) # Short tag for easier testing parser.feed("") # Feed content longer than max_tag_length long_content = "A" * 50 result = parser.feed(long_content) print(f"Comparing thinking_buffer length: Got {len(parser.thinking_buffer)}") # Buffer should keep last max_tag_length chars assert len(parser.thinking_buffer) <= parser.max_tag_length def test_split_closing_tag(self): """ What it does: Verifies split closing tag is handled. Purpose: Ensure closing tag split across chunks is detected. """ print("Feeding split closing tag...") parser = ThinkingParser() parser.feed("Hello") parser.feed("World") print(f"Comparing state: Expected STREAMING, Got {parser.state}") assert parser.state == ParserState.STREAMING class TestThinkingParserFeedStreaming: """Tests for ThinkingParser.feed() in STREAMING state.""" def test_passes_content_through(self): """ What it does: Verifies content is passed through in STREAMING state. Purpose: Ensure regular content is returned as-is. """ print("Feeding content in STREAMING state...") parser = ThinkingParser() # Transition to STREAMING by feeding non-tag content parser.feed("Regular content") result = parser.feed("More content") print(f"Comparing regular_content: Expected 'More content', Got '{result.regular_content}'") assert result.regular_content == "More content" assert result.thinking_content is None def test_ignores_thinking_tags_in_streaming(self): """ What it does: Verifies thinking tags are ignored in STREAMING state. Purpose: Ensure tags after initial detection are passed through. """ print("Feeding thinking tag in STREAMING state...") parser = ThinkingParser() parser.feed("Regular content") # Transition to STREAMING result = parser.feed("This should be regular") print(f"Comparing regular_content: Got '{result.regular_content}'") assert result.regular_content == "This should be regular" assert result.thinking_content is None class TestThinkingParserFinalize: """Tests for ThinkingParser.finalize().""" def test_flushes_thinking_buffer(self): """ What it does: Verifies thinking buffer is flushed on finalize. Purpose: Ensure remaining thinking content is returned. """ print("Finalizing parser with thinking buffer...") parser = ThinkingParser() parser.feed("Incomplete thinking") result = parser.finalize() print(f"Comparing thinking_content: Got '{result.thinking_content}'") assert result.thinking_content is not None assert result.is_last_thinking_chunk is True def test_flushes_initial_buffer(self): """ What it does: Verifies initial buffer is flushed on finalize. Purpose: Ensure buffered content is returned when no tag found. """ print("Finalizing parser with initial buffer...") parser = ThinkingParser() parser.feed("Content") parser.finalize() print(f"Comparing buffers: thinking_buffer='{parser.thinking_buffer}', initial_buffer='{parser.initial_buffer}'") assert parser.thinking_buffer == "" assert parser.initial_buffer == "" class TestThinkingParserReset: """Tests for ThinkingParser.reset().""" def test_resets_to_initial_state(self): """ What it does: Verifies reset returns parser to initial state. Purpose: Ensure parser can be reused. """ print("Resetting parser after use...") parser = ThinkingParser() parser.feed("ContentRegular") parser.reset() print(f"Comparing state: Expected PRE_CONTENT, Got {parser.state}") assert parser.state == ParserState.PRE_CONTENT assert parser.initial_buffer == "" assert parser.thinking_buffer == "" assert parser.open_tag is None assert parser.close_tag is None assert parser.is_first_thinking_chunk is True assert parser._thinking_block_found is False class TestThinkingParserFoundThinkingBlock: """Tests for ThinkingParser.found_thinking_block property.""" def test_false_initially(self): """ What it does: Verifies found_thinking_block is False initially. Purpose: Ensure property starts as False. """ print("Checking found_thinking_block initially...") parser = ThinkingParser() print(f"Comparing: Expected False, Got {parser.found_thinking_block}") assert parser.found_thinking_block is False def test_true_after_tag_detection(self): """ What it does: Verifies found_thinking_block is True after tag detection. Purpose: Ensure property is set when thinking block is found. """ print("Checking found_thinking_block after tag detection...") parser = ThinkingParser() parser.feed("Content") print(f"Comparing: Expected True, Got {parser.found_thinking_block}") assert parser.found_thinking_block is True def test_false_when_no_tag(self): """ What it does: Verifies found_thinking_block is False when no tag found. Purpose: Ensure property stays False for regular content. """ print("Checking found_thinking_block with no tag...") parser = ThinkingParser() parser.feed("Regular content without thinking tags") print(f"Comparing: Expected False, Got {parser.found_thinking_block}") assert parser.found_thinking_block is False class TestThinkingParserProcessForOutput: """Tests for ThinkingParser.process_for_output().""" def test_as_reasoning_content_mode(self): """ What it does: Verifies as_reasoning_content mode returns content as-is. Purpose: Ensure content is returned unchanged for reasoning_content field. """ print("Testing as_reasoning_content mode...") parser = ThinkingParser(handling_mode="as_reasoning_content") parser.open_tag = "" parser.close_tag = "" result = parser.process_for_output("Thinking content", is_first=True, is_last=True) print(f"Comparing: Expected 'Thinking content', Got '{result}'") assert result == "Thinking content" def test_remove_mode(self): """ What it does: Verifies remove mode returns None. Purpose: Ensure thinking content is removed. """ print("Testing remove mode...") parser = ThinkingParser(handling_mode="remove") result = parser.process_for_output("Thinking content", is_first=True, is_last=True) print(f"Comparing: Expected None, Got {result}") assert result is None def test_pass_mode_first_chunk(self): """ What it does: Verifies pass mode adds opening tag to first chunk. Purpose: Ensure tags are preserved in pass mode. """ print("Testing pass mode with first chunk...") parser = ThinkingParser(handling_mode="pass") parser.open_tag = "" parser.close_tag = "" result = parser.process_for_output("Content", is_first=True, is_last=False) print(f"Comparing: Expected 'Content', Got '{result}'") assert result == "Content" def test_pass_mode_last_chunk(self): """ What it does: Verifies pass mode adds closing tag to last chunk. Purpose: Ensure closing tag is added in pass mode. """ print("Testing pass mode with last chunk...") parser = ThinkingParser(handling_mode="pass") parser.open_tag = "" parser.close_tag = "" result = parser.process_for_output("Content", is_first=False, is_last=True) print(f"Comparing: Expected 'Content', Got '{result}'") assert result == "Content" def test_pass_mode_first_and_last_chunk(self): """ What it does: Verifies pass mode adds both tags when first and last. Purpose: Ensure both tags are added for single chunk. """ print("Testing pass mode with first and last chunk...") parser = ThinkingParser(handling_mode="pass") parser.open_tag = "" parser.close_tag = "" result = parser.process_for_output("Content", is_first=True, is_last=True) print(f"Comparing: Expected 'Content', Got '{result}'") assert result == "Content" def test_pass_mode_middle_chunk(self): """ What it does: Verifies pass mode returns content as-is for middle chunk. Purpose: Ensure no tags are added for middle chunks. """ print("Testing pass mode with middle chunk...") parser = ThinkingParser(handling_mode="pass") parser.open_tag = "" parser.close_tag = "" result = parser.process_for_output("Content", is_first=False, is_last=False) print(f"Comparing: Expected 'Content', Got '{result}'") assert result == "Content" def test_strip_tags_mode(self): """ What it does: Verifies strip_tags mode returns content without tags. Purpose: Ensure content is returned without tags. """ print("Testing strip_tags mode...") parser = ThinkingParser(handling_mode="strip_tags") result = parser.process_for_output("Thinking content", is_first=True, is_last=True) print(f"Comparing: Expected 'Thinking content', Got '{result}'") assert result == "Thinking content" def test_none_content_returns_none(self): """ What it does: Verifies None content returns None. Purpose: Ensure None is handled correctly. """ print("Testing None content...") parser = ThinkingParser() result = parser.process_for_output(None, is_first=True, is_last=True) print(f"Comparing: Expected None, Got {result}") assert result is None def test_empty_content_returns_none(self): """ What it does: Verifies empty content returns None. Purpose: Ensure empty string is handled correctly. """ print("Testing empty content...") parser = ThinkingParser() result = parser.process_for_output("", is_first=True, is_last=True) print(f"Comparing: Expected None, Got {result}") assert result is None class TestThinkingParserFullFlow: """Integration tests for full parsing flow.""" def test_complete_thinking_block(self): """ What it does: Verifies complete thinking block parsing. Purpose: Ensure full flow works correctly. """ print("Testing complete thinking block flow...") parser = ThinkingParser() # Feed complete thinking block result1 = parser.feed("This is my reasoning process.Here is the answer.") print(f"State: {parser.state}") print(f"Thinking content: {result1.thinking_content}") print(f"Regular content: {result1.regular_content}") assert parser.state == ParserState.STREAMING assert parser.found_thinking_block is True assert result1.regular_content == "Here is the answer." def test_multi_chunk_thinking_block(self): """ What it does: Verifies thinking block split across multiple chunks. Purpose: Ensure chunked content is handled correctly. """ print("Testing multi-chunk thinking block...") parser = ThinkingParser() # Feed in multiple chunks result1 = parser.feed("Let me think") print(f"After chunk 2: state={parser.state}") assert parser.state == ParserState.IN_THINKING result3 = parser.feed(" about this...The answer is 42.") print(f"After chunk 4: state={parser.state}") assert parser.state == ParserState.STREAMING assert result4.regular_content == "The answer is 42." def test_no_thinking_block(self): """ What it does: Verifies handling of content without thinking block. Purpose: Ensure regular content passes through unchanged. """ print("Testing content without thinking block...") parser = ThinkingParser() result = parser.feed("This is just regular content without any thinking tags.") print(f"State: {parser.state}") print(f"Regular content: {result.regular_content}") assert parser.state == ParserState.STREAMING assert parser.found_thinking_block is False assert result.regular_content == "This is just regular content without any thinking tags." def test_thinking_block_with_newlines(self): """ What it does: Verifies thinking block with newlines after closing tag. Purpose: Ensure newlines are stripped from regular content. """ print("Testing thinking block with newlines...") parser = ThinkingParser() result = parser.feed("Reasoning\n\n\nAnswer here") print(f"Regular content: '{result.regular_content}'") assert result.regular_content == "Answer here" def test_empty_thinking_block(self): """ What it does: Verifies empty thinking block handling. Purpose: Ensure empty thinking block doesn't break parser. """ print("Testing empty thinking block...") parser = ThinkingParser() result = parser.feed("Answer") print(f"State: {parser.state}") print(f"Regular content: '{result.regular_content}'") assert parser.state == ParserState.STREAMING assert result.regular_content == "Answer" def test_thinking_block_only_whitespace_after(self): """ What it does: Verifies thinking block with only whitespace after closing tag. Purpose: Ensure whitespace-only content after tag returns None. """ print("Testing thinking block with only whitespace after...") parser = ThinkingParser() result = parser.feed("Reasoning \n\n ") print(f"Regular content: {result.regular_content}") # Whitespace-only content should be stripped to None assert result.regular_content is None or result.regular_content == "" class TestThinkingParserEdgeCases: """Edge case tests for ThinkingParser.""" def test_nested_tags_not_supported(self): """ What it does: Verifies nested tags are not specially handled. Purpose: Ensure nested tags are treated as content. """ print("Testing nested tags...") parser = ThinkingParser() result = parser.feed("OuterInnerStill outerAnswer") print(f"State: {parser.state}") # First closes the block assert parser.state == ParserState.STREAMING def test_tag_in_middle_of_content(self): """ What it does: Verifies tag in middle of content is not detected. Purpose: Ensure tags are only detected at start. """ print("Testing tag in middle of content...") parser = ThinkingParser() result = parser.feed("Some text This is not a thinking block") print(f"State: {parser.state}") print(f"Regular content: '{result.regular_content}'") assert parser.state == ParserState.STREAMING assert parser.found_thinking_block is False assert "" in result.regular_content def test_malformed_closing_tag(self): """ What it does: Verifies malformed closing tag is not detected. Purpose: Ensure only exact closing tag is matched. """ print("Testing malformed closing tag...") parser = ThinkingParser() parser.feed("Content") result = parser.feed("More content") # Wrong case print(f"State: {parser.state}") # Should still be in thinking state assert parser.state == ParserState.IN_THINKING def test_unicode_content(self): """ What it does: Verifies Unicode content is handled correctly. Purpose: Ensure non-ASCII characters work. """ print("Testing Unicode content...") parser = ThinkingParser() result = parser.feed("Думаю о проблеме 🤔Ответ: 42") print(f"Regular content: '{result.regular_content}'") assert parser.state == ParserState.STREAMING assert result.regular_content == "Ответ: 42" def test_very_long_thinking_content(self): """ What it does: Verifies very long thinking content is handled. Purpose: Ensure large content doesn't break parser. """ print("Testing very long thinking content...") parser = ThinkingParser() long_content = "A" * 10000 result = parser.feed(f"{long_content}Done") print(f"State: {parser.state}") assert parser.state == ParserState.STREAMING assert result.regular_content == "Done" def test_special_characters_in_content(self): """ What it does: Verifies special characters are handled. Purpose: Ensure HTML-like content doesn't break parser. """ print("Testing special characters...") parser = ThinkingParser() result = parser.feed("Content with bold and & entitiesAnswer") print(f"State: {parser.state}") assert parser.state == ParserState.STREAMING assert result.regular_content == "Answer" def test_multiple_feeds_after_streaming(self): """ What it does: Verifies multiple feeds in STREAMING state. Purpose: Ensure parser continues to work after transition. """ print("Testing multiple feeds in STREAMING state...") parser = ThinkingParser() parser.feed("ThinkingFirst") result2 = parser.feed(" Second") result3 = parser.feed(" Third") print(f"Result 2: '{result2.regular_content}'") print(f"Result 3: '{result3.regular_content}'") assert result2.regular_content == " Second" assert result3.regular_content == " Third" class TestThinkingParserConfigIntegration: """Tests for ThinkingParser integration with config.""" def test_uses_config_handling_mode(self): """ What it does: Verifies parser uses FAKE_REASONING_HANDLING from config. Purpose: Ensure config integration works. """ print("Testing config handling mode...") with patch('kiro.thinking_parser.FAKE_REASONING_HANDLING', 'remove'): parser = ThinkingParser() print(f"Handling mode: {parser.handling_mode}") assert parser.handling_mode == "remove" def test_uses_config_open_tags(self): """ What it does: Verifies parser uses FAKE_REASONING_OPEN_TAGS from config. Purpose: Ensure config integration works. """ print("Testing config open tags...") custom_tags = [""] with patch('kiro.thinking_parser.FAKE_REASONING_OPEN_TAGS', custom_tags): parser = ThinkingParser() print(f"Open tags: {parser.open_tags}") assert parser.open_tags == custom_tags def test_default_initial_buffer_size_from_config(self): """ What it does: Verifies parser uses default initial_buffer_size from config. Purpose: Ensure config value is used when not overridden. Note: We can't easily patch the config value after import, so we just verify the default is used. Custom values are tested in TestThinkingParserInitialization.test_custom_initial_buffer_size. """ print("Testing default initial buffer size from config...") from kiro.config import FAKE_REASONING_INITIAL_BUFFER_SIZE parser = ThinkingParser() print(f"Initial buffer size: {parser.initial_buffer_size}") print(f"Config value: {FAKE_REASONING_INITIAL_BUFFER_SIZE}") assert parser.initial_buffer_size == FAKE_REASONING_INITIAL_BUFFER_SIZE class TestInjectThinkingTags: """Tests for inject_thinking_tags function in converters.""" def test_injects_tags_when_enabled(self): """ What it does: Verifies tags are injected when FAKE_REASONING_ENABLED is True. Purpose: Ensure tags are added to content. """ print("Testing tag injection when enabled...") from kiro.converters_core import inject_thinking_tags with patch('kiro.converters_core.FAKE_REASONING_ENABLED', True): with patch('kiro.converters_core.FAKE_REASONING_MAX_TOKENS', 4000): result = inject_thinking_tags("Hello") print(f"Result: '{result}'") assert "enabled" in result assert "4000" in result assert "Hello" in result def test_no_injection_when_disabled(self): """ What it does: Verifies tags are not injected when FAKE_REASONING_ENABLED is False. Purpose: Ensure tags are not added when disabled. """ print("Testing no tag injection when disabled...") from kiro.converters_core import inject_thinking_tags with patch('kiro.converters_core.FAKE_REASONING_ENABLED', False): result = inject_thinking_tags("Hello") print(f"Result: '{result}'") assert result == "Hello" assert "" not in result def test_injection_preserves_content(self): """ What it does: Verifies original content is preserved after injection. Purpose: Ensure content is not modified. """ print("Testing content preservation...") from kiro.converters_core import inject_thinking_tags original = "This is my original content with special chars: <>&" with patch('kiro.converters_core.FAKE_REASONING_ENABLED', True): with patch('kiro.converters_core.FAKE_REASONING_MAX_TOKENS', 4000): result = inject_thinking_tags(original) print(f"Result ends with original: {result.endswith(original)}") assert result.endswith(original)