UnitTestFramework.cpp 3.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152
  1. // SPDX-FileCopyrightText: 2021 Jorrit Rouwe
  2. // SPDX-License-Identifier: MIT
  3. #include <Jolt.h>
  4. #include <Core/FPException.h>
  5. #include <RegisterTypes.h>
  6. #ifdef JPH_PLATFORM_ANDROID
  7. #include <Core/Color.h>
  8. #include <android/log.h>
  9. #include <android_native_app_glue.h>
  10. #endif // JPH_PLATFORM_ANDROID
  11. using namespace JPH;
  12. // Emit everything needed for the main function
  13. #define DOCTEST_CONFIG_IMPLEMENT
  14. #define DOCTEST_CONFIG_NO_WINDOWS_SEH
  15. #include "doctest.h"
  16. using namespace doctest;
  17. #ifndef JPH_PLATFORM_ANDROID
  18. // Generic entry point
  19. int main(int argc, char** argv)
  20. {
  21. #if defined(JPH_PLATFORM_WINDOWS) && defined(_DEBUG)
  22. // Enable leak detection
  23. _CrtSetDbgFlag(_CRTDBG_ALLOC_MEM_DF | _CRTDBG_LEAK_CHECK_DF);
  24. #endif
  25. // Enable floating point exceptions
  26. FPExceptionsEnable enable_exceptions;
  27. JPH_UNUSED(enable_exceptions);
  28. // Register physics types
  29. RegisterTypes();
  30. return Context(argc, argv).run();
  31. }
  32. #else // !JPH_PLATFORM_ANDROID
  33. // Reporter that writes logs to the Android log
  34. struct LogReporter : public ConsoleReporter
  35. {
  36. LogReporter(const ContextOptions &inOptions) :
  37. ConsoleReporter(inOptions, mStream)
  38. {
  39. }
  40. #define REPORTER_OVERRIDE(func, type, arg) \
  41. void func(type arg) override \
  42. { \
  43. ConsoleReporter::func(arg); \
  44. const char *str = mStream.str().c_str(); \
  45. if (str[0] != 0) \
  46. __android_log_write(ANDROID_LOG_INFO, "Jolt", str); \
  47. mStream.str(""); \
  48. }
  49. REPORTER_OVERRIDE(test_run_start, DOCTEST_EMPTY, DOCTEST_EMPTY)
  50. REPORTER_OVERRIDE(test_run_end, const TestRunStats &, in)
  51. REPORTER_OVERRIDE(test_case_start, const TestCaseData &, in)
  52. REPORTER_OVERRIDE(test_case_reenter, const TestCaseData &, in)
  53. REPORTER_OVERRIDE(test_case_end, const CurrentTestCaseStats &, in)
  54. REPORTER_OVERRIDE(test_case_exception, const TestCaseException &, in)
  55. REPORTER_OVERRIDE(subcase_start, const SubcaseSignature &, in)
  56. REPORTER_OVERRIDE(subcase_end, DOCTEST_EMPTY, DOCTEST_EMPTY)
  57. REPORTER_OVERRIDE(log_assert, const AssertData &, in)
  58. REPORTER_OVERRIDE(log_message, const MessageData &, in)
  59. REPORTER_OVERRIDE(test_case_skipped, const TestCaseData &, in)
  60. private:
  61. thread_local static std::ostringstream mStream;
  62. };
  63. thread_local std::ostringstream LogReporter::mStream;
  64. DOCTEST_REGISTER_REPORTER("android_log", 0, LogReporter);
  65. void AndroidInitialize(android_app *inApp)
  66. {
  67. // Enable floating point exceptions
  68. FPExceptionsEnable enable_exceptions;
  69. JPH_UNUSED(enable_exceptions);
  70. // Register physics types
  71. RegisterTypes();
  72. // Run all tests
  73. Context context;
  74. context.addFilter("reporters", "android_log");
  75. int return_value = context.run();
  76. // Color the screen according to the test result
  77. JPH::Color color = return_value == 0? JPH::Color::sGreen : JPH::Color::sRed;
  78. ANativeWindow_acquire(inApp->window);
  79. ANativeWindow_Buffer buffer;
  80. ARect bounds;
  81. ANativeWindow_lock(inApp->window, &buffer, &bounds);
  82. switch (buffer.format)
  83. {
  84. case AHARDWAREBUFFER_FORMAT_R8G8B8A8_UNORM:
  85. case AHARDWAREBUFFER_FORMAT_R8G8B8X8_UNORM:
  86. {
  87. uint32 color_u32 = color.GetUInt32();
  88. for (int y = 0; y < buffer.height; ++y)
  89. {
  90. uint32 *dest = (uint32 *)((uint8 *)buffer.bits + y * buffer.stride * sizeof(uint32));
  91. for (int x = 0; x < buffer.width; ++x)
  92. *dest++ = color_u32;
  93. }
  94. break;
  95. }
  96. default:
  97. // TODO implement
  98. break;
  99. }
  100. ANativeWindow_unlockAndPost(inApp->window);
  101. ANativeWindow_release(inApp->window);
  102. }
  103. // Handle callback from Android
  104. void AndroidHandleCommand(android_app *inApp, int32_t inCmd)
  105. {
  106. switch (inCmd)
  107. {
  108. case APP_CMD_INIT_WINDOW:
  109. AndroidInitialize(inApp);
  110. break;
  111. }
  112. }
  113. // Main entry point for android
  114. void android_main(struct android_app *ioApp)
  115. {
  116. ioApp->onAppCmd = AndroidHandleCommand;
  117. int events;
  118. android_poll_source *source;
  119. do
  120. {
  121. if (ALooper_pollAll(1, nullptr, &events, (void **)&source) >= 0 && source != nullptr)
  122. source->process(ioApp, source);
  123. } while (ioApp->destroyRequested == 0);
  124. }
  125. #endif // JPH_PLATFORM_ANDROID