| 825 | |
| 826 | template <NumQubitsFlag Ctrls, NumQubitsFlag Targs, ArgsFlag Args, ApplyFlag Apply> |
| 827 | void testOperationValidation(auto operation) { |
| 828 | |
| 829 | // use any cached Qureg (though postMultiply*() functions accept only density matrices) |
| 830 | Qureg qureg = getCachedDensmatrs().begin()->second; |
| 831 | |
| 832 | // in lieu of preparing random inputs like testOperationCorrectness() |
| 833 | // above, we instead obtain simple, fixed, compatible inputs |
| 834 | auto [ctrls,states,targs] = getFixedCtrlsStatesTargs<Ctrls,Targs,Args>(qureg.numQubits); |
| 835 | auto furtherArgs = getFixedRemainingArgs<Targs,Args>(targs); |
| 836 | |
| 837 | // calling apiFunc() will pass the above args with their call-time values |
| 838 | auto apiFunc = [&]() { |
| 839 | constexpr NumQubitsFlag RevTargs = (Args==paulistr||Args==pauligad)? zero : Targs; |
| 840 | auto func = [](auto&&... allArgs) { return invokeApiOperation<Ctrls,RevTargs>(allArgs...); }; |
| 841 | std::apply(func, std::tuple_cat(tuple{operation, qureg, ctrls, states, targs}, furtherArgs)); |
| 842 | }; |
| 843 | |
| 844 | // convenience vars |
| 845 | int numQubits = qureg.numQubits; |
| 846 | int numTargs = (int) targs.size(); |
| 847 | int numCtrls = (int) ctrls.size(); |
| 848 | |
| 849 | /// @todo |
| 850 | /// below, we return from intendedly skipped SECTIONS which |
| 851 | /// appears to work (does not corrupt test statistics, and |
| 852 | /// does not attribute skipped tests to having passed the |
| 853 | /// section) but is an undocumented Catch2 trick. Check safe! |
| 854 | |
| 855 | SECTION( "qureg uninitialised" ) { |
| 856 | |
| 857 | // spoof uninitialised value |
| 858 | qureg.numQubits = -123; |
| 859 | REQUIRE_THROWS_WITH( apiFunc(), ContainsSubstring("invalid Qureg") ); |
| 860 | } |
| 861 | |
| 862 | SECTION( "invalid target" ) { |
| 863 | |
| 864 | // not applicable (PauliStr already made from targs) |
| 865 | if (Args == paulistr || Args == pauligad) |
| 866 | return; |
| 867 | |
| 868 | // sabotage a target |
| 869 | int ind = GENERATE_COPY( range(0,numTargs) ); |
| 870 | int val = GENERATE_COPY( -1, numQubits ); |
| 871 | targs[ind] = val; |
| 872 | |
| 873 | REQUIRE_THROWS_WITH( apiFunc(), ContainsSubstring("Invalid target qubit") ); |
| 874 | } |
| 875 | |
| 876 | SECTION( "invalid non-Identity Pauli index" ) { |
| 877 | |
| 878 | if (Args != paulistr && Args != pauligad) |
| 879 | return; |
| 880 | |
| 881 | PauliStr badStr = getPauliStr("X", {numQubits + 1}); |
| 882 | if constexpr (Args == paulistr) furtherArgs = tuple{ badStr }; |
| 883 | if constexpr (Args == pauligad) furtherArgs = tuple{ badStr, 1 }; |
| 884 |
nothing calls this directly
no test coverage detected