From 74316283c43d88bb613bd040019927fa68f4dec2 Mon Sep 17 00:00:00 2001 From: kunitoki Date: Thu, 28 Nov 2024 11:11:49 +0100 Subject: [PATCH] More tweaks --- cmake/yup.cmake | 1 + modules/juce_core/juce_core.cpp | 3 +- .../juce_core/native/juce_Network_wasm.cpp | 314 ++++++++++++++++++ .../native/juce_SystemStats_wasm.cpp | 181 +++++++--- modules/juce_core/system/juce_SystemStats.cpp | 38 +-- tests/CMakeLists.txt | 8 +- tests/juce_core/juce_ElementComparator.cpp | 2 +- tests/juce_core/juce_Enumerate.cpp | 16 +- tests/juce_core/juce_FlagSet.cpp | 12 +- tests/juce_core/juce_Identifier.cpp | 22 +- tests/juce_core/juce_LinkedListPointer.cpp | 38 +-- tests/juce_core/juce_ListenerList.cpp | 174 +++++----- tests/juce_core/juce_PlatformDefs.cpp | 6 +- tests/juce_core/juce_StringPool.cpp | 14 +- tests/juce_core/juce_SystemStats.cpp | 232 +++++++++++++ tests/juce_core/juce_Time.cpp | 11 +- 16 files changed, 848 insertions(+), 224 deletions(-) create mode 100644 modules/juce_core/native/juce_Network_wasm.cpp create mode 100644 tests/juce_core/juce_SystemStats.cpp diff --git a/cmake/yup.cmake b/cmake/yup.cmake index 33dcb59b..8bad0a85 100644 --- a/cmake/yup.cmake +++ b/cmake/yup.cmake @@ -741,6 +741,7 @@ function (yup_standalone_app) -sPTHREAD_POOL_SIZE=8 -sFORCE_FILESYSTEM=1 -sNODERAWFS=0 + -sFETCH=1 -sDEFAULT_LIBRARY_FUNCS_TO_INCLUDE='$dynCall' --shell-file "${CMAKE_SOURCE_DIR}/cmake/platforms/${yup_platform}/shell.html") diff --git a/modules/juce_core/juce_core.cpp b/modules/juce_core/juce_core.cpp index b60f2ab8..08a9d3e2 100644 --- a/modules/juce_core/juce_core.cpp +++ b/modules/juce_core/juce_core.cpp @@ -102,7 +102,7 @@ JUCE_END_IGNORE_WARNINGS_MSVC #if JUCE_EMSCRIPTEN #include -#include +#include #endif #if JUCE_LINUX || JUCE_BSD @@ -293,6 +293,7 @@ extern char** environ; #elif JUCE_WASM #include "native/juce_SystemStats_wasm.cpp" #include "native/juce_Files_wasm.cpp" +#include "native/juce_Network_wasm.cpp" #include "native/juce_Threads_wasm.cpp" #include "native/juce_PlatformTimer_generic.cpp" #endif diff --git a/modules/juce_core/native/juce_Network_wasm.cpp b/modules/juce_core/native/juce_Network_wasm.cpp new file mode 100644 index 00000000..0c16d466 --- /dev/null +++ b/modules/juce_core/native/juce_Network_wasm.cpp @@ -0,0 +1,314 @@ +/* + ============================================================================== + + This file is part of the YUP library. + Copyright (c) 2024 - kunitoki@gmail.com + + YUP is an open source library subject to open-source licensing. + + The code included in this file is provided under the terms of the ISC license + http://www.isc.org/downloads/software-support-policy/isc-license. Permission + to use, copy, modify, and/or distribute this software for any purpose with or + without fee is hereby granted provided that the above copyright notice and + this permission notice appear in all copies. + + YUP IS PROVIDED "AS IS" WITHOUT ANY WARRANTY, AND ALL WARRANTIES, WHETHER + EXPRESSED OR IMPLIED, INCLUDING MERCHANTABILITY AND FITNESS FOR PURPOSE, ARE + DISCLAIMED. + + ============================================================================== +*/ + +namespace juce +{ + +void MACAddress::findAllAddresses (Array& result) +{ + result.clearQuick(); +} + +bool JUCE_CALLTYPE Process::openEmailWithAttachments (const String& /* targetEmailAddress */, + const String& /* emailSubject */, + const String& /* bodyText */, + const StringArray& /* filesToAttach */) +{ + jassertfalse; // xxx todo + return false; +} + +//============================================================================== +#if JUCE_EMSCRIPTEN && ! JUCE_USE_CURL +class WebInputStream::Pimpl +{ +public: + Pimpl (WebInputStream& pimplOwner, const URL& urlToCopy, bool addParametersToBody) + : owner (pimplOwner) + , url (urlToCopy) + , addParametersToRequestBody (addParametersToBody) + , hasBodyDataToSend (addParametersToRequestBody || url.hasBodyDataToSend()) + , httpRequestCmd (hasBodyDataToSend ? "POST" : "GET") + { + } + + ~Pimpl() + { + cancel(); + } + + //============================================================================== + // WebInputStream methods + void withExtraHeaders (const String& extraHeaders) + { + if (! headers.endsWithChar ('\n') && headers.isNotEmpty()) + headers << "\r\n"; + + headers << extraHeaders; + + if (! headers.endsWithChar ('\n') && headers.isNotEmpty()) + headers << "\r\n"; + } + + void withCustomRequestCommand (const String& customRequestCommand) { httpRequestCmd = customRequestCommand; } + + void withConnectionTimeout (int timeoutInMs) { timeOutMs = timeoutInMs; } + + void withNumRedirectsToFollow (int maxRedirectsToFollow) { numRedirectsToFollow = maxRedirectsToFollow; } + + int getStatusCode() const { return statusCode; } + + StringPairArray getRequestHeaders() const { return WebInputStream::parseHttpHeaders (headers); } + + StringPairArray getResponseHeaders() const + { + return responseHeaders; + } + + bool connect (WebInputStream::Listener* listener) + { + if (hasBeenCancelled) + return false; + + address = url.toString (! addParametersToRequestBody); + + statusCode = 0; + finished = false; + position = 0; + totalBytesRead = 0; + + // Prepare the fetch attributes + emscripten_fetch_attr_init (&fetchAttr); + + std::strncpy (fetchAttr.requestMethod, httpRequestCmd.toRawUTF8(), sizeof (fetchAttr.requestMethod) - 1); + fetchAttr.requestMethod[sizeof (fetchAttr.requestMethod) - 1] = '\0'; + + // Handle headers + headerData = parseHeaders (headers); + fetchAttr.requestHeaders = headerData.data(); + + // Handle POST data + if (hasBodyDataToSend) + { + WebInputStream::createHeadersAndPostData (url, headers, postData, addParametersToRequestBody); + fetchAttr.requestData = (const char*)postData.getData(); + fetchAttr.requestDataSize = postData.getSize(); + } + + fetchAttr.attributes = EMSCRIPTEN_FETCH_LOAD_TO_MEMORY; + fetchAttr.onsuccess = &onFetchSuccess; + fetchAttr.onprogress = &onFetchProgress; + fetchAttr.onerror = &onFetchError; + fetchAttr.userData = this; + + // Start the fetch request + fetchHandle = emscripten_fetch (&fetchAttr, address.toRawUTF8()); + + return true; + } + + void cancel() + { + hasBeenCancelled = true; + finished = true; + + if (fetchHandle) + { + emscripten_fetch_close (fetchHandle); + fetchHandle = nullptr; + } + } + + //============================================================================== + bool isError() const { return fetchHandle == nullptr || statusCode == 0; } + + bool isExhausted() { return finished && position >= contentLength; } + + int64 getPosition() { return position; } + + int64 getTotalLength() { return contentLength; } + + int read (void* buffer, int bytesToRead) + { + if (isError() || totalBytesRead >= contentLength) + return 0; + + int bytesAvailable = (int) (dataBuffer.size() - position); + int bytesToCopy = jmin (bytesToRead, bytesAvailable); + + if (bytesToCopy > 0) + { + std::memcpy (buffer, dataBuffer.data() + position, bytesToCopy); + position += bytesToCopy; + totalBytesRead += bytesToCopy; + return bytesToCopy; + } + + // No data available yet, return 0 + return 0; + } + + bool setPosition (int64 wantedPos) + { + if (isError()) + return false; + + if (wantedPos >= 0 && wantedPos <= (int64) dataBuffer.size()) + { + position = wantedPos; + return true; + } + + return false; + } + + //============================================================================== + int statusCode = 0; + +private: + WebInputStream& owner; + URL url; + StringArray headerLines; + String address, headers; + MemoryBlock postData; + int64 contentLength = -1, position = 0, totalBytesRead = 0; + bool finished = false; + const bool addParametersToRequestBody, hasBodyDataToSend; + int timeOutMs = 0; + int numRedirectsToFollow = 5; + String httpRequestCmd; + bool hasBeenCancelled = false; + + emscripten_fetch_attr_t fetchAttr; + emscripten_fetch_t* fetchHandle = nullptr; + std::vector dataBuffer; + StringPairArray responseHeaders; + std::vector headerData; // to keep header strings alive + + // Callback for successful fetch + static void onFetchSuccess (emscripten_fetch_t* fetch) + { + Pimpl* self = static_cast (fetch->userData); + + self->statusCode = fetch->status; + self->contentLength = fetch->numBytes; + self->dataBuffer.assign (fetch->data, fetch->data + fetch->numBytes); + self->finished = true; + + // Parse response headers + if (auto headersSize = emscripten_fetch_get_response_headers_length(fetch); headersSize > 0) + { + std::vector headersBuffer (headersSize + 1); + emscripten_fetch_get_response_headers (fetch, headersBuffer.data(), headersBuffer.size()); + headersBuffer.back() = '\0'; + + self->parseResponseHeaders (headersBuffer.data()); + } + + // Close the fetch + emscripten_fetch_close (fetch); + self->fetchHandle = nullptr; + } + + // Callback for fetch error + static void onFetchError (emscripten_fetch_t* fetch) + { + Pimpl* self = static_cast (fetch->userData); + + self->statusCode = fetch->status; + self->finished = true; + + // Close the fetch + emscripten_fetch_close (fetch); + self->fetchHandle = nullptr; + } + + // Callback for fetch progress (optional) + static void onFetchProgress (emscripten_fetch_t* fetch) + { + // We can implement progress updates here if needed + // For now, we can leave this empty or implement listener callbacks + } + + // Helper to parse headers into the format expected by emscripten_fetch + std::vector parseHeaders (const String& headersString) + { + StringArray headerLines = StringArray::fromLines (headersString.trim()); + + std::vector headerArray; + for (const auto& line : headerLines) + { + int colonPos = line.indexOfChar (':'); + if (colonPos > 0) + { + String key = line.substring (0, colonPos).trim(); + String value = line.substring (colonPos + 1).trim(); + + // Store the key and value strings + headerKeyValues.emplace_back (key.toRawUTF8()); + headerKeyValues.emplace_back (value.toRawUTF8()); + + // Store pointers to the strings + headerArray.push_back (headerKeyValues[headerKeyValues.size() - 2].c_str()); + headerArray.push_back (headerKeyValues.back().c_str()); + } + } + + headerArray.push_back (nullptr); + return headerArray; + } + + std::vector headerKeyValues; // To keep header strings alive + + // Helper to parse response headers + void parseResponseHeaders (const char* headers) + { + if (headers == nullptr) + return; + + String headersString (headers); + StringArray lines; + lines.addLines (headersString); + + for (const auto& line : lines) + { + int colonPos = line.indexOfChar (':'); + if (colonPos > 0) + { + String key = line.substring (0, colonPos).trim(); + String value = line.substring (colonPos + 1).trim(); + + auto previousValue = responseHeaders[key]; + responseHeaders.set (key, previousValue.isEmpty() ? value : (previousValue + "," + value)); + } + } + } + + JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (Pimpl) +}; + +std::unique_ptr URL::downloadToFile (const File& targetLocation, const DownloadTaskOptions& options) +{ + return URL::DownloadTask::createFallbackDownloader (*this, targetLocation, options); +} +#endif + +} // namespace juce diff --git a/modules/juce_core/native/juce_SystemStats_wasm.cpp b/modules/juce_core/native/juce_SystemStats_wasm.cpp index 87792c09..d626173c 100644 --- a/modules/juce_core/native/juce_SystemStats_wasm.cpp +++ b/modules/juce_core/native/juce_SystemStats_wasm.cpp @@ -42,11 +42,7 @@ namespace juce void Logger::outputDebugString (const String& text) { -#if JUCE_EMSCRIPTEN - EM_ASM({ console.log(UTF8ToString($0)); }, text.toRawUTF8()); -#else - std::printf ("%.*s", text.length(), text.toRawUTF8()); -#endif + std::fprintf (stderr, "%.*s", text.length(), text.toRawUTF8()); } //============================================================================== @@ -62,17 +58,22 @@ SystemStats::OperatingSystemType SystemStats::getOperatingSystemType() String SystemStats::getOperatingSystemName() { #if JUCE_EMSCRIPTEN - auto navigator = emscripten::val::global("navigator"); - - String platform{ navigator["platform"].as().c_str() }; - - if (platform.isEmpty()) - platform = "unknown"; - - return platform; + char* platform = reinterpret_cast (EM_ASM_PTR ({ + var str = navigator.platform || "unknown"; + var lengthBytes = lengthBytesUTF8 (str) + 1; + var ptr = _malloc (lengthBytes); + stringToUTF8 (str, ptr, lengthBytes); + return ptr; + })); + + String platformString (platform ? platform : "unknown"); + free (platform); + + return platformString; #else return "WASM"; #endif + } bool SystemStats::isOperatingSystem64Bit() @@ -80,11 +81,45 @@ bool SystemStats::isOperatingSystem64Bit() return sizeof(void*) == 8; } +String SystemStats::getUniqueDeviceID() +{ +#if JUCE_EMSCRIPTEN + char* deviceInfo = reinterpret_cast (EM_ASM_PTR ({ + var info = navigator.userAgent || ""; + info += navigator.platform || ""; + info += navigator.language || ""; + + var lengthBytes = lengthBytesUTF8 (info) + 1; + var ptr = _malloc (lengthBytes); + stringToUTF8 (info, ptr, lengthBytes); + return ptr; + })); + + String infoString (deviceInfo ? deviceInfo : ""); + free (deviceInfo); + + return String (static_cast (infoString.hashCode64())); +#else + return {}; +#endif +} + String SystemStats::getDeviceDescription() { #if JUCE_EMSCRIPTEN - auto navigator = emscripten::val::global("navigator"); - return { navigator["userAgent"].as().c_str() }; + char* userAgent = reinterpret_cast (EM_ASM_PTR ({ + var str = navigator.userAgent || "unknown"; + var lengthBytes = lengthBytesUTF8 (str) + 1; + var ptr = _malloc (lengthBytes); + stringToUTF8 (str, ptr, lengthBytes); + return ptr; + })); + + String userAgentString (userAgent ? userAgent : "unknown"); + + free (userAgent); + + return userAgentString; #else return "WASM VM"; #endif @@ -101,12 +136,13 @@ int SystemStats::getCpuSpeedInMegahertz() { return 0; } int SystemStats::getMemorySizeInMegabytes() { #if JUCE_EMSCRIPTEN - auto navigator = emscripten::val::global("navigator"); - if (! navigator.hasOwnProperty("deviceMemory")) + int memoryMB = EM_ASM_INT ({ + if ("deviceMemory" in navigator) + return navigator.deviceMemory * 1024; return 0; + }); - double deviceMemoryGB = navigator["deviceMemory"].as(); - return static_cast(deviceMemoryGB * 1024); // Convert GB to MB + return memoryMB * 1024; // Convert GB to MB #else return 0; #endif @@ -126,11 +162,18 @@ String SystemStats::getComputerName() { return {}; } String SystemStats::getUserLanguage() { #if JUCE_EMSCRIPTEN - auto navigator = emscripten::val::global("navigator"); - if (! navigator.hasOwnProperty("language")) - return {}; - - return { navigator["language"].as().c_str() }; + char* language = reinterpret_cast (EM_ASM_PTR ({ + var str = navigator.language || ""; + var lengthBytes = lengthBytesUTF8 (str) + 1; + var ptr = _malloc (lengthBytes); + stringToUTF8 (str, ptr, lengthBytes); + return ptr; + })); + + String languageString (language ? language : ""); + free (language); + + return languageString; #else return {}; #endif @@ -139,14 +182,25 @@ String SystemStats::getUserLanguage() String SystemStats::getUserRegion() { #if JUCE_EMSCRIPTEN - auto intl = emscripten::val::global("Intl"); - if (intl.hasOwnProperty("DateTimeFormat")) - { - auto localeOptions = intl.call("DateTimeFormat").call("resolvedOptions"); - if (localeOptions.hasOwnProperty("locale")) - return { localeOptions["locale"].as().c_str() }; - } - return {}; + char* locale = reinterpret_cast (EM_ASM_PTR ({ + var str = ""; + if (typeof Intl !== 'undefined' && Intl.DateTimeFormat) + { + var options = Intl.DateTimeFormat().resolvedOptions(); + if (options.locale) + str = options.locale; + } + + var lengthBytes = lengthBytesUTF8 (str) + 1; + var ptr = _malloc (lengthBytes); + stringToUTF8 (str, ptr, lengthBytes); + return ptr; + })); + + String localeString (locale ? locale : ""); + free (locale); + + return localeString; #else return {}; #endif @@ -161,28 +215,62 @@ String SystemStats::getDisplayLanguage() void CPUInformation::initialise() noexcept { #if JUCE_EMSCRIPTEN - auto navigator = emscripten::val::global("navigator"); - if (navigator.hasOwnProperty("hardwareConcurrency")) - { - numLogicalCPUs = navigator["hardwareConcurrency"].as(); - numPhysicalCPUs = numLogicalCPUs; // Physical core info isn't available - return; - } -#endif - + int hwConcurrency = EM_ASM_INT ({ + if ("hardwareConcurrency" in navigator) + return navigator.hardwareConcurrency; + return 1; + }); + + numLogicalCPUs = hwConcurrency > 0 ? hwConcurrency : 1; + numPhysicalCPUs = numLogicalCPUs; // Physical core info isn't available +#else numLogicalCPUs = 1; numPhysicalCPUs = 1; +#endif } //============================================================================== +namespace { +std::chrono::steady_clock::time_point getTimeSinceStartupFallback() noexcept +{ + static const auto timeSinceStartup = std::chrono::steady_clock::now(); + return timeSinceStartup; +} + +bool isRunningUnderBrowser() +{ + static bool isRunningUnderBrowser = [] + { + return EM_ASM_INT({ + return typeof window !== "undefined" ? 1 : 0; + }); + }(); + + return isRunningUnderBrowser; +} +} // namespace + uint32 juce_millisecondsSinceStartup() noexcept { - return static_cast (emscripten_get_now()); +#if JUCE_EMSCRIPTEN + if (isRunningUnderBrowser()) + return static_cast (emscripten_get_now()); +#endif + + const auto elapsed = std::chrono::duration_cast + (std::chrono::steady_clock::now() - getTimeSinceStartupFallback()); + + return static_cast(elapsed.count()); } int64 Time::getHighResolutionTicks() noexcept { - return static_cast (emscripten_get_now() * 1000.0); +#if JUCE_EMSCRIPTEN + if (isRunningUnderBrowser()) + return static_cast (emscripten_get_now() * 1000.0); +#endif + + return static_cast (juce_millisecondsSinceStartup() * 1000.0); } int64 Time::getHighResolutionTicksPerSecond() noexcept @@ -192,7 +280,12 @@ int64 Time::getHighResolutionTicksPerSecond() noexcept double Time::getMillisecondCounterHiRes() noexcept { - return emscripten_get_now(); +#if JUCE_EMSCRIPTEN + if (isRunningUnderBrowser()) + return emscripten_get_now(); +#endif + + return static_cast (juce_millisecondsSinceStartup()); } bool Time::setSystemTimeToThisTime() const diff --git a/modules/juce_core/system/juce_SystemStats.cpp b/modules/juce_core/system/juce_SystemStats.cpp index 0d89b608..50353b62 100644 --- a/modules/juce_core/system/juce_SystemStats.cpp +++ b/modules/juce_core/system/juce_SystemStats.cpp @@ -243,7 +243,7 @@ String SystemStats::getStackBacktrace() { String result; -#if JUCE_MINGW || JUCE_WASM +#if JUCE_MINGW || (JUCE_WASM && !JUCE_EMSCRIPTEN) jassertfalse; // sorry, not implemented yet! #elif JUCE_WINDOWS @@ -277,6 +277,12 @@ String SystemStats::getStackBacktrace() } } +#elif JUCE_EMSCRIPTEN + std::string temporaryStack; + temporaryStack.resize (10 * EM_ASM_INT_V ({ return (lengthBytesUTF8 || Module.lengthBytesUTF8)(stackTrace()); })); + EM_ASM_ARGS({ (stringToUTF8 || Module.stringToUTF8)(stackTrace(), $0, $1); }, temporaryStack.data(), temporaryStack.size()); + result << temporaryStack.c_str(); + #else void* stack[128]; @@ -332,8 +338,6 @@ String SystemStats::getStackBacktrace() } //============================================================================== -#if ! JUCE_WASM - static SystemStats::CrashHandlerFunction globalCrashHandler = nullptr; #if JUCE_WINDOWS @@ -363,7 +367,7 @@ void SystemStats::setApplicationCrashHandler (CrashHandlerFunction handler) SetUnhandledExceptionFilter (handleCrash); #elif JUCE_WASM - // TODO + // TODO #else const int signals[] = { SIGFPE, SIGILL, SIGSEGV, SIGBUS, SIGABRT, SIGSYS }; @@ -377,8 +381,6 @@ void SystemStats::setApplicationCrashHandler (CrashHandlerFunction handler) #endif } -#endif - bool SystemStats::isRunningInAppExtensionSandbox() noexcept { #if JUCE_MAC || JUCE_IOS @@ -402,28 +404,4 @@ bool SystemStats::isRunningInAppExtensionSandbox() noexcept #endif } -#if JUCE_UNIT_TESTS - -class UniqueHardwareIDTest final : public UnitTest -{ -public: - //============================================================================== - UniqueHardwareIDTest() - : UnitTest ("UniqueHardwareID", UnitTestCategories::analytics) - { - } - - void runTest() override - { - beginTest ("getUniqueDeviceID returns usable data."); - { - expect (SystemStats::getUniqueDeviceID().isNotEmpty()); - } - } -}; - -static UniqueHardwareIDTest uniqueHardwareIDTest; - -#endif - } // namespace juce diff --git a/tests/CMakeLists.txt b/tests/CMakeLists.txt index 24314303..32d7d05a 100644 --- a/tests/CMakeLists.txt +++ b/tests/CMakeLists.txt @@ -19,10 +19,10 @@ cmake_minimum_required(VERSION 3.28) -#if ("${yup_platform}" MATCHES "^(emscripten)$") -# add_definitions (-DTEST_HAS_PTHREAD=0) -# set (gtest_disable_pthreads ON CACHE BOOL "" FORCE) -#endif() +if ("${yup_platform}" MATCHES "^(emscripten)$") + add_definitions (-DTEST_HAS_PTHREAD=0) + set (gtest_disable_pthreads ON CACHE BOOL "" FORCE) +endif() # ==== Setup googletests include (FetchContent) diff --git a/tests/juce_core/juce_ElementComparator.cpp b/tests/juce_core/juce_ElementComparator.cpp index b954aaa1..d91d197f 100644 --- a/tests/juce_core/juce_ElementComparator.cpp +++ b/tests/juce_core/juce_ElementComparator.cpp @@ -36,7 +36,7 @@ struct IntComparator } }; -TEST (SortFunctionConverterTest, SortFunctionConverterWorks) +TEST (SortFunctionConverterTests, SortFunctionConverterWorks) { std::vector vec { 5, 2, 9, 1, 5, 6 }; diff --git a/tests/juce_core/juce_Enumerate.cpp b/tests/juce_core/juce_Enumerate.cpp index 0b5ffd09..8d873a5a 100644 --- a/tests/juce_core/juce_Enumerate.cpp +++ b/tests/juce_core/juce_Enumerate.cpp @@ -41,7 +41,7 @@ #include -TEST (Enumerate, Works_With_Bidirectional_Iterators) +TEST (EnumerateTests, Works_With_Bidirectional_Iterators) { const std::list elements { 10, 20, 30, 40, 50 }; std::vector counts; @@ -52,7 +52,7 @@ TEST (Enumerate, Works_With_Bidirectional_Iterators) EXPECT_EQ (counts, (std::vector { 0, 1, 2, 3, 4 })); } -TEST (Enumerate, Works_With_Random_Access_Iterators) +TEST (EnumerateTests, Works_With_Random_Access_Iterators) { const std::vector strings { "a", "bb", "ccc", "dddd", "eeeee" }; @@ -64,7 +64,7 @@ TEST (Enumerate, Works_With_Random_Access_Iterators) EXPECT_EQ (counts, (std::vector { 1, 3, 5, 7, 9 })); } -TEST (Enumerate, Works_With_Mutable_Ranges) +TEST (EnumerateTests, Works_With_Mutable_Ranges) { std::vector strings { "", "", "", "", "" }; @@ -74,7 +74,7 @@ TEST (Enumerate, Works_With_Mutable_Ranges) EXPECT_EQ (strings, (std::vector { "0", "1", "2", "3", "4" })); } -TEST (Enumerate, Iterator_Can_Be_Incremented_By_More_Than_One) +TEST (EnumerateTests, Iterator_Can_Be_Incremented_By_More_Than_One) { std::vector ints (6); @@ -88,7 +88,7 @@ TEST (Enumerate, Iterator_Can_Be_Incremented_By_More_Than_One) EXPECT_EQ (counts, (std::vector { 0, 2, 4 })); } -TEST (Enumerate, Iterator_Can_Be_Started_At_Non_Zero_Value) +TEST (EnumerateTests, Iterator_Can_Be_Started_At_Non_Zero_Value) { const std::vector ints (6); @@ -100,14 +100,14 @@ TEST (Enumerate, Iterator_Can_Be_Started_At_Non_Zero_Value) EXPECT_EQ (counts, (std::vector { 5, 6, 7, 8, 9, 10 })); } -TEST (Enumerate, Subtracting_Two_Iterators_Returns_The_Difference_Between_The_Base_Iterators) +TEST (EnumerateTests, Subtracting_Two_Iterators_Returns_The_Difference_Between_The_Base_Iterators) { const std::vector ints (6); const auto enumerated = juce::enumerate (ints); EXPECT_EQ ((int) (enumerated.end() - enumerated.begin()), (int) ints.size()); } -TEST (Enumerate, EnumerateIterator_Can_Be_Decremented) +TEST (EnumerateTests, EnumerateIterator_Can_Be_Decremented) { const std::vector ints (5); std::vector counts; @@ -120,7 +120,7 @@ TEST (Enumerate, EnumerateIterator_Can_Be_Decremented) EXPECT_EQ (counts, (std::vector { -1, -2, -3, -4, -5 })); } -TEST (Enumerate, EnumerateIterator_Can_Be_Compared) +TEST (EnumerateTests, EnumerateIterator_Can_Be_Compared) { const std::vector ints (6); const auto enumerated = juce::enumerate (ints); diff --git a/tests/juce_core/juce_FlagSet.cpp b/tests/juce_core/juce_FlagSet.cpp index 047aac16..6e305f85 100644 --- a/tests/juce_core/juce_FlagSet.cpp +++ b/tests/juce_core/juce_FlagSet.cpp @@ -37,35 +37,35 @@ static inline constexpr LogOption verboseLog = LogOption::declareValue(); } // namespace -TEST (FlagSet, Default_Constructed) +TEST (FlagSetTests, Default_Constructed) { LogOption option; EXPECT_FALSE (option.test (verboseLog)); EXPECT_FALSE (option.test (noErrorLog)); } -TEST (FlagSet, Default_Constructed_From_Default) +TEST (FlagSetTests, Default_Constructed_From_Default) { LogOption option = defaultLog; EXPECT_FALSE (option.test (verboseLog)); EXPECT_FALSE (option.test (noErrorLog)); } -TEST (FlagSet, Default_Constructed_From_Value) +TEST (FlagSetTests, Default_Constructed_From_Value) { LogOption option = verboseLog; EXPECT_TRUE (option.test (verboseLog)); EXPECT_FALSE (option.test (noErrorLog)); } -TEST (FlagSet, Default_Constructed_From_Values) +TEST (FlagSetTests, Default_Constructed_From_Values) { LogOption option = verboseLog | noErrorLog; EXPECT_TRUE (option.test (verboseLog)); EXPECT_TRUE (option.test (noErrorLog)); } -TEST (FlagSet, To_String) +TEST (FlagSetTests, To_String) { EXPECT_EQ (juce::String ("00"), defaultLog.toString()); EXPECT_EQ (juce::String ("10"), verboseLog.toString()); @@ -75,7 +75,7 @@ TEST (FlagSet, To_String) EXPECT_EQ (juce::String ("11"), option.toString()); } -TEST (FlagSet, From_String) +TEST (FlagSetTests, From_String) { EXPECT_EQ (defaultLog, LogOption::fromString ("00")); EXPECT_EQ (verboseLog, LogOption::fromString ("10")); diff --git a/tests/juce_core/juce_Identifier.cpp b/tests/juce_core/juce_Identifier.cpp index 9caa8aa8..6c8625f2 100644 --- a/tests/juce_core/juce_Identifier.cpp +++ b/tests/juce_core/juce_Identifier.cpp @@ -25,21 +25,21 @@ using namespace juce; -TEST (Identifier, DefaultConstructorCreatesNullIdentifier) +TEST (IdentifierTests, DefaultConstructorCreatesNullIdentifier) { Identifier id; EXPECT_TRUE (id.isNull()); EXPECT_FALSE (id.isValid()); } -TEST (Identifier, ConstructFromStringLiteral) +TEST (IdentifierTests, ConstructFromStringLiteral) { Identifier id ("test"); EXPECT_EQ (id.toString(), "test"); EXPECT_TRUE (id.isValid()); } -TEST (Identifier, ConstructFromStringObject) +TEST (IdentifierTests, ConstructFromStringObject) { String name = "example"; Identifier id (name); @@ -47,28 +47,28 @@ TEST (Identifier, ConstructFromStringObject) EXPECT_TRUE (id.isValid()); } -TEST (Identifier, CopyConstructor) +TEST (IdentifierTests, CopyConstructor) { Identifier original ("copyTest"); Identifier copy = original; EXPECT_EQ (copy, original); } -TEST (Identifier, MoveConstructor) +TEST (IdentifierTests, MoveConstructor) { Identifier original ("moveTest"); Identifier moved = std::move (original); EXPECT_EQ (moved.toString(), "moveTest"); } -TEST (Identifier, AssignmentOperator) +TEST (IdentifierTests, AssignmentOperator) { Identifier id1 ("first"); Identifier id2 = id1; EXPECT_EQ (id2, id1); } -TEST (Identifier, MoveAssignmentOperator) +TEST (IdentifierTests, MoveAssignmentOperator) { Identifier id1 ("first"); Identifier id2 ("second"); @@ -76,7 +76,7 @@ TEST (Identifier, MoveAssignmentOperator) EXPECT_EQ (id2.toString(), "first"); } -TEST (Identifier, ComparisonOperators) +TEST (IdentifierTests, ComparisonOperators) { Identifier id1 ("same"); Identifier id2 ("same"); @@ -88,7 +88,7 @@ TEST (Identifier, ComparisonOperators) EXPECT_FALSE (id1 != id2); } -TEST (Identifier, IsValidIdentifier) +TEST (IdentifierTests, IsValidIdentifier) { EXPECT_TRUE (Identifier::isValidIdentifier ("valid_name")); EXPECT_FALSE (Identifier::isValidIdentifier ("invalid name")); @@ -97,14 +97,14 @@ TEST (Identifier, IsValidIdentifier) EXPECT_FALSE (Identifier::isValidIdentifier ("_1 23")); } -TEST (Identifier, ConversionToStringRef) +TEST (IdentifierTests, ConversionToStringRef) { Identifier id ("conversion"); StringRef ref = id; EXPECT_EQ (ref, StringRef ("conversion")); } -TEST (Identifier, ConversionToCharPointer) +TEST (IdentifierTests, ConversionToCharPointer) { Identifier id ("pointer"); auto ptr = id.getCharPointer(); diff --git a/tests/juce_core/juce_LinkedListPointer.cpp b/tests/juce_core/juce_LinkedListPointer.cpp index 4222bf0b..d259a3eb 100644 --- a/tests/juce_core/juce_LinkedListPointer.cpp +++ b/tests/juce_core/juce_LinkedListPointer.cpp @@ -36,13 +36,13 @@ struct TestObject } }; -TEST (LinkedListPointer, DefaultConstructor) +TEST (LinkedListPointerTests, DefaultConstructor) { LinkedListPointer list; EXPECT_EQ (list.get(), nullptr); } -TEST (LinkedListPointer, ConstructorWithHeadItem) +TEST (LinkedListPointerTests, ConstructorWithHeadItem) { auto* obj = new TestObject (1); LinkedListPointer list (obj); @@ -50,7 +50,7 @@ TEST (LinkedListPointer, ConstructorWithHeadItem) delete obj; } -TEST (LinkedListPointer, AssignmentOperator) +TEST (LinkedListPointerTests, AssignmentOperator) { auto* obj = new TestObject (1); LinkedListPointer list; @@ -59,7 +59,7 @@ TEST (LinkedListPointer, AssignmentOperator) delete obj; } -TEST (LinkedListPointer, MoveConstructor) +TEST (LinkedListPointerTests, MoveConstructor) { auto* obj = new TestObject (1); LinkedListPointer list1 (obj); @@ -69,7 +69,7 @@ TEST (LinkedListPointer, MoveConstructor) delete obj; } -TEST (LinkedListPointer, MoveAssignmentOperator) +TEST (LinkedListPointerTests, MoveAssignmentOperator) { auto* obj = new TestObject (1); LinkedListPointer list1 (obj); @@ -81,7 +81,7 @@ TEST (LinkedListPointer, MoveAssignmentOperator) } /* -TEST (LinkedListPointer, GetLast) +TEST (LinkedListPointerTests, GetLast) { auto* obj1 = new TestObject(1); auto* obj2 = new TestObject(2); @@ -93,7 +93,7 @@ TEST (LinkedListPointer, GetLast) } */ -TEST (LinkedListPointer, Size) +TEST (LinkedListPointerTests, Size) { LinkedListPointer list; EXPECT_EQ (list.size(), 0); @@ -108,7 +108,7 @@ TEST (LinkedListPointer, Size) delete obj2; } -TEST (LinkedListPointer, Contains) +TEST (LinkedListPointerTests, Contains) { auto* obj1 = new TestObject (1); auto* obj2 = new TestObject (2); @@ -121,7 +121,7 @@ TEST (LinkedListPointer, Contains) delete obj2; } -TEST (LinkedListPointer, InsertNext) +TEST (LinkedListPointerTests, InsertNext) { auto* obj1 = new TestObject (1); auto* obj2 = new TestObject (2); @@ -134,7 +134,7 @@ TEST (LinkedListPointer, InsertNext) delete obj2; } -TEST (LinkedListPointer, InsertAtIndex) +TEST (LinkedListPointerTests, InsertAtIndex) { auto* obj1 = new TestObject (1); auto* obj2 = new TestObject (2); @@ -151,7 +151,7 @@ TEST (LinkedListPointer, InsertAtIndex) delete obj3; } -TEST (LinkedListPointer, ReplaceNext) +TEST (LinkedListPointerTests, ReplaceNext) { auto* obj1 = new TestObject (1); auto* obj2 = new TestObject (2); @@ -163,7 +163,7 @@ TEST (LinkedListPointer, ReplaceNext) delete obj2; } -TEST (LinkedListPointer, RemoveNext) +TEST (LinkedListPointerTests, RemoveNext) { auto* obj1 = new TestObject (1); auto* obj2 = new TestObject (2); @@ -176,7 +176,7 @@ TEST (LinkedListPointer, RemoveNext) delete obj2; } -TEST (LinkedListPointer, Remove) +TEST (LinkedListPointerTests, Remove) { auto* obj1 = new TestObject (1); auto* obj2 = new TestObject (2); @@ -189,7 +189,7 @@ TEST (LinkedListPointer, Remove) delete obj2; } -TEST (LinkedListPointer, DeleteAll) +TEST (LinkedListPointerTests, DeleteAll) { auto* obj1 = new TestObject (1); auto* obj2 = new TestObject (2); @@ -199,7 +199,7 @@ TEST (LinkedListPointer, DeleteAll) EXPECT_EQ (list.get(), nullptr); } -TEST (LinkedListPointer, CopyToArray) +TEST (LinkedListPointerTests, CopyToArray) { auto* obj1 = new TestObject (1); auto* obj2 = new TestObject (2); @@ -213,7 +213,7 @@ TEST (LinkedListPointer, CopyToArray) delete obj2; } -TEST (LinkedListPointer, SwapWith) +TEST (LinkedListPointerTests, SwapWith) { auto* obj1 = new TestObject (1); auto* obj2 = new TestObject (2); @@ -226,7 +226,7 @@ TEST (LinkedListPointer, SwapWith) delete obj2; } -TEST (LinkedListPointer, Appender) +TEST (LinkedListPointerTests, Appender) { LinkedListPointer list; LinkedListPointer::Appender appender (list); @@ -240,7 +240,7 @@ TEST (LinkedListPointer, Appender) delete obj2; } -TEST (LinkedListPointer, FindPointerTo) +TEST (LinkedListPointerTests, FindPointerTo) { auto* obj1 = new TestObject (1); auto* obj2 = new TestObject (2); @@ -258,7 +258,7 @@ TEST (LinkedListPointer, FindPointerTo) } /* -TEST (LinkedListPointer, AddCopyOfList) +TEST (LinkedListPointerTests, AddCopyOfList) { auto* obj1 = new TestObject(1); auto* obj2 = new TestObject(2); diff --git a/tests/juce_core/juce_ListenerList.cpp b/tests/juce_core/juce_ListenerList.cpp index a6bd8062..a2fcb166 100644 --- a/tests/juce_core/juce_ListenerList.cpp +++ b/tests/juce_core/juce_ListenerList.cpp @@ -48,7 +48,81 @@ class MockListener MOCK_METHOD (void, myCallbackMethod, (int, bool) ); }; -TEST (ListenerList, Add_Remove_Contains) +class ListenerListTests : public ::testing::Test +{ +protected: + class TestListener + { + public: + explicit TestListener (std::function cb) + : callback (std::move (cb)) + { + } + + void doCallback() + { + ++numCalls; + callback(); + } + + int getNumCalls() const { return numCalls; } + + private: + int numCalls = 0; + std::function callback; + }; + + class TestObject + { + public: + void addListener (std::function cb) + { + listeners.push_back (std::make_unique (std::move (cb))); + listenerList.add (listeners.back().get()); + } + + void removeListener (int i) { listenerList.remove (listeners[(size_t) i].get()); } + + void callListeners() + { + ++callLevel; + listenerList.call ([] (auto& l) + { + l.doCallback(); + }); + --callLevel; + } + + int getNumListeners() const { return (int) listeners.size(); } + + auto& getListener (int i) { return *listeners[(size_t) i]; } + + int getCallLevel() const { return callLevel; } + + bool wereAllNonRemovedListenersCalled (int numCalls) const + { + return std::all_of (std::begin (listeners), std::end (listeners), [&] (auto& listener) + { + return (! listenerList.contains (listener.get())) || listener->getNumCalls() == numCalls; + }); + } + + private: + std::vector> listeners; + juce::ListenerList listenerList; + int callLevel = 0; + }; + + static std::set chooseUnique (juce::Random& random, int max, int numChosen) + { + std::set result; + while ((int) result.size() < numChosen) + result.insert (random.nextInt ({ 0, max })); + return result; + } +}; + +TEST_F (ListenerListTests, Add_Remove_Contains) { juce::ListenerList listeners; MockListener listener1, listener2; @@ -67,7 +141,7 @@ TEST (ListenerList, Add_Remove_Contains) EXPECT_FALSE (listeners.contains (&listener2)); } -TEST (ListenerList, Call) +TEST_F (ListenerListTests, Call) { juce::ListenerList listeners; MockListener listener1, listener2; @@ -81,7 +155,7 @@ TEST (ListenerList, Call) listeners.call (&MockListener::myCallbackMethod, 1234, true); } -TEST (ListenerList, Call_Excluding) +TEST_F (ListenerListTests, Call_Excluding) { juce::ListenerList listeners; MockListener listener1, listener2; @@ -95,7 +169,7 @@ TEST (ListenerList, Call_Excluding) listeners.callExcluding (&listener2, &MockListener::myCallbackMethod, 1234, true); } -TEST (ListenerList, Call_Checked) +TEST_F (ListenerListTests, Call_Checked) { struct BailOutChecker { @@ -119,7 +193,7 @@ TEST (ListenerList, Call_Checked) listeners.callChecked (checker, &MockListener::myCallbackMethod, 1234, true); } -TEST (ListenerList, Call_Checked_Excluding) +TEST_F (ListenerListTests, Call_Checked_Excluding) { struct BailOutChecker { @@ -143,7 +217,7 @@ TEST (ListenerList, Call_Checked_Excluding) listeners.callCheckedExcluding (&listener2, checker, &MockListener::myCallbackMethod, 1234, true); } -TEST (ListenerList, Add_Scoped) +TEST_F (ListenerListTests, Add_Scoped) { juce::ListenerList listeners; MockListener listener1; @@ -156,7 +230,7 @@ TEST (ListenerList, Add_Scoped) EXPECT_FALSE (listeners.contains (&listener1)); } -TEST (ListenerList, Size_Is_Empty) +TEST_F (ListenerListTests, Size_Is_Empty) { juce::ListenerList listeners; MockListener listener1, listener2; @@ -178,7 +252,7 @@ TEST (ListenerList, Size_Is_Empty) } /* -TEST (ListenerList, Null_Pointer_Handling) +TEST_F (ListenerListTests, Null_Pointer_Handling) { juce::ListenerList listeners; MockListener* nullListener = nullptr; @@ -191,7 +265,7 @@ TEST (ListenerList, Null_Pointer_Handling) } */ -TEST (ListenerList, Multiple_Add_Remove) +TEST_F (ListenerListTests, Multiple_Add_Remove) { juce::ListenerList listeners; MockListener listener1; @@ -206,7 +280,7 @@ TEST (ListenerList, Multiple_Add_Remove) EXPECT_EQ (listeners.size(), 0); } -TEST (ListenerList, Call_During_Callback) +TEST_F (ListenerListTests, Call_During_Callback) { juce::ListenerList listeners; MockListener listener1, listener2; @@ -225,7 +299,7 @@ TEST (ListenerList, Call_During_Callback) EXPECT_EQ (listeners.size(), 2); } -TEST (ListenerList, Remove_During_Callback) +TEST_F (ListenerListTests, Remove_During_Callback) { juce::ListenerList listeners; MockListener listener1, listener2; @@ -246,7 +320,7 @@ TEST (ListenerList, Remove_During_Callback) EXPECT_FALSE (listeners.contains (&listener2)); } -TEST (ListenerList, Clear_During_Callback) +TEST_F (ListenerListTests, Clear_During_Callback) { juce::ListenerList listeners; MockListener listener1, listener2; @@ -264,7 +338,7 @@ TEST (ListenerList, Clear_During_Callback) EXPECT_EQ (listeners.size(), 0); } -TEST (ListenerList, Nested_Call) +TEST_F (ListenerListTests, Nested_Call) { juce::ListenerList listeners; MockListener listener1, listener2; @@ -283,80 +357,6 @@ TEST (ListenerList, Nested_Call) listeners.call (&MockListener::myCallbackMethod, 1234, true); } -class ListenerListTests : public ::testing::Test -{ -protected: - class TestListener - { - public: - explicit TestListener (std::function cb) - : callback (std::move (cb)) - { - } - - void doCallback() - { - ++numCalls; - callback(); - } - - int getNumCalls() const { return numCalls; } - - private: - int numCalls = 0; - std::function callback; - }; - - class TestObject - { - public: - void addListener (std::function cb) - { - listeners.push_back (std::make_unique (std::move (cb))); - listenerList.add (listeners.back().get()); - } - - void removeListener (int i) { listenerList.remove (listeners[(size_t) i].get()); } - - void callListeners() - { - ++callLevel; - listenerList.call ([] (auto& l) - { - l.doCallback(); - }); - --callLevel; - } - - int getNumListeners() const { return (int) listeners.size(); } - - auto& getListener (int i) { return *listeners[(size_t) i]; } - - int getCallLevel() const { return callLevel; } - - bool wereAllNonRemovedListenersCalled (int numCalls) const - { - return std::all_of (std::begin (listeners), std::end (listeners), [&] (auto& listener) - { - return (! listenerList.contains (listener.get())) || listener->getNumCalls() == numCalls; - }); - } - - private: - std::vector> listeners; - juce::ListenerList listenerList; - int callLevel = 0; - }; - - static std::set chooseUnique (juce::Random& random, int max, int numChosen) - { - std::set result; - while ((int) result.size() < numChosen) - result.insert (random.nextInt ({ 0, max })); - return result; - } -}; - TEST_F (ListenerListTests, RemovingAlreadyCalledListener) { TestObject test; diff --git a/tests/juce_core/juce_PlatformDefs.cpp b/tests/juce_core/juce_PlatformDefs.cpp index f1960872..8c55ae6a 100644 --- a/tests/juce_core/juce_PlatformDefs.cpp +++ b/tests/juce_core/juce_PlatformDefs.cpp @@ -27,14 +27,14 @@ using namespace juce; -TEST (PlatformDefs, Stringify) +TEST (PlatformDefsTests, Stringify) { constexpr auto x = std::string_view (JUCE_STRINGIFY (abcdf)); static_assert (x == "abcdf"); } -TEST (PlatformDefs, IsConstantEvaluated) +TEST (PlatformDefsTests, IsConstantEvaluated) { constexpr auto x = [] { @@ -50,7 +50,7 @@ TEST (PlatformDefs, IsConstantEvaluated) EXPECT_EQ (y, 2); } -TEST (PlatformDefs, ConstexprJassertfalse) +TEST (PlatformDefsTests, ConstexprJassertfalse) { constexpr auto x = [] { diff --git a/tests/juce_core/juce_StringPool.cpp b/tests/juce_core/juce_StringPool.cpp index 0d80f892..280892b6 100644 --- a/tests/juce_core/juce_StringPool.cpp +++ b/tests/juce_core/juce_StringPool.cpp @@ -28,7 +28,7 @@ using namespace juce; -class StringPoolTest : public ::testing::Test +class StringPoolTests : public ::testing::Test { protected: StringPool pool; @@ -40,7 +40,7 @@ class StringPoolTest : public ::testing::Test } }; -TEST_F (StringPoolTest, ReturnsSameInstanceForDuplicateString) +TEST_F (StringPoolTests, ReturnsSameInstanceForDuplicateString) { String str = "testString"; auto pooled1 = pool.getPooledString (str); @@ -50,7 +50,7 @@ TEST_F (StringPoolTest, ReturnsSameInstanceForDuplicateString) EXPECT_EQ (pooled1.getCharPointer().getAddress(), pooled2.getCharPointer().getAddress()); } -TEST_F (StringPoolTest, ReturnsSameInstanceForDifferentInputTypes) +TEST_F (StringPoolTests, ReturnsSameInstanceForDifferentInputTypes) { const char* cstr = "anotherTest"; String str (cstr); @@ -64,7 +64,7 @@ TEST_F (StringPoolTest, ReturnsSameInstanceForDifferentInputTypes) EXPECT_EQ (pooled1.getCharPointer().getAddress(), pooled3.getCharPointer().getAddress()); } -TEST_F (StringPoolTest, DifferentStringsDifferentInstances) +TEST_F (StringPoolTests, DifferentStringsDifferentInstances) { auto pooled1 = pool.getPooledString ("stringOne"); auto pooled2 = pool.getPooledString ("stringTwo"); @@ -73,7 +73,7 @@ TEST_F (StringPoolTest, DifferentStringsDifferentInstances) } /* -TEST_F (StringPoolTest, GarbageCollectFreesUnreferencedStrings) +TEST_F (StringPoolTests, GarbageCollectFreesUnreferencedStrings) { std::string b{ "temp2" }, c{ "temp3" }; @@ -99,7 +99,7 @@ TEST_F (StringPoolTest, GarbageCollectFreesUnreferencedStrings) } */ -TEST_F (StringPoolTest, DifferentPoolDifferentStrings) +TEST_F (StringPoolTests, DifferentPoolDifferentStrings) { StringPool pool1, pool2; @@ -109,7 +109,7 @@ TEST_F (StringPoolTest, DifferentPoolDifferentStrings) EXPECT_NE (pooled1.getCharPointer().getAddress(), pooled2.getCharPointer().getAddress()); } -TEST_F (StringPoolTest, GlobalPoolSingletonInstance) +TEST_F (StringPoolTests, GlobalPoolSingletonInstance) { auto& globalPool1 = StringPool::getGlobalPool(); auto& globalPool2 = StringPool::getGlobalPool(); diff --git a/tests/juce_core/juce_SystemStats.cpp b/tests/juce_core/juce_SystemStats.cpp new file mode 100644 index 00000000..047e1bbb --- /dev/null +++ b/tests/juce_core/juce_SystemStats.cpp @@ -0,0 +1,232 @@ +/* + ============================================================================== + + This file is part of the YUP library. + Copyright (c) 2024 - kunitoki@gmail.com + + YUP is an open source library subject to open-source licensing. + + The code included in this file is provided under the terms of the ISC license + http://www.isc.org/downloads/software-support-policy/isc-license. Permission + to use, copy, modify, and/or distribute this software for any purpose with or + without fee is hereby granted provided that the above copyright notice and + this permission notice appear in all copies. + + YUP IS PROVIDED "AS IS" WITHOUT ANY WARRANTY, AND ALL WARRANTIES, WHETHER + EXPRESSED OR IMPLIED, INCLUDING MERCHANTABILITY AND FITNESS FOR PURPOSE, ARE + DISCLAIMED. + + ============================================================================== +*/ + +#include + +#include + +using namespace juce; + +TEST (SystemStats, JUCEVersion) +{ + auto version = SystemStats::getJUCEVersion(); + EXPECT_FALSE(version.isEmpty()); +} + +TEST (SystemStats, OperatingSystemType) +{ + auto systemType = SystemStats::getOperatingSystemType(); + +#if JUCE_WINDOWS + EXPECT_TRUE(systemType & SystemStats::OperatingSystemType::Windows); +#elif JUCE_MAC + EXPECT_TRUE(systemType & SystemStats::OperatingSystemType::MacOSX); +#elif JUCE_LINUX + EXPECT_TRUE(systemType & SystemStats::OperatingSystemType::Linux); +#elif JUCE_ANDROID + EXPECT_TRUE(systemType & SystemStats::OperatingSystemType::Android); +#elif JUCE_IOS + EXPECT_TRUE(systemType & SystemStats::OperatingSystemType::iOS); +#elif JUCE_EMSCRIPTEN + EXPECT_TRUE(systemType & SystemStats::OperatingSystemType::WebBrowser); +#elif JUCE_WASM + EXPECT_TRUE(systemType & SystemStats::OperatingSystemType::WASM); +#else + ignoreUnused(systemType); +#endif +} + +TEST (SystemStatsTests, GetOperatingSystemName) +{ + String osName = SystemStats::getOperatingSystemName(); + EXPECT_FALSE(osName.isEmpty()); +} + +TEST (SystemStatsTests, IsOperatingSystem64Bit) +{ + bool is64Bit = SystemStats::isOperatingSystem64Bit(); + if constexpr (sizeof(void*) == 8) + EXPECT_TRUE(is64Bit); + else + EXPECT_FALSE(is64Bit); +} + +TEST (SystemStatsTests, GetEnvironmentVariable) +{ + String existingVar = SystemStats::getEnvironmentVariable("PATH", "default"); + EXPECT_FALSE(existingVar.isEmpty()); + + String nonExistingVar = SystemStats::getEnvironmentVariable("NON_EXISTENT_VAR", "default"); + EXPECT_EQ(nonExistingVar, "default"); +} + +TEST (SystemStatsTests, DISABLED_SetAndRemoveEnvironmentVariable) +{ + String varName = "JUCE_TEST_ENV_VAR"; + String varValue = "JUCE_TEST_VALUE"; + + bool setResult = SystemStats::setEnvironmentVariable(varName, varValue); + EXPECT_TRUE(setResult); + + String fetchedValue = SystemStats::getEnvironmentVariable(varName, ""); + EXPECT_EQ(fetchedValue, varValue); + + bool removeResult = SystemStats::removeEnvironmentVariable(varName); + EXPECT_TRUE(removeResult); + + String afterRemoval = SystemStats::getEnvironmentVariable(varName, ""); + EXPECT_EQ(afterRemoval, ""); +} + +TEST (SystemStatsTests, GetEnvironmentVariables) +{ + auto envVars = SystemStats::getEnvironmentVariables(); + EXPECT_GT(envVars.size(), 0); +} + +TEST (SystemStatsTests, DISABLED_UserAndComputerInfo) +{ + String logonName = SystemStats::getLogonName(); + EXPECT_FALSE(logonName.isEmpty()); + + String fullUserName = SystemStats::getFullUserName(); + EXPECT_FALSE(fullUserName.isEmpty()); + + String computerName = SystemStats::getComputerName(); + EXPECT_FALSE(computerName.isEmpty()); +} + +TEST (SystemStatsTests, LocaleInfo) +{ + String userLanguage = SystemStats::getUserLanguage(); + EXPECT_FALSE(userLanguage.isEmpty()); + EXPECT_GE(userLanguage.length(), 2); + + String userRegion = SystemStats::getUserRegion(); + EXPECT_FALSE(userRegion.isEmpty()); + EXPECT_GT(userRegion.length(), 0); + + String displayLanguage = SystemStats::getDisplayLanguage(); + EXPECT_FALSE(displayLanguage.isEmpty()); + EXPECT_GE(displayLanguage.length(), 2); +} + +TEST (SystemStatsTests, DeviceInfo) +{ + String deviceDescription = SystemStats::getDeviceDescription(); + EXPECT_TRUE(deviceDescription.isNotEmpty()); + +#if !JUCE_WASM + String deviceManufacturer = SystemStats::getDeviceManufacturer(); + EXPECT_TRUE(deviceManufacturer.isNotEmpty()); +#endif +} + +TEST (SystemStatsTests, GetUniqueDeviceID) +{ + String deviceID = SystemStats::getUniqueDeviceID(); + EXPECT_TRUE(deviceID.isNotEmpty()); + + String deviceID2 = SystemStats::getUniqueDeviceID(); + EXPECT_EQ(deviceID, deviceID2); +} + +TEST (SystemStatsTests, GetMachineIdentifiers) +{ + auto identifiers = SystemStats::getMachineIdentifiers(SystemStats::MachineIdFlags::uniqueId); + EXPECT_FALSE(identifiers.isEmpty()); +} + +TEST (SystemStatsTests, CpuInfo) +{ + int numCpus = SystemStats::getNumCpus(); + EXPECT_GT(numCpus, 0); + + int numPhysicalCpus = SystemStats::getNumPhysicalCpus(); + EXPECT_GT(numPhysicalCpus, 0); + +#if !JUCE_WASM + int cpuSpeed = SystemStats::getCpuSpeedInMegahertz(); + EXPECT_GT(cpuSpeed, 0); + + String cpuVendor = SystemStats::getCpuVendor(); + EXPECT_TRUE(cpuVendor.isNotEmpty()); + + String cpuModel = SystemStats::getCpuModel(); + EXPECT_TRUE(cpuModel.isNotEmpty()); +#endif +} + +TEST (SystemStatsTests, CpuFeatures) +{ + EXPECT_NO_THROW(SystemStats::hasMMX()); + EXPECT_NO_THROW(SystemStats::hasSSE()); + EXPECT_NO_THROW(SystemStats::hasSSE2()); + EXPECT_NO_THROW(SystemStats::hasSSE3()); + EXPECT_NO_THROW(SystemStats::hasSSSE3()); + EXPECT_NO_THROW(SystemStats::hasSSE41()); + EXPECT_NO_THROW(SystemStats::hasSSE42()); + EXPECT_NO_THROW(SystemStats::hasAVX()); + EXPECT_NO_THROW(SystemStats::hasAVX2()); + EXPECT_NO_THROW(SystemStats::hasNeon()); +} + +TEST (SystemStatsTests, MemoryInfo) +{ +#if !JUCE_WASM + int memorySize = SystemStats::getMemorySizeInMegabytes(); + EXPECT_GT(memorySize, 0); +#endif + + int pageSize = SystemStats::getPageSize(); + EXPECT_GT(pageSize, 0); +} + +TEST (SystemStatsTests, GetStackBacktrace) +{ +#if !JUCE_WASM + String backtrace = SystemStats::getStackBacktrace(); + EXPECT_TRUE(backtrace.isNotEmpty()); +#endif +} + +TEST (SystemStatsTests, SetApplicationCrashHandler) +{ + static bool handlerCalled = false; + auto crashHandler = [](void*) { handlerCalled = true; }; + + SystemStats::setApplicationCrashHandler(crashHandler); + EXPECT_NO_THROW(SystemStats::setApplicationCrashHandler(crashHandler)); +} + +TEST (SystemStatsTests, IsRunningInAppExtensionSandbox) +{ + bool isSandboxed = SystemStats::isRunningInAppExtensionSandbox(); + EXPECT_TRUE(isSandboxed == true || isSandboxed == false); +} + +#if JUCE_MAC +TEST (SystemStatsTests, IsAppSandboxEnabled) +{ + bool isSandboxEnabled = SystemStats::isAppSandboxEnabled(); + EXPECT_TRUE(isSandboxEnabled == true || isSandboxEnabled == false); +} +#endif diff --git a/tests/juce_core/juce_Time.cpp b/tests/juce_core/juce_Time.cpp index 3de476f3..dd412692 100644 --- a/tests/juce_core/juce_Time.cpp +++ b/tests/juce_core/juce_Time.cpp @@ -23,6 +23,8 @@ #include +#include + using namespace juce; TEST (TimeTests, DefaultConstructor) @@ -248,7 +250,7 @@ TEST (TimeTests, ComparisonOperators) TEST (TimeTests, GetMillisecondCounter) { uint32 millis1 = Time::getMillisecondCounter(); - EXPECT_GT (millis1, 0); + EXPECT_GE (millis1, 0); Time::waitForMillisecondCounter (millis1 + 100); uint32 millis2 = Time::getMillisecondCounter(); EXPECT_GT (millis2, millis1); @@ -257,7 +259,7 @@ TEST (TimeTests, GetMillisecondCounter) TEST (TimeTests, GetMillisecondCounterHiRes) { double hiResMillis1 = Time::getMillisecondCounterHiRes(); - EXPECT_GT (hiResMillis1, 0.0); + EXPECT_GE (hiResMillis1, 0.0); Time::waitForMillisecondCounter (static_cast (hiResMillis1) + 100); double hiResMillis2 = Time::getMillisecondCounterHiRes(); EXPECT_GT (hiResMillis2, hiResMillis1); @@ -266,7 +268,10 @@ TEST (TimeTests, GetMillisecondCounterHiRes) TEST (TimeTests, GetApproximateMillisecondCounter) { uint32 approxMillis1 = Time::getApproximateMillisecondCounter(); - EXPECT_GT (approxMillis1, 0); + EXPECT_GE (approxMillis1, 0); + Time::waitForMillisecondCounter (approxMillis1 + 100); + uint32 approxMillis2 = Time::getApproximateMillisecondCounter(); + EXPECT_GT (approxMillis2, approxMillis1); } TEST (TimeTests, GetHighResolutionTicks)