From 9c0a76218f4acee181f0ab74c053b6674042d4bb Mon Sep 17 00:00:00 2001 From: Tomasz Blaszczak Date: Wed, 25 Feb 2026 15:55:05 +0100 Subject: [PATCH 1/4] test: Simplify api-test app --- .github/Dockerfile | 1 - .../{run-cpp-test.sh => run-api-test-app.sh} | 11 +- .github/workflows/ci.yml | 15 +- CMakeLists.txt | 1 - test/api_test_app/CMakeLists.txt | 88 +----- test/api_test_app/apis/accessibilityDemo.cpp | 75 +++++ .../{cpp => apis}/accessibilityDemo.h | 7 +- .../{cpp => apis}/advertisingDemo.cpp | 22 +- .../{cpp => apis}/advertisingDemo.h | 7 +- test/api_test_app/apis/deviceDemo.cpp | 86 ++++++ test/api_test_app/{cpp => apis}/deviceDemo.h | 7 +- test/api_test_app/apis/discoveryDemo.cpp | 67 +++++ .../{cpp => apis}/discoveryDemo.h | 7 +- test/api_test_app/apis/displayDemo.cpp | 54 ++++ test/api_test_app/{cpp => apis}/displayDemo.h | 8 +- .../{cpp => apis}/lifecycleDemo.cpp | 56 ++-- .../{cpp => apis}/lifecycleDemo.h | 8 +- .../{cpp => apis}/localizationDemo.cpp | 38 ++- .../{cpp => apis}/localizationDemo.h | 7 +- .../{cpp => apis}/networkDemo.cpp | 23 +- test/api_test_app/{cpp => apis}/networkDemo.h | 7 +- test/api_test_app/apis/presentationDemo.cpp | 54 ++++ .../{cpp => apis}/presentationDemo.h | 7 +- test/api_test_app/{cpp => apis}/statsDemo.cpp | 25 +- test/api_test_app/{cpp => apis}/statsDemo.h | 7 +- test/api_test_app/apis/texttospeechDemo.cpp | 153 ++++++++++ .../{cpp => apis}/texttospeechDemo.h | 13 +- test/api_test_app/build.sh | 12 +- test/api_test_app/cpp/accessibilityDemo.cpp | 81 ------ test/api_test_app/cpp/chooseInterface.cpp | 106 ------- test/api_test_app/cpp/chooseInterface.h | 35 --- test/api_test_app/cpp/deviceDemo.cpp | 82 ------ test/api_test_app/cpp/discoveryDemo.cpp | 69 ----- test/api_test_app/cpp/displayDemo.cpp | 58 ---- .../cpp/firebolt-open-rpc.json.in | 4 - test/api_test_app/cpp/fireboltDemoBase.cpp | 78 ----- test/api_test_app/cpp/fireboltDemoBase.h | 111 ------- test/api_test_app/cpp/presentationDemo.cpp | 57 ---- test/api_test_app/cpp/texttospeechDemo.cpp | 151 ---------- test/api_test_app/main.cpp | 272 ++++++++---------- test/api_test_app/utils.cpp | 107 +++++++ test/api_test_app/utils.h | 91 ++++++ 42 files changed, 953 insertions(+), 1215 deletions(-) rename .github/scripts/{run-cpp-test.sh => run-api-test-app.sh} (89%) create mode 100644 test/api_test_app/apis/accessibilityDemo.cpp rename test/api_test_app/{cpp => apis}/accessibilityDemo.h (85%) rename test/api_test_app/{cpp => apis}/advertisingDemo.cpp (60%) rename test/api_test_app/{cpp => apis}/advertisingDemo.h (85%) create mode 100644 test/api_test_app/apis/deviceDemo.cpp rename test/api_test_app/{cpp => apis}/deviceDemo.h (85%) create mode 100644 test/api_test_app/apis/discoveryDemo.cpp rename test/api_test_app/{cpp => apis}/discoveryDemo.h (85%) create mode 100644 test/api_test_app/apis/displayDemo.cpp rename test/api_test_app/{cpp => apis}/displayDemo.h (85%) rename test/api_test_app/{cpp => apis}/lifecycleDemo.cpp (61%) rename test/api_test_app/{cpp => apis}/lifecycleDemo.h (85%) rename test/api_test_app/{cpp => apis}/localizationDemo.cpp (50%) rename test/api_test_app/{cpp => apis}/localizationDemo.h (85%) rename test/api_test_app/{cpp => apis}/networkDemo.cpp (60%) rename test/api_test_app/{cpp => apis}/networkDemo.h (85%) create mode 100644 test/api_test_app/apis/presentationDemo.cpp rename test/api_test_app/{cpp => apis}/presentationDemo.h (85%) rename test/api_test_app/{cpp => apis}/statsDemo.cpp (52%) rename test/api_test_app/{cpp => apis}/statsDemo.h (85%) create mode 100644 test/api_test_app/apis/texttospeechDemo.cpp rename test/api_test_app/{cpp => apis}/texttospeechDemo.h (74%) delete mode 100644 test/api_test_app/cpp/accessibilityDemo.cpp delete mode 100644 test/api_test_app/cpp/chooseInterface.cpp delete mode 100644 test/api_test_app/cpp/chooseInterface.h delete mode 100644 test/api_test_app/cpp/deviceDemo.cpp delete mode 100644 test/api_test_app/cpp/discoveryDemo.cpp delete mode 100644 test/api_test_app/cpp/displayDemo.cpp delete mode 100644 test/api_test_app/cpp/firebolt-open-rpc.json.in delete mode 100644 test/api_test_app/cpp/fireboltDemoBase.cpp delete mode 100644 test/api_test_app/cpp/fireboltDemoBase.h delete mode 100644 test/api_test_app/cpp/presentationDemo.cpp delete mode 100644 test/api_test_app/cpp/texttospeechDemo.cpp create mode 100644 test/api_test_app/utils.cpp create mode 100644 test/api_test_app/utils.h diff --git a/.github/Dockerfile b/.github/Dockerfile index 4f32f1c..fdfb877 100644 --- a/.github/Dockerfile +++ b/.github/Dockerfile @@ -1,4 +1,3 @@ - FROM ubuntu:24.04 ENV DEBIAN_FRONTEND=noninteractive diff --git a/.github/scripts/run-cpp-test.sh b/.github/scripts/run-api-test-app.sh similarity index 89% rename from .github/scripts/run-cpp-test.sh rename to .github/scripts/run-api-test-app.sh index 594491a..39787d1 100755 --- a/.github/scripts/run-cpp-test.sh +++ b/.github/scripts/run-api-test-app.sh @@ -1,7 +1,7 @@ #!/usr/bin/env bash # vim: ts=4 -# Copyright 2025 Comcast Cable Communications Management, LLC +# Copyright 2026 Comcast Cable Communications Management, LLC # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. @@ -57,7 +57,7 @@ done [[ -e "$specOpenRpc" ]] || die "OpenRPC spec '$specOpenRpc' not found" [[ -e "$specAppOpenRpc" ]] || die "OpenRPC App spec '$specAppOpenRpc' not found" [[ -e "$mockConfig" ]] || die "Config '$mockConfig' not found" -[[ -e "$testExe" ]] || die "Executable for cpp_test '$testExe' not found" +[[ -e "$testExe" ]] || die "Executable '$testExe' not found" cfgFile=$mockPath/server/src/.mf.config.json @@ -93,13 +93,10 @@ while ! nc -z localhost $mockPort >/dev/null 2>&1; do sleep 1 done -echo "Starting cpp_test with -mock and -auto flags" +echo "Starting '$(basename "$testExe") --mock --auto'" cd "$(dirname "$testExe")" - -# Capture exit code without triggering set -e set +e -"./$(basename "$testExe")" -mock -auto +"./$(basename "$testExe")" --mock --auto exitCode=$? -set -e exit $exitCode diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index bf73d6f..01baa9a 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -269,7 +269,7 @@ jobs: --app-openrpc /workspace/docs/openrpc/the-spec/firebolt-app-open-rpc.json \ --test-exe /workspace/build/test/ctApp - cpp_demo_tests: + api_test_app: permissions: contents: read packages: read @@ -292,7 +292,7 @@ jobs: name: build-dir path: ${{ github.workspace }}/build - - name: Build api_test_app standalone + - name: Build api-test-app standalone run: | docker run --rm --user "$(id -u):$(id -g)" -v ${{ github.workspace }}:/workspace ${{ needs.build_docker.outputs.image_tag }} \ bash -c " \ @@ -314,16 +314,13 @@ jobs: path: ${{ env.MOCK_PATH }} key: ${{ runner.os }}-mock-${{ steps.setup-mock.outputs.deps_cache_key }} - - name: Run Demo with mock server + - name: Run api-test-app with mock server run: | - chmod +x ${{ github.workspace }}/test/api_test_app/build/api_test_app + chmod +x ${{ github.workspace }}/test/api_test_app/build/api-test-app docker run --rm --user "$(id -u):$(id -g)" -v ${{ github.workspace }}:/workspace -v ${{ env.MOCK_PATH }}:/mock ${{ needs.build_docker.outputs.image_tag }} \ - ./.github/scripts/run-cpp-test.sh \ + ./.github/scripts/run-api-test-app.sh \ --mock /mock \ --config /workspace/.github/mock-firebolt/config.json \ --openrpc /workspace/docs/openrpc/the-spec/firebolt-open-rpc.json \ --app-openrpc /workspace/docs/openrpc/the-spec/firebolt-app-open-rpc.json \ - --test-exe /workspace/test/api_test_app/build/api_test_app - - # Removed artifact upload step for api_test_app binary as per PR feedback - + --test-exe /workspace/test/api_test_app/build/api-test-app diff --git a/CMakeLists.txt b/CMakeLists.txt index 6e78881..4a427ab 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -101,4 +101,3 @@ endif() if (ENABLE_TESTS) add_subdirectory(test) endif() - diff --git a/test/api_test_app/CMakeLists.txt b/test/api_test_app/CMakeLists.txt index 27eb4b6..a395a34 100644 --- a/test/api_test_app/CMakeLists.txt +++ b/test/api_test_app/CMakeLists.txt @@ -16,7 +16,7 @@ if (NOT CMAKE_PROJECT_NAME) cmake_minimum_required(VERSION 3.10) - project(api_test_app CXX) + project(api-test-app CXX) # Read SYSROOT_PATH from environment if not set as CMake variable if (NOT SYSROOT_PATH AND DEFINED ENV{SYSROOT_PATH}) @@ -30,7 +30,7 @@ if (NOT CMAKE_PROJECT_NAME) # Add paths for finding installed packages if (SYSROOT_PATH) - list(APPEND CMAKE_PREFIX_PATH + list(APPEND CMAKE_PREFIX_PATH "${SYSROOT_PATH}/usr/lib/cmake" "${SYSROOT_PATH}/usr/share/cmake" ) @@ -40,117 +40,53 @@ if (NOT CMAKE_PROJECT_NAME) "${SYSROOT_PATH}/tools/cmake" ) endif() - - # Add standard system paths for finding packages - list(APPEND CMAKE_PREFIX_PATH - "/usr/local" - "/usr" - ) + endif () -set(API_TEST_APP api_test_app) +set(API_TEST_APP api-test-app) message("Setup ${API_TEST_APP}") add_compile_options(-Wall -Wextra -Wpedantic) -# Generate header file with embedded JSON content -file(READ "../../docs/openrpc/the-spec/firebolt-open-rpc.json" JSON_CONTENT) -configure_file( - cpp/firebolt-open-rpc.json.in - "${CMAKE_BINARY_DIR}/generated/firebolt-open-rpc_json.h" - @ONLY -) - -file(GLOB SOURCES CONFIGURE_DEPENDS cpp/*.cpp) +file(GLOB SOURCES CONFIGURE_DEPENDS apis/*.cpp) add_executable(${API_TEST_APP} main.cpp + utils.cpp ${SOURCES} ) if (ENABLE_DEMO_APP) - # Building as part of the main project - dependencies already available - if(TARGET nlohmann_json_schema_validator::validator) - set(NLOHMANN_VALIDATOR_TARGET nlohmann_json_schema_validator::validator) - else() - set(NLOHMANN_VALIDATOR_TARGET nlohmann_json_schema_validator) - endif() - if(TARGET CURL::libcurl) - set(CURL_TARGET CURL::libcurl) - else() - set(CURL_TARGET curl) - endif() - if(TARGET Threads::Threads) - set(THREADS_TARGET Threads::Threads) - else() - set(THREADS_TARGET pthread) - endif() target_link_libraries(${API_TEST_APP} PRIVATE FireboltClient nlohmann_json::nlohmann_json - ${NLOHMANN_VALIDATOR_TARGET} - ${CURL_TARGET} - ${THREADS_TARGET} ) - set(SOURCE_ROOT ${CMAKE_SOURCE_DIR}) - target_link_directories(${API_TEST_APP} PRIVATE $ENV{SYSROOT_PATH}/usr/lib) else() - # Building standalone - find all installed dependencies find_package(FireboltTransport CONFIG REQUIRED) find_package(FireboltClient CONFIG REQUIRED) - find_package(nlohmann_json REQUIRED) - find_package(nlohmann_json_schema_validator CONFIG REQUIRED) - find_package(CURL REQUIRED) - find_package(Threads REQUIRED) - if(TARGET nlohmann_json_schema_validator::validator) - set(NLOHMANN_VALIDATOR_TARGET nlohmann_json_schema_validator::validator) - else() - set(NLOHMANN_VALIDATOR_TARGET nlohmann_json_schema_validator) - endif() - if(TARGET CURL::libcurl) - set(CURL_TARGET CURL::libcurl) - else() - set(CURL_TARGET curl) - endif() - if(TARGET Threads::Threads) - set(THREADS_TARGET Threads::Threads) - else() - set(THREADS_TARGET pthread) - endif() target_link_libraries(${API_TEST_APP} PRIVATE FireboltTransport::FireboltTransport FireboltClient::FireboltClient - nlohmann_json::nlohmann_json - ${NLOHMANN_VALIDATOR_TARGET} - ${CURL_TARGET} - ${THREADS_TARGET} ) - set(SOURCE_ROOT ${CMAKE_SOURCE_DIR}/../..) -endif () +endif() target_include_directories(${API_TEST_APP} PRIVATE - - $ - $ - $ - $ - $ + $ + $ + $ + $ ) -add_compile_definitions(UT_OPEN_RPC_FILE="firebolt-open-rpc.json") - set_target_properties(${API_TEST_APP} PROPERTIES CXX_STANDARD 17 CXX_STANDARD_REQUIRED YES - BUILD_RPATH "${CMAKE_BINARY_DIR}/src" - INSTALL_RPATH "$ORIGIN/../src" ) install( TARGETS ${API_TEST_APP} DESTINATION bin -) \ No newline at end of file +) diff --git a/test/api_test_app/apis/accessibilityDemo.cpp b/test/api_test_app/apis/accessibilityDemo.cpp new file mode 100644 index 0000000..93a0e9b --- /dev/null +++ b/test/api_test_app/apis/accessibilityDemo.cpp @@ -0,0 +1,75 @@ +/** + * Copyright 2026 Comcast Cable Communications Management, LLC + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#include "accessibilityDemo.h" +#include +#include +#include +#include +#include + +using namespace Firebolt; +using namespace Firebolt::Accessibility; + +AccessibilityDemo::AccessibilityDemo() + : DemoBase("Accessibility") +{ + methods_.push_back("Accessibility.audioDescription"); + methods_.push_back("Accessibility.closedCaptionsSettings"); + methods_.push_back("Accessibility.highContrastUI"); + methods_.push_back("Accessibility.voiceGuidanceSettings"); +} + +void AccessibilityDemo::runOption(const std::string& method) +{ + std::cout << "Running Accessibility method: " << method << std::endl; + + if (method == "Accessibility.closedCaptionsSettings") + { + auto r = Firebolt::IFireboltAccessor::Instance().AccessibilityInterface().closedCaptionsSettings(); + if (succeed(r)) + { + std::cout << "Closed Captions Settings - Enabled: " << std::boolalpha << r->enabled << std::endl; + } + } + else if (method == "Accessibility.audioDescription") + { + auto r = Firebolt::IFireboltAccessor::Instance().AccessibilityInterface().audioDescription(); + if (succeed(r)) + { + std::cout << "Audio Description Enabled: " << std::boolalpha << *r << std::endl; + } + } + else if (method == "Accessibility.highContrastUI") + { + auto r = Firebolt::IFireboltAccessor::Instance().AccessibilityInterface().highContrastUI(); + if (succeed(r)) + { + std::cout << "High Contrast UI Enabled: " << std::boolalpha << *r << std::endl; + } + } + else if (method == "Accessibility.voiceGuidanceSettings") + { + auto r = Firebolt::IFireboltAccessor::Instance().AccessibilityInterface().voiceGuidanceSettings(); + if (succeed(r)) + { + std::cout << "Voice Guidance Settings - Enabled: " << std::boolalpha << r->enabled << ", Rate: " << r->rate + << std::endl; + } + } +} diff --git a/test/api_test_app/cpp/accessibilityDemo.h b/test/api_test_app/apis/accessibilityDemo.h similarity index 85% rename from test/api_test_app/cpp/accessibilityDemo.h rename to test/api_test_app/apis/accessibilityDemo.h index 250a49f..5df4ecf 100644 --- a/test/api_test_app/cpp/accessibilityDemo.h +++ b/test/api_test_app/apis/accessibilityDemo.h @@ -18,14 +18,13 @@ #pragma once -#include "fireboltDemoBase.h" +#include "utils.h" #include -#include -class AccessibilityDemo : public FireboltDemoBase +class AccessibilityDemo : public DemoBase { public: AccessibilityDemo(); ~AccessibilityDemo() = default; - void runOption(const int index); + void runOption(const std::string& method) override; }; diff --git a/test/api_test_app/cpp/advertisingDemo.cpp b/test/api_test_app/apis/advertisingDemo.cpp similarity index 60% rename from test/api_test_app/cpp/advertisingDemo.cpp rename to test/api_test_app/apis/advertisingDemo.cpp index a9026ba..838e3ca 100644 --- a/test/api_test_app/cpp/advertisingDemo.cpp +++ b/test/api_test_app/apis/advertisingDemo.cpp @@ -17,6 +17,7 @@ */ #include "advertisingDemo.h" +#include #include #include #include @@ -25,24 +26,21 @@ using namespace Firebolt; using namespace Firebolt::Advertising; AdvertisingDemo::AdvertisingDemo() - : FireboltDemoBase() + : DemoBase("Advertising") { - methodsFromRpc("Advertising"); + methods_.push_back("Advertising.advertisingId"); } -void AdvertisingDemo::runOption(const int index) +void AdvertisingDemo::runOption(const std::string& method) { - std::string key = itemDescriptions_[index].name; - - if (key == "Advertising.advertisingId") + if (method == "Advertising.advertisingId") { - Result result = Firebolt::IFireboltAccessor::Instance().AdvertisingInterface().advertisingId(); - if (validateResult(result)) + auto r = Firebolt::IFireboltAccessor::Instance().AdvertisingInterface().advertisingId(); + if (succeed(r)) { - Ifa ifa = result.value(); - std::cout << "IFA: " << ifa.ifa << std::endl; - std::cout << "IFA Type: " << ifa.ifa_type << std::endl; - std::cout << "LMT: " << ifa.lmt << std::endl; + std::cout << "IFA: " << r->ifa << std::endl; + std::cout << "IFA Type: " << r->ifa_type << std::endl; + std::cout << "LMT: " << r->lmt << std::endl; } } } diff --git a/test/api_test_app/cpp/advertisingDemo.h b/test/api_test_app/apis/advertisingDemo.h similarity index 85% rename from test/api_test_app/cpp/advertisingDemo.h rename to test/api_test_app/apis/advertisingDemo.h index f4a7940..5d55153 100644 --- a/test/api_test_app/cpp/advertisingDemo.h +++ b/test/api_test_app/apis/advertisingDemo.h @@ -18,14 +18,13 @@ #pragma once -#include "fireboltDemoBase.h" +#include "utils.h" #include -#include -class AdvertisingDemo : public FireboltDemoBase +class AdvertisingDemo : public DemoBase { public: AdvertisingDemo(); ~AdvertisingDemo() = default; - void runOption(const int index); + void runOption(const std::string& method) override; }; diff --git a/test/api_test_app/apis/deviceDemo.cpp b/test/api_test_app/apis/deviceDemo.cpp new file mode 100644 index 0000000..4184ee3 --- /dev/null +++ b/test/api_test_app/apis/deviceDemo.cpp @@ -0,0 +1,86 @@ +/** + * Copyright 2026 Comcast Cable Communications Management, LLC + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#include "deviceDemo.h" +#include +#include +#include +#include +#include + +#include "json_types/jsondata_device_types.h" + +using namespace Firebolt; +using namespace Firebolt::Device; + +DeviceDemo::DeviceDemo() + : DemoBase("Device") +{ + methods_.push_back("Device.chipsetId"); + methods_.push_back("Device.deviceClass"); + methods_.push_back("Device.timeInActiveState"); + methods_.push_back("Device.uid"); + methods_.push_back("Device.uptime"); +} + +void DeviceDemo::runOption(const std::string& method) +{ + std::cout << "Running Device method: " << method << std::endl; + + if (method == "Device.chipsetId") + { + auto r = Firebolt::IFireboltAccessor::Instance().DeviceInterface().chipsetId(); + if (succeed(r)) + { + std::cout << "Device Chipset ID: " << *r << std::endl; + } + } + else if (method == "Device.deviceClass") + { + auto r = Firebolt::IFireboltAccessor::Instance().DeviceInterface().deviceClass(); + if (succeed(r)) + { + std::cout << "Device Class: " << Firebolt::JSON::toString(Firebolt::Device::JsonData::DeviceClassEnum, *r) + << std::endl; + } + } + else if (method == "Device.timeInActiveState") + { + auto r = Firebolt::IFireboltAccessor::Instance().DeviceInterface().timeInActiveState(); + if (succeed(r)) + { + std::cout << "Device Time In Active State (seconds): " << *r << std::endl; + } + } + else if (method == "Device.uid") + { + auto r = Firebolt::IFireboltAccessor::Instance().DeviceInterface().uid(); + if (succeed(r)) + { + std::cout << "Device UID: " << *r << std::endl; + } + } + else if (method == "Device.uptime") + { + auto r = Firebolt::IFireboltAccessor::Instance().DeviceInterface().uptime(); + if (succeed(r)) + { + std::cout << "Device Uptime (seconds): " << *r << std::endl; + } + } +} diff --git a/test/api_test_app/cpp/deviceDemo.h b/test/api_test_app/apis/deviceDemo.h similarity index 85% rename from test/api_test_app/cpp/deviceDemo.h rename to test/api_test_app/apis/deviceDemo.h index 531fce9..c17e12a 100644 --- a/test/api_test_app/cpp/deviceDemo.h +++ b/test/api_test_app/apis/deviceDemo.h @@ -18,14 +18,13 @@ #pragma once -#include "fireboltDemoBase.h" +#include "utils.h" #include -#include -class DeviceDemo : public FireboltDemoBase +class DeviceDemo : public DemoBase { public: DeviceDemo(); ~DeviceDemo() = default; - void runOption(const int index); + void runOption(const std::string& method) override; }; diff --git a/test/api_test_app/apis/discoveryDemo.cpp b/test/api_test_app/apis/discoveryDemo.cpp new file mode 100644 index 0000000..939810c --- /dev/null +++ b/test/api_test_app/apis/discoveryDemo.cpp @@ -0,0 +1,67 @@ +/** + * Copyright 2026 Comcast Cable Communications Management, LLC + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#include "discoveryDemo.h" +#include "utils.h" +#include +#include +#include +#include +#include + +#include "json_types/jsondata_discovery.h" + +using namespace Firebolt; +using namespace Firebolt::Discovery; + +DiscoveryDemo::DiscoveryDemo() + : DemoBase("Discovery") +{ + methods_.push_back("Discovery.watched"); +} + +void DiscoveryDemo::runOption(const std::string& method) +{ + std::cout << "Running Discovery method: " << method << std::endl; + + if (method == "Discovery.watched") + { + std::string entityId = paramFromConsole("entityId", "exampleEntityId"); + std::optional progress = 0.5; + try + { + progress = std::stof( + paramFromConsole("progress (percentage as (0-0.999) for VOD, number of seconds for live)", "0.5")); + } + catch (const std::exception&) + { + } + std::optional completed = paramFromConsole("completed (true/false)", "false") == "true"; + std::string watchedOn = paramFromConsole("watchedOn (ISO 8601 timestamp)", "2024-01-01T00:00:00Z"); + + std::optional agePolicyOpt = chooseEnumFromList(Firebolt::Discovery::JsonData::AgePolicyEnum, + "Choose an age policy for the watch event:"); + + auto r = Firebolt::IFireboltAccessor::Instance().DiscoveryInterface().watched(entityId, progress, completed, + watchedOn, agePolicyOpt); + if (succeed(r)) + { + std::cout << "Discovery.watched result: " << std::boolalpha << *r << std::endl; + } + } +} diff --git a/test/api_test_app/cpp/discoveryDemo.h b/test/api_test_app/apis/discoveryDemo.h similarity index 85% rename from test/api_test_app/cpp/discoveryDemo.h rename to test/api_test_app/apis/discoveryDemo.h index 6b10096..f578b43 100644 --- a/test/api_test_app/cpp/discoveryDemo.h +++ b/test/api_test_app/apis/discoveryDemo.h @@ -18,14 +18,13 @@ #pragma once -#include "fireboltDemoBase.h" +#include "utils.h" #include -#include -class DiscoveryDemo : public FireboltDemoBase +class DiscoveryDemo : public DemoBase { public: DiscoveryDemo(); ~DiscoveryDemo() = default; - void runOption(const int index); + void runOption(const std::string& method) override; }; diff --git a/test/api_test_app/apis/displayDemo.cpp b/test/api_test_app/apis/displayDemo.cpp new file mode 100644 index 0000000..ae9201e --- /dev/null +++ b/test/api_test_app/apis/displayDemo.cpp @@ -0,0 +1,54 @@ +/** + * Copyright 2026 Comcast Cable Communications Management, LLC + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#include "displayDemo.h" +#include +#include +#include +#include + +using namespace Firebolt; +using namespace Firebolt::Display; + +DisplayDemo::DisplayDemo() + : DemoBase("Display") +{ + methods_.push_back("Display.maxResolution"); + methods_.push_back("Display.size"); +} + +void DisplayDemo::runOption(const std::string& method) +{ + std::cout << "Running Display method: " << method << std::endl; + if (method == "Display.maxResolution") + { + auto r = Firebolt::IFireboltAccessor::Instance().DisplayInterface().maxResolution(); + if (succeed(r)) + { + std::cout << "Max Resolution - Width: " << r->width << ", Height: " << r->height << std::endl; + } + } + else if (method == "Display.size") + { + auto r = Firebolt::IFireboltAccessor::Instance().DisplayInterface().size(); + if (succeed(r)) + { + std::cout << "Display Size - Width: " << r->width << ", Height: " << r->height << std::endl; + } + } +} diff --git a/test/api_test_app/cpp/displayDemo.h b/test/api_test_app/apis/displayDemo.h similarity index 85% rename from test/api_test_app/cpp/displayDemo.h rename to test/api_test_app/apis/displayDemo.h index 423b54c..27626bf 100644 --- a/test/api_test_app/cpp/displayDemo.h +++ b/test/api_test_app/apis/displayDemo.h @@ -15,16 +15,16 @@ * * SPDX-License-Identifier: Apache-2.0 */ + #pragma once -#include "fireboltDemoBase.h" +#include "utils.h" #include -#include -class DisplayDemo : public FireboltDemoBase +class DisplayDemo : public DemoBase { public: DisplayDemo(); ~DisplayDemo() = default; - void runOption(const int index); + void runOption(const std::string& method) override; }; diff --git a/test/api_test_app/cpp/lifecycleDemo.cpp b/test/api_test_app/apis/lifecycleDemo.cpp similarity index 61% rename from test/api_test_app/cpp/lifecycleDemo.cpp rename to test/api_test_app/apis/lifecycleDemo.cpp index 7c578d2..d079d7f 100644 --- a/test/api_test_app/cpp/lifecycleDemo.cpp +++ b/test/api_test_app/apis/lifecycleDemo.cpp @@ -18,6 +18,8 @@ #include "lifecycleDemo.h" #include "json_types/jsondata_lifecycle_types.h" +#include "utils.h" +#include #include #include #include @@ -26,32 +28,33 @@ using namespace Firebolt; using namespace Firebolt::Lifecycle; LifecycleDemo::LifecycleDemo() - : FireboltDemoBase() + : DemoBase("Lifecycle") { - methodsFromRpc("Lifecycle2"); + methods_.push_back("Lifecycle2.close"); + methods_.push_back("Lifecycle2.state"); + methods_.push_back("Lifecycle2.onStateChanged"); + methods_.push_back("Lifecycle2.unsubscribe"); + methods_.push_back("Lifecycle2.unsubscribeAll"); } -void LifecycleDemo::runOption(const int index) +void LifecycleDemo::runOption(const std::string& method) { - std::string key = itemDescriptions_[index].name; - - if (key == "Lifecycle2.close") + if (method == "Lifecycle2.close") { CloseType type = chooseEnumFromList(Firebolt::Lifecycle::JsonData::CloseReasonEnum, "Choose Close Type:"); - Result r = Firebolt::IFireboltAccessor::Instance().LifecycleInterface().close(type); - validateResult(r); + auto r = Firebolt::IFireboltAccessor::Instance().LifecycleInterface().close(type); + succeed(r); } - else if (key == "Lifecycle2.state") + else if (method == "Lifecycle2.state") { - Result r = Firebolt::IFireboltAccessor::Instance().LifecycleInterface().state(); - if (validateResult(r)) + auto r = Firebolt::IFireboltAccessor::Instance().LifecycleInterface().state(); + if (succeed(r)) { - currentState_ = r.value(); std::cout << "Current Lifecycle State: " - << stringFromEnum(Firebolt::Lifecycle::JsonData::LifecycleStateEnum, currentState_) << std::endl; + << Firebolt::JSON::toString(Firebolt::Lifecycle::JsonData::LifecycleStateEnum, *r) << std::endl; } } - else if (key == "Lifecycle2.onStateChanged") + else if (method == "Lifecycle2.onStateChanged") { auto callback = [&](const std::vector& changes) { @@ -66,22 +69,27 @@ void LifecycleDemo::runOption(const int index) currentState_ = change.newState; } }; - Result r = + auto r = Firebolt::IFireboltAccessor::Instance().LifecycleInterface().subscribeOnStateChanged(std::move(callback)); - if (validateResult(r)) + if (succeed(r)) { - std::cout << "Subscribed to Lifecycle state changes with Subscription ID: " << r.value() << std::endl; + std::cout << "Subscribed to Lifecycle state changes with Subscription ID: " << *r << std::endl; } } - else if (key == "Lifecycle2.unsubscribe") + else if (method == "Lifecycle2.unsubscribe") { - std::string idStr; - paramFromConsole("Subscription ID to unsubscribe", "0", idStr); - SubscriptionId id = static_cast(std::stoul(idStr)); - Result r = Firebolt::IFireboltAccessor::Instance().LifecycleInterface().unsubscribe(id); - validateResult(r); + SubscriptionId id = 0; + try + { + id = static_cast(std::stoul(paramFromConsole("Subscription ID to unsubscribe", "0"))); + } + catch (const std::exception&) + { + } + auto r = Firebolt::IFireboltAccessor::Instance().LifecycleInterface().unsubscribe(id); + succeed(r); } - else if (key == "Lifecycle2.unsubscribeAll") + else if (method == "Lifecycle2.unsubscribeAll") { Firebolt::IFireboltAccessor::Instance().LifecycleInterface().unsubscribeAll(); std::cout << "Unsubscribed from all Lifecycle subscriptions." << std::endl; diff --git a/test/api_test_app/cpp/lifecycleDemo.h b/test/api_test_app/apis/lifecycleDemo.h similarity index 85% rename from test/api_test_app/cpp/lifecycleDemo.h rename to test/api_test_app/apis/lifecycleDemo.h index 4df3020..9ccf509 100644 --- a/test/api_test_app/cpp/lifecycleDemo.h +++ b/test/api_test_app/apis/lifecycleDemo.h @@ -18,16 +18,16 @@ #pragma once -#include "fireboltDemoBase.h" +#include "utils.h" +#include #include -#include -class LifecycleDemo : public FireboltDemoBase +class LifecycleDemo : public DemoBase { public: LifecycleDemo(); ~LifecycleDemo() = default; - void runOption(const int index); + void runOption(const std::string& method) override; private: Firebolt::Lifecycle::LifecycleState currentState_; diff --git a/test/api_test_app/cpp/localizationDemo.cpp b/test/api_test_app/apis/localizationDemo.cpp similarity index 50% rename from test/api_test_app/cpp/localizationDemo.cpp rename to test/api_test_app/apis/localizationDemo.cpp index 0695117..19bd772 100644 --- a/test/api_test_app/cpp/localizationDemo.cpp +++ b/test/api_test_app/apis/localizationDemo.cpp @@ -17,52 +17,50 @@ */ #include "localizationDemo.h" +#include #include #include #include using namespace Firebolt; -using namespace Firebolt::Localization; LocalizationDemo::LocalizationDemo() - : FireboltDemoBase() + : DemoBase("Localization") { - methodsFromRpc("Localization"); + methods_.push_back("Localization.country"); + methods_.push_back("Localization.preferredAudioLanguages"); + methods_.push_back("Localization.presentationLanguage"); } -void LocalizationDemo::runOption(const int index) +void LocalizationDemo::runOption(const std::string& method) { - std::string key = itemDescriptions_[index].name; - - if (key == "Localization.country") + if (method == "Localization.country") { - Result result = Firebolt::IFireboltAccessor::Instance().LocalizationInterface().country(); - if (validateResult(result)) + auto r = Firebolt::IFireboltAccessor::Instance().LocalizationInterface().country(); + if (succeed(r)) { - std::cout << "Country: " << result.value() << std::endl; + std::cout << "Country: " << *r << std::endl; } } - else if (key == "Localization.preferredAudioLanguages") + else if (method == "Localization.preferredAudioLanguages") { - Result> result = - Firebolt::IFireboltAccessor::Instance().LocalizationInterface().preferredAudioLanguages(); - if (validateResult(result)) + auto r = Firebolt::IFireboltAccessor::Instance().LocalizationInterface().preferredAudioLanguages(); + if (succeed(r)) { std::cout << "Preferred Audio Languages: "; - for (const auto& lang : result.value()) + for (const auto& lang : *r) { std::cout << lang << " "; } std::cout << std::endl; } } - else if (key == "Localization.presentationLanguage") + else if (method == "Localization.presentationLanguage") { - Result result = - Firebolt::IFireboltAccessor::Instance().LocalizationInterface().presentationLanguage(); - if (validateResult(result)) + auto r = Firebolt::IFireboltAccessor::Instance().LocalizationInterface().presentationLanguage(); + if (succeed(r)) { - std::cout << "Presentation Language: " << result.value() << std::endl; + std::cout << "Presentation Language: " << *r << std::endl; } } } diff --git a/test/api_test_app/cpp/localizationDemo.h b/test/api_test_app/apis/localizationDemo.h similarity index 85% rename from test/api_test_app/cpp/localizationDemo.h rename to test/api_test_app/apis/localizationDemo.h index 1e73556..f18fb0a 100644 --- a/test/api_test_app/cpp/localizationDemo.h +++ b/test/api_test_app/apis/localizationDemo.h @@ -18,14 +18,13 @@ #pragma once -#include "fireboltDemoBase.h" +#include "utils.h" #include -#include -class LocalizationDemo : public FireboltDemoBase +class LocalizationDemo : public DemoBase { public: LocalizationDemo(); ~LocalizationDemo() = default; - void runOption(const int index); + void runOption(const std::string& method) override; }; diff --git a/test/api_test_app/cpp/networkDemo.cpp b/test/api_test_app/apis/networkDemo.cpp similarity index 60% rename from test/api_test_app/cpp/networkDemo.cpp rename to test/api_test_app/apis/networkDemo.cpp index e741a65..ec6477f 100644 --- a/test/api_test_app/cpp/networkDemo.cpp +++ b/test/api_test_app/apis/networkDemo.cpp @@ -17,33 +17,30 @@ */ #include "networkDemo.h" +#include +#include #include #include #include -#include "json_types/jsondata_device_types.h" - using namespace Firebolt; -using namespace Firebolt::Device; NetworkDemo::NetworkDemo() - : FireboltDemoBase() + : DemoBase("Network") { - methodsFromRpc("Network"); + methods_.push_back("Network.connected"); } -void NetworkDemo::runOption(const int index) +void NetworkDemo::runOption(const std::string& method) { - std::string key = itemDescriptions_[index].name; - - std::cout << "Running Network method: " << key << std::endl; + std::cout << "Running Network method: " << method << std::endl; - if (key == "Network.connected") + if (method == "Network.connected") { - Result r = Firebolt::IFireboltAccessor::Instance().NetworkInterface().connected(); - if (validateResult(r)) + auto r = Firebolt::IFireboltAccessor::Instance().NetworkInterface().connected(); + if (succeed(r)) { - std::cout << "Network Connected: " << (r.value() ? "true" : "false") << std::endl; + std::cout << "Network Connected: " << std::boolalpha << *r << std::endl; } } } diff --git a/test/api_test_app/cpp/networkDemo.h b/test/api_test_app/apis/networkDemo.h similarity index 85% rename from test/api_test_app/cpp/networkDemo.h rename to test/api_test_app/apis/networkDemo.h index 0c005bb..65f5995 100644 --- a/test/api_test_app/cpp/networkDemo.h +++ b/test/api_test_app/apis/networkDemo.h @@ -18,14 +18,13 @@ #pragma once -#include "fireboltDemoBase.h" +#include "utils.h" #include -#include -class NetworkDemo : public FireboltDemoBase +class NetworkDemo : public DemoBase { public: NetworkDemo(); ~NetworkDemo() = default; - void runOption(const int index); + void runOption(const std::string& method) override; }; diff --git a/test/api_test_app/apis/presentationDemo.cpp b/test/api_test_app/apis/presentationDemo.cpp new file mode 100644 index 0000000..dfcae4a --- /dev/null +++ b/test/api_test_app/apis/presentationDemo.cpp @@ -0,0 +1,54 @@ +/** + * Copyright 2026 Comcast Cable Communications Management, LLC + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#include "presentationDemo.h" +#include +#include +#include +#include +#include + +using namespace Firebolt; + +PresentationDemo::PresentationDemo() + : DemoBase("Presentation") +{ + methods_.push_back("Presentation.focused"); + methods_.push_back("Presentation.onFocusedChanged"); +} + +void PresentationDemo::runOption(const std::string& method) +{ + if (method == "Presentation.focused") + { + auto r = Firebolt::IFireboltAccessor::Instance().PresentationInterface().focused(); + if (succeed(r)) + { + std::cout << "Presentation focused: " << std::boolalpha << *r << std::endl; + } + } + else if (method == "Presentation.onFocusedChanged") + { + auto r = Firebolt::IFireboltAccessor::Instance().PresentationInterface().subscribeOnFocusedChanged( + [&](bool focused) { std::cout << "Presentation focus changed: " << std::boolalpha << focused << std::endl; }); + if (succeed(r)) + { + std::cout << "Subscribed to Presentation.onFocusedChanged with SubscriptionId: " << *r << std::endl; + } + } +} diff --git a/test/api_test_app/cpp/presentationDemo.h b/test/api_test_app/apis/presentationDemo.h similarity index 85% rename from test/api_test_app/cpp/presentationDemo.h rename to test/api_test_app/apis/presentationDemo.h index d51e7c7..fab07f5 100644 --- a/test/api_test_app/cpp/presentationDemo.h +++ b/test/api_test_app/apis/presentationDemo.h @@ -18,14 +18,13 @@ #pragma once -#include "fireboltDemoBase.h" +#include "utils.h" #include -#include -class PresentationDemo : public FireboltDemoBase +class PresentationDemo : public DemoBase { public: PresentationDemo(); ~PresentationDemo() = default; - void runOption(const int index); + void runOption(const std::string& method) override; }; diff --git a/test/api_test_app/cpp/statsDemo.cpp b/test/api_test_app/apis/statsDemo.cpp similarity index 52% rename from test/api_test_app/cpp/statsDemo.cpp rename to test/api_test_app/apis/statsDemo.cpp index b6d9686..cc2524f 100644 --- a/test/api_test_app/cpp/statsDemo.cpp +++ b/test/api_test_app/apis/statsDemo.cpp @@ -17,34 +17,29 @@ */ #include "statsDemo.h" +#include #include #include #include -#include "json_types/jsondata_device_types.h" - using namespace Firebolt; -using namespace Firebolt::Stats; StatsDemo::StatsDemo() - : FireboltDemoBase() + : DemoBase("Stats") { - methodsFromRpc("Stats"); + methods_.push_back("Stats.memoryUsage"); } -void StatsDemo::runOption(const int index) +void StatsDemo::runOption(const std::string& method) { - std::string key = itemDescriptions_[index].name; - - std::cout << "Running Stats method: " << key << std::endl; - if (key == "Stats.memoryUsage") + std::cout << "Running Stats method: " << method << std::endl; + if (method == "Stats.memoryUsage") { - Result r = Firebolt::IFireboltAccessor::Instance().StatsInterface().memoryUsage(); - if (validateResult(r)) + auto r = Firebolt::IFireboltAccessor::Instance().StatsInterface().memoryUsage(); + if (succeed(r)) { - MemoryInfo memInfo = r.value(); - std::cout << "User Memory Used: " << memInfo.userMemoryUsed << " / " << memInfo.userMemoryLimit << std::endl; - std::cout << "GPU Memory Used: " << memInfo.gpuMemoryUsed << " / " << memInfo.gpuMemoryLimit << std::endl; + std::cout << "User Memory Used: " << r->userMemoryUsed << " / " << r->userMemoryLimit << std::endl; + std::cout << "GPU Memory Used: " << r->gpuMemoryUsed << " / " << r->gpuMemoryLimit << std::endl; } } } diff --git a/test/api_test_app/cpp/statsDemo.h b/test/api_test_app/apis/statsDemo.h similarity index 85% rename from test/api_test_app/cpp/statsDemo.h rename to test/api_test_app/apis/statsDemo.h index 6efbc65..827510f 100644 --- a/test/api_test_app/cpp/statsDemo.h +++ b/test/api_test_app/apis/statsDemo.h @@ -18,14 +18,13 @@ #pragma once -#include "fireboltDemoBase.h" +#include "utils.h" #include -#include -class StatsDemo : public FireboltDemoBase +class StatsDemo : public DemoBase { public: StatsDemo(); ~StatsDemo() = default; - void runOption(const int index); + void runOption(const std::string& method) override; }; diff --git a/test/api_test_app/apis/texttospeechDemo.cpp b/test/api_test_app/apis/texttospeechDemo.cpp new file mode 100644 index 0000000..ed336db --- /dev/null +++ b/test/api_test_app/apis/texttospeechDemo.cpp @@ -0,0 +1,153 @@ +/** + * Copyright 2026 Comcast Cable Communications Management, LLC + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#include "texttospeechDemo.h" +#include "utils.h" +#include +#include + +using namespace Firebolt; +using namespace Firebolt::TextToSpeech; + +TextToSpeechDemo::TextToSpeechDemo() + : DemoBase("TextToSpeech") +{ + methods_.push_back("TextToSpeech.cancel"); + methods_.push_back("TextToSpeech.getSpeechState"); + methods_.push_back("TextToSpeech.listVoices"); + methods_.push_back("TextToSpeech.pause"); + methods_.push_back("TextToSpeech.resume"); + methods_.push_back("TextToSpeech.speak"); + methods_.push_back("TextToSpeech.onSpeechPause"); + methods_.push_back("TextToSpeech.onSpeechResume"); + methods_.push_back("TextToSpeech.onSpeechStart"); + methods_.push_back("TextToSpeech.onWillSpeak"); +} + +SpeechId TextToSpeechDemo::chooseSpeechIdFromConsole() +{ + try + { + return std::stoi(paramFromConsole("speech ID", std::to_string(speechId_))); + } + catch (const std::exception&) + { + return 0; + } +} + +void TextToSpeechDemo::runOption(const std::string& method) +{ + std::cout << "Running TextToSpeech method: " << method << std::endl; + + if (method == "TextToSpeech.cancel") + { + SpeechId speechId = chooseSpeechIdFromConsole(); + auto r = IFireboltAccessor::Instance().TextToSpeechInterface().cancel(speechId); + succeed(r); + } + else if (method == "TextToSpeech.getSpeechState") + { + SpeechId speechId = chooseSpeechIdFromConsole(); + auto r = IFireboltAccessor::Instance().TextToSpeechInterface().getSpeechState(speechId); + if (succeed(r)) + { + const SpeechState& state = r->speechState; + std::cout << "Current state for speech ID '" << speechId << "': " << (int)state << std::endl; + } + } + else if (method == "TextToSpeech.listVoices") + { + std::string language = paramFromConsole("language (BCP 47 locale tag)", "en-US"); + + auto r = IFireboltAccessor::Instance().TextToSpeechInterface().listVoices(language); + if (succeed(r)) + { + const auto& voices = r->voices; + std::cout << "Voices available for language '" << language << "':" << std::endl; + for (const auto& voice : voices) + { + std::cout << " Name: " << voice << std::endl; + } + } + } + else if (method == "TextToSpeech.pause") + { + SpeechId speechId = chooseSpeechIdFromConsole(); + auto r = IFireboltAccessor::Instance().TextToSpeechInterface().pause(speechId); + succeed(r); + } + else if (method == "TextToSpeech.resume") + { + SpeechId speechId = chooseSpeechIdFromConsole(); + auto r = IFireboltAccessor::Instance().TextToSpeechInterface().resume(speechId); + succeed(r); + } + else if (method == "TextToSpeech.speak") + { + std::string text = paramFromConsole("text to speak", "Hello, world!"); + + auto r = IFireboltAccessor::Instance().TextToSpeechInterface().speak(text); + if (succeed(r)) + { + std::cout << "SpeechResponse: SpeechId: '" << r->speechId << "', TTSStatus: '" << r->ttsStatus << "' " + << std::endl; + speechId_ = r->speechId; + } + } + else if (method == "TextToSpeech.onSpeechPause") + { + auto callback = [&](const SpeechIdEvent& event) + { std::cout << "Speech Pause notification received for Speech ID: " << event.speechId << std::endl; }; + auto r = IFireboltAccessor::Instance().TextToSpeechInterface().subscribeOnSpeechPause(std::move(callback)); + if (succeed(r)) + { + std::cout << "Subscribed to onSpeechPause with Subscription ID: " << *r << std::endl; + } + } + else if (method == "TextToSpeech.onSpeechResume") + { + auto callback = [&](const SpeechIdEvent& event) + { std::cout << "Speech Resume notification received for Speech ID: " << event.speechId << std::endl; }; + auto r = IFireboltAccessor::Instance().TextToSpeechInterface().subscribeOnSpeechResume(std::move(callback)); + if (succeed(r)) + { + std::cout << "Subscribed to onSpeechResume with Subscription ID: " << *r << std::endl; + } + } + else if (method == "TextToSpeech.onSpeechStart") + { + auto callback = [&](const SpeechIdEvent& event) + { std::cout << "Speech Start notification received for Speech ID: " << event.speechId << std::endl; }; + auto r = IFireboltAccessor::Instance().TextToSpeechInterface().subscribeOnSpeechStart(std::move(callback)); + if (succeed(r)) + { + std::cout << "Subscribed to onSpeechStart with Subscription ID: " << *r << std::endl; + } + } + else if (method == "TextToSpeech.onWillSpeak") + { + auto callback = [&](const TextToSpeech::SpeechIdEvent& event) + { std::cout << "Will Speak notification received for Speech ID: " << event.speechId << std::endl; }; + auto r = IFireboltAccessor::Instance().TextToSpeechInterface().subscribeOnWillSpeak(std::move(callback)); + if (succeed(r)) + { + std::cout << "Subscribed to onWillSpeak with Subscription ID: " << *r << std::endl; + } + } +} diff --git a/test/api_test_app/cpp/texttospeechDemo.h b/test/api_test_app/apis/texttospeechDemo.h similarity index 74% rename from test/api_test_app/cpp/texttospeechDemo.h rename to test/api_test_app/apis/texttospeechDemo.h index 132f03e..a19b008 100644 --- a/test/api_test_app/cpp/texttospeechDemo.h +++ b/test/api_test_app/apis/texttospeechDemo.h @@ -18,19 +18,18 @@ #pragma once -#include "fireboltDemoBase.h" +#include "utils.h" +#include #include -#include -using namespace Firebolt::TextToSpeech; -class TextToSpeechDemo : public FireboltDemoBase +class TextToSpeechDemo : public DemoBase { public: TextToSpeechDemo(); ~TextToSpeechDemo() = default; - void runOption(const int index); + void runOption(const std::string& method) override; private: - SpeechId chooseSpeechIdFromConsole(); - SpeechId speechId_ = 0; + Firebolt::TextToSpeech::SpeechId chooseSpeechIdFromConsole(); + Firebolt::TextToSpeech::SpeechId speechId_ = 0; }; diff --git a/test/api_test_app/build.sh b/test/api_test_app/build.sh index 42225fd..c2eb763 100755 --- a/test/api_test_app/build.sh +++ b/test/api_test_app/build.sh @@ -22,12 +22,12 @@ bdir="build" run=true buildType="Debug" -while [ ! -z "$1" ]; do +while [[ -n $1 ]]; do case $1 in --clean) rm -rf $bdir;; --just-run) export LD_LIBRARY_PATH="$bdir/src:$SYSROOT_PATH/usr/lib:$LD_LIBRARY_PATH" - $bdir/api_test_app -mock + $bdir/api-test-app --mock exit;; --no-run) run=false;; --release) buildType="Release";; @@ -37,8 +37,8 @@ while [ ! -z "$1" ]; do esac; shift done -[ ! -z "$SYSROOT_PATH" ] || { echo "SYSROOT_PATH not set" >/dev/stderr; exit 1; } -[ -e "$SYSROOT_PATH" ] || { echo "SYSROOT_PATH not exist ($SYSROOT_PATH)" >/dev/stderr; exit 1; } +[[ -n "$SYSROOT_PATH" ]] || { echo "SYSROOT_PATH not set" >/dev/stderr; exit 1; } +[[ -e "$SYSROOT_PATH" ]] || { echo "SYSROOT_PATH not exist ($SYSROOT_PATH)" >/dev/stderr; exit 1; } if [[ ! -e "$bdir" ]]; then cmake -B $bdir \ @@ -59,7 +59,7 @@ fi cmake --build $bdir if $run; then - export LD_LIBRARY_PATH=$bdir/src:$SYSROOT_PATH/usr/lib:$LD_LIBRARY_PATH - $bdir/api_test_app -mock + export LD_LIBRARY_PATH="$bdir/src:$SYSROOT_PATH/usr/lib:$LD_LIBRARY_PATH" + $bdir/api-test-app --mock fi diff --git a/test/api_test_app/cpp/accessibilityDemo.cpp b/test/api_test_app/cpp/accessibilityDemo.cpp deleted file mode 100644 index c35cf6a..0000000 --- a/test/api_test_app/cpp/accessibilityDemo.cpp +++ /dev/null @@ -1,81 +0,0 @@ -/** - * Copyright 2026 Comcast Cable Communications Management, LLC - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - * SPDX-License-Identifier: Apache-2.0 - */ - -#include "accessibilityDemo.h" -#include -#include -#include - -#include "json_types/jsondata_device_types.h" - -using namespace Firebolt; -using namespace Firebolt::Accessibility; - -AccessibilityDemo::AccessibilityDemo() - : FireboltDemoBase() -{ - methodsFromRpc("Accessibility"); -} - -void AccessibilityDemo::runOption(const int index) -{ - std::string key = itemDescriptions_[index].name; - - std::cout << "Running Accessibility method: " << key << std::endl; - - if (key == "Accessibility.closedCaptionsSettings") - { - Result r = - Firebolt::IFireboltAccessor::Instance().AccessibilityInterface().closedCaptionsSettings(); - if (validateResult(r)) - { - ClosedCaptionsSettings settings = r.value(); - std::cout << "Closed Captions Settings - Enabled: " << (settings.enabled ? "true" : "false") << std::endl; - } - } - else if (key == "Accessibility.audioDescription") - { - Result r = Firebolt::IFireboltAccessor::Instance().AccessibilityInterface().audioDescription(); - if (validateResult(r)) - { - bool enabled = r.value(); - std::cout << "Audio Description Enabled: " << (enabled ? "true" : "false") << std::endl; - } - } - else if (key == "Accessibility.highContrastUI") - { - Result r = Firebolt::IFireboltAccessor::Instance().AccessibilityInterface().highContrastUI(); - if (validateResult(r)) - { - bool enabled = r.value(); - - std::cout << "High Contrast UI Enabled: " << (enabled ? "true" : "false") << std::endl; - } - } - else if (key == "Accessibility.voiceGuidanceSettings") - { - Result r = - Firebolt::IFireboltAccessor::Instance().AccessibilityInterface().voiceGuidanceSettings(); - if (validateResult(r)) - { - VoiceGuidanceSettings settings = r.value(); - std::cout << "Voice Guidance Settings - Enabled: " << (settings.enabled ? "true" : "false") - << ", Rate: " << settings.rate << std::endl; - } - } -} \ No newline at end of file diff --git a/test/api_test_app/cpp/chooseInterface.cpp b/test/api_test_app/cpp/chooseInterface.cpp deleted file mode 100644 index 8642f5b..0000000 --- a/test/api_test_app/cpp/chooseInterface.cpp +++ /dev/null @@ -1,106 +0,0 @@ -/** - * Copyright 2026 Comcast Cable Communications Management, LLC - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - * SPDX-License-Identifier: Apache-2.0 - */ - -#include "chooseInterface.h" -#include "fireboltDemoBase.h" - -#include "accessibilityDemo.h" -#include "advertisingDemo.h" -#include "deviceDemo.h" -#include "discoveryDemo.h" -#include "displayDemo.h" -#include "lifecycleDemo.h" -#include "localizationDemo.h" -#include "networkDemo.h" -#include "presentationDemo.h" -#include "statsDemo.h" -#include "texttospeechDemo.h" - -#include -#include - -ChooseInterface::ChooseInterface() - : FireboltDemoBase() -{ - for (auto& [key, value] : json_["info"]["x-module-descriptions"].items()) - { - std::cout << key << ": " << value << std::endl; - if (key != "Internal") - { - itemDescriptions_.push_back({key, value.get()}); - std::cout << "Added interface: " << key << std::endl; - } - } - - interfaces.clear(); - interfaces.emplace_back(std::make_unique()); - interfaces.emplace_back(std::make_unique()); - interfaces.emplace_back(std::make_unique()); - interfaces.emplace_back(std::make_unique()); - interfaces.emplace_back(std::make_unique()); - interfaces.emplace_back(std::make_unique()); - interfaces.emplace_back(std::make_unique()); - interfaces.emplace_back(std::make_unique()); - interfaces.emplace_back(std::make_unique()); - interfaces.emplace_back(std::make_unique()); - interfaces.emplace_back(std::make_unique()); - - std::cout << interfaces.size() << " interfaces, " << itemDescriptions_.size() << " descriptions" << std::endl; - assert(interfaces.size() == itemDescriptions_.size()); -} - -ChooseInterface::~ChooseInterface() = default; - -void ChooseInterface::runOption(const int index) -{ - FireboltDemoBase* selectedInterface = interfaces[index].get(); - std::cout << "Running interface: " << itemDescriptions_[index].name << std::endl; - - for (;;) - { - int methodIndex = selectedInterface->chooseOption(); - - if (methodIndex == -1) - { - break; // Go back to interface selection - } - - selectedInterface->runOption(methodIndex); - } -} - -void ChooseInterface::autoRun() -{ - for (int i = 0; i < (int)interfaces.size(); ++i) - { - FireboltDemoBase* selectedInterface = interfaces[i].get(); - if (selectedInterface == nullptr) - { - std::cerr << "Interface not implemented for: " << itemDescriptions_[i].name << std::endl; - std::abort(); - } - std::cout << "Auto-running interface: " << itemDescriptions_[i].name << std::endl; - - // Assuming each interface has a predefined set of methods to run - for (int j = 0; j < selectedInterface->listSize(); ++j) - { - std::cout << "Auto-running method: " << selectedInterface->method(j) << std::endl; - selectedInterface->runOption(j); - } - } -} diff --git a/test/api_test_app/cpp/chooseInterface.h b/test/api_test_app/cpp/chooseInterface.h deleted file mode 100644 index 0711e64..0000000 --- a/test/api_test_app/cpp/chooseInterface.h +++ /dev/null @@ -1,35 +0,0 @@ -/** - * Copyright 2026 Comcast Cable Communications Management, LLC - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - * SPDX-License-Identifier: Apache-2.0 - */ - -#pragma once - -#include "fireboltDemoBase.h" -#include - -class ChooseInterface : public FireboltDemoBase -{ -public: - ChooseInterface(); - ~ChooseInterface(); - - void runOption(const int index); - void autoRun(); - -private: - std::vector> interfaces; -}; diff --git a/test/api_test_app/cpp/deviceDemo.cpp b/test/api_test_app/cpp/deviceDemo.cpp deleted file mode 100644 index 808fa8c..0000000 --- a/test/api_test_app/cpp/deviceDemo.cpp +++ /dev/null @@ -1,82 +0,0 @@ -/** - * Copyright 2026 Comcast Cable Communications Management, LLC - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - * SPDX-License-Identifier: Apache-2.0 - */ - -#include "deviceDemo.h" -#include -#include -#include - -#include "json_types/jsondata_device_types.h" - -using namespace Firebolt; -using namespace Firebolt::Device; - -DeviceDemo::DeviceDemo() - : FireboltDemoBase() -{ - methodsFromRpc("Device"); -} - -void DeviceDemo::runOption(const int index) -{ - std::string key = itemDescriptions_[index].name; - - std::cout << "Running Device method: " << key << std::endl; - - if (key == "Device.deviceClass") - { - Result r = Firebolt::IFireboltAccessor::Instance().DeviceInterface().deviceClass(); - if (validateResult(r)) - { - std::cout << "Device Class: " << stringFromEnum(Firebolt::Device::JsonData::DeviceClassEnum, r.value()) - << std::endl; - } - } - else if (key == "Device.uptime") - { - Result r = Firebolt::IFireboltAccessor::Instance().DeviceInterface().uptime(); - if (validateResult(r)) - { - std::cout << "Device Uptime (seconds): " << r.value() << std::endl; - } - } - else if (key == "Device.timeInActiveState") - { - Result r = Firebolt::IFireboltAccessor::Instance().DeviceInterface().timeInActiveState(); - if (validateResult(r)) - { - std::cout << "Device Time In Active State (seconds): " << r.value() << std::endl; - } - } - else if (key == "Device.chipsetId") - { - Result r = Firebolt::IFireboltAccessor::Instance().DeviceInterface().chipsetId(); - if (validateResult(r)) - { - std::cout << "Device Chipset ID: " << r.value() << std::endl; - } - } - else if (key == "Device.uid") - { - Result r = Firebolt::IFireboltAccessor::Instance().DeviceInterface().uid(); - if (validateResult(r)) - { - std::cout << "Device UID: " << r.value() << std::endl; - } - } -} diff --git a/test/api_test_app/cpp/discoveryDemo.cpp b/test/api_test_app/cpp/discoveryDemo.cpp deleted file mode 100644 index a3fc5a3..0000000 --- a/test/api_test_app/cpp/discoveryDemo.cpp +++ /dev/null @@ -1,69 +0,0 @@ -/** - * Copyright 2026 Comcast Cable Communications Management, LLC - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - * SPDX-License-Identifier: Apache-2.0 - */ - -#include "discoveryDemo.h" -#include -#include -#include - -#include "json_types/jsondata_discovery.h" - -using namespace Firebolt; -using namespace Firebolt::Discovery; - -DiscoveryDemo::DiscoveryDemo() - : FireboltDemoBase() -{ - methodsFromRpc("Discovery"); -} - -void DiscoveryDemo::runOption(const int index) -{ - std::string key = itemDescriptions_[index].name; - - std::cout << "Running Discovery method: " << key << std::endl; - - if (key == "Discovery.watched") - { - std::string entityId; - paramFromConsole("entityId", "exampleEntityId", entityId); - - std::string progressStr; - paramFromConsole("progress (percentage as (0-0.999) for VOD, number of seconds for live)", "0.5", progressStr); - std::optional progress = std::stof(progressStr); - - std::string completedStr; - paramFromConsole("completed (true/false)", "false", completedStr); - std::optional completed = completedStr == "true"; - - std::string watchedOn; - paramFromConsole("watchedOn (ISO 8601 timestamp)", "2024-01-01T00:00:00Z", watchedOn); - - AgePolicy agePolicy = chooseEnumFromList(Firebolt::Discovery::JsonData::AgePolicyEnum, - "Choose an age policy for the watch event:"); - std::optional agePolicyOpt = agePolicy; - - Result r = Firebolt::IFireboltAccessor::Instance().DiscoveryInterface().watched(entityId, progress, - completed, watchedOn, - agePolicyOpt); - if (validateResult(r)) - { - std::cout << "Discovery.watched result: " << (r.value() ? "true" : "false") << std::endl; - } - } -} diff --git a/test/api_test_app/cpp/displayDemo.cpp b/test/api_test_app/cpp/displayDemo.cpp deleted file mode 100644 index 50814ff..0000000 --- a/test/api_test_app/cpp/displayDemo.cpp +++ /dev/null @@ -1,58 +0,0 @@ -/** - * Copyright 2026 Comcast Cable Communications Management, LLC - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - * SPDX-License-Identifier: Apache-2.0 - */ - -#include "displayDemo.h" -#include -#include -#include - -#include "json_types/jsondata_device_types.h" - -using namespace Firebolt; -using namespace Firebolt::Display; - -DisplayDemo::DisplayDemo() - : FireboltDemoBase() -{ - methodsFromRpc("Display"); -} - -void DisplayDemo::runOption(const int index) -{ - std::string key = itemDescriptions_[index].name; - - std::cout << "Running Display method: " << key << std::endl; - if (key == "Display.maxResolution") - { - Result r = Firebolt::IFireboltAccessor::Instance().DisplayInterface().maxResolution(); - if (validateResult(r)) - { - DisplaySize res = r.value(); - std::cout << "Max Resolution - Width: " << res.width << ", Height: " << res.height << std::endl; - } - } - else if (key == "Display.size") - { - Result r = Firebolt::IFireboltAccessor::Instance().DisplayInterface().size(); - if (validateResult(r)) - { - DisplaySize size = r.value(); - std::cout << "Display Size - Width: " << size.width << ", Height: " << size.height << std::endl; - } - } -} diff --git a/test/api_test_app/cpp/firebolt-open-rpc.json.in b/test/api_test_app/cpp/firebolt-open-rpc.json.in deleted file mode 100644 index c86998e..0000000 --- a/test/api_test_app/cpp/firebolt-open-rpc.json.in +++ /dev/null @@ -1,4 +0,0 @@ -#pragma once -#include - -constexpr std::string_view JSON_DATA = R"JSON_DELIMITER(@JSON_CONTENT@)JSON_DELIMITER"; \ No newline at end of file diff --git a/test/api_test_app/cpp/fireboltDemoBase.cpp b/test/api_test_app/cpp/fireboltDemoBase.cpp deleted file mode 100644 index e89feb7..0000000 --- a/test/api_test_app/cpp/fireboltDemoBase.cpp +++ /dev/null @@ -1,78 +0,0 @@ -/** - * Copyright 2026 Comcast Cable Communications Management, LLC - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - * SPDX-License-Identifier: Apache-2.0 - */ - -#include "fireboltDemoBase.h" -#include "firebolt-open-rpc_json.h" -#include -#include -#include -#include -#include - -nlohmann::json FireboltDemoBase::json_; - -#ifndef UT_OPEN_RPC_FILE -#define UT_OPEN_RPC_FILE "firebolt-open-rpc.json" -#endif - -FireboltDemoBase::FireboltDemoBase() -{ - loadRpc(); -} - -int FireboltDemoBase::chooseFromList(const std::vector& options, const std::string& prompt, bool allowCancel) -{ - std::cout << std::endl << prompt << std::endl; - for (size_t i = 0; i < options.size(); ++i) - { - std::cout << i << ": " << options[i] << std::endl; - } - - int choice = getOption(static_cast(options.size() - 1), allowCancel); - - return choice; -} - -int FireboltDemoBase::chooseOption() -{ - std::vector methodNames; - for (const auto& item : itemDescriptions_) - { - methodNames.push_back(item.name); - } - return chooseFromList(methodNames, "Choose a method to run:", true); -} - -void FireboltDemoBase::loadRpc() -{ - json_ = nlohmann::json::parse(JSON_DATA); -} - -void FireboltDemoBase::methodsFromRpc(const std::string& interfaceName) -{ - std::vector methodNames; - - std::string interfaceStr = interfaceName + "."; - for (const auto& method : json_["methods"]) - { - if (method.contains("name") && method["name"].get().rfind(interfaceStr, 0) == 0) - { - itemDescriptions_.push_back({method["name"], method["summary"]}); - } - } -} diff --git a/test/api_test_app/cpp/fireboltDemoBase.h b/test/api_test_app/cpp/fireboltDemoBase.h deleted file mode 100644 index 62e263b..0000000 --- a/test/api_test_app/cpp/fireboltDemoBase.h +++ /dev/null @@ -1,111 +0,0 @@ -/** - * Copyright 2026 Comcast Cable Communications Management, LLC - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - * SPDX-License-Identifier: Apache-2.0 - */ - -#pragma once - -#include "firebolt/firebolt.h" - -#include -#include -#include -#include - -extern bool gAutoRun; -extern int getOption(int n, bool allowCancel = false); - -extern void paramFromConsole(const std::string& name, const std::string& def, std::string& value); - -struct ItemDescription -{ - std::string name; - std::string description; -}; - -class FireboltDemoBase -{ -public: - FireboltDemoBase(); - virtual ~FireboltDemoBase() = default; - - virtual void runOption(const int index) = 0; - int listSize() const { return static_cast(itemDescriptions_.size()); } - std::string method(int index) const { return itemDescriptions_[index].name; } - - int chooseOption(); - -protected: - int chooseFromList(const std::vector& options, const std::string& prompt, bool allowCancel = false); - void loadRpc(); - - template bool validateResult(const Firebolt::Result& result) const - { - return doValidateResult(result.error()); - } - - bool validateResult(const Firebolt::Result& result) const { return doValidateResult(result.error()); } - - template T chooseEnumFromList(const Firebolt::JSON::EnumType& enumType, const std::string& prompt) - { - if (gAutoRun) - { - T defaultValue = enumType.begin()->second; - std::cout << "Auto-selecting '" << enumType.begin()->first << "' for " << prompt << "." << std::endl; - return defaultValue; - } - - std::vector options; - for (const auto& pair : enumType) - { - options.push_back(pair.first); - } - - int choice = chooseFromList(options, prompt, false); - - return enumType.at(options[choice]); - } - - template std::string stringFromEnum(Firebolt::JSON::EnumType enumType, T value) - { - for (const auto& pair : enumType) - { - if (pair.second == value) - { - return pair.first; - } - } - return {}; - } - - void methodsFromRpc(const std::string& interfaceName); - - static nlohmann::json json_; - - std::vector itemDescriptions_; - -private: - bool doValidateResult(Firebolt::Error error) const - { - if (error != Firebolt::Error::None) - { - std::cout << "Operation failed with error: " << static_cast(error) << std::endl; - return false; - } - std::cout << "Operation succeeded." << std::endl; - return true; - } -}; diff --git a/test/api_test_app/cpp/presentationDemo.cpp b/test/api_test_app/cpp/presentationDemo.cpp deleted file mode 100644 index 51323e9..0000000 --- a/test/api_test_app/cpp/presentationDemo.cpp +++ /dev/null @@ -1,57 +0,0 @@ -/** - * Copyright 2026 Comcast Cable Communications Management, LLC - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - * SPDX-License-Identifier: Apache-2.0 - */ - -#include "presentationDemo.h" -#include -#include -#include - -using namespace Firebolt; -using namespace Firebolt::Presentation; - -PresentationDemo::PresentationDemo() - : FireboltDemoBase() -{ - methodsFromRpc("Presentation"); -} - -void PresentationDemo::runOption(const int index) -{ - std::string key = itemDescriptions_[index].name; - - if (key == "Presentation.focused") - { - Result r = Firebolt::IFireboltAccessor::Instance().PresentationInterface().focused(); - if (validateResult(r)) - { - std::cout << "Presentation focused: " << (r.value() ? "true" : "false") << std::endl; - } - } - else if (key == "Presentation.onFocusedChanged") - { - auto subscriptionResult = - Firebolt::IFireboltAccessor::Instance().PresentationInterface().subscribeOnFocusedChanged( - [&](bool focused) - { std::cout << "Presentation focus changed: " << (focused ? "true" : "false") << std::endl; }); - if (validateResult(subscriptionResult)) - { - SubscriptionId subId = subscriptionResult.value(); - std::cout << "Subscribed to Presentation.onFocusedChanged with SubscriptionId: " << subId << std::endl; - } - } -} diff --git a/test/api_test_app/cpp/texttospeechDemo.cpp b/test/api_test_app/cpp/texttospeechDemo.cpp deleted file mode 100644 index 72fd7e2..0000000 --- a/test/api_test_app/cpp/texttospeechDemo.cpp +++ /dev/null @@ -1,151 +0,0 @@ -/** - * Copyright 2026 Comcast Cable Communications Management, LLC - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - * SPDX-License-Identifier: Apache-2.0 - */ - -#include "texttospeechDemo.h" -#include -#include -#include - -#include "json_types/jsondata_texttospeech_types.h" - -using namespace Firebolt; -using namespace Firebolt::TextToSpeech; - -TextToSpeechDemo::TextToSpeechDemo() - : FireboltDemoBase() -{ - methodsFromRpc("TextToSpeech"); -} - -SpeechId TextToSpeechDemo::chooseSpeechIdFromConsole() -{ - std::string sId; - - std::string savedId = std::to_string(speechId_); - - paramFromConsole("speech ID", savedId, sId); - SpeechId speechId = std::stoi(sId); - return speechId; -} - -void TextToSpeechDemo::runOption(const int index) -{ - std::string key = itemDescriptions_[index].name; - - std::cout << "Running TextToSpeech method: " << key << std::endl; - - if (key == "TextToSpeech.speak") - { - std::string text; - paramFromConsole("text to speak", "Hello, world!", text); - - Result r = IFireboltAccessor::Instance().TextToSpeechInterface().speak(text); - validateResult(r); - std::cout << "SpeechResponse: SpeechId'" << r.value().speechId << " TTSStatus'" << r.value().ttsStatus << "' " - << std::endl; - speechId_ = r.value().speechId; - } - else if (key == "TextToSpeech.listVoices") - { - std::string language; - paramFromConsole("language (BCP 47 locale tag)", "en-US", language); - - Result r = IFireboltAccessor::Instance().TextToSpeechInterface().listVoices(language); - if (validateResult(r)) - { - const auto& voices = r.value().voices; - std::cout << "Voices available for language '" << language << "':" << std::endl; - for (const auto& voice : voices) - { - std::cout << " Name: " << voice << std::endl; - } - } - } - else if (key == "TextToSpeech.pause") - { - SpeechId speechId = chooseSpeechIdFromConsole(); - Result r = IFireboltAccessor::Instance().TextToSpeechInterface().pause(speechId); - validateResult(r); - } - else if (key == "TextToSpeech.resume") - { - SpeechId speechId = chooseSpeechIdFromConsole(); - Result r = IFireboltAccessor::Instance().TextToSpeechInterface().resume(speechId); - validateResult(r); - } - else if (key == "TextToSpeech.cancel") - { - SpeechId speechId = chooseSpeechIdFromConsole(); - Result r = IFireboltAccessor::Instance().TextToSpeechInterface().cancel(speechId); - validateResult(r); - } - else if (key == "TextToSpeech.getSpeechState") - { - SpeechId speechId = chooseSpeechIdFromConsole(); - Result r = IFireboltAccessor::Instance().TextToSpeechInterface().getSpeechState(speechId); - if (validateResult(r)) - { - const SpeechState& state = r.value().speechState; - std::cout << "Current state for speech ID '" << speechId << "': " << (int)state << std::endl; - } - } - else if (key == "TextToSpeech.onWillSpeak") - { - auto callback = [&](const TextToSpeech::SpeechIdEvent& event) - { std::cout << "Will Speak notification received for Speech ID: " << event.speechId << std::endl; }; - Result r = - IFireboltAccessor::Instance().TextToSpeechInterface().subscribeOnWillSpeak(std::move(callback)); - if (validateResult(r)) - { - std::cout << "Subscribed to onWillSpeak with Subscription ID: " << r.value() << std::endl; - } - } - else if (key == "TextToSpeech.onSpeechStart") - { - auto callback = [&](const SpeechIdEvent& event) - { std::cout << "Speech Start notification received for Speech ID: " << event.speechId << std::endl; }; - Result r = - IFireboltAccessor::Instance().TextToSpeechInterface().subscribeOnSpeechStart(std::move(callback)); - if (validateResult(r)) - { - std::cout << "Subscribed to OnSpeechStart with Subscription ID: " << r.value() << std::endl; - } - } - else if (key == "TextToSpeech.onSpeechPause") - { - auto callback = [&](const SpeechIdEvent& event) - { std::cout << "Speech Pause notification received for Speech ID: " << event.speechId << std::endl; }; - Result r = - IFireboltAccessor::Instance().TextToSpeechInterface().subscribeOnSpeechPause(std::move(callback)); - if (validateResult(r)) - { - std::cout << "Subscribed to OnSpeechPause with Subscription ID: " << r.value() << std::endl; - } - } - else if (key == "TextToSpeech.onSpeechResume") - { - auto callback = [&](const SpeechIdEvent& event) - { std::cout << "Speech Resume notification received for Speech ID: " << event.speechId << std::endl; }; - Result r = - IFireboltAccessor::Instance().TextToSpeechInterface().subscribeOnSpeechResume(std::move(callback)); - if (validateResult(r)) - { - std::cout << "Subscribed to OnSpeechResume with Subscription ID: " << r.value() << std::endl; - } - } -} diff --git a/test/api_test_app/main.cpp b/test/api_test_app/main.cpp index f7e0c0f..6c69ff7 100644 --- a/test/api_test_app/main.cpp +++ b/test/api_test_app/main.cpp @@ -16,154 +16,60 @@ * SPDX-License-Identifier: Apache-2.0 */ -#include -#include -#include -#include -#include -#include -#include +#include "accessibilityDemo.h" +#include "advertisingDemo.h" +#include "deviceDemo.h" +#include "discoveryDemo.h" +#include "displayDemo.h" +#include "lifecycleDemo.h" +#include "localizationDemo.h" +#include "networkDemo.h" +#include "presentationDemo.h" +#include "statsDemo.h" +#include "texttospeechDemo.h" + +#include "utils.h" + +#include +#include +#include -#include "cpp/chooseInterface.h" - -std::atomic gConnected{false}; -bool gAutoRun = false; - -//--------------- -void paramFromConsole(const std::string& name, const std::string& def, std::string& value) +int main(int argc, char** argv) { - if (gAutoRun) - { - std::cout << "Auto-selecting " << def << " for " << name << "." << std::endl; - value = def; - return; - } - - std::cout << "Enter " << name << " (default: " << def << "): "; + auto& appConfig = GetAppConfig(); - std::string input; + Firebolt::LogLevel logLevel = Firebolt::LogLevel::Notice; + std::string url; - std::getline(std::cin, input); - - if (input.empty()) - { - value = def; - std::cout << "Using default value: " << def << std::endl; - } - else - { - value = input; - } -} - -int getOption(int n, bool allowCancel) -{ - std::string input; - - while (true) + for (int i = 1; i < argc; ++i) { - std::cout << "Select option"; - if (allowCancel) + if (std::string(argv[i]) == "--auto") { - std::cout << " or 'q' to go back"; + appConfig.autoRun = true; } - std::cout << ": "; - std::cin >> input; - - // eat the rest of the line to avoid affecting the next input - std::cin.ignore(std::numeric_limits::max(), '\n'); - - // Check if user wants to quit - if (allowCancel && input.length() == 1 && std::tolower(input[0]) == 'q') + else if (std::string(argv[i]) == "--mock") { - return -1; + url = "ws://127.0.0.1:9998/"; } - - // Try to convert to integer - try + else if (std::string(argv[i]) == "--platform") { - int num = std::stoi(input); - - // Check if number is in valid range - if (num >= 0 && num <= n) - { - return num; - } - else - { - std::cout << "Please enter a number between 0 and " << n << "." << std::endl; - } - } - catch (const std::invalid_argument&) - { - std::cout << "Invalid input. Please enter a number"; - if (allowCancel) - { - std::cout << " or 'q'"; - } - std::cout << "." << std::endl; - } - catch (const std::out_of_range&) - { - std::cout << "Number too large. Please enter a number between 0 and " << n << "." << std::endl; + url = "ws://127.0.0.1:3474/"; } - } -} - -void connectionChanged(const bool connected, const Firebolt::Error error) -{ - std::cout << "Change in connection: connected: " << connected << " error: " << static_cast(error) << std::endl; - gConnected.store(connected, std::memory_order_release); -} - -void createFireboltInstance(const std::string& url) -{ - Firebolt::Config config; - config.wsUrl = url; - config.waitTime_ms = 1000; - config.log.level = Firebolt::LogLevel::Debug; - - gConnected = false; - Firebolt::IFireboltAccessor::Instance().Connect(config, connectionChanged); -} - -void destroyFireboltInstance() -{ - Firebolt::IFireboltAccessor::Instance().Disconnect(); -} - -bool waitOnConnectionReady() -{ - uint32_t waiting = 10000; - static constexpr uint32_t SLEEPSLOT_TIME = 100; - - // Right, a wait till connection is closed is requested.. - while ((waiting > 0) && !gConnected.load(std::memory_order_acquire)) - { - - uint32_t sleepSlot = (waiting > SLEEPSLOT_TIME ? SLEEPSLOT_TIME : waiting); - // Right, lets sleep in slices of 100 ms - std::this_thread::sleep_for(std::chrono::milliseconds(sleepSlot)); - waiting -= sleepSlot; - } - return gConnected.load(std::memory_order_acquire); -} - -int main(int argc, char** argv) -{ - std::string url = ""; - - // check args for -auto option - for (int i = 1; i < argc; ++i) - { - std::cout << "Arg: " << argv[i] << std::endl; - if (std::string(argv[i]) == "-auto") + else if (std::string(argv[i]) == "--dbg") { - gAutoRun = true; + logLevel = Firebolt::LogLevel::Debug; } - else if (std::string(argv[i]) == "-mock") + else if (std::string(argv[i]) == "--help") { - url = "ws://127.0.0.1:9998"; // Default URL for local mock server + /* clang-format off */ + std::cout << "Usage: " << argv[0] << " [--auto] [--mock] [--platform] [--dbg] [--help]" << std::endl; + std::cout << " --auto Automatically run all methods for all interfaces without user input." << std::endl; + std::cout << " --mock Connect to a local mock server instead of the default Firebolt Demo Service." << std::endl; + std::cout << " --platform Connect to the platform's Firebolt service (default if available)." << std::endl; + std::cout << " --dbg Enable debug logging." << std::endl; + std::cout << " --help Show this help message." << std::endl; + /* clang-format on */ + return 0; } } @@ -176,43 +82,105 @@ int main(int argc, char** argv) } else { - url = "ws://127.0.0.1:3474"; // Default URL for RDK Central's Firebolt Demo Service + url = "ws://127.0.0.1:9998/"; } - std::cout << "-----Using firebolt URL: " << url << std::endl; } + std::cout << "Using firebolt URL: " << url << std::endl; - createFireboltInstance(url); + Firebolt::Config config; + config.wsUrl = url; + config.waitTime_ms = 1000; + config.log.level = logLevel; + + std::promise connectionPromise; + std::once_flag connectionOnce; + auto future = connectionPromise.get_future(); - std::this_thread::sleep_for(std::chrono::seconds(1)); + /* clang-format off */ + auto result = Firebolt::IFireboltAccessor::Instance().Connect( + config, + [&](const bool connected, const Firebolt::Error error) + { + std::cout << "Change in connection: connected: " << std::boolalpha << connected << ", error: " << static_cast(error) << std::endl; + std::call_once(connectionOnce, [&] { connectionPromise.set_value(connected); }); + }); + /* clang-format on */ - if (!waitOnConnectionReady()) + if (result != Firebolt::Error::None) { - std::cout << "Test not able to connect with server..." << std::endl; - return -1; + std::cout << "Connection call failed" << std::endl; + return 1; + } + if (future.wait_for(std::chrono::seconds(2)) == std::future_status::timeout) + { + std::cout << "Connection timed out" << std::endl; + return 1; + } + if (!future.get()) + { + std::cout << "Failed to connect" << std::endl; + return 1; } - ChooseInterface chooseInterface; - - if (gAutoRun) + std::vector> interfaces; + + interfaces.emplace_back(std::make_unique()); + interfaces.emplace_back(std::make_unique()); + interfaces.emplace_back(std::make_unique()); + interfaces.emplace_back(std::make_unique()); + interfaces.emplace_back(std::make_unique()); + interfaces.emplace_back(std::make_unique()); + interfaces.emplace_back(std::make_unique()); + interfaces.emplace_back(std::make_unique()); + interfaces.emplace_back(std::make_unique()); + interfaces.emplace_back(std::make_unique()); + interfaces.emplace_back(std::make_unique()); + + if (appConfig.autoRun) { - chooseInterface.autoRun(); + for (auto& interface : interfaces) + { + std::cout << "Auto-running interface: " << interface->name() << std::endl; + + for (auto& method : interface->methods()) + { + std::cout << "Auto-running method: " << method << std::endl; + interface->runOption(method); + } + } } else { - for (;;) + std::vector interfaceNames; + for (const auto& interface : interfaces) { - int interfaceIndex = chooseInterface.chooseOption(); - + interfaceNames.push_back(interface->name()); + } + while (true) + { + int interfaceIndex = chooseFromList(interfaceNames, "Select an interface to test:"); if (interfaceIndex == -1) { - break; // Exit the program + break; + } + auto& selectedInterface = interfaces[interfaceIndex]; + std::cout << "Selected interface: " << selectedInterface->name() << std::endl; + std::vector methodNames = selectedInterface->methods(); + while (true) + { + int methodIndex = chooseFromList(methodNames, "Select a method to run:"); + if (methodIndex == -1) + { + break; + } + const std::string& methodName = methodNames[methodIndex]; + std::cout << "Selected method: " << methodName << std::endl; + selectedInterface->runOption(methodName); } - - chooseInterface.runOption(interfaceIndex); } } - destroyFireboltInstance(); + Firebolt::IFireboltAccessor::Instance().Disconnect(); return 0; } diff --git a/test/api_test_app/utils.cpp b/test/api_test_app/utils.cpp new file mode 100644 index 0000000..fc0bbe1 --- /dev/null +++ b/test/api_test_app/utils.cpp @@ -0,0 +1,107 @@ +/** + * Copyright 2026 Comcast Cable Communications Management, LLC + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#include "utils.h" + +#include + +static AppConfig gAppConfig; + +AppConfig& GetAppConfig() +{ + return gAppConfig; +} + +std::string paramFromConsole(const std::string& name, const std::string& def) +{ + if (GetAppConfig().autoRun) + { + std::cout << "Auto-selecting " << def << " for " << name << "." << std::endl; + return def; + } + + std::cout << "Enter " << name << " (default: " << def << "): "; + + std::string input; + std::getline(std::cin, input); + + if (input.empty()) + { + return def; + } + return input; +} + +int getOption(int max) +{ + std::string input; + + while (true) + { + std::cout << "Select option or enter/q to go back: "; + std::getline(std::cin, input); + + if (input.length() == 0 || strcasecmp(input.c_str(), "q") == 0) + { + return -1; + } + + try + { + int num = std::stoi(input); + + if (num > 0 && num <= max) + { + return num; + } + else + { + std::cout << "Please enter a number between 1 and " << max << " (inclusive)." << std::endl; + } + } + catch (const std::invalid_argument&) + { + std::cout << "Invalid input. Please enter a number or 'q'." << std::endl; + } + catch (const std::out_of_range&) + { + std::cout << "Number too large. Please enter a number between 1 and " << max << " (inclusive)." << std::endl; + } + } +} + +int chooseFromList(const std::vector& options, const std::string& prompt) +{ + if (options.empty()) + { + return -1; + } + std::cout << std::endl << prompt << std::endl; + for (size_t i = 0; i < options.size(); ++i) + { + std::cout << (i + 1) << ": " << options[i] << std::endl; + } + + int choice = getOption(options.size()); + if (choice == -1) + { + return -1; + } + + return choice - 1; +} diff --git a/test/api_test_app/utils.h b/test/api_test_app/utils.h new file mode 100644 index 0000000..7a3d72e --- /dev/null +++ b/test/api_test_app/utils.h @@ -0,0 +1,91 @@ +/** + * Copyright 2026 Comcast Cable Communications Management, LLC + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#pragma once + +#include +#include +#include +#include +#include +#include + +struct AppConfig +{ + bool autoRun = false; +}; + +AppConfig& GetAppConfig(); + +std::string paramFromConsole(const std::string& name, const std::string& def); +int chooseFromList(const std::vector& options, const std::string& prompt); + +class DemoBase +{ +public: + DemoBase(const std::string& name) + : name_(name) + { + } + virtual ~DemoBase() = default; + + std::string name() const { return name_; } + virtual void runOption(const std::string& method) = 0; + const std::vector& methods() const { return methods_; } + +protected: + template bool succeed(const Firebolt::Result& result) const + { + if (result) + { + return true; + } + std::cout << "Error: " << static_cast(result.error()) << std::endl; + return false; + } + + std::string name_; + std::vector methods_; +}; + +template T chooseEnumFromList(const Firebolt::JSON::EnumType& enumType, const std::string& prompt) +{ + if (enumType.empty()) + { + throw std::runtime_error("EnumType cannot be empty"); + } + if (GetAppConfig().autoRun) + { + std::cout << "Auto-selecting '" << enumType.begin()->first << "' for " << prompt << "." << std::endl; + return enumType.begin()->second; + } + + std::vector options; + for (const auto& pair : enumType) + { + options.push_back(pair.first); + } + + int choice = chooseFromList(options, prompt); + if (choice == -1) + { + choice = 0; + } + + return enumType.at(options[choice]); +} From b3e4c4fe78b4ccd932d2903ea4ff1e63d13c86e3 Mon Sep 17 00:00:00 2001 From: Tomasz Blaszczak Date: Thu, 26 Feb 2026 10:39:05 +0100 Subject: [PATCH 2/4] test: In api-test app allow to read test suite from stdin Allow to invoke as `./build/api-test-app #include #include +#include int main(int argc, char** argv) { @@ -136,7 +137,36 @@ int main(int argc, char** argv) interfaces.emplace_back(std::make_unique()); interfaces.emplace_back(std::make_unique()); - if (appConfig.autoRun) + if (!isatty(fileno(stdin))) + { + appConfig.autoRun = true; + std::string line; + while (std::getline(std::cin, line)) + { + bool found = false; + for (const auto& interface : interfaces) + { + for (const auto& method : interface->methods()) + { + if (method == line) + { + interface->runOption(method); + found = true; + break; + } + } + if (found) + { + break; + } + } + if (!found) + { + std::cout << "Method not found: " << line << std::endl; + } + } + } + else if (appConfig.autoRun) { for (auto& interface : interfaces) { diff --git a/test/api_test_app/test-suite.example b/test/api_test_app/test-suite.example new file mode 100644 index 0000000..3a6c667 --- /dev/null +++ b/test/api_test_app/test-suite.example @@ -0,0 +1,5 @@ +Accessibility.highContrastUI +Device.chipsetId +TextToSpeech.speak +TextToSpeech.listVoices +TextToSpeech.pause From f2b2901dd7f438fdae5b2e9758f027ec7f891e71 Mon Sep 17 00:00:00 2001 From: Tomasz Blaszczak Date: Thu, 26 Feb 2026 11:33:35 +0100 Subject: [PATCH 3/4] test: Remove previous demo app --- demo/CMakeLists.txt | 71 ------------ demo/FireboltDemoService.cpp | 216 ----------------------------------- demo/FireboltDemoService.h | 51 --------- demo/build.sh | 55 --------- demo/main.cpp | 54 --------- 5 files changed, 447 deletions(-) delete mode 100644 demo/CMakeLists.txt delete mode 100644 demo/FireboltDemoService.cpp delete mode 100644 demo/FireboltDemoService.h delete mode 100755 demo/build.sh delete mode 100644 demo/main.cpp diff --git a/demo/CMakeLists.txt b/demo/CMakeLists.txt deleted file mode 100644 index 6aa69f3..0000000 --- a/demo/CMakeLists.txt +++ /dev/null @@ -1,71 +0,0 @@ -# Copyright 2025 Comcast Cable Communications Management, LLC -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. -# -# SPDX-License-Identifier: Apache-2.0 - -if (NOT CMAKE_PROJECT_NAME) - cmake_minimum_required(VERSION 3.10) - project(FireboltCoreDemo) - - if (CMAKE_INSTALL_PREFIX_INITIALIZED_TO_DEFAULT) - set(CMAKE_INSTALL_PREFIX "${SYSROOT_PATH}/usr" CACHE INTERNAL "" FORCE) - set(CMAKE_PREFIX_PATH ${SYSROOT_PATH}/usr/lib/cmake CACHE INTERNAL "" FORCE) - endif() - - list(APPEND CMAKE_MODULE_PATH - "${SYSROOT_PATH}/usr/lib/cmake" - "${SYSROOT_PATH}/tools/cmake" - ) -endif () -set(DEMO_APP demoApp) - -message("Setup ${DEMO_APP}") - -add_compile_options(-Wall -Wextra -Wpedantic) - -find_package(FireboltTransport CONFIG REQUIRED) - -add_executable(${DEMO_APP} - FireboltDemoService.cpp - main.cpp) - -if (NOT ENABLE_DEMO_APP) - find_package(FireboltClient CONFIG REQUIRED) - target_link_libraries(${DEMO_APP} - PRIVATE - FireboltTransport::FireboltTransport - FireboltClient::FireboltClient - ) -else() - target_link_libraries(${DEMO_APP} - PRIVATE - FireboltClient - ) -endif () - -target_include_directories(${DEMO_APP} - PRIVATE - $ - $ -) - -set_target_properties(${DEMO_APP} PROPERTIES - CXX_STANDARD 17 - CXX_STANDARD_REQUIRED YES -) - -install( - TARGETS ${DEMO_APP} - DESTINATION bin -) diff --git a/demo/FireboltDemoService.cpp b/demo/FireboltDemoService.cpp deleted file mode 100644 index f6a520c..0000000 --- a/demo/FireboltDemoService.cpp +++ /dev/null @@ -1,216 +0,0 @@ -/** - * Copyright 2025 Comcast Cable Communications Management, LLC - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - * SPDX-License-Identifier: Apache-2.0 - */ - -#include "FireboltDemoService.h" -#include -#include -#include -#include -#include - -namespace -{ -std::ostream& operator<<(std::ostream& out, Firebolt::Error& error) -{ - switch (error) - { - case Firebolt::Error::None: - { - out << "None"; - break; - } - case Firebolt::Error::General: - { - out << "General"; - break; - } - case Firebolt::Error::Timedout: - { - out << "Timedout"; - break; - } - case Firebolt::Error::NotConnected: - { - out << "NotConnected"; - break; - } - case Firebolt::Error::AlreadyConnected: - { - out << "AlreadyConnected"; - break; - } - case Firebolt::Error::InvalidRequest: - { - out << "InvalidRequest"; - break; - } - case Firebolt::Error::MethodNotFound: - { - out << "MethodNotFound"; - break; - } - case Firebolt::Error::InvalidParams: - { - out << "InvalidParams"; - break; - } - case Firebolt::Error::CapabilityNotAvailable: - { - out << "CapabilityNotAvaialbale"; - break; - } - case Firebolt::Error::CapabilityNotSupported: - { - out << "CapabilityNotSupported"; - break; - } - case Firebolt::Error::CapabilityGet: - { - out << "CapabilityGet"; - break; - } - case Firebolt::Error::CapabilityNotPermitted: - { - out << "CapabilityNotPermitted"; - break; - } - } - return out; -} -} // namespace - -FireboltDemoService::FireboltDemoService() -{ - std::string url = "ws://127.0.0.1:9998/"; - const char* fireboltEndpoint = std::getenv("FIREBOLT_ENDPOINT"); - if (fireboltEndpoint) - { - url = fireboltEndpoint; - } - std::cout << "Using firebolt URL: " << url << std::endl; - - Firebolt::Config config; - config.wsUrl = url; - config.waitTime_ms = 3000; - config.log.level = Firebolt::LogLevel::Debug; - - auto error = - Firebolt::IFireboltAccessor::Instance().Connect(config, [this](const bool connected, const Firebolt::Error error) - { this->onConnectionChanged(connected, error); }); - if (Firebolt::Error::None != error) - { - throw std::runtime_error("Failed to connect"); - } - std::unique_lock lock{mutex_}; - if (!cv_.wait_for(lock, std::chrono::seconds{1}, [this]() { return connected_; })) - { - deinitialize(); - throw std::runtime_error("Cannot connect to Firebolt"); - } - std::cout << "We are connected!\n"; -} - -FireboltDemoService::~FireboltDemoService() -{ - deinitialize(); -} - -std::string bool2str(const bool value) -{ - return value ? "true" : "false"; -} - -void FireboltDemoService::lifecycle() -{ - auto state = Firebolt::IFireboltAccessor::Instance().LifecycleInterface().state(); - if (state) - { - std::cout << "Current state: " << static_cast(*state) << std::endl; - } - else - { - std::cout << "Cannot get current state, err:" << state.error() << std::endl; - } - - auto id = Firebolt::IFireboltAccessor::Instance().LifecycleInterface().subscribeOnStateChanged( - [&](const std::vector& changes) - { - std::cout << "[Subscription] Lifecycle state changed: " << static_cast(changes[0].newState) - << ", old state: " << static_cast(changes[0].oldState) << std::endl; - }); - if (!id) - { - std::cout << "Failed to subscribe, error: " << id.error() << std::endl; - return; - } - lifecycleSubscriptionIds_.insert(*id); -} - -void FireboltDemoService::presentation() -{ - auto focus = Firebolt::IFireboltAccessor::Instance().PresentationInterface().focused(); - if (focus) - { - std::cout << "Current focus: " << static_cast(*focus) << std::endl; - } - else - { - std::cout << "Cannot get current focus, err:" << focus.error() << std::endl; - } - auto id = Firebolt::IFireboltAccessor::Instance().PresentationInterface().subscribeOnFocusedChanged( - [&](const bool focus) { std::cout << "[Subscription] Presentation focus changed: " << focus << std::endl; }); - if (!id) - { - std::cout << "Failed to subscribe, error: " << id.error() << std::endl; - return; - } - presentationSubscriptionIds_.insert(*id); -} - -void FireboltDemoService::unsubscribeAll() -{ - std::cout << "Unsubscribing..." << std::endl; - for (const auto& id : lifecycleSubscriptionIds_) - { - auto result{Firebolt::IFireboltAccessor::Instance().LifecycleInterface().unsubscribe(id)}; - if (!result) - { - std::cout << "Unsubscribe with id: " << id << " failed, error: " << result.error() << std::endl; - } - } - for (const auto& id : presentationSubscriptionIds_) - { - auto result{Firebolt::IFireboltAccessor::Instance().PresentationInterface().unsubscribe(id)}; - if (!result) - { - std::cout << "Unsubscribe with id: " << id << " failed, error: " << result.error() << std::endl; - } - } -} - -void FireboltDemoService::onConnectionChanged(const bool connected, const Firebolt::Error /* error */) -{ - std::unique_lock lock{mutex_}; - connected_ = connected; - cv_.notify_one(); -} - -void FireboltDemoService::deinitialize() -{ - Firebolt::IFireboltAccessor::Instance().Disconnect(); -} diff --git a/demo/FireboltDemoService.h b/demo/FireboltDemoService.h deleted file mode 100644 index 74bdaec..0000000 --- a/demo/FireboltDemoService.h +++ /dev/null @@ -1,51 +0,0 @@ -/** - * Copyright 2025 Comcast Cable Communications Management, LLC - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - * SPDX-License-Identifier: Apache-2.0 - */ - -#pragma once - -#include -#include -#include -#include - -class FireboltDemoService -{ -public: - FireboltDemoService(); - ~FireboltDemoService(); - FireboltDemoService(const FireboltDemoService&) = delete; - FireboltDemoService(FireboltDemoService&&) = delete; - FireboltDemoService& operator=(const FireboltDemoService&) = delete; - FireboltDemoService& operator=(FireboltDemoService&&) = delete; - - void lifecycle(); - void presentation(); - - void unsubscribeAll(); - -private: - void onConnectionChanged(const bool connected, const Firebolt::Error error); - void deinitialize(); - -private: - std::mutex mutex_{}; - std::condition_variable cv_; - bool connected_{false}; - std::set lifecycleSubscriptionIds_; - std::set presentationSubscriptionIds_; -}; diff --git a/demo/build.sh b/demo/build.sh deleted file mode 100755 index 59f4e7f..0000000 --- a/demo/build.sh +++ /dev/null @@ -1,55 +0,0 @@ -#!/usr/bin/env bash - -# Copyright 2025 Comcast Cable Communications Management, LLC -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. -# -# SPDX-License-Identifier: Apache-2.0 - -set -e - -bdir="build" -run=true -buildType="Debug" - -while [[ ! -z $1 ]]; do - case $1 in - --clean) rm -rf $bdir;; - --just-run) - export LD_LIBRARY_PATH=$bdir/src:$SYSROOT_PATH/usr/lib:$LD_LIBRARY_PATH - $bdir/FireboltCoreDemo - exit;; - --no-run) run=false;; - --release) buildTarget="Release";; - --sysroot) SYSROOT_PATH="$2"; shift;; - --) shift; break;; - *) break;; - esac; shift -done - -[[ ! -z $SYSROOT_PATH ]] || { echo "SYSROOT_PATH not set" >/dev/stderr; exit 1; } -[[ -e $SYSROOT_PATH ]] || { echo "SYSROOT_PATH not exist ($SYSROOT_PATH)" >/dev/stderr; exit 1; } - -if [[ ! -e $bdir ]]; then - cmake -B $bdir \ - -DCMAKE_BUILD_TYPE=$buildType \ - -DSYSROOT_PATH=$SYSROOT_PATH \ - "$@" -fi -cmake --build $bdir - -if $run; then - export LD_LIBRARY_PATH=$bdir/src:$SYSROOT_PATH/usr/lib:$LD_LIBRARY_PATH - $bdir/demoApp -fi - diff --git a/demo/main.cpp b/demo/main.cpp deleted file mode 100644 index d8126d0..0000000 --- a/demo/main.cpp +++ /dev/null @@ -1,54 +0,0 @@ -/** - * Copyright 2025 Comcast Cable Communications Management, LLC - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - * SPDX-License-Identifier: Apache-2.0 - */ - -#include "FireboltDemoService.h" -#include -#include - -int main() -{ - try - { - std::cout << "Firebolt Client POC Demo" << std::endl; - - FireboltDemoService service; - - std::cout << "Lifecycle" << std::endl; - service.lifecycle(); - service.presentation(); - std::cout << std::endl; - std::cout << "All subscribers are registered, events can be sent to the app from mock" << std::endl; - while (1) - { - std::cout << "Press 'q' to quit" << std::endl; - std::string input; - getline(std::cin, input); - if (input == "q") - { - break; - } - } - service.unsubscribeAll(); - return 0; - } - catch (const std::exception& e) - { - std::cout << "Firebolt error: " << e.what() << std::endl; - return 1; - } -} From 4409b808176d14a9f236feeba003135ca0756b7b Mon Sep 17 00:00:00 2001 From: Tomasz Blaszczak Date: Thu, 26 Feb 2026 12:10:59 +0100 Subject: [PATCH 4/4] test: Add in api-test app remaining APIs --- test/api_test_app/apis/deviceDemo.cpp | 10 ++++++++++ test/api_test_app/apis/displayDemo.cpp | 11 ++++++++++- 2 files changed, 20 insertions(+), 1 deletion(-) diff --git a/test/api_test_app/apis/deviceDemo.cpp b/test/api_test_app/apis/deviceDemo.cpp index 4184ee3..23c9416 100644 --- a/test/api_test_app/apis/deviceDemo.cpp +++ b/test/api_test_app/apis/deviceDemo.cpp @@ -33,6 +33,7 @@ DeviceDemo::DeviceDemo() { methods_.push_back("Device.chipsetId"); methods_.push_back("Device.deviceClass"); + methods_.push_back("Device.hdr"); methods_.push_back("Device.timeInActiveState"); methods_.push_back("Device.uid"); methods_.push_back("Device.uptime"); @@ -59,6 +60,15 @@ void DeviceDemo::runOption(const std::string& method) << std::endl; } } + else if (method == "Device.hdr") + { + auto r = Firebolt::IFireboltAccessor::Instance().DeviceInterface().hdr(); + if (succeed(r)) + { + std::cout << "HDR: {" << std::boolalpha << r->hdr10 << ", " << r->hdr10Plus << ", " << r->dolbyVision + << ", " << r->hlg << "}" << std::endl; + } + } else if (method == "Device.timeInActiveState") { auto r = Firebolt::IFireboltAccessor::Instance().DeviceInterface().timeInActiveState(); diff --git a/test/api_test_app/apis/displayDemo.cpp b/test/api_test_app/apis/displayDemo.cpp index ae9201e..86bdf24 100644 --- a/test/api_test_app/apis/displayDemo.cpp +++ b/test/api_test_app/apis/displayDemo.cpp @@ -28,6 +28,7 @@ using namespace Firebolt::Display; DisplayDemo::DisplayDemo() : DemoBase("Display") { + methods_.push_back("Display.edid"); methods_.push_back("Display.maxResolution"); methods_.push_back("Display.size"); } @@ -35,7 +36,15 @@ DisplayDemo::DisplayDemo() void DisplayDemo::runOption(const std::string& method) { std::cout << "Running Display method: " << method << std::endl; - if (method == "Display.maxResolution") + if (method == "Display.edid") + { + auto r = Firebolt::IFireboltAccessor::Instance().DisplayInterface().edid(); + if (succeed(r)) + { + std::cout << "EDID: " << *r << std::endl; + } + } + else if (method == "Display.maxResolution") { auto r = Firebolt::IFireboltAccessor::Instance().DisplayInterface().maxResolution(); if (succeed(r))