Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
21 commits
Select commit Hold shift + click to select a range
822d3ed
Merge branch 'main' of https://github.com/ezrafield/c2testcase
Jun 16, 2026
596e2dc
Revert "Merge branch 'main' of https://github.com/ezrafield/c2testcase"
Jun 16, 2026
22a34c9
Merge branch 'main' of https://github.com/ezrafield/c2testcase
Jun 16, 2026
07e93a7
Merge branch 'main' of https://github.com/ezrafield/c2testcase
Jun 17, 2026
ef7308b
Merge branch 'main' of https://github.com/ezrafield/c2testcase
Jun 17, 2026
64ebdc2
Merge branch 'main' of https://github.com/ezrafield/c2testcase
Jun 17, 2026
e5a5edf
Merge branch 'main' of https://github.com/ezrafield/c2testcase
Jun 17, 2026
6ab4e0c
Merge branch 'main' of https://github.com/ezrafield/c2testcase
Jun 17, 2026
3fc74ab
Merge branch 'main' of https://github.com/ezrafield/c2testcase
Jun 17, 2026
34f619d
Merge branch 'main' of https://github.com/ezrafield/c2testcase
Jun 17, 2026
9e19ea7
Merge branch 'main' of https://github.com/ezrafield/c2testcase
Jun 17, 2026
7acc751
Merge branch 'main' of https://github.com/ezrafield/c2testcase
Jun 18, 2026
5f65dd7
Merge branch 'main' of https://github.com/ezrafield/c2testcase
Jun 18, 2026
ef5dec2
Merge branch 'main' of https://github.com/ezrafield/c2testcase
Jun 18, 2026
c6f19b7
Merge branch 'main' of https://github.com/ezrafield/c2testcase
Jun 18, 2026
d2f9c6f
Merge branch 'main' of https://github.com/ezrafield/c2testcase
Jun 18, 2026
bbc46fa
Merge branch 'main' of https://github.com/ezrafield/c2testcase
Jun 19, 2026
e168170
Merge branch 'main' of https://github.com/ezrafield/c2testcase
Jun 19, 2026
51733e9
Merge branch 'main' of https://github.com/ezrafield/c2testcase
Jun 19, 2026
78698a0
Merge branch 'main' of https://github.com/ezrafield/c2testcase
Jun 19, 2026
2e657a4
update
Jul 1, 2026
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
32 changes: 26 additions & 6 deletions src/api/app.py
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@
MCDC_MODES,
excel_export_rows,
generate_mcdc_report,
parse_support_template,
safe_excel_filename,
testcase_table_rows_from_dict,
testcase_table_rows_to_csv,
Expand Down Expand Up @@ -40,14 +41,15 @@ def index() -> str:
async def generate_cases(
source: UploadFile = File(...),
headers: list[UploadFile] | None = File(default=None),
support_template: UploadFile | None = File(default=None),
target_function: str = Form(default=""),
input_variables: str = Form(default=""),
output_variables: str = Form(default=""),
compile_flags: str = Form(default=""),
excel_format_version: str = Form(default="1.3"),
excel_format_version: str = Form(default=""),
excel_architecture: str = Form(default=""),
excel_scope: str = Form(default=""),
excel_name: str = Form(default="mcdc_testcases"),
excel_name: str = Form(default=""),
max_conditions: int = Form(default=12),
mcdc_mode: str = Form(default="unique-cause"),
) -> dict[str, object]:
Expand All @@ -73,6 +75,18 @@ async def generate_cases(
header_path.write_bytes(await header.read())
header_paths.append(header_path)

interface_override = None
template_metadata: ExcelExportMetadata | None = None
if support_template is not None and support_template.filename:
if not support_template.filename.lower().endswith(".xlsx"):
raise HTTPException(status_code=400, detail="Support template must be a .xlsx file.")
template_path = workspace / safe_name(support_template.filename)
template_path.write_bytes(await support_template.read())
try:
interface_override, template_metadata = parse_support_template(template_path)
except (ValueError, KeyError) as error:
raise HTTPException(status_code=400, detail=f"Could not parse support template: {error}")

output_dir = workspace / "out"
parsed_input_variables, manual_inputs = parse_variable_setup(input_variables)
parsed_output_variables, manual_outputs = parse_variable_setup(output_variables)
Expand All @@ -88,12 +102,16 @@ async def generate_cases(
output_variables=parsed_output_variables,
manual_outputs=manual_outputs,
mcdc_mode=mcdc_mode,
interface_override=interface_override,
)
# When a support template carries metadata, use it as the default for any blank
# Excel export field so the generated sheet preserves the template's identity.
template_metadata = template_metadata or ExcelExportMetadata()
excel_metadata = ExcelExportMetadata(
format_version=excel_format_version.strip() or "1.3",
architecture=excel_architecture.strip(),
scope=excel_scope.strip(),
name=excel_name.strip() or "mcdc_testcases",
format_version=excel_format_version.strip() or template_metadata.format_version or "1.3",
architecture=excel_architecture.strip() or template_metadata.architecture,
scope=excel_scope.strip() or template_metadata.scope,
name=excel_name.strip() or template_metadata.name or "mcdc_testcases",
)
json_path, harness_path, gap_report_path, excel_path = write_report_artifacts(
report,
Expand Down Expand Up @@ -580,6 +598,8 @@ def render_index_html() -> str:
<input id="source" name="source" type="file" accept=".c" required>
<label for="headers">Headers</label>
<input id="headers" name="headers" type="file" accept=".h" multiple>
<label for="support_template">Support template (Excel)</label>
<input id="support_template" name="support_template" type="file" accept=".xlsx">
<label for="target_function">Target function</label>
<input id="target_function" name="target_function" type="text" placeholder="logic">
<label for="input_variables">Manual input setup</label>
Expand Down
30 changes: 28 additions & 2 deletions src/cli.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,13 @@
import argparse
from pathlib import Path

from src.services.mcdc_generator import MCDC_MODES, generate_mcdc_report, write_report_artifacts
from src.services.mcdc_generator import (
MCDC_MODES,
ExcelExportMetadata,
generate_mcdc_report,
parse_support_template,
write_report_artifacts,
)

ManualValue = int | float | bool | str

Expand All @@ -28,6 +34,11 @@ def build_parser() -> argparse.ArgumentParser:
default=[],
help="Optional .h file recorded for future harness/build integration.",
)
parser.add_argument(
"--support-template",
type=Path,
help="Optional support Excel (.xlsx) template defining the Input/Parameter/Output columns to generate.",
)
parser.add_argument(
"--target-function",
help="Optional function name to record in generated reports.",
Expand Down Expand Up @@ -88,6 +99,18 @@ def main(argv: list[str] | None = None) -> int:
if not include_dir.exists() or not include_dir.is_dir():
raise SystemExit(f"Include directory not found: {include_dir}")

interface_override = None
excel_metadata: ExcelExportMetadata | None = None
if args.support_template is not None:
if not args.support_template.exists():
raise SystemExit(f"Support template not found: {args.support_template}")
if args.support_template.suffix.lower() != ".xlsx":
raise SystemExit("Support template must be a .xlsx file.")
try:
interface_override, excel_metadata = parse_support_template(args.support_template)
except (ValueError, KeyError) as error:
raise SystemExit(f"Could not parse support template: {error}")

input_variables, manual_inputs = parse_variable_setup(args.input_variable)
output_variables, manual_outputs = parse_variable_setup(args.output_variable)
report = generate_mcdc_report(
Expand All @@ -102,8 +125,11 @@ def main(argv: list[str] | None = None) -> int:
output_variables=output_variables,
manual_outputs=manual_outputs,
mcdc_mode=args.mcdc_mode,
interface_override=interface_override,
)
json_path, harness_path, gap_report_path, excel_path = write_report_artifacts(
report, args.output_dir, excel_metadata=excel_metadata
)
json_path, harness_path, gap_report_path, excel_path = write_report_artifacts(report, args.output_dir)

print(f"Generated MC/DC target score ({report.mcdc_mode}): {report.score:.1%}")
print(f"Cases: {json_path}")
Expand Down
Loading
Loading