You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

126 lines
3.4KB

  1. #pragma once
  2. #include "asserts.h"
  3. #include <vector>
  4. /**
  5. * Utility class that counts up in binary using an array of ints to hold the bits.
  6. *
  7. */
  8. class BitCounter
  9. {
  10. public:
  11. void reset(int size)
  12. {
  13. done = false;
  14. state.resize(size);
  15. for (int i = 0; i < size; ++i) {
  16. state[i] = 0;
  17. }
  18. }
  19. bool atMax() const
  20. {
  21. for (size_t i = 0; i < state.size(); ++i) {
  22. if (state[i] == 0) {
  23. return false;
  24. }
  25. }
  26. return true;
  27. }
  28. bool isDone() const
  29. {
  30. return done;
  31. }
  32. void next()
  33. {
  34. if (atMax()) {
  35. done = true;
  36. return;
  37. }
  38. state[0]++;
  39. for (size_t i = 0; i < state.size(); ++i) {
  40. if (state[i] > 1) {
  41. state[i] = 0;
  42. ++state[i + 1];
  43. }
  44. }
  45. }
  46. template <typename Q>
  47. void setState(std::vector<Q>& testSignal, const std::vector< std::pair<float, float>>* signalLimits)
  48. {
  49. for (int i = (int) state.size() - 1; i >= 0; --i) {
  50. float min = -10.f;
  51. float max = 10.f;
  52. if (signalLimits) { // here we want to clip these to the possible values of params
  53. min = (*signalLimits)[i].first;
  54. max = (*signalLimits)[i].second;
  55. assertNE(min, max);
  56. assertGT(max, min);
  57. }
  58. testSignal[i].value = state[i] > 0 ? max : min;
  59. }
  60. }
  61. void dump(const char * label)
  62. {
  63. printf("State (%s): ", label);
  64. for (int i = (int) state.size() - 1; i >= 0; --i) {
  65. printf("%d ", state[i]);
  66. }
  67. printf("\n");
  68. }
  69. private:
  70. std::vector<int> state;
  71. bool done;
  72. };
  73. /**
  74. * Tests a composite by feeding all the inputs and parameters (in every possible permutation)
  75. * with extreme inputs. Asserts that the output stays in a semi-sane range.
  76. * Typically this test will fail by triggering an assert in some distant code.
  77. */
  78. template <typename T>
  79. class ExtremeTester
  80. {
  81. public:
  82. static void test(T& dut,
  83. const std::vector< std::pair<float, float>>& paramLimits,
  84. bool checkOutput,
  85. const char * testName)
  86. {
  87. printf("extreme test starting for %s. %s ....\n", testName, checkOutput ? "test output" : "");
  88. const int numInputs = dut.NUM_INPUTS;
  89. const int numParams = dut.NUM_PARAMS;
  90. const int numOutputs = dut.NUM_OUTPUTS;
  91. assert(numInputs < 20);
  92. assertEQ(paramLimits.size(), numParams);
  93. const std::vector< std::pair<float, float>> * nullLimits = nullptr;
  94. BitCounter inputState;
  95. BitCounter paramsState;
  96. for (inputState.reset(numInputs); !inputState.isDone(); inputState.next()) {
  97. inputState.setState(dut.inputs, nullLimits);
  98. for (paramsState.reset(numParams); !paramsState.isDone(); paramsState.next()) {
  99. paramsState.setState(dut.params, &paramLimits);
  100. for (int i = 0; i < 100; ++i) {
  101. dut.step();
  102. for (int j = 0; j < numOutputs; ++j) {
  103. const float out = dut.outputs[j].value;
  104. if (checkOutput) {
  105. assertGE(out, -150);
  106. assertLE(out, 150);
  107. }
  108. }
  109. }
  110. }
  111. }
  112. printf("extreme test done\n");
  113. }
  114. };