Merge branch 'dev' of git.science.uu.nl:ics/sp/2025/n25b/pepperplus-cb into feat/program-reset-llm
This commit is contained in:
@@ -1,4 +1,6 @@
|
||||
import asyncio
|
||||
import json
|
||||
import time
|
||||
from unittest.mock import AsyncMock, MagicMock, mock_open, patch
|
||||
|
||||
import agentspeak
|
||||
@@ -77,11 +79,6 @@ async def test_incorrect_belief_collector_message(agent, mock_settings):
|
||||
agent.bdi_agent.call.assert_not_called() # did not set belief
|
||||
|
||||
|
||||
@pytest.mark.asyncio
|
||||
async def test():
|
||||
pass
|
||||
|
||||
|
||||
@pytest.mark.asyncio
|
||||
async def test_handle_llm_response(agent):
|
||||
"""Test that LLM responses are forwarded to the Robot Speech Agent"""
|
||||
@@ -124,3 +121,148 @@ async def test_custom_actions(agent):
|
||||
next(gen) # Execute
|
||||
|
||||
agent._send_to_llm.assert_called_with("Hello", "Norm", "Goal")
|
||||
|
||||
|
||||
def test_add_belief_sets_event(agent):
|
||||
"""Test that a belief triggers wake event and call()"""
|
||||
agent._wake_bdi_loop = MagicMock()
|
||||
|
||||
belief = Belief(name="test_belief", arguments=["a", "b"])
|
||||
agent._apply_beliefs([belief])
|
||||
|
||||
assert agent.bdi_agent.call.called
|
||||
agent._wake_bdi_loop.set.assert_called()
|
||||
|
||||
|
||||
def test_apply_beliefs_empty_returns(agent):
|
||||
"""Line: if not beliefs: return"""
|
||||
agent._wake_bdi_loop = MagicMock()
|
||||
agent._apply_beliefs([])
|
||||
agent.bdi_agent.call.assert_not_called()
|
||||
agent._wake_bdi_loop.set.assert_not_called()
|
||||
|
||||
|
||||
def test_remove_belief_success_wakes_loop(agent):
|
||||
"""Line: if result: wake set"""
|
||||
agent._wake_bdi_loop = MagicMock()
|
||||
agent.bdi_agent.call.return_value = True
|
||||
|
||||
agent._remove_belief("remove_me", ["x"])
|
||||
|
||||
assert agent.bdi_agent.call.called
|
||||
trigger, goaltype, literal, *_ = agent.bdi_agent.call.call_args.args
|
||||
|
||||
assert trigger == agentspeak.Trigger.removal
|
||||
assert goaltype == agentspeak.GoalType.belief
|
||||
assert literal.functor == "remove_me"
|
||||
assert literal.args[0].functor == "x"
|
||||
|
||||
agent._wake_bdi_loop.set.assert_called()
|
||||
|
||||
|
||||
def test_remove_belief_failure_does_not_wake(agent):
|
||||
"""Line: else result is False"""
|
||||
agent._wake_bdi_loop = MagicMock()
|
||||
agent.bdi_agent.call.return_value = False
|
||||
|
||||
agent._remove_belief("not_there", ["y"])
|
||||
|
||||
assert agent.bdi_agent.call.called # removal was attempted
|
||||
agent._wake_bdi_loop.set.assert_not_called()
|
||||
|
||||
|
||||
def test_remove_all_with_name_wakes_loop(agent):
|
||||
"""Cover _remove_all_with_name() removed counter + wake"""
|
||||
agent._wake_bdi_loop = MagicMock()
|
||||
|
||||
fake_literal = agentspeak.Literal("delete_me", (agentspeak.Literal("arg1"),))
|
||||
fake_key = ("delete_me", 1)
|
||||
agent.bdi_agent.beliefs = {fake_key: {fake_literal}}
|
||||
|
||||
agent._remove_all_with_name("delete_me")
|
||||
|
||||
assert agent.bdi_agent.call.called
|
||||
agent._wake_bdi_loop.set.assert_called()
|
||||
|
||||
|
||||
@pytest.mark.asyncio
|
||||
async def test_bdi_step_true_branch_hits_line_67(agent):
|
||||
"""Force step() to return True once so line 67 is actually executed"""
|
||||
# counter that isn't tied to MagicMock.call_count ordering
|
||||
counter = {"i": 0}
|
||||
|
||||
def fake_step():
|
||||
counter["i"] += 1
|
||||
return counter["i"] == 1 # True only first time
|
||||
|
||||
# Important: wrap fake_step into another mock so `.called` still exists
|
||||
agent.bdi_agent.step = MagicMock(side_effect=fake_step)
|
||||
agent.bdi_agent.shortest_deadline = MagicMock(return_value=None)
|
||||
|
||||
agent._running = True
|
||||
agent._wake_bdi_loop = asyncio.Event()
|
||||
agent._wake_bdi_loop.set()
|
||||
|
||||
task = asyncio.create_task(agent._bdi_loop())
|
||||
await asyncio.sleep(0.01)
|
||||
task.cancel()
|
||||
try:
|
||||
await task
|
||||
except asyncio.CancelledError:
|
||||
pass
|
||||
|
||||
assert agent.bdi_agent.step.called
|
||||
assert counter["i"] >= 1 # proves True branch ran
|
||||
|
||||
|
||||
def test_replace_belief_calls_remove_all(agent):
|
||||
"""Cover: if belief.replace: self._remove_all_with_name()"""
|
||||
agent._remove_all_with_name = MagicMock()
|
||||
agent._wake_bdi_loop = MagicMock()
|
||||
|
||||
belief = Belief(name="user_said", arguments=["Hello"], replace=True)
|
||||
agent._apply_beliefs([belief])
|
||||
|
||||
agent._remove_all_with_name.assert_called_with("user_said")
|
||||
|
||||
|
||||
@pytest.mark.asyncio
|
||||
async def test_send_to_llm_creates_prompt_and_sends(agent):
|
||||
"""Cover entire _send_to_llm() including message send and logger.info"""
|
||||
agent.bdi_agent = MagicMock() # ensure mocked BDI does not interfere
|
||||
agent._wake_bdi_loop = MagicMock()
|
||||
|
||||
await agent._send_to_llm("hello world", "n1\nn2", "g1")
|
||||
|
||||
# send() was called
|
||||
assert agent.send.called
|
||||
sent_msg: InternalMessage = agent.send.call_args.args[0]
|
||||
|
||||
# Message routing values correct
|
||||
assert sent_msg.to == settings.agent_settings.llm_name
|
||||
assert "hello world" in sent_msg.body
|
||||
|
||||
# JSON contains split norms/goals
|
||||
body = json.loads(sent_msg.body)
|
||||
assert body["norms"] == ["n1", "n2"]
|
||||
assert body["goals"] == ["g1"]
|
||||
|
||||
|
||||
@pytest.mark.asyncio
|
||||
async def test_deadline_sleep_branch(agent):
|
||||
"""Specifically assert the if deadline: sleep → maybe_more_work=True branch"""
|
||||
future_deadline = time.time() + 0.005
|
||||
agent.bdi_agent.step.return_value = False
|
||||
agent.bdi_agent.shortest_deadline.return_value = future_deadline
|
||||
|
||||
start_time = time.time()
|
||||
agent._running = True
|
||||
agent._wake_bdi_loop = asyncio.Event()
|
||||
agent._wake_bdi_loop.set()
|
||||
|
||||
task = asyncio.create_task(agent._bdi_loop())
|
||||
await asyncio.sleep(0.01)
|
||||
task.cancel()
|
||||
|
||||
duration = time.time() - start_time
|
||||
assert duration >= 0.004 # loop slept until deadline
|
||||
|
||||
@@ -87,3 +87,49 @@ async def test_send_beliefs_to_bdi(agent):
|
||||
assert sent.to == settings.agent_settings.bdi_core_name
|
||||
assert sent.thread == "beliefs"
|
||||
assert json.loads(sent.body)["beliefs"] == [belief.model_dump() for belief in beliefs]
|
||||
|
||||
|
||||
@pytest.mark.asyncio
|
||||
async def test_setup_executes(agent):
|
||||
"""Covers setup and asserts the agent has a name."""
|
||||
await agent.setup()
|
||||
assert agent.name == "belief_collector_agent" # simple property assertion
|
||||
|
||||
|
||||
@pytest.mark.asyncio
|
||||
async def test_handle_message_unrecognized_type_executes(agent):
|
||||
"""Covers the else branch for unrecognized message type."""
|
||||
payload = {"type": "unknown_type"}
|
||||
msg = make_msg(payload, sender="tester")
|
||||
# Wrap send to ensure nothing is sent
|
||||
agent.send = AsyncMock()
|
||||
await agent.handle_message(msg)
|
||||
# Assert no messages were sent
|
||||
agent.send.assert_not_awaited()
|
||||
|
||||
|
||||
@pytest.mark.asyncio
|
||||
async def test_handle_emo_text_executes(agent):
|
||||
"""Covers the _handle_emo_text method."""
|
||||
# The method does nothing, but we can assert it returns None
|
||||
result = await agent._handle_emo_text({}, "origin")
|
||||
assert result is None
|
||||
|
||||
|
||||
@pytest.mark.asyncio
|
||||
async def test_send_beliefs_to_bdi_empty_executes(agent):
|
||||
"""Covers early return when beliefs are empty."""
|
||||
agent.send = AsyncMock()
|
||||
await agent._send_beliefs_to_bdi({})
|
||||
# Assert that nothing was sent
|
||||
agent.send.assert_not_awaited()
|
||||
|
||||
|
||||
@pytest.mark.asyncio
|
||||
async def test_handle_belief_text_invalid_returns_none(agent, mocker):
|
||||
payload = {"type": "belief_extraction_text", "beliefs": {"user_said": "invalid-argument"}}
|
||||
|
||||
result = await agent._handle_belief_text(payload, "origin")
|
||||
|
||||
# The method itself returns None
|
||||
assert result is None
|
||||
|
||||
@@ -56,3 +56,10 @@ async def test_process_transcription_demo(agent, mock_settings):
|
||||
assert sent.thread == "beliefs"
|
||||
parsed = json.loads(sent.body)
|
||||
assert parsed["beliefs"]["user_said"] == [transcription]
|
||||
|
||||
|
||||
@pytest.mark.asyncio
|
||||
async def test_setup_initializes_beliefs(agent):
|
||||
"""Covers the setup method and ensures beliefs are initialized."""
|
||||
await agent.setup()
|
||||
assert agent.beliefs == {"mood": ["X"], "car": ["Y"]}
|
||||
|
||||
Reference in New Issue
Block a user