Spaces:
Sleeping
Sleeping
| import os | |
| import pytest | |
| import numpy as np | |
| import cv2 | |
| from src.app import ( | |
| draw_visualizations, | |
| make_html_performance_dashboard, | |
| run_app_inference, | |
| discover_presets, | |
| load_preset_image | |
| ) | |
| def test_draw_visualizations(): | |
| # Test drawing on single channel grayscale image | |
| drawing_gray = np.ones((100, 100), dtype=np.uint8) * 255 | |
| results = [ | |
| {"bbox": (10, 10, 20, 20), "confidence": 0.85, "rotation": "R90"} | |
| ] | |
| vis_gray = draw_visualizations(drawing_gray, results) | |
| assert vis_gray.ndim == 3 | |
| assert vis_gray.shape[2] == 3 | |
| # Test drawing on BGR image | |
| drawing_bgr = np.ones((100, 100, 3), dtype=np.uint8) * 255 | |
| vis_bgr = draw_visualizations(drawing_bgr, results) | |
| assert vis_bgr.shape == (100, 100, 3) | |
| def test_make_html_performance_dashboard(): | |
| report = { | |
| "total_time_seconds": 1.25, | |
| "current_ram_mb": 150.0, | |
| "ram_delta_mb": 10.5, | |
| "num_proposals_total": 5, | |
| "num_detected": 2, | |
| "durations_seconds": { | |
| "load_drawing": 0.1, | |
| "detect": 1.15 | |
| } | |
| } | |
| html = make_html_performance_dashboard(report) | |
| assert "Performance Dashboard" in html | |
| assert "1.250 s" in html | |
| assert "150.0 MB" in html | |
| assert "+10.5 MB" in html | |
| assert "5" in html | |
| assert "2" in html | |
| assert "load_drawing" in html | |
| def test_run_app_inference_missing_paths(): | |
| vis, json_out, dashboard_html = run_app_inference( | |
| pattern_path="", | |
| drawing_path="", | |
| mode="v3", | |
| conf_thresh=0.75, | |
| v1_thresh=0.5, | |
| v2_thresh=0.8, | |
| alpha=0.3, | |
| iou_thresh=0.3, | |
| enable_refine=False, | |
| var_std=5.0, | |
| margin=0.15, | |
| extractor_choice="auto" | |
| ) | |
| assert vis is None | |
| assert isinstance(json_out, dict) | |
| assert "error" in json_out | |
| assert "Vui lòng upload đầy đủ ảnh mẫu" in json_out["error"] | |
| assert dashboard_html == "" | |
| def test_run_app_inference_valid(tmp_path, dummy_pattern, dummy_grayscale_drawing): | |
| pattern_path = os.path.join(tmp_path, "pattern.png") | |
| drawing_path = os.path.join(tmp_path, "drawing.png") | |
| cv2.imwrite(pattern_path, dummy_pattern) | |
| cv2.imwrite(drawing_path, dummy_grayscale_drawing) | |
| vis, json_out, dashboard_html = run_app_inference( | |
| pattern_path=pattern_path, | |
| drawing_path=drawing_path, | |
| mode="v3", | |
| conf_thresh=0.40, | |
| v1_thresh=0.40, | |
| v2_thresh=0.50, | |
| alpha=0.30, | |
| iou_thresh=0.30, | |
| enable_refine=True, | |
| var_std=5.0, | |
| margin=0.15, | |
| extractor_choice="auto" | |
| ) | |
| assert vis is not None | |
| assert vis.shape == (300, 300, 3) | |
| assert isinstance(json_out, list) | |
| assert len(json_out) > 0 | |
| assert "bbox" in json_out[0] | |
| assert "Performance Dashboard" in dashboard_html | |
| def test_preset_file_discovery(): | |
| patterns, drawings = discover_presets() | |
| # Verify lists contain only valid extensions or are lists | |
| assert isinstance(patterns, list) | |
| assert isinstance(drawings, list) | |
| valid_exts = ('.png', '.jpg', '.jpeg') | |
| for p in patterns: | |
| assert p.lower().endswith(valid_exts) | |
| for d in drawings: | |
| assert d.lower().endswith(valid_exts) | |
| def test_load_preset_image_security_and_bounds(): | |
| patterns, drawings = discover_presets() | |
| # Happy paths (nếu có tệp trong data) | |
| if patterns: | |
| path = load_preset_image(patterns[0], "patterns") | |
| assert path is not None | |
| assert os.path.exists(path) | |
| # Edge cases | |
| assert load_preset_image(None, "patterns") is None | |
| assert load_preset_image("", "patterns") is None | |
| assert load_preset_image("non_existent_file.png", "patterns") is None | |
| # Chống Path Traversal (Security test) | |
| assert load_preset_image("../app.py", "patterns") is None | |
| assert load_preset_image("../../../etc/passwd", "patterns") is None | |
| def test_run_app_inference_cancellation(tmp_path, dummy_pattern, dummy_grayscale_drawing): | |
| from src.exceptions import CancellationState | |
| pattern_path = os.path.join(tmp_path, "pattern.png") | |
| drawing_path = os.path.join(tmp_path, "drawing.png") | |
| cv2.imwrite(pattern_path, dummy_pattern) | |
| cv2.imwrite(drawing_path, dummy_grayscale_drawing) | |
| cancellation_state = CancellationState() | |
| cancellation_state.cancel() # Abort before start | |
| vis, json_out, dashboard_html = run_app_inference( | |
| pattern_path=pattern_path, | |
| drawing_path=drawing_path, | |
| mode="v3", | |
| conf_thresh=0.40, | |
| v1_thresh=0.40, | |
| v2_thresh=0.50, | |
| alpha=0.30, | |
| iou_thresh=0.30, | |
| enable_refine=True, | |
| var_std=5.0, | |
| margin=0.15, | |
| extractor_choice="auto", | |
| cancellation_state=cancellation_state, | |
| reset_cancellation=False | |
| ) | |
| assert vis is None | |
| assert isinstance(json_out, dict) | |
| assert "error" in json_out | |
| assert "hủy" in json_out["error"].lower() | |