From bb1890b031977a1e5b67da98cd11a1d1a0dacd2a Mon Sep 17 00:00:00 2001 From: Dan Rosser Date: Tue, 11 Aug 2026 22:36:24 +1000 Subject: [PATCH 1/2] of Menu 0.4.2 -> 0.4.3 fix for macOS / osx was downloading without option for other platforms / releases --- scripts/of.sh | 49 ++++++++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 48 insertions(+), 1 deletion(-) diff --git a/scripts/of.sh b/scripts/of.sh index d954367bd45..6f91294f08b 100755 --- a/scripts/of.sh +++ b/scripts/of.sh @@ -1,6 +1,6 @@ #!/usr/bin/env bash # of.sh - openFrameworks CLI | Dan Rosser 2025 -OF_SCRIPT_VERSION=0.4.2 +OF_SCRIPT_VERSION=0.4.3 OF_DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )" OF_DIR="$(realpath "$OF_DIR/../")" @@ -1341,6 +1341,50 @@ menuPickLibSource(){ export LIB_SOURCE } +menuPickLibPlatform(){ + local source="${1:-$LIB_SOURCE}" + local current="${2:-$OF_PLATFORM}" + local -a opts=() + case "$source" in + apothecary) + opts=( + "osx — desktop host libraries|osx" + "macos — multi-target XCFrameworks (iOS, macOS, tvOS)|macos" + "ios — iPhone / iPad|ios" + "android|android" + "linux|linux" + "emscripten|emscripten" + "msys2|msys2" + "vs — Visual Studio|vs" + ) + ;; + oflibs) + opts=( + "osx / macos|osx" + "linux|linux" + "linux aarch64|linuxaarch64" + "emscripten|emscripten" + "Visual Studio|vs" + ) + ;; + archive) + opts=( + "osx|osx" + "ios|ios" + "android|android" + "linux|linux" + "msys2|msys2" + "Visual Studio|vs" + ) + ;; + esac + [[ ${#opts[@]} -gt 0 ]] || return 1 + echoNote "detected platform: ${current}${OF_ARCH:+ / ${OF_ARCH}}" + menuPick "Libraries for which platform?" "${opts[@]}" || return 1 + LIB_PLATFORM="$UI_MENU_RESULT" + export LIB_PLATFORM +} + menuPickLibTag(){ local source="${1:-$LIB_SOURCE}" local -a opts=() @@ -1411,6 +1455,9 @@ menuDownloadLibs(){ menuPickLibSource || return 2 echoSuccess "source → $LIB_SOURCE" + menuPickLibPlatform "$LIB_SOURCE" "$platformDir" || return 2 + platformDir="$LIB_PLATFORM" + echoSuccess "platform → $platformDir" menuPickLibTag "$LIB_SOURCE" || return 2 echoSuccess "tag → $LIB_TAG" From 615dece5f2eb7eefb6e74daec8923bd6e014c402 Mon Sep 17 00:00:00 2001 From: Dan Rosser Date: Fri, 14 Aug 2026 03:03:03 +1000 Subject: [PATCH 2/2] of Menu / tests libs (cherry picked from commit bffe51c24151e1e2fa779e1a9d4548429e138b96) --- scripts/of.sh | 59 ++++++++++++ scripts/of_build.sh | 125 ++++++++++++++++++++++++++ tests/libs/freetypeTest/addons.make | 1 + tests/libs/freetypeTest/src/main.cpp | 28 ++++++ tests/libs/glmTest/addons.make | 1 + tests/libs/glmTest/src/main.cpp | 34 +++++++ tests/libs/jsonTest/addons.make | 1 + tests/libs/jsonTest/src/main.cpp | 31 +++++++ tests/libs/opensslTest/addons.make | 1 + tests/libs/opensslTest/src/main.cpp | 42 +++++++++ tests/libs/pugixmlTest/addons.make | 1 + tests/libs/pugixmlTest/src/main.cpp | 34 +++++++ tests/libs/uriparserTest/addons.make | 1 + tests/libs/uriparserTest/src/main.cpp | 41 +++++++++ tests/libs/zlibTest/addons.make | 1 + tests/libs/zlibTest/src/main.cpp | 37 ++++++++ 16 files changed, 438 insertions(+) create mode 100644 tests/libs/freetypeTest/addons.make create mode 100644 tests/libs/freetypeTest/src/main.cpp create mode 100644 tests/libs/glmTest/addons.make create mode 100644 tests/libs/glmTest/src/main.cpp create mode 100644 tests/libs/jsonTest/addons.make create mode 100644 tests/libs/jsonTest/src/main.cpp create mode 100644 tests/libs/opensslTest/addons.make create mode 100644 tests/libs/opensslTest/src/main.cpp create mode 100644 tests/libs/pugixmlTest/addons.make create mode 100644 tests/libs/pugixmlTest/src/main.cpp create mode 100644 tests/libs/uriparserTest/addons.make create mode 100644 tests/libs/uriparserTest/src/main.cpp create mode 100644 tests/libs/zlibTest/addons.make create mode 100644 tests/libs/zlibTest/src/main.cpp diff --git a/scripts/of.sh b/scripts/of.sh index 6f91294f08b..55af5037781 100755 --- a/scripts/of.sh +++ b/scripts/of.sh @@ -955,6 +955,7 @@ printHelp(){ cleanup projects|caches|libs Free disk (artifacts / downloads / prebuilts) version of | pg Version info upgrade addons | apps Upgrade tree + test [group] Run tests/ smoke tests (build + run), or menu for bash smoke scripts too installed Alias for status apothecary Build libraries via apothecary submodule @@ -1037,6 +1038,56 @@ menuVersion(){ printf '\n' } +# test() — runs either the tests/*/* smoke test projects (build + run, +# reusing cmdTest from of_build.sh) or one of the standalone smoke_test_*.sh +# bash scripts under scripts/dev/ (e.g. smoke_test_nightly.sh). +menuTest(){ + local choice + if ! menuCanRun; then + echoWarning "no TTY — running all tests/ smoke tests non-interactively" + cmdTest + return $? + fi + printBanner "test" + + local -a opts=("All tests/ smoke tests (build + run)|tests-all") + local g gName + if [[ -d "${OF_DIR}/tests" ]]; then + for g in "${OF_DIR}/tests"/*/; do + [[ -d "$g" ]] || continue + gName=$(basename "${g%/}") + opts+=("tests/${gName} only|tests-${gName}") + done + fi + local -a smokeScripts=() + local s + for s in "${OF_CORE_SCRIPT_DIR}/dev"/smoke_test_*.sh; do + [[ -f "$s" ]] && smokeScripts+=("$(basename "$s")") + done + for s in "${smokeScripts[@]}"; do + opts+=("Smoke script — ${s}|script:${s}") + done + opts+=("Back|back") + + menuPick "Run which tests?" "${opts[@]}" || return 2 + choice="$UI_MENU_RESULT" + case "$choice" in + tests-all) cmdTest ;; + tests-*) cmdTest "${choice#tests-}" ;; + script:*) + local scriptName="${choice#script:}" + local scriptPath="${OF_CORE_SCRIPT_DIR}/dev/${scriptName}" + local -a args=() + if menuCanRun && confirmYes "Include the real network/build checks (--real)?"; then + args+=(--real) + fi + ensureScript "$scriptPath" 2>/dev/null + bash "$scriptPath" "${args[@]}" + ;; + back) return 2 ;; + esac +} + OF_LIB_STATE_FILE="${OF_DIR}/libs/.of-cli-state" # Essentials used to decide "installed" @@ -2373,6 +2424,7 @@ cmdMenu(){ "draw() — build (menuBuild)|build" \ "cleanup() — free space (menuCleanup)|cleanup" \ "version() — info (menuVersion)|version" \ + "test() — smoke tests (menuTest)|test" \ "exit()|exit" then echoInfo "bye" @@ -2387,6 +2439,7 @@ cmdMenu(){ build) menuBuild ;; cleanup|clean) menuCleanup ;; version) menuVersion; menuPause ;; + test) menuTest; [[ $? -eq 2 ]] || menuPause ;; exit|quit) echoSuccess "bye"; return 0 ;; *) echoError "unknown: $choice"; menuPause ;; esac @@ -2528,6 +2581,12 @@ runCommand(){ esac ;; upgrade) cmdUpgrade "$subcmd" ;; + test) + case "${subcmd:-}" in + ""|menu) menuTest ;; + *) cmdTest "$subcmd" ;; + esac + ;; cleanup|clean) case "${subcmd:-}" in ""|menu) menuCleanup ;; diff --git a/scripts/of_build.sh b/scripts/of_build.sh index a0324c8114e..f698ef83880 100644 --- a/scripts/of_build.sh +++ b/scripts/of_build.sh @@ -871,6 +871,131 @@ runNativeApp(){ return 1 } +# Finds a project's Debug binary and runs it synchronously, returning its +# exit code. Unlike runNativeApp (which `open`s GUI apps asynchronously and +# can't report pass/fail), this is for headless test binaries built with +# ofAppNoWindow — used by `of test`. +findTestBinary(){ + local project="$1" name + name=$(basename "$project") + local -a candidates=( + "${project}/bin/${name}_debug.app/Contents/MacOS/${name}_debug" + "${project}/bin/${name}_debug" + "${project}/bin/${name}_debug.exe" + ) + local c + for c in "${candidates[@]}"; do + [[ -x "$c" ]] && { printf '%s' "$c"; return 0; } + done + return 1 +} + +# Builds (Debug) and runs one tests// project, streaming its +# ofxUnitTests output. Returns the test binary's exit code. +runTestProject(){ + local project="$1" + local buildLog + buildLog=$(mktemp) + + ensureProjectMakefile "$project" || { + echoError "no Makefile and could not install template Makefile" + rm -f "$buildLog" + return 1 + } + if ! ( cd "$project" && make -j"$(ofBuildJobs)" Debug ) >"$buildLog" 2>&1; then + echoError "build failed" + tail -25 "$buildLog" | sed 's/^/ /' + rm -f "$buildLog" + return 1 + fi + rm -f "$buildLog" + + local bin + bin=$(findTestBinary "$project") || { + echoError "built but no debug binary found under bin/" + return 1 + } + "$bin" +} + +# Discovers and runs every tests// project (or just tests/ +# if $1 is given), mirroring what scripts/ci/*/run_tests.sh do in CI but +# reusable from the CLI/menu. Prints a tick per test, full output only on +# failure, and a pass/fail summary at the end. +cmdTest(){ + local filterGroup="${1:-}" + local testsDir="${OF_DIR}/tests" + [[ -d "$testsDir" ]] || { echoError "no tests/ directory found"; return 1; } + + printBanner "test" + echoInfo "running smoke tests under tests/${filterGroup:+$filterGroup/}" + printf '\n' + + local -a groups=() + local g + if [[ -n "$filterGroup" ]]; then + [[ -d "${testsDir}/${filterGroup}" ]] || { echoError "no tests/${filterGroup} folder"; return 1; } + groups=("${testsDir}/${filterGroup}") + else + for g in "${testsDir}"/*/; do + [[ -d "$g" ]] && groups+=("${g%/}") + done + fi + + local total=0 passed=0 failed=0 + local -a failedNames=() + local group groupName test name t0 t1 runLog + + for group in "${groups[@]}"; do + groupName=$(basename "$group") + printf ' %s%s%s\n' "$C_BOLD" "$groupName" "$C_RESET" + for test in "$group"/*/; do + [[ -d "$test" && -d "${test}src" ]] || continue + test="${test%/}" + name=$(basename "$test") + total=$((total + 1)) + # \r-overwrite the pending marker only when actually attached to a + # terminal -- otherwise (piped/logged output) it just garbles two + # lines together, so print plain sequential lines instead + if isInteractive; then + printf ' %s·%s %s/%s' "$C_MUTED" "$C_RESET" "$groupName" "$name" + else + printf ' · %s/%s ... ' "$groupName" "$name" + fi + runLog=$(mktemp) + t0=$(date +%s) + if runTestProject "$test" >"$runLog" 2>&1; then + t1=$(date +%s) + if isInteractive; then + printf '\r %s✓%s %s/%s %s(%ss)%s\n' "$C_OK" "$C_RESET" "$groupName" "$name" "$C_MUTED" "$((t1 - t0))" "$C_RESET" + else + printf 'ok (%ss)\n' "$((t1 - t0))" + fi + passed=$((passed + 1)) + else + t1=$(date +%s) + if isInteractive; then + printf '\r %s✗%s %s/%s %s(%ss)%s\n' "$C_ERR" "$C_RESET" "$groupName" "$name" "$C_MUTED" "$((t1 - t0))" "$C_RESET" + else + printf 'FAILED (%ss)\n' "$((t1 - t0))" + fi + failed=$((failed + 1)) + failedNames+=("${groupName}/${name}") + sed 's/^/ /' "$runLog" + fi + rm -f "$runLog" + done + done + + printf '\n' + if [[ "$failed" -eq 0 ]]; then + echoSuccess "${passed}/${total} tests passed" + return 0 + fi + echoError "${failed}/${total} tests failed: ${failedNames[*]}" + return 1 +} + # --------------------------------------------------------------------------- # High-level command: build one project with a system # --------------------------------------------------------------------------- diff --git a/tests/libs/freetypeTest/addons.make b/tests/libs/freetypeTest/addons.make new file mode 100644 index 00000000000..0e0303d2e09 --- /dev/null +++ b/tests/libs/freetypeTest/addons.make @@ -0,0 +1 @@ +ofxUnitTests diff --git a/tests/libs/freetypeTest/src/main.cpp b/tests/libs/freetypeTest/src/main.cpp new file mode 100644 index 00000000000..48ca1de597b --- /dev/null +++ b/tests/libs/freetypeTest/src/main.cpp @@ -0,0 +1,28 @@ +#include "ofMain.h" +#include "ofAppNoWindow.h" +#include "ofxUnitTests.h" +#include +#include FT_FREETYPE_H + +class ofApp: public ofxUnitTestsApp{ + void run(){ + FT_Library library; + FT_Error err = FT_Init_FreeType(&library); + ofxTestEq(err, (FT_Error)0, "FT_Init_FreeType() succeeds"); + + FT_Int major = 0, minor = 0, patch = 0; + FT_Library_Version(library, &major, &minor, &patch); + ofxTest(major > 0 || minor > 0, "FT_Library_Version() reports a sane version"); + + FT_Error doneErr = FT_Done_FreeType(library); + ofxTestEq(doneErr, (FT_Error)0, "FT_Done_FreeType() succeeds"); + } +}; + +int main(){ + ofInit(); + auto window = std::make_shared(); + auto app = std::make_shared(); + ofRunApp(window, app); + return ofRunMainLoop(); +} diff --git a/tests/libs/glmTest/addons.make b/tests/libs/glmTest/addons.make new file mode 100644 index 00000000000..0e0303d2e09 --- /dev/null +++ b/tests/libs/glmTest/addons.make @@ -0,0 +1 @@ +ofxUnitTests diff --git a/tests/libs/glmTest/src/main.cpp b/tests/libs/glmTest/src/main.cpp new file mode 100644 index 00000000000..b8413dcf015 --- /dev/null +++ b/tests/libs/glmTest/src/main.cpp @@ -0,0 +1,34 @@ +#include "ofMain.h" +#include "ofAppNoWindow.h" +#include "ofxUnitTests.h" +#include +#include + +class ofApp: public ofxUnitTestsApp{ + void run(){ + glm::mat4 identity(1.0f); + glm::vec4 v(1.0f, 2.0f, 3.0f, 1.0f); + glm::vec4 transformed = identity * v; + ofxTestEq(transformed.x, v.x, "identity matrix leaves x unchanged"); + ofxTestEq(transformed.y, v.y, "identity matrix leaves y unchanged"); + ofxTestEq(transformed.z, v.z, "identity matrix leaves z unchanged"); + + glm::mat4 translated = glm::translate(identity, glm::vec3(10.0f, 0.0f, 0.0f)); + glm::vec4 moved = translated * glm::vec4(0.0f, 0.0f, 0.0f, 1.0f); + ofxTestEq(moved.x, 10.0f, "translate() moves x by 10"); + + glm::vec3 a(1.0f, 0.0f, 0.0f); + glm::vec3 b(0.0f, 1.0f, 0.0f); + ofxTestEq(glm::dot(a, b), 0.0f, "perpendicular unit vectors dot to 0"); + glm::vec3 crossed = glm::cross(a, b); + ofxTestEq(crossed.z, 1.0f, "cross(x,y) == z"); + } +}; + +int main(){ + ofInit(); + auto window = std::make_shared(); + auto app = std::make_shared(); + ofRunApp(window, app); + return ofRunMainLoop(); +} diff --git a/tests/libs/jsonTest/addons.make b/tests/libs/jsonTest/addons.make new file mode 100644 index 00000000000..0e0303d2e09 --- /dev/null +++ b/tests/libs/jsonTest/addons.make @@ -0,0 +1 @@ +ofxUnitTests diff --git a/tests/libs/jsonTest/src/main.cpp b/tests/libs/jsonTest/src/main.cpp new file mode 100644 index 00000000000..240d3fccfe0 --- /dev/null +++ b/tests/libs/jsonTest/src/main.cpp @@ -0,0 +1,31 @@ +#include "ofMain.h" +#include "ofAppNoWindow.h" +#include "ofxUnitTests.h" +#include "json.hpp" + +class ofApp: public ofxUnitTestsApp{ + void run(){ + using nlohmann::json; + + auto parsed = json::parse(R"({"name":"openFrameworks","version":12,"addons":["ofxGui","ofxOsc"]})"); + ofxTestEq(parsed["name"].get(), std::string("openFrameworks"), "parses string field"); + ofxTestEq(parsed["version"].get(), 12, "parses int field"); + ofxTestEq(parsed["addons"].size(), (size_t)2, "parses array field"); + ofxTestEq(parsed["addons"][0].get(), std::string("ofxGui"), "array element 0"); + + json built; + built["ok"] = true; + built["count"] = 3; + ofxTestEq(built.dump(), std::string("{\"count\":3,\"ok\":true}"), "serializes back to json"); + + ofxTest(!json::accept(std::string("{not valid json")), "rejects malformed json"); + } +}; + +int main(){ + ofInit(); + auto window = std::make_shared(); + auto app = std::make_shared(); + ofRunApp(window, app); + return ofRunMainLoop(); +} diff --git a/tests/libs/opensslTest/addons.make b/tests/libs/opensslTest/addons.make new file mode 100644 index 00000000000..0e0303d2e09 --- /dev/null +++ b/tests/libs/opensslTest/addons.make @@ -0,0 +1 @@ +ofxUnitTests diff --git a/tests/libs/opensslTest/src/main.cpp b/tests/libs/opensslTest/src/main.cpp new file mode 100644 index 00000000000..e1ffe9dd0dd --- /dev/null +++ b/tests/libs/opensslTest/src/main.cpp @@ -0,0 +1,42 @@ +#include "ofMain.h" +#include "ofAppNoWindow.h" +#include "ofxUnitTests.h" +#include +#include +#include +#include + +class ofApp: public ofxUnitTestsApp{ + void run(){ + ofxTest(OPENSSL_VERSION_NUMBER > 0, "OPENSSL_VERSION_NUMBER is defined"); + + // SHA-256 of the empty string is a well-known constant -- a good + // canary that the linked openssl actually implements the digest + // correctly, not just that the symbols resolve + unsigned char digest[EVP_MAX_MD_SIZE]; + unsigned int digestLen = 0; + EVP_MD_CTX* ctx = EVP_MD_CTX_new(); + ofxTest(ctx != nullptr, "EVP_MD_CTX_new() succeeds"); + + int initOk = EVP_DigestInit_ex(ctx, EVP_sha256(), nullptr); + ofxTestEq(initOk, 1, "EVP_DigestInit_ex(sha256) succeeds"); + + int finalOk = EVP_DigestFinal_ex(ctx, digest, &digestLen); + ofxTestEq(finalOk, 1, "EVP_DigestFinal_ex() succeeds"); + EVP_MD_CTX_free(ctx); + + std::ostringstream hex; + for(unsigned int i = 0; i < digestLen; i++){ + hex << std::hex << std::setw(2) << std::setfill('0') << (int)digest[i]; + } + ofxTestEq(hex.str(), std::string("e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855"), "SHA-256(\"\") matches the known constant"); + } +}; + +int main(){ + ofInit(); + auto window = std::make_shared(); + auto app = std::make_shared(); + ofRunApp(window, app); + return ofRunMainLoop(); +} diff --git a/tests/libs/pugixmlTest/addons.make b/tests/libs/pugixmlTest/addons.make new file mode 100644 index 00000000000..0e0303d2e09 --- /dev/null +++ b/tests/libs/pugixmlTest/addons.make @@ -0,0 +1 @@ +ofxUnitTests diff --git a/tests/libs/pugixmlTest/src/main.cpp b/tests/libs/pugixmlTest/src/main.cpp new file mode 100644 index 00000000000..20716dee475 --- /dev/null +++ b/tests/libs/pugixmlTest/src/main.cpp @@ -0,0 +1,34 @@ +#include "ofMain.h" +#include "ofAppNoWindow.h" +#include "ofxUnitTests.h" +#include + +class ofApp: public ofxUnitTestsApp{ + void run(){ + const char* xml = "ofxGuiofxOsc"; + + pugi::xml_document doc; + pugi::xml_parse_result result = doc.load_string(xml); + ofxTest(result, "parses well-formed xml"); + + auto app = doc.child("settings").child("app"); + ofxTestEq(std::string(app.attribute("version").value()), std::string("12"), "reads an attribute"); + + int addonCount = 0; + for(auto addon : app.children("addon")) addonCount++; + ofxTestEq(addonCount, 2, "iterates repeated child elements"); + ofxTestEq(std::string(app.child("addon").child_value()), std::string("ofxGui"), "reads element text"); + + pugi::xml_document bad; + pugi::xml_parse_result badResult = bad.load_string(""); + ofxTest(!badResult, "rejects malformed xml"); + } +}; + +int main(){ + ofInit(); + auto window = std::make_shared(); + auto app = std::make_shared(); + ofRunApp(window, app); + return ofRunMainLoop(); +} diff --git a/tests/libs/uriparserTest/addons.make b/tests/libs/uriparserTest/addons.make new file mode 100644 index 00000000000..0e0303d2e09 --- /dev/null +++ b/tests/libs/uriparserTest/addons.make @@ -0,0 +1 @@ +ofxUnitTests diff --git a/tests/libs/uriparserTest/src/main.cpp b/tests/libs/uriparserTest/src/main.cpp new file mode 100644 index 00000000000..ce6e2f58ece --- /dev/null +++ b/tests/libs/uriparserTest/src/main.cpp @@ -0,0 +1,41 @@ +#include "ofMain.h" +#include "ofAppNoWindow.h" +#include "ofxUnitTests.h" +#include +#include + +class ofApp: public ofxUnitTestsApp{ + void run(){ + const std::string url = "https://openframeworks.cc/download/?version=0.12.1#top"; + + UriUriA uri; + const char* errorPos; + int rc = uriParseSingleUriA(&uri, url.c_str(), &errorPos); + ofxTestEq(rc, 0, "parses a well-formed url"); + + auto rangeToString = [](const UriTextRangeA& r) -> std::string { + if(!r.first || !r.afterLast) return ""; + return std::string(r.first, r.afterLast - r.first); + }; + + ofxTestEq(rangeToString(uri.scheme), std::string("https"), "extracts scheme"); + ofxTestEq(rangeToString(uri.hostText), std::string("openframeworks.cc"), "extracts host"); + ofxTestEq(rangeToString(uri.fragment), std::string("top"), "extracts fragment"); + + uriFreeUriMembersA(&uri); + + UriUriA badUri; + const char* badErrorPos; + int badRc = uriParseSingleUriA(&badUri, "not a uri : : :", &badErrorPos); + ofxTest(badRc != 0, "rejects malformed uri"); + uriFreeUriMembersA(&badUri); + } +}; + +int main(){ + ofInit(); + auto window = std::make_shared(); + auto app = std::make_shared(); + ofRunApp(window, app); + return ofRunMainLoop(); +} diff --git a/tests/libs/zlibTest/addons.make b/tests/libs/zlibTest/addons.make new file mode 100644 index 00000000000..0e0303d2e09 --- /dev/null +++ b/tests/libs/zlibTest/addons.make @@ -0,0 +1 @@ +ofxUnitTests diff --git a/tests/libs/zlibTest/src/main.cpp b/tests/libs/zlibTest/src/main.cpp new file mode 100644 index 00000000000..3ab034c6798 --- /dev/null +++ b/tests/libs/zlibTest/src/main.cpp @@ -0,0 +1,37 @@ +#include "ofMain.h" +#include "ofAppNoWindow.h" +#include "ofxUnitTests.h" +#include +#include + +class ofApp: public ofxUnitTestsApp{ + void run(){ + // the version string is compiled into the lib we downloaded/built — + // a mismatch here usually means download_libs deployed the wrong + // platform's archive, or a stale one + ofxTest(strlen(zlibVersion()) > 0, "zlibVersion() returns a non-empty string"); + + const std::string original = "openFrameworks zlib smoke test - compress then decompress this exact string and expect it back unchanged."; + + uLongf compressedSize = compressBound((uLong)original.size()); + std::vector compressed(compressedSize); + int cres = compress(compressed.data(), &compressedSize, (const Bytef*)original.data(), (uLong)original.size()); + ofxTestEq(cres, Z_OK, "compress() succeeds"); + + uLongf decompressedSize = (uLongf)original.size(); + std::vector decompressed(decompressedSize); + int dres = uncompress(decompressed.data(), &decompressedSize, compressed.data(), compressedSize); + ofxTestEq(dres, Z_OK, "uncompress() succeeds"); + + std::string roundTripped((char*)decompressed.data(), decompressedSize); + ofxTestEq(roundTripped, original, "round-tripped data matches original"); + } +}; + +int main(){ + ofInit(); + auto window = std::make_shared(); + auto app = std::make_shared(); + ofRunApp(window, app); + return ofRunMainLoop(); +}