1+ # Copyright (c) Microsoft Corporation. All rights reserved.
2+ # Licensed under the MIT License.
3+ """Unit tests for the change_cwd() context manager in lsp_utils."""
4+
5+ import logging
6+ import os
7+ import pathlib
8+ import sys
9+ from unittest .mock import patch
10+
11+ # Ensure bundled libs and tool are importable.
12+ _PROJECT_ROOT = pathlib .Path (__file__ ).parent .parent .parent .parent
13+ sys .path .insert (0 , os .fsdecode (_PROJECT_ROOT / "bundled" / "libs" ))
14+ sys .path .insert (0 , os .fsdecode (_PROJECT_ROOT / "bundled" / "tool" ))
15+
16+ import lsp_utils
17+
18+
19+ def test_change_cwd_happy_path (tmp_path ):
20+ """change_cwd switches to the requested directory and restores SERVER_CWD after."""
21+ original_cwd = os .getcwd ()
22+ target = str (tmp_path )
23+
24+ with lsp_utils .change_cwd (target ):
25+ inside_cwd = os .getcwd ()
26+
27+ assert os .path .normcase (inside_cwd ) == os .path .normcase (target )
28+ # After the context manager exits the working directory is restored.
29+ assert os .path .normcase (os .getcwd ()) == os .path .normcase (lsp_utils .SERVER_CWD )
30+
31+ # Restore for other tests.
32+ os .chdir (original_cwd )
33+
34+
35+ def test_change_cwd_permission_error_does_not_crash (caplog ):
36+ """When os.chdir raises PermissionError the body still runs, cwd is unchanged, and a warning is logged."""
37+ original_cwd = os .getcwd ()
38+ body_executed = False
39+
40+ with patch ("lsp_utils.os.chdir" , side_effect = PermissionError ("Access denied" )):
41+ with caplog .at_level (logging .WARNING ):
42+ with lsp_utils .change_cwd ("/restricted/path" ):
43+ body_executed = True
44+ # The working directory must not have changed.
45+ assert os .path .normcase (os .getcwd ()) == os .path .normcase (original_cwd )
46+
47+ assert body_executed
48+ # cwd is still the original after the context manager exits.
49+ assert os .path .normcase (os .getcwd ()) == os .path .normcase (original_cwd )
50+ # A warning must have been emitted mentioning the inaccessible path and the error.
51+ assert any ("/restricted/path" in r .message for r in caplog .records )
52+ assert any ("Access denied" in r .message for r in caplog .records )
53+
54+
55+ def test_change_cwd_oserror_does_not_crash (caplog ):
56+ """When os.chdir raises an arbitrary OSError the body still runs and a warning is logged."""
57+ original_cwd = os .getcwd ()
58+ body_executed = False
59+
60+ with patch ("lsp_utils.os.chdir" , side_effect = OSError ("Some OS error" )):
61+ with caplog .at_level (logging .WARNING ):
62+ with lsp_utils .change_cwd ("/inaccessible" ):
63+ body_executed = True
64+ assert os .path .normcase (os .getcwd ()) == os .path .normcase (original_cwd )
65+
66+ assert body_executed
67+ assert os .path .normcase (os .getcwd ()) == os .path .normcase (original_cwd )
68+ assert any ("/inaccessible" in r .message for r in caplog .records )
69+ assert any ("Some OS error" in r .message for r in caplog .records )
0 commit comments