mrs83 commited on
Commit
6a95a78
·
1 Parent(s): e60e679

add processing module tests

Browse files
Files changed (1) hide show
  1. tests/test_processing.py +124 -0
tests/test_processing.py ADDED
@@ -0,0 +1,124 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import pytest
2
+ from unittest.mock import MagicMock, patch
3
+
4
+ from blossomtune_gradio import processing
5
+
6
+
7
+ @pytest.fixture(autouse=True)
8
+ def reset_process_store():
9
+ """
10
+ Fixture that runs automatically for every test in this module.
11
+ It resets the process_store to its default state to ensure test isolation.
12
+ """
13
+ processing.process_store = {"superlink": None, "runner": None}
14
+ yield
15
+ # Teardown is not strictly necessary as it's reset at the start,
16
+ # but it's good practice.
17
+ processing.process_store = {"superlink": None, "runner": None}
18
+
19
+
20
+ @patch("blossomtune_gradio.processing.threading.Thread")
21
+ @patch(
22
+ "blossomtune_gradio.processing.shutil.which",
23
+ return_value="/fake/path/flower-superlink",
24
+ )
25
+ def test_start_superlink_success(mock_which, mock_thread):
26
+ """Verify that start_superlink successfully starts a thread."""
27
+ success, message = processing.start_superlink()
28
+
29
+ assert success is True
30
+ assert message == "Superlink process started."
31
+ mock_thread.assert_called_once()
32
+ # Check that the thread is targeting the run_process function
33
+ call_args = mock_thread.call_args
34
+ assert call_args.kwargs["target"] == processing.run_process
35
+ # Check that the command is correct
36
+ assert call_args.kwargs["args"][0] == ["/fake/path/flower-superlink", "--insecure"]
37
+
38
+
39
+ def test_start_superlink_already_running(mocker):
40
+ """Verify that start_superlink returns False if a process is already running."""
41
+ # Mock a running process
42
+ mock_process = MagicMock()
43
+ mock_process.poll.return_value = None # None means it's running
44
+ processing.process_store["superlink"] = mock_process
45
+
46
+ success, message = processing.start_superlink()
47
+ assert success is False
48
+ assert "already running" in message
49
+
50
+
51
+ @patch("blossomtune_gradio.processing.os.path.exists", return_value=True)
52
+ @patch("blossomtune_gradio.processing.sqlite3.connect")
53
+ @patch("blossomtune_gradio.processing.threading.Thread")
54
+ @patch("blossomtune_gradio.processing.shutil.which", return_value="/fake/path/flwr")
55
+ def test_start_runner_success(mock_which, mock_thread, mock_sqlite, mock_exists):
56
+ """Verify that start_runner successfully starts a thread when conditions are met."""
57
+ # Mock a running superlink process
58
+ mock_superlink = MagicMock()
59
+ mock_superlink.poll.return_value = None
60
+ processing.process_store["superlink"] = mock_superlink
61
+
62
+ success, message = processing.start_runner("app.main", "run1", "10")
63
+
64
+ assert success is True
65
+ assert message == "Federation Run is starting...."
66
+ mock_thread.assert_called_once()
67
+ mock_sqlite.assert_called_once() # Check if DB was updated
68
+
69
+
70
+ def test_start_runner_superlink_not_running():
71
+ """Verify start_runner fails if superlink is not running."""
72
+ processing.process_store["superlink"] = None
73
+ success, message = processing.start_runner("app.main", "run1", "10")
74
+ assert success is False
75
+ assert "Superlink is not running" in message
76
+
77
+
78
+ def test_start_runner_missing_args():
79
+ """Verify start_runner fails if arguments are missing."""
80
+ mock_superlink = MagicMock()
81
+ mock_superlink.poll.return_value = None
82
+ processing.process_store["superlink"] = mock_superlink
83
+
84
+ success, message = processing.start_runner("", "run1", "10")
85
+ assert success is False
86
+ assert "provide a Runner App" in message
87
+
88
+
89
+ @patch("blossomtune_gradio.processing.os.path.exists", return_value=False)
90
+ def test_start_runner_app_path_not_found(mock_exists):
91
+ """Verify start_runner fails if the app path doesn't exist."""
92
+ mock_superlink = MagicMock()
93
+ mock_superlink.poll.return_value = None
94
+ processing.process_store["superlink"] = mock_superlink
95
+
96
+ success, message = processing.start_runner("non.existent.app", "run1", "10")
97
+ assert success is False
98
+ assert "Unable to find app path" in message
99
+
100
+
101
+ def test_stop_process_running():
102
+ """Verify stop_process terminates a running process."""
103
+ mock_process = MagicMock()
104
+ mock_process.poll.return_value = None # Running
105
+ processing.process_store["superlink"] = mock_process
106
+
107
+ processing.stop_process("superlink")
108
+
109
+ mock_process.terminate.assert_called_once()
110
+ mock_process.wait.assert_called_once()
111
+ assert processing.process_store["superlink"] is None
112
+
113
+
114
+ def test_stop_process_not_running(mocker):
115
+ """Verify stop_process does nothing if the process is not running."""
116
+ log_mock = mocker.patch("blossomtune_gradio.processing.log")
117
+ processing.process_store["superlink"] = None
118
+
119
+ processing.stop_process("superlink")
120
+
121
+ # Check that the specific "no process was running" log was called
122
+ log_mock.assert_any_call(
123
+ "[Superlink] Stop command received, but no process was running."
124
+ )