diff --git a/tests/executables_src/testPropagateDataFaultFlag.cc b/tests/executables_src/testPropagateDataFaultFlag.cc index 85b15af211f6499d83de1f37bc30594001d19979..7ebfc582af7ecb0b18c8c893c31f618122c3eeb2 100644 --- a/tests/executables_src/testPropagateDataFaultFlag.cc +++ b/tests/executables_src/testPropagateDataFaultFlag.cc @@ -557,6 +557,9 @@ struct Fixture_noTestableMode { ChimeraTK::BackendFactory::getInstance().createBackend(TestApplication3::ExceptionDummyCDD1))), device2DummyBackend(boost::dynamic_pointer_cast<ctk::ExceptionDummy>( ChimeraTK::BackendFactory::getInstance().createBackend(TestApplication3::ExceptionDummyCDD2))) { + auto device1Status = + test.getScalar<int32_t>(ctk::RegisterPath("/Devices") / TestApplication3::ExceptionDummyCDD1 / "status"); + device1DummyBackend->open(); device2DummyBackend->open(); @@ -567,6 +570,7 @@ struct Fixture_noTestableMode { test.setScalarDefault("m1/o1", DEFAULT); test.runApplication(); + CHECK_EQUAL_TIMEOUT((device1Status.readLatest(), device1Status), 0, 100000); // Making sure the default is written to the device before proceeding. auto m1o1 = device1DummyBackend->getRegisterAccessor<int>("m1/o1", 1, 0, false); @@ -594,6 +598,9 @@ BOOST_AUTO_TEST_CASE(testDeviceReadFailure) { auto threadedFanoutInput = test.getScalar<int>("m1/o1"); auto result = test.getScalar<int>("m1/Module1_result"); + auto device2Status = + test.getScalar<int32_t>(ctk::RegisterPath("/Devices") / TestApplication3::ExceptionDummyCDD2 / "status"); + threadedFanoutInput = 10000; consumingFanoutSource = 1000; pollRegister = 1; @@ -607,29 +614,40 @@ BOOST_AUTO_TEST_CASE(testDeviceReadFailure) { // -------------------------------------------------------------// // device module exception + threadedFanoutInput = 20000; pollRegister = 0; device2DummyBackend->throwExceptionRead = true; threadedFanoutInput.write(); - // when the error detected the old value is written with faulty flag + // The new value from the fanout input should have been propagated, + // the new value of the poll input is not seen, because it gets skipped result.read(); - BOOST_CHECK_EQUAL(result, 11001); + BOOST_CHECK_EQUAL(result, 21001); BOOST_CHECK(result.dataValidity() == ctk::DataValidity::faulty); // -------------------------------------------------------------// + + threadedFanoutInput = 30000; + threadedFanoutInput.write(); + // Further reads to the poll input are skipped + result.read(); + BOOST_CHECK_EQUAL(result, 31001); + BOOST_CHECK(result.dataValidity() == ctk::DataValidity::faulty); + + // -------------------------------------------------------------// + // recovery from device module exception device2DummyBackend->throwExceptionRead = false; - // When the device recovers, the old value is written with ok flag - // It might be that the main loop does not write the value each time, so it has - // to be done once so the data does not stay invalid. - result.read(); - BOOST_CHECK_EQUAL(result, 11001); - BOOST_CHECK(result.dataValidity() == ctk::DataValidity::ok); + CHECK_EQUAL_TIMEOUT((device2Status.readLatest(), device2Status), 0, 100000); - // finally the loop runs though and propagates the new value + threadedFanoutInput = 40000; + threadedFanoutInput.write(); result.read(); - BOOST_CHECK_EQUAL(result, 11000); + // Now we expect also the last value written to the pollRegister being + // propagated and the DataValidity should be ok again. + BOOST_CHECK_EQUAL(result, 41000); + BOOST_CHECK(result.dataValidity() == ctk::DataValidity::ok); } BOOST_AUTO_TEST_CASE(testReadDeviceWithTrigger) { @@ -786,26 +804,16 @@ BOOST_AUTO_TEST_CASE(testDataFlowOnDeviceException) { // Now the device has to go into the error state CHECK_EQUAL_TIMEOUT((deviceStatus.readLatest(), deviceStatus), 1, 10000); - // The data is propagated once more to make sure the invaldi flag goes through (in this case it already was invalid, but - // cannot be nown by the code, see testDataValidPropagationOnException. + // The new value of the threadedFanoutInput should be propagated, the + // pollRegister is skipped, see testDataValidPropagationOnException. m1_result.read(); - // FIXME: The correct behaviour according to the new spec is that the new value of threadedFanoutInput is already processed. - //BOOST_CHECK_EQUAL(m1_result, 1100); - BOOST_CHECK_EQUAL(m1_result, 1101); + BOOST_CHECK_EQUAL(m1_result, 1100); BOOST_CHECK(m1_result.dataValidity() == ctk::DataValidity::faulty); m2_result.read(); - // FIXME: The correct behaviour according to the new spec is that the new value of threadedFanoutInput is already processed. - //BOOST_CHECK_EQUAL(m2_result, 1100); - BOOST_CHECK_EQUAL(m2_result, 1101); + // Same for m2 + BOOST_CHECK_EQUAL(m2_result, 1100); BOOST_CHECK(m2_result.dataValidity() == ctk::DataValidity::faulty); - // Trigger the loop another time. Now the execution is blocked - threadedFanoutInput = 2; - threadedFanoutInput.write(); - - // The result of m1 must not be written out again. We can't test this at this safely here. - // Instead, we know that the next read after recovery will already contain the new data. - // ---------------------------------------------------------------------// // device exception recovery device2DummyBackend->throwExceptionRead = false; @@ -816,26 +824,14 @@ BOOST_AUTO_TEST_CASE(testDataFlowOnDeviceException) { // nothing else in the queue BOOST_CHECK(deviceStatus.readNonBlocking() == false); - /////////////////// FIXME: This is old behaviour and will go away with proper implementation of the spec////////////////// - - // After recovering the old data has been written once, still with invalid because the fan input is still invalid - m1_result.read(); - BOOST_CHECK_EQUAL(m1_result, 1101); - BOOST_CHECK(m1_result.dataValidity() == ctk::DataValidity::faulty); - m2_result.read(); - BOOST_CHECK_EQUAL(m2_result, 1101); - BOOST_CHECK(m2_result.dataValidity() == ctk::DataValidity::faulty); + // ---------------------------------------------------------------------// + // Now both, threadedFanoutInput and pollRegister should propagate + pollRegister = 300; + threadedFanoutInput = 2; + threadedFanoutInput.write(); - // Now the data for threadedFanoutInput = 0 is propagated. In the new spec this was already done above m1_result.read(); - BOOST_CHECK_EQUAL(m1_result, 1200); - m2_result.read(); - BOOST_CHECK_EQUAL(m2_result, 1200); - - /////////////////// END OF FIXME: old behaviour /////////////////////////////////////////////////// - - m1_result.read(); // we know there must be exaclty one value being written. Wait for it. - BOOST_CHECK_EQUAL(m1_result, 1202); + BOOST_CHECK_EQUAL(m1_result, 1302); // Data validity still faulty because the input from the fan is invalid BOOST_CHECK(m1_result.dataValidity() == ctk::DataValidity::faulty); // again, nothing else in the queue @@ -843,7 +839,7 @@ BOOST_AUTO_TEST_CASE(testDataFlowOnDeviceException) { // same for m2 m2_result.read(); - BOOST_CHECK_EQUAL(m2_result, 1202); + BOOST_CHECK_EQUAL(m2_result, 1302); BOOST_CHECK(m2_result.dataValidity() == ctk::DataValidity::faulty); BOOST_CHECK(m2_result.readNonBlocking() == false); @@ -854,12 +850,12 @@ BOOST_AUTO_TEST_CASE(testDataFlowOnDeviceException) { threadedFanoutInput.write(); m1_result.read(); - BOOST_CHECK_EQUAL(m1_result, 1203); + BOOST_CHECK_EQUAL(m1_result, 1303); BOOST_CHECK(m1_result.dataValidity() == ctk::DataValidity::ok); BOOST_CHECK(m1_result.readNonBlocking() == false); m2_result.read(); - BOOST_CHECK_EQUAL(m2_result, 1203); + BOOST_CHECK_EQUAL(m2_result, 1303); BOOST_CHECK(m2_result.dataValidity() == ctk::DataValidity::ok); BOOST_CHECK(m1_result.readNonBlocking() == false); } @@ -936,45 +932,80 @@ BOOST_AUTO_TEST_CASE(testDataValidPropagationOnException) { device2DummyBackend->throwExceptionRead = true; pushInput.write(); - // Output should be rewritten exactly once and the data valditity should be propagated CHECK_EQUAL_TIMEOUT((deviceStatus.readLatest(), deviceStatus), 1, 10000); result.read(); BOOST_CHECK(result.readLatest() == false); - // FIXME: This is olde behaviour: - BOOST_CHECK_EQUAL(result, 11); - // According to the new spec the new value for the push input should have been propagated already: - //BOOST_CHECK_EQUAL(result, 21); + // The new data from the pushInput and the DataValidity::faulty should have been propagated to the outout, + // the pollRegister should be skipped (Exceptionhandling spec B.2.2.3), so we don't expect the latest assigned value of 2 + BOOST_CHECK_EQUAL(result, 21); BOOST_CHECK(result.dataValidity() == ctk::DataValidity::faulty); - // triggering once more does not produce any output until the device has recovered + // Writeing the pushInput should still trigger module execution and + // update the result value. Result validity should still be faulty because + // the device still has the exception pushInput = 30; pushInput.setDataValidity(ctk::DataValidity::ok); pushInput.write(); - // just a short sleep, waiting for nothing. We will test below that there was nothing when the device recovers - sleep(1); - BOOST_CHECK(result.readLatest() == false); + result.read(); + BOOST_CHECK_EQUAL(result, 31); + BOOST_CHECK(result.dataValidity() == ctk::DataValidity::faulty); + // let the device recover + device2DummyBackend->throwExceptionRead = false; + CHECK_EQUAL_TIMEOUT((deviceStatus.readLatest(), deviceStatus), 0, 10000); + + // Everything should be back to normal, also the value of the pollRegister + // should be reflected in the output + pushInput = 40; pollRegister = 3; - device2DummyBackend->throwExceptionRead = false; // let the device recover + pushInput.write(); + result.read(); + BOOST_CHECK_EQUAL(result, 43); + BOOST_CHECK(result.dataValidity() == ctk::DataValidity::ok); + // nothing more in the queue + BOOST_CHECK(result.readLatest() == false); - // the 2 from the poll register is never seen... + // Check if we get faulty output from the exception alone, + // keep pushInput ok + pollRegister = 4; + pushInput = 50; + device2DummyBackend->throwExceptionRead = true; - // /////////////////////////// FIXME: old behaviour. This will go away with the new spec - // The original data is written again, still with faulty as the push input was faulty as well + pushInput.write(); result.read(); - BOOST_CHECK_EQUAL(result, 11); + BOOST_CHECK(result.readLatest() == false); + // The new data from the pushInput, the device exception should yield DataValidity::faulty at the outout, + BOOST_CHECK_EQUAL(result, 53); BOOST_CHECK(result.dataValidity() == ctk::DataValidity::faulty); - // The 20 at the push input is propagated (together with its faulty flag). It already sees the new value from the poll type - // It's good that this goes away. This combination was never at the souces at the same time. + + // Also set pushInputValidity to faulty + pushInput = 60; + pushInput.setDataValidity(ctk::DataValidity::faulty); + pushInput.write(); result.read(); - BOOST_CHECK_EQUAL(result, 23); + BOOST_CHECK_EQUAL(result, 63); BOOST_CHECK(result.dataValidity() == ctk::DataValidity::faulty); - // /////////////////////////// END OF FIXME: old behaviour + // let the device recover + device2DummyBackend->throwExceptionRead = false; + CHECK_EQUAL_TIMEOUT((deviceStatus.readLatest(), deviceStatus), 0, 10000); + + // The new pollRegister value should now be reflected in the result, + // but it's still faulty from the pushInput + pushInput = 70; + pollRegister = 5; + pushInput.write(); + result.read(); + BOOST_CHECK_EQUAL(result, 75); + BOOST_CHECK(result.dataValidity() == ctk::DataValidity::faulty); - // The new, good value arrives + // MAke pushInput ok, everything should be back to normal + pushInput = 80; + pushInput.setDataValidity(ctk::DataValidity::ok); + pollRegister = 6; + pushInput.write(); result.read(); - BOOST_CHECK_EQUAL(result, 33); + BOOST_CHECK_EQUAL(result, 86); BOOST_CHECK(result.dataValidity() == ctk::DataValidity::ok); // nothing more in the queue BOOST_CHECK(result.readLatest() == false);