bool SoftwareTimerOrderingTestCase::run_() const { constexpr auto totalSoftwareTimers = totalThreads; for (const auto& phase : priorityTestPhases) { SequenceAsserter sequenceAsserter; using TestSoftwareTimer = decltype(makeStaticSoftwareTimer(&SequenceAsserter::sequencePoint, std::ref(std::declval<SequenceAsserter&>()), std::declval<unsigned int>())); std::array<TestSoftwareTimer, totalSoftwareTimers> softwareTimers {{ makeStaticSoftwareTimer(&SequenceAsserter::sequencePoint, std::ref(sequenceAsserter), static_cast<unsigned int>(phase.first[phase.second[0]].second)), makeStaticSoftwareTimer(&SequenceAsserter::sequencePoint, std::ref(sequenceAsserter), static_cast<unsigned int>(phase.first[phase.second[1]].second)), makeStaticSoftwareTimer(&SequenceAsserter::sequencePoint, std::ref(sequenceAsserter), static_cast<unsigned int>(phase.first[phase.second[2]].second)), makeStaticSoftwareTimer(&SequenceAsserter::sequencePoint, std::ref(sequenceAsserter), static_cast<unsigned int>(phase.first[phase.second[3]].second)), makeStaticSoftwareTimer(&SequenceAsserter::sequencePoint, std::ref(sequenceAsserter), static_cast<unsigned int>(phase.first[phase.second[4]].second)), makeStaticSoftwareTimer(&SequenceAsserter::sequencePoint, std::ref(sequenceAsserter), static_cast<unsigned int>(phase.first[phase.second[5]].second)), makeStaticSoftwareTimer(&SequenceAsserter::sequencePoint, std::ref(sequenceAsserter), static_cast<unsigned int>(phase.first[phase.second[6]].second)), makeStaticSoftwareTimer(&SequenceAsserter::sequencePoint, std::ref(sequenceAsserter), static_cast<unsigned int>(phase.first[phase.second[7]].second)), makeStaticSoftwareTimer(&SequenceAsserter::sequencePoint, std::ref(sequenceAsserter), static_cast<unsigned int>(phase.first[phase.second[8]].second)), makeStaticSoftwareTimer(&SequenceAsserter::sequencePoint, std::ref(sequenceAsserter), static_cast<unsigned int>(phase.first[phase.second[9]].second)), }}; waitForNextTick(); for (size_t i = 0; i < softwareTimers.size(); ++i) softwareTimers[i].start(TickClock::duration{maxPhasePriority + 1 - phase.first[phase.second[i]].first}); if (sequenceAsserter.assertSequence(0) == false) return false; for (const auto& softwareTimer : softwareTimers) while(softwareTimer.isRunning()) { } if (sequenceAsserter.assertSequence(totalSoftwareTimers) == false) return false; } return true; }
bool CallOnceOperationsTestCase::run_() const { #if DISTORTOS_CALLONCE_SUPPORTED == 1 || DOXYGEN == 1 const auto contextSwitchCount = statistics::getContextSwitchCount(); SequenceAsserter sequenceAsserter; OnceFlag onceFlag; std::array<DynamicThread, totalThreads> threads {{ makeTestThread(testCasePriority_ - 1, sequenceAsserter, SequencePoints{0, 12}, onceFlag), makeTestThread(testCasePriority_ - 1, sequenceAsserter, SequencePoints{2, 13}, onceFlag), makeTestThread(testCasePriority_ - 1, sequenceAsserter, SequencePoints{3, 14}, onceFlag), makeTestThread(testCasePriority_ - 1, sequenceAsserter, SequencePoints{4, 15}, onceFlag), makeTestThread(testCasePriority_ - 1, sequenceAsserter, SequencePoints{5, 16}, onceFlag), makeTestThread(testCasePriority_ - 1, sequenceAsserter, SequencePoints{6, 17}, onceFlag), makeTestThread(testCasePriority_ - 1, sequenceAsserter, SequencePoints{7, 18}, onceFlag), makeTestThread(testCasePriority_ - 1, sequenceAsserter, SequencePoints{8, 19}, onceFlag), makeTestThread(testCasePriority_ - 1, sequenceAsserter, SequencePoints{9, 20}, onceFlag), makeTestThread(testCasePriority_ - 1, sequenceAsserter, SequencePoints{10, 21}, onceFlag), }}; waitForNextTick(); const auto start = TickClock::now(); for (auto& thread : threads) thread.start(); ThisThread::setPriority(testCasePriority_ - 2); bool invalidState {}; for (size_t i = 1; i < threads.size(); ++i) if (threads[i].getState() != ThreadState::BlockedOnOnceFlag) invalidState = true; for (auto& thread : threads) thread.join(); if (invalidState != false) return false; if (TickClock::now() - start != sleepForDuration + decltype(sleepForDuration){1}) return false; if (sequenceAsserter.assertSequence(totalThreads * 2 + 2) == false) return false; constexpr auto totalContextSwitches = 2 * totalThreads + 3 + waitForNextTickContextSwitchCount; if (statistics::getContextSwitchCount() - contextSwitchCount != totalContextSwitches) return false; #endif // DISTORTOS_CALLONCE_SUPPORTED == 1 || DOXYGEN == 1 return true; }
bool ThreadSleepForTestCase::run_() const { for (const auto& phase : priorityTestPhases) { SequenceAsserter sequenceAsserter; std::array<TickClock::duration, totalThreads> durationDeviations {{}}; std::array<TestThread, totalThreads> threads {{ makeTestThread(phase.first[phase.second[0]], sequenceAsserter, durationDeviations[0]), makeTestThread(phase.first[phase.second[1]], sequenceAsserter, durationDeviations[1]), makeTestThread(phase.first[phase.second[2]], sequenceAsserter, durationDeviations[2]), makeTestThread(phase.first[phase.second[3]], sequenceAsserter, durationDeviations[3]), makeTestThread(phase.first[phase.second[4]], sequenceAsserter, durationDeviations[4]), makeTestThread(phase.first[phase.second[5]], sequenceAsserter, durationDeviations[5]), makeTestThread(phase.first[phase.second[6]], sequenceAsserter, durationDeviations[6]), makeTestThread(phase.first[phase.second[7]], sequenceAsserter, durationDeviations[7]), makeTestThread(phase.first[phase.second[8]], sequenceAsserter, durationDeviations[8]), makeTestThread(phase.first[phase.second[9]], sequenceAsserter, durationDeviations[9]), }}; { architecture::InterruptMaskingLock interruptMaskingLock; // wait for beginning of next tick - test threads should be started in the same tick ThisThread::sleepFor({}); for (auto& thread : threads) thread.start(); } for (auto& thread : threads) thread.join(); if (sequenceAsserter.assertSequence(totalThreads) == false) return false; // sleepFor() always sleeps one tick longer for (const auto& durationDeviation : durationDeviations) if (durationDeviation != TickClock::duration{1}) return false; } return true; }
bool SignalsInterruptionTestCase::run_() const { const auto contextSwitchCount = statistics::getContextSwitchCount(); auto expectedContextSwitchCount = decltype(contextSwitchCount) {}; for (const auto testStepType : testStepTypes) { SequenceAsserter sequenceAsserter; // initially no signals may be pending if (ThisThread::Signals::getPendingSignalSet().getBitset().any() == true) return false; TestStepStorage testStepStorage; auto& testStep = makeTestStep(testStepType, testStepStorage, sequenceAsserter); const auto testStepRunResult = testStep.run(sequenceAsserter); const auto testStepParameters = testStep.getParameters(); testStep.~TestStep(); if (testStepRunResult == false) return false; if (sequenceAsserter.assertSequence(testStepParameters.first) == false) return false; expectedContextSwitchCount += testStepParameters.second; if (statistics::getContextSwitchCount() - contextSwitchCount != expectedContextSwitchCount) return false; } // after the test no signals may be pending if (ThisThread::Signals::getPendingSignalSet().getBitset().any() == true) return false; if (statistics::getContextSwitchCount() - contextSwitchCount != expectedContextSwitchCount) return false; return true; }
bool ThreadPriorityTestCase::run_() const { for (const auto& phase : priorityTestPhases) { SequenceAsserter sequenceAsserter; std::array<TestThread, totalThreads> threads {{ makeTestThread(phase.first[phase.second[0]], sequenceAsserter), makeTestThread(phase.first[phase.second[1]], sequenceAsserter), makeTestThread(phase.first[phase.second[2]], sequenceAsserter), makeTestThread(phase.first[phase.second[3]], sequenceAsserter), makeTestThread(phase.first[phase.second[4]], sequenceAsserter), makeTestThread(phase.first[phase.second[5]], sequenceAsserter), makeTestThread(phase.first[phase.second[6]], sequenceAsserter), makeTestThread(phase.first[phase.second[7]], sequenceAsserter), makeTestThread(phase.first[phase.second[8]], sequenceAsserter), makeTestThread(phase.first[phase.second[9]], sequenceAsserter), }}; { architecture::InterruptMaskingLock interruptMaskingLock; for (auto& thread : threads) thread.start(); } for (auto& thread : threads) thread.join(); if (sequenceAsserter.assertSequence(totalThreads) == false) return false; } return true; }
bool FifoQueuePriorityTestCase::run_() const { const auto contextSwitchCount = statistics::getContextSwitchCount(); std::remove_const<decltype(contextSwitchCount)>::type expectedContextSwitchCount {}; constexpr size_t fifoQueueTypes {2}; for (const auto& stage : stages) for (const auto& phase : priorityTestPhases) { StaticFifoQueueWrapper<totalThreads> fifoQueueWrapper; StaticRawFifoQueueWrapper<totalThreads> rawFifoQueueWrapper; using QueueWrapperHolder = estd::ReferenceHolder<const QueueWrapper>; const QueueWrapperHolder queueWrappers[fifoQueueTypes] { QueueWrapperHolder{fifoQueueWrapper}, QueueWrapperHolder{rawFifoQueueWrapper}, }; for (auto& queueWrapperHolder : queueWrappers) { auto& queueWrapper = queueWrapperHolder.get(); SequenceAsserter sequenceAsserter; const auto& threadFunction = std::get<0>(stage); std::array<TestThread, totalThreads> threads {{ makeTestThread(threadFunction, 0, phase.first[phase.second[0]], sequenceAsserter, queueWrapper), makeTestThread(threadFunction, 1, phase.first[phase.second[1]], sequenceAsserter, queueWrapper), makeTestThread(threadFunction, 2, phase.first[phase.second[2]], sequenceAsserter, queueWrapper), makeTestThread(threadFunction, 3, phase.first[phase.second[3]], sequenceAsserter, queueWrapper), makeTestThread(threadFunction, 4, phase.first[phase.second[4]], sequenceAsserter, queueWrapper), makeTestThread(threadFunction, 5, phase.first[phase.second[5]], sequenceAsserter, queueWrapper), makeTestThread(threadFunction, 6, phase.first[phase.second[6]], sequenceAsserter, queueWrapper), makeTestThread(threadFunction, 7, phase.first[phase.second[7]], sequenceAsserter, queueWrapper), makeTestThread(threadFunction, 8, phase.first[phase.second[8]], sequenceAsserter, queueWrapper), makeTestThread(threadFunction, 9, phase.first[phase.second[9]], sequenceAsserter, queueWrapper), }}; // execute Prepare if (std::get<1>(stage) != nullptr) std::get<1>(stage)(queueWrapper); bool result {true}; for (auto& thread : threads) { thread.start(); // 2 context switches: "into" the thread and "back" to main thread when test thread blocks on FIFO // queue expectedContextSwitchCount += 2; if (statistics::getContextSwitchCount() - contextSwitchCount != expectedContextSwitchCount) result = false; } if (sequenceAsserter.assertSequence(totalThreads) == false) result = false; for (size_t i = 0; i < threads.size(); ++i) { const auto triggerResult = std::get<2>(stage)(queueWrapper, i); if (triggerResult == false) result = false; // 2 context switches: into" the unblocked thread and "back" to main thread when test thread // terminates expectedContextSwitchCount += 2; if (statistics::getContextSwitchCount() - contextSwitchCount != expectedContextSwitchCount) result = false; } for (auto& thread : threads) thread.join(); // execute FinalCheck if (std::get<3>(stage) != nullptr && std::get<3>(stage)(queueWrapper) == false) result = false; if (result == false || sequenceAsserter.assertSequence(totalThreads * 2) == false) return false; } } if (statistics::getContextSwitchCount() - contextSwitchCount != 2 * 4 * totalThreads * priorityTestPhases.size() * fifoQueueTypes) return false; return true; }
bool ThreadSleepUntilTestCase::run_() const { const auto allocatedMemory = mallinfo().uordblks; for (const auto& phase : priorityTestPhases) { { SequenceAsserter sequenceAsserter; std::array<TickClock::duration, totalThreads> timePointDeviations {{}}; std::array<int, totalThreads> sharedRets {{}}; const auto now = TickClock::now(); std::array<DynamicThread, totalThreads> threads {{ makeTestThread(now, phase.first[phase.second[0]], sequenceAsserter, timePointDeviations[0], sharedRets[0]), makeTestThread(now, phase.first[phase.second[1]], sequenceAsserter, timePointDeviations[1], sharedRets[1]), makeTestThread(now, phase.first[phase.second[2]], sequenceAsserter, timePointDeviations[2], sharedRets[2]), makeTestThread(now, phase.first[phase.second[3]], sequenceAsserter, timePointDeviations[3], sharedRets[3]), makeTestThread(now, phase.first[phase.second[4]], sequenceAsserter, timePointDeviations[4], sharedRets[4]), makeTestThread(now, phase.first[phase.second[5]], sequenceAsserter, timePointDeviations[5], sharedRets[5]), makeTestThread(now, phase.first[phase.second[6]], sequenceAsserter, timePointDeviations[6], sharedRets[6]), makeTestThread(now, phase.first[phase.second[7]], sequenceAsserter, timePointDeviations[7], sharedRets[7]), makeTestThread(now, phase.first[phase.second[8]], sequenceAsserter, timePointDeviations[8], sharedRets[8]), makeTestThread(now, phase.first[phase.second[9]], sequenceAsserter, timePointDeviations[9], sharedRets[9]), }}; { architecture::InterruptMaskingLock interruptMaskingLock; for (auto& thread : threads) thread.start(); } bool invalidState {}; for (const auto& thread : threads) if (thread.getState() != ThreadState::sleeping) invalidState = true; for (auto& thread : threads) thread.join(); if (invalidState != false) return false; if (sequenceAsserter.assertSequence(totalThreads) == false) return false; for (const auto& timePointDeviation : timePointDeviations) if (timePointDeviation != TickClock::duration{}) return false; for (const auto& sharedRet : sharedRets) if (sharedRet != 0) return false; } if (mallinfo().uordblks != allocatedMemory) // dynamic memory must be deallocated after each test phase return false; } return true; }
bool MutexPriorityTestCase::run_() const { using Parameters = std::tuple<Mutex::Type, Mutex::Protocol, uint8_t>; static const Parameters parametersArray[] { Parameters{Mutex::Type::normal, Mutex::Protocol::none, {}}, Parameters{Mutex::Type::normal, Mutex::Protocol::priorityProtect, UINT8_MAX}, Parameters{Mutex::Type::normal, Mutex::Protocol::priorityInheritance, {}}, Parameters{Mutex::Type::errorChecking, Mutex::Protocol::none, {}}, Parameters{Mutex::Type::errorChecking, Mutex::Protocol::priorityProtect, UINT8_MAX}, Parameters{Mutex::Type::errorChecking, Mutex::Protocol::priorityInheritance, {}}, Parameters{Mutex::Type::recursive, Mutex::Protocol::none, {}}, Parameters{Mutex::Type::recursive, Mutex::Protocol::priorityProtect, UINT8_MAX}, Parameters{Mutex::Type::recursive, Mutex::Protocol::priorityInheritance, {}}, }; for (const auto& parameters : parametersArray) for (const auto& phase : priorityTestPhases) { SequenceAsserter sequenceAsserter; Mutex mutex {std::get<0>(parameters), std::get<1>(parameters), std::get<2>(parameters)}; std::array<DynamicThread, totalThreads> threads {{ makeTestThread(phase.first[phase.second[0]], sequenceAsserter, mutex), makeTestThread(phase.first[phase.second[1]], sequenceAsserter, mutex), makeTestThread(phase.first[phase.second[2]], sequenceAsserter, mutex), makeTestThread(phase.first[phase.second[3]], sequenceAsserter, mutex), makeTestThread(phase.first[phase.second[4]], sequenceAsserter, mutex), makeTestThread(phase.first[phase.second[5]], sequenceAsserter, mutex), makeTestThread(phase.first[phase.second[6]], sequenceAsserter, mutex), makeTestThread(phase.first[phase.second[7]], sequenceAsserter, mutex), makeTestThread(phase.first[phase.second[8]], sequenceAsserter, mutex), makeTestThread(phase.first[phase.second[9]], sequenceAsserter, mutex), }}; mutex.lock(); { architecture::InterruptMaskingLock interruptMaskingLock; for (auto& thread : threads) { thread.start(); // make sure each test threads blocks on mutex in the order of starting, even if current thread // inherits test thread's high priority ThisThread::sleepFor(TickClock::duration{1}); } } bool invalidState {}; for (const auto& thread : threads) if (thread.getState() != ThreadState::blockedOnMutex) invalidState = true; mutex.unlock(); for (auto& thread : threads) thread.join(); if (invalidState != false) return false; if (sequenceAsserter.assertSequence(totalThreads) == false) return false; } return true; }