Skip to content

Commit

Permalink
test: ✅ Add and update tests to increase coverage (#18)
Browse files Browse the repository at this point in the history
* test: ✅ Add and update tests to increase coverage

* fix: 🐛 Fix incorrect test

* style: ♻️ Fix linter issues

* test: ✅ Add test for situation where user requests 0 problem causes from diagnostics
  • Loading branch information
DRovara authored Sep 4, 2024
1 parent 2204fe5 commit 4b326b4
Show file tree
Hide file tree
Showing 13 changed files with 369 additions and 13 deletions.
14 changes: 9 additions & 5 deletions src/backend/dd/DDSimDebug.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -250,9 +250,6 @@ Result ddsimStepOutBackward(SimulationState* self) {
const auto size = ddsim->callReturnStack.size();
Result res = OK;
while ((res = self->stepBackward(self)) == OK) {
if (self->wasBreakpointHit(self)) {
break;
}
if (self->wasBreakpointHit(self)) {
break;
}
Expand Down Expand Up @@ -513,6 +510,9 @@ Result ddsimRunAll(SimulationState* self, size_t* failedAssertions) {

Result ddsimRunSimulation(SimulationState* self) {
auto* ddsim = toDDSimulationState(self);
if (!self->canStepForward(self)) {
return ERROR;
}
while (!self->isFinished(self)) {
if (ddsim->paused) {
ddsim->paused = false;
Expand All @@ -531,6 +531,9 @@ Result ddsimRunSimulation(SimulationState* self) {

Result ddsimRunSimulationBackward(SimulationState* self) {
auto* ddsim = toDDSimulationState(self);
if (!self->canStepBackward(self)) {
return ERROR;
}
while (self->canStepBackward(self)) {
if (ddsim->paused) {
ddsim->paused = false;
Expand Down Expand Up @@ -570,12 +573,13 @@ Result ddsimPauseSimulation(SimulationState* self) {

bool ddsimCanStepForward(SimulationState* self) {
auto* ddsim = toDDSimulationState(self);
return ddsim->currentInstruction < ddsim->instructionTypes.size();
return ddsim->ready &&
ddsim->currentInstruction < ddsim->instructionTypes.size();
}

bool ddsimCanStepBackward(SimulationState* self) {
auto* ddsim = toDDSimulationState(self);
return !ddsim->previousInstructionStack.empty();
return ddsim->ready && !ddsim->previousInstructionStack.empty();
}

bool ddsimIsFinished(SimulationState* self) {
Expand Down
8 changes: 8 additions & 0 deletions src/backend/dd/DDSimDiagnostics.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -152,6 +152,10 @@ size_t tryFindMissingInteraction(DDDiagnostics* diagnostics,
DDSimulationState* state, size_t instruction,
const std::unique_ptr<Assertion>& assertion,
ErrorCause* output, size_t count) {
if (count == 0) {
return 0;
}

auto targets = assertion->getTargetQubits();
auto outputs = Span(output, count);
std::vector<size_t> targetQubits(targets.size());
Expand Down Expand Up @@ -191,6 +195,10 @@ size_t tryFindMissingInteraction(DDDiagnostics* diagnostics,

size_t tryFindZeroControls(DDDiagnostics* diagnostics, size_t instruction,
ErrorCause* output, size_t count) {
if (count == 0) {
return 0;
}

std::vector<uint8_t> dependencies(
diagnostics->interface.getInstructionCount(&diagnostics->interface));
diagnostics->interface.getDataDependencies(
Expand Down
5 changes: 3 additions & 2 deletions src/common/parsing/AssertionParsing.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -85,7 +85,7 @@ Complex parseComplex(std::string complexString) {
double real = 0;
double imaginary = 0;
for (auto& part : parts) {
if (part.find('i') != std::string::npos &&
if (part.find('i') != std::string::npos ||
part.find('j') != std::string::npos) {
imaginary +=
std::stod(replaceString(replaceString(part, "i", ""), "j", ""));
Expand Down Expand Up @@ -151,7 +151,8 @@ std::unique_ptr<Assertion> parseAssertion(std::string assertionString,
} catch (const std::invalid_argument& e) {
similarityThreshold = 1.0;
} catch (const std::out_of_range& e) {
similarityThreshold = 1.0;
throw ParsingError(
"Similarity threshold out of range. It must be between 0 and 1");
}

if (blockContent.find(';') == std::string::npos) {
Expand Down
3 changes: 1 addition & 2 deletions src/common/parsing/CodePreprocessing.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,6 @@
#include <map>
#include <memory>
#include <set>
#include <stdexcept>
#include <string>
#include <utility>
#include <vector>
Expand Down Expand Up @@ -204,7 +203,7 @@ preprocessCode(const std::string& code, size_t startIndex,

if (isFunctionDefinition(line)) {
if (!block.valid) {
throw std::runtime_error("Gate definitions require a body block");
throw ParsingError("Gate definitions require a body block");
}
const auto f = parseFunctionDefinition(line);
functionDefinitions.insert({f.name, f});
Expand Down
6 changes: 6 additions & 0 deletions test/circuits/failing-assertions-multiple-causes.qasm
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
qreg q[5]; // 0

cx q[0], q[1]; // 1
cx q[0], q[2]; // 2

assert-ent q[0], q[1], q[2], q[3], q[4]; // 3 (fails)
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
qreg q[5]; // 0

h q[0]; // 1

assert-ent q[0], q[1], q[2], q[3], q[4]; // 2 (fails)
7 changes: 7 additions & 0 deletions test/circuits/failing-assertions-multiple-zero-controls.qasm
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
qreg q[4]; // 0

cx q[0], q[1]; // 1
cx q[0], q[2]; // 2
cx q[0], q[3]; // 3

assert-ent q[0], q[1], q[2], q[3]; // 4 (fails)
90 changes: 88 additions & 2 deletions test/test_custom_code.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,8 @@ class CustomCodeTest : public testing::Test {
std::string userCode;
size_t offset = 0;

void loadCode(size_t numQubits, size_t numClassics, const char* code) {
void loadCode(size_t numQubits, size_t numClassics, const char* code,
bool shouldFail = false) {
if (numQubits < 1) {
numQubits = 1;
}
Expand All @@ -41,7 +42,8 @@ class CustomCodeTest : public testing::Test {

userCode = code;
fullCode = ss.str();
state->loadCode(state, fullCode.c_str());
ASSERT_EQ(state->loadCode(state, fullCode.c_str()),
shouldFail ? ERROR : OK);
}

void forwardTo(size_t instruction) {
Expand All @@ -68,6 +70,8 @@ TEST_F(CustomCodeTest, ClassicControlledOperation) {
state->getStateVectorFull(state, &sv);
ASSERT_TRUE(complexEquality(amplitudes[0], 1, 0.0) ||
complexEquality(amplitudes[1], 1, 0.0));

ASSERT_EQ(state->stepBackward(state), OK);
}

TEST_F(CustomCodeTest, ResetGate) {
Expand Down Expand Up @@ -167,3 +171,85 @@ TEST_F(CustomCodeTest, LegalSubstateCircuitEqualityAssertion) {
ASSERT_EQ(state->runAll(state, &numErrors), OK);
ASSERT_EQ(numErrors, 0);
}

TEST_F(CustomCodeTest, ErrorInCode) {
loadCode(3, 0, "x f[0];", true);
size_t numErrors = 0;
ASSERT_EQ(state->runAll(state, &numErrors), ERROR);
ASSERT_EQ(numErrors, 0);
ASSERT_EQ(state->runSimulation(state), ERROR);
ASSERT_EQ(state->runSimulationBackward(state), ERROR);
}

TEST_F(CustomCodeTest, StackTraceErrorInCode) {
loadCode(3, 0, "x f[0];", true);
size_t depth = 0;
ASSERT_EQ(state->getStackDepth(state, &depth), ERROR);
ASSERT_EQ(state->getStackTrace(state, 10, nullptr), ERROR);
}

TEST_F(CustomCodeTest, ErrorAssertionInCircuitEqualityAssertion) {
loadCode(3, 0,
"x q[0];"
"assert-eq q[0], q[1], q[2] { qreg q[3]; assert-sup q[0]; }");
ASSERT_EQ(state->runAll(state, nullptr), ERROR);
}

TEST_F(CustomCodeTest, BarrierInstruction) {
loadCode(1, 0,
"barrier;"
"x q[0];");
ASSERT_EQ(state->stepForward(state), OK);
ASSERT_EQ(state->stepForward(state), OK);

ASSERT_EQ(state->stepForward(state), OK);
ASSERT_EQ(state->stepBackward(state), OK);
ASSERT_EQ(state->stepOverForward(state), OK);
ASSERT_EQ(state->stepOverBackward(state), OK);
}

TEST_F(CustomCodeTest, ErrorAssertionInvalidIndex) {
loadCode(3, 0,
"x q[0];"
"assert-sup q[3];");
ASSERT_EQ(state->runAll(state, nullptr), ERROR);
}

TEST_F(CustomCodeTest, ErrorAssertionInvalidQubit) {
loadCode(3, 0,
"x q[0];"
"assert-sup f[3];");
ASSERT_EQ(state->runAll(state, nullptr), ERROR);
}

TEST_F(CustomCodeTest, AssertionInCustomGate) {
loadCode(3, 0,
"gate test q0 {"
"h q0;"
"assert-sup q0;"
"}"
"test q[0];");
size_t errors = 0;
ASSERT_EQ(state->runAll(state, &errors), OK);
ASSERT_EQ(errors, 0);
}

TEST_F(CustomCodeTest, AssertionInCustomGateShadowing) {
loadCode(3, 0,
"gate test q {"
"h q;"
"assert-sup q;"
"}"
"test q[0];");
size_t errors = 0;
ASSERT_EQ(state->runAll(state, &errors), OK);
ASSERT_EQ(errors, 0);
}

TEST_F(CustomCodeTest, CommentAtEnd) {
loadCode(3, 0, "x q[0]; // Comment");
size_t errors = 0;
ASSERT_EQ(state->runAll(state, &errors), OK);
ASSERT_EQ(errors, 0);
ASSERT_EQ(state->getCurrentInstruction(state), 3);
}
13 changes: 13 additions & 0 deletions test/test_data_retrieval.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -174,3 +174,16 @@ TEST_F(DataRetrievalTest, GetStateVectorSub) {
ASSERT_TRUE(complexEquality(amplitudes[2], 0.0, 0.0));
ASSERT_TRUE(complexEquality(amplitudes[3], 0.0, 0.0));
}

TEST_F(DataRetrievalTest, GetUnknownClassicalVariable) {
Variable v;

forwardTo(6);
ASSERT_EQ(state->getClassicalVariable(state, "u[0]", &v), ERROR);
}

TEST_F(DataRetrievalTest, GetBadClassicalVariableName) {
std::array<char, 256> name = {0};
forwardTo(6);
ASSERT_EQ(state->getClassicalVariableName(state, 5, name.data()), ERROR);
}
78 changes: 78 additions & 0 deletions test/test_diagnostics.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@
#include <map>
#include <set>
#include <string>
#include <utility>
#include <vector>

class DiagnosticsTest : public testing::Test {
Expand Down Expand Up @@ -72,6 +73,18 @@ TEST_F(DiagnosticsTest, ControlAlwaysZeroTest) {
ASSERT_EQ(problems[0].instruction, 4);
}

TEST_F(DiagnosticsTest, MaximumControlAlwaysZeroTest) {
loadFromFile("failing-assertions-multiple-zero-controls");
state->runSimulation(state);
std::array<ErrorCause, 10> problems{};
ASSERT_EQ(diagnostics->potentialErrorCauses(diagnostics, problems.data(), 10),
3);
ASSERT_EQ(diagnostics->potentialErrorCauses(diagnostics, problems.data(), 3),
3);
ASSERT_EQ(diagnostics->potentialErrorCauses(diagnostics, problems.data(), 2),
2);
}

TEST_F(DiagnosticsTest, MissingInteraction) {
loadFromFile("failing-assertions-missing-interaction");
state->runSimulation(state);
Expand All @@ -83,3 +96,68 @@ TEST_F(DiagnosticsTest, MissingInteraction) {
ASSERT_EQ(problems[0].type, ErrorCauseType::MissingInteraction);
ASSERT_EQ(problems[0].instruction, 7);
}

TEST_F(DiagnosticsTest, MaximumMissingInteraction) {
loadFromFile("failing-assertions-multiple-missing-interaction");
state->runSimulation(state);
ASSERT_EQ(state->getCurrentInstruction(state), 2);
std::array<ErrorCause, 20> problems{};
ASSERT_EQ(diagnostics->potentialErrorCauses(diagnostics, problems.data(), 20),
10);
ASSERT_EQ(diagnostics->potentialErrorCauses(diagnostics, problems.data(), 10),
10);
ASSERT_EQ(diagnostics->potentialErrorCauses(diagnostics, problems.data(), 3),
3);
}

TEST_F(DiagnosticsTest, MaximumMultipleCauses) {
loadFromFile("failing-assertions-multiple-causes");
state->runSimulation(state);
ASSERT_EQ(state->getCurrentInstruction(state), 3);
std::array<ErrorCause, 20> problems{};
const std::vector<size_t> maxErrors = {20, 8, 7, 4};
const std::vector<std::pair<size_t, std::vector<ErrorCauseType>>>
expectedTypes = {
{9,
{MissingInteraction, MissingInteraction, MissingInteraction,
MissingInteraction, MissingInteraction, MissingInteraction,
MissingInteraction, ControlAlwaysZero, ControlAlwaysZero}},
{8,
{MissingInteraction, MissingInteraction, MissingInteraction,
MissingInteraction, MissingInteraction, MissingInteraction,
MissingInteraction, ControlAlwaysZero}},
{7,
{MissingInteraction, MissingInteraction, MissingInteraction,
MissingInteraction, MissingInteraction, MissingInteraction,
MissingInteraction}},
{4,
{MissingInteraction, MissingInteraction, MissingInteraction,
MissingInteraction}},
};
for (size_t i = 0; i < maxErrors.size(); i++) {
const auto [expectedCount, types] = expectedTypes[i];
ASSERT_EQ(diagnostics->potentialErrorCauses(diagnostics, problems.data(),
maxErrors[i]),
expectedCount);
for (size_t j = 0; j < expectedCount; j++) {
ASSERT_EQ(problems.at(j).type, types[j]);
}
}
}

TEST_F(DiagnosticsTest, NoFailedAssertions) {
loadFromFile("complex-jumps");
state->runSimulation(state);
std::array<ErrorCause, 5> problems{};
ASSERT_EQ(diagnostics->potentialErrorCauses(diagnostics, problems.data(), 5),
0);
}

TEST_F(DiagnosticsTest, RequestZeroProblems) {
loadFromFile("failing-assertions");
state->runSimulation(state);
std::array<ErrorCause, 10> problems{};
const size_t count =
diagnostics->potentialErrorCauses(diagnostics, problems.data(), 0);
ASSERT_EQ(count, 0);
}
Loading

0 comments on commit 4b326b4

Please sign in to comment.