|
1 | | -"""Tests for EXTENSIONS_REF environment variable support.""" |
| 1 | +"""Tests for EXTENSIONS_REF environment variable support. |
2 | 2 |
|
3 | | -import os |
4 | | -import sys |
5 | | -from unittest import mock |
| 3 | +These tests use subprocess to run each test in an isolated Python process, |
| 4 | +avoiding module state pollution that would affect other tests. |
| 5 | +""" |
6 | 6 |
|
| 7 | +import subprocess |
| 8 | +import sys |
7 | 9 |
|
8 | | -def test_extensions_ref_default(): |
9 | | - """PUBLIC_SKILLS_BRANCH should default to 'main' when EXTENSIONS_REF is not set.""" |
10 | | - # Clear EXTENSIONS_REF if set |
11 | | - with mock.patch.dict(os.environ, {}, clear=False): |
12 | | - if "EXTENSIONS_REF" in os.environ: |
13 | | - del os.environ["EXTENSIONS_REF"] |
14 | 10 |
|
15 | | - # Force reload of the module to pick up environment variable |
16 | | - if "openhands.sdk.context.skills.skill" in sys.modules: |
17 | | - del sys.modules["openhands.sdk.context.skills.skill"] |
| 11 | +def _run_in_subprocess(test_code: str, env_extra: dict | None = None) -> None: |
| 12 | + """Run test code in a subprocess with the given environment variables.""" |
| 13 | + import os |
18 | 14 |
|
19 | | - from openhands.sdk.context.skills.skill import PUBLIC_SKILLS_BRANCH |
| 15 | + env = os.environ.copy() |
| 16 | + if env_extra: |
| 17 | + env.update(env_extra) |
20 | 18 |
|
21 | | - assert PUBLIC_SKILLS_BRANCH == "main", ( |
22 | | - f"Expected 'main' but got '{PUBLIC_SKILLS_BRANCH}'" |
| 19 | + result = subprocess.run( |
| 20 | + [sys.executable, "-c", test_code], |
| 21 | + env=env, |
| 22 | + capture_output=True, |
| 23 | + text=True, |
| 24 | + ) |
| 25 | + if result.returncode != 0: |
| 26 | + raise AssertionError( |
| 27 | + f"Subprocess test failed:\nstdout: {result.stdout}\nstderr: {result.stderr}" |
23 | 28 | ) |
24 | 29 |
|
25 | 30 |
|
26 | | -def test_extensions_ref_custom_branch(): |
27 | | - """PUBLIC_SKILLS_BRANCH should use EXTENSIONS_REF when set.""" |
28 | | - # Set EXTENSIONS_REF |
29 | | - with mock.patch.dict(os.environ, {"EXTENSIONS_REF": "feature-branch"}, clear=False): |
30 | | - # Force reload of the module to pick up environment variable |
31 | | - if "openhands.sdk.context.skills.skill" in sys.modules: |
32 | | - del sys.modules["openhands.sdk.context.skills.skill"] |
| 31 | +def test_extensions_ref_default(): |
| 32 | + """PUBLIC_SKILLS_BRANCH should default to 'main' when EXTENSIONS_REF is not set.""" |
| 33 | + code = """ |
| 34 | +import os |
| 35 | +if "EXTENSIONS_REF" in os.environ: |
| 36 | + del os.environ["EXTENSIONS_REF"] |
| 37 | +from openhands.sdk.context.skills.skill import PUBLIC_SKILLS_BRANCH |
| 38 | +assert PUBLIC_SKILLS_BRANCH == "main", ( |
| 39 | + f"Expected 'main' but got '{PUBLIC_SKILLS_BRANCH}'" |
| 40 | +) |
| 41 | +""" |
| 42 | + _run_in_subprocess(code) |
33 | 43 |
|
34 | | - from openhands.sdk.context.skills.skill import PUBLIC_SKILLS_BRANCH |
35 | 44 |
|
36 | | - assert PUBLIC_SKILLS_BRANCH == "feature-branch", ( |
37 | | - f"Expected 'feature-branch' but got '{PUBLIC_SKILLS_BRANCH}'" |
38 | | - ) |
| 45 | +def test_extensions_ref_custom_branch(): |
| 46 | + """PUBLIC_SKILLS_BRANCH should use EXTENSIONS_REF when set.""" |
| 47 | + code = """ |
| 48 | +from openhands.sdk.context.skills.skill import PUBLIC_SKILLS_BRANCH |
| 49 | +assert PUBLIC_SKILLS_BRANCH == "feature-branch", ( |
| 50 | + f"Expected 'feature-branch' but got '{PUBLIC_SKILLS_BRANCH}'" |
| 51 | +) |
| 52 | +""" |
| 53 | + _run_in_subprocess(code, {"EXTENSIONS_REF": "feature-branch"}) |
39 | 54 |
|
40 | 55 |
|
41 | 56 | def test_extensions_ref_with_load_public_skills(): |
42 | 57 | """load_public_skills should respect EXTENSIONS_REF environment variable.""" |
43 | | - with mock.patch.dict(os.environ, {"EXTENSIONS_REF": "test-branch"}, clear=False): |
44 | | - # Force reload of the module |
45 | | - if "openhands.sdk.context.skills.skill" in sys.modules: |
46 | | - del sys.modules["openhands.sdk.context.skills.skill"] |
47 | | - |
48 | | - from openhands.sdk.context.skills.skill import ( |
49 | | - PUBLIC_SKILLS_BRANCH, |
50 | | - load_public_skills, |
51 | | - ) |
52 | | - |
53 | | - # Verify the constant is set correctly |
54 | | - assert PUBLIC_SKILLS_BRANCH == "test-branch" |
55 | | - |
56 | | - # Mock the actual git operations and verify branch is passed |
57 | | - with mock.patch( |
58 | | - "openhands.sdk.context.skills.skill.update_skills_repository" |
59 | | - ) as mock_update: |
60 | | - mock_update.return_value = ( |
61 | | - None # Simulate failed clone (expected behavior for test) |
62 | | - ) |
63 | | - |
64 | | - load_public_skills() |
65 | | - |
66 | | - # Verify the branch was passed to update_skills_repository |
67 | | - mock_update.assert_called_once() |
68 | | - call_args = mock_update.call_args |
69 | | - # branch is 2nd positional arg: (repo_url, branch, cache_dir) |
70 | | - assert call_args[0][1] == "test-branch", ( |
71 | | - f"Expected branch='test-branch' but got {call_args[0][1]}" |
72 | | - ) |
| 58 | + code = """ |
| 59 | +from unittest import mock |
| 60 | +from openhands.sdk.context.skills.skill import ( |
| 61 | + PUBLIC_SKILLS_BRANCH, |
| 62 | + load_public_skills, |
| 63 | +) |
| 64 | +assert PUBLIC_SKILLS_BRANCH == "test-branch", ( |
| 65 | + f"Expected 'test-branch' but got '{PUBLIC_SKILLS_BRANCH}'" |
| 66 | +) |
| 67 | +with mock.patch( |
| 68 | + "openhands.sdk.context.skills.skill.update_skills_repository" |
| 69 | +) as mock_update: |
| 70 | + mock_update.return_value = None |
| 71 | + load_public_skills() |
| 72 | + mock_update.assert_called_once() |
| 73 | + call_args = mock_update.call_args |
| 74 | + # branch is 2nd positional arg: (repo_url, branch, cache_dir) |
| 75 | + assert call_args[0][1] == "test-branch", ( |
| 76 | + f"Expected branch='test-branch' but got {call_args[0][1]}" |
| 77 | + ) |
| 78 | +""" |
| 79 | + _run_in_subprocess(code, {"EXTENSIONS_REF": "test-branch"}) |
73 | 80 |
|
74 | 81 |
|
75 | 82 | def test_extensions_ref_empty_string(): |
76 | 83 | """Empty EXTENSIONS_REF should fall back to 'main'.""" |
77 | | - with mock.patch.dict(os.environ, {"EXTENSIONS_REF": ""}, clear=False): |
78 | | - # Force reload of the module |
79 | | - if "openhands.sdk.context.skills.skill" in sys.modules: |
80 | | - del sys.modules["openhands.sdk.context.skills.skill"] |
81 | | - |
82 | | - from openhands.sdk.context.skills.skill import PUBLIC_SKILLS_BRANCH |
83 | | - |
84 | | - # Empty string should fall back to 'main' via os.environ.get default |
85 | | - assert PUBLIC_SKILLS_BRANCH == "", ( |
86 | | - "Empty EXTENSIONS_REF should result in empty string " |
87 | | - "(os.environ.get behavior)" |
88 | | - ) |
| 84 | + code = """ |
| 85 | +from openhands.sdk.context.skills.skill import PUBLIC_SKILLS_BRANCH |
| 86 | +# Empty string returns empty string per os.environ.get behavior |
| 87 | +assert PUBLIC_SKILLS_BRANCH == "", ( |
| 88 | + f"Expected '' but got '{PUBLIC_SKILLS_BRANCH}'" |
| 89 | +) |
| 90 | +""" |
| 91 | + _run_in_subprocess(code, {"EXTENSIONS_REF": ""}) |
0 commit comments