Skip to content

Commit ce59a53

Browse files
GiggleLiuclaude
andcommitted
Add comprehensive test coverage for QASM 3.0 print_qasm functions
Added 62 new tests covering all print_qasm functions in types_v3.jl: - Classical type printing (int, uint, float, bit, angle with/without widths) - Classical declarations (with/without const, with/without initializers) - Qubit declarations (with/without size) - Control flow (if/else, while, for with ranges and sets) - Break and continue statements - Gate modifiers (inv, ctrl, negctrl, pow) - Modified gates - Input/Output declarations - Round-trip parse -> print -> parse tests This significantly improves coverage of types_v3.jl from ~18% to expected >95%. All 277+ tests now pass. 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
1 parent 3f710f5 commit ce59a53

File tree

1 file changed

+174
-0
lines changed

1 file changed

+174
-0
lines changed

test/runtests.jl

Lines changed: 174 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -665,3 +665,177 @@ end
665665
end
666666
@test has_break || has_continue # At least one should be found
667667
end
668+
@testset "QASM 3.0 print_qasm coverage" begin
669+
# Test classical type printing
670+
@testset "Classical types" begin
671+
@test sprint(Types.print_qasm, IntType()) == "int"
672+
@test sprint(Types.print_qasm, IntType(Token{:int}("32"))) == "int[32]"
673+
@test sprint(Types.print_qasm, UIntType()) == "uint"
674+
@test sprint(Types.print_qasm, UIntType(Token{:int}("64"))) == "uint[64]"
675+
@test sprint(Types.print_qasm, FloatType()) == "float"
676+
@test sprint(Types.print_qasm, FloatType(Token{:int}("64"))) == "float[64]"
677+
@test sprint(Types.print_qasm, BitType()) == "bit"
678+
@test sprint(Types.print_qasm, BitType(Token{:int}("5"))) == "bit[5]"
679+
@test sprint(Types.print_qasm, AngleType()) == "angle"
680+
@test sprint(Types.print_qasm, AngleType(Token{:int}("20"))) == "angle[20]"
681+
end
682+
683+
# Test classical declarations
684+
@testset "Classical declarations" begin
685+
decl1 = ClassicalDecl(false, IntType(Token{:int}("32")), Token{:id}("x"), nothing)
686+
@test occursin("int[32]", sprint(Types.print_qasm, decl1))
687+
@test occursin("x", sprint(Types.print_qasm, decl1))
688+
689+
decl2 = ClassicalDecl(true, FloatType(Token{:int}("64")), Token{:id}("y"), Token{:float64}("3.14"))
690+
@test occursin("const", sprint(Types.print_qasm, decl2))
691+
@test occursin("float[64]", sprint(Types.print_qasm, decl2))
692+
@test occursin("y", sprint(Types.print_qasm, decl2))
693+
@test occursin("3.14", sprint(Types.print_qasm, decl2))
694+
end
695+
696+
# Test qubit declarations
697+
@testset "Qubit declarations" begin
698+
decl1 = QubitDecl(nothing, Token{:id}("q"))
699+
@test occursin("qubit", sprint(Types.print_qasm, decl1))
700+
@test occursin("q", sprint(Types.print_qasm, decl1))
701+
702+
decl2 = QubitDecl(Token{:id}("q"), Token{:int}("2"))
703+
@test occursin("qubit[2]", sprint(Types.print_qasm, decl2))
704+
@test occursin("q", sprint(Types.print_qasm, decl2))
705+
end
706+
707+
# Test control flow statements
708+
@testset "If-else statements" begin
709+
# If without else
710+
if_stmt = IfElseStmt(Token{:id}("c"), [Token{:id}("x")], nothing)
711+
output = sprint(Types.print_qasm, if_stmt)
712+
@test occursin("if", output)
713+
@test occursin("c", output)
714+
715+
# If with else
716+
if_else = IfElseStmt(Token{:id}("c"), [Token{:id}("x")], [Token{:id}("y")])
717+
output2 = sprint(Types.print_qasm, if_else)
718+
@test occursin("if", output2)
719+
@test occursin("else", output2)
720+
end
721+
722+
@testset "While statements" begin
723+
while_stmt = WhileStmt(Token{:id}("c"), [Token{:id}("x")])
724+
output = sprint(Types.print_qasm, while_stmt)
725+
@test occursin("while", output)
726+
@test occursin("c", output)
727+
end
728+
729+
@testset "For statements" begin
730+
# For with range
731+
range = RangeExpr(Token{:int}("0"), Token{:int}("10"))
732+
for_stmt = ForStmt(IntType(), Token{:id}("i"), range, [Token{:id}("x")])
733+
output = sprint(Types.print_qasm, for_stmt)
734+
@test occursin("for", output)
735+
@test occursin("int", output)
736+
@test occursin("i", output)
737+
@test occursin("in", output)
738+
739+
# For with discrete set
740+
set = DiscreteSet([Token{:int}("1"), Token{:int}("5"), Token{:int}("10")])
741+
for_stmt2 = ForStmt(IntType(), Token{:id}("i"), set, [Token{:id}("x")])
742+
output2 = sprint(Types.print_qasm, for_stmt2)
743+
@test occursin("for", output2)
744+
@test occursin("{", output2)
745+
@test occursin("1", output2)
746+
@test occursin("5", output2)
747+
@test occursin("10", output2)
748+
end
749+
750+
@testset "Range and set printing" begin
751+
# Range without step
752+
range1 = RangeExpr(Token{:int}("0"), Token{:int}("10"))
753+
@test occursin("[0:10]", sprint(Types.print_qasm, range1))
754+
755+
# Range with step
756+
range2 = RangeExpr(Token{:int}("0"), Token{:int}("2"), Token{:int}("10"))
757+
@test occursin("[0:2:10]", sprint(Types.print_qasm, range2))
758+
759+
# Discrete set
760+
set = DiscreteSet([Token{:int}("1"), Token{:int}("5")])
761+
output = sprint(Types.print_qasm, set)
762+
@test occursin("{", output)
763+
@test occursin("1", output)
764+
@test occursin("5", output)
765+
@test occursin("}", output)
766+
end
767+
768+
@testset "Break and continue" begin
769+
@test sprint(Types.print_qasm, BreakStmt()) == "break;"
770+
@test sprint(Types.print_qasm, ContinueStmt()) == "continue;"
771+
end
772+
773+
@testset "Gate modifiers" begin
774+
@test sprint(Types.print_qasm, GateModifier(:inv)) == "inv"
775+
@test sprint(Types.print_qasm, GateModifier(:ctrl)) == "ctrl"
776+
@test sprint(Types.print_qasm, GateModifier(:negctrl)) == "negctrl"
777+
778+
pow_mod = GateModifier(:pow, Token{:int}("2"))
779+
output = sprint(Types.print_qasm, pow_mod)
780+
@test occursin("pow", output)
781+
@test occursin("2", output)
782+
end
783+
784+
@testset "Modified gates" begin
785+
bit = Bit(Token{:id}("q"), Token{:int}("0"))
786+
inst = Instruction("h", Any[], Any[bit])
787+
mod_gate = ModifiedGate([GateModifier(:inv)], inst)
788+
789+
output = sprint(Types.print_qasm, mod_gate)
790+
@test occursin("inv", output)
791+
@test occursin("@", output)
792+
@test occursin("h", output)
793+
end
794+
795+
@testset "Input/Output declarations" begin
796+
input_decl = InputDecl(FloatType(Token{:int}("64")), Token{:id}("theta"))
797+
output = sprint(Types.print_qasm, input_decl)
798+
@test occursin("input", output)
799+
@test occursin("float[64]", output)
800+
@test occursin("theta", output)
801+
@test occursin(";", output)
802+
803+
output_decl = OutputDecl(BitType(Token{:int}("2")), Token{:id}("c"))
804+
output2 = sprint(Types.print_qasm, output_decl)
805+
@test occursin("output", output2)
806+
@test occursin("bit[2]", output2)
807+
@test occursin("c", output2)
808+
@test occursin(";", output2)
809+
end
810+
811+
# Test round-trip: parse -> print -> parse
812+
@testset "Round-trip tests" begin
813+
qasm1 = """
814+
OPENQASM 3.0;
815+
int[32] x = 5;
816+
"""
817+
ast1 = OpenQASM.parse(qasm1)
818+
printed1 = sprint(Types.print_qasm, ast1)
819+
ast1_reparsed = OpenQASM.parse(printed1)
820+
@test ast1_reparsed isa MainProgram
821+
822+
qasm2 = """
823+
OPENQASM 3.0;
824+
qubit[2] q;
825+
"""
826+
ast2 = OpenQASM.parse(qasm2)
827+
printed2 = sprint(Types.print_qasm, ast2)
828+
ast2_reparsed = OpenQASM.parse(printed2)
829+
@test ast2_reparsed isa MainProgram
830+
831+
qasm3 = """
832+
OPENQASM 3.0;
833+
input float[64] theta;
834+
output bit c;
835+
"""
836+
ast3 = OpenQASM.parse(qasm3)
837+
printed3 = sprint(Types.print_qasm, ast3)
838+
ast3_reparsed = OpenQASM.parse(printed3)
839+
@test ast3_reparsed isa MainProgram
840+
end
841+
end

0 commit comments

Comments
 (0)