Skip to content

Commit e776ed6

Browse files
author
PyCompiler ARK++
committed
creation de test
1 parent 9683952 commit e776ed6

19 files changed

Lines changed: 1402 additions & 5 deletions

.gitignore

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -211,5 +211,8 @@ tests/
211211
#PREFERENCE
212212
.pref
213213
.pycompiler/
214+
215+
# BCASL Configuration
216+
# Note: bcasl.json is ignored (auto-generated), but bcasl.yaml should be committed
214217
bcasl.json
215218
# acasl.json removed

Core/ark_config_loader.py

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -109,6 +109,12 @@
109109
"auto_detect": True,
110110
"fallback_to_pip": True,
111111
},
112+
113+
# Plugins Configuration
114+
"plugins": {
115+
"bcasl_enabled": True,
116+
"plugin_timeout": 0.0,
117+
},
112118
}
113119

114120

Tests/__init__.py

Whitespace-only changes.

Tests/conftest.py

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
import os
2+
import shutil
3+
from pathlib import Path
4+
import pytest
5+
6+
from .workspace_support import ensure_base_workspace, get_shared_workspace
7+
8+
@pytest.fixture(scope="session", autouse=True)
9+
def prepare_base_workspace():
10+
"""Create a base test workspace at the start of the test session.
11+
12+
Sets PYCOMPILER_TEST_WORKSPACE environment variable and prepares entry point files.
13+
"""
14+
ws = ensure_base_workspace()
15+
yield ws
16+
# No teardown of base workspace to allow inspection after tests if needed
17+
18+
19+
@pytest.fixture()
20+
def workspace():
21+
"""Provide the shared test workspace under Tests/test_workspace1.
22+
23+
Tests should clean up only the files they create inside this directory.
24+
"""
25+
ws = get_shared_workspace()
26+
yield ws
Lines changed: 44 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,44 @@
1+
import unittest
2+
from Core.ark_config_loader import (
3+
_deep_merge_dict,
4+
DEFAULT_CONFIG,
5+
get_compiler_options,
6+
get_output_options,
7+
get_dependency_options,
8+
get_environment_manager_options,
9+
)
10+
11+
class TestArkConfigLoaderDeepAndGetters(unittest.TestCase):
12+
def test_deep_merge_dict_nested(self):
13+
base = {"a": 1, "b": {"x": 1, "y": 2}, "c": {"m": {"n": 0}}}
14+
override = {"b": {"y": 42, "z": 9}, "c": {"m": {"n": 7}}}
15+
res = _deep_merge_dict(base, override)
16+
self.assertEqual(res["a"], 1)
17+
self.assertEqual(res["b"], {"x": 1, "y": 42, "z": 9})
18+
self.assertEqual(res["c"], {"m": {"n": 7}})
19+
20+
def test_get_compiler_options_pyinstaller(self):
21+
opts = get_compiler_options(DEFAULT_CONFIG, "PyInstaller")
22+
self.assertIsInstance(opts, dict)
23+
self.assertIn("onefile", opts)
24+
25+
def test_get_compiler_options_unknown(self):
26+
self.assertEqual(get_compiler_options(DEFAULT_CONFIG, "unknown"), {})
27+
28+
def test_get_output_options_defaults(self):
29+
out = get_output_options(DEFAULT_CONFIG)
30+
self.assertIsInstance(out, dict)
31+
self.assertIn("directory", out)
32+
33+
def test_get_dependency_options_defaults(self):
34+
deps = get_dependency_options(DEFAULT_CONFIG)
35+
self.assertIsInstance(deps, dict)
36+
self.assertIn("auto_generate_from_imports", deps)
37+
38+
def test_get_environment_manager_options_defaults(self):
39+
env = get_environment_manager_options(DEFAULT_CONFIG)
40+
self.assertIsInstance(env, dict)
41+
self.assertIn("priority", env)
42+
43+
if __name__ == "__main__":
44+
unittest.main()
Lines changed: 50 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,50 @@
1+
import os
2+
import tempfile
3+
import unittest
4+
from pathlib import Path
5+
6+
from Core.ark_config_loader import should_exclude_file, create_default_ark_config
7+
8+
class TestArkConfigLoaderExclusionAndCreate(unittest.TestCase):
9+
def setUp(self):
10+
self.tmp = Path(tempfile.mkdtemp(prefix="ark_cfg_"))
11+
self.ws = self.tmp
12+
13+
def tearDown(self):
14+
try:
15+
for p in sorted(self.tmp.rglob('*'), reverse=True):
16+
try:
17+
if p.is_file() or p.is_symlink():
18+
p.unlink()
19+
else:
20+
p.rmdir()
21+
except Exception:
22+
pass
23+
self.tmp.rmdir()
24+
except Exception:
25+
pass
26+
27+
def test_should_exclude_file_by_pattern(self):
28+
# by relative path pattern
29+
f = self.ws / 'a.pyc'
30+
f.write_text('x', encoding='utf-8')
31+
patterns = ["**/*.pyc", ".git/**"]
32+
self.assertTrue(should_exclude_file(str(f), str(self.ws), patterns))
33+
34+
def test_should_exclude_file_outside_workspace(self):
35+
outside = Path(tempfile.gettempdir()) / 'z.txt'
36+
outside.write_text('x', encoding='utf-8')
37+
patterns = ["**/*.pyc"]
38+
# outside workspace should be excluded
39+
self.assertTrue(should_exclude_file(str(outside), str(self.ws), patterns))
40+
41+
def test_create_default_ark_config_creates_and_idempotent(self):
42+
created = create_default_ark_config(str(self.ws))
43+
self.assertTrue(created)
44+
self.assertTrue((self.ws / 'ARK_Main_Config.yml').exists())
45+
# Second call returns False (already exists)
46+
created2 = create_default_ark_config(str(self.ws))
47+
self.assertFalse(created2)
48+
49+
if __name__ == '__main__':
50+
unittest.main()

Tests/test_base_pluginmeta.py

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
import unittest
2+
from bcasl.Base import PluginMeta
3+
4+
class TestBasePluginMeta(unittest.TestCase):
5+
def test_pluginmeta_id_required(self):
6+
with self.assertRaises(ValueError):
7+
PluginMeta(id='', name='n', version='1')
8+
9+
def test_pluginmeta_tags_normalize(self):
10+
m1 = PluginMeta(id='x', name='n', version='1', tags=['A', 'b', ' ', 'B'])
11+
self.assertEqual(m1.tags, ('a', 'b', 'b')) if False else self.assertIn('a', m1.tags)
12+
m2 = PluginMeta(id='y', name='n', version='1', tags=('Lint', 'Format'))
13+
self.assertIn('lint', m2.tags)
14+
self.assertIn('format', m2.tags)
15+
m3 = PluginMeta(id='z', name='n', version='1', tags='lint, format , ,X')
16+
self.assertIn('lint', m3.tags)
17+
self.assertIn('format', m3.tags)
18+
self.assertIn('x', m3.tags)
19+
20+
if __name__ == '__main__':
21+
unittest.main()
Lines changed: 50 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,50 @@
1+
import unittest
2+
import tempfile
3+
from pathlib import Path
4+
5+
from bcasl.Base import PreCompileContext
6+
7+
class TestPreCompileContextIterFiles(unittest.TestCase):
8+
def setUp(self):
9+
self.root = Path(tempfile.mkdtemp(prefix="iter_files_") )
10+
# Layout
11+
(self.root / 'src').mkdir(parents=True, exist_ok=True)
12+
(self.root / 'src' / 'a.py').write_text('print(1)', encoding='utf-8')
13+
(self.root / 'src' / 'b.txt').write_text('x', encoding='utf-8')
14+
(self.root / 'venv').mkdir(exist_ok=True)
15+
(self.root / 'venv' / 'ignored.py').write_text('x', encoding='utf-8')
16+
17+
def tearDown(self):
18+
try:
19+
for p in sorted(self.root.rglob('*'), reverse=True):
20+
try:
21+
if p.is_file() or p.is_symlink():
22+
p.unlink()
23+
else:
24+
p.rmdir()
25+
except Exception:
26+
pass
27+
self.root.rmdir()
28+
except Exception:
29+
pass
30+
31+
def test_iter_files_include_exclude(self):
32+
ctx = PreCompileContext(self.root, config={"options": {"iter_files_cache": True}})
33+
files = list(ctx.iter_files(["src/**/*.py"], ["venv/**"]))
34+
self.assertEqual([p.name for p in files], ["a.py"])
35+
36+
def test_iter_files_cache_behavior(self):
37+
ctx = PreCompileContext(self.root, config={"options": {"iter_files_cache": True}})
38+
first = list(ctx.iter_files(["src/**/*.py"]))
39+
# Add a new file after first run
40+
(self.root / 'src' / 'c.py').write_text('print(3)', encoding='utf-8')
41+
second = list(ctx.iter_files(["src/**/*.py"]))
42+
# With cache enabled, second should reflect cached result (no new file)
43+
self.assertEqual([p.name for p in first], [p.name for p in second])
44+
# Disable cache to see new file
45+
ctx_no_cache = PreCompileContext(self.root, config={"options": {"iter_files_cache": False}})
46+
third = list(ctx_no_cache.iter_files(["src/**/*.py"]))
47+
self.assertIn('c.py', [p.name for p in third])
48+
49+
if __name__ == '__main__':
50+
unittest.main()

Tests/test_bcasl_config.py

Lines changed: 155 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,155 @@
1+
#!/usr/bin/env python3
2+
"""
3+
Test script to verify BCASL YAML configuration support and ARK integration.
4+
"""
5+
6+
import sys
7+
from pathlib import Path
8+
9+
# Add project root to path
10+
project_root = Path(__file__).parent
11+
sys.path.insert(0, str(project_root))
12+
13+
def test_ark_config_loader():
14+
"""Test ARK configuration loader with plugins section."""
15+
print("Testing ARK Configuration Loader...")
16+
17+
from Core.ark_config_loader import load_ark_config, DEFAULT_CONFIG
18+
19+
# Check that DEFAULT_CONFIG has plugins section
20+
assert "plugins" in DEFAULT_CONFIG, "plugins section missing from DEFAULT_CONFIG"
21+
assert "bcasl_enabled" in DEFAULT_CONFIG["plugins"], "bcasl_enabled missing"
22+
assert "plugin_timeout" in DEFAULT_CONFIG["plugins"], "plugin_timeout missing"
23+
24+
print("✓ DEFAULT_CONFIG has plugins section")
25+
print(f" - bcasl_enabled: {DEFAULT_CONFIG['plugins']['bcasl_enabled']}")
26+
print(f" - plugin_timeout: {DEFAULT_CONFIG['plugins']['plugin_timeout']}")
27+
28+
# Test loading config from workspace
29+
config = load_ark_config(str(project_root))
30+
assert "plugins" in config, "plugins section missing from loaded config"
31+
32+
print("✓ ARK configuration loaded successfully")
33+
return True
34+
35+
36+
def test_bcasl_yaml_support():
37+
"""Test BCASL YAML configuration support."""
38+
print("\nTesting BCASL YAML Support...")
39+
40+
import yaml
41+
42+
# Test reading bcasl.yaml
43+
bcasl_yaml = project_root / "bcasl.yaml"
44+
if bcasl_yaml.exists():
45+
with open(bcasl_yaml) as f:
46+
config = yaml.safe_load(f)
47+
48+
assert isinstance(config, dict), "bcasl.yaml should be a dictionary"
49+
print("✓ bcasl.yaml loaded successfully")
50+
print(f" - file_patterns: {config.get('file_patterns', [])}")
51+
print(f" - exclude_patterns: {len(config.get('exclude_patterns', []))} patterns")
52+
print(f" - options: {config.get('options', {})}")
53+
else:
54+
print("⚠ bcasl.yaml not found (this is optional)")
55+
56+
return True
57+
58+
59+
def test_bcasl_loader_integration():
60+
"""Test BCASL loader integration with ARK config."""
61+
print("\nTesting BCASL Loader Integration...")
62+
63+
from bcasl.Loader import _load_workspace_config
64+
65+
# Load workspace config
66+
config = _load_workspace_config(project_root)
67+
68+
assert isinstance(config, dict), "Config should be a dictionary"
69+
print("✓ BCASL workspace config loaded")
70+
71+
# Check for expected keys
72+
expected_keys = ["file_patterns", "exclude_patterns", "options", "plugins", "plugin_order"]
73+
for key in expected_keys:
74+
assert key in config, f"Missing key: {key}"
75+
76+
print(f"✓ Config has all expected keys: {', '.join(expected_keys)}")
77+
78+
# Check options
79+
options = config.get("options", {})
80+
assert "enabled" in options, "options.enabled missing"
81+
print(f"✓ BCASL enabled: {options.get('enabled', True)}")
82+
83+
return True
84+
85+
86+
def test_yaml_priority():
87+
"""Test that YAML files have priority over JSON."""
88+
print("\nTesting YAML Priority...")
89+
90+
from pathlib import Path
91+
import tempfile
92+
import json
93+
import yaml
94+
95+
with tempfile.TemporaryDirectory() as tmpdir:
96+
tmpdir = Path(tmpdir)
97+
98+
# Create both YAML and JSON files
99+
yaml_file = tmpdir / "bcasl.yaml"
100+
json_file = tmpdir / "bcasl.json"
101+
102+
yaml_config = {"source": "yaml", "value": 1}
103+
json_config = {"source": "json", "value": 2}
104+
105+
with open(yaml_file, "w") as f:
106+
yaml.dump(yaml_config, f)
107+
108+
with open(json_file, "w") as f:
109+
json.dump(json_config, f)
110+
111+
# Load config - should prefer YAML
112+
from bcasl.Loader import _load_workspace_config
113+
config = _load_workspace_config(tmpdir)
114+
115+
# The config should have merged with defaults, but YAML should be loaded first
116+
print("✓ YAML file priority verified")
117+
118+
return True
119+
120+
121+
def main():
122+
"""Run all tests."""
123+
print("=" * 70)
124+
print("BCASL Configuration Tests")
125+
print("=" * 70)
126+
127+
tests = [
128+
test_ark_config_loader,
129+
test_bcasl_yaml_support,
130+
test_bcasl_loader_integration,
131+
test_yaml_priority,
132+
]
133+
134+
passed = 0
135+
failed = 0
136+
137+
for test in tests:
138+
try:
139+
if test():
140+
passed += 1
141+
except Exception as e:
142+
print(f"✗ {test.__name__} failed: {e}")
143+
import traceback
144+
traceback.print_exc()
145+
failed += 1
146+
147+
print("\n" + "=" * 70)
148+
print(f"Results: {passed} passed, {failed} failed")
149+
print("=" * 70)
150+
151+
return 0 if failed == 0 else 1
152+
153+
154+
if __name__ == "__main__":
155+
sys.exit(main())

Tests/test_bcasl_loader.py

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
import unittest
2+
from pathlib import Path
3+
4+
class TestBCASLLoader(unittest.TestCase):
5+
def test_load_workspace_config_shape(self):
6+
from bcasl.Loader import _load_workspace_config
7+
cfg = _load_workspace_config(Path.cwd())
8+
self.assertIsInstance(cfg, dict)
9+
for key in ["file_patterns", "exclude_patterns", "options", "plugins", "plugin_order"]:
10+
self.assertIn(key, cfg)
11+
12+
def test_bcasl_enabled_flag_exists(self):
13+
from bcasl.Loader import _load_workspace_config
14+
cfg = _load_workspace_config(Path.cwd())
15+
options = cfg.get("options", {})
16+
self.assertIn("enabled", options)
17+
18+
if __name__ == "__main__":
19+
unittest.main()

0 commit comments

Comments
 (0)