use quantrs2_circuit::builder::CircuitBuilder;
use quantrs2_circuit::prelude::*;
#[test]
fn test_qasm3_export_simple() {
let mut builder = CircuitBuilder::<2>::new();
builder.h(Qubit::new(0)).unwrap();
builder.cx(Qubit::new(0), Qubit::new(1)).unwrap();
let circuit = builder.build();
let qasm = export_qasm3(&circuit).expect("Failed to export circuit");
assert!(qasm.contains("OPENQASM 3.0"));
assert!(qasm.contains("qubit[2] q"));
assert!(qasm.contains("h q[0]"));
assert!(qasm.contains("cx q[0], q[1]"));
println!("Generated QASM:\n{qasm}");
}
#[test]
fn test_qasm3_export_with_measurements() {
let mut builder = CircuitBuilder::<3>::new();
builder.h(Qubit::new(0)).unwrap();
builder.cx(Qubit::new(0), Qubit::new(1)).unwrap();
builder.cx(Qubit::new(1), Qubit::new(2)).unwrap();
builder.measure(Qubit::new(0)).unwrap();
builder.measure(Qubit::new(1)).unwrap();
builder.measure(Qubit::new(2)).unwrap();
let circuit = builder.build();
let mut exporter = QasmExporter::new(ExportOptions {
include_stdgates: true,
decompose_custom: false,
include_gate_comments: false,
optimize: false,
pretty_print: true,
});
let qasm = exporter.export(&circuit).expect("Failed to export circuit");
assert!(qasm.contains("bit[3] c"));
assert!(qasm.contains("measure"));
println!("GHZ circuit QASM:\n{qasm}");
}
#[test]
fn test_qasm3_parse_simple() {
let qasm_code = r#"
OPENQASM 3.0;
include "stdgates.inc";
qubit[3] q;
bit[3] c;
// Create superposition
h q[0];
// Bell pair on first two qubits
cx q[0], q[1];
// Entangle third qubit
cx q[1], q[2];
// Measure all
measure q -> c;
"#;
let program = parse_qasm3(qasm_code).expect("Failed to parse QASM");
validate_qasm3(&program).expect("Validation failed");
assert_eq!(program.version, "3.0");
assert_eq!(program.includes.len(), 1);
assert_eq!(program.declarations.len(), 2); assert_eq!(program.statements.len(), 4); }
#[test]
fn test_qasm3_parse_parametric_gates() {
let qasm_code = r"
OPENQASM 3.0;
qubit[2] q;
// Parametric rotations
rx(pi/2) q[0];
ry(pi/4) q[1];
rz(pi/8) q[0];
// Controlled rotation
crx(pi/3) q[0], q[1];
";
let program = parse_qasm3(qasm_code).expect("Failed to parse QASM");
validate_qasm3(&program).expect("Validation failed");
assert_eq!(program.statements.len(), 4);
}
#[test]
fn test_qasm3_parse_custom_gate() {
let qasm_code = r"
OPENQASM 3.0;
// Define custom bell gate
gate bell a, b {
h a;
cx a, b;
}
qubit[2] q;
// Use custom gate
bell q[0], q[1];
";
let program = parse_qasm3(qasm_code).expect("Failed to parse QASM");
validate_qasm3(&program).expect("Validation failed");
assert_eq!(program.declarations.len(), 2);
let mut found_gate = false;
for decl in &program.declarations {
if let quantrs2_circuit::qasm::ast::Declaration::GateDefinition(def) = decl {
assert_eq!(def.name, "bell");
assert_eq!(def.qubits.len(), 2);
assert_eq!(def.body.len(), 2); found_gate = true;
}
}
assert!(found_gate, "Custom gate definition not found");
}
#[test]
fn test_qasm3_parse_control_flow() {
let qasm_code = r"
OPENQASM 3.0;
qubit[4] q;
bit[4] c;
// Basic gates
h q[0];
cx q[0], q[1];
// For loop with fixed indices
for i in [0:2] {
h q[0];
h q[1];
}
";
let program = parse_qasm3(qasm_code).expect("Failed to parse QASM");
validate_qasm3(&program).expect("Validation failed");
assert_eq!(program.statements.len(), 3); }
#[test]
fn test_qasm3_validation_errors() {
let qasm_code = r"
OPENQASM 3.0;
qubit[2] q;
h r[0]; // r is undefined
";
let program = parse_qasm3(qasm_code).expect("Failed to parse");
let result = validate_qasm3(&program);
assert!(result.is_err());
let qasm_code = r"
OPENQASM 3.0;
qubit[2] q;
h q[5]; // index 5 is out of bounds
";
let program = parse_qasm3(qasm_code).expect("Failed to parse");
let result = validate_qasm3(&program);
assert!(result.is_err());
let qasm_code = r"
OPENQASM 3.0;
qubit q;
rx q; // rx requires 1 parameter
";
let program = parse_qasm3(qasm_code).expect("Failed to parse");
let result = validate_qasm3(&program);
assert!(result.is_err());
}
#[test]
fn test_qasm3_round_trip() {
let mut builder = CircuitBuilder::<3>::new();
builder.h(Qubit::new(0)).unwrap();
builder
.rx(Qubit::new(1), std::f64::consts::PI / 4.0)
.unwrap();
builder.cx(Qubit::new(0), Qubit::new(2)).unwrap();
builder.measure(Qubit::new(0)).unwrap();
builder.measure(Qubit::new(1)).unwrap();
builder.measure(Qubit::new(2)).unwrap();
let original_circuit = builder.build();
let qasm = export_qasm3(&original_circuit).expect("Failed to export");
println!("Exported QASM:\n{qasm}");
let program = parse_qasm3(&qasm).expect("Failed to parse exported QASM");
validate_qasm3(&program).expect("Validation failed");
assert_eq!(program.statements.len(), 6); }
#[test]
fn test_qasm3_advanced_features() {
let qasm_code = r#"
OPENQASM 3.0;
include "stdgates.inc";
// Constants
const n = 4;
const angle = pi/8;
// Registers
qubit[n] q;
bit[n] c;
// Basic operations
h q[0];
rx(angle) q[1];
cx q[0], q[1];
// Reset
reset q[0];
// Barrier
barrier q;
"#;
let program = parse_qasm3(qasm_code).expect("Failed to parse QASM");
validate_qasm3(&program).expect("Validation failed");
assert_eq!(program.declarations.len(), 4);
assert!(
program.statements.len() >= 5,
"Expected at least 5 statements"
);
}
#[cfg(test)]
mod integration_tests {
use super::*;
#[test]
fn test_qasm3_compatibility() {
let mut builder = CircuitBuilder::<4>::new();
let n = 4;
for j in 0..n {
builder.h(Qubit::new(j)).unwrap();
for k in (j + 1)..n {
let angle = std::f64::consts::PI / f64::from(1 << (k - j));
builder.cp(Qubit::new(j), Qubit::new(k), angle).unwrap();
}
}
for i in 0..n / 2 {
builder.swap(Qubit::new(i), Qubit::new(n - 1 - i)).unwrap();
}
let circuit = builder.build();
let qasm = export_qasm3(&circuit).expect("Failed to export QFT circuit");
println!("QFT Circuit QASM:\n{qasm}");
let program = parse_qasm3(&qasm).expect("Failed to parse QFT QASM");
validate_qasm3(&program).expect("QFT validation failed");
}
}