VirtualStackTest.cpp 3.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119
  1. 
  2. #include "../testTools.h"
  3. #include "../../DFPSR/base/virtualStack.h"
  4. #include "../../DFPSR/base/threading.h"
  5. #include <random>
  6. inline int random(int min, int max) {
  7. return (std::rand() % (1 + max - min)) + min;
  8. }
  9. static bool bruteTest(int maxSize, int maxDepth) {
  10. // Select a random power of two as the alignment.
  11. uintptr_t alignment = 1 << random(0, 8);
  12. // The padded size does not have rounding requirements.
  13. uint64_t paddedSize = random(1, maxSize);
  14. uint64_t start = random(0, 255);
  15. uint64_t stride = random(0, 255);
  16. UnsafeAllocation allocation = virtualStack_push(paddedSize, memory_createAlignmentAndMask(alignment));
  17. if ((uintptr_t)(allocation.data) % alignment != 0) {
  18. virtualStack_pop();
  19. return false;
  20. }
  21. for (int i = 0; i < paddedSize; i++) {
  22. allocation.data[i] = i * stride + start;
  23. }
  24. if (maxDepth > 1) {
  25. if (!bruteTest(maxSize, maxDepth - 1)) {
  26. virtualStack_pop();
  27. return false;
  28. }
  29. }
  30. for (int i = 0; i < paddedSize; i++) {
  31. if (allocation.data[i] != (uint8_t)(i * stride + start)) {
  32. virtualStack_pop();
  33. return false;
  34. }
  35. }
  36. virtualStack_pop();
  37. return true;
  38. }
  39. START_TEST(VirtualStack)
  40. { // Single threaded
  41. // TODO: Allocate structures with explicit alignment requirements exceeding the largest element's size.
  42. VirtualStackAllocation<int32_t> x(9);
  43. {
  44. ASSERT_EQUAL((uintptr_t)(x.getUnsafe()) % alignof(int32_t), 0);
  45. x[0] = 01;
  46. x[1] = 12;
  47. x[2] = 23;
  48. x[3] = 34;
  49. x[4] = 45;
  50. x[5] = 56;
  51. x[6] = 67;
  52. x[7] = 78;
  53. x[8] = 89;
  54. SafePointer<int32_t> pointerY;
  55. {
  56. VirtualStackAllocation<int32_t> y(3);
  57. pointerY = y;
  58. // Check that the memory address pointed to is evenly divisible by the type's alignment.
  59. ASSERT_EQUAL((uintptr_t)(y.getUnsafe()) % alignof(int32_t), 0);
  60. y[0] = 2147483000;
  61. y[1] = -2147483000;
  62. y[2] = 65;
  63. #ifdef SAFE_POINTER_CHECKS
  64. // This should crash because -1 is outside of the 0..2 range.
  65. ASSERT_CRASH(y[-1], U"SafePointer out of bound exception!");
  66. #endif
  67. // Reading within bounds and checking that the data was stored correctly.
  68. ASSERT_EQUAL(y[0], 2147483000);
  69. ASSERT_EQUAL(y[1], -2147483000);
  70. ASSERT_EQUAL(y[2], 65);
  71. #ifdef SAFE_POINTER_CHECKS
  72. // This should crash because 3 is outside of the 0..2 range.
  73. ASSERT_CRASH(y[3], U"SafePointer out of bound exception!");
  74. #endif
  75. }
  76. #ifdef SAFE_POINTER_CHECKS
  77. // This should crash because pointerY points to memory that was freed when y's scope ended.
  78. ASSERT_CRASH(pointerY[0], U"SafePointer identity exception!");
  79. #endif
  80. }
  81. #ifdef SAFE_POINTER_CHECKS
  82. ASSERT_CRASH(x[-1], U"SafePointer out of bound exception!");
  83. #endif
  84. ASSERT_EQUAL(x[0], 01);
  85. ASSERT_EQUAL(x[1], 12);
  86. ASSERT_EQUAL(x[2], 23);
  87. ASSERT_EQUAL(x[3], 34);
  88. ASSERT_EQUAL(x[4], 45);
  89. ASSERT_EQUAL(x[5], 56);
  90. ASSERT_EQUAL(x[6], 67);
  91. ASSERT_EQUAL(x[7], 78);
  92. ASSERT_EQUAL(x[8], 89);
  93. #ifdef SAFE_POINTER_CHECKS
  94. ASSERT_CRASH(x[9], U"SafePointer out of bound exception!");
  95. #endif
  96. // TODO: Try to access memory from another thread and assert that it triggers an exception.
  97. }
  98. { // Single threaded bruteforce test
  99. ASSERT(bruteTest(10000, 1000));
  100. }
  101. { // Multi threaded bruteforce test
  102. const int jobCount = 10;
  103. bool results[jobCount] = {};
  104. List<std::function<void()>> jobs;
  105. for (int i = 0; i < jobCount; i++) {
  106. bool* result = &results[i];
  107. jobs.push([result, i](){
  108. *result = bruteTest(10000, 1000);
  109. });
  110. }
  111. threadedWorkFromList(jobs);
  112. for (int i = 0; i < jobCount; i++) {
  113. ASSERT(results[i]);
  114. }
  115. }
  116. END_TEST