mirror of
https://github.com/allaunthefox/Research-Stack.git
synced 2026-07-31 03:05:21 +00:00
379 lines
13 KiB
Python
379 lines
13 KiB
Python
# SPDX-License-Identifier: Apache-2.0
|
|
# Copyright (c) 2025 Allaun
|
|
|
|
"""Tests for nodupe/tools/network/network_plugin.py - NetworkTool."""
|
|
|
|
from unittest.mock import MagicMock, patch
|
|
|
|
import pytest
|
|
|
|
# Import directly from the plugin file to avoid __init__.py import chain issues
|
|
from nodupe.tools.network import network_plugin
|
|
|
|
NetworkTool = network_plugin.NetworkTool
|
|
register_tool = network_plugin.register_tool
|
|
|
|
|
|
class TestNetworkToolProperties:
|
|
"""Test NetworkTool properties."""
|
|
|
|
def test_name_property(self):
|
|
"""NetworkTool.name returns correct value."""
|
|
tool = NetworkTool()
|
|
assert tool.name == "network_tool"
|
|
|
|
def test_version_property(self):
|
|
"""NetworkTool.version returns correct value."""
|
|
tool = NetworkTool()
|
|
assert tool.version == "1.0.0"
|
|
|
|
def test_dependencies_property(self):
|
|
"""NetworkTool.dependencies returns empty list."""
|
|
tool = NetworkTool()
|
|
assert tool.dependencies == []
|
|
|
|
|
|
class TestNetworkToolInitialization:
|
|
"""Test NetworkTool initialization."""
|
|
|
|
def test_init_creates_manager(self):
|
|
"""NetworkTool initializes with a manager."""
|
|
tool = NetworkTool()
|
|
assert tool.manager is not None
|
|
|
|
def test_api_methods_property(self):
|
|
"""NetworkTool.api_methods returns correct methods."""
|
|
tool = NetworkTool()
|
|
api_methods = tool.api_methods
|
|
|
|
assert 'upload_file' in api_methods
|
|
assert 'download_file' in api_methods
|
|
assert 'list_files' in api_methods
|
|
assert 'delete_file' in api_methods
|
|
|
|
# Verify they are bound to manager methods
|
|
assert api_methods['upload_file'] == tool.manager.upload_file
|
|
assert api_methods['download_file'] == tool.manager.download_file
|
|
assert api_methods['list_files'] == tool.manager.list_files
|
|
assert api_methods['delete_file'] == tool.manager.delete_file
|
|
|
|
def test_api_methods_are_callable(self):
|
|
"""NetworkTool.api_methods returns callable methods."""
|
|
tool = NetworkTool()
|
|
api_methods = tool.api_methods
|
|
|
|
assert callable(api_methods['upload_file'])
|
|
assert callable(api_methods['download_file'])
|
|
assert callable(api_methods['list_files'])
|
|
assert callable(api_methods['delete_file'])
|
|
|
|
|
|
class TestNetworkToolInitialize:
|
|
"""Test NetworkTool.initialize() method."""
|
|
|
|
def test_initialize_registers_service(self):
|
|
"""initialize() registers network_manager service."""
|
|
tool = NetworkTool()
|
|
container = MagicMock()
|
|
|
|
tool.initialize(container)
|
|
|
|
container.register_service.assert_called_once_with('network_manager', tool.manager)
|
|
|
|
def test_initialize_with_mock_container(self):
|
|
"""initialize() works with mock container."""
|
|
tool = NetworkTool()
|
|
container = MagicMock()
|
|
container.register_service = MagicMock()
|
|
|
|
tool.initialize(container)
|
|
|
|
assert container.register_service.called
|
|
|
|
def test_initialize_preserves_manager(self):
|
|
"""initialize() preserves the manager reference."""
|
|
tool = NetworkTool()
|
|
container = MagicMock()
|
|
original_manager = tool.manager
|
|
|
|
tool.initialize(container)
|
|
|
|
assert tool.manager is original_manager
|
|
|
|
|
|
class TestNetworkToolShutdown:
|
|
"""Test NetworkTool.shutdown() method."""
|
|
|
|
def test_shutdown_no_error(self):
|
|
"""shutdown() completes without error."""
|
|
tool = NetworkTool()
|
|
# Should not raise
|
|
tool.shutdown()
|
|
|
|
def test_shutdown_multiple_times(self):
|
|
"""shutdown() can be called multiple times without error."""
|
|
tool = NetworkTool()
|
|
tool.shutdown()
|
|
tool.shutdown() # Should not raise
|
|
|
|
def test_shutdown_before_initialize(self):
|
|
"""shutdown() works even if initialize was not called."""
|
|
tool = NetworkTool()
|
|
tool.shutdown() # Should not raise
|
|
|
|
|
|
class TestNetworkToolGetCapabilities:
|
|
"""Test NetworkTool.get_capabilities() method."""
|
|
|
|
def test_get_capabilities_returns_dict(self):
|
|
"""get_capabilities() returns a dictionary with expected keys."""
|
|
tool = NetworkTool()
|
|
capabilities = tool.get_capabilities()
|
|
|
|
assert isinstance(capabilities, dict)
|
|
assert 'storage_backend' in capabilities
|
|
assert 'available' in capabilities
|
|
|
|
def test_get_capabilities_storage_backend(self):
|
|
"""get_capabilities() returns string for storage_backend."""
|
|
tool = NetworkTool()
|
|
capabilities = tool.get_capabilities()
|
|
|
|
assert isinstance(capabilities['storage_backend'], str)
|
|
# Should be either LocalStorageBackend or S3StorageBackend depending on availability
|
|
assert capabilities['storage_backend'] in ['LocalStorageBackend', 'S3StorageBackend']
|
|
|
|
def test_get_capabilities_available(self):
|
|
"""get_capabilities() returns True for available."""
|
|
tool = NetworkTool()
|
|
capabilities = tool.get_capabilities()
|
|
|
|
assert capabilities['available'] is True
|
|
|
|
def test_get_capabilities_with_mocked_manager(self):
|
|
"""get_capabilities() uses manager info correctly."""
|
|
tool = NetworkTool()
|
|
mock_storage = MagicMock()
|
|
mock_storage.__class__.__name__ = 'MockStorageBackend'
|
|
tool.manager.storage_backend = mock_storage
|
|
|
|
capabilities = tool.get_capabilities()
|
|
|
|
assert capabilities['storage_backend'] == 'MockStorageBackend'
|
|
|
|
|
|
class TestRegisterTool:
|
|
"""Test register_tool() function."""
|
|
|
|
def test_register_tool_returns_network_tool(self):
|
|
"""register_tool() returns a NetworkTool instance."""
|
|
tool = register_tool()
|
|
assert isinstance(tool, NetworkTool)
|
|
|
|
def test_register_tool_creates_new_instance(self):
|
|
"""register_tool() creates a new instance each call."""
|
|
tool1 = register_tool()
|
|
tool2 = register_tool()
|
|
assert tool1 is not tool2
|
|
|
|
def test_register_tool_properties(self):
|
|
"""register_tool() returns tool with correct properties."""
|
|
tool = register_tool()
|
|
assert tool.name == "network_tool"
|
|
assert tool.version == "1.0.0"
|
|
assert tool.dependencies == []
|
|
|
|
|
|
class TestNetworkToolDescribeUsage:
|
|
"""Test NetworkTool.describe_usage() method."""
|
|
|
|
def test_describe_usage_returns_string(self):
|
|
"""describe_usage() returns a string."""
|
|
tool = NetworkTool()
|
|
description = tool.describe_usage()
|
|
|
|
assert isinstance(description, str)
|
|
assert "network" in description.lower() or "storage" in description.lower()
|
|
|
|
def test_describe_usage_mentions_s3(self):
|
|
"""describe_usage() mentions S3 support."""
|
|
tool = NetworkTool()
|
|
description = tool.describe_usage()
|
|
|
|
assert "s3" in description.lower()
|
|
|
|
def test_describe_usage_mentions_local(self):
|
|
"""describe_usage() mentions local filesystem."""
|
|
tool = NetworkTool()
|
|
description = tool.describe_usage()
|
|
|
|
assert "local" in description.lower()
|
|
|
|
def test_describe_usage_mentions_operations(self):
|
|
"""describe_usage() mentions file operations."""
|
|
tool = NetworkTool()
|
|
description = tool.describe_usage()
|
|
|
|
assert "upload" in description.lower() or "download" in description.lower()
|
|
|
|
|
|
class TestNetworkToolRunStandalone:
|
|
"""Test NetworkTool.run_standalone() method."""
|
|
|
|
def test_run_standalone_returns_zero(self, capsys):
|
|
"""run_standalone() returns 0 and prints output."""
|
|
tool = NetworkTool()
|
|
result = tool.run_standalone([])
|
|
|
|
assert result == 0
|
|
captured = capsys.readouterr()
|
|
assert "Network Tool: Self-test mode." in captured.out
|
|
assert "Storage backend:" in captured.out
|
|
assert "Available:" in captured.out
|
|
|
|
def test_run_standalone_with_args(self, capsys):
|
|
"""run_standalone() handles args parameter."""
|
|
tool = NetworkTool()
|
|
result = tool.run_standalone(['--verbose', '--test'])
|
|
|
|
assert result == 0
|
|
|
|
def test_run_standalone_empty_args(self, capsys):
|
|
"""run_standalone() works with empty args."""
|
|
tool = NetworkTool()
|
|
result = tool.run_standalone([])
|
|
|
|
assert result == 0
|
|
captured = capsys.readouterr()
|
|
assert "Network Tool: Self-test mode." in captured.out
|
|
|
|
def test_run_standalone_with_various_args(self, capsys):
|
|
"""run_standalone() handles various argument formats."""
|
|
tool = NetworkTool()
|
|
|
|
# Test with different argument formats
|
|
for args in [['--help'], ['-v'], ['test', 'arg1', 'arg2'], []]:
|
|
result = tool.run_standalone(args)
|
|
assert result == 0
|
|
|
|
|
|
class TestNetworkToolWithMockedManager:
|
|
"""Test NetworkTool with mocked manager for complete coverage."""
|
|
|
|
@patch('nodupe.tools.network.network_plugin.get_network_manager')
|
|
def test_with_mocked_s3_backend(self, mock_get_manager):
|
|
"""Test with mocked S3 backend."""
|
|
mock_manager = MagicMock()
|
|
mock_storage = MagicMock()
|
|
mock_storage.__class__.__name__ = 'S3StorageBackend'
|
|
mock_manager.storage_backend = mock_storage
|
|
mock_get_manager.return_value = mock_manager
|
|
|
|
tool = NetworkTool()
|
|
|
|
caps = tool.get_capabilities()
|
|
assert caps['storage_backend'] == 'S3StorageBackend'
|
|
assert caps['available'] is True
|
|
|
|
@patch('nodupe.tools.network.network_plugin.get_network_manager')
|
|
def test_with_mocked_local_backend(self, mock_get_manager):
|
|
"""Test with mocked Local backend."""
|
|
mock_manager = MagicMock()
|
|
mock_storage = MagicMock()
|
|
mock_storage.__class__.__name__ = 'LocalStorageBackend'
|
|
mock_manager.storage_backend = mock_storage
|
|
mock_get_manager.return_value = mock_manager
|
|
|
|
tool = NetworkTool()
|
|
|
|
caps = tool.get_capabilities()
|
|
assert caps['storage_backend'] == 'LocalStorageBackend'
|
|
|
|
@patch('nodupe.tools.network.network_plugin.get_network_manager')
|
|
def test_api_methods_call_manager(self, mock_get_manager):
|
|
"""Test that api_methods correctly call manager methods."""
|
|
mock_manager = MagicMock()
|
|
mock_storage = MagicMock()
|
|
mock_manager.storage_backend = mock_storage
|
|
mock_manager.upload_file.return_value = True
|
|
mock_manager.download_file.return_value = True
|
|
mock_manager.list_files.return_value = ['file1.txt']
|
|
mock_manager.delete_file.return_value = True
|
|
mock_get_manager.return_value = mock_manager
|
|
|
|
tool = NetworkTool()
|
|
|
|
# Test upload_file
|
|
tool.api_methods['upload_file']('local.txt', 'remote.txt')
|
|
mock_manager.upload_file.assert_called_once()
|
|
|
|
# Test download_file
|
|
tool.api_methods['download_file']('remote.txt', 'local.txt')
|
|
mock_manager.download_file.assert_called_once()
|
|
|
|
# Test list_files
|
|
tool.api_methods['list_files']('prefix')
|
|
mock_manager.list_files.assert_called_once()
|
|
|
|
# Test delete_file
|
|
tool.api_methods['delete_file']('remote.txt')
|
|
mock_manager.delete_file.assert_called_once()
|
|
|
|
|
|
class TestNetworkToolEdgeCases:
|
|
"""Test NetworkTool edge cases."""
|
|
|
|
@patch('nodupe.tools.network.network_plugin.get_network_manager')
|
|
def test_manager_raises_exception(self, mock_get_manager):
|
|
"""Test handling when manager raises exception."""
|
|
mock_manager = MagicMock()
|
|
mock_manager.storage_backend = MagicMock()
|
|
mock_manager.upload_file.side_effect = Exception("Upload error")
|
|
mock_get_manager.return_value = mock_manager
|
|
|
|
tool = NetworkTool()
|
|
|
|
with pytest.raises(Exception, match="Upload error"):
|
|
tool.manager.upload_file('local.txt', 'remote.txt')
|
|
|
|
@patch('nodupe.tools.network.network_plugin.get_network_manager')
|
|
def test_manager_returns_false(self, mock_get_manager):
|
|
"""Test handling when manager operations return False."""
|
|
mock_manager = MagicMock()
|
|
mock_storage = MagicMock()
|
|
mock_manager.storage_backend = mock_storage
|
|
mock_manager.upload_file.return_value = False
|
|
mock_manager.download_file.return_value = False
|
|
mock_manager.list_files.return_value = []
|
|
mock_manager.delete_file.return_value = False
|
|
mock_get_manager.return_value = mock_manager
|
|
|
|
tool = NetworkTool()
|
|
|
|
assert tool.manager.upload_file('local.txt', 'remote.txt') is False
|
|
assert tool.manager.download_file('remote.txt', 'local.txt') is False
|
|
assert tool.manager.list_files('prefix') == []
|
|
assert tool.manager.delete_file('remote.txt') is False
|
|
|
|
def test_tool_instantiation_multiple_times(self):
|
|
"""Test that multiple tool instances can be created."""
|
|
tool1 = NetworkTool()
|
|
tool2 = NetworkTool()
|
|
|
|
assert tool1 is not tool2
|
|
assert tool1.name == tool2.name
|
|
assert tool1.version == tool2.version
|
|
|
|
@patch('nodupe.tools.network.network_plugin.get_network_manager')
|
|
def test_manager_storage_backend_none(self, mock_get_manager):
|
|
"""Test handling when manager has no storage backend."""
|
|
mock_manager = MagicMock()
|
|
mock_manager.storage_backend = None
|
|
mock_get_manager.return_value = mock_manager
|
|
|
|
tool = NetworkTool()
|
|
|
|
# MagicMock returns 'NoneType' when accessing __class__.__name__ on None
|
|
caps = tool.get_capabilities()
|
|
assert caps['storage_backend'] == 'NoneType'
|
|
assert caps['available'] is True
|