The open source OpenXR runtime
at main 13 kB view raw
1// Copyright 2021, Collabora, Ltd. 2// SPDX-License-Identifier: BSL-1.0 3/*! 4 * @file 5 * @brief HistoryBuffer collection tests. 6 * @author Rylie Pavlik <rylie.pavlik@collabora.com> 7 */ 8 9#include <math/m_relation_history.h> 10#include <util/u_time.h> 11#include <util/u_template_historybuf.hpp> 12#include <iostream> 13 14 15using xrt::auxiliary::util::HistoryBuffer; 16 17template <typename Container> 18static inline std::ostream & 19operator<<(std::ostream &os, const xrt::auxiliary::util::RandomAccessIteratorBase<Container> &iter_base) 20{ 21 os << "Iterator@[" << iter_base.index() << "]"; 22 return os; 23} 24 25 26#include "catch_amalgamated.hpp" 27 28 29 30TEST_CASE("m_relation_history") 31{ 32 m_relation_history *rh = nullptr; 33 34 m_relation_history_create(&rh); 35 SECTION("empty buffer") 36 { 37 xrt_space_relation out_relation = XRT_SPACE_RELATION_ZERO; 38 CHECK(m_relation_history_get(rh, 0, &out_relation) == M_RELATION_HISTORY_RESULT_INVALID); 39 CHECK(m_relation_history_get(rh, 1, &out_relation) == M_RELATION_HISTORY_RESULT_INVALID); 40 } 41 SECTION("populated buffer") 42 { 43 xrt_space_relation relation = XRT_SPACE_RELATION_ZERO; 44 relation.relation_flags = (xrt_space_relation_flags)( // 45 XRT_SPACE_RELATION_POSITION_TRACKED_BIT | // 46 XRT_SPACE_RELATION_POSITION_VALID_BIT | // 47 XRT_SPACE_RELATION_ORIENTATION_TRACKED_BIT | // 48 XRT_SPACE_RELATION_ORIENTATION_VALID_BIT | // 49 XRT_SPACE_RELATION_LINEAR_VELOCITY_VALID_BIT); // 50 relation.linear_velocity.x = 1.f; 51 52 // arbitrary value 53 constexpr auto T0 = 20 * (uint64_t)U_TIME_1S_IN_NS; 54 // one second after T0 55 constexpr auto T1 = T0 + (uint64_t)U_TIME_1S_IN_NS; 56 // two seconds after T0 57 constexpr auto T2 = T1 + (uint64_t)U_TIME_1S_IN_NS; 58 59 xrt_space_relation out_relation = XRT_SPACE_RELATION_ZERO; 60 int64_t out_time = 0; 61 62 CHECK(m_relation_history_get_size(rh) == 0); 63 CHECK_FALSE(m_relation_history_get_latest(rh, &out_time, &out_relation)); 64 65 66 CHECK(m_relation_history_push(rh, &relation, T0)); 67 CHECK(m_relation_history_get_size(rh) == 1); 68 CHECK(m_relation_history_get_latest(rh, &out_time, &out_relation)); 69 CHECK(out_time == T0); 70 71 relation.pose.position.x = 1.f; 72 CHECK(m_relation_history_push(rh, &relation, T1)); 73 CHECK(m_relation_history_get_size(rh) == 2); 74 CHECK(m_relation_history_get_latest(rh, &out_time, &out_relation)); 75 CHECK(out_time == T1); 76 77 relation.pose.position.x = 2.f; 78 CHECK(m_relation_history_push(rh, &relation, T2)); 79 CHECK(m_relation_history_get_size(rh) == 3); 80 CHECK(m_relation_history_get_latest(rh, &out_time, &out_relation)); 81 CHECK(out_time == T2); 82 83 // Try going back in time: should fail to push, leave state the same 84 CHECK_FALSE(m_relation_history_push(rh, &relation, T1)); 85 CHECK(m_relation_history_get_size(rh) == 3); 86 CHECK(m_relation_history_get_latest(rh, &out_time, &out_relation)); 87 CHECK(out_time == T2); 88 89 CHECK(m_relation_history_get(rh, 0, &out_relation) == M_RELATION_HISTORY_RESULT_INVALID); 90 91 CHECK(m_relation_history_get(rh, T0, &out_relation) == M_RELATION_HISTORY_RESULT_EXACT); 92 CHECK(out_relation.pose.position.x == 0.f); 93 94 CHECK(m_relation_history_get(rh, T1, &out_relation) == M_RELATION_HISTORY_RESULT_EXACT); 95 CHECK(out_relation.pose.position.x == 1.f); 96 97 CHECK(m_relation_history_get(rh, T2, &out_relation) == M_RELATION_HISTORY_RESULT_EXACT); 98 CHECK(out_relation.pose.position.x == 2.f); 99 100 101 CHECK(m_relation_history_get(rh, T0 - (uint64_t)U_TIME_1S_IN_NS, &out_relation) == 102 M_RELATION_HISTORY_RESULT_REVERSE_PREDICTED); 103 CHECK(out_relation.pose.position.x < 0.f); 104 105 CHECK(m_relation_history_get(rh, (T0 + T1) / 2, &out_relation) == 106 M_RELATION_HISTORY_RESULT_INTERPOLATED); 107 CHECK(out_relation.pose.position.x > 0.f); 108 CHECK(out_relation.pose.position.x < 1.f); 109 110 CHECK(m_relation_history_get(rh, (T1 + T2) / 2, &out_relation) == 111 M_RELATION_HISTORY_RESULT_INTERPOLATED); 112 CHECK(out_relation.pose.position.x > 1.f); 113 CHECK(out_relation.pose.position.x < 2.f); 114 115 CHECK(m_relation_history_get(rh, T2 + (uint64_t)U_TIME_1S_IN_NS, &out_relation) == 116 M_RELATION_HISTORY_RESULT_PREDICTED); 117 CHECK(out_relation.pose.position.x > 2.f); 118 } 119 120 121 m_relation_history_destroy(&rh); 122} 123 124 125TEST_CASE("RelationHistory") 126{ 127 using xrt::auxiliary::math::RelationHistory; 128 RelationHistory rh; 129 130 SECTION("empty buffer") 131 { 132 xrt_space_relation out_relation = XRT_SPACE_RELATION_ZERO; 133 CHECK(rh.get(0, &out_relation) == M_RELATION_HISTORY_RESULT_INVALID); 134 CHECK(rh.get(1, &out_relation) == M_RELATION_HISTORY_RESULT_INVALID); 135 } 136 SECTION("populated buffer") 137 { 138 xrt_space_relation relation = XRT_SPACE_RELATION_ZERO; 139 relation.relation_flags = (xrt_space_relation_flags)( // 140 XRT_SPACE_RELATION_POSITION_TRACKED_BIT | // 141 XRT_SPACE_RELATION_POSITION_VALID_BIT | // 142 XRT_SPACE_RELATION_ORIENTATION_TRACKED_BIT | // 143 XRT_SPACE_RELATION_ORIENTATION_VALID_BIT | // 144 XRT_SPACE_RELATION_LINEAR_VELOCITY_VALID_BIT); // 145 relation.linear_velocity.x = 1.f; 146 147 // arbitrary value 148 constexpr auto T0 = 20 * (uint64_t)U_TIME_1S_IN_NS; 149 // one second after T0 150 constexpr auto T1 = T0 + (uint64_t)U_TIME_1S_IN_NS; 151 // two seconds after T0 152 constexpr auto T2 = T1 + (uint64_t)U_TIME_1S_IN_NS; 153 154 xrt_space_relation out_relation = XRT_SPACE_RELATION_ZERO; 155 int64_t out_time = 0; 156 157 CHECK(rh.size() == 0); 158 CHECK_FALSE(rh.get_latest(&out_time, &out_relation)); 159 160 161 CHECK(rh.push(relation, T0)); 162 CHECK(rh.size() == 1); 163 CHECK(rh.get_latest(&out_time, &out_relation)); 164 CHECK(out_time == T0); 165 166 relation.pose.position.x = 1.f; 167 CHECK(rh.push(relation, T1)); 168 CHECK(rh.size() == 2); 169 CHECK(rh.get_latest(&out_time, &out_relation)); 170 CHECK(out_time == T1); 171 172 relation.pose.position.x = 2.f; 173 CHECK(rh.push(relation, T2)); 174 CHECK(rh.size() == 3); 175 CHECK(rh.get_latest(&out_time, &out_relation)); 176 CHECK(out_time == T2); 177 178 // Try going back in time: should fail to push, leave state the same 179 CHECK_FALSE(rh.push(relation, T1)); 180 CHECK(rh.size() == 3); 181 CHECK(rh.get_latest(&out_time, &out_relation)); 182 CHECK(out_time == T2); 183 184 CHECK(rh.get(0, &out_relation) == M_RELATION_HISTORY_RESULT_INVALID); 185 186 CHECK(rh.get(T0, &out_relation) == M_RELATION_HISTORY_RESULT_EXACT); 187 CHECK(out_relation.pose.position.x == 0.f); 188 189 CHECK(rh.get(T1, &out_relation) == M_RELATION_HISTORY_RESULT_EXACT); 190 CHECK(out_relation.pose.position.x == 1.f); 191 192 CHECK(rh.get(T2, &out_relation) == M_RELATION_HISTORY_RESULT_EXACT); 193 CHECK(out_relation.pose.position.x == 2.f); 194 195 196 CHECK(rh.get(T0 - (uint64_t)U_TIME_1S_IN_NS, &out_relation) == 197 M_RELATION_HISTORY_RESULT_REVERSE_PREDICTED); 198 CHECK(out_relation.pose.position.x < 0.f); 199 200 CHECK(rh.get((T0 + T1) / 2, &out_relation) == M_RELATION_HISTORY_RESULT_INTERPOLATED); 201 CHECK(out_relation.pose.position.x > 0.f); 202 CHECK(out_relation.pose.position.x < 1.f); 203 204 CHECK(rh.get((T1 + T2) / 2, &out_relation) == M_RELATION_HISTORY_RESULT_INTERPOLATED); 205 CHECK(out_relation.pose.position.x > 1.f); 206 CHECK(out_relation.pose.position.x < 2.f); 207 208 CHECK(rh.get(T2 + (uint64_t)U_TIME_1S_IN_NS, &out_relation) == M_RELATION_HISTORY_RESULT_PREDICTED); 209 CHECK(out_relation.pose.position.x > 2.f); 210 } 211} 212 213TEST_CASE("u_template_historybuf") 214{ 215 HistoryBuffer<int, 4> buffer; 216 SECTION("behavior when empty") 217 { 218 CHECK(buffer.empty()); 219 CHECK(0 == buffer.size()); // NOLINT 220 CHECK_FALSE(buffer.begin().valid()); 221 CHECK_FALSE(buffer.end().valid()); 222 CHECK(buffer.begin() == buffer.end()); 223 { 224 INFO("Check after pop_back"); 225 REQUIRE_FALSE(buffer.pop_back()); 226 CHECK(buffer.empty()); 227 } 228 } 229 SECTION("behavior with one") 230 { 231 buffer.push_back(0); 232 CHECK_FALSE(buffer.empty()); 233 CHECK(buffer.size() == 1); 234 235 // check iterators 236 CHECK(buffer.begin().valid()); 237 CHECK_FALSE(buffer.end().valid()); 238 CHECK_FALSE(buffer.begin() == buffer.end()); 239 { 240 auto it = buffer.end(); 241 // should be permanently cleared 242 ++it; 243 CHECK_FALSE(it.valid()); 244 --it; 245 CHECK_FALSE(it.valid()); 246 } 247 CHECK(buffer.begin() == buffer.cbegin()); 248 CHECK(buffer.end() == buffer.cend()); 249 250 // can we decrement our past-the-end iterator to get the begin iterator? 251 CHECK(buffer.begin() == --(buffer.end())); 252 253 // make sure post-decrement works right 254 CHECK_FALSE(buffer.begin() == (buffer.end())--); 255 256 // make sure post-increment works right 257 CHECK(buffer.begin() == buffer.begin()++); 258 259 // make sure pre-increment works right 260 CHECK_FALSE(buffer.begin() == ++(buffer.begin())); 261 262 263 // check contents 264 CHECK_NOTHROW(buffer.get_at_index(0)); 265 CHECK_FALSE(buffer.get_at_index(0) == nullptr); 266 CHECK(*buffer.get_at_index(0) == 0); 267 268 CHECK_FALSE(buffer.get_at_age(0) == nullptr); 269 CHECK(*buffer.get_at_age(0) == 0); 270 CHECK_FALSE(buffer.get_at_clamped_age(0) == nullptr); 271 CHECK(*buffer.get_at_clamped_age(0) == 0); 272 273 CHECK(buffer.get_at_age(1) == nullptr); 274 275 CHECK_FALSE(buffer.get_at_clamped_age(1) == nullptr); 276 CHECK(*buffer.get_at_clamped_age(1) == 0); 277 278 CHECK_FALSE(buffer.get_at_clamped_age(2) == nullptr); 279 CHECK(*buffer.get_at_clamped_age(2) == 0); 280 281 CHECK_NOTHROW(buffer.front()); 282 CHECK(buffer.front() == 0); 283 284 CHECK_NOTHROW(buffer.back()); 285 CHECK(buffer.back() == 0); 286 287 CHECK(*buffer.begin() == buffer.front()); 288 289 { 290 INFO("Check after pop_back"); 291 REQUIRE(buffer.pop_back()); 292 CHECK(buffer.size() == 0); 293 294 REQUIRE_FALSE(buffer.pop_back()); 295 } 296 } 297 298 SECTION("behavior with two") 299 { 300 buffer.push_back(0); 301 buffer.push_back(1); 302 CHECK_FALSE(buffer.empty()); 303 CHECK(buffer.size() == 2); 304 SECTION("check iterators") 305 { 306 // check iterators 307 CHECK(buffer.begin().valid()); 308 CHECK_FALSE(buffer.end().valid()); 309 CHECK_FALSE(buffer.begin() == buffer.end()); 310 { 311 auto it = buffer.end(); 312 // should be permanently cleared 313 ++it; 314 CHECK_FALSE(it.valid()); 315 --it; 316 CHECK_FALSE(it.valid()); 317 } 318 CHECK(buffer.begin() == buffer.cbegin()); 319 CHECK(buffer.end() == buffer.cend()); 320 321 // can we decrement our past-the-end iterator to get the begin iterator? 322 CHECK(buffer.begin() == --(--(buffer.end()))); 323 324 // make sure post-decrement works right 325 CHECK_FALSE(buffer.begin() == (buffer.end())--); 326 327 // make sure post-increment works right 328 CHECK(buffer.begin() == buffer.begin()++); 329 330 // make sure pre-increment works right 331 CHECK_FALSE(buffer.begin() == ++(buffer.begin())); 332 } 333 SECTION("check contents") 334 { 335 // check contents 336 CHECK_NOTHROW(buffer.get_at_index(0)); 337 CHECK_FALSE(buffer.get_at_index(0) == nullptr); 338 CHECK(*buffer.get_at_index(0) == 0); 339 CHECK_FALSE(buffer.get_at_index(1) == nullptr); 340 CHECK(*buffer.get_at_index(1) == 1); 341 CHECK(buffer.get_at_index(2) == nullptr); 342 343 CHECK_NOTHROW(buffer.get_at_age(0)); 344 CHECK_FALSE(buffer.get_at_age(0) == nullptr); 345 CHECK(*buffer.get_at_age(0) == 1); 346 CHECK_FALSE(buffer.get_at_clamped_age(0) == nullptr); 347 CHECK(*buffer.get_at_clamped_age(0) == 1); 348 349 CHECK_FALSE(buffer.get_at_age(1) == nullptr); 350 CHECK(*buffer.get_at_age(1) == 0); 351 CHECK_FALSE(buffer.get_at_clamped_age(1) == nullptr); 352 CHECK(*buffer.get_at_clamped_age(1) == 0); 353 354 CHECK(buffer.get_at_age(2) == nullptr); 355 356 CHECK_FALSE(buffer.get_at_clamped_age(2) == nullptr); 357 CHECK(*buffer.get_at_clamped_age(2) == 0); 358 359 CHECK_FALSE(buffer.get_at_clamped_age(3) == nullptr); 360 CHECK(*buffer.get_at_clamped_age(3) == 0); 361 362 CHECK_NOTHROW(buffer.front()); 363 CHECK(buffer.front() == 0); 364 365 CHECK_NOTHROW(buffer.back()); 366 CHECK(buffer.back() == 1); 367 368 CHECK(*buffer.begin() == buffer.front()); 369 CHECK(buffer.back() == *(--buffer.end())); 370 } 371 SECTION("Check after pop_back") 372 { 373 REQUIRE(buffer.pop_back()); 374 CHECK(buffer.size() == 1); 375 CHECK(buffer.front() == 0); 376 377 REQUIRE(buffer.pop_back()); 378 CHECK(buffer.size() == 0); 379 } 380 } 381 382 SECTION("algorithm behavior with 3") 383 { 384 buffer.push_back(0); 385 buffer.push_back(2); 386 buffer.push_back(4); 387 CHECK_FALSE(buffer.empty()); 388 CHECK(buffer.size() == 3); 389 CHECK(buffer.begin() == std::find(buffer.begin(), buffer.end(), 0)); 390 CHECK(++(buffer.begin()) == std::find(buffer.begin(), buffer.end(), 2)); 391 CHECK(buffer.end() == std::find(buffer.begin(), buffer.end(), 5)); 392 393 CHECK(++(buffer.begin()) == std::lower_bound(buffer.begin(), buffer.end(), 1)); 394 } 395} 396 397TEST_CASE("IteratorBase") 398{ 399 400 HistoryBuffer<int, 4> buffer; 401 buffer.push_back(0); 402 buffer.push_back(2); 403 buffer.push_back(4); 404 using namespace xrt::auxiliary::util; 405 using const_iterator = typename HistoryBuffer<int, 4>::const_iterator; 406 const_iterator default_constructed{}; 407 const_iterator begin_constructed = buffer.begin(); 408 const_iterator end_constructed = buffer.end(); 409 410 SECTION("Check default constructed") 411 { 412 CHECK_FALSE(default_constructed.valid()); 413 CHECK(default_constructed.is_cleared()); 414 } 415 SECTION("Check begin constructed") 416 { 417 CHECK(begin_constructed.valid()); 418 CHECK_FALSE(begin_constructed.is_cleared()); 419 CHECK((--begin_constructed).is_cleared()); 420 } 421 SECTION("Check end constructed") 422 { 423 CHECK_FALSE(end_constructed.valid()); 424 CHECK_FALSE(end_constructed.is_cleared()); 425 // if we go past the end, we can go backwards into validity. 426 CHECK_FALSE((++end_constructed).is_cleared()); 427 } 428}