1
from __future__ import annotations
6
from pathlib import Path
7
from typing import TYPE_CHECKING
12
from autogpt.agents import Agent, BaseAgent
14
from autogpt.core.utils.json_schema import JSONSchema
15
from autogpt.models.command import Command, CommandParameter
16
from autogpt.models.command_registry import CommandRegistry
22
type=JSONSchema.Type.INTEGER,
23
description="Argument 1",
30
type=JSONSchema.Type.STRING,
31
description="Argument 2",
38
def example_command_method(arg1: int, arg2: str, agent: BaseAgent) -> str:
39
"""Example function for testing the Command class."""
40
# This function is static because it is not used by any other test cases.
41
return f"{arg1} - {arg2}"
44
def test_command_creation():
45
"""Test that a Command object can be created with the correct attributes."""
48
description="Example command",
49
method=example_command_method,
50
parameters=PARAMETERS,
53
assert cmd.name == "example"
54
assert cmd.description == "Example command"
55
assert cmd.method == example_command_method
58
== "example: Example command. Params: (arg1: integer, arg2: Optional[string])"
66
description="Example command",
67
method=example_command_method,
68
parameters=PARAMETERS,
72
def test_command_call(example_command: Command, agent: Agent):
73
"""Test that Command(*args) calls and returns the result of method(*args)."""
74
result = example_command(arg1=1, arg2="test", agent=agent)
75
assert result == "1 - test"
78
def test_command_call_with_invalid_arguments(example_command: Command, agent: Agent):
79
"""Test that calling a Command object with invalid arguments raises a TypeError."""
80
with pytest.raises(TypeError):
81
example_command(arg1="invalid", does_not_exist="test", agent=agent)
84
def test_register_command(example_command: Command):
85
"""Test that a command can be registered to the registry."""
86
registry = CommandRegistry()
88
registry.register(example_command)
90
assert registry.get_command(example_command.name) == example_command
91
assert len(registry.commands) == 1
94
def test_unregister_command(example_command: Command):
95
"""Test that a command can be unregistered from the registry."""
96
registry = CommandRegistry()
98
registry.register(example_command)
99
registry.unregister(example_command)
101
assert len(registry.commands) == 0
102
assert example_command.name not in registry
106
def example_command_with_aliases(example_command: Command):
107
example_command.aliases = ["example_alias", "example_alias_2"]
108
return example_command
111
def test_register_command_aliases(example_command_with_aliases: Command):
112
"""Test that a command can be registered to the registry."""
113
registry = CommandRegistry()
114
command = example_command_with_aliases
116
registry.register(command)
118
assert command.name in registry
119
assert registry.get_command(command.name) == command
120
for alias in command.aliases:
121
assert registry.get_command(alias) == command
122
assert len(registry.commands) == 1
125
def test_unregister_command_aliases(example_command_with_aliases: Command):
126
"""Test that a command can be unregistered from the registry."""
127
registry = CommandRegistry()
128
command = example_command_with_aliases
130
registry.register(command)
131
registry.unregister(command)
133
assert len(registry.commands) == 0
134
assert command.name not in registry
135
for alias in command.aliases:
136
assert alias not in registry
139
def test_command_in_registry(example_command_with_aliases: Command):
140
"""Test that `command_name in registry` works."""
141
registry = CommandRegistry()
142
command = example_command_with_aliases
144
assert command.name not in registry
145
assert "nonexistent_command" not in registry
147
registry.register(command)
149
assert command.name in registry
150
assert "nonexistent_command" not in registry
151
for alias in command.aliases:
152
assert alias in registry
155
def test_get_command(example_command: Command):
156
"""Test that a command can be retrieved from the registry."""
157
registry = CommandRegistry()
159
registry.register(example_command)
160
retrieved_cmd = registry.get_command(example_command.name)
162
assert retrieved_cmd == example_command
165
def test_get_nonexistent_command():
166
"""Test that attempting to get a nonexistent command raises a KeyError."""
167
registry = CommandRegistry()
169
assert registry.get_command("nonexistent_command") is None
170
assert "nonexistent_command" not in registry
173
def test_call_command(agent: Agent):
174
"""Test that a command can be called through the registry."""
175
registry = CommandRegistry()
178
description="Example command",
179
method=example_command_method,
180
parameters=PARAMETERS,
183
registry.register(cmd)
184
result = registry.call("example", arg1=1, arg2="test", agent=agent)
186
assert result == "1 - test"
189
def test_call_nonexistent_command(agent: Agent):
190
"""Test that attempting to call a nonexistent command raises a KeyError."""
191
registry = CommandRegistry()
193
with pytest.raises(KeyError):
194
registry.call("nonexistent_command", arg1=1, arg2="test", agent=agent)
197
def test_import_mock_commands_module():
198
"""Test that the registry can import a module with mock command plugins."""
199
registry = CommandRegistry()
200
mock_commands_module = "tests.mocks.mock_commands"
202
registry.import_command_module(mock_commands_module)
204
assert "function_based_cmd" in registry
205
assert registry.commands["function_based_cmd"].name == "function_based_cmd"
207
registry.commands["function_based_cmd"].description
208
== "Function-based test command"
212
def test_import_temp_command_file_module(tmp_path: Path):
214
Test that the registry can import a command plugins module from a temp file.
216
tmp_path (pathlib.Path): Path to a temporary directory.
218
registry = CommandRegistry()
220
# Create a temp command file
221
src = Path(os.getcwd()) / "tests/mocks/mock_commands.py"
222
temp_commands_file = tmp_path / "mock_commands.py"
223
shutil.copyfile(src, temp_commands_file)
225
# Add the temp directory to sys.path to make the module importable
226
sys.path.append(str(tmp_path))
228
temp_commands_module = "mock_commands"
229
registry.import_command_module(temp_commands_module)
231
# Remove the temp directory from sys.path
232
sys.path.remove(str(tmp_path))
234
assert "function_based_cmd" in registry
235
assert registry.commands["function_based_cmd"].name == "function_based_cmd"
237
registry.commands["function_based_cmd"].description
238
== "Function-based test command"