vtk-m/vtkm/cont/testing/UnitTestTimer.cxx
2020-05-13 13:00:40 -04:00

151 lines
4.3 KiB
C++

//============================================================================
// Copyright (c) Kitware, Inc.
// All rights reserved.
// See LICENSE.txt for details.
//
// This software is distributed WITHOUT ANY WARRANTY; without even
// the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
// PURPOSE. See the above copyright notice for more information.
//============================================================================
#include <vtkm/cont/DeviceAdapterList.h>
#include <vtkm/cont/RuntimeDeviceTracker.h>
#include <vtkm/cont/Timer.h>
#include <vtkm/cont/testing/Testing.h>
#include <chrono>
#include <thread>
namespace
{
using TimerTestDevices =
vtkm::ListAppend<VTKM_DEFAULT_DEVICE_ADAPTER_LIST, vtkm::List<vtkm::cont::DeviceAdapterTagAny>>;
constexpr long long waitTimeMilliseconds = 5;
struct Waiter
{
std::chrono::high_resolution_clock::time_point Start = std::chrono::high_resolution_clock::now();
long long ExpectedTimeMilliseconds = 0;
vtkm::Float64 Wait()
{
// Update when we want to wait to.
this->ExpectedTimeMilliseconds += waitTimeMilliseconds;
vtkm::Float64 expectedTimeSeconds = vtkm::Float64(this->ExpectedTimeMilliseconds) / 1000;
long long elapsedMilliseconds = std::chrono::duration_cast<std::chrono::milliseconds>(
std::chrono::high_resolution_clock::now() - this->Start)
.count();
long long millisecondsToSleep = this->ExpectedTimeMilliseconds - elapsedMilliseconds;
std::cout << " Sleeping for " << millisecondsToSleep << "ms (to " << expectedTimeSeconds
<< "s)\n";
std::this_thread::sleep_for(std::chrono::milliseconds(millisecondsToSleep));
return expectedTimeSeconds;
}
};
void CheckTime(const vtkm::cont::Timer& timer, vtkm::Float64 expectedTime)
{
vtkm::Float64 elapsedTime = timer.GetElapsedTime();
VTKM_TEST_ASSERT(
elapsedTime > (expectedTime - 0.001), "Timer did not capture full wait. ", elapsedTime);
}
void DoTimerCheck(vtkm::cont::Timer& timer)
{
std::cout << " Starting timer\n";
timer.Start();
VTKM_TEST_ASSERT(timer.Started(), "Timer fails to track started status");
VTKM_TEST_ASSERT(!timer.Stopped(), "Timer fails to track non stopped status");
Waiter waiter;
vtkm::Float64 expectedTime = 0.0;
CheckTime(timer, expectedTime);
expectedTime = waiter.Wait();
CheckTime(timer, expectedTime);
std::cout << " Make sure timer is still running\n";
VTKM_TEST_ASSERT(!timer.Stopped(), "Timer fails to track stopped status");
expectedTime = waiter.Wait();
CheckTime(timer, expectedTime);
std::cout << " Stop the timer\n";
timer.Stop();
VTKM_TEST_ASSERT(timer.Stopped(), "Timer fails to track stopped status");
CheckTime(timer, expectedTime);
waiter.Wait(); // Do not advanced expected time
std::cout << " Check that timer legitimately stopped\n";
CheckTime(timer, expectedTime);
}
struct TimerCheckFunctor
{
void operator()(vtkm::cont::DeviceAdapterId device) const
{
if ((device != vtkm::cont::DeviceAdapterTagAny()) &&
!vtkm::cont::GetRuntimeDeviceTracker().CanRunOn(device))
{
// A timer will not work if set on a device that is not supported. Just skip this test.
return;
}
{
vtkm::cont::Timer timer(device);
DoTimerCheck(timer);
}
{
vtkm::cont::Timer timer;
timer.Reset(device);
DoTimerCheck(timer);
}
{
vtkm::cont::GetRuntimeDeviceTracker().DisableDevice(device);
vtkm::cont::Timer timer(device);
vtkm::cont::GetRuntimeDeviceTracker().ResetDevice(device);
DoTimerCheck(timer);
}
{
vtkm::cont::ScopedRuntimeDeviceTracker scoped(device);
vtkm::cont::Timer timer(device);
timer.Start();
VTKM_TEST_ASSERT(timer.Started(), "Timer fails to track started status");
//simulate a device failing
scoped.DisableDevice(device);
Waiter waiter;
waiter.Wait();
CheckTime(timer, 0.0);
}
}
};
void DoTimerTest()
{
std::cout << "Check default timer\n";
vtkm::cont::Timer timer;
DoTimerCheck(timer);
vtkm::ListForEach(TimerCheckFunctor(), TimerTestDevices());
}
} // anonymous namespace
int UnitTestTimer(int argc, char* argv[])
{
return vtkm::cont::testing::Testing::Run(DoTimerTest, argc, argv);
}