55
66import pytest
77
8+ import quantumpytho .modules .dna_circuits as dna_circuits
89from quantumpytho .modules .dna_circuits import (
910 get_available_dna_circuit_ids ,
1011 get_available_dna_circuits ,
1112 get_available_dna_sequences ,
1213 get_dna_circuit_preview ,
1314 get_dna_sequence ,
1415 load_dna_circuit ,
16+ load_dna_circuit_metadata ,
1517 load_qasm_circuit_file ,
18+ run_dna_circuit_explorer ,
1619 summarize_dna_circuit ,
1720 validate_qasm_file ,
1821)
@@ -43,6 +46,14 @@ def test_load_dna_circuit_parses_qasm():
4346 assert circuit .num_clbits == 21
4447
4548
49+ def test_load_dna_circuit_metadata_reads_bundled_json ():
50+ """Bundled metadata should be readable without summary normalization."""
51+ metadata = load_dna_circuit_metadata ("dna_helix_10bp" )
52+
53+ assert metadata ["qubits" ] == 21
54+ assert metadata ["config" ]["base_pairs" ] == 10
55+
56+
4657def test_load_stealth_dna_circuit_parses_qasm ():
4758 """Bundled 34bp stealth QASM should parse into a large Qiskit circuit."""
4859 circuit = load_dna_circuit ("stealth_dna_34bp" )
@@ -64,6 +75,16 @@ def test_summarize_dna_circuit_normalizes_metadata():
6475 assert summary .sequences ["strand1" ] == "GTAGGTAAGC"
6576
6677
78+ def test_dna_summary_to_dict_is_json_safe ():
79+ """Normalized summaries should serialize into simple Python data."""
80+ summary = summarize_dna_circuit ("dna_helix_10bp" )
81+ payload = summary .to_dict ()
82+
83+ assert payload ["circuit_id" ] == "dna_helix_10bp"
84+ assert payload ["sequences" ] == summary .sequences
85+ assert payload ["geometry" ] == summary .geometry
86+
87+
6788def test_summarize_stealth_dna_circuit_preserves_large_asset_metadata ():
6889 """Large stealth asset should preserve curated metadata and parsed metrics."""
6990 summary = summarize_dna_circuit ("stealth_dna_34bp" )
@@ -95,6 +116,21 @@ def test_stealth_circuit_preview_contains_named_registers():
95116 assert "qreg bridge[34];" in preview
96117
97118
119+ def test_validate_qasm_file_rejects_missing_file (tmp_path : Path ):
120+ """Missing QASM files should raise a helpful error."""
121+ with pytest .raises (FileNotFoundError , match = "not found" ):
122+ validate_qasm_file (tmp_path / "missing.qasm" )
123+
124+
125+ def test_validate_qasm_file_rejects_invalid_header (tmp_path : Path ):
126+ """Non-OpenQASM files should be rejected before parsing."""
127+ invalid_qasm = tmp_path / "invalid.qasm"
128+ invalid_qasm .write_text ("qreg q[1];" , encoding = "utf-8" )
129+
130+ with pytest .raises (ValueError , match = "not valid OpenQASM" ):
131+ validate_qasm_file (invalid_qasm )
132+
133+
98134def test_validate_qasm_file_rejects_empty_file (tmp_path : Path ):
99135 """Empty QASM placeholders should be rejected clearly."""
100136 empty_qasm = tmp_path / "empty.qasm"
@@ -113,6 +149,12 @@ def test_available_dna_sequences_contains_blueprint_and_library_entries():
113149 assert "lib_acgt" in record_ids
114150
115151
152+ def test_get_dna_sequence_unknown_record_raises_keyerror ():
153+ """Sequence lookup should fail clearly for unknown ids."""
154+ with pytest .raises (KeyError , match = "Unknown DNA sequence record" ):
155+ get_dna_sequence ("missing-record" )
156+
157+
116158def test_get_dna_sequence_blueprint_is_normalized ():
117159 """Blueprint sequence should be normalized by stripping separators."""
118160 record = get_dna_sequence ("seq_3" )
@@ -122,6 +164,41 @@ def test_get_dna_sequence_blueprint_is_normalized():
122164 assert record .phi_scaling == pytest .approx (0.7232610426788172 )
123165
124166
167+ def test_dna_sequence_to_dict_is_json_safe ():
168+ """Sequence records should serialize into simple Python data."""
169+ record = get_dna_sequence ("seq_3" )
170+ payload = record .to_dict ()
171+
172+ assert payload ["record_id" ] == "seq_3"
173+ assert payload ["sequence" ] == record .sequence
174+ assert payload ["metadata" ] == record .metadata
175+
176+
177+ def test_load_dna_circuit_metadata_raises_for_missing_bundled_file (
178+ monkeypatch : pytest .MonkeyPatch , tmp_path : Path
179+ ):
180+ """Missing bundled metadata files should raise a clear error."""
181+ monkeypatch .setattr (dna_circuits , "_data_dir" , lambda : tmp_path )
182+
183+ with pytest .raises (FileNotFoundError , match = "DNA metadata file not found" ):
184+ load_dna_circuit_metadata ("dna_helix_10bp" )
185+
186+
187+ def test_load_dna_circuit_rejects_unknown_asset ():
188+ """Unknown bundled circuit ids should fail clearly."""
189+ with pytest .raises (KeyError , match = "Unknown DNA circuit asset" ):
190+ load_dna_circuit ("missing-circuit" )
191+
192+
193+ def test_load_qasm_circuit_file_rejects_unsupported_openqasm_version (tmp_path : Path ):
194+ """Unknown OpenQASM versions should fail before import."""
195+ qasm_path = tmp_path / "sample.qasm"
196+ qasm_path .write_text ("OPENQASM 4.0;\n qubit q;\n " , encoding = "utf-8" )
197+
198+ with pytest .raises (ValueError , match = "Unsupported OpenQASM version" ):
199+ load_qasm_circuit_file (qasm_path )
200+
201+
125202def test_load_qasm_circuit_file_handles_openqasm3_optional_dependency (tmp_path : Path ):
126203 """OpenQASM 3 loading should either parse or fail with an install hint."""
127204 qasm3_path = tmp_path / "sample.qasm"
@@ -136,3 +213,31 @@ def test_load_qasm_circuit_file_handles_openqasm3_optional_dependency(tmp_path:
136213 else :
137214 circuit = load_qasm_circuit_file (qasm3_path )
138215 assert circuit .num_qubits == 1
216+
217+
218+ def test_run_dna_circuit_explorer_allows_quit (
219+ monkeypatch : pytest .MonkeyPatch , capsys : pytest .CaptureFixture [str ]
220+ ):
221+ """CLI explorer should return cleanly when the user quits."""
222+ monkeypatch .setattr ("builtins.input" , lambda _ : "q" )
223+
224+ run_dna_circuit_explorer ()
225+
226+ output = capsys .readouterr ().out
227+ assert "[DNA-Inspired Circuit Explorer]" in output
228+ assert "Returning to main menu..." in output
229+
230+
231+ def test_run_dna_circuit_explorer_uses_default_selection (
232+ monkeypatch : pytest .MonkeyPatch , capsys : pytest .CaptureFixture [str ]
233+ ):
234+ """Blank input should select the first bundled DNA circuit."""
235+ monkeypatch .setattr ("builtins.input" , lambda _ : "" )
236+ monkeypatch .setattr (dna_circuits .importlib .util , "find_spec" , lambda _ : None )
237+
238+ run_dna_circuit_explorer ()
239+
240+ output = capsys .readouterr ().out
241+ assert "OpenQASM 3 import support: install qiskit_qasm3_import" in output
242+ assert "Name: DNA Helix 10bp" in output
243+ assert "QASM preview:" in output
0 commit comments