tests, model

This commit is contained in:
Evgeny Vakhteev
2023-04-17 20:51:27 -07:00
parent 193c80849f
commit 9fd80a8660
5 changed files with 290 additions and 8 deletions

View File

@@ -6,7 +6,7 @@ from __future__ import annotations
import os
from pathlib import Path
from typing import Type
from typing import Type, Optional
import yaml
from autogpt.prompts.generator import PromptGenerator

View File

@@ -1,5 +1,4 @@
"""Handles loading of plugins."""
import zipfile
from typing import Any, Dict, List, Optional, Tuple, TypedDict
from typing import TypeVar
@@ -11,7 +10,7 @@ class Message(TypedDict):
content: str
class BaseOpenAIPluginClient():
class BaseOpenAIPlugin:
"""
This is a template for Auto-GPT plugins.
"""

View File

@@ -14,7 +14,7 @@ from abstract_singleton import AbstractSingleton
from openapi_python_client.cli import Config as OpenAPIConfig
from autogpt.config import Config
from autogpt.models.base_open_ai_plugin import BaseOpenAIPluginClient
from autogpt.models.base_open_ai_plugin import BaseOpenAIPlugin
def inspect_zip_for_module(zip_path: str, debug: bool = False) -> Optional[str]:
@@ -160,18 +160,18 @@ def initialize_openai_plugins(manifests_specs: dict, cfg: Config, debug: bool =
def instantiate_openai_plugin_clients(manifests_specs_clients: dict, cfg: Config, debug: bool = False) -> dict:
"""
Instantiates BaseOpenAIPluginClient instances for each OpenAI plugin.
Instantiates BaseOpenAIPlugin instances for each OpenAI plugin.
Args:
manifests_specs_clients (dict): per url dictionary of manifest, spec and client.
cfg (Config): Config instance including plugins config
debug (bool, optional): Enable debug logging. Defaults to False.
Returns:
plugins (dict): per url dictionary of BaseOpenAIPluginClient instances.
plugins (dict): per url dictionary of BaseOpenAIPlugin instances.
"""
plugins = {}
for url, manifest_spec_client in manifests_specs_clients.items():
plugins[url] = BaseOpenAIPluginClient(manifest_spec_client)
plugins[url] = BaseOpenAIPlugin(manifest_spec_client)
return plugins
@@ -197,7 +197,7 @@ def scan_plugins(cfg: Config, debug: bool = False) -> List[Tuple[str, Path]]:
if manifests_specs.keys():
manifests_specs_clients = initialize_openai_plugins(manifests_specs, cfg, debug)
for url, openai_plugin_meta in manifests_specs_clients.items():
plugin = BaseOpenAIPluginClient(openai_plugin_meta)
plugin = BaseOpenAIPlugin(openai_plugin_meta)
plugins.append((plugin, url))
return plugins

View File

@@ -0,0 +1,61 @@
import pytest
from typing import Any, Dict, List, Optional, Tuple
from autogpt.models.base_open_ai_plugin import BaseOpenAIPlugin, Message, PromptGenerator
class DummyPlugin(BaseOpenAIPlugin):
pass
@pytest.fixture
def dummy_plugin():
manifests_specs_clients = {
"manifest": {
"name_for_model": "Dummy",
"schema_version": "1.0",
"description_for_model": "A dummy plugin for testing purposes"
},
"client": None,
"openapi_spec": None
}
return DummyPlugin(manifests_specs_clients)
def test_dummy_plugin_inheritance(dummy_plugin):
assert isinstance(dummy_plugin, BaseOpenAIPlugin)
def test_dummy_plugin_name(dummy_plugin):
assert dummy_plugin._name == "Dummy"
def test_dummy_plugin_version(dummy_plugin):
assert dummy_plugin._version == "1.0"
def test_dummy_plugin_description(dummy_plugin):
assert dummy_plugin._description == "A dummy plugin for testing purposes"
def test_dummy_plugin_default_methods(dummy_plugin):
assert not dummy_plugin.can_handle_on_response()
assert not dummy_plugin.can_handle_post_prompt()
assert not dummy_plugin.can_handle_on_planning()
assert not dummy_plugin.can_handle_post_planning()
assert not dummy_plugin.can_handle_pre_instruction()
assert not dummy_plugin.can_handle_on_instruction()
assert not dummy_plugin.can_handle_post_instruction()
assert not dummy_plugin.can_handle_pre_command()
assert not dummy_plugin.can_handle_post_command()
assert not dummy_plugin.can_handle_chat_completion(None, None, None, None)
assert dummy_plugin.on_response(None) is None
assert dummy_plugin.post_prompt(None) is None
assert dummy_plugin.on_planning(None, None) is None
assert dummy_plugin.post_planning(None) is None
assert dummy_plugin.pre_instruction(None) is None
assert dummy_plugin.on_instruction(None) is None
assert dummy_plugin.post_instruction(None) is None
assert dummy_plugin.pre_command(None, None) is None
assert dummy_plugin.post_command(None, None) is None
assert dummy_plugin.handle_chat_completion(None, None, None, None) is None

View File

@@ -0,0 +1,222 @@
import json
import os
import tempfile
import zipfile
from pathlib import Path
from urllib.parse import urlparse
from unittest.mock import MagicMock, patch
import pytest
from autogpt.plugins import create_directory_if_not_exists, inspect_zip_for_module, load_plugins, \
blacklist_whitelist_check, instantiate_openai_plugin_clients, scan_plugins, fetch_openai_plugins_manifest_and_spec, \
initialize_openai_plugins
PLUGINS_TEST_DIR = "tests/unit/data/test_plugins"
PLUGIN_TEST_ZIP_FILE = "Auto-GPT-Plugin-Test-master.zip"
PLUGIN_TEST_INIT_PY = "Auto-GPT-Plugin-Test-master/src/auto_gpt_plugin_template/__init__.py"
def test_inspect_zip_for_module():
with tempfile.TemporaryDirectory() as temp_dir:
zip_path = os.path.join(temp_dir, "sample.zip")
with zipfile.ZipFile(zip_path, "w") as zf:
zf.writestr("test_module/__init__.py", "")
result = plugins.inspect_zip_for_module(zip_path)
assert result == "test_module/__init__.py"
result = plugins.inspect_zip_for_module(zip_path, debug=True)
assert result == "test_module/__init__.py"
with zipfile.ZipFile(zip_path, "w") as zf:
zf.writestr("not_a_module.py", "")
result = plugins.inspect_zip_for_module(zip_path)
assert result is None
def test_write_dict_to_json_file():
with tempfile.NamedTemporaryFile(mode="w+", delete=False) as file:
test_data = {"test_key": "test_value"}
plugins.write_dict_to_json_file(test_data, file.name)
file.seek(0)
loaded_data = json.load(file)
assert loaded_data == test_data
def test_create_directory_if_not_exists():
with tempfile.TemporaryDirectory() as temp_dir:
new_dir = os.path.join(temp_dir, "test_dir")
assert not os.path.exists(new_dir)
result = create_directory_if_not_exists(new_dir)
assert result is True
assert os.path.exists(new_dir)
result = create_directory_if_not_exists(new_dir)
assert result is True
@pytest.fixture
def config_mock():
config = MagicMock()
config.plugins_dir = "/plugins"
config.plugins_openai = []
return config
@patch("autogpt.plugins.write_dict_to_json_file")
@patch("requests.get")
@patch("autogpt.plugins.create_directory_if_not_exists")
def test_fetch_openai_plugins_manifest_and_spec(create_directory_mock, write_dict_mock, requests_get_mock, config_mock):
requests_get_mock.side_effect = [
MagicMock(status_code=200, json=lambda: {
"schema_version": "v1",
"api": {"type": "openapi", "url": "http://example.com/openapi.json"}
}),
MagicMock(status_code=404),
]
config_mock.plugins_openai = ["http://example.com"]
result = fetch_openai_plugins_manifest_and_spec(config_mock)
assert len(result) == 1
assert "http://example.com" in result
assert "manifest" in result["http://example.com"]
assert "openapi_spec" in result["http://example.com"]
create_directory_mock.assert_called_once()
write_dict_mock.assert_called_once()
requests_get_mock.assert_has_calls([
patch("requests.get", args=("http://example.com/.well-known/ai-plugin.json",)),
patch("requests.get", args=("http://example.com/openapi.json",)),
])
# @patch("BaseOpenAIPlugin")
# def test_instantiate_openai_plugin_clients(base_openai_plugin_client_mock, config_mock):
# manifests_specs_clients = {
# "http://example.com": {
# "manifest": {},
# "openapi_spec": {},
# "client": MagicMock(),
# }
# }
#
# result = instantiate_openai_plugin_clients(manifests_specs_clients, config_mock)
# assert len(result) == 1
def test_scan_plugins(config_mock):
with patch("inspect_zip_for_module", return_value="test_module/__init__.py"):
plugins = scan_plugins(config_mock)
assert len(plugins) == 0
# @patch("BaseOpenAIPlugin")
# def test_initialize_openai_plugins(base_openai_plugin_client_mock, config_mock):
# manifests_specs = {
# "http://example.com": {
# "manifest": {},
# "openapi_spec": {},
# }
# }
#
# with patch("Path.cwd") as cwd_mock:
# cwd_mock.return_value = Path("/fake_cwd")
# result = initialize_openai_plugins(manifests_specs, config_mock)
# assert len(result) == 1
# assert "http://example.com" in result
# assert "client" in result["http://example.com"]
def test_blacklist_whitelist_check(config_mock):
class Plugin1(MagicMock):
__name__ = "Plugin1"
class Plugin2(MagicMock):
__name__ = "Plugin2"
config_mock.plugins_blacklist = ["Plugin1"]
config_mock.plugins_whitelist = ["Plugin2"]
plugins = [Plugin1, Plugin2]
result = blacklist_whitelist_check(plugins, config_mock)
assert len(result) == 1
assert isinstance(result[0], Plugin2)
config_mock.plugins_blacklist = []
config_mock.plugins_whitelist = []
with patch("builtins.input", side_effect=["y", "n"]):
result = blacklist_whitelist_check(plugins, config_mock)
assert len(result) == 1
assert isinstance(result[0], Plugin1)
@patch("autogpt.plugins.scan_plugins")
@patch("autogpt.plugins.blacklist_whitelist_check")
def test_load_plugins(blacklist_whitelist_check_mock, scan_plugins_mock, config_mock):
load_plugins(cfg=config_mock, debug=True)
scan_plugins_mock.assert_called_once_with(config_mock)
blacklist_whitelist_check_mock.assert_called_once_with(scan_plugins_mock.return_value, config_mock)
def test_inspect_zip_for_module_no_init_py():
with patch("zipfile.ZipFile") as zip_mock:
zip_mock.return_value.__enter__.return_value.namelist.return_value = ["test_module/file1.py"]
result = inspect_zip_for_module("test_module.zip")
assert result is None
def test_create_directory_if_not_exists_error():
with patch("os.makedirs") as makedirs_mock:
makedirs_mock.side_effect = OSError("Error creating directory")
result = create_directory_if_not_exists("non_existent_dir")
assert result is False
def test_fetch_openai_plugins_manifest_and_spec_invalid_manifest():
with patch("requests.get") as get_mock:
get_mock.return_value.status_code = 200
get_mock.return_value.json.return_value = {
"schema_version": "v2",
"api": {"type": "openapi"},
}
config = MagicMock()
config.plugins_openai = ["http://example.com"]
result = fetch_openai_plugins_manifest_and_spec(config)
assert result == {}
# @patch("BaseOpenAIPlugin")
# def test_instantiate_openai_plugin_clients_invalid_input(base_openai_plugin_client_mock):
# with pytest.raises(TypeError):
# instantiate_openai_plugin_clients("invalid_input", MagicMock())
def test_scan_plugins_invalid_config():
with pytest.raises(AttributeError):
scan_plugins("invalid_config")
def test_blacklist_whitelist_check_invalid_plugins_input():
with pytest.raises(TypeError):
blacklist_whitelist_check("invalid_plugins_input", MagicMock())
def test_blacklist_whitelist_check_invalid_config_input():
with pytest.raises(TypeError):
blacklist_whitelist_check([], "invalid_config_input")
def test_load_plugins_invalid_config_input():
with pytest.raises(TypeError):
load_plugins("invalid_config_input")