Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Unittests #30

Merged
merged 7 commits into from
Dec 5, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
222 changes: 177 additions & 45 deletions tests/test_common.py
Original file line number Diff line number Diff line change
@@ -1,88 +1,220 @@
import os
import unittest
from pathlib import Path
from unittest.mock import MagicMock, patch
from unittest.mock import MagicMock, mock_open, patch

from lib.core_utils.common import YggdrasilUtilities


class TestYggdrasilUtilities(unittest.TestCase):

@patch("lib.utils.common.importlib.import_module")
def setUp(self):
# Backup original values
self.original_module_cache = YggdrasilUtilities.module_cache.copy()
self.original_config_dir = YggdrasilUtilities.CONFIG_DIR

# Reset module cache
YggdrasilUtilities.module_cache = {}

# Use a temporary config directory
self.temp_config_dir = Path("/tmp/yggdrasil_test_config")
self.temp_config_dir.mkdir(parents=True, exist_ok=True)
YggdrasilUtilities.CONFIG_DIR = self.temp_config_dir

def tearDown(self):
# Restore original values
YggdrasilUtilities.module_cache = self.original_module_cache
YggdrasilUtilities.CONFIG_DIR = self.original_config_dir

# Clean up temporary config directory
for item in self.temp_config_dir.glob("*"):
item.unlink()
self.temp_config_dir.rmdir()

@patch("importlib.import_module")
def test_load_realm_class_success(self, mock_import_module):
# Mock successful class loading
# Mock module and class
mock_module = MagicMock()
mock_class = MagicMock()
setattr(mock_module, "MockClass", mock_class)
mock_import_module.return_value = mock_module
mock_module.MyClass = mock_class

result = YggdrasilUtilities.load_realm_class("my_module.MyClass")
module_path = "some.module.MockClass"
result = YggdrasilUtilities.load_realm_class(module_path)

mock_import_module.assert_called_once_with("my_module")
self.assertEqual(result, mock_class)
self.assertIn(module_path, YggdrasilUtilities.module_cache)
mock_import_module.assert_called_with("some.module")

@patch("importlib.import_module")
def test_load_realm_class_module_not_found(self, mock_import_module):
# Simulate ImportError
mock_import_module.side_effect = ImportError("Module not found")

module_path = "nonexistent.module.ClassName"
result = YggdrasilUtilities.load_realm_class(module_path)

self.assertIsNone(result)
mock_import_module.assert_called_with("nonexistent.module")

@patch("lib.utils.common.importlib.import_module")
def test_load_realm_class_failure(self, mock_import_module):
# Mock import error
mock_import_module.side_effect = ImportError()
@patch("importlib.import_module")
def test_load_realm_class_attribute_error(self, mock_import_module):
# Module exists but class does not
mock_module = MagicMock()
mock_import_module.return_value = mock_module

result = YggdrasilUtilities.load_realm_class("non_existent_module.MyClass")
module_path = "some.module.MissingClass"
result = YggdrasilUtilities.load_realm_class(module_path)

mock_import_module.assert_called_once_with("non_existent_module")
self.assertIsNone(result)
mock_import_module.assert_called_with("some.module")

@patch("lib.utils.common.importlib.import_module")
@patch("importlib.import_module")
def test_load_module_success(self, mock_import_module):
# Mock successful module loading
# Mock module
mock_module = MagicMock()
mock_import_module.return_value = mock_module

result = YggdrasilUtilities.load_module("my_module")
module_path = "some.module"
result = YggdrasilUtilities.load_module(module_path)

mock_import_module.assert_called_once_with("my_module")
self.assertEqual(result, mock_module)
self.assertIn(module_path, YggdrasilUtilities.module_cache)
mock_import_module.assert_called_with("some.module")

@patch("lib.utils.common.importlib.import_module")
def test_load_module_failure(self, mock_import_module):
# Mock import error
mock_import_module.side_effect = ImportError()
@patch("importlib.import_module")
def test_load_module_import_error(self, mock_import_module):
# Simulate ImportError
mock_import_module.side_effect = ImportError("Module not found")

result = YggdrasilUtilities.load_module("non_existent_module")
module_path = "nonexistent.module"
result = YggdrasilUtilities.load_module(module_path)

mock_import_module.assert_called_once_with("non_existent_module")
self.assertIsNone(result)
mock_import_module.assert_called_with("nonexistent.module")

@patch("lib.utils.common.Path.exists")
def test_get_path_file_exists(self, mock_exists):
# Your input needed: Adjust the file path according to your project structure
mock_exists.return_value = True
expected_path = Path(
"/home/anastasios/Documents/git/Yggdrasil/yggdrasil_workspace/common/configurations/config.json"
) # Replace with actual expected path

result = YggdrasilUtilities.get_path("config.json")
def test_get_path_file_exists(self):
# Create a dummy config file
file_name = "config.yaml"
test_file = self.temp_config_dir / file_name
test_file.touch()

self.assertIsNotNone(result)
self.assertEqual(result, expected_path)
result = YggdrasilUtilities.get_path(file_name)

@patch("lib.utils.common.Path.exists")
def test_get_path_file_not_exists(self, mock_exists):
mock_exists.return_value = False
self.assertEqual(result, test_file)

result = YggdrasilUtilities.get_path("config.json")
def test_get_path_file_not_exists(self):
file_name = "missing_config.yaml"
result = YggdrasilUtilities.get_path(file_name)

self.assertIsNone(result)

@patch.dict("lib.utils.common.os.environ", {"MY_VAR": "value"})
def test_env_variable_exists(self):
result = YggdrasilUtilities.env_variable("MY_VAR")
self.assertEqual(result, "value")
with patch.dict(os.environ, {"TEST_ENV_VAR": "test_value"}):
result = YggdrasilUtilities.env_variable("TEST_ENV_VAR")
self.assertEqual(result, "test_value")

def test_env_variable_not_exists_with_default(self):
result = YggdrasilUtilities.env_variable(
"NONEXISTENT_ENV_VAR", default="default_value"
)
self.assertEqual(result, "default_value")

def test_env_variable_not_exists_no_default(self):
result = YggdrasilUtilities.env_variable("NONEXISTENT_ENV_VAR")
self.assertIsNone(result)

@patch("builtins.open", new_callable=mock_open, read_data="123")
def test_get_last_processed_seq_file_exists(self, mock_file):
seq_file = self.temp_config_dir / ".last_processed_seq"
seq_file.touch()

with patch.object(YggdrasilUtilities, "get_path", return_value=seq_file):
result = YggdrasilUtilities.get_last_processed_seq()

self.assertEqual(result, "123")

def test_get_last_processed_seq_file_not_exists(self):
with patch.object(YggdrasilUtilities, "get_path", return_value=None):
result = YggdrasilUtilities.get_last_processed_seq()
self.assertEqual(result, "0") # Default value as per method

@patch("builtins.open", new_callable=mock_open)
def test_save_last_processed_seq_success(self, mock_file):
seq_file = self.temp_config_dir / ".last_processed_seq"

with patch.object(YggdrasilUtilities, "get_path", return_value=seq_file):
YggdrasilUtilities.save_last_processed_seq("456")

mock_file.assert_called_with(seq_file, "w")
mock_file().write.assert_called_with("456")

def test_save_last_processed_seq_no_seq_file(self):
with patch.object(YggdrasilUtilities, "get_path", return_value=None):
# Should handle gracefully
YggdrasilUtilities.save_last_processed_seq("789")

def test_module_cache_persistence(self):
# Mock module
mock_module = MagicMock()
with patch("importlib.import_module", return_value=mock_module) as mock_import:
module_path = "some.module"

# First call
result1 = YggdrasilUtilities.load_module(module_path)
# Second call should use cache
result2 = YggdrasilUtilities.load_module(module_path)

self.assertEqual(result1, result2)
mock_import.assert_called_once_with("some.module")

@patch("builtins.open", new_callable=mock_open, read_data="")
def test_get_last_processed_seq_empty_file(self, mock_file):
seq_file = self.temp_config_dir / ".last_processed_seq"
seq_file.touch()

with patch.object(YggdrasilUtilities, "get_path", return_value=seq_file):
result = YggdrasilUtilities.get_last_processed_seq()

self.assertEqual(result, "0") # Assumes default when file is empty

@patch("builtins.open", new_callable=mock_open, read_data="abc")
def test_get_last_processed_seq_invalid_content(self, mock_file):
seq_file = self.temp_config_dir / ".last_processed_seq"
seq_file.touch()

with patch.object(YggdrasilUtilities, "get_path", return_value=seq_file):
result = YggdrasilUtilities.get_last_processed_seq()

self.assertEqual(result, "abc") # Returns content as-is

@patch("builtins.open", side_effect=Exception("File error"))
def test_get_last_processed_seq_file_error(self, mock_file):
seq_file = self.temp_config_dir / ".last_processed_seq"

with patch.object(YggdrasilUtilities, "get_path", return_value=seq_file):
result = YggdrasilUtilities.get_last_processed_seq()
self.assertEqual(result, "0") # Should handle exception and return default

@patch("builtins.open", side_effect=Exception("File error"))
def test_save_last_processed_seq_file_error(self, mock_file):
seq_file = self.temp_config_dir / ".last_processed_seq"

with patch.object(YggdrasilUtilities, "get_path", return_value=seq_file):
# Should handle exception gracefully
YggdrasilUtilities.save_last_processed_seq("123")

@patch.dict("lib.utils.common.os.environ", {}, clear=True)
def test_env_variable_not_exists(self):
result = YggdrasilUtilities.env_variable("MY_VAR", default="default")
self.assertEqual(result, "default")
def test_get_path_with_relative_file_name(self):
# Use relative path components in file name
file_name = "../outside_config.yaml"
result = YggdrasilUtilities.get_path(file_name)
self.assertIsNone(result) # Should not allow navigating outside config dir

# TODO: Additional test cases or scenarios
def test_get_path_with_absolute_file_name(self):
# Use absolute path
file_name = "/etc/passwd"
result = YggdrasilUtilities.get_path(file_name)
self.assertIsNone(result) # Should not allow absolute paths


if __name__ == "__main__":
Expand Down
Loading
Loading