From af1981731a59217935aab2441ad3ef14cf92ea7d Mon Sep 17 00:00:00 2001 From: Damien Cavanagh Date: Thu, 22 Jan 2026 15:25:38 +0000 Subject: [PATCH 1/3] cpp_test first commit --- CMakeLists.txt | 2 + test/cpp_test/.vscode/launch.json | 37 ++++++ test/cpp_test/CMakeLists.txt | 54 ++++++++ test/cpp_test/cpp/accessibilityDemo.cpp | 84 ++++++++++++ test/cpp_test/cpp/accessibilityDemo.h | 31 +++++ test/cpp_test/cpp/advertisingDemo.cpp | 54 ++++++++ test/cpp_test/cpp/advertisingDemo.h | 31 +++++ test/cpp_test/cpp/chooseInterface.cpp | 97 ++++++++++++++ test/cpp_test/cpp/chooseInterface.h | 35 +++++ test/cpp_test/cpp/deviceDemo.cpp | 86 ++++++++++++ test/cpp_test/cpp/deviceDemo.h | 31 +++++ test/cpp_test/cpp/displayDemo.cpp | 43 ++++++ test/cpp_test/cpp/displayDemo.h | 11 ++ test/cpp_test/cpp/firebolt-open-rpc.json.in | 4 + test/cpp_test/cpp/fireboltdemo.cpp | 138 +++++++++++++++++++ test/cpp_test/cpp/fireboltdemo.h | 98 ++++++++++++++ test/cpp_test/cpp/lifecycleDemo.cpp | 136 +++++++++++++++++++ test/cpp_test/cpp/lifecycleDemo.h | 36 +++++ test/cpp_test/cpp/localizationDemo.cpp | 71 ++++++++++ test/cpp_test/cpp/localizationDemo.h | 31 +++++ test/cpp_test/cpp/outputstream.h | 54 ++++++++ test/cpp_test/cpp/presentationDemo.cpp | 69 ++++++++++ test/cpp_test/cpp/presentationDemo.h | 34 +++++ test/cpp_test/cpp/statsDemo.cpp | 53 ++++++++ test/cpp_test/cpp/statsDemo.h | 31 +++++ test/cpp_test/cpp/utils.cpp | 139 ++++++++++++++++++++ test/cpp_test/cpp/utils.h | 45 +++++++ test/cpp_test/main.cpp | 111 ++++++++++++++++ 28 files changed, 1646 insertions(+) create mode 100644 test/cpp_test/.vscode/launch.json create mode 100644 test/cpp_test/CMakeLists.txt create mode 100644 test/cpp_test/cpp/accessibilityDemo.cpp create mode 100644 test/cpp_test/cpp/accessibilityDemo.h create mode 100644 test/cpp_test/cpp/advertisingDemo.cpp create mode 100644 test/cpp_test/cpp/advertisingDemo.h create mode 100644 test/cpp_test/cpp/chooseInterface.cpp create mode 100644 test/cpp_test/cpp/chooseInterface.h create mode 100644 test/cpp_test/cpp/deviceDemo.cpp create mode 100644 test/cpp_test/cpp/deviceDemo.h create mode 100644 test/cpp_test/cpp/displayDemo.cpp create mode 100644 test/cpp_test/cpp/displayDemo.h create mode 100644 test/cpp_test/cpp/firebolt-open-rpc.json.in create mode 100644 test/cpp_test/cpp/fireboltdemo.cpp create mode 100644 test/cpp_test/cpp/fireboltdemo.h create mode 100644 test/cpp_test/cpp/lifecycleDemo.cpp create mode 100644 test/cpp_test/cpp/lifecycleDemo.h create mode 100644 test/cpp_test/cpp/localizationDemo.cpp create mode 100644 test/cpp_test/cpp/localizationDemo.h create mode 100644 test/cpp_test/cpp/outputstream.h create mode 100644 test/cpp_test/cpp/presentationDemo.cpp create mode 100644 test/cpp_test/cpp/presentationDemo.h create mode 100644 test/cpp_test/cpp/statsDemo.cpp create mode 100644 test/cpp_test/cpp/statsDemo.h create mode 100644 test/cpp_test/cpp/utils.cpp create mode 100644 test/cpp_test/cpp/utils.h create mode 100644 test/cpp_test/main.cpp diff --git a/CMakeLists.txt b/CMakeLists.txt index 14008c9..8b9589f 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -91,8 +91,10 @@ add_subdirectory(src) if (ENABLE_DEMO_APP) add_subdirectory(demo) + add_subdirectory(test/cpp_test) #for now endif() if (ENABLE_TESTS) add_subdirectory(test) endif() + diff --git a/test/cpp_test/.vscode/launch.json b/test/cpp_test/.vscode/launch.json new file mode 100644 index 0000000..ea2c49e --- /dev/null +++ b/test/cpp_test/.vscode/launch.json @@ -0,0 +1,37 @@ +{ + "version": "0.2.0", + "configurations": [ + { + "name": "Debug cpp_test", + "type": "cppdbg", + "request": "launch", + "program": "${workspaceFolder}/build/cpp_test", + "args": [], + "stopAtEntry": false, + "cwd": "${workspaceFolder}", + "environment": [], + "externalConsole": false, + "MIMode": "gdb", + "setupCommands": [ + { + "description": "Enable pretty-printing for gdb", + "text": "-enable-pretty-printing", + "ignoreFailures": true + }, + { + "description": "Add FireboltTransport source", + "text": "directory /home/damien/FIREBOLT_RDKCENTRAL2/firebolt-native-transport/src", + "ignoreFailures": false + } + ], + "environment": [ + { + "name": "LD_LIBRARY_PATH", + "value": "/home/damien/FIREBOLT_RDKCENTRAL2/sysroot/usr/lib:${env:LD_LIBRARY_PATH}" + } + ], + "miDebuggerPath": "/usr/bin/gdb", + + } + ] +} \ No newline at end of file diff --git a/test/cpp_test/CMakeLists.txt b/test/cpp_test/CMakeLists.txt new file mode 100644 index 0000000..3a5a408 --- /dev/null +++ b/test/cpp_test/CMakeLists.txt @@ -0,0 +1,54 @@ +cmake_minimum_required(VERSION 3.10) +project(cpp_test) + +set(CMAKE_CXX_STANDARD 17) + +add_executable(cpp_test + main.cpp + cpp/advertisingDemo.cpp + cpp/accessibilityDemo.cpp + cpp/chooseInterface.cpp + cpp/deviceDemo.cpp + cpp/displayDemo.cpp + cpp/fireboltdemo.cpp + cpp/lifecycleDemo.cpp + cpp/localizationDemo.cpp + cpp/presentationDemo.cpp + cpp/statsDemo.cpp + cpp/utils.cpp +) + +list(APPEND CMAKE_PREFIX_PATH ${SYSROOT_PATH}) + +find_package(FireboltTransport) +find_package(nlohmann_json REQUIRED) +find_package(nlohmann_json_schema_validator REQUIRED) +find_package(CURL REQUIRED) + +# 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 +) + +# Make sure your target can find the generated header +target_include_directories(cpp_test PRIVATE ${CMAKE_BINARY_DIR}/generated) + +target_include_directories(cpp_test PRIVATE + $ + $ + $ + $ +) + +add_compile_definitions(UT_OPEN_RPC_FILE="firebolt-open-rpc.json") + +target_link_libraries(cpp_test + FireboltClient + FireboltTransport::FireboltTransport + nlohmann_json::nlohmann_json + nlohmann_json_schema_validator::validator + CURL::libcurl +) \ No newline at end of file diff --git a/test/cpp_test/cpp/accessibilityDemo.cpp b/test/cpp_test/cpp/accessibilityDemo.cpp new file mode 100644 index 0000000..5792e01 --- /dev/null +++ b/test/cpp_test/cpp/accessibilityDemo.cpp @@ -0,0 +1,84 @@ +/** + * 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 "accessibilityDemo.h" +#include +#include +#include + +#include "json_types/jsondata_device_types.h" + +#include "outputstream.h" +extern OutputStream gOutput; + +using namespace Firebolt; +using namespace Firebolt::Accessibility; + +AccessibilityDemo::AccessibilityDemo() + : IFireboltDemo() +{ + methodsFromRpc("Accessibility"); +} + +void AccessibilityDemo::runOption(const int index) +{ + std::string key = names_[index]; + + outStream_ << "Running Accessibility method: " << key << std::endl; + + if (key == "Accessibility.closedCaptionsSettings") + { + Result r = + Firebolt::IFireboltAccessor::Instance().AccessibilityInterface().closedCaptionsSettings(); + if (validateResult(r)) + { + ClosedCaptionsSettings settings = r.value(); + gOutput << "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(); + gOutput << "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(); + + gOutput << "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(); + gOutput << "Voice Guidance Settings - Enabled: " << (settings.enabled ? "true" : "false") + << ", Rate: " << settings.rate << std::endl; + } + } +} \ No newline at end of file diff --git a/test/cpp_test/cpp/accessibilityDemo.h b/test/cpp_test/cpp/accessibilityDemo.h new file mode 100644 index 0000000..a0394bf --- /dev/null +++ b/test/cpp_test/cpp/accessibilityDemo.h @@ -0,0 +1,31 @@ +/** + * 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 "fireboltdemo.h" + +class AccessibilityDemo : public IFireboltDemo +{ +public: + AccessibilityDemo(); + ~AccessibilityDemo() = default; + void runOption(const int index); +}; diff --git a/test/cpp_test/cpp/advertisingDemo.cpp b/test/cpp_test/cpp/advertisingDemo.cpp new file mode 100644 index 0000000..cec1570 --- /dev/null +++ b/test/cpp_test/cpp/advertisingDemo.cpp @@ -0,0 +1,54 @@ +/** + * 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 "advertisingDemo.h" +#include +#include +#include + +#include "outputstream.h" +extern OutputStream gOutput; + +// #include "json_types/jsondata_device_types.h" + +using namespace Firebolt; +using namespace Firebolt::Advertising; + +AdvertisingDemo::AdvertisingDemo() + : IFireboltDemo() +{ + methodsFromRpc("Advertising"); +} + +void AdvertisingDemo::runOption(const int index) +{ + std::string key = names_[index]; + + if (key == "Advertising.advertisingId") + { + Result result = Firebolt::IFireboltAccessor::Instance().AdvertisingInterface().advertisingId(); + if (validateResult(result)) + { + Ifa ifa = result.value(); + gOutput << "IFA: " << ifa.ifa << std::endl; + gOutput << "IFA Type: " << ifa.ifa_type << std::endl; + gOutput << "LMT: " << ifa.lmt << std::endl; + } + } +} diff --git a/test/cpp_test/cpp/advertisingDemo.h b/test/cpp_test/cpp/advertisingDemo.h new file mode 100644 index 0000000..009e57a --- /dev/null +++ b/test/cpp_test/cpp/advertisingDemo.h @@ -0,0 +1,31 @@ +/** + * 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 "fireboltdemo.h" + +class AdvertisingDemo : public IFireboltDemo +{ +public: + AdvertisingDemo(); + ~AdvertisingDemo() = default; + void runOption(const int index); +}; diff --git a/test/cpp_test/cpp/chooseInterface.cpp b/test/cpp_test/cpp/chooseInterface.cpp new file mode 100644 index 0000000..1295c5d --- /dev/null +++ b/test/cpp_test/cpp/chooseInterface.cpp @@ -0,0 +1,97 @@ +/** + * 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 "chooseInterface.h" +#include "fireboltdemo.h" + +#include "accessibilityDemo.h" +#include "advertisingDemo.h" +#include "deviceDemo.h" +#include "displayDemo.h" +#include "lifecycleDemo.h" +#include "localizationDemo.h" +#include "presentationDemo.h" +#include "statsDemo.h" + +#include + +#include "outputstream.h" +extern OutputStream gOutput; + +ChooseInterface::ChooseInterface() + : IFireboltDemo() +{ + for (auto& [key, value] : json_["info"]["x-module-descriptions"].items()) + { + std::cout << key << ": " << value << std::endl; + if (key != "Internal") + { + names_.push_back(key); + descriptions_.push_back(value.get()); + } + } + + interfaces = {new AccessibilityDemo(), new AdvertisingDemo(), new DeviceDemo(), new DisplayDemo(), + new LifecycleDemo(), new LocalizationDemo(), new PresentationDemo(), new StatsDemo()}; +} + +ChooseInterface::~ChooseInterface() +{ + for (auto interfacePtr : interfaces) + { + delete interfacePtr; + } +} + +void ChooseInterface::runOption(const int index) +{ + IFireboltDemo* selectedInterface = interfaces[index]; + gOutput << "Running interface: " << names_[index] << 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) + { + IFireboltDemo* selectedInterface = interfaces[i]; + if (selectedInterface == nullptr) + { + continue; // Skip unimplemented interfaces + } + gOutput << "Auto-running interface: " << names_[i] << std::endl; + + // Assuming each interface has a predefined set of methods to run + for (int j = 0; j < selectedInterface->listSize(); ++j) + { + gOutput << "Auto-running method: " << selectedInterface->methods()[j] << std::endl; + selectedInterface->runOption(j); + } + } +} diff --git a/test/cpp_test/cpp/chooseInterface.h b/test/cpp_test/cpp/chooseInterface.h new file mode 100644 index 0000000..a639412 --- /dev/null +++ b/test/cpp_test/cpp/chooseInterface.h @@ -0,0 +1,35 @@ +/** + * 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 "fireboltdemo.h" + +class ChooseInterface : public IFireboltDemo +{ +public: + ChooseInterface(); + ~ChooseInterface(); + std::vector methods() const { return names_; } + + void runOption(const int index); + void autoRun(); + +private: + std::vector interfaces; +}; diff --git a/test/cpp_test/cpp/deviceDemo.cpp b/test/cpp_test/cpp/deviceDemo.cpp new file mode 100644 index 0000000..470264f --- /dev/null +++ b/test/cpp_test/cpp/deviceDemo.cpp @@ -0,0 +1,86 @@ +/** + * 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 "deviceDemo.h" +#include +#include +#include + +#include "json_types/jsondata_device_types.h" + +#include "outputstream.h" +extern OutputStream gOutput; + +using namespace Firebolt; +using namespace Firebolt::Device; + +DeviceDemo::DeviceDemo() + : IFireboltDemo() +{ + methodsFromRpc("Device"); +} + +void DeviceDemo::runOption(const int index) +{ + std::string key = names_[index]; + + outStream_ << "Running Device method: " << key << std::endl; + + if (key == "Device.class") + { + Result r = Firebolt::IFireboltAccessor::Instance().DeviceInterface().deviceClass(); + if (validateResult(r)) + { + gOutput << "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)) + { + gOutput << "Device Uptime (seconds): " << r.value() << std::endl; + } + } + else if (key == "Device.timeInActiveState") + { + Result r = Firebolt::IFireboltAccessor::Instance().DeviceInterface().timeInActiveState(); + if (validateResult(r)) + { + gOutput << "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)) + { + gOutput << "Device Chipset ID: " << r.value() << std::endl; + } + } + else if (key == "Device.uid") + { + Result r = Firebolt::IFireboltAccessor::Instance().DeviceInterface().uid(); + if (validateResult(r)) + { + gOutput << "Device UID: " << r.value() << std::endl; + } + } +} diff --git a/test/cpp_test/cpp/deviceDemo.h b/test/cpp_test/cpp/deviceDemo.h new file mode 100644 index 0000000..e035dd1 --- /dev/null +++ b/test/cpp_test/cpp/deviceDemo.h @@ -0,0 +1,31 @@ +/** + * 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 "fireboltdemo.h" + +class DeviceDemo : public IFireboltDemo +{ +public: + DeviceDemo(); + ~DeviceDemo() = default; + void runOption(const int index); +}; diff --git a/test/cpp_test/cpp/displayDemo.cpp b/test/cpp_test/cpp/displayDemo.cpp new file mode 100644 index 0000000..cc412a6 --- /dev/null +++ b/test/cpp_test/cpp/displayDemo.cpp @@ -0,0 +1,43 @@ +#include "displayDemo.h" +#include +#include +#include + +#include "json_types/jsondata_device_types.h" + +#include "outputstream.h" +extern OutputStream gOutput; + +using namespace Firebolt; +using namespace Firebolt::Display; + +DisplayDemo::DisplayDemo() + : IFireboltDemo() +{ + methodsFromRpc("Display"); +} + +void DisplayDemo::runOption(const int index) +{ + std::string key = names_[index]; + + outStream_ << "Running Display method: " << key << std::endl; + if (key == "Display.maxResolution") + { + Result r = Firebolt::IFireboltAccessor::Instance().DisplayInterface().maxResolution(); + if (validateResult(r)) + { + DisplaySize res = r.value(); + gOutput << "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(); + gOutput << "Display Size - Width: " << size.width << ", Height: " << size.height << std::endl; + } + } +} diff --git a/test/cpp_test/cpp/displayDemo.h b/test/cpp_test/cpp/displayDemo.h new file mode 100644 index 0000000..3c96e24 --- /dev/null +++ b/test/cpp_test/cpp/displayDemo.h @@ -0,0 +1,11 @@ +#include +#include +#include "fireboltdemo.h" + +class DisplayDemo : public IFireboltDemo +{ +public: + DisplayDemo(); + ~DisplayDemo() = default; + void runOption(const int index); +}; diff --git a/test/cpp_test/cpp/firebolt-open-rpc.json.in b/test/cpp_test/cpp/firebolt-open-rpc.json.in new file mode 100644 index 0000000..8aad328 --- /dev/null +++ b/test/cpp_test/cpp/firebolt-open-rpc.json.in @@ -0,0 +1,4 @@ +#pragma once +#include + +constexpr std::string_view JSON_DATA = R"(@JSON_CONTENT@)"; \ No newline at end of file diff --git a/test/cpp_test/cpp/fireboltdemo.cpp b/test/cpp_test/cpp/fireboltdemo.cpp new file mode 100644 index 0000000..e188e52 --- /dev/null +++ b/test/cpp_test/cpp/fireboltdemo.cpp @@ -0,0 +1,138 @@ +/** + * 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 "fireboltdemo.h" +#include "firebolt-open-rpc_json.h" +#include "utils.h" +#include +#include +#include +#include + +#include "outputstream.h" +extern OutputStream gOutput; + +nlohmann::json IFireboltDemo::json_; + +#ifndef UT_OPEN_RPC_FILE +#define UT_OPEN_RPC_FILE "firebolt-open-rpc.json" +#endif + +IFireboltDemo::IFireboltDemo() +{ + loadRpc(); +} + +void IFireboltDemo::paramFromConsole(const std::string& name, const std::string& def, std::string& value) +{ + gOutput << "Enter " << name << " (default: " << def << "): "; + std::string input; + std::getline(std::cin, input); + if (input.empty()) + { + value = def; + } + else + { + value = input; + } +} + +int getOption(int n) +{ + std::string input; + + while (true) + { + std::cout << "Select option or 'q' to go back: "; + std::cin >> input; + + // Check if user wants to quit + if (input.length() == 1 && std::tolower(input[0]) == 'q') + { + return -1; + } + + // Try to convert to integer + try + { + int num = std::stoi(input); + + // Check if number is in valid range + if (num >= 0 && num <= n) + { + return num; + } + else + { + gOutput << "Please enter a number between 0 and " << n << "." << 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 0 and " << n << "." << std::endl; + } + } +} + +int IFireboltDemo::chooseFromList(const std::vector& options, const std::string& prompt) +{ + std::cout << 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)); + + return choice; +} + +int IFireboltDemo::chooseOption() +{ + return chooseFromList(names_, "Choose a method to run:"); +} + +void IFireboltDemo::loadRpc() +{ + json_ = nlohmann::json::parse(JSON_DATA); +} + +std::vector IFireboltDemo::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) + { + + names_.push_back(method["name"]); + descriptions_.push_back(method["summary"]); + gOutput << "Found method: " << names_.back() << ":" << descriptions_.back() << std::endl; + } + } + + return methodNames; +} diff --git a/test/cpp_test/cpp/fireboltdemo.h b/test/cpp_test/cpp/fireboltdemo.h new file mode 100644 index 0000000..61969fe --- /dev/null +++ b/test/cpp_test/cpp/fireboltdemo.h @@ -0,0 +1,98 @@ +/** + * 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 "firebolt/firebolt.h" +#include "outputstream.h" +#include +#include +#include +#include + +class IFireboltDemo +{ +public: + IFireboltDemo(); + virtual ~IFireboltDemo() = default; + + int chooseOption(); + virtual void runOption(const int index) = 0; + int listSize() const { return static_cast(names_.size()); } + std::vector methods() const { return names_; } + +protected: + void paramFromConsole(const std::string& name, const std::string& def, std::string& value); + int chooseFromList(const std::vector& options, const std::string& prompt); + + 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) + { + std::vector options; + for (const auto& pair : enumType) + { + options.push_back(pair.first); + std::cout << "Option: " << pair.first << std::endl; + } + + int choice = chooseFromList(options, prompt); + + 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 {}; + } + + std::vector methodsFromRpc(const std::string& interfaceName); + + static nlohmann::json json_; + + std::vector names_; + std::vector descriptions_; + + OutputStream outStream_; + +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/cpp_test/cpp/lifecycleDemo.cpp b/test/cpp_test/cpp/lifecycleDemo.cpp new file mode 100644 index 0000000..edfb05b --- /dev/null +++ b/test/cpp_test/cpp/lifecycleDemo.cpp @@ -0,0 +1,136 @@ +/** + * 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 "lifecycleDemo.h" +#include "json_types/jsondata_lifecycle_types.h" +#include "utils.h" +#include +#include +#include + +using namespace Firebolt; +using namespace Firebolt::Lifecycle; + +#include "outputstream.h" +extern OutputStream gOutput; +extern bool gAutoRun; + +LifecycleDemo::LifecycleDemo() + : IFireboltDemo() +{ + methodsFromRpc("Lifecycle2"); + names_.push_back("Trigger lifecycle state change"); + descriptions_.push_back("Simulate a lifecycle state change event from the platform."); + currentState_ = LifecycleState::INITIALIZING; +} + +void LifecycleDemo::runOption(const int index) +{ + std::string key = names_[index]; + + if (key == "Lifecycle2.close") + { + CloseType type = CloseType::DEACTIVATE; + if (gAutoRun) + { + gOutput << "Auto-selecting 'deactivate' for Close Type." << std::endl; + } + else + { + type = chooseEnumFromList(Firebolt::Lifecycle::JsonData::CloseReasonEnum, "Choose Close Type!!:"); + } + + Result r = Firebolt::IFireboltAccessor::Instance().LifecycleInterface().close(type); + validateResult(r); + } + else if (key == "Lifecycle2.state") + { + Result r = Firebolt::IFireboltAccessor::Instance().LifecycleInterface().state(); + if (validateResult(r)) + { + currentState_ = r.value(); + printCurrentState(); + } + } + else if (key == "Lifecycle2.onStateChanged") + { + auto callback = [&](const std::vector& changes) + { + gOutput << "Lifecycle State Changes received:" << std::endl; + for (const auto& change : changes) + { + gOutput << " From " + << Firebolt::JSON::toString(Firebolt::Lifecycle::JsonData::LifecycleStateEnum, change.oldState) + << " to " + << Firebolt::JSON::toString(Firebolt::Lifecycle::JsonData::LifecycleStateEnum, change.newState) + << std::endl; + currentState_ = change.newState; + } + }; + Result r = + Firebolt::IFireboltAccessor::Instance().LifecycleInterface().subscribeOnStateChanged(std::move(callback)); + if (validateResult(r)) + { + gOutput << "Subscribed to Lifecycle state changes with Subscription ID: " << r.value() << std::endl; + } + } + else if (key == "Trigger lifecycle state change") + { + triggerLifecycleStateChange(); + } + else if (key == "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); + } + else if (key == "Lifecycle2.unsubscribeAll") + { + Firebolt::IFireboltAccessor::Instance().LifecycleInterface().unsubscribeAll(); + gOutput << "Unsubscribed from all Lifecycle subscriptions." << std::endl; + } +} + +void LifecycleDemo::triggerLifecycleStateChange() +{ + LifecycleState newState = LifecycleState::ACTIVE; + if (gAutoRun) + { + gOutput << "Auto-selecting 'active' for new Lifecycle State." << std::endl; + } + else + { + newState = chooseEnumFromList(Firebolt::Lifecycle::JsonData::LifecycleStateEnum, + "Choose new Lifecycle State to simulate:"); + } + + nlohmann::json params; + params["value"] = nlohmann::json::array(); + params["value"].push_back( + {{"newState", Firebolt::JSON::toString(Firebolt::Lifecycle::JsonData::LifecycleStateEnum, newState)}, + {"oldState", Firebolt::JSON::toString(Firebolt::Lifecycle::JsonData::LifecycleStateEnum, currentState_)}}); + triggerEvent("Lifecycle2.onStateChanged", params.dump()); +} + +void LifecycleDemo::printCurrentState() +{ + gOutput << "Current Lifecycle State: " + << stringFromEnum(Firebolt::Lifecycle::JsonData::LifecycleStateEnum, currentState_) << std::endl; +} \ No newline at end of file diff --git a/test/cpp_test/cpp/lifecycleDemo.h b/test/cpp_test/cpp/lifecycleDemo.h new file mode 100644 index 0000000..9f970e2 --- /dev/null +++ b/test/cpp_test/cpp/lifecycleDemo.h @@ -0,0 +1,36 @@ +/** + * 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 "fireboltdemo.h" + +class LifecycleDemo : public IFireboltDemo +{ +public: + LifecycleDemo(); + ~LifecycleDemo() = default; + void runOption(const int index); + +private: + void triggerLifecycleStateChange(); + void printCurrentState(); + Firebolt::Lifecycle::LifecycleState currentState_; +}; diff --git a/test/cpp_test/cpp/localizationDemo.cpp b/test/cpp_test/cpp/localizationDemo.cpp new file mode 100644 index 0000000..f896237 --- /dev/null +++ b/test/cpp_test/cpp/localizationDemo.cpp @@ -0,0 +1,71 @@ +/** + * 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 "localizationDemo.h" +#include +#include +#include + +#include "outputstream.h" +extern OutputStream gOutput; + +using namespace Firebolt; +using namespace Firebolt::Localization; + +LocalizationDemo::LocalizationDemo() + : IFireboltDemo() +{ + methodsFromRpc("Localization"); +} + +void LocalizationDemo::runOption(const int index) +{ + std::string key = names_[index]; + + if (key == "Localization.country") + { + Result result = Firebolt::IFireboltAccessor::Instance().LocalizationInterface().country(); + if (validateResult(result)) + { + gOutput << "Country: " << result.value() << std::endl; + } + } + else if (key == "Localization.preferredAudioLanguages") + { + Result> result = + Firebolt::IFireboltAccessor::Instance().LocalizationInterface().preferredAudioLanguages(); + if (validateResult(result)) + { + gOutput << "Preferred Audio Languages: "; + for (const auto& lang : result.value()) + { + gOutput << lang << " "; + } + gOutput << std::endl; + } + } + else if (key == "Localization.presentationLanguage") + { + Result result = + Firebolt::IFireboltAccessor::Instance().LocalizationInterface().presentationLanguage(); + if (validateResult(result)) + { + gOutput << "Presentation Language: " << result.value() << std::endl; + } + } +} diff --git a/test/cpp_test/cpp/localizationDemo.h b/test/cpp_test/cpp/localizationDemo.h new file mode 100644 index 0000000..bdcde26 --- /dev/null +++ b/test/cpp_test/cpp/localizationDemo.h @@ -0,0 +1,31 @@ +/** + * 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 "fireboltdemo.h" + +class LocalizationDemo : public IFireboltDemo +{ +public: + LocalizationDemo(); + ~LocalizationDemo() = default; + void runOption(const int index); +}; diff --git a/test/cpp_test/cpp/outputstream.h b/test/cpp_test/cpp/outputstream.h new file mode 100644 index 0000000..fc0da7a --- /dev/null +++ b/test/cpp_test/cpp/outputstream.h @@ -0,0 +1,54 @@ +/** + * 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 OutputStream +{ + std::unique_ptr file_; + std::ostream* out_; + +public: + OutputStream() + : out_(&std::cout) + { + } + OutputStream(const std::string& filename) + : file_(std::make_unique(filename)), + out_(file_.get()) + { + } + + template OutputStream& operator<<(const T& value) + { + (*out_) << value; + return *this; + } + + // Support for std::endl and other manipulators + OutputStream& operator<<(std::ostream& (*manip)(std::ostream&)) + { + (*out_) << manip; + return *this; + } +}; \ No newline at end of file diff --git a/test/cpp_test/cpp/presentationDemo.cpp b/test/cpp_test/cpp/presentationDemo.cpp new file mode 100644 index 0000000..9cc19b5 --- /dev/null +++ b/test/cpp_test/cpp/presentationDemo.cpp @@ -0,0 +1,69 @@ +/** + * 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 "presentationDemo.h" +#include +#include +#include + +#include "utils.h" + +#include "outputstream.h" +extern OutputStream gOutput; + +using namespace Firebolt; +using namespace Firebolt::Presentation; + +PresentationDemo::PresentationDemo() + : IFireboltDemo() +{ + methodsFromRpc("Presentation"); + names_.push_back("Trigger presentation state change"); + descriptions_.push_back("Simulate a presentation state change event from the platform."); +} + +void PresentationDemo::runOption(const int index) +{ + std::string key = names_[index]; + + if (key == "Presentation.focused") + { + Result r = Firebolt::IFireboltAccessor::Instance().PresentationInterface().focused(); + if (validateResult(r)) + { + gOutput << "Presentation focused: " << (r.value() ? "true" : "false") << std::endl; + } + } + else if (key == "Presentation.onFocusedChanged") + { + auto subscriptionResult = + Firebolt::IFireboltAccessor::Instance().PresentationInterface().subscribeOnFocusedChanged( + [&](bool focused) + { gOutput << "Presentation focus changed: " << (focused ? "true" : "false") << std::endl; }); + if (validateResult(subscriptionResult)) + { + SubscriptionId subId = subscriptionResult.value(); + gOutput << "Subscribed to Presentation.onFocusedChanged with SubscriptionId: " << subId << std::endl; + } + } +} + +void PresentationDemo::triggerPresentationStateChange() +{ + triggerEvent("Presentation.onFocusedChanged", R"({"focused": true})"); +} \ No newline at end of file diff --git a/test/cpp_test/cpp/presentationDemo.h b/test/cpp_test/cpp/presentationDemo.h new file mode 100644 index 0000000..83bcb01 --- /dev/null +++ b/test/cpp_test/cpp/presentationDemo.h @@ -0,0 +1,34 @@ +/** + * 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 "fireboltdemo.h" + +class PresentationDemo : public IFireboltDemo +{ +public: + PresentationDemo(); + ~PresentationDemo() = default; + void runOption(const int index); + +private: + void triggerPresentationStateChange(); +}; diff --git a/test/cpp_test/cpp/statsDemo.cpp b/test/cpp_test/cpp/statsDemo.cpp new file mode 100644 index 0000000..f0f1b75 --- /dev/null +++ b/test/cpp_test/cpp/statsDemo.cpp @@ -0,0 +1,53 @@ +/** + * 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 "statsDemo.h" +#include +#include +#include + +#include "json_types/jsondata_device_types.h" + +#include "outputstream.h" +extern OutputStream gOutput; + +using namespace Firebolt; +using namespace Firebolt::Stats; + +StatsDemo::StatsDemo() + : IFireboltDemo() +{ + methodsFromRpc("Stats"); +} + +void StatsDemo::runOption(const int index) +{ + std::string key = names_[index]; + + outStream_ << "Running Stats method: " << key << std::endl; + if (key == "Stats.memoryUsage") + { + Result r = Firebolt::IFireboltAccessor::Instance().StatsInterface().memoryUsage(); + if (validateResult(r)) + { + MemoryInfo memInfo = r.value(); + gOutput << "User Memory Used: " << memInfo.userMemoryUsed << " / " << memInfo.userMemoryLimit << std::endl; + gOutput << "GPU Memory Used: " << memInfo.gpuMemoryUsed << " / " << memInfo.gpuMemoryLimit << std::endl; + } + } +} diff --git a/test/cpp_test/cpp/statsDemo.h b/test/cpp_test/cpp/statsDemo.h new file mode 100644 index 0000000..feb4147 --- /dev/null +++ b/test/cpp_test/cpp/statsDemo.h @@ -0,0 +1,31 @@ +/** + * 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 "fireboltdemo.h" + +class StatsDemo : public IFireboltDemo +{ +public: + StatsDemo(); + ~StatsDemo() = default; + void runOption(const int index); +}; diff --git a/test/cpp_test/cpp/utils.cpp b/test/cpp_test/cpp/utils.cpp new file mode 100644 index 0000000..d3a13a0 --- /dev/null +++ b/test/cpp_test/cpp/utils.cpp @@ -0,0 +1,139 @@ +/* + * If not stated otherwise in this file or this component's LICENSE file the + * following copyright and licenses apply: + * + * Copyright 2025 Sky UK + * + * 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. + */ + +#include "utils.h" + +#include +#include + +#include + +#include +#include +#include +#include + +#define FAIL() std::cout + +// curl http get helper function using +std::string httpGet(const std::string& url) +{ + CURL* curl = curl_easy_init(); + if (!curl) + return ""; + curl_easy_setopt(curl, CURLOPT_URL, url.c_str()); + + struct curl_slist* headers = nullptr; + headers = curl_slist_append(headers, "Content-Type: application/json"); + curl_easy_setopt(curl, CURLOPT_HTTPHEADER, headers); + + std::string response; + curl_easy_setopt( + curl, CURLOPT_WRITEFUNCTION, + +[](char* ptr, size_t size, size_t nmemb, std::string* data) + { + data->append(ptr, size * nmemb); + return size * nmemb; + }); + curl_easy_setopt(curl, CURLOPT_WRITEDATA, &response); + + CURLcode res = curl_easy_perform(curl); + curl_easy_cleanup(curl); + + return (res == CURLE_OK) ? response : ""; +} + +// curl http post helper function using +std::string httpPost(const std::string& url, const std::string& postData) +{ + CURL* curl = curl_easy_init(); + if (!curl) + return ""; + curl_easy_setopt(curl, CURLOPT_URL, url.c_str()); + curl_easy_setopt(curl, CURLOPT_POST, 1L); + curl_easy_setopt(curl, CURLOPT_POSTFIELDS, postData.c_str()); + curl_easy_setopt(curl, CURLOPT_POSTFIELDSIZE, postData.size()); + + struct curl_slist* headers = nullptr; + headers = curl_slist_append(headers, "Content-Type: application/json"); + curl_easy_setopt(curl, CURLOPT_HTTPHEADER, headers); + + std::string response; + curl_easy_setopt( + curl, CURLOPT_WRITEFUNCTION, + +[](char* ptr, size_t size, size_t nmemb, std::string* data) + { + data->append(ptr, size * nmemb); + return size * nmemb; + }); + curl_easy_setopt(curl, CURLOPT_WRITEDATA, &response); + + CURLcode res = curl_easy_perform(curl); + curl_easy_cleanup(curl); + + return (res == CURLE_OK) ? response : ""; +} + +void triggerRaw(const std::string& payload) +{ + httpPost("http://localhost:3333/api/v1/raw", payload); +} + +void triggerEvent(const std::string& method, const std::string& params) +{ + nlohmann::json eventMessage; + eventMessage["method"] = method; + eventMessage["result"] = nlohmann::json::parse(params); + + httpPost("http://localhost:3333/api/v1/event", eventMessage.dump()); +} + +void verifyEventSubscription(const Firebolt::Result& id) +{ + if (id) + { + std::cout << "Event Subscription is successful." << std::endl; + } + else + { + FAIL() << "Event Subscription failed. " + toError(id); + } +} +void verifyUnsubscribeResult(const Firebolt::Result& result) +{ + + if (result.error() == Firebolt::Error::None) + { + std::cout << "Unsubscribe success" << std::endl; + } + else + { + FAIL() << "Unsubscribe failed." + toError(result); + } +} +void verifyEventReceived(std::mutex& mtx, std::condition_variable& cv, bool& eventReceived) +{ + + // Wait for the event to be received or timeout after 5 seconds + std::unique_lock lock(mtx); + if (!cv.wait_for(lock, std::chrono::seconds(5), [&] { return eventReceived; })) + { + FAIL() << "Did not receive event within timeout"; + } +} diff --git a/test/cpp_test/cpp/utils.h b/test/cpp_test/cpp/utils.h new file mode 100644 index 0000000..0586900 --- /dev/null +++ b/test/cpp_test/cpp/utils.h @@ -0,0 +1,45 @@ +/* + * If not stated otherwise in this file or this component's LICENSE file the + * following copyright and licenses apply: + * + * Copyright 2025 Sky UK + * + * 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. + */ + +#pragma once + +#include +#include +#include +#include +#include + +std::string httpGet(const std::string& url); +std::string httpPost(const std::string& url, const std::string& postData); + +void triggerEvent(const std::string& method, const std::string& params); +void triggerRaw(const std::string& payload); + +void verifyEventSubscription(const Firebolt::Result& id); +void verifyUnsubscribeResult(const Firebolt::Result& result); +void verifyEventReceived(std::mutex& mtx, std::condition_variable& cv, bool& eventReceived); + +template inline std::string toError(const Firebolt::Result& result) +{ + if (result) + { + return ""; + } + return "Error: " + std::to_string(static_cast(result.error())); +} diff --git a/test/cpp_test/main.cpp b/test/cpp_test/main.cpp new file mode 100644 index 0000000..5240b14 --- /dev/null +++ b/test/cpp_test/main.cpp @@ -0,0 +1,111 @@ +#include +#include +#include +#include +#include + +#include "cpp/chooseInterface.h" + +#include "cpp/outputstream.h" + +OutputStream gOutput; + +bool gConnected = false; +bool gAutoRun = false; + +void connectionChanged(const bool connected, const Firebolt::Error error) +{ + std::cout << "Change in connection: connected: " << connected << " error: " << static_cast(error) << std::endl; + gConnected = connected; +} + +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 == false)) + { + + uint32_t sleepSlot = (waiting > SLEEPSLOT_TIME ? SLEEPSLOT_TIME : waiting); + // Right, lets sleep in slices of 100 ms + usleep(sleepSlot); + waiting -= sleepSlot; + } + return gConnected; +} + +int main(int argc, char** argv) +{ + gOutput = OutputStream("firebolt_test_output.txt"); + + gOutput << "Logging to file instead of console" << std::endl; + + // 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") + { + gAutoRun = true; + break; + } + } + + std::string url = "ws://127.0.0.1:9998"; + createFireboltInstance(url); + + std::this_thread::sleep_for(std::chrono::seconds(1)); + + // ::testing::InitGoogleTest(&argc, argv); + if (!waitOnConnectionReady()) + { + std::cout << "Test not able to connect with server..." << std::endl; + return -1; + } + + if (gAutoRun) + { + gOutput = OutputStream("firebolt_test_output.txt"); + ChooseInterface chooseInterface; + chooseInterface.autoRun(); + return 0; + } + + gOutput = OutputStream(); + + ChooseInterface chooseInterface; + + for (;;) + { + int interfaceIndex = chooseInterface.chooseOption(); + + if (interfaceIndex == -1) + { + break; // Exit the program + } + + chooseInterface.runOption(interfaceIndex); + } + + destroyFireboltInstance(); + + return 0; +} From b3e59ab034d549e4c1f9353b84a74cb4adab7ec9 Mon Sep 17 00:00:00 2001 From: Damien Cavanagh Date: Mon, 26 Jan 2026 13:55:49 +0000 Subject: [PATCH 2/3] CI --- .github/workflows/ci.yml | 54 ++++++++++++++++++++++++++++++++++++++++ 1 file changed, 54 insertions(+) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index c041dc4..00e2b31 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -249,3 +249,57 @@ jobs: --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/build/test/FireboltClientComponentTests + + cpp_demo_tests: + permissions: + contents: read + packages: read + needs: [build_docker] + runs-on: ubuntu-latest + steps: + - name: Log in to the Container registry + uses: docker/login-action@v3 + with: + registry: ghcr.io + username: ${{ github.actor }} + password: ${{ secrets.GITHUB_TOKEN }} + + - name: Checkout Code + uses: actions/checkout@v4 + with: + fetch-depth: 0 + + - name: Get version + run: | + VERSION=$(git describe --tags --dirty --match "v[0-9]*") + echo "VERSION=$VERSION" >> $GITHUB_ENV + echo "version: $VERSION" + + - name: Configure Project with Demo + run: | + docker run --rm --user "$(id -u):$(id -g)" -v ${{ github.workspace }}:/workspace ${{ needs.build_docker.outputs.image_tag }} \ + bash -c " \ + set -e \ + && cmake -B build -S . \ + -DCMAKE_BUILD_TYPE=Debug \ + -DENABLE_DEMO_APP=ON \ + " + + - name: Build Project with cpp_test + run: | + docker run --rm --user "$(id -u):$(id -g)" -v ${{ github.workspace }}:/workspace ${{ needs.build_docker.outputs.image_tag }} \ + bash -c " \ + set -e \ + && cmake --build build --parallel \ + " + + - name: Run cpp_test executable + run: | + chmod +x ${{ github.workspace }}/build/test/cpp_test/cpp_test + docker run --rm --user "$(id -u):$(id -g)" -v ${{ github.workspace }}:/workspace ${{ needs.build_docker.outputs.image_tag }} \ + bash -c " \ + set -e \ + && cd /workspace/build/test/cpp_test \ + && ./cpp_test \ + " + \ No newline at end of file From fdf50ba28735ba2f759d9693b46c58f67b32e896 Mon Sep 17 00:00:00 2001 From: Damien Cavanagh Date: Tue, 27 Jan 2026 17:34:55 +0000 Subject: [PATCH 3/3] PR comments --- test/cpp_test/.vscode/launch.json | 37 -------------------------- test/cpp_test/cpp/displayDemo.cpp | 18 +++++++++++++ test/cpp_test/cpp/displayDemo.h | 19 +++++++++++++ test/cpp_test/cpp/outputstream.h | 8 ++++++ test/cpp_test/cpp/presentationDemo.cpp | 4 ++- test/cpp_test/cpp/presentationDemo.h | 2 +- test/cpp_test/main.cpp | 20 +++++++++++++- 7 files changed, 68 insertions(+), 40 deletions(-) delete mode 100644 test/cpp_test/.vscode/launch.json diff --git a/test/cpp_test/.vscode/launch.json b/test/cpp_test/.vscode/launch.json deleted file mode 100644 index ea2c49e..0000000 --- a/test/cpp_test/.vscode/launch.json +++ /dev/null @@ -1,37 +0,0 @@ -{ - "version": "0.2.0", - "configurations": [ - { - "name": "Debug cpp_test", - "type": "cppdbg", - "request": "launch", - "program": "${workspaceFolder}/build/cpp_test", - "args": [], - "stopAtEntry": false, - "cwd": "${workspaceFolder}", - "environment": [], - "externalConsole": false, - "MIMode": "gdb", - "setupCommands": [ - { - "description": "Enable pretty-printing for gdb", - "text": "-enable-pretty-printing", - "ignoreFailures": true - }, - { - "description": "Add FireboltTransport source", - "text": "directory /home/damien/FIREBOLT_RDKCENTRAL2/firebolt-native-transport/src", - "ignoreFailures": false - } - ], - "environment": [ - { - "name": "LD_LIBRARY_PATH", - "value": "/home/damien/FIREBOLT_RDKCENTRAL2/sysroot/usr/lib:${env:LD_LIBRARY_PATH}" - } - ], - "miDebuggerPath": "/usr/bin/gdb", - - } - ] -} \ No newline at end of file diff --git a/test/cpp_test/cpp/displayDemo.cpp b/test/cpp_test/cpp/displayDemo.cpp index cc412a6..f16d5af 100644 --- a/test/cpp_test/cpp/displayDemo.cpp +++ b/test/cpp_test/cpp/displayDemo.cpp @@ -1,3 +1,21 @@ +/** + * 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 "displayDemo.h" #include #include diff --git a/test/cpp_test/cpp/displayDemo.h b/test/cpp_test/cpp/displayDemo.h index 3c96e24..7139bc1 100644 --- a/test/cpp_test/cpp/displayDemo.h +++ b/test/cpp_test/cpp/displayDemo.h @@ -1,3 +1,22 @@ +/** + * 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 "fireboltdemo.h" diff --git a/test/cpp_test/cpp/outputstream.h b/test/cpp_test/cpp/outputstream.h index fc0da7a..791bbe0 100644 --- a/test/cpp_test/cpp/outputstream.h +++ b/test/cpp_test/cpp/outputstream.h @@ -39,6 +39,14 @@ class OutputStream { } + // Delete copy operations since we have a unique_ptr member + OutputStream(const OutputStream&) = delete; + OutputStream& operator=(const OutputStream&) = delete; + + // Allow move operations (optional, but good practice) + OutputStream(OutputStream&&) = default; + OutputStream& operator=(OutputStream&&) = default; + template OutputStream& operator<<(const T& value) { (*out_) << value; diff --git a/test/cpp_test/cpp/presentationDemo.cpp b/test/cpp_test/cpp/presentationDemo.cpp index 9cc19b5..3d39508 100644 --- a/test/cpp_test/cpp/presentationDemo.cpp +++ b/test/cpp_test/cpp/presentationDemo.cpp @@ -63,7 +63,9 @@ void PresentationDemo::runOption(const int index) } } +/* void PresentationDemo::triggerPresentationStateChange() { triggerEvent("Presentation.onFocusedChanged", R"({"focused": true})"); -} \ No newline at end of file +} +*/ \ No newline at end of file diff --git a/test/cpp_test/cpp/presentationDemo.h b/test/cpp_test/cpp/presentationDemo.h index 83bcb01..c9e5b82 100644 --- a/test/cpp_test/cpp/presentationDemo.h +++ b/test/cpp_test/cpp/presentationDemo.h @@ -30,5 +30,5 @@ class PresentationDemo : public IFireboltDemo void runOption(const int index); private: - void triggerPresentationStateChange(); + // void triggerPresentationStateChange(); }; diff --git a/test/cpp_test/main.cpp b/test/cpp_test/main.cpp index 5240b14..c7f5221 100644 --- a/test/cpp_test/main.cpp +++ b/test/cpp_test/main.cpp @@ -1,3 +1,21 @@ +/** + * 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 #include #include @@ -46,7 +64,7 @@ bool waitOnConnectionReady() uint32_t sleepSlot = (waiting > SLEEPSLOT_TIME ? SLEEPSLOT_TIME : waiting); // Right, lets sleep in slices of 100 ms - usleep(sleepSlot); + std::this_thread::sleep_for(std::chrono::milliseconds(sleepSlot)); waiting -= sleepSlot; } return gConnected;