Rotary Logger  1.0.2
The middleware rotary logger
Loading...
Searching...
No Matches
test_control_functions.py
Go to the documentation of this file.
1"""
2# +==== BEGIN rotary_logger =================+
3# LOGO:
4# ..........####...####..........
5# ......###.....#.#########......
6# ....##........#.###########....
7# ...#..........#.############...
8# ...#..........#.#####.######...
9# ..#.....##....#.###..#...####..
10# .#.....#.##...#.##..##########.
11# #.....##########....##...######
12# #.....#...##..#.##..####.######
13# .#...##....##.#.##..###..#####.
14# ..#.##......#.#.####...######..
15# ..#...........#.#############..
16# ..#...........#.#############..
17# ...##.........#.############...
18# ......#.......#.#########......
19# .......#......#.########.......
20# .........#####...#####.........
21# /STOP
22# PROJECT: rotary_logger
23# FILE: test_control_functions.py
24# CREATION DATE: 02-11-2025
25# LAST Modified: 3:41:37 04-03-2026
26# DESCRIPTION:
27# A module that provides a universal python light on iops way of logging to files your program execution.
28# /STOP
29# COPYRIGHT: (c) Asperguide
30# PURPOSE: File in charge of testing the control functions that provide status and information.
31# // AR
32# +==== END rotary_logger =================+
33"""
34
35
36import sys
37import threading
38import time
39from concurrent.futures import ThreadPoolExecutor
40from pathlib import Path
41
42import pytest
43
44from rotary_logger.rotary_logger_cls import RotaryLogger
45
46
48 orig_out = sys.stdout
49 rl = RotaryLogger()
50 # start logging into tmp_path
51 rl.start_logging(log_folder=tmp_path, merged=False)
52
53 # After start, atexit handlers should be recorded
54 assert getattr(rl, "_atexit_registered", False) in (True, False)
55 # The registered flushers list should exist when registered
56 if rl._atexit_registered:
57 assert hasattr(rl, "_registered_flushers")
58 assert len(rl._registered_flushers) >= 1
59
60 # stop_logging should restore original stdout and unregister atexit handlers
61 rl.stop_logging()
62 assert sys.stdout is orig_out
63 assert getattr(rl, "_atexit_registered", False) is False
64
65
66def test_pause_and_resume_toggle(tmp_path: Path):
67 rl = RotaryLogger()
68 rl.start_logging(log_folder=tmp_path, merged=False)
69
70 # Initially logging should be active
71 assert rl.is_logging() is True
72
73 # Pause
74 paused = rl.pause_logging()
75 assert paused is True
76 # while paused, is_logging should be False
77 assert rl.is_logging() is False
78
79 # Resume
80 resumed = rl.resume_logging()
81 # resume_logging returns paused state (False)
82 assert resumed is False
83 assert rl.is_logging() is True
84
85 rl.stop_logging()
86
87
88def _toggle_pause_resume(rl: RotaryLogger, stop_event: threading.Event):
89 # Rapidly toggle pause/resume until stop_event is set
90 while not stop_event.is_set():
91 rl.pause_logging()
92 rl.resume_logging()
93
94
96 rl = RotaryLogger()
97 rl.start_logging(log_folder=tmp_path, merged=False)
98
99 stop_event = threading.Event()
100
101 # Start a few threads toggling pause/resume
102 threads = []
103 for _ in range(6):
104 t = threading.Thread(target=_toggle_pause_resume,
105 args=(rl, stop_event))
106 t.start()
107 threads.append(t)
108
109 # Meanwhile write some output to the current stdout for a short while
110 try:
111 for _ in range(100):
112 print("ping")
113 time.sleep(0.002)
114 finally:
115 # Stop the togglers
116 stop_event.set()
117 for t in threads:
118 t.join(timeout=1.0)
119
120 # Ensure no exceptions and logger remains in a valid state
121 assert isinstance(rl.is_logging(), bool)
122 rl.stop_logging()
123
124
126 """pause_logging(toggle=False) should always pause, even if already paused."""
127 rl = RotaryLogger()
128 rl.start_logging(log_folder=tmp_path, merged=False)
129 assert rl.is_logging()
130
131 # First call: running → pause
132 result = rl.pause_logging(toggle=False)
133 assert result is True
134
135 # Second call: already paused → still pause (idempotent)
136 result = rl.pause_logging(toggle=False)
137 assert result is True
138
139 rl.stop_logging()
140
141
143 """resume_logging(toggle=True) should pause when the logger is currently running."""
144 rl = RotaryLogger()
145 rl.start_logging(log_folder=tmp_path, merged=False)
146 assert rl.is_logging()
147
148 # toggle=True when active → should pause
149 result = rl.resume_logging(toggle=True)
150 assert result is True
151 assert not rl.is_logging()
152
153 rl.stop_logging()
154
155
157 """is_redirected() should return False before and after stop_logging, True during."""
158 from rotary_logger import constants as CONST
159
160 rl = RotaryLogger()
161 assert rl.is_redirected(CONST.StdMode.STDOUT) is False
162 assert rl.is_redirected(CONST.StdMode.STDERR) is False
163
164 rl.start_logging(log_folder=tmp_path, merged=False)
165 assert rl.is_redirected(CONST.StdMode.STDOUT) is True
166 assert rl.is_redirected(CONST.StdMode.STDERR) is True
167
168 rl.stop_logging()
169 assert rl.is_redirected(CONST.StdMode.STDOUT) is False
170 assert rl.is_redirected(CONST.StdMode.STDERR) is False
171
172
174 """Calling the RotaryLogger instance like a function should start logging."""
175 rl = RotaryLogger(default_log_folder=tmp_path)
176 orig_out = sys.stdout
177 try:
178 rl() # __call__ delegates to start_logging() with no args
179 assert rl.is_logging()
180 finally:
181 rl.stop_logging()
182 # Guard: ensure stdout is restored even on unexpected failure
183 if sys.stdout is not orig_out and not hasattr(sys.stdout, 'original_stream'):
184 sys.stdout = orig_out
185
186
188 """stop_logging should restore sys.stdin and clear stdin_stream."""
189 orig_in = sys.stdin
190 rl = RotaryLogger()
191 rl.start_logging(log_folder=tmp_path, merged=True)
192 assert rl.stdin_stream is not None
193
194 rl.stop_logging()
195 assert rl.stdin_stream is None
196 assert sys.stdin is orig_in
_toggle_pause_resume(RotaryLogger rl, threading.Event stop_event)
test_resume_logging_toggle_true_pauses_when_active(Path tmp_path)
test_is_redirected_reflects_logging_state(Path tmp_path)
test_start_stop_registers_and_unregisters_atexit(Path tmp_path)
test_pause_logging_toggle_false_always_pauses(Path tmp_path)
test_rotary_logger_callable_starts_logging(Path tmp_path)