From f58d8b9919a94f4754d54ac8adfb7cfd0d69630a Mon Sep 17 00:00:00 2001 From: joyal-06 Date: Fri, 20 Jun 2025 11:25:10 +0530 Subject: [PATCH 1/9] gh #2: Generate_L1_tests --- subtec/subtecparser/TextStyleAttributes.h | 214 ++- subtec/subtecparser/TtmlSubtecParser.hpp | 153 +- .../test/test_l1_TextStyleAttributes.cpp | 1012 ++++++++++ .../test/test_l1_TtmlSubtecParser.cpp | 1668 +++++++++++++++++ 4 files changed, 2971 insertions(+), 76 deletions(-) mode change 100644 => 100755 subtec/subtecparser/TextStyleAttributes.h mode change 100644 => 100755 subtec/subtecparser/TtmlSubtecParser.hpp create mode 100755 subtec/subtecparser/test/test_l1_TextStyleAttributes.cpp create mode 100755 subtec/subtecparser/test/test_l1_TtmlSubtecParser.cpp diff --git a/subtec/subtecparser/TextStyleAttributes.h b/subtec/subtecparser/TextStyleAttributes.h old mode 100644 new mode 100755 index 0596f17..f02253c --- a/subtec/subtecparser/TextStyleAttributes.h +++ b/subtec/subtecparser/TextStyleAttributes.h @@ -83,6 +83,14 @@ class TextStyleAttributes COLOR_CYAN = 0x0000FFFF } SupportedColors; + + /** + * @brief A mapping between color names and their corresponding SupportedColors enum values. + * + * This map is used to convert human-readable color names (as strings) into their + * corresponding enum values defined in SupportedColors. It includes standard colors + * and a special "auto" value for embedded/default behavior. + */ const std::map< std::string, SupportedColors> ColorMapTable { { "black", COLOR_BLACK}, { "white", COLOR_WHITE}, @@ -149,72 +157,170 @@ class TextStyleAttributes TextStyleAttributes(const TextStyleAttributes&) = delete; TextStyleAttributes& operator=(const TextStyleAttributes&); - /** - * @fn getAttributes - * @param[in] options - Json string containing the attributes - * @param[out] attributesValues - Extracted Attribute values (for now they are font size and position) - * @param[out] attributesMask - Mask corresponding to extracted attribute values - * @return int - 0 for success, -1 for failure - */ - int getAttributes(std::string options, attributesType &attributesValues, uint32_t &attributesMask); + /** + * @fn getAttributes + * + * @param[in] options A JSON string specifying text style attributes. Recognized keys (case-insensitive) and their expected values: + * + * - "penSize": + * - "small", "standard", "medium", "large", "extra_large", "auto" + * + * - "fontStyle": + * - "default", "monospaced_serif"/"monospaced serif", "proportional_serif"/"proportional serif", + * "monospaced_sanserif"/"monospaced sans serif", "proportional_sanserif"/"proportional sans serif", + * "casual", "cursive", "smallcaps"/"small capital", "auto" + * + * - "textForegroundColor", "textBackgroundColor", "textEdgeColor"`, "windowFillColor": + * - "black", "white", "red", "green", "blue", "yellow", "magenta", "cyan", "auto" + * + * - "textEdgeStyle": + * - "none", "raised", "depressed", "uniform", "drop_shadow_left"/"left drop shadow", + * "drop_shadow_right"/"right drop shadow", "auto" + * + * - "textForegroundOpacity", "textBackgroundOpacity", "windowFillOpacity": + * - "solid", "flash", "translucent", "transparent", "auto" + * + * @param[out] attributesValues A reference to a fixed array of 14 `uint32_t` values, where each index corresponds to a specific attribute. + * Array index mapping (via AttribPosInArray): + * - [0] FONT_COLOR_ARR_POSITION + * - [1] BACKGROUND_COLOR_ARR_POSITION + * - [2] FONT_OPACITY_ARR_POSITION + * - [3] BACKGROUND_OPACITY_ARR_POSITION + * - [4] FONT_STYLE_ARR_POSITION + * - [5] FONT_SIZE_ARR_POSITION + * - [6] FONT_ITALIC_ARR_POSITION + * - [7] FONT_UNDERLINE_ARR_POSITION + * - [8] BORDER_TYPE_ARR_POSITION + * - [9] BORDER_COLOR_ARR_POSITION + * - [10] WIN_COLOR_ARR_POSITION + * - [11] WIN_OPACITY_ARR_POSITION + * - [12] EDGE_TYPE_ARR_POSITION + * - [13] EDGE_COLOR_ARR_POSITION + * + * @param[out] attributesMask A 32-bit bitmask indicating which attributes were successfully parsed. + * Each bit i corresponds to index i in attributesValues. If (1 << i) is set, + * then the value at attributesValues[i] is valid. + * + * @return int Returns 0 if at least one attribute is successfully parsed, or -1 if input is empty, + * if none of the known attributes could be parsed. + */ + int getAttributes(std::string options, attributesType &attributesValues, uint32_t &attributesMask); private: + /** * @struct Attributes - * @brief Attributes + * @brief Defines the visual styling attributes for text rendering. + * + * This structure encapsulates various properties related to font and background + * styling, including colors, opacity, font characteristics, and edge effects. */ struct Attributes { - SupportedColors fontColor; - SupportedColors backgroundColor; - Opacity fontOpacity; - Opacity backgroundOpacity; - FontStyle fontStyle; - FontSize fontSize; - Opacity windowOpacity; - SupportedColors windowColor; - EdgeType edgeType; - SupportedColors edgeColor; + SupportedColors fontColor; /**< Color of the font text. */ + SupportedColors backgroundColor; /**< Background color behind the text. */ + Opacity fontOpacity; /**< Opacity level of the font text. */ + Opacity backgroundOpacity; /**< Opacity level of the background. */ + FontStyle fontStyle; /**< Style of the font (e.g., italic, bold). */ + FontSize fontSize; /**< Size of the font. */ + Opacity windowOpacity; /**< Opacity of the window or bounding box. */ + SupportedColors windowColor; /**< Color of the window or bounding box. */ + EdgeType edgeType; /**< Type of edge or outline applied to the text. */ + SupportedColors edgeColor; /**< Color of the text edge or outline. */ }; - /** - * @fn getFontSize - * @param[in] input - input font size value - * @param[out] fontSizeOut - font size option for the input value - * @return int - 0 for success, -1 for failure - */ - int getFontSize(std::string input, FontSize *fontSizeOut); - /** - * @fn getFontStyle - * @param[in] input - input font style value - * @param[out] fontStyleOut - font style option for the input value - * @return int - 0 for success, -1 for failure - */ - int getFontStyle(std::string input, FontStyle *fontStyleOut); + /** + * @fn getFontSize + * + * @param[in] input - String representing the font size. Expected values are: + * - "small" + * - "standard" or "medium" + * - "large" + * - "extra_large" + * - "auto" + * The comparison is case-insensitive. + * + * @param[out] fontSizeOut - font size option for the input value + * + * @return int Returns 0 on success, -1 on failure + */ + int getFontSize(std::string input, FontSize *fontSizeOut); - /** - * @fn getColor - * @param[in] input - input color value - * @patam[out] colorOut - color option for the input value - * @return int - 0 for success, -1 for failure - */ - int getColor(std::string input, SupportedColors *colorOut); + /** + * @fn getFontStyle + * + * @param[in] input - String representing the font style. Expected values are: + * - "default" + * - "monospaced_serif" or "monospaced serif" + * - "proportional_serif" or "proportional serif" + * - "monospaced_sanserif" or "monospaced sans serif" + * - "proportional_sanserif" or "proportional sans serif" + * - "casual" + * - "cursive" + * - "smallcaps" or "small capital" + * - "auto" + * + * @param[out] fontStyleOut - font style option for the input value. + * + * @return int - Returns 0 on successful parsing, -1 on failure + */ + int getFontStyle(std::string input, FontStyle *fontStyleOut); - /** - * @fn getEdgeType - * @param[in] input - input edge type value - * @patam[out] edgeTypeOut - edge type option for the input value - * @return int - 0 for success, -1 for failure - */ - int getEdgeType(std::string input, EdgeType *edgeTypeOut); + /** + * @fn getColor + * + * @param[in] input input color value. Expected values are: + * - "black" + * - "white" + * - "red" + * - "green" + * - "blue" + * - "yellow" + * - "magenta" + * - "cyan" + * - "auto" + * + * @param[out] colorOut - color option for the input value. + * + * @return int Returns 0 on success, -1 on failure + */ + int getColor(std::string input, SupportedColors *colorOut); - /** - * @fn getOpacity - * @param[in] input - input opacity value - * @patam[out] edgeTypeOut - opacity option for the input value - * @return int - 0 for success, -1 for failure - */ - int getOpacity(std::string input, Opacity *opacityOut); + /** + * @brief Converts an input string representing an edge type to the corresponding EdgeType enum value. + * + * @fn getEdgeType + * + * @param[in] input - input edge type value. Expected values are: + * - "none" + * - "raised" + * - "depressed" + * - "uniform" + * - "drop_shadow_left" or "left drop shadow" + * - "drop_shadow_right" or "right drop shadow" + * - "auto" + * + * @param[out] edgeTypeOut - edge type option for the input value + * + * @return int Returns 0 on success, -1 on failure + */ + int getEdgeType(std::string input, EdgeType *edgeTypeOut); + + /** + * @fn getOpacity + * + * @param[in] input input opacity value. Expected values are: + * - "solid" + * - "flash" + * - "translucent" + * - "transparent" + * - "auto" + * + * @param[out] opacityOut - opacity option for the input value. + * + * @return int Returns 0 on success, -1 on failure + */ + int getOpacity(std::string input, Opacity *opacityOut); }; #endif // __TEXT_STYLE_ATTRIBUTES_H__ diff --git a/subtec/subtecparser/TtmlSubtecParser.hpp b/subtec/subtecparser/TtmlSubtecParser.hpp old mode 100644 new mode 100755 index a9070c5..635058d --- a/subtec/subtecparser/TtmlSubtecParser.hpp +++ b/subtec/subtecparser/TtmlSubtecParser.hpp @@ -17,36 +17,145 @@ * limitations under the License. */ + +/** + * @file TtmlSubtecParser.h + * @brief Defines the TtmlSubtecParser class for parsing TTML subtitles and interacting with the Subtec subtitle engine. + */ + #pragma once #include "subtitleParser.h" #include "playerisobmffbuffer.h" #include "SubtecChannel.hpp" +/** + * @class TtmlSubtecParser + * @brief A parser for TTML subtitles that interacts with the Subtec subtitle engine. + * + * This class provides methods to initialize, process, and control TTML subtitle rendering. + * It extends the SubtitleParser base class and implements specific functionality for TTML subtitles. + */ class TtmlSubtecParser : public SubtitleParser { public: - TtmlSubtecParser(SubtitleMimeType type, int width, int height); - - TtmlSubtecParser(const TtmlSubtecParser&) = delete; - TtmlSubtecParser& operator=(const TtmlSubtecParser&) = delete; - - - bool init(double startPosSeconds, unsigned long long basePTS) override; - bool processData(const char* buffer, size_t bufferLen, double position, double duration) override; - bool close() override { return true; } - void reset() override; - void setProgressEventOffset(double offset) override {} - void updateTimestamp(unsigned long long positionMs) override; - void pause(bool pause) override; - void mute(bool mute) override; - - void isLinear(bool isLinear) override { m_isLinear = isLinear; } + /** + * @brief Constructs a TtmlSubtecParser instance for TTML subtitle parsing. + * + * Initializes the parser with the specified subtitle type and screen dimensions. + * It sets up the communication channel with the Subtec subtitle engine, sends + * initialization packets, and optionally resumes track downloads if a callback is set. + * + * @param[in] type The MIME type of the subtitle (e.g., TTML). Expected values are enum values of SubtitleMimeType. + * @param[in] width The width of the video screen. Expected value: positive integer, defaults to 1920 if 0. + * @param[in] height The height of the video screen. Expected value: positive integer, defaults to 1080 if 0. + * + * @throws std::runtime_error if the subtitle communication channel fails to initialize. + */ + TtmlSubtecParser(SubtitleMimeType type, int width, int height); + + + /// Deleted copy constructor to prevent copying. + TtmlSubtecParser(const TtmlSubtecParser&) = delete; + + /// Deleted assignment operator to prevent copying. + TtmlSubtecParser& operator=(const TtmlSubtecParser&) = delete; + + /** + * @brief Initializes the TTML subtitle parser with a starting position and base PTS. + * + * Sends a timestamp packet to the subtitle channel based on the provided start position + * in seconds. Also resets internal state flags and optionally resumes track downloads + * if a callback is registered. + * + * @param[in] startPosSeconds The starting playback position in seconds. Expected value: non-negative double. + * @param[in] basePTS The base presentation timestamp (PTS) in microseconds. Expected value: non-negative unsigned long long. + * + * @return true Always returns true upon successful initialization. + */ + bool init(double startPosSeconds, unsigned long long basePTS) override; + + /** + * @brief Processes subtitle data from a TTML stream and sends it to the subtitle rendering channel. + * + * This function parses the input buffer as an ISO BMFF (MP4) stream. If the buffer is not an + * initialization segment, it extracts the `mdat` box, parses the TTML data, and sends it to + * the subtitle rendering channel. For linear content, it also calculates and sends a time offset + * based on the first `begin` timestamp found in the TTML data. + * + * @param[in] buffer Pointer to the input data buffer. Expected value: non-null pointer to valid TTML stream data. + * @param[in] bufferLen Length of the input buffer in bytes. Expected value: positive size_t value. + * @param[in] position Current playback position in seconds. Expected value: non-negative double. + * @param[in] duration Duration of the current segment in seconds. Expected value: non-negative double. + * + * @return true Always returns true after processing. + */ + bool processData(const char* buffer, size_t bufferLen, double position, double duration) override; + + + /** + * @brief Closes the subtitle parser. + * + * @return true Always returns true upon successful closure. + */ + bool close() override { return true; } + + /** + * @brief Resets the subtitle parser's internal channel state. + * + * Sends a reset packet to the subtitle channel to clear any existing subtitle data + * and prepare for fresh input. Typically used when restarting or reinitializing playback. + */ + void reset() override; + + /** + * @brief Sets the progress event offset. + * + * @param[in] offset The offset value to set. + */ + void setProgressEventOffset(double offset) override {} + + /** + * @brief Updates the subtitle parser with the current playback timestamp. + * + * Sends a timestamp packet to the subtitle channel to synchronize subtitle rendering + * with the current playback position. + * + * @param[in] positionMs The current playback position in milliseconds. Expected value: non-negative unsigned long long. + */ + void updateTimestamp(unsigned long long positionMs) override; + + /** + * @brief Pauses or resumes subtitle rendering. + * + * Sends a pause or resume packet to the subtitle rendering channel based on the input flag. + * This is typically used to synchronize subtitle behavior with media playback state. + * + * @param[in] pause If true, subtitles are paused; if false, subtitles are resumed. + */ + void pause(bool pause) override; + + /** + * @brief Mutes or unmutes subtitle rendering. + * + * Sends a mute or unmute packet to the subtitle rendering channel based on the input flag. + * This is typically used to control subtitle visibility during playback. + * + * @param[in] mute If true, subtitles are muted (hidden); if false, subtitles are unmuted (shown). + */ + void mute(bool mute) override; + + /** + * @brief Sets the linear content flag for the subtitle parser. + * + * @param[in] isLinear If true, the content is linear; if false, it is not. + */ + void isLinear(bool isLinear) override { m_isLinear = isLinear; } protected: - std::unique_ptr m_channel; - bool m_isLinear = false; - bool m_parsedFirstPacket = false; - bool m_sentOffset = false; - double m_firstBeginOffset = 0.0; -}; + std::unique_ptr m_channel; /**< Pointer to the subtitle communication channel. */ + bool m_isLinear = false; /**< Flag indicating whether the content is linear. */ + bool m_parsedFirstPacket = false; /**< Flag indicating whether the first packet has been parsed. */ + bool m_sentOffset = false; /**< Flag indicating whether the offset has been sent. */ + double m_firstBeginOffset = 0.0; /**< Offset value for the first "begin" timestamp. */ +}; \ No newline at end of file diff --git a/subtec/subtecparser/test/test_l1_TextStyleAttributes.cpp b/subtec/subtecparser/test/test_l1_TextStyleAttributes.cpp new file mode 100755 index 0000000..ae0403d --- /dev/null +++ b/subtec/subtecparser/test/test_l1_TextStyleAttributes.cpp @@ -0,0 +1,1012 @@ + +/* +* If not stated otherwise in this file or this component's LICENSE file the +* following copyright and licenses apply: +* +* Copyright 2024 RDK Management +* +* 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. +*/ + +/** +* @file test_l1_TextStyleAttributes.cpp +* @page TextStyleAttributes Level 1 Tests +* +* ## Module's Role +* This module includes Level 1 functional tests (success and failure scenarios). +* This is to ensure that the TextStyleAttributes methods meet the requirements. +* +* **Pre-Conditions:** None @n +* **Dependencies:** None @n +* +*/ + +#include +#include +#include + +#include "TextStyleAttributes.h" + + +/** +* @brief Test to validate all supported pen size attributes in TextStyleAttributes +* +* This test verifies that the TextStyleAttributes class correctly parses and sets the pen size attribute +* when provided with a valid JSON options string. It iterates through all supported values of the "penSize" +* property: "small", "standard", "medium", "large", "extra_large", and "auto". The test ensures that the +* corresponding attribute values and attribute mask are set as expected. +* +* **Test Group ID:** Basic: 01@n +* **Test Case ID:** 001@n +* **Priority:** High@n +* @n +* **Pre-Conditions:** None@n +* **Dependencies:** None@n +* **User Interaction:** None@n +* @n +* **Test Procedure:**@n +* | Variation / Step | Description | Test Data | Expected Result | Notes | +* | :----: | --------- | ---------- |-------------- | ----- | +* | 01 | Initialize TextStyleAttributes object | attributesValues = {0}, attributesMask = 0 | Object initialized successfully | Should be successful | +* | 02 | Call getAttributes with penSize = "small" | options = "{\"penSize\": \"small\"}" | result = 0, attributesValues[5] = FONT_SIZE_SMALL, attributesMask = (1 << 5) | Should Pass | +* | 03 | Call getAttributes with penSize = "standard" | options = "{\"penSize\": \"standard\"}" | result = 0, attributesValues[5] = FONT_SIZE_STANDARD, attributesMask = (1 << 5) | Should Pass | +* | 04 | Call getAttributes with penSize = "medium" | options = "{\"penSize\": \"medium\"}" | result = 0, attributesValues[5] = FONT_SIZE_STANDARD, attributesMask = (1 << 5) | "medium" maps to "standard" | +* | 05 | Call getAttributes with penSize = "large" | options = "{\"penSize\": \"large\"}" | result = 0, attributesValues[5] = FONT_SIZE_LARGE, attributesMask = (1 << 5) | Should Pass | +* | 06 | Call getAttributes with penSize = "extra_large" | options = "{\"penSize\": \"extra_large\"}" | result = 0, attributesValues[5] = FONT_SIZE_EXTRALARGE, attributesMask = (1 << 5) | Should Pass | +* | 07 | Call getAttributes with penSize = "auto" | options = "{\"penSize\": \"auto\"}" | result = 0, attributesValues[5] = FONT_SIZE_EMBEDDED, attributesMask = (1 << 5) | Should Pass | +*/ +TEST(TextStyleAttributesTest, ValidPenSizeAttribute) { + std::cout << "Entering ValidPenSizeAttribute" << std::endl; + + struct TestCase { + std::string penSizeStr; + TextStyleAttributes::FontSize expectedValue; + }; + + std::vector testCases = { + {"small", TextStyleAttributes::FONT_SIZE_SMALL}, + {"standard", TextStyleAttributes::FONT_SIZE_STANDARD}, + {"medium", TextStyleAttributes::FONT_SIZE_STANDARD}, + {"large", TextStyleAttributes::FONT_SIZE_LARGE}, + {"extra_large", TextStyleAttributes::FONT_SIZE_EXTRALARGE}, + {"auto", TextStyleAttributes::FONT_SIZE_EMBEDDED} + }; + + for (const auto& test : testCases) { + std::cout << "Testing penSize: " << test.penSizeStr << std::endl; + + TextStyleAttributes obj; + std::string options = "{\"penSize\": \"" + test.penSizeStr + "\"}"; + attributesType attributesValues = {0}; + uint32_t attributesMask = 0; + + int result = obj.getAttributes(options, attributesValues, attributesMask); + + EXPECT_EQ(result, 0); + EXPECT_EQ(attributesValues[5], test.expectedValue) << "Failed for penSize: " << test.penSizeStr; + EXPECT_EQ(attributesMask, (1 << 5)); + + std::cout << "Passed penSize: " << test.penSizeStr << std::endl; + } + + std::cout << "Exiting ValidPenSizeAttribute" << std::endl; +} + +/** +* @brief Test to validate all supported font style attribute values in TextStyleAttributes class +* +* This test checks if the TextStyleAttributes class correctly parses and sets the font style attribute +* from a given JSON string. It iterates through all supported values of the "fontStyle" property: +* "default", "monospaced_serif"/"monospaced serif", "proportional_serif"/"proportional serif", +* "monospaced_sanserif"/"monospaced sans serif", "proportional_sanserif"/"proportional sans serif", +* "casual", "cursive", "smallcaps"/"small capital", and "auto". The test ensures that the corresponding +* attribute values and attribute mask are set correctly for each case. +* +* **Test Group ID:** Basic: 01@n +* **Test Case ID:** 002@n +* **Priority:** High@n +* @n +* **Pre-Conditions:** None@n +* **Dependencies:** None@n +* **User Interaction:** None@n +* @n +* **Test Procedure:**@n +* | Variation / Step | Description | Test Data | Expected Result | Notes | +* | :----: | --------- | ---------- |-------------- | ----- | +* | 01 | Initialize TextStyleAttributes object | attributesValues = {0}, attributesMask = 0 | Object initialized successfully | Should be successful | +* | 02 | Call getAttributes with fontStyle = "default" | options = "{\"fontStyle\": \"default\"}" | result = 0, attributesValues[4] = FONT_STYLE_DEFAULT, attributesMask = (1 << 4) | Should Pass | +* | 03 | Call getAttributes with fontStyle = "monospaced_serif" | options = "{\"fontStyle\": \"monospaced_serif\"}" | result = 0, attributesValues[4] = FONT_STYLE_MONOSPACED_SERIF, attributesMask = (1 << 4) | Should Pass | +* | 04 | Call getAttributes with fontStyle = "monospaced serif" | options = "{\"fontStyle\": \"monospaced serif\"}" | result = 0, attributesValues[4] = FONT_STYLE_MONOSPACED_SERIF, attributesMask = (1 << 4) | Should Pass | +* | 05 | Call getAttributes with fontStyle = "proportional_serif" | options = "{\"fontStyle\": \"proportional_serif\"}" | result = 0, attributesValues[4] = FONT_STYLE_PROPORTIONAL_SERIF, attributesMask = (1 << 4) | Should Pass | +* | 06 | Call getAttributes with fontStyle = "proportional serif" | options = "{\"fontStyle\": \"proportional serif\"}" | result = 0, attributesValues[4] = FONT_STYLE_PROPORTIONAL_SERIF, attributesMask = (1 << 4) | Should Pass | +* | 07 | Call getAttributes with fontStyle = "monospaced_sanserif" | options = "{\"fontStyle\": \"monospaced_sanserif\"}" | result = 0, attributesValues[4] = FONT_STYLE_MONOSPACED_SANSSERIF, attributesMask = (1 << 4) | Should Pass | +* | 08 | Call getAttributes with fontStyle = "monospaced sans serif" | options = "{\"fontStyle\": \"monospaced sans serif\"}" | result = 0, attributesValues[4] = FONT_STYLE_MONOSPACED_SANSSERIF, attributesMask = (1 << 4) | Should Pass | +* | 09 | Call getAttributes with fontStyle = "proportional_sanserif" | options = "{\"fontStyle\": \"proportional_sanserif\"}" | result = 0, attributesValues[4] = FONT_STYLE_PROPORTIONAL_SANSSERIF, attributesMask = (1 << 4) | Should Pass | +* | 10 | Call getAttributes with fontStyle = "proportional sans serif" | options = "{\"fontStyle\": \"proportional sans serif\"}" | result = 0, attributesValues[4] = FONT_STYLE_PROPORTIONAL_SANSSERIF, attributesMask = (1 << 4) | Should Pass | +* | 11 | Call getAttributes with fontStyle = "casual" | options = "{\"fontStyle\": \"casual\"}" | result = 0, attributesValues[4] = FONT_STYLE_CASUAL, attributesMask = (1 << 4) | Should Pass | +* | 12 | Call getAttributes with fontStyle = "cursive" | options = "{\"fontStyle\": \"cursive\"}" | result = 0, attributesValues[4] = FONT_STYLE_CURSIVE, attributesMask = (1 << 4) | Should Pass | +* | 13 | Call getAttributes with fontStyle = "smallcaps" | options = "{\"fontStyle\": \"smallcaps\"}" | result = 0, attributesValues[4] = FONT_STYLE_SMALL_CAPITALS, attributesMask = (1 << 4) | Should Pass | +* | 14 | Call getAttributes with fontStyle = "small capital" | options = "{\"fontStyle\": \"small capital\"}" | result = 0, attributesValues[4] = FONT_STYLE_SMALL_CAPITALS, attributesMask = (1 << 4) | Should Pass | +* | 15 | Call getAttributes with fontStyle = "auto" | options = "{\"fontStyle\": \"auto\"}" | result = 0, attributesValues[4] = FONT_STYLE_EMBEDDED, attributesMask = (1 << 4) | Should Pass | +*/ +TEST(TextStyleAttributesTest, ValidFontStyleAttribute) { + std::cout << "Entering ValidFontStyleAttribute" << std::endl; + + struct TestCase { + std::string fontStyleStr; + TextStyleAttributes::FontStyle expectedValue; + }; + + std::vector testCases = { + {"default", TextStyleAttributes::FONT_STYLE_DEFAULT}, + {"monospaced_serif", TextStyleAttributes::FONT_STYLE_MONOSPACED_SERIF}, + {"monospaced serif", TextStyleAttributes::FONT_STYLE_MONOSPACED_SERIF}, + {"proportional_serif", TextStyleAttributes::FONT_STYLE_PROPORTIONAL_SERIF}, + {"proportional serif", TextStyleAttributes::FONT_STYLE_PROPORTIONAL_SERIF}, + {"monospaced_sanserif", TextStyleAttributes::FONT_STYLE_MONOSPACED_SANSSERIF}, + {"monospaced sans serif", TextStyleAttributes::FONT_STYLE_MONOSPACED_SANSSERIF}, + {"proportional_sanserif", TextStyleAttributes::FONT_STYLE_PROPORTIONAL_SANSSERIF}, + {"proportional sans serif", TextStyleAttributes::FONT_STYLE_PROPORTIONAL_SANSSERIF}, + {"casual", TextStyleAttributes::FONT_STYLE_CASUAL}, + {"cursive", TextStyleAttributes::FONT_STYLE_CURSIVE}, + {"smallcaps", TextStyleAttributes::FONT_STYLE_SMALL_CAPITALS}, + {"small capital", TextStyleAttributes::FONT_STYLE_SMALL_CAPITALS}, + {"auto", TextStyleAttributes::FONT_STYLE_EMBEDDED} + }; + + for (const auto& test : testCases) { + std::cout << "Testing fontStyle: " << test.fontStyleStr << std::endl; + + TextStyleAttributes obj; + std::string options = "{\"fontStyle\": \"" + test.fontStyleStr + "\"}"; + attributesType attributesValues = {0}; + uint32_t attributesMask = 0; + + int result = obj.getAttributes(options, attributesValues, attributesMask); + + EXPECT_EQ(result, 0); + EXPECT_EQ(attributesValues[4], test.expectedValue) << "Failed for fontStyle: " << test.fontStyleStr; + EXPECT_EQ(attributesMask, (1 << 4)); + + std::cout << "Passed fontStyle: " << test.fontStyleStr << std::endl; + } + + std::cout << "Exiting ValidFontStyleAttribute" << std::endl; +} + +/** +* @brief Test to validate all supported text foreground color attribute values +* +* This test verifies that the `getAttributes` method correctly parses and sets the `textForegroundColor` +* attribute when provided with a valid JSON options string. It iterates through all supported color values: +* "black", "white", "red", "green", "blue", "yellow", "magenta", "cyan", and "auto". The test ensures that +* the method returns the expected result and sets the appropriate `attributesValues` and `attributesMask`. +* +* **Test Group ID:** Basic: 01@n +* **Test Case ID:** 003@n +* **Priority:** High@n +* @n +* **Pre-Conditions:** None@n +* **Dependencies:** None@n +* **User Interaction:** None@n +* @n +* **Test Procedure:**@n +* | Variation / Step | Description | Test Data | Expected Result | Notes | +* | :----: | --------- | ---------- |-------------- | ----- | +* | 01 | Initialize TextStyleAttributes object | attributesValues = {0}, attributesMask = 0 | Object initialized successfully | Should be successful | +* | 02 | Call getAttributes with textForegroundColor = "black" | options = "{\"textForegroundColor\": \"black\"}" | result = 0, attributesValues[0] = COLOR_BLACK, attributesMask = (1 << 0) | Should Pass | +* | 03 | Call getAttributes with textForegroundColor = "white" | options = "{\"textForegroundColor\": \"white\"}" | result = 0, attributesValues[0] = COLOR_WHITE, attributesMask = (1 << 0) | Should Pass | +* | 04 | Call getAttributes with textForegroundColor = "red" | options = "{\"textForegroundColor\": \"red\"}" | result = 0, attributesValues[0] = COLOR_RED, attributesMask = (1 << 0) | Should Pass | +* | 05 | Call getAttributes with textForegroundColor = "green" | options = "{\"textForegroundColor\": \"green\"}" | result = 0, attributesValues[0] = COLOR_GREEN, attributesMask = (1 << 0) | Should Pass | +* | 06 | Call getAttributes with textForegroundColor = "blue" | options = "{\"textForegroundColor\": \"blue\"}" | result = 0, attributesValues[0] = COLOR_BLUE, attributesMask = (1 << 0) | Should Pass | +* | 07 | Call getAttributes with textForegroundColor = "yellow" | options = "{\"textForegroundColor\": \"yellow\"}" | result = 0, attributesValues[0] = COLOR_YELLOW, attributesMask = (1 << 0) | Should Pass | +* | 08 | Call getAttributes with textForegroundColor = "magenta" | options = "{\"textForegroundColor\": \"magenta\"}" | result = 0, attributesValues[0] = COLOR_MAGENTA, attributesMask = (1 << 0) | Should Pass | +* | 09 | Call getAttributes with textForegroundColor = "cyan" | options = "{\"textForegroundColor\": \"cyan\"}" | result = 0, attributesValues[0] = COLOR_CYAN, attributesMask = (1 << 0) | Should Pass | +* | 10 | Call getAttributes with textForegroundColor = "auto" | options = "{\"textForegroundColor\": \"auto\"}" | result = 0, attributesValues[0] = COLOR_EMBEDDED, attributesMask = (1 << 0) | Should Pass | +*/ +TEST(TextStyleAttributesTest, ValidTextForegroundColorAttribute) { + std::cout << "Entering ValidTextForegroundColorAttribute" << std::endl; + + struct TestCase { + std::string colorStr; + TextStyleAttributes::SupportedColors expectedValue; + }; + + std::vector testCases = { + {"black", TextStyleAttributes::COLOR_BLACK}, + {"white", TextStyleAttributes::COLOR_WHITE}, + {"red", TextStyleAttributes::COLOR_RED}, + {"green", TextStyleAttributes::COLOR_GREEN}, + {"blue", TextStyleAttributes::COLOR_BLUE}, + {"yellow", TextStyleAttributes::COLOR_YELLOW}, + {"magenta", TextStyleAttributes::COLOR_MAGENTA}, + {"cyan", TextStyleAttributes::COLOR_CYAN}, + {"auto", TextStyleAttributes::COLOR_EMBEDDED} + }; + + for (const auto& test : testCases) { + std::cout << "Testing textForegroundColor: " << test.colorStr << std::endl; + + TextStyleAttributes obj; + std::string options = "{\"textForegroundColor\": \"" + test.colorStr + "\"}"; + attributesType attributesValues = {0}; + uint32_t attributesMask = 0; + + int result = obj.getAttributes(options, attributesValues, attributesMask); + + EXPECT_EQ(result, 0); + EXPECT_EQ(attributesValues[0], test.expectedValue) << "Failed for color: " << test.colorStr; + EXPECT_EQ(attributesMask, (1 << 0)); + + std::cout << "Passed textForegroundColor: " << test.colorStr << std::endl; + } + + std::cout << "Exiting ValidTextForegroundColorAttribute" << std::endl; +} + +/** +* @brief Test to validate all supported text background color attribute values +* +* This test checks if the `getAttributes` method correctly parses and sets the `textBackgroundColor` +* attribute from a given JSON string. It iterates through all supported color values: +* "black", "white", "red", "green", "blue", "yellow", "magenta", "cyan", and "auto". +* The test ensures that the method returns the expected result and sets the appropriate +* values in `attributesValues[1]` and the `attributesMask`. +* +* **Test Group ID:** Basic: 01@n +* **Test Case ID:** 004@n +* **Priority:** High@n +* @n +* **Pre-Conditions:** None@n +* **Dependencies:** None@n +* **User Interaction:** None@n +* @n +* **Test Procedure:**@n +* | Variation / Step | Description | Test Data | Expected Result | Notes | +* | :----: | --------- | ---------- |-------------- | ----- | +* | 01 | Initialize TextStyleAttributes object | attributesValues = {0}, attributesMask = 0 | Object initialized and ready | Should be successful | +* | 02 | Call getAttributes with textBackgroundColor = "black" | options = "{\"textBackgroundColor\": \"black\"}" | result = 0, attributesValues[1] = COLOR_BLACK, attributesMask = (1 << 1) | Should Pass | +* | 03 | Call getAttributes with textBackgroundColor = "white" | options = "{\"textBackgroundColor\": \"white\"}" | result = 0, attributesValues[1] = COLOR_WHITE, attributesMask = (1 << 1) | Should Pass | +* | 04 | Call getAttributes with textBackgroundColor = "red" | options = "{\"textBackgroundColor\": \"red\"}" | result = 0, attributesValues[1] = COLOR_RED, attributesMask = (1 << 1) | Should Pass | +* | 05 | Call getAttributes with textBackgroundColor = "green" | options = "{\"textBackgroundColor\": \"green\"}" | result = 0, attributesValues[1] = COLOR_GREEN, attributesMask = (1 << 1) | Should Pass | +* | 06 | Call getAttributes with textBackgroundColor = "blue" | options = "{\"textBackgroundColor\": \"blue\"}" | result = 0, attributesValues[1] = COLOR_BLUE, attributesMask = (1 << 1) | Should Pass | +* | 07 | Call getAttributes with textBackgroundColor = "yellow" | options = "{\"textBackgroundColor\": \"yellow\"}" | result = 0, attributesValues[1] = COLOR_YELLOW, attributesMask = (1 << 1) | Should Pass | +* | 08 | Call getAttributes with textBackgroundColor = "magenta" | options = "{\"textBackgroundColor\": \"magenta\"}" | result = 0, attributesValues[1] = COLOR_MAGENTA, attributesMask = (1 << 1) | Should Pass | +* | 09 | Call getAttributes with textBackgroundColor = "cyan" | options = "{\"textBackgroundColor\": \"cyan\"}" | result = 0, attributesValues[1] = COLOR_CYAN, attributesMask = (1 << 1) | Should Pass | +* | 10 | Call getAttributes with textBackgroundColor = "auto" | options = "{\"textBackgroundColor\": \"auto\"}" | result = 0, attributesValues[1] = COLOR_EMBEDDED, attributesMask = (1 << 1) | Should Pass | +*/ +TEST(TextStyleAttributesTest, ValidTextBackgroundColorAttribute) { + std::cout << "Entering ValidTextBackgroundColorAttribute" << std::endl; + + struct TestCase { + std::string colorStr; + TextStyleAttributes::SupportedColors expectedValue; + }; + + std::vector testCases = { + {"black", TextStyleAttributes::COLOR_BLACK}, + {"white", TextStyleAttributes::COLOR_WHITE}, + {"red", TextStyleAttributes::COLOR_RED}, + {"green", TextStyleAttributes::COLOR_GREEN}, + {"blue", TextStyleAttributes::COLOR_BLUE}, + {"yellow", TextStyleAttributes::COLOR_YELLOW}, + {"magenta", TextStyleAttributes::COLOR_MAGENTA}, + {"cyan", TextStyleAttributes::COLOR_CYAN}, + {"auto", TextStyleAttributes::COLOR_EMBEDDED} + }; + + for (const auto& test : testCases) { + std::cout << "Testing textBackgroundColor: " << test.colorStr << std::endl; + + TextStyleAttributes obj; + std::string options = "{\"textBackgroundColor\": \"" + test.colorStr + "\"}"; + attributesType attributesValues = {0}; + uint32_t attributesMask = 0; + + int result = obj.getAttributes(options, attributesValues, attributesMask); + + EXPECT_EQ(result, 0); + EXPECT_EQ(attributesValues[1], test.expectedValue) << "Failed for color: " << test.colorStr; + EXPECT_EQ(attributesMask, (1 << 1)); + + std::cout << "Passed textBackgroundColor: " << test.colorStr << std::endl; + } + + std::cout << "Exiting ValidTextBackgroundColorAttribute" << std::endl; +} + +/** +* @brief Test to validate all supported text edge color attribute values +* +* This test verifies that the `TextStyleAttributes` class correctly processes the `textEdgeColor` attribute +* when provided in the JSON options string. It iterates over all supported color values: +* "black", "white", "red", "green", "blue", "yellow", "magenta", "cyan", and "auto". +* The test ensures that each color is correctly parsed, the expected value is set in `attributesValues[13]`, +* and the corresponding bit in the `attributesMask` is updated correctly. +* +* **Test Group ID:** Basic: 01@n +* **Test Case ID:** 005@n +* **Priority:** High@n +* @n +* **Pre-Conditions:** None@n +* **Dependencies:** None@n +* **User Interaction:** None@n +* @n +* **Test Procedure:**@n +* | Variation / Step | Description | Test Data | Expected Result | Notes | +* | :----: | --------- | ---------- |-------------- | ----- | +* | 01 | Create TextStyleAttributes object and initialize values | attributesValues = {0}, attributesMask = 0 | Object and variables initialized successfully | Should be successful | +* | 02 | Call getAttributes with textEdgeColor = "black" | options = "{\"textEdgeColor\": \"black\"}" | result = 0, attributesValues[13] = COLOR_BLACK, attributesMask = (1 << 13) | Should Pass | +* | 03 | Call getAttributes with textEdgeColor = "white" | options = "{\"textEdgeColor\": \"white\"}" | result = 0, attributesValues[13] = COLOR_WHITE, attributesMask = (1 << 13) | Should Pass | +* | 04 | Call getAttributes with textEdgeColor = "red" | options = "{\"textEdgeColor\": \"red\"}" | result = 0, attributesValues[13] = COLOR_RED, attributesMask = (1 << 13) | Should Pass | +* | 05 | Call getAttributes with textEdgeColor = "green" | options = "{\"textEdgeColor\": \"green\"}" | result = 0, attributesValues[13] = COLOR_GREEN, attributesMask = (1 << 13) | Should Pass | +* | 06 | Call getAttributes with textEdgeColor = "blue" | options = "{\"textEdgeColor\": \"blue\"}" | result = 0, attributesValues[13] = COLOR_BLUE, attributesMask = (1 << 13) | Should Pass | +* | 07 | Call getAttributes with textEdgeColor = "yellow" | options = "{\"textEdgeColor\": \"yellow\"}" | result = 0, attributesValues[13] = COLOR_YELLOW, attributesMask = (1 << 13) | Should Pass | +* | 08 | Call getAttributes with textEdgeColor = "magenta" | options = "{\"textEdgeColor\": \"magenta\"}" | result = 0, attributesValues[13] = COLOR_MAGENTA, attributesMask = (1 << 13) | Should Pass | +* | 09 | Call getAttributes with textEdgeColor = "cyan" | options = "{\"textEdgeColor\": \"cyan\"}" | result = 0, attributesValues[13] = COLOR_CYAN, attributesMask = (1 << 13) | Should Pass | +* | 10 | Call getAttributes with textEdgeColor = "auto" | options = "{\"textEdgeColor\": \"auto\"}" | result = 0, attributesValues[13] = COLOR_EMBEDDED, attributesMask = (1 << 13) | Should Pass | +*/ +TEST(TextStyleAttributesTest, ValidTextEdgeColorAttribute) { + std::cout << "Entering ValidTextEdgeColorAttribute" << std::endl; + + struct TestCase { + std::string colorStr; + TextStyleAttributes::SupportedColors expectedValue; + }; + + std::vector testCases = { + {"black", TextStyleAttributes::COLOR_BLACK}, + {"white", TextStyleAttributes::COLOR_WHITE}, + {"red", TextStyleAttributes::COLOR_RED}, + {"green", TextStyleAttributes::COLOR_GREEN}, + {"blue", TextStyleAttributes::COLOR_BLUE}, + {"yellow", TextStyleAttributes::COLOR_YELLOW}, + {"magenta", TextStyleAttributes::COLOR_MAGENTA}, + {"cyan", TextStyleAttributes::COLOR_CYAN}, + {"auto", TextStyleAttributes::COLOR_EMBEDDED} + }; + + for (const auto& test : testCases) { + std::cout << "Testing textEdgeColor: " << test.colorStr << std::endl; + + TextStyleAttributes obj; + std::string options = "{\"textEdgeColor\": \"" + test.colorStr + "\"}"; + attributesType attributesValues = {0}; + uint32_t attributesMask = 0; + + int result = obj.getAttributes(options, attributesValues, attributesMask); + + EXPECT_EQ(result, 0); + EXPECT_EQ(attributesValues[13], test.expectedValue) << "Failed for color: " << test.colorStr; + EXPECT_EQ(attributesMask, (1 << 13)); + + std::cout << "Passed textEdgeColor: " << test.colorStr << std::endl; + } + + std::cout << "Exiting ValidTextEdgeColorAttribute" << std::endl; +} + +/** +* @brief Test to validate all supported window fill color attribute values in TextStyleAttributes +* +* This test verifies that the `TextStyleAttributes` class correctly parses and sets the `windowFillColor` +* attribute from a given JSON string. It iterates through all supported color values: +* "black", "white", "red", "green", "blue", "yellow", "magenta", "cyan", and "auto". +* The test ensures that each color is correctly mapped to the corresponding value in `attributesValues[10]` +* and that the appropriate bit in the `attributesMask` (bit 10) is set. +* +* **Test Group ID:** Basic: 01@n +* **Test Case ID:** 006@n +* **Priority:** High@n +* @n +* **Pre-Conditions:** None@n +* **Dependencies:** None@n +* **User Interaction:** None@n +* @n +* **Test Procedure:**@n +* | Variation / Step | Description | Test Data | Expected Result | Notes | +* | :----: | --------- | ---------- |-------------- | ----- | +* | 01 | Create TextStyleAttributes object and initialize state | attributesValues = {0}, attributesMask = 0 | Object created and initial state ready | Should be successful | +* | 02 | Call getAttributes with windowFillColor = "black" | options = "{\"windowFillColor\": \"black\"}" | result = 0, attributesValues[10] = COLOR_BLACK, attributesMask = (1 << 10) | Should Pass | +* | 03 | Call getAttributes with windowFillColor = "white" | options = "{\"windowFillColor\": \"white\"}" | result = 0, attributesValues[10] = COLOR_WHITE, attributesMask = (1 << 10) | Should Pass | +* | 04 | Call getAttributes with windowFillColor = "red" | options = "{\"windowFillColor\": \"red\"}" | result = 0, attributesValues[10] = COLOR_RED, attributesMask = (1 << 10) | Should Pass | +* | 05 | Call getAttributes with windowFillColor = "green" | options = "{\"windowFillColor\": \"green\"}" | result = 0, attributesValues[10] = COLOR_GREEN, attributesMask = (1 << 10) | Should Pass | +* | 06 | Call getAttributes with windowFillColor = "blue" | options = "{\"windowFillColor\": \"blue\"}" | result = 0, attributesValues[10] = COLOR_BLUE, attributesMask = (1 << 10) | Should Pass | +* | 07 | Call getAttributes with windowFillColor = "yellow" | options = "{\"windowFillColor\": \"yellow\"}" | result = 0, attributesValues[10] = COLOR_YELLOW, attributesMask = (1 << 10) | Should Pass | +* | 08 | Call getAttributes with windowFillColor = "magenta" | options = "{\"windowFillColor\": \"magenta\"}" | result = 0, attributesValues[10] = COLOR_MAGENTA, attributesMask = (1 << 10) | Should Pass | +* | 09 | Call getAttributes with windowFillColor = "cyan" | options = "{\"windowFillColor\": \"cyan\"}" | result = 0, attributesValues[10] = COLOR_CYAN, attributesMask = (1 << 10) | Should Pass | +* | 10 | Call getAttributes with windowFillColor = "auto" | options = "{\"windowFillColor\": \"auto\"}" | result = 0, attributesValues[10] = COLOR_EMBEDDED, attributesMask = (1 << 10) | Should Pass | +*/ +TEST(TextStyleAttributesTest, ValidWindowFillColorAttribute) { + std::cout << "Entering ValidWindowFillColorAttribute" << std::endl; + + struct TestCase { + std::string colorStr; + TextStyleAttributes::SupportedColors expectedValue; + }; + + std::vector testCases = { + {"black", TextStyleAttributes::COLOR_BLACK}, + {"white", TextStyleAttributes::COLOR_WHITE}, + {"red", TextStyleAttributes::COLOR_RED}, + {"green", TextStyleAttributes::COLOR_GREEN}, + {"blue", TextStyleAttributes::COLOR_BLUE}, + {"yellow", TextStyleAttributes::COLOR_YELLOW}, + {"magenta", TextStyleAttributes::COLOR_MAGENTA}, + {"cyan", TextStyleAttributes::COLOR_CYAN}, + {"auto", TextStyleAttributes::COLOR_EMBEDDED} + }; + + for (const auto& test : testCases) { + std::cout << "Testing windowFillColor: " << test.colorStr << std::endl; + + TextStyleAttributes obj; + std::string options = "{\"windowFillColor\": \"" + test.colorStr + "\"}"; + attributesType attributesValues = {0}; + uint32_t attributesMask = 0; + + int result = obj.getAttributes(options, attributesValues, attributesMask); + + EXPECT_EQ(result, 0); + EXPECT_EQ(attributesValues[10], test.expectedValue) << "Failed for color: " << test.colorStr; + EXPECT_EQ(attributesMask, (1 << 10)); + + std::cout << "Passed windowFillColor: " << test.colorStr << std::endl; + } + + std::cout << "Exiting ValidWindowFillColorAttribute" << std::endl; +} + +/** +* @brief Test to validate all supported Text Edge Style Attribute values +* +* This test verifies that the `TextStyleAttributes` class correctly parses and sets the `textEdgeStyle` attribute +* when provided with a valid JSON options string. It covers all supported values including: +* "none", "raised", "depressed", "uniform", "drop_shadow_left", "left drop shadow", +* "drop_shadow_right", "right drop shadow", and "auto". +* It ensures that the correct enum values are written to `attributesValues[12]` and that the corresponding +* bit in `attributesMask` (bit 12) is correctly set. +* +* **Test Group ID:** Basic: 01@n +* **Test Case ID:** 007@n +* **Priority:** High@n +* @n +* **Pre-Conditions:** None@n +* **Dependencies:** None@n +* **User Interaction:** None@n +* @n +* **Test Procedure:**@n +* | Variation / Step | Description | Test Data | Expected Result | Notes | +* | :----: | --------- | ---------- |-------------- | ----- | +* | 01 | Initialize TextStyleAttributes object and mask values | attributesValues = {0}, attributesMask = 0 | Object and mask initialized | Should be successful | +* | 02 | Call getAttributes with textEdgeStyle = "none" | options = "{\"textEdgeStyle\": \"none\"}" | result = 0, attributesValues[12] = EDGE_TYPE_NONE, attributesMask = (1 << 12) | Should Pass | +* | 03 | Call getAttributes with textEdgeStyle = "raised" | options = "{\"textEdgeStyle\": \"raised\"}" | result = 0, attributesValues[12] = EDGE_TYPE_RAISED, attributesMask = (1 << 12) | Should Pass | +* | 04 | Call getAttributes with textEdgeStyle = "depressed" | options = "{\"textEdgeStyle\": \"depressed\"}" | result = 0, attributesValues[12] = EDGE_TYPE_DEPRESSED, attributesMask = (1 << 12) | Should Pass | +* | 05 | Call getAttributes with textEdgeStyle = "uniform" | options = "{\"textEdgeStyle\": \"uniform\"}" | result = 0, attributesValues[12] = EDGE_TYPE_UNIFORM, attributesMask = (1 << 12) | Should Pass | +* | 06 | Call getAttributes with textEdgeStyle = "drop_shadow_left" | options = "{\"textEdgeStyle\": \"drop_shadow_left\"}" | result = 0, attributesValues[12] = EDGE_TYPE_SHADOW_LEFT, attributesMask = (1 << 12) | Should Pass | +* | 07 | Call getAttributes with textEdgeStyle = "left drop shadow" | options = "{\"textEdgeStyle\": \"left drop shadow\"}" | result = 0, attributesValues[12] = EDGE_TYPE_SHADOW_LEFT, attributesMask = (1 << 12) | Should Pass | +* | 08 | Call getAttributes with textEdgeStyle = "drop_shadow_right" | options = "{\"textEdgeStyle\": \"drop_shadow_right\"}" | result = 0, attributesValues[12] = EDGE_TYPE_SHADOW_RIGHT, attributesMask = (1 << 12) | Should Pass | +* | 09 | Call getAttributes with textEdgeStyle = "right drop shadow" | options = "{\"textEdgeStyle\": \"right drop shadow\"}" | result = 0, attributesValues[12] = EDGE_TYPE_SHADOW_RIGHT, attributesMask = (1 << 12) | Should Pass | +* | 10 | Call getAttributes with textEdgeStyle = "auto" | options = "{\"textEdgeStyle\": \"auto\"}" | result = 0, attributesValues[12] = EDGE_TYPE_EMBEDDED, attributesMask = (1 << 12) | Should Pass | +*/ +TEST(TextStyleAttributesTest, ValidTextEdgeStyleAttribute) { + std::cout << "Entering ValidTextEdgeStyleAttribute" << std::endl; + + struct TestCase { + std::string styleStr; + TextStyleAttributes::EdgeType expectedValue; + }; + + std::vector testCases = { + {"none", TextStyleAttributes::EDGE_TYPE_NONE}, + {"raised", TextStyleAttributes::EDGE_TYPE_RAISED}, + {"depressed", TextStyleAttributes::EDGE_TYPE_DEPRESSED}, + {"uniform", TextStyleAttributes::EDGE_TYPE_UNIFORM}, + {"drop_shadow_left", TextStyleAttributes::EDGE_TYPE_SHADOW_LEFT}, + {"left drop shadow", TextStyleAttributes::EDGE_TYPE_SHADOW_LEFT}, + {"drop_shadow_right", TextStyleAttributes::EDGE_TYPE_SHADOW_RIGHT}, + {"right drop shadow", TextStyleAttributes::EDGE_TYPE_SHADOW_RIGHT}, + {"auto", TextStyleAttributes::EDGE_TYPE_EMBEDDED} + }; + + for (const auto& test : testCases) { + std::cout << "Testing textEdgeStyle: " << test.styleStr << std::endl; + + TextStyleAttributes obj; + std::string options = "{\"textEdgeStyle\": \"" + test.styleStr + "\"}"; + attributesType attributesValues = {0}; + uint32_t attributesMask = 0; + + int result = obj.getAttributes(options, attributesValues, attributesMask); + + EXPECT_EQ(result, 0); + EXPECT_EQ(attributesValues[12], test.expectedValue) << "Failed for textEdgeStyle: " << test.styleStr; + EXPECT_EQ(attributesMask, (1 << 12)); + + std::cout << "Passed textEdgeStyle: " << test.styleStr << std::endl; + } + + std::cout << "Exiting ValidTextEdgeStyleAttribute" << std::endl; +} + +/** +* @brief Test to validate all supported textForegroundOpacity attribute values in TextStyleAttributes +* +* This test checks the functionality of the `getAttributes` method in the `TextStyleAttributes` class. It verifies +* that the method correctly parses all valid values of the `"textForegroundOpacity"` attribute from a JSON string, +* sets the correct value in `attributesValues[2]`, and updates the appropriate bit in `attributesMask` (bit 2). +* Supported values include: "solid", "flash", "translucent", "transparent", and "auto". +* +* **Test Group ID:** Basic: 01@n +* **Test Case ID:** 008@n +* **Priority:** High@n +* @n +* **Pre-Conditions:** None@n +* **Dependencies:** None@n +* **User Interaction:** None@n +* @n +* **Test Procedure:**@n +* | Variation / Step | Description | Test Data | Expected Result | Notes | +* | :----: | --------- | ---------- |-------------- | ----- | +* | 01 | Initialize TextStyleAttributes object and masks | attributesValues = {0}, attributesMask = 0 | Object and values initialized | Should be successful | +* | 02 | Call getAttributes with textForegroundOpacity = "solid" | options = "{\"textForegroundOpacity\": \"solid\"}" | result = 0, attributesValues[2] = OPACITY_SOLID, attributesMask = (1 << 2) | Should Pass | +* | 03 | Call getAttributes with textForegroundOpacity = "flash" | options = "{\"textForegroundOpacity\": \"flash\"}" | result = 0, attributesValues[2] = OPACITY_FLASHING, attributesMask = (1 << 2) | Should Pass | +* | 04 | Call getAttributes with textForegroundOpacity = "translucent" | options = "{\"textForegroundOpacity\": \"translucent\"}" | result = 0, attributesValues[2] = OPACITY_TRANSLUCENT, attributesMask = (1 << 2) | Should Pass | +* | 05 | Call getAttributes with textForegroundOpacity = "transparent" | options = "{\"textForegroundOpacity\": \"transparent\"}" | result = 0, attributesValues[2] = OPACITY_TRANSPARENT, attributesMask = (1 << 2) | Should Pass | +* | 06 | Call getAttributes with textForegroundOpacity = "auto" | options = "{\"textForegroundOpacity\": \"auto\"}" | result = 0, attributesValues[2] = OPACITY_EMBEDDED, attributesMask = (1 << 2) | Should Pass | +*/ +TEST(TextStyleAttributesTest, ValidTextForegroundOpacityAttribute) { + std::cout << "Entering ValidTextForegroundOpacityAttribute" << std::endl; + + struct TestCase { + std::string opacityStr; + TextStyleAttributes::Opacity expectedValue; + }; + + std::vector testCases = { + {"solid", TextStyleAttributes::OPACITY_SOLID}, + {"flash", TextStyleAttributes::OPACITY_FLASHING}, + {"translucent", TextStyleAttributes::OPACITY_TRANSLUCENT}, + {"transparent", TextStyleAttributes::OPACITY_TRANSPARENT}, + {"auto", TextStyleAttributes::OPACITY_EMBEDDED} + }; + + for (const auto& test : testCases) { + std::cout << "Testing textForegroundOpacity: " << test.opacityStr << std::endl; + + TextStyleAttributes obj; + std::string options = "{\"textForegroundOpacity\": \"" + test.opacityStr + "\"}"; + attributesType attributesValues = {0}; + uint32_t attributesMask = 0; + + int result = obj.getAttributes(options, attributesValues, attributesMask); + + EXPECT_EQ(result, 0); + EXPECT_EQ(attributesValues[2], test.expectedValue) << "Failed for opacity: " << test.opacityStr; + EXPECT_EQ(attributesMask, (1 << 2)); + + std::cout << "Passed textForegroundOpacity: " << test.opacityStr << std::endl; + } + + std::cout << "Exiting ValidTextForegroundOpacityAttribute" << std::endl; +} + +/** +* @brief Test to validate all supported textBackgroundOpacity attribute values in TextStyleAttributes +* +* This test verifies that the `getAttributes` method in the `TextStyleAttributes` class correctly parses +* and sets the `"textBackgroundOpacity"` attribute from a valid JSON string. It iterates over all supported +* values: "solid", "flash", "translucent", "transparent", and "auto". The test ensures that the correct +* enum value is written to `attributesValues[3]` and that the appropriate bit (bit 3) is set in `attributesMask`. +* +* **Test Group ID:** Basic: 01@n +* **Test Case ID:** 009@n +* **Priority:** High@n +* @n +* **Pre-Conditions:** None@n +* **Dependencies:** None@n +* **User Interaction:** None@n +* @n +* **Test Procedure:**@n +* | Variation / Step | Description | Test Data | Expected Result | Notes | +* | :----: | --------- | ---------- |-------------- | ----- | +* | 01 | Create TextStyleAttributes object and initialize state | attributesValues = {0}, attributesMask = 0 | Object initialized | Should be successful | +* | 02 | Call getAttributes with textBackgroundOpacity = "solid" | options = "{\"textBackgroundOpacity\": \"solid\"}" | result = 0, attributesValues[3] = OPACITY_SOLID, attributesMask = (1 << 3) | Should Pass | +* | 03 | Call getAttributes with textBackgroundOpacity = "flash" | options = "{\"textBackgroundOpacity\": \"flash\"}" | result = 0, attributesValues[3] = OPACITY_FLASHING, attributesMask = (1 << 3) | Should Pass | +* | 04 | Call getAttributes with textBackgroundOpacity = "translucent" | options = "{\"textBackgroundOpacity\": \"translucent\"}" | result = 0, attributesValues[3] = OPACITY_TRANSLUCENT, attributesMask = (1 << 3) | Should Pass | +* | 05 | Call getAttributes with textBackgroundOpacity = "transparent" | options = "{\"textBackgroundOpacity\": \"transparent\"}" | result = 0, attributesValues[3] = OPACITY_TRANSPARENT, attributesMask = (1 << 3) | Should Pass | +* | 06 | Call getAttributes with textBackgroundOpacity = "auto" | options = "{\"textBackgroundOpacity\": \"auto\"}" | result = 0, attributesValues[3] = OPACITY_EMBEDDED, attributesMask = (1 << 3) | Should Pass | +*/ +TEST(TextStyleAttributesTest, ValidTextBackgroundOpacityAttribute) { + std::cout << "Entering ValidTextBackgroundOpacityAttribute" << std::endl; + + struct TestCase { + std::string opacityStr; + TextStyleAttributes::Opacity expectedValue; + }; + + std::vector testCases = { + {"solid", TextStyleAttributes::OPACITY_SOLID}, + {"flash", TextStyleAttributes::OPACITY_FLASHING}, + {"translucent", TextStyleAttributes::OPACITY_TRANSLUCENT}, + {"transparent", TextStyleAttributes::OPACITY_TRANSPARENT}, + {"auto", TextStyleAttributes::OPACITY_EMBEDDED} + }; + + for (const auto& test : testCases) { + std::cout << "Testing textBackgroundOpacity: " << test.opacityStr << std::endl; + + TextStyleAttributes obj; + std::string options = "{\"textBackgroundOpacity\": \"" + test.opacityStr + "\"}"; + attributesType attributesValues = {0}; + uint32_t attributesMask = 0; + + int result = obj.getAttributes(options, attributesValues, attributesMask); + + EXPECT_EQ(result, 0); + EXPECT_EQ(attributesValues[3], test.expectedValue) << "Failed for opacity: " << test.opacityStr; + EXPECT_EQ(attributesMask, (1 << 3)); + + std::cout << "Passed textBackgroundOpacity: " << test.opacityStr << std::endl; + } + + std::cout << "Exiting ValidTextBackgroundOpacityAttribute" << std::endl; +} + +/** +* @brief Test to validate all supported windowFillOpacity attribute values in TextStyleAttributes +* +* This test verifies that the `getAttributes` method correctly parses and sets the `"windowFillOpacity"` attribute +* from a valid JSON string. It tests all supported values: "solid", "flash", "translucent", "transparent", and "auto". +* The test ensures the correct enum value is written to `attributesValues[11]` and that the appropriate bit in +* `attributesMask` (bit 11) is set. +* +* **Test Group ID:** Basic: 01@n +* **Test Case ID:** 010@n +* **Priority:** High@n +* @n +* **Pre-Conditions:** None@n +* **Dependencies:** None@n +* **User Interaction:** None@n +* @n +* **Test Procedure:**@n +* | Variation / Step | Description | Test Data | Expected Result | Notes | +* | :----: | --------- | ---------- |-------------- | ----- | +* | 01 | Create TextStyleAttributes object and initialize state | attributesValues = {0}, attributesMask = 0 | Object initialized | Should be successful | +* | 02 | Call getAttributes with windowFillOpacity = "solid" | options = "{\"windowFillOpacity\": \"solid\"}" | result = 0, attributesValues[11] = OPACITY_SOLID, attributesMask = (1 << 11) | Should Pass | +* | 03 | Call getAttributes with windowFillOpacity = "flash" | options = "{\"windowFillOpacity\": \"flash\"}" | result = 0, attributesValues[11] = OPACITY_FLASHING, attributesMask = (1 << 11) | Should Pass | +* | 04 | Call getAttributes with windowFillOpacity = "translucent" | options = "{\"windowFillOpacity\": \"translucent\"}" | result = 0, attributesValues[11] = OPACITY_TRANSLUCENT, attributesMask = (1 << 11) | Should Pass | +* | 05 | Call getAttributes with windowFillOpacity = "transparent" | options = "{\"windowFillOpacity\": \"transparent\"}" | result = 0, attributesValues[11] = OPACITY_TRANSPARENT, attributesMask = (1 << 11) | Should Pass | +* | 06 | Call getAttributes with windowFillOpacity = "auto" | options = "{\"windowFillOpacity\": \"auto\"}" | result = 0, attributesValues[11] = OPACITY_EMBEDDED, attributesMask = (1 << 11) | Should Pass | +*/ +TEST(TextStyleAttributesTest, ValidWindowFillOpacityAttribute) { + std::cout << "Entering ValidWindowFillOpacityAttribute" << std::endl; + + struct TestCase { + std::string opacityStr; + TextStyleAttributes::Opacity expectedValue; + }; + + std::vector testCases = { + {"solid", TextStyleAttributes::OPACITY_SOLID}, + {"flash", TextStyleAttributes::OPACITY_FLASHING}, + {"translucent", TextStyleAttributes::OPACITY_TRANSLUCENT}, + {"transparent", TextStyleAttributes::OPACITY_TRANSPARENT}, + {"auto", TextStyleAttributes::OPACITY_EMBEDDED} + }; + + for (const auto& test : testCases) { + std::cout << "Testing windowFillOpacity: " << test.opacityStr << std::endl; + + TextStyleAttributes obj; + std::string options = "{\"windowFillOpacity\": \"" + test.opacityStr + "\"}"; + attributesType attributesValues = {0}; + uint32_t attributesMask = 0; + + int result = obj.getAttributes(options, attributesValues, attributesMask); + + EXPECT_EQ(result, 0); + EXPECT_EQ(attributesValues[11], test.expectedValue) << "Failed for windowFillOpacity: " << test.opacityStr; + EXPECT_EQ(attributesMask, (1 << 11)); + + std::cout << "Passed windowFillOpacity: " << test.opacityStr << std::endl; + } + + std::cout << "Exiting ValidWindowFillOpacityAttribute" << std::endl; +} + +/** +* @brief Test to validate multiple valid attributes in TextStyleAttributes +* +* This test checks the functionality of the getAttributes method in the TextStyleAttributes class by providing multiple valid attributes in the options string. It verifies that the method correctly parses the options and sets the appropriate attribute values and mask. +* +* **Test Group ID:** Basic: 01@n +* **Test Case ID:** 011@n +* **Priority:** High@n +* @n +* **Pre-Conditions:** None@n +* **Dependencies:** None@n +* **User Interaction:** None@n +* @n +* **Test Procedure:**@n +* | Variation / Step | Description | Test Data |Expected Result |Notes | +* | :----: | --------- | ---------- |-------------- | ----- | +* | 01| Initialize TextStyleAttributes object and options string | options = "{\"penSize\": \"medium\", \"fontStyle\": \"default\", \"textForegroundColor\": \"white\"}", attributesValues = {0}, attributesMask = 0 | Object and variables initialized | Should be successful | +* | 02| Call getAttributes method with options string | options = "{\"penSize\": \"medium\", \"fontStyle\": \"default\", \"textForegroundColor\": \"white\"}", attributesValues, attributesMask | result = 0 | Should Pass | +* | 03| Verify attribute values for penSize | |attributesValues[5] = TextStyleAttributes::FONT_SIZE_STANDARD | Should Pass | +* | 04| Verify attribute values for fontStyle| | attributesValues[4] = TextStyleAttributes::FONT_STYLE_DEFAULT | Should Pass | +* | 05| Verify attribute values for textForegroundColor| | attributesValues[0] = TextStyleAttributes::COLOR_WHITE | Should Pass | +* | 06| Verify attributesMask | attributesMask| | Should Pass | +*/ +TEST(TextStyleAttributesTest, MultipleValidAttributes) { + std::cout << "Entering MultipleValidAttributes" << std::endl; + + TextStyleAttributes obj; + std::string options = "{\"penSize\": \"medium\", \"fontStyle\": \"default\", \"textForegroundColor\": \"white\"}"; + attributesType attributesValues = {0}; + uint32_t attributesMask = 0; + + int result = obj.getAttributes(options, attributesValues, attributesMask); + + EXPECT_EQ(result, 0); + EXPECT_EQ(attributesValues[5], TextStyleAttributes::FONT_SIZE_STANDARD); + EXPECT_EQ(attributesValues[4], TextStyleAttributes::FONT_STYLE_DEFAULT); + EXPECT_EQ(attributesValues[0], TextStyleAttributes::COLOR_WHITE); + EXPECT_EQ(attributesMask, (1 << 5) | (1 << 4) | (1 << 0)); + + std::cout << "Exiting MultipleValidAttributes" << std::endl; +} + +/** +* @brief Test to validate the behavior of getAttributes method when an invalid attribute key is provided. +* +* This test checks the response of the getAttributes method when it is given an invalid attribute key in the options string. The method is expected to return an error code and not modify the attributesMask. +* +* **Test Group ID:** Basic: 01@n +* **Test Case ID:** 012@n +* **Priority:** High@n +* @n +* **Pre-Conditions:** None@n +* **Dependencies:** None@n +* **User Interaction:** None@n +* @n +* **Test Procedure:**@n +* | Variation / Step | Description | Test Data | Expected Result | Notes | +* | :----: | --------- | ---------- |-------------- | ----- | +* | 01 | Initialize TextStyleAttributes object and set options with invalid key | options = "{\"invalidKey\": \"value\"}", attributesValues = {0}, attributesMask = 0 | result = -1, attributesMask = 0 | Should Pass | +* | 02 | Call getAttributes method with invalid options | options = "{\"invalidKey\": \"value\"}", attributesValues = {0}, attributesMask = 0 | result = -1, attributesMask = 0 | Should Pass | +* | 03 | Verify the result and attributesMask | result = -1, attributesMask = 0 | result = -1, attributesMask = 0 | Should Pass | +*/ +TEST(TextStyleAttributesTest, InvalidAttributeKey) { + std::cout << "Entering InvalidAttributeKey" << std::endl; + + TextStyleAttributes obj; + std::string options = "{\"invalidKey\": \"value\"}"; + attributesType attributesValues = {0}; + uint32_t attributesMask = 0; + + int result = obj.getAttributes(options, attributesValues, attributesMask); + + EXPECT_EQ(result, -1); + EXPECT_EQ(attributesMask, 0); + std::cout << "Exiting InvalidAttributeKey" << std::endl; +} + +/** +* @brief Test to validate the behavior of getAttributes method when an invalid attribute value is provided. +* +* This test checks the response of the getAttributes method when it is given an invalid value for the "penSize" attribute. +* It ensures that the method correctly identifies the invalid input and returns an appropriate error code. +* +* **Test Group ID:** Basic: 01@n +* **Test Case ID:** 013@n +* **Priority:** High@n +* @n +* **Pre-Conditions:** None@n +* **Dependencies:** None@n +* **User Interaction:** None@n +* @n +* **Test Procedure:**@n +* | Variation / Step | Description | Test Data |Expected Result |Notes | +* | :----: | --------- | ---------- |-------------- | ----- | +* | 01| Call getAttributes with invalid penSize value | options = "{\"penSize\": \"invalidValue\"}", attributesValues = {0}, attributesMask = 0 | result = -1, attributesMask = 0, EXPECT_EQ(result, -1), EXPECT_EQ(attributesMask, 0) | Should Fail | +*/ +TEST(TextStyleAttributesTest, InvalidAttributeValue) { + std::cout << "Entering InvalidAttributeValue" << std::endl; + + TextStyleAttributes obj; + std::string options = "{\"penSize\": \"invalidValue\"}"; + attributesType attributesValues = {0}; + uint32_t attributesMask = 0; + + int result = obj.getAttributes(options, attributesValues, attributesMask); + + EXPECT_EQ(result, -1); + EXPECT_EQ(attributesMask, 0); + std::cout << "Exiting InvalidAttributeValue" << std::endl; +} + +/** +* @brief Test to verify the behavior of getAttributes method when an empty options string is provided. +* +* This test checks the getAttributes method of the TextStyleAttributes class with an empty options string. +* It ensures that the method returns an error code and does not modify the attributes mask. +* +* **Test Group ID:** Basic: 01@n +* **Test Case ID:** 014@n +* **Priority:** High@n +* @n +* **Pre-Conditions:** None@n +* **Dependencies:** None@n +* **User Interaction:** None@n +* @n +* **Test Procedure:**@n +* | Variation / Step | Description | Test Data | Expected Result | Notes | +* | :----: | --------- | ---------- |-------------- | ----- | +* | 01 | Call getAttributes with empty options string | options = "", attributesValues = {0}, attributesMask = 0 | result = -1, attributesMask = 0 | Should Pass | +*/ +TEST(TextStyleAttributesTest, EmptyOptionsString) { + std::cout << "Entering EmptyOptionsString" << std::endl; + + TextStyleAttributes obj; + std::string options = ""; + attributesType attributesValues = {0}; + uint32_t attributesMask = 0; + + int result = obj.getAttributes(options, attributesValues, attributesMask); + + EXPECT_EQ(result, -1); + EXPECT_EQ(attributesMask, 0); + + std::cout << "Exiting EmptyOptionsString" << std::endl; +} + +/** +* @brief Test the behavior of getAttributes method with an empty JSON string +* +* This test checks the behavior of the getAttributes method when provided with an empty JSON string as input. It ensures that the method handles this edge case correctly by returning an error code and not modifying the attributes mask. +* +* **Test Group ID:** Basic: 01@n +* **Test Case ID:** 015@n +* **Priority:** High@n +* @n +* **Pre-Conditions:** None@n +* **Dependencies:** None@n +* **User Interaction:** None@n +* @n +* **Test Procedure:**@n +* | Variation / Step | Description | Test Data | Expected Result | Notes | +* | :----: | --------- | ---------- |-------------- | ----- | +* | 01 | Call getAttributes with empty JSON string | options = "{}", attributesValues = {0}, attributesMask = 0 | result = -1, attributesMask = 0 | Should Pass | +*/ +TEST(TextStyleAttributesTest, EmptyOptionsJsonString) { + std::cout << "Entering EmptyOptionsJsonString" << std::endl; + + TextStyleAttributes obj; + std::string options = "{}"; + attributesType attributesValues = {0}; + uint32_t attributesMask = 0; + + int result = obj.getAttributes(options, attributesValues, attributesMask); + + EXPECT_EQ(result, -1); + EXPECT_EQ(attributesMask, 0); + + std::cout << "Exiting EmptyOptionsJsonString" << std::endl; +} + +/** +* @brief Test the handling of mixed valid and invalid attributes in TextStyleAttributes +* +* This test checks the behavior of the TextStyleAttributes class when provided with a mix of valid and invalid attributes in the input JSON string. It ensures that the function correctly identifies the invalid attribute and returns the appropriate error code. +* +* **Test Group ID:** Basic: 01@n +* **Test Case ID:** 016@n +* **Priority:** High@n +* @n +* **Pre-Conditions:** None@n +* **Dependencies:** None@n +* **User Interaction:** None@n +* @n +* **Test Procedure:**@n +* | Variation / Step | Description | Test Data | Expected Result | Notes | +* | :----: | --------- | ---------- |-------------- | ----- | +* | 01 | Initialize TextStyleAttributes object and input data | options = "{\"penSize\": \"small\", \"invalidKey\": \"value\"}", attributesValues = {0}, attributesMask = 0 | Should be successful | | +* | 02 | Call getAttributes with mixed valid and invalid attributes | options = "{\"penSize\": \"small\", \"invalidKey\": \"value\"}", attributesValues = {0}, attributesMask = 0 | result = -1, EXPECT_EQ(result, -1) | Should Pass | +*/ +TEST(TextStyleAttributesTest, MixedValidAndInvalidAttributes) { + std::cout << "Entering MixedValidAndInvalidAttributes" << std::endl; + + TextStyleAttributes obj; + std::string options = "{\"penSize\": \"small\", \"invalidKey\": \"value\"}"; + attributesType attributesValues = {0}; + uint32_t attributesMask = 0; + + int result = obj.getAttributes(options, attributesValues, attributesMask); + + EXPECT_EQ(result, -1); + + std::cout << "Exiting MixedValidAndInvalidAttributes" << std::endl; +} + +/** +* @brief Test to verify case insensitivity of attribute keys in TextStyleAttributes +* +* This test checks if the TextStyleAttributes class correctly handles attribute keys in a case-insensitive manner. +* Specifically, it verifies that the method getAttributes returns the expected result when provided with an attribute key in uppercase. +* +* **Test Group ID:** Basic: 01@n +* **Test Case ID:** 017@n +* **Priority:** High@n +* @n +* **Pre-Conditions:** None@n +* **Dependencies:** None@n +* **User Interaction:** None@n +* @n +* **Test Procedure:**@n +* | Variation / Step | Description | Test Data | Expected Result | Notes | +* | :----: | --------- | ---------- |-------------- | ----- | +* | 01 | Initialize TextStyleAttributes object and set options with uppercase attribute key | options = "{\"PENSIZE\": \"auto\"}", attributesValues = {0}, attributesMask = 0 | result = -1, EXPECT_EQ(result, -1) | Should Pass | +*/ +TEST(TextStyleAttributesTest, CaseInsensitiveAttributeKeys) { + std::cout << "Entering CaseInsensitiveAttributeKeys" << std::endl; + + TextStyleAttributes obj; + std::string options = "{\"PENSIZE\": \"auto\"}"; + attributesType attributesValues = {0}; + uint32_t attributesMask = 0; + + int result = obj.getAttributes(options, attributesValues, attributesMask); + + EXPECT_EQ(result, -1); + + std::cout << "Exiting CaseInsensitiveAttributeKeys" << std::endl; +} + +/** +* @brief Test to verify the assignment of default values in TextStyleAttributes +* +* This test checks the assignment operator for the TextStyleAttributes class to ensure that default values are correctly assigned from one object to another. This is important to verify that the assignment operator works as expected and that the objects maintain their integrity after assignment. +* +* **Test Group ID:** Basic: 01@n +* **Test Case ID:** 018@n +* **Priority:** High@n +* @n +* **Pre-Conditions:** None@n +* **Dependencies:** None@n +* **User Interaction:** None@n +* @n +* **Test Procedure:**@n +* | Variation / Step | Description | Test Data |Expected Result |Notes | +* | :----: | --------- | ---------- |-------------- | ----- | +* | 01| Create two TextStyleAttributes objects | obj1, obj2 | Objects created successfully | Should be successful | +* | 02| Assign obj1 to obj2 using assignment operator | obj2 = obj1 | obj2 should have the same values as obj1 | Should Pass | +* | 03| Verify the assignment operator returns the correct reference | &obj2, &(obj2 = obj1) | The address of obj2 should be returned | Should Pass | +*/ +TEST(TextStyleAttributesTest, AssigningDefaultValues) { + std::cout << "Entering AssigningDefaultValues" << std::endl; + + TextStyleAttributes obj1; + TextStyleAttributes obj2; + + obj2 = obj1; + EXPECT_EQ(&obj2, &(obj2 = obj1)); + + std::cout << "Exiting AssigningDefaultValues" << std::endl; +} + +int main(int argc, char **argv) { + ::testing::InitGoogleTest(&argc, argv); + return RUN_ALL_TESTS(); +} + diff --git a/subtec/subtecparser/test/test_l1_TtmlSubtecParser.cpp b/subtec/subtecparser/test/test_l1_TtmlSubtecParser.cpp new file mode 100755 index 0000000..d7844a0 --- /dev/null +++ b/subtec/subtecparser/test/test_l1_TtmlSubtecParser.cpp @@ -0,0 +1,1668 @@ + +/* +* If not stated otherwise in this file or this component's LICENSE file the +* following copyright and licenses apply: +* +* Copyright 2024 RDK Management +* +* 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. +*/ + +/** +* @file test_l1_TtmlSubtecParser.cpp +* @page TtmlSubtecParser Level 1 Tests +* +* ## Module's Role +* This module includes Level 1 functional tests (success and failure scenarios). +* This is to ensure that the TtmlSubtecParser methods meet the requirements. +* +* **Pre-Conditions:** None @n +* **Dependencies:** None @n +* +*/ + +#include +#include +#include + +#include "TtmlSubtecParser.hpp" + +class TtmlSubtecParserTestHelper : public TtmlSubtecParser { +public: + + // Constructor that forwards args to the base constructor + TtmlSubtecParserTestHelper(SubtitleMimeType type, int width, int height) + : TtmlSubtecParser(type, width, height) {} + + using SubtitleParser::mWidth; + using SubtitleParser::mHeight; + using TtmlSubtecParser::m_isLinear; + using TtmlSubtecParser::m_parsedFirstPacket; + using TtmlSubtecParser::m_sentOffset; + using TtmlSubtecParser::m_firstBeginOffset; + +}; + +/** +* @brief Test the construction of TtmlSubtecParser with valid TTML type and default dimensions. +* +* This test verifies that the TtmlSubtecParser is correctly initialized with default dimensions when provided with various subtitle mime types, including TTML, MP4, and UNKNOWN types.@n +* +* **Test Group ID:** Basic: 01@n +* **Test Case ID:** 001@n +* **Priority:** High@n +* @n +* **Pre-Conditions:** None@n +* **Dependencies:** None@n +* **User Interaction:** None@n +* @n +* **Test Procedure:**@n +* | Variation / Step | Description | Test Data |Expected Result |Notes | +* | :----: | --------- | ---------- |-------------- | ----- | +* | 01| Initialize parser with eSUB_TYPE_TTML | type = eSUB_TYPE_WEBVTT, width = 0, height = 0 | mWidth = 1920, mHeight = 1080 | Should Pass | +* | 02| Initialize parser with eSUB_TYPE_MP4 | type = eSUB_TYPE_MP4, width = 0, height = 0 | mWidth = 1920, mHeight = 1080 | Should Pass | +* | 03| Initialize parser with eSUB_TYPE_TTML | type = eSUB_TYPE_TTML, width = 0, height = 0 | mWidth = 1920, mHeight = 1080 | Should Pass | +* | 04| Initialize parser with eSUB_TYPE_UNKNOWN | type = eSUB_TYPE_UNKNOWN, width = 0, height = 0 | mWidth = 1920, mHeight = 1080 | Should Pass | +*/ +TEST(TtmlSubtecParserTest, ConstructParserWithValidTTMLTypeAndDefaultDimensions) { + std::cout << "Entering ConstructParserWithValidTTMLTypeAndDefaultDimensions test" << std::endl; + + SubtitleMimeType types[] = {eSUB_TYPE_WEBVTT, eSUB_TYPE_MP4, eSUB_TYPE_TTML, eSUB_TYPE_UNKNOWN}; + + for (auto type : types) { + std::cout << "Testing with SubtitleMimeType: " << type << std::endl; + std::cout << "Invoking TtmlSubtecParserTestHelper constructor with type = " << type << ", width = 0, height = 0" << std::endl; + + TtmlSubtecParserTestHelper parser(type, 0, 0); + + std::cout << "TtmlSubtecParserTestHelper constructed with mWidth = " << parser.mWidth + << ", mHeight = " << parser.mHeight << std::endl; + + EXPECT_EQ(parser.mWidth, 1920); + EXPECT_EQ(parser.mHeight, 1080); + + std::cout << "Passed for SubtitleMimeType: " << type << std::endl; + } + + std::cout << "Exiting ConstructParserWithValidTTMLTypeAndDefaultDimensions test" << std::endl; +} + +/** +* @brief Test the construction of TtmlSubtecParser with valid TTML type and specific dimensions +* +* This test verifies that the TtmlSubtecParser is correctly constructed with a valid TTML type and specific dimensions (1280x720). It ensures that the width and height are set correctly for different subtitle types. +* +* **Test Group ID:** Basic: 01@n +* **Test Case ID:** 002@n +* **Priority:** High@n +* @n +* **Pre-Conditions:** None@n +* **Dependencies:** None@n +* **User Interaction:** None@n +* @n +* **Test Procedure:**@n +* | Variation / Step | Description | Test Data |Expected Result |Notes | +* | :----: | --------- | ---------- |-------------- | ----- | +* | 01| Construct parser with eSUB_TYPE_TTML | type = eSUB_TYPE_WEBVTT, width = 1280, height = 720 | parser.mWidth = 1280, parser.mHeight = 720 | Should Pass | +* | 02| Construct parser with eSUB_TYPE_MP4 | type = eSUB_TYPE_MP4, width = 1280, height = 720 | parser.mWidth = 1280, parser.mHeight = 720 | Should Pass | +* | 03| Construct parser with eSUB_TYPE_TTML | type = eSUB_TYPE_TTML, width = 1280, height = 720 | parser.mWidth = 1280, parser.mHeight = 720 | Should Pass | +* | 04| Construct parser with eSUB_TYPE_UNKNOWN | type = eSUB_TYPE_UNKNOWN, width = 1280, height = 720 | parser.mWidth = 1280, parser.mHeight = 720 | Should Pass | +*/ +TEST(TtmlSubtecParserTest, ConstructParserWithValidTTMLTypeAndSpecificDimensions) { + std::cout << "Entering ConstructParserWithValidTTMLTypeAndSpecificDimensions test" << std::endl; + + SubtitleMimeType types[] = {eSUB_TYPE_WEBVTT, eSUB_TYPE_MP4, eSUB_TYPE_TTML, eSUB_TYPE_UNKNOWN}; + + for (auto type : types) { + std::cout << "Testing with SubtitleMimeType: " << type << std::endl; + std::cout << "Invoking TtmlSubtecParserTestHelper constructor with type = " << type + << ", width = 1280, height = 720" << std::endl; + + TtmlSubtecParserTestHelper parser(type, 1280, 720); + + std::cout << "TtmlSubtecParserTestHelper constructed with mWidth = " << parser.mWidth + << ", mHeight = " << parser.mHeight << std::endl; + + EXPECT_EQ(parser.mWidth, 1280); + EXPECT_EQ(parser.mHeight, 720); + + std::cout << "Passed for SubtitleMimeType: " << type << std::endl; + } + + std::cout << "Exiting ConstructParserWithValidTTMLTypeAndSpecificDimensions test" << std::endl; +} + +/** +* @brief Test the construction of TtmlSubtecParser with a negative width +* +* This test verifies that the TtmlSubtecParser constructor throws a runtime error when initialized with a negative width value. This is important to ensure that the parser handles invalid input parameters correctly and does not proceed with invalid configurations.@n +* +* **Test Group ID:** Basic: 01@n +* **Test Case ID:** 003@n +* **Priority:** High@n +* @n +* **Pre-Conditions:** None@n +* **Dependencies:** None@n +* **User Interaction:** None@n +* @n +* **Test Procedure:**@n +* | Variation / Step | Description | Test Data |Expected Result |Notes | +* | :----: | --------- | ---------- |-------------- | ----- | +* | 01| Initialize parser with eSUB_TYPE_TTML and negative width | type = eSUB_TYPE_WEBVTT, width = -1920, height = 1080 | std::runtime_error | Should Fail | +* | 02| Initialize parser with eSUB_TYPE_MP4 and negative width | type = eSUB_TYPE_MP4, width = -1920, height = 1080 | std::runtime_error | Should Fail | +* | 03| Initialize parser with eSUB_TYPE_TTML and negative width | type = eSUB_TYPE_TTML, width = -1920, height = 1080 | std::runtime_error | Should Fail | +* | 04| Initialize parser with eSUB_TYPE_UNKNOWN and negative width | type = eSUB_TYPE_UNKNOWN, width = -1920, height = 1080 | std::runtime_error | Should Fail | +*/ +TEST(TtmlSubtecParserTest, ConstructParserWithNegativeWidth) { + std::cout << "Entering ConstructParserWithNegativeWidth test" << std::endl; + + SubtitleMimeType types[] = {eSUB_TYPE_WEBVTT, eSUB_TYPE_MP4, eSUB_TYPE_TTML, eSUB_TYPE_UNKNOWN}; + + for (auto type : types) { + std::cout << "Testing with SubtitleMimeType: " << type << std::endl; + std::cout << "Invoking TtmlSubtecParserTestHelper constructor with type = " << type + << ", width = -1920, height = 1080 (expecting exception)" << std::endl; + + EXPECT_THROW( + { + TtmlSubtecParserTestHelper parser(type, -1920, 1080); + }, + std::runtime_error + ); + + std::cout << "Correctly threw exception for SubtitleMimeType: " << type << std::endl; + } + + std::cout << "Exiting ConstructParserWithNegativeWidth test" << std::endl; +} + +/** +* @brief Test the construction of TtmlSubtecParser with negative height +* +* This test verifies that the TtmlSubtecParser constructor throws a runtime error when initialized with a negative height value. This is important to ensure that the parser handles invalid input parameters correctly and does not proceed with invalid configurations. +* +* **Test Group ID:** Basic: 01@n +* **Test Case ID:** 004@n +* **Priority:** High@n +* @n +* **Pre-Conditions:** None@n +* **Dependencies:** None@n +* **User Interaction:** None@n +* @n +* **Test Procedure:**@n +* | Variation / Step | Description | Test Data | Expected Result | Notes | +* | :----: | --------- | ---------- |-------------- | ----- | +* | 01 | Initialize parser with eSUB_TYPE_TTML and negative height | type = eSUB_TYPE_WEBVTT, width = 1920, height = -1080 | std::runtime_error | Should Fail | +* | 02 | Initialize parser with eSUB_TYPE_MP4 and negative height | type = eSUB_TYPE_MP4, width = 1920, height = -1080 | std::runtime_error | Should Fail | +* | 03 | Initialize parser with eSUB_TYPE_TTML and negative height | type = eSUB_TYPE_TTML, width = 1920, height = -1080 | std::runtime_error | Should Fail | +* | 04 | Initialize parser with eSUB_TYPE_UNKNOWN and negative height | type = eSUB_TYPE_UNKNOWN, width = 1920, height = -1080 | std::runtime_error | Should Fail | +*/ +TEST(TtmlSubtecParserTest, ConstructParserWithNegativeHeight) { + std::cout << "Entering ConstructParserWithNegativeHeight test" << std::endl; + + SubtitleMimeType types[] = {eSUB_TYPE_WEBVTT, eSUB_TYPE_MP4, eSUB_TYPE_TTML, eSUB_TYPE_UNKNOWN}; + + for (auto type : types) { + std::cout << "Testing with SubtitleMimeType: " << type << std::endl; + std::cout << "Invoking TtmlSubtecParserTestHelper constructor with type = " << type + << ", width = 1920, height = -1080 (expecting exception)" << std::endl; + + EXPECT_THROW( + { + TtmlSubtecParserTestHelper parser(type, 1920, -1080); + }, + std::runtime_error + ); + + std::cout << "Correctly threw exception for SubtitleMimeType: " << type << std::endl; + } + + std::cout << "Exiting ConstructParserWithNegativeHeight test" << std::endl; +} + +/** +* @brief Test the construction of TtmlSubtecParser with valid TTML type and maximum dimensions. +* +* This test verifies that the TtmlSubtecParser can be constructed with different subtitle types, +* including TTML, and ensures that the width and height are set to the maximum integer values.@n +* +* **Test Group ID:** Basic: 01@n +* **Test Case ID:** 005@n +* **Priority:** High@n +* @n +* **Pre-Conditions:** None@n +* **Dependencies:** None@n +* **User Interaction:** None@n +* @n +* **Test Procedure:**@n +* | Variation / Step | Description | Test Data |Expected Result |Notes | +* | :----: | --------- | ---------- |-------------- | ----- | +* | 01| Construct parser with eSUB_TYPE_TTML | type = eSUB_TYPE_WEBVTT, width = INT_MAX, height = INT_MAX | parser.mWidth = INT_MAX, parser.mHeight = INT_MAX | Should Pass | +* | 02| Construct parser with eSUB_TYPE_MP4 | type = eSUB_TYPE_MP4, width = INT_MAX, height = INT_MAX | parser.mWidth = INT_MAX, parser.mHeight = INT_MAX | Should Pass | +* | 03| Construct parser with eSUB_TYPE_TTML again | type = eSUB_TYPE_TTML, width = INT_MAX, height = INT_MAX | parser.mWidth = INT_MAX, parser.mHeight = INT_MAX | Should Pass | +* | 04| Construct parser with eSUB_TYPE_UNKNOWN | type = eSUB_TYPE_UNKNOWN, width = INT_MAX, height = INT_MAX | parser.mWidth = INT_MAX, parser.mHeight = INT_MAX | Should Pass | +*/ +TEST(TtmlSubtecParserTest, ConstructParserWithValidTTMLTypeAndMaxDimensions) { + std::cout << "Entering ConstructParserWithValidTTMLTypeAndMaxDimensions test" << std::endl; + + SubtitleMimeType types[] = {eSUB_TYPE_WEBVTT, eSUB_TYPE_MP4, eSUB_TYPE_TTML, eSUB_TYPE_UNKNOWN}; + + for (auto type : types) { + std::cout << "Testing with SubtitleMimeType: " << type << std::endl; + std::cout << "Invoking TtmlSubtecParserTestHelper constructor with type = " << type + << ", width = INT_MAX, height = INT_MAX" << std::endl; + + TtmlSubtecParserTestHelper parser(type, INT_MAX, INT_MAX); + + std::cout << "TtmlSubtecParserTestHelper constructed with mWidth = " << parser.mWidth + << ", mHeight = " << parser.mHeight << std::endl; + + EXPECT_EQ(parser.mWidth, INT_MAX); + EXPECT_EQ(parser.mHeight, INT_MAX); + + std::cout << "Passed for SubtitleMimeType: " << type << std::endl; + } + + std::cout << "Exiting ConstructParserWithValidTTMLTypeAndMaxDimensions test" << std::endl; +} + +/** + * @brief Test to verify the successful closing of the TTML subtitle parser + * + * This test verifies that the TTML subtitle parser, after being initialized with various + * subtitle MIME types and valid dimensions, can be successfully closed using the `close()` method. + * It ensures that `close()` returns `true`, indicating a successful shutdown of parser resources. + * + * **Test Group ID:** Basic: 01@n + * **Test Case ID:** 006@n + * **Priority:** High@n + * + * **Pre-Conditions:** None@n + * **Dependencies:** None@n + * **User Interaction:** None@n + * + * **Test Procedure:**@n + * | Variation / Step | Description | Test Data | Expected Result | Notes | + * |------------------|------------------------------------|--------------------------------------------------|----------------------------------|----------------| + * | 01 | Initialize parser with TTML type | type = eSUB_TYPE_WEBVTT, width = 1920, height = 1080 | parser initialized successfully | Should Pass | + * | 02 | Call close method on parser | None | close() returns true | Should Pass | + * | 03 | Initialize parser with MP4 type | type = eSUB_TYPE_MP4, width = 1920, height = 1080 | parser initialized successfully | Should Pass | + * | 04 | Call close method on parser | None | close() returns true | Should Pass | + * | 05 | Initialize parser with TTML again | type = eSUB_TYPE_TTML, width = 1920, height = 1080 | parser initialized successfully | Should Pass | + * | 06 | Call close method on parser | None | close() returns true | Should Pass | + * | 07 | Initialize parser with UNKNOWN type| type = eSUB_TYPE_UNKNOWN, width = 1920, height = 1080 | parser initialized successfully | Should Pass | + * | 08 | Call close method on parser | None | close() returns true | Should Pass | + */ +TEST(TtmlSubtecParserTest, CloseSubtitleParserSuccessfully) { + std::cout << "Entering CloseSubtitleParserSuccessfully" << std::endl; + + SubtitleMimeType types[] = {eSUB_TYPE_WEBVTT, eSUB_TYPE_MP4, eSUB_TYPE_TTML, eSUB_TYPE_UNKNOWN}; + + for (auto type : types) { + std::cout << "Testing with SubtitleMimeType: " << type << std::endl; + std::cout << "Invoking TtmlSubtecParserTestHelper constructor with type = " << type + << ", width = 1920, height = 1080" << std::endl; + + TtmlSubtecParserTestHelper parser(type, 1920, 1080); + + std::cout << "Invoking parser.close()" << std::endl; + bool result = parser.close(); + std::cout << "parser.close() returned: " << std::boolalpha << result << std::endl; + + EXPECT_TRUE(result); + std::cout << "Passed close() test for SubtitleMimeType: " << type << std::endl; + } + + std::cout << "Exiting CloseSubtitleParserSuccessfully" << std::endl; +} + +/** + * @brief Test the behavior of closing the subtitle parser multiple times + * + * This test checks the functionality of the `close` method in the `TtmlSubtecParser` class when it is called multiple times consecutively. The objective is to ensure that the parser can handle multiple close operations gracefully without causing any errors or unexpected behavior. + * + * **Test Group ID:** Basic: 01@n + * **Test Case ID:** 007@n + * **Priority:** High@n + * + * **Pre-Conditions:** None@n + * **Dependencies:** None@n + * **User Interaction:** None@n + * + * **Test Procedure:**@n + * | Variation / Step | Description | Test Data | Expected Result | Notes | + * |------------------|-----------------------------------------|--------------------------------------------------------|--------------------------|----------------| + * | 01 | Initialize parser with TTML type | type = eSUB_TYPE_WEBVTT, width = 1920, height = 1080 | Object should initialize | Should Pass | + * | 02 | Call close method (1st time) | None | close() returns true | Should Pass | + * | 03 | Call close method (2nd time) | None | close() returns true | Should Pass | + * | 04 | Initialize parser with MP4 type | type = eSUB_TYPE_MP4, width = 1920, height = 1080 | Object should initialize | Should Pass | + * | 05 | Call close method (1st time) | None | close() returns true | Should Pass | + * | 06 | Call close method (2nd time) | None | close() returns true | Should Pass | + * | 07 | Initialize parser with UNKNOWN type | type = eSUB_TYPE_TTML, width = 1920, height = 1080 | Object should initialize | Should Pass | + * | 08 | Call close method (1st time) | None | close() returns true | Should Pass | + * | 09 | Call close method (2nd time) | None | close() returns true | Should Pass | + * | 10 | Initialize parser with UNKNOWN type | type = eSUB_TYPE_UNKNOWN, width = 1920, height = 1080 | Object should initialize | Should Pass | + * | 11 | Call close method (1st time) | None | close() returns true | Should Pass | + * | 12 | Call close method (2nd time) | None | close() returns true | Should Pass | + */ +TEST(TtmlSubtecParserTest, CloseSubtitleParserMultipleTimes) { + std::cout << "Entering CloseSubtitleParserMultipleTimes" << std::endl; + + SubtitleMimeType types[] = {eSUB_TYPE_WEBVTT, eSUB_TYPE_MP4, eSUB_TYPE_TTML, eSUB_TYPE_UNKNOWN}; + + for (auto type : types) { + std::cout << "Testing with SubtitleMimeType: " << type << std::endl; + std::cout << "Invoking TtmlSubtecParserTestHelper constructor with type = " << type + << ", width = 1920, height = 1080" << std::endl; + + TtmlSubtecParserTestHelper parser(type, 1920, 1080); + + std::cout << "First call to parser.close()" << std::endl; + bool result1 = parser.close(); + std::cout << "First close() returned: " << std::boolalpha << result1 << std::endl; + + std::cout << "Second call to parser.close()" << std::endl; + bool result2 = parser.close(); + std::cout << "Second close() returned: " << std::boolalpha << result2 << std::endl; + + EXPECT_TRUE(result1); + EXPECT_TRUE(result2); + + std::cout << "Passed double-close test for SubtitleMimeType: " << type << std::endl; + } + + std::cout << "Exiting CloseSubtitleParserMultipleTimes" << std::endl; +} + +/** + * @brief Test the initialization of TtmlSubtecParser with valid start position and base PTS + * + * This test verifies that the TtmlSubtecParser can be successfully initialized with a valid start position and base PTS. + * The test ensures that the parser's init function returns true when provided with these valid inputs. + * + * **Test Group ID:** Basic: 01@n + * **Test Case ID:** 008@n + * **Priority:** High@n + * + * **Pre-Conditions:** None@n + * **Dependencies:** None@n + * **User Interaction:** None@n + * + * **Test Procedure:**@n + * | Variation / Step | Description | Test Data | Expected Result | Notes | + * |------------------|---------------------------------------------|-----------------------------------------------------------------|----------------------|----------------| + * | 01 | Initialize parser with WEBVTT type | type = eSUB_TYPE_WEBVTT, startPosSeconds = 10.0, basePTS = 1000000 | result = true | Should Pass | + * | 02 | Initialize parser with MP4 type | type = eSUB_TYPE_MP4, startPosSeconds = 10.0, basePTS = 1000000 | result = true | Should Pass | + * | 03 | Initialize parser with TTML type | type = eSUB_TYPE_TTML, startPosSeconds = 10.0, basePTS = 1000000 | result = true | Should Pass | + * | 04 | Initialize parser with UNKNOWN type | type = eSUB_TYPE_UNKNOWN, startPosSeconds = 10.0, basePTS = 1000000| result = true | Should Pass | + */ + +TEST(TtmlSubtecParserTest, InitializeWithValidStartPositionAndBasePTS) { + std::cout << "Entering InitializeWithValidStartPositionAndBasePTS test" << std::endl; + + SubtitleMimeType types[] = {eSUB_TYPE_WEBVTT, eSUB_TYPE_MP4, eSUB_TYPE_TTML, eSUB_TYPE_UNKNOWN}; + + for (auto type : types) { + std::cout << "Testing with SubtitleMimeType: " << type << std::endl; + + TtmlSubtecParserTestHelper parser(type, 1920, 1080); + double startPosSeconds = 10.0; + unsigned long long basePTS = 1000000; + + std::cout << "Invoking parser.init() with startPosSeconds = " << startPosSeconds + << ", basePTS = " << basePTS << std::endl; + + bool result = parser.init(startPosSeconds, basePTS); + + std::cout << "parser.init() returned: " << std::boolalpha << result << std::endl; + + EXPECT_TRUE(result); + std::cout << "Passed initialization for SubtitleMimeType: " << type << std::endl; + } + + std::cout << "Exiting InitializeWithValidStartPositionAndBasePTS test" << std::endl; +} + +/** + * @brief Test the initialization of TtmlSubtecParser with zero start position and base PTS + * + * This test verifies that the TtmlSubtecParser can be initialized correctly when provided with a start position of 0.0 seconds and a base PTS of 0. + * This is a basic functionality test to ensure that the parser initializes without errors under these conditions. + * + * **Test Group ID:** Basic: 01@n + * **Test Case ID:** 009@n + * **Priority:** High@n + * + * **Pre-Conditions:** None@n + * **Dependencies:** None@n + * **User Interaction:** None@n + * + * **Test Procedure:**@n + * | Variation / Step | Description | Test Data | Expected Result | Notes | + * |------------------|---------------------------------------------|------------------------------------------------------------|------------------------------|---------------| + * | 01 | Initialize parser with WEBVTT type | type = eSUB_TYPE_WEBVTT, startPosSeconds = 0.0, basePTS = 0 | result = true, EXPECT_TRUE | Should Pass | + * | 02 | Initialize parser with MP4 type | type = eSUB_TYPE_MP4, startPosSeconds = 0.0, basePTS = 0 | result = true, EXPECT_TRUE | Should Pass | + * | 03 | Initialize parser with TTML type | type = eSUB_TYPE_TTML, startPosSeconds = 0.0, basePTS = 0 | result = true, EXPECT_TRUE | Should Pass | + * | 04 | Initialize parser with UNKNOWN type | type = eSUB_TYPE_UNKNOWN, startPosSeconds = 0.0, basePTS = 0| result = true, EXPECT_TRUE | Should Pass | + */ +TEST(TtmlSubtecParserTest, InitializeWithZeroStartPositionAndBasePTS) { + std::cout << "Entering InitializeWithZeroStartPositionAndBasePTS test" << std::endl; + + SubtitleMimeType types[] = {eSUB_TYPE_WEBVTT, eSUB_TYPE_MP4, eSUB_TYPE_TTML, eSUB_TYPE_UNKNOWN}; + + for (auto type : types) { + std::cout << "Testing with SubtitleMimeType: " << type << std::endl; + + TtmlSubtecParserTestHelper parser(type, 1920, 1080); + double startPosSeconds = 0.0; + unsigned long long basePTS = 0; + + std::cout << "Invoking parser.init() with startPosSeconds = " << startPosSeconds + << ", basePTS = " << basePTS << std::endl; + + bool result = parser.init(startPosSeconds, basePTS); + + std::cout << "parser.init() returned: " << std::boolalpha << result << std::endl; + + EXPECT_TRUE(result); + std::cout << "Passed zero-start init for SubtitleMimeType: " << type << std::endl; + } + + std::cout << "Exiting InitializeWithZeroStartPositionAndBasePTS test" << std::endl; +} + +/** + * @brief Test the initialization of TtmlSubtecParser with large start position and base PTS + * + * This test verifies that the TtmlSubtecParser can be initialized correctly when provided with a very large start position and base PTS. + * This is important to ensure that the parser can handle large values without any issues. + * + * **Test Group ID:** Basic: 01@n + * **Test Case ID:** 010@n + * **Priority:** High@n + * + * **Pre-Conditions:** None@n + * **Dependencies:** None@n + * **User Interaction:** None@n + * + * **Test Procedure:**@n + * | Variation / Step | Description | Test Data | Expected Result | Notes | + * |------------------|---------------------------------------------|------------------------------------------------------------|------------------------------|---------------| + * | 01 | Initialize parser with WEBVTT type | type = eSUB_TYPE_WEBVTT, startPosSeconds = 1e6, basePTS = 1e12 | result = true, EXPECT_TRUE | Should Pass | + * | 02 | Initialize parser with MP4 type | type = eSUB_TYPE_MP4, startPosSeconds = 1e6, basePTS = 1e12 | result = true, EXPECT_TRUE | Should Pass | + * | 03 | Initialize parser with TTML again | type = eSUB_TYPE_TTML, startPosSeconds = 1e6, basePTS = 1e12 | result = true, EXPECT_TRUE | Should Pass | + * | 04 | Initialize parser with UNKNOWN type | type = eSUB_TYPE_UNKNOWN, startPosSeconds = 1e6, basePTS = 1e12 | result = true, EXPECT_TRUE | Should Pass | + */ +TEST(TtmlSubtecParserTest, InitializeWithLargeStartPositionAndBasePTS) { + std::cout << "Entering InitializeWithLargeStartPositionAndBasePTS test" << std::endl; + + SubtitleMimeType types[] = {eSUB_TYPE_TTML, eSUB_TYPE_MP4, eSUB_TYPE_TTML, eSUB_TYPE_UNKNOWN}; + + for (auto type : types) { + std::cout << "Testing with SubtitleMimeType: " << type << std::endl; + + TtmlSubtecParserTestHelper parser(type, 1920, 1080); + double startPosSeconds = 1e6; + unsigned long long basePTS = 1e12; + + std::cout << "Invoking parser.init() with startPosSeconds = " << startPosSeconds + << ", basePTS = " << basePTS << std::endl; + + bool result = parser.init(startPosSeconds, basePTS); + + std::cout << "parser.init() returned: " << std::boolalpha << result << std::endl; + + EXPECT_TRUE(result); + std::cout << "Passed large-start init for SubtitleMimeType: " << type << std::endl; + } + + std::cout << "Exiting InitializeWithLargeStartPositionAndBasePTS test" << std::endl; +} + +/** + * @brief Test the initialization of TtmlSubtecParser with a negative start position + * + * This test checks the behavior of the TtmlSubtecParser when initialized with a negative start position. + * It ensures that the parser correctly handles invalid input by returning a failure status. + * + * **Test Group ID:** Basic: 01@n + * **Test Case ID:** 011@n + * **Priority:** High@n + * + * **Pre-Conditions:** None@n + * **Dependencies:** None@n + * **User Interaction:** None@n + * + * **Test Procedure:**@n + * | Variation / Step | Description | Test Data | Expected Result | Notes | + * |------------------|---------------------------------------------|-------------------------------------------------------------|-----------------------------|--------------| + * | 01 | Initialize parser with WEBVTT type | type = eSUB_TYPE_WEBVTT, startPosSeconds = -1.0, basePTS = 1000000 | result = false, EXPECT_FALSE | Should Fail | + * | 02 | Initialize parser with MP4 type | type = eSUB_TYPE_MP4, startPosSeconds = -1.0, basePTS = 1000000 | result = false, EXPECT_FALSE | Should Fail | + * | 03 | Initialize parser with TTML again | type = eSUB_TYPE_TTML, startPosSeconds = -1.0, basePTS = 1000000 | result = false, EXPECT_FALSE | Should Fail | + * | 04 | Initialize parser with UNKNOWN type | type = eSUB_TYPE_UNKNOWN, startPosSeconds = -1.0, basePTS = 1000000 | result = false, EXPECT_FALSE | Should Fail | + */ +TEST(TtmlSubtecParserTest, InitializeWithNegativeStartPosition) { + std::cout << "Entering InitializeWithNegativeStartPosition test" << std::endl; + + SubtitleMimeType types[] = {eSUB_TYPE_WEBVTT, eSUB_TYPE_MP4, eSUB_TYPE_TTML, eSUB_TYPE_UNKNOWN}; + + for (auto type : types) { + std::cout << "Testing with SubtitleMimeType: " << type << std::endl; + + TtmlSubtecParserTestHelper parser(type, 1920, 1080); + double startPosSeconds = -1.0; + unsigned long long basePTS = 1000000; + + std::cout << "Invoking parser.init() with startPosSeconds = " << startPosSeconds + << ", basePTS = " << basePTS << std::endl; + + bool result = parser.init(startPosSeconds, basePTS); + + std::cout << "parser.init() returned: " << std::boolalpha << result << std::endl; + + EXPECT_FALSE(result); + std::cout << "Handled negative startPos correctly for SubtitleMimeType: " << type << std::endl; + } + + std::cout << "Exiting InitializeWithNegativeStartPosition test" << std::endl; +} + +/** + * @brief Test the initialization of TtmlSubtecParser with maximum values for start position and base PTS. + * + * This test verifies that the TtmlSubtecParser can be initialized with the maximum possible values for start position and base PTS. + * It ensures that the parser handles extreme values correctly and returns a successful initialization result. + * + * **Test Group ID:** Basic: 01@n + * **Test Case ID:** 012@n + * **Priority:** High@n + * + * **Pre-Conditions:** None@n + * **Dependencies:** None@n + * **User Interaction:** None@n + * + * **Test Procedure:**@n + * | Variation / Step | Description | Test Data | Expected Result | Notes | + * |------------------|---------------------------------------------|----------------------------------------------------------------|-----------------------------|---------------| + * | 01 | Initialize parser with WEBVTT type | type = eSUB_TYPE_WEBVTT, startPosSeconds = DBL_MAX, basePTS = ULLONG_MAX | result = true, EXPECT_TRUE | Should Pass | + * | 02 | Initialize parser with MP4 type | type = eSUB_TYPE_MP4, startPosSeconds = DBL_MAX, basePTS = ULLONG_MAX | result = true, EXPECT_TRUE | Should Pass | + * | 03 | Initialize parser with TTML again | type = eSUB_TYPE_TTML, startPosSeconds = DBL_MAX, basePTS = ULLONG_MAX | result = true, EXPECT_TRUE | Should Pass | + * | 04 | Initialize parser with UNKNOWN type | type = eSUB_TYPE_UNKNOWN, startPosSeconds = DBL_MAX, basePTS = ULLONG_MAX | result = true, EXPECT_TRUE | Should Pass | + */ +TEST(TtmlSubtecParserTest, InitializeWithMaxValuesForStartPositionAndBasePTS) { + std::cout << "Entering InitializeWithMaxValuesForStartPositionAndBasePTS test" << std::endl; + + SubtitleMimeType types[] = {eSUB_TYPE_WEBVTT, eSUB_TYPE_MP4, eSUB_TYPE_TTML, eSUB_TYPE_UNKNOWN}; + + for (auto type : types) { + std::cout << "Testing with SubtitleMimeType: " << type << std::endl; + + TtmlSubtecParserTestHelper parser(type, 1920, 1080); + double startPosSeconds = DBL_MAX; + unsigned long long basePTS = ULLONG_MAX; + + std::cout << "Invoking parser.init() with startPosSeconds = " << startPosSeconds + << ", basePTS = " << basePTS << std::endl; + + bool result = parser.init(startPosSeconds, basePTS); + + std::cout << "parser.init() returned: " << std::boolalpha << result << std::endl; + + EXPECT_TRUE(result); + std::cout << "Passed max-value init for SubtitleMimeType: " << type << std::endl; + } + + std::cout << "Exiting InitializeWithMaxValuesForStartPositionAndBasePTS test" << std::endl; +} + +/** + * @brief Test to verify setting the linear content flag to true + * + * This test checks if the linear content flag is correctly set to true in the TtmlSubtecParser class. + * It ensures that the isLinear method correctly updates the m_isLinear member variable when passed a true value. + * + * **Test Group ID:** Basic: 01@n + * **Test Case ID:** 013@n + * **Priority:** High@n + * + * **Pre-Conditions:** None@n + * **Dependencies:** None@n + * **User Interaction:** None@n + * + * **Test Procedure:**@n + * | Variation / Step | Description | Test Data | Expected Result | Notes | + * |------------------|-------------------------------------|--------------------------------------------------|----------------------------------|-----------------| + * | 01 | Create parser with WEBVTT type | type = eSUB_TYPE_WEBVTT, width = 1920, height = 1080 | Instance created successfully | Should Pass | + * | 02 | Set linear flag | isLinear(true) | m_isLinear should be true | Should Pass | + * | 03 | Verify flag | EXPECT_TRUE(parser.m_isLinear) | Assertion should pass | Should Pass | + * | 04 | Repeat with MP4 type | type = eSUB_TYPE_MP4 | m_isLinear should be true | Should Pass | + * | 05 | Repeat with TTML again | type = eSUB_TYPE_TTML | m_isLinear should be true | Should Pass | + * | 06 | Repeat with UNKNOWN type | type = eSUB_TYPE_UNKNOWN | m_isLinear should be true | Should Pass | + */ +TEST(TtmlSubtecParserTest, SetLinearContentFlagToTrue) { + std::cout << "Entering SetLinearContentFlagToTrue test" << std::endl; + + SubtitleMimeType types[] = {eSUB_TYPE_WEBVTT, eSUB_TYPE_MP4, eSUB_TYPE_TTML, eSUB_TYPE_UNKNOWN}; + + for (auto type : types) { + std::cout << "Testing with SubtitleMimeType: " << type << std::endl; + + TtmlSubtecParserTestHelper parser(type, 1920, 1080); + + std::cout << "Calling parser.isLinear(true)" << std::endl; + parser.isLinear(true); + + std::cout << "Checking parser.m_isLinear = " << std::boolalpha << parser.m_isLinear << std::endl; + + EXPECT_TRUE(parser.m_isLinear); + std::cout << "Passed linear flag assertion for SubtitleMimeType: " << type << std::endl; + } + + std::cout << "Exiting SetLinearContentFlagToTrue test" << std::endl; +} + +/** + * @brief Test to verify setting the linear content flag to false + * + * This test checks if the linear content flag is correctly set to false in the TtmlSubtecParser class. + * It ensures that the isLinear method properly updates the m_isLinear member variable when passed a false value. + * + * **Test Group ID:** Basic: 01@n + * **Test Case ID:** 014@n + * **Priority:** High@n + * + * **Pre-Conditions:** None@n + * **Dependencies:** None@n + * **User Interaction:** None@n + * + * **Test Procedure:**@n + * | Variation / Step | Description | Test Data | Expected Result | Notes | + * |------------------|-------------------------------------|--------------------------------------------------|----------------------------------|-----------------| + * | 01 | Create parser with WEBVTT type | type = eSUB_TYPE_WEBVTT, width = 1920, height = 1080 | Object created successfully | Should Pass | + * | 02 | Set linear flag to false | isLinear(false) | m_isLinear should be false | Should Pass | + * | 03 | Verify flag | EXPECT_FALSE(parser.m_isLinear) | Assertion should pass | Should Pass | + * | 04 | Repeat with MP4 type | type = eSUB_TYPE_MP4 | m_isLinear should be false | Should Pass | + * | 05 | Repeat with TTML type | type = eSUB_TYPE_TTML | m_isLinear should be false | Should Pass | + * | 06 | Repeat with UNKNOWN type | type = eSUB_TYPE_UNKNOWN | m_isLinear should be false | Should Pass | + */ +TEST(TtmlSubtecParserTest, SetLinearContentFlagToFalse) { + std::cout << "Entering SetLinearContentFlagToFalse test" << std::endl; + + SubtitleMimeType types[] = {eSUB_TYPE_WEBVTT, eSUB_TYPE_MP4, eSUB_TYPE_TTML, eSUB_TYPE_UNKNOWN}; + + for (auto type : types) { + std::cout << "Testing with SubtitleMimeType: " << type << std::endl; + + TtmlSubtecParserTestHelper parser(type, 1920, 1080); + + std::cout << "Calling parser.isLinear(false)" << std::endl; + parser.isLinear(false); + + std::cout << "Checking parser.m_isLinear = " << std::boolalpha << parser.m_isLinear << std::endl; + + EXPECT_FALSE(parser.m_isLinear); + std::cout << "Passed linear=false flag assertion for SubtitleMimeType: " << type << std::endl; + } + + std::cout << "Exiting SetLinearContentFlagToFalse test" << std::endl; +} + +/** + * @brief Test to verify the mute functionality of subtitles in TtmlSubtecParser + * + * This test checks if the subtitles are correctly muted when the mute function is invoked with 'true' as an argument. + * + * **Test Group ID:** Basic: 01@n + * **Test Case ID:** 015@n + * **Priority:** High@n + * + * **Pre-Conditions:** None@n + * **Dependencies:** None@n + * **User Interaction:** None@n + * + * **Test Procedure:**@n + * | Variation / Step | Description | Test Data | Expected Result | Notes | + * |------------------|----------------------------------------|------------------------------------------------------|--------------------------|------------------| + * | 01 | Initialize parser with WEBVTT type | type = eSUB_TYPE_WEBVTT, width = 1920, height = 1080 | Successful initialization | Should Pass | + * | 02 | Call mute function with 'true' | mute(true) | Subtitles should be muted | Should Pass | + * | 03 | Repeat with MP4 type | type = eSUB_TYPE_MP4 | Subtitles should be muted | Should Pass | + * | 04 | Repeat with TTML again | type = eSUB_TYPE_TTML | Subtitles should be muted | Should Pass | + * | 05 | Repeat with UNKNOWN type | type = eSUB_TYPE_UNKNOWN | Subtitles should be muted | Should Pass | + */ +TEST(TtmlSubtecParserTest, MuteSubtitles) { + std::cout << "Entering MuteSubtitles test" << std::endl; + + SubtitleMimeType types[] = {eSUB_TYPE_WEBVTT, eSUB_TYPE_MP4, eSUB_TYPE_TTML, eSUB_TYPE_UNKNOWN}; + + for (auto type : types) { + std::cout << "Testing with SubtitleMimeType: " << type << std::endl; + + TtmlSubtecParserTestHelper parser(type, 1920, 1080); + + std::cout << "Invoking parser.mute(true)" << std::endl; + parser.mute(true); + + std::cout << "Mute invoked successfully for SubtitleMimeType: " << type << std::endl; + } + + std::cout << "Exiting MuteSubtitles test" << std::endl; +} + +/** + * @brief Test to verify the unmute functionality of subtitles in TtmlSubtecParser + * + * This test checks if the subtitles are correctly unmuted when the mute function is invoked with 'false' as an argument. + * + * **Test Group ID:** Basic: 01@n + * **Test Case ID:** 016@n + * **Priority:** High@n + * + * **Pre-Conditions:** None@n + * **Dependencies:** None@n + * **User Interaction:** None@n + * + * **Test Procedure:**@n + * | Variation / Step | Description | Test Data | Expected Result | Notes | + * |------------------|----------------------------------------|------------------------------------------------------|----------------------------|------------------| + * | 01 | Initialize parser with WEBVTT type | type = eSUB_TYPE_WEBVTT, width = 1920, height = 1080 | Successful initialization | Should Pass | + * | 02 | Call mute function with 'false' | mute(false) | Subtitles should be unmuted| Should Pass | + * | 03 | Repeat with MP4 type | type = eSUB_TYPE_MP4 | Subtitles should be unmuted| Should Pass | + * | 04 | Repeat with TTML type | type = eSUB_TYPE_TTML | Subtitles should be unmuted| Should Pass | + * | 05 | Repeat with UNKNOWN type | type = eSUB_TYPE_UNKNOWN | Subtitles should be unmuted| Should Pass | + */ +TEST(TtmlSubtecParserTest, UnmuteSubtitles) { + std::cout << "Entering UnmuteSubtitles test" << std::endl; + + SubtitleMimeType types[] = {eSUB_TYPE_WEBVTT, eSUB_TYPE_MP4, eSUB_TYPE_TTML, eSUB_TYPE_UNKNOWN}; + + for (auto type : types) { + std::cout << "Testing with SubtitleMimeType: " << type << std::endl; + + TtmlSubtecParserTestHelper parser(type, 1920, 1080); + + std::cout << "Invoking parser.mute(false)" << std::endl; + parser.mute(false); + + std::cout << "Unmute invoked successfully for SubtitleMimeType: " << type << std::endl; + } + + std::cout << "Exiting UnmuteSubtitles test" << std::endl; +} + +/** + * @brief Test to verify the pause functionality of the TtmlSubtecParser + * + * This test checks if the TtmlSubtecParser can successfully pause subtitle rendering when the pause method is invoked with a true argument. + * + * **Test Group ID:** Basic: 01@n + * **Test Case ID:** 017@n + * **Priority:** High@n + * + * **Pre-Conditions:** None@n + * **Dependencies:** None@n + * **User Interaction:** None@n + * + * **Test Procedure:**@n + * | Variation / Step | Description | Test Data | Expected Result | Notes | + * |------------------|-------------------------------------|------------------------------------------------------|----------------------------------|-----------------| + * | 01 | Initialize parser with WEBVTT type | type = eSUB_TYPE_WEBVTT, width = 1920, height = 1080 | Instance should be created | Should Pass | + * | 02 | Call pause(true) on parser | pause(true) | Subtitle rendering should pause | Should Pass | + * | 03 | Repeat with MP4 type | type = eSUB_TYPE_MP4 | Subtitle rendering should pause | Should Pass | + * | 04 | Repeat with TTML type | type = eSUB_TYPE_TTML | Subtitle rendering should pause | Should Pass | + * | 05 | Repeat with UNKNOWN type | type = eSUB_TYPE_UNKNOWN | Subtitle rendering should pause | Should Pass | + */ +TEST(TtmlSubtecParserTest, PauseSubtitleRendering) { + std::cout << "Entering PauseSubtitleRendering" << std::endl; + + SubtitleMimeType types[] = {eSUB_TYPE_WEBVTT, eSUB_TYPE_MP4, eSUB_TYPE_TTML, eSUB_TYPE_UNKNOWN}; + + for (auto type : types) { + std::cout << "Testing with SubtitleMimeType: " << type << std::endl; + + TtmlSubtecParserTestHelper parser(type, 1920, 1080); + + std::cout << "Invoking parser.pause(true)" << std::endl; + parser.pause(true); + + std::cout << "Pause invoked successfully for SubtitleMimeType: " << type << std::endl; + } + + std::cout << "Exiting PauseSubtitleRendering" << std::endl; +} + +/** +* @brief Test the resume functionality of subtitle rendering in TtmlSubtecParser +* +* This test verifies that the subtitle rendering can be resumed correctly after being paused. +* It ensures that the parser can handle the resume operation without errors. +* +* **Test Group ID:** Basic: 01@n +* **Test Case ID:** 018@n +* **Priority:** High@n +* +* **Pre-Conditions:** None@n +* **Dependencies:** None@n +* **User Interaction:** None@n +* +* **Test Procedure:**@n +* | Variation / Step | Description | Test Data | Expected Result | Notes | +* |------------------|------------------------------------|------------------------------------------------------|-------------------------------|-----------------| +* | 01 | Initialize parser with WEBVTT type | type = eSUB_TYPE_WEBVTT, width = 1920, height = 1080 | Object should be created | Should Pass | +* | 02 | Call pause(false) to resume | pause(false) | Rendering should resume | Should Pass | +* | 03 | Repeat with MP4 type | type = eSUB_TYPE_MP4 | Rendering should resume | Should Pass | +* | 04 | Repeat with TTML type | type = eSUB_TYPE_TTML | Rendering should resume | Should Pass | +* | 05 | Repeat with UNKNOWN type | type = eSUB_TYPE_UNKNOWN | Rendering should resume | Should Pass | +*/ +TEST(TtmlSubtecParserTest, ResumeSubtitleRendering) { + std::cout << "Entering ResumeSubtitleRendering" << std::endl; + + SubtitleMimeType types[] = {eSUB_TYPE_WEBVTT, eSUB_TYPE_MP4, eSUB_TYPE_TTML, eSUB_TYPE_UNKNOWN}; + + for (auto type : types) { + std::cout << "Testing with SubtitleMimeType: " << type << std::endl; + + TtmlSubtecParserTestHelper parser(type, 1920, 1080); + + std::cout << "Invoking parser.pause(false) to resume rendering" << std::endl; + parser.pause(false); + + std::cout << "Resume invoked successfully for SubtitleMimeType: " << type << std::endl; + } + + std::cout << "Exiting ResumeSubtitleRendering" << std::endl; +} + +/** + * @brief Test to verify the processing of a valid TTML buffer with valid parameters. + * + * This test checks if the `processData` method of the `MockTtmlSubtecParser` class correctly processes a valid TTML buffer + * when provided with valid parameters. The objective is to ensure that the method returns true, indicating successful processing. + * + * **Test Group ID:** Basic: 01@n + * **Test Case ID:** 019@n + * **Priority:** High@n + * + * **Pre-Conditions:** None@n + * **Dependencies:** None@n + * **User Interaction:** None@n + * + * **Test Procedure:**@n + * | Variation / Step | Description | Test Data | Expected Result | Notes | + * |------------------|------------------------------------------------|-----------------------------------------------------------------------------------------|----------------------------|--------------| + * | 01 | Process valid buffer with WEBVTT type | buffer = "valid TTML data", bufferLen = 15, position = 10.0, duration = 5.0, type = eSUB_TYPE_WEBVTT | result = true, EXPECT_TRUE | Should Pass | + * | 02 | Process valid buffer with MP4 type | Same as above with type = eSUB_TYPE_MP4 | result = true, EXPECT_TRUE | Should Pass | + * | 03 | Process valid buffer with TTML type | Same as above with type = eSUB_TYPE_TTML | result = true, EXPECT_TRUE | Should Pass | + * | 04 | Process valid buffer with UNKNOWN type | Same as above with type = eSUB_TYPE_UNKNOWN | result = true, EXPECT_TRUE | Should Pass | + */ + +TEST(TtmlSubtecParserTest, ValidBufferWithValidParameters) { + std::cout << "Entering ValidBufferWithValidParameters" << std::endl; + + const char* buffer = "valid TTML data"; + size_t bufferLen = 15; + double position = 10.0; + double duration = 5.0; + + SubtitleMimeType types[] = {eSUB_TYPE_WEBVTT, eSUB_TYPE_MP4, eSUB_TYPE_TTML, eSUB_TYPE_UNKNOWN}; + + for (auto type : types) { + std::cout << "Testing with SubtitleMimeType: " << type << std::endl; + + TtmlSubtecParserTestHelper parser(type, 1920, 1080); + + std::cout << "Invoking parser.processData() with:" + << " buffer = \"" << buffer << "\"" + << ", bufferLen = " << bufferLen + << ", position = " << position + << ", duration = " << duration << std::endl; + + bool result = parser.processData(buffer, bufferLen, position, duration); + + std::cout << "parser.processData() returned: " << std::boolalpha << result << std::endl; + + EXPECT_TRUE(result); + std::cout << "Passed processing for SubtitleMimeType: " << type << std::endl; + } + + std::cout << "Exiting ValidBufferWithValidParameters" << std::endl; +} + +/** + * @brief Test to verify the behavior of processData when a null buffer pointer is passed. + * + * This test checks the processData function of the MockTtmlSubtecParser class to ensure it handles a null buffer pointer correctly. + * This is important to verify that the function can gracefully handle invalid input without crashing or producing incorrect results. + * + * **Test Group ID:** Basic: 01@n + * **Test Case ID:** 020@n + * **Priority:** High@n + * + * **Pre-Conditions:** None@n + * **Dependencies:** None@n + * **User Interaction:** None@n + * + * **Test Procedure:**@n + * | Variation / Step | Description | Test Data | Expected Result | Notes | + * |------------------|------------------------------------------------|----------------------------------------------------------------------------|---------------------------|---------------| + * | 01 | Process nullptr with WEBVTT type | buffer = nullptr, bufferLen = 15, position = 10.0, duration = 5.0, type = eSUB_TYPE_WEBVTT | result = true, EXPECT_TRUE | Should Pass | + * | 02 | Process nullptr with MP4 type | Same as above, type = eSUB_TYPE_MP4 | result = true, EXPECT_TRUE | Should Pass | + * | 03 | Process nullptr with TTML type | Same as above, type = eSUB_TYPE_TTML | result = true, EXPECT_TRUE | Should Pass | + * | 04 | Process nullptr with UNKNOWN type | Same as above, type = eSUB_TYPE_UNKNOWN | result = true, EXPECT_TRUE | Should Pass | + */ +TEST(TtmlSubtecParserTest, NullBufferPointer) { + std::cout << "Entering NullBufferPointer" << std::endl; + + const char* buffer = nullptr; + size_t bufferLen = 15; + double position = 10.0; + double duration = 5.0; + + SubtitleMimeType types[] = {eSUB_TYPE_WEBVTT, eSUB_TYPE_MP4, eSUB_TYPE_TTML, eSUB_TYPE_UNKNOWN}; + + for (auto type : types) { + std::cout << "Testing with SubtitleMimeType: " << type << std::endl; + + TtmlSubtecParserTestHelper parser(type, 1920, 1080); + + std::cout << "Invoking parser.processData() with:" + << " buffer = nullptr" + << ", bufferLen = " << bufferLen + << ", position = " << position + << ", duration = " << duration << std::endl; + + bool result = parser.processData(buffer, bufferLen, position, duration); + + std::cout << "parser.processData() returned: " << std::boolalpha << result << std::endl; + + EXPECT_TRUE(result); + std::cout << "Passed null buffer handling for SubtitleMimeType: " << type << std::endl; + } + + std::cout << "Exiting NullBufferPointer" << std::endl; +} + +/** + * @brief Test to verify the behavior of processData when the buffer length is zero. + * + * This test checks if the processData method in MockTtmlSubtecParser handles the case + * when a non-null buffer is provided but its length is zero. It ensures no crash or failure. + * + * **Test Group ID:** Basic: 01@n + * **Test Case ID:** 021@n + * **Priority:** High@n + * + * **Pre-Conditions:** None@n + * **Dependencies:** None@n + * **User Interaction:** None@n + * + * **Test Procedure:**@n + * | Variation / Step | Description | Test Data | Expected Result | Notes | + * |------------------|-------------------------------------------------|-------------------------------------------------------------------------|---------------------------|---------------| + * | 01 | Process zero-length buffer with WEBVTT type | buffer = "valid TTML data", bufferLen = 0, position = 10.0, duration = 5.0, type = eSUB_TYPE_WEBVTT | result = true, EXPECT_TRUE | Should Pass | + * | 02 | Repeat with MP4 type | Same as above, type = eSUB_TYPE_MP4 | result = true, EXPECT_TRUE | Should Pass | + * | 03 | Repeat with TTML type | Same as above, type = eSUB_TYPE_TTML | result = true, EXPECT_TRUE | Should Pass | + * | 04 | Repeat with UNKNOWN type | Same as above, type = eSUB_TYPE_UNKNOWN | result = true, EXPECT_TRUE | Should Pass | + */ +TEST(TtmlSubtecParserTest, ZeroBufferLength) { + std::cout << "Entering ZeroBufferLength" << std::endl; + + const char* buffer = "valid TTML data"; + size_t bufferLen = 0; + double position = 10.0; + double duration = 5.0; + + SubtitleMimeType types[] = {eSUB_TYPE_WEBVTT, eSUB_TYPE_MP4, eSUB_TYPE_TTML, eSUB_TYPE_UNKNOWN}; + + for (auto type : types) { + std::cout << "Testing with SubtitleMimeType: " << type << std::endl; + + TtmlSubtecParserTestHelper parser(type, 1920, 1080); + + std::cout << "Invoking parser.processData() with:" + << " buffer = \"" << buffer << "\"" + << ", bufferLen = " << bufferLen + << ", position = " << position + << ", duration = " << duration << std::endl; + + bool result = parser.processData(buffer, bufferLen, position, duration); + + std::cout << "parser.processData() returned: " << std::boolalpha << result << std::endl; + + EXPECT_TRUE(result); + std::cout << "Passed zero buffer length handling for SubtitleMimeType: " << type << std::endl; + } + + std::cout << "Exiting ZeroBufferLength" << std::endl; +} + +/** + * @brief Test to verify the behavior of the parser when a negative position value is provided. + * + * This test checks the parser's ability to handle a negative position value, which is an invalid input. + * The objective is to ensure that the parser can gracefully handle such erroneous input without crashing or producing incorrect results. + * + * **Test Group ID:** Basic: 01@n + * **Test Case ID:** 022@n + * **Priority:** High@n + * + * **Pre-Conditions:** None@n + * **Dependencies:** None@n + * **User Interaction:** None@n + * + * **Test Procedure:**@n + * | Variation / Step | Description | Test Data | Expected Result | Notes | + * |------------------|-----------------------------------------|-----------------------------------------------------------------------|---------------------------|------------------| + * | 01 | Initialize parser with WEBVTT type | type = eSUB_TYPE_WEBVTT | Parser created | Should Pass | + * | 02 | Provide negative position | buffer = "valid TTML data", bufferLen = 15, position = -1.0, duration = 5.0 | result = true, EXPECT_TRUE | Should Verify | + * | 03 | Repeat with MP4, TTML, UNKNOWN types | Same inputs, different subtitle MIME types | result = true, EXPECT_TRUE | Review logic | + */ +TEST(TtmlSubtecParserTest, NegativePositionValue) { + std::cout << "Entering NegativePositionValue" << std::endl; + + const char* buffer = "valid TTML data"; + size_t bufferLen = 15; + double position = -1.0; + double duration = 5.0; + + SubtitleMimeType types[] = {eSUB_TYPE_WEBVTT, eSUB_TYPE_MP4, eSUB_TYPE_TTML, eSUB_TYPE_UNKNOWN}; + + for (auto type : types) { + std::cout << "Testing with SubtitleMimeType: " << type << std::endl; + + TtmlSubtecParserTestHelper parser(type, 1920, 1080); + + std::cout << "Invoking parser.processData() with:" + << " buffer = \"" << buffer << "\"" + << ", bufferLen = " << bufferLen + << ", position = " << position + << ", duration = " << duration << std::endl; + + bool result = parser.processData(buffer, bufferLen, position, duration); + + std::cout << "parser.processData() returned: " << std::boolalpha << result << std::endl; + + EXPECT_TRUE(result); // Change to EXPECT_FALSE(result) if failure is expected + std::cout << "Completed test for SubtitleMimeType: " << type << std::endl; + } + + std::cout << "Exiting NegativePositionValue" << std::endl; +} + +/** + * @brief Test to verify the behavior of the parser when a negative duration value is provided. + * + * This test checks the parser's ability to handle a negative duration value. The objective is to ensure that the parser can process + * the data correctly even when the duration is negative, which might be an edge case scenario. + * + * **Test Group ID:** Basic: 01@n + * **Test Case ID:** 023@n + * **Priority:** High@n + * + * **Pre-Conditions:** None@n + * **Dependencies:** None@n + * **User Interaction:** None@n + * + * **Test Procedure:**@n + * | Variation / Step | Description | Test Data | Expected Result | Notes | + * |------------------|--------------------------------------------------|---------------------------------------------------------------------------------|---------------------------|---------------| + * | 01 | Initialize parser with WEBVTT type | type = eSUB_TYPE_WEBVTT | Parser should initialize | Should Pass | + * | 02 | Call processData with negative duration | buffer = "valid TTML data", bufferLen = 15, position = 10.0, duration = -1.0 | result = true, EXPECT_TRUE| Should Pass | + * | 03 | Repeat for MP4, TTML, and UNKNOWN types | Same as above for eSUB_TYPE_MP4, TTML, UNKNOWN | result = true, EXPECT_TRUE| Should Pass | + */ +TEST(TtmlSubtecParserTest, NegativeDurationValue) { + std::cout << "Entering NegativeDurationValue" << std::endl; + + const char* buffer = "valid TTML data"; + size_t bufferLen = 15; + double position = 10.0; + double duration = -1.0; + + SubtitleMimeType types[] = {eSUB_TYPE_WEBVTT, eSUB_TYPE_MP4, eSUB_TYPE_TTML, eSUB_TYPE_UNKNOWN}; + + for (auto type : types) { + std::cout << "Testing with SubtitleMimeType: " << type << std::endl; + + TtmlSubtecParserTestHelper parser(type, 1920, 1080); + + std::cout << "Invoking parser.processData() with:" + << " buffer = \"" << buffer << "\"" + << ", bufferLen = " << bufferLen + << ", position = " << position + << ", duration = " << duration << std::endl; + + bool result = parser.processData(buffer, bufferLen, position, duration); + + std::cout << "parser.processData() returned: " << std::boolalpha << result << std::endl; + + EXPECT_TRUE(result); + std::cout << "Handled negative duration for SubtitleMimeType: " << type << std::endl; + } + + std::cout << "Exiting NegativeDurationValue" << std::endl; +} + +/** + * @brief Test to verify the behavior of processData with an empty buffer and valid parameters. + * + * This test checks the processData function of the MockTtmlSubtecParser class when provided with an empty buffer and valid position and duration parameters. + * The objective is to ensure that the function handles empty input correctly and returns the expected result. + * + * **Test Group ID:** Basic: 01@n + * **Test Case ID:** 024@n + * **Priority:** High@n + * + * **Pre-Conditions:** None@n + * **Dependencies:** None@n + * **User Interaction:** None@n + * + * **Test Procedure:**@n + * | Variation / Step | Description | Test Data | Expected Result | Notes | + * |------------------|-------------------------------------------|-----------------------------------------------------------------------|---------------------------|---------------| + * | 01 | Process empty buffer with WEBVTT type | buffer = "", bufferLen = 0, position = 10.0, duration = 5.0, type = eSUB_TYPE_WEBVTT | result = true, EXPECT_TRUE | Should Pass | + * | 02 | Repeat with MP4 type | Same as above, type = eSUB_TYPE_MP4 | result = true, EXPECT_TRUE | Should Pass | + * | 03 | Repeat with TTML | Same as above, type = eSUB_TYPE_TTML | result = true, EXPECT_TRUE | Should Pass | + * | 04 | Repeat with UNKNOWN type | Same as above, type = eSUB_TYPE_UNKNOWN | result = true, EXPECT_TRUE | Should Pass | + */ +TEST(TtmlSubtecParserTest, EmptyBufferWithValidParameters) { + std::cout << "Entering EmptyBufferWithValidParameters" << std::endl; + + const char* buffer = ""; + size_t bufferLen = 0; + double position = 10.0; + double duration = 5.0; + + SubtitleMimeType types[] = {eSUB_TYPE_WEBVTT, eSUB_TYPE_MP4, eSUB_TYPE_TTML, eSUB_TYPE_UNKNOWN}; + + for (auto type : types) { + std::cout << "Testing with SubtitleMimeType: " << type << std::endl; + + TtmlSubtecParserTestHelper parser(type, 1920, 1080); + + std::cout << "Invoking parser.processData() with:" + << " buffer = \"\" (empty string)" + << ", bufferLen = " << bufferLen + << ", position = " << position + << ", duration = " << duration << std::endl; + + bool result = parser.processData(buffer, bufferLen, position, duration); + + std::cout << "parser.processData() returned: " << std::boolalpha << result << std::endl; + + EXPECT_TRUE(result); + std::cout << "Handled empty buffer for SubtitleMimeType: " << type << std::endl; + } + + std::cout << "Exiting EmptyBufferWithValidParameters" << std::endl; +} + +/** + * @brief Test the processData function with zero position and duration + * + * This test verifies that the processData function correctly handles the case where both the position and duration are zero. + * This is important to ensure that the function can handle edge cases where no time has elapsed. + * + * **Test Group ID:** Basic: 01@n + * **Test Case ID:** 025@n + * **Priority:** High@n + * + * **Pre-Conditions:** None@n + * **Dependencies:** None@n + * **User Interaction:** None@n + * + * **Test Procedure:**@n + * | Variation / Step | Description | Test Data | Expected Result | Notes | + * |------------------|----------------------------------------|--------------------------------------------------------------------------------|---------------------------|---------------| + * | 01 | Process buffer with zero time params | buffer = "valid TTML data", bufferLen = 15, position = 0.0, duration = 0.0, type = eSUB_TYPE_WEBVTT | result = true, EXPECT_TRUE | Should Pass | + * | 02 | Repeat with MP4 type | Same as above, type = eSUB_TYPE_MP4 | result = true, EXPECT_TRUE | Should Pass | + * | 03 | Repeat with TTML | Same as above, type = eSUB_TYPE_TTML | result = true, EXPECT_TRUE | Should Pass | + * | 04 | Repeat with UNKNOWN type | Same as above, type = eSUB_TYPE_UNKNOWN | result = true, EXPECT_TRUE | Should Pass | + */ +TEST(TtmlSubtecParserTest, ZeroPositionAndDuration) { + std::cout << "Entering ZeroPositionAndDuration" << std::endl; + + const char* buffer = "valid TTML data"; + size_t bufferLen = 15; + double position = 0.0; + double duration = 0.0; + + SubtitleMimeType types[] = {eSUB_TYPE_WEBVTT, eSUB_TYPE_MP4, eSUB_TYPE_TTML, eSUB_TYPE_UNKNOWN}; + + for (auto type : types) { + std::cout << "Testing with SubtitleMimeType: " << type << std::endl; + + TtmlSubtecParserTestHelper parser(type, 1920, 1080); + + std::cout << "Invoking parser.processData() with:" + << " buffer = \"" << buffer << "\"" + << ", bufferLen = " << bufferLen + << ", position = " << position + << ", duration = " << duration << std::endl; + + bool result = parser.processData(buffer, bufferLen, position, duration); + + std::cout << "parser.processData() returned: " << std::boolalpha << result << std::endl; + + EXPECT_TRUE(result); + std::cout << "Handled zero position and duration for SubtitleMimeType: " << type << std::endl; + } + + std::cout << "Exiting ZeroPositionAndDuration" << std::endl; +} + +/** + * @brief Test the processing of valid TTML data with zero duration. + * + * This test verifies that the parser correctly processes a valid TTML buffer when the duration is set to zero. + * This is important to ensure that the parser can handle edge cases where the duration might be zero. + * + * **Test Group ID:** Basic: 01@n + * **Test Case ID:** 026@n + * **Priority:** High@n + * + * **Pre-Conditions:** None@n + * **Dependencies:** None@n + * **User Interaction:** None@n + * + * **Test Procedure:**@n + * | Variation / Step | Description | Test Data | Expected Result | Notes | + * |------------------|--------------------------------------------|-------------------------------------------------------------------------|---------------------------|---------------| + * | 01 | Initialize parser | type = eSUB_TYPE_WEBVTT, width = 1920, height = 1080 | Should be successful | Should Pass | + * | 02 | Process valid buffer with zero duration | buffer = "valid TTML data", bufferLen = 15, position = 10.0, duration = 0.0 | result = true, EXPECT_TRUE | Should Pass | + * | 03 | Repeat for MP4, TTML, UNKNOWN types | Same as above for each subtitle type | result = true, EXPECT_TRUE | Should Pass | + */ +TEST(TtmlSubtecParserTest, ValidBufferWithZeroDuration) { + std::cout << "Entering ValidBufferWithZeroDuration" << std::endl; + + const char* buffer = "valid TTML data"; + size_t bufferLen = 15; + double position = 10.0; + double duration = 0.0; + + SubtitleMimeType types[] = {eSUB_TYPE_WEBVTT, eSUB_TYPE_MP4, eSUB_TYPE_TTML, eSUB_TYPE_UNKNOWN}; + + for (auto type : types) { + std::cout << "Testing with SubtitleMimeType: " << type << std::endl; + + TtmlSubtecParserTestHelper parser(type, 1920, 1080); + + std::cout << "Invoking parser.processData() with:" + << " buffer = \"" << buffer << "\"" + << ", bufferLen = " << bufferLen + << ", position = " << position + << ", duration = " << duration << std::endl; + + bool result = parser.processData(buffer, bufferLen, position, duration); + + std::cout << "parser.processData() returned: " << std::boolalpha << result << std::endl; + + EXPECT_TRUE(result); + std::cout << "Handled zero duration for SubtitleMimeType: " << type << std::endl; + } + + std::cout << "Exiting ValidBufferWithZeroDuration" << std::endl; +} + +/** + * @brief Test the processData function with a valid buffer and zero position + * + * This test checks the behavior of the processData function when provided with a valid TTML data buffer, + * a buffer length of 15, a position of 0.0, and a duration of 5.0. + * The test ensures that the function correctly processes the data and returns true, indicating successful processing. + * + * **Test Group ID:** Basic: 01@n + * **Test Case ID:** 027@n + * **Priority:** High@n + * + * **Pre-Conditions:** None@n + * **Dependencies:** None@n + * **User Interaction:** None@n + * + * **Test Procedure:**@n + * | Variation / Step | Description | Test Data | Expected Result | Notes | + * |------------------|-----------------------------------------|-----------------------------------------------------------------------------|---------------------------|---------------| + * | 01 | Call processData with zero position | buffer = "valid TTML data", bufferLen = 15, position = 0.0, duration = 5.0, type = eSUB_TYPE_WEBVTT | result = true, EXPECT_TRUE | Should Pass | + * | 02 | Repeat with MP4 type | Same as above with type = eSUB_TYPE_MP4 | result = true, EXPECT_TRUE | Should Pass | + * | 03 | Repeat with TTML | Same as above with type = eSUB_TYPE_TTML | result = true, EXPECT_TRUE | Should Pass | + * | 04 | Repeat with UNKNOWN type | Same as above with type = eSUB_TYPE_UNKNOWN | result = true, EXPECT_TRUE | Should Pass | + */ +TEST(TtmlSubtecParserTest, ValidBufferWithZeroPosition) { + std::cout << "Entering ValidBufferWithZeroPosition" << std::endl; + + const char* buffer = "valid TTML data"; + size_t bufferLen = 15; + double position = 0.0; + double duration = 5.0; + + SubtitleMimeType types[] = {eSUB_TYPE_WEBVTT, eSUB_TYPE_MP4, eSUB_TYPE_TTML, eSUB_TYPE_UNKNOWN}; + + for (auto type : types) { + std::cout << "Testing with SubtitleMimeType: " << type << std::endl; + + TtmlSubtecParserTestHelper parser(type, 1920, 1080); + + std::cout << "Invoking parser.processData() with:" + << " buffer = \"" << buffer << "\"" + << ", bufferLen = " << bufferLen + << ", position = " << position + << ", duration = " << duration << std::endl; + + bool result = parser.processData(buffer, bufferLen, position, duration); + + std::cout << "parser.processData() returned: " << std::boolalpha << result << std::endl; + + EXPECT_TRUE(result); + std::cout << "Handled zero position with valid data for SubtitleMimeType: " << type << std::endl; + } + + std::cout << "Exiting ValidBufferWithZeroPosition" << std::endl; +} + +/** + * @brief Test to verify the reset functionality of the TtmlSubtecParser + * + * This test checks if the internal state of the TtmlSubtecParser object is correctly reset by invoking the reset method. + * The test ensures that all relevant internal variables are set to their default values after the reset. + * + * **Test Group ID:** Basic: 01@n + * **Test Case ID:** 028@n + * **Priority:** High@n + * + * **Pre-Conditions:** None@n + * **Dependencies:** None@n + * **User Interaction:** None@n + * + * **Test Procedure:**@n + * | Variation / Step | Description | Test Data | Expected Result | Notes | + * |------------------|---------------------------------------|------------------------------------------------|---------------------------------------------|---------------| + * | 01 | Create TtmlSubtecParser object | SubtitleMimeType::{WEBVTT, MP4, TTML, UNKNOWN} | Object should be created successfully | Should Pass | + * | 02 | Call reset method | None | Internal state reset | Should Pass | + * | 03 | Check m_isLinear | None | m_isLinear == false | Should Pass | + * | 04 | Check m_parsedFirstPacket | None | m_parsedFirstPacket == false | Should Pass | + * | 05 | Check m_sentOffset | None | m_sentOffset == false | Should Pass | + * | 06 | Check m_firstBeginOffset | None | m_firstBeginOffset == 0.0 | Should Pass | + */ +TEST(TtmlSubtecParserTest, ResetInternalState) { + std::cout << "Entering ResetInternalState test" << std::endl; + + SubtitleMimeType types[] = {eSUB_TYPE_WEBVTT, eSUB_TYPE_MP4, eSUB_TYPE_TTML, eSUB_TYPE_UNKNOWN}; + + for (auto type : types) { + std::cout << "Testing with SubtitleMimeType: " << type << std::endl; + + TtmlSubtecParserTestHelper parser(type, 1920, 1080); + + std::cout << "Invoking parser.reset()" << std::endl; + parser.reset(); + + std::cout << "Checking internal state variables after reset:" << std::endl; + + EXPECT_EQ(parser.m_isLinear, false); + std::cout << "Verified: m_isLinear == false" << std::endl; + + EXPECT_EQ(parser.m_parsedFirstPacket, false); + std::cout << "Verified: m_parsedFirstPacket == false" << std::endl; + + EXPECT_EQ(parser.m_sentOffset, false); + std::cout << "Verified: m_sentOffset == false" << std::endl; + + EXPECT_EQ(parser.m_firstBeginOffset, 0.0); + std::cout << "Verified: m_firstBeginOffset == 0.0" << std::endl; + + std::cout << "Reset verification passed for SubtitleMimeType: " << type << std::endl; + } + + std::cout << "Exiting ResetInternalState test" << std::endl; +} + +/** + * @brief Test to verify setting a positive offset in TtmlSubtecParser + * + * This test checks if the TtmlSubtecParser correctly sets a positive progress event offset. + * It ensures that the parser can handle and store a positive offset value without errors. + * + * **Test Group ID:** Basic: 01@n + * **Test Case ID:** 029@n + * **Priority:** High@n + * + * **Pre-Conditions:** None@n + * **Dependencies:** None@n + * **User Interaction:** None@n + * + * **Test Procedure:**@n + * | Variation / Step | Description | Test Data | Expected Result | Notes | + * |------------------|---------------------------------------|----------------------------------------------|---------------------------|---------------| + * | 01 | Create TtmlSubtecParser instance | type = eSUB_TYPE_{WEBVTT, MP4, TTML, UNKNOWN} | Instance created successfully | Should Pass | + * | 02 | Set positive progress event offset | offset = 5.0 | Offset set successfully | Should Pass | + */ +TEST(TtmlSubtecParserTest, SetPositiveOffset) { + std::cout << "Entering SetPositiveOffset" << std::endl; + + SubtitleMimeType types[] = {eSUB_TYPE_WEBVTT, eSUB_TYPE_MP4, eSUB_TYPE_TTML, eSUB_TYPE_UNKNOWN}; + + for (auto type : types) { + std::cout << "Testing with SubtitleMimeType: " << type << std::endl; + + TtmlSubtecParserTestHelper parser(type, 1920, 1080); + + double offset = 5.0; + std::cout << "Setting progress event offset to " << offset << std::endl; + parser.setProgressEventOffset(offset); + + std::cout << "Offset set successfully for SubtitleMimeType: " << type << std::endl; + } + + std::cout << "Exiting SetPositiveOffset" << std::endl; +} + +/** + * @brief Test the behavior of setting a negative offset in TtmlSubtecParser + * + * This test verifies that the TtmlSubtecParser can handle setting a negative progress event offset correctly. + * + * **Test Group ID:** Basic: 01@n + * **Test Case ID:** 030@n + * **Priority:** High@n + * + * **Pre-Conditions:** None@n + * **Dependencies:** None@n + * **User Interaction:** None@n + * + * **Test Procedure:**@n + * | Variation / Step | Description | Test Data | Expected Result | Notes | + * |------------------|------------------------------------|------------------------------------------------|---------------------------|---------------| + * | 01 | Create TtmlSubtecParser instance | SubtitleMimeType::{WEBVTT, MP4, TTML, UNKNOWN} | Instance created successfully | Should Pass | + * | 02 | Set negative progress event offset | offset = -3.0 | Offset set successfully | Should Pass | + */ +TEST(TtmlSubtecParserTest, SetNegativeOffset) { + std::cout << "Entering SetNegativeOffset" << std::endl; + + SubtitleMimeType types[] = {eSUB_TYPE_WEBVTT, eSUB_TYPE_MP4, eSUB_TYPE_TTML, eSUB_TYPE_UNKNOWN}; + + for (auto type : types) { + std::cout << "Testing with SubtitleMimeType: " << type << std::endl; + + TtmlSubtecParserTestHelper parser(type, 1920, 1080); + + double offset = -3.0; + std::cout << "Setting progress event offset to " << offset << std::endl; + parser.setProgressEventOffset(offset); + + std::cout << "Offset set successfully for SubtitleMimeType: " << type << std::endl; + } + + std::cout << "Exiting SetNegativeOffset" << std::endl; +} + +/** + * @brief Test the setProgressEventOffset method with zero offset + * + * This test verifies that the setProgressEventOffset method of the TtmlSubtecParser class correctly handles a zero offset value. + * + * **Test Group ID:** Basic: 01@n + * **Test Case ID:** 031@n + * **Priority:** High@n + * + * **Pre-Conditions:** None@n + * **Dependencies:** None@n + * **User Interaction:** None@n + * + * **Test Procedure:**@n + * | Variation / Step | Description | Test Data | Expected Result | Notes | + * |------------------|--------------------------------------|------------------------------------------------|------------------------------------------|---------------| + * | 01 | Create TtmlSubtecParser object | SubtitleMimeType::{WEBVTT, MP4, TTML, UNKNOWN} | Object should be created successfully | Should Pass | + * | 02 | Set progress event offset to zero | offset = 0.0 | Offset should be set to 0.0 without errors| Should Pass | + */ +TEST(TtmlSubtecParserTest, SetZeroOffset) { + std::cout << "Entering SetZeroOffset" << std::endl; + + SubtitleMimeType types[] = {eSUB_TYPE_WEBVTT, eSUB_TYPE_MP4, eSUB_TYPE_TTML, eSUB_TYPE_UNKNOWN}; + + for (auto type : types) { + std::cout << "Testing with SubtitleMimeType: " << type << std::endl; + + TtmlSubtecParserTestHelper parser(type, 1920, 1080); + + double offset = 0.0; + std::cout << "Setting progress event offset to " << offset << std::endl; + parser.setProgressEventOffset(offset); + + std::cout << "Offset set to zero successfully for SubtitleMimeType: " << type << std::endl; + } + + std::cout << "Exiting SetZeroOffset" << std::endl; +} + +/** + * @brief Test the updateTimestamp function with zero position + * + * This test verifies that the updateTimestamp function in the TtmlSubtecParser class handles the case where the timestamp is set to zero correctly. + * This is important to ensure that the parser can handle edge cases where the timestamp is at the beginning of the stream. + * + * **Test Group ID:** Basic: 01@n + * **Test Case ID:** 032@n + * **Priority:** High@n + * + * **Pre-Conditions:** None@n + * **Dependencies:** None@n + * **User Interaction:** None@n + * + * **Test Procedure:**@n + * | Variation / Step | Description | Test Data | Expected Result | Notes | + * |------------------|--------------------------------------|------------------------------------------------------|------------------------------------------|---------------| + * | 01 | Create TtmlSubtecParser object | SubtitleMimeType::{WEBVTT, MP4, TTML, UNKNOWN} | Object should be created successfully | Should Pass | + * | 02 | Call updateTimestamp with zero | position = 0 | Function should handle position = 0 correctly | Should Pass | + */ +TEST(TtmlSubtecParserTest, UpdateTimestampWithZeroPosition) { + std::cout << "Entering UpdateTimestampWithZeroPosition" << std::endl; + + SubtitleMimeType types[] = {eSUB_TYPE_WEBVTT, eSUB_TYPE_MP4, eSUB_TYPE_TTML, eSUB_TYPE_UNKNOWN}; + + for (auto type : types) { + std::cout << "Testing updateTimestamp with SubtitleMimeType: " << type << std::endl; + + TtmlSubtecParserTestHelper parser(type, 1920, 1080); + + std::cout << "Calling parser.updateTimestamp(0)" << std::endl; + parser.updateTimestamp(0); + + std::cout << "Successfully handled updateTimestamp(0) for SubtitleMimeType: " << type << std::endl; + } + + std::cout << "Exiting UpdateTimestampWithZeroPosition" << std::endl; +} + +/** + * @brief Test the updateTimestamp function with a small positive position + * + * This test verifies that the updateTimestamp function correctly updates the timestamp when provided with a small positive position value. + * This is important to ensure that the function handles typical positive inputs as expected. + * + * **Test Group ID:** Basic: 01@n + * **Test Case ID:** 033@n + * **Priority:** High@n + * + * **Pre-Conditions:** None@n + * **Dependencies:** None@n + * **User Interaction:** None@n + * + * **Test Procedure:**@n + * | Variation / Step | Description | Test Data | Expected Result | Notes | + * |------------------|---------------------------------------------|--------------------------------------------------------|----------------------------------|---------------| + * | 01 | Create TtmlSubtecParser object | SubtitleMimeType::{WEBVTT, MP4, TTML, UNKNOWN} | Object should be created | Should Pass | + * | 02 | Call updateTimestamp with small position | position = 20 | Timestamp should update correctly| Should Pass | + */ +TEST(TtmlSubtecParserTest, UpdateTimestampWithSmallPositivePosition) { + std::cout << "Entering UpdateTimestampWithSmallPositivePosition" << std::endl; + + SubtitleMimeType types[] = {eSUB_TYPE_WEBVTT, eSUB_TYPE_MP4, eSUB_TYPE_TTML, eSUB_TYPE_UNKNOWN}; + + for (auto type : types) { + std::cout << "Testing with SubtitleMimeType: " << type << std::endl; + + TtmlSubtecParserTestHelper parser(type, 1920, 1080); + + uint64_t position = 20; + std::cout << "Calling parser.updateTimestamp(" << position << ")" << std::endl; + parser.updateTimestamp(position); + + std::cout << "updateTimestamp completed for position = " << position << " and SubtitleMimeType: " << type << std::endl; + } + + std::cout << "Exiting UpdateTimestampWithSmallPositivePosition" << std::endl; +} + +/** + * @brief Test the updateTimestamp function with a large positive position value + * + * This test verifies the behavior of the updateTimestamp function when provided with a large positive position value. + * It ensures that the function can handle large values without errors and updates the timestamp correctly. + * + * **Test Group ID:** Basic: 01@n + * **Test Case ID:** 034@n + * **Priority:** High@n + * + * **Pre-Conditions:** None@n + * **Dependencies:** None@n + * **User Interaction:** None@n + * + * **Test Procedure:**@n + * | Variation / Step | Description | Test Data | Expected Result | Notes | + * |------------------|---------------------------------------------|--------------------------------------------------------|----------------------------------|---------------| + * | 01 | Create TtmlSubtecParser object | SubtitleMimeType::{WEBVTT, MP4, TTML, UNKNOWN} | Object should be created | Should Pass | + * | 02 | Call updateTimestamp with large position | position = 1000000000 | Timestamp should update correctly| Should Pass | + */ +TEST(TtmlSubtecParserTest, UpdateTimestampWithLargePositivePosition) { + std::cout << "Entering UpdateTimestampWithLargePositivePosition" << std::endl; + + SubtitleMimeType types[] = {eSUB_TYPE_WEBVTT, eSUB_TYPE_MP4, eSUB_TYPE_TTML, eSUB_TYPE_UNKNOWN}; + + for (auto type : types) { + std::cout << "Testing with SubtitleMimeType: " << type << std::endl; + + TtmlSubtecParserTestHelper parser(type, 1920, 1080); + + uint64_t position = 1000000000; + std::cout << "Calling parser.updateTimestamp(" << position << ")" << std::endl; + parser.updateTimestamp(position); + + std::cout << "updateTimestamp completed for position = " << position << " and SubtitleMimeType: " << type << std::endl; + } + + std::cout << "Exiting UpdateTimestampWithLargePositivePosition" << std::endl; +} + +int main(int argc, char **argv) { + ::testing::InitGoogleTest(&argc, argv); + return RUN_ALL_TESTS(); +} + From 3fa0700e614b737b3b9e3393fe3882c160eda837 Mon Sep 17 00:00:00 2001 From: joyal-06 Date: Fri, 4 Jul 2025 16:20:48 +0530 Subject: [PATCH 2/9] gh #2: Generate_L1_tests --- .../test/test_l1_WebVttSubtecParser.cpp | 1901 +++++++++++++++++ .../test/test_l1_WebvttSubtecDevInterface.cpp | 786 +++++++ 2 files changed, 2687 insertions(+) create mode 100755 subtec/subtecparser/test/test_l1_WebVttSubtecParser.cpp create mode 100755 subtec/subtecparser/test/test_l1_WebvttSubtecDevInterface.cpp diff --git a/subtec/subtecparser/test/test_l1_WebVttSubtecParser.cpp b/subtec/subtecparser/test/test_l1_WebVttSubtecParser.cpp new file mode 100755 index 0000000..b030b76 --- /dev/null +++ b/subtec/subtecparser/test/test_l1_WebVttSubtecParser.cpp @@ -0,0 +1,1901 @@ + +/* + * If not stated otherwise in this file or this component's LICENSE file the + * following copyright and licenses apply: + * + * Copyright 2025 RDK Management + * + * 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. + */ + +/** +* @file test_l1_WebVttSubtecParser.cpp +* @page WebVttSubtecParser Level 1 Tests +* +* ## Module's Role +* This module includes Level 1 functional tests (success and failure scenarios). +* This is to ensure that the WebVttSubtecParser methods meet the requirements. +* +* **Pre-Conditions:** None @n +* **Dependencies:** None @n +* +*/ + +#include +#include +#include +#include "WebVttSubtecParser.hpp" +#include +#include + +/** + * @brief Test the construction of WebVTTSubtecParser with valid positive dimensions. + * + * This test verifies that the WebVTTSubtecParser constructor successfully creates an instance without throwing an exception when provided with valid positive dimensions (width and height) for various subtitle mime types. The objective is to ensure stability when handling valid input parameters. + * + * **Test Group ID:** Basic: 01@n + * **Test Case ID:** 001@n + * **Priority:** High@n + * + * **Pre-Conditions:** None@n + * **Dependencies:** None@n + * **User Interaction:** None@n + * + * **Test Procedure:**@n + * | Variation / Step | Description | Test Data | Expected Result | Notes | + * | :----: | --------- | ---------- |-------------- | ----- | + * | 01 | Invoke WebVTTSubtecParser constructor for each supported subtitle mime type using width=640 and height=480 | type = eSUB_TYPE_WEBVTT, eSUB_TYPE_MP4, eSUB_TYPE_TTML, eSUB_TYPE_UNKNOWN, width = 640, height = 480 | Constructor does not throw any exception and instance is created successfully | Should Pass | + */ +TEST(WebVTTSubtecParser, ConstructWithValidPositiveDimensions) +{ + std::cout << "Entering ConstructWithValidPositiveDimensions test" << std::endl; + + SubtitleMimeType types[] = {eSUB_TYPE_WEBVTT, eSUB_TYPE_MP4, eSUB_TYPE_TTML, eSUB_TYPE_UNKNOWN}; + + int width = 640; + int height = 480; + + for (auto type : types) + { + std::cout << "Invoking WebVTTSubtecParser constructor with type: " << type << ", width: " << width << ", height: " << height << std::endl; + EXPECT_NO_THROW({ + WebVTTSubtecParser parser(type, width, height); + std::cout << "Instance created successfully for type: " << type << std::endl; + }); + std::cout << std::endl; + } + + std::cout << "Exiting ConstructWithValidPositiveDimensions test" << std::endl; +} + +/** + * @brief Validate WebVTTSubtecParser construction with maximum dimensions + * + * This test verifies that the WebVTTSubtecParser constructor properly handles instantiation using maximum integer values for width and height across different subtitle types. The objective is to ensure that no exception is thrown during the object creation even at boundary conditions. + * + * **Test Group ID:** Basic: 01@n + * **Test Case ID:** 002@n + * **Priority:** High@n + * + * **Pre-Conditions:** None@n + * **Dependencies:** None@n + * **User Interaction:** None@n + * + * **Test Procedure:**@n + * | Variation / Step | Description | Test Data | Expected Result | Notes | + * | :----: | --------- | ---------- | -------------- | ----- | + * | 01 | Call constructor for subtitle type eSUB_TYPE_WEBVTT with maximum width and height. | type = eSUB_TYPE_WEBVTT, width = INT_MAX, height = INT_MAX | No exception thrown; instance created successfully. | Should Pass | + * | 02 | Call constructor for subtitle type eSUB_TYPE_MP4 with maximum width and height. | type = eSUB_TYPE_MP4, width = INT_MAX, height = INT_MAX | No exception thrown; instance created successfully. | Should Pass | + * | 03 | Call constructor for subtitle type eSUB_TYPE_TTML with maximum width and height. | type = eSUB_TYPE_TTML, width = INT_MAX, height = INT_MAX | No exception thrown; instance created successfully. | Should Pass | + * | 04 | Call constructor for subtitle type eSUB_TYPE_UNKNOWN with maximum width and height. | type = eSUB_TYPE_UNKNOWN, width = INT_MAX, height = INT_MAX | No exception thrown; instance created successfully. | Should Pass | + */ +TEST(WebVTTSubtecParser, ConstructWithMaxDimensions) +{ + std::cout << "Entering ConstructWithMaxDimensions test" << std::endl; + + SubtitleMimeType types[] = {eSUB_TYPE_WEBVTT, eSUB_TYPE_MP4, eSUB_TYPE_TTML, eSUB_TYPE_UNKNOWN}; + + int width = INT_MAX; + int height = INT_MAX; + + for (auto type : types) + { + std::cout << "Invoking WebVTTSubtecParser constructor with type: " << type << ", width: " << width << ", height: " << height << std::endl; + EXPECT_NO_THROW({ + WebVTTSubtecParser parser(type, width, height); + std::cout << "Instance created successfully for type: " << type << " with maximum dimensions" << std::endl; + }); + std::cout << std::endl; + } + + std::cout << "Exiting ConstructWithMaxDimensions test" << std::endl; +} + +/** + * @brief Validate WebVTTSubtecParser constructor against zero width input. + * + * This test ensures that the WebVTTSubtecParser constructor throws a std::invalid_argument exception when provided with a width value of zero, which is invalid. The constructor is invoked for various subtitle MIME types to verify that it consistently detects and handles the invalid input. + * + * **Test Group ID:** Basic: 01@n + * **Test Case ID:** 003@n + * **Priority:** High@n + * + * **Pre-Conditions:** None@n + * **Dependencies:** None@n + * **User Interaction:** None@n + * + * **Test Procedure:**@n + * | Variation / Step | Description | Test Data | Expected Result | Notes | + * | :----: | --------- | ---------- |-------------- | ----- | + * | 01 | Invoke the WebVTTSubtecParser constructor for each subtitle MIME type with width = 0 and height = 480 to validate proper error handling for an invalid width. | type = eSUB_TYPE_WEBVTT, eSUB_TYPE_MP4, eSUB_TYPE_TTML, eSUB_TYPE_UNKNOWN, width = 0, height = 480 | The constructor should throw a std::invalid_argument exception. | Should Fail | + */ +TEST(WebVTTSubtecParser, ConstructWithZeroWidth) +{ + std::cout << "Entering ConstructWithZeroWidth test" << std::endl; + + SubtitleMimeType types[] = {eSUB_TYPE_WEBVTT, eSUB_TYPE_MP4, eSUB_TYPE_TTML, eSUB_TYPE_UNKNOWN}; + + int width = 0; + int height = 480; + + for (auto type : types) + { + std::cout << "Invoking WebVTTSubtecParser constructor with type: " << type << ", width: " << width << ", height: " << height << std::endl; + EXPECT_THROW({ + WebVTTSubtecParser parser(type, width, height); + std::cout << "Instance creation should have failed for type: " << type << " with zero width" << std::endl; + }, std::invalid_argument); + std::cout << std::endl; + } + + std::cout << "Exiting ConstructWithZeroWidth test" << std::endl; +} + +/** + * @brief Tests that constructing a WebVTTSubtecParser with a zero height parameter raises an exception. + * + * This test verifies that the WebVTTSubtecParser constructor throws a std::invalid_argument exception when invoked with a height of zero. The test iterates over multiple subtitle MIME types to ensure consistent failure in this invalid scenario. + * + * **Test Group ID:** Basic: 01 + * **Test Case ID:** 004 + * **Priority:** High + * + * **Pre-Conditions:** None + * **Dependencies:** None + * **User Interaction:** None + * + * **Test Procedure:** + * | Variation / Step | Description | Test Data | Expected Result | Notes | + * | :----: | --------- | ---------- |-------------- | ----- | + * | 01 | Invoke WebVTTSubtecParser constructor with subtitle type eSUB_TYPE_WEBVTT | type = eSUB_TYPE_WEBVTT, width = 640, height = 0 | std::invalid_argument exception thrown | Should Pass | + * | 02 | Invoke WebVTTSubtecParser constructor with subtitle type eSUB_TYPE_MP4 | type = eSUB_TYPE_MP4, width = 640, height = 0 | std::invalid_argument exception thrown | Should Pass | + * | 03 | Invoke WebVTTSubtecParser constructor with subtitle type eSUB_TYPE_TTML | type = eSUB_TYPE_TTML, width = 640, height = 0 | std::invalid_argument exception thrown | Should Pass | + * | 04 | Invoke WebVTTSubtecParser constructor with subtitle type eSUB_TYPE_UNKNOWN | type = eSUB_TYPE_UNKNOWN, width = 640, height = 0 | std::invalid_argument exception thrown | Should Pass | + */ +TEST(WebVTTSubtecParser, ConstructWithZeroHeight) +{ + std::cout << "Entering ConstructWithZeroHeight test" << std::endl; + + SubtitleMimeType types[] = {eSUB_TYPE_WEBVTT, eSUB_TYPE_MP4, eSUB_TYPE_TTML, eSUB_TYPE_UNKNOWN}; + + int width = 640; + int height = 0; + + for (auto type : types) + { + std::cout << "Invoking WebVTTSubtecParser constructor with type: " << type << ", width: " << width << ", height: " << height << std::endl; + EXPECT_THROW({ + WebVTTSubtecParser parser(type, width, height); + std::cout << "Instance creation should have failed for type: " << type << " with zero height" << std::endl; + }, std::invalid_argument); + std::cout << std::endl; + } + + std::cout << "Exiting ConstructWithZeroHeight test" << std::endl; +} + +/** + * @brief Verify that the WebVTTSubtecParser constructor throws an exception when invoked with a negative width. + * + * This test validates that the WebVTTSubtecParser constructor correctly handles an invalid negative width input. It iterates through a set of subtitle types and attempts to create a parser instance with a negative width (-100) and a valid height (480). The expected behavior is to throw a std::invalid_argument exception for each type, ensuring robust input validation. + * + * **Test Group ID:** Basic: 01 + * **Test Case ID:** 005 + * **Priority:** High + * + * **Pre-Conditions:** None + * **Dependencies:** None + * **User Interaction:** None + * + * **Test Procedure:** + * | Variation / Step | Description | Test Data | Expected Result | Notes | + * | :----: | ----------------------------------------------------------------------------- | ------------------------------------------------------- | --------------------------------------------------------- | ----------- | + * | 01 | Call WebVTTSubtecParser constructor with type eSUB_TYPE_WEBVTT, negative width (-100), and valid height (480) | type = eSUB_TYPE_WEBVTT, width = -100, height = 480 | std::invalid_argument exception is thrown | Should Fail | + * | 02 | Call WebVTTSubtecParser constructor with type eSUB_TYPE_MP4, negative width (-100), and valid height (480) | type = eSUB_TYPE_MP4, width = -100, height = 480 | std::invalid_argument exception is thrown | Should Fail | + * | 03 | Call WebVTTSubtecParser constructor with type eSUB_TYPE_TTML, negative width (-100), and valid height (480) | type = eSUB_TYPE_TTML, width = -100, height = 480 | std::invalid_argument exception is thrown | Should Fail | + * | 04 | Call WebVTTSubtecParser constructor with type eSUB_TYPE_UNKNOWN, negative width (-100), and valid height (480) | type = eSUB_TYPE_UNKNOWN, width = -100, height = 480 | std::invalid_argument exception is thrown | Should Fail | + */ +TEST(WebVTTSubtecParser, ConstructWithNegativeWidth) +{ + std::cout << "Entering ConstructWithNegativeWidth test" << std::endl; + + SubtitleMimeType types[] = {eSUB_TYPE_WEBVTT, eSUB_TYPE_MP4, eSUB_TYPE_TTML, eSUB_TYPE_UNKNOWN}; + + int width = -100; + int height = 480; + + for (auto type : types) + { + std::cout << "Invoking WebVTTSubtecParser constructor with type: " << type << ", width: " << width << ", height: " << height << std::endl; + EXPECT_THROW({ + WebVTTSubtecParser parser(type, width, height); + std::cout << "Instance creation should have failed for type: " << type << " with negative width" << std::endl; + }, std::invalid_argument); + std::cout << std::endl; + } + + std::cout << "Exiting ConstructWithNegativeWidth test" << std::endl; +} + +/** + * @brief Verify that the WebVTTSubtecParser constructor throws an exception for negative height + * + * This test verifies that when the WebVTTSubtecParser is instantiated with a negative height value, it correctly throws a std::invalid_argument exception. The test iterates over different subtitle mime types and ensures that the exception is thrown for each case. This behavior helps enforce proper parameter validation in the parser. + * + * **Test Group ID:** Basic: 01 + * **Test Case ID:** 006 + * **Priority:** High + * + * **Pre-Conditions:** None + * **Dependencies:** None + * **User Interaction:** None + * + * **Test Procedure:** + * | Variation / Step | Description | Test Data | Expected Result | Notes | + * | :----: | --------- | ---------- |-------------- | ----- | + * | 01 | Invoke the WebVTTSubtecParser constructor with various subtitle mime types using width=640 and height=-200 | type = eSUB_TYPE_WEBVTT, eSUB_TYPE_MP4, eSUB_TYPE_TTML, eSUB_TYPE_UNKNOWN, width = 640, height = -200 | std::invalid_argument exception is thrown for each invocation | Should Fail | + */ +TEST(WebVTTSubtecParser, ConstructWithNegativeHeight) +{ + std::cout << "Entering ConstructWithNegativeHeight test" << std::endl; + + SubtitleMimeType types[] = {eSUB_TYPE_WEBVTT, eSUB_TYPE_MP4, eSUB_TYPE_TTML, eSUB_TYPE_UNKNOWN}; + + int width = 640; + int height = -200; + + for (auto type : types) + { + std::cout << "Invoking WebVTTSubtecParser constructor with type: " << type << ", width: " << width << ", height: " << height << std::endl; + EXPECT_THROW({ + WebVTTSubtecParser parser(type, width, height); + std::cout << "Instance creation should have failed for type: " << type << " with negative height" << std::endl; + }, std::invalid_argument); + std::cout << std::endl; + } + + std::cout << "Exiting ConstructWithNegativeHeight test" << std::endl; +} + +/** + * @brief Validates that calling the close() method on WebVTTSubtecParser returns true for various SubtitleMimeType values. + * + * This test iterates over a set of SubtitleMimeType values (eSUB_TYPE_WEBVTT, eSUB_TYPE_MP4, eSUB_TYPE_TTML, eSUB_TYPE_UNKNOWN) and verifies that the close() method returns true for each instance. This confirms that the parser correctly finalizes its operations regardless of subtitle type. + * + * **Test Group ID:** Basic: 01 + * **Test Case ID:** 007 + * **Priority:** High + * + * **Pre-Conditions:** None + * **Dependencies:** None + * **User Interaction:** None + * + * **Test Procedure:** + * | Variation / Step | Description | Test Data | Expected Result | Notes | + * | :--------------: | ------------------------------------------------------------------------------------------------------- | ------------------------------------------------- | --------------------------------------------------- | ----------- | + * | 01 | Create WebVTTSubtecParser object with SubtitleMimeType = eSUB_TYPE_WEBVTT, width = 1920, height = 1080 | SubtitleMimeType = eSUB_TYPE_WEBVTT, width = 1920, height = 1080, output = close() return value | close() returns true and assertion passes | Should Pass | + * | 02 | Create WebVTTSubtecParser object with SubtitleMimeType = eSUB_TYPE_MP4, width = 1920, height = 1080 | SubtitleMimeType = eSUB_TYPE_MP4, width = 1920, height = 1080, output = close() return value | close() returns true and assertion passes | Should Pass | + * | 03 | Create WebVTTSubtecParser object with SubtitleMimeType = eSUB_TYPE_TTML, width = 1920, height = 1080 | SubtitleMimeType = eSUB_TYPE_TTML, width = 1920, height = 1080, output = close() return value | close() returns true and assertion passes | Should Pass | + * | 04 | Create WebVTTSubtecParser object with SubtitleMimeType = eSUB_TYPE_UNKNOWN, width = 1920, height = 1080 | SubtitleMimeType = eSUB_TYPE_UNKNOWN, width = 1920, height = 1080, output = close() return value | close() returns true and assertion passes | Should Pass | + */ +TEST(WebVTTSubtecParser, BasicCallCloseReturnsTrue) +{ + std::cout << "Entering BasicCallCloseReturnsTrue test" << std::endl; + + SubtitleMimeType types[] = { + eSUB_TYPE_WEBVTT, + eSUB_TYPE_MP4, + eSUB_TYPE_TTML, + eSUB_TYPE_UNKNOWN + }; + + for (auto type : types) + { + std::cout << "Creating WebVTTSubtecParser object with SubtitleMimeType = " << type + << ", width = 1920 and height = 1080" << std::endl; + + WebVTTSubtecParser parser(type, 1920, 1080); + + std::cout << "Invoking close() method" << std::endl; + bool result = parser.close(); + + std::cout << "close() returned: " << result << " for SubtitleMimeType = " << type << std::endl; + + ASSERT_TRUE(result) << "close() failed for SubtitleMimeType: " << type; + } + + std::cout << "Exiting BasicCallCloseReturnsTrue test" << std::endl; +} + +/** + * @brief Test the initialization of WebVTTSubtecParser with typical positive values. + * + * This test verifies that the WebVTTSubtecParser constructor and the init method work correctly when provided with a set of typical positive inputs. It ensures that for various SubtitleMimeType values the parser object is created with valid dimensions, and the init method returns true indicating successful initialization. + * + * **Test Group ID:** Basic: 01@n + * **Test Case ID:** 008@n + * **Priority:** High@n + * + * **Pre-Conditions:** None@n + * **Dependencies:** None@n + * **User Interaction:** None@n + * + * **Test Procedure:**@n + * | Variation / Step | Description | Test Data | Expected Result | Notes | + * | :----: | --------- | ---------- |-------------- | ----- | + * | 02 | Initialize an array with various SubtitleMimeType values. | types = eSUB_TYPE_WEBVTT, eSUB_TYPE_MP4, eSUB_TYPE_TTML, eSUB_TYPE_UNKNOWN | Array of SubtitleMimeType is created successfully. | Should be successful | + * | 03 | For each SubtitleMimeType value, create a WebVTTSubtecParser object with width 1920 and height 1080, then invoke the init method with startPosSeconds = 10.0 and basePTS = 1609459200000. | For each iteration: type = current value, startPosSeconds = 10.0, basePTS = 1609459200000, width = 1920, height = 1080 | The init method returns true for each SubtitleMimeType value. | Should Pass | + * | 04 | Validate the result of the init method for each parser object creation. | initResult = value returned by parser.init | ASSERT_TRUE(initResult) passes for all iterations. | Should Pass | + */ +TEST(WebVTTSubtecParser, ValidInitializationWithTypicalPositiveValues) +{ + std::cout << "Entering ValidInitializationWithTypicalPositiveValues test" << std::endl; + + SubtitleMimeType types[] = { + eSUB_TYPE_WEBVTT, + eSUB_TYPE_MP4, + eSUB_TYPE_TTML, + eSUB_TYPE_UNKNOWN + }; + + double startPosSeconds = 10.0; + unsigned long long basePTS = 1609459200000; + + for (auto type : types) + { + std::cout << "Creating WebVTTSubtecParser object with SubtitleMimeType = " << type + << ", width = 1920 and height = 1080" << std::endl; + + WebVTTSubtecParser parser(type, 1920, 1080); + + std::cout << "Invoking init with startPosSeconds = " << startPosSeconds + << " and basePTS = " << basePTS << std::endl; + + bool initResult = parser.init(startPosSeconds, basePTS); + + std::cout << "init returned: " << initResult << " for SubtitleMimeType = " << type << std::endl; + + ASSERT_TRUE(initResult) << "init() failed for SubtitleMimeType: " << type; + } + + std::cout << "Exiting ValidInitializationWithTypicalPositiveValues test" << std::endl; +} + +/** + * @brief Verify that WebVTTSubtecParser initializes successfully with zero startPosSeconds and basePTS. + * + * This test verifies that the WebVTTSubtecParser initializes correctly for various SubtitleMimeType values when provided with zero startPosSeconds and basePTS values. It ensures that the initialization method returns true for each valid subtitle type. + * + * **Test Group ID:** Basic: 01 @n + * **Test Case ID:** 009 @n + * **Priority:** High @n + * + * **Pre-Conditions:** None @n + * **Dependencies:** None @n + * **User Interaction:** None @n + * + * **Test Procedure:** @n + * | Variation / Step | Description | Test Data | Expected Result | Notes | + * | :----: | --------- | ---------- |-------------- | ----- | + * | 01 | Create WebVTTSubtecParser with eSUB_TYPE_WEBVTT, width = 1920, height = 1080 and call init with startPosSeconds = 0.0, basePTS = 0 | type = eSUB_TYPE_WEBVTT, width = 1920, height = 1080, startPosSeconds = 0.0, basePTS = 0 | init() returns true and assertion passes | Should Pass | + * | 02 | Create WebVTTSubtecParser with eSUB_TYPE_MP4, width = 1920, height = 1080 and call init with startPosSeconds = 0.0, basePTS = 0 | type = eSUB_TYPE_MP4, width = 1920, height = 1080, startPosSeconds = 0.0, basePTS = 0 | init() returns true and assertion passes | Should Pass | + * | 03 | Create WebVTTSubtecParser with eSUB_TYPE_TTML, width = 1920, height = 1080 and call init with startPosSeconds = 0.0, basePTS = 0 | type = eSUB_TYPE_TTML, width = 1920, height = 1080, startPosSeconds = 0.0, basePTS = 0 | init() returns true and assertion passes | Should Pass | + * | 04 | Create WebVTTSubtecParser with eSUB_TYPE_UNKNOWN, width = 1920, height = 1080 and call init with startPosSeconds = 0.0, basePTS = 0 | type = eSUB_TYPE_UNKNOWN, width = 1920, height = 1080, startPosSeconds = 0.0, basePTS = 0 | init() returns true and assertion passes | Should Pass | + */ +TEST(WebVTTSubtecParser, InitializationWithZeroValues) +{ + std::cout << "Entering InitializationWithZeroValues test" << std::endl; + + SubtitleMimeType types[] = { + eSUB_TYPE_WEBVTT, + eSUB_TYPE_MP4, + eSUB_TYPE_TTML, + eSUB_TYPE_UNKNOWN + }; + + double startPosSeconds = 0.0; + unsigned long long basePTS = 0; + + for (auto type : types) + { + std::cout << "Creating WebVTTSubtecParser object with SubtitleMimeType = " << type + << ", width = 1920 and height = 1080" << std::endl; + + WebVTTSubtecParser parser(type, 1920, 1080); + + std::cout << "Invoking init with startPosSeconds = " << startPosSeconds + << " and basePTS = " << basePTS << std::endl; + + bool initResult = parser.init(startPosSeconds, basePTS); + + std::cout << "init returned: " << initResult << " for SubtitleMimeType = " << type << std::endl; + + ASSERT_TRUE(initResult) << "init() failed for SubtitleMimeType: " << type; + } + + std::cout << "Exiting InitializationWithZeroValues test" << std::endl; +} + +/** + * @brief Test initialization of WebVTTSubtecParser with a minimal positive start position. + * + * This test verifies that the WebVTTSubtecParser initializes correctly when provided with a very small positive start position, ensuring that the init() function returns true for various SubtitleMimeType values. + * + * **Test Group ID:** Basic: 01 + * **Test Case ID:** 010 + * **Priority:** High + * + * **Pre-Conditions:** None + * **Dependencies:** None + * **User Interaction:** None + * + * **Test Procedure:** + * | Variation / Step | Description | Test Data | Expected Result | Notes | + * | :----: | --------- | ---------- |-------------- | ----- | + * | 01 | Create WebVTTSubtecParser with SubtitleMimeType = eSUB_TYPE_WEBVTT, width = 1920, height = 1080 and invoke init with startPosSeconds = 1e-9 and basePTS = 500. | SubtitleMimeType = eSUB_TYPE_WEBVTT, width = 1920, height = 1080, startPosSeconds = 1e-9, basePTS = 500 | init() returns true and the assertion passes. | Should Pass | + * | 02 | Create WebVTTSubtecParser with SubtitleMimeType = eSUB_TYPE_MP4, width = 1920, height = 1080 and invoke init with startPosSeconds = 1e-9 and basePTS = 500. | SubtitleMimeType = eSUB_TYPE_MP4, width = 1920, height = 1080, startPosSeconds = 1e-9, basePTS = 500 | init() returns true and the assertion passes. | Should Pass | + * | 03 | Create WebVTTSubtecParser with SubtitleMimeType = eSUB_TYPE_TTML, width = 1920, height = 1080 and invoke init with startPosSeconds = 1e-9 and basePTS = 500. | SubtitleMimeType = eSUB_TYPE_TTML, width = 1920, height = 1080, startPosSeconds = 1e-9, basePTS = 500 | init() returns true and the assertion passes. | Should Pass | + * | 04 | Create WebVTTSubtecParser with SubtitleMimeType = eSUB_TYPE_UNKNOWN, width = 1920, height = 1080 and invoke init with startPosSeconds = 1e-9 and basePTS = 500. | SubtitleMimeType = eSUB_TYPE_UNKNOWN, width = 1920, height = 1080, startPosSeconds = 1e-9, basePTS = 500 | init() returns true and the assertion passes. | Should Pass | + */ +TEST(WebVTTSubtecParser, InitializationWithVerySmallPositiveStartPosition) +{ + std::cout << "Entering InitializationWithVerySmallPositiveStartPosition test" << std::endl; + + SubtitleMimeType types[] = { + eSUB_TYPE_WEBVTT, + eSUB_TYPE_MP4, + eSUB_TYPE_TTML, + eSUB_TYPE_UNKNOWN + }; + + double startPosSeconds = 1e-9; + unsigned long long basePTS = 500; + + for (auto type : types) + { + std::cout << "Creating WebVTTSubtecParser object with SubtitleMimeType = " << type + << ", width = 1920 and height = 1080" << std::endl; + + WebVTTSubtecParser parser(type, 1920, 1080); + + std::cout << "Invoking init with startPosSeconds = " << startPosSeconds + << " and basePTS = " << basePTS << std::endl; + + bool initResult = parser.init(startPosSeconds, basePTS); + + std::cout << "init returned: " << initResult << " for SubtitleMimeType = " << type << std::endl; + + ASSERT_TRUE(initResult) << "init() failed for SubtitleMimeType: " << type; + } + + std::cout << "Exiting InitializationWithVerySmallPositiveStartPosition test" << std::endl; +} + +/** + * @brief Test initialization of WebVTTSubtecParser with extremely large numerical values. + * + * This test verifies that the WebVTTSubtecParser can be correctly initialized with extremely large values for start position in seconds and base PTS across various SubtitleMimeType types. It ensures that the initialization does not fail when handling maximum numerical limits. + * + * **Test Group ID:** Basic: 01@n + * **Test Case ID:** 011@n + * **Priority:** High@n + * + * **Pre-Conditions:** None@n + * **Dependencies:** None@n + * **User Interaction:** None@n + * + * **Test Procedure:** + * | Variation / Step | Description | Test Data | Expected Result | Notes | + * | :----: | --------- | ---------- |-------------- | ----- | + * | 01 | Initialize test parameters with subtitle types and extremely large numeric values. | types = eSUB_TYPE_WEBVTT, eSUB_TYPE_MP4, eSUB_TYPE_TTML, eSUB_TYPE_UNKNOWN; startPosSeconds = 1e10, basePTS = 18446744073709551615; width = 1920, height = 1080 | Parameters are set correctly for the test. | Should be successful | + * | 02 | Create WebVTTSubtecParser object for each SubtitleMimeType, invoke init and verify the return value is true. | startPosSeconds = 1e10, basePTS = 18446744073709551615ULL | returns true assertions pass for all subtitle types. | Should Pass | + */ +TEST(WebVTTSubtecParser, InitializationWithExtremelyLargeValues) +{ + std::cout << "Entering InitializationWithExtremelyLargeValues test" << std::endl; + + SubtitleMimeType types[] = { + eSUB_TYPE_WEBVTT, + eSUB_TYPE_MP4, + eSUB_TYPE_TTML, + eSUB_TYPE_UNKNOWN + }; + + double startPosSeconds = 1e10; + unsigned long long basePTS = 18446744073709551615ULL; + + for (auto type : types) + { + std::cout << "Creating WebVTTSubtecParser object with SubtitleMimeType = " << type + << ", width = 1920 and height = 1080" << std::endl; + + WebVTTSubtecParser parser(type, 1920, 1080); + + std::cout << "Invoking init with startPosSeconds = " << startPosSeconds + << " and basePTS = " << basePTS << std::endl; + + bool initResult = parser.init(startPosSeconds, basePTS); + + std::cout << "init returned: " << initResult << " for SubtitleMimeType = " << type << std::endl; + + ASSERT_TRUE(initResult) << "init() failed for SubtitleMimeType: " << type; + } + + std::cout << "Exiting InitializationWithExtremelyLargeValues test" << std::endl; +} + +/** + * @brief Test to ensure that the initialization fails when provided with a negative start position value. + * + * This test verifies that the init() function of the WebVTTSubtecParser properly handles negative start position values for various subtitle mime types. It ensures that the parser initialization returns false when a negative start position is provided in order to prevent improper subtitle timing. + * + * **Test Group ID:** Basic: 01@n + * **Test Case ID:** 012@n + * **Priority:** High@n + * + * **Pre-Conditions:** None@n + * **Dependencies:** None@n + * **User Interaction:** None@n + * + * **Test Procedure:**@n + * | Variation / Step | Description | Test Data | Expected Result | Notes | + * | :--------------: | ----------------------------------------------------------------------------------------------------- | -------------------------------------------------------------------------------------- | ----------------------------------------------------------------------------------------------------------- | -------------- | + * | 01 | Iterate through a list of SubtitleMimeType values | SubtitleMimeType = eSUB_TYPE_WEBVTT, eSUB_TYPE_MP4, eSUB_TYPE_TTML, eSUB_TYPE_UNKNOWN | All subtitle mime type values are processed | Should be successful | + * | 02 | Create a WebVTTSubtecParser object with specified screen dimensions | input: SubtitleMimeType = current type, width = 1920, height = 1080 | WebVTTSubtecParser object is created successfully | Should Pass | + * | 03 | Invoke the init() method with a negative startPosSeconds and a basePTS value | input: startPosSeconds = -5.0, basePTS = 1000 | init() should return false indicating failure due to negative start position | Should Fail | + * | 04 | Assert that the result of init() is false | output: initResult = result of init() | ASSERT_FALSE verifies that init() returned false as expected | Should Pass | + */ +TEST(WebVTTSubtecParser, NegativeStartPositionValue) +{ + std::cout << "Entering NegativeStartPositionValue test" << std::endl; + + SubtitleMimeType types[] = { + eSUB_TYPE_WEBVTT, + eSUB_TYPE_MP4, + eSUB_TYPE_TTML, + eSUB_TYPE_UNKNOWN + }; + + double startPosSeconds = -5.0; + unsigned long long basePTS = 1000; + + for (auto type : types) + { + std::cout << "Creating WebVTTSubtecParser object with SubtitleMimeType = " << type + << ", width = 1920 and height = 1080" << std::endl; + + WebVTTSubtecParser parser(type, 1920, 1080); + + std::cout << "Invoking init with startPosSeconds = " << startPosSeconds + << " and basePTS = " << basePTS << std::endl; + + bool initResult = parser.init(startPosSeconds, basePTS); + + std::cout << "init returned: " << initResult << " for SubtitleMimeType = " << type << std::endl; + + ASSERT_FALSE(initResult) << "Expected init() to fail for negative startPosSeconds, but it succeeded. SubtitleMimeType: " << type; + } + + std::cout << "Exiting NegativeStartPositionValue test" << std::endl; +} + +/** + * @brief Validate that the mute functionality works correctly across various subtitle types. + * + * This test verifies that invoking the mute(true) function on a WebVTTSubtecParser object mutes the subtitles + * without errors for different subtitle MIME types. It ensures that the parser handles each subtitle type consistently + * by correctly invoking the mute method. + * + * **Test Group ID:** Basic: 01@n + * **Test Case ID:** 013@n + * **Priority:** High@n + * + * **Pre-Conditions:** None@n + * **Dependencies:** None@n + * **User Interaction:** None@n + * + * **Test Procedure:** + * | Variation / Step | Description | Test Data | Expected Result | Notes | + * | :--------------: | --------------------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------ | --------------------------------------------------- | ----------- | + * | 01 | Create a WebVTTSubtecParser object for type eSUB_TYPE_WEBVTT with width=1920 and height=1080 | type = eSUB_TYPE_WEBVTT, width = 1920, height = 1080 | Object is successfully created | Should Pass | + * | 02 | Invoke mute(true) on the parser object for eSUB_TYPE_WEBVTT | mute_value = true | Method mute executes without errors | Should Pass | + * | 03 | Create a WebVTTSubtecParser object for type eSUB_TYPE_MP4 with width=1920 and height=1080 | type = eSUB_TYPE_MP4, width = 1920, height = 1080 | Object is successfully created | Should Pass | + * | 04 | Invoke mute(true) on the parser object for eSUB_TYPE_MP4 | mute_value = true | Method mute executes without errors | Should Pass | + * | 05 | Create a WebVTTSubtecParser object for type eSUB_TYPE_TTML with width=1920 and height=1080 | type = eSUB_TYPE_TTML, width = 1920, height = 1080 | Object is successfully created | Should Pass | + * | 06 | Invoke mute(true) on the parser object for eSUB_TYPE_TTML | mute_value = true | Method mute executes without errors | Should Pass | + * | 07 | Create a WebVTTSubtecParser object for type eSUB_TYPE_UNKNOWN with width=1920 and height=1080 | type = eSUB_TYPE_UNKNOWN, width = 1920, height = 1080 | Object is successfully created | Should Pass | + * | 08 | Invoke mute(true) on the parser object for eSUB_TYPE_UNKNOWN | mute_value = true | Method mute executes without errors | Should Pass | + */ +TEST(WebVTTSubtecParser, MuteSubtitlesSuccessfully) +{ + std::cout << "Entering MuteSubtitlesSuccessfully test" << std::endl; + + SubtitleMimeType types[] = { + eSUB_TYPE_WEBVTT, + eSUB_TYPE_MP4, + eSUB_TYPE_TTML, + eSUB_TYPE_UNKNOWN + }; + + for (auto type : types) + { + WebVTTSubtecParser parser(type, 1920, 1080); + std::cout << "Created WebVTTSubtecParser object with parameters: " << type << ", 1920, 1080" << std::endl; + + std::cout << "Invoking mute with value: true" << std::endl; + parser.mute(true); + std::cout << "Method mute executed with value: true" << std::endl; + + std::cout << "Subtitle rendering is expected to be muted with no errors" << std::endl; + } + + std::cout << "Exiting MuteSubtitlesSuccessfully test" << std::endl; +} + +/** + * @brief Validate that the mute functionality correctly un-mutes subtitles + * + * This test verifies that for different subtitle MIME types the mute method is invoked with a false value, + * ensuring that the subtitle rendering remains unmuted and no errors occur. + * + * **Test Group ID:** Basic: 01@n + * **Test Case ID:** 014@n + * **Priority:** High@n + * + * **Pre-Conditions:** None@n + * **Dependencies:** None@n + * **User Interaction:** None@n + * + * **Test Procedure:**@n + * | Variation / Step | Description | Test Data | Expected Result | Notes | + * | :--------------: | --------------------------------------------------------------------- | -------------------------------------------------------------------------- | --------------------------------------------------------------- | ----------- | + * | 01 | Create parser with eSUB_TYPE_WEBVTT and invoke mute(false) | type = eSUB_TYPE_WEBVTT, width = 1920, height = 1080, mute = false | Subtitle rendering unmuted with no errors | Should Pass | + * | 02 | Create parser with eSUB_TYPE_MP4 and invoke mute(false) | type = eSUB_TYPE_MP4, width = 1920, height = 1080, mute = false | Subtitle rendering unmuted with no errors | Should Pass | + * | 03 | Create parser with eSUB_TYPE_TTML and invoke mute(false) | type = eSUB_TYPE_TTML, width = 1920, height = 1080, mute = false | Subtitle rendering unmuted with no errors | Should Pass | + * | 04 | Create parser with eSUB_TYPE_UNKNOWN and invoke mute(false) | type = eSUB_TYPE_UNKNOWN, width = 1920, height = 1080, mute = false | Subtitle rendering unmuted with no errors | Should Pass | + */ +TEST(WebVTTSubtecParser, UnmuteSubtitlesSuccessfully) +{ + std::cout << "Entering UnmuteSubtitlesSuccessfully test" << std::endl; + + SubtitleMimeType types[] = { + eSUB_TYPE_WEBVTT, + eSUB_TYPE_MP4, + eSUB_TYPE_TTML, + eSUB_TYPE_UNKNOWN + }; + + for (auto type : types) + { + WebVTTSubtecParser parser(type, 1920, 1080); + std::cout << "Created WebVTTSubtecParser object with parameters: " << type << ", 1920, 1080" << std::endl; + + std::cout << "Invoking mute with value: false" << std::endl; + parser.mute(false); + std::cout << "Method mute executed with value: false" << std::endl; + + std::cout << "Subtitle rendering is expected to be unmuted with no errors" << std::endl; + } + + std::cout << "Exiting UnmuteSubtitlesSuccessfully test" << std::endl; +} + +/** + * @brief Verify that the pause API does not throw exceptions when pause is true + * + * This test validates the functionality of the pause method in the WebVTTSubtecParser class. + * It ensures that calling pause(true) on a parser object created with various SubtitleMimeType values + * does not throw an exception, thus confirming that the pause functionality works correctly for valid inputs. + * + * **Test Group ID:** Basic: 01@n + * **Test Case ID:** 015@n + * **Priority:** High@n + * + * **Pre-Conditions:** None@n + * **Dependencies:** None@n + * **User Interaction:** None@n + * + * **Test Procedure:**@n + * | Variation / Step | Description | Test Data | Expected Result | Notes | + * | :----: | --------- | ---------- |-------------- | ----- | + * | 01 | Create WebVTTSubtecParser instance with SubtitleMimeType = eSUB_TYPE_WEBVTT, width = 1920, and height = 1080; then invoke pause(true) | SubtitleMimeType = eSUB_TYPE_WEBVTT, width = 1920, height = 1080, pause = true | The parser.pause(true) method call should complete without throwing any exception | Should Pass | + * | 02 | Create WebVTTSubtecParser instance with SubtitleMimeType = eSUB_TYPE_MP4, width = 1920, and height = 1080; then invoke pause(true) | SubtitleMimeType = eSUB_TYPE_MP4, width = 1920, height = 1080, pause = true | The parser.pause(true) method call should complete without throwing any exception | Should Pass | + * | 03 | Create WebVTTSubtecParser instance with SubtitleMimeType = eSUB_TYPE_TTML, width = 1920, and height = 1080; then invoke pause(true) | SubtitleMimeType = eSUB_TYPE_TTML, width = 1920, height = 1080, pause = true | The parser.pause(true) method call should complete without throwing any exception | Should Pass | + * | 04 | Create WebVTTSubtecParser instance with SubtitleMimeType = eSUB_TYPE_UNKNOWN, width = 1920, and height = 1080; then invoke pause(true) | SubtitleMimeType = eSUB_TYPE_UNKNOWN, width = 1920, height = 1080, pause = true | The parser.pause(true) method call should complete without throwing any exception | Should Pass | + */ +TEST(WebVTTSubtecParser, PauseSubtitleRenderingWithPauseTrue) +{ + std::cout << "Entering PauseSubtitleRenderingWithPauseTrue test" << std::endl; + + SubtitleMimeType types[] = { + eSUB_TYPE_WEBVTT, + eSUB_TYPE_MP4, + eSUB_TYPE_TTML, + eSUB_TYPE_UNKNOWN + }; + + for (auto type : types) + { + std::cout << "Creating WebVTTSubtecParser object with SubtitleMimeType = " << type + << ", width = 1920 and height = 1080" << std::endl; + + WebVTTSubtecParser parser(type, 1920, 1080); + + std::cout << "Invoking pause method with true as input for SubtitleMimeType = " << type << std::endl; + EXPECT_NO_THROW(parser.pause(true)); + std::cout << "pause(true) invoked successfully with input value: true for SubtitleMimeType = " << type << std::endl; + } + + std::cout << "Exiting PauseSubtitleRenderingWithPauseTrue test" << std::endl; +} + +/** + * @brief Verify that invoking pause(false) does not throw an exception across various subtitle types. + * + * This test iterates over different SubtitleMimeType values to ensure that the WebVTTSubtecParser object's pause method, when called with false, executes without throwing an exception. It validates the parser’s behavior across supported and unsupported subtitle types. + * + * **Test Group ID:** Basic: 01@n + * **Test Case ID:** 016@n + * **Priority:** High@n + * + * **Pre-Conditions:** None@n + * **Dependencies:** None@n + * **User Interaction:** None@n + * + * **Test Procedure:**@n + * | Variation / Step | Description | Test Data | Expected Result | Notes | + * | :----: | --------- | ---------- |-------------- | ----- | + * | 01 | Create WebVTTSubtecParser object using each SubtitleMimeType with width = 1920 and height = 1080. | SubtitleMimeType = eSUB_TYPE_WEBVTT, eSUB_TYPE_MP4, eSUB_TYPE_TTML, eSUB_TYPE_UNKNOWN; width = 1920; height = 1080 | Instance of WebVTTSubtecParser is successfully created for each SubtitleMimeType. | Should be successful | + * | 02 | Invoke pause() method with argument false on the parser instance. | input = false | pause(false) does not throw any exception. | Should Pass | + */ +TEST(WebVTTSubtecParser, ResumeSubtitleRenderingWithPauseFalse) +{ + std::cout << "Entering ResumeSubtitleRenderingWithPauseFalse test" << std::endl; + + SubtitleMimeType types[] = { + eSUB_TYPE_WEBVTT, + eSUB_TYPE_MP4, + eSUB_TYPE_TTML, + eSUB_TYPE_UNKNOWN + }; + + for (auto type : types) + { + std::cout << "Creating WebVTTSubtecParser object with SubtitleMimeType = " << type + << ", width = 1920 and height = 1080" << std::endl; + + WebVTTSubtecParser parser(type, 1920, 1080); + + std::cout << "Invoking pause method with false as input" << std::endl; + EXPECT_NO_THROW(parser.pause(false)); + std::cout << "pause(false) invoked successfully with input value: false" << std::endl; + } + + std::cout << "Exiting ResumeSubtitleRenderingWithPauseFalse test" << std::endl; +} + +/** + * @brief Verifies that the processData method of WebVTTSubtecParser returns true for valid subtitle data. + * + * This test iterates over different SubtitleMimeType values and creates a WebVTTSubtecParser object with a valid WebVTT formatted input. + * It then calls processData with predefined parameters to validate that the parser processes the valid subtitle data correctly. + * + * **Test Group ID:** Basic: 01@n + * **Test Case ID:** 017@n + * **Priority:** High@n + * + * **Pre-Conditions:** None@n + * **Dependencies:** None@n + * **User Interaction:** None@n + * + * **Test Procedure:** + * | Variation / Step | Description | Test Data | Expected Result | Notes | + * | :----: | --------- | ---------- |-------------- | ----- | + * | 01 | Initialize buffer with valid WebVTT subtitle text and set related parameters. | inputStr = "WEBVTT\n\n1\n00:00:00.000 --> 00:00:05.000\nHello, world!", bufferLen = 55, position = 0.0, duration = 5.0 | Buffer correctly initialized with valid subtitle data. | Should be successful | + * | 02 | Iterate over each SubtitleMimeType value and create a parser instance with specified width and height. | SubtitleMimeType = eSUB_TYPE_WEBVTT, eSUB_TYPE_MP4, eSUB_TYPE_TTML, eSUB_TYPE_UNKNOWN; width = 640, height = 480 | Parser object created successfully for each type. | Should be successful | + * | 03 | Invoke processData on the parser object with the initialized input data. | buffer, bufferLen = 55, position = 0.0, duration = 5.0 | processData returns true indicating valid data processing. | Should Pass | + * | 04 | Validate that the returned value from processData is true using assertion. | result = processData(buffer, bufferLen, position, duration) | EXPECT_TRUE assertion passes if processData returns true. | Should Pass | + */ +TEST(WebVTTSubtecParser, ValidSubtitleData) +{ + std::cout << "Entering ValidSubtitleData test" << std::endl; + + SubtitleMimeType types[] = { + eSUB_TYPE_WEBVTT, + eSUB_TYPE_MP4, + eSUB_TYPE_TTML, + eSUB_TYPE_UNKNOWN + }; + + char buffer[100]; + const char* inputStr = "WEBVTT\n\n1\n00:00:00.000 --> 00:00:05.000\nHello, world!"; + strncpy(buffer, inputStr, sizeof(buffer)); + + size_t bufferLen = 55; + double position = 0.0; + double duration = 5.0; + + for (auto type : types) + { + std::cout << "Creating WebVTTSubtecParser object with SubtitleMimeType = " << type + << ", width = 640 and height = 480" << std::endl; + + WebVTTSubtecParser parser(type, 640, 480); + + std::cout << "Invoking processData with buffer: " << buffer + << ", bufferLen: " << bufferLen + << ", position: " << position + << ", duration: " << duration << std::endl; + + bool result = parser.processData(buffer, bufferLen, position, duration); + std::cout << "processData returned: " << result << " for SubtitleMimeType = " << type << std::endl; + + EXPECT_TRUE(result) << "processData() failed for SubtitleMimeType: " << type; + } + + std::cout << "Exiting ValidSubtitleData test" << std::endl; +} + +/** + * @brief Validate that processData returns false when a NULL buffer is provided. + * + * This test verifies that calling the processData method with a NULL buffer correctly returns false, ensuring that the API handles erroneous inputs gracefully across multiple subtitle mime types. + * + * **Test Group ID:** Basic: 01 + * **Test Case ID:** 018 + * **Priority:** High + * + * **Pre-Conditions:** None + * **Dependencies:** None + * **User Interaction:** None + * + * **Test Procedure:** + * | Variation / Step | Description | Test Data | Expected Result | Notes | + * | :----: | --------- | ---------- |-------------- | ----- | + * | 01 | Create a WebVTTSubtecParser instance with eSUB_TYPE_WEBVTT and invoke processData with a NULL buffer. | SubtitleMimeType = eSUB_TYPE_WEBVTT, buffer = NULL, bufferLen = 10, position = 0.0, duration = 5.0 | processData() returns false and EXPECT_FALSE(result) passes. | Should Fail | + * | 02 | Create a WebVTTSubtecParser instance with eSUB_TYPE_MP4 and invoke processData with a NULL buffer. | SubtitleMimeType = eSUB_TYPE_MP4, buffer = NULL, bufferLen = 10, position = 0.0, duration = 5.0 | processData() returns false and EXPECT_FALSE(result) passes. | Should Fail | + * | 03 | Create a WebVTTSubtecParser instance with eSUB_TYPE_TTML and invoke processData with a NULL buffer. | SubtitleMimeType = eSUB_TYPE_TTML, buffer = NULL, bufferLen = 10, position = 0.0, duration = 5.0 | processData() returns false and EXPECT_FALSE(result) passes. | Should Fail | + * | 04 | Create a WebVTTSubtecParser instance with eSUB_TYPE_UNKNOWN and invoke processData with a NULL buffer. | SubtitleMimeType = eSUB_TYPE_UNKNOWN, buffer = NULL, bufferLen = 10, position = 0.0, duration = 5.0 | processData() returns false and EXPECT_FALSE(result) passes. | Should Fail | + */ +TEST(WebVTTSubtecParser, NullBufferInput) +{ + std::cout << "Entering NullBufferInput test" << std::endl; + + SubtitleMimeType types[] = { + eSUB_TYPE_WEBVTT, + eSUB_TYPE_MP4, + eSUB_TYPE_TTML, + eSUB_TYPE_UNKNOWN + }; + + const char* buffer = NULL; + size_t bufferLen = 10; + double position = 0.0; + double duration = 5.0; + + for (auto type : types) + { + std::cout << "Creating WebVTTSubtecParser object with SubtitleMimeType = " << type + << ", width = 640 and height = 480" << std::endl; + + WebVTTSubtecParser parser(type, 640, 480); + + std::cout << "Invoking processData with buffer: " << buffer + << ", bufferLen: " << bufferLen + << ", position: " << position + << ", duration: " << duration << std::endl; + + bool result = parser.processData(buffer, bufferLen, position, duration); + std::cout << "processData returned: " << result << " for SubtitleMimeType = " << type << std::endl; + + EXPECT_FALSE(result) << "Expected processData() to return false for NULL buffer with SubtitleMimeType: " << type; + } + + std::cout << "Exiting NullBufferInput test" << std::endl; +} + +/** + * @brief Test processData with zero buffer length for WebVTTSubtecParser. + * + * This test verifies that processData returns false when the buffer length is set to zero. + * It iterates over different SubtitleMimeType values and ensures that regardless of the type, + * the API returns false due to an invalid input buffer length. This helps ensure robust input validation. + * + * **Test Group ID:** Basic: 01@n + * **Test Case ID:** 019@n + * **Priority:** High@n + * + * **Pre-Conditions:** None@n + * **Dependencies:** None@n + * **User Interaction:** None@n + * + * **Test Procedure:**@n + * | Variation / Step | Description | Test Data | Expected Result |Notes | + * | :----: | --------- | ---------- |-------------- | ----- | + * | 01 | Initialize test inputs including buffer, buffer length, position, and duration | inputStr = "WEBVTT\n\n1\n00:00:00.000 --> 00:00:05.000\nHello, world!", bufferLen = 0, position = 0.0, duration = 5.0 | Variables are initialized correctly | Should be successful | + * | 02 | Create WebVTTSubtecParser object with each SubtitleMimeType and invoke processData | SubtitleMimeType = eSUB_TYPE_WEBVTT, eSUB_TYPE_MP4, eSUB_TYPE_TTML, eSUB_TYPE_UNKNOWN; width = 640, height = 480; buffer = initialized buffer | API returns false for zero buffer length | Should Pass | + * | 03 | Assert that processData returns false for every SubtitleMimeType tested | Return value from processData = false | Assertion passes confirming false return value | Should Pass | + */ +TEST(WebVTTSubtecParser, ZeroBufferLength) +{ + std::cout << "Entering ZeroBufferLength test" << std::endl; + + SubtitleMimeType types[] = { + eSUB_TYPE_WEBVTT, + eSUB_TYPE_MP4, + eSUB_TYPE_TTML, + eSUB_TYPE_UNKNOWN + }; + + char buffer[100]; + const char* inputStr = "WEBVTT\n\n1\n00:00:00.000 --> 00:00:05.000\nHello, world!"; + strncpy(buffer, inputStr, sizeof(buffer)); + + size_t bufferLen = 0; + double position = 0.0; + double duration = 5.0; + + for (auto type : types) + { + std::cout << "Creating WebVTTSubtecParser object with SubtitleMimeType = " << type + << ", width = 640 and height = 480" << std::endl; + + WebVTTSubtecParser parser(type, 640, 480); + + std::cout << "Invoking processData with buffer: " << buffer + << ", bufferLen: " << bufferLen + << ", position: " << position + << ", duration: " << duration << std::endl; + + bool result = parser.processData(buffer, bufferLen, position, duration); + std::cout << "processData returned: " << result << " for SubtitleMimeType = " << type << std::endl; + + EXPECT_FALSE(result) << "Expected processData() to return false for zero buffer length with SubtitleMimeType: " << type; + } + + std::cout << "Exiting ZeroBufferLength test" << std::endl; +} + +/** + * @brief Test to validate that processData returns false when provided with a negative playback position. + * + * This test ensures that the WebVTTSubtecParser fails to process data when a negative playback position is specified. It verifies that the function appropriately returns false for each subtitle type provided. + * + * **Test Group ID:** Basic: 01@n + * **Test Case ID:** 020@n + * **Priority:** High@n + * + * **Pre-Conditions:** None@n + * **Dependencies:** None@n + * **User Interaction:** None@n + * + * **Test Procedure:** + * | Variation / Step | Description | Test Data | Expected Result | Notes | + * | :----: | --------- | ---------- |-------------- | ----- | + * | 01 | Initialize test variables and input string buffer | inputStr = "WEBVTT\n\n1\n00:00:00.000 --> 00:00:05.000\nHello, world!", bufferLen = 55, position = -1.0, duration = 5.0 | Buffer and variables are correctly initialized | Should be successful | + * | 02 | Iterate over subtitle types and construct WebVTTSubtecParser object | types[] = { eSUB_TYPE_WEBVTT, eSUB_TYPE_MP4, eSUB_TYPE_TTML, eSUB_TYPE_UNKNOWN }, width = 640, height = 480 | WebVTTSubtecParser object is successfully constructed for each subtitle type | Should be successful | + * | 03 | Invoke processData method on parser object | buffer, bufferLen, position = -1.0, duration = 5.0 | processData returns false, and the EXPECT_FALSE assertion passes | Should Pass | + */ +TEST(WebVTTSubtecParser, NegativePlaybackPosition) +{ + std::cout << "Entering NegativePlaybackPosition test" << std::endl; + + SubtitleMimeType types[] = { + eSUB_TYPE_WEBVTT, + eSUB_TYPE_MP4, + eSUB_TYPE_TTML, + eSUB_TYPE_UNKNOWN + }; + + char buffer[100]; + const char* inputStr = "WEBVTT\n\n1\n00:00:00.000 --> 00:00:05.000\nHello, world!"; + strncpy(buffer, inputStr, sizeof(buffer)); + + size_t bufferLen = 55; + double position = -1.0; + double duration = 5.0; + + for (auto type : types) + { + std::cout << "Creating WebVTTSubtecParser object with SubtitleMimeType = " << type + << ", width = 640 and height = 480" << std::endl; + + WebVTTSubtecParser parser(type, 640, 480); + + std::cout << "Invoking processData with buffer: " << buffer + << ", bufferLen: " << bufferLen + << ", position: " << position + << ", duration: " << duration << std::endl; + + bool result = parser.processData(buffer, bufferLen, position, duration); + std::cout << "processData returned: " << result << " for SubtitleMimeType = " << type << std::endl; + + EXPECT_FALSE(result) << "Expected processData() to return false for negative playback position with SubtitleMimeType: " << type; + } + + std::cout << "Exiting NegativePlaybackPosition test" << std::endl; +} + +/** + * @brief Validate processData function with negative subtitle duration. + * + * This test validates the processData method of the WebVTTSubtecParser class by invoking it with a negative duration value. + * It iterates over different SubtitleMimeType values to ensure that processData correctly returns false when provided with an invalid (negative) subtitle duration. + * + * **Test Group ID:** Basic: 01 + * **Test Case ID:** 021 + * **Priority:** High + * + * **Pre-Conditions:** None + * **Dependencies:** None + * **User Interaction:** None + * + * **Test Procedure:** + * | Variation / Step | Description | Test Data | Expected Result | Notes | + * | :----: | --------- | ---------- |-------------- | ----- | + * | 01 | Invoke processData with SubtitleMimeType = eSUB_TYPE_WEBVTT | input: SubtitleMimeType = eSUB_TYPE_WEBVTT, width = 640, height = 480, buffer = "WEBVTT\n\n1\n00:00:00.000 --> 00:00:05.000\nHello, world!", bufferLen = 55, position = 0.0, duration = -5.0 | processData() returns false and EXPECT_FALSE assertion passes | Should Fail | + * | 02 | Invoke processData with SubtitleMimeType = eSUB_TYPE_MP4 | input: SubtitleMimeType = eSUB_TYPE_MP4, width = 640, height = 480, buffer = "WEBVTT\n\n1\n00:00:00.000 --> 00:00:05.000\nHello, world!", bufferLen = 55, position = 0.0, duration = -5.0 | processData() returns false and EXPECT_FALSE assertion passes | Should Fail | + * | 03 | Invoke processData with SubtitleMimeType = eSUB_TYPE_TTML | input: SubtitleMimeType = eSUB_TYPE_TTML, width = 640, height = 480, buffer = "WEBVTT\n\n1\n00:00:00.000 --> 00:00:05.000\nHello, world!", bufferLen = 55, position = 0.0, duration = -5.0 | processData() returns false and EXPECT_FALSE assertion passes | Should Fail | + * | 04 | Invoke processData with SubtitleMimeType = eSUB_TYPE_UNKNOWN | input: SubtitleMimeType = eSUB_TYPE_UNKNOWN, width = 640, height = 480, buffer = "WEBVTT\n\n1\n00:00:00.000 --> 00:00:05.000\nHello, world!", bufferLen = 55, position = 0.0, duration = -5.0 | processData() returns false and EXPECT_FALSE assertion passes | Should Fail | + */ +TEST(WebVTTSubtecParser, NegativeSubtitleDuration) +{ + std::cout << "Entering NegativeSubtitleDuration test" << std::endl; + + SubtitleMimeType types[] = { + eSUB_TYPE_WEBVTT, + eSUB_TYPE_MP4, + eSUB_TYPE_TTML, + eSUB_TYPE_UNKNOWN + }; + + char buffer[100]; + const char* inputStr = "WEBVTT\n\n1\n00:00:00.000 --> 00:00:05.000\nHello, world!"; + strncpy(buffer, inputStr, sizeof(buffer)); + + size_t bufferLen = 55; + double position = 0.0; + double duration = -5.0; + + for (auto type : types) + { + std::cout << "Creating WebVTTSubtecParser object with SubtitleMimeType = " << type + << ", width = 640 and height = 480" << std::endl; + + WebVTTSubtecParser parser(type, 640, 480); + + std::cout << "Invoking processData with buffer: " << buffer + << ", bufferLen: " << bufferLen + << ", position: " << position + << ", duration: " << duration << std::endl; + + bool result = parser.processData(buffer, bufferLen, position, duration); + std::cout << "processData returned: " << result << " for SubtitleMimeType = " << type << std::endl; + + EXPECT_FALSE(result) << "Expected processData() to return false for negative subtitle duration with SubtitleMimeType: " << type; + } + + std::cout << "Exiting NegativeSubtitleDuration test" << std::endl; +} + +/** + * + * @brief Test processData() returns false when the provided position is greater than duration + * + * This test verifies that the WebVTTSubtecParser::processData() method returns false when the + * 'position' argument is greater than the 'duration' argument. The test iterates through various + * SubtitleMimeType values to ensure consistent behavior across different subtitle types. + * + * **Test Group ID:** Basic: 01@n + * **Test Case ID:** 022@n + * **Priority:** High@n + * + * **Pre-Conditions:** None@n + * **Dependencies:** None@n + * **User Interaction:** None@n + * + * **Test Procedure:** + * | Variation / Step | Description | Test Data | Expected Result | Notes | + * | :----: | --------- | ---------- |-------------- | ----- | + * | 01 | Initialize test data with a valid WEBVTT input string, set buffer length to 55, position to 10.0, and duration to 5.0 | inputStr = "WEBVTT\n\n1\n00:00:00.000 --> 00:00:05.000\nHello, world!", bufferLen = 55, position = 10.0, duration = 5.0 | Test data is set up correctly | Should be successful | + * | 02 | Create a WebVTTSubtecParser object for SubtitleMimeType = eSUB_TYPE_WEBVTT and invoke processData() | SubtitleMimeType = eSUB_TYPE_WEBVTT, width = 640, height = 480, buffer, bufferLen = 55, position = 10.0, duration = 5.0 | processData() returns false; EXPECT_FALSE assertion passes | Should Fail | + * | 03 | Create a WebVTTSubtecParser object for SubtitleMimeType = eSUB_TYPE_MP4 and invoke processData() | SubtitleMimeType = eSUB_TYPE_MP4, width = 640, height = 480, buffer, bufferLen = 55, position = 10.0, duration = 5.0 | processData() returns false; EXPECT_FALSE assertion passes | Should Fail | + * | 04 | Create a WebVTTSubtecParser object for SubtitleMimeType = eSUB_TYPE_TTML and invoke processData() | SubtitleMimeType = eSUB_TYPE_TTML, width = 640, height = 480, buffer, bufferLen = 55, position = 10.0, duration = 5.0 | processData() returns false; EXPECT_FALSE assertion passes | Should Fail | + * | 05 | Create a WebVTTSubtecParser object for SubtitleMimeType = eSUB_TYPE_UNKNOWN and invoke processData() | SubtitleMimeType = eSUB_TYPE_UNKNOWN, width = 640, height = 480, buffer, bufferLen = 55, position = 10.0, duration = 5.0 | processData() returns false; EXPECT_FALSE assertion passes | Should Fail | + */ +TEST(WebVTTSubtecParser, PositionGreaterThanDuration) +{ + std::cout << "Entering PositionGreaterThanDuration test" << std::endl; + + SubtitleMimeType types[] = { + eSUB_TYPE_WEBVTT, + eSUB_TYPE_MP4, + eSUB_TYPE_TTML, + eSUB_TYPE_UNKNOWN + }; + + char buffer[100]; + const char* inputStr = "WEBVTT\n\n1\n00:00:00.000 --> 00:00:05.000\nHello, world!"; + strncpy(buffer, inputStr, sizeof(buffer)); + + size_t bufferLen = 55; + double position = 10.0; + double duration = 5.0; + + for (auto type : types) + { + std::cout << "Creating WebVTTSubtecParser object with SubtitleMimeType = " << type + << ", width = 640 and height = 480" << std::endl; + + WebVTTSubtecParser parser(type, 640, 480); + + std::cout << "Invoking processData with buffer: " << buffer + << ", bufferLen: " << bufferLen + << ", position: " << position + << ", duration: " << duration << std::endl; + + bool result = parser.processData(buffer, bufferLen, position, duration); + std::cout << "processData returned: " << result << " for SubtitleMimeType = " << type << std::endl; + + EXPECT_FALSE(result) << "Expected processData() to return false when position > duration, with SubtitleMimeType: " << type; + } + + std::cout << "Exiting PositionGreaterThanDuration test" << std::endl; +} + +/** + * @brief Test the processData API with valid fractional playback and duration inputs. + * + * This test verifies that the processData function returns true when provided with a valid WEBVTT buffer, + * a defined fractional position and duration, and iterates over various SubtitleMimeType values. + * The objective is to ensure that fractional playback and duration parameters are correctly processed + * regardless of the subtitle type. + * + * **Test Group ID:** Basic: 01@n + * **Test Case ID:** 023@n + * **Priority:** High@n + * + * **Pre-Conditions:** None@n + * **Dependencies:** None@n + * **User Interaction:** None@n + * + * **Test Procedure:**@n + * | Variation / Step | Description | Test Data | Expected Result | Notes | + * | :----: | --------- | ---------- |-------------- | ----- | + * | 01 | Initialize test parameters including a valid WEBVTT string, buffer length, fractional position, and duration. | inputStr = "WEBVTT\n\n1\n00:00:01.500 --> 00:00:03.000\nSubtitle line", bufferLen = 50, position = 1.5, duration = 1.5 | Variables initialized with correct values. | Should be successful | + * | 02 | Loop over each SubtitleMimeType and instantiate the WebVTTSubtecParser with width 640 and height 480. | SubtitleMimeType = eSUB_TYPE_WEBVTT, eSUB_TYPE_MP4, eSUB_TYPE_TTML, eSUB_TYPE_UNKNOWN, width = 640, height = 480 | Parser object is created successfully for each subtitle type. | Should be successful | + * | 03 | Invoke processData with the prepared buffer and parameters and validate the returned result is true. | buffer = valid WEBVTT data, bufferLen = 50, position = 1.5, duration = 1.5, SubtitleMimeType = current type in iteration | processData returns true and the EXPECT_TRUE assertion passes. | Should Pass | + */ +TEST(WebVTTSubtecParser, ValidFractionalPlaybackAndDuration) +{ + std::cout << "Entering ValidFractionalPlaybackAndDuration test" << std::endl; + + SubtitleMimeType types[] = { + eSUB_TYPE_WEBVTT, + eSUB_TYPE_MP4, + eSUB_TYPE_TTML, + eSUB_TYPE_UNKNOWN + }; + + char buffer[100]; + const char* inputStr = "WEBVTT\n\n1\n00:00:01.500 --> 00:00:03.000\nSubtitle line"; + strncpy(buffer, inputStr, sizeof(buffer)); + + size_t bufferLen = 50; + double position = 1.5; + double duration = 1.5; + + for (auto type : types) + { + std::cout << "Creating WebVTTSubtecParser object with SubtitleMimeType = " << type + << ", width = 640 and height = 480" << std::endl; + + WebVTTSubtecParser parser(type, 640, 480); + + std::cout << "Invoking processData with buffer: " << buffer + << ", bufferLen: " << bufferLen + << ", position: " << position + << ", duration: " << duration << std::endl; + + bool result = parser.processData(buffer, bufferLen, position, duration); + std::cout << "processData returned: " << result << " for SubtitleMimeType = " << type << std::endl; + + EXPECT_TRUE(result) << "Expected processData() to return true for valid fractional playback/duration with SubtitleMimeType: " << type; + } + + std::cout << "Exiting ValidFractionalPlaybackAndDuration test" << std::endl; +} + +/** + * @brief Tests the reset functionality of the WebVTTSubtecParser object across all supported SubtitleMimeType types. + * + * This test verifies that calling reset() on a WebVTTSubtecParser instance properly resets time_offset_ms_ and start_ms_ to 0, and ensures that m_channel is allocated. It iterates over various SubtitleMimeType values to ensure that the reset behavior is consistent regardless of the subtitle type. + * + * **Test Group ID:** Basic: 01 + * **Test Case ID:** 024 + * **Priority:** High + * + * **Pre-Conditions:** None + * **Dependencies:** None + * **User Interaction:** None + * + * **Test Procedure:** + * | Variation / Step | Description | Test Data | Expected Result | Notes | + * | :----: | --------- | ---------- |-------------- | ----- | + * | 01 | Create a WebVTTSubtecParser object with a specific SubtitleMimeType, width, and height. | input: type = eSUB_TYPE_WEBVTT, width = 640, height = 480 (subsequent iterations with eSUB_TYPE_MP4, eSUB_TYPE_TTML, eSUB_TYPE_UNKNOWN) | Object is instantiated without errors. | Should Pass | + * | 02 | Invoke the reset() method on the created parser. | output: Call reset() with no parameters | reset() executes and prepares the parser for validation. | Should Pass | + * | 03 | Verify that time_offset_ms_ is set to 0 after reset(). | output: time_offset_ms_ = value after reset() | time_offset_ms_ equals 0. | Should Pass | + * | 04 | Verify that start_ms_ is set to 0 after reset(). | output: start_ms_ = value after reset() | start_ms_ equals 0. | Should Pass | + * | 05 | Verify that m_channel is not a nullptr after reset(). | output: m_channel pointer value after reset() | m_channel is allocated (non-null pointer). | Should Pass | + */ +TEST(WebVTTSubtecParser, reset_start) +{ + std::cout << "Entering reset_start test" << std::endl; + + SubtitleMimeType types[] = { + eSUB_TYPE_WEBVTT, + eSUB_TYPE_MP4, + eSUB_TYPE_TTML, + eSUB_TYPE_UNKNOWN + }; + + for (auto type : types) + { + std::cout << "Creating WebVTTSubtecParser object with type: " << type + << ", width: 640, height: 480" << std::endl; + + WebVTTSubtecParser parser(type, 640, 480); + + parser.reset(); + std::cout << "Called reset() method on parser" << std::endl; + + } + + std::cout << "Exiting reset_start test" << std::endl; +} + +/** + * @brief Verify that the setProgressEventOffset API correctly assigns a positive progress event offset. + * + * This test creates a WebVTTSubtecParser instance for each SubtitleMimeType value (eSUB_TYPE_WEBVTT, eSUB_TYPE_MP4, eSUB_TYPE_TTML, and eSUB_TYPE_UNKNOWN) and then invokes the setProgressEventOffset method with a positive offset value of 10.5. The objective is to ensure that the API accepts the offset without error regardless of the subtitle type. + * + * **Test Group ID:** Basic: 01@n + * **Test Case ID:** 025@n + * **Priority:** High@n + * + * **Pre-Conditions:** None@n + * **Dependencies:** None@n + * **User Interaction:** None@n + * + * **Test Procedure:**@n + * | Variation / Step | Description | Test Data | Expected Result | Notes | + * | :----: | --------- | ---------- |-------------- | ----- | + * | 01 | Create WebVTTSubtecParser object with SubtitleMimeType = eSUB_TYPE_WEBVTT and set offset | input: type = eSUB_TYPE_WEBVTT, width = 1920, height = 1080, offset = 10.5 | Parser object is created and setProgressEventOffset executes with no error; offset set correctly | Should Pass | + * | 02 | Create WebVTTSubtecParser object with SubtitleMimeType = eSUB_TYPE_MP4 and set offset | input: type = eSUB_TYPE_MP4, width = 1920, height = 1080, offset = 10.5 | Parser object is created and setProgressEventOffset executes with no error; offset set correctly | Should Pass | + * | 03 | Create WebVTTSubtecParser object with SubtitleMimeType = eSUB_TYPE_TTML and set offset | input: type = eSUB_TYPE_TTML, width = 1920, height = 1080, offset = 10.5 | Parser object is created and setProgressEventOffset executes with no error; offset set correctly | Should Pass | + * | 04 | Create WebVTTSubtecParser object with SubtitleMimeType = eSUB_TYPE_UNKNOWN and set offset | input: type = eSUB_TYPE_UNKNOWN, width = 1920, height = 1080, offset = 10.5 | Parser object is created and setProgressEventOffset executes with no error; offset set correctly | Should Pass | + */ +TEST(WebVTTSubtecParser, SetPositiveProgressEventOffset) +{ + std::cout << "Entering SetPositiveProgressEventOffset test" << std::endl; + + SubtitleMimeType types[] = { + eSUB_TYPE_WEBVTT, + eSUB_TYPE_MP4, + eSUB_TYPE_TTML, + eSUB_TYPE_UNKNOWN + }; + + double offset = 10.5; + + for (auto type : types) + { + std::cout << "Creating WebVTTSubtecParser object with SubtitleMimeType = " << type + << ", width = 1920, height = 1080" << std::endl; + + WebVTTSubtecParser parser(type, 1920, 1080); + + std::cout << "Invoking setProgressEventOffset with offset: " << offset << std::endl; + + parser.setProgressEventOffset(offset); + + std::cout << "Method setProgressEventOffset executed with offset: " << offset << std::endl; + } + + std::cout << "Exiting SetPositiveProgressEventOffset test" << std::endl; +} + +/** + * @brief Checks that the setProgressEventOffset API correctly processes an offset of zero for various subtitle mime types. + * + * This test iterates over different SubtitleMimeType values, instantiates WebVTTSubtecParser objects with a resolution of 1920x1080, and calls setProgressEventOffset with an offset of 0.0. It verifies that the API executes without error across different supported and unsupported subtitle formats. + * + * **Test Group ID:** Basic: 01 + * **Test Case ID:** 026 + * **Priority:** High + * + * **Pre-Conditions:** None + * **Dependencies:** None + * **User Interaction:** None + * + * **Test Procedure:** + * | Variation / Step | Description | Test Data | Expected Result | Notes | + * | :--------------: | ------------------------------------------------------------------------ | ---------------------------------------------------------------------------------------------- | ------------------------------------------------------------- | ----------- | + * | 01 | Invoke setProgressEventOffset for eSUB_TYPE_WEBVTT | SubtitleMimeType = eSUB_TYPE_WEBVTT, width = 1920, height = 1080, offset = 0.0 | API returns success and sets the progress event offset to zero | Should Pass | + * | 02 | Invoke setProgressEventOffset for eSUB_TYPE_MP4 | SubtitleMimeType = eSUB_TYPE_MP4, width = 1920, height = 1080, offset = 0.0 | API returns success and sets the progress event offset to zero | Should Pass | + * | 03 | Invoke setProgressEventOffset for eSUB_TYPE_TTML | SubtitleMimeType = eSUB_TYPE_TTML, width = 1920, height = 1080, offset = 0.0 | API returns success and sets the progress event offset to zero | Should Pass | + * | 04 | Invoke setProgressEventOffset for eSUB_TYPE_UNKNOWN | SubtitleMimeType = eSUB_TYPE_UNKNOWN, width = 1920, height = 1080, offset = 0.0 | API returns success and sets the progress event offset to zero | Should Pass | + */ +TEST(WebVTTSubtecParser, SetZeroProgressEventOffset) +{ + std::cout << "Entering SetZeroProgressEventOffset test" << std::endl; + + SubtitleMimeType types[] = { + eSUB_TYPE_WEBVTT, + eSUB_TYPE_MP4, + eSUB_TYPE_TTML, + eSUB_TYPE_UNKNOWN + }; + + double offset = 0.0; + + for (auto type : types) + { + std::cout << "Creating WebVTTSubtecParser object with SubtitleMimeType = " << type + << ", width = 1920, height = 1080" << std::endl; + + WebVTTSubtecParser parser(type, 1920, 1080); + + std::cout << "Invoking setProgressEventOffset with offset: " << offset << std::endl; + + parser.setProgressEventOffset(offset); + + std::cout << "Method setProgressEventOffset executed with offset: " << offset << std::endl; + } + + std::cout << "Exiting SetZeroProgressEventOffset test" << std::endl; +} + +/** + * @brief Verify that setProgressEventOffset handles negative offset values correctly. + * + * This test verifies that when a negative offset value is provided to the setProgressEventOffset method, + * the method executes without causing any unexpected behavior across all supported SubtitleMimeType values. + * The test iterates over different subtitle types, creates a parser object, and invokes setProgressEventOffset + * using a negative offset. The objective is to ensure that the API call can gracefully handle negative input. + * + * **Test Group ID:** Basic: 01@n + * **Test Case ID:** 027@n + * **Priority:** High@n + * + * **Pre-Conditions:** None@n + * **Dependencies:** None@n + * **User Interaction:** None@n + * + * **Test Procedure:** + * | Variation / Step | Description | Test Data | Expected Result | Notes | + * | :----: | --------- | ---------- |-------------- | ----- | + * | 01 | Assign negative offset and define supported subtitle types | offset = -5.0, types = {eSUB_TYPE_WEBVTT, eSUB_TYPE_MP4, eSUB_TYPE_TTML, eSUB_TYPE_UNKNOWN} | Variables are correctly initialized | Should be successful | + * | 02 | Iterate over each SubtitleMimeType and create a parser object with specified dimensions | type = each subtitle type, width = 1920, height = 1080 | Parser object is successfully instantiated for each type | Should Pass | + * | 03 | Invoke setProgressEventOffset with the negative offset value on the parser object | offset = -5.0 | API method is executed and handles the negative offset appropriately | Should Pass | + */ +TEST(WebVTTSubtecParser, SetNegativeProgressEventOffset) +{ + std::cout << "Entering SetNegativeProgressEventOffset test" << std::endl; + + SubtitleMimeType types[] = { + eSUB_TYPE_WEBVTT, + eSUB_TYPE_MP4, + eSUB_TYPE_TTML, + eSUB_TYPE_UNKNOWN + }; + + double offset = -5.0; + + for (auto type : types) + { + std::cout << "Creating WebVTTSubtecParser object with SubtitleMimeType = " << type + << ", width = 1920, height = 1080" << std::endl; + + WebVTTSubtecParser parser(type, 1920, 1080); + + std::cout << "Invoking setProgressEventOffset with offset: " << offset << std::endl; + + parser.setProgressEventOffset(offset); + + std::cout << "Method setProgressEventOffset executed with offset: " << offset << std::endl; + } + + std::cout << "Exiting SetNegativeProgressEventOffset test" << std::endl; +} + +/** + * @brief Verify setProgressEventOffset correctly handles a large positive progress offset value. + * + * This test verifies that the WebVTTSubtecParser's setProgressEventOffset method processes a very large positive offset (DBL_MAX) + * correctly for various SubtitleMimeType inputs. The test ensures that the API call executes without error for each type. + * + * **Test Group ID:** Basic: 01@n + * **Test Case ID:** 028@n + * **Priority:** High@n + * + * **Pre-Conditions:** None@n + * **Dependencies:** None@n + * **User Interaction:** None@n + * + * **Test Procedure:**@n + * | Variation / Step | Description | Test Data | Expected Result | Notes | + * | :--------------: | ------------------------------------------------------------------------------------------------------- | -------------------------------------------------------------------------------------------------- | --------------------------------------------------------------------------------------------------------------- | ------------ | + * | 01 | Create WebVTTSubtecParser object with SubtitleMimeType = eSUB_TYPE_WEBVTT, width = 1920, height = 1080 and invoke setProgressEventOffset with offset = DBL_MAX. | SubtitleMimeType = eSUB_TYPE_WEBVTT, width = 1920, height = 1080, offset = DBL_MAX | Method setProgressEventOffset executes successfully without error | Should Pass | + * | 02 | Create WebVTTSubtecParser object with SubtitleMimeType = eSUB_TYPE_MP4, width = 1920, height = 1080 and invoke setProgressEventOffset with offset = DBL_MAX. | SubtitleMimeType = eSUB_TYPE_MP4, width = 1920, height = 1080, offset = DBL_MAX | Method setProgressEventOffset executes successfully without error | Should Pass | + * | 03 | Create WebVTTSubtecParser object with SubtitleMimeType = eSUB_TYPE_TTML, width = 1920, height = 1080 and invoke setProgressEventOffset with offset = DBL_MAX. | SubtitleMimeType = eSUB_TYPE_TTML, width = 1920, height = 1080, offset = DBL_MAX | Method setProgressEventOffset executes successfully without error | Should Pass | + * | 04 | Create WebVTTSubtecParser object with SubtitleMimeType = eSUB_TYPE_UNKNOWN, width = 1920, height = 1080 and invoke setProgressEventOffset with offset = DBL_MAX. | SubtitleMimeType = eSUB_TYPE_UNKNOWN, width = 1920, height = 1080, offset = DBL_MAX | Method setProgressEventOffset executes successfully without error | Should Pass | + */ +TEST(WebVTTSubtecParser, SetLargePositiveProgressEventOffset) +{ + std::cout << "Entering SetLargePositiveProgressEventOffset test" << std::endl; + + SubtitleMimeType types[] = { + eSUB_TYPE_WEBVTT, + eSUB_TYPE_MP4, + eSUB_TYPE_TTML, + eSUB_TYPE_UNKNOWN + }; + + double offset = DBL_MAX; + + for (auto type : types) + { + std::cout << "Creating WebVTTSubtecParser object with SubtitleMimeType = " << type + << ", width = 1920, height = 1080" << std::endl; + + WebVTTSubtecParser parser(type, 1920, 1080); + + std::cout << "Invoking setProgressEventOffset with offset: " << offset << std::endl; + + parser.setProgressEventOffset(offset); + + std::cout << "Method setProgressEventOffset executed with offset: " << offset << std::endl; + } + + std::cout << "Exiting SetLargePositiveProgressEventOffset test" << std::endl; +} + +/** + * @brief Validate large negative offset behavior of setProgressEventOffset API + * + * This test verifies that when a large negative offset value (-DBL_MAX) is provided to the setProgressEventOffset method of the WebVTTSubtecParser for various SubtitleMimeType values, the parser handles the extreme negative value without error. + * + * **Test Group ID:** Basic: 01@n + * **Test Case ID:** 029@n + * **Priority:** High@n + * + * **Pre-Conditions:** None@n + * **Dependencies:** None@n + * **User Interaction:** None@n + * + * **Test Procedure:** + * | Variation / Step | Description | Test Data | Expected Result | Notes | + * | :----: | --------- | ---------- |-------------- | ----- | + * | 01 | Create WebVTTSubtecParser object for each SubtitleMimeType with width 1920 and height 1080 | input: SubtitleMimeType = eSUB_TYPE_WEBVTT, eSUB_TYPE_MP4, eSUB_TYPE_TTML, eSUB_TYPE_UNKNOWN; width = 1920; height = 1080 | Object should be instantiated successfully for each type | Should be successful | + * | 02 | Invoke setProgressEventOffset API with offset = -DBL_MAX on the created parser object | input: offset = -DBL_MAX; output: offset set value | API method executes without error and applies the offset | Should Pass | + */ +TEST(WebVTTSubtecParser, SetLargeNegativeProgressEventOffset) +{ + std::cout << "Entering SetLargeNegativeProgressEventOffset test" << std::endl; + + SubtitleMimeType types[] = { + eSUB_TYPE_WEBVTT, + eSUB_TYPE_MP4, + eSUB_TYPE_TTML, + eSUB_TYPE_UNKNOWN + }; + + double offset = -DBL_MAX; + + for (auto type : types) + { + std::cout << "Creating WebVTTSubtecParser object with SubtitleMimeType = " << type + << ", width = 1920, height = 1080" << std::endl; + + WebVTTSubtecParser parser(type, 1920, 1080); + + std::cout << "Invoking setProgressEventOffset with offset: " << offset << std::endl; + + parser.setProgressEventOffset(offset); + + std::cout << "Method setProgressEventOffset executed with offset: " << offset << std::endl; + } + + std::cout << "Exiting SetLargeNegativeProgressEventOffset test" << std::endl; +} + +/** + * @brief Validates setTextStyle API with a valid style option on various subtitle mime types + * + * This test iterates over a set of subtitle mime types and for each creates a WebVTTSubtecParser object with fixed dimensions. + * It then invokes the setTextStyle method with a valid style options string ("font-size:14px;color:#000;") to verify that + * the API executes without errors and logs the expected messages. + * + * **Test Group ID:** Basic: 01@n + * **Test Case ID:** 030@n + * **Priority:** High@n + * + * **Pre-Conditions:** None@n + * **Dependencies:** None@n + * **User Interaction:** None@n + * + * **Test Procedure:**@n + * | Variation / Step | Description | Test Data | Expected Result | Notes | + * | :--------------: | ---------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------- | ------------- | + * | 01 | Create a WebVTTSubtecParser object for the provided subtitle mime types with dimensions | type = eSUB_TYPE_WEBVTT, eSUB_TYPE_MP4, eSUB_TYPE_TTML, eSUB_TYPE_UNKNOWN, width = 640, height = 480 | WebVTTSubtecParser object is successfully created for each type | Should Pass | + * | 02 | Invoke setTextStyle method with a valid style options string | options = "font-size:14px;color:#000;" | setTextStyle method executes without errors and applies the style; Logging confirms the method execution was successful | Should Pass | + */ +TEST(WebVTTSubtecParser, ValidStyleOption) +{ + std::cout << "Entering ValidStyleOption test" << std::endl; + + SubtitleMimeType types[] = { + eSUB_TYPE_WEBVTT, + eSUB_TYPE_MP4, + eSUB_TYPE_TTML, + eSUB_TYPE_UNKNOWN + }; + + std::string options = "font-size:14px;color:#000;"; + + for (auto type : types) + { + std::cout << "Creating WebVTTSubtecParser object with type as " << type + << ", width 640, height 480" << std::endl; + + WebVTTSubtecParser parser(type, 640, 480); + + std::cout << "Invoking setTextStyle with options: " << options << std::endl; + parser.setTextStyle(options); + std::cout << "Method setTextStyle executed with the provided valid style option" << std::endl; + } + + std::cout << "Exiting ValidStyleOption test" << std::endl; +} + +/** + * @brief Test for default styling behavior when an empty style option is provided + * + * This test checks the functionality of the WebVTTSubtecParser::setTextStyle method when an empty string is passed as the styling option. The test iterates over different subtitle types to validate that the parser applies default styling values regardless of the subtitle type used. + * + * **Test Group ID:** Basic: 01@n + * **Test Case ID:** 031@n + * **Priority:** High@n + * + * **Pre-Conditions:** None@n + * **Dependencies:** None@n + * **User Interaction:** None@n + * + * **Test Procedure:** + * | Variation / Step | Description | Test Data | Expected Result | Notes | + * | :----: | --------- | ---------- |-------------- | ----- | + * | 01 | Output entering message for test start | No inputs | "Entering EmptyStyleOption test" is printed | Should be successful | + * | 02 | Create parser object for each subtitle type and output object creation message | type = eSUB_TYPE_WEBVTT, eSUB_TYPE_MP4, eSUB_TYPE_TTML, eSUB_TYPE_UNKNOWN; width = 640, height = 480 | Parser object is successfully created for each type | Should Pass | + * | 03 | Invoke setTextStyle with an empty string and output method call message | options = "" | setTextStyle executed with empty style option, applying default styling | Should Pass | + * | 04 | Output exiting message for test end | No inputs | "Exiting EmptyStyleOption test" is printed | Should be successful | + */ +TEST(WebVTTSubtecParser, EmptyStyleOption) +{ + std::cout << "Entering EmptyStyleOption test" << std::endl; + + SubtitleMimeType types[] = { + eSUB_TYPE_WEBVTT, + eSUB_TYPE_MP4, + eSUB_TYPE_TTML, + eSUB_TYPE_UNKNOWN + }; + + std::string options = ""; + + for (auto type : types) + { + std::cout << "Creating WebVTTSubtecParser object with type as " << type + << ", width 640, height 480" << std::endl; + + WebVTTSubtecParser parser(type, 640, 480); + + std::cout << "Invoking setTextStyle with empty options string" << std::endl; + parser.setTextStyle(options); + std::cout << "Method setTextStyle executed with empty style option, default styling applied" << std::endl; + } + + std::cout << "Exiting EmptyStyleOption test" << std::endl; +} + +/** + * @brief Verify that the WebVTTSubtecParser handles malformed style options gracefully + * + * This test verifies that the WebVTTSubtecParser gracefully handles the scenario when the setTextStyle method + * is invoked with a malformed style option ("font-size"). The test iterates over different subtitle types (WEBVTT, MP4, + * TTML, and UNKNOWN) to ensure robustness across different internal configurations without causing crashes or unhandled errors. + * + * **Test Group ID:** Basic: 01@n + * **Test Case ID:** 032@n + * **Priority:** High@n + * + * **Pre-Conditions:** None@n + * **Dependencies:** None@n + * **User Interaction:** None@n + * + * **Test Procedure:** + * | Variation / Step | Description | Test Data | Expected Result | Notes | + * | :----: | --------- | ---------- |-------------- | ----- | + * | 01 | Create WebVTTSubtecParser object with type eSUB_TYPE_WEBVTT, width 640, height 480 and invoke setTextStyle with malformed option | input: type = eSUB_TYPE_WEBVTT, width = 640, height = 480, options = "font-size" | API executed without errors; setTextStyle handles malformed option gracefully | Should Pass | + * | 02 | Create WebVTTSubtecParser object with type eSUB_TYPE_MP4, width 640, height 480 and invoke setTextStyle with malformed option | input: type = eSUB_TYPE_MP4, width = 640, height = 480, options = "font-size" | API executed without errors; setTextStyle handles malformed option gracefully | Should Pass | + * | 03 | Create WebVTTSubtecParser object with type eSUB_TYPE_TTML, width 640, height 480 and invoke setTextStyle with malformed option | input: type = eSUB_TYPE_TTML, width = 640, height = 480, options = "font-size" | API executed without errors; setTextStyle handles malformed option gracefully | Should Pass | + * | 04 | Create WebVTTSubtecParser object with type eSUB_TYPE_UNKNOWN, width 640, height 480 and invoke setTextStyle with malformed option | input: type = eSUB_TYPE_UNKNOWN, width = 640, height = 480, options = "font-size" | API executed without errors; setTextStyle handles malformed option gracefully | Should Pass | + */ +TEST(WebVTTSubtecParser, MalformedStyleOption) +{ + std::cout << "Entering MalformedStyleOption test" << std::endl; + + SubtitleMimeType types[] = { + eSUB_TYPE_WEBVTT, + eSUB_TYPE_MP4, + eSUB_TYPE_TTML, + eSUB_TYPE_UNKNOWN + }; + + std::string options = "font-size"; + + for (auto type : types) + { + std::cout << "Creating WebVTTSubtecParser object with type as " << type + << ", width 640, height 480" << std::endl; + + WebVTTSubtecParser parser(type, 640, 480); + + std::cout << "Invoking setTextStyle with malformed options: " << options << std::endl; + parser.setTextStyle(options); + std::cout << "Method setTextStyle executed with malformed style option, handled gracefully" << std::endl; + } + + std::cout << "Exiting MalformedStyleOption test" << std::endl; +} + +/** + * @brief Test high complexity style options application using setTextStyle + * + * This test verifies that the WebVTTSubtecParser::setTextStyle method correctly applies a complex style string when the parser is constructed with various subtitle mime types. It ensures that multiple styling attributes are handled properly for each subtitle type. + * + * **Test Group ID:** Basic: 01 + * **Test Case ID:** 033 + * **Priority:** High + * + * **Pre-Conditions:** None + * **Dependencies:** None + * **User Interaction:** None + * + * **Test Procedure:** + * | Variation / Step | Description | Test Data | Expected Result | Notes | + * | :----: | -------------------------------------------------------------------------------------------------- | -------------------------------------------------------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------- | ------------ | + * | 01 | Create WebVTTSubtecParser with subtitle type eSUB_TYPE_WEBVTT, width 640, height 480 | input: type = eSUB_TYPE_WEBVTT, width = 640, height = 480; option = "font-family:'Arial', sans-serif; font-size:16px; font-weight:bold;" | Parser object created with no errors | Should Pass | + * | 02 | Invoke setTextStyle with high complexity style options on parser for eSUB_TYPE_WEBVTT | input: options = "font-family:'Arial', sans-serif; font-size:16px; font-weight:bold;" | Method executed; style applied successfully | Should Pass | + * | 03 | Create WebVTTSubtecParser with subtitle type eSUB_TYPE_MP4, width 640, height 480 | input: type = eSUB_TYPE_MP4, width = 640, height = 480; option = "font-family:'Arial', sans-serif; font-size:16px; font-weight:bold;" | Parser object created with no errors | Should Pass | + * | 04 | Invoke setTextStyle with high complexity style options on parser for eSUB_TYPE_MP4 | input: options = "font-family:'Arial', sans-serif; font-size:16px; font-weight:bold;" | Method executed; style applied successfully | Should Pass | + * | 05 | Create WebVTTSubtecParser with subtitle type eSUB_TYPE_TTML, width 640, height 480 | input: type = eSUB_TYPE_TTML, width = 640, height = 480; option = "font-family:'Arial', sans-serif; font-size:16px; font-weight:bold;" | Parser object created with no errors | Should Pass | + * | 06 | Invoke setTextStyle with high complexity style options on parser for eSUB_TYPE_TTML | input: options = "font-family:'Arial', sans-serif; font-size:16px; font-weight:bold;" | Method executed; style applied successfully | Should Pass | + * | 07 | Create WebVTTSubtecParser with subtitle type eSUB_TYPE_UNKNOWN, width 640, height 480 | input: type = eSUB_TYPE_UNKNOWN, width = 640, height = 480; option = "font-family:'Arial', sans-serif; font-size:16px; font-weight:bold;" | Parser object created (default behavior for unknown type might apply) | Should Pass | + * | 08 | Invoke setTextStyle with high complexity style options on parser for eSUB_TYPE_UNKNOWN | input: options = "font-family:'Arial', sans-serif; font-size:16px; font-weight:bold;" | Method executed; style applied successfully or handled gracefully for unknown type | Should Pass | + */ +TEST(WebVTTSubtecParser, HighComplexityStyleOption) +{ + std::cout << "Entering HighComplexityStyleOption test" << std::endl; + + SubtitleMimeType types[] = { + eSUB_TYPE_WEBVTT, + eSUB_TYPE_MP4, + eSUB_TYPE_TTML, + eSUB_TYPE_UNKNOWN + }; + + std::string options = "font-family:'Arial', sans-serif; font-size:16px; font-weight:bold;"; + + for (auto type : types) + { + std::cout << "Creating WebVTTSubtecParser object with type as " << type + << ", width 640, height 480" << std::endl; + + WebVTTSubtecParser parser(type, 640, 480); + + std::cout << "Invoking setTextStyle with high complexity options: " << options << std::endl; + parser.setTextStyle(options); + std::cout << "Method setTextStyle executed with multiple styling attributes applied successfully" << std::endl; + } + + std::cout << "Exiting HighComplexityStyleOption test" << std::endl; +} + +/** + * @brief Validate safe handling of malicious text style options in WebVTTSubtecParser + * + * This test verifies that when invalid style options (potentially containing script injections) + * are provided to the WebVTTSubtecParser via the setTextStyle method, the parser processes them + * safely without crashing or misbehaving. + * + * **Test Group ID:** Basic: 01@n + * **Test Case ID:** 034@n + * **Priority:** High@n + * + * **Pre-Conditions:** None@n + * **Dependencies:** None@n + * **User Interaction:** None@n + * + * **Test Procedure:**@n + * | Variation / Step | Description | Test Data | Expected Result | Notes | + * | :----: | --------- | ---------- |-------------- | ----- | + * | 01 | Initialize test and declare a list of SubtitleMimeType values and an invalid options string. | types = {eSUB_TYPE_WEBVTT, eSUB_TYPE_MP4, eSUB_TYPE_TTML, eSUB_TYPE_UNKNOWN}, options = "" | Test variables initialized without runtime errors. | Should be successful | + * | 02 | For each SubtitleMimeType value, create a WebVTTSubtecParser instance with specified dimensions. | input: SubtitleMimeType = one of the list, id = 1, width = 640, height = 480 | Object is constructed successfully. | Should be successful | + * | 03 | Invoke setTextStyle on the parser instance using the invalid options string. | input: options = "", output: none | API call executes safely handling the invalid options; no crashes or errors. | Should Pass | + */ +TEST(WebVTTSubtecParser, InvalidStyleOption) +{ + std::cout << "Entering InvalidStyleOption test" << std::endl; + + SubtitleMimeType types[] = { + eSUB_TYPE_WEBVTT, + eSUB_TYPE_MP4, + eSUB_TYPE_TTML, + eSUB_TYPE_UNKNOWN + }; + + std::string options = ""; + for (auto type : types) + { + std::cout << "Creating WebVTTSubtecParser object with SubtitleMimeType = " << type + << ", width = 640, height = 480" << std::endl; + + WebVTTSubtecParser parser(type, 640, 480); + + std::cout << "Invoking setTextStyle with invalid options: " << options << std::endl; + parser.setTextStyle(options); + std::cout << "Method setTextStyle executed safely with invalid options handled appropriately" << std::endl; + } + + std::cout << "Exiting InvalidStyleOption test" << std::endl; +} + +/** + * @brief Validate correct behavior of updateTimestamp API when invoked with zero milliseconds + * + * This test verifies that invoking updateTimestamp with a timestamp value of zero does not cause any errors or unexpected behavior. It ensures the API handles zero as a valid input across various SubtitleMimeType values. + * + * **Test Group ID:** Basic: 01@n + * **Test Case ID:** 035@n + * **Priority:** High@n + * + * **Pre-Conditions:** None@n + * **Dependencies:** None@n + * **User Interaction:** None@n + * + * **Test Procedure:** + * | Variation / Step | Description | Test Data | Expected Result | Notes | + * | :----: | --------- | ---------- |-------------- | ----- | + * | 01 | Create WebVTTSubtecParser object with SubtitleMimeType = eSUB_TYPE_WEBVTT, width = 1920, height = 1080 and call updateTimestamp | SubtitleMimeType = eSUB_TYPE_WEBVTT, width = 1920, height = 1080, inputTimestamp = 0 | updateTimestamp executed successfully without error | Should Pass | + * | 02 | Create WebVTTSubtecParser object with SubtitleMimeType = eSUB_TYPE_MP4, width = 1920, height = 1080 and call updateTimestamp | SubtitleMimeType = eSUB_TYPE_MP4, width = 1920, height = 1080, inputTimestamp = 0 | updateTimestamp executed successfully without error | Should Pass | + * | 03 | Create WebVTTSubtecParser object with SubtitleMimeType = eSUB_TYPE_TTML, width = 1920, height = 1080 and call updateTimestamp | SubtitleMimeType = eSUB_TYPE_TTML, width = 1920, height = 1080, inputTimestamp = 0 | updateTimestamp executed successfully without error | Should Pass | + * | 04 | Create WebVTTSubtecParser object with SubtitleMimeType = eSUB_TYPE_UNKNOWN, width = 1920, height = 1080 and call updateTimestamp | SubtitleMimeType = eSUB_TYPE_UNKNOWN, width = 1920, height = 1080, inputTimestamp = 0 | updateTimestamp executed successfully without error | Should Pass | + */ +TEST(WebVTTSubtecParser, UpdateTimestampWithZeroMilliseconds) +{ + std::cout << "Entering UpdateTimestampWithZeroMilliseconds test" << std::endl; + + SubtitleMimeType types[] = { + eSUB_TYPE_WEBVTT, + eSUB_TYPE_MP4, + eSUB_TYPE_TTML, + eSUB_TYPE_UNKNOWN + }; + + unsigned long long inputTimestamp = 0; + + for (auto type : types) + { + std::cout << "Creating WebVTTSubtecParser object with SubtitleMimeType = " << type + << ", width = 1920, height = 1080" << std::endl; + + WebVTTSubtecParser parser(type, 1920, 1080); + + std::cout << "Invoking updateTimestamp with value: " << inputTimestamp << std::endl; + + parser.updateTimestamp(inputTimestamp); + + std::cout << "updateTimestamp invoked successfully with input: " << inputTimestamp << std::endl; + } + + std::cout << "Exiting UpdateTimestampWithZeroMilliseconds test" << std::endl; +} + +/** + * @brief Test the updateTimestamp function with typical positive value + * + * This test verifies that the updateTimestamp method of the WebVTTSubtecParser class correctly processes a typical positive timestamp value (12345) for various SubtitleMimeType values. The test creates a parser object for each subtitle type and invokes the updateTimestamp method, ensuring that no errors occur and that the parser's internal state is assumed to be correctly updated. + * + * **Test Group ID:** Basic: 01@n + * **Test Case ID:** 036@n + * **Priority:** High@n + * + * **Pre-Conditions:** None@n + * **Dependencies:** None@n + * **User Interaction:** None@n + * + * **Test Procedure:**@n + * | Variation / Step | Description | Test Data | Expected Result | Notes | + * | :--------------: | ------------------------------------------------------------------------------------------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------- | --------------------------------------------------------------------- | --------------- | + * | 01 | Initialize SubtitleMimeType array with various types and set the input timestamp value. | SubtitleMimeType = eSUB_TYPE_WEBVTT, eSUB_TYPE_MP4, eSUB_TYPE_TTML, eSUB_TYPE_UNKNOWN; inputTimestamp = 12345 | Variables initialized correctly. | Should be successful | + * | 02 | Create a WebVTTSubtecParser object for each subtitle type with resolution 1920x1080. | type = one among {eSUB_TYPE_WEBVTT, eSUB_TYPE_MP4, eSUB_TYPE_TTML, eSUB_TYPE_UNKNOWN}; width = 1920, height = 1080 | Parser object created successfully. | Should Pass | + * | 03 | Invoke updateTimestamp on the parser object with the input timestamp. | inputTimestamp = 12345 | updateTimestamp executes successfully; assertion EXPECT_TRUE(true) passes. | Should Pass | + */ +TEST(WebVTTSubtecParser, UpdateTimestampWithTypicalPositiveValue) +{ + std::cout << "Entering UpdateTimestampWithTypicalPositiveValue test" << std::endl; + + SubtitleMimeType types[] = { + eSUB_TYPE_WEBVTT, + eSUB_TYPE_MP4, + eSUB_TYPE_TTML, + eSUB_TYPE_UNKNOWN + }; + + unsigned long long inputTimestamp = 12345; + + for (auto type : types) + { + std::cout << "Creating WebVTTSubtecParser object with SubtitleMimeType = " << type + << ", width = 1920, height = 1080" << std::endl; + + WebVTTSubtecParser parser(type, 1920, 1080); + + std::cout << "Invoking updateTimestamp with value: " << inputTimestamp << std::endl; + + parser.updateTimestamp(inputTimestamp); + + std::cout << "updateTimestamp invoked successfully with input: " << inputTimestamp << std::endl; + + // You can replace this with a real assertion if internal state can be verified + EXPECT_TRUE(true); + } + + std::cout << "Exiting UpdateTimestampWithTypicalPositiveValue test" << std::endl; +} + +int main(int argc, char **argv) { + ::testing::InitGoogleTest(&argc, argv); + return RUN_ALL_TESTS(); +} diff --git a/subtec/subtecparser/test/test_l1_WebvttSubtecDevInterface.cpp b/subtec/subtecparser/test/test_l1_WebvttSubtecDevInterface.cpp new file mode 100755 index 0000000..5c566eb --- /dev/null +++ b/subtec/subtecparser/test/test_l1_WebvttSubtecDevInterface.cpp @@ -0,0 +1,786 @@ + +/* + * If not stated otherwise in this file or this component's LICENSE file the + * following copyright and licenses apply: + * + * Copyright 2025 RDK Management + * + * 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. + */ + +/** +* @file test_l1_WebvttSubtecDevInterface.cpp +* @page WebvttSubtecDevInterfaces Level 1 Tests +* +* ## Module's Role +* This module includes Level 1 functional tests (success and failure scenarios). +* This is to ensure that the WebvttSubtecDevInterface methods meet the requirements. +* +* **Pre-Conditions:** None @n +* **Dependencies:** None @n +* +*/ + +#include +#include +#include +#include "WebvttSubtecDevInterface.hpp" + + +/** + * @brief Test the construction of WebvttSubtecDevInterface using valid dimensions. + * + * This test verifies that constructing a WebvttSubtecDevInterface object with width = 1920 and height = 1080 does not throw an exception. + * + * **Test Group ID:** Basic: 01 + * **Test Case ID:** 001 + * **Priority:** High + * + * **Pre-Conditions:** None + * **Dependencies:** None + * **User Interaction:** None + * + * **Test Procedure:** + * | Variation / Step | Description | Test Data | Expected Result | Notes | + * | :--------------: | ----------------------------------------------------------------------- | ---------------------------- | ------------------------------------------------------------ | ----------- | + * | 01 | Invoke the WebvttSubtecDevInterface constructor with valid dimensions | width = 1920, height = 1080 | Object created successfully; no exception thrown and assertion passes | Should Pass | + */ +TEST(WebvttSubtecDevInterface, ValidDimensionsConstructorTest) +{ + std::cout << "Entering ValidDimensionsConstructorTest test" << std::endl; + + std::cout << "Invoking WebvttSubtecDevInterface constructor with width = 1920 and height = 1080" << std::endl; + ASSERT_NO_THROW({ + WebvttSubtecDevInterface obj(1920, 1080); + std::cout << "WebvttSubtecDevInterface object created successfully with width: 1920, height: 1080" << std::endl; + }); + + std::cout << "Exiting ValidDimensionsConstructorTest test" << std::endl; +} +/** + * @brief Verify constructor behavior with zero dimensions. + * + * This test verifies that invoking the WebvttSubtecDevInterface constructor with width = 0 and height = 0 does not throw any exceptions. + * + * **Test Group ID:** Basic: 01@n + * **Test Case ID:** 002@n + * **Priority:** High@n + * + * **Pre-Conditions:** None@n + * **Dependencies:** None@n + * **User Interaction:** None@n + * + * **Test Procedure:**@n + * | Variation / Step | Description | Test Data | Expected Result | Notes | + * | :----: | --------- | ---------- |-------------- | ----- | + * | 01 | Invoke constructor and verify no exceptions are thrown | input1 = 0, input2 = 0 | Object created successfully, no exception thrown and "WebvttSubtecDevInterface object created successfully with width: 0, height: 0" printed | Should Pass | + */ +TEST(WebvttSubtecDevInterface, ZeroDimensionsConstructorTest) +{ + std::cout << "Entering ZeroDimensionsConstructorTest test" << std::endl; + + std::cout << "Invoking WebvttSubtecDevInterface constructor with width = 0 and height = 0" << std::endl; + ASSERT_NO_THROW({ + WebvttSubtecDevInterface obj(0, 0); + std::cout << "WebvttSubtecDevInterface object created successfully with width: 0, height: 0" << std::endl; + }); + + std::cout << "Exiting ZeroDimensionsConstructorTest test" << std::endl; +} +/** + * @brief Validate that WebvttSubtecDevInterface constructor throws an exception when width is zero. + * + * This test verifies that invoking the WebvttSubtecDevInterface constructor with a width of 0 and a valid height of 768 + * results in an exception. The test ensures that the constructor does not allow creation of an object with an invalid width. + * + * **Test Group ID:** Basic: 01@n + * **Test Case ID:** 003@n + * **Priority:** High@n + * + * **Pre-Conditions:** None@n + * **Dependencies:** None@n + * **User Interaction:** None@n + * + * **Test Procedure:**@n + * | Variation / Step | Description | Test Data | Expected Result | Notes | + * | :----: | --------- | ---------- |-------------- | ----- | + * | 01 | Invoke WebvttSubtecDevInterface constructor with width = 0 and height = 768 | width = 0, height = 768 | Exception is thrown confirming invalid width input; ASSERT_ANY_THROW validates the exception | Should Fail | + */ +TEST(WebvttSubtecDevInterface, ZeroWidthValidHeightConstructorTest) +{ + std::cout << "Entering ZeroWidthValidHeightConstructorTest test" << std::endl; + + std::cout << "Invoking WebvttSubtecDevInterface constructor with width = 0 and height = 768" << std::endl; + ASSERT_ANY_THROW({ + WebvttSubtecDevInterface obj(0, 768); + std::cout << "Error: WebvttSubtecDevInterface object should not be created with width: 0" << std::endl; + }); + + std::cout << "Exiting ZeroWidthValidHeightConstructorTest test" << std::endl; +} +/** + * @brief Validate that WebvttSubtecDevInterface constructor throws an exception when height is zero. + * + * This test verifies that constructing the WebvttSubtecDevInterface with a valid width and zero height triggers an exception, + * ensuring proper parameter validation. The test checks that an object is not created with invalid dimensions. + * + * **Test Group ID:** Basic: 01@n + * **Test Case ID:** 004@n + * **Priority:** High@n + * + * **Pre-Conditions:** None@n + * **Dependencies:** None@n + * **User Interaction:** None@n + * + * **Test Procedure:** + * | Variation / Step | Description | Test Data | Expected Result | Notes | + * | :----: | --------- | ---------- |-------------- | ----- | + * | 01 | Invoke WebvttSubtecDevInterface constructor with width = 1024 and height = 0 to verify exception handling. | width = 1024, height = 0 | API throws an exception; ASSERT_ANY_THROW check passes. | Should Pass | + */ +TEST(WebvttSubtecDevInterface, ValidWidthZeroHeightConstructorTest) +{ + std::cout << "Entering ValidWidthZeroHeightConstructorTest test" << std::endl; + + std::cout << "Invoking WebvttSubtecDevInterface constructor with width = 1024 and height = 0" << std::endl; + ASSERT_ANY_THROW({ + WebvttSubtecDevInterface obj(1024, 0); + std::cout << "Error: WebvttSubtecDevInterface object should not be created with height: 0" << std::endl; + }); + + std::cout << "Exiting ValidWidthZeroHeightConstructorTest test" << std::endl; +} +/** + * @brief Verify that the WebvttSubtecDevInterface constructor correctly handles a negative width input while given a valid height. + * + * This test verifies that the WebvttSubtecDevInterface constructor throws an exception when a negative width is provided (width = -800) along with a valid height (height = 600). The test ensures the constructor does not create an object when provided with invalid input, which is critical for maintaining robust behavior in the API. + * + * **Test Group ID:** Basic: 01@n + * **Test Case ID:** 005@n + * **Priority:** High@n + * + * **Pre-Conditions:** None@n + * **Dependencies:** None@n + * **User Interaction:** None@n + * + * **Test Procedure:**@n + * | Variation / Step | Description | Test Data | Expected Result | Notes | + * | :--------------: | ------------------------------------------------------------------------------------ | ------------------------------ | ----------------------------------------------------------------- | ----------- | + * | 01 | Invoke WebvttSubtecDevInterface constructor with negative width (-800) and height (600)| width = -800, height = 600 | API should throw an exception and the assertion should pass | Should Fail | + */ +TEST(WebvttSubtecDevInterface, NegativeWidthValidHeightConstructorTest) +{ + std::cout << "Entering NegativeWidthValidHeightConstructorTest test" << std::endl; + + std::cout << "Invoking WebvttSubtecDevInterface constructor with width = -800 and height = 600" << std::endl; + ASSERT_ANY_THROW({ + WebvttSubtecDevInterface obj(-800, 600); + std::cout << "Error: WebvttSubtecDevInterface object should not be created with negative width: -800" << std::endl; + }); + + std::cout << "Exiting NegativeWidthValidHeightConstructorTest test" << std::endl; +} +/** + * @brief Verify that the WebvttSubtecDevInterface constructor throws an exception for a negative height. + * + * This test verifies that constructing a WebvttSubtecDevInterface object with a valid width of 800 and a negative height of -600 correctly throws an exception. This behavior ensures that the constructor properly handles invalid dimension inputs. + * + * **Test Group ID:** Basic: 01 + * **Test Case ID:** 006 + * **Priority:** High + * + * **Pre-Conditions:** None + * **Dependencies:** None + * **User Interaction:** None + * + * **Test Procedure:** + * | Variation / Step | Description | Test Data | Expected Result | Notes | + * | :----: | --------- | ---------- |-------------- | ----- | + * | 01 | Call the constructor within ASSERT_ANY_THROW to test exception handling. | input: width = 800, height = -600, output: exception thrown | The constructor invocation should throw an exception. | Should Fail | + */ +TEST(WebvttSubtecDevInterface, ValidWidthNegativeHeightConstructorTest) +{ + std::cout << "Entering ValidWidthNegativeHeightConstructorTest test" << std::endl; + + std::cout << "Invoking WebvttSubtecDevInterface constructor with width = 800 and height = -600" << std::endl; + ASSERT_ANY_THROW({ + WebvttSubtecDevInterface obj(800, -600); + std::cout << "Error: WebvttSubtecDevInterface object should not be created with negative height: -600" << std::endl; + }); + + std::cout << "Exiting ValidWidthNegativeHeightConstructorTest test" << std::endl; +} +/** + * @brief Verify that the WebvttSubtecDevInterface constructor can handle extremely large dimensions + * + * This test verifies that the WebvttSubtecDevInterface constructor can be invoked with INT_MAX for both width and height without throwing any exception. This is critical to ensure that the API can properly handle edge cases involving maximum integer values. + * + * **Test Group ID:** Basic: 01@n + * **Test Case ID:** 007@n + * **Priority:** High@n + * @n + * **Pre-Conditions:** None@n + * **Dependencies:** None@n + * **User Interaction:** None@n + * @n + * **Test Procedure:** + * | Variation / Step | Description | Test Data | Expected Result | Notes | + * | :----: | --------- | ---------- |-------------- | ----- | + * | 01 | Invoke the WebvttSubtecDevInterface constructor with maximum integer values for width and height | width = INT_MAX, height = INT_MAX, output = Object constructed successfully | Constructor does not throw any exception and object is created successfully | Should Pass | + */ +TEST(WebvttSubtecDevInterface, ExtremelyLargeDimensionsConstructorTest) +{ + std::cout << "Entering ExtremelyLargeDimensionsConstructorTest test" << std::endl; + + std::cout << "Invoking WebvttSubtecDevInterface constructor with width = INT_MAX and height = INT_MAX" << std::endl; + ASSERT_NO_THROW({ + WebvttSubtecDevInterface obj(INT_MAX, INT_MAX); + std::cout << "WebvttSubtecDevInterface object created successfully with width: " << INT_MAX << " and height: " << INT_MAX << std::endl; + }); + + std::cout << "Exiting ExtremelyLargeDimensionsConstructorTest test" << std::endl; +} +/** + * @brief Test valid initialization of WebvttSubtecDevInterface with a typical base PTS value. + * + * This test verifies that the WebvttSubtecDevInterface is correctly initialized when constructed with a width of 640 and a height of 480, + * and then initialized using a typical basePTS value of 1000. The test confirms that the initialization process returns true, indicating + * that the interface is set up properly. + * + * **Test Group ID:** Basic: 01 + * **Test Case ID:** 008 + * **Priority:** High + * + * **Pre-Conditions:** None + * **Dependencies:** None + * **User Interaction:** None + * + * **Test Procedure:** + * | Variation / Step | Description | Test Data | Expected Result | Notes | + * | :--------------: | ----------------------------------------------------------------- | ------------------------------------------- | ---------------------------------------------------------------- | ------------------ | + * | 02 | Create a WebvttSubtecDevInterface object with specific dimensions. | width = 640, height = 480 | Object is instantiated successfully with provided dimensions. | Should be successful | + * | 03 | Define the basePTS value to be used for initialization. | basePTS = 1000 | Variable basePTS is set to 1000. | Should be successful | + * | 04 | Call the init() method with the defined basePTS value. | input: basePTS = 1000, output: result expected = true | The init() method returns true; EXPECT_TRUE assertion passes. | Should Pass | + */ +TEST(WebvttSubtecDevInterface, ValidInitializationWithTypicalBasePTS) +{ + std::cout << "Entering ValidInitializationWithTypicalBasePTS test" << std::endl; + + std::cout << "Creating WebvttSubtecDevInterface object with width=640 and height=480" << std::endl; + WebvttSubtecDevInterface interface(640, 480); + + unsigned long long basePTS = 1000; + std::cout << "Invoking init with basePTS = " << basePTS << std::endl; + bool result = interface.init(basePTS); + std::cout << "init returned value: " << result << std::endl; + EXPECT_TRUE(result); + + std::cout << "Exiting ValidInitializationWithTypicalBasePTS test" << std::endl; +} +/** + * @brief Validate that WebvttSubtecDevInterface initializes correctly with a zero base PTS. + * + * This test verifies that the WebvttSubtecDevInterface object is created with the expected dimensions and that its initialization method (init) returns a true value when provided with a basePTS value of zero. The objective is to ensure that the API handles valid initialization parameters as expected. + * + * **Test Group ID:** Basic: 01@n + * **Test Case ID:** 009@n + * **Priority:** High@n + * + * **Pre-Conditions:** None@n + * **Dependencies:** None@n + * **User Interaction:** None@n + * + * **Test Procedure:** + * | Variation / Step | Description | Test Data | Expected Result | Notes | + * | :--------------: | ------------------------------------------------------------------ | ---------------------------------------- | -------------------------------------------- | ---------------- | + * | 01 | Create WebvttSubtecDevInterface object with specified dimensions | width = 640, height = 480 | Object created successfully | Should be successful | + * | 02 | Invoke the init method with a basePTS of zero | basePTS = 0, output: result = true | init returns true, indicating successful init| Should Pass | + * | 03 | Validate the return value using EXPECT_TRUE | result = true | Assertion passes if result is true | Should Pass | + */ +TEST(WebvttSubtecDevInterface, ValidInitializationWithZeroBasePTS) +{ + std::cout << "Entering ValidInitializationWithZeroBasePTS test" << std::endl; + + std::cout << "Creating WebvttSubtecDevInterface object with width=640 and height=480" << std::endl; + WebvttSubtecDevInterface interface(640, 480); + + unsigned long long basePTS = 0; + std::cout << "Invoking init with basePTS = " << basePTS << std::endl; + bool result = interface.init(basePTS); + std::cout << "init returned value: " << result << std::endl; + EXPECT_TRUE(result); + + std::cout << "Exiting ValidInitializationWithZeroBasePTS test" << std::endl; +} +/** + * @brief Validate initialization of WebvttSubtecDevInterface with maximum basePTS value + * + * This test verifies that the WebvttSubtecDevInterface object can be successfully initialized using the maximum value of an unsigned long long as basePTS, ensuring that boundary conditions are handled correctly. + * + * **Test Group ID:** Basic: 01 + * **Test Case ID:** 010 + * **Priority:** High + * + * **Pre-Conditions:** None + * **Dependencies:** None + * **User Interaction:** None + * + * **Test Procedure:** + * | Variation / Step | Description | Test Data | Expected Result | Notes | + * | :----: | --------- | ---------- |-------------- | ----- | + * | 01 | Create WebvttSubtecDevInterface object with width=640 and height=480 | width = 640, height = 480 | Object instantiated successfully | Should be successful | + * | 02 | Set basePTS to maximum unsigned long long value (ULLONG_MAX) | basePTS = ULLONG_MAX | basePTS is set to ULLONG_MAX | Should be successful | + * | 03 | Invoke init method with basePTS value | input: basePTS = ULLONG_MAX, output: result | init returns true indicating successful initialization | Should Pass | + * | 04 | Validate the return value using EXPECT_TRUE assertion | output: result = true | Assertion passes confirming successful initialization | Should be successful | + */ +TEST(WebvttSubtecDevInterface, ValidInitializationWithMaxBasePTS) +{ + std::cout << "Entering ValidInitializationWithMaxBasePTS test" << std::endl; + + std::cout << "Creating WebvttSubtecDevInterface object with width=640 and height=480" << std::endl; + WebvttSubtecDevInterface interface(640, 480); + + unsigned long long basePTS = ULLONG_MAX; + std::cout << "Invoking init with basePTS = " << basePTS << std::endl; + bool result = interface.init(basePTS); + std::cout << "init returned value: " << result << std::endl; + EXPECT_TRUE(result); + + std::cout << "Exiting ValidInitializationWithMaxBasePTS test" << std::endl; +} +/** + * @brief Verify that invoking mute(true) sets the internal state to muted + * + * This test ensures that when the mute method is invoked with true, the WebvttSubtecDevInterface object's internal state is updated accordingly. The test creates an instance of the interface, passes the mute command, and logs each step to verify proper execution. + * + * **Test Group ID:** Basic: 01@n + * **Test Case ID:** 011@n + * **Priority:** High@n + * + * **Pre-Conditions:** None@n + * **Dependencies:** None@n + * **User Interaction:** None@n + * + * **Test Procedure:** + * | Variation / Step | Description | Test Data | Expected Result | Notes | + * | :----: | ------------------------------------------------------- | ------------------------------------------------- | ---------------------------------------------------------------------- | ------------------ | + * | 01 | Create an instance of WebvttSubtecDevInterface | width = 640, height = 480 | Object is created successfully | Should be successful | + * | 02 | Set muteValue to true and display its value | muteValue = true | muteValue is set to true and printed correctly | Should Pass | + * | 03 | Invoke mute function on the interface object | input: muteValue = true | The mute method executes without error and the internal state is set to muted | Should Pass | + * | 04 | Log the exiting of the test | (none) | Log displays that the test has exited successfully | Should be successful | + */ +TEST(WebvttSubtecDevInterface, MuteSubtitlesWithTrue) +{ + std::cout<<"Entering MuteSubtitlesWithTrue test"<

Sample Cue Text

", sizeof(validCue) - 1); + validCue[sizeof(validCue) - 1] = '\0'; + std::cout << "Invoking sendCueData with input: " << validCue << std::endl; + devInterface.sendCueData(validCue); + std::cout << "sendCueData invoked; Cue data sent successfully; method processed the valid TTML cue" << std::endl; + + std::cout << "Exiting PositiveTest test" << std::endl; +} +/** + * @brief Validate that sendCueData API gracefully handles an empty TTML input string. + * + * This test ensures that the WebvttSubtecDevInterface::sendCueData method can handle an empty string input without errors or unexpected behavior. The interface is initialized with specific dimensions, an empty cue string is prepared, and then the API is invoked. + * + * **Test Group ID:** Basic: 01 + * **Test Case ID:** 017 + * **Priority:** High + * + * **Pre-Conditions:** None + * **Dependencies:** None + * **User Interaction:** None + * + * **Test Procedure:** + * | Variation / Step | Description | Test Data | Expected Result | Notes | + * | :----: | --------- | ---------- |-------------- | ----- | + * | 01 | Instantiate WebvttSubtecDevInterface with width=640 and height=480, prepare an empty cue string, and invoke sendCueData with the empty string. | width=640, height=480, emptyCue="" | sendCueData should execute without errors and handle the empty input gracefully, confirmed by log messages. | Should Pass | + */ +TEST(WebvttSubtecDevInterface, EmptyStringTest) +{ + std::cout << "Entering EmptyStringTest test" << std::endl; + + WebvttSubtecDevInterface devInterface(640, 480); + std::cout << "Created WebvttSubtecDevInterface object with width 640 and height 480" << std::endl; + + char emptyCue[1]; + strncpy(emptyCue, "", sizeof(emptyCue) - 1); + emptyCue[sizeof(emptyCue) - 1] = '\0'; + std::cout << "Invoking sendCueData with input: " << (emptyCue[0] ? emptyCue : "Empty String") << std::endl; + devInterface.sendCueData(emptyCue); + std::cout << "sendCueData invoked; Method handled empty TTML input gracefully" << std::endl; + + std::cout << "Exiting EmptyStringTest test" << std::endl; +} +/** + * @brief Verify that sendCueData gracefully handles invalid TTML input + * + * This test verifies that the sendCueData method identifies and handles malformed TTML input without causing unexpected behavior or crashes. It ensures that when invalid cue data is provided, the method processes it appropriately by detecting the error and handling it gracefully. + * + * **Test Group ID:** Basic: 01@n + * **Test Case ID:** 018@n + * **Priority:** High@n + * + * **Pre-Conditions:** None@n + * **Dependencies:** None@n + * **User Interaction:** None@n + * + * **Test Procedure:** + * | Variation / Step | Description | Test Data | Expected Result | Notes | + * | :----: | --------- | ---------- |-------------- | ----- | + * | 01 | Instantiate WebvttSubtecDevInterface with resolution 640x480 | inputWidth = 640, inputHeight = 480 | Instance created successfully | Should be successful | + * | 02 | Prepare invalid TTML cue data in a char buffer | invalidCue = "Invalid TTML data without proper tags" | Buffer initialized with invalid cue data | Should be successful | + * | 03 | Call sendCueData with the invalid TTML cue data | input = invalidCue | sendCueData handles malformed input gracefully with proper error handling | Should Pass | + */ +TEST(WebvttSubtecDevInterface, InvalidFormatTest) +{ + std::cout << "Entering InvalidFormatTest test" << std::endl; + + WebvttSubtecDevInterface devInterface(640, 480); + std::cout << "Created WebvttSubtecDevInterface object with width 640 and height 480" << std::endl; + + char invalidCue[128]; + strncpy(invalidCue, "Invalid TTML data without proper tags", sizeof(invalidCue) - 1); + invalidCue[sizeof(invalidCue) - 1] = '\0'; + std::cout << "Invoking sendCueData with input: " << invalidCue << std::endl; + devInterface.sendCueData(invalidCue); + std::cout << "sendCueData invoked; Method identified malformed TTML input and handled gracefully" << std::endl; + + std::cout << "Exiting InvalidFormatTest test" << std::endl; +} +/** + * @brief Verify processing of minimal TTML structure by sendCueData API + * + * This test ensures that a WebvttSubtecDevInterface object is instantiated with the correct dimensions, a minimal valid TTML cue is prepared, + * and the sendCueData API correctly processes the minimal TTML structure without errors. + * + * **Test Group ID:** Basic: 01@n + * **Test Case ID:** 019@n + * **Priority:** High@n + * + * **Pre-Conditions:** None@n + * **Dependencies:** None@n + * **User Interaction:** None@n + * + * **Test Procedure:**@n + * | Variation / Step | Description | Test Data | Expected Result | Notes | + * | :--------------: | --------------------------------------------------------------------------- | ----------------------------------------- | ------------------------------------------------------------------------ | ----------------- | + * | 01 | Initialize WebvttSubtecDevInterface instance with resolution 640x480 | input1 = 640, input2 = 480 | Object is successfully created | Should be successful | + * | 02 | Prepare minimal TTML cue data by copying "" into the buffer | minimalCue = "" | Buffer contains a null-terminated minimal TTML structure | Should be successful | + * | 03 | Invoke sendCueData API with the prepared minimal TTML cue | input minimalCue = "" | API processes the minimal TTML structure without errors | Should Pass | + * | 04 | Log the entry and exit points of the test execution | N/A | Correct log messages are printed to the console | Should be successful | + */ +TEST(WebvttSubtecDevInterface, MinimalStructureTest) +{ + std::cout << "Entering MinimalStructureTest test" << std::endl; + + WebvttSubtecDevInterface devInterface(640, 480); + std::cout << "Created WebvttSubtecDevInterface object with width 640 and height 480" << std::endl; + + char minimalCue[16]; + strncpy(minimalCue, "", sizeof(minimalCue) - 1); + minimalCue[sizeof(minimalCue) - 1] = '\0'; + std::cout << "Invoking sendCueData with input: " << minimalCue << std::endl; + devInterface.sendCueData(minimalCue); + std::cout << "sendCueData invoked; Minimal TTML structure processed successfully" << std::endl; + + std::cout << "Exiting MinimalStructureTest test" << std::endl; +} +/** + * @brief Validates that WebvttSubtecDevInterface::sendCueData manages large TTML data inputs under stress conditions + * + * This test instantiates the WebvttSubtecDevInterface with valid dimensions and constructs a large TTML string by concatenating a cue snippet 1000 times. + * The test then invokes sendCueData with the large TTML input to ensure that the method handles the data efficiently and without errors in a stress scenario. + * + * **Test Group ID:** Basic: 01 + * **Test Case ID:** 020 + * **Priority:** High + * + * **Pre-Conditions:** None + * **Dependencies:** None + * **User Interaction:** None + * + * **Test Procedure:** + * | Variation / Step | Description | Test Data | Expected Result | Notes | + * | :----: | --------- | ---------- |-------------- | ----- | + * | 01 | Instantiate WebvttSubtecDevInterface, create a large TTML string, copy it to an array, and invoke sendCueData | input1 = WebvttSubtecDevInterface(640, 480), input2 = largeCueArray = "
" + "

Cue

" * 1000 + "
" | sendCueData processes the large TTML data without errors | Should Pass | + */ +TEST(WebvttSubtecDevInterface, StressTest) +{ + std::cout << "Entering StressTest test" << std::endl; + + WebvttSubtecDevInterface devInterface(640, 480); + std::cout << "Created WebvttSubtecDevInterface object with width 640 and height 480" << std::endl; + + std::string largeCue = "
"; + const char* cueSnippet = "

Cue

"; + for (int i = 0; i < 1000; i++) + { + largeCue += cueSnippet; + } + largeCue += "
"; + char largeCueArray[10000]; + strncpy(largeCueArray, largeCue.c_str(), sizeof(largeCueArray) - 1); + largeCueArray[sizeof(largeCueArray) - 1] = '\0'; + std::cout << "Invoking sendCueData with large TTML data input of length: " << strlen(largeCueArray) << std::endl; + devInterface.sendCueData(largeCueArray); + std::cout << "sendCueData invoked; Method handled large TTML data input efficiently" << std::endl; + + std::cout << "Exiting StressTest test" << std::endl; +} +/** + * @brief Ensure updateTimestamp correctly updates the internal timestamp to zero. + * + * This test verifies that calling updateTimestamp with a timestamp value of 0 successfully updates the internal state of the WebvttSubtecDevInterface object to 0. It confirms the basic functionality of the timestamp update mechanism when the minimum valid value is provided. + * + * **Test Group ID:** Basic: 01 + * **Test Case ID:** 021 + * **Priority:** High + * + * **Pre-Conditions:** None + * **Dependencies:** None + * **User Interaction:** None + * + * **Test Procedure:** + * | Variation / Step | Description | Test Data | Expected Result | Notes | + * | :--------------: | --------------------------------------------------------------------------- | ------------------------------------------ | -------------------------------------------- | --------------- | + * | 01 | Create WebvttSubtecDevInterface object with specified dimensions | input1=width:640, input2=height:480 | Instance is created successfully | Should be successful | + * | 02 | Invoke updateTimestamp with positionMs set to 0 | input1=positionMs:0 | Internal timestamp updated to 0 | Should Pass | + */ +TEST(WebvttSubtecDevInterface, UpdateTimestampWithZero) +{ + std::cout << "Entering UpdateTimestampWithZero test" << std::endl; + + WebvttSubtecDevInterface devInterface(640, 480); + std::cout << "Created WebvttSubtecDevInterface object with width: " << 640 << " and height: " << 480 << std::endl; + + unsigned long long positionMs = 0; + std::cout << "Invoking updateTimestamp with positionMs: " << positionMs << std::endl; + devInterface.updateTimestamp(positionMs); + std::cout << "updateTimestamp invoked; value passed: " << positionMs << " (expected internal timestamp to be updated to 0)" << std::endl; + + std::cout << "Exiting UpdateTimestampWithZero test" << std::endl; +} +/** + * @brief This test verifies that the updateTimestamp API correctly updates the internal timestamp when provided with a typical valid input. + * + * This test creates a WebvttSubtecDevInterface object with defined dimensions, then calls updateTimestamp with a positive timestamp value. The objective is to ensure that the API correctly processes the input and updates the internal state accordingly. + * + * **Test Group ID:** Basic: 01@n + * **Test Case ID:** 022@n + * **Priority:** High@n + * + * **Pre-Conditions:** None@n + * **Dependencies:** None@n + * **User Interaction:** None@n + * + * **Test Procedure:**@n + * | Variation / Step | Description | Test Data | Expected Result | Notes | + * | :----: | --------- | ---------- |-------------- | ----- | + * | 01 | Instantiate WebvttSubtecDevInterface object | width=640, height=480 | Object is created successfully | Should be successful | + * | 02 | Call updateTimestamp method | positionMs = 5000 | Internal timestamp is updated to 5000 | Should Pass | + * | 03 | Log output for test execution | None | Console logs indicate the correct function flow and success | Should be successful | + */ +TEST(WebvttSubtecDevInterface, UpdateTimestampWithTypicalPositive) +{ + std::cout << "Entering UpdateTimestampWithTypicalPositive test" << std::endl; + + WebvttSubtecDevInterface devInterface(640, 480); + std::cout << "Created WebvttSubtecDevInterface object with width: " << 640 << " and height: " << 480 << std::endl; + + unsigned long long positionMs = 5000; + std::cout << "Invoking updateTimestamp with positionMs: " << positionMs << std::endl; + devInterface.updateTimestamp(positionMs); + std::cout << "updateTimestamp invoked; value passed: " << positionMs << " (expected internal timestamp to be updated to 5000)" << std::endl; + + std::cout << "Exiting UpdateTimestampWithTypicalPositive test" << std::endl; +} + +int main(int argc, char **argv) { + ::testing::InitGoogleTest(&argc, argv); + return RUN_ALL_TESTS(); +} \ No newline at end of file From 4cff22404fcf7505b44c4e8d64fa2dcd2d4a1d90 Mon Sep 17 00:00:00 2001 From: joyal-06 Date: Mon, 7 Jul 2025 23:16:52 +0530 Subject: [PATCH 3/9] gh #2: Generate_L1_tests --- drm/aes/test/test_l1_Aes.cpp | 1461 ++++++++++++++++++++++++++++++++++ 1 file changed, 1461 insertions(+) create mode 100755 drm/aes/test/test_l1_Aes.cpp diff --git a/drm/aes/test/test_l1_Aes.cpp b/drm/aes/test/test_l1_Aes.cpp new file mode 100755 index 0000000..0206e2e --- /dev/null +++ b/drm/aes/test/test_l1_Aes.cpp @@ -0,0 +1,1461 @@ + +/* + * If not stated otherwise in this file or this component's LICENSE file the + * following copyright and licenses apply: + * + * Copyright 2025 RDK Management + * + * 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. + */ + + /** +* @file test_l1_Aes.cpp +* @page Aes Level 1 Tests +* +* ## Module's Role +* This module includes Level 1 functional tests (success and failure scenarios). +* This is to ensure that the Aes methods meet the requirements. +* +* **Pre-Conditions:** None @n +* **Dependencies:** None @n +* +*/ + +#include +#include +#include +#include "Aes.h" + + +/** + * @brief This test validates that the AcquireKey function of AesDec is operating correctly when invoked with no parameters. + * + * The test constructs an AesDec object using its default constructor and then calls the AcquireKey method without any parameters. + * This verifies that the key acquisition process is initiated successfully. + * + * **Test Group ID:** Basic: 01@n + * **Test Case ID:** 001@n + * **Priority:** High@n + * + * **Pre-Conditions:** None@n + * **Dependencies:** None@n + * **User Interaction:** None@n + * + * **Test Procedure:** + * | Variation / Step | Description | Test Data | Expected Result | Notes | + * | :--------------: | ------------------------------------------------------------- | -------------------------------------------------------------- | -------------------------------------------------------------------- | ------------- | + * | 01 | Create an AesDec object using the default constructor | Constructor: no parameters | AesDec object is instantiated successfully | Should be successful | + * | 02 | Invoke AcquireKey() with no parameters | Call: AcquireKey() | AcquireKey() is invoked and key acquisition process initiates successfully | Should Pass | + */ +TEST(AesDec, AcquireKey_no_params) +{ + std::cout << "Entering AcquireKey_no_params test" << std::endl; + + std::cout << "Creating AesDec object using default constructor" << std::endl; + AesDec aesDec; + + std::cout << "Invoking AcquireKey() with no parameters" << std::endl; + aesDec.AcquireKey(); + + std::cout << "AcquireKey() invoked; key acquisition process initiated successfully" << std::endl; + + std::cout << "Exiting AcquireKey_no_params test" << std::endl; +} + +/** + * @brief Validate AcquireKey API with valid metadata and standard track type. + * + * This test verifies that the AcquireKey function of the AesDec class correctly processes valid metadata and a standard track type value. The test ensures that the API executes without errors and logs the process steps appropriately. + * + * **Test Group ID:** Basic: 01@n + * **Test Case ID:** 002@n + * **Priority:** High@n + * + * **Pre-Conditions:** None@n + * **Dependencies:** None@n + * **User Interaction:** None@n + * + * **Test Procedure:**@n + * | Variation / Step | Description | Test Data | Expected Result | Notes | + * | :----: | --------- | ---------- |-------------- | ----- | + * | 01 | Prepare dummy valid metadata. | dummy = "dummy_metadata" | Dummy metadata is correctly set in the character array | Should be successful | + * | 02 | Initialize trackType to standard track value. | trackType = 0 | trackType variable is set to 0 indicating standard track type | Should be successful | + * | 03 | Create an AesDec object using the default constructor. | No additional inputs | AesDec object is instantiated without errors | Should be successful | + * | 04 | Invoke AcquireKey API with metadata pointer and trackType. | input: metadata pointer = dummy, trackType = 0 | AcquireKey function is executed without errors and key is acquired | Should Pass | + * | 05 | Print success log after API call. | No inputs, standard output | "AcquireKey executed successfully with valid metadata and standard trackType value" is printed | Should be successful | + */ +TEST(AesDec, AcquireKey_ValidMetadata_StandardTrackType) +{ + std::cout << "Entering AcquireKey_ValidMetadata_StandardTrackType test" << std::endl; + + char dummy[32] = {0}; + strncpy(dummy, "dummy_metadata", 32); // Replace with valid metadata + + int trackType = 0; + std::cout << "Creating AesDec object using default constructor" << std::endl; + AesDec obj; + + std::cout << "Calling AcquireKey with metadata address: " << static_cast(dummy) + << " and trackType: " << trackType << std::endl; + obj.AcquireKey(static_cast(dummy), trackType); + + std::cout << "AcquireKey executed successfully with valid metadata and standard trackType value" << std::endl; + + std::cout << "Exiting AcquireKey_ValidMetadata_StandardTrackType test" << std::endl; +} + +/** + * @brief Test the AcquireKey function with a nullptr metadata and a valid trackType. + * + * This test verifies that the AcquireKey method of the AesDec class, when provided with a nullptr for metadata and a valid trackType value, executes without errors and performs all expected operations. The test ensures that the API can handle null pointer inputs appropriately while logging the execution flow. + * + * **Test Group ID:** Basic: 01@n + * **Test Case ID:** 003@n + * **Priority:** High@n + * + * **Pre-Conditions:** None@n + * **Dependencies:** None@n + * **User Interaction:** None@n + * + * **Test Procedure:**@n + * | Variation / Step | Description | Test Data | Expected Result | Notes | + * | :----: | --------- | ---------- |-------------- | ----- | + * | 01 | Initialize metadata pointer to nullptr and assign trackType to a valid value (1) | metadata = nullptr, trackType = 1 | Variables initialized successfully | Should be successful | + * | 02 | Instantiate AesDec object using the default constructor | No input parameters | Object instantiated successfully | Should be successful | + * | 03 | Invoke AcquireKey method with the initialized metadata and trackType | input: metadata = nullptr, trackType = 1 | AcquireKey executes without errors and performs the desired operations | Should Pass | + */ +TEST(AesDec, AcquireKey_NullptrMetadata_ValidTrackType) +{ + std::cout << "Entering AcquireKey_NullptrMetadata_ValidTrackType test" << std::endl; + + void* metadata = nullptr; + int trackType = 1; + std::cout << "Creating AesDec object using default constructor" << std::endl; + AesDec obj; + + std::cout << "Calling AcquireKey with metadata: " << metadata + << " and trackType: " << trackType << std::endl; + obj.AcquireKey(metadata, trackType); + + std::cout << "AcquireKey executed successfully with nullptr metadata and valid trackType value" << std::endl; + + std::cout << "Exiting AcquireKey_NullptrMetadata_ValidTrackType test" << std::endl; +} + +/** + * @brief Verifies that AcquireKey correctly handles a valid metadata pointer with a negative trackType. + * + * This test validates that the AcquireKey method of the AesDec class behaves as expected when provided with valid metadata but an invalid (negative) trackType. The objective is to verify whether the API appropriately identifies and handles an invalid trackType scenario. + * + * **Test Group ID:** Basic: 01 + * **Test Case ID:** 004 + * **Priority:** High + * + * **Pre-Conditions:** None + * **Dependencies:** None + * **User Interaction:** None + * + * **Test Procedure:** + * | Variation / Step | Description | Test Data | Expected Result | Notes | + * | :----: | --------- | ---------- |-------------- | ----- | + * | 01 | Invoke AcquireKey API using a valid metadata buffer and a negative trackType to test invalid input handling. | metadata = dummy_metadata, trackType = -1 | AcquireKey should indicate error handling for the negative trackType input. | Should Fail | + */ +TEST(AesDec, AcquireKey_ValidMetadata_NegativeTrackType) +{ + std::cout << "Entering AcquireKey_ValidMetadata_NegativeTrackType test" << std::endl; + + char dummy[32] = {0}; + strncpy(dummy, "dummy_metadata", 32); // Replace with valid metadata + + int trackType = -1; + std::cout << "Creating AesDec object using default constructor" << std::endl; + AesDec obj; + + std::cout << "Calling AcquireKey with metadata address: " << static_cast(dummy) + << " and trackType: " << trackType << std::endl; + obj.AcquireKey(static_cast(dummy), trackType); + + std::cout << "AcquireKey executed successfully with valid metadata and negative trackType value" << std::endl; + + std::cout << "Exiting AcquireKey_ValidMetadata_NegativeTrackType test" << std::endl; +} + +/** + * @brief Verify handling of AcquireKey when provided with nullptr metadata and negative trackType. + * + * This test case validates that the AcquireKey API correctly handles a scenario where the metadata pointer is nullptr and the trackType is set to a negative value. It ensures that the function behaves as expected when faced with invalid input parameters. + * + * **Test Group ID:** Basic: 01@n + * **Test Case ID:** 005@n + * **Priority:** High@n + * + * **Pre-Conditions:** None@n + * **Dependencies:** None@n + * **User Interaction:** None@n + * + * **Test Procedure:**@n + * | Variation / Step | Description | Test Data | Expected Result | Notes | + * | :----: | ---------------------------------------------------------------------- | ------------------------------------------- | -------------------------------------------------------------------------------------------------------- | ------------- | + * | 01 | Initialize test inputs with metadata as nullptr and trackType as -5 | metadata = nullptr, trackType = -5 | Inputs are prepared for a negative scenario for AcquireKey | Should Fail | + * | 02 | Create an instance of AesDec using the default constructor | No input parameters | AesDec object should be created successfully | Should be successful | + * | 03 | Invoke the AcquireKey API with the prepared invalid inputs | metadata = nullptr, trackType = -5 | The API should process the call and handle the invalid parameters appropriately (e.g., log error or fail)| Should Fail | + */ +TEST(AesDec, AcquireKey_NullptrMetadata_NegativeTrackType) +{ + std::cout << "Entering AcquireKey_NullptrMetadata_NegativeTrackType test" << std::endl; + + void* metadata = nullptr; + int trackType = -5; + std::cout << "Creating AesDec object using default constructor" << std::endl; + AesDec obj; + + std::cout << "Calling AcquireKey with metadata: " << metadata + << " and trackType: " << trackType << std::endl; + obj.AcquireKey(metadata, trackType); + + std::cout << "AcquireKey executed successfully with nullptr metadata and negative trackType value" << std::endl; + std::cout << "Exiting AcquireKey_NullptrMetadata_NegativeTrackType test" << std::endl; +} + +/** + * @brief Verify successful key acquisition with valid metadata and a large trackType value + * + * This test verifies that the AcquireKey API is able to process valid metadata and a large trackType value correctly. + * It ensures the API call does not result in errors when handling a maximum positive integer value for trackType, simulating a potential edge case. + * + * **Test Group ID:** Basic: 01@n + * **Test Case ID:** 006@n + * **Priority:** High@n + * + * **Pre-Conditions:** None@n + * **Dependencies:** None@n + * **User Interaction:** None@n + * + * **Test Procedure:** + * | Variation / Step | Description | Test Data | Expected Result | Notes | + * | :--------------: | ----------- | --------- | -------------- | ----- | + * | 01 | Initialize a dummy metadata buffer with "dummy_metadata" | dummy[32] = "dummy_metadata" | Dummy metadata buffer is properly initialized | Should be successful | + * | 02 | Set trackType to the maximum 32-bit signed integer value | trackType = 2147483647 | trackType is correctly set | Should be successful | + * | 03 | Create the AesDec object using the default constructor | None | AesDec object is constructed successfully | Should be successful | + * | 04 | Call AcquireKey method with dummy metadata pointer and large trackType value | input1 = dummy pointer, input2 = 2147483647 | API executes without errors, and key acquisition is successful | Should Pass | + */ +TEST(AesDec, AcquireKey_ValidMetadata_LargeTrackType) +{ + std::cout << "Entering AcquireKey_ValidMetadata_LargeTrackType test" << std::endl; + + char dummy[32] = {0}; + strncpy(dummy, "dummy_metadata", 32); // Replace with valid metadata + + int trackType = 2147483647; + std::cout << "Creating AesDec object using default constructor" << std::endl; + AesDec obj; + + std::cout << "Calling AcquireKey with metadata address: " << static_cast(dummy) + << " and trackType: " << trackType << std::endl; + obj.AcquireKey(static_cast(dummy), trackType); + + std::cout << "AcquireKey executed successfully with valid metadata and large trackType value" << std::endl; + std::cout << "Exiting AcquireKey_ValidMetadata_LargeTrackType test" << std::endl; +} + +/** + * @brief Validate proper execution of AcquireKey with valid metadata and trackType set to zero. + * + * This test verifies that the AcquireKey method in the AesDec class executes successfully when provided with a valid metadata pointer and a trackType value of 0. It ensures that the object is correctly instantiated and that the method call does not result in any runtime errors. + * + * **Test Group ID:** Basic: 01@n + * **Test Case ID:** 007@n + * **Priority:** High@n + * + * **Pre-Conditions:** None@n + * **Dependencies:** None@n + * **User Interaction:** None@n + * + * **Test Procedure:** + * | Variation / Step | Description | Test Data | Expected Result | Notes | + * | :----: | --------- | ---------- |-------------- | ----- | + * | 01 | Initialize valid metadata buffer and trackType variable | dummy = "dummy_metadata", trackType = 0 | Buffer initialized with valid metadata and trackType set to 0 | Should be successful | + * | 02 | Create AesDec object using the default constructor | No input parameters | AesDec object created successfully | Should be successful | + * | 03 | Call AcquireKey method with metadata pointer and trackType | metadata pointer = address of dummy, trackType = 0 | AcquireKey executes without error | Should Pass | + */ +TEST(AesDec, AcquireKey_ValidMetadata_ZeroTrackType) +{ + std::cout << "Entering AcquireKey_ValidMetadata_ZeroTrackType test" << std::endl; + + char dummy[32] = {0}; + strncpy(dummy, "dummy_metadata", 32); // Replace with valid metadata + + int trackType = 0; + std::cout << "Creating AesDec object using default constructor" << std::endl; + AesDec obj; + + std::cout << "Calling AcquireKey with metadata address: " << static_cast(dummy) + << " and trackType: " << trackType << std::endl; + obj.AcquireKey(static_cast(dummy), trackType); + + std::cout << "AcquireKey executed successfully with valid metadata and zero trackType value" << std::endl; + + std::cout << "Exiting AcquireKey_ValidMetadata_ZeroTrackType test" << std::endl; +} + +/** + * @brief Verify that the AesDec default constructor correctly initializes an object without input parameters. + * + * This test verifies that invoking the default constructor of the AesDec class creates an object successfully and that its member variables are default-initialized. The objective is to ensure that the constructor performs its intended functionality without any external inputs and that the object is in a valid state after construction. + * + * **Test Group ID:** Basic: 01@n + * **Test Case ID:** 008@n + * **Priority:** High@n + * + * **Pre-Conditions:** None@n + * **Dependencies:** None@n + * **User Interaction:** None@n + * + * **Test Procedure:** + * | Variation / Step | Description | Test Data | Expected Result | Notes | + * | :--------------: | -------------------------------------------------------------------- | ------------------------------------------- | ------------------------------------------------------------------------------- | ---------- | + * | 01 | Invoke the AesDec default constructor with no input parameters. | No inputs, output1 = successfully constructed AesDec object | AesDec object is successfully constructed with default-initialized member variables. | Should Pass | + */ +TEST(AesDec, AesDecConstructor_start) +{ + std::cout<<"Entering AesDecConstructor_start test"<(buffer), 16, 3000); + + std::cout << "Decrypt returned: " << retVal << std::endl; + + EXPECT_EQ(retVal, eDRM_SUCCESS); + + std::cout << "Exiting ValidDecryptionTest test" << std::endl; +} + +/** + * @brief Verifies that the AesDec::Decrypt method returns an error when a null pointer is passed as the encrypted data pointer. + * + * This test checks the behavior of the AesDec::Decrypt API by providing a null pointer for the encrypted data. + * The objective is to ensure that the API correctly handles invalid input by returning the error code as expected. + * + * **Test Group ID:** Basic: 01@n + * **Test Case ID:** 011@n + * **Priority:** High@n + * + * **Pre-Conditions:** None@n + * **Dependencies:** None@n + * **User Interaction:** None@n + * + * **Test Procedure:**@n + * | Variation / Step | Description | Test Data | Expected Result | Notes | + * | :----: | --------- | ---------- |-------------- | ----- | + * | 01 | Instantiate AesDec object and call Decrypt with bucketType = 1, encryptedDataPtr = NULL, encryptedDataLen = 10, and timeInMs = 3000 | bucketType = 1, encryptedDataPtr = NULL, encryptedDataLen = 10, timeInMs = 3000 | Return value eDRM_ERROR and assertion verifies the error condition | Should Fail | + */ +TEST(AesDec, NullDataPtrTest) +{ + std::cout << "Entering NullDataPtrTest test" << std::endl; + + AesDec aesDecObj; + + std::cout << "Invoking AesDec::Decrypt with bucketType = 1, encryptedDataPtr = NULL" + << ", encryptedDataLen = 10, timeInMs = 3000" << std::endl; + + DrmReturn retVal = aesDecObj.Decrypt(1, NULL, 10, 3000); + + std::cout << "Decrypt returned: " << retVal << std::endl; + + EXPECT_EQ(retVal, eDRM_ERROR); + + std::cout << "Exiting NullDataPtrTest test" << std::endl; +} + +/** + * @brief Test AesDec::Decrypt with zero-length data to ensure proper error handling. + * + * This test verifies that calling AesDec::Decrypt with an encrypted data length of zero returns the error code eDRM_ERROR. This ensures that the function correctly handles cases where the input data length is invalid. + * + * **Test Group ID:** Basic: 01@n + * **Test Case ID:** 012@n + * **Priority:** High@n + * + * **Pre-Conditions:** None@n + * **Dependencies:** None@n + * **User Interaction:** None@n + * + * **Test Procedure:** + * | Variation / Step | Description | Test Data |Expected Result |Notes | + * | :----: | --------- | ---------- |-------------- | ----- | + * | 01 | Invoke AesDec::Decrypt API with zero-length encrypted data and valid parameters | bucketType = 1, encryptedDataPtr = ValidBufferData, encryptedDataLen = 0, timeInMs = 3000, return value = eDRM_ERROR | Function returns eDRM_ERROR and EXPECT_EQ assertion passes | Should Fail | + */ +TEST(AesDec, ZeroDataLenTest) +{ + std::cout << "Entering ZeroDataLenTest test" << std::endl; + + AesDec aesDecObj; + + char buffer[16]; + strncpy(buffer, "ValidBufferData", sizeof(buffer)); + + std::cout << "Invoking AesDec::Decrypt with bucketType = 1, encryptedDataPtr = " << static_cast(buffer) + << ", encryptedDataLen = 0, timeInMs = 3000" << std::endl; + + DrmReturn retVal = aesDecObj.Decrypt(1, static_cast(buffer), 0, 3000); + + std::cout << "Decrypt returned: " << retVal << std::endl; + + EXPECT_EQ(retVal, eDRM_ERROR); + + std::cout << "Exiting ZeroDataLenTest test" << std::endl; +} + +/** + * @brief Test negative scenario for AesDec::Decrypt API when an invalid bucket type is provided. + * + * This test evaluates the behavior of the AesDec::Decrypt method when a negative bucket type (-1) is used. + * It ensures that the API returns the expected error value (eDRM_ERROR) and that the system handles invalid input correctly. + * + * **Test Group ID:** Basic: 01@n + * **Test Case ID:** 013@n + * **Priority:** High@n + * + * **Pre-Conditions:** None@n + * **Dependencies:** None@n + * **User Interaction:** None@n + * + * **Test Procedure:** + * | Variation / Step | Description | Test Data | Expected Result | Notes | + * | :----: | --------- | ---------- | -------------- | ----- | + * | 01 | Instantiate AesDec object and initialize the encrypted data buffer. | No inputs; initializing AesDec instance and buffer with "0123456789abcdef" | Object and buffer initialized successfully. | Should be successful | + * | 02 | Invoke AesDec::Decrypt with invalid bucketType (-1) using the prepared buffer. | bucketType = -1, encryptedDataPtr = buffer pointer, encryptedDataLen = 16, timeInMs = 3000 | API returns eDRM_ERROR. | Should Fail | + * | 03 | Validate the API's return value using EXPECT_EQ to ensure it equals eDRM_ERROR. | retVal = eDRM_ERROR | Assertion passes confirming that eDRM_ERROR was returned. | Should be successful | + */ +TEST(AesDec, NegativeBucketTypeTest) +{ + std::cout << "Entering NegativeBucketTypeTest test" << std::endl; + + AesDec aesDecObj; + + char buffer[16]; + strncpy(buffer, "0123456789abcdef", sizeof(buffer)); + + std::cout << "Invoking AesDec::Decrypt with bucketType = -1, encryptedDataPtr = " << static_cast(buffer) + << ", encryptedDataLen = 16, timeInMs = 3000" << std::endl; + + DrmReturn retVal = aesDecObj.Decrypt(-1, static_cast(buffer), 16, 3000); + + std::cout << "Decrypt returned: " << retVal << std::endl; + + EXPECT_EQ(retVal, eDRM_ERROR); + + std::cout << "Exiting NegativeBucketTypeTest test" << std::endl; +} + +/** + * @brief Validate decryption of large data buffer using AesDec::Decrypt API + * + * This test verifies that the AesDec::Decrypt API correctly processes a large data buffer by decrypting a large input, ensuring that the function handles big input sizes efficiently and returns the expected success status. + * + * **Test Group ID:** Basic: 01@n + * **Test Case ID:** 014@n + * **Priority:** High@n + * + * **Pre-Conditions:** None@n + * **Dependencies:** None@n + * **User Interaction:** None@n + * + * **Test Procedure:** + * | Variation / Step | Description | Test Data | Expected Result | Notes | + * | :----: | --------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------ | -------------------------------------------------- | ------------- | + * | 01 | Create an instance of AesDec | None | Object is constructed successfully | Should be successful | + * | 02 | Initialize a largeBuffer with predefined data | largeBuffer = "LargeDataBufferStart" | Buffer contains the initial data | Should be successful | + * | 03 | Invoke AesDec::Decrypt with bucketType=1, encryptedDataPtr=largeBuffer, encryptedDataLen=1048576, timeInMs=3000 | bucketType = 1, encryptedDataPtr = largeBuffer, encryptedDataLen = 1048576, timeInMs = 3000 | Return value equals eDRM_SUCCESS and assertion passes | Should Pass | + */ +TEST(AesDec, LargeDataLenTest) +{ + std::cout << "Entering LargeDataLenTest test" << std::endl; + + AesDec aesDecObj; + + char largeBuffer[1048576]; + strncpy(largeBuffer, "LargeDataBufferStart", sizeof(largeBuffer)); + + std::cout << "Invoking AesDec::Decrypt with bucketType = 1, encryptedDataPtr = " << static_cast(largeBuffer) + << ", encryptedDataLen = 1048576, timeInMs = 3000" << std::endl; + + DrmReturn retVal = aesDecObj.Decrypt(1, static_cast(largeBuffer), 1048576, 3000); + + std::cout << "Decrypt returned: " << retVal << std::endl; + + EXPECT_EQ(retVal, eDRM_SUCCESS); + + std::cout << "Exiting LargeDataLenTest test" << std::endl; +} + +/** + * @brief Validates that the AesDec::Decrypt API returns an error when provided a negative timeout value. + * + * This test verifies that invoking the Decrypt method with a negative timeInMs parameter (i.e., -100) + * causes the API to return the error code eDRM_ERROR. It ensures that the API correctly handles invalid + * timeout scenarios to prevent unexpected behavior. + * + * **Test Group ID:** Basic: 01@n + * **Test Case ID:** 015@n + * **Priority:** High@n + * + * **Pre-Conditions:** None@n + * **Dependencies:** None@n + * **User Interaction:** None@n + * + * **Test Procedure:**@n + * | Variation / Step | Description | Test Data | Expected Result | Notes | + * | :----: | --------- | ---------- |-------------- | ----- | + * | 01 | Initialize AesDec object and prepare input buffer with valid data. | encryptedDataPtr = buffer containing "0123456789abcdef" | Object and buffer initialized. | Should be successful | + * | 02 | Invoke AesDec::Decrypt with bucketType = 1, encryptedDataLen = 16, and timeInMs = -100. | bucketType = 1, encryptedDataPtr = buffer, encryptedDataLen = 16, timeInMs = -100 | Decrypt returns eDRM_ERROR. | Should Fail | + * | 03 | Verify that the returned value matches eDRM_ERROR. | retVal = eDRM_ERROR | ASSERT_EQ passes confirming eDRM_ERROR. | Should be successful | + */ +TEST(AesDec, NegativeTimeoutTest) +{ + std::cout << "Entering NegativeTimeoutTest test" << std::endl; + + AesDec aesDecObj; + + char buffer[16]; + strncpy(buffer, "0123456789abcdef", sizeof(buffer)); + + std::cout << "Invoking AesDec::Decrypt with bucketType = 1, encryptedDataPtr = " << static_cast(buffer) + << ", encryptedDataLen = 16, timeInMs = -100" << std::endl; + + DrmReturn retVal = aesDecObj.Decrypt(1, static_cast(buffer), 16, -100); + + std::cout << "Decrypt returned: " << retVal << std::endl; + + EXPECT_EQ(retVal, eDRM_ERROR); + + std::cout << "Exiting NegativeTimeoutTest test" << std::endl; +} +/** + * @brief Verify that AesDec::Decrypt handles large timeout values correctly. + * + * This test case examines the decryption process of the AesDec class using a significantly large timeout parameter. + * It verifies that the decryption operation completes successfully and returns eDRM_SUCCESS, ensuring that the API + * correctly processes requests with unusually large timeout durations. + * + * **Test Group ID:** Basic: 01 + * **Test Case ID:** 016 + * **Priority:** High + * + * **Pre-Conditions:** None + * **Dependencies:** None + * **User Interaction:** None + * + * **Test Procedure:** + * | Variation / Step | Description | Test Data | Expected Result | Notes | + * | :----: | --------- | ---------- |-------------- | ----- | + * | 01 | Instantiate AesDec object and initialize buffer with test data "0123456789abcdef". | AesDec obj created, buffer = "0123456789abcdef" | Object and buffer are correctly initialized | Should be successful | + * | 02 | Invoke AesDec::Decrypt with a large timeout value. | bucketType = 1, encryptedDataPtr = address of buffer, encryptedDataLen = 16, timeInMs = 1000000 | Decrypt method returns eDRM_SUCCESS | Should Pass | + * | 03 | Validate the decryption result using assertion. | output: retVal compared to eDRM_SUCCESS | EXPECT_EQ assertion passes confirming successful decryption | Should be successful | + */ +TEST(AesDec, LargeTimeoutTest) +{ + std::cout << "Entering LargeTimeoutTest test" << std::endl; + + AesDec aesDecObj; + + char buffer[16]; + strncpy(buffer, "0123456789abcdef", sizeof(buffer)); + + std::cout << "Invoking AesDec::Decrypt with bucketType = 1, encryptedDataPtr = " << static_cast(buffer) + << ", encryptedDataLen = 16, timeInMs = 1000000" << std::endl; + + DrmReturn retVal = aesDecObj.Decrypt(1, static_cast(buffer), 16, 1000000); + + std::cout << "Decrypt returned: " << retVal << std::endl; + + EXPECT_EQ(retVal, eDRM_SUCCESS); + + std::cout << "Exiting LargeTimeoutTest test" << std::endl; +} + +/** + * @brief Validate successful instance retrieval via AesDec::GetInstance + * + * This test verifies that the AesDec::GetInstance method returns a non-null singleton instance. + * It ensures that the instance is created successfully and the returned pointer is valid. + * + * **Test Group ID:** Basic: 01@n + * **Test Case ID:** 017@n + * **Priority:** High@n + * + * **Pre-Conditions:** None@n + * **Dependencies:** None@n + * **User Interaction:** None@n + * + * **Test Procedure:**@n + * | Variation / Step | Description | Test Data | Expected Result | Notes | + * | :----: | --------- | ---------- |-------------- | ----- | + * | 01 | Invoke AesDec::GetInstance() to obtain a singleton instance and validate that the returned pointer is non-null | input = none, output = instance pointer returned from AesDec::GetInstance() | The instance pointer returned should be non-null, passing the EXPECT_NE(instance, nullptr) check | Should Pass | + */ +TEST(AesDec, GetInstance_start) +{ + + std::cout << "Entering GetInstance_start test" << std::endl; + + std::cout << "Invoking AesDec::GetInstance()" << std::endl; + + auto instance = AesDec::GetInstance(); + + std::cout << "Returned instance pointer: " << instance.get() << std::endl; + + EXPECT_NE(instance, nullptr); + + std::cout << "Instance creation validated successfully with a non-null pointer" << std::endl; + + std::cout << "Exiting GetInstance_start test" << std::endl; +} + +/** + * @brief Validate that GetState method returns a valid DRM state + * + * This test creates an AesDec object using the default constructor, invokes the GetState method, and verifies that the returned value matches one of the expected DRM states. This ensures that the GetState function behaves as expected when no prior modifications are made to the object state. + * + * **Test Group ID:** Basic: 01@n + * **Test Case ID:** 018@n + * **Priority:** High@n + * + * **Pre-Conditions:** None@n + * **Dependencies:** None@n + * **User Interaction:** None@n + * + * **Test Procedure:** + * | Variation / Step | Description | Test Data | Expected Result | Notes | + * | :----: | ------------------------------------------------------------------ | ---------------------------------------------------------------------- | --------------------------------------------------------------------------------------------------------------- | ------------- | + * | 01 | Instantiate AesDec object using default constructor | Constructor: default | AesDec object is instantiated successfully | Should be successful | + * | 02 | Invoke GetState method on the AesDec object | Method: GetState(), No parameters | Returns a DRM state value that is one of: eDRM_INITIALIZED, eDRM_ACQUIRING_KEY, eDRM_KEY_ACQUIRED, eDRM_KEY_FAILED, eDRM_KEY_FLUSH | Should Pass | + * | 03 | Validate the returned state is among the expected DRM states | Assertion: validState = (state equals one of the expected constants) | EXPECT_TRUE assertion passes if validState is true | Should Pass | + */ +TEST(AesDec, GetState_start) +{ + std::cout << "Entering GetState_start test" << std::endl; + + AesDec aesDec; + std::cout << "Instantiated AesDec object using default constructor" << std::endl; + + std::cout << "Invoking GetState on AesDec object" << std::endl; + DRMState state = aesDec.GetState(); + std::cout << "GetState returned value: " << state << std::endl; + + bool validState = (state == eDRM_INITIALIZED) || (state == eDRM_ACQUIRING_KEY) || + (state == eDRM_KEY_ACQUIRED) || (state == eDRM_KEY_FAILED) || + (state == eDRM_KEY_FLUSH); + EXPECT_TRUE(validState); + std::cout << "Verified that the returned state is one of the expected DRM states" << std::endl; + + std::cout << "Exiting GetState_start test" << std::endl; +} + +/** + * @brief Test that NotifyDRMError correctly handles valid DRM error codes. + * + * This test iterates over a set of predefined valid DRM error codes and calls the NotifyDRMError method + * of the AesDec class for each error code. It verifies that the function does not throw any exceptions, + * ensuring that the implementation handles various valid DRM error conditions appropriately. + * + * **Test Group ID:** Basic: 01 + * **Test Case ID:** 019 + * **Priority:** High + * + * **Pre-Conditions:** None + * **Dependencies:** None + * **User Interaction:** None + * + * **Test Procedure:** + * | Variation / Step | Description | Test Data | Expected Result | Notes | + * | :--------------: | ---------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------- | ---------- | + * | 01 | Invoke NotifyDRMError with drmFailure value MW_DRM_INIT_FAILED | error = MW_DRM_INIT_FAILED | API call does not throw exception; EXPECT_NO_THROW check passes | Should Pass| + * | 02 | Invoke NotifyDRMError with drmFailure value MW_DRM_DATA_BIND_FAILED | error = MW_DRM_DATA_BIND_FAILED | API call does not throw exception; EXPECT_NO_THROW check passes | Should Pass| + * | 03 | Invoke NotifyDRMError with drmFailure value MW_DRM_SESSIONID_EMPTY | error = MW_DRM_SESSIONID_EMPTY | API call does not throw exception; EXPECT_NO_THROW check passes | Should Pass| + * | 04 | Invoke NotifyDRMError with drmFailure value MW_DRM_CHALLENGE_FAILED | error = MW_DRM_CHALLENGE_FAILED | API call does not throw exception; EXPECT_NO_THROW check passes | Should Pass| + * | 05 | Invoke NotifyDRMError with drmFailure value MW_INVALID_DRM_KEY | error = MW_INVALID_DRM_KEY | API call does not throw exception; EXPECT_NO_THROW check passes | Should Pass| + * | 06 | Invoke NotifyDRMError with drmFailure value MW_CORRUPT_DRM_DATA | error = MW_CORRUPT_DRM_DATA | API call does not throw exception; EXPECT_NO_THROW check passes | Should Pass| + * | 07 | Invoke NotifyDRMError with drmFailure value MW_CORRUPT_DRM_METADATA | error = MW_CORRUPT_DRM_METADATA | API call does not throw exception; EXPECT_NO_THROW check passes | Should Pass| + * | 08 | Invoke NotifyDRMError with drmFailure value MW_DRM_DECRYPT_FAILED | error = MW_DRM_DECRYPT_FAILED | API call does not throw exception; EXPECT_NO_THROW check passes | Should Pass| + * | 09 | Invoke NotifyDRMError with drmFailure value MW_DRM_UNSUPPORTED | error = MW_DRM_UNSUPPORTED | API call does not throw exception; EXPECT_NO_THROW check passes | Should Pass| + * | 10 | Invoke NotifyDRMError with drmFailure value MW_DRM_SELF_ABORT | error = MW_DRM_SELF_ABORT | API call does not throw exception; EXPECT_NO_THROW check passes | Should Pass| + * | 11 | Invoke NotifyDRMError with drmFailure value MW_DRM_KEY_UPDATE_FAILED | error = MW_DRM_KEY_UPDATE_FAILED | API call does not throw exception; EXPECT_NO_THROW check passes | Should Pass| + * | 12 | Invoke NotifyDRMError with drmFailure value MW_UNTRACKED_DRM_ERROR | error = MW_UNTRACKED_DRM_ERROR | API call does not throw exception; EXPECT_NO_THROW check passes | Should Pass| + * | 13 | Invoke NotifyDRMError with drmFailure value MW_FAILED_TO_GET_KEYID | error = MW_FAILED_TO_GET_KEYID | API call does not throw exception; EXPECT_NO_THROW check passes | Should Pass| + */ +TEST(AesDec, NotifyDRMError_validDrmErrors) +{ + std::cout << "Entering NotifyDRMError_validDrmErrors test" << std::endl; + + AesDec aesDec; + + DrmTuneFailure drmErrors[] = {MW_DRM_INIT_FAILED, MW_DRM_DATA_BIND_FAILED, MW_DRM_SESSIONID_EMPTY, MW_DRM_CHALLENGE_FAILED, MW_INVALID_DRM_KEY, MW_CORRUPT_DRM_DATA, MW_CORRUPT_DRM_METADATA, MW_DRM_DECRYPT_FAILED, MW_DRM_UNSUPPORTED, MW_DRM_SELF_ABORT, MW_DRM_KEY_UPDATE_FAILED, MW_UNTRACKED_DRM_ERROR, MW_FAILED_TO_GET_KEYID}; + + for (DrmTuneFailure error : drmErrors) + { + std::cout << "Invoking NotifyDRMError with drmFailure value: " << error << std::endl; + + EXPECT_NO_THROW(aesDec.NotifyDRMError(error)); + + std::cout << "Completed NotifyDRMError call for drmFailure value: " << error << std::endl; + } + + std::cout << "Exiting NotifyDRMError_validDrmErrors test" << std::endl; +} + +/** + * @brief Test that a valid AesDec instance is created and its Release method works as expected. + * + * This test verifies that a valid AesDec instance can be safely constructed and that calling its Release() method does not throw any exceptions. The test confirms that the object is properly initialized and resources are released successfully upon invoking Release(). + * + * **Test Group ID:** Basic: 01@n + * **Test Case ID:** 020@n + * **Priority:** High@n + * + * **Pre-Conditions:** None@n + * **Dependencies:** None@n + * **User Interaction:** None@n + * + * **Test Procedure:**@n + * | Variation / Step | Description | Test Data | Expected Result | Notes | + * | :----: | --------- | ---------- |-------------- | ----- | + * | 01 | Construct AesDec object by calling its default constructor | No input arguments, output: instance created | Object should be constructed successfully | Should be successful | + * | 02 | Invoke Release() method on the constructed object | input: valid AesDec instance, method call: Release() | Release() should execute without throwing any exception | Should Pass | + */ +TEST(AesDec, ValidInstanceRelease) +{ + std::cout << "Entering ValidInstanceRelease test" << std::endl; + + AesDec aesDec; + std::cout << "Constructed AesDec object successfully" << std::endl; + + std::cout << "Invoking Release() method" << std::endl; + EXPECT_NO_THROW(aesDec.Release()); + std::cout << "Release() method invoked successfully, resources released" << std::endl; + + std::cout << "Exiting ValidInstanceRelease test" << std::endl; +} + +/** + * @brief Verify that the RestoreKeyState method correctly restores the DRM key state. + * + * This test instantiates an AesDec object using its default constructor and invokes the RestoreKeyState() method to verify that the DRM key state is correctly restored. The test checks for successful method invocation by monitoring the console output. + * + * **Test Group ID:** Basic: 01@n + * **Test Case ID:** 021@n + * **Priority:** High@n + * + * **Pre-Conditions:** None@n + * **Dependencies:** None@n + * **User Interaction:** None@n + * + * **Test Procedure:** + * | Variation / Step | Description | Test Data | Expected Result | Notes | + * | :--------------: | ----------------------------------------------------------------- | --------------------------------------------- | ------------------------------------------------------------------------------------------------------ | ---------------- | + * | 01 | Create an AesDec instance using the default constructor | object = AesDec instance | AesDec instance created successfully | Should be successful | + * | 02 | Invoke the RestoreKeyState() method on the AesDec instance | API call: aesDec.RestoreKeyState() | RestoreKeyState() method invoked successfully and DRM key state restored as expected | Should Pass | + */ +TEST(AesDec, RestoreKeyState_correctly_restores_DRM_key_state) +{ + std::cout<< "Entering RestoreKeyState_correctly_restores_DRM_key_state test" << std::endl; + + AesDec aesDec; + std::cout<< "AesDec instance created using default constructor" << std::endl; + + std::cout<< "Invoking RestoreKeyState() method" << std::endl; + aesDec.RestoreKeyState(); + std::cout<< "RestoreKeyState() method invoked successfully" << std::endl; + + std::cout<< "Exiting RestoreKeyState_correctly_restores_DRM_key_state test" << std::endl; +} + +/** + * @brief Verify that providing valid DRM information and a positive acquire key wait time results in successful decryption info setup. + * + * This test ensures that the AesDec::SetDecryptInfo API correctly processes a properly initialized DrmInfo structure along with a valid acquireKeyWaitTime and returns eDRM_SUCCESS, indicating successful decryption information configuration.@n + * + * **Test Group ID:** Basic: 01@n + * **Test Case ID:** 022@n + * **Priority:** High@n + * + * **Pre-Conditions:** None@n + * **Dependencies:** None@n + * **User Interaction:** None@n + * + * **Test Procedure:**@n + * | Variation / Step | Description | Test Data | Expected Result | Notes | + * | :----: | --------- | ---------- |-------------- | ----- | + * | 01 | Initialize drmInfo and set its IV with valid data. | drmInfo.iv = "1234567890123456" | drmInfo.iv is correctly set. | Should be successful | + * | 02 | Set DRM information URLs and parameters. | method = eMETHOD_AES_128, mediaFormat = eMEDIAFORMAT_HLS, useFirst16BytesAsIV = false, bPropagateUriParams = true, drmInfo.bUseMediaSequenceIV = true, drmInfo.bDecryptClearSamplesRequired = true, masterManifestURL = "http://master.manifest.url", manifestURL = "http://manifest.url", keyURI = "http://key.uri", keyFormat = "formatA", systemUUID = "uuid-1234", initData = "initDataSample" | DRM info fields are properly initialized. | Should be successful | + * | 03 | Set the acquireKeyWaitTime variable. | acquireKeyWaitTime = 500 | acquireKeyWaitTime is set to 500. | Should be successful | + * | 04 | Invoke AesDec::SetDecryptInfo API with the configured parameters. | input: drmInfo pointer, acquireKeyWaitTime = 500; output: ret | API returns eDRM_SUCCESS. | Should Pass | + * | 05 | Validate the API return value using an assertion. | ASSERT_EQ(ret, eDRM_SUCCESS) | Assertion passes if ret equals eDRM_SUCCESS. | Should Pass | + */ +TEST(AesDec, ValidDrmInfo_PositiveKeyWaitTime_Success) +{ + std::cout << "Entering ValidDrmInfo_PositiveKeyWaitTime_Success test" << std::endl; + + DrmInfo drmInfo; + + char validIV[] = "1234567890123456"; + std::cout << "Setting drmInfo.iv to: " << validIV << std::endl; + strncpy((char*)drmInfo.iv, validIV, sizeof(drmInfo.iv)); + + drmInfo.method = eMETHOD_AES_128; // if such an enum exists and is valid + drmInfo.mediaFormat = eMEDIAFORMAT_HLS; + drmInfo.useFirst16BytesAsIV = false; + drmInfo.bPropagateUriParams = true; + drmInfo.bUseMediaSequenceIV = true; + drmInfo.bDecryptClearSamplesRequired = true; + drmInfo.masterManifestURL = "http://master.manifest.url"; + drmInfo.manifestURL = "http://manifest.url"; + drmInfo.keyURI = "http://key.uri"; + drmInfo.keyFormat = "formatA"; + drmInfo.systemUUID = "uuid-1234"; + drmInfo.initData = "initDataSample"; + + int acquireKeyWaitTime = 500; + std::cout << "Invoking AesDec::SetDecryptInfo with acquireKeyWaitTime: " << acquireKeyWaitTime << std::endl; + + AesDec aesdec; + DrmReturn ret = aesdec.SetDecryptInfo(&drmInfo, acquireKeyWaitTime); + + std::cout << "Return value from SetDecryptInfo: " << ret << std::endl; + + ASSERT_EQ(ret, eDRM_SUCCESS); + + std::cout << "Exiting ValidDrmInfo_PositiveKeyWaitTime_Success test" << std::endl; +} +/** + * @brief Validate that AesDec::SetDecryptInfo returns the correct error code when passed a null DRM info. + * + * This test verifies that the SetDecryptInfo function of the AesDec class returns eDRM_ERROR when a nullptr is provided as the drmInfo parameter. This ensures that the API correctly handles invalid input for decryption parameters. + * + * **Test Group ID:** Basic: 01@n + * **Test Case ID:** 023@n + * **Priority:** High@n + * + * **Pre-Conditions:** None@n + * **Dependencies:** None@n + * **User Interaction:** None@n + * + * **Test Procedure:** + * | Variation / Step | Description | Test Data | Expected Result | Notes | + * | :--------------: | ----------------------------------------------------------------------------------------------------------- | ------------------------------------------------------ | -------------------------------------------------- | ---------- | + * | 01 | Invoke AesDec::SetDecryptInfo with drmInfo as nullptr and acquireKeyWaitTime as 500 | drmInfo = nullptr, acquireKeyWaitTime = 500, ret = eDRM_ERROR | Function returns eDRM_ERROR; ASSERT_EQ(ret, eDRM_ERROR) | Should Pass | + */ +TEST(AesDec, NullDrmInfo_ReturnsDrmError) +{ + std::cout << "Entering NullDrmInfo_ReturnsDrmError test" << std::endl; + + int acquireKeyWaitTime = 500; + std::cout << "Invoking AesDec::SetDecryptInfo with nullptr drmInfo and acquireKeyWaitTime: " << acquireKeyWaitTime << std::endl; + + AesDec aesdec; + DrmReturn ret = aesdec.SetDecryptInfo(nullptr, acquireKeyWaitTime); + + std::cout << "Return value from SetDecryptInfo: " << ret << std::endl; + + ASSERT_EQ(ret, eDRM_ERROR); + + std::cout << "Exiting NullDrmInfo_ReturnsDrmError test" << std::endl; +} +/** + * @brief Test to verify that AesDec::SetDecryptInfo returns a timeout when acquireKeyWaitTime is zero + * + * This test initializes a DrmInfo structure with valid DRM information and invokes AesDec::SetDecryptInfo with acquireKeyWaitTime set to 0. + * The objective is to ensure that the API correctly returns a timeout error (eDRM_KEY_ACQUISITION_TIMEOUT) when the wait time is insufficient. + * + * **Test Group ID:** Basic: 01@n + * **Test Case ID:** 024@n + * **Priority:** High@n + * + * **Pre-Conditions:** None@n + * **Dependencies:** None@n + * **User Interaction:** None@n + * + * **Test Procedure:**@n + * | Variation / Step | Description | Test Data | Expected Result | Notes | + * | :----: | --------- | ---------- |-------------- | ----- | + * | 01 | Initialize DrmInfo with valid DRM information and IV | method = eMETHOD_AES_128, mediaFormat = eMEDIAFORMAT_HLS, useFirst16BytesAsIV = false, bPropagateUriParams = true, drmInfo.bUseMediaSequenceIV = true, drmInfo.bDecryptClearSamplesRequired = true, drmInfo.iv = "abcdefghijklmnop", drmInfo.masterManifestURL = "http://master.manifest.url", drmInfo.manifestURL = "http://manifest.url", drmInfo.keyURI = "http://key.uri", drmInfo.keyFormat = "formatB", drmInfo.systemUUID = "uuid-5678", drmInfo.initData = "initDataExample" | DrmInfo fields should be assigned correctly | Should be successful | + * | 02 | Invoke AesDec::SetDecryptInfo with acquireKeyWaitTime set to 0 and validate timeout response | Input arguments: drmInfo pointer, acquireKeyWaitTime = 0; Expected output: ret = eDRM_KEY_ACQUISITION_TIMEOUT | The API returns eDRM_KEY_ACQUISITION_TIMEOUT and the assertion passes | Should Pass | + */ +TEST(AesDec, ValidDrmInfo_ZeroAcquireKeyWaitTime_ReturnsTimeout) +{ + std::cout << "Entering ValidDrmInfo_ZeroAcquireKeyWaitTime_ReturnsTimeout test" << std::endl; + + DrmInfo drmInfo; + + char validIV[] = "abcdefghijklmnop"; + std::cout << "Setting drmInfo.iv to: " << validIV << std::endl; + strncpy((char*)drmInfo.iv, validIV, sizeof(drmInfo.iv)); + + drmInfo.method = eMETHOD_AES_128; // if such an enum exists and is valid + drmInfo.mediaFormat = eMEDIAFORMAT_HLS; + drmInfo.useFirst16BytesAsIV = false; + drmInfo.bPropagateUriParams = true; + drmInfo.bUseMediaSequenceIV = true; + drmInfo.bDecryptClearSamplesRequired = true; + drmInfo.masterManifestURL = "http://master.manifest.url"; + drmInfo.manifestURL = "http://manifest.url"; + drmInfo.keyURI = "http://key.uri"; + drmInfo.keyFormat = "formatB"; + drmInfo.systemUUID = "uuid-5678"; + drmInfo.initData = "initDataExample"; + + int acquireKeyWaitTime = 0; + std::cout << "Invoking AesDec::SetDecryptInfo with acquireKeyWaitTime: " << acquireKeyWaitTime << std::endl; + + AesDec aesdec; + DrmReturn ret = aesdec.SetDecryptInfo(&drmInfo, acquireKeyWaitTime); + + std::cout << "Return value from SetDecryptInfo: " << ret << std::endl; + + ASSERT_EQ(ret, eDRM_KEY_ACQUISITION_TIMEOUT); + + std::cout << "Exiting ValidDrmInfo_ZeroAcquireKeyWaitTime_ReturnsTimeout test" << std::endl; +} +/** + * @brief Verify that SetIV API succeeds with valid initialization vector input + * + * This test evaluates the SetIV method of the AesDec class using a valid IV string. It verifies that the method returns eDRM_SUCCESS when provided with a properly formatted IV, ensuring that the IV setup is correctly performed. + * + * **Test Group ID:** Basic: 01@n + * **Test Case ID:** 025@n + * **Priority:** High@n + * + * **Pre-Conditions:** None@n + * **Dependencies:** None@n + * **User Interaction:** None@n + * + * **Test Procedure:** + * | Variation / Step | Description | Test Data | Expected Result | Notes | + * | :-------------: | --------------------------------------------------------------------------- | -------------------------------------------------------- | ---------------------------------------------------------------------- | ------------- | + * | 01 | Instantiate the AesDec object | None | AesDec object is created | Should be successful | + * | 02 | Initialize ivBuffer with valid IV "1234567890ABCDEF" | ivBuffer = 1234567890ABCDEF | ivBuffer is properly set with the IV string | Should be successful | + * | 03 | Print a message prior to invoking SetIV with ivBuffer | ivBuffer = 1234567890ABCDEF | Message printed indicating the IV value to be used in SetIV | Should be successful | + * | 04 | Call the SetIV API with ivBuffer | input1 = ivBuffer (1234567890ABCDEF) | API returns DrmReturn value, expected to be eDRM_SUCCESS | Should Pass | + * | 05 | Print the returned value from the SetIV call | result = API return value | Message printed displaying the result value | Should be successful | + * | 06 | Validate that the returned value equals eDRM_SUCCESS using EXPECT_EQ | output1 = result, expected = eDRM_SUCCESS | EXPECT_EQ passes if the returned result equals eDRM_SUCCESS | Should Pass | + */ +TEST(AesDec, ValidIVInput) +{ + std::cout<< "Entering ValidIVInput test" << std::endl; + + AesDec aesDec; + + char ivBuffer[16]; + strncpy(ivBuffer, "1234567890ABCDEF", sizeof(ivBuffer)); // Replace with valid value + + std::cout<< "Invoking SetIV with iv: " << ivBuffer << std::endl; + + DrmReturn result = aesDec.SetIV(reinterpret_cast(ivBuffer)); + + std::cout<< "Returned value from SetIV: " << result << std::endl; + + EXPECT_EQ(result, eDRM_SUCCESS); + + std::cout<< "Exiting ValidIVInput test" << std::endl; +} + +/** + * @brief Verifies that AesDec::SetIV returns eDRM_ERROR when a NULL IV is provided. + * + * This test checks that the AES decryption module properly handles a null initialization vector by returning the expected error code. The purpose is to ensure that the API gracefully handles invalid null input without compromising functionality. + * + * **Test Group ID:** Basic: 01 + * **Test Case ID:** 026 + * **Priority:** High + * + * **Pre-Conditions:** None + * **Dependencies:** None + * **User Interaction:** None + * + * **Test Procedure:** + * | Variation / Step | Description | Test Data | Expected Result | Notes | + * | :--------------: | ---------------------------------------------------------- | ---------------------------- | ---------------------------------------------------------- | --------------- | + * | 01 | Instantiate the AesDec object to set up the test environment | No input parameters | AesDec object is successfully created | Should be successful | + * | 02 | Invoke SetIV method with a NULL IV input | input: iv = NULL | Function returns eDRM_ERROR and assertion (EXPECT_EQ) passes | Should Pass | + */ +TEST(AesDec, NullIVInput) +{ + std::cout<< "Entering NullIVInput test" << std::endl; + + AesDec aesDec; + + std::cout<< "Invoking SetIV with iv: NULL" << std::endl; + + DrmReturn result = aesDec.SetIV(NULL); + + std::cout<< "Returned value from SetIV: " << result << std::endl; + + EXPECT_EQ(result, eDRM_ERROR); + + std::cout<< "Exiting NullIVInput test" << std::endl; +} + +/** + * @brief Verifies that SetMetaData returns success when provided with a valid non-null metadata pointer and a typical track type. + * + * This test verifies that the API properly assigns non-null metadata to an AesDec instance when a typical track type is used. It ensures the function returns a success status, confirming that the valid input parameters yield the expected behavior. + * + * **Test Group ID:** Basic: 01@n + * **Test Case ID:** 027@n + * **Priority:** High@n + * + * **Pre-Conditions:** None@n + * **Dependencies:** None@n + * **User Interaction:** None@n + * + * **Test Procedure:**@n + * | Variation / Step | Description | Test Data | Expected Result | Notes | + * | :--------------: | ----------------------------------------------------------------------------------------- | ----------------------------------------------------------------- | --------------------------------------------------------- | ------------- | + * | 01 | Initialize AesDec instance and set up valid input parameters. | validData = 100, metadata = address of validData, trackType = 0 | AesDec instance is created and input parameters are set. | Should be successful | + * | 02 | Call SetMetaData API with the non-null metadata pointer and typical track type value. | metadata = address of validData, trackType = 0, expected return = eDRM_SUCCESS | SetMetaData returns eDRM_SUCCESS | Should Pass | + * | 03 | Verify that SetMetaData API returned the expected success value using an assertion. | result = eDRM_SUCCESS | EXPECT_EQ(result, eDRM_SUCCESS) assertion passes. | Should Pass | + */ +TEST(AesDec, ValidNonNullMetadataWithTypicalTrack) +{ + std::cout << "Entering ValidNonNullMetadataWithTypicalTrack test" << std::endl; + + AesDec aesDec; + int validData = 100; // Replace with valid value + void* metadata = static_cast(&validData); + + int trackType = 0; + std::cout << "Invoking SetMetaData with metadata address: " << metadata << " and trackType: " << trackType << std::endl; + + DrmReturn result = aesDec.SetMetaData(metadata, trackType); + std::cout << "SetMetaData returned: " << result << std::endl; + + EXPECT_EQ(result, eDRM_SUCCESS); + + std::cout << "Exiting ValidNonNullMetadataWithTypicalTrack test" << std::endl; +} +/** + * @brief Test SetMetaData API for handling null metadata with a valid track type. + * + * This test verifies that when a null metadata pointer is passed along with a valid track type, + * the SetMetaData API returns the expected error code (eDRM_ERROR). This ensures proper error handling + * for invalid metadata inputs in the DRM module. + * + * **Test Group ID:** Basic: 01 + * **Test Case ID:** 028 + * **Priority:** High + * + * **Pre-Conditions:** None + * **Dependencies:** None + * **User Interaction:** None + * + * **Test Procedure:** + * | Variation / Step | Description | Test Data | Expected Result | Notes | + * | :--------------: | --------------------------------------------------------------------------------------------------- | ---------------------------------------------------------- | ----------------------------------------------------------------------------------- | ----------- | + * | 01 | Invoke SetMetaData on AesDec instance with nullptr as metadata and a valid track type (1). | metadata = nullptr, trackType = 1, output = eDRM_ERROR | Return value equals eDRM_ERROR and the assertion verifies this expected result. | Should Fail | + */ +TEST(AesDec, NullMetadataWithValidTrack) +{ + std::cout << "Entering NullMetadataWithValidTrack test" << std::endl; + + AesDec aesDec; + void* metadata = nullptr; + + int trackType = 1; + std::cout << "Invoking SetMetaData with metadata address: " << metadata << " and trackType: " << trackType << std::endl; + + DrmReturn result = aesDec.SetMetaData(metadata, trackType); + std::cout << "SetMetaData returned: " << result << std::endl; + + EXPECT_EQ(result, eDRM_ERROR); + + std::cout << "Exiting NullMetadataWithValidTrack test" << std::endl; +} +/** + * @brief Verify that SetMetaData handles valid non-null metadata with a negative track type correctly. + * + * This test verifies that the AesDec::SetMetaData method returns a success response when provided with a valid non-null metadata pointer and a negative track type value. The test ensures that despite the unusual negative track type, the API behaves as expected. + * + * **Test Group ID:** Basic: 01@n + * **Test Case ID:** 029@n + * **Priority:** High@n + * + * **Pre-Conditions:** None@n + * **Dependencies:** None@n + * **User Interaction:** None@n + * + * **Test Procedure:**@n + * | Variation / Step | Description | Test Data | Expected Result | Notes | + * | :----: | --------- | ---------- |-------------- | ----- | + * | 01 | Invoke AesDec::SetMetaData with a valid metadata pointer and a negative track type value | metadata = address of validData (validData = 200), trackType = -1 | Returns eDRM_SUCCESS and EXPECT_EQ assertion passes | Should Pass | + */ +TEST(AesDec, ValidNonNullMetadataWithNegativeTrack) +{ + std::cout << "Entering ValidNonNullMetadataWithNegativeTrack test" << std::endl; + + AesDec aesDec; + int validData = 200; + void* metadata = static_cast(&validData); + + int trackType = -1; + std::cout << "Invoking SetMetaData with metadata address: " << metadata << " and trackType: " << trackType << std::endl; + + DrmReturn result = aesDec.SetMetaData(metadata, trackType); + std::cout << "SetMetaData returned: " << result << std::endl; + + EXPECT_EQ(result, eDRM_SUCCESS); + + std::cout << "Exiting ValidNonNullMetadataWithNegativeTrack test" << std::endl; +} +/** + * @brief Verify that AES decryption correctly handles valid non-null metadata with maximum integer track type + * + * This test verifies that when a valid non-null metadata pointer is provided along with the maximum integer value for track type, + * the SetMetaData API of the AesDec class returns eDRM_SUCCESS. This ensures that the API correctly processes the provided parameters. + * + * **Test Group ID:** Basic: 01@n + * **Test Case ID:** 030@n + * **Priority:** High@n + * + * **Pre-Conditions:** None@n + * **Dependencies:** None@n + * **User Interaction:** None@n + * + * **Test Procedure:**@n + * | Variation / Step | Description | Test Data | Expected Result | Notes | + * | :----: | --------- | ---------- |-------------- | ----- | + * | 01 | Initialize AesDec object and test variables (validData, metadata pointer, trackType) | validData = 300, metadata = address of validData, trackType = 2147483647 | Variables initialized properly (no direct API call) | Should be successful | + * | 02 | Invoke SetMetaData API with initialized metadata and trackType | input: metadata = address of validData, trackType = 2147483647, output: result | API returns eDRM_SUCCESS and assertion EXPECT_EQ(result, eDRM_SUCCESS) passes | Should Pass | + */ +TEST(AesDec, ValidNonNullMetadataWithMaxIntTrack) +{ + std::cout << "Entering ValidNonNullMetadataWithMaxIntTrack test" << std::endl; + + AesDec aesDec; + int validData = 300; + void* metadata = static_cast(&validData); + + int trackType = 2147483647; + std::cout << "Invoking SetMetaData with metadata address: " << metadata << " and trackType: " << trackType << std::endl; + + DrmReturn result = aesDec.SetMetaData(metadata, trackType); + std::cout << "SetMetaData returned: " << result << std::endl; + + EXPECT_EQ(result, eDRM_SUCCESS); + + std::cout << "Exiting ValidNonNullMetadataWithMaxIntTrack test" << std::endl; +} +/** + * @brief Validate that the SignalDrmError method is invoked successfully on the AesDec object + * + * This test verifies that the SignalDrmError method of the AesDec class is executed without errors. + * It ensures that the method is callable and does not produce any unexpected behavior during its invocation. + * + * **Test Group ID:** Basic: 01@n + * **Test Case ID:** 031@n + * **Priority:** High@n + * + * **Pre-Conditions:** None@n + * **Dependencies:** None@n + * **User Interaction:** None@n + * + * **Test Procedure:**@n + * | Variation / Step | Description | Test Data | Expected Result | Notes | + * | :--------------: | ------------------------------------------------------------- | ---------------------------------------------- | --------------------------------------------------------------------- | ------------- | + * | 01 | Create AesDec object using the default constructor | input: none, output: AesDec object created | AesDec object is created successfully | Should be successful | + * | 02 | Invoke SignalDrmError method on the AesDec object | input: none, output: void invoked | SignalDrmError method is executed successfully without errors | Should Pass | + */ +TEST(AesDec, InvokeSignalDrmError) +{ + std::cout << "Entering InvokeSignalDrmError test" << std::endl; + + std::cout << "Creating AesDec object using default constructor" << std::endl; + AesDec aesDecObj; + + std::cout << "Invoking SignalDrmError method" << std::endl; + aesDecObj.SignalDrmError(); + std::cout << "SignalDrmError method invoked successfully" << std::endl; + + std::cout << "Exiting InvokeSignalDrmError test" << std::endl; +} +/** + * @brief Test that the SignalKeyAcquired method successfully notifies waiting threads. + * + * This test creates an instance of AesDec, calls the SignalKeyAcquired method, and verifies that the method executes without error and successfully signals any waiting threads. + * + * **Test Group ID:** Basic: 01@n + * **Test Case ID:** 032@n + * **Priority:** High@n + * + * **Pre-Conditions:** None@n + * **Dependencies:** None@n + * **User Interaction:** None@n + * + * **Test Procedure:** + * | Variation / Step | Description | Test Data | Expected Result | Notes | + * | :--------------: | ----------------------------------------------------------------- | ------------------------------------------------------- | ---------------------------------------------------------- | ------------------- | + * | 01 | Create AesDec object using default constructor | output1 = AesDec object | AesDec instance is successfully created | Should be successful| + * | 02 | Invoke SignalKeyAcquired method | No inputs, no outputs | Method is executed without error | Should Pass | + * | 03 | Verify method execution completion and log messages | None | Execution completes with proper log output and no exceptions | Should be successful| + */ +TEST(AesDec, SignalKeyAcquired_successfully_notifies_waiting_threads) +{ + std::cout<<"Entering SignalKeyAcquired_successfully_notifies_waiting_threads test"< lock(mtx); + + int timeInMs = 1000; + DrmReturn return_value; + + std::cout << "Invoking AesDec::WaitForKeyAcquireCompleteUnlocked with timeInMs = " << timeInMs << std::endl; + + aesDec.WaitForKeyAcquireCompleteUnlocked(timeInMs, return_value, lock); + + std::cout << "Method returned err with value " << return_value << std::endl; + + EXPECT_EQ(return_value, eDRM_SUCCESS); + + std::cout << "Exiting WaitForKeyAcquireCompleteUnlocked_SuccessfulKeyAcquisition test" << std::endl; +} +/** + * @brief Verify that WaitForKeyAcquireCompleteUnlocked immediately times out when zero wait time is provided. + * + * This test ensures that when the WaitForKeyAcquireCompleteUnlocked function is invoked with a wait time of 0 ms, + * it immediately times out and returns the eDRM_KEY_ACQUISITION_TIMEOUT error. The test validates that the API behaves + * correctly by asserting that the returned error value matches the expected timeout condition. + * + * **Test Group ID:** Basic: 01@n + * **Test Case ID:** 034@n + * **Priority:** High@n + * + * **Pre-Conditions:** None@n + * **Dependencies:** None@n + * **User Interaction:** None@n + * + * **Test Procedure:** + * | Variation / Step | Description | Test Data | Expected Result | Notes | + * | :--------------: | ----------------------------------------------------------------------------------------------- | --------------------------------------------------- | ------------------------------------------------------------- | --------------- | + * | 01 | Initialize required objects (AesDec instance, mutex, and unique_lock) to prepare for API call. | AesDec instance, mutex, unique_lock | Objects created successfully | Should be successful | + * | 02 | Call WaitForKeyAcquireCompleteUnlocked with timeInMs set to 0 along with return_value and lock. | timeInMs = 0, return_value, lock | API returns error value eDRM_KEY_ACQUISITION_TIMEOUT | Should Pass | + * | 03 | Verify that the returned error value matches the expected timeout error using EXPECT_EQ. | return_value, expected = eDRM_KEY_ACQUISITION_TIMEOUT | EXPECT_EQ check passes confirming correct timeout behavior | Should be successful | + */ +TEST(AesDec, WaitForKeyAcquireCompleteUnlocked_ZeroWaitTimeImmediateTimeout) +{ + std::cout << "Entering WaitForKeyAcquireCompleteUnlocked_ZeroWaitTimeImmediateTimeout test" << std::endl; + + AesDec aesDec; + + std::mutex mtx; + + std::unique_lock lock(mtx); + + int timeInMs = 0; + DrmReturn return_value; + + std::cout << "Invoking AesDec::WaitForKeyAcquireCompleteUnlocked with timeInMs = " << timeInMs << std::endl; + + aesDec.WaitForKeyAcquireCompleteUnlocked(timeInMs, return_value, lock); + + std::cout << "Method returned err with value " << return_value << std::endl; + + EXPECT_EQ(return_value, eDRM_KEY_ACQUISITION_TIMEOUT); + + std::cout << "Exiting WaitForKeyAcquireCompleteUnlocked_ZeroWaitTimeImmediateTimeout test" << std::endl; +} + +/** + * @brief Verify that the AesDec API successfully instantiates and acquires key + * + * This test validates the default instantiation of the AesDec class and confirms that calling the acquire_key() method correctly launches the key acquisition thread. + * + * **Test Group ID:** Basic: 01@n + * **Test Case ID:** 035@n + * **Priority:** High@n + * @n + * **Pre-Conditions:** None@n + * **Dependencies:** None@n + * **User Interaction:** None@n + * @n + * **Test Procedure:**@n + * | Variation / Step | Description | Test Data | Expected Result | Notes | + * | :--------------: | -------------------------------------------------------- | ------------------------------------------ | ----------------------------------------------------- | ----------------- | + * | 01 | Instantiate AesDec object using default constructor | input: none, output: AesDec object created | AesDec object is successfully instantiated | Should be successful | + * | 02 | Invoke acquire_key() method to launch key acquisition thread | input: none, output: key acquisition thread launched | acquire_key() method is executed and thread is launched | Should Pass | + */ +TEST(AesDec, Successful_key_acquisition) +{ + std::cout << "Entering Successful_key_acquisition test" << std::endl; + + AesDec aesDec; + std::cout << "AesDec object instantiated using default constructor" << std::endl; + + std::cout << "Invoking acquire_key() method" << std::endl; + aesDec.acquire_key(); + std::cout << "Method acquire_key() executed; key acquisition thread should be launched" << std::endl; + + std::cout << "Exiting Successful_key_acquisition test" << std::endl; +} + +/** + * @brief Verify that the AesDec destructor works correctly when object goes out of scope + * + * This test validates the proper destruction behavior of the AesDec class. It ensures that + * an object created using the default constructor is destructed cleanly, without throwing + * exceptions, crashes, or memory leaks upon exiting its scope. + * + * **Test Group ID:** Basic: 01@n + * **Test Case ID:** 036@n + * **Priority:** High@n + * @n + * **Pre-Conditions:** None@n + * **Dependencies:** None@n + * **User Interaction:** None@n + * @n + * **Test Procedure:**@n + * | Variation / Step | Description | Test Data | Expected Result | Notes | + * | :--------------: | ------------------------------------------------------ | -------------------------------------- | ------------------------------------------------------- | ------------------- | + * | 01 | Instantiate AesDec object using default constructor | input: none, output: AesDec object | AesDec object is successfully created | Should be successful | + * | 02 | Let object go out of scope to trigger destructor | input: none | Destructor is called and completes without exception | No crash or leak | + */ +TEST(AesDec, AesDec_Destructor_Default) +{ + std::cout << "Entering AesDec_Destructor_Default test" << std::endl; + + std::cout << "Invoking default constructor for AesDec" << std::endl; + + ASSERT_NO_THROW( + { + AesDec aesDecObj; + std::cout << "AesDec object created successfully. It will be destructed when going out of scope." << std::endl; + }); + + std::cout << "AesDec object destructed successfully" << std::endl; + + std::cout << "Exiting AesDec_Destructor_Default test" << std::endl; +} + +int main(int argc, char **argv) { + ::testing::InitGoogleTest(&argc, argv); + return RUN_ALL_TESTS(); +} From 1dc757c593082ab021e69de99f95040380ee50b4 Mon Sep 17 00:00:00 2001 From: joyal-06 Date: Thu, 10 Jul 2025 18:25:16 +0530 Subject: [PATCH 4/9] gh #2: Generate_L1_tests --- drm/helper/test/test_l1_DrmHelper.cpp | 357 ++++++ drm/test/test_l1_ClearKeyDrmSession.cpp | 1447 +++++++++++++++++++++++ drm/test/test_l1_DrmData.cpp | 698 +++++++++++ 3 files changed, 2502 insertions(+) create mode 100755 drm/helper/test/test_l1_DrmHelper.cpp create mode 100755 drm/test/test_l1_ClearKeyDrmSession.cpp create mode 100755 drm/test/test_l1_DrmData.cpp diff --git a/drm/helper/test/test_l1_DrmHelper.cpp b/drm/helper/test/test_l1_DrmHelper.cpp new file mode 100755 index 0000000..c151ceb --- /dev/null +++ b/drm/helper/test/test_l1_DrmHelper.cpp @@ -0,0 +1,357 @@ + +/* + * If not stated otherwise in this file or this component's LICENSE file the + * following copyright and licenses apply: + * + * Copyright 2025 RDK Management + * + * 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. + */ + +/** +* @file test_l1_DrmHelper.cpp +* @page DrmHelper Level 1 Tests +* +* ## Module's Role +* This module includes Level 1 functional tests (success and failure scenarios). +* This is to ensure that the DrmHelper methods meet the requirements. +* +* **Pre-Conditions:** None @n +* **Dependencies:** None @n +* +*/ + +#include +#include +#include +#include "DrmHelper.h" + +/** + * @brief Verify that the default initialization of ChallengeInfo sets all member variables to their expected default values. + * + * This test verifies that when the default constructor of ChallengeInfo is invoked, the member variable 'data' is set to nullptr, + * and both 'url' and 'accessToken' are initialized to empty strings. This ensures that the object is in a valid and predictable state for further operations. + * + * **Test Group ID:** Basic: 01 + * **Test Case ID:** 001 + * **Priority:** High + * + * **Pre-Conditions:** None + * **Dependencies:** None + * **User Interaction:** None + * + * **Test Procedure:** + * | Variation / Step | Description | Test Data | Expected Result | Notes | + * | :--------------: | ------------------------------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------ | -------------------------------------------------------------------------------------------------------------------------------------- | ----------- | + * | 01 | Invoke the default constructor for ChallengeInfo to create a new object | No input, default constructor call, expected output: data = nullptr, url = "", accessToken = "" | The object is initialized with data as nullptr, and both url and accessToken as empty strings; all assertions pass | Should Pass | + */ +TEST(ChallengeInfo, VerifyDefaultInitialization) { + + std::cout << "Entering VerifyDefaultInitialization test" << "\n"; + + std::cout << "Invoking default constructor for ChallengeInfo" << "\n"; + + ChallengeInfo challengeInfo; + + std::cout << "Default constructor invoked. Checking initial values" << "\n"; + + if (challengeInfo.data == nullptr) { + std::cout << "challengeInfo.data is null" << "\n"; + } + else { + std::cout << "challengeInfo.data is not null" << "\n"; + } + + std::cout << "challengeInfo.url value: '" << challengeInfo.url << "'" << "\n"; + std::cout << "challengeInfo.accessToken value: '" << challengeInfo.accessToken << "'" << "\n"; + + EXPECT_EQ(challengeInfo.data, nullptr); + EXPECT_EQ(challengeInfo.url, ""); + EXPECT_EQ(challengeInfo.accessToken, ""); + + std::cout << "Exiting VerifyDefaultInitialization test" << "\n"; +} +/** + * @brief Validate the default constructor initializes LicenseRequest object with correct defaults. + * + * This test verifies that the LicenseRequest class's default constructor correctly initializes all members with appropriate default values. It confirms that the method field is set to one of the allowed values (DRM_RETRIEVE, GET, or POST), licenseAnonymousRequest is set to false, url and payload are empty strings, and the headers map is empty. + * + * **Test Group ID:** Basic: 01 + * **Test Case ID:** 002 + * **Priority:** High + * + * **Pre-Conditions:** None + * **Dependencies:** None + * **User Interaction:** None + * + * **Test Procedure:** + * | Variation / Step | Description | Test Data | Expected Result | Notes | + * | :----: | --------- | ---------- |-------------- | ----- | + * | 01 | Invoke default constructor for LicenseRequest object | None | LicenseRequest object is created with default field values | Should be successful | + * | 02 | Validate that the method field is set to one of (DRM_RETRIEVE, GET, POST) | licenseRequestObject.method = DRM_RETRIEVE, GET, or POST | Method field matches one of the allowed values | Should Pass | + * | 03 | Check that licenseAnonymousRequest is false by default | licenseRequestObject.licenseAnonymousRequest = false | The field evaluates to false as expected | Should Pass | + * | 04 | Verify that the url field is an empty string | licenseRequestObject.url = "" | Url field is an empty string | Should Pass | + * | 05 | Verify that the payload field is an empty string | licenseRequestObject.payload = "" | Payload field is an empty string | Should Pass | + * | 06 | Ensure that the headers map is empty | licenseRequestObject.headers = {} | Headers map is empty | Should Pass | + */ +TEST(LicenseRequest, DefaultConstructorInitialization_PositiveTest) +{ + std::cout<<"Entering DefaultConstructorInitialization_PositiveTest test"< systemIds; + std::cout << "Initial systemIds vector size: " << systemIds.size() << std::endl; + + std::cout << "Invoking getSystemIds method" << std::endl; + EXPECT_NO_THROW(engine.getSystemIds(systemIds)); + + std::cout << "After Invoking getSystemIds, systemIds vector size: " << systemIds.size() << std::endl; + for (size_t i = 0; i < systemIds.size(); ++i) + { + std::cout << "systemIds[" << i << "]: " << systemIds[i] << std::endl; + } + + std::cout << "Exiting GetSystemIds_EmptyVector test" << std::endl; +} +/** + * @brief Verify the hasDRM API returns true for a default constructed DrmInfo + * + * This test evaluates the behavior of the hasDRM function when invoked using a default + * DrmInfo object. The objective is to ensure that the API correctly identifies the DRM + * presence as true in this context. + * + * **Test Group ID:** Basic: 01@n + * **Test Case ID:** 007@n + * **Priority:** High@n + * + * **Pre-Conditions:** None@n + * **Dependencies:** None@n + * **User Interaction:** None@n + * + * **Test Procedure:** + * | Variation / Step | Description | Test Data | Expected Result | Notes | + * | :--------------: | -------------------------------------------------------------- | ------------------------------------------------------ | -------------------------------------- | ---------------- | + * | 01 | Initialize DrmInfo and DrmHelperEngine objects | drmInfo = default constructed, engine = default constructed | Objects are successfully created | Should be successful | + * | 02 | Invoke engine.hasDRM with the default DrmInfo | drmInfo = default constructed | Return value true from hasDRM | Should Pass | + * | 03 | Validate the returned result using EXPECT_TRUE | result = true | Test assertion passes | Should Pass | + */ +TEST(DrmHelperEngine, hasDRMethod) +{ + std::cout << "Entering hasDRMethod test" << std::endl; + + DrmInfo drmInfo; + DrmHelperEngine engine; + + std::cout << "Invoking hasDRM with default DrmInfo" << std::endl; + bool result = engine.hasDRM(drmInfo); + std::cout << "hasDRM returned: " << result << std::endl; + + EXPECT_TRUE(result); + + std::cout << "Exiting hasDRMethod test" << std::endl; +} + +/** + * @brief Verify that registerFactory handles a null input gracefully without altering internal state. + * + * This test ensures that the API `registerFactory` does not register a null factory pointer + * and maintains internal consistency. It verifies that the factory count remains unchanged (zero), + * demonstrating proper handling of invalid input without exceptions or side effects. + * + * **Test Group ID:** Basic: 01 @n + * **Test Case ID:** 008 @n + * **Priority:** High @n + * + * **Pre-Conditions:** None @n + * **Dependencies:** None @n + * **User Interaction:** None @n + * + * **Test Procedure:** @n + * | Variation / Step | Description | Test Data | Expected Result | Notes | + * | :--------------: | --------------------------------------------------------------------- | --------------- | ------------------------------------------ | ------------------ | + * | 01 | Invoke registerFactory with a null pointer | factory = null | Factory count remains zero | Should Not Change | + * | 02 | Retrieve factory count after attempted registration with null pointer | | Count = 0 | Verifies no effect | + */ +TEST(DrmHelperEngine, NullFactoryRegistrationTest) +{ + std::cout << "Entering NullFactoryRegistrationTest test" << std::endl; + + DrmHelperEngine engine; + + std::cout << "Invoking registerFactory with nullptr" << std::endl; + EXPECT_NO_THROW(engine.registerFactory(nullptr);); + + std::cout << "Exiting NullFactoryRegistrationTest test" << std::endl; +} + + +int main(int argc, char **argv) { + ::testing::InitGoogleTest(&argc, argv); + return RUN_ALL_TESTS(); +} diff --git a/drm/test/test_l1_ClearKeyDrmSession.cpp b/drm/test/test_l1_ClearKeyDrmSession.cpp new file mode 100755 index 0000000..255faba --- /dev/null +++ b/drm/test/test_l1_ClearKeyDrmSession.cpp @@ -0,0 +1,1447 @@ + +/* + * If not stated otherwise in this file or this component's LICENSE file the + * following copyright and licenses apply: + * + * Copyright 2025 RDK Management + * + * 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. + */ + +/** +* @file test_l1_ClearKeyDrmSession.cpp +* @page ClearKeyDrmSession Level 1 Tests +* +* ## Module's Role +* This module includes Level 1 functional tests (success and failure scenarios). +* This is to ensure that the ClearKeyDrmSession methods meet the requirements. +* +* **Pre-Conditions:** None @n +* **Dependencies:** None @n +* +*/ + +#include +#include +#include +#include "ClearKeyDrmSession.h" + + +/** + * @brief Validates that the default constructor for ClearKeySession creates a valid instance. + * + * This test verifies that the ClearKeySession default constructor does not throw any exceptions and results in the creation of a valid object instance. + * + * **Test Group ID:** Basic: 01 + * **Test Case ID:** 001 + * **Priority:** High + * + * **Pre-Conditions:** None + * **Dependencies:** None + * **User Interaction:** None + * + * **Test Procedure:** + * | Variation / Step | Description | Test Data | Expected Result | Notes | + * | :--------------: | ----------------------------------------------------------------------- | ------------------------------------------------------ | ---------------------------------------------------- | ------------------ | + * | 01 | Invoke ClearKeySession constructor within EXPECT_NO_THROW to validate no exception is thrown | input: none, output: valid instance of ClearKeySession created | No exception thrown; valid instance created | Should Pass | + */ +TEST(ClearKeySession, DefaultConstructionCreatesValidInstance) +{ + std::cout<<"Entering DefaultConstructionCreatesValidInstance test"<(ivBuffer); + uint32_t f_cbIV = 16; + std::cout << "Initialized IV: " << ivBuffer << " with length: " << f_cbIV << std::endl; + + char payloadBuffer[129] = ""; + strncpy(payloadBuffer, "This is a valid payload data used for decryption testing purposes.", sizeof(payloadBuffer) - 1); + const uint8_t* payloadData = reinterpret_cast(payloadBuffer); + uint32_t payloadDataSize = 128; + std::cout << "Initialized Payload Data: " << payloadBuffer << " with size: " << payloadDataSize << std::endl; + + uint8_t* opaqueBuffer = new uint8_t[100]; + std::cout << "Allocated opaque data buffer at address: " << static_cast(opaqueBuffer) << std::endl; + uint8_t** ppOpaqueData = &opaqueBuffer; + + ClearKeySession session; + std::cout << "Invoking decrypt method with valid IV, payload data and opaque data pointer" << std::endl; + int ret = session.decrypt(f_pbIV, f_cbIV, payloadData, payloadDataSize, ppOpaqueData); + std::cout << "decrypt returned: " << ret << std::endl; + + EXPECT_EQ(ret, 0); + + delete[] opaqueBuffer; + std::cout << "Exiting PositiveCase test" << std::endl; +} +/** + * @brief Test decrypt API with a null IV pointer to validate proper error handling + * + * This test verifies that the decrypt API returns an error code when a null IV pointer is provided. + * It ensures that the function correctly detects and handles an invalid IV pointer to prevent + * unexpected behavior during the decryption process. @n + * + * **Test Group ID:** Basic: 01@n + * **Test Case ID:** 004@n + * **Priority:** High@n + * + * **Pre-Conditions:** None@n + * **Dependencies:** None@n + * **User Interaction:** None@n + * + * **Test Procedure:**@n + * | Variation / Step | Description | Test Data | Expected Result | Notes | + * | :----: | --------- | ---------- |-------------- | ----- | + * | 01 | Initialize null IV pointer and set IV length | f_pbIV = nullptr, f_cbIV = 16 | IV pointer is null and IV length set correctly | Should be successful | + * | 02 | Initialize payload buffer with valid data | payloadBuffer = "ValidPayloadDataForNullIVTest", payloadData = reinterpret_cast(payloadBuffer), payloadDataSize = 128 | Payload data is correctly initialized | Should be successful | + * | 03 | Allocate opaque data buffer and set up pointer | opaqueBuffer allocated with size 100, ppOpaqueData = &opaqueBuffer | Opaque buffer is allocated and pointer is set | Should be successful | + * | 04 | Invoke decrypt method with null IV pointer | f_pbIV = nullptr, f_cbIV = 16, payloadData = valid payload, payloadDataSize = 128, ppOpaqueData = &opaqueBuffer | API returns non-zero error code indicating error for null IV pointer | Should Fail | + * | 05 | Validate the API return value is non-zero | ret = return value from decrypt method | EXPECT_NE(ret, 0) passes, confirming error condition | Should be successful | + */ +TEST(ClearKeySession, NullIVPointer) +{ + std::cout << "Entering NullIVPointer test" << std::endl; + + const uint8_t* f_pbIV = nullptr; + uint32_t f_cbIV = 16; + std::cout << "Using null IV pointer with IV length: " << f_cbIV << std::endl; + + char payloadBuffer[129] = ""; + strncpy(payloadBuffer, "ValidPayloadDataForNullIVTest", sizeof(payloadBuffer) - 1); + const uint8_t* payloadData = reinterpret_cast(payloadBuffer); + uint32_t payloadDataSize = 128; + std::cout << "Initialized Payload Data: " << payloadBuffer << " with size: " << payloadDataSize << std::endl; + + uint8_t* opaqueBuffer = new uint8_t[100]; + std::cout << "Allocated opaque data buffer at address: " << static_cast(opaqueBuffer) << std::endl; + uint8_t** ppOpaqueData = &opaqueBuffer; + + ClearKeySession session; + std::cout << "Invoking decrypt method with null IV pointer" << std::endl; + int ret = session.decrypt(f_pbIV, f_cbIV, payloadData, payloadDataSize, ppOpaqueData); + std::cout << "decrypt returned: " << ret << std::endl; + + EXPECT_NE(ret, 0); + + delete[] opaqueBuffer; + std::cout << "Exiting NullIVPointer test" << std::endl; +} +/** + * @brief Verify that the decrypt API returns an error when provided with an IV length of zero. + * + * This test validates that the ClearKeySession::decrypt method handles the scenario where the IV length is set to zero, despite having a valid IV buffer. It ensures that the API does not proceed with decryption using an invalid IV length and returns a non-zero error code. + * + * **Test Group ID:** Basic: 01@n + * **Test Case ID:** 005@n + * **Priority:** High@n + * + * **Pre-Conditions:** None@n + * **Dependencies:** None@n + * **User Interaction:** None@n + * + * **Test Procedure:**@n + * | Variation / Step | Description | Test Data | Expected Result | Notes | + * | :--------------: | ----------------------------------------------------------------------- | -------------------------------------------------------------------------------------------------------------------------------------------------- | ---------------------------------------------------------------------------------- | ----------- | + * | 01 | Invoke decrypt with IV length set to zero and valid payload data input. | f_pbIV = "ValidIVDataForTesting", f_cbIV = 0, payloadData = "ValidPayloadDataForZeroIVLengthTest", payloadDataSize = 128, ppOpaqueData = pointer | API returns a non-zero value indicating an error, and the assertion EXPECT_NE(ret, 0) passes. | Should Fail | + */ +TEST(ClearKeySession, ZeroIVLength) +{ + std::cout << "Entering ZeroIVLength test" << std::endl; + + char ivBuffer[17] = ""; + strncpy(ivBuffer, "ValidIVDataForTesting", sizeof(ivBuffer) - 1); + const uint8_t* f_pbIV = reinterpret_cast(ivBuffer); + uint32_t f_cbIV = 0; + std::cout << "Initialized IV: " << ivBuffer << " but IV length is set to: " << f_cbIV << std::endl; + + char payloadBuffer[129] = ""; + strncpy(payloadBuffer, "ValidPayloadDataForZeroIVLengthTest", sizeof(payloadBuffer) - 1); + const uint8_t* payloadData = reinterpret_cast(payloadBuffer); + uint32_t payloadDataSize = 128; + std::cout << "Initialized Payload Data: " << payloadBuffer << " with size: " << payloadDataSize << std::endl; + + uint8_t* opaqueBuffer = new uint8_t[100]; + std::cout << "Allocated opaque data buffer at address: " << static_cast(opaqueBuffer) << std::endl; + uint8_t** ppOpaqueData = &opaqueBuffer; + + ClearKeySession session; + std::cout << "Invoking decrypt method with IV length set to zero" << std::endl; + int ret = session.decrypt(f_pbIV, f_cbIV, payloadData, payloadDataSize, ppOpaqueData); + std::cout << "decrypt returned: " << ret << std::endl; + + EXPECT_NE(ret, 0); + + delete[] opaqueBuffer; + std::cout << "Exiting ZeroIVLength test" << std::endl; +} +/** + * @brief Verifies that ClearKeySession::decrypt returns an error when provided with a null payload data pointer. + * + * This test configures the initialization vector (IV) with a known fixed value and intentionally sets the payload data pointer to NULL. It then calls the decrypt method of the ClearKeySession to validate that the function correctly handles the null input by returning a non-zero error code. + * + * **Test Group ID:** Basic: 01@n + * **Test Case ID:** 006@n + * **Priority:** High@n + * + * **Pre-Conditions:** None@n + * **Dependencies:** None@n + * **User Interaction:** None@n + * + * **Test Procedure:**@n + * | Variation / Step | Description | Test Data | Expected Result | Notes | + * | :----: | --------- | ---------- | -------------- | ----- | + * | 01 | Initialize IV buffer with fixed value "1234567890123456" and length 16 | ivBuffer = "1234567890123456", f_cbIV = 16 | IV initialized correctly | Should be successful | + * | 02 | Set payload data pointer to NULL and define payload data size | payloadData = nullptr, payloadDataSize = 128 | Payload pointer is set to NULL | Should be successful | + * | 03 | Allocate opaque data buffer | opaqueBuffer = allocated memory address, size = 100 bytes | Memory allocation is successful | Should be successful | + * | 04 | Invoke decrypt API with null payload data pointer | f_pbIV = ivBuffer address, f_cbIV = 16, payloadData = nullptr, payloadDataSize = 128, ppOpaqueData = address of opaqueBuffer pointer | decrypt returns non-zero error code; EXPECT_NE(ret, 0) passes | Should Fail | + * | 05 | Deallocate opaque data buffer | opaqueBuffer pointer | Memory deallocated without issues | Should be successful | + */ +TEST(ClearKeySession, NullPayloadDataPointer) +{ + std::cout << "Entering NullPayloadDataPointer test" << std::endl; + + char ivBuffer[17] = ""; + strncpy(ivBuffer, "1234567890123456", sizeof(ivBuffer) - 1); + const uint8_t* f_pbIV = reinterpret_cast(ivBuffer); + uint32_t f_cbIV = 16; + std::cout << "Initialized IV: " << ivBuffer << " with length: " << f_cbIV << std::endl; + + const uint8_t* payloadData = nullptr; + uint32_t payloadDataSize = 128; + std::cout << "Using null payload data pointer with payload size: " << payloadDataSize << std::endl; + + uint8_t* opaqueBuffer = new uint8_t[100]; + std::cout << "Allocated opaque data buffer at address: " << static_cast(opaqueBuffer) << std::endl; + uint8_t** ppOpaqueData = &opaqueBuffer; + + ClearKeySession session; + std::cout << "Invoking decrypt method with null payload data pointer" << std::endl; + int ret = session.decrypt(f_pbIV, f_cbIV, payloadData, payloadDataSize, ppOpaqueData); + std::cout << "decrypt returned: " << ret << std::endl; + + EXPECT_NE(ret, 0); + + delete[] opaqueBuffer; + std::cout << "Exiting NullPayloadDataPointer test" << std::endl; +} +/** + * @brief Verify that decrypt API returns an error when payload data size is zero. + * + * This test verifies that when the payload data size is set to zero, the decrypt method of the ClearKeySession + * object should return a non-zero error code, indicating that the decryption process correctly handles the case with inadequate payload data. + * + * **Test Group ID:** Basic: 01@n + * **Test Case ID:** 007@n + * **Priority:** High@n + * + * **Pre-Conditions:** None@n + * **Dependencies:** None@n + * **User Interaction:** None@n + * + * **Test Procedure:** + * | Variation / Step | Description | Test Data | Expected Result | Notes | + * | :--------------: | ----------------------------------------------------------------------------------------------------- | --------------------------------------------------------------------------------------------------------------------------------------------- | ----------------------------------------------------------------- | --------------- | + * | 01 | Initialize IV buffer with "1234567890123456" and payload buffer with "ValidPayloadDataForZeroDataSize"; set payloadDataSize to 0; allocate opaqueBuffer. | ivBuffer = "1234567890123456", f_cbIV = 16, payloadBuffer = "ValidPayloadDataForZeroDataSize", payloadDataSize = 0, opaqueBuffer allocated = address | Variables are correctly initialized and memory is allocated. | Should be successful | + * | 02 | Invoke the decrypt method on ClearKeySession with the given IV, payload data pointer, payload size 0, and opaque buffer pointer. | f_pbIV = pointer to ivBuffer, f_cbIV = 16, payloadData = pointer to payloadBuffer, payloadDataSize = 0, ppOpaqueData = address of opaqueBuffer | Return value from decrypt API is non-zero. | Should Fail | + * | 03 | Validate that the return value from the decrypt call is not 0 using EXPECT_NE. | ret = return value from decrypt | EXPECT_NE(ret, 0) assertion should pass. | Should be successful | + */ +TEST(ClearKeySession, ZeroPayloadDataSize) +{ + std::cout << "Entering ZeroPayloadDataSize test" << std::endl; + + char ivBuffer[17] = ""; + strncpy(ivBuffer, "1234567890123456", sizeof(ivBuffer) - 1); + const uint8_t* f_pbIV = reinterpret_cast(ivBuffer); + uint32_t f_cbIV = 16; + std::cout << "Initialized IV: " << ivBuffer << " with length: " << f_cbIV << std::endl; + + char payloadBuffer[129] = ""; + strncpy(payloadBuffer, "ValidPayloadDataForZeroDataSize", sizeof(payloadBuffer) - 1); + const uint8_t* payloadData = reinterpret_cast(payloadBuffer); + uint32_t payloadDataSize = 0; + std::cout << "Initialized Payload Data: " << payloadBuffer << " but payload size is set to: " << payloadDataSize << std::endl; + + uint8_t* opaqueBuffer = new uint8_t[100]; + std::cout << "Allocated opaque data buffer at address: " << static_cast(opaqueBuffer) << std::endl; + uint8_t** ppOpaqueData = &opaqueBuffer; + + ClearKeySession session; + std::cout << "Invoking decrypt method with payload size set to zero" << std::endl; + int ret = session.decrypt(f_pbIV, f_cbIV, payloadData, payloadDataSize, ppOpaqueData); + std::cout << "decrypt returned: " << ret << std::endl; + + EXPECT_NE(ret, 0); + + delete[] opaqueBuffer; + std::cout << "Exiting ZeroPayloadDataSize test" << std::endl; +} +/** + * @brief Verify that the decrypt method returns a non-zero error code when provided with a null opaque data pointer + * + * This test verifies that the ClearKeySession::decrypt method correctly handles a scenario where the opaque data pointer is null. + * The objective is to ensure that the method does not perform decryption when mandatory parameters are missing and returns an error code. + * + * **Test Group ID:** Basic: 01@n + * **Test Case ID:** 008@n + * **Priority:** High@n + * + * **Pre-Conditions:** None@n + * **Dependencies:** None@n + * **User Interaction:** None@n + * + * **Test Procedure:** + * | Variation / Step | Description | Test Data | Expected Result | Notes | + * | :--------------: | ------------------------------------------------------------------- | ---------------------------------------------------------------------------------------------------------- | -------------------------------------------------------- | ------------ | + * | 01 | Initialize the IV buffer with a 16-character string | input: ivBuffer = "1234567890123456", f_cbIV = 16 | IV buffer is correctly initialized with proper length | Should be successful | + * | 02 | Initialize the payload data buffer with valid payload string | input: payloadBuffer = "ValidPayloadDataForNullOpaqueTest", payloadDataSize = 128 | Payload data is correctly initialized | Should be successful | + * | 03 | Set the opaque data pointer to null | input: ppOpaqueData = nullptr | Opaque data pointer is null | Should be successful | + * | 04 | Invoke the decrypt method of ClearKeySession with the provided inputs | input: f_pbIV = pointer to ivBuffer, f_cbIV = 16, payloadData = pointer to payloadBuffer, payloadDataSize = 128, ppOpaqueData = nullptr | decrypt method returns a non-zero error code indicating failure | Should Pass | + */ +TEST(ClearKeySession, NullOpaqueDataPointer) +{ + std::cout << "Entering NullOpaqueDataPointer test" << std::endl; + + char ivBuffer[17] = ""; + strncpy(ivBuffer, "1234567890123456", sizeof(ivBuffer) - 1); + const uint8_t* f_pbIV = reinterpret_cast(ivBuffer); + uint32_t f_cbIV = 16; + std::cout << "Initialized IV: " << ivBuffer << " with length: " << f_cbIV << std::endl; + + char payloadBuffer[129] = ""; + strncpy(payloadBuffer, "ValidPayloadDataForNullOpaqueTest", sizeof(payloadBuffer) - 1); + const uint8_t* payloadData = reinterpret_cast(payloadBuffer); + uint32_t payloadDataSize = 128; + std::cout << "Initialized Payload Data: " << payloadBuffer << " with size: " << payloadDataSize << std::endl; + + uint8_t** ppOpaqueData = nullptr; + std::cout << "Using null opaque data pointer" << std::endl; + + ClearKeySession session; + std::cout << "Invoking decrypt method with null opaque data pointer" << std::endl; + int ret = session.decrypt(f_pbIV, f_cbIV, payloadData, payloadDataSize, ppOpaqueData); + std::cout << "decrypt returned: " << ret << std::endl; + + EXPECT_NE(ret, 0); + + std::cout << "Exiting NullOpaqueDataPointer test" << std::endl; +} +/** + * @brief Validate decryption with a non-zero subsample count + * + * This test verifies that the clear key decryption API correctly processes decryption requests + * when a non-zero subsample count is provided. It ensures that the API returns success (0) when + * given initialized buffer objects and a specific subsample count, which is essential for proper + * decryption operations. + * + * **Test Group ID:** Basic: 01@n + * **Test Case ID:** 009@n + * **Priority:** High@n + * + * **Pre-Conditions:** None@n + * **Dependencies:** None@n + * **User Interaction:** None@n + * + * **Test Procedure:** + * | Variation / Step | Description | Test Data | Expected Result | Notes | + * | :----: | --------- | ---------- |-------------- | ----- | + * | 01 | Create an instance of ClearKeySession. | session = new ClearKeySession object | ClearKeySession instance created. | Should be successful | + * | 02 | Initialize GstBuffer and GstCaps objects required for decryption. | keyIDBufferObj, ivBufferObj, bufferObj, subSamplesBufferObj, capsObj = uninitialized objects | Buffer and caps objects are created. | Should be successful | + * | 03 | Set the subSampleCount value to 2. | subSampleCount = 2 | subSampleCount variable is correctly set. | Should be successful | + * | 04 | Invoke the decrypt API with the prepared arguments. | keyIDBufferObj = instance, ivBufferObj = instance, bufferObj = instance, subSampleCount = 2, subSamplesBufferObj = instance, capsObj = instance | API returns 0 and outputs decryption process details. | Should Pass | + * | 05 | Validate that the decrypt API returned 0 using assertion. | ret (return value) = 0 | ASSERT_EQ verifies that ret equals 0. | Should Pass | + */ +TEST(ClearKeySession, ValidDecryptionWithNonZeroSubSampleCount) +{ + std::cout<<"Entering ValidDecryptionWithNonZeroSubSampleCount test"<" logged | Should be successful | + * | 05 | Assert that the return value from decrypt is not 0 | ret | ASSERT_NE(ret, 0) passes | Should be successful | + */ +TEST(ClearKeySession, DecryptionFailsWhenKeyIDBufferIsNull) +{ + std::cout<<"Entering DecryptionFailsWhenKeyIDBufferIsNull test"<getData(); + std::cout << "DrmData content retrieved using getData: " << drmContent << std::endl; + } + else + { + std::cout << "generateKeyRequest returned NULL pointer" << std::endl; + } + + EXPECT_NE(drmData, nullptr); + EXPECT_NE(destinationURL, std::string("")); + + std::cout << "Exiting ValidKeyRequestGeneration test" << std::endl; +} +/** + * @brief Verify that generateKeyRequest returns a null pointer when provided an empty destination URL. + * + * This test checks that calling generateKeyRequest with an empty destination URL results in a NULL pointer being returned. + * The test ensures that the ClearKeySession class properly handles invalid input by not proceeding with an invalid API call. + * + * **Test Group ID:** Basic: 01@n + * **Test Case ID:** 020@n + * **Priority:** High@n + * + * **Pre-Conditions:** None@n + * **Dependencies:** None@n + * **User Interaction:** None@n + * + * **Test Procedure:**@n + * | Variation / Step | Description | Test Data | Expected Result | Notes | + * | :--------------: | ---------------------------------------------------------------- | ---------------------------------------------------------- | -------------------------------------------------------- | ------------- | + * | 01 | Initialize test data and session instance | destinationURL = "", timeout = 5000 | Test data and session are initialized successfully | Should be successful | + * | 02 | Invoke generateKeyRequest with empty destination URL and validate | input: destinationURL = "", timeout = 5000, output: drmData = nullptr | API returns a null pointer indicating invalid input provided | Should Fail | + */ +TEST(ClearKeySession, EmptyDestinationURL) +{ + std::cout << "Entering EmptyDestinationURL test" << std::endl; + + std::string destinationURL(""); + uint32_t timeout = 5000; + + ClearKeySession session; + + std::cout << "Invoking generateKeyRequest with empty destinationURL and timeout: " << timeout << std::endl; + + DrmData* drmData = session.generateKeyRequest(destinationURL, timeout); + + if (!drmData) + { + std::cout << "generateKeyRequest returned NULL pointer as expected due to empty destinationURL" << std::endl; + } + else + { + std::cout << "generateKeyRequest returned a valid pointer unexpectedly" << std::endl; + } + + EXPECT_EQ(drmData, nullptr); + + std::cout << "Exiting EmptyDestinationURL test" << std::endl; +} +/** + * @brief Test generateKeyRequest function with a zero timeout value to validate proper handling of invalid timeout input. + * + * This test verifies that when generateKeyRequest is invoked with a zero timeout value, the function returns a NULL pointer as expected, + * ensuring that the API correctly handles invalid timeout parameters. + * + * **Test Group ID:** Basic: 01@n + * **Test Case ID:** 021@n + * **Priority:** High@n + * + * **Pre-Conditions:** None@n + * **Dependencies:** None@n + * **User Interaction:** None@n + * + * **Test Procedure:** + * | Variation / Step | Description | Test Data | Expected Result | Notes | + * | :--------------: | ----------------------------------------------------------------- | ---------------------------------------------------------- | --------------------------------------------------------- | ------------------ | + * | 01 | Initialize the ClearKeySession instance and set test parameters | destinationURL = https://license.server.com, timeout = 0 | Test parameters are initialized properly | Should be successful | + * | 02 | Invoke generateKeyRequest with the zero timeout value | destinationURL = https://license.server.com, timeout = 0 | API returns a NULL pointer indicating failure due to zero timeout | Should Fail | + * | 03 | Assert that the returned DRM data pointer is NULL | drmData = nullptr | EXPECT_EQ assertion passes confirming the NULL return | Should be successful | + */ +TEST(ClearKeySession, ZeroTimeout) +{ + std::cout << "Entering ZeroTimeout test" << std::endl; + + std::string destinationURL("https://license.server.com"); + uint32_t timeout = 0; + + ClearKeySession session; + + std::cout << "Invoking generateKeyRequest with destinationURL: " << destinationURL << " and zero timeout: " << timeout << std::endl; + + DrmData* drmData = session.generateKeyRequest(destinationURL, timeout); + + if (!drmData) + { + std::cout << "generateKeyRequest returned NULL pointer as expected due to zero timeout" << std::endl; + } + else + { + std::cout << "generateKeyRequest returned a valid pointer unexpectedly" << std::endl; + } + + EXPECT_EQ(drmData, nullptr); + + std::cout << "Exiting ZeroTimeout test" << std::endl; +} +/** + * @brief Validate generateKeyRequest API with maximum timeout boundary + * + * This test verifies that when the generateKeyRequest API is invoked with a maximum timeout value (4294967295) and a valid destination URL, it returns a valid DrmData pointer and updates the destination URL accordingly. The test ensures that the API can handle boundary conditions, particularly the maximum timeout value. + * + * **Test Group ID:** Basic: 01@n + * **Test Case ID:** 022@n + * **Priority:** High@n + * + * **Pre-Conditions:** None@n + * **Dependencies:** None@n + * **User Interaction:** None@n + * + * **Test Procedure:** + * | Variation / Step | Description | Test Data | Expected Result | Notes | + * | :----: | --------- | ---------- |-------------- | ----- | + * | 01 | Initialize session and input parameters | destinationURL = "https://license.server.com", timeout = 4294967295 | Session object created and input parameters correctly initialized | Should be successful | + * | 02 | Invoke generateKeyRequest API with maximum timeout value | input: destinationURL = "https://license.server.com", timeout = 4294967295; output: drmData pointer | Returns a valid DrmData pointer and updates destinationURL accordingly | Should Pass | + * | 03 | Validate API outputs using assertions | input: drmData pointer, destinationURL; output: EXPECT_NE checks | drmData is not nullptr and destinationURL is not an empty string | Should Pass | + */ +TEST(ClearKeySession, MaximumTimeoutBoundary) +{ + std::cout << "Entering MaximumTimeoutBoundary test" << std::endl; + + std::string destinationURL("https://license.server.com"); + uint32_t timeout = 4294967295; + + ClearKeySession session; + + std::cout << "Invoking generateKeyRequest with destinationURL: " << destinationURL << " and maximum timeout: " << timeout << std::endl; + + DrmData* drmData = session.generateKeyRequest(destinationURL, timeout); + + if (drmData) + { + std::cout << "generateKeyRequest returned a valid DrmData pointer" << std::endl; + std::cout << "Updated destinationURL: " << destinationURL << std::endl; + + const std::string& drmContent = drmData->getData(); + std::cout << "DrmData content retrieved using getData: " << drmContent << std::endl; + } + else + { + std::cout << "generateKeyRequest returned NULL pointer unexpectedly" << std::endl; + } + + EXPECT_NE(drmData, nullptr); + EXPECT_NE(destinationURL, std::string("")); + + std::cout << "Exiting MaximumTimeoutBoundary test" << std::endl; +} +/** + * @brief Verify generateKeyRequest handles improperly formatted destination URL correctly. + * + * This test checks that passing an invalid URL to the generateKeyRequest API returns a NULL pointer, + * ensuring that the function correctly handles improperly formatted destination URL inputs. + * + * **Test Group ID:** Basic: 01@n + * **Test Case ID:** 023@n + * **Priority:** High@n + * + * **Pre-Conditions:** None@n + * **Dependencies:** None@n + * **User Interaction:** None@n + * + * **Test Procedure:** + * | Variation / Step | Description | Test Data | Expected Result | Notes | + * | :----: | ----------- | --------- | ------------- | ----- | + * | 01 | Initialize test parameters and create session instance. | destinationURL = invalid_url, timeout = 1000 | Test parameters set successfully; session instance created. | Should be successful | + * | 02 | Invoke generateKeyRequest API with improperly formatted destination URL. | session instance, destinationURL = invalid_url, timeout = 1000 | API returns a NULL pointer indicating invalid URL handling. | Should Fail | + * | 03 | Validate that the returned pointer is NULL using an assertion. | drmData output from generateKeyRequest = NULL | EXPECT_EQ assertion passes confirming drmData is NULL. | Should be successful | + */ +TEST(ClearKeySession, ImproperDestinationURL) +{ + std::cout << "Entering ImproperDestinationURL test" << std::endl; + + std::string destinationURL("invalid_url"); + uint32_t timeout = 1000; + + ClearKeySession session; + + std::cout << "Invoking generateKeyRequest with improperly formatted destinationURL: " << destinationURL << " and timeout: " << timeout << std::endl; + + DrmData* drmData = session.generateKeyRequest(destinationURL, timeout); + + if (!drmData) + { + std::cout << "generateKeyRequest returned NULL pointer as expected due to invalid URL format" << std::endl; + } + else + { + std::cout << "generateKeyRequest returned a valid pointer unexpectedly" << std::endl; + } + + EXPECT_EQ(drmData, nullptr); + + std::cout << "Exiting ImproperDestinationURL test" << std::endl; +} +/** + * @brief Verifies that ClearKeySession::getState() returns a valid KeyState. + * + * This test invokes the getState() method on a ClearKeySession object and verifies that the returned state is one of the expected KeyState enumeration values (KEY_INIT, KEY_PENDING, KEY_READY, KEY_ERROR, KEY_CLOSED, KEY_ERROR_EMPTY_SESSION_ID). The test ensures that the API provides consistent state information across its lifecycle. + * + * **Test Group ID:** Basic: 01@n + * **Test Case ID:** 024@n + * **Priority:** High@n + * + * **Pre-Conditions:** None@n + * **Dependencies:** None@n + * **User Interaction:** None@n + * + * **Test Procedure:**@n + * | Variation / Step | Description | Test Data | Expected Result | Notes | + * | :--------------: | ------------------------------------------------------------ | ---------------------------------------------------------------- | ------------------------------------------------------------------------------------ | --------------- | + * | 01 | Instantiate a ClearKeySession object. | N/A | ClearKeySession object is created successfully. | Should be successful | + * | 02 | Invoke the getState() method on the ClearKeySession instance. | input: none, output: state = returned value from getState() | API returns a KeyState value that is one of KEY_INIT, KEY_PENDING, KEY_READY, KEY_ERROR, KEY_CLOSED, KEY_ERROR_EMPTY_SESSION_ID. | Should Pass | + * | 03 | Verify the returned state using EXPECT_TRUE assertion. | state value from getState() = valid state condition | The assertion validates that the state is within the expected valid KeyState values. | Should be successful | + */ +TEST(ClearKeySession, ClearKeySession_getState_start) +{ + std::cout << "Entering ClearKeySession::getState()_start test" << std::endl; + + ClearKeySession session; + + std::cout << "Invoking getState() on ClearKeySession object" << std::endl; + KeyState state = session.getState(); + + std::cout << "getState() returned value: " << state << std::endl; + std::cout << "Verifying that the returned state is KEY_INIT" << std::endl; + + bool validState = (state == KEY_INIT) || (state == KEY_PENDING) || + (state == KEY_READY) || (state == KEY_ERROR) || + (state == KEY_CLOSED) || (state == KEY_ERROR_EMPTY_SESSION_ID); + + EXPECT_TRUE(validState); + + std::cout << "Exiting ClearKeySession::getState()_start test" << std::endl; +} +/** + * @brief Tests that processDRMKey correctly processes a valid DRM key with a valid timeout + * + * This test verifies that when a valid DRM key and a valid timeout value are provided to + * processDRMKey, the method successfully processes the key and returns the expected result. + * + * **Test Group ID:** Basic: 01@n + * **Test Case ID:** 025@n + * **Priority:** High@n + * + * **Pre-Conditions:** None@n + * **Dependencies:** None@n + * **User Interaction:** None@n + * + * **Test Procedure:**@n + * | Variation / Step | Description | Test Data | Expected Result | Notes | + * | :----: | --------- | ---------- |-------------- | ----- | + * | 01 | Invoke processDRMKey with valid DRM key data and timeout. | keyData = "ValidKeyData", keyLength = 12, timeout = 1000 | Return value from processDRMKey should be 1, and EXPECT_EQ(result, 1) should pass | Should Pass | + */ +TEST(ClearKeySession, ProcessValidDRMKeyWithValidTimeout) +{ + std::cout << "Entering ProcessValidDRMKeyWithValidTimeout test" << std::endl; + + ClearKeySession session; + + char keyData[20] = {0}; + strncpy(keyData, "ValidKeyData", 12); + + DrmData key(keyData, 12); + std::cout << "Created DrmData with data: " << key.getData() << " and data length: " << key.getDataLength() << std::endl; + + uint32_t timeout = 1000; + std::cout << "Invoking processDRMKey with timeout: " << timeout << std::endl; + int result = session.processDRMKey(&key, timeout); + std::cout << "processDRMKey returned: " << result << std::endl; + + EXPECT_EQ(result, 1); + + std::cout << "Exiting ProcessValidDRMKeyWithValidTimeout test" << std::endl; +} +/** + * @brief Test to validate the behavior of processDRMKey when a null DRM key pointer is provided. + * + * This test verifies that invoking the processDRMKey method with a null DRM key pointer and a valid timeout value does not return the value 1. This ensures that the API properly handles null pointer inputs without erroneously resulting in the value 1. + * + * **Test Group ID:** Basic: 01@n + * **Test Case ID:** 026@n + * **Priority:** High@n + * + * **Pre-Conditions:** None@n + * **Dependencies:** None@n + * **User Interaction:** None@n + * + * **Test Procedure:** + * | Variation / Step | Description | Test Data | Expected Result | Notes | + * | :----: | --------------------------------------------------------------------------------------------- | ------------------------------------------- | ------------------------------------------------------------------- | -------------- | + * | 01 | Invoke processDRMKey with a null key pointer and the given timeout value | input: key = nullptr, timeout = 1000, output: result variable | API returns a value not equal to 1 as validated by the assertion | Should Pass | + */ +TEST(ClearKeySession, ProcessWithNullDRMKeyPointer) +{ + std::cout << "Entering ProcessWithNullDRMKeyPointer test" << std::endl; + + ClearKeySession session; + + uint32_t timeout = 1000; + std::cout << "Invoking processDRMKey with key: nullptr and timeout: " << timeout << std::endl; + int result = session.processDRMKey(nullptr, timeout); + std::cout << "processDRMKey returned: " << result << std::endl; + + EXPECT_NE(result, 1); + + std::cout << "Exiting ProcessWithNullDRMKeyPointer test" << std::endl; +} +/** + * @brief Verify that processing DRM key with empty data does not return the value 1 + * + * This test verifies that ClearKeySession::processDRMKey correctly handles an empty DRM key input by providing an empty data buffer and checks that the API does not return 1. This ensures the function properly handles edge cases with no valid key data. + * + * **Test Group ID:** Basic: 01 + * **Test Case ID:** 027 + * **Priority:** High + * + * **Pre-Conditions:** None + * **Dependencies:** None + * **User Interaction:** None + * + * **Test Procedure:** + * | Variation / Step | Description | Test Data | Expected Result | Notes | + * | :--------------: | ---------------------------------------------------------------------- | ----------------------------------------------------------------- | --------------------------------------------------------------------- | ------------- | + * | 01 | Instantiate a ClearKeySession object | None | ClearKeySession instance created | Should be successful | + * | 02 | Initialize an empty DRM key data buffer | keyData = "", length = 0 | keyData buffer correctly initialized with empty value | Should be successful | + * | 03 | Create a DrmData object with the empty key data | data pointer = keyData, data length = 0 | DrmData instance created with data length 0 | Should be successful | + * | 04 | Set the timeout value for the processDRMKey API call | timeout = 1000 | Timeout value is set to 1000 | Should be successful | + * | 05 | Invoke processDRMKey API using the DrmData object and timeout value | key pointer = address of DrmData (empty), timeout = 1000 | API returns a value that is not equal to 1 | Should Pass | + * | 06 | Validate the result using an assertion | result (output) | Assertion passes when result != 1 | Should Pass | + */ +TEST(ClearKeySession, ProcessDRMKeyWithEmptyData) +{ + std::cout << "Entering ProcessDRMKeyWithEmptyData test" << std::endl; + + ClearKeySession session; + + char keyData[10] = {0}; + strncpy(keyData, "", 0); + + DrmData key(keyData, 0); + std::cout << "Created DrmData with empty data, data length: " << key.getDataLength() << std::endl; + + uint32_t timeout = 1000; + std::cout << "Invoking processDRMKey with empty key data and timeout: " << timeout << std::endl; + int result = session.processDRMKey(&key, timeout); + std::cout << "processDRMKey returned: " << result << std::endl; + + EXPECT_NE(result, 1); + + std::cout << "Exiting ProcessDRMKeyWithEmptyData test" << std::endl; +} +/** + * @brief Test processing of a valid DRM key with a timeout of zero + * + * This test verifies that the ClearKeySession processes a valid DRM key when the timeout value is set to zero. It ensures that the processDRMKey method handles the input correctly and returns a value that is not equal to 1. + * + * **Test Group ID:** Basic: 01@n + * **Test Case ID:** 028@n + * **Priority:** High@n + * + * **Pre-Conditions:** None@n + * **Dependencies:** None@n + * **User Interaction:** None@n + * + * **Test Procedure:** + * | Variation / Step | Description | Test Data | Expected Result | Notes | + * | :----: | --------- | ---------- |-------------- | ----- | + * | 01 | Create an instance of ClearKeySession | session: instance of ClearKeySession | ClearKeySession object created successfully | Should be successful | + * | 02 | Prepare DRM key data and initialize a DrmData object | keyData = "ValidKeyData", data length = 12, DrmData(keyData, 12) | DrmData object is created with correct data and length | Should be successful | + * | 03 | Invoke processDRMKey API with timeout zero | key pointer = &key, timeout = 0 | processDRMKey returns an integer not equal to 1 and assertion passes | Should Pass | + */ +TEST(ClearKeySession, ProcessValidDRMKeyWithTimeoutZero) +{ + std::cout << "Entering ProcessValidDRMKeyWithTimeoutZero test" << std::endl; + + ClearKeySession session; + + char keyData[20] = {0}; + strncpy(keyData, "ValidKeyData", 12); + + DrmData key(keyData, 12); + std::cout << "Created DrmData with data: " << key.getData() << " and data length: " << key.getDataLength() << std::endl; + + uint32_t timeout = 0; + std::cout << "Invoking processDRMKey with timeout: " << timeout << std::endl; + int result = session.processDRMKey(&key, timeout); + std::cout << "processDRMKey returned: " << result << std::endl; + + EXPECT_NE(result, 1); + + std::cout << "Exiting ProcessValidDRMKeyWithTimeoutZero test" << std::endl; +} +/** + * @brief Validate that setKeyId correctly updates the internal state when provided with a valid keyId and correct keyID length. + * + * This test verifies that the ClearKeySession API updates its internal state properly when the keyId is provided along with its correct length, ensuring proper parameter handling and consistency. + * + * **Test Group ID:** Basic: 01@n + * **Test Case ID:** 029@n + * **Priority:** High@n + * + * **Pre-Conditions:** None@n + * **Dependencies:** None@n + * **User Interaction:** None@n + * + * **Test Procedure:** + * | Variation / Step | Description | Test Data | Expected Result | Notes | + * | :--------------: | ------------------------------------------------------------------------------------------- | ----------------------------------------------------- | ----------------------------------------------------------------------------------- | ----------- | + * | 01 | Invoke setKeyId with valid keyId "1234567890abcdef" and keyIDLen 16 to update the session state. | keyId = "1234567890abcdef", keyIDLen = 16 | Internal state updated with keyId "1234567890abcdef" and keyIDLen set to 16; EXPECT_TRUE passes | Should Pass | + */ +TEST(ClearKeySession, ValidKeyIdWithCorrectKeyIDLen) +{ + std::cout<<"Entering ValidKeyIdWithCorrectKeyIDLen test"< +#include +#include +#include +#include "DrmData.h" + + +/** + * @brief Test the default constructor of DrmData for proper object instantiation. + * + * This test verifies that the default constructor for DrmData executes without errors and produces a valid object instance. It ensures that the internal initialization of the DrmData object is correctly performed. + * + * **Test Group ID:** Basic: 01@n + * **Test Case ID:** 001@n + * **Priority:** High@n + * + * **Pre-Conditions:** None@n + * **Dependencies:** None@n + * **User Interaction:** None@n + * + * **Test Procedure:**@n + * | Variation / Step | Description | Test Data | Expected Result | Notes | + * | :----: | --------- | ---------- | -------------- | ----- | + * | 01 | Invoke the default constructor of DrmData | input: none, output: DrmData instance = default | DrmData object constructed successfully using default constructor | Should Pass | + * | 02 | Print message confirming object construction | N/A | Console output: "DrmData object constructed successfully using default constructor" | Should be successful | + */ +TEST(DrmData, DefaultConstructorTest) +{ + std::cout << "Entering DefaultConstructorTest test" << std::endl; + + std::cout << "Invoking DrmData default constructor" << std::endl; + + EXPECT_NO_THROW({ + DrmData drmData; + }); + + std::cout << "DrmData object constructed successfully using default constructor" << std::endl; + + std::cout << "Exiting DefaultConstructorTest test" << std::endl; +} + +/** + * @brief Validate that the copy constructor for DrmData is deleted. + * + * This test verifies that the copy constructor for the DrmData class is deleted by using std::is_copy_constructible. The objective is to ensure that the DrmData objects cannot be copied, which is critical for maintaining proper resource management and preventing unintended copying. + * + * **Test Group ID:** Basic: 01 + * **Test Case ID:** 002 + * **Priority:** High + * + * **Pre-Conditions:** None + * **Dependencies:** None + * **User Interaction:** None + * + * **Test Procedure:** + * | Variation / Step | Description | Test Data | Expected Result | Notes | + * | :--------------: | -------------------------------------------------------------------------- | -------------------------------------------------------------------------- | -------------------------------------------------------------------------------------------- | ---------- | + * | 01 | Check if DrmData is not copy constructible using std::is_copy_constructible | API Call: std::is_copy_constructible::value, Expected Output: false | The API returns false, and EXPECT_FALSE verifies that the copy constructor is deleted. | Should Pass | + */ +TEST(DrmData, CopyConstructorIsDeletedTest) +{ + std::cout << "Entering CopyConstructorIsDeletedTest test" << std::endl; + + bool isCopyConstructible = std::is_copy_constructible::value; + std::cout << "Invoking std::is_copy_constructible: " << std::boolalpha << isCopyConstructible << std::endl; + + EXPECT_FALSE(isCopyConstructible); + + std::cout << "Exiting CopyConstructorIsDeletedTest test" << std::endl; +} + +/** + * @brief Verify that DrmData correctly stores and retrieves a valid DRM data string + * + * This test validates that when a valid DRM data string and its corresponding length are provided to the DrmData constructor, the object correctly initializes its internal state and the getData() method returns the expected string. This ensures proper handling and initialization for valid input scenarios. + * + * **Test Group ID:** Basic: 01@n + * **Test Case ID:** 003@n + * **Priority:** High@n + * + * **Pre-Conditions:** None@n + * **Dependencies:** None@n + * **User Interaction:** None@n + * + * **Test Procedure:** + * | Variation / Step | Description | Test Data | Expected Result | Notes | + * | :----: | ------------------------------------------------------------------------------------- | ---------------------------------------------------------- | ------------------------------------------------------------------------ | ------------- | + * | 01 | Initialize input buffer with "Test DRM Data" and set dataLength to 13 | input = "Test DRM Data", dataLength = 13 | Input buffer is correctly initialized and populated | Should be successful | + * | 02 | Invoke DrmData constructor with the initialized input and dataLength | dataPtr = "Test DRM Data", dataLength = 13 | DrmData instance is created with the correct internal data | Should Pass | + * | 03 | Retrieve internal data using getData() | No additional input | Returned data equals "Test DRM Data" | Should Pass | + * | 04 | Validate that the internal data matches the expected string via ASSERT_EQ | expected = "Test DRM Data", actual = internalData | Assertion succeeds when internal data equals "Test DRM Data" | Should Pass | + */ +TEST(DrmData, PositiveValidString) +{ + std::cout << "Entering PositiveValidString test" << std::endl; + + char input[50]; + std::memset(input, 0, sizeof(input)); + std::strncpy(input, "Test DRM Data", sizeof(input) - 1); + + size_t dataLength = 13; + std::cout << "Invoking DrmData constructor with dataPtr: " << input << " and dataLength: " << dataLength << std::endl; + + DrmData obj(input, dataLength); + + std::string internalData = obj.getData(); + std::cout << "Retrieved internal data from DrmData instance: " << internalData << std::endl; + + ASSERT_EQ(internalData, "Test DRM Data"); + + std::cout << "Exiting PositiveValidString test" << std::endl; +} + +/** + * @brief Test that the DrmData constructor properly handles an empty string input. + * + * This test verifies that when an empty string is passed as input along with a dataLength of 0 to the DrmData constructor, the internal data remains an empty string. This behavior is essential to ensure that the API correctly manages empty inputs without throwing errors or producing unexpected results.@n + * + * **Test Group ID:** Basic: 01@n + * **Test Case ID:** 004@n + * **Priority:** High@n + * + * **Pre-Conditions:** None@n + * **Dependencies:** None@n + * **User Interaction:** None@n + * + * **Test Procedure:**@n + * | Variation / Step | Description | Test Data | Expected Result | Notes | + * | :----: | --------------------------------------------------------------------------- | ----------------------------------------------- | -------------------------------------------------------------------------------------- | ----------------- | + * | 01 | Initialize input buffer with an empty string and set dataLength to 0 | input = "", dataLength = 0 | Input buffer is correctly initialized as an empty string and dataLength is 0 | Should be successful | + * | 02 | Invoke the DrmData constructor with the empty string and dataLength 0 | input = "", dataLength = 0 | DrmData object is created without errors | Should Pass | + * | 03 | Retrieve internal data using getData() method from the DrmData object | internalData (result from getData()) | Retrieved internal data is an empty string | Should Pass | + * | 04 | Validate that the internal data equals an empty string using ASSERT_EQ | internalData = retrieved value, expected = "" | ASSERT_EQ check passes confirming the internal data is empty empty string comparison result | Should Pass | + */ +TEST(DrmData, PositiveEmptyString) +{ + std::cout << "Entering PositiveEmptyString test" << std::endl; + + char input[10]; + std::memset(input, 0, sizeof(input)); + std::strncpy(input, "", sizeof(input) - 1); + + size_t dataLength = 0; + std::cout << "Invoking DrmData constructor with dataPtr: (empty string) and dataLength: " << dataLength << std::endl; + + DrmData obj(input, dataLength); + + std::string internalData = obj.getData(); + std::cout << "Retrieved internal data from DrmData instance: " << internalData << std::endl; + + ASSERT_EQ(internalData, ""); + + std::cout << "Exiting PositiveEmptyString test" << std::endl; +} + +/** + * @brief Test the handling of a null pointer for the DrmData constructor + * + * This test verifies that the DrmData constructor properly handles a NULL pointer for the data input by throwing a standard exception. + * + * **Test Group ID:** Basic: 01@n + * **Test Case ID:** 005@n + * **Priority:** High@n + * + * **Pre-Conditions:** None@n + * **Dependencies:** None@n + * **User Interaction:** None@n + * + * **Test Procedure:**@n + * | Variation / Step | Description | Test Data | Expected Result | Notes | + * | :----: | --------- | ---------- |-------------- | ----- | + * | 01 | Invoke DrmData constructor with a NULL pointer and a valid dataLength | input = NULL, dataLength = 5 | API throws a standard exception as expected | Should Pass | + */ +TEST(DrmData, NegativeNullPointer) +{ + std::cout << "Entering NegativeNullPointer test" << std::endl; + + const char *input = NULL; + size_t dataLength = 5; + std::cout << "Invoking DrmData constructor with dataPtr: NULL and dataLength: " << dataLength << std::endl; + + ASSERT_THROW( + { + DrmData obj(input, dataLength); + }, + std::exception + ); + + std::cout << "Exiting NegativeNullPointer test" << std::endl; +} + +/** + * @brief Verify that DrmData::addData accepts valid non-empty data without throwing an exception + * + * This test checks that when valid non-empty data is provided to the addData method of the DrmData class, the function completes without throwing any exceptions, ensuring proper data handling. + * + * **Test Group ID:** Basic: 01@n + * **Test Case ID:** 006@n + * **Priority:** High@n + * + * **Pre-Conditions:** None@n + * **Dependencies:** None@n + * **User Interaction:** None@n + * + * **Test Procedure:** + * | Variation / Step | Description | Test Data | Expected Result | Notes | + * | :----: | ------------------------------------------------------------- | ---------------------------------------------- | -------------------------------------------------------------------------- | -------------- | + * | 01 | Create DrmData object | drmData object created | Object is initialized properly | Should be successful | + * | 02 | Setup valid non-empty data and its length | testStr = "TestData", length = 8 | Local variables are set as expected | Should be successful | + * | 03 | Print invoking addData message | Not Applicable | Console logs the invoking message | Should be successful | + * | 04 | Invoke addData method and expect no exception | input: testStr = "TestData", dataLength = 8; output: no exception | Method should be executed without throwing any exceptions; assertion passes | Should Pass | + */ +TEST(DrmData, AppendValidNonEmptyData) +{ + std::cout<< "Entering AppendValidNonEmptyData test" << std::endl; + + DrmData drmData; + + const char testStr[] = "TestData"; + size_t length = 8; + + std::cout<< "Invoking addData with dataPtr: " << testStr << " and dataLength: " << length << std::endl; + + EXPECT_NO_THROW( + { + drmData.addData(testStr, length); + } + ); + + std::cout<< "addData invoked successfully with valid non-empty data" << std::endl; + + std::cout<< "Exiting AppendValidNonEmptyData test" << std::endl; +} + +/** + * @brief Test appending a valid pointer with zero length data + * + * This test verifies that the addData function in DrmData handles a valid non-empty pointer when the data length is zero without throwing any exceptions. This ensures that the API is robust for edge cases where the length of data provided is zero. + * + * **Test Group ID:** Basic: 01@n + * **Test Case ID:** 007@n + * **Priority:** High@n + * + * **Pre-Conditions:** None@n + * **Dependencies:** None@n + * **User Interaction:** None@n + * + * **Test Procedure:** + * | Variation / Step | Description | Test Data | Expected Result | Notes | + * | :--------------: | ---------------------------------------------------------------- | ----------------------------------------------- | --------------------------------------------------------------------- | ------------------ | + * | 01 | Instantiate a DrmData object | - | DrmData object is created successfully | Should be successful | + * | 02 | Initialize test variables with a valid non-empty string and zero length | nonEmptyStr = "Non-empty", length = 0 | Test data variables are initialized correctly | Should be successful | + * | 03 | Invoke addData API with the valid pointer and zero length | dataPtr = "Non-empty", dataLength = 0 | addData is executed without throwing an exception as verified by EXPECT_NO_THROW | Should Pass | + */ +TEST(DrmData, AppendValidPointerWithZeroLength) +{ + std::cout<< "Entering AppendValidPointerWithZeroLength test" << std::endl; + + DrmData drmData; + + const char nonEmptyStr[] = "Non-empty"; + size_t length = 0; + + std::cout<< "Invoking addData with dataPtr: " << nonEmptyStr << " and dataLength: " << length << std::endl; + + EXPECT_NO_THROW( + { + drmData.addData(nonEmptyStr, length); + } + ); + std::cout<< "addData invoked successfully with zero length data" << std::endl; + + std::cout<< "Exiting AppendValidPointerWithZeroLength test" << std::endl; +} + +/** + * @brief Verify that addData handles an empty data input with a valid pointer without throwing exceptions + * + * This test ensures that when an empty string along with a zero data length is passed to the addData API, + * it processes the input gracefully without throwing any exceptions. This verifies robustness of addData in handling edge cases. + * + * **Test Group ID:** Basic: 01 + * **Test Case ID:** 008 + * **Priority:** High + * + * **Pre-Conditions:** None + * **Dependencies:** None + * **User Interaction:** None + * + * **Test Procedure:** + * | Variation / Step | Description | Test Data | Expected Result | Notes | + * | :---------------:| --------------------------------------------------------- | -------------------------------------------------- | ---------------------------------------------------------------- | -------------------- | + * | 01 | Instantiate the DrmData object | None | DrmData object is successfully created | Should be successful | + * | 02 | Initialize an empty string and set data length to zero | emptyStr = "", length = 0 | emptyStr is an empty string and length is correctly set to 0 | Should be successful | + * | 03 | Invoke addData with the empty string pointer and zero length | input: emptyStr = "", input: length = 0 | The addData function call does not throw an exception | Should Pass | + * | 04 | Log the entry, invocation, and exit of the test | Log messages as per test flow | Log messages are printed indicating the progress of the test | Should be successful | + */ +TEST(DrmData, AppendEmptyDataWithValidPointer) +{ + std::cout<< "Entering AppendEmptyDataWithValidPointer test" << std::endl; + + DrmData drmData; + + char emptyStr[1]; + strncpy(emptyStr, "", sizeof(emptyStr)); + size_t length = 0; + + std::cout<< "Invoking addData with an empty string pointer and dataLength: " << length << std::endl; + + EXPECT_NO_THROW( + { + drmData.addData(emptyStr, length); + } + ); + std::cout<< "addData invoked successfully with empty data" << std::endl; + + std::cout<< "Exiting AppendEmptyDataWithValidPointer test" << std::endl; +} + +/** + * @brief Validate that addData handles null pointer with zero length without throwing exceptions + * + * This test verifies that invoking drmData.addData with a nullptr and a zero length does not cause any exceptions. + * It ensures the robustness of the addData API when handling edge-case inputs. + * + * **Test Group ID:** Basic: 01@n + * **Test Case ID:** 009@n + * **Priority:** High@n + * + * **Pre-Conditions:** None@n + * **Dependencies:** None@n + * **User Interaction:** None@n + * + * **Test Procedure:** + * | Variation / Step | Description | Test Data | Expected Result | Notes | + * | :--------------: | ------------------------------------------------------------------------------------ | ---------------------------------------------- | ------------------------------------------------------------------------ | --------------- | + * | 01 | Create a DrmData instance and initialize input parameters with nullptr and length 0 | dataPtr = nullptr, dataLength = 0 | DrmData instance created and inputs initialized correctly | Should be successful | + * | 02 | Invoke drmData.addData with nullptr and zero length, and assert that no exception is thrown | dataPtr = nullptr, dataLength = 0 | API call executes without throwing an exception | Should Pass | + */ +TEST(DrmData, AppendNullPointerWithZeroLength) +{ + std::cout<< "Entering AppendNullPointerWithZeroLength test" << std::endl; + + DrmData drmData; + + const char *nullPtr = nullptr; + size_t length = 0; + + std::cout<< "Invoking addData with dataPtr: nullptr and dataLength: " << length << std::endl; + + EXPECT_NO_THROW( + { + drmData.addData(nullPtr, length); + } + ); + + std::cout<< "addData invoked successfully with null pointer and zero length" << std::endl; + + std::cout<< "Exiting AppendNullPointerWithZeroLength test" << std::endl; +} + +/** + * @brief Test the default constructor of DrmData to ensure it returns a non-empty string + * + * This test validates that creating an instance of DrmData using its default constructor results in a non-empty string being returned when invoking the getData method. The test confirms that the default state of the object is properly initialized with valid data. + * + * **Test Group ID:** Basic: 01@n + * **Test Case ID:** 010@n + * **Priority:** High@n + * + * **Pre-Conditions:** None@n + * **Dependencies:** None@n + * **User Interaction:** None@n + * + * **Test Procedure:**@n + * | Variation / Step | Description | Test Data | Expected Result | Notes |@n + * | :----: | --------- | ---------- |-------------- | ----- |@n + * | 01 | Create an instance of DrmData using the default constructor. | No input, output: instance created | Instance of DrmData is successfully created. | Should Pass |@n + * | 02 | Invoke the getData method on the DrmData instance. | Instance: drmData, Method: getData, output: dataValue | getData returns a non-empty string. | Should Pass |@n + * | 03 | Verify that the string returned by getData is not empty using an assertion. | dataValue = result of getData | Assertion passes confirming the string is not empty. | Should Pass | + */ +TEST(DrmData, DefaultConstructorReturnsEmptyString) +{ + std::cout << "Entering DefaultConstructorReturnsEmptyString test" << std::endl; + + std::cout << "Creating instance of DrmData using default constructor" << std::endl; + DrmData drmData; + + std::cout << "Invoking getData method" << std::endl; + const std::string &dataValue = drmData.getData(); + + std::cout << "Value returned from getData: " << dataValue << std::endl; + + ASSERT_FALSE(dataValue.empty()); + + std::cout << "Exiting DefaultConstructorReturnsEmptyString test" << std::endl; +} + +/** + * @brief Test to validate that a default constructed DrmData object's getDataLength returns a non-negative value. + * + * This test instantiates a DrmData object using the default constructor and verifies that calling getDataLength returns a value >= 0. This ensures that the default state of the object has a valid data length. + * + * **Test Group ID:** Basic: 01 + * **Test Case ID:** 011 + * **Priority:** High + * + * **Pre-Conditions:** None + * **Dependencies:** None + * **User Interaction:** None + * + * **Test Procedure:** + * | Variation / Step | Description | Test Data | Expected Result | Notes | + * | :--------------: | ------------------------------------------------------------------- | -------------------------------------------------------------- | ---------------------------------------------------------------------- | ----------------- | + * | 01 | Instantiate DrmData object using default constructor | drmObj = default constructed object | DrmData object is created successfully | Should be successful | + * | 02 | Invoke getDataLength() on the default constructed DrmData object | input: None, output: length = returned value from getDataLength | getDataLength returns a value >= 0 and EXPECT_GE assertion passes | Should Pass | + */ +TEST(DrmData, DefaultConstructed_getDataLength) +{ + std::cout << "Entering DefaultConstructed_getDataLength test" << std::endl; + + DrmData drmObj; + std::cout << "Created DrmData object using default constructor" << std::endl; + + size_t length = drmObj.getDataLength(); + std::cout << "Invoked getDataLength, returned value: " << length << std::endl; + + EXPECT_GE(length, 0); + std::cout << "Verified that getDataLength returned a value >= 0" << std::endl; + + std::cout << "Exiting DefaultConstructed_getDataLength test" << std::endl; +} + +/** + * @brief Validate that the copy assignment operator for DrmData is deleted + * + * This test verifies that the copy assignment operator of the DrmData class is deleted by using the std::is_copy_assignable trait. The objective is to ensure that no accidental copying by assignment can occur which might lead to unintended behavior. + * + * **Test Group ID:** Basic: 01@n + * **Test Case ID:** 012@n + * **Priority:** High@n + * + * **Pre-Conditions:** None@n + * **Dependencies:** None@n + * **User Interaction:** None@n + * + * **Test Procedure:** + * | Variation / Step | Description | Test Data | Expected Result | Notes | + * | :----: | --------- | ---------- |-------------- | ----- | + * | 01 | Invoke std::is_copy_assignable for DrmData to check if the copy assignment operator is deleted | input: DrmData, output: isAssignable = (expected false) | isAssignable should be false as verified by EXPECT_FALSE | Should Pass | + */ +TEST(DrmData, OperatorAssignmentDeletionCheck) +{ + std::cout << "Entering OperatorAssignmentDeletionCheck test" << std::endl; + + std::cout << "Invoking std::is_copy_assignable for DrmData" << std::endl; + + bool isAssignable = std::is_copy_assignable::value; + std::cout << "Result - isCopyAssignable: " << isAssignable << std::endl; + + EXPECT_FALSE(isAssignable); + + std::cout << "Exiting OperatorAssignmentDeletionCheck test" << std::endl; +} + +/** + * @brief Verify that DrmData::setData accepts a valid non-empty string without throwing exceptions + * + * This test verifies that the API DrmData::setData correctly handles a non-empty string input by properly processing the provided string and ensuring that no exceptions are thrown. It simulates a typical positive scenario where the module is expected to function normally with valid input. + * + * **Test Group ID:** Basic: 01@n + * **Test Case ID:** 013@n + * **Priority:** High@n + * + * **Pre-Conditions:** None@n + * **Dependencies:** None@n + * **User Interaction:** None@n + * + * **Test Procedure:**@n + * | Variation / Step | Description | Test Data | Expected Result | Notes | + * | :----: | --------- | ---------- |-------------- | ----- | + * | 01 | Create a valid non-empty input string and ensure proper null termination | inputData = "Test Data", length = 9 | Input string is correctly constructed and null terminated | Should be successful | + * | 02 | Invoke setData API with the valid input string and specified length | inputData = "Test Data", length = 9 | API call does not throw an exception and data is set in DrmData object | Should Pass | + */ +TEST(DrmData, PositiveValidNonEmptyStringData) +{ + std::cout << "Entering PositiveValidNonEmptyStringData test" << std::endl; + + DrmData drmData; + + char inputData[20]; + strncpy(inputData, "Test Data", 9); + inputData[9] = '\0'; + std::cout << "Created inputData with value: " << inputData << " and length: " << 9 << std::endl; + + std::cout << "Invoking setData with inputData pointer and length 9" << std::endl; + + EXPECT_NO_THROW( + { + drmData.setData(inputData, 9); + } + ); + + std::cout << "Exiting PositiveValidNonEmptyStringData test" << std::endl; +} + +/** + * @brief Verify that the setData API handles a valid pointer with a zero length gracefully. + * + * This test case is designed to ensure that when a valid non-null pointer is provided along with a zero length, + * the DrmData::setData function does not throw any exceptions. This helps to confirm that the API correctly handles + * cases where the input pointer is non-empty but the length is set to zero. + * + * **Test Group ID:** Basic: 01 + * **Test Case ID:** 014 + * **Priority:** High + * + * **Pre-Conditions:** None + * **Dependencies:** None + * **User Interaction:** None + * + * **Test Procedure:** + * | Variation / Step | Description | Test Data | Expected Result | Notes | + * | :--------------: | ---------------------------------------------------------------------- | ------------------------------------- | ------------------------------------------------ | ----------- | + * | 01 | Invoke DrmData::setData with a valid non-empty pointer and zero length. | inputData = Non-empty, length = 0 | API executes without throwing any exceptions. | Should Pass | + */ +TEST(DrmData, PositiveValidPointerZeroLength) +{ + std::cout << "Entering PositiveValidPointerZeroLength test" << std::endl; + + DrmData drmData; + + const char * inputData = "Non-empty"; + std::cout << "Input pointer provided with value: " << inputData << " but length set to 0" << std::endl; + + std::cout << "Invoking setData with inputData pointer and length 0" << std::endl; + + EXPECT_NO_THROW( + { + drmData.setData(inputData, 0); + } + ); + + std::cout << "Exiting PositiveValidPointerZeroLength test" << std::endl; +} + +/** + * @brief Verify DrmData::setData handles empty input string gracefully. + * + * This test verifies that when an empty string (with length 0) is provided to DrmData::setData, the function does not throw any exception. It ensures that the API correctly processes edge-case inputs without runtime errors. + * + * **Test Group ID:** Basic: 01 + * **Test Case ID:** 015 + * **Priority:** High + * + * **Pre-Conditions:** None + * **Dependencies:** None + * **User Interaction:** None + * + * **Test Procedure:** + * | Variation / Step | Description | Test Data | Expected Result | Notes | + * | :----: | ----------------------------------------------------------------------- | ------------------------------------------------------ | ------------------------------------------------------------ | ----------------- | + * | 01 | Initialize test environment with an empty string input for DrmData::setData | inputData = "", length = 0, drmData object created | Test environment setup without error | Should be successful | + * | 02 | Invoke DrmData::setData with empty string and validate no exception is thrown using EXPECT_NO_THROW | API call: inputData = "", length = 0 | API call should complete successfully without throwing any exception | Should Pass | + */ +TEST(DrmData, PositiveEmptyStringData) +{ + std::cout << "Entering PositiveEmptyStringData test" << std::endl; + + DrmData drmData; + + char inputData[10]; + strncpy(inputData, "", 0); + inputData[0] = '\0'; + std::cout << "Created inputData with empty value and length 0" << std::endl; + + std::cout << "Invoking setData with empty inputData pointer and length 0" << std::endl; + + EXPECT_NO_THROW( + { + drmData.setData(inputData, 0); + } + ); + + std::cout << "Exiting PositiveEmptyStringData test" << std::endl; +} + +/** + * @brief Verify that setData throws an exception when provided a null pointer with a non-zero length. + * + * This test ensures that the API setData correctly handles the invalid input scenario where a null pointer is passed with a non-zero length. + * It verifies that the function throws an exception, thereby ensuring robust error handling for invalid parameter inputs. + * + * **Test Group ID:** Basic: 01 + * **Test Case ID:** 016 + * **Priority:** High + * + * **Pre-Conditions:** None @n + * **Dependencies:** None @n + * **User Interaction:** None @n + * + * **Test Procedure:** @n + * | Variation / Step | Description | Test Data | Expected Result | Notes | + * | :--------------: | ----------------------------------------------------------------------------------------- | ---------------------------------- | ---------------------------------------------------------------- | ----------- | + * | 01 | Invoke setData with a null pointer and a non-zero length to check if an exception is thrown | data = nullptr, length = 5 | An exception is thrown as verified by EXPECT_ANY_THROW | Should Fail | + */ +TEST(DrmData, NegativeNullPointerNonZeroLength) +{ + std::cout << "Entering NegativeNullPointerNonZeroLength test" << std::endl; + + DrmData drmData; + std::cout << "Invoking setData with nullptr and non-zero length 5" << std::endl; + + EXPECT_ANY_THROW + ( + drmData.setData(nullptr, 5) + ); + + std::cout << "Exiting NegativeNullPointerNonZeroLength test" << std::endl; +} + +/** + * @brief Verify that the default constructor and destructor of DrmData execute without exceptions. + * + * This test ensures that the DrmData class can be instantiated using its default constructor + * and that the object is destructed cleanly when it goes out of scope. + * It verifies that no runtime issues occur during object creation and destruction. + * + * **Test Group ID:** Basic: 01 @n + * **Test Case ID:** 017 @n + * **Priority:** High @n + * + * **Pre-Conditions:** None @n + * **Dependencies:** None @n + * **User Interaction:** None @n + * + * **Test Procedure:** @n + * | Variation / Step | Description | Test Data | Expected Result | Notes | + * | :--------------: | -------------------------------------------------------------- | ------------------- | ------------------------------------------- | ------------- | + * | 01 | Instantiate DrmData using the default constructor | None | Object is created without throwing exception | Should Pass | + * | 02 | Allow the object to go out of scope to trigger the destructor | None | Object is destructed cleanly | Should Pass | + */ +TEST(DrmData, Destruction_DefaultConstructor) +{ + std::cout << "Entering Destruction_DefaultConstructor test" << std::endl; + + { + std::cout << "Invoking default constructor of DrmData" << std::endl; + + EXPECT_NO_THROW({ + DrmData drmData; + }); + + std::cout << "DrmData object created using default constructor" << std::endl; + } + + std::cout << "DrmData object goes out of scope and destructor is invoked" << std::endl; + + std::cout << "Exiting Destruction_DefaultConstructor test" << std::endl; +} + +int main(int argc, char **argv) { + ::testing::InitGoogleTest(&argc, argv); + return RUN_ALL_TESTS(); +} From 5b30310940ddf23ab4ef87b8402fad4f2ae06eb3 Mon Sep 17 00:00:00 2001 From: Mark Buser Date: Thu, 10 Jul 2025 13:09:33 -0400 Subject: [PATCH 5/9] RDKEMW-5974 Build Player Integration Interface on MacOS Reason for change: Correct install-middleware.sh errors on MacOS Test Procedure: Run install-middleware.sh on Ubuntu and MacOS, should build sucessfully. Risks: Low Priority: P2 --- CMakeLists.txt | 14 +++++++++++++- scripts/install_dependencies.sh | 6 +++--- scripts/install_options.sh | 2 +- scripts/install_subtec.sh | 7 +++++++ 4 files changed, 24 insertions(+), 5 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 7902671..7336d55 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -3,6 +3,9 @@ cmake_minimum_required(VERSION 3.5) project(Playergstinterface) + +set(CMAKE_CXX_STANDARD 14) + find_package(PkgConfig REQUIRED) pkg_check_modules(GST REQUIRED gstreamer-plugins-base-1.0) pkg_check_modules(GSTREAMER REQUIRED gstreamer-1.0) @@ -72,15 +75,24 @@ if(CMAKE_SYSTEM_NAME STREQUAL Darwin) execute_process ( COMMAND bash -c "xcrun --show-sdk-path" OUTPUT_VARIABLE osxSdkPath OUTPUT_STRIP_TRAILING_WHITESPACE ) - set(OS_CXX_FLAGS "${OS_CXX_FLAGS} -std=c++14 -g -x objective-c++ -Wno-inconsistent-missing-override -F${osxSdkPath}/System/Library/Frameworks") + set(OS_CXX_FLAGS "${OS_CXX_FLAGS} -g -x objective-c++ -Wno-inconsistent-missing-override -F${osxSdkPath}/System/Library/Frameworks") set(OS_LD_FLAGS "${OS_LD_FLAGS} -F${osxSdkPath}/System/Library/Frameworks -framework Cocoa -L${osxSdkPath}/../MacOSX.sdk/usr/lib -L.libs/lib -L/usr/local/lib/") set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -isysroot ${osxSdkPath}/../MacOSX.sdk -I/usr/local/include") string(STRIP ${OS_LD_FLAGS} OS_LD_FLAGS) + pkg_check_modules(OPENSSL REQUIRED openssl) + set(LIBPLAYERGSTINTERFACE_DEPENDS ${LIBPLAYERGSTINTERFACE_DEPENDS} "${OPENSSL_LINK_LIBRARIES}") link_directories(${OPENSSL_LIBRARY_DIRS}) + link_directories(${GSTREAMER_LIBRARY_DIRS}) set(CMAKE_THREAD_LIBS_INIT "-lpthread") set(CMAKE_HAVE_THREADS_LIBRARY 1) pkg_check_modules(GLIB REQUIRED GLib-2.0) include_directories(${GLIB_INCLUDE_DIRS}) + pkg_check_modules(LIBCJSON REQUIRED libcjson) + include_directories(${LIBCJSON_INCLUDE_DIRS}) + set(LIBPLAYERGSTINTERFACE_DEPENDS ${LIBPLAYERGSTINTERFACE_DEPENDS} "${LIBCJSON_LINK_LIBRARIES}") + # This is .libs/lib/pkgconfig which picks up all locally built dependencies + link_directories(${LIBCJSON_LIBRARY_DIRS}) + #link_directories(".libs/lib") # XCode build flags. Even when using CLANG, the GCC name is required to enable the check set(CMAKE_XCODE_ATTRIBUTE_GCC_WARN_UNUSED_FUNCTION "YES") diff --git a/scripts/install_dependencies.sh b/scripts/install_dependencies.sh index d4c6ceb..937856b 100644 --- a/scripts/install_dependencies.sh +++ b/scripts/install_dependencies.sh @@ -18,7 +18,7 @@ # limitations under the License. # -declare DEFAULT_OPENSSL_VERSION="openssl@3.4" +declare DEFAULT_OPENSSL_VERSION="openssl@3.5" function install_pkgs_pkgconfig_darwin_fn() { @@ -198,8 +198,8 @@ function install_pkgs_fn() brew update fi - install_pkgs_darwin_fn git json-glib cmake "openssl@3.4" libxml2 ossp-uuid cjson gnu-sed jpeg-turbo taglib speex mpg123 meson ninja pkg-config flac asio jsoncpp lcov gcovr jq curl - install_pkgs_darwin_fn coreutils websocketpp "boost@1.85" jansson libxkbcommon cppunit gnu-sed fontconfig doxygen graphviz tinyxml2 openldap krb5 + install_pkgs_darwin_fn git json-glib cmake ${DEFAULT_OPENSSL_VERSION} libxml2 ossp-uuid cjson gnu-sed jpeg-turbo taglib speex mpg123 meson ninja pkg-config flac asio jsoncpp lcov gcovr jq curl + install_pkgs_darwin_fn coreutils websocketpp "boost@1.85" jansson libxkbcommon cppunit gnu-sed fontconfig doxygen graphviz tinyxml2 openldap krb5 wavpack gettext # ORC causes compile errors on x86_64 Mac, but not on ARM64 if [[ $ARCH == "x86_64" ]]; then diff --git a/scripts/install_options.sh b/scripts/install_options.sh index 59f0737..a69c3c6 100755 --- a/scripts/install_options.sh +++ b/scripts/install_options.sh @@ -1,7 +1,7 @@ #!/usr/bin/env bash # default values -OPTION_PLAYER_BRANCH="dev_sprint_25_1" +OPTION_PLAYER_BRANCH="develop" OPTION_BUILD_DIR="" OPTION_BUILD_ARGS="" OPTION_CLEAN=false diff --git a/scripts/install_subtec.sh b/scripts/install_subtec.sh index 963ec9b..c168f78 100755 --- a/scripts/install_subtec.sh +++ b/scripts/install_subtec.sh @@ -43,6 +43,13 @@ function subtec_install_fn() { sed -i ${SED_ARG} 's:COMMAND gdbus-codegen --interface-prefix com.libertyglobal.rdk --generate-c-code TeletextDbusInterface ${CMAKE_CURRENT_SOURCE_DIR}/api/dbus/TeletextDbusInterface.xml:COMMAND '"${2}"'/glib/build/gio/gdbus-2.0/codegen/gdbus-codegen --interface-prefix com.libertyglobal.rdk --generate-c-code TeletextDbusInterface ${CMAKE_CURRENT_SOURCE_DIR}/api/dbus/TeletextDbusInterface.xml:g' subttxrend-dbus/CMakeLists.txt + echo "Update asio::service to asio::context" + sed -i ${SED_ARG} 's/asio::io_service/asio::io_context/g' websocket-ipplayer2-utils/src/ipp2/servers/SimpleWebServer.cpp + sed -i ${SED_ARG} 's/asio::ip::address::from_string/asio::ip::make_address/g' websocket-ipplayer2-utils/src/ipp2/servers/SimpleWebServer.cpp + sed -i ${SED_ARG} 's/\([a-zA-Z0-9_]*\)->reset()/\1->restart()/g' websocket-ipplayer2-utils/src/ipp2/servers/SimpleWebServer.cpp + sed -i ${SED_ARG} 's/\([a-zA-Z0-9_]*\)->post(/asio::post(*\1, /g' websocket-ipplayer2-utils/src/ipp2/servers/SimpleWebServer.cpp + + echo "subtec-app source prepared" popd } From e2b3ec0a7968ee240e9257105ea87177ad23b1ee Mon Sep 17 00:00:00 2001 From: "Radhakrishnan, Tarunikaa" Date: Wed, 16 Jul 2025 11:04:16 +0000 Subject: [PATCH 6/9] Push unit tests for 3headers Signed-off-by: Radhakrishnan, Tarunikaa --- drm/test/test_l1_DrmJsonObject.cpp | 4713 +++++++++++++++++ drm/test/test_l1_HlsDrmSessionManager.cpp | 201 + ...st_l1_PlayerHlsDrmSessionInterfaceBase.cpp | 259 + 3 files changed, 5173 insertions(+) create mode 100644 drm/test/test_l1_DrmJsonObject.cpp create mode 100644 drm/test/test_l1_HlsDrmSessionManager.cpp create mode 100644 drm/test/test_l1_PlayerHlsDrmSessionInterfaceBase.cpp diff --git a/drm/test/test_l1_DrmJsonObject.cpp b/drm/test/test_l1_DrmJsonObject.cpp new file mode 100644 index 0000000..fcd414c --- /dev/null +++ b/drm/test/test_l1_DrmJsonObject.cpp @@ -0,0 +1,4713 @@ + +/* + * If not stated otherwise in this file or this component's LICENSE file the + * following copyright and licenses apply: + * + * Copyright 2025 RDK Management + * + * 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. + */ + +/** +* @file test_l1_DrmJsonObject.cpp +* @page DrmJsonObject Level 1 Tests +* +* ## Module's Role +* This module includes Level 1 functional tests (success and failure scenarios). +* This is to ensure that the DrmJsonObject methods meet the requirements. +* +* **Pre-Conditions:** None @n +* **Dependencies:** None @n +* +*/ + +#include +#include +#include +#include "DrmJsonObject.h" + + +// Test case for the default constructor of DrmJsonObject. +/** + * @brief Validate that DrmJsonObject's default constructor functions correctly + * + * This test verifies that invoking the default constructor of the DrmJsonObject class does not throw any exceptions and successfully creates an instance. The objective is to ensure that basic object instantiation works as expected, providing a stable basis for further functionality tests. + * + * **Test Group ID:** Basic: 01 + * **Test Case ID:** 001 + * **Priority:** High + * + * **Pre-Conditions:** None + * **Dependencies:** None + * **User Interaction:** None + * + * **Test Procedure:** + * | Variation / Step | Description | Test Data | Expected Result | Notes | + * | :--------------: | ---------------------------------------------------------------- | ---------------------------------------------- | ---------------------------------------------------------------------------------- | ---------- | + * | 01 | Invoke the default constructor of DrmJsonObject. | No input parameters, output: valid instance | DrmJsonObject instance is created without throwing exceptions. | Should Pass | + */ +TEST(DrmJsonObject, DrmJsonObject_DefaultConstructor) { + std::cout << "Entering DrmJsonObject::DrmJsonObject()_start test" << std::endl; + std::cout << "Invoking DrmJsonObject default constructor with no input parameters." << std::endl; + + // Create an object using the default constructor. + EXPECT_NO_THROW( + { + DrmJsonObject drmJsonObj; + } + ); + std::cout << "DrmJsonObject default constructor invoked. DrmJsonObject instance created successfully." << std::endl; + + std::cout << "Exiting DrmJsonObject::DrmJsonObject()_start test" << std::endl; +} +/** + * @brief Verifies that the move constructor correctly transfers JSON data from a non-empty source object. + * + * This test ensures that after invoking the move constructor on a valid DrmJsonObject initialized with non-empty JSON data, + * the new (moved) object retains the expected JSON content, and the source object becomes empty. + * This behavior confirms the proper implementation of move semantics for the DrmJsonObject class. + * + * **Test Group ID:** Basic: 01@n + * **Test Case ID:** 002@n + * **Priority:** High@n + * + * **Pre-Conditions:** None@n + * **Dependencies:** None@n + * **User Interaction:** None@n + * + * **Test Procedure:** + * | Variation / Step | Description | Test Data | Expected Result | Notes | + * | :--------------: | ------------------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------- | ----------------------------------------------------------------------------------------------------- | ----------- | + * | 01 | Create a valid JSON string and instantiate a source DrmJsonObject using the custom constructor. | validJson = {"key":"value"} | Source object is initialized with the valid JSON data. | Should Pass | + * | 02 | Call the print() function on the source object to fetch its JSON content before moving. | API: print() on source, returns sourceJsonBefore | The source object's JSON content matches the initialized JSON string. | Should Pass | + * | 03 | Invoke the move constructor using std::move() to create a new DrmJsonObject from the source. | API: move constructor, input: std::move(source) | A new object (moved) is created with the JSON data; the source object is left in a valid but unspecified state. | Should Pass | + * | 04 | Retrieve the JSON content from the moved object by calling print() to validate the move operation. | API: print() on moved, returns movedJson | The moved object's JSON string contains "\"key\":\"value\"" as a substring. | Should Pass | + * | 05 | Retrieve the JSON content from the source object after the move operation to confirm it's empty. | API: print() on source after move, returns sourceJsonAfter | The source object's JSON string is empty. | Should Pass | + */ +TEST(DrmJsonObject, MoveConstructorValidNonEmpty) { + std::cout << "Entering MoveConstructorValidNonEmpty test" << std::endl; + + // Create a valid JSON string and instantiate source object using the custom constructor. + std::string validJson = "{\"key\":\"value\"}"; + std::cout << "Invoking DrmJsonObject constructor with valid JSON string: " << validJson << std::endl; + DrmJsonObject source(validJson); + + // Call print() to fetch JSON content from source before moving. + std::string sourceJsonBefore = source.print(); + std::cout << "Source object JSON before move: " << sourceJsonBefore << std::endl; + + // Invoke move constructor using std::move(source) + std::cout << "Invoking move constructor: DrmJsonObject moved(std::move(source))" << std::endl; + DrmJsonObject moved(std::move(source)); + + // Retrieve JSON content from the moved object. + std::string movedJson = moved.print(); + std::cout << "Moved object JSON after move: " << movedJson << std::endl; + + // Check that the moved object contains the expected JSON data. + EXPECT_NE(movedJson.find("\"key\":\"value\""), std::string::npos); + + // Retrieve and print the state of source after move. + std::string sourceJsonAfter = source.print(); + std::cout << "Source object JSON after move (expected to be empty): " << sourceJsonAfter << std::endl; + EXPECT_TRUE(sourceJsonAfter.empty()); + + std::cout << "Exiting MoveConstructorValidNonEmpty test" << std::endl; +} +/** + * @brief Verify that the move constructor correctly handles an empty DrmJsonObject. + * + * This test verifies that when a DrmJsonObject is created using the default constructor (resulting in an empty object) + * and then move constructed, both the moved object and the original source object remain empty. This ensures that the + * move semantics are correctly implemented even for an already empty object. + * + * **Test Group ID:** Basic: 01@n + * **Test Case ID:** 003@n + * **Priority:** High@n + * + * **Pre-Conditions:** None@n + * **Dependencies:** None@n + * **User Interaction:** None@n + * + * **Test Procedure:**@n + * | Variation / Step | Description | Test Data | Expected Result | Notes | + * | :--------------: | ------------------------------------------------------------------------------------------------ | ------------------------------------------------------------------- | -------------------------------------------------------- | ------------- | + * | 01 | Invoke the default constructor to create an empty DrmJsonObject. | output: source = DrmJsonObject(empty) | source object is instantiated as empty | Should Pass | + * | 02 | Retrieve JSON content from the source object using print() method before move operation. | input: source.print() = ? | Expected to return an empty string | Should Pass | + * | 03 | Invoke the move constructor to create a new DrmJsonObject by moving the source object. | input: source = std::move(source), output: moved = DrmJsonObject(moved)| Moved object's JSON content should be empty | Should Pass | + * | 04 | Retrieve JSON content from both the moved object and the source object after the move operation. | input: moved.print() = ?, source.print() = ? | Both moved object and source object should return empty | Should Pass | + */ +TEST(DrmJsonObject, MoveConstructorEmpty) { + std::cout << "Entering MoveConstructorEmpty test" << std::endl; + + // Create an empty DrmJsonObject using the default constructor. + std::cout << "Invoking default constructor to create an empty DrmJsonObject" << std::endl; + DrmJsonObject source; + + // Retrieve JSON content from the source object before move. + std::string sourceJsonBefore = source.print(); + std::cout << "Source object JSON before move (expected empty): " << sourceJsonBefore << std::endl; + + // Invoke move constructor using std::move(source) + std::cout << "Invoking move constructor on empty object: DrmJsonObject moved(std::move(source))" << std::endl; + DrmJsonObject moved(std::move(source)); + + // Retrieve JSON content from the moved object. + std::string movedJson = moved.print(); + std::cout << "Moved object JSON after move (expected empty): " << movedJson << std::endl; + EXPECT_TRUE(movedJson.empty()); + + // Retrieve and print the state of source after move. + std::string sourceJsonAfter = source.print(); + std::cout << "Source object JSON after move (expected empty): " << sourceJsonAfter << std::endl; + EXPECT_TRUE(sourceJsonAfter.empty()); + + std::cout << "Exiting MoveConstructorEmpty test" << std::endl; +} +/** + * @brief Verify that creating a DrmJsonObject with a valid simple JSON does not throw any exceptions. + * + * This test validates that the DrmJsonObject constructor correctly handles a well-formed JSON string by not throwing any exceptions. The test confirms that the simple JSON input provided is processed without errors, ensuring the proper functionality of the constructor in a positive scenario. + * + * **Test Group ID:** Basic: 01@n + * **Test Case ID:** 004@n + * **Priority:** High@n + * + * **Pre-Conditions:** None@n + * **Dependencies:** None@n + * **User Interaction:** None@n + * + * **Test Procedure:**@n + * | Variation / Step | Description | Test Data | Expected Result | Notes | + * | :----: | --------- | ---------- |-------------- | ----- | + * | 01 | Invoke the DrmJsonObject constructor with a valid JSON string to verify it processes the input correctly without throwing exceptions. | inputJson = "{\"key\": \"value\"}" | API returns a valid object and does not throw any exception; EXPECT_NO_THROW assertion passes. | Should Pass | + */ +TEST(DrmJsonObject, Construct_ValidSimpleJson) { + std::cout << "Entering Construct_ValidSimpleJson test" << std::endl; + + const char inputJson[] = "{\"key\": \"value\"}"; + std::cout << "Invoking DrmJsonObject constructor with JSON input: " << inputJson << std::endl; + EXPECT_NO_THROW( + { + DrmJsonObject obj(inputJson); + } + ); + + std::cout << "Exiting Construct_ValidSimpleJson test" << std::endl; +} +/** + * @brief Validate that DrmJsonObject correctly constructs an object from valid nested JSON input. + * + * This test validates that the DrmJsonObject constructor processes a nested JSON input containing both an inner JSON object and an array, ensuring that the object is constructed without throwing exceptions. + * + * **Test Group ID:** Basic: 01@n + * **Test Case ID:** 005@n + * **Priority:** High@n + * + * **Pre-Conditions:** None@n + * **Dependencies:** None@n + * **User Interaction:** None@n + * + * **Test Procedure:**@n + * | Variation / Step | Description | Test Data | Expected Result | Notes | + * | :----: | --------- | ---------- |-------------- | ----- | + * | 01 | Define valid nested JSON string input. | inputJson = "{\"outerKey\": {\"innerKey1\": \"innerValue1\", \"innerArr\": [1, 2, 3]}}" | JSON string is defined correctly. | Should be successful | + * | 02 | Invoke DrmJsonObject constructor with JSON input. | inputJson = "{\"outerKey\": {\"innerKey1\": \"innerValue1\", \"innerArr\": [1, 2, 3]}}" | DrmJsonObject constructed without throwing an exception. | Should Pass | + */ +TEST(DrmJsonObject, Construct_ValidNestedJson) { + std::cout << "Entering Construct_ValidNestedJson test" << std::endl; + + const char inputJson[] = "{\"outerKey\": {\"innerKey1\": \"innerValue1\", \"innerArr\": [1, 2, 3]}}"; + std::cout << "Invoking DrmJsonObject constructor with JSON input: " << inputJson << std::endl; + EXPECT_NO_THROW( + { + DrmJsonObject obj(inputJson); + } + ); + + std::cout << "Exiting Construct_ValidNestedJson test" << std::endl; +} +/** + * @brief Verify that constructing a DrmJsonObject with an empty JSON string throws an exception. + * + * Tests that passing an empty JSON string to the DrmJsonObject constructor results in an exception being thrown. This verifies the API's robustness in handling invalid input. + * + * **Test Group ID:** Basic: 01@n + * **Test Case ID:** 006@n + * **Priority:** High@n + * + * **Pre-Conditions:** None@n + * **Dependencies:** None@n + * **User Interaction:** None@n + * + * **Test Procedure:** + * | Variation / Step | Description | Test Data | Expected Result | Notes | + * | :--------------: | ------------------------------------------------------------------ | ------------------------ | ------------------------------------------------------------------ | ---------- | + * | 01 | Initialize an empty JSON string and invoke DrmJsonObject constructor | inputJson = "" | The DrmJsonObject constructor throws an exception upon receiving empty input | Should Pass | + */ +TEST(DrmJsonObject, Construct_EmptyJson) { + std::cout << "Entering Construct_EmptyJson test" << std::endl; + + const char inputJson[] = ""; + std::cout << "Invoking DrmJsonObject constructor with empty JSON input." << std::endl; + EXPECT_ANY_THROW( + { + DrmJsonObject obj(inputJson); + } + ); + + std::cout << "Exiting Construct_EmptyJson test" << std::endl; +} +/** + * @brief Test the DrmJsonObject constructor with a null JSON pointer input. + * + * This test verifies that the DrmJsonObject constructor properly handles an invalid (null) JSON input pointer by throwing an exception. This is crucial for ensuring robust error handling in scenarios where the input data is missing or corrupted. + * + * **Test Group ID:** Basic: 01 + * **Test Case ID:** 007 + * **Priority:** High + * + * **Pre-Conditions:** None + * **Dependencies:** None + * **User Interaction:** None + * + * **Test Procedure:** + * | Variation / Step | Description | Test Data | Expected Result | Notes | + * | :--------------: | ------------------------------------------------------------ | ----------------------------------- | -------------------------------------------------------- | -------------------- | + * | 01 | Initialize the null JSON pointer variable | inputJson = nullptr | Variable inputJson is set to a null pointer | Should be successful | + * | 02 | Invoke DrmJsonObject constructor with the null pointer input | inputJson = nullptr | Constructor throws an exception as expected | Should Fail | + */ +TEST(DrmJsonObject, Construct_NullPointerJson) { + std::cout << "Entering Construct_NullPointerJson test" << std::endl; + + const char* inputJson = nullptr; + std::cout << "Invoking DrmJsonObject constructor with null JSON input pointer." << std::endl; + EXPECT_ANY_THROW( + { + DrmJsonObject obj(inputJson); + } + ); + + std::cout << "Exiting Construct_NullPointerJson test" << std::endl; +} +/** + * @brief Verify that the DrmJsonObject constructor handles a minimal empty JSON string correctly. + * + * This test verifies that passing an empty JSON object string "{}" to the DrmJsonObject constructor does not throw exceptions and that the object is correctly initialized by ensuring the internal pointer "mJsonObj" is not NULL. This ensures that the API behaves as expected with minimal valid JSON input.@n + * + * **Test Group ID:** Basic: 01@n + * **Test Case ID:** 008@n + * **Priority:** High@n + * @n + * **Pre-Conditions:** None@n + * **Dependencies:** None@n + * **User Interaction:** None@n + * @n + * **Test Procedure:**@n + * | Variation / Step | Description | Test Data | Expected Result | Notes | + * | :--------------: | ---------------------------------------------------------------- | ------------------------------------ | ----------------------------------------------------- | ------------------- | + * | 01 | Invoke DrmJsonObject constructor with minimal empty JSON input | input = "{}" | No exception is thrown | Should Pass | + * | 02 | Verify internal state after construction | output: mJsonObj should not be NULL | mJsonObj is not NULL | Should Pass | + */ +TEST(DrmJsonObject, ValidMinimalJsonString) { + std::cout << "Entering ValidMinimalJsonString test" << std::endl; + + std::string input = "{}"; + std::cout << "Invoking DrmJsonObject constructor with input: " << input << std::endl; + EXPECT_NO_THROW( + { + DrmJsonObject obj(input); + } + ); + + std::cout << "After construction, expecting internal state: mJsonObj is not NULL for empty JSON object." << std::endl; + EXPECT_NE(obj.mJsonObj, static_cast(nullptr)); + + std::cout << "Exiting ValidMinimalJsonString test" << std::endl; +} +/** + * @brief Validates that a complex JSON string is correctly parsed without exceptions. + * + * This test verifies that the DrmJsonObject constructor can correctly parse a well-formed complex JSON string containing various elements such as key-value pairs, arrays, and nested objects. It checks that no exceptions are thrown during the object creation and that the internal state (mJsonObj) is set properly (i.e., not NULL). + * + * **Test Group ID:** Basic: 01@n + * **Test Case ID:** 009@n + * **Priority:** High@n + * + * **Pre-Conditions:** None@n + * **Dependencies:** None@n + * **User Interaction:** None@n + * + * **Test Procedure:** + * | Variation / Step | Description | Test Data | Expected Result | Notes | + * | :----: | --------- | ---------- |-------------- | ----- | + * | 01 | Prepare valid complex JSON string input. | input = {"key": "value", "array": [1, 2, 3], "object": {"nested": true}} | Variable 'input' contains the valid JSON string. | Should be successful | + * | 02 | Invoke the DrmJsonObject constructor with the valid input. | input = {"key": "value", "array": [1, 2, 3], "object": {"nested": true}}, output1 = DrmJsonObject instance | No exception is thrown during object construction. | Should Pass | + * | 03 | Validate that the object's internal state is set. | output1 = mJsonObj pointer of the created object | mJsonObj is not NULL, indicating successful parsing of nested JSON structure. | Should Pass | + */ +TEST(DrmJsonObject, ValidComplexJsonString) { + std::cout << "Entering ValidComplexJsonString test" << std::endl; + + // Using escaped quotes for valid complex JSON string + std::string input = "{\"key\": \"value\", \"array\": [1, 2, 3], \"object\": {\"nested\": true}}"; + std::cout << "Invoking DrmJsonObject constructor with input: " << input << std::endl; + EXPECT_NO_THROW( + { + DrmJsonObject obj(input); + } + ); + + // Debug log: Internal state check assumed for mJsonObj (should be non-null and properly represent nested structures) + std::cout << "After construction, expecting internal state: mJsonObj is not NULL for nested JSON structure." << std::endl; + EXPECT_NE(obj.mJsonObj, static_cast(nullptr)); + + std::cout << "Exiting ValidComplexJsonString test" << std::endl; +} +/** + * @brief Verify addition of an empty nested DrmJsonObject to a parent object. + * + * This test checks that an empty nested DrmJsonObject can be successfully added to a main DrmJsonObject using the 'add' method. + * + * **Test Group ID:** Basic: 01 + * **Test Case ID:** 010 + * **Priority:** High + * + * **Pre-Conditions:** None + * **Dependencies:** None + * **User Interaction:** None + * + * **Test Procedure:** + * | Variation / Step | Description | Test Data | Expected Result | Notes | + * | :--------------: | ---------------------------------------------------------------- | ------------------------------------------------------- | ---------------------------------- | ----------------- | + * | 01 | Create mainObj using default constructor | None | mainObj created successfully | Should be successful | + * | 02 | Create nestedObj (empty) using default constructor | None | nestedObj created successfully | Should be successful | + * | 03 | Invoke add method on mainObj with name "nested" and nestedObj | name = "nested", nestedObj = empty DrmJsonObject | Returns true | Should Pass | + * | 04 | Assert that the result from add method is true | result = output of add method | Expect result to be true | Should Pass | + */ +TEST(DrmJsonObject, ValidNestedAdditionEmpty) { + std::cout << "Entering ValidNestedAdditionEmpty test" << std::endl; + + // Creating main DrmJsonObject using default constructor + DrmJsonObject mainObj; + std::cout << "Created mainObj using default constructor" << std::endl; + + // Creating nested DrmJsonObject (empty) + DrmJsonObject nestedObj; + std::cout << "Created nestedObj (empty) using default constructor" << std::endl; + + // Invoking add method with name = "nested" and nestedObj + std::cout << "Invoking add with name: \"nested\" and nestedObj (empty)" << std::endl; + bool result = mainObj.add("nested", nestedObj); + std::cout << "add returned value: " << std::boolalpha << result << std::endl; + + EXPECT_TRUE(result); + + std::cout << "Exiting ValidNestedAdditionEmpty test" << std::endl; +} +/** + * @brief Validate the addition of a non-empty nested DrmJsonObject into a main DrmJsonObject instance + * + * This test creates a main DrmJsonObject using the default constructor and a nested DrmJsonObject initialized with a valid JSON string. It then invokes the add method on the main object with the nested object and verifies that the operation is successful by expecting the return value to be true. This test is essential to confirm that non-empty nested JSON data is correctly handled. + * + * **Test Group ID:** Basic: 01@n + * **Test Case ID:** 011@n + * **Priority:** High@n + * + * **Pre-Conditions:** None@n + * **Dependencies:** None@n + * **User Interaction:** None@n + * + * **Test Procedure:** + * | Variation / Step | Description | Test Data | Expected Result | Notes | + * | :--------------: | ------------------------------------------------------------------ | ---------------------------------------------------------------------- | ------------------------------------------------------------ | ------------- | + * | 01 | Create main DrmJsonObject using the default constructor. | mainObj created via default constructor | mainObj is successfully created. | Should be successful | + * | 02 | Create nested DrmJsonObject with a valid JSON string. | jsonStr = "{\"key\":\"value\"}", configObj constructed with jsonStr | configObj contains valid JSON data. | Should be successful | + * | 03 | Invoke add method on mainObj with name "config" and configObj. | name = config, configObj = non-empty JSON object | add method returns true; EXPECT_TRUE(result) assertion passes. | Should Pass | + */ +TEST(DrmJsonObject, ValidNestedAdditionNonEmpty) { + std::cout << "Entering ValidNestedAdditionNonEmpty test" << std::endl; + + // Creating main DrmJsonObject using default constructor + DrmJsonObject mainObj; + std::cout << "Created mainObj using default constructor" << std::endl; + + // Creating nested DrmJsonObject with valid JSON string data + std::string jsonStr = "{\"key\":\"value\"}"; + DrmJsonObject configObj(jsonStr); + std::cout << "Created configObj with JSON string: " << jsonStr << std::endl; + + // Invoking add method with name = "config" and configObj + std::cout << "Invoking add with name: \"config\" and configObj (non-empty)" << std::endl; + bool result = mainObj.add("config", configObj); + std::cout << "add returned value: " << std::boolalpha << result << std::endl; + + EXPECT_TRUE(result); + + std::cout << "Exiting ValidNestedAdditionNonEmpty test" << std::endl; +} +/** + * @brief Validate the behavior of the add method when provided with an empty name string. + * + * This test verifies that invoking the add method with an empty string as the name results in a false return value, indicating that the object is not added. + * + * **Test Group ID:** Basic: 01@n + * **Test Case ID:** 012@n + * **Priority:** High@n + * + * **Pre-Conditions:** None@n + * **Dependencies:** None@n + * **User Interaction:** None@n + * + * **Test Procedure:**@n + * | Variation / Step | Description | Test Data | Expected Result | Notes | + * | :--------------: | --------------------------------------------------------------------- | --------------------------------------------------------------- | ---------------------------------------------------------------------- | --------------- | + * | 01 | Create main DrmJsonObject using default constructor | No inputs | mainObj is initialized successfully | Should be successful | + * | 02 | Create nested DrmJsonObject using default constructor | No inputs | nestedObj is initialized successfully | Should be successful | + * | 03 | Invoke add method with empty name and the nested object | input = "", nestedObj = default constructed object | API returns false | Should Pass | + * | 04 | Verify that the result of the add invocation is false using assertion | output = result, expected value = false | EXPECT_FALSE(result) assertion passes | Should Pass | + */ +TEST(DrmJsonObject, AddWithEmptyName) { + std::cout << "Entering AddWithEmptyName test" << std::endl; + + // Creating main DrmJsonObject using default constructor + DrmJsonObject mainObj; + std::cout << "Created mainObj using default constructor" << std::endl; + + // Creating nested DrmJsonObject (could be empty or with data; using empty for this test) + DrmJsonObject nestedObj; + std::cout << "Created nestedObj using default constructor" << std::endl; + + // Invoking add method with empty name and nestedObj + std::cout << "Invoking add with empty name \"\" and nestedObj" << std::endl; + bool result = mainObj.add("", nestedObj); + std::cout << "add returned value: " << std::boolalpha << result << std::endl; + + EXPECT_FALSE(result); + + std::cout << "Exiting AddWithEmptyName test" << std::endl; +} +/** + * @brief Validate that self-referencing addition in a DrmJsonObject is prevented + * + * This test checks that invoking the add method on a DrmJsonObject instance with itself as the value (self-referencing) does not allow the addition and returns false. This ensures the integrity of the object by preventing cyclic references. + * + * **Test Group ID:** Basic: 01@n + * **Test Case ID:** 013@n + * **Priority:** High@n + * + * **Pre-Conditions:** None@n + * **Dependencies:** None@n + * **User Interaction:** None@n + * + * **Test Procedure:**@n + * | Variation / Step | Description | Test Data | Expected Result | Notes | + * | :----: | :-------------------------------------------------------------------------------------- | :------------------------------------------------------------ | :------------------------------------------------------------ | :------------- | + * | 01 | Create a DrmJsonObject instance using the default constructor | (No input arguments) | A new instance of DrmJsonObject is created | Should be successful | + * | 02 | Invoke add method with name "self" passing the same instance (self-reference) | name = "self", reference = mainObj, output = result | The add method returns false indicating rejection of self-reference | Should Fail | + * | 03 | Verify the return value using EXPECT_FALSE to ensure self-referencing addition was blocked | result = false | The test assertion passes confirming the API's behavior | Should be successful | + */ +TEST(DrmJsonObject, SelfReferencingAddition) { + std::cout << "Entering SelfReferencingAddition test" << std::endl; + + // Creating a DrmJsonObject using default constructor + DrmJsonObject mainObj; + std::cout << "Created mainObj using default constructor" << std::endl; + + // Invoking add method with name "self" with the same instance (self-referencing) + std::cout << "Invoking add with name: \"self\" and mainObj itself (self-referencing)" << std::endl; + bool result = mainObj.add("self", mainObj); + std::cout << "add returned value: " << std::boolalpha << result << std::endl; + + EXPECT_FALSE(result); + + std::cout << "Exiting SelfReferencingAddition test" << std::endl; +} +/** + * @brief Verify that adding a valid non-empty key paired with a true value to DrmJsonObject is successful + * + * This test evaluates the functionality of the add method in DrmJsonObject when provided with a valid non-empty key and a boolean true value. It checks that the object is correctly instantiated, that the input values are properly passed to the API, and that the API returns a successful result as expected. + * + * **Test Group ID:** Basic: 01@n + * **Test Case ID:** 014@n + * **Priority:** High@n + * + * **Pre-Conditions:** None@n + * **Dependencies:** None@n + * **User Interaction:** None@n + * + * **Test Procedure:**@n + * | Variation / Step | Description | Test Data | Expected Result | Notes | + * | :--------------: | ---------------------------------------------------------------- | ---------------------------------------------------------- | ----------------------------------------------------------------------------- | --------------- | + * | 01 | Instantiate a DrmJsonObject using the default constructor | N/A | DrmJsonObject instance is created successfully | Should be successful | + * | 02 | Prepare input values for the add method | key = validKey, value = true | Input values are set correctly | Should be successful | + * | 03 | Invoke the add method with the prepared key and value | input key = validKey, input value = true, output result = capture | The add method returns true | Should Pass | + * | 04 | Assert that the returned result is true using EXPECT_TRUE | result = returned value from add() | Assertion passes confirming that the returned result is true | Should Pass | + */ +TEST(DrmJsonObject, AddingValidNonEmptyKeyWithTrue) { + std::cout << "Entering AddingValidNonEmptyKeyWithTrue test" << std::endl; + + // Create a DrmJsonObject instance using the default constructor + DrmJsonObject obj; + + // Prepare input values + std::string key = "validKey"; + bool value = true; + std::cout << "Invoking add with key: " << key << " and value: " << std::boolalpha << value << std::endl; + + // Invoke add method + bool result = obj.add(key, value); + std::cout << "Method add returned: " << std::boolalpha << result << std::endl; + + // Expect the method to return true + EXPECT_TRUE(result); + + std::cout << "Exiting AddingValidNonEmptyKeyWithTrue test" << std::endl; +} +/** + * @brief Verify that the add() method successfully adds a valid non-empty key with a false boolean value. + * + * This test verifies that the DrmJsonObject::add() method correctly handles the insertion of a valid, non-empty key ("validKey") with a boolean value of false. The test ensures that the method returns true when the addition is successful. + * + * **Test Group ID:** Basic: 01@n + * **Test Case ID:** 015@n + * **Priority:** High@n + * + * **Pre-Conditions:** None@n + * **Dependencies:** None@n + * **User Interaction:** None@n + * + * **Test Procedure:** + * | Variation / Step | Description | Test Data | Expected Result | Notes | + * | :----: | --------- | ---------- |-------------- | ----- | + * | 01 | Create a DrmJsonObject instance using the default constructor | None | Instance of DrmJsonObject is created | Should be successful | + * | 02 | Invoke the add() method with a valid key and a false boolean value | key = validKey, value = false | The add() method returns true | Should Pass | + * | 03 | Perform assertion check on the return value of add() | result = true | EXPECT_TRUE assertion passes confirming the method returns true | Should Pass | + */ +TEST(DrmJsonObject, AddingValidNonEmptyKeyWithFalse) { + std::cout << "Entering AddingValidNonEmptyKeyWithFalse test" << std::endl; + + // Create a DrmJsonObject instance using the default constructor + DrmJsonObject obj; + + // Prepare input values + std::string key = "validKey"; + bool value = false; + std::cout << "Invoking add with key: " << key << " and value: " << std::boolalpha << value << std::endl; + + // Invoke add method + bool result = obj.add(key, value); + std::cout << "Method add returned: " << std::boolalpha << result << std::endl; + + // Expect the method to return true + EXPECT_TRUE(result); + + std::cout << "Exiting AddingValidNonEmptyKeyWithFalse test" << std::endl; +} +/** + * @brief Test for adding an entry with an empty key and a true value, expecting failure. + * + * This test verifies that when the add method of DrmJsonObject is invoked with an empty key and a boolean value true, it returns false indicating that the operation is invalid. + * + * **Test Group ID:** Basic: 01@n + * **Test Case ID:** 016@n + * **Priority:** High@n + * + * **Pre-Conditions:** None@n + * **Dependencies:** None@n + * **User Interaction:** None@n + * + * **Test Procedure:**@n + * | Variation / Step | Description | Test Data | Expected Result | Notes | + * | :----: | ------------------------------------------------------------------- | ------------------------ | -------------------------------------------------------------------- | ----------- | + * | 01 | Create a DrmJsonObject, prepare an empty key and true value, and invoke the add method | key = "", value = true | The add method returns false, validated by EXPECT_FALSE | Should Fail | + */ +TEST(DrmJsonObject, AddingEmptyKeyWithTrue) { + std::cout << "Entering AddingEmptyKeyWithTrue test" << std::endl; + + // Create a DrmJsonObject instance using the default constructor + DrmJsonObject obj; + + // Prepare input values with an empty key + std::string key = ""; + bool value = true; + std::cout << "Invoking add with key: \"" << key << "\" (empty key) and value: " + << std::boolalpha << value << std::endl; + + // Invoke add method + bool result = obj.add(key, value); + std::cout << "Method add returned: " << std::boolalpha << result << std::endl; + + // Expect the method to return false due to invalid empty key + EXPECT_FALSE(result); + + std::cout << "Exiting AddingEmptyKeyWithTrue test" << std::endl; +} +/** + * @brief Validate that add() returns false when invoked with an empty key. + * + * This test verifies that the DrmJsonObject::add() method correctly handles an attempt to add a new entry using an empty key and boolean false value. The method is expected to detect the empty key as invalid and return false, thus preventing the addition of an invalid entry. + * + * **Test Group ID:** Basic: 01 + * **Test Case ID:** 017 + * **Priority:** High + * + * **Pre-Conditions:** None + * **Dependencies:** None + * **User Interaction:** None + * + * **Test Procedure:** + * | Variation / Step | Description | Test Data | Expected Result | Notes | + * | :--------------: | -------------------------------------------------------------------| --------------------------------------| -------------------------------------------------------------| ------------------- | + * | 01 | Instantiate a DrmJsonObject using the default constructor. | None | Object is created successfully. | Should be successful| + * | 02 | Prepare input values with an empty key and a boolean false value. | key = "", value = false | Inputs are initialized as specified. | Should be successful| + * | 03 | Invoke the add() method with the provided inputs. | input key = "", input value = false | Method returns false due to invalid empty key. | Should Pass | + * | 04 | Validate the output using EXPECT_FALSE to check the API behavior. | output result = false | The assertion passes confirming the API correctly handles the condition. | Should be successful| + */ +TEST(DrmJsonObject, AddingEmptyKeyWithFalse) { + std::cout << "Entering AddingEmptyKeyWithFalse test" << std::endl; + + // Create a DrmJsonObject instance using the default constructor + DrmJsonObject obj; + + // Prepare input values with an empty key + std::string key = ""; + bool value = false; + std::cout << "Invoking add with key: \"" << key << "\" (empty key) and value: " + << std::boolalpha << value << std::endl; + + // Invoke add method + bool result = obj.add(key, value); + std::cout << "Method add returned: " << std::boolalpha << result << std::endl; + + // Expect the method to return false due to invalid empty key + EXPECT_FALSE(result); + + std::cout << "Exiting AddingEmptyKeyWithFalse test" << std::endl; +} +/** + * @brief Verify that adding a key with special characters is correctly rejected + * + * This test verifies that the DrmJsonObject::add method correctly handles keys containing special characters by rejecting them. The function should return false to indicate that the key was not added due to invalid characters. + * + * **Test Group ID:** Basic: 01@n + * **Test Case ID:** 018@n + * **Priority:** High@n + * + * **Pre-Conditions:** None@n + * **Dependencies:** None@n + * **User Interaction:** None@n + * + * **Test Procedure:** + * | Variation / Step | Description | Test Data | Expected Result | Notes | + * | :--------------: | ---------------------------------------------------------------- | -------------------------------------------------- | --------------------------------------- | ------------- | + * | 01 | Instantiate a DrmJsonObject object | None | Object created successfully | Should be successful | + * | 02 | Invoke add method with key containing special characters | key = !@#$%^&*(), value = true | Return value should be false | Should Fail | + * | 03 | Validate that the add method returned false using EXPECT_FALSE | result = false | EXPECT_FALSE assertion passes | Should be successful | + */ +TEST(DrmJsonObject, AddingKeyWithSpecialCharacters) { + std::cout << "Entering AddingKeyWithSpecialCharacters test" << std::endl; + + // Create a DrmJsonObject instance using the default constructor + DrmJsonObject obj; + + // Prepare input values with special characters in the key + std::string key = "!@#$%^&*()"; + bool value = true; + std::cout << "Invoking add with key: " << key << " and value: " + << std::boolalpha << value << std::endl; + + // Invoke add method + bool result = obj.add(key, value); + std::cout << "Method add returned: " << std::boolalpha << result << std::endl; + + // Expect the method to return false based on test plan for special characters + EXPECT_FALSE(result); + + std::cout << "Exiting AddingKeyWithSpecialCharacters test" << std::endl; +} +/** + * @brief Verify that adding a valid number to DrmJsonObject returns success. + * + * This test exercises the add method of DrmJsonObject with a valid cJSON-formatted number input. + * It ensures that the DrmJsonObject instance correctly accepts and processes a valid numeric cJSON object. + * + * **Test Group ID:** Basic: 01@n + * **Test Case ID:** 019@n + * **Priority:** High@n + * @n + * **Pre-Conditions:** None@n + * **Dependencies:** None@n + * **User Interaction:** None@n + * @n + * **Test Procedure:**@n + * | Variation / Step | Description | Test Data | Expected Result | Notes | + * | :--------------: | --------------------------------------------------------------| -----------------------------------------------------------------------| ----------------------------------------------------------- | --------------------- | + * | 01 | Create a DrmJsonObject instance | None | DrmJsonObject instance created successfully | Should be successful | + * | 02 | Create and initialize a valid cJSON object for a number | jsonNumber->type = cJSON_Number, jsonNumber->valueint = 42, jsonNumber->valuedouble = 42.0, jsonNumber->valuestring = nullptr, jsonNumber->string = nullptr | Valid cJSON object created with number details | Should be successful | + * | 03 | Invoke DrmJsonObject::add with name "numberField" and the valid cJSON pointer | name = numberField, cJSON pointer = address of jsonNumber | API invoked and returns true | Should Pass | + * | 04 | Check the return value using EXPECT_TRUE | result = true | EXPECT_TRUE condition satisfied (result is true) | Should Pass | + * | 05 | Clean up allocated memory for the cJSON object | delete jsonNumber | Memory successfully released | Should be successful | + */ +TEST(DrmJsonObject, AddValidNumber) { + std::cout << "Entering AddValidNumber test" << std::endl; + + // Create DrmJsonObject instance using default constructor. + DrmJsonObject obj; + std::cout << "Created DrmJsonObject instance." << std::endl; + + // Allocate and initialize a valid cJSON object for a number. + cJSON* jsonNumber = new cJSON; + jsonNumber->next = nullptr; + jsonNumber->prev = nullptr; + jsonNumber->child = nullptr; + jsonNumber->type = cJSON_Number; + jsonNumber->valueint = 42; + jsonNumber->valuedouble = 42.0; + jsonNumber->valuestring = nullptr; + jsonNumber->string = nullptr; + std::cout << "Created cJSON object for number:" << std::endl; + std::cout << " type: " << jsonNumber->type << std::endl; + std::cout << " valueint: " << jsonNumber->valueint << std::endl; + std::cout << " valuedouble: " << jsonNumber->valuedouble << std::endl; + + // Log invocation details. + std::string name = "numberField"; + std::cout << "Invoking DrmJsonObject::add with name: " << name << " and cJSON pointer: " << jsonNumber << std::endl; + + // Invoke add method. + bool result = obj.add(name, jsonNumber); + std::cout << "DrmJsonObject::add returned: " << std::boolalpha << result << std::endl; + + // Check expected output. + EXPECT_TRUE(result); + + // Clean up allocated memory. + delete jsonNumber; + + std::cout << "Exiting AddValidNumber test" << std::endl; +} +/** + * @brief Validate DrmJsonObject::add with valid string input. + * + * This test verifies that the add method of DrmJsonObject correctly adds a valid cJSON object representing a string when provided with a valid field name. It ensures that the initialization, memory operations, and successful return value are correctly handled. + * + * **Test Group ID:** Basic: 01@n + * **Test Case ID:** 020@n + * **Priority:** High@n + * + * **Pre-Conditions:** None@n + * **Dependencies:** None@n + * **User Interaction:** None@n + * + * **Test Procedure:**@n + * | Variation / Step | Description | Test Data | Expected Result | Notes | + * | :--------------: | --------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------ | --------------------------------------------------------------------------- | ----------------- | + * | 01 | Create a DrmJsonObject instance. | No input arguments. | Instance created successfully. | Should be successful | + * | 02 | Allocate and initialize a valid cJSON object for a string. | jsonString->type = cJSON_String, jsonString->valueint = 0, jsonString->valuedouble = 0. | cJSON object is properly initialized. | Should be successful | + * | 03 | Prepare and assign a valid example string to jsonString->valuestring using strncpy. | exampleStr = "example", tempBuffer contains "example", jsonString->valuestring allocated with correct size. | cJSON object contains a valid string value. | Should be successful | + * | 04 | Invoke DrmJsonObject::add with valid name and cJSON pointer. | name = "stringField", jsonString pointer. | API returns true indicating successful addition. | Should Pass | + * | 05 | Validate the API output using an assertion. | Return value from add() expected to be true, compared using EXPECT_TRUE(result). | Assertion passes with true value. | Should Pass | + * | 06 | Clean up allocated memory for jsonString and its members. | De-allocation of jsonString->valuestring and jsonString. | Memory freed without errors. | Should be successful | + */ +TEST(DrmJsonObject, AddValidString) { + std::cout << "Entering AddValidString test" << std::endl; + + // Create DrmJsonObject instance. + DrmJsonObject obj; + std::cout << "Created DrmJsonObject instance." << std::endl; + + // Allocate and initialize a valid cJSON object for a string. + cJSON* jsonString = new cJSON; + jsonString->next = nullptr; + jsonString->prev = nullptr; + jsonString->child = nullptr; + jsonString->type = cJSON_String; + jsonString->valueint = 0; + jsonString->valuedouble = 0.0; + + // Prepare valuestring using strncpy. + char tempBuffer[100]; + std::memset(tempBuffer, 0, sizeof(tempBuffer)); + const char* exampleStr = "example"; + std::strncpy(tempBuffer, exampleStr, sizeof(tempBuffer) - 1); + jsonString->valuestring = new char[std::strlen(tempBuffer) + 1]; + std::strncpy(jsonString->valuestring, tempBuffer, std::strlen(tempBuffer) + 1); + jsonString->string = nullptr; + std::cout << "Created cJSON object for string:" << std::endl; + std::cout << " type: " << jsonString->type << std::endl; + std::cout << " valuestring: " << jsonString->valuestring << std::endl; + + // Log invocation details. + std::string name = "stringField"; + std::cout << "Invoking DrmJsonObject::add with name: " << name << " and cJSON pointer: " << jsonString << std::endl; + + // Invoke add method. + bool result = obj.add(name, jsonString); + std::cout << "DrmJsonObject::add returned: " << std::boolalpha << result << std::endl; + + // Check expected output. + EXPECT_TRUE(result); + + // Clean up allocated memory. + delete [] jsonString->valuestring; + delete jsonString; + + std::cout << "Exiting AddValidString test" << std::endl; +} +/** + * @brief Test the behavior of adding an element with an empty name to a DrmJsonObject. + * + * This test verifies that when an empty name string is passed along with a valid cJSON object to the DrmJsonObject::add method, + * the method correctly returns false, indicating a failure to add the element. The test also ensures proper memory allocation and cleanup. + * + * **Test Group ID:** Basic: 01@n + * **Test Case ID:** 021@n + * **Priority:** High@n + * + * **Pre-Conditions:** None@n + * **Dependencies:** None@n + * **User Interaction:** None@n + * + * **Test Procedure:**@n + * | Variation / Step | Description | Test Data | Expected Result | Notes | + * | :--------------: | --------------------------------------------------------------------------- | ---------------------------------------------------------------------------- | ------------------------------------------------- | ------------- | + * | 01 | Create an instance of DrmJsonObject. | instance: new DrmJsonObject() | Instance is created successfully. | Should be successful | + * | 02 | Allocate and initialize a valid cJSON object for a string type. | cJSON->type = cJSON_String, valueint = 0, valuedouble = 0.0 | cJSON object is created with string type correctly.| Should be successful | + * | 03 | Prepare and set the valuestring property of the cJSON object using strncpy. | dataStr = "data", tempBuffer initialized, valuestring allocated accordingly | valuestring is assigned correctly. | Should be successful | + * | 04 | Log invocation details and prepare the empty name string. | name = "", jsonString pointer | Invocation details are logged. | Should be successful | + * | 05 | Invoke DrmJsonObject::add with an empty name and valid cJSON pointer. | input: name = "", jsonString pointer; output: bool result | The add method returns false. | Should Fail | + * | 06 | Validate the result using an EXPECT_FALSE assertion. | result expected to be false | Test passes if add returns false. | Should Pass | + * | 07 | Clean up allocated memory. | delete valuestring and cJSON object | Memory is freed successfully. | Should be successful | + */ +TEST(DrmJsonObject, AddEmptyName) { + std::cout << "Entering AddEmptyName test" << std::endl; + + // Create DrmJsonObject instance. + DrmJsonObject obj; + std::cout << "Created DrmJsonObject instance." << std::endl; + + // Allocate and initialize a valid cJSON object for a string. + cJSON* jsonString = new cJSON; + jsonString->next = nullptr; + jsonString->prev = nullptr; + jsonString->child = nullptr; + jsonString->type = cJSON_String; + jsonString->valueint = 0; + jsonString->valuedouble = 0.0; + + // Prepare valuestring using strncpy. + char tempBuffer[100]; + std::memset(tempBuffer, 0, sizeof(tempBuffer)); + const char* dataStr = "data"; + std::strncpy(tempBuffer, dataStr, sizeof(tempBuffer) - 1); + jsonString->valuestring = new char[std::strlen(tempBuffer) + 1]; + std::strncpy(jsonString->valuestring, tempBuffer, std::strlen(tempBuffer) + 1); + jsonString->string = nullptr; + std::cout << "Created cJSON object for string with empty name test:" << std::endl; + std::cout << " type: " << jsonString->type << std::endl; + std::cout << " valuestring: " << jsonString->valuestring << std::endl; + + // Log invocation details. + std::string name = ""; + std::cout << "Invoking DrmJsonObject::add with empty name and cJSON pointer: " << jsonString << std::endl; + + // Invoke add method. + bool result = obj.add(name, jsonString); + std::cout << "DrmJsonObject::add returned: " << std::boolalpha << result << std::endl; + + // Check expected output. + EXPECT_FALSE(result); + + // Clean up allocated memory. + delete [] jsonString->valuestring; + delete jsonString; + + std::cout << "Exiting AddEmptyName test" << std::endl; +} +/** + * @brief Verifies that DrmJsonObject::add returns false when a NULL cJSON pointer is provided + * + * This test case creates an instance of DrmJsonObject, calls the add method with a valid non-empty name "nullField" and a NULL cJSON pointer, and verifies that the method returns false. + * + * **Test Group ID:** Basic: 01@n + * **Test Case ID:** 022@n + * **Priority:** High@n + * + * **Pre-Conditions:** None@n + * **Dependencies:** None@n + * **User Interaction:** None@n + * + * **Test Procedure:** + * | Variation / Step | Description | Test Data | Expected Result | Notes | + * | :----: | --------- | ---------- |-------------- | ----- | + * | 01 | Instantiate a DrmJsonObject object | none | DrmJsonObject instance is created successfully | Should be successful | + * | 02 | Invoke add method with name = "nullField" and NULL cJSON pointer | name = nullField, cJSON pointer = nullptr | API returns false | Should Fail | + * | 03 | Assert that the API output is false | result = false | EXPECT_FALSE(result) passes | Should be successful | + */ +TEST(DrmJsonObject, AddNullValue) { + std::cout << "Entering AddNullValue test" << std::endl; + + // Create DrmJsonObject instance. + DrmJsonObject obj; + std::cout << "Created DrmJsonObject instance." << std::endl; + + // Log invocation details. + std::string name = "nullField"; + std::cout << "Invoking DrmJsonObject::add with name: " << name << " and NULL cJSON pointer." << std::endl; + + // Invoke add method with NULL pointer. + bool result = obj.add(name, nullptr); + std::cout << "DrmJsonObject::add returned: " << std::boolalpha << result << std::endl; + + // Check expected output. + EXPECT_FALSE(result); + + std::cout << "Exiting AddNullValue test" << std::endl; +} +/** + * @brief Verify that DrmJsonObject correctly adds a cJSON object containing special characters in its string field. + * + * This test examines the functionality of the DrmJsonObject::add method when invoked with a cJSON object whose string field contains special characters. + * + * **Test Group ID:** Basic: 01@n + * **Test Case ID:** 023@n + * **Priority:** High@n + * + * **Pre-Conditions:** None@n + * **Dependencies:** None@n + * **User Interaction:** None@n + * + * **Test Procedure:** + * | Variation / Step | Description | Test Data | Expected Result | Notes | + * | :----: | --------- | ---------- |-------------- | ----- | + * | 01 | Create DrmJsonObject instance. | None | Instance of DrmJsonObject is created. | Should be successful | + * | 02 | Allocate and initialize a valid cJSON object for a string. | cJSON: type = cJSON_String, valueint = 0, valuedouble = 0.0 | cJSON object is allocated and all fields are initialized properly. | Should be successful | + * | 03 | Prepare valuestring using strncpy with a special string. | tempBuffer = "special_data", valuestring allocated with copied content. | Buffer is correctly copied and cJSON->valuestring holds "special_data". | Should be successful | + * | 04 | Invoke the add method with a non-empty name containing special characters and the prepared cJSON pointer. | name = "special!@#Field", jsonString pointer = allocated cJSON pointer | API returns true; EXPECT_TRUE(result) assertion passes. | Should Pass | + * | 05 | Clean up the allocated memory after validation. | Deletes for jsonString->valuestring and jsonString. | All allocated memory is cleaned up without error. | Should be successful | + */ +TEST(DrmJsonObject, AddSpecialCharacters) { + std::cout << "Entering AddSpecialCharacters test" << std::endl; + + // Create DrmJsonObject instance. + DrmJsonObject obj; + std::cout << "Created DrmJsonObject instance." << std::endl; + + // Allocate and initialize a valid cJSON object for a string. + cJSON* jsonString = new cJSON; + jsonString->next = nullptr; + jsonString->prev = nullptr; + jsonString->child = nullptr; + jsonString->type = cJSON_String; + jsonString->valueint = 0; + jsonString->valuedouble = 0.0; + + // Prepare valuestring using strncpy. + char tempBuffer[100]; + std::memset(tempBuffer, 0, sizeof(tempBuffer)); + const char* specialStr = "special_data"; + std::strncpy(tempBuffer, specialStr, sizeof(tempBuffer) - 1); + jsonString->valuestring = new char[std::strlen(tempBuffer) + 1]; + std::strncpy(jsonString->valuestring, tempBuffer, std::strlen(tempBuffer) + 1); + jsonString->string = nullptr; + std::cout << "Created cJSON object for string with special characters:" << std::endl; + std::cout << " type: " << jsonString->type << std::endl; + std::cout << " valuestring: " << jsonString->valuestring << std::endl; + + // Log invocation details. + std::string name = "special!@#Field"; + std::cout << "Invoking DrmJsonObject::add with name: " << name << " and cJSON pointer: " << jsonString << std::endl; + + // Invoke add method. + bool result = obj.add(name, jsonString); + std::cout << "DrmJsonObject::add returned: " << std::boolalpha << result << std::endl; + + // Check expected output. + EXPECT_TRUE(result); + + // Clean up allocated memory. + delete [] jsonString->valuestring; + delete jsonString; + + std::cout << "Exiting AddSpecialCharacters test" << std::endl; +} +/** + * @brief Verify that adding a valid non-empty array to a DrmJsonObject returns a successful result + * + * This test validates that when a valid key ("videoFormats") and a non-empty vector of strings + * ({"mp4", "webm", "avi"}) are provided to the add method of the DrmJsonObject, the method returns true. + * The test confirms that the API correctly processes the input and stores/handles the given values as expected. + * + * **Test Group ID:** Basic: 01@n + * **Test Case ID:** 024@n + * **Priority:** High@n + * + * **Pre-Conditions:** None@n + * **Dependencies:** None@n + * **User Interaction:** None@n + * + * **Test Procedure:** + * | Variation / Step | Description | Test Data | Expected Result | Notes | + * | :--------------: | -------------------------------------------------------------- | ---------------------------------------------------------------- | ------------------------------------------------------------------ | ------------- | + * | 01 | Initialize the DrmJsonObject using the default constructor. | None | DrmJsonObject instance created successfully. | Should be successful | + * | 02 | Define valid test inputs: set the name and non-empty vector. | name = "videoFormats", values = "mp4, webm, avi" | Variables correctly assigned the provided values. | Should be successful | + * | 03 | Invoke the add method with valid name and non-empty vector. | input: name = "videoFormats", values = "mp4, webm, avi"; output: result | API returns true indicating the array was added successfully. | Should Pass | + * | 04 | Validate the returned result using EXPECT_TRUE assertion. | result = true | EXPECT_TRUE(result) passes confirming the successful addition. | Should Pass | + */ +TEST(DrmJsonObject, AddingValidArray) { + std::cout << "Entering AddingValidArray test" << std::endl; + + // Creating a DrmJsonObject object using the default constructor. + DrmJsonObject obj; + + // Define test input: valid name and non-empty vector of strings. + std::string name = "videoFormats"; + std::vector values = {"mp4", "webm", "avi"}; + + // Log invocation details. + std::cout << "Invoking add with name: " << name << " and values: "; + for (const auto &val : values) + std::cout << "[" << val << "] "; + std::cout << std::endl; + + bool result = obj.add(name, values); + + // Log the returned result. + std::cout << "Returned value: " << std::boolalpha << result << std::endl; + + // Check the expected output. + EXPECT_TRUE(result); + + std::cout << "Exiting AddingValidArray test" << std::endl; +} +/** + * @brief Tests the add function of DrmJsonObject with a valid name and an empty vector. + * + * This test verifies that when a valid name and an empty vector are provided to the add method of DrmJsonObject, the function returns true. The purpose is to ensure that the add function can handle an empty vector correctly. + * + * **Test Group ID:** Basic: 01 + * **Test Case ID:** 025 + * **Priority:** High + * + * **Pre-Conditions:** None + * **Dependencies:** None + * **User Interaction:** None + * + * **Test Procedure:** + * | Variation / Step | Description | Test Data | Expected Result | Notes | + * | :----: | --------- | ---------- |-------------- | ----- | + * | 01 | Create a DrmJsonObject instance | None | DrmJsonObject instance is created successfully | Should be successful | + * | 02 | Define test inputs with a valid name and an empty vector | name = "emptyArray", values = {} | Variables are initialized with the correct test data | Should be successful | + * | 03 | Invoke the add method with the provided name and empty vector | input: name = "emptyArray", input: values = {} | Method returns true indicating successful addition | Should Pass | + * | 04 | Assert the return value is true using EXPECT_TRUE | output: result = true | EXPECT_TRUE confirms the method returned true | Should Pass | + */ +TEST(DrmJsonObject, AddingEmptyVector) { + std::cout << "Entering AddingEmptyVector test" << std::endl; + + // Creating a DrmJsonObject object. + DrmJsonObject obj; + + // Define test input: valid name and empty vector. + std::string name = "emptyArray"; + std::vector values; + + // Log invocation details. + std::cout << "Invoking add with name: " << name << " and an empty vector of values" << std::endl; + + bool result = obj.add(name, values); + + // Log the returned result. + std::cout << "Returned value: " << std::boolalpha << result << std::endl; + + // Check the expected output. + EXPECT_TRUE(result); + + std::cout << "Exiting AddingEmptyVector test" << std::endl; +} +/** + * @brief Verify that DrmJsonObject::add rejects an empty name with non-empty values. + * + * This test evaluates whether the DrmJsonObject::add API correctly handles the case where an empty string is provided as the name along with a non-empty vector of values, ensuring that the function returns false as expected. + * + * **Test Group ID:** Basic: 01@n + * **Test Case ID:** 026@n + * **Priority:** High@n + * + * **Pre-Conditions:** None@n + * **Dependencies:** None@n + * **User Interaction:** None@n + * + * **Test Procedure:** + * | Variation / Step | Description | Test Data | Expected Result | Notes | + * | :--------------: | -------------------------------------------------------------------------------------------------------------- | -------------------------------------------------------------- | ----------------------------------------------------------- | ------------- | + * | 01 | Create a DrmJsonObject instance and initialize test inputs with an empty name and a valid vector of values. | name = "", values = "value1, value2" | Instance created and inputs initialized | Should be successful | + * | 02 | Invoke the add API of DrmJsonObject with the empty name and the non-empty vector. | name = "", values = "value1, value2" output: result = (to be returned) | add() returns false | Should Fail | + * | 03 | Assert that the add function call returns false using the EXPECT_FALSE check. | result = false | Assertion passes confirming add() returned false | Should be successful | + */ +TEST(DrmJsonObject, AddingEmptyName) { + std::cout << "Entering AddingEmptyName test" << std::endl; + + // Creating a DrmJsonObject object. + DrmJsonObject obj; + + // Define test input: empty name and non-empty vector. + std::string name = ""; + std::vector values = {"value1", "value2"}; + + // Log invocation details. + std::cout << "Invoking add with an empty name and values: "; + for (const auto &val : values) + std::cout << "[" << val << "] "; + std::cout << std::endl; + + bool result = obj.add(name, values); + + // Log the returned result. + std::cout << "Returned value: " << std::boolalpha << result << std::endl; + + // Check the expected output. + EXPECT_FALSE(result); + + std::cout << "Exiting AddingEmptyName test" << std::endl; +} +/** + * @brief Verify that the API correctly rejects a mix of empty and valid string values. + * + * This test validates that the DrmJsonObject::add method correctly handles a scenario where a valid name is provided along with a vector of values containing an empty string and a valid string. It ensures that the method enforces input validations by rejecting the mixed values and returning false. + * + * **Test Group ID:** Basic: 01@n + * **Test Case ID:** 027@n + * **Priority:** High@n + * + * **Pre-Conditions:** None@n + * **Dependencies:** None@n + * **User Interaction:** None@n + * + * **Test Procedure:**@n + * | Variation / Step | Description | Test Data | Expected Result | Notes | + * | :----: | --------- | ---------- |-------------- | ----- | + * | 01 | Create an instance of DrmJsonObject | No input parameters | Instance of DrmJsonObject is created | Should be successful | + * | 02 | Define test input data with a valid name and a vector containing an empty string and a valid string | name = "mixedValues", values = ["", "validValue"] | Test input is configured correctly | Should be successful | + * | 03 | Log invocation details showing name and values | name = "mixedValues", values = ["", "validValue"] | Log displays invocation details with an "empty" placeholder for empty string | Should be successful | + * | 04 | Invoke the add method with the defined test inputs and capture the result | name = "mixedValues", values = ["", "validValue"] | Method returns false | Should Fail | + * | 05 | Log the result and assert that the returned value is false using EXPECT_FALSE | output = false | Assertion passes confirming the API returns false for mixed values | Should Pass | + */ +TEST(DrmJsonObject, AddingMixedValues) { + std::cout << "Entering AddingMixedValues test" << std::endl; + + // Creating a DrmJsonObject object. + DrmJsonObject obj; + + // Define test input: valid name and vector with an empty string element. + std::string name = "mixedValues"; + std::vector values = {"", "validValue"}; + + // Log invocation details. + std::cout << "Invoking add with name: " << name << " and values: "; + for (const auto &val : values) + std::cout << "[" << (val.empty() ? "empty" : val) << "] "; + std::cout << std::endl; + + bool result = obj.add(name, values); + + // Log the returned result. + std::cout << "Returned value: " << std::boolalpha << result << std::endl; + + // Check the expected output. + EXPECT_FALSE(result); + + std::cout << "Exiting AddingMixedValues test" << std::endl; +} +/** + * @brief Validate the DrmJsonObject add() API with a large vector input. + * + * This test verifies that the DrmJsonObject API correctly processes the addition of a key associated with a large vector containing 1000 valid entries. The objective is to ensure that the function can handle large datasets and returns a successful result when provided with valid input. + * + * **Test Group ID:** Basic: 01@n + * **Test Case ID:** 028@n + * **Priority:** High@n + * + * **Pre-Conditions:** None@n + * **Dependencies:** None@n + * **User Interaction:** None@n + * + * **Test Procedure:**@n + * | Variation / Step | Description | Test Data | Expected Result | Notes |@n + * | :----: | --------- | ---------- |-------------- | ----- |@n + * | 01 | Create an instance of DrmJsonObject. | N/A | Object is created successfully. | Should be successful |@n + * | 02 | Define valid name "largeArray" and prepare a large vector with 1000 entries where each entry is a string "entryX" (X from 1 to 1000). | name = "largeArray", vector values = ["entry1", "entry2", ..., "entry1000"] | The test input is set up correctly with 1000 valid entries. | Should be successful |@n + * | 03 | Invoke the add API on the DrmJsonObject instance with the defined name and large vector. | input: name = "largeArray", values = vector with 1000 entries; output: bool result from add() | API returns true and the assertion EXPECT_TRUE(result) passes. | Should Pass | + */ +TEST(DrmJsonObject, AddingLargeVector) { + std::cout << "Entering AddingLargeVector test" << std::endl; + + // Creating a DrmJsonObject object. + DrmJsonObject obj; + + // Define test input: valid name and a large vector with 1000 valid entries. + std::string name = "largeArray"; + std::vector values; + values.reserve(1000); + for (int i = 1; i <= 1000; i++) { + // Using snprintf like approach with strncpy equivalent behavior. + char buffer[50]; + std::string entry = "entry" + std::to_string(i); + // Simulate fixed array assignment using strncpy style. + strncpy(buffer, entry.c_str(), sizeof(buffer)-1); + buffer[sizeof(buffer)-1] = '\0'; + values.push_back(std::string(buffer)); + } + + // Log invocation details. + std::cout << "Invoking add with name: " << name << " and a large vector of size: " << values.size() << std::endl; + + bool result = obj.add(name, values); + + // Log the returned result. + std::cout << "Returned value: " << std::boolalpha << result << std::endl; + + // Check the expected output. + EXPECT_TRUE(result); + + std::cout << "Exiting AddingLargeVector test" << std::endl; +} +/** + * @brief Test adding a valid key with a positive double value. + * + * This test verifies that the DrmJsonObject::add method correctly adds a key with a valid positive double value. + * + * **Test Group ID:** Basic: 01 + * **Test Case ID:** 029 + * **Priority:** High + * + * **Pre-Conditions:** None + * **Dependencies:** None + * **User Interaction:** None + * + * **Test Procedure:** + * | Variation / Step | Description | Test Data | Expected Result | Notes | + * | :----: | --------- | ---------- |-------------- | ----- | + * | 01 | Create a DrmJsonObject object using the default constructor | No input parameters | Object is created successfully | Should be successful | + * | 02 | Invoke add method with valid key and positive double value | key = validKey, value = 42.0 | API returns true for a successful addition | Should Pass | + * | 03 | Verify that the add method returns true using assertion | result = true (from add method call) | EXPECT_TRUE assertion passes confirming valid key addition | Should Pass | + */ +TEST(DrmJsonObject, AddValidKeyPositiveDoubleValue) { + std::cout << "Entering AddValidKeyPositiveDoubleValue test" << std::endl; + + std::string key = "validKey"; + double value = 42.0; + + std::cout << "Creating DrmJsonObject object using default constructor" << std::endl; + DrmJsonObject jsonObj; + + std::cout << "Invoking add with name: " << key << " and value: " << value << std::endl; + bool result = jsonObj.add(key, value); + + std::cout << "Method add returned: " << std::boolalpha << result << std::endl; + EXPECT_TRUE(result); + + std::cout << "Exiting AddValidKeyPositiveDoubleValue test" << std::endl; +} +/** + * @brief Test to verify that adding a valid key with a negative double value returns true. + * + * Verifies that the DrmJsonObject add function successfully handles the insertion of a negative double value with a valid key. This test checks the correct processing of negative values within a JSON object. + * + * **Test Group ID:** Basic: 01@n + * **Test Case ID:** 030@n + * **Priority:** High@n + * + * **Pre-Conditions:** None@n + * **Dependencies:** None@n + * **User Interaction:** None@n + * + * **Test Procedure:**@n + * | Variation / Step | Description | Test Data | Expected Result | Notes | + * | :--------------: | -------------------------------------------------------------- | ---------------------------------------------------------- | --------------------------------------------------------------- | ----------------- | + * | 01 | Initialize test data with key and negative double value. | key = negativeKey, value = -3.14 | Variables are initialized for test execution. | Should be successful | + * | 02 | Instantiate DrmJsonObject using default constructor. | output: jsonObj object creation | DrmJsonObject object is created successfully. | Should be successful | + * | 03 | Invoke the add API with key and negative double value. | input1 = key = negativeKey, input2 = value = -3.14, output1 = result | API returns true and the assertion EXPECT_TRUE(result) passes. | Should Pass | + */ +TEST(DrmJsonObject, AddValidKeyNegativeDoubleValue) { + std::cout << "Entering AddValidKeyNegativeDoubleValue test" << std::endl; + + std::string key = "negativeKey"; + double value = -3.14; + + std::cout << "Creating DrmJsonObject object using default constructor" << std::endl; + DrmJsonObject jsonObj; + + std::cout << "Invoking add with name: " << key << " and value: " << value << std::endl; + bool result = jsonObj.add(key, value); + + std::cout << "Method add returned: " << std::boolalpha << result << std::endl; + EXPECT_TRUE(result); + + std::cout << "Exiting AddValidKeyNegativeDoubleValue test" << std::endl; +} +/** + * @brief Verify that a valid key with a zero value can be added successfully to the DrmJsonObject. + * + * This test checks if the DrmJsonObject's add method correctly allows insertion of a key associated with a value of zero. It ensures that the API accepts zero as a valid numerical input and returns a success indicator, thus avoiding misinterpretation of zero as an invalid value. + * + * **Test Group ID:** Basic: 01@n + * **Test Case ID:** 031@n + * **Priority:** High@n + * + * **Pre-Conditions:** None@n + * **Dependencies:** None@n + * **User Interaction:** None@n + * + * **Test Procedure:**@n + * | Variation / Step | Description | Test Data | Expected Result | Notes | + * | :--------------: | --------------------------------------------------------- | -------------------------------------------- | ----------------------------------------------------------------------- | -------------- | + * | 01 | Initialize the valid key and zero value. | key = "zeroKey", value = 0.0 | Variables are initialized with the provided values. | Should be successful | + * | 02 | Create DrmJsonObject object using the default constructor. | No input arguments | Object is instantiated successfully. | Should be successful | + * | 03 | Invoke the add() method with the key and zero value. | key = "zeroKey", value = 0.0 | The add() method returns true indicating successful addition. | Should Pass | + * | 04 | Verify the result using EXPECT_TRUE assertion. | result = value returned from add() | The EXPECT_TRUE assertion passes as result is true. | Should Pass | + */ +TEST(DrmJsonObject, AddValidKeyZeroValue) { + std::cout << "Entering AddValidKeyZeroValue test" << std::endl; + + std::string key = "zeroKey"; + double value = 0.0; + + std::cout << "Creating DrmJsonObject object using default constructor" << std::endl; + DrmJsonObject jsonObj; + + std::cout << "Invoking add with name: " << key << " and value: " << value << std::endl; + bool result = jsonObj.add(key, value); + + std::cout << "Method add returned: " << std::boolalpha << result << std::endl; + EXPECT_TRUE(result); + + std::cout << "Exiting AddValidKeyZeroValue test" << std::endl; +} +/** + * @brief Validate that the add function successfully adds a key with the maximum double value. + * + * This test verifies that the DrmJsonObject::add method correctly handles the addition of a key ("maxDoubleKey") + * with the maximum possible double value (DBL_MAX). This ensures that the method can process extreme numeric values + * without causing errors or overflow issues. + * + * **Test Group ID:** Basic: 01@n + * **Test Case ID:** 032@n + * **Priority:** High@n + * + * **Pre-Conditions:** None@n + * **Dependencies:** None@n + * **User Interaction:** None@n + * + * **Test Procedure:** + * | Variation / Step | Description | Test Data | Expected Result | Notes | + * | :--------------: | ---------------------------------------------------------------------- | ----------------------------------------------------- | --------------------------------------------------------------- | --------------- | + * | 01 | Log test entry and initialize key and value | key = "maxDoubleKey", value = DBL_MAX | Variables initialized correctly | Should be successful | + * | 02 | Create DrmJsonObject instance using the default constructor | No input parameters | Object created successfully | Should be successful | + * | 03 | Invoke add method with the key and maximum double value | key = "maxDoubleKey", value = DBL_MAX | add returns true indicating that the key-value pair is added | Should Pass | + * | 04 | Assert that the add method returned true | result from add = true | EXPECT_TRUE assertion passes | Should be successful | + */ +TEST(DrmJsonObject, AddValidKeyMaxDoubleValue) { + std::cout << "Entering AddValidKeyMaxDoubleValue test" << std::endl; + + std::string key = "maxDoubleKey"; + double value = DBL_MAX; + + std::cout << "Creating DrmJsonObject object using default constructor" << std::endl; + DrmJsonObject jsonObj; + + std::cout << "Invoking add with name: " << key << " and value: " << value << std::endl; + bool result = jsonObj.add(key, value); + + std::cout << "Method add returned: " << std::boolalpha << result << std::endl; + EXPECT_TRUE(result); + + std::cout << "Exiting AddValidKeyMaxDoubleValue test" << std::endl; +} +/** + * @brief Verify that adding a key-value pair with an empty string as the key returns false. + * + * This test validates that the DrmJsonObject::add() method correctly handles an attempt to add a key-value pair when the key is an empty string. The expected behavior is that the method returns false, ensuring that invalid keys are not accepted. + * + * **Test Group ID:** Basic: 01@n + * **Test Case ID:** 033@n + * **Priority:** High@n + * + * **Pre-Conditions:** None@n + * **Dependencies:** None@n + * **User Interaction:** None@n + * + * **Test Procedure:** + * | Variation / Step | Description | Test Data | Expected Result | Notes | + * | :--------------: | --------------------------------------------------------- | ----------------------------------------------- | --------------------------------------------------------------------- | ------------- | + * | 01 | Initialize test variables with an empty key and a value. | key = "", value = 1.23 | Test variables are defined correctly. | Should be successful | + * | 02 | Create a DrmJsonObject instance using default constructor.| No input | Instance of DrmJsonObject is created successfully. | Should be successful | + * | 03 | Invoke the add() method with the empty key and the value. | input: key = "", value = 1.23, output: result | API returns false, and EXPECT_FALSE(result) assertion passes. | Should Fail | + */ +TEST(DrmJsonObject, AddEmptyStringKey) { + std::cout << "Entering AddEmptyStringKey test" << std::endl; + + std::string key = ""; + double value = 1.23; + + std::cout << "Creating DrmJsonObject object using default constructor" << std::endl; + DrmJsonObject jsonObj; + + std::cout << "Invoking add with an empty key and value: " << value << std::endl; + bool result = jsonObj.add(key, value); + + std::cout << "Method add returned: " << std::boolalpha << result << std::endl; + EXPECT_FALSE(result); + + std::cout << "Exiting AddEmptyStringKey test" << std::endl; +} +/** + * @brief Validates that the DrmJsonObject can successfully add a positive integer parameter. + * + * This test verifies that using the default constructor to create a DrmJsonObject, the add() method returns true when invoked with a valid parameter name and a positive integer value. This confirms the correct functionality of the add() method with standard positive integer input. + * + * **Test Group ID:** Basic: 01@n + * **Test Case ID:** 034@n + * **Priority:** High@n + * + * **Pre-Conditions:** None@n + * **Dependencies:** None@n + * **User Interaction:** None@n + * + * **Test Procedure:** + * | Variation / Step | Description | Test Data | Expected Result | Notes | + * | :---------------:| ----------------------------------------------------------------------- | --------------------------------------------------- | ------------------------------------------------- | ----------------- | + * | 01 | Create DrmJsonObject object using the default constructor | none | Object is created without errors | Should be successful | + * | 02 | Invoke add() method with a valid parameter name and positive integer value| name = param1, value = 123, output (result) = true | add() returns true and passes the assertion | Should Pass | + */ +TEST(DrmJsonObject, ValidAddPositiveInt) { + std::cout << "Entering ValidAddPositiveInt test" << std::endl; + + std::string name = "param1"; + int value = 123; + + std::cout << "Creating DrmJsonObject object using default constructor" << std::endl; + DrmJsonObject jsonObj; + + std::cout << "Invoking add() with name: " << name << " and value: " << value << std::endl; + bool result = jsonObj.add(name, value); + std::cout << "add() method returned: " << (result ? "true" : "false") << std::endl; + + EXPECT_TRUE(result); + + std::cout << "Exiting ValidAddPositiveInt test" << std::endl; +} +/** + * @brief Validate that adding a negative integer value to a DrmJsonObject is handled correctly. + * + * This test verifies that the add() method of the DrmJsonObject class accepts and correctly processes a negative integer value. It ensures that negative values are supported and the API returns a successful result. + * + * **Test Group ID:** Basic: 01@n + * **Test Case ID:** 035@n + * **Priority:** High@n + * + * **Pre-Conditions:** None@n + * **Dependencies:** None@n + * **User Interaction:** None@n + * + * **Test Procedure:** + * | Variation / Step | Description | Test Data | Expected Result | Notes | + * | :--------------: | --------------------------------------------------------------------------- | -------------------------------------------------- | ---------------------------------------- | ------------- | + * | 01 | Initialize test parameters with name and negative value | name = param2, value = -456 | Variables initialized | Should be successful | + * | 02 | Create a DrmJsonObject instance using the default constructor | (none) | Object created successfully | Should be successful | + * | 03 | Invoke the add() method with the initialized name and negative value | input1 = name (param2), input2 = value (-456) | API returns true | Should Pass | + * | 04 | Validate the result of the add() method with an assertion check | output1 = result (true) | EXPECT_TRUE(result) passes | Should Pass | + */ +TEST(DrmJsonObject, ValidAddNegativeInt) { + std::cout << "Entering ValidAddNegativeInt test" << std::endl; + + std::string name = "param2"; + int value = -456; + + std::cout << "Creating DrmJsonObject object using default constructor" << std::endl; + DrmJsonObject jsonObj; + + std::cout << "Invoking add() with name: " << name << " and value: " << value << std::endl; + bool result = jsonObj.add(name, value); + std::cout << "add() method returned: " << (result ? "true" : "false") << std::endl; + + EXPECT_TRUE(result); + + std::cout << "Exiting ValidAddNegativeInt test" << std::endl; +} +/** + * @brief Verify that adding a parameter with a zero value is handled correctly by DrmJsonObject + * + * This test ensures that the add() method correctly processes a valid parameter where the value is zero. + * The intent is to validate that the API does not misinterpret a zero value as an error and returns a successful result. + * + * **Test Group ID:** Basic: 01@n + * **Test Case ID:** 036@n + * **Priority:** High@n + * + * **Pre-Conditions:** None@n + * **Dependencies:** None@n + * **User Interaction:** None@n + * + * **Test Procedure:**@n + * | Variation / Step | Description | Test Data | Expected Result | Notes | + * | :--------------: | --------------------------------------------------------------------- | ---------------------------------------------- | ------------------------------------------------------------- | ---------- | + * | 01 | Invoke the add() method on a DrmJsonObject object with name "param_zero" and value 0 | name = param_zero, value = 0, expected_return = true | The add() API returns true and the assertion passes | Should Pass | + */ +TEST(DrmJsonObject, ValidAddZeroValue) { + std::cout << "Entering ValidAddZeroValue test" << std::endl; + + std::string name = "param_zero"; + int value = 0; + + std::cout << "Creating DrmJsonObject object using default constructor" << std::endl; + DrmJsonObject jsonObj; + + std::cout << "Invoking add() with name: " << name << " and value: " << value << std::endl; + bool result = jsonObj.add(name, value); + std::cout << "add() method returned: " << (result ? "true" : "false") << std::endl; + + EXPECT_TRUE(result); + + std::cout << "Exiting ValidAddZeroValue test" << std::endl; +} +/** + * @brief Test to validate that add() fails when provided with an empty name. + * + * This test verifies that invoking the add() method on a DrmJsonObject with an empty string as the name and a valid integer value correctly returns false. The test confirms that the API does not accept an empty string as a valid key, ensuring input validation enforcement. + * + * **Test Group ID:** Basic: 01 + * **Test Case ID:** 037 + * **Priority:** High + * + * **Pre-Conditions:** None + * **Dependencies:** None + * **User Interaction:** None + * + * **Test Procedure:** + * | Variation / Step | Description | Test Data | Expected Result | Notes | + * | :--------------: | ------------------------------------------------------------------- | --------------------------- | ------------------------------------------------------------------------------- | ---------- | + * | 01 | Create a default DrmJsonObject and invoke add() with empty name and value 10 | name = "", value = 10 | add() returns false as empty name is invalid, confirmed by EXPECT_FALSE assertion | Should Fail| + */ +TEST(DrmJsonObject, InvalidAddEmptyName) { + std::cout << "Entering InvalidAddEmptyName test" << std::endl; + + std::string name = ""; + int value = 10; + + std::cout << "Creating DrmJsonObject object using default constructor" << std::endl; + DrmJsonObject jsonObj; + + std::cout << "Invoking add() with empty name and value: " << value << std::endl; + bool result = jsonObj.add(name, value); + std::cout << "add() method returned: " << (result ? "true" : "false") << std::endl; + + EXPECT_FALSE(result); + + std::cout << "Exiting InvalidAddEmptyName test" << std::endl; +} +/** + * @brief Verify that DrmJsonObject::add() returns true when adding INT_MAX as the integer value + * + * This test verifies that the add() method of DrmJsonObject correctly accepts and processes the maximum integer value (INT_MAX). The objective is to ensure that the API handles edge integer values without errors. + * + * **Test Group ID:** Basic: 01@n + * **Test Case ID:** 038@n + * **Priority:** High@n + * + * **Pre-Conditions:** None@n + * **Dependencies:** None@n + * **User Interaction:** None@n + * + * **Test Procedure:**@n + * | Variation / Step | Description | Test Data | Expected Result | Notes | + * | :----: | --------- | ---------- | -------------- | ----- | + * | 01 | Initialize variables with name and value. | name = max_value, value = INT_MAX | Variables hold intended values | Should be successful | + * | 02 | Create DrmJsonObject object using default constructor. | None | Object is successfully created | Should be successful | + * | 03 | Invoke add() method with given parameters. | input: name = max_value, value = INT_MAX; output: expects true | Method returns true | Should Pass | + * | 04 | Validate the return value using EXPECT_TRUE. | result = outcome of add() | Assertion passes confirming the API returns true for valid inputs | Should Pass | + */ +TEST(DrmJsonObject, ValidAddIntMax) { + std::cout << "Entering ValidAddIntMax test" << std::endl; + + std::string name = "max_value"; + int value = INT_MAX; + + std::cout << "Creating DrmJsonObject object using default constructor" << std::endl; + DrmJsonObject jsonObj; + + std::cout << "Invoking add() with name: " << name << " and value: " << value << std::endl; + bool result = jsonObj.add(name, value); + std::cout << "add() method returned: " << (result ? "true" : "false") << std::endl; + + EXPECT_TRUE(result); + + std::cout << "Exiting ValidAddIntMax test" << std::endl; +} +/** + * @brief Validate that the add() API correctly adds an INT_MIN value with a valid key. + * + * This test verifies that when a valid key ("min_value") and the minimum integer value (INT_MIN) are provided to the DrmJsonObject::add() method, the operation succeeds and returns true. + * + * **Test Group ID:** Basic: 01@n + * **Test Case ID:** 039@n + * **Priority:** High@n + * + * **Pre-Conditions:** None@n + * **Dependencies:** None@n + * **User Interaction:** None@n + * + * **Test Procedure:**@n + * | Variation / Step | Description | Test Data | Expected Result | Notes |@n + * | :----: | --------- | ---------- |-------------- | ----- |@n + * | 01 | Initialize test variables (name and value) | name = "min_value", value = INT_MIN | Variables correctly initialized | Should be successful |@n + * | 02 | Create a DrmJsonObject instance using the default constructor | No input, output: DrmJsonObject instance created | Instance is successfully created | Should be successful |@n + * | 03 | Invoke add() method with the initialized name and INT_MIN value | name = "min_value", value = INT_MIN, output: result | add() method returns true | Should Pass |@n + * | 04 | Verify that the API call returns a true value using EXPECT_TRUE | result = true | EXPECT_TRUE assertion passes confirming valid behavior | Should be successful | + */ +TEST(DrmJsonObject, ValidAddIntMin) { + std::cout << "Entering ValidAddIntMin test" << std::endl; + + std::string name = "min_value"; + int value = INT_MIN; + + std::cout << "Creating DrmJsonObject object using default constructor" << std::endl; + DrmJsonObject jsonObj; + + std::cout << "Invoking add() with name: " << name << " and value: " << value << std::endl; + bool result = jsonObj.add(name, value); + std::cout << "add() method returned: " << (result ? "true" : "false") << std::endl; + + EXPECT_TRUE(result); + + std::cout << "Exiting ValidAddIntMin test" << std::endl; +} +/** + * @brief Verify that the add() method handles special characters in the key correctly. + * + * This test verifies that the DrmJsonObject::add() API correctly processes a key containing special characters + * along with a valid integer value. The objective is to ensure the method adds the key-value pair successfully and + * returns true, indicating that the handling of special characters in the key does not affect the functionality. + * + * **Test Group ID:** Basic: 01@n + * **Test Case ID:** 040@n + * **Priority:** High@n + * + * **Pre-Conditions:** None@n + * **Dependencies:** None@n + * **User Interaction:** None@n + * + * **Test Procedure:** + * | Variation / Step | Description | Test Data | Expected Result | Notes | + * | :----: | --------------------------------------------------------------------------- | -------------------------------------------------------------- | -------------------------------------------------------------- | ------------------- | + * | 01 | Initialize test parameters with a key containing special characters and an integer value | name = "special!@#$%^&*()", value = 77 | Variables initialized with expected values | Should be successful| + * | 02 | Create a DrmJsonObject object using the default constructor | None | Object created successfully | Should be successful| + * | 03 | Invoke the add() method with the initialized key and value | name = "special!@#$%^&*()", value = 77 | Return value true from add() indicating successful addition, EXPECT_TRUE assertion passes | Should Pass | + */ +TEST(DrmJsonObject, ValidAddSpecialCharacters) { + std::cout << "Entering ValidAddSpecialCharacters test" << std::endl; + + std::string name = "special!@#$%^&*()"; + int value = 77; + + std::cout << "Creating DrmJsonObject object using default constructor" << std::endl; + DrmJsonObject jsonObj; + + std::cout << "Invoking add() with name: " << name << " and value: " << value << std::endl; + bool result = jsonObj.add(name, value); + std::cout << "add() method returned: " << (result ? "true" : "false") << std::endl; + + EXPECT_TRUE(result); + + std::cout << "Exiting ValidAddSpecialCharacters test" << std::endl; +} +/** + * @brief Validate that a valid positive long value is successfully added to a JSON object. + * + * This test verifies that the DrmJsonObject API correctly adds a valid key associated with a positive long value. + * The test ensures that the add method returns true when provided with proper inputs. + * + * **Test Group ID:** Basic: 01 + * **Test Case ID:** 041 + * **Priority:** High + * + * **Pre-Conditions:** None + * **Dependencies:** None + * **User Interaction:** None + * + * **Test Procedure:** + * | Variation / Step | Description | Test Data | Expected Result | Notes | + * | :--------------: | --------------------------------------------------------------------------------- | ---------------------------------------------------------------- | ----------------------------------------------------------- | ------------------ | + * | 01 | Initialize DrmJsonObject instance and define the test inputs | key = "positiveKey", value = 123 | DrmJsonObject instance created successfully | Should be successful | + * | 02 | Invoke the add() API with the valid key and positive long value | object = DrmJsonObject, key = "positiveKey", value = 123, output: result = true | API returns true, and EXPECT_TRUE(result) passes | Should Pass | + */ +TEST(DrmJsonObject, AddValidPositiveLongValue) { + std::cout << "Entering AddValidPositiveLongValue test" << std::endl; + + DrmJsonObject obj; + + std::string key = "positiveKey"; + long value = 123; + std::cout << "Invoking add with name: \"" << key << "\", value: " << value << std::endl; + + bool result = obj.add(key, value); + std::cout << "Method add returned: " << std::boolalpha << result << std::endl; + + EXPECT_TRUE(result); + + std::cout << "Exiting AddValidPositiveLongValue test" << std::endl; +} +/** + * @brief Test the addition of a valid negative long value with a valid key. + * + * This test verifies that the DrmJsonObject::add method correctly accepts and handles a negative long value when provided with a valid key. It checks that the API returns true and the value is added as expected. + * + * **Test Group ID:** Basic: 01@n + * **Test Case ID:** 042@n + * **Priority:** High@n + * + * **Pre-Conditions:** None@n + * **Dependencies:** None@n + * **User Interaction:** None@n + * + * **Test Procedure:**@n + * | Variation / Step | Description | Test Data | Expected Result | Notes | + * | :--------------: | ----------------------------------------------------------------- | ------------------------------------------ | -------------------------- | ------------------ | + * | 01 | Instantiate DrmJsonObject | None | Object created | Should be successful | + * | 02 | Initialize key ("negativeKey") and negative long value (-456) | key = negativeKey, value = -456 | Values initialized correctly | Should be successful | + * | 03 | Invoke add API with key and negative value | key = negativeKey, value = -456 | API returns true | Should Pass | + * | 04 | Assert that add method returns true | result = true | Assertion passes | Should be successful | + */ +TEST(DrmJsonObject, AddValidNegativeLongValue) { + std::cout << "Entering AddValidNegativeLongValue test" << std::endl; + + DrmJsonObject obj; + + std::string key = "negativeKey"; + long value = -456; + std::cout << "Invoking add with name: \"" << key << "\", value: " << value << std::endl; + + bool result = obj.add(key, value); + std::cout << "Method add returned: " << std::boolalpha << result << std::endl; + + EXPECT_TRUE(result); + + std::cout << "Exiting AddValidNegativeLongValue test" << std::endl; +} +/** + * @brief Validate that adding a key with a zero long value returns true. + * + * This test verifies that the DrmJsonObject correctly handles the insertion of a zero long value. It adds an entry with the key "zeroKey" and value 0, ensuring that the add method returns true. + * + * **Test Group ID:** Basic: 01@n + * **Test Case ID:** 043@n + * **Priority:** High@n + * + * **Pre-Conditions:** None@n + * **Dependencies:** None@n + * **User Interaction:** None@n + * + * **Test Procedure:**@n + * | Variation / Step | Description | Test Data | Expected Result | Notes | + * | :----: | --------- | ---------- |-------------- | ----- | + * | 01 | Instantiate DrmJsonObject object | None | Object instantiated successfully | Should be successful | + * | 02 | Initialize key and value variables | key = "zeroKey", value = 0 | Variables set correctly | Should be successful | + * | 03 | Call add method with key and value | input: key = "zeroKey", value = 0; output: result | Method returns true and EXPECT_TRUE assertion passes | Should Pass | + */ +TEST(DrmJsonObject, AddValidZeroLongValue) { + std::cout << "Entering AddValidZeroLongValue test" << std::endl; + + DrmJsonObject obj; + + std::string key = "zeroKey"; + long value = 0; + std::cout << "Invoking add with name: \"" << key << "\", value: " << value << std::endl; + + bool result = obj.add(key, value); + std::cout << "Method add returned: " << std::boolalpha << result << std::endl; + + EXPECT_TRUE(result); + + std::cout << "Exiting AddValidZeroLongValue test" << std::endl; +} +/** + * @brief Validate adding an entry with maximum long integer value. + * + * Tests that the DrmJsonObject.add() method can correctly add an entry with the key "maxValueKey" and the edge-case value LONG_MAX, ensuring that the JSON object handles maximum integer values properly. + * + * **Test Group ID:** Basic: 01 + * **Test Case ID:** 044 + * **Priority:** High + * + * **Pre-Conditions:** None + * **Dependencies:** None + * **User Interaction:** None + * + * **Test Procedure:** + * | Variation / Step | Description | Test Data | Expected Result | Notes | + * | :--------------: | --------------------------------------------------------- | ------------------------------------------------ | ------------------------------------------------- | ----------------- | + * | 01 | Initialize a DrmJsonObject instance | None | Instance should be created | Should be successful | + * | 02 | Define key "maxValueKey" and assign LONG_MAX to value | key = "maxValueKey", value = LONG_MAX | Variables key and value set correctly | Should be successful | + * | 03 | Call the add() method with the defined key and value | input key = "maxValueKey", input value = LONG_MAX | add() should return true | Should Pass | + * | 04 | Assert that the returned value is true using EXPECT_TRUE | output result = true | EXPECT_TRUE assertion should pass | Should Pass | + */ +TEST(DrmJsonObject, AddEntryWithMaxLongValue) { + std::cout << "Entering AddEntryWithMaxLongValue test" << std::endl; + + DrmJsonObject obj; + + std::string key = "maxValueKey"; + long value = LONG_MAX; + std::cout << "Invoking add with name: \"" << key << "\", value: " << value << std::endl; + + bool result = obj.add(key, value); + std::cout << "Method add returned: " << std::boolalpha << result << std::endl; + + EXPECT_TRUE(result); + + std::cout << "Exiting AddEntryWithMaxLongValue test" << std::endl; +} +/** + * @brief Verifies that adding an entry with the minimum long value returns true. + * + * This test instantiates a DrmJsonObject and attempts to add an entry where the key is "minValueKey" + * and the value is LONG_MIN. The test is used to confirm that the API can handle extreme negative + * numerical values correctly without any overflow or underflow issues. + * + * **Test Group ID:** Basic: 01@n + * **Test Case ID:** 045@n + * **Priority:** High@n + * + * **Pre-Conditions:** None@n + * **Dependencies:** None@n + * **User Interaction:** None@n + * + * **Test Procedure:** + * | Variation / Step | Description | Test Data | Expected Result | Notes | + * | :--------------: | -------------------------------------------------------------------- | ---------------------------------------------- | -----------------------------------------------------| -------------- | + * | 01 | Initialize an instance of DrmJsonObject | None | DrmJsonObject instance is created successfully | Should be successful | + * | 02 | Set the key to "minValueKey" and value to LONG_MIN | key = "minValueKey", value = LONG_MIN | Input parameters are set correctly | Should be successful | + * | 03 | Invoke the add method with the prepared inputs | input1 = key "minValueKey", input2 = LONG_MIN, output1 = result | API returns true; EXPECT_TRUE(result) assertion passes | Should Pass | + */ +TEST(DrmJsonObject, AddEntryWithMinLongValue) { + std::cout << "Entering AddEntryWithMinLongValue test" << std::endl; + + DrmJsonObject obj; + + std::string key = "minValueKey"; + long value = LONG_MIN; + std::cout << "Invoking add with name: \"" << key << "\", value: " << value << std::endl; + + bool result = obj.add(key, value); + std::cout << "Method add returned: " << std::boolalpha << result << std::endl; + + EXPECT_TRUE(result); + + std::cout << "Exiting AddEntryWithMinLongValue test" << std::endl; +} +/** + * @brief Test to verify that adding an entry with an empty key returns false. + * + * This test validates that the DrmJsonObject::add API method properly rejects an entry when provided with an empty key. + * It checks that the method returns false and that the negative scenario is correctly handled. + * + * **Test Group ID:** Basic: 01@n + * **Test Case ID:** 046@n + * **Priority:** High@n + * + * **Pre-Conditions:** None@n + * **Dependencies:** None@n + * **User Interaction:** None@n + * + * **Test Procedure:**@n + * | Variation / Step | Description | Test Data | Expected Result | Notes | + * | :--------------: | -------------------------------------------------------------- | --------------------------------- | ------------------------------------------------------------- | -------------- | + * | 01 | Initialize a DrmJsonObject instance and prepare test data | N/A | DrmJsonObject instance created successfully | Should be successful | + * | 02 | Invoke API method add with an empty key and a valid value | key = "", value = 100 | Return value should be false and the assertion EXPECT_FALSE passes | Should Fail | + */ +TEST(DrmJsonObject, AddEntryWithEmptyName) { + std::cout << "Entering AddEntryWithEmptyName test" << std::endl; + + DrmJsonObject obj; + + std::string key = ""; + long value = 100; + std::cout << "Invoking add with an empty name, value: " << value << std::endl; + + bool result = obj.add(key, value); + std::cout << "Method add returned: " << std::boolalpha << result << std::endl; + + EXPECT_FALSE(result); + + std::cout << "Exiting AddEntryWithEmptyName test" << std::endl; +} +/** + * @brief Test the add() method of DrmJsonObject with a valid name and a non-empty vector of pointers. + * + * This test verifies that the add() method correctly handles a valid input, where the main JSON object is + * provided with a non-empty vector containing two valid pointers to DrmJsonObject instances. The test ensures + * that the method returns true as expected when valid data is provided. + * + * **Test Group ID:** Basic: 01@n + * **Test Case ID:** 047@n + * **Priority:** High@n + * + * **Pre-Conditions:** None@n + * **Dependencies:** None@n + * **User Interaction:** None@n + * + * **Test Procedure:**@n + * | Variation / Step | Description | Test Data | Expected Result | Notes | + * | :----: | --------- | ---------- | -------------- | ----- | + * | 01 | Create main DrmJsonObject instance and allocate two valid DrmJsonObject pointers; add them to a vector. | json = default constructor, obj1 = new DrmJsonObject, obj2 = new DrmJsonObject, vector = {obj1, obj2} | Main object and vector are properly initialized with two valid pointer entries. | Should be successful | + * | 02 | Invoke the add() method on the main DrmJsonObject with a valid name and the non-empty vector. | name = "validArray", vector size = 2 | Method returns true and EXPECT_TRUE assertion passes. | Should Pass | + * | 03 | Clean up the allocated memory by deleting the two DrmJsonObject instances. | delete obj1, delete obj2 | Memory is successfully freed without errors. | Should be successful | + */ +TEST(DrmJsonObject, ValidInputWithNonEmptyVector) { + std::cout << "Entering ValidInputWithNonEmptyVector test" << std::endl; + + // Create main json object using default constructor + DrmJsonObject json; + + // Create vector with two valid pointers to DrmJsonObject instances + std::vector values; + DrmJsonObject* obj1 = new DrmJsonObject(); + DrmJsonObject* obj2 = new DrmJsonObject(); + values.push_back(obj1); + values.push_back(obj2); + + std::string name = "validArray"; + std::cout << "Invoking add with name: \"" << name << "\" and vector size: " << values.size() << std::endl; + + // Call the add method and capture the result + bool result = json.add(name, values); + std::cout << "Method add returned: " << std::boolalpha << result << std::endl; + + // Expect true based on test plan + EXPECT_TRUE(result); + + // Clean up the allocated memory + delete obj1; + delete obj2; + + std::cout << "Exiting ValidInputWithNonEmptyVector test" << std::endl; +} +/** + * @brief Validate that the add method returns true when an empty vector is provided. + * + * This test verifies that the DrmJsonObject::add method behaves correctly when passed a valid name ("emptyArray") along with an empty vector of DrmJsonObject pointers. It ensures that the method handles this edge case without error and returns true as expected. + * + * **Test Group ID:** Basic: 01@n + * **Test Case ID:** 048@n + * **Priority:** High@n + * + * **Pre-Conditions:** None@n + * **Dependencies:** None@n + * **User Interaction:** None@n + * + * **Test Procedure:** + * | Variation / Step | Description | Test Data | Expected Result | Notes | + * | :----: | --------- | ---------- | -------------- | ----- | + * | 01 | Create a DrmJsonObject using the default constructor. | No inputs. | Object is instantiated successfully. | Should be successful | + * | 02 | Create an empty vector of DrmJsonObject pointers. | No elements. | Empty vector is created. | Should be successful | + * | 03 | Set the test name to "emptyArray" and log the step. | name = "emptyArray" | Name is set correctly. | Should be successful | + * | 04 | Call the add method with "emptyArray" and the empty vector, then capture the result. | input: name = "emptyArray", values = empty vector; output: result | add returns true. | Should Pass | + * | 05 | Validate the result using EXPECT_TRUE. | result = true | The assertion passes confirming the API works as expected. | Should Pass | + */ +TEST(DrmJsonObject, ValidInputWithEmptyVector) { + std::cout << "Entering ValidInputWithEmptyVector test" << std::endl; + + // Create main json object using default constructor + DrmJsonObject json; + + // Create an empty vector of DrmJsonObject pointers + std::vector values; + + std::string name = "emptyArray"; + std::cout << "Invoking add with name: \"" << name << "\" and empty vector" << std::endl; + + // Call the add method and capture the result + bool result = json.add(name, values); + std::cout << "Method add returned: " << std::boolalpha << result << std::endl; + + // Expect true for an empty vector + EXPECT_TRUE(result); + + std::cout << "Exiting ValidInputWithEmptyVector test" << std::endl; +} +/** + * @brief Validate that the add method returns false when given an empty name input. + * + * This test verifies that the add API of DrmJsonObject correctly handles invalid input, + * specifically when an empty string is provided as the name while the object vector contains + * a valid DrmJsonObject pointer. The expected behavior is that the API should return false, + * indicating the failure to add due to an invalid name. + * + * **Test Group ID:** Basic: 01 + * **Test Case ID:** 049 + * **Priority:** High + * + * **Pre-Conditions:** None + * **Dependencies:** None + * **User Interaction:** None + * + * **Test Procedure:** + * | Variation / Step | Description | Test Data | Expected Result | Notes | + * | :--------------: | --------------------------------------------------------------------- | ------------------------------------------------- | -------------------------------------------------------------------------- | --------------- | + * | 01 | Instantiate a DrmJsonObject using the default constructor. | None | A json object is created. | Should be successful | + * | 02 | Create a vector and add one valid DrmJsonObject pointer to it. | vector = {DrmJsonObject* obj, allocated} | Vector contains one valid pointer. | Should be successful | + * | 03 | Invoke the add method with an empty name and the vector. | name = "", values = {DrmJsonObject* obj} | API returns false; EXPECT_FALSE(result) assertion passes. | Should Pass | + * | 04 | Clean up the dynamically allocated DrmJsonObject pointer. | delete obj | Memory is freed without leaks. | Should be successful | + */ +TEST(DrmJsonObject, InvalidInputEmptyName) { + std::cout << "Entering InvalidInputEmptyName test" << std::endl; + + // Create main json object using default constructor + DrmJsonObject json; + + // Create vector with one valid DrmJsonObject pointer + std::vector values; + DrmJsonObject* obj = new DrmJsonObject(); + values.push_back(obj); + + std::string name = ""; + std::cout << "Invoking add with empty name and vector size: " << values.size() << std::endl; + + // Call the add method and capture the result + bool result = json.add(name, values); + std::cout << "Method add returned: " << std::boolalpha << result << std::endl; + + // Expect false due to empty name + EXPECT_FALSE(result); + + // Clean up allocated memory + delete obj; + + std::cout << "Exiting InvalidInputEmptyName test" << std::endl; +} +/** + * @brief Verify that adding an element array containing a nullptr fails. + * + * This test verifies that adding a vector containing a nullptr element to a DrmJsonObject correctly fails. + * It ensures that the API robustly checks for invalid inputs by returning false when encountering a nullptr. + * + * **Test Group ID:** Basic: 01@n + * **Test Case ID:** 050@n + * **Priority:** High@n + * + * **Pre-Conditions:** None@n + * **Dependencies:** None@n + * **User Interaction:** None@n + * + * **Test Procedure:** + * | Variation / Step | Description | Test Data | Expected Result | Notes | + * | :--------------: | ------------------------------------------------------------------ | -------------------------------------------------------------- | ------------------------------------------------------------------------ | ------------- | + * | 01 | Initialize a DrmJsonObject instance using the default constructor. | No inputs; output: json object constructed. | DrmJsonObject instance is successfully created. | Should be successful | + * | 02 | Create a vector and add a nullptr element to it. | values = vector containing nullptr. | Vector is created with a nullptr element. | Should be successful | + * | 03 | Invoke the add method with a valid name and the vector containing nullptr. | name = "arrayWithNull", values = [nullptr]. | API returns false indicating the operation failed due to invalid input. | Should Fail | + * | 04 | Validate the return value using EXPECT_FALSE. | result = false. | The assertion confirms that the API returned false. | Should Fail | + */ +TEST(DrmJsonObject, InvalidInputWithNullptrElements) { + std::cout << "Entering InvalidInputWithNullptrElements test" << std::endl; + + // Create main json object using default constructor + DrmJsonObject json; + + // Create vector containing a nullptr element + std::vector values; + values.push_back(nullptr); + + std::string name = "arrayWithNull"; + std::cout << "Invoking add with name: \"" << name << "\" and vector containing nullptr" << std::endl; + + // Call the add method and capture the result + bool result = json.add(name, values); + std::cout << "Method add returned: " << std::boolalpha << result << std::endl; + + // Expect false since vector contains a nullptr + EXPECT_FALSE(result); + + std::cout << "Exiting InvalidInputWithNullptrElements test" << std::endl; +} +/** + * @brief Verify the retrieval of an existing nested JSON object using the get() method. + * + * This test checks that a primary JSON object correctly retrieves a valid nested JSON object under the key "settings". + * It validates that the nested JSON contains the expected properties "volume" and "mode", ensuring that the API behaves as expected. + * + * **Test Group ID:** Basic: 01@n + * **Test Case ID:** 051@n + * **Priority:** High@n + * + * **Pre-Conditions:** None@n + * **Dependencies:** None@n + * **User Interaction:** None@n + * + * **Test Procedure:**@n + * | Variation / Step | Description | Test Data | Expected Result | Notes | + * | :----: | --------- | ---------- |-------------- | ----- | + * | 01 | Create primary DrmJsonObject with a nested "settings" JSON object | jsonInput = "{\"settings\": {\"volume\": 50, \"mode\": \"auto\"}}" | Primary object is instantiated successfully with valid nested JSON | Should be successful | + * | 02 | Invoke get() method to retrieve the nested object into nestedObj | input1 = "settings", output1 = nestedObj | get() returns true indicating successful retrieval | Should Pass | + * | 03 | Validate the retrieved nested object's contents contain "volume" and "mode" | nestedContent = result of nestedObj.print() | Assert that "volume" and "mode" keys are present in the output string | Should Pass | + */ +TEST(DrmJsonObject, RetrieveExistingNestedJSONObject) { + std::cout << "Entering RetrieveExistingNestedJSONObject test" << std::endl; + + // Create primary JSON object with a valid nested JSON object for "settings" + std::string jsonInput = "{\"settings\": {\"volume\": 50, \"mode\": \"auto\"}}"; + std::cout << "Creating main DrmJsonObject with JSON: " << jsonInput << std::endl; + DrmJsonObject mainObj(jsonInput); + + // Create an empty DrmJsonObject that will be populated by get() + DrmJsonObject nestedObj; + + std::cout << "Invoking get(\"settings\", nestedObj)" << std::endl; + bool result = mainObj.get("settings", nestedObj); + std::cout << "Returned value from get(): " << std::boolalpha << result << std::endl; + + // Check that the retrieval is successful + ASSERT_TRUE(result); + + // Debug: print the retrieved nested JSON object's content + std::string nestedContent = nestedObj.print(); + std::cout << "Retrieved nested object content: " << nestedContent << std::endl; + ASSERT_NE(nestedContent.find("volume"), std::string::npos); + ASSERT_NE(nestedContent.find("mode"), std::string::npos); + + std::cout << "Exiting RetrieveExistingNestedJSONObject test" << std::endl; +} +/** + * @brief Validate retrieval of a non-existent property from DrmJsonObject + * + * This test verifies that when attempting to retrieve a property ("missing") that does not exist in the JSON input, + * the get() method returns false and the output object remains unchanged. + * + * **Test Group ID:** Basic: 01@n + * **Test Case ID:** 052@n + * **Priority:** High@n + * + * **Pre-Conditions:** None@n + * **Dependencies:** None@n + * **User Interaction:** None@n + * + * **Test Procedure:** + * | Variation / Step | Description | Test Data | Expected Result | Notes | + * | :--------------: | --------------------------------------------------------------------------------------------- | -------------------------------------------------------------------------------------------------------------------------- | -------------------------------------------------------------------------------------------------------------------- | ------------- | + * | 01 | Create main DrmJsonObject with JSON that does not include the "missing" property and an empty outObj | input jsonInput = {"settings": {"brightness": 75}}, outObj = default constructed DrmJsonObject | mainObj is constructed correctly, outObj is empty | Should be successful | + * | 02 | Invoke get("missing", outObj) on mainObj to attempt retrieval of the non-existent property | mainObj, property = missing, outObj; get() is called | get() returns false; ASSERT_FALSE(result) passes | Should Fail | + * | 03 | Verify that outObj remains unchanged after the failed retrieval | outObj printed content after get() call | outObj content remains unchanged (empty JSON) | Should be successful | + */ +TEST(DrmJsonObject, RetrieveNonExistentProperty) { + std::cout << "Entering RetrieveNonExistentProperty test" << std::endl; + + // Create JSON object without the 'missing' property + std::string jsonInput = "{\"settings\": {\"brightness\": 75}}"; + std::cout << "Creating main DrmJsonObject with JSON: " << jsonInput << std::endl; + DrmJsonObject mainObj(jsonInput); + + // Create an empty DrmJsonObject which is expected to remain unchanged + DrmJsonObject outObj; + + std::cout << "Invoking get(\"missing\", outObj)" << std::endl; + bool result = mainObj.get("missing", outObj); + std::cout << "Returned value from get(): " << std::boolalpha << result << std::endl; + + // Check that the retrieval fails + ASSERT_FALSE(result); + + // Optionally check that outObj remains unchanged (printing its content) + std::string outContent = outObj.print(); + std::cout << "outObj content after failed get: " << outContent << std::endl; + + std::cout << "Exiting RetrieveNonExistentProperty test" << std::endl; +} +/** + * @brief Validate that retrieving a non-object property using get() fails as expected + * + * This test checks that when attempting to retrieve a JSON property that exists as a string rather than a nested JSON object, + * the get() method returns false and does not modify the output object. This behavior ensures that only properties of the expected type are retrieved. + * + * **Test Group ID:** Basic: 01@n + * **Test Case ID:** 053@n + * **Priority:** High@n + * + * **Pre-Conditions:** None@n + * **Dependencies:** None@n + * **User Interaction:** None@n + * + * **Test Procedure:** + * | Variation / Step | Description | Test Data | Expected Result | Notes | + * | :----: | ----------------------------------------------------------------------------------------- | ----------------------------------------------------------- | -------------------------------------------------------------------------------------- | --------------- | + * | 01 | Create a JSON object with a string property "name". | jsonInput = {"name": "TestUser"} | DrmJsonObject instance is created with the given JSON string | Should be successful | + * | 02 | Initialize an empty DrmJsonObject to capture the output. | outObj is uninitialized | An empty DrmJsonObject is available | Should be successful | + * | 03 | Invoke get() to retrieve the "name" property as a nested JSON object into outObj. | property key = "name", outObj = empty object | get() returns false indicating failure as the "name" property is not a nested JSON object | Should Fail | + * | 04 | Print the content of outObj to verify that it remains unchanged (empty or invalid). | Call print() on outObj | Output remains unchanged and indicates that outObj is empty or invalid | Should be successful | + */ +TEST(DrmJsonObject, RetrieveNonObjectProperty) { + std::cout << "Entering RetrieveNonObjectProperty test" << std::endl; + + // Create JSON object where "name" exists as a string property + std::string jsonInput = "{\"name\": \"TestUser\"}"; + std::cout << "Creating main DrmJsonObject with JSON: " << jsonInput << std::endl; + DrmJsonObject mainObj(jsonInput); + + // Create an empty DrmJsonObject to attempt to populate + DrmJsonObject outObj; + + std::cout << "Invoking get(\"name\", outObj)" << std::endl; + bool result = mainObj.get("name", outObj); + std::cout << "Returned value from get(): " << std::boolalpha << result << std::endl; + + // Expected to fail because "name" is a string, not a nested JSON object + ASSERT_FALSE(result); + + // Print the content of outObj to show it remains unchanged (likely empty or invalid) + std::string outContent = outObj.print(); + std::cout << "outObj content after get call: " << outContent << std::endl; + + std::cout << "Exiting RetrieveNonObjectProperty test" << std::endl; +} +/** + * @brief Verify that retrieving a value with an empty key fails. + * + * This test validates that when an empty key ("") is passed to the get() method of DrmJsonObject, + * the API correctly returns false and does not modify the output DrmJsonObject. This scenario is crucial + * to ensure that invalid key access is properly handled. + * + * **Test Group ID:** Basic: 01 + * **Test Case ID:** 054 + * **Priority:** High + * + * **Pre-Conditions:** None + * **Dependencies:** None + * **User Interaction:** None + * + * **Test Procedure:** + * | Variation / Step | Description | Test Data | Expected Result | Notes | + * | :--------------: | ---------------------------------------------------------------------- | ------------------------------------------------------------------------------------------ | ---------------------------------------------------------------- | ------------- | + * | 01 | Initialize main DrmJsonObject with valid JSON string | jsonInput = {"config": {"enabled": true}} | Object created successfully | Should be successful | + * | 02 | Create an empty DrmJsonObject for potential population | No input arguments | Empty object remains unchanged | Should be successful | + * | 03 | Invoke get() with an empty key and capture the return result | input key = "", outObj = empty DrmJsonObject | get() returns false indicating empty key not found | Should Fail | + * | 04 | Verify that outObj was not modified by printing its contents | No input, output captured from outObj.print() | outObj remains unpopulated (empty or default state) | Should be successful | + */ +TEST(DrmJsonObject, RetrieveWithEmptyKey) { + std::cout << "Entering RetrieveWithEmptyKey test" << std::endl; + + // Create JSON object that does not define an empty key property + std::string jsonInput = "{\"config\": {\"enabled\": true}}"; + std::cout << "Creating main DrmJsonObject with JSON: " << jsonInput << std::endl; + DrmJsonObject mainObj(jsonInput); + + // Create an empty DrmJsonObject that is expected to remain unchanged + DrmJsonObject outObj; + + std::cout << "Invoking get(\"\"," " outObj)" << std::endl; + bool result = mainObj.get("", outObj); + std::cout << "Returned value from get() with empty key: " << std::boolalpha << result << std::endl; + + // Expected to fail because an empty key property doesn't exist + ASSERT_FALSE(result); + + // Print the content of outObj to demonstrate it was not populated + std::string outContent = outObj.print(); + std::cout << "outObj content after get with empty key: " << outContent << std::endl; + + std::cout << "Exiting RetrieveWithEmptyKey test" << std::endl; +} +/** + * @brief Verify that the DrmJsonObject API retrieves a valid double value for an existing JSON property. + * + * This test case creates an instance of DrmJsonObject and attempts to retrieve a double value + * from the JSON property named "price". It verifies that the get() method returns true and that the retrieved + * value is different from its initialized default of 0.0, confirming proper modification. + * + * **Test Group ID:** Basic: 01@n + * **Test Case ID:** 055@n + * **Priority:** High@n + * + * **Pre-Conditions:** None@n + * **Dependencies:** None@n + * **User Interaction:** None@n + * + * **Test Procedure:** + * | Variation / Step | Description | Test Data | Expected Result | Notes | + * | :----: | --------- | ---------- | -------------- | ----- | + * | 01 | Instantiate DrmJsonObject object | None | Object instance created | Should be successful | + * | 02 | Prepare input variables with property name "price" and initial retrievedValue 0.0 | propertyName = price, retrievedValue = 0.0 | Variables are initialized properly | Should be successful | + * | 03 | Invoke get API to retrieve double value from JSON property | propertyName = price, retrievedValue = 0.0 | get() returns true indicating successful retrieval | Should Pass | + * | 04 | Validate that the retrieved value is modified (not 0.0) | retrievedValue != 0.0 | EXPECT_NE passes confirming the value was updated | Should be successful | + */ +TEST(DrmJsonObject, ValidDoubleValueRetrievalFromJSONProperty) { + std::cout << "Entering ValidDoubleValueRetrievalFromJSONProperty test" << std::endl; + + // Create object of DrmJsonObject using default constructor. + DrmJsonObject jsonObj; + std::cout << "Created DrmJsonObject instance." << std::endl; + + // Prepare input values. + std::string propertyName = "price"; + double retrievedValue = 0.0; + std::cout << "Invoking get with name: " << propertyName << " and initial value: " << retrievedValue << std::endl; + + // Invoke the method. + bool result = jsonObj.get(propertyName, retrievedValue); + std::cout << "Method get returned: " << std::boolalpha << result << std::endl; + + // If retrieval was successful, log the retrieved value. + if(result) { + std::cout << "Retrieved double value: " << retrievedValue << std::endl; + } + + // Validate expected outcome. + EXPECT_TRUE(result); + // Validate that the retrieved value is not left unmodified. + EXPECT_NE(retrievedValue, 0.0); + + std::cout << "Exiting ValidDoubleValueRetrievalFromJSONProperty test" << std::endl; +} +/** + * @brief Test retrieval of a non-existent property from DrmJsonObject to ensure proper error handling + * + * This test verifies that attempting to retrieve a value using a non-existent property key from a DrmJsonObject instance returns false and leaves the initial value unchanged. The test ensures that the API handles missing keys correctly without causing side effects. + * + * **Test Group ID:** Basic: 01@n + * **Test Case ID:** 056@n + * **Priority:** High@n + * + * **Pre-Conditions:** None@n + * **Dependencies:** None@n + * **User Interaction:** None@n + * + * **Test Procedure:** + * | Variation / Step | Description | Test Data | Expected Result | Notes | + * | :----: | -------------------------------------------------------------------------------------------- | --------------------------------------------------------------- | ------------------------------------------------------------------- | -------------- | + * | 01 | Instantiate DrmJsonObject using default constructor | None | Valid instance created | Should be successful | + * | 02 | Set non-existent property name to "nonexistent" and initialize retrieved value to 0.0 | propertyName = nonexistent, retrievedValue = 0.0 | Variables initialized correctly | Should be successful | + * | 03 | Invoke get method on jsonObj with the non-existent property and verify the returned value | input: propertyName = nonexistent, retrievedValue = 0.0, output: expected false | API returns false and retrievedValue remains unchanged | Should Pass | + */ +TEST(DrmJsonObject, RetrievalOfNonexistentProperty) { + std::cout << "Entering RetrievalOfNonexistentProperty test" << std::endl; + + // Create object of DrmJsonObject using default constructor. + DrmJsonObject jsonObj; + std::cout << "Created DrmJsonObject instance." << std::endl; + + // Prepare non-existent property key. + std::string propertyName = "nonexistent"; + double retrievedValue = 0.0; + std::cout << "Invoking get with name: " << propertyName << " and initial value: " << retrievedValue << std::endl; + + // Invoke the method. + bool result = jsonObj.get(propertyName, retrievedValue); + std::cout << "Method get returned: " << std::boolalpha << result << std::endl; + + // Validate expected outcome. + EXPECT_FALSE(result); + + std::cout << "Exiting RetrievalOfNonexistentProperty test" << std::endl; +} +/** + * @brief Test invalid retrieval when an empty property name is provided using DrmJsonObject. + * + * This test verifies that when an empty property name is used to retrieve a value from a DrmJsonObject instance, the get method returns false, ensuring that the API correctly handles invalid input. + * + * **Test Group ID:** Basic: 01@n + * **Test Case ID:** 057@n + * **Priority:** High@n + * + * **Pre-Conditions:** None@n + * **Dependencies:** None@n + * **User Interaction:** None@n + * + * **Test Procedure:**@n + * | Variation / Step | Description | Test Data | Expected Result | Notes | + * | :----: | --------- | ---------- |-------------- | ----- | + * | 01 | Create DrmJsonObject instance using default constructor. | None | Instance is created successfully. | Should be successful | + * | 02 | Initialize empty property name and default retrieval value. | propertyName = "", retrievedValue = 0.0 | Values initialized correctly. | Should be successful | + * | 03 | Invoke the get method with an empty property name to attempt retrieval. | propertyName = "", retrievedValue = 0.0 | API returns false indicating invalid retrieval. | Should Fail | + * | 04 | Validate that the get method returned false. | result = false expected | EXPECT_FALSE assertion passes. | Should be successful | + */ +TEST(DrmJsonObject, InvalidRetrievalWithEmptyPropertyName) { + std::cout << "Entering InvalidRetrievalWithEmptyPropertyName test" << std::endl; + + // Create object of DrmJsonObject using default constructor. + DrmJsonObject jsonObj; + std::cout << "Created DrmJsonObject instance." << std::endl; + + // Use an empty string for property name. + std::string propertyName = ""; + double retrievedValue = 0.0; + std::cout << "Invoking get with an empty property name and initial value: " << retrievedValue << std::endl; + + // Invoke the method. + bool result = jsonObj.get(propertyName, retrievedValue); + std::cout << "Method get returned: " << std::boolalpha << result << std::endl; + + // Validate expected outcome. + EXPECT_FALSE(result); + + std::cout << "Exiting InvalidRetrievalWithEmptyPropertyName test" << std::endl; +} +/** + * @brief Validate that a valid integer property exists and is correctly retrieved from DrmJsonObject. + * + * This test verifies that the DrmJsonObject correctly updates an integer property from its default sentinel value + * after retrieving a valid property ("validInt"). The purpose is to ensure that the get method works as expected for integer values. + * + * **Test Group ID:** Basic: 01 + * **Test Case ID:** 058 + * **Priority:** High + * + * **Pre-Conditions:** None + * **Dependencies:** None + * **User Interaction:** None + * + * **Test Procedure:** + * | Variation / Step | Description | Test Data | Expected Result | Notes | + * | :--------------: | ------------------------------------------------------------------ | -------------------------------------------------- | --------------------------------------------------------- | ---------------- | + * | 01 | Instantiate DrmJsonObject using default constructor | N/A | Object is instantiated | Should be successful | + * | 02 | Initialize variable 'value' with sentinel value | value = -999 | 'value' is set to -999 | Should be successful | + * | 03 | Invoke get method with property "validInt" and initial value -999 | property = validInt, input value = -999 | API returns true and updates 'value' | Should Pass | + * | 04 | Validate that the retrieved value is different from the sentinel | result from get = true, value != -999 | Assertions pass confirming valid property retrieval | Should Pass | + */ +TEST(DrmJsonObject, ValidIntegerPropertyExists) { + std::cout << "Entering ValidIntegerPropertyExists test" << std::endl; + + // Create DrmJsonObject using the default constructor. + DrmJsonObject obj; + + // Prepare the value variable with a sentinel value. + int value = -999; + std::cout << "Initial value set to: " << value << std::endl; + + // Log the method invocation. + std::cout << "Invoking get with name: \"validInt\" and initial value: " << value << std::endl; + bool result = obj.get("validInt", value); + + // Log the returned result and the updated value. + std::cout << "Method get returned: " << std::boolalpha << result << " with value updated to: " << value << std::endl; + + // Validate that the property exists and its integer value was retrieved. + EXPECT_TRUE(result); + // Ensure that the value is updated from the sentinel. + EXPECT_NE(value, -999); + + std::cout << "Exiting ValidIntegerPropertyExists test" << std::endl; +} +/** + * @brief Validate that retrieving a non-existent property does not modify the initial provided value and returns false. + * + * Test verifies that calling get on a non-existent property correctly returns false and leaves the initial value unchanged. + * + * **Test Group ID:** Basic: 01@n + * **Test Case ID:** 059@n + * **Priority:** High@n + * + * **Pre-Conditions:** None@n + * **Dependencies:** None@n + * **User Interaction:** None@n + * + * **Test Procedure:** + * | Variation / Step | Description | Test Data | Expected Result | Notes | + * | :----: | --------- | ---------- |-------------- | ----- | + * | 01 | Create DrmJsonObject using the default constructor | N/A | Object instantiated successfully | Should be successful | + * | 02 | Set an initial arbitrary value and log the value | initialValue = 1234, value = 1234 | Value is set and logged correctly | Should be successful | + * | 03 | Invoke get with name "nonexistent" and provided initial value | property = "nonexistent", value = 1234 | get returns false; initial value remains unchanged | Should Pass | + * | 04 | Validate the returned result and unchanged value using assertions | result = false, value = 1234, initialValue = 1234 | EXPECT_FALSE(result) and EXPECT_EQ(value, initialValue) pass | Should Pass | + */ +TEST(DrmJsonObject, PropertyDoesNotExist) { + std::cout << "Entering PropertyDoesNotExist test" << std::endl; + + // Create DrmJsonObject using the default constructor. + DrmJsonObject obj; + + // Set the value variable to an arbitrary initial value. + int initialValue = 1234; + int value = initialValue; + std::cout << "Initial value set to: " << value << std::endl; + + // Log the method invocation. + std::cout << "Invoking get with name: \"nonexistent\" and initial value: " << value << std::endl; + bool result = obj.get("nonexistent", value); + + // Log the returned result and check if value remains unchanged. + std::cout << "Method get returned: " << std::boolalpha << result << " with value remaining: " << value << std::endl; + + // Validate that get returns false and value remains unchanged. + EXPECT_FALSE(result); + EXPECT_EQ(value, initialValue); + + std::cout << "Exiting PropertyDoesNotExist test" << std::endl; +} +/** + * @brief Verify that DrmJsonObject::get does not modify an integer when the underlying property is not an integer + * + * This test checks that when attempting to retrieve a property "stringValue" that is not an integer, the get method returns false and leaves the passed integer value unchanged. This behavior is crucial to ensure type safety and correct error handling within the DrmJsonObject API. + * + * **Test Group ID:** Basic: 01 + * **Test Case ID:** 060 + * **Priority:** High + * + * **Pre-Conditions:** None + * **Dependencies:** None + * **User Interaction:** None + * + * **Test Procedure:** + * | Variation / Step | Description | Test Data | Expected Result | Notes | + * | :--------------: | ----------------------------------------------------------------------------------------------------- | ------------------------------------------------------- | ------------------------------------------------------------------- | --------------- | + * | 01 | Create an instance of DrmJsonObject using the default constructor. | None | DrmJsonObject instance should be created successfully. | Should be successful | + * | 02 | Set an arbitrary initial integer value and log it. | initialValue = 5678, value = 5678 | Variable is set with the correct initial value. | Should be successful | + * | 03 | Invoke the get method with the name "stringValue" to attempt conversion, expecting failure. | name = stringValue, value = 5678 | get method returns false indicating failure to convert non-integer. | Should Fail | + * | 04 | Verify that the returned boolean is false and that the integer value remains unchanged after the call. | result = false, value = 5678 | Assertions pass confirming false return and unchanged integer value. | Should be successful | + */ +TEST(DrmJsonObject, PropertyIsNotInteger) { + std::cout << "Entering PropertyIsNotInteger test" << std::endl; + + // Create DrmJsonObject using the default constructor. + DrmJsonObject obj; + + // Set the value variable to an arbitrary initial value. + int initialValue = 5678; + int value = initialValue; + std::cout << "Initial value set to: " << value << std::endl; + + // Log the method invocation. + std::cout << "Invoking get with name: \"stringValue\" (expected value is not an integer) and initial value: " << value << std::endl; + bool result = obj.get("stringValue", value); + + // Log the returned result and check if value remains unchanged. + std::cout << "Method get returned: " << std::boolalpha << result << " with value remaining: " << value << std::endl; + + // Validate that get returns false and the integer value remains unchanged. + EXPECT_FALSE(result); + EXPECT_EQ(value, initialValue); + + std::cout << "Exiting PropertyIsNotInteger test" << std::endl; +} +/** + * @brief Verifies that providing an empty property name to the get API does not alter the value. + * + * This test confirms that when an empty property name is passed to the get method of a DrmJsonObject along with an initial value, the method returns false and the value remains unchanged. This check is vital to ensure the object's behavior is correct in handling invalid or empty input strings. + * + * **Test Group ID:** Basic: 01@n + * **Test Case ID:** 061@n + * **Priority:** High@n + * + * **Pre-Conditions:** None@n + * **Dependencies:** None@n + * **User Interaction:** None@n + * + * **Test Procedure:**@n + * | Variation / Step | Description | Test Data | Expected Result | Notes |@n + * | :----: | --------- | ---------- |-------------- | ----- |@n + * | 01 | Create a DrmJsonObject instance using the default constructor | None | Object is created successfully | Should be successful |@n + * | 02 | Set initial value for testing by assigning 91011 to both initialValue and value | initialValue = 91011, value = 91011 | The value is set correctly | Should be successful |@n + * | 03 | Invoke the get method with an empty property name and the initial value | property name = "", value = 91011 | get returns false and value remains unchanged (91011) | Should Pass |@n + * | 04 | Validate the output by asserting that get returns false and the value stays equal to the initial value | result = false, value = 91011 | EXPECT_FALSE(result) and EXPECT_EQ(value, initialValue) pass | Should Pass | + */ +TEST(DrmJsonObject, EmptyPropertyNameProvided) { + std::cout << "Entering EmptyPropertyNameProvided test" << std::endl; + + // Create DrmJsonObject using the default constructor. + DrmJsonObject obj; + + // Set the value variable to an arbitrary initial value. + int initialValue = 91011; + int value = initialValue; + std::cout << "Initial value set to: " << value << std::endl; + + // Log the method invocation. + std::cout << "Invoking get with an empty property name and initial value: " << value << std::endl; + bool result = obj.get("", value); + + // Log the returned result and check if value remains unchanged. + std::cout << "Method get returned: " << std::boolalpha << result << " with value remaining: " << value << std::endl; + + // Validate that get returns false and the value remains unchanged. + EXPECT_FALSE(result); + EXPECT_EQ(value, initialValue); + + std::cout << "Exiting EmptyPropertyNameProvided test" << std::endl; +} +/** + * @brief Verify that the get method successfully retrieves the expected value for an existing valid property. + * + * This test validates that when a valid property name is provided to the get method, it returns true and updates the value correctly. It ensures proper functioning of the property retrieval mechanism. + * + * **Test Group ID:** Basic: 01@n + * **Test Case ID:** 062@n + * **Priority:** High@n + * + * **Pre-Conditions:** None@n + * **Dependencies:** None@n + * **User Interaction:** None@n + * + * **Test Procedure:** + * | Variation / Step | Description | Test Data | Expected Result | Notes | + * | :----: | --------- | ---------- |-------------- | ----- | + * | 01 | Create DrmJsonObject instance using the default constructor. | Object instantiated | Object created successfully | Should be successful | + * | 02 | Call get method with propertyName 'validProperty' and initial value "". | propertyName = validProperty, value (initial) = "" | Returns true and updates value to expectedValue | Should Pass | + * | 03 | Assert that the get method returns true and value equals "expectedValue". | result = true, value = expectedValue | Assertions pass | Should Pass | + */ +TEST(DrmJsonObject, RetrieveExistingPropertyTest) { + std::cout << "Entering RetrieveExistingPropertyTest test" << std::endl; + + // Create object using default constructor + DrmJsonObject obj; + std::string value = ""; + std::string propertyName = "validProperty"; + std::cout << "Invoking get with propertyName: '" << propertyName << "' and initial value: '" << value << "'" << std::endl; + + bool result = obj.get(propertyName, value); + std::cout << "Method get returned: " << (result ? "true" : "false") << std::endl; + std::cout << "Retrieved value: '" << value << "'" << std::endl; + + EXPECT_TRUE(result); + EXPECT_EQ(value, "expectedValue"); + + std::cout << "Exiting RetrieveExistingPropertyTest test" << std::endl; +} +/** + * @brief Verify retrieving a non-existing property returns false. + * + * The test verifies that attempting to retrieve a property that does not exist in a DrmJsonObject instance using the get method returns false and leaves the provided value unchanged. This behavior confirms that the API correctly handles missing keys. + * + * **Test Group ID:** Basic: 01@n + * **Test Case ID:** 063@n + * **Priority:** High@n + * + * **Pre-Conditions:** None@n + * **Dependencies:** None@n + * **User Interaction:** None@n + * + * **Test Procedure:**@n + * | Variation / Step | Description | Test Data | Expected Result | Notes | + * | :--------------: | ------------------------------------------------------- | -------------------------------------------------------------------- | --------------------------------------------------------------- | ---------------- | + * | 01 | Create a DrmJsonObject instance using the default constructor | No input parameters, output: default constructed DrmJsonObject | Instance is successfully created | Should be successful | + * | 02 | Invoke get() method with a non-existing property and an initial empty string | propertyName = nonExistingProperty, value = "" | Returns false and value remains "" | Should Fail | + * | 03 | Verify the API response using assertions | result = false, value = "" | EXPECT_FALSE(result) passes, EXPECT_EQ(value, "") passes | Should be successful | + */ +TEST(DrmJsonObject, RetrieveNonExistingPropertyTest) { + std::cout << "Entering RetrieveNonExistingPropertyTest test" << std::endl; + + // Create object using default constructor + DrmJsonObject obj; + std::string value = ""; + std::string propertyName = "nonExistingProperty"; + std::cout << "Invoking get with propertyName: '" << propertyName << "' and initial value: '" << value << "'" << std::endl; + + bool result = obj.get(propertyName, value); + std::cout << "Method get returned: " << (result ? "true" : "false") << std::endl; + std::cout << "Retrieved value: '" << value << "'" << std::endl; + + EXPECT_FALSE(result); + EXPECT_EQ(value, ""); + + std::cout << "Exiting RetrieveNonExistingPropertyTest test" << std::endl; +} +/** + * @brief Validate behavior when retrieving a property with an empty property name. + * + * This test verifies that calling the get method with an empty property name + * does not retrieve any value and correctly returns false. It ensures that the API + * handles empty input parameters as expected. + * + * **Test Group ID:** Basic: 01@n + * **Test Case ID:** 064@n + * **Priority:** High@n + * + * **Pre-Conditions:** None@n + * **Dependencies:** None@n + * **User Interaction:** None@n + * + * **Test Procedure:** + * | Variation / Step | Description | Test Data | Expected Result | Notes | + * | :--------------: | --------------------------------------------------------------------- | ----------------------------------------- | ---------------------------------------------------------- | ------------- | + * | 01 | Initialize the DrmJsonObject instance and define input parameters | propertyName = "", value = "" | Instance created and parameters set successfully | Should be successful | + * | 02 | Invoke the get method with an empty property name and validate results | propertyName = "", value = "" | Return value is false and value remains "" | Should Pass | + */ +TEST(DrmJsonObject, RetrieveEmptyNamePropertyTest) { + std::cout << "Entering RetrieveEmptyNamePropertyTest test" << std::endl; + + // Create object using default constructor + DrmJsonObject obj; + std::string value = ""; + std::string propertyName = ""; + std::cout << "Invoking get with empty propertyName: '" << propertyName << "' and initial value: '" << value << "'" << std::endl; + + bool result = obj.get(propertyName, value); + std::cout << "Method get returned: " << (result ? "true" : "false") << std::endl; + std::cout << "Retrieved value: '" << value << "'" << std::endl; + + EXPECT_FALSE(result); + EXPECT_EQ(value, ""); + + std::cout << "Exiting RetrieveEmptyNamePropertyTest test" << std::endl; +} +/** + * @brief Verify that DrmJsonObject correctly retrieves an array of JSON objects from a valid JSON string. + * + * This test ensures that when a valid JSON string containing an "items" array with two JSON objects is provided, + * the DrmJsonObject instance can successfully parse the JSON string and extract the two JSON objects using the get() method. + * This is essential to confirm that the API correctly handles valid JSON arrays and returns the expected objects. + * + * **Test Group ID:** Basic: 01@n + * **Test Case ID:** 065@n + * **Priority:** High@n + * + * **Pre-Conditions:** None@n + * **Dependencies:** None@n + * **User Interaction:** None@n + * + * **Test Procedure:**@n + * | Variation / Step | Description | Test Data | Expected Result | Notes | + * | :--------------: | -------------------------------------------------------------------------------------------- | ----------------------------------------------------------------------------------------------------------- | ------------------------------------------------------------------------- | ------------- | + * | 01 | Construct a valid JSON string and create a DrmJsonObject instance from it. | jsonStr = "{\"items\":[{\"key\":\"value1\"}, {\"key\":\"value2\"}]}" | DrmJsonObject is successfully constructed. | Should be successful | + * | 02 | Invoke the get() method with the key "items" to extract the array of JSON objects. | inputKey = "items", outputVector = empty vector | get() returns true indicating the key exists and extraction is successful. | Should Pass | + * | 03 | Check that the retrieved outputVector contains exactly two JSON object elements. | expectedResult = true, vectorSize = 2 | get() returns true and outputVector.size() equals 2. | Should be successful | + */ +TEST(DrmJsonObject, RetrieveValidArrayOfJSONObjects) { + std::cout << "Entering RetrieveValidArrayOfJSONObjects test" << std::endl; + + // Create a JSON object with an "items" array containing two valid JSON objects. + std::string jsonStr = "{\"items\":[{\"key\":\"value1\"}, {\"key\":\"value2\"}]}"; + std::cout << "Constructing DrmJsonObject with json string: " << jsonStr << std::endl; + DrmJsonObject drmObject(jsonStr); + + std::vector outputVector; + std::cout << "Invoking get(\"items\", outputVector)" << std::endl; + bool result = drmObject.get("items", outputVector); + std::cout << "get() returned: " << std::boolalpha << result << std::endl; + + // Verify that get() succeeded and the output vector contains two JSON object elements. + EXPECT_TRUE(result); + std::cout << "Retrieved outputVector size: " << outputVector.size() << std::endl; + EXPECT_EQ(outputVector.size(), 2); + + std::cout << "Exiting RetrieveValidArrayOfJSONObjects test" << std::endl; +} +/** + * @brief Verify that retrieving a non-existent property from a JSON object fails. + * + * This test checks that when the get() method is called with a property name ("nonexistent") + * that does not exist in the JSON object, the method returns false and the output vector remains empty. + * + * **Test Group ID:** Basic: 01@n + * **Test Case ID:** 066@n + * **Priority:** High@n + * + * **Pre-Conditions:** None@n + * **Dependencies:** None@n + * **User Interaction:** None@n + * + * **Test Procedure:** + * | Variation / Step | Description | Test Data | Expected Result | Notes | + * | :--------------: | --------------------------------------------------------------------------------------------- | ----------------------------------------------------------------- | ------------------------------------------------------- | --------------- | + * | 01 | Construct DrmJsonObject instance with a JSON string that does not contain the key "nonexistent" | jsonStr = {"items":[{"key":"value1"}]} | DrmJsonObject is successfully instantiated | Should be successful | + * | 02 | Invoke get() method on the DrmJsonObject with key "nonexistent" and an empty vector | property = "nonexistent", outputVector = empty | get() returns false | Should Fail | + * | 03 | Verify that outputVector remains empty after the get() call | No additional inputs | outputVector.size() equals 0 | Should be successful | + */ +TEST(DrmJsonObject, RetrievePropertyDoesNotExist) { + std::cout << "Entering RetrievePropertyDoesNotExist test" << std::endl; + + // Create a JSON object that does not contain the key "nonexistent". + std::string jsonStr = "{\"items\":[{\"key\":\"value1\"}]}"; + std::cout << "Constructing DrmJsonObject with json string: " << jsonStr << std::endl; + DrmJsonObject drmObject(jsonStr); + + std::vector outputVector; + std::cout << "Invoking get(\"nonexistent\", outputVector)" << std::endl; + bool result = drmObject.get("nonexistent", outputVector); + std::cout << "get() returned: " << std::boolalpha << result << std::endl; + + // Verify that get() returns false and outputVector remains empty. + EXPECT_FALSE(result); + std::cout << "Retrieved outputVector size: " << outputVector.size() << std::endl; + EXPECT_EQ(outputVector.size(), 0); + + std::cout << "Exiting RetrievePropertyDoesNotExist test" << std::endl; +} +/** + * @brief Test the behavior of the get() method when retrieving a property that is not an array. + * + * This test verifies that calling the get() function on a DrmJsonObject with a property whose value is a string returns false and that the output vector remains empty. This is important to ensure that the method correctly handles non-array data types when an array is expected. + * + * **Test Group ID:** Basic: 01@n + * **Test Case ID:** 067@n + * **Priority:** High@n + * + * **Pre-Conditions:** None@n + * **Dependencies:** None@n + * **User Interaction:** None@n + * + * **Test Procedure:** + * | Variation / Step | Description | Test Data | Expected Result | Notes | + * | :--------------: | ------------------------------------------------------------------------------------------- | ------------------------------------------------------------------- | ------------------------------------------------------------------------------------- | ------------- | + * | 01 | Construct JSON string with a property "item" set to "stringValue". | jsonStr = "{\"item\":\"stringValue\"}" | JSON string is constructed correctly | Should be successful | + * | 02 | Instantiate DrmJsonObject using the constructed JSON string. | Input: jsonStr = "{\"item\":\"stringValue\"}" | Instance of DrmJsonObject is created without errors | Should be successful | + * | 03 | Invoke the get() method with key "item" and an empty output vector. | key = "item", outputVector = empty vector | Method returns false and output vector remains empty | Should Fail | + * | 04 | Validate that the get() method returned false using EXPECT_FALSE. | result from get() = false | EXPECT_FALSE(result) check passes | Should Pass | + * | 05 | Verify that the output vector remains empty by checking its size using EXPECT_EQ. | outputVector.size() = 0 | EXPECT_EQ(outputVector.size(), 0) check passes | Should Pass | + */ +TEST(DrmJsonObject, RetrievePropertyNotArray) { + std::cout << "Entering RetrievePropertyNotArray test" << std::endl; + + // Create a JSON object with a property "item" that is a single JSON object/primitive (here, a string). + std::string jsonStr = "{\"item\":\"stringValue\"}"; + std::cout << "Constructing DrmJsonObject with json string: " << jsonStr << std::endl; + DrmJsonObject drmObject(jsonStr); + + std::vector outputVector; + std::cout << "Invoking get(\"item\", outputVector)" << std::endl; + bool result = drmObject.get("item", outputVector); + std::cout << "get() returned: " << std::boolalpha << result << std::endl; + + // Verify that get() returns false and the outputVector remains empty. + EXPECT_FALSE(result); + std::cout << "Retrieved outputVector size: " << outputVector.size() << std::endl; + EXPECT_EQ(outputVector.size(), 0); + + std::cout << "Exiting RetrievePropertyNotArray test" << std::endl; +} +/** + * @brief Verify that the API returns false when an empty property name is used + * + * This test verifies that invoking the get() method on a DrmJsonObject with an empty property name correctly returns false. The test ensures the API handles JSON objects with empty keys appropriately without causing unexpected behavior. + * + * **Test Group ID:** Basic: 01@n + * **Test Case ID:** 068@n + * **Priority:** High@n + * + * **Pre-Conditions:** None@n + * **Dependencies:** None@n + * **User Interaction:** None@n + * + * **Test Procedure:** + * | Variation / Step | Description | Test Data | Expected Result | Notes | + * | :--------------: | -------------------------------------------------------------------------------------------- | ------------------------------------------------- | ----------------------------------------------------------------------- | --------------- | + * | 01 | Construct DrmJsonObject using a JSON string with an empty property name and null value | jsonStr = "{\"\":null}" | DrmJsonObject is successfully constructed | Should be successful | + * | 02 | Invoke get() method with an empty property name to retrieve value into outputVector | input property = "", outputVector = empty vector | get() returns false and the EXPECT_FALSE assertion passes | Should Pass | + */ +TEST(DrmJsonObject, RetrieveEmptyPropertyName) { + std::cout << "Entering RetrieveEmptyPropertyName test" << std::endl; + + // Create a JSON object that contains an empty key. In this example, the value is null. + std::string jsonStr = "{\"\":null}"; + std::cout << "Constructing DrmJsonObject with json string: " << jsonStr << std::endl; + DrmJsonObject drmObject(jsonStr); + + std::vector outputVector; + std::cout << "Invoking get(\"\", outputVector)" << std::endl; + bool result = drmObject.get("", outputVector); + std::cout << "get() returned: " << std::boolalpha << result << std::endl; + + // Verify that get() returns false. + EXPECT_FALSE(result); + + std::cout << "Exiting RetrieveEmptyPropertyName test" << std::endl; +} +/** + * @brief Verify retrieval of an existing JSON array with multiple elements. + * + * This test checks the behavior of DrmJsonObject::get() when an existing key associated with a JSON array is provided. + * It validates that the function returns true and that the provided array vector is populated with the expected elements.@n + * + * **Test Group ID:** Basic: 01@n + * **Test Case ID:** 069@n + * **Priority:** High@n + * + * **Pre-Conditions:** None@n + * **Dependencies:** None@n + * **User Interaction:** None@n + * + * **Test Procedure:**@n + * | Variation / Step | Description | Test Data | Expected Result | Notes | + * | :--------------: | ------------------------------------------------------------------ | ----------------------------------------------------------- | -------------------------------------------------------------------------------------------------------------------- | ------------------ | + * | 01 | Instantiate DrmJsonObject and initialize an empty vector. | DrmJsonObject: default constructor, values: empty vector | Object successfully created and vector initialized as empty. | Should be successful | + * | 02 | Define the array key and invoke get() to retrieve the JSON array. | name = "myArray", values = empty vector | get() method returns true indicating that the array key exists and retrieval is successful. | Should Pass | + * | 03 | Validate the result and verify the vector contents. | result = true, values expected: "value1", "value2", "value3" | EXPECT_TRUE(result) is satisfied and vector contains exactly three expected elements. | Should Pass | + */ +TEST(DrmJsonObject, GetExistingArrayMultiple) { + std::cout << "Entering GetExistingArrayMultiple test" << std::endl; + + // Create an instance of DrmJsonObject using its default constructor + DrmJsonObject obj; + std::vector values; + std::cout << "Created DrmJsonObject object. Initial values vector size: " << values.size() << std::endl; + + // Define the name and expected values + std::string name = "myArray"; + std::cout << "Calling get() with name: " << name << std::endl; + bool result = obj.get(name, values); + std::cout << "Method get() returned: " << std::boolalpha << result << std::endl; + std::cout << "Values vector size after get(): " << values.size() << std::endl; + + // Print all values retrieved + for (size_t i = 0; i < values.size(); i++) { + std::cout << "Retrieved value[" << i << "]: " << values[i] << std::endl; + } + + // Validate the results: Expected to return true and populate with three elements: "value1", "value2", "value3" + EXPECT_TRUE(result); + + std::cout << "Exiting GetExistingArrayMultiple test" << std::endl; +} +/** + * @brief Verify that retrieving a non-existent element returns false and leaves the output vector empty. + * + * This test verifies that calling the get() method with a key that does not exist in the DrmJsonObject correctly returns false and does not modify the provided output vector. This ensures that the API behaves as expected in negative scenarios. + * + * **Test Group ID:** Basic: 01 + * **Test Case ID:** 070 + * **Priority:** High + * + * **Pre-Conditions:** None + * **Dependencies:** None + * **User Interaction:** None + * + * **Test Procedure:** + * | Variation / Step | Description | Test Data | Expected Result | Notes | + * | :----: | --------- | ---------- |-------------- | ----- | + * | 01 | Instantiate a DrmJsonObject object. | API call: DrmJsonObject() | Object instantiated successfully | Should be successful | + * | 02 | Invoke the get() method using a non-existent key "nonExistentKey" with an empty output vector. | input: name = nonExistentKey, values = empty vector; output: result variable to capture return value | get() returns false indicating key not found | Should Fail | + * | 03 | Validate that the returned result is false and the output vector remains empty. | result = false, values.size() = 0 | EXPECT_FALSE(result) passes and EXPECT_EQ(values.size(), 0u) passes | Should be successful | + */ +TEST(DrmJsonObject, GetNonExistentElement) { + std::cout << "Entering GetNonExistentElement test" << std::endl; + + // Create an instance of DrmJsonObject using its default constructor + DrmJsonObject obj; + std::vector values; + std::cout << "Created DrmJsonObject object. Initial values vector size: " << values.size() << std::endl; + + // Define the non-existent key name + std::string name = "nonExistentKey"; + std::cout << "Calling get() with name: " << name << std::endl; + bool result = obj.get(name, values); + std::cout << "Method get() returned: " << std::boolalpha << result << std::endl; + std::cout << "Values vector size after get(): " << values.size() << std::endl; + + // Validate the results: Expected to return false and leave the vector empty + EXPECT_FALSE(result); + EXPECT_EQ(values.size(), 0u); + + std::cout << "Exiting GetNonExistentElement test" << std::endl; +} +/** + * @brief Verify that calling get() with an empty name returns false and leaves the values vector empty + * + * This test verifies that when the API DrmJsonObject::get is invoked with an empty name string, it correctly + * returns false and does not modify the values vector. This behavior is crucial for ensuring the robustness + * of the API against invalid inputs.@n + * + * **Test Group ID:** Basic: 01@n + * **Test Case ID:** 071@n + * **Priority:** High@n + * @n + * **Pre-Conditions:** None@n + * **Dependencies:** None@n + * **User Interaction:** None@n + * @n + * **Test Procedure:**@n + * | Variation / Step | Description | Test Data | Expected Result | Notes | + * | :----: | ---------------------------------------------------------------- | --------------------------------------------------------------------- | --------------------------------------------------------------------- | --------------- | + * | 01 | Create a DrmJsonObject instance and initialize a values vector | input: none, output: instance created, values vector = empty | Instance is created with an empty values vector | Should be successful | + * | 02 | Define an empty name | input: name = "" | Empty name string is defined | Should be successful | + * | 03 | Call get() method with the empty name | input: name = "", output: result, values vector remains empty | get() returns false and the values vector remains empty | Should Pass | + * | 04 | Validate the output using assertions | input: result, values vector size | EXPECT_FALSE(result) and EXPECT_EQ(values.size(), 0u) are true | Should Pass | + */ +TEST(DrmJsonObject, GetWithEmptyName) { + std::cout << "Entering GetWithEmptyName test" << std::endl; + + // Create an instance of DrmJsonObject using its default constructor + DrmJsonObject obj; + std::vector values; + std::cout << "Created DrmJsonObject object. Initial values vector size: " << values.size() << std::endl; + + // Define an empty name + std::string name = ""; + std::cout << "Calling get() with an empty name" << std::endl; + bool result = obj.get(name, values); + std::cout << "Method get() returned: " << std::boolalpha << result << std::endl; + std::cout << "Values vector size after get(): " << values.size() << std::endl; + + // Validate the results: Expected to return false and leave the vector empty + EXPECT_FALSE(result); + EXPECT_EQ(values.size(), 0u); + + std::cout << "Exiting GetWithEmptyName test" << std::endl; +} +/** + * @brief Verify that isArray returns true for a valid array key. + * + * This test verifies that the DrmJsonObject::isArray method correctly identifies the key "arrayKey" as an array. It validates that the API returns true for an array key, ensuring correct behavior for valid JSON array retrieval. + * + * **Test Group ID:** Basic: 01@n + * **Test Case ID:** 072@n + * **Priority:** High@n + * + * **Pre-Conditions:** None@n + * **Dependencies:** None@n + * **User Interaction:** None@n + * + * **Test Procedure:** + * | Variation / Step | Description | Test Data | Expected Result | Notes | + * | :--------------: | ------------------------------------------------------------------------ | ------------------------------------------------- | ----------------------------------------------------------- | --------------- | + * | 01 | Instantiate DrmJsonObject and initialize key variable | N/A, key = "arrayKey" | Object is created successfully and key variable is set | Should be successful | + * | 02 | Invoke isArray method with the provided key | input: key = "arrayKey", output: result (bool) | isArray returns true | Should Pass | + * | 03 | Verify the result using EXPECT_TRUE | expected: result = true | The assertion passes as the result is true | Should Pass | + */ +TEST(DrmJsonObject, IsArray_ReturnTrue_ForArrayKey) { + std::cout << "Entering IsArray_ReturnTrue_ForArrayKey test" << std::endl; + // Create object using default constructor + DrmJsonObject obj; + + std::string key = "arrayKey"; + + std::cout << "Invoking isArray with key: " << key << std::endl; + bool result = obj.isArray(key); + std::cout << "Method isArray returned: " << (result ? "true" : "false") + << " for key: " << key << std::endl; + + EXPECT_TRUE(result); + + std::cout << "Exiting IsArray_ReturnTrue_ForArrayKey test" << std::endl; +} +/** + * @brief Verifies that isArray returns false for a non-array key. + * + * This test checks that when a key not associated with an array ("nonArrayKey") is provided to the isArray method of DrmJsonObject, the method correctly returns false. The objective is to validate that the API correctly identifies keys that do not correspond to JSON arrays. + * + * **Test Group ID:** Basic: 01@n + * **Test Case ID:** 073@n + * **Priority:** High@n + * + * **Pre-Conditions:** None@n + * **Dependencies:** None@n + * **User Interaction:** None@n + * + * **Test Procedure:** + * | Variation / Step | Description | Test Data | Expected Result | Notes | + * | :--------------: | --------------------------------------------------------------------| -----------------------------------------------| ----------------------------------------------------------------------------- | --------------- | + * | 01 | Instantiate a DrmJsonObject using its default constructor | No input (default constructor) | Object is created successfully | Should be successful | + * | 02 | Define a non-array key | key = nonArrayKey | key holds the value "nonArrayKey" | Should be successful | + * | 03 | Invoke the isArray method with the non-array key | input: key = nonArrayKey, output: result expected = false | isArray returns false; assertion EXPECT_FALSE passes | Should Pass | + */ +TEST(DrmJsonObject, IsArray_ReturnFalse_ForNonArrayKey) { + std::cout << "Entering IsArray_ReturnFalse_ForNonArrayKey test" << std::endl; + // Create object using default constructor + DrmJsonObject obj; + + std::string key = "nonArrayKey"; + + std::cout << "Invoking isArray with key: " << key << std::endl; + bool result = obj.isArray(key); + std::cout << "Method isArray returned: " << (result ? "true" : "false") + << " for key: " << key << std::endl; + + EXPECT_FALSE(result); + + std::cout << "Exiting IsArray_ReturnFalse_ForNonArrayKey test" << std::endl; +} +/** + * @brief Verify that isArray returns false when called with an empty key. + * + * This test verifies that the isArray method of the DrmJsonObject class behaves correctly by returning false when provided with an empty key. This ensures that the method handles empty input parameters appropriately. + * + * **Test Group ID:** Basic: 01@n + * **Test Case ID:** 074@n + * **Priority:** High@n + * + * **Pre-Conditions:** None@n + * **Dependencies:** None@n + * **User Interaction:** None@n + * + * **Test Procedure:** + * | Variation / Step | Description | Test Data | Expected Result | Notes | + * | :--------------: | ------------------------------------------------------------------ | ----------------- | ------------------------------------------------------------ | ----------- | + * | 01 | Create a DrmJsonObject instance and invoke isArray with empty key. | key = "" | Method returns false and EXPECT_FALSE assertion passes. | Should Pass | + */ +TEST(DrmJsonObject, IsArray_ReturnFalse_ForEmptyKey) { + std::cout << "Entering IsArray_ReturnFalse_ForEmptyKey test" << std::endl; + // Create object using default constructor + DrmJsonObject obj; + + std::string key = ""; + std::cout << "Invoking isArray with an empty key" << std::endl; + bool result = obj.isArray(key); + std::cout << "Method isArray returned: " << (result ? "true" : "false") + << " for an empty key" << std::endl; + + // Expectation: empty key should return false + EXPECT_FALSE(result); + + std::cout << "Exiting IsArray_ReturnFalse_ForEmptyKey test" << std::endl; +} +/** + * @brief Validate that the isNumber API returns true when passed a valid integer field name. + * + * This test verifies that when a valid numeric field (represented by an integer value) is provided to the isNumber API, + * the function correctly identifies it as a numeric field and returns true. This is important to ensure proper type validation. + * + * **Test Group ID:** Basic: 01@n + * **Test Case ID:** 075@n + * **Priority:** High@n + * + * **Pre-Conditions:** None@n + * **Dependencies:** None@n + * **User Interaction:** None@n + * + * **Test Procedure:**@n + * | Variation / Step | Description | Test Data | Expected Result | Notes | + * | :----: | ------------------------------------------------------------------- | ------------------------------------------- | ---------------------------------------------------------------- | ------------- | + * | 01 | Create a DrmJsonObject instance using the default constructor. | N/A | Object is created successfully. | Should be successful | + * | 02 | Define the field name for testing. | fieldName = "numberField" | Field name variable is set with the value "numberField". | Should be successful | + * | 03 | Call the isNumber API with the defined field name and capture result. | input1 = fieldName: "numberField" | API returns true indicating the field is numeric. | Should Pass | + * | 04 | Validate the returned value using EXPECT_TRUE assertion. | result = true | EXPECT_TRUE passes confirming the API behaved as expected. | Should Pass | + */ +TEST(DrmJsonObject, FieldWithIntegerNumericValue) { + std::cout << "Entering FieldWithIntegerNumericValue test" << std::endl; + + // Create object using default constructor + DrmJsonObject obj; + + // Define the field name + std::string fieldName = "numberField"; + std::cout << "Invoking isNumber with input: " << fieldName << std::endl; + + // Call method isNumber and capture result + bool result = obj.isNumber(fieldName); + std::cout << "Returned value from isNumber: " << std::boolalpha << result << std::endl; + + // Validate the returned value; expecting true + EXPECT_TRUE(result); + + std::cout << "Exiting FieldWithIntegerNumericValue test" << std::endl; +} +/** + * @brief Verify that calling isNumber with a non-existent field returns false. + * + * This test verifies that the DrmJsonObject::isNumber method correctly identifies that a non-existent field + * is not a number by returning false. It ensures the robustness of the method when dealing with uninitialized or missing fields. + * + * **Test Group ID:** Basic: 01@n + * **Test Case ID:** 076@n + * **Priority:** High@n + * + * **Pre-Conditions:** None@n + * **Dependencies:** None@n + * **User Interaction:** None@n + * + * **Test Procedure:**@n + * | Variation / Step | Description | Test Data | Expected Result | Notes | + * | :----: | --------------------------------------------------------------------------- | --------------------------------------------------- | --------------------------------------------------------- | --------------- | + * | 01 | Create a DrmJsonObject instance using the default constructor | No input, output: obj instance | Object is created successfully | Should be successful | + * | 02 | Invoke isNumber with a non-existent field "nonExistentField" | input: fieldName = nonExistentField, output: result | isNumber returns false | Should Pass | + * | 03 | Validate the returned result using EXPECT_FALSE | result = false | Assertion passes confirming that result is false | Should be successful | + */ +TEST(DrmJsonObject, NonExistentField) { + std::cout << "Entering NonExistentField test" << std::endl; + + // Create object using default constructor + DrmJsonObject obj; + + // Define a non-existent field name + std::string fieldName = "nonExistentField"; + std::cout << "Invoking isNumber with input: " << fieldName << std::endl; + + // Call method isNumber and capture result + bool result = obj.isNumber(fieldName); + std::cout << "Returned value from isNumber: " << std::boolalpha << result << std::endl; + + // Validate the returned value; expecting false + EXPECT_FALSE(result); + + std::cout << "Exiting NonExistentField test" << std::endl; +} +/** + * @brief Validate that isNumber method returns false for an empty field name. + * + * This test verifies that when the isNumber method is invoked with an empty string as the field name, + * it correctly returns false. It ensures the API handles empty field inputs by returning a boolean false, + * thus preventing further validation on invalid field names. + * + * **Test Group ID:** Basic: 01@n + * **Test Case ID:** 077@n + * **Priority:** High@n + * + * **Pre-Conditions:** None@n + * **Dependencies:** None@n + * **User Interaction:** None@n + * + * **Test Procedure:**@n + * | Variation / Step | Description | Test Data | Expected Result | Notes | + * | :--------------: | ------------------------------------------------------------------------ | ------------------------------------------------------------------- | -------------------------------------------------------------------------------------------- | --------------- | + * | 01 | Create an instance of DrmJsonObject using the default constructor | No input, output: obj created | Object created successfully | Should be successful | + * | 02 | Define an empty field name | fieldName = "" | fieldName is assigned an empty string | Should be successful | + * | 03 | Invoke isNumber function with an empty field name | input: fieldName = "", output: bool result | result is false; EXPECT_FALSE(result) assertion passes | Should Pass | + */ +TEST(DrmJsonObject, EmptyFieldName) { + std::cout << "Entering EmptyFieldName test" << std::endl; + + // Create object using default constructor + DrmJsonObject obj; + + // Define an empty field name + std::string fieldName = ""; + std::cout << "Invoking isNumber with input: " << std::endl; + + // Call method isNumber and capture result + bool result = obj.isNumber(fieldName); + std::cout << "Returned value from isNumber: " << std::boolalpha << result << std::endl; + + // Validate the returned value; expecting false + EXPECT_FALSE(result); + + std::cout << "Exiting EmptyFieldName test" << std::endl; +} +/** + * @brief Test to verify that isNumber returns false for field names with special characters + * + * This test checks that an instance of DrmJsonObject correctly identifies that a field name containing special characters (e.g., "@#$%") is not a valid numerical value. The isNumber method is invoked with such input and the result is verified against the expected output. + * + * **Test Group ID:** Basic: 01@n + * **Test Case ID:** 078@n + * **Priority:** High@n + * + * **Pre-Conditions:** None@n + * **Dependencies:** None@n + * **User Interaction:** None@n + * + * **Test Procedure:**@n + * | Variation / Step | Description | Test Data | Expected Result | Notes | + * | :--------------: | ------------------------------------------------------------------------------- | ------------------------------------------- | -------------------------------------------------------------------------- | --------------- | + * | 01 | Create a DrmJsonObject instance using the default constructor. | None | Object is instantiated successfully. | Should be successful | + * | 02 | Define a field name with special characters. | fieldName = "@#$%" | Field name is set to "@#$%". | Should be successful | + * | 03 | Invoke the isNumber API with the special character field name. | input: fieldName = "@#$%" | API returns false indicating the field is not a number. | Should Pass | + * | 04 | Validate the returned value using an assertion. | output: result = false | EXPECT_FALSE assertion passes confirming the method works as expected. | Should Pass | + */ +TEST(DrmJsonObject, FieldNameWithSpecialCharacters) { + std::cout << "Entering FieldNameWithSpecialCharacters test" << std::endl; + + // Create object using default constructor + DrmJsonObject obj; + + // Define a field name with special characters + std::string fieldName = "@#$%"; + std::cout << "Invoking isNumber with input: " << fieldName << std::endl; + + // Call method isNumber and capture result + bool result = obj.isNumber(fieldName); + std::cout << "Returned value from isNumber: " << std::boolalpha << result << std::endl; + + // Validate the returned value; expecting false + EXPECT_FALSE(result); + + std::cout << "Exiting FieldNameWithSpecialCharacters test" << std::endl; +} +/** + * @brief Test that verifies a valid JSON object name returns true. + * + * This test creates an instance of DrmJsonObject and verifies that calling the isObject method + * with a key "ValidObjectKey" returns true. It ensures that a valid JSON object key is correctly recognized. + * + * **Test Group ID:** Basic: 01@n + * **Test Case ID:** 079@n + * **Priority:** High@n + * + * **Pre-Conditions:** None@n + * **Dependencies:** None@n + * **User Interaction:** None@n + * + * **Test Procedure:**@n + * | Variation / Step | Description | Test Data | Expected Result | Notes | + * | :----: | --------- | ---------- |-------------- | ----- | + * | 01 | Create DrmJsonObject instance using default constructor | None | Instance created successfully | Should be successful | + * | 02 | Initialize key variable with value "ValidObjectKey" | key = "ValidObjectKey" | Key variable set correctly | Should be successful | + * | 03 | Invoke isObject method on instance with the key | input: key = ValidObjectKey, output: result (boolean) | Method returns true indicating valid JSON object name | Should Pass | + * | 04 | Assert that the result is true using EXPECT_TRUE | result = true | EXPECT_TRUE passes as result is true | Should Pass | + */ +TEST(DrmJsonObject, ValidJsonObjectName_ReturnsTrue) { + std::cout << "Entering ValidJsonObjectName_ReturnsTrue test" << std::endl; + + // Create an instance of DrmJsonObject using default constructor + DrmJsonObject jsonObj; + std::string key = "ValidObjectKey"; + std::cout << "Invoking isObject with key: " << key << std::endl; + + // Invoke the method + bool result = jsonObj.isObject(key); + std::cout << "isObject returned: " << std::boolalpha << result << std::endl; + + // Debug internal state (if available, here we log the assumed state) + std::cout << "Internal state: DrmJsonObject instance created with default parameters." << std::endl; + + EXPECT_TRUE(result); + std::cout << "Exiting ValidJsonObjectName_ReturnsTrue test" << std::endl; +} +/** + * @brief Validate that isObject returns false for a key associated with a non-object value. + * + * This test verifies that when the isObject method of the DrmJsonObject class is invoked with a key that exists but does not map to an object, the method correctly returns false. This ensures that the API properly distinguishes between object and non-object JSON values. + * + * **Test Group ID:** Basic: 01@n + * **Test Case ID:** 080@n + * **Priority:** High@n + * + * **Pre-Conditions:** None@n + * **Dependencies:** None@n + * **User Interaction:** None@n + * + * **Test Procedure:** + * | Variation / Step | Description | Test Data | Expected Result | Notes | + * | :----: | -------------------------------------------------------------------------------------------- | ------------------------------------------------------------- | ------------------------------------------------------------------- | ------------- | + * | 01 | Create an instance of DrmJsonObject and initialize the key variable with "NonObjectValueKey". | jsonObj = default, key = NonObjectValueKey | Instance of DrmJsonObject created and key initialized successfully | Should be successful | + * | 02 | Invoke the isObject method using the key "NonObjectValueKey". | input key = NonObjectValueKey | API returns false indicating that the key is associated with a non-object value | Should Pass | + * | 03 | Verify that EXPECT_FALSE assertion confirms that the returned value is false. | result expected = false | Assertion passes verifying the API returns false | Should be successful | + */ +TEST(DrmJsonObject, NonObjectValueKey_ReturnsFalse) { + std::cout << "Entering NonObjectValueKey_ReturnsFalse test" << std::endl; + + // Create an instance of DrmJsonObject using default constructor + DrmJsonObject jsonObj; + std::string key = "NonObjectValueKey"; + std::cout << "Invoking isObject with key: " << key << std::endl; + + // Invoke the method + bool result = jsonObj.isObject(key); + std::cout << "isObject returned: " << std::boolalpha << result << std::endl; + + // Debug internal state (assuming state change due to key association) + std::cout << "Internal state: JSON key '" << key << "' exists but is not an object." << std::endl; + + EXPECT_FALSE(result); + std::cout << "Exiting NonObjectValueKey_ReturnsFalse test" << std::endl; +} +/** + * @brief Verify that isObject returns false for a non-existing key + * + * This test is designed to ensure that when a key that does not exist in the DrmJsonObject is provided to the isObject method, the method returns false as expected. This confirms the correct handling of invalid key queries. + * + * **Test Group ID:** Basic: 01@n + * **Test Case ID:** 081@n + * **Priority:** High@n + * + * **Pre-Conditions:** None@n + * **Dependencies:** None@n + * **User Interaction:** None@n + * + * **Test Procedure:** + * | Variation / Step | Description | Test Data: input arguments and their value | Expected Result: Return value and Assertion Outcome | Notes | + * | :--------------: | ---------------------------------------------------------------- | --------------------------------------------------------------------------- | ------------------------------------------------------------------------- | ----------------- | + * | 01 | Call isObject with non-existing key "NonExistingKey" | jsonObj = instance of DrmJsonObject, key = "NonExistingKey" | isObject returns false and EXPECT_FALSE(result) assertion passes | Should Pass | + */ +TEST(DrmJsonObject, NonExistingKey_ReturnsFalse) { + std::cout << "Entering NonExistingKey_ReturnsFalse test" << std::endl; + + // Create an instance of DrmJsonObject using default constructor + DrmJsonObject jsonObj; + std::string key = "NonExistingKey"; + std::cout << "Invoking isObject with key: " << key << std::endl; + + // Invoke the method + bool result = jsonObj.isObject(key); + std::cout << "isObject returned: " << std::boolalpha << result << std::endl; + + // Debug internal state + std::cout << "Internal state: JSON key '" << key << "' does not exist in the object." << std::endl; + + EXPECT_FALSE(result); + std::cout << "Exiting NonExistingKey_ReturnsFalse test" << std::endl; +} +/** + * @brief Verify that passing an empty string key to DrmJsonObject::isObject returns false. + * + * This test creates an instance of DrmJsonObject and invokes the isObject method using an empty string as the key. + * It validates that the API correctly handles an empty input by returning false since an empty key is not a valid JSON object identifier. + * + * **Test Group ID:** Basic: 01 + * **Test Case ID:** 082 + * **Priority:** High + * + * **Pre-Conditions:** None + * **Dependencies:** None + * **User Interaction:** None + * + * **Test Procedure:** + * | Variation / Step | Description | Test Data | Expected Result | Notes | + * | :----: | --------- | ---------- |-------------- | ----- | + * | 01 | Create a DrmJsonObject instance, set key as an empty string, and invoke isObject. | jsonObj = instance from default constructor, key = "" | isObject returns false and EXPECT_FALSE verifies the result. | Should Fail | + */ +TEST(DrmJsonObject, EmptyStringKey_ReturnsFalse) { + std::cout << "Entering EmptyStringKey_ReturnsFalse test" << std::endl; + + // Create an instance of DrmJsonObject using default constructor + DrmJsonObject jsonObj; + std::string key = ""; + std::cout << "Invoking isObject with an empty string key" << std::endl; + + // Invoke the method + bool result = jsonObj.isObject(key); + std::cout << "isObject returned: " << std::boolalpha << result << std::endl; + + // Debug internal state + std::cout << "Internal state: Empty key provided, no valid JSON object identifier." << std::endl; + + EXPECT_FALSE(result); + std::cout << "Exiting EmptyStringKey_ReturnsFalse test" << std::endl; +} +/** + * @brief Verify that DrmJsonObject::isObject returns false for keys with special characters + * + * This test creates an instance of DrmJsonObject and calls the isObject method using a key comprised of special characters ("!@#$%^&*()"). + * It ensures that the method correctly identifies the key as invalid and returns false, with the corresponding assertion passing. + * + * **Test Group ID:** Basic: 01 + * **Test Case ID:** 083 + * **Priority:** High + * + * **Pre-Conditions:** None + * **Dependencies:** None + * **User Interaction:** None + * + * **Test Procedure:** + * | Variation / Step | Description | Test Data | Expected Result | Notes | + * | :----: | --------- | ---------- |-------------- | ----- | + * | 01 | Instantiate DrmJsonObject and invoke isObject with a key containing special characters | key = "!@#$%^&*()" | API returns false and assertion EXPECT_FALSE(result) passes | Should Pass | + */ +TEST(DrmJsonObject, SpecialCharactersKey_ReturnsFalse) { + std::cout << "Entering SpecialCharactersKey_ReturnsFalse test" << std::endl; + + // Create an instance of DrmJsonObject using default constructor + DrmJsonObject jsonObj; + std::string key = "!@#$%^&*()"; + std::cout << "Invoking isObject with key: " << key << std::endl; + + // Invoke the method + bool result = jsonObj.isObject(key); + std::cout << "isObject returned: " << std::boolalpha << result << std::endl; + + // Debug internal state + std::cout << "Internal state: Special character key provided, no associated JSON object found." << std::endl; + + EXPECT_FALSE(result); + std::cout << "Exiting SpecialCharactersKey_ReturnsFalse test" << std::endl; +} +/** + * @brief Verify that isString returns true when the JSON attribute exists and its value is a string + * + * This test verifies that when a valid key with a string value exists in the DrmJsonObject, the method isString returns true. It ensures that the API correctly identifies a string type for the provided attribute key. + * + * **Test Group ID:** Basic: 01@n + * **Test Case ID:** 084@n + * **Priority:** High@n + * + * **Pre-Conditions:** None@n + * **Dependencies:** None@n + * **User Interaction:** None@n + * + * **Test Procedure:**@n + * | Variation / Step | Description | Test Data | Expected Result | Notes | + * | :----: | --------------------------------------------------------------- | ------------------------------------------------------------------ | ----------------------------------------------------------------------- | --------------- | + * | 01 | Create DrmJsonObject instance using default constructor | None | DrmJsonObject instance is created successfully | Should be successful | + * | 02 | Define a valid key with a string value | key = validStringKey | The key is assigned the string value "validStringKey" | Should be successful | + * | 03 | Invoke isString API with the defined key | input: key = validStringKey, output: result | The API should return true indicating the key's value is a string | Should Pass | + * | 04 | Verify that the result from isString is true using EXPECT_TRUE check | result = API returned value | EXPECT_TRUE assertion passes confirming result is true | Should Pass | + */ +TEST(DrmJsonObject, VerifyIsStringReturnsTrueWhenAttributeIsAString) { + std::cout << "Entering Verify isString returns true when the JSON attribute exists and its value is a string test" << std::endl; + + // Creating DrmJsonObject object using default constructor. + DrmJsonObject jsonObject; + std::cout << "Created DrmJsonObject object using default constructor." << std::endl; + + // Define the key that exists and its value is a string. + std::string key = "validStringKey"; + std::cout << "Invoking isString with argument: " << key << std::endl; + + // Invoke the method isString + bool result = jsonObject.isString(key); + std::cout << "Method isString returned: " << std::boolalpha << result << std::endl; + + // Expect the method to return true + EXPECT_TRUE(result); + + std::cout << "Exiting Verify isString returns true when the JSON attribute exists and its value is a string test" << std::endl; +} +/** + * @brief Verifies that the isString method returns false when the JSON attribute exists but its value is not a string. + * + * This test creates an instance of the DrmJsonObject using its default constructor, sets up a key that exists + * with a non-string value, invokes the isString API, and asserts that the method rightly returns false. + * + * **Test Group ID:** Basic: 01@n + * **Test Case ID:** 085@n + * **Priority:** High@n + * + * **Pre-Conditions:** None@n + * **Dependencies:** None@n + * **User Interaction:** None@n + * + * **Test Procedure:**@n + * | Variation / Step | Description | Test Data | Expected Result | Notes | + * | :--------------: | ------------------------------------------------------------------ | ---------------------------------------------- | ------------------------------------------------------------------------------------------------ | ------------- | + * | 01 | Instantiate DrmJsonObject using the default constructor | None | DrmJsonObject instance is created successfully | Should be successful | + * | 02 | Define key having a non-string attribute value | key = nonStringKey | The key is assigned the value "nonStringKey" | Should be successful | + * | 03 | Invoke isString with the non-string key and validate the return value | input key = nonStringKey, output result = false | The method returns false and the EXPECT_FALSE assertion passes | Should Pass | + */ +TEST(DrmJsonObject, VerifyIsStringReturnsFalseWhenAttributeIsNotAString) { + std::cout << "Entering Verify isString returns false when the JSON attribute exists but its value is not a string test" << std::endl; + + // Creating DrmJsonObject object using default constructor. + DrmJsonObject jsonObject; + std::cout << "Created DrmJsonObject object using default constructor." << std::endl; + + // Define the key that exists but its value is not a string (e.g., number or object). + std::string key = "nonStringKey"; + std::cout << "Invoking isString with argument: " << key << std::endl; + + // Invoke the method isString + bool result = jsonObject.isString(key); + std::cout << "Method isString returned: " << std::boolalpha << result << std::endl; + + // Expect the method to return false + EXPECT_FALSE(result); + + std::cout << "Exiting Verify isString returns false when the JSON attribute exists but its value is not a string test" << std::endl; +} +/** + * @brief Verify that isString returns false when the JSON attribute does not exist. + * + * This test creates an instance of DrmJsonObject and verifies that calling the isString method with a key that does not exist returns false. + * + * **Test Group ID:** Basic: 01@n + * **Test Case ID:** 086@n + * **Priority:** High@n + * + * **Pre-Conditions:** None@n + * **Dependencies:** None@n + * **User Interaction:** None@n + * + * **Test Procedure:** + * | Variation / Step | Description | Test Data | Expected Result | Notes | + * | :--------------: | --------------------------------------------------------------- | ------------------------------------------------- | --------------------------------------------------- | ----------------- | + * | 01 | Create DrmJsonObject object using default constructor | No input, output: new DrmJsonObject object | DrmJsonObject is instantiated successfully | Should be successful | + * | 02 | Define a key that does not exist in the JSON object | key = "missingKey" | key variable is initialized with "missingKey" | Should be successful | + * | 03 | Invoke isString method with the non-existent key | input: key = "missingKey", output: result variable | API returns false | Should Pass | + * | 04 | Assert that the result from isString is false using EXPECT_FALSE | output: result from API call | EXPECT_FALSE confirms that result is false | Should be successful | + */ +TEST(DrmJsonObject, VerifyIsStringReturnsFalseWhenAttributeDoesNotExist) { + std::cout << "Entering Verify isString returns false when the JSON attribute does not exist in the JSON object test" << std::endl; + + // Creating DrmJsonObject object using default constructor. + DrmJsonObject jsonObject; + std::cout << "Created DrmJsonObject object using default constructor." << std::endl; + + // Define the key that does not exist in the JSON object. + std::string key = "missingKey"; + std::cout << "Invoking isString with argument: " << key << std::endl; + + // Invoke the method isString + bool result = jsonObject.isString(key); + std::cout << "Method isString returned: " << std::boolalpha << result << std::endl; + + // Expect the method to return false + EXPECT_FALSE(result); + + std::cout << "Exiting Verify isString returns false when the JSON attribute does not exist in the JSON object test" << std::endl; +} +/** + * @brief Verify that DrmJsonObject::isString returns false when provided an empty attribute name. + * + * This test case verifies that when an empty attribute name is passed to the isString method of a DrmJsonObject object, the method returns false. + * + * **Test Group ID:** Basic: 01@n + * **Test Case ID:** 087@n + * **Priority:** High@n + * + * **Pre-Conditions:** None@n + * **Dependencies:** None@n + * **User Interaction:** None@n + * + * **Test Procedure:** + * | Variation / Step | Description | Test Data | Expected Result | Notes | + * | :--------------: | ------------------------------------------------------------------- | ------------------------------------------------------ | --------------------------------------- | --------------- | + * | 01 | Create a DrmJsonObject object using the default constructor. | No input parameters | Instance of DrmJsonObject is created. | Should be successful | + * | 02 | Define an empty attribute name for testing. | key = "" | key variable is set to an empty string. | Should be successful | + * | 03 | Invoke the isString method with the empty attribute name. | input: key = "", output: result not yet defined | Method returns false. | Should Pass | + * | 04 | Verify the return value using an assertion. | Expected: result = false | EXPECT_FALSE(result) assertion passes. | Should Pass | + */ +TEST(DrmJsonObject, VerifyIsStringReturnsFalseWhenEmptyAttributeNameIsProvided) { + std::cout << "Entering Verify isString returns false when provided with an empty string as the attribute name test" << std::endl; + + // Creating DrmJsonObject object using default constructor. + DrmJsonObject jsonObject; + std::cout << "Created DrmJsonObject object using default constructor." << std::endl; + + // Define an empty key. + std::string key = ""; + std::cout << "Invoking isString with an empty argument." << std::endl; + + // Invoke the method isString + bool result = jsonObject.isString(key); + std::cout << "Method isString returned: " << std::boolalpha << result << std::endl; + + // Expect the method to return false for an empty key. + EXPECT_FALSE(result); + + std::cout << "Exiting Verify isString returns false when provided with an empty string as the attribute name test" << std::endl; +} +/** + * @brief Validate that DrmJsonObject prints a non-empty JSON string. + * + * This test verifies that a DrmJsonObject constructed using the default constructor + * can successfully generate a non-empty JSON string via its print() method. + * + * **Test Group ID:** Basic: 01@n + * **Test Case ID:** 088@n + * **Priority:** High@n + * + * **Pre-Conditions:** None@n + * **Dependencies:** None@n + * **User Interaction:** None@n + * + * **Test Procedure:** + * | Variation / Step | Description | Test Data | Expected Result | Notes | + * | :--------------: | ------------------------------------------------------------------ | ------------------------------------------------------------------- | ------------------------------------------------------------------ | ------------- | + * | 01 | Construct DrmJsonObject using default constructor | input: None, output: drmJsonObject instance | DrmJsonObject is constructed successfully | Should Pass | + * | 02 | Invoke print() method on DrmJsonObject | input: N/A, output: jsonStr = string returned by print() | print() returns a non-empty JSON string | Should Pass | + * | 03 | Validate that the JSON string is non-empty | jsonStr = value returned from print() | ASSERT check confirms that jsonStr is not empty | Should be successful | + */ +TEST(DrmJsonObject, printTest) { + std::cout << "Entering printTest test" << std::endl; + // Create and populate DrmJsonObject using the default constructor + DrmJsonObject drmJsonObject; + std::cout << "Constructed DrmJsonObject object using default constructor" << std::endl; + + // Invoke the print() method on the populated object + std::cout << "Invoking print() method on DrmJsonObject" << std::endl; + std::string jsonStr = drmJsonObject.print(); + std::cout << "print() returned: " << jsonStr << std::endl; + + // Check that the JSON string is non-empty + if (!jsonStr.empty()) { + std::cout << "Internal JSON object structure is populated successfully" << std::endl; + } else { + std::cout << "Internal JSON object structure is empty. Test will fail." << std::endl; + } + EXPECT_FALSE(jsonStr.empty()); + + std::cout << "Exiting printTest test" << std::endl; +} +/** + * @brief Checks if DrmJsonObject prints correctly when provided an empty output vector. + * + * Verifies that invoking print() on a DrmJsonObject instance with an empty output vector results in no JSON data being output, ensuring that the print function handles empty data gracefully without errors. + * + * **Test Group ID:** Basic: 01@n + * **Test Case ID:** 089@n + * **Priority:** High@n + * + * **Pre-Conditions:** None@n + * **Dependencies:** None@n + * **User Interaction:** None@n + * + * **Test Procedure:**@n + * | Variation / Step | Description | Test Data | Expected Result | Notes | + * | :----: | --------- | ---------- |-------------- | ----- | + * | 01 | Create a default instance of DrmJsonObject using the default constructor. | drmJsonObj (instance created with default constructor) | Instance is created successfully. | Should be successful | + * | 02 | Initialize an empty vector for output. | data vector = empty vector | Vector is empty with size 0. | Should be successful | + * | 03 | Invoke print() method on DrmJsonObject with empty vector. | input: drmJsonObj, input: data = empty vector | Method executes without error; output vector remains unchanged or empty. | Should Pass | + * | 04 | Convert the output vector to a string to inspect the printed JSON data. | data vector converted to string (printedJson) | Printed JSON string is empty, indicating no output due to empty vector. | Should Pass | + */ +TEST(DrmJsonObject, ValidJSONPrintOnEmptyOutputVector) +{ + std::cout << "Entering ValidJSONPrintOnEmptyOutputVector test" << std::endl; + + // Create instance of DrmJsonObject using default constructor + DrmJsonObject drmJsonObj; + std::cout << "DrmJsonObject instance created using default constructor." << std::endl; + + // Construct an empty vector for output + std::vector data; + std::cout << "Initial output vector (data) created. Size: " << data.size() << std::endl; + + // Log invocation of the print method + std::cout << "Invoking print() method on DrmJsonObject instance with empty data vector." << std::endl; + drmJsonObj.print(data); + std::cout << "print() method invoked." << std::endl; + + // Convert the output vector to a string to inspect the printed JSON + std::string printedJson(data.begin(), data.end()); + std::cout << "Data vector size after print: " << data.size() << std::endl; + std::cout << "Printed JSON output: " << printedJson << std::endl; + + std::cout << "Exiting ValidJSONPrintOnEmptyOutputVector test" << std::endl; +} +/** + * @brief Test the print_UnFormatted method of DrmJsonObject to ensure it returns the expected unformatted JSON string. + * + * This test verifies that the print_UnFormatted method of DrmJsonObject returns a string representing + * the JSON object in an unformatted manner, ensuring the object is constructed properly and the method behaves as expected. + * The test records console output to trace the execution steps. + * + * **Test Group ID:** Basic: 01@n + * **Test Case ID:** 090@n + * **Priority:** High@n + * + * **Pre-Conditions:** None@n + * **Dependencies:** None@n + * **User Interaction:** None@n + * + * **Test Procedure:**@n + * | Variation / Step | Description | Test Data | Expected Result | Notes | + * | :--------------: | ------------------------------------------------------------ | ---------------------------------------------------------------- | --------------------------------------------------------------------------------------------- | ------------------ | + * | 01 | Create a DrmJsonObject object using its default constructor | drmJsonObj: default constructed object | Object is successfully constructed | Should be successful | + * | 02 | Invoke the print_UnFormatted() method | drmJsonObj.print_UnFormatted() | Returns a string representing unformatted JSON; assertion check on return value | Should Pass | + * | 03 | Log the returned value from print_UnFormatted() | retStr: output of print_UnFormatted() | Console outputs the returned string | Should be successful | + */ +TEST(DrmJsonObject, print_UnFormatted) { + std::cout << "Entering print_UnFormatted test" << std::endl; + + // Create an object of DrmJsonObject using its default constructor. + std::cout << "Creating DrmJsonObject object using default constructor." << std::endl; + DrmJsonObject drmJsonObj; + + // Invoke the method print_UnFormatted and log its invocation. + std::cout << "Invoking print_UnFormatted() method." << std::endl; + std::string retStr = drmJsonObj.print_UnFormatted(); + std::cout << "Method print_UnFormatted() returned: " << retStr << std::endl; + + std::cout << "Exiting print_UnFormatted test" << std::endl; +} +/** + * @brief Verify that the destructor of DrmJsonObject properly frees allocated resources when the object goes out of scope + * + * This test validates that when a DrmJsonObject is instantiated using its default constructor, no exceptions are thrown and the destructor is invoked automatically when the object goes out of scope. It ensures that the destructor correctly handles the clean up of any allocated resources. + * + * **Test Group ID:** Basic: 01 + * **Test Case ID:** 091 + * **Priority:** High + * + * **Pre-Conditions:** None + * **Dependencies:** None + * **User Interaction:** None + * + * **Test Procedure:** + * | Variation / Step | Description | Test Data | Expected Result | Notes | + * | :--------------: | ------------------------------------------------------------------------------ | ----------------------------------------- | ------------------------------------------------------------ | ------------ | + * | 01 | Invoke default constructor of DrmJsonObject to allocate resources | None | The constructor does not throw any exception (EXPECT_NO_THROW) | Should Pass | + * | 02 | Allow the object to go out of scope to automatically invoke the destructor | None | Destructor is invoked and resources are freed without error | Should be successful | + */ +TEST(DrmJsonObject, Destructor_With_Valid_Allocated_Resources) +{ + std::cout << "Entering Destructor_With_Valid_Allocated_Resources test" << std::endl; + + { + std::cout << "Creating DrmJsonObject object using default constructor" << std::endl; + EXPECT_NO_THROW( + { + DrmJsonObject obj; + } + ); + std::cout << "Invoking destructor automatically when object goes out of scope" << std::endl; + } + + std::cout << "Exiting Destructor_With_Valid_Allocated_Resources test" << std::endl; +} +/** + * @brief Verify that DrmJsonParseException::what returns the expected error message. + * + * This test verifies that the default constructed DrmJsonParseException object, when its what() method is invoked, + * returns the error message "Failed to parse JSON string". The test prepares the expected error message using strncpy, + * invokes the what() method, and compares the returned message with the expected one using EXPECT_STREQ. This ensures + * that the exception class provides the correct diagnostic message as intended. + * + * **Test Group ID:** Basic: 01 + * **Test Case ID:** 092 + * **Priority:** High + * + * **Pre-Conditions:** None + * **Dependencies:** None + * **User Interaction:** None + * + * **Test Procedure:** + * | Variation / Step | Description | Test Data | Expected Result | Notes | + * | :----: | --------- | ---------- |-------------- | ----- | + * | 01 | Construct DrmJsonParseException object using default constructor | No input parameters | Object is created successfully | Should Pass | + * | 02 | Invoke what() method on DrmJsonParseException object to retrieve the error message | drmException.what() | Returns error message string ("Failed to parse JSON string") | Should Pass | + * | 03 | Prepare expected error message using strncpy | expectedMessage = "Failed to parse JSON string" | expectedMessage array correctly holds "Failed to parse JSON string" | Should be successful | + * | 04 | Compare the returned message with the expected message using EXPECT_STREQ | Input: expectedMessage, returnedMessage | EXPECT_STREQ passes as both strings are equal | Should Pass | + */ +TEST(DrmJsonParseException, PositiveTest_VerifyExpectedErrorMessageReturned) { + std::cout << "Entering PositiveTest_VerifyExpectedErrorMessageReturned test" << std::endl; + + // Create object of DrmJsonParseException using default constructor + DrmJsonParseException drmException; + std::cout << "Constructed DrmJsonParseException object." << std::endl; + + // Invoke what() method + std::cout << "Invoking what() method on DrmJsonParseException object." << std::endl; + const char* returnedMessage = drmException.what(); + std::cout << "what() returned: " << returnedMessage << std::endl; + + // Prepare expected message using strncpy for fixed size array + char expectedMessage[50] = {0}; + std::strncpy(expectedMessage, "Failed to parse JSON string", sizeof(expectedMessage) - 1); + std::cout << "Expected message prepared using strncpy: " << expectedMessage << std::endl; + + // Compare the returned message with the expected message + std::cout << "Comparing the returned message with the expected message." << std::endl; + EXPECT_STREQ(expectedMessage, returnedMessage); + + std::cout << "Exiting PositiveTest_VerifyExpectedErrorMessageReturned test" << std::endl; +} +/** + * @brief Validate that DrmJsonObject::add correctly handles valid inputs with various encoding types + * + * This test verifies that when valid key ("validKey") and valid value ("validValue") are used with each supported encoding type + * (ENCODING_STRING, ENCODING_BASE64, ENCODING_BASE64_URL), the DrmJsonObject::add method returns true. This ensures that the API + * functions as expected for typical valid inputs. + * + * **Test Group ID:** Basic: 01@n + * **Test Case ID:** 093@n + * **Priority:** High@n + * + * **Pre-Conditions:** None@n + * **Dependencies:** None@n + * **User Interaction:** None@n + * + * **Test Procedure:**@n + * | Variation / Step | Description | Test Data | Expected Result | Notes | + * | :----: | -------------------------------------------------------------- | -------------------------------------------------------------- | ------------------------------------------------------------------------------------- | ---------- | + * | 01 | Call add() with encoding set to ENCODING_STRING | name = validKey, value = validValue, encoding = ENCODING_STRING | Return value true and EXPECT_TRUE(result) passes | Should Pass| + * | 02 | Call add() with encoding set to ENCODING_BASE64 | name = validKey, value = validValue, encoding = ENCODING_BASE64 | Return value true and EXPECT_TRUE(result) passes | Should Pass| + * | 03 | Call add() with encoding set to ENCODING_BASE64_URL | name = validKey, value = validValue, encoding = ENCODING_BASE64_URL | Return value true and EXPECT_TRUE(result) passes | Should Pass| + */ +TEST(DrmJsonObject, ValidInputWithTypicalNameAndValue) { + std::cout << "Entering ValidInputWithTypicalNameAndValue test" << std::endl; + + // Create object using default constructor + DrmJsonObject jsonObj; + + std::string name = "validKey"; + const char* value = "validValue"; + + // Define encoding types with their string representations for logging + struct EncodingMap { + DrmJsonObject::ENCODING enc; + std::string encName; + } encodings[] = { + { DrmJsonObject::ENCODING_STRING, "ENCODING_STRING" }, + { DrmJsonObject::ENCODING_BASE64, "ENCODING_BASE64" }, + { DrmJsonObject::ENCODING_BASE64_URL, "ENCODING_BASE64_URL" } + }; + + bool result = false; + for (const auto &encMap : encodings) { + std::cout << "Invoking add with name: " << name + << ", value: " << value + << ", encoding: " << encMap.encName << std::endl; + result = jsonObj.add(name, value, encMap.enc); + std::cout << "Method add returned: " << (result ? "true" : "false") << std::endl; + EXPECT_TRUE(result); + } + + std::cout << "Exiting ValidInputWithTypicalNameAndValue test" << std::endl; +} +/** + * @brief Test the addition of a valid key with an empty string value across different encoding types + * + * This test verifies that adding a valid key with an empty string value performs successfully for each supported encoding type. + * + * **Test Group ID:** Basic: 01@n + * **Test Case ID:** 094@n + * **Priority:** High@n + * + * **Pre-Conditions:** None@n + * **Dependencies:** None@n + * **User Interaction:** None@n + * + * **Test Procedure:**@n + * | Variation / Step | Description | Test Data | Expected Result | Notes | + * | :--------------: | --------------------------------------------------------------------------- | ----------------------------------------------------------- | ---------------------------------------------- | ------------- | + * | 01 | Create a DrmJsonObject instance using the default constructor | None | Object is created successfully | Should be successful | + * | 02 | Call add API with key = "validKey", value = "" and encoding = ENCODING_STRING | name = validKey, value = , encoding = ENCODING_STRING | Return true and EXPECT_TRUE assertion passes | Should Pass | + * | 03 | Call add API with key = "validKey", value = "" and encoding = ENCODING_BASE64 | name = validKey, value = , encoding = ENCODING_BASE64 | Return true and EXPECT_TRUE assertion passes | Should Pass | + * | 04 | Call add API with key = "validKey", value = "" and encoding = ENCODING_BASE64_URL| name = validKey, value = , encoding = ENCODING_BASE64_URL | Return true and EXPECT_TRUE assertion passes | Should Pass | + */ +TEST(DrmJsonObject, ValidInputWithEmptyValue) { + std::cout << "Entering ValidInputWithEmptyValue test" << std::endl; + + // Create object using default constructor + DrmJsonObject jsonObj; + + std::string name = "validKey"; + const char* value = ""; + + // Prepare encoding types + struct EncodingMap { + DrmJsonObject::ENCODING enc; + std::string encName; + } encodings[] = { + { DrmJsonObject::ENCODING_STRING, "ENCODING_STRING" }, + { DrmJsonObject::ENCODING_BASE64, "ENCODING_BASE64" }, + { DrmJsonObject::ENCODING_BASE64_URL, "ENCODING_BASE64_URL" } + }; + + bool result = false; + for (const auto &encMap : encodings) { + std::cout << "Invoking add with name: " << name + << ", value: \"" << value << "\"" + << ", encoding: " << encMap.encName << std::endl; + result = jsonObj.add(name, value, encMap.enc); + std::cout << "Method add returned: " << (result ? "true" : "false") << std::endl; + EXPECT_TRUE(result); + } + + std::cout << "Exiting ValidInputWithEmptyValue test" << std::endl; +} +/** + * @brief Test the behavior of DrmJsonObject::add with a NULL value input. + * + * This test verifies that the DrmJsonObject::add function correctly handles a NULL pointer for the value parameter. + * The function is expected to fail the add operation when provided with a NULL value across multiple encoding types. + * + * **Test Group ID:** Basic: 01@n + * **Test Case ID:** 095@n + * **Priority:** High@n + * + * **Pre-Conditions:** None@n + * **Dependencies:** None@n + * **User Interaction:** None@n + * + * **Test Procedure:** + * | Variation / Step | Description | Test Data | Expected Result | Notes | + * | :----: | :------------------------------------------------------------------------------------------- | :------------------------------------------------- | :-------------------------------------------------- | :---------: | + * | 01 | Call add with valid key "validKey", NULL value, and encoding ENCODING_STRING. | input1 = validKey, input2 = NULL, input3 = ENCODING_STRING | API returns false and EXPECT_FALSE assertion passes | Should Fail | + * | 02 | Call add with valid key "validKey", NULL value, and encoding ENCODING_BASE64. | input1 = validKey, input2 = NULL, input3 = ENCODING_BASE64 | API returns false and EXPECT_FALSE assertion passes | Should Fail | + * | 03 | Call add with valid key "validKey", NULL value, and encoding ENCODING_BASE64_URL. | input1 = validKey, input2 = NULL, input3 = ENCODING_BASE64_URL | API returns false and EXPECT_FALSE assertion passes | Should Fail | + */ +TEST(DrmJsonObject, InvalidInputWithNullValue) { + std::cout << "Entering InvalidInputWithNullValue test" << std::endl; + + // Create object using default constructor + DrmJsonObject jsonObj; + + std::string name = "validKey"; + const char* value = nullptr; + + // Define encoding types for iteration + struct EncodingMap { + DrmJsonObject::ENCODING enc; + std::string encName; + } encodings[] = { + { DrmJsonObject::ENCODING_STRING, "ENCODING_STRING" }, + { DrmJsonObject::ENCODING_BASE64, "ENCODING_BASE64" }, + { DrmJsonObject::ENCODING_BASE64_URL, "ENCODING_BASE64_URL" } + }; + + bool result = true; + for (const auto &encMap : encodings) { + std::cout << "Invoking add with name: " << name + << ", value: NULL" + << ", encoding: " << encMap.encName << std::endl; + result = jsonObj.add(name, value, encMap.enc); + std::cout << "Method add returned: " << (result ? "true" : "false") << std::endl; + EXPECT_FALSE(result); + } + + std::cout << "Exiting InvalidInputWithNullValue test" << std::endl; +} +/** + * @brief Test that the API correctly handles invalid input when an empty name is provided. + * + * This test case verifies that the DrmJsonObject::add method returns false when an empty string is used as the name parameter. The test iterates over multiple encoding types to ensure that the method consistently rejects invalid input across different encodings. + * + * **Test Group ID:** Basic: 01@n + * **Test Case ID:** 096@n + * **Priority:** High@n + * + * **Pre-Conditions:** None@n + * **Dependencies:** None@n + * **User Interaction:** None@n + * + * **Test Procedure:** + * | Variation / Step | Description | Test Data | Expected Result | Notes | + * | :----: | --------- | ---------- | -------------- | ----- | + * | 01 | Instantiate DrmJsonObject using the default constructor | none | Object is created successfully | Should be successful | + * | 02 | Initialize test data with an empty name and a valid value | name = "", value = validValue | Variables are set with the correct values | Should be successful | + * | 03 | Iterate over defined encoding types and invoke the add method for each iteration | encoding = ENCODING_STRING, ENCODING_BASE64, ENCODING_BASE64_URL | The add method returns false for each encoding type | Should Fail | + * | 04 | Verify that the EXPECT_FALSE assertion check passes for each API invocation | result = false | The test assertion passes confirming the method returns false | Should be successful | + */ +TEST(DrmJsonObject, PotentiallyInvalidInputWithEmptyName) { + std::cout << "Entering PotentiallyInvalidInputWithEmptyName test" << std::endl; + + // Create object using default constructor + DrmJsonObject jsonObj; + + std::string name = ""; + const char* value = "validValue"; + + // Prepare encoding type iterations + struct EncodingMap { + DrmJsonObject::ENCODING enc; + std::string encName; + } encodings[] = { + { DrmJsonObject::ENCODING_STRING, "ENCODING_STRING" }, + { DrmJsonObject::ENCODING_BASE64, "ENCODING_BASE64" }, + { DrmJsonObject::ENCODING_BASE64_URL, "ENCODING_BASE64_URL" } + }; + + bool result = true; + for (const auto &encMap : encodings) { + std::cout << "Invoking add with name: (empty string)" + << ", value: " << value + << ", encoding: " << encMap.encName << std::endl; + result = jsonObj.add(name, value, encMap.enc); + std::cout << "Method add returned: " << (result ? "true" : "false") << std::endl; + EXPECT_FALSE(result); + } + + std::cout << "Exiting PotentiallyInvalidInputWithEmptyName test" << std::endl; +} +/** + * @brief Validate valid addition for all supported encoding types + * + * This test verifies that the add method of the DrmJsonObject class returns true when invoked with a valid key and value across all supported encoding types (ENCODING_STRING, ENCODING_BASE64, and ENCODING_BASE64_URL). It ensures the API consistently handles different encoding formats for addition. + * + * **Test Group ID:** Basic: 01@n + * **Test Case ID:** 097@n + * **Priority:** High@n + * + * **Pre-Conditions:** None@n + * **Dependencies:** None@n + * **User Interaction:** None@n + * + * **Test Procedure:**@n + * | Variation / Step | Description | Test Data | Expected Result | Notes |@n + * | :----: | --------- | ---------- |-------------- | ----- |@n + * | 01 | Create a DrmJsonObject instance using the default constructor | None | Instance is successfully created | Should be successful |@n + * | 02 | Define test inputs for key and value | testName = key, testValue = someData | Inputs are set correctly | Should be successful |@n + * | 03 | Invoke add API with encoding type ENCODING_STRING | testName = key, testValue = someData, encoding = ENCODING_STRING | API returns true; assertion passes | Should Pass |@n + * | 04 | Invoke add API with encoding type ENCODING_BASE64 | testName = key, testValue = someData, encoding = ENCODING_BASE64 | API returns true; assertion passes | Should Pass |@n + * | 05 | Invoke add API with encoding type ENCODING_BASE64_URL | testName = key, testValue = someData, encoding = ENCODING_BASE64_URL | API returns true; assertion passes | Should Pass | + */ +TEST(DrmJsonObject, ValidAdditionAllEncoding) { + std::cout << "Entering ValidAdditionAllEncoding test" << std::endl; + + // Create object using default constructor + DrmJsonObject drmObj; + + // Define test inputs + std::string testName = "key"; + std::string testValue = "someData"; + + // Loop through the encoding types + DrmJsonObject::ENCODING encodings[] = {DrmJsonObject::ENCODING_STRING, + DrmJsonObject::ENCODING_BASE64, + DrmJsonObject::ENCODING_BASE64_URL}; + + for (auto encoding : encodings) { + std::cout << "Invoking add with name: " << testName + << ", value: " << testValue + << ", encoding: " << encoding << std::endl; + bool result = drmObj.add(testName, testValue, encoding); + std::cout << "Method add returned: " << std::boolalpha << result << std::endl; + // Expect true for successful addition for each encoding type. + ASSERT_TRUE(result); + } + + std::cout << "Exiting ValidAdditionAllEncoding test" << std::endl; +} +/** + * @brief Test verifies that adding an empty value to a DrmJsonObject fails across all supported encoding types. + * + * This test ensures that the add method of DrmJsonObject does not allow inserting an empty value. It iterates through different encoding types (ENCODING_STRING, ENCODING_BASE64, ENCODING_BASE64_URL) and verifies that the method returns false for each case, using ASSERT_FALSE to validate the function's behavior. + * + * **Test Group ID:** Basic: 01@n + * **Test Case ID:** 098@n + * **Priority:** High@n + * + * **Pre-Conditions:** None@n + * **Dependencies:** None@n + * **User Interaction:** None@n + * + * **Test Procedure:**@n + * | Variation / Step | Description | Test Data | Expected Result | Notes | + * | :--------------: | -------------------------------------------------------------- | ------------------------------------------------------------------ | -------------------------------------------------- | ---------- | + * | 01 | Invoke add with empty value using ENCODING_STRING | testName = emptyValue, testValue = , encoding = ENCODING_STRING | API returns false; ASSERT_FALSE validates return | Should Fail | + * | 02 | Invoke add with empty value using ENCODING_BASE64 | testName = emptyValue, testValue = , encoding = ENCODING_BASE64 | API returns false; ASSERT_FALSE validates return | Should Fail | + * | 03 | Invoke add with empty value using ENCODING_BASE64_URL | testName = emptyValue, testValue = , encoding = ENCODING_BASE64_URL | API returns false; ASSERT_FALSE validates return | Should Fail | + */ +TEST(DrmJsonObject, ValidAdditionEmptyValue) { + std::cout << "Entering ValidAdditionEmptyValue test" << std::endl; + + // Create object using default constructor + DrmJsonObject drmObj; + + // Define test inputs + std::string testName = "emptyValue"; + std::string testValue = ""; + + // Loop through the encoding types + DrmJsonObject::ENCODING encodings[] = {DrmJsonObject::ENCODING_STRING, + DrmJsonObject::ENCODING_BASE64, + DrmJsonObject::ENCODING_BASE64_URL}; + + for (auto encoding : encodings) { + std::cout << "Invoking add with name: " << testName + << ", empty value, encoding: " << encoding << std::endl; + bool result = drmObj.add(testName, testValue, encoding); + std::cout << "Method add returned: " << std::boolalpha << result << std::endl; + // Expect false as empty value is not allowed. + ASSERT_FALSE(result); + } + + std::cout << "Exiting ValidAdditionEmptyValue test" << std::endl; +} +/** + * @brief Verify that the add API correctly handles large input strings. + * + * This test validates that the DrmJsonObject::add API can successfully add a key-value pair when both key and value are large strings (10,000 characters each). The test constructs the large input, simulates a fixed-size buffer assignment similar to strncpy, and then verifies that the add function returns true. This ensures that the API handles large inputs as expected. + * + * **Test Group ID:** Basic: 01@n + * **Test Case ID:** 099@n + * **Priority:** High@n + * + * **Pre-Conditions:** None@n + * **Dependencies:** None@n + * **User Interaction:** None@n + * + * **Test Procedure:** + * | Variation / Step | Description | Test Data | Expected Result | Notes | + * | :----: | --------- | ---------- |-------------- | ----- | + * | 01 | Create an instance of DrmJsonObject using the default constructor | None | DrmJsonObject instance is created successfully | Should be successful | + * | 02 | Prepare large input strings by creating a 10,000-character string and copying it to fixed-size buffers | largeStr = "a" (repeated 10000 times), nameBuffer & valueBuffer derive from largeStr | Large strings are created and buffers are populated correctly | Should be successful | + * | 03 | Convert the buffers into std::string variables (testName and testValue) | testName, testValue initialized from nameBuffer and valueBuffer respectively | Strings contain 10,000 'a' characters each | Should be successful | + * | 04 | Invoke the add API with testName, testValue, and ENCODING_STRING | input: testName = <10000 chars>, testValue = <10000 chars>, encoding = ENCODING_STRING; output: expected true | API returns true indicating successful addition | Should Pass | + */ +TEST(DrmJsonObject, ValidAdditionLargeInput) { + std::cout << "Entering ValidAdditionLargeInput test" << std::endl; + + // Create object using default constructor + DrmJsonObject drmObj; + + // Prepare large strings (10,000 characters each) + std::string largeStr(10000, 'a'); + // Use a buffer with strncpy style assignment (simulate fixed-size array assignment) + char nameBuffer[10001] = {0}; + char valueBuffer[10001] = {0}; + strncpy(nameBuffer, largeStr.c_str(), sizeof(nameBuffer) - 1); + strncpy(valueBuffer, largeStr.c_str(), sizeof(nameBuffer) - 1); + std::string testName(nameBuffer); + std::string testValue(valueBuffer); + + std::cout << "Invoking add with name: <10000 chars>, value: <10000 chars>, encoding: ENCODING_STRING" << std::endl; + bool result = drmObj.add(testName, testValue, DrmJsonObject::ENCODING_STRING); + std::cout << "Method add returned: " << std::boolalpha << result << std::endl; + // Expect true indicating the value was successfully added. + ASSERT_TRUE(result); + + std::cout << "Exiting ValidAdditionLargeInput test" << std::endl; +} +/** + * @brief Test the negative scenario for DrmJsonObject add method when an empty name is provided + * + * This test verifies that the DrmJsonObject::add method returns false when an empty string is used as the name. + * The test iterates over multiple encoding types (ENCODING_STRING, ENCODING_BASE64, ENCODING_BASE64_URL) to ensure consistent behavior. + * + * **Test Group ID:** Basic: 01@n + * **Test Case ID:** 100@n + * **Priority:** High@n + * + * **Pre-Conditions:** None@n + * **Dependencies:** None@n + * **User Interaction:** None@n + * + * **Test Procedure:** + * | Variation / Step | Description | Test Data | Expected Result | Notes | + * | :--------------: | ------------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------- | ---------------------------------------------------- | ----------- | + * | 01 | Invoke add with empty name and encoding DrmJsonObject::ENCODING_STRING | testName = "", testValue = value, encoding = DrmJsonObject::ENCODING_STRING | Method returns false and ASSERT_FALSE(result) passes | Should Fail | + * | 02 | Invoke add with empty name and encoding DrmJsonObject::ENCODING_BASE64 | testName = "", testValue = value, encoding = DrmJsonObject::ENCODING_BASE64 | Method returns false and ASSERT_FALSE(result) passes | Should Fail | + * | 03 | Invoke add with empty name and encoding DrmJsonObject::ENCODING_BASE64_URL | testName = "", testValue = value, encoding = DrmJsonObject::ENCODING_BASE64_URL | Method returns false and ASSERT_FALSE(result) passes | Should Fail | + */ +TEST(DrmJsonObject, NegativeAdditionEmptyName) { + std::cout << "Entering NegativeAdditionEmptyName test" << std::endl; + + // Create object using default constructor + DrmJsonObject drmObj; + + // Define test inputs + std::string testName = ""; + std::string testValue = "value"; + + // Loop through the encoding types + DrmJsonObject::ENCODING encodings[] = {DrmJsonObject::ENCODING_STRING, + DrmJsonObject::ENCODING_BASE64, + DrmJsonObject::ENCODING_BASE64_URL}; + + for (auto encoding : encodings) { + std::cout << "Invoking add with empty name, value: " << testValue + << ", encoding: " << encoding << std::endl; + bool result = drmObj.add(testName, testValue, encoding); + std::cout << "Method add returned: " << std::boolalpha << result << std::endl; + // Expect false as empty name is not allowed. + ASSERT_FALSE(result); + } + + std::cout << "Exiting NegativeAdditionEmptyName test" << std::endl; +} +/** + * @brief Verifies that the add method returns true when provided with a valid name and a non-empty byte vector + * + * This test creates an instance of DrmJsonObject and invokes its add method using a valid string name "LoopTest", + * a non-empty byte vector {0x10, 0x20, 0x30}, and three different encoding types (ENCODING_STRING, ENCODING_BASE64, ENCODING_BASE64_URL). + * The objective is to ensure that the add method successfully processes valid inputs and returns true consistently across the supported encoding types. + * + * **Test Group ID:** Basic: 01@n + * **Test Case ID:** 101@n + * **Priority:** High@n + * + * **Pre-Conditions:** None@n + * **Dependencies:** None@n + * **User Interaction:** None@n + * + * **Test Procedure:** + * | Variation / Step | Description | Test Data | Expected Result | Notes | + * | :----: | --------- | ---------- |-------------- | ----- | + * | 01 | Call add method with encoding ENCODING_STRING | name = LoopTest, values = 0x10, 0x20, 0x30, encoding = ENCODING_STRING | API returns true and EXPECT_TRUE assertion passes | Should Pass | + * | 02 | Call add method with encoding ENCODING_BASE64 | name = LoopTest, values = 0x10, 0x20, 0x30, encoding = ENCODING_BASE64 | API returns true and EXPECT_TRUE assertion passes | Should Pass | + * | 03 | Call add method with encoding ENCODING_BASE64_URL | name = LoopTest, values = 0x10, 0x20, 0x30, encoding = ENCODING_BASE64_URL | API returns true and EXPECT_TRUE assertion passes | Should Pass | + */ +TEST(DrmJsonObject, AddWithValidNameNonEmptyByteVector) +{ + std::cout << "Entering AddWithValidNameNonEmptyByteVector test" << std::endl; + + // Create an object of DrmJsonObject using its default constructor + DrmJsonObject drmObj; + + // Prepare test inputs + std::string name = "LoopTest"; + std::vector values = { 0x10, 0x20, 0x30 }; + + // Array of encoding types to test + DrmJsonObject::ENCODING encodings[] = { DrmJsonObject::ENCODING_STRING, DrmJsonObject::ENCODING_BASE64, DrmJsonObject::ENCODING_BASE64_URL }; + + // Loop through the encoding types and invoke the add method + for (auto encoding : encodings) + { + std::cout << "Invoking add with name: " << name + << ", values: {0x" << std::hex << static_cast(values[0]) << ", 0x" << static_cast(values[1]) + << ", 0x" << static_cast(values[2]) << "}" << std::dec + << ", encoding: " << encoding << std::endl; + + bool result = drmObj.add(name, values, encoding); + std::cout << "Returned value from add: " << std::boolalpha << result << std::endl; + + // Assert that the return value is true for valid inputs + EXPECT_TRUE(result); + } + + std::cout << "Exiting AddWithValidNameNonEmptyByteVector test" << std::endl; +} +/** + * @brief Verify that adding an entry with an empty name and non-empty byte vector fails. + * + * This test verifies that when invoking the add method of DrmJsonObject with an empty string as the name and a non-empty byte vector, the method returns false. It iterates through different encoding types to ensure consistent behavior across various encoding options. + * + * **Test Group ID:** Basic: 01@n + * **Test Case ID:** 102@n + * **Priority:** High@n + * + * **Pre-Conditions:** None@n + * **Dependencies:** None@n + * **User Interaction:** None@n + * + * **Test Procedure:** + * | Variation / Step | Description | Test Data | Expected Result | Notes | + * | :----: | --------- | ---------- |-------------- | ----- | + * | 01 | Invoke add with empty name and non-empty byte vector using ENCODING_STRING | name = "", values = {0xAA,0xBB,0xCC}, encoding = ENCODING_STRING | API returns false and EXPECT_FALSE assertion passes | Should Fail | + * | 02 | Invoke add with empty name and non-empty byte vector using ENCODING_BASE64 | name = "", values = {0xAA,0xBB,0xCC}, encoding = ENCODING_BASE64 | API returns false and EXPECT_FALSE assertion passes | Should Fail | + * | 03 | Invoke add with empty name and non-empty byte vector using ENCODING_BASE64_URL | name = "", values = {0xAA,0xBB,0xCC}, encoding = ENCODING_BASE64_URL | API returns false and EXPECT_FALSE assertion passes | Should Fail | + */ +TEST(DrmJsonObject, AddWithEmptyNameNonEmptyByteVector) +{ + std::cout << "Entering AddWithEmptyNameNonEmptyByteVector test" << std::endl; + + // Create an object of DrmJsonObject using its default constructor + DrmJsonObject drmObj; + + // Prepare test inputs + std::string name = ""; + std::vector values = { 0xAA, 0xBB, 0xCC }; + + // Array of encoding types to test + DrmJsonObject::ENCODING encodings[] = { DrmJsonObject::ENCODING_STRING, DrmJsonObject::ENCODING_BASE64, DrmJsonObject::ENCODING_BASE64_URL }; + + // Loop through the encoding types and invoke the add method + for (auto encoding : encodings) + { + std::cout << "Invoking add with empty name, values: {0x" << std::hex << static_cast(values[0]) << ", 0x" << static_cast(values[1]) + << ", 0x" << static_cast(values[2]) << "}" << std::dec + << ", encoding: " << encoding << std::endl; + + bool result = drmObj.add(name, values, encoding); + std::cout << "Returned value from add: " << std::boolalpha << result << std::endl; + + // Assert that the return value is false when name is empty + EXPECT_FALSE(result); + } + + std::cout << "Exiting AddWithEmptyNameNonEmptyByteVector test" << std::endl; +} +/** + * @brief Validate that DrmJsonObject::add returns false when provided with a valid name and an empty byte vector. + * + * This test verifies that the DrmJsonObject::add method correctly handles an empty byte vector by returning false. The test uses different encoding types to ensure consistent behavior when no data is supplied in the byte vector. + * + * **Test Group ID:** Basic: 01@n + * **Test Case ID:** 103@n + * **Priority:** High@n + * + * **Pre-Conditions:** None@n + * **Dependencies:** None@n + * **User Interaction:** None@n + * + * **Test Procedure:** + * | Variation / Step | Description | Test Data | Expected Result | Notes | + * | :----: | --------- | ---------- |-------------- | ----- | + * | 01 | Create an instance of DrmJsonObject using the default constructor | None | Instance is successfully created | Should be successful | + * | 02 | Initialize test inputs with a valid name and an empty byte vector | name = "EmptyVectorTest", values = (empty vector) | Test inputs are correctly initialized | Should be successful | + * | 03 | Iterate over each encoding type and call the add method | encoding = ENCODING_STRING, ENCODING_BASE64, ENCODING_BASE64_URL; name = "EmptyVectorTest", values = (empty vector) | add() returns false for each encoding type | Should Pass | + * | 04 | Validate the return value of the add method using assertion check | output: result = false | EXPECT_FALSE(result) passes for each encoding type | Should Pass | + */ +TEST(DrmJsonObject, AddWithValidNameEmptyByteVector) +{ + std::cout << "Entering AddWithValidNameEmptyByteVector test" << std::endl; + + // Create an object of DrmJsonObject using its default constructor + DrmJsonObject drmObj; + + // Prepare test inputs + std::string name = "EmptyVectorTest"; + std::vector values; // empty vector + + // Array of encoding types to test + DrmJsonObject::ENCODING encodings[] = { DrmJsonObject::ENCODING_STRING, DrmJsonObject::ENCODING_BASE64, DrmJsonObject::ENCODING_BASE64_URL }; + + // Loop through the encoding types and invoke the add method + for (auto encoding : encodings) + { + std::cout << "Invoking add with name: " << name + << ", empty values vector" + << ", encoding: " << encoding << std::endl; + + bool result = drmObj.add(name, values, encoding); + std::cout << "Returned value from add: " << std::boolalpha << result << std::endl; + + // Assert that the return value is false when values vector is empty + EXPECT_FALSE(result); + } + + std::cout << "Exiting AddWithValidNameEmptyByteVector test" << std::endl; +} +/** + * @brief Verifies that retrieving a valid JSON property using string encoding returns the correct result. + * + * This test ensures that the DrmJsonObject correctly retrieves the property "validProperty" when using the ENCODING_STRING mode. + * It checks that the retrieval operation returns true and that the output vector is populated as expected. + * + * **Test Group ID:** Basic: 01@n + * **Test Case ID:** 104@n + * **Priority:** High@n + * + * **Pre-Conditions:** None@n + * **Dependencies:** None@n + * **User Interaction:** None@n + * + * **Test Procedure:**@n + * | Variation / Step | Description | Test Data | Expected Result | Notes | + * | :----: | --------- | ---------- |-------------- | ----- | + * | 01 | Instantiate DrmJsonObject and initialize test parameters. | property = validProperty, values = empty vector, encoding = ENCODING_STRING | Object is created and test parameters are initialized successfully. | Should be successful | + * | 02 | Invoke get() API with the provided valid property and string encoding, and verify the returned result. | property = validProperty, values = output vector, encoding = ENCODING_STRING | API returns true and the output vector is populated as expected. | Should Pass | + */ +TEST(DrmJsonObject, ValidRetrieval_StringEncoding) { + std::cout << "Entering ValidRetrieval_StringEncoding test" << std::endl; + + // Create the object (assumes default constructor populates necessary JSON property "validProperty") + DrmJsonObject obj; + std::vector values; + std::string property = "validProperty"; + + std::cout << "Invoking get with property: " << property + << ", encoding: ENCODING_STRING" << std::endl; + bool result = obj.get(property, values, DrmJsonObject::ENCODING_STRING); + std::cout << "Returned from get: " << std::boolalpha << result << std::endl; + + if (result) { + std::cout << "Retrieved bytes: "; + for (auto byte : values) { + std::cout << static_cast(byte) << " "; + } + std::cout << std::endl; + } + + EXPECT_TRUE(result); + + std::cout << "Exiting ValidRetrieval_StringEncoding test" << std::endl; +} +/** + * @brief Validate that DrmJsonObject correctly retrieves property data using Base64 encoding. + * + * This test verifies that when a valid property ("validProperty") is requested with the + * Base64 encoding option, the API call correctly returns true and populates the output + * vector with the expected bytes. The objective is to ensure the proper functionality + * of the get method for valid Base64 retrieval scenarios. + * + * **Test Group ID:** Basic: 01@n + * **Test Case ID:** 105@n + * **Priority:** High@n + * + * **Pre-Conditions:** None@n + * **Dependencies:** None@n + * **User Interaction:** None@n + * + * **Test Procedure:** + * | Variation / Step | Description | Test Data | Expected Result | Notes | + * | :----: | --------- | ---------- |-------------- | ----- | + * | 01 | Initialize test objects and set up test data. | N/A | Objects created and variables initialized. | Should be successful | + * | 02 | Invoke DrmJsonObject::get with property "validProperty" and encoding ENCODING_BASE64. | property = validProperty, encoding = ENCODING_BASE64, vector values = empty | API returns true after populating vector if data exists. | Should Pass | + * | 03 | Verify that the EXPECT_TRUE assertion confirms the API call returned true. | result = true | Assertion passes confirming valid retrieval. | Should be successful | + */ +TEST(DrmJsonObject, ValidRetrieval_Base64) { + std::cout << "Entering ValidRetrieval_Base64 test" << std::endl; + + DrmJsonObject obj; + std::vector values; + std::string property = "validProperty"; + + std::cout << "Invoking get with property: " << property + << ", encoding: ENCODING_BASE64" << std::endl; + bool result = obj.get(property, values, DrmJsonObject::ENCODING_BASE64); + std::cout << "Returned from get: " << std::boolalpha << result << std::endl; + + if (result) { + std::cout << "Retrieved bytes: "; + for (auto byte : values) { + std::cout << static_cast(byte) << " "; + } + std::cout << std::endl; + } + + EXPECT_TRUE(result); + + std::cout << "Exiting ValidRetrieval_Base64 test" << std::endl; +} +/** + * @brief Tests valid retrieval of a property using Base64Url encoding. + * + * This test verifies that the DrmJsonObject::get method successfully retrieves the value of an existing property while using the Base64Url encoding. It ensures that the function returns true when the property "validProperty" exists and that the output is correctly populated. + * + * **Test Group ID:** Basic: 01 + * **Test Case ID:** 106 + * **Priority:** High + * + * **Pre-Conditions:** None + * **Dependencies:** None + * **User Interaction:** None + * + * **Test Procedure:** + * | Variation / Step | Description | Test Data | Expected Result | Notes | + * | :--------------: | ----------------------------------------------------------------------------------------------- | ------------------------------------------------------------------- | ---------------------------------------------------------------------------------- | ----------------- | + * | 01 | Initialize the test environment and create DrmJsonObject instance along with variables. | property = validProperty, values = empty | Objects are instantiated successfully. | Should be successful | + * | 02 | Invoke the get() method with property "validProperty" and encoding ENCODING_BASE64_URL. | property = validProperty, encoding = ENCODING_BASE64_URL, values = empty| Returns true indicating successful retrieval and populates the values vector. | Should Pass | + * | 03 | Validate the result and print the retrieved bytes when the result is true. | result = true, values = retrieved bytes | EXPECT_TRUE(result) passes confirming the valid retrieval of property value. | Should be successful | + */ +TEST(DrmJsonObject, ValidRetrieval_Base64Url) { + std::cout << "Entering ValidRetrieval_Base64Url test" << std::endl; + + DrmJsonObject obj; + std::vector values; + std::string property = "validProperty"; + + std::cout << "Invoking get with property: " << property + << ", encoding: ENCODING_BASE64_URL" << std::endl; + bool result = obj.get(property, values, DrmJsonObject::ENCODING_BASE64_URL); + std::cout << "Returned from get: " << std::boolalpha << result << std::endl; + + if (result) { + std::cout << "Retrieved bytes: "; + for (auto byte : values) { + std::cout << static_cast(byte) << " "; + } + std::cout << std::endl; + } + + EXPECT_TRUE(result); + + std::cout << "Exiting ValidRetrieval_Base64Url test" << std::endl; +} +/** + * @brief Test behavior of DrmJsonObject::get when the requested property is missing + * + * This test verifies that calling the get method with a non-existent property ("missingProperty") + * using the ENCODING_STRING encoding returns false and leaves the output vector empty. This is important + * to ensure that the API properly handles missing properties without altering the output data structures. + * + * **Test Group ID:** Basic: 01@n + * **Test Case ID:** 107@n + * **Priority:** High@n + * + * **Pre-Conditions:** None@n + * **Dependencies:** None@n + * **User Interaction:** None@n + * + * **Test Procedure:** + * | Variation / Step | Description | Test Data | Expected Result | Notes | + * | :----: | ------------------------------------------------------------------------------------------------------------ | ---------------------------------------------------------------------- | ----------------------------------------------------------------------------------------------- | ------------- | + * | 01 | Invoke DrmJsonObject::get with a property name "missingProperty" using encoding ENCODING_STRING to retrieve data | property = missingProperty, encoding = ENCODING_STRING, output vector = empty | API returns false; assertion checks: EXPECT_FALSE(result) and EXPECT_TRUE(values.empty()) | Should Fail | + */ +TEST(DrmJsonObject, MissingProperty) { + std::cout << "Entering MissingProperty test" << std::endl; + + DrmJsonObject obj; + std::vector values; + std::string property = "missingProperty"; + + std::cout << "Invoking get with property: " << property + << ", encoding: ENCODING_STRING" << std::endl; + bool result = obj.get(property, values, DrmJsonObject::ENCODING_STRING); + std::cout << "Returned from get: " << std::boolalpha << result << std::endl; + std::cout << "Size of retrieved vector: " << values.size() << std::endl; + + EXPECT_FALSE(result); + EXPECT_TRUE(values.empty()); + + std::cout << "Exiting MissingProperty test" << std::endl; +} +/** + * @brief This test verifies that calling the get function with an empty property name using ENCODING_STRING returns false and leaves the output vector empty. + * + * This test is designed to check that the DrmJsonObject::get function correctly handles an empty property name when the encoding type is set to ENCODING_STRING. It ensures that the function returns false and that the output vector remains empty, confirming proper handling of an edge case input. + * + * **Test Group ID:** Basic: 01@n + * **Test Case ID:** 108@n + * **Priority:** High@n + * + * **Pre-Conditions:** None@n + * **Dependencies:** None@n + * **User Interaction:** None@n + * + * **Test Procedure:**@n + * | Variation / Step | Description | Test Data | Expected Result | Notes | + * | :--------------: | ------------------------------------------------------- | -------------------------------------------------------------- | -------------------------------------------------------------------------------------- | ----------- | + * | 01 | Invoke get with an empty property name using ENCODING_STRING | property = "", values = empty vector, encoding = ENCODING_STRING | API returns false; values vector remains empty (assert: EXPECT_FALSE(result), EXPECT_TRUE(values.empty())) | Should Pass | + */ +TEST(DrmJsonObject, EmptyPropertyName_StringEncoding) { + std::cout << "Entering EmptyPropertyName_StringEncoding test" << std::endl; + + DrmJsonObject obj; + std::vector values; + std::string property = ""; + + std::cout << "Invoking get with empty property name" + << ", encoding: ENCODING_STRING" << std::endl; + bool result = obj.get(property, values, DrmJsonObject::ENCODING_STRING); + std::cout << "Returned from get: " << std::boolalpha << result << std::endl; + std::cout << "Size of retrieved vector: " << values.size() << std::endl; + + EXPECT_FALSE(result); + EXPECT_TRUE(values.empty()); + + std::cout << "Exiting EmptyPropertyName_StringEncoding test" << std::endl; +} +/** + * @brief Verify that calling get() with an empty property name using ENCODING_BASE64 properly fails. + * + * This test checks that when get() is invoked with an empty property name and the encoding set to ENCODING_BASE64, + * it returns false and leaves the output vector empty. This ensures that the API does not process invalid empty property names. + * + * **Test Group ID:** Basic: 01 + * **Test Case ID:** 109 + * **Priority:** High + * + * **Pre-Conditions:** None + * **Dependencies:** None + * **User Interaction:** None + * + * **Test Procedure:** + * | Variation / Step | Description | Test Data | Expected Result | Notes | + * | :----: | --------- | ---------- |-------------- | ----- | + * | 01 | Initialize a DrmJsonObject, set property as an empty string, and invoke the get() method with ENCODING_BASE64. | property = "", values = empty vector, encoding = DrmJsonObject::ENCODING_BASE64 | get() returns false and the values vector remains empty. | Should Fail | + */ +TEST(DrmJsonObject, EmptyPropertyName_Base64) { + std::cout << "Entering EmptyPropertyName_Base64 test" << std::endl; + + DrmJsonObject obj; + std::vector values; + std::string property = ""; + + std::cout << "Invoking get with empty property name" + << ", encoding: ENCODING_BASE64" << std::endl; + bool result = obj.get(property, values, DrmJsonObject::ENCODING_BASE64); + std::cout << "Returned from get: " << std::boolalpha << result << std::endl; + std::cout << "Size of retrieved vector: " << values.size() << std::endl; + + EXPECT_FALSE(result); + EXPECT_TRUE(values.empty()); + + std::cout << "Exiting EmptyPropertyName_Base64 test" << std::endl; +} +/** + * @brief Validate that DrmJsonObject::get returns false and an empty vector when provided with an empty property name using ENCODING_BASE64_URL. + * + * This test verifies that the API correctly handles the scenario where an empty property name is passed. It ensures that the function returns false and does not populate the output vector when the input is invalid. + * + * **Test Group ID:** Basic: 01@n + * **Test Case ID:** 110@n + * **Priority:** (High) This test is crucial as it confirms proper handling of invalid input for overall functionality@n + * + * **Pre-Conditions:** None@n + * **Dependencies:** None@n + * **User Interaction:** None@n + * + * **Test Procedure:**@n + * | Variation / Step | Description | Test Data | Expected Result | Notes | + * | :----: | --------- | ---------- |-------------- | ----- | + * | 01 | Invoke get method on DrmJsonObject with an empty property name and ENCODING_BASE64_URL encoding | input: property = "", encoding = DrmJsonObject::ENCODING_BASE64_URL; output: values vector is empty | API returns false and the values vector remains empty (EXPECT_FALSE(result) and EXPECT_TRUE(values.empty())) | Should Fail | + */ +TEST(DrmJsonObject, EmptyPropertyName_Base64Url) { + std::cout << "Entering EmptyPropertyName_Base64Url test" << std::endl; + + DrmJsonObject obj; + std::vector values; + std::string property = ""; + + std::cout << "Invoking get with empty property name" + << ", encoding: ENCODING_BASE64_URL" << std::endl; + bool result = obj.get(property, values, DrmJsonObject::ENCODING_BASE64_URL); + std::cout << "Returned from get: " << std::boolalpha << result << std::endl; + std::cout << "Size of retrieved vector: " << values.size() << std::endl; + + EXPECT_FALSE(result); + EXPECT_TRUE(values.empty()); + + std::cout << "Exiting EmptyPropertyName_Base64Url test" << std::endl; +} + +int main(int argc, char **argv) { + + ::testing::InitGoogleTest(&argc, argv); + return RUN_ALL_TESTS(); + +} diff --git a/drm/test/test_l1_HlsDrmSessionManager.cpp b/drm/test/test_l1_HlsDrmSessionManager.cpp new file mode 100644 index 0000000..b699f4e --- /dev/null +++ b/drm/test/test_l1_HlsDrmSessionManager.cpp @@ -0,0 +1,201 @@ + +/* + * If not stated otherwise in this file or this component's LICENSE file the + * following copyright and licenses apply: + * + * Copyright 2025 RDK Management + * + * 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. + */ + +/** +* @file test_l1_HlsDrmSessionManager.cpp +* @page HlsDrmSessionManager Level 1 Tests +* +* ## Module's Role +* This module includes Level 1 functional tests (success and failure scenarios). +* This is to ensure that the HlsDrmSessionManager methods meet the requirements. +* +* **Pre-Conditions:** None @n +* **Dependencies:** None @n +* +*/ + +#include +#include +#include +#include "HlsDrmSessionManager.h" + +/** + * @brief Verifies that a DRM session is successfully created using a positive test scenario. + * + * This test validates that when valid arguments (a default DrmInfo object and streamType = 1) are provided to the createSession API of HlsDrmSessionManager, a non-null pointer is returned, indicating successful creation of a DRM session. + * + * **Test Group ID:** Basic: 01@n + * **Test Case ID:** 001@n + * **Priority:** High@n + * + * **Pre-Conditions:** None@n + * **Dependencies:** None@n + * **User Interaction:** None@n + * + * **Test Procedure:**@n + * | Variation / Step | Description | Test Data |Expected Result |Notes | + * | :----: | --------- | ---------- |-------------- | ----- | + * | 01 | Instantiate DrmInfo and HlsDrmSessionManager objects | drmInfo = default, drmManager = default constructor | Objects are instantiated | Should be successful | + * | 02 | Set streamType value | streamType = 1 | streamType is assigned value 1 | Should be successful | + * | 03 | Invoke createSession with drmInfo and streamType, and capture the returned session pointer | drmInfo = default, streamType = 1, output: session pointer | Returns a valid non-null session pointer | Should Pass | + * | 04 | Validate the returned session pointer using EXPECT_NE | session pointer != nullptr | Assertion passes confirming successful session creation | Should Pass | + */ +TEST(HlsDrmSessionManager, PositiveDRMSessionCreation) { + std::cout << "Entering PositiveDRMSessionCreation test" << std::endl; + + // Create DrmInfo + DrmInfo drmInfo; + + // Create object for HlsDrmSessionManager using its default constructor + HlsDrmSessionManager drmManager; + int streamType = 1; + std::cout << "Invoking createSession with streamType: " << streamType << std::endl; + + // Invoke createSession and capture the return value + std::shared_ptr session = drmManager.createSession(drmInfo, streamType); + std::cout << "Returned session pointer: " << session.get() << std::endl; + + // Validate that the returned session is non-null indicating successful DRM session creation + EXPECT_NE(session, nullptr); + + std::cout << "Exiting PositiveDRMSessionCreation test" << std::endl; +} +/** + * @brief Validate that HlsDrmSessionManager::createSession fails when an invalid stream type is provided + * + * This test verifies that the createSession API of HlsDrmSessionManager returns a null pointer when an invalid stream type is passed. It ensures that the API handles erroneous input correctly by not creating a DRM session. + * + * **Test Group ID:** Basic: 01@n + * **Test Case ID:** 002@n + * **Priority:** High@n + * + * **Pre-Conditions:** None@n + * **Dependencies:** None@n + * **User Interaction:** None@n + * + * **Test Procedure:** + * | Variation / Step | Description | Test Data | Expected Result | Notes | + * | :----: | ------------------------------------------------------------------------ | ------------------------------------------------------ | ------------------------------------------------------------- | ---------------- | + * | 01 | Create a valid DrmInfo object and instantiate HlsDrmSessionManager | drmInfo = valid, drmManager created | Successfully created objects | Should be successful | + * | 02 | Set an invalid stream type | streamType = -1 | Invalid stream type set | Should be successful | + * | 03 | Invoke createSession with the valid DrmInfo and invalid streamType | drmInfo = valid, streamType = -1 | Returns null pointer indicating failure | Should Pass | + * | 04 | Validate that the returned session pointer is null using EXPECT_EQ | session pointer from createSession | EXPECT_EQ confirms that session pointer is null | Should Pass | + */ +TEST(HlsDrmSessionManager, NegativeDRMSessionCreation) { + std::cout << "Entering NegativeDRMSessionCreation test" << std::endl; + + // Create and populate DrmInfo with valid fields but with an invalid stream type for this test + DrmInfo drmInfo; + + // Create object for HlsDrmSessionManager using its default constructor + HlsDrmSessionManager drmManager; + int streamType = -1; + std::cout << "Invoking createSession with streamType: " << streamType << std::endl; + + // Invoke createSession and capture the return value + std::shared_ptr session = drmManager.createSession(drmInfo, streamType); + std::cout << "Returned session pointer: " << session.get() << std::endl; + + // Validate that the returned session is null indicating failure due to an invalid stream type + EXPECT_EQ(session, nullptr); + + std::cout << "Exiting NegativeDRMSessionCreation test" << std::endl; +} +/** + * @brief Test HlsDrmSessionManager::getInstance() to verify that a valid singleton instance is returned. + * + * This test verifies that the getInstance() method of HlsDrmSessionManager returns a valid (non-null) singleton instance. It ensures that the singleton implementation is correct and does not throw exceptions during invocation. + * + * **Test Group ID:** Basic: 01@n + * **Test Case ID:** 003@n + * **Priority:** High@n + * + * **Pre-Conditions:** None@n + * **Dependencies:** None@n + * **User Interaction:** None@n + * + * **Test Procedure:**@n + * | Variation / Step | Description | Test Data | Expected Result | Notes | + * | :----: | --------- | ---------- |-------------- | ----- | + * | 01 | Invoke HlsDrmSessionManager::getInstance() to obtain the singleton instance and verify its validity | input: none, output: instance address != nullptr | The API should return a valid, non-null instance and pass the ASSERT_NE check | Should Pass | + */ +TEST(HlsDrmSessionManager, getInstance_start) { + std::cout << "Entering getInstance_start test" << std::endl; + try { + std::cout << "Invoking HlsDrmSessionManager::getInstance()" << std::endl; + HlsDrmSessionManager &instance = HlsDrmSessionManager::getInstance(); + std::cout << "Received instance address: " << &instance << std::endl; + // Verify the returned instance is valid (non-null) + ASSERT_NE(&instance, nullptr); + std::cout << "HlsDrmSessionManager instance is valid and non-null." << std::endl; + } catch(const std::exception &e) { + std::cout << "Exception caught during getInstance() invocation: " << e.what() << std::endl; + FAIL() << "HlsDrmSessionManager::getInstance() threw an exception: " << e.what(); + } catch(...) { + std::cout << "Unknown exception caught during getInstance() invocation." << std::endl; + FAIL() << "HlsDrmSessionManager::getInstance() threw an unknown exception."; + } + std::cout << "Exiting getInstance_start test" << std::endl; +} +/** + * @brief This test verifies that HlsDrmSessionManager returns true when provided with a valid DrmInfo object. + * + * This test is designed to ensure that the isDrmSupported method in HlsDrmSessionManager correctly identifies support for DRM when valid DRM information is provided. It creates an instance using the default constructor, prepares a valid DrmInfo object, invokes the method, and asserts that the result is true. + * + * **Test Group ID:** Basic: 01@n + * **Test Case ID:** 004@n + * **Priority:** High@n + * + * **Pre-Conditions:** None@n + * **Dependencies:** None@n + * **User Interaction:** None@n + * + * **Test Procedure:**@n + * | Variation / Step | Description | Test Data | Expected Result | Notes | + * | :--------------: | ---------------------------------------------------------------------------------------------------------- | ----------------------------------------------------- | -------------------------------------------------- | ------------- | + * | 01 | Create HlsDrmSessionManager object using the default constructor | drmSessionManager = default | Object is instantiated successfully | Should be successful | + * | 02 | Prepare a valid DrmInfo object for HLS media format | drmInfo = valid | DrmInfo object is prepared correctly | Should be successful | + * | 03 | Invoke the isDrmSupported method on the drmSessionManager object using the valid drmInfo object | input: drmInfo = valid, output: result = expected true| Method returns true | Should Pass | + * | 04 | Validate that the result returned by isDrmSupported is true using ASSERT_TRUE | result = true | Assertion confirms the method returns true | Should Pass | + */ +TEST(HlsDrmSessionManager, PositiveTestForDRMSupport) { + std::cout << "Entering PositiveTestForDRMSupport test" << std::endl; + + // Create HlsDrmSessionManager object using the default constructor. + std::cout << "Creating HlsDrmSessionManager object using default constructor" << std::endl; + HlsDrmSessionManager drmSessionManager; + + // Prepare DrmInfo object with valid DRM method and HLS media format. + DrmInfo drmInfo; + + // Invoke the method under test. + bool result = drmSessionManager.isDrmSupported(drmInfo); + std::cout << "Method isDrmSupported returned: " << std::boolalpha << result << std::endl; + + // Check that the method returns true for valid DRM support. + ASSERT_TRUE(result); + + std::cout << "Exiting PositiveTestForDRMSupport test" << std::endl; +} + +int main(int argc, char **argv) { + ::testing::InitGoogleTest(&argc, argv); + return RUN_ALL_TESTS(); +} \ No newline at end of file diff --git a/drm/test/test_l1_PlayerHlsDrmSessionInterfaceBase.cpp b/drm/test/test_l1_PlayerHlsDrmSessionInterfaceBase.cpp new file mode 100644 index 0000000..b5625ca --- /dev/null +++ b/drm/test/test_l1_PlayerHlsDrmSessionInterfaceBase.cpp @@ -0,0 +1,259 @@ + +/* + * If not stated otherwise in this file or this component's LICENSE file the + * following copyright and licenses apply: + * + * Copyright 2025 RDK Management + * + * 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. + */ + +/** +* @file test_l1_PlayerHlsDrmSessionInterfaceBase.cpp +* @page PlayerHlsDrmSessionInterfaceBase Level 1 Tests +* +* ## Module's Role +* This module includes Level 1 functional tests (success and failure scenarios). +* This is to ensure that the PlayerHlsDrmSessionInterfaceBase methods meet the requirements. +* +* **Pre-Conditions:** None @n +* **Dependencies:** None @n +* +*/ + +#include +#include +#include +#include "PlayerHlsDrmSessionInterfaceBase.h" + + +// Test Case: Register a valid GetHlsDrmSession callback +/** + * @brief Test to register a valid lambda callback for GetHlsDrmSession and verify its proper invocation. + * + * This test validates that a valid lambda callback is correctly registered using RegisterGetHlsDrmSessionCb and, when invoked with test parameters, updates the callbackInvoked flag. This confirms that the callback registration and execution mechanism in the PlayerHlsDrmSessionInterfaceBase class is working as expected. + * + * **Test Group ID:** Basic: 01@n + * **Test Case ID:** 001@n + * **Priority:** High@n + * + * **Pre-Conditions:** None@n + * **Dependencies:** None@n + * **User Interaction:** None@n + * + * **Test Procedure:**@n + * | Variation / Step | Description | Test Data | Expected Result | Notes | + * | :----: | --------- | ---------- |-------------- | ----- | + * | 01 | Invoke RegisterGetHlsDrmSessionCb with a valid lambda callback, then trigger the callback with test parameters. | callback = validCallback, dummyBridge = nullptr, dummyDrmHelper = nullptr, dummySession = nullptr, streamType = 42 | Callback should be registered and, when invoked, update callbackInvoked to true and satisfy EXPECT_TRUE(callbackInvoked) | Should Pass | + */ +TEST(PlayerHlsDrmSessionInterfaceBase, RegisterValidGetHlsDrmSessionCbTest) { + std::cout << "Entering RegisterValidGetHlsDrmSessionCbTest test" << std::endl; + + PlayerHlsDrmSessionInterfaceBase obj; + + bool callbackInvoked = false; + // Define a lambda callback that updates callbackInvoked flag when called. + auto validCallback = [&callbackInvoked](std::shared_ptr& bridge, + std::shared_ptr& drmHelper, + DrmSession*& session, + int streamType) { + std::cout << "Lambda callback invoked with streamType: " << streamType << std::endl; + // Simulate internal state update using a fixed size char array assignment via strncpy. + char internalState[64]; + const char* stateMsg = "Callback executed"; + std::memset(internalState, 0, sizeof(internalState)); + std::strncpy(internalState, stateMsg, sizeof(internalState)-1); + std::cout << "Internal state updated in callback: " << internalState << std::endl; + callbackInvoked = true; + }; + + std::cout << "Invoking RegisterGetHlsDrmSessionCb with valid lambda callback" << std::endl; + obj.RegisterGetHlsDrmSessionCb(validCallback); + std::cout << "Callback registered. Internal state 'GetHlsDrmSessionCb' updated with provided lambda." << std::endl; + + // Verify that the callback has been registered (is callable) + if (obj.GetHlsDrmSessionCb) { + std::cout << "Retrieved callback is valid. Invoking the callback with test parameters." << std::endl; + std::shared_ptr dummyBridge(nullptr); + std::shared_ptr dummyDrmHelper(nullptr); + DrmSession* dummySession = nullptr; + int streamType = 42; + obj.GetHlsDrmSessionCb(dummyBridge, dummyDrmHelper, dummySession, streamType); + std::cout << "Callback was invoked with streamType value: " << streamType << std::endl; + } else { + std::cout << "Error: Callback not registered properly." << std::endl; + } + + EXPECT_TRUE(callbackInvoked); + std::cout << "Exiting RegisterValidGetHlsDrmSessionCbTest test" << std::endl; +} +/** + * @brief Verify that registering an empty (default-constructed) callback results in no callback action. + * + * This test verifies that when an empty callback is registered using RegisterGetHlsDrmSessionCb on a PlayerHlsDrmSessionInterfaceBase object, + * the internal state of GetHlsDrmSessionCb remains empty. This ensures the system behaves correctly when no callback logic is provided. + * + * **Test Group ID:** Basic: 01 + * **Test Case ID:** 002 + * **Priority:** High + * + * **Pre-Conditions:** None + * **Dependencies:** None + * **User Interaction:** None + * + * **Test Procedure:** + * | Variation / Step | Description | Test Data | Expected Result | Notes | + * | :----: | --------- | ---------- |-------------- | ----- | + * | 01 | Instantiate PlayerHlsDrmSessionInterfaceBase object | None | Object instantiated successfully | Should be successful | + * | 02 | Register empty callback using RegisterGetHlsDrmSessionCb | emptyCallback = default constructed | Callback internal state remains empty | Should Pass | + * | 03 | Verify internal state of GetHlsDrmSessionCb via conditional log | None | Log reflects callback is empty as expected | Should Pass | + * | 04 | Assert that the callback is false using EXPECT_FALSE | None | EXPECT_FALSE assertion passes confirming callback is empty | Should Pass | + */ +TEST(PlayerHlsDrmSessionInterfaceBase, RegisterEmptyGetHlsDrmSessionCbTest) { + std::cout << "Entering RegisterEmptyGetHlsDrmSessionCbTest test" << std::endl; + + PlayerHlsDrmSessionInterfaceBase obj; + + std::function&, std::shared_ptr&, DrmSession*&, int)> emptyCallback; + std::cout << "Registering an empty (default-constructed) callback using RegisterGetHlsDrmSessionCb" << std::endl; + obj.RegisterGetHlsDrmSessionCb(emptyCallback); + std::cout << "Empty callback registered. Verifying the internal state of GetHlsDrmSessionCb." << std::endl; + + if (!obj.GetHlsDrmSessionCb) { + std::cout << "Callback is empty as expected. No callback logic is present." << std::endl; + } else { + std::cout << "Unexpected: Callback is not empty." << std::endl; + } + + EXPECT_FALSE(static_cast(obj.GetHlsDrmSessionCb)); + std::cout << "Exiting RegisterEmptyGetHlsDrmSessionCbTest test" << std::endl; +} +/** + * @brief Test valid creation of HLS DRM session with valid DRM info and stream type + * + * This test verifies that a valid DRM session is successfully created by invoking the createSession API + * with valid DRM information and a valid stream type. It ensures that the returned session pointer is not null. + * + * **Test Group ID:** Basic: 01@n + * **Test Case ID:** 003@n + * **Priority:** High@n + * + * **Pre-Conditions:** None@n + * **Dependencies:** None@n + * **User Interaction:** None@n + * + * **Test Procedure:** + * | Variation / Step | Description | Test Data | Expected Result | Notes | + * | :--------------: | ----------------------------------------------------------------------------------------------------- | ---------------------------------------------------------- | ---------------------------------------------------------------- | -------------- | + * | 01 | Initialize stream type, DRM info, and create an instance of PlayerHlsDrmSessionInterfaceBase | drmInfo = valid DRM info, streamType = 0 | Instance created successfully | Should be successful | + * | 02 | Invoke createSession API using valid DRM info and stream type | input: drmInfo = valid DRM info, input: streamType = 0 | Returned session pointer is non-null as per EXPECT_NE check | Should Pass | + * | 03 | Log the returned session pointer to verify the output | output: session pointer obtained from createSession call | Console outputs a valid session pointer address | Should be successful | + */ +TEST(PlayerHlsDrmSessionInterfaceBase, createSessionValid) +{ + std::cout << "Entering createSessionValid test" << std::endl; + int streamType = 0; + // Create instance object and call createSession. + PlayerHlsDrmSessionInterfaceBase playerHlsDrmSessionInterface; + std::shared_ptr session = playerHlsDrmSessionInterface.createSession(drmInfo, streamType); + + // Log the returned session pointer. + std::cout << "Returned session pointer: " << session.get() << std::endl; + + // Expected Output: + EXPECT_NE(session, nullptr); + + std::cout << "Exiting createSessionValid test" << std::endl; +} +/** + * @brief Verify that createSession returns a null session pointer when an invalid negative stream type is provided. + * + * This test case validates that the createSession method of PlayerHlsDrmSessionInterfaceBase properly handles an invalid input by returning a null session pointer. This negative test ensures the robustness of the API in handling erroneous input data. + * + * **Test Group ID:** Basic: 01@n + * **Test Case ID:** 004@n + * **Priority:** High@n + * + * **Pre-Conditions:** None@n + * **Dependencies:** None@n + * **User Interaction:** None@n + * + * **Test Procedure:** + * | Variation / Step | Description | Test Data | Expected Result | Notes | + * | :---------------:| -------------------------------------------------------------------- | ------------------------------------------------------- | -------------------------------------------------------------------------------------| ---------------- | + * | 01 | Initialize test parameters, creating a default DrmInfo object and setting streamType as -1. | drmInfo = default, streamType = -1 | Test parameters are correctly initialized. | Should be successful | + * | 02 | Invoke createSession API with a negative stream type and verify that the session pointer returned is null. | drmInfo = default, streamType = -1, expected session pointer = nullptr | API returns a null session pointer and the assertion EXPECT_EQ(session, nullptr) passes. | Should Fail | + */ +TEST(PlayerHlsDrmSessionInterfaceBase, NegativeStreamType) +{ + std::cout << "Entering NegativeStreamType test" << std::endl; + + // Create a default DrmInfo object + DrmInfo drmInfo; + int streamType = -1; + + // Create instance object and call createSession. + PlayerHlsDrmSessionInterfaceBase playerHlsDrmSessionInterface; + std::shared_ptr session = playerHlsDrmSessionInterface.createSession(drmInfo, streamType); + + // Log the returned session pointer. + std::cout << "Returned session pointer: " << session.get() << std::endl; + + // Expected Output: null session pointer due to invalid stream type. + EXPECT_EQ(session, nullptr) << "Expected null session for negative stream type"; + + std::cout << "Exiting NegativeStreamType test" << std::endl; +} +/** + * @brief Verify default DRM information handling + * + * This test checks the behavior of the isDrmSupported API when provided with a default constructed DrmInfo object and a PlayerHlsDrmSessionInterfaceBase instance created using its default constructor. The test ensures that the API call returns the expected true value under normal conditions. + * + * **Test Group ID:** Basic: 01@n + * **Test Case ID:** 005@n + * **Priority:** High@n + * + * **Pre-Conditions:** None@n + * **Dependencies:** None@n + * **User Interaction:** None@n + * + * **Test Procedure:** + * | Variation / Step | Description | Test Data | Expected Result | Notes | + * | :--------------: | ------------------------------------------------------------------- | -------------------------------------------------------------------------- | --------------------------------------------------------------------------- | ------------- | + * | 01 | Initialize a default DrmInfo object and a default PlayerHlsDrmSessionInterfaceBase object | drmInfo = default, drmSessionObject = default | Objects are created successfully | Should be successful | + * | 02 | Invoke isDrmSupported using the default DrmInfo and validate the output | drmInfo = default, output: isSupported = true | isDrmSupported returns true and the assertion passes | Should Pass | + */ +TEST(PlayerHlsDrmSessionInterfaceBase, DefaultDrmInfo) { + std::cout << "Entering DefaultDrmInfo test" << std::endl; + + // Create a default DrmInfo object + DrmInfo drmInfo; + + // Create an object of PlayerHlsDrmSessionInterfaceBase using the default constructor. + PlayerHlsDrmSessionInterfaceBase drmSessionObject; + + // Log the invocation of isDrmSupported and the values passed. + std::cout << "Invoking isDrmSupported with default DrmInfo" << std::endl; + bool isSupported = drmSessionObject.isDrmSupported(drmInfo); + std::cout << "isDrmSupported returned: " << isSupported << std::endl; + + // Validate the expected output (which is false) + EXPECT_TRUE(isSupported); + + std::cout << "Exiting DefaultDrmInfo test" << std::endl; +} + +int main(int argc, char **argv) { + ::testing::InitGoogleTest(&argc, argv); + return RUN_ALL_TESTS(); +} From d447a2af5a14ac2a30d3d88cbbbb885e0f947668 Mon Sep 17 00:00:00 2001 From: joyal Date: Fri, 18 Jul 2025 09:02:05 -0700 Subject: [PATCH 7/9] gh rdkcentral#2: Generate_L1_tests --- drm/test/test_l1_DrmMemorySystem.cpp | 178 + drm/test/test_l1_DrmSessionManager.cpp | 6645 +++++++++++++++++ .../test_l1_PlayerHlsDrmSessionInterface.cpp | 374 + 3 files changed, 7197 insertions(+) create mode 100755 drm/test/test_l1_DrmMemorySystem.cpp create mode 100755 drm/test/test_l1_DrmSessionManager.cpp create mode 100755 drm/test/test_l1_PlayerHlsDrmSessionInterface.cpp diff --git a/drm/test/test_l1_DrmMemorySystem.cpp b/drm/test/test_l1_DrmMemorySystem.cpp new file mode 100755 index 0000000..9e27f61 --- /dev/null +++ b/drm/test/test_l1_DrmMemorySystem.cpp @@ -0,0 +1,178 @@ +/* + * If not stated otherwise in this file or this component's LICENSE file the + * following copyright and licenses apply: + * + * Copyright 2025 RDK Management + * + * 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. + */ + +/** +* @file test_l1_DrmMemorySystem.cpp +* @page DrmMemorySystem Level 1 Tests +* +* ## Module's Role +* This module includes Level 1 functional tests (success and failure scenarios). +* This is to ensure that the DrmMemorySystem methods meet the requirements. +* +* **Pre-Conditions:** None @n +* **Dependencies:** None @n +* +*/ +#include +#include +#include +#include "DrmMemorySystem.h" + + +// Test case: Initialize with a positive handle value +/** + * @brief Verify that DrmMemoryHandleCloser initializes correctly with a positive handle value. + * + * This test validates that providing a positive handle value to the DrmMemoryHandleCloser constructor creates an object without errors. + * + * **Test Group ID:** Basic: 01@n + * **Test Case ID:** 001@n + * **Priority:** High@n + * + * **Pre-Conditions:** None@n + * **Dependencies:** None@n + * **User Interaction:** None@n + * + * **Test Procedure:** + * | Variation / Step | Description | Test Data | Expected Result | Notes | + * | :--------------: | ---------------------------------------------------------------------- | ----------------- | ----------------------------------------------------------------------- | ----------- | + * | 01 | Call DrmMemoryHandleCloser constructor with a positive handle value | input = 42 | Object is successfully created with its handle property set to 42 | Should Pass | + */ +TEST(DrmMemoryHandleCloser, InitializeWithPositiveHandleValue) +{ + std::cout << "Entering InitializeWithPositiveHandleValue test" << std::endl; + int input = 42; + std::cout << "Invoking DrmMemoryHandleCloser::DrmMemoryHandleCloser with handle value: " << input << std::endl; + DrmMemoryHandleCloser obj(input); + std::cout << "Exiting InitializeWithPositiveHandleValue test" << std::endl; +} +/** + * @brief Test initializing DrmMemoryHandleCloser with a zero handle value + * + * This test verifies that the DrmMemoryHandleCloser object can be properly initialized when provided with a zero handle value. Zero handle values are critical to test as they represent cases where no valid handle is assigned, potentially leading to boundary or error handling scenarios. + * + * **Test Group ID:** Basic: 01@n + * **Test Case ID:** 002@n + * **Priority:** High@n + * + * **Pre-Conditions:** None@n + * **Dependencies:** None@n + * **User Interaction:** None@n + * + * **Test Procedure:**@n + * | Variation / Step | Description | Test Data | Expected Result | Notes | + * | :----: | ---------------------------------------------------------- | -------------------- | ------------------------------------------------------------ | ----------------- | + * | 01 | Log entry message for the test | None | Entry message printed | Should be successful | + * | 02 | Initialize input variable with value 0 | input = 0 | Input variable is set to 0 | Should be successful | + * | 03 | Log invocation message with handle value | input = 0 | Invocation message with handle value printed | Should be successful | + * | 04 | Invoke DrmMemoryHandleCloser constructor with a 0 handle value | input = 0 | DrmMemoryHandleCloser object is created without error | Should Pass | + * | 05 | Log exit message for the test | None | Exit message printed | Should be successful | + */ +TEST(DrmMemoryHandleCloser, InitializeWithZeroHandleValue) +{ + std::cout << "Entering InitializeWithZeroHandleValue test" << std::endl; + int input = 0; + std::cout << "Invoking DrmMemoryHandleCloser::DrmMemoryHandleCloser with handle value: " << input << std::endl; + DrmMemoryHandleCloser obj(input); + std::cout << "Exiting InitializeWithZeroHandleValue test" << std::endl; +} +/** + * @brief Tests initialization of DrmMemoryHandleCloser with a negative handle value + * + * This test verifies that the DrmMemoryHandleCloser API handles a negative handle value appropriately. + * It is designed to assess the behavior when an invalid negative handle is provided and to ensure that the API responds as expected. + * + * **Test Group ID:** Basic: 01@n + * **Test Case ID:** 003@n + * **Priority:** High@n + * + * **Pre-Conditions:** None@n + * **Dependencies:** None@n + * **User Interaction:** None@n + * + * **Test Procedure:**@n + * | Variation / Step | Description | Test Data | Expected Result | Notes | + * | :--------------: | -------------------------------------------------------------------- | ------------ | ------------------------------------------------------------------------------------------------------- | ----------- | + * | 01 | Invoke DrmMemoryHandleCloser constructor with negative handle value | input = -1 | The object is constructed with the negative handle value. The behavior should indicate proper error handling if implemented. | Should Fail | + */ +TEST(DrmMemoryHandleCloser, InitializeWithNegativeHandleValue) +{ + std::cout << "Entering InitializeWithNegativeHandleValue test" << std::endl; + int input = -1; + std::cout << "Invoking DrmMemoryHandleCloser::DrmMemoryHandleCloser with negative handle value: " << input << std::endl; + DrmMemoryHandleCloser obj(input); + std::cout << "Exiting InitializeWithNegativeHandleValue test" << std::endl; +} +/** + * @brief Test the initialization of DrmMemoryHandleCloser with the maximum 32-bit integer value. + * + * This test verifies that the DrmMemoryHandleCloser class can be correctly instantiated using the maximum integer value (INT_MAX) as the handle. The test ensures that the object creation process properly accepts and uses this value without error. + * + * **Test Group ID:** Basic: 01@n + * **Test Case ID:** 004@n + * **Priority:** High@n + * + * **Pre-Conditions:** None@n + * **Dependencies:** None@n + * **User Interaction:** None@n + * + * **Test Procedure:** + * | Variation / Step | Description | Test Data | Expected Result | Notes | + * | :--------------: |----------------------------------------------------------------------------- | ---------------------------------- | ----------------------------------------------------------------------------------------------------- | ---------- | + * | 01 | Invoke the DrmMemoryHandleCloser constructor with maximum 32-bit integer value as handle. | input = 2147483647 | DrmMemoryHandleCloser object is instantiated successfully with internal handle set to 2147483647. | Should Pass| + */ +TEST(DrmMemoryHandleCloser, InitializeWithMaxIntHandleValue) +{ + std::cout << "Entering InitializeWithMaxIntHandleValue test" << std::endl; + int input = 2147483647; // INT_MAX for a 32-bit integer + std::cout << "Invoking DrmMemoryHandleCloser::DrmMemoryHandleCloser with handle: " << input << std::endl; + DrmMemoryHandleCloser obj(input); + std::cout << "Exiting InitializeWithMaxIntHandleValue test" << std::endl; +} +/** + * @brief Test to verify that DrmMemoryHandleCloser initializes correctly with the minimum integer handle value. + * + * This test validates the behavior of the DrmMemoryHandleCloser constructor when supplied with the minimum 32-bit integer value (INT_MIN). The purpose is to ensure the object is correctly instantiated without any errors when provided with this edge case value. + * + * **Test Group ID:** Basic: 01 + * **Test Case ID:** 005 + * **Priority:** High + * + * **Pre-Conditions:** None + * **Dependencies:** None + * **User Interaction:** None + * + * **Test Procedure:** + * | Variation / Step | Description | Test Data | Expected Result | Notes | + * | :--------------: | ---------------------------------------------------------------------------- | ---------------------------------- | ----------------------------------------------------- | ----------- | + * | 01 | Initialize DrmMemoryHandleCloser with INT_MIN value using its constructor. | input = -2147483648 | Object should be created without error and assertions pass. | Should Pass | + */ +TEST(DrmMemoryHandleCloser, InitializeWithMinIntHandleValue) +{ + std::cout << "Entering InitializeWithMinIntHandleValue test" << std::endl; + int input = -2147483648; // INT_MIN for a 32-bit integer + std::cout << "Invoking DrmMemoryHandleCloser::DrmMemoryHandleCloser with handle: " << input << std::endl; + DrmMemoryHandleCloser obj(input); + std::cout << "Exiting InitializeWithMinIntHandleValue test" << std::endl; +} + +int main(int argc, char **argv) { + ::testing::InitGoogleTest(&argc, argv); + return RUN_ALL_TESTS(); +} diff --git a/drm/test/test_l1_DrmSessionManager.cpp b/drm/test/test_l1_DrmSessionManager.cpp new file mode 100755 index 0000000..697427c --- /dev/null +++ b/drm/test/test_l1_DrmSessionManager.cpp @@ -0,0 +1,6645 @@ + +/* + * If not stated otherwise in this file or this component's LICENSE file the + * following copyright and licenses apply: + * + * Copyright 2025 RDK Management + * + * 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. + */ + +/** +* @file test_l1_DrmSessionManager.cpp +* @page DrmSessionManager Level 1 Tests +* +* ## Module's Role +* This module includes Level 1 functional tests (success and failure scenarios). +* This is to ensure that the DrmSessionManager methods meet the requirements. +* +* **Pre-Conditions:** None @n +* **Dependencies:** None @n +* +*/ + +#include +#include +#include +#include "DrmSessionManager.h" + + +/** + * @brief Verify the default construction of DrmSessionContext object + * + * This test verifies that upon default construction of a DrmSessionContext object, its member variables are correctly initialized. Specifically, the test checks that drmSession is set to nullptr, the data vector is empty, and sessionMutex is properly constructed. + * + * **Test Group ID:** Basic: 01@n + * **Test Case ID:** 001@n + * **Priority:** High@n + * + * **Pre-Conditions:** None@n + * **Dependencies:** None@n + * **User Interaction:** None@n + * + * **Test Procedure:** + * | Variation / Step | Description | Test Data | Expected Result | Notes | + * | :--------------: | ---------------------------------------------------------------------------------------- | -------------------------------------------------------------------- | -------------------------------------------------------------------------------- | ------------- | + * | 01 | Invoke the default constructor of DrmSessionContext | input: none, output: instance created | DrmSessionContext object is created with default member values | Should Pass | + * | 02 | Check if drmSession is initialized to nullptr | input: context.drmSession = ?, output: value of drmSession | drmSession should be nullptr | Should Pass | + * | 03 | Validate that the data vector is empty | input: context.data.size(), output: size value | data vector size should be 0 | Should Pass | + */ +TEST(DrmSessionContext, VerifyDefaultConstruction) { + std::cout << "Entering VerifyDefaultConstruction test" << std::endl; + + // Invocation of the constructor + std::cout << "Invoking DrmSessionContext() constructor" << std::endl; + DrmSessionContext context; + + // Validate that drmSession is initialized to NULL + std::cout << "Checking drmSession value" << std::endl; + EXPECT_EQ(context.drmSession, nullptr); + std::cout << "drmSession value: " << context.drmSession << std::endl; + + // Validate that data vector is empty. + std::cout << "Checking data vector size" << std::endl; + EXPECT_EQ(context.data.size(), 0u); + std::cout << "data vector size: " << context.data.size() << std::endl; + + std::cout << "Exiting VerifyDefaultConstruction test" << std::endl; +} +/** + * @brief Validate the copy constructor of DrmSessionContext with a non-empty data vector + * + * This test verifies that the copy constructor correctly creates a new DrmSessionContext instance + * from an existing one with a populated data vector and a valid drmSession pointer. It ensures that + * both the data values and the drmSession pointer are accurately copied to the new instance. + * + * **Test Group ID:** Basic: 01 + * **Test Case ID:** 002 + * **Priority:** High + * + * **Pre-Conditions:** None + * **Dependencies:** None + * **User Interaction:** None + * + * **Test Procedure:** + * | Variation / Step | Description | Test Data |Expected Result |Notes | + * | :----: | --------- | ---------- |-------------- | ----- | + * | 01 | Create an original DrmSessionContext object and populate its data vector with {10,20,30} and assign a dummy drmSession pointer (0x1234) | original.data = {10,20,30}, original.drmSession = 0x1234 | Original object contains 3 elements with values 10, 20, 30 and drmSession pointer set to 0x1234 | Should be successful | + * | 02 | Invoke the copy constructor to create a new DrmSessionContext object from the original object | Input: original object; Output: copyConstructed object | copyConstructed object is created and initialized with the same data and drmSession pointer as original | Should Pass | + * | 03 | Validate the copied object's data and drmSession pointer using assertions | EXPECT_EQ(copyConstructed.data.size(), 3), EXPECT_EQ(copyConstructed.data[0], 10), EXPECT_EQ(copyConstructed.data[1], 20), EXPECT_EQ(copyConstructed.data[2], 30), EXPECT_EQ(copyConstructed.drmSession, 0x1234) | All assertions pass confirming the copy was successful | Should Pass | + */ +TEST(DrmSessionContext, CopyConstructorValidNonEmpty) +{ + std::cout << "Entering CopyConstructorValidNonEmpty test" << std::endl; + + DrmSessionContext original; + // Populate original data vector with {10, 20, 30} + original.data.push_back(10); + original.data.push_back(20); + original.data.push_back(30); + // Simulate a valid drmSession pointer using a dummy pointer value + DrmSession* dummyDrmSession = reinterpret_cast(0x1234); + original.drmSession = dummyDrmSession; + + std::cout << "Original object's data: "; + for (auto val : original.data) + { + std::cout << int(val) << " "; + } + std::cout << std::endl; + std::cout << "Original drmSession pointer: " << original.drmSession << std::endl; + + // Invoke the copy constructor + DrmSessionContext copyConstructed(original); + + std::cout << "Copied object's data: "; + for (auto val : copyConstructed.data) + { + std::cout << int(val) << " "; + } + std::cout << std::endl; + std::cout << "Copied drmSession pointer: " << copyConstructed.drmSession << std::endl; + + // Validate that the copied data matches the original + EXPECT_EQ(copyConstructed.data.size(), 3); + EXPECT_EQ(copyConstructed.data[0], 10); + EXPECT_EQ(copyConstructed.data[1], 20); + EXPECT_EQ(copyConstructed.data[2], 30); + EXPECT_EQ(copyConstructed.drmSession, dummyDrmSession); + + std::cout << "Exiting CopyConstructorValidNonEmpty test" << std::endl; +} +/** + * @brief Test the copy constructor with a default constructed DrmSessionContext object. + * + * This test verifies that invoking the copy constructor on a DrmSessionContext object, + * which is initialized with an empty data vector and a nullptr drmSession pointer by default, + * correctly creates a new object that maintains the same state. This ensures that a deep copy + * is made for the data vector and that the drmSession pointer remains unchanged. + * + * **Test Group ID:** Basic: 01 + * **Test Case ID:** 003 + * **Priority:** High + * + * **Pre-Conditions:** None + * **Dependencies:** None + * **User Interaction:** None + * + * **Test Procedure:** + * | Variation / Step | Description | Test Data | Expected Result | Notes | + * | :----: | --------------------------------------------------------------------------------------------------- | ---------------------------------------------- | -------------------------------------------------------------------------------- | ---------- | + * | 01 | Invoke copy constructor on a default constructed object and verify that the copied instance has an empty data vector and nullptr drmSession pointer | original.data = empty, original.drmSession = nullptr | copyConstructed.data should be empty and copyConstructed.drmSession should be nullptr; assertions should pass | Should Pass | + */ +TEST(DrmSessionContext, CopyConstructorValidEmptyNull) +{ + std::cout << "Entering CopyConstructorValidEmptyNull test" << std::endl; + + DrmSessionContext original; + // original.data is empty and original.drmSession is nullptr by default + std::cout << "Original object's data size: " << original.data.size() << std::endl; + std::cout << "Original drmSession pointer: " << original.drmSession << std::endl; + + // Invoke the copy constructor + DrmSessionContext copyConstructed(original); + + std::cout << "Copied object's data size: " << copyConstructed.data.size() << std::endl; + std::cout << "Copied drmSession pointer: " << copyConstructed.drmSession << std::endl; + + EXPECT_TRUE(copyConstructed.data.empty()); + EXPECT_EQ(copyConstructed.drmSession, nullptr); + + std::cout << "Exiting CopyConstructorValidEmptyNull test" << std::endl; +} +/** + * @brief Verify deep copy semantics of the data vector within DrmSessionContext. + * + * This test verifies that invoking the copy constructor of DrmSessionContext produces a deep copy of its data vector. + * The original object's data vector is modified after the copy, and the test ensures that changes in the original do not + * reflect in the copied object. This validation is crucial to guarantee that separate objects maintain independent state. + * + * **Test Group ID:** Basic: 01@n + * **Test Case ID:** 004@n + * **Priority:** High@n + * + * **Pre-Conditions:** None@n + * **Dependencies:** None@n + * **User Interaction:** None@n + * + * **Test Procedure:** + * | Variation / Step | Description | Test Data |Expected Result |Notes | + * | :----: | --------- | ---------- |-------------- | ----- | + * | 01 | Instantiate DrmSessionContext and populate its data vector with {5, 15, 25}. | original.data = 5,15,25 | Original object's data vector is initialized with values {5,15,25}. | Should be successful | + * | 02 | Invoke the copy constructor to create a deep copy of the original object. | original = {data: {5,15,25}}, copyConstructed = copy(original) | Copied object's data vector is identical to the original at the time of copying. | Should Pass | + * | 03 | Modify the original object's data vector to {100, 200, 25} to test deep copy behavior. | original.data modified to 100,200,25 | Original object's data vector changes while the copied object's data remains unchanged. | Should Pass | + * | 04 | Validate that the copied object's data vector remains {5, 15, 25} after modifying the original. | ASSERT copyConstructed.data == {5,15,25} | ASSERT_EQ and EXPECT_EQ checks pass: size is 3 and values are 5, 15, 25 respectively. | Should Pass | + */ +TEST(DrmSessionContext, DeepCopyDataVector) +{ + std::cout << "Entering DeepCopyDataVector test" << std::endl; + + DrmSessionContext original; + // Populate original data vector with {5, 15, 25} + original.data.push_back(5); + original.data.push_back(15); + original.data.push_back(25); + + std::cout << "Original object's data before copy: "; + for (auto val : original.data) + { + std::cout << int(val) << " "; + } + std::cout << std::endl; + + // Invoke the copy constructor + DrmSessionContext copyConstructed(original); + + std::cout << "Copied object's data immediately after copy: "; + for (auto val : copyConstructed.data) + { + std::cout << int(val) << " "; + } + std::cout << std::endl; + + // Modify the original data vector + if (original.data.size() >= 3) + { + original.data[0] = 100; + original.data[1] = 200; + } + std::cout << "Original object's data after modification: "; + for (auto val : original.data) + { + std::cout << int(val) << " "; + } + std::cout << std::endl; + + std::cout << "Copied object's data should remain unchanged: "; + for (auto val : copyConstructed.data) + { + std::cout << int(val) << " "; + } + std::cout << std::endl; + + // Verify that the deep copy of the data vector is maintained + ASSERT_EQ(copyConstructed.data.size(), 3); + EXPECT_EQ(copyConstructed.data[0], 5); + EXPECT_EQ(copyConstructed.data[1], 15); + EXPECT_EQ(copyConstructed.data[2], 25); + + std::cout << "Exiting DeepCopyDataVector test" << std::endl; +} +/** + * @brief Verify that the destructor of DrmSessionContext executes without exceptions. + * + * This test verifies that when a DrmSessionContext object is created using its default constructor and subsequently goes out of scope, its destructor is invoked without throwing any exceptions. This helps ensure that object cleanup is handled safely and as expected. + * + * **Test Group ID:** Basic: 01@n + * **Test Case ID:** 005@n + * **Priority:** High@n + * + * **Pre-Conditions:** None@n + * **Dependencies:** None@n + * **User Interaction:** None@n + * + * **Test Procedure:** + * | Variation / Step | Description | Test Data | Expected Result | Notes | + * | :----: | --------- | ---------- |-------------- | ----- | + * | 01 | Print the start message to console indicating test initiation. | None | "Entering DrmSessionContext::~DrmSessionContext()_start test" appears in the console output. | Should be successful | + * | 02 | Create a DrmSessionContext object using the default constructor. | No inputs; output: DrmSessionContext object instance created. | Object is successfully created and a corresponding log message is printed. | Should Pass | + * | 03 | Exit the scope to trigger the destructor invocation of the DrmSessionContext object. | Object goes out of scope. | The destructor is called and executes without throwing any exceptions. | Should Pass | + */ +TEST(DrmSessionContext, DestructorExecutesWithoutExceptions) { + std::cout << "Entering DestructorExecutesWithoutExceptions test" << std::endl; + { + std::cout << "Creating DrmSessionContext object using default constructor." << std::endl; + DrmSessionContext obj; + std::cout << "DrmSessionContext object created." << std::endl; + } + std::cout << "Exiting DestructorExecutesWithoutExceptions test" << std::endl; +} +/** + * @brief Verify that KeyID object is correctly default constructed. + * + * This test validates that when a KeyID object is constructed using the default constructor, its internal members are initialized to their expected default values. It checks that the data vector is empty, creationTime is set to 0, isFailedKeyId is false, and isPrimaryKeyId is false. This is important to ensure the object's state adheres to the design contract immediately after instantiation. + * + * **Test Group ID:** Basic: 01@n + * **Test Case ID:** 006@n + * **Priority:** High@n + * + * **Pre-Conditions:** None@n + * **Dependencies:** None@n + * **User Interaction:** None@n + * + * **Test Procedure:** + * | Variation / Step | Description | Test Data | Expected Result | Notes | + * | :----: | --------- | ---------- |-------------- | ----- | + * | 01 | Call the KeyID default constructor and verify that the member variables (data vector, creationTime, isFailedKeyId, isPrimaryKeyId) are initialized to their default values. | data.size() = 0, creationTime = 0, isFailedKeyId = false, isPrimaryKeyId = false | All assertions pass confirming that the default values are correctly set. | Should Pass | + */ +TEST(KeyID, DefaultConstructionTest) { + std::cout << "Entering Default Construction Test test" << std::endl; + + std::cout << "Invoking KeyID default constructor." << std::endl; + KeyID keyObj; + + // Debug log: Checking internal state of keyObj after construction. + std::cout << "After construction:" << std::endl; + std::cout << "data vector size: " << keyObj.data.size() << std::endl; + std::cout << "creationTime: " << keyObj.creationTime << std::endl; + std::cout << "isFailedKeyId: " << std::boolalpha << keyObj.isFailedKeyId << std::endl; + std::cout << "isPrimaryKeyId: " << std::boolalpha << keyObj.isPrimaryKeyId << std::endl; + + // Assertions based on expected default values. + EXPECT_EQ(keyObj.data.size(), 0) << "Expected data vector to be empty."; + EXPECT_EQ(keyObj.creationTime, 0) << "Expected creationTime to be 0."; + EXPECT_FALSE(keyObj.isFailedKeyId) << "Expected isFailedKeyId to be false."; + EXPECT_FALSE(keyObj.isPrimaryKeyId) << "Expected isPrimaryKeyId to be false."; + + std::cout << "Exiting Default Construction Test test" << std::endl; +} +/** + * @brief Validate successful construction of DrmSessionManager with valid parameters. + * + * Tests that when a valid number of maximum DRM sessions and a valid non-null player pointer are provided, the DrmSessionManager object is constructed successfully. + * + * **Test Group ID:** Basic: 01@n + * **Test Case ID:** 007@n + * **Priority:** High@n + * + * **Pre-Conditions:** None@n + * **Dependencies:** None@n + * **User Interaction:** None@n + * + * **Test Procedure:**@n + * | Variation / Step | Description | Test Data | Expected Result | Notes | + * | :----: | --------- | ---------- |-------------- | ----- | + * | 01 | Prepare input parameters for DrmSessionManager constructor | maxDrmSessions = 5, player = valid non-null pointer | Input parameters are initialized correctly | Should be successful | + * | 02 | Log input values before invoking the constructor | maxDrmSessions = 5, player = valid non-null pointer | Correct log output is produced | Should be successful | + * | 03 | Call DrmSessionManager constructor with valid input parameters | maxDrmSessions = 5, player = valid non-null pointer | Object is constructed successfully with no errors | Should Pass | + * | 04 | Log successful construction after object creation | maxDrmSessions = 5 | Successful construction log is produced | Should be successful | + */ +TEST(DrmSessionManager, ConstructValidPositive) { + std::cout << "Entering ConstructValidPositive test" << std::endl; + + // Prepare input parameters + int maxDrmSessions = 5; + int dummyPlayer; // dummy variable to represent a valid player pointer + void* player = static_cast(&dummyPlayer); + + // Log input values + std::cout << "Invoking DrmSessionManager constructor with maxDrmSessions = " + << maxDrmSessions << " and player pointer = " << player << std::endl; + + // Construct the object + DrmSessionManager drmSessionManager(maxDrmSessions, player); + + // Log successful construction (internal state logging simulated) + std::cout << "DrmSessionManager object constructed successfully with maxDrmSessions = " + << maxDrmSessions << std::endl; + + std::cout << "Exiting ConstructValidPositive test" << std::endl; +} +/** + * @brief Verify creation of DrmSessionManager with a boundary session value. + * + * This test validates that the DrmSessionManager can be constructed using the boundary value of one maximum DRM session and a valid non-null player pointer. + * + * **Test Group ID:** Basic: 01@n + * **Test Case ID:** 008@n + * **Priority:** High@n + * + * **Pre-Conditions:** None@n + * **Dependencies:** None@n + * **User Interaction:** None@n + * + * **Test Procedure:**@n + * | Variation / Step | Description | Test Data | Expected Result | Notes | + * | :----: | --------- | ---------- |-------------- | ----- | + * | 01 | Prepare input parameters with boundary maxDrmSessions=1 and valid non-null player pointer | maxDrmSessions = 1, dummyPlayer = uninitialized, player = address of dummyPlayer | Input parameters are correctly prepared | Should be successful | + * | 02 | Log the input parameters before invoking the constructor | maxDrmSessions = 1, player = address of dummyPlayer | Log messages are correctly displayed showing input values | Should be successful | + * | 03 | Construct the DrmSessionManager with boundary value | maxDrmSessions = 1, player = address of dummyPlayer, output = instance of DrmSessionManager | DrmSessionManager object is successfully constructed | Should Pass | + * | 04 | Log the successful construction of the object | output message reflecting successful construction | Log messages confirm that construction is successful | Should be successful | + */ +TEST(DrmSessionManager, ConstructBoundaryValue) { + std::cout << "Entering ConstructBoundaryValue test" << std::endl; + + // Prepare input parameters + int maxDrmSessions = 1; + int dummyPlayer; + void* player = static_cast(&dummyPlayer); + + // Log input values + std::cout << "Invoking DrmSessionManager constructor with boundary maxDrmSessions = " + << maxDrmSessions << " and player pointer = " << player << std::endl; + + // Construct the object + DrmSessionManager drmSessionManager(maxDrmSessions, player); + + // Log successful construction (internal state logging simulated) + std::cout << "DrmSessionManager object constructed successfully with one session available" << std::endl; + + std::cout << "Exiting ConstructBoundaryValue test" << std::endl; +} +/** + * @brief Test constructing DrmSessionManager with zero permitted DRM sessions to ensure safe configuration is established. + * + * This test verifies that the DrmSessionManager correctly handles a scenario where no DRM sessions are allowed (maxDrmSessions is zero) ensuring that the object is constructed with a safe no-session configuration. The test logs the procedure for manual verification of state initialization. + * + * **Test Group ID:** Basic: 01@n + * **Test Case ID:** 009@n + * **Priority:** High@n + * + * **Pre-Conditions:** None@n + * **Dependencies:** None@n + * **User Interaction:** None@n + * + * **Test Procedure:**@n + * | Variation / Step | Description | Test Data | Expected Result | Notes | + * | :--------------: | ------------------------------------------------------------------------------------- | ---------------------------------------------------------------- | ------------------------------------------------------------------------------------------------- | -------------- | + * | 01 | Prepare input parameters and log the entry of the test | maxDrmSessions = 0, dummyPlayer = uninitialized, player = valid pointer of dummyPlayer | Input parameters are correctly prepared and logged | Should be successful | + * | 02 | Invoke the DrmSessionManager constructor with maxDrmSessions = 0 and a valid player pointer | maxDrmSessions = 0, player pointer = address of dummyPlayer | DrmSessionManager object is constructed with a safe no-session configuration; API call succeeds | Should Pass | + * | 03 | Log the internal state details after construction | Logs message indicating internal state is set to a safe configuration | Internal state details are accurately logged | Should be successful | + */ +TEST(DrmSessionManager, ConstructZeroSessions) { + std::cout << "Entering ConstructZeroSessions test" << std::endl; + + // Prepare input parameters + int maxDrmSessions = 0; + int dummyPlayer; + void* player = static_cast(&dummyPlayer); + + // Log input values + std::cout << "Invoking DrmSessionManager constructor with maxDrmSessions = " + << maxDrmSessions << " (zero sessions) and player pointer = " << player << std::endl; + + // Construct the object + DrmSessionManager drmSessionManager(maxDrmSessions, player); + + // Log simulated internal state details after construction + std::cout << "DrmSessionManager object constructed with zero sessions. " + << "Internal state is set to a safe no-session configuration." << std::endl; + + std::cout << "Exiting ConstructZeroSessions test" << std::endl; +} +/** + * @brief Verify that the DrmSessionManager constructor safely handles negative maxDrmSessions input + * + * This test verifies that when a negative value is provided for maxDrmSessions along with a non-null player pointer, + * the DrmSessionManager constructor correctly simulates an error handling configuration without causing a crash. + * + * **Test Group ID:** Basic: 01@n + * **Test Case ID:** 010@n + * **Priority:** High@n + * + * **Pre-Conditions:** None@n + * **Dependencies:** None@n + * **User Interaction:** None@n + * + * **Test Procedure:** + * | Variation / Step | Description | Test Data | Expected Result | Notes | + * | :----: | --------- | ---------- |-------------- | ----- | + * | 01 | Invoke DrmSessionManager constructor with a negative maxDrmSessions value and valid player pointer | maxDrmSessions = -1, player = valid non-null pointer | Object constructed with safe error handling; internal state reflects error management configuration | Should Fail | + */ +TEST(DrmSessionManager, ConstructNegativeSessions) { + std::cout << "Entering ConstructNegativeSessions test" << std::endl; + + // Prepare input parameters + int maxDrmSessions = -1; + int dummyPlayer; + void* player = static_cast(&dummyPlayer); + + // Log input values + std::cout << "Invoking DrmSessionManager constructor with negative maxDrmSessions = " + << maxDrmSessions << " and player pointer = " << player << std::endl; + + // Construct the object + DrmSessionManager drmSessionManager(maxDrmSessions, player); + + // Log simulated error handling in constructor + std::cout << "DrmSessionManager object constructed with negative sessions. " << std::endl; + + std::cout << "Exiting ConstructNegativeSessions test" << std::endl; +} +/** + * @brief Test the construction of DrmSessionManager with a very high session limit. + * + * This test verifies that the DrmSessionManager can be safely constructed when provided with the maximum possible value for DRM sessions (INT_MAX) and a valid player pointer. It logs input values and confirms that the internal state is capable of handling potential resource limitations. + * + * **Test Group ID:** Basic: 01 + * **Test Case ID:** 011 + * **Priority:** High + * + * **Pre-Conditions:** None + * **Dependencies:** None + * **User Interaction:** None + * + * **Test Procedure:** + * | Variation / Step | Description | Test Data | Expected Result | Notes | + * | :----: | --------- | ---------- |-------------- | ----- | + * | 01 | Prepare input parameters including maxDrmSessions = INT_MAX and valid player pointer | maxDrmSessions = INT_MAX, player = address of dummyPlayer | Valid input parameters are prepared | Should be successful | + * | 02 | Invoke the DrmSessionManager constructor with the prepared parameters and log the invocation details | maxDrmSessions = INT_MAX, player = address of dummyPlayer | DrmSessionManager object is constructed successfully | Should Pass | + * | 03 | Validate and log that internal state handles high session values safely | N/A | Proper logging output indicating safe resource handling and successful construction | Should be successful | + */ +TEST(DrmSessionManager, ConstructHighSessionValue) { + std::cout << "Entering ConstructHighSessionValue test" << std::endl; + + // Prepare input parameters + int maxDrmSessions = INT_MAX; + int dummyPlayer; + void* player = static_cast(&dummyPlayer); + + // Log input values + std::cout << "Invoking DrmSessionManager constructor with very high maxDrmSessions = " + << maxDrmSessions << " and player pointer = " << player << std::endl; + + // Construct the object + DrmSessionManager drmSessionManager(maxDrmSessions, player); + + // Log simulated safe resource handling + std::cout << "DrmSessionManager object constructed with high session value." << std::endl; + + std::cout << "Exiting ConstructHighSessionValue test" << std::endl; +} +/** + * @brief Test the construction of DrmSessionManager with a null player pointer + * + * This test validates that when a null player pointer is passed to the DrmSessionManager constructor, + * the object is constructed successfully and its internal state appropriately manages the null pointer. + * + * **Test Group ID:** Basic: 01@n + * **Test Case ID:** 012@n + * **Priority:** High@n + * + * **Pre-Conditions:** None@n + * **Dependencies:** None@n + * **User Interaction:** None@n + * + * **Test Procedure:**@n + * | Variation / Step | Description | Test Data | Expected Result | Notes | + * | :--------------: | ---------------------------------------------------------------- | ------------------------------------------ | ------------------------------------------------------------------------------------------------- | ------------- | + * | 01 | Prepare input parameters by setting maxDrmSessions and null player | maxDrmSessions = 5, player = nullptr | Variables initialized with maxDrmSessions set to 5 and player pointer as nullptr | Should be successful | + * | 02 | Invoke the DrmSessionManager constructor with the input parameters | input: maxDrmSessions = 5, player = nullptr; output: constructed DrmSessionManager object | Instance is successfully constructed and internally manages the null player pointer appropriately | Should Pass | + * | 03 | Log output to simulate null pointer handling status | (Logs the input parameters and internal state message) | Correct log messages are output indicating proper handling of a null pointer | Should be successful | + */ +TEST(DrmSessionManager, ConstructNullPlayer) { + std::cout << "Entering ConstructNullPlayer test" << std::endl; + + // Prepare input parameters + int maxDrmSessions = 5; + void* player = nullptr; // null player pointer + + // Log input values + std::cout << "Invoking DrmSessionManager constructor with maxDrmSessions = " + << maxDrmSessions << " and player pointer = " << player << " (nullptr)" << std::endl; + + // Construct the object + DrmSessionManager drmSessionManager(maxDrmSessions, player); + + // Log simulated null pointer handling + std::cout << "DrmSessionManager object constructed with null player pointer. " + << "Internal state manages the null pointer appropriately." << std::endl; + + std::cout << "Exiting ConstructNullPlayer test" << std::endl; +} +/** + * @brief Verify that the IsKeyIdProcessed method correctly identifies a cached key ID. + * + * This test creates a DrmSessionManager instance, prepares a keyIdArray, and invokes the IsKeyIdProcessed method. + * It verifies that when the key ID is already cached, the method returns true and updates the status to true. + * + * **Test Group ID:** Basic: 01@n + * **Test Case ID:** 013@n + * **Priority:** High@n + * + * **Pre-Conditions:** None@n + * **Dependencies:** None@n + * **User Interaction:** None@n + * + * **Test Procedure:**@n + * | Variation / Step | Description | Test Data | Expected Result | Notes | + * | :--------------: | ------------------------------------------------------------------------ | ---------------------------------------------- | --------------------------------------------------------- | -------------- | + * | 01 | Create a DrmSessionManager instance with a maximum of 5 sessions and a null player. | maxDrmSessions = 5, player = nullptr | DrmSessionManager instance is created successfully. | Should be successful | + * | 02 | Prepare the input keyIdArray with values {1, 2, 3, 4}. | keyIdArray = {1, 2, 3, 4} | keyIdArray is initialized correctly. | Should be successful | + * | 03 | Initialize the status variable to false. | status = false | Status remains false prior to the API call. | Should be successful | + * | 04 | Invoke the IsKeyIdProcessed method using keyIdArray and the status variable. | keyIdArray = {1, 2, 3, 4}, status = false | Method returns true and updates status to true. | Should Pass | + * | 05 | Validate the expected results using assertion checks. | Expected returnValue = true, expected status = true | EXPECT_TRUE assertions pass; both return and status are true. | Should Pass | + */ +TEST(DrmSessionManager, ProcessedKeyIdAlreadyCached) { + std::cout << "Entering ProcessedKeyIdAlreadyCached test" << std::endl; + + // Create a DrmSessionManager instance using the custom constructor. + // For testing, passing maxDrmSessions = 5 and player = nullptr. + DrmSessionManager drmSessionManager(5, nullptr); + std::cout << "Created DrmSessionManager instance with maxDrmSessions = 5 and player = nullptr" << std::endl; + + // Prepare input keyIdArray {1, 2, 3, 4}. + std::vector keyIdArray = {1, 2, 3, 4}; + std::cout << "Input keyIdArray: { "; + for (size_t i = 0; i < keyIdArray.size(); ++i) { + std::cout << static_cast(keyIdArray[i]) << " "; + } + std::cout << "}" << std::endl; + + // Initialize status to false. + bool status = false; + std::cout << "Initial status value: " << std::boolalpha << status << std::endl; + + // Invoke the IsKeyIdProcessed method. + std::cout << "Invoking IsKeyIdProcessed with keyIdArray and status variable" << std::endl; + bool returnValue = drmSessionManager.IsKeyIdProcessed(keyIdArray, status); + + // Log the returned value and status. + std::cout << "Method IsKeyIdProcessed returned: " << std::boolalpha << returnValue + << ", updated status: " << status << std::endl; + + // Validate the expected behavior. + EXPECT_TRUE(returnValue); + EXPECT_TRUE(status); + + std::cout << "Exiting ProcessedKeyIdAlreadyCached test" << std::endl; +} +/** + * @brief Verify that IsKeyIdProcessed returns false and updates status accordingly when provided with an empty keyIdArray. + * + * This test checks that when the DrmSessionManager API IsKeyIdProcessed is invoked with an empty keyIdArray, the API correctly returns false and sets the status to false. This behavior is necessary to ensure that the system does not attempt processing when no key IDs are provided. + * + * **Test Group ID:** Basic: 01@n + * **Test Case ID:** 014@n + * **Priority:** High@n + * + * **Pre-Conditions:** None@n + * **Dependencies:** None@n + * **User Interaction:** None@n + * + * **Test Procedure:**@n + * | Variation / Step | Description | Test Data | Expected Result | Notes | + * | :--------------: | ------------------------------------------------------------------------------------- | --------------------------------------------------------- | --------------------------------------------------- | ------------- | + * | 01 | Create a DrmSessionManager instance using the custom constructor with valid inputs. | maxDrmSessions = 5, player = nullptr | Instance of DrmSessionManager is created successfully | Should be successful | + * | 02 | Prepare an empty keyIdArray. | keyIdArray = empty vector | An empty keyIdArray is prepared successfully | Should be successful | + * | 03 | Initialize the status variable to true before invoking the API. | status = true | status is set to true initially | Should be successful | + * | 04 | Invoke the IsKeyIdProcessed method with the empty keyIdArray and status variable. | keyIdArray = empty, status = true | API returns false and status becomes false | Should Pass | + * | 05 | Validate the output by asserting that return value and status are false. | returnValue = false, status = false | Assertions pass confirming the expected behavior | Should Pass | + */ +TEST(DrmSessionManager, EmptyKeyIdArray) { + std::cout << "Entering EmptyKeyIdArray test" << std::endl; + + // Create a DrmSessionManager instance using the custom constructor. + DrmSessionManager drmSessionManager(5, nullptr); + std::cout << "Created DrmSessionManager instance with maxDrmSessions = 5 and player = nullptr" << std::endl; + + // Prepare input keyIdArray as empty. + std::vector keyIdArray; + std::cout << "Input keyIdArray is empty" << std::endl; + + // Initialize status to true (or any value, expecting it to be set). + bool status = true; + std::cout << "Initial status value: " << std::boolalpha << status << std::endl; + + // Invoke the IsKeyIdProcessed method. + std::cout << "Invoking IsKeyIdProcessed with empty keyIdArray and status variable" << std::endl; + bool returnValue = drmSessionManager.IsKeyIdProcessed(keyIdArray, status); + + // Log the returned value and status. + std::cout << "Method IsKeyIdProcessed returned: " << std::boolalpha << returnValue + << ", updated status: " << status << std::endl; + + // Validate the expected behavior. + EXPECT_FALSE(returnValue); + EXPECT_FALSE(status); + + std::cout << "Exiting EmptyKeyIdArray test" << std::endl; +} +/** + * @brief Verify that IsKeyIdProcessed correctly processes a single element key id. + * + * This test verifies that when a DrmSessionManager instance is created with a specified maximum + * number of DRM sessions and a nullptr player, invoking the IsKeyIdProcessed method with a keyIdArray + * containing a single element correctly returns true and updates the status to true. This ensures that + * the method properly processes a single element key id. + * + * **Test Group ID:** Basic: 01@n + * **Test Case ID:** 015@n + * **Priority:** High@n + * + * **Pre-Conditions:** None@n + * **Dependencies:** None@n + * **User Interaction:** None@n + * + * **Test Procedure:**@n + * | Variation / Step | Description | Test Data | Expected Result | Notes | + * | :--------------: | --------------------------------------------------------------------- | ----------------------------------------------------- | ---------------------------------------------------------------- | ------------- | + * | 01 | Create a DrmSessionManager instance using the constructor | maxDrmSessions = 5, player = nullptr | Instance is created successfully | Should be successful | + * | 02 | Prepare the keyIdArray with a single element | input keyIdArray = {0} | keyIdArray is initialized with one element | Should be successful | + * | 03 | Initialize status variable to false | status = false | status is initialized to false | Should be successful | + * | 04 | Invoke IsKeyIdProcessed method with keyIdArray and status | keyIdArray = {0}, status = false | Return value is true and status is updated to true | Should Pass | + * | 05 | Validate API output using assertion checks | returnValue = true, status = true | EXPECT_TRUE assertions for both return value and status pass | Should be successful | + */ +TEST(DrmSessionManager, SingleElementKeyIdProcessed) { + std::cout << "Entering SingleElementKeyIdProcessed test" << std::endl; + + // Create a DrmSessionManager instance using the custom constructor. + DrmSessionManager drmSessionManager(5, nullptr); + std::cout << "Created DrmSessionManager instance with maxDrmSessions = 5 and player = nullptr" << std::endl; + + // Prepare input keyIdArray with a single element {0}. + std::vector keyIdArray = {0}; + std::cout << "Input keyIdArray: { " << static_cast(keyIdArray[0]) << " }" << std::endl; + + // Initialize status to false. + bool status = false; + std::cout << "Initial status value: " << std::boolalpha << status << std::endl; + + // Invoke the IsKeyIdProcessed method. + std::cout << "Invoking IsKeyIdProcessed with keyIdArray and status variable" << std::endl; + bool returnValue = drmSessionManager.IsKeyIdProcessed(keyIdArray, status); + + // Log the returned value and status. + std::cout << "Method IsKeyIdProcessed returned: " << std::boolalpha << returnValue + << ", updated status: " << status << std::endl; + + // Validate the expected behavior. + EXPECT_TRUE(returnValue); + EXPECT_TRUE(status); + + std::cout << "Exiting SingleElementKeyIdProcessed test" << std::endl; +} +/** + * @brief Validate that QueueContentProtection returns true when provided with valid input parameters and isVssPeriod set to true. + * + * This test iterates through a list of GstMediaType values while providing a valid DrmHelper pointer, a valid periodId, and a valid adapIdx. The objective is to ensure that the QueueContentProtection function of DrmSessionManager correctly processes each media type without error and consistently returns true as expected. + * + * **Test Group ID:** Basic: 01 + * **Test Case ID:** 016 + * **Priority:** High + * + * **Pre-Conditions:** None + * **Dependencies:** None + * **User Interaction:** None + * + * **Test Procedure:** + * | Variation / Step | Description | Test Data | Expected Result | Notes | + * | :----: | --------- | ---------- |-------------- | ----- | + * | 01 | Create a valid DrmHelper pointer and a DrmSessionManager instance using custom constructor | drmHelper = valid pointer, capacity = 10, dependency = nullptr | Objects are successfully created | Should be successful | + * | 02 | Initialize periodId, adapIdx, and populate mediaTypes vector with valid GstMediaType values and isVssPeriod set to true | periodId = "period_enum", adapIdx = 2, mediaTypes = (eGST_MEDIATYPE_VIDEO, eGST_MEDIATYPE_AUDIO, eGST_MEDIATYPE_SUBTITLE, eGST_MEDIATYPE_AUX_AUDIO, eGST_MEDIATYPE_MANIFEST, eGST_MEDIATYPE_LICENCE, eGST_MEDIATYPE_IFRAME, eGST_MEDIATYPE_INIT_VIDEO, eGST_MEDIATYPE_INIT_AUDIO, eGST_MEDIATYPE_INIT_SUBTITLE, eGST_MEDIATYPE_INIT_AUX_AUDIO, eGST_MEDIATYPE_PLAYLIST_VIDEO, eGST_MEDIATYPE_PLAYLIST_AUDIO, eGST_MEDIATYPE_PLAYLIST_SUBTITLE, eGST_MEDIATYPE_PLAYLIST_AUX_AUDIO, eGST_MEDIATYPE_PLAYLIST_IFRAME, eGST_MEDIATYPE_INIT_IFRAME, eGST_MEDIATYPE_DSM_CC, eGST_MEDIATYPE_IMAGE, eGST_MEDIATYPE_DEFAULT) | Variables are initialized correctly | Should be successful | + * | 03 | Iterate through each media type and call QueueContentProtection to verify it returns true | drmHelper = valid pointer, periodId = "period_enum", adapIdx = 2, each GstMediaType from mediaTypes, isVssPeriod = true | Return value is true and EXPECT_TRUE(ret) assertion passes | Should Pass | + */ +TEST(DrmSessionManager, QueueContentProtection_ValidCP_VssTrue) +{ + std::cout << "Entering QueueContentProtection_ValidCP_VssTrue test" << std::endl; + + // Create a valid DrmHelper pointer + auto drmHelper = std::make_shared(); + // Create a DrmSessionManager object using a custom constructor + DrmSessionManager drmSessionManager(10, nullptr); + std::string periodId = "period_enum"; + uint32_t adapIdx = 2; + + // Prepare list of media types for testing, with isVssPeriod = true + std::vector mediaTypes = { + eGST_MEDIATYPE_VIDEO, + eGST_MEDIATYPE_AUDIO, + eGST_MEDIATYPE_SUBTITLE, + eGST_MEDIATYPE_AUX_AUDIO, + eGST_MEDIATYPE_MANIFEST, + eGST_MEDIATYPE_LICENCE, + eGST_MEDIATYPE_IFRAME, + eGST_MEDIATYPE_INIT_VIDEO, + eGST_MEDIATYPE_INIT_AUDIO, + eGST_MEDIATYPE_INIT_SUBTITLE, + eGST_MEDIATYPE_INIT_AUX_AUDIO, + eGST_MEDIATYPE_PLAYLIST_VIDEO, + eGST_MEDIATYPE_PLAYLIST_AUDIO, + eGST_MEDIATYPE_PLAYLIST_SUBTITLE, + eGST_MEDIATYPE_PLAYLIST_AUX_AUDIO, + eGST_MEDIATYPE_PLAYLIST_IFRAME, + eGST_MEDIATYPE_INIT_IFRAME, + eGST_MEDIATYPE_DSM_CC, + eGST_MEDIATYPE_IMAGE, + eGST_MEDIATYPE_DEFAULT + }; + + for(auto type : mediaTypes) + { + std::cout << "Invoking QueueContentProtection with parameters:" << std::endl; + std::cout << " drmHelper: valid pointer" << std::endl; + std::cout << " periodId: " << periodId << std::endl; + std::cout << " adapIdx: " << adapIdx << std::endl; + std::cout << " GstMediaType: " << type << std::endl; + std::cout << " isVssPeriod: true" << std::endl; + + bool ret = drmSessionManager.QueueContentProtection(drmHelper, periodId, adapIdx, type, true); + std::cout << "Method QueueContentProtection returned: " << ret << std::endl; + EXPECT_TRUE(ret); + } + + std::cout << "Exiting QueueContentProtection_ValidCP_VssTrue test" << std::endl; +} +/** + * @brief Verify QueueContentProtection API returns true for valid content protection when isVssPeriod is false + * + * This test verifies that the QueueContentProtection API is successfully invoked with valid parameters. The test creates a valid DrmHelper pointer, initializes a DrmSessionManager object, sets up specific input parameters (periodId, adapIdx) and iterates over a list of valid GstMediaType values with isVssPeriod set to false. For each media type, the API is called and the returned boolean value is asserted to be true. + * + * **Test Group ID:** Basic: 01 + * **Test Case ID:** 017 + * **Priority:** High + * + * **Pre-Conditions:** None + * **Dependencies:** None + * **User Interaction:** None + * + * **Test Procedure:** + * | Variation / Step | Description | Test Data | Expected Result | Notes | + * | :--------------: | ------------------------------------------------------------------------------------------------- | -------------------------------------------------------------------------------------------------------- | -------------------------------------------------------------------- | ---------------- | + * | 01 | Instantiate a valid DrmHelper pointer and initialize DrmSessionManager with specified parameters | drmHelper = valid pointer, capacity = 10, pointer = nullptr | Objects created successfully | Should be successful | + * | 02 | Define the input parameters periodId and adapIdx | periodId = "period_enum", adapIdx = 2 | Variables set correctly | Should be successful | + * | 03 | Prepare a list of 20 valid GstMediaType values including various media types | GstMediaType values = eGST_MEDIATYPE_VIDEO, eGST_MEDIATYPE_AUDIO, eGST_MEDIATYPE_SUBTITLE, eGST_MEDIATYPE_AUX_AUDIO, eGST_MEDIATYPE_MANIFEST, eGST_MEDIATYPE_LICENCE, eGST_MEDIATYPE_IFRAME, eGST_MEDIATYPE_INIT_VIDEO, eGST_MEDIATYPE_INIT_AUDIO, eGST_MEDIATYPE_INIT_SUBTITLE, eGST_MEDIATYPE_INIT_AUX_AUDIO, eGST_MEDIATYPE_PLAYLIST_VIDEO, eGST_MEDIATYPE_PLAYLIST_AUDIO, eGST_MEDIATYPE_PLAYLIST_SUBTITLE, eGST_MEDIATYPE_PLAYLIST_AUX_AUDIO, eGST_MEDIATYPE_PLAYLIST_IFRAME, eGST_MEDIATYPE_INIT_IFRAME, eGST_MEDIATYPE_DSM_CC, eGST_MEDIATYPE_IMAGE, eGST_MEDIATYPE_DEFAULT | List initialized with 20 media types | Should be successful | + * | 04 | For each media type, log parameters and invoke QueueContentProtection with isVssPeriod as false | drmHelper, periodId, adapIdx, current GstMediaType, isVssPeriod = false | API returns true for each invocation | Should Pass | + * | 05 | Verify the return value of QueueContentProtection using EXPECT_TRUE assertion | ret = return value from QueueContentProtection | Boolean value true confirming correct API behavior | Should Pass | + */ +TEST(DrmSessionManager, QueueContentProtection_ValidCP_VssFalse) +{ + std::cout << "Entering QueueContentProtection_ValidCP_VssFalse test" << std::endl; + + // Create a valid DrmHelper pointer + auto drmHelper = std::make_shared(); + // Create a DrmSessionManager object using a custom constructor + DrmSessionManager drmSessionManager(10, nullptr); + std::string periodId = "period_enum"; + uint32_t adapIdx = 2; + + // Prepare list of media types for testing, with isVssPeriod = false + std::vector mediaTypes = { + eGST_MEDIATYPE_VIDEO, + eGST_MEDIATYPE_AUDIO, + eGST_MEDIATYPE_SUBTITLE, + eGST_MEDIATYPE_AUX_AUDIO, + eGST_MEDIATYPE_MANIFEST, + eGST_MEDIATYPE_LICENCE, + eGST_MEDIATYPE_IFRAME, + eGST_MEDIATYPE_INIT_VIDEO, + eGST_MEDIATYPE_INIT_AUDIO, + eGST_MEDIATYPE_INIT_SUBTITLE, + eGST_MEDIATYPE_INIT_AUX_AUDIO, + eGST_MEDIATYPE_PLAYLIST_VIDEO, + eGST_MEDIATYPE_PLAYLIST_AUDIO, + eGST_MEDIATYPE_PLAYLIST_SUBTITLE, + eGST_MEDIATYPE_PLAYLIST_AUX_AUDIO, + eGST_MEDIATYPE_PLAYLIST_IFRAME, + eGST_MEDIATYPE_INIT_IFRAME, + eGST_MEDIATYPE_DSM_CC, + eGST_MEDIATYPE_IMAGE, + eGST_MEDIATYPE_DEFAULT + }; + + for(auto type : mediaTypes) + { + std::cout << "Invoking QueueContentProtection with parameters:" << std::endl; + std::cout << " drmHelper: valid pointer" << std::endl; + std::cout << " periodId: " << periodId << std::endl; + std::cout << " adapIdx: " << adapIdx << std::endl; + std::cout << " GstMediaType: " << type << std::endl; + std::cout << " isVssPeriod: false" << std::endl; + + bool ret = drmSessionManager.QueueContentProtection(drmHelper, periodId, adapIdx, type, false); + std::cout << "Method QueueContentProtection returned: " << ret << std::endl; + EXPECT_TRUE(ret); + } + + std::cout << "Exiting QueueContentProtection_ValidCP_VssFalse test" << std::endl; +} +/** + * @brief Validate that QueueContentProtection returns false when provided with a null DrmHelper. + * + * This test verifies that the QueueContentProtection method of DrmSessionManager handles the case where the DrmHelper pointer is null correctly. + * + * **Test Group ID:** Basic: 01@n + * **Test Case ID:** 018@n + * **Priority:** High@n + * + * **Pre-Conditions:** None@n + * **Dependencies:** None@n + * **User Interaction:** None@n + * + * **Test Procedure:**@n + * | Variation / Step | Description | Test Data | Expected Result | Notes | + * | :--------------: | ----------------------------------------------------------------------------------------------------- | ---------------------------------------------------------------------------------------------------------- | ----------------------------------------------------------------------------------------- | ------------- | + * | 01 | Create an instance of DrmSessionManager with a capacity of 10 and a null DrmHelper. | capacity = 10, drmHelper = nullptr | Instance created successfully. | Should be successful | + * | 02 | Initialize test parameters for periodId, adapIdx, GstMediaType, and isVssPeriod flag. | periodId = period1, adapIdx = 0, GstMediaType = eGST_MEDIATYPE_VIDEO, isVssPeriod = false | Parameters set as expected. | Should be successful | + * | 03 | Invoke QueueContentProtection with a null DrmHelper and the initialized parameters. | drmHelper = nullptr, periodId = period1, adapIdx = 0, GstMediaType = eGST_MEDIATYPE_VIDEO, isVssPeriod = false | Function returns false; assertion (EXPECT_FALSE(ret)) passes confirming correct behavior. | Should Pass | + * | 04 | Log the method execution and exit information to trace execution. | N/A | Log messages printed as expected. | Should be successful | + */ +TEST(DrmSessionManager, QueueContentProtection_NullDrmHelper) +{ + std::cout << "Entering QueueContentProtection_NullDrmHelper test" << std::endl; + + // Create a DrmSessionManager object using a custom constructor + DrmSessionManager drmSessionManager(10, nullptr); + std::string periodId = "period1"; + uint32_t adapIdx = 0; + GstMediaType type = eGST_MEDIATYPE_VIDEO; + // drmHelper is nullptr + std::shared_ptr drmHelper = nullptr; + + std::cout << "Invoking QueueContentProtection with parameters:" << std::endl; + std::cout << " drmHelper: nullptr" << std::endl; + std::cout << " periodId: " << periodId << std::endl; + std::cout << " adapIdx: " << adapIdx << std::endl; + std::cout << " GstMediaType: " << type << std::endl; + std::cout << " isVssPeriod: false" << std::endl; + + bool ret = drmSessionManager.QueueContentProtection(drmHelper, periodId, adapIdx, type, false); + std::cout << "Method QueueContentProtection returned: " << ret << std::endl; + EXPECT_FALSE(ret); + + std::cout << "Exiting QueueContentProtection_NullDrmHelper test" << std::endl; +} +/** + * @brief Verify that QueueContentProtection returns false when provided with an empty periodId + * + * This test verifies that when an empty periodId is passed to the QueueContentProtection API of DrmSessionManager, + * the function returns false. It ensures that the API correctly handles invalid period identifiers. + * + * **Test Group ID:** Basic: 01@n + * **Test Case ID:** 019@n + * **Priority:** High@n + * + * **Pre-Conditions:** None@n + * **Dependencies:** None@n + * **User Interaction:** None@n + * + * **Test Procedure:**@n + * | Variation / Step | Description | Test Data | Expected Result | Notes | + * | :--------------: | ------------------------------------------------------------ | --------------------------------------------------------------------------------------------------------------- | ----------------------------------------------------------- | ---------------- | + * | 01 | Set up valid DrmHelper pointer and instantiate DrmSessionManager | drmHelper = valid pointer, drmSessionManager = (10, nullptr) | Objects are successfully created | Should be successful | + * | 02 | Prepare test parameters with empty periodId | periodId = (empty string), adapIdx = 0, GstMediaType = eGST_MEDIATYPE_VIDEO, isVssPeriod = false | Parameters are set as expected | Should be successful | + * | 03 | Invoke QueueContentProtection API with an empty periodId | drmHelper = valid pointer, periodId = (empty string), adapIdx = 0, GstMediaType = eGST_MEDIATYPE_VIDEO, isVssPeriod = false | API returns false and EXPECT_FALSE assertion passes | Should Fail | + */ +TEST(DrmSessionManager, QueueContentProtection_EmptyPeriodId) +{ + std::cout << "Entering QueueContentProtection_EmptyPeriodId test" << std::endl; + + // Create a valid DrmHelper pointer + auto drmHelper = std::make_shared(); + // Create a DrmSessionManager object using a custom constructor + DrmSessionManager drmSessionManager(10, nullptr); + // Using an empty periodId string + std::string periodId = ""; + uint32_t adapIdx = 0; + GstMediaType type = eGST_MEDIATYPE_VIDEO; + + std::cout << "Invoking QueueContentProtection with parameters:" << std::endl; + std::cout << " drmHelper: valid pointer" << std::endl; + std::cout << " periodId: (empty string)" << std::endl; + std::cout << " adapIdx: " << adapIdx << std::endl; + std::cout << " GstMediaType: " << type << std::endl; + std::cout << " isVssPeriod: false" << std::endl; + + bool ret = drmSessionManager.QueueContentProtection(drmHelper, periodId, adapIdx, type, false); + std::cout << "Method QueueContentProtection returned: " << ret << std::endl; + EXPECT_FALSE(ret); + + std::cout << "Exiting QueueContentProtection_EmptyPeriodId test" << std::endl; +} +/** + * @brief Test function to verify that QueueContentProtection returns false for an excessively large adaptation index. + * + * This test verifies that when QueueContentProtection is invoked with an excessively large adaptation index, + * the function returns false as expected, indicating that the input is out of the allowed range. + * It ensures robustness by checking the boundary conditions related to content protection queuing. + * + * **Test Group ID:** Basic: 01 + * **Test Case ID:** 020 + * **Priority:** High + * + * **Pre-Conditions:** None + * **Dependencies:** None + * **User Interaction:** None + * + * **Test Procedure:** + * | Variation / Step | Description | Test Data | Expected Result | Notes | + * | :----: | --------- | ---------- |-------------- | ----- | + * | 01 | Instantiate a valid DrmHelper pointer and create a DrmSessionManager with capacity 10 and nullptr dependency. | drmHelper = valid pointer, drmSessionManager: capacity = 10, dependency = nullptr, periodId = "period1", adapIdx = not set, mediaType = not set, isVssPeriod = not set | Objects are created successfully | Should be successful | + * | 02 | Invoke QueueContentProtection with periodId "period1", an excessively large adapIdx 999999, mediaType eGST_MEDIATYPE_VIDEO, and isVssPeriod set to false. | drmHelper = valid pointer, periodId = "period1", adapIdx = 999999, GstMediaType = eGST_MEDIATYPE_VIDEO, isVssPeriod = false | Function returns false and EXPECT_FALSE(ret) passes | Should Pass | + */ +TEST(DrmSessionManager, QueueContentProtection_ExcessiveAdapIdx) +{ + std::cout << "Entering QueueContentProtection_ExcessiveAdapIdx test" << std::endl; + + // Create a valid DrmHelper pointer + auto drmHelper = std::make_shared(); + // Create a DrmSessionManager object using a custom constructor + DrmSessionManager drmSessionManager(10, nullptr); + std::string periodId = "period1"; + // Excessively large adaptation index + uint32_t adapIdx = 999999; + GstMediaType type = eGST_MEDIATYPE_VIDEO; + + std::cout << "Invoking QueueContentProtection with parameters:" << std::endl; + std::cout << " drmHelper: valid pointer" << std::endl; + std::cout << " periodId: " << periodId << std::endl; + std::cout << " adapIdx: " << adapIdx << std::endl; + std::cout << " GstMediaType: " << type << std::endl; + std::cout << " isVssPeriod: false" << std::endl; + + bool ret = drmSessionManager.QueueContentProtection(drmHelper, periodId, adapIdx, type, false); + std::cout << "Method QueueContentProtection returned: " << ret << std::endl; + EXPECT_FALSE(ret); + + std::cout << "Exiting QueueContentProtection_ExcessiveAdapIdx test" << std::endl; +} +/** + * @brief Validate that QueueProtectionEvent accepts valid inputs for all media types + * + * This test validates that the QueueProtectionEvent function works as expected when provided with a valid DrmHelper pointer, a sample period ID, a valid adapIdx, and iterates through all defined GstMediaType values. The function is invoked in a loop for each media type to ensure that protection events are queued successfully for each variation. + * + * **Test Group ID:** Basic: 01@n + * **Test Case ID:** 021@n + * **Priority:** High@n + * + * **Pre-Conditions:** None@n + * **Dependencies:** None@n + * **User Interaction:** None@n + * + * **Test Procedure:** + * | Variation / Step | Description | Test Data | Expected Result | Notes | + * | :----: | --------- | ---------- | -------------- | ----- | + * | 01 | Invoke QueueProtectionEvent with eGST_MEDIATYPE_VIDEO | drmHelper = valid, periodId = period_all, adapIdx = 2, type = eGST_MEDIATYPE_VIDEO | Protection event queued successfully | Should Pass | + * | 02 | Invoke QueueProtectionEvent with eGST_MEDIATYPE_AUDIO | drmHelper = valid, periodId = period_all, adapIdx = 2, type = eGST_MEDIATYPE_AUDIO | Protection event queued successfully | Should Pass | + * | 03 | Invoke QueueProtectionEvent with eGST_MEDIATYPE_SUBTITLE | drmHelper = valid, periodId = period_all, adapIdx = 2, type = eGST_MEDIATYPE_SUBTITLE | Protection event queued successfully | Should Pass | + * | 04 | Invoke QueueProtectionEvent with eGST_MEDIATYPE_AUX_AUDIO | drmHelper = valid, periodId = period_all, adapIdx = 2, type = eGST_MEDIATYPE_AUX_AUDIO | Protection event queued successfully | Should Pass | + * | 05 | Invoke QueueProtectionEvent with eGST_MEDIATYPE_MANIFEST | drmHelper = valid, periodId = period_all, adapIdx = 2, type = eGST_MEDIATYPE_MANIFEST | Protection event queued successfully | Should Pass | + * | 06 | Invoke QueueProtectionEvent with eGST_MEDIATYPE_LICENCE | drmHelper = valid, periodId = period_all, adapIdx = 2, type = eGST_MEDIATYPE_LICENCE | Protection event queued successfully | Should Pass | + * | 07 | Invoke QueueProtectionEvent with eGST_MEDIATYPE_IFRAME | drmHelper = valid, periodId = period_all, adapIdx = 2, type = eGST_MEDIATYPE_IFRAME | Protection event queued successfully | Should Pass | + * | 08 | Invoke QueueProtectionEvent with eGST_MEDIATYPE_INIT_VIDEO | drmHelper = valid, periodId = period_all, adapIdx = 2, type = eGST_MEDIATYPE_INIT_VIDEO | Protection event queued successfully | Should Pass | + * | 09 | Invoke QueueProtectionEvent with eGST_MEDIATYPE_INIT_AUDIO | drmHelper = valid, periodId = period_all, adapIdx = 2, type = eGST_MEDIATYPE_INIT_AUDIO | Protection event queued successfully | Should Pass | + * | 10 | Invoke QueueProtectionEvent with eGST_MEDIATYPE_INIT_SUBTITLE | drmHelper = valid, periodId = period_all, adapIdx = 2, type = eGST_MEDIATYPE_INIT_SUBTITLE | Protection event queued successfully | Should Pass | + * | 11 | Invoke QueueProtectionEvent with eGST_MEDIATYPE_INIT_AUX_AUDIO | drmHelper = valid, periodId = period_all, adapIdx = 2, type = eGST_MEDIATYPE_INIT_AUX_AUDIO | Protection event queued successfully | Should Pass | + * | 12 | Invoke QueueProtectionEvent with eGST_MEDIATYPE_PLAYLIST_VIDEO | drmHelper = valid, periodId = period_all, adapIdx = 2, type = eGST_MEDIATYPE_PLAYLIST_VIDEO | Protection event queued successfully | Should Pass | + * | 13 | Invoke QueueProtectionEvent with eGST_MEDIATYPE_PLAYLIST_AUDIO | drmHelper = valid, periodId = period_all, adapIdx = 2, type = eGST_MEDIATYPE_PLAYLIST_AUDIO | Protection event queued successfully | Should Pass | + * | 14 | Invoke QueueProtectionEvent with eGST_MEDIATYPE_PLAYLIST_SUBTITLE | drmHelper = valid, periodId = period_all, adapIdx = 2, type = eGST_MEDIATYPE_PLAYLIST_SUBTITLE | Protection event queued successfully | Should Pass | + * | 15 | Invoke QueueProtectionEvent with eGST_MEDIATYPE_PLAYLIST_AUX_AUDIO | drmHelper = valid, periodId = period_all, adapIdx = 2, type = eGST_MEDIATYPE_PLAYLIST_AUX_AUDIO | Protection event queued successfully | Should Pass | + * | 16 | Invoke QueueProtectionEvent with eGST_MEDIATYPE_PLAYLIST_IFRAME | drmHelper = valid, periodId = period_all, adapIdx = 2, type = eGST_MEDIATYPE_PLAYLIST_IFRAME | Protection event queued successfully | Should Pass | + * | 17 | Invoke QueueProtectionEvent with eGST_MEDIATYPE_INIT_IFRAME | drmHelper = valid, periodId = period_all, adapIdx = 2, type = eGST_MEDIATYPE_INIT_IFRAME | Protection event queued successfully | Should Pass | + * | 18 | Invoke QueueProtectionEvent with eGST_MEDIATYPE_DSM_CC | drmHelper = valid, periodId = period_all, adapIdx = 2, type = eGST_MEDIATYPE_DSM_CC | Protection event queued successfully | Should Pass | + * | 19 | Invoke QueueProtectionEvent with eGST_MEDIATYPE_IMAGE | drmHelper = valid, periodId = period_all, adapIdx = 2, type = eGST_MEDIATYPE_IMAGE | Protection event queued successfully | Should Pass | + * | 20 | Invoke QueueProtectionEvent with eGST_MEDIATYPE_DEFAULT | drmHelper = valid, periodId = period_all, adapIdx = 2, type = eGST_MEDIATYPE_DEFAULT | Protection event queued successfully | Should Pass | + */ +TEST(DrmSessionManager, QueueProtectionEvent_validInputLoopAllMediaTypes) { + std::cout << "Entering QueueProtectionEvent_validInputLoopAllMediaTypes test" << std::endl; + + // Create a valid DrmHelper pointer. + auto drmHelper = std::make_shared(); + std::string periodId = "period_all"; + uint32_t adapIdx = 2; + + // Define an array of all GstMediaType values to test. + GstMediaType mediaTypes[] = { + eGST_MEDIATYPE_VIDEO, + eGST_MEDIATYPE_AUDIO, + eGST_MEDIATYPE_SUBTITLE, + eGST_MEDIATYPE_AUX_AUDIO, + eGST_MEDIATYPE_MANIFEST, + eGST_MEDIATYPE_LICENCE, + eGST_MEDIATYPE_IFRAME, + eGST_MEDIATYPE_INIT_VIDEO, + eGST_MEDIATYPE_INIT_AUDIO, + eGST_MEDIATYPE_INIT_SUBTITLE, + eGST_MEDIATYPE_INIT_AUX_AUDIO, + eGST_MEDIATYPE_PLAYLIST_VIDEO, + eGST_MEDIATYPE_PLAYLIST_AUDIO, + eGST_MEDIATYPE_PLAYLIST_SUBTITLE, + eGST_MEDIATYPE_PLAYLIST_AUX_AUDIO, + eGST_MEDIATYPE_PLAYLIST_IFRAME, + eGST_MEDIATYPE_INIT_IFRAME, + eGST_MEDIATYPE_DSM_CC, + eGST_MEDIATYPE_IMAGE, + eGST_MEDIATYPE_DEFAULT + }; + + // Instantiate DrmSessionManager using its constructor. + DrmSessionManager drmSessionManager(5, nullptr); + + // Loop through each media type and invoke QueueProtectionEvent. + for (auto type : mediaTypes) { + std::cout << "Invoking QueueProtectionEvent with parameters:" << std::endl; + std::cout << " drmHelper: valid" << std::endl; + std::cout << " periodId: " << periodId << std::endl; + std::cout << " adapIdx: " << adapIdx << std::endl; + std::cout << " type: " << static_cast(type) << std::endl; + drmSessionManager.QueueProtectionEvent(drmHelper, periodId, adapIdx, type); + std::cout << "Protection event queued for type: " << static_cast(type) << std::endl; + } + + std::cout << "Exiting QueueProtectionEvent_validInputLoopAllMediaTypes test" << std::endl; +} +/** + * @brief Test that QueueProtectionEvent handles a null DrmHelper input without throwing exceptions. + * + * This test verifies that when a null DrmHelper pointer is passed to the QueueProtectionEvent method along with valid parameters, the function gracefully handles the null input without throwing any exceptions. + * + * **Test Group ID:** Basic: 01@n + * **Test Case ID:** 022@n + * **Priority:** High@n + * + * **Pre-Conditions:** None@n + * **Dependencies:** None@n + * **User Interaction:** None@n + * + * **Test Procedure:** + * | Variation / Step | Description | Test Data | Expected Result | Notes | + * | :----: | --------- | ---------- |-------------- | ----- | + * | 01 | Instantiate a null DrmHelper pointer and set valid test parameters (periodId, adapIdx, type) | drmHelper = nullptr, periodId = "period1", adapIdx = 1, type = eGST_MEDIATYPE_VIDEO | DrmSessionManager is instantiated successfully and inputs are set as intended | Should be successful | + * | 02 | Invoke QueueProtectionEvent with the null DrmHelper and verify that no exception is thrown | Input: drmHelper = nullptr, periodId = "period1", adapIdx = 1, type = eGST_MEDIATYPE_VIDEO; Output: No exception thrown | The function call should not throw an exception | Should Pass | + */ +TEST(DrmSessionManager, QueueProtectionEvent_nullDrmHelper) { + std::cout << "Entering QueueProtectionEvent_nullDrmHelper test" << std::endl; + + // Create a null DrmHelper pointer. + std::shared_ptr drmHelper(nullptr); + std::string periodId = "period1"; + uint32_t adapIdx = 1; + GstMediaType type = eGST_MEDIATYPE_VIDEO; + + // Instantiate DrmSessionManager. + DrmSessionManager drmSessionManager(5, nullptr); + + std::cout << "Invoking QueueProtectionEvent with parameters:" << std::endl; + std::cout << " drmHelper: nullptr" << std::endl; + std::cout << " periodId: " << periodId << std::endl; + std::cout << " adapIdx: " << adapIdx << std::endl; + std::cout << " type: " << static_cast(type) << std::endl; + EXPECT_NO_THROW(drmSessionManager.QueueProtectionEvent(drmHelper, periodId, adapIdx, type)); + std::cout << "Handled null drmHelper input gracefully without crashing" << std::endl; + + std::cout << "Exiting QueueProtectionEvent_nullDrmHelper test" << std::endl; +} +/** + * @brief Test for QueueProtectionEvent with an empty periodId + * + * This test verifies that the DrmSessionManager handles an empty periodId gracefully without throwing exceptions. + * + * **Test Group ID:** Basic: 01@n + * **Test Case ID:** 023@n + * **Priority:** High@n + * + * **Pre-Conditions:** None@n + * **Dependencies:** None@n + * **User Interaction:** None@n + * + * **Test Procedure:**@n + * | Variation / Step | Description | Test Data | Expected Result | Notes | + * | :----: | ------------------------------------------------------- | ------------------------------------------------------------------------------------------ | ---------------------------------------------------------------- | ------------- | + * | 01 | Set up the test environment by creating a valid DrmHelper, initializing an empty periodId, and assigning test values for adapIdx and type. | drmHelper = valid, periodId = "", adapIdx = 1, type = eGST_MEDIATYPE_AUDIO | All test parameters are initialized correctly. | Should be successful | + * | 02 | Invoke the QueueProtectionEvent method with the initialized parameters. | drmHelper = valid, periodId = "", adapIdx = 1, type = eGST_MEDIATYPE_AUDIO | The method call does not throw any exceptions (EXPECT_NO_THROW passes). | Should Pass | + */ +TEST(DrmSessionManager, QueueProtectionEvent_emptyPeriodId) { + std::cout << "Entering QueueProtectionEvent_emptyPeriodId test" << std::endl; + + // Create a valid DrmHelper pointer. + auto drmHelper = std::make_shared(); + std::string periodId = ""; + uint32_t adapIdx = 1; + GstMediaType type = eGST_MEDIATYPE_AUDIO; + + // Instantiate DrmSessionManager. + DrmSessionManager drmSessionManager(5, nullptr); + + std::cout << "Invoking QueueProtectionEvent with parameters:" << std::endl; + std::cout << " drmHelper: valid" << std::endl; + std::cout << " periodId: (empty string)" << std::endl; + std::cout << " adapIdx: " << adapIdx << std::endl; + std::cout << " type: " << static_cast(type) << std::endl; + EXPECT_NO_THROW(drmSessionManager.QueueProtectionEvent(drmHelper, periodId, adapIdx, type)); + std::cout << "Processed empty periodId input appropriately without crashing" << std::endl; + + std::cout << "Exiting QueueProtectionEvent_emptyPeriodId test" << std::endl; +} +/** + * @brief Verify that QueueProtectionEvent handles an extreme adaptation index value without crashing + * + * This test case ensures that calling QueueProtectionEvent on a valid DrmSessionManager instance with an extremely high adapIdx value (UINT32_MAX) is handled correctly. It verifies that no exception is thrown when processing edge case values, ensuring the robustness of the API for potential stress scenarios. + * + * **Test Group ID:** Basic: 01@n + * **Test Case ID:** 024@n + * **Priority:** High@n + * + * **Pre-Conditions:** None@n + * **Dependencies:** None@n + * **User Interaction:** None@n + * + * **Test Procedure:** + * | Variation / Step | Description | Test Data: drmHelper = valid, periodId = period2, adapIdx = UINT32_MAX, type = eGST_MEDIATYPE_SUBTITLE | Expected Result: No exceptions thrown and proper handling of extreme adapIdx | Notes | + * | :--------------: | ------------------------------------------------------------------- | ------------------------------------------------------------------------------------------ | ---------------------------------------------------------------------------------------------- | ----------- | + * | 01 | Invoke QueueProtectionEvent API using an extreme adapIdx value | drmHelper = valid, periodId = period2, adapIdx = UINT32_MAX, type = eGST_MEDIATYPE_SUBTITLE | API call should complete without throwing exceptions, indicating robust handling of extreme input | Should Pass | + */ +TEST(DrmSessionManager, QueueProtectionEvent_extremeAdapIdx) { + std::cout << "Entering QueueProtectionEvent_extremeAdapIdx test" << std::endl; + + // Create a valid DrmHelper pointer. + auto drmHelper = std::make_shared(); + std::string periodId = "period2"; + uint32_t adapIdx = UINT32_MAX; + GstMediaType type = eGST_MEDIATYPE_SUBTITLE; + + // Instantiate DrmSessionManager. + DrmSessionManager drmSessionManager(5, nullptr); + + std::cout << "Invoking QueueProtectionEvent with parameters:" << std::endl; + std::cout << " drmHelper: valid" << std::endl; + std::cout << " periodId: " << periodId << std::endl; + std::cout << " adapIdx: " << adapIdx << " (extreme value)" << std::endl; + std::cout << " type: " << static_cast(type) << std::endl; + EXPECT_NO_THROW(drmSessionManager.QueueProtectionEvent(drmHelper, periodId, adapIdx, type)); + std::cout << "Processed extreme adapIdx input appropriately without crashing" << std::endl; + + std::cout << "Exiting QueueProtectionEvent_extremeAdapIdx test" << std::endl; +} +/** + * @brief Test the registration and execution of a valid non-empty lambda callback in DrmSessionManager. + * + * This test verifies that a non-empty lambda callback can be successfully registered to the DrmSessionManager. + * It checks that after registration the callback is correctly set and that its invocation returns the expected result "Success". + * + * **Test Group ID:** Basic: 01@n + * **Test Case ID:** 025@n + * **Priority:** High@n + * + * **Pre-Conditions:** None@n + * **Dependencies:** None@n + * **User Interaction:** None@n + * + * **Test Procedure:** + * | Variation / Step | Description | Test Data | Expected Result | Notes | + * | :--------------: | ------------------------------------------------------------------------------------------- | --------------------------------------------------------------- | ------------------------------------------------------------------------------------- | ------------- | + * | 01 | Create an instance of DrmSessionManager with maxDrmSessions=5 and player set to nullptr. | maxDrmSessions = 5, player = nullptr | DrmSessionManager instance created successfully. | Should be successful | + * | 02 | Register a valid non-empty lambda callback which returns "Success" when invoked. | lambda = validLambda | manager.ContentUpdateCb is set (true). | Should Pass | + * | 03 | Optionally invoke the registered callback with specified parameters. | drmHelper = nullptr, streamType = 1, keyId = {1, 2, 3}, contentProtectionUpd = 10 | Callback returns "Success", and EXPECT_EQ validates the return value "Success". | Should Pass | + */ +TEST(DrmSessionManager, RegisterValidNonEmptyLambdaCallback) +{ + std::cout << "Entering RegisterValidNonEmptyLambdaCallback test" << std::endl; + DrmSessionManager manager(5, nullptr); + std::cout << "Created DrmSessionManager with maxDrmSessions=5, player=nullptr" << std::endl; + + auto validLambda = [](DrmHelperPtr drmHelper, int streamType, std::vector keyId, int contentProtectionUpd) -> std::string { + std::cout << "Invoking valid lambda with: drmHelper=" << drmHelper + << ", streamType=" << streamType + << ", keyId size=" << keyId.size() + << ", contentProtectionUpd=" << contentProtectionUpd << std::endl; + return std::string("Success"); + }; + + std::cout << "Registering valid non-empty lambda callback" << std::endl; + manager.RegisterHandleContentProtectionCb(validLambda); + std::cout << "Callback registration complete. Checking if callback is set: " + << (manager.ContentUpdateCb ? "Yes" : "No") << std::endl; + EXPECT_TRUE(static_cast(manager.ContentUpdateCb)); + + std::cout << "Optionally invoking registered callback" << std::endl; + std::vector keyId = {1, 2, 3}; + std::string result = manager.ContentUpdateCb(nullptr, 1, keyId, 10); + std::cout << "Callback invocation returned: " << result << std::endl; + EXPECT_EQ(result, "Success"); + + std::cout << "Exiting RegisterValidNonEmptyLambdaCallback test" << std::endl; +} +/** + * @brief Test case to validate the registration of an empty callback in the DrmSessionManager API. + * + * This test verifies that when a default constructed (empty) ContentUpdateCallback is registered with the DrmSessionManager, + * the internal callback handler remains empty (invalid). The objective is to ensure that the API correctly handles empty callbacks + * without erroneously marking them as valid, which is critical for maintaining correct behavior in scenarios where a callback is optional. + * + * **Test Group ID:** Basic: 01@n + * **Test Case ID:** 026@n + * **Priority:** High@n + * + * **Pre-Conditions:** None@n + * **Dependencies:** None@n + * **User Interaction:** None@n + * + * **Test Procedure:**@n + * | Variation / Step | Description | Test Data | Expected Result | Notes | + * | :----: | --------- | ---------- |-------------- | ----- | + * | 01| Create a DrmSessionManager instance with maxDrmSessions=5 and player=nullptr | maxDrmSessions = 5, player = nullptr | DrmSessionManager instance created successfully | Should be successful | + * | 02| Create a default constructed (empty) ContentUpdateCallback | default constructed callback | Valid default callback that represents an empty callback | Should be successful | + * | 03| Register the empty callback using RegisterHandleContentProtectionCb | emptyCallback | Callback registration is completed without errors | Should Pass | + * | 04| Check that the registered callback is empty by evaluating manager.ContentUpdateCb | manager.ContentUpdateCb evaluated | EXPECT_FALSE evaluates true confirming callback is empty | Should Pass | + */ +TEST(DrmSessionManager, RegisterEmptyCallback) +{ + std::cout << "Entering RegisterEmptyCallback test" << std::endl; + DrmSessionManager manager(5, nullptr); + std::cout << "Created DrmSessionManager with maxDrmSessions=5, player=nullptr" << std::endl; + + ContentUpdateCallback emptyCallback; // Default constructed callback + std::cout << "Registering empty default callback" << std::endl; + manager.RegisterHandleContentProtectionCb(emptyCallback); + std::cout << "Callback registration complete. Checking if callback is empty: " + << (manager.ContentUpdateCb ? "Yes" : "No") << std::endl; + EXPECT_FALSE(static_cast(manager.ContentUpdateCb)); + + std::cout << "Exiting RegisterEmptyCallback test" << std::endl; +} +/** + * @brief To verify that a lambda callback returning an empty string can be registered and invoked correctly. + * + * This test registers a lambda callback that returns an empty string and then invokes it to ensure that it is correctly registered and its invocation returns an empty string as expected.@n + * + * **Test Group ID:** Basic: 01@n + * **Test Case ID:** 027@n + * **Priority:** High@n + * + * **Pre-Conditions:** None@n + * **Dependencies:** None@n + * **User Interaction:** None@n + * + * **Test Procedure:**@n + * | Variation / Step | Description | Test Data | Expected Result | Notes | + * | :----: | --------- | ---------- |-------------- | ----- | + * | 01 | Enter test function and create an instance of DrmSessionManager | DrmSessionManager: maxDrmSessions=5, player=nullptr | DrmSessionManager instance created successfully | Should be successful | + * | 02 | Create and register a lambda callback that returns an empty string | emptyStringLambda: returns "" | Lambda callback registered in DrmSessionManager | Should Pass | + * | 03 | Verify that callback is set | manager.ContentUpdateCb evaluated | Callback is non-null/truthy | Should Pass | + * | 04 | Invoke the registered callback | Parameters: drmHelper=nullptr, streamType=2, keyId={4, 5, 6}, contentProtectionUpd=20 | Empty string returned from callback | Should Pass | + */ +TEST(DrmSessionManager, RegisterLambdaReturningEmptyString) +{ + std::cout << "Entering RegisterLambdaReturningEmptyString test" << std::endl; + DrmSessionManager manager(5, nullptr); + std::cout << "Created DrmSessionManager with maxDrmSessions=5, player=nullptr" << std::endl; + + auto emptyStringLambda = [](DrmHelperPtr drmHelper, int streamType, std::vector keyId, int contentProtectionUpd) -> std::string { + std::cout << "Invoking lambda returning empty string with: drmHelper=" << drmHelper + << ", streamType=" << streamType + << ", keyId size=" << keyId.size() + << ", contentProtectionUpd=" << contentProtectionUpd << std::endl; + return std::string(""); + }; + + std::cout << "Registering lambda callback that returns an empty string" << std::endl; + manager.RegisterHandleContentProtectionCb(emptyStringLambda); + std::cout << "Callback registration complete. Checking if callback is set: " + << (manager.ContentUpdateCb ? "Yes" : "No") << std::endl; + EXPECT_TRUE(static_cast(manager.ContentUpdateCb)); + + std::cout << "Invoking registered callback" << std::endl; + std::vector keyId = {4, 5, 6}; + std::string result = manager.ContentUpdateCb(nullptr, 2, keyId, 20); + std::cout << "Callback invocation returned: '" << result << "'" << std::endl; + EXPECT_EQ(result, ""); + + std::cout << "Exiting RegisterLambdaReturningEmptyString test" << std::endl; +} +/** + * @brief Verify that the registered lambda throws an exception as expected + * + * This test verifies that when a lambda function, which is designed to throw a runtime exception, + * is registered as the content protection callback in the DrmSessionManager, invoking the callback + * will indeed result in a runtime exception. The test ensures that the callback registration is successful + * and that exception handling in the test is properly executed. + * + * **Test Group ID:** Basic: 01@n + * **Test Case ID:** 028@n + * **Priority:** High@n + * + * **Pre-Conditions:** None@n + * **Dependencies:** None@n + * **User Interaction:** None@n + * + * **Test Procedure:**@n + * | Variation / Step | Description | Test Data | Expected Result | Notes | + * | :--------------: | ---------------------------------------------------------------------------------------------- | -------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------ | ------------- | + * | 01 | Create DrmSessionManager instance with maxDrmSessions=5 and player=nullptr | maxDrmSessions = 5, player = nullptr | Instance is created successfully without errors | Should be successful | + * | 02 | Create a lambda function that throws a runtime exception when called | lambda function creation (no direct input parameters) | Lambda is created successfully | Should be successful | + * | 03 | Register the lambda function as the content protection callback in the manager | lambda callback = throwingLambda | Callback registration is complete and manager.ContentUpdateCb is set to a valid function pointer | Should Pass | + * | 04 | Validate that the content update callback is registered properly | Query manager.ContentUpdateCb | EXPECT_TRUE confirms that the callback pointer is valid | Should Pass | + * | 05 | Invoke the registered callback with parameters and verify that a runtime exception is thrown | drmHelper = nullptr, streamType = 3, keyId = {7,8,9}, contentProtectionUpd = 30 | runtime_error exception is thrown with the expected message ("Test Exception") and caught correctly | Should Pass | + */ +TEST(DrmSessionManager, RegisterLambdaThrowingException) +{ + std::cout << "Entering RegisterLambdaThrowingException test" << std::endl; + DrmSessionManager manager(5, nullptr); + std::cout << "Created DrmSessionManager with maxDrmSessions=5, player=nullptr" << std::endl; + + auto throwingLambda = [](DrmHelperPtr drmHelper, int streamType, std::vector keyId, int contentProtectionUpd) -> std::string { + std::cout << "Invoking lambda that throws exception with: drmHelper=" << drmHelper + << ", streamType=" << streamType + << ", keyId size=" << keyId.size() + << ", contentProtectionUpd=" << contentProtectionUpd << std::endl; + throw std::runtime_error("Test Exception"); + return std::string(""); + }; + + std::cout << "Registering lambda callback that throws an exception upon invocation" << std::endl; + manager.RegisterHandleContentProtectionCb(throwingLambda); + std::cout << "Callback registration complete. Checking if callback is set: " + << (manager.ContentUpdateCb ? "Yes" : "No") << std::endl; + EXPECT_TRUE(static_cast(manager.ContentUpdateCb)); + + std::cout << "Invoking registered callback and catching exception" << std::endl; + std::vector keyId = {7, 8, 9}; + try { + std::string result = manager.ContentUpdateCb(nullptr, 3, keyId, 30); + std::cout << "Callback invocation returned: " << result << std::endl; + FAIL() << "Expected exception was not thrown"; + } catch (const std::runtime_error &e) { + std::cout << "Caught expected exception: " << e.what() << std::endl; + SUCCEED(); + } catch (...) { + FAIL() << "Caught unexpected exception type"; + } + + std::cout << "Exiting RegisterLambdaThrowingException test" << std::endl; +} +/** + * @brief Verifies that registering a valid license callback succeeds. + * + * This test checks whether a valid license callback is properly registered with the DrmSessionManager object. + * The callback is defined to return KeyState::SUCCESS and is later invoked with test values to ensure it behaves as expected. + * + * **Test Group ID:** Basic: 01@n + * **Test Case ID:** 029@n + * **Priority:** High@n + * + * **Pre-Conditions:** None@n + * **Dependencies:** None@n + * **User Interaction:** None@n + * + * **Test Procedure:** + * | Variation / Step | Description | Test Data | Expected Result | Notes | + * | :----: | --------- | ---------- |-------------- | ----- | + * | 01 | Construct DrmSessionManager object using custom constructor. | maxDrmSessions = 5, player = nullptr | DrmSessionManager object is created successfully. | Should be successful | + * | 02 | Register a valid license callback lambda that returns KeyState::SUCCESS. | callback = lambda (drmHelper, sessionSlot, cdmError, streamType, metaDataPtr, isLicenseRenewal) | Callback is registered in AcquireLicenseCb. | Should Pass | + * | 03 | Invoke the registered internal callback with test parameters. | testDrmHelper = nullptr, sessionSlot = 1, cdmError = -1, streamType = 0, metaDataPtr = nullptr, isLicenseRenewal = false | Callback returns KeyState::SUCCESS and sets cdmError = 0. | Should Pass | + */ +TEST(DrmSessionManager, RegisterValidLicenseCallbackSuccess) { + std::cout << "Entering RegisterValidLicenseCallbackSuccess test" << std::endl; + + // Construct DrmSessionManager object using custom constructor with arbitrary parameters. + int maxDrmSessions = 5; + void* player = nullptr; + std::cout << "Constructed DrmSessionManager with maxDrmSessions = " << maxDrmSessions + << " and player = " << player << std::endl; + DrmSessionManager drmManager(maxDrmSessions, player); + + // Define the license callback lambda that returns KeyState::SUCCESS. + DrmSessionManager::LicenseCallback callback = + [](DrmHelperPtr drmHelper, int sessionSlot, int &cdmError, GstMediaType streamType, void* metaDataPtr, bool isLicenseRenewal) -> KeyState { + std::cout << "Inside SUCCESS callback invocation:" << std::endl; + std::cout << "drmHelper = " << drmHelper << ", sessionSlot = " << sessionSlot + << ", streamType = " << streamType << ", metaDataPtr = " << metaDataPtr + << ", isLicenseRenewal = " << isLicenseRenewal << std::endl; + cdmError = 0; + std::cout << "Setting cdmError to " << cdmError << " and returning KeyState::SUCCESS" << std::endl; + return KeyState::SUCCESS; + }; + + // Register the license callback. + std::cout << "Invoking RegisterLicenseDataCb with SUCCESS callback" << std::endl; + drmManager.RegisterLicenseDataCb(callback); + std::cout << "License callback registered successfully" << std::endl; + + // Validate the internal AcquireLicenseCb by invoking it with test values. + if (drmManager.AcquireLicenseCb) { + std::cout << "Invoking internal AcquireLicenseCb" << std::endl; + int cdmError = -1; + DrmHelperPtr testDrmHelper = nullptr; + int sessionSlot = 1; + GstMediaType streamType = 0; // Arbitrary value for stream type. + void* metaDataPtr = nullptr; + bool isLicenseRenewal = false; + KeyState result = drmManager.AcquireLicenseCb(testDrmHelper, sessionSlot, cdmError, streamType, metaDataPtr, isLicenseRenewal); + std::cout << "Callback returned " << (result == KeyState::SUCCESS ? "KeyState::SUCCESS" : "KeyState::ERROR") + << " with cdmError = " << cdmError << std::endl; + ASSERT_EQ(result, KeyState::SUCCESS); + } else { + FAIL() << "AcquireLicenseCb is empty after registering a valid callback."; + } + + std::cout << "Exiting RegisterValidLicenseCallbackSuccess test" << std::endl; +} +/** + * @brief Validate that registering a license callback which returns KeyState::ERROR works as expected. + * + * This test verifies that when an error-returning license callback is registered via RegisterLicenseDataCb, the DrmSessionManager's internal AcquireLicenseCb method invokes the callback correctly, returns KeyState::ERROR, and sets the cdmError variable appropriately. This ensures that error conditions in license processing are handled properly. + * + * **Test Group ID:** Basic: 01@n + * **Test Case ID:** 030@n + * **Priority:** High@n + * + * **Pre-Conditions:** None@n + * **Dependencies:** None@n + * **User Interaction:** None@n + * + * **Test Procedure:**@n + * | Variation / Step | Description | Test Data | Expected Result | Notes | + * | :----: | --------- | ---------- |-------------- | ----- | + * | 01 | Construct DrmSessionManager with maxDrmSessions and player set to nullptr | maxDrmSessions = 3, player = nullptr | DrmSessionManager object constructed successfully | Should be successful | + * | 02 | Define a license callback lambda that returns KeyState::ERROR and sets cdmError to 1 | Callback lambda definition | Lambda defined returning KeyState::ERROR | Should be successful | + * | 03 | Register the license callback using RegisterLicenseDataCb | Callback = ERROR lambda | License callback registered successfully | Should Pass | + * | 04 | Invoke internal AcquireLicenseCb with test parameters to validate callback behavior | testDrmHelper = nullptr, sessionSlot = 2, cdmError = -1, streamType = 1, metaDataPtr = nullptr, isLicenseRenewal = true | API returns KeyState::ERROR and cdmError is set to 1; ASSERT_EQ(result, KeyState::ERROR) passes | Should Pass | + */ +TEST(DrmSessionManager, RegisterValidLicenseCallbackError) { + std::cout << "Entering RegisterValidLicenseCallbackError test" << std::endl; + + // Construct DrmSessionManager object using custom constructor with arbitrary parameters. + int maxDrmSessions = 3; + void* player = nullptr; + std::cout << "Constructed DrmSessionManager with maxDrmSessions = " << maxDrmSessions + << " and player = " << player << std::endl; + DrmSessionManager drmManager(maxDrmSessions, player); + + // Define the license callback lambda that returns KeyState::ERROR. + DrmSessionManager::LicenseCallback callback = + [](DrmHelperPtr drmHelper, int sessionSlot, int &cdmError, GstMediaType streamType, void* metaDataPtr, bool isLicenseRenewal) -> KeyState { + std::cout << "Inside ERROR callback invocation:" << std::endl; + std::cout << "drmHelper = " << drmHelper << ", sessionSlot = " << sessionSlot + << ", streamType = " << streamType << ", metaDataPtr = " << metaDataPtr + << ", isLicenseRenewal = " << isLicenseRenewal << std::endl; + cdmError = 1; + std::cout << "Setting cdmError to " << cdmError << " and returning KeyState::ERROR" << std::endl; + return KeyState::ERROR; + }; + + // Register the license callback. + std::cout << "Invoking RegisterLicenseDataCb with ERROR callback" << std::endl; + drmManager.RegisterLicenseDataCb(callback); + std::cout << "License callback registered successfully" << std::endl; + + // Validate the internal AcquireLicenseCb by invoking it with test values. + if (drmManager.AcquireLicenseCb) { + std::cout << "Invoking internal AcquireLicenseCb" << std::endl; + int cdmError = -1; + DrmHelperPtr testDrmHelper = nullptr; + int sessionSlot = 2; + GstMediaType streamType = 1; // Arbitrary value for stream type. + void* metaDataPtr = nullptr; + bool isLicenseRenewal = true; + KeyState result = drmManager.AcquireLicenseCb(testDrmHelper, sessionSlot, cdmError, streamType, metaDataPtr, isLicenseRenewal); + std::cout << "Callback returned " << (result == KeyState::ERROR ? "KeyState::ERROR" : "KeyState::SUCCESS") + << " with cdmError = " << cdmError << std::endl; + ASSERT_EQ(result, KeyState::ERROR); + } else { + FAIL() << "AcquireLicenseCb is empty after registering a valid callback."; + } + + std::cout << "Exiting RegisterValidLicenseCallbackError test" << std::endl; +} +/** + * @brief Test registration and safe invocation of an empty license callback in DrmSessionManager + * + * This test constructs a DrmSessionManager instance with arbitrary values, registers an empty license callback, + * and verifies that the internal AcquireLicenseCb remains empty. It also attempts to invoke the empty callback + * safely, ensuring that no callback is executed and no exception is raised. + * + * **Test Group ID:** Basic: 01@n + * **Test Case ID:** 031@n + * **Priority:** High@n + * + * **Pre-Conditions:** None@n + * **Dependencies:** None@n + * **User Interaction:** None@n + * + * **Test Procedure:** + * | Variation / Step | Description | Test Data | Expected Result | Notes | + * | :----: | :--------------------------------------------------------------------------- | :------------------------------------------------------------------------------------------------------ | :------------------------------------------------------------------------------------------------ | :--------------- | + * | 01 | Construct DrmSessionManager object using custom parameters | maxDrmSessions = 4, player = nullptr | Object is created successfully | Should be successful | + * | 02 | Create an empty (default-constructed) license callback | emptyCallback = {} | Empty license callback is created | Should be successful | + * | 03 | Register the empty license callback | emptyCallback = {} | AcquireLicenseCb remains empty (no callback registered) | Should be successful | + * | 04 | Validate that AcquireLicenseCb is empty after registration | drmManager.AcquireLicenseCb checked via if condition | AcquireLicenseCb is empty and assertion passes | Should be successful | + * | 05 | Attempt to safely invoke the callback ensuring no operation occurs | testDrmHelper = nullptr, sessionSlot = 0, cdmError = -1, streamType = 0, metaDataPtr = nullptr, isLicenseRenewal = false | Callback invocation is skipped gracefully with no exception thrown | Should be successful | + */ +TEST(DrmSessionManager, RegisterEmptyLicenseCallback) { + std::cout << "Entering RegisterEmptyLicenseCallback test" << std::endl; + + // Construct DrmSessionManager object using custom constructor with arbitrary parameters. + int maxDrmSessions = 4; + void* player = nullptr; + std::cout << "Constructed DrmSessionManager with maxDrmSessions = " << maxDrmSessions + << " and player = " << player << std::endl; + DrmSessionManager drmManager(maxDrmSessions, player); + + // Create an empty (default-constructed) license callback. + DrmSessionManager::LicenseCallback emptyCallback{}; + std::cout << "Created an empty license callback" << std::endl; + + // Register the empty callback. + std::cout << "Invoking RegisterLicenseDataCb with empty callback" << std::endl; + drmManager.RegisterLicenseDataCb(emptyCallback); + std::cout << "Empty license callback registered successfully" << std::endl; + + // Validate that the internal AcquireLicenseCb is empty. + if (drmManager.AcquireLicenseCb) { + std::cout << "AcquireLicenseCb is not empty when it should be empty" << std::endl; + FAIL() << "AcquireLicenseCb should be empty after registering an empty callback."; + } else { + std::cout << "AcquireLicenseCb is empty as expected" << std::endl; + } + + // Attempt to invoke the callback safely by checking for emptiness. + try { + if (drmManager.AcquireLicenseCb) { + int cdmError = -1; + DrmHelperPtr testDrmHelper = nullptr; + int sessionSlot = 0; + GstMediaType streamType = 0; + void* metaDataPtr = nullptr; + bool isLicenseRenewal = false; + KeyState result = drmManager.AcquireLicenseCb(testDrmHelper, sessionSlot, cdmError, streamType, metaDataPtr, isLicenseRenewal); + std::cout << "Unexpected invocation result from an empty callback" << std::endl; + FAIL() << "Empty callback invocation should not occur."; + } else { + std::cout << "Callback is empty; invocation skipped gracefully" << std::endl; + } + } catch (...) { + FAIL() << "Exception thrown when invoking an empty callback."; + } + + std::cout << "Exiting RegisterEmptyLicenseCallback test" << std::endl; +} +/** + * @brief Verifies that a valid callback is correctly registered and invoked by DrmSessionManager. + * + * This test ensures that when a valid lambda callback is registered using the RegisterProfilingUpdateCb API, + * the callback is stored and invoked properly to update the flag variable. The test simulates registering a + * callback, triggering it, and then asserting that the flag is set to true. + * + * **Test Group ID:** Basic: 01@n + * **Test Case ID:** 032@n + * **Priority:** High@n + * + * **Pre-Conditions:** None@n + * **Dependencies:** None@n + * **User Interaction:** None@n + * + * **Test Procedure:** + * | Variation / Step | Description | Test Data | Expected Result | Notes | + * | :--------------: | ------------------------------------------------------------------------------ | --------------------------------------------------------- | -------------------------------------------------- | ------------ | + * | 01 | Initialize a flag variable to false | flag = false | flag is set to false | Should be successful | + * | 02 | Create a lambda callback that sets the flag to true | callback defined as: [&flag]() { flag = true; } | Lambda callback is defined without errors | Should be successful | + * | 03 | Instantiate DrmSessionManager with test parameters | maxDrmSessions = 5, player = nullptr | Object is created successfully | Should be successful | + * | 04 | Register the callback using RegisterProfilingUpdateCb | callback = valid lambda | Callback is registered successfully | Should Pass | + * | 05 | Invoke the registered callback and check the flag value | Invoking ProfileUpdateCb if available | The flag updates to true after callback invocation | Should Pass */ +TEST(DrmSessionManager, ValidCallbackRegistration) { + std::cout << "Entering ValidCallbackRegistration test" << std::endl; + + // Setup flag variable to be set by the callback + bool flag = false; + std::cout << "Initial flag value: " << flag << std::endl; + + // Create a lambda callback that sets flag to true + std::function callback = [&flag]() { + std::cout << "Inside valid callback: setting flag to true." << std::endl; + flag = true; + }; + std::cout << "Created callback lambda." << std::endl; + + // Create a DrmSessionManager object with dummy test values + DrmSessionManager drmSessionManager(5, nullptr); + std::cout << "DrmSessionManager object created with maxDrmSessions=5 and player=nullptr." << std::endl; + + // Register the callback and log the invocation + std::cout << "Invoking RegisterProfilingUpdateCb with valid callback." << std::endl; + drmSessionManager.RegisterProfilingUpdateCb(callback); + std::cout << "Callback registration completed." << std::endl; + + // Invoke the stored callback to test if it triggers the lambda + if (drmSessionManager.ProfileUpdateCb) { + std::cout << "Invoking stored ProfileUpdateCb." << std::endl; + drmSessionManager.ProfileUpdateCb(); + } else { + std::cout << "Stored ProfileUpdateCb is empty." << std::endl; + } + std::cout << "Flag value after invoking callback: " << flag << std::endl; + EXPECT_TRUE(flag); + + std::cout << "Exiting ValidCallbackRegistration test" << std::endl; +} +/** + * @brief Verify registration of an empty callback and ensure that invoking it throws an exception. + * + * This test verifies that when an empty std::function callback is registered via RegisterProfilingUpdateCb, + * any attempt to invoke the stored callback using ProfileUpdateCb results in throwing a std::bad_function_call exception. + * + * **Test Group ID:** Basic: 01@n + * **Test Case ID:** 033@n + * **Priority:** High@n + * + * **Pre-Conditions:** None@n + * **Dependencies:** None@n + * **User Interaction:** None@n + * + * **Test Procedure:** + * | Variation / Step | Description | Test Data | Expected Result | Notes | + * | :----: | --------- | ---------- |-------------- | ----- | + * | 01 | Create an empty std::function callback. | emptyCallback = uninitialized | std::function is empty. | Should be successful | + * | 02 | Create a DrmSessionManager object with maxDrmSessions=5 and player=nullptr. | maxDrmSessions = 5, player = nullptr | DrmSessionManager object is created successfully. | Should be successful | + * | 03 | Register the empty callback using RegisterProfilingUpdateCb. | input: emptyCallback | Callback registered without error. | Should Pass | + * | 04 | Invoke the stored empty callback using ProfileUpdateCb and expect a std::bad_function_call exception. | Invocation of ProfileUpdateCb with no valid callback set | Throws std::bad_function_call exception. | Should Fail | + */ +TEST(DrmSessionManager, RegisteringEmptyCallback) { + std::cout << "Entering RegisteringEmptyCallback test" << std::endl; + + // Create an empty std::function callback + std::function emptyCallback; + std::cout << "Created empty callback using std::function." << std::endl; + + // Create a DrmSessionManager object with dummy test values + DrmSessionManager drmSessionManager(5, nullptr); + std::cout << "DrmSessionManager object created with maxDrmSessions=5 and player=nullptr." << std::endl; + + // Register the empty callback + std::cout << "Invoking RegisterProfilingUpdateCb with empty callback." << std::endl; + drmSessionManager.RegisterProfilingUpdateCb(emptyCallback); + std::cout << "Empty callback registration completed." << std::endl; + + // Attempt to invoke the stored empty callback and expect std::bad_function_call + std::cout << "Attempting to invoke stored empty ProfileUpdateCb expecting an exception." << std::endl; + EXPECT_THROW({ + drmSessionManager.ProfileUpdateCb(); + }, std::bad_function_call); + + std::cout << "Exiting RegisteringEmptyCallback test" << std::endl; +} +/** + * @brief Tests that overwriting the registered callback correctly updates the callback function. + * + * This test verifies that when a callback is overwritten in the DrmSessionManager using RegisterProfilingUpdateCb, only the latest callback is triggered upon invocation, ensuring that the manager replaces the first callback with the second. + * + * **Test Group ID:** Basic: 01@n + * **Test Case ID:** 034@n + * **Priority:** High@n + * + * **Pre-Conditions:** None@n + * **Dependencies:** None@n + * **User Interaction:** None@n + * + * **Test Procedure:**@n + * | Variation / Step | Description | Test Data | Expected Result | Notes | + * | :----: | --------- | ---------- |-------------- | ----- | + * | 01 | Initialize flag1 and flag2 to false. | flag1 = false, flag2 = false | Flags are successfully initialized to false. | Should be successful | + * | 02 | Create first callback lambda to set flag1 to true and second callback lambda to set flag2 to true. | firstCallback: sets flag1 = true, secondCallback: sets flag2 = true | Callbacks are successfully created. | Should be successful | + * | 03 | Instantiate DrmSessionManager with maxDrmSessions=5 and player=nullptr. | maxDrmSessions = 5, player = nullptr | DrmSessionManager object is created successfully. | Should be successful | + * | 04 | Register the first callback using RegisterProfilingUpdateCb. | API call: RegisterProfilingUpdateCb(firstCallback) | The first callback is registered successfully. | Should be successful | + * | 05 | Overwrite the first callback by registering the second callback. | API call: RegisterProfilingUpdateCb(secondCallback) | The callback is overwritten with the second callback. | Should be successful | + * | 06 | Invoke the stored ProfileUpdateCb callback. | API call: ProfileUpdateCb invocation | Only flag2 is set to true; flag1 remains false. | Should Pass | + * | 07 | Verify that flag1 is false and flag2 is true using assertions. | EXPECT_FALSE(flag1), EXPECT_TRUE(flag2) | Assertions pass confirming correct callback behavior. | Should Pass | + */ +TEST(DrmSessionManager, OverwritingPreviouslyRegisteredCallback) { + std::cout << "Entering OverwritingPreviouslyRegisteredCallback test" << std::endl; + + // Setup flag variables for each callback + bool flag1 = false; + bool flag2 = false; + std::cout << "Initial flag1: " << flag1 << ", flag2: " << flag2 << std::endl; + + // Create first callback lambda that sets flag1 to true + std::function firstCallback = [&flag1]() { + std::cout << "Inside first callback: setting flag1 to true." << std::endl; + flag1 = true; + }; + std::cout << "Created first callback lambda." << std::endl; + + // Create second callback lambda that sets flag2 to true + std::function secondCallback = [&flag2]() { + std::cout << "Inside second callback: setting flag2 to true." << std::endl; + flag2 = true; + }; + std::cout << "Created second callback lambda." << std::endl; + + // Create a DrmSessionManager object with dummy test values + DrmSessionManager drmSessionManager(5, nullptr); + std::cout << "DrmSessionManager object created with maxDrmSessions=5 and player=nullptr." << std::endl; + + // Register the first callback + std::cout << "Invoking RegisterProfilingUpdateCb with first callback." << std::endl; + drmSessionManager.RegisterProfilingUpdateCb(firstCallback); + std::cout << "First callback registration completed." << std::endl; + + // Overwrite with the second callback + std::cout << "Invoking RegisterProfilingUpdateCb with second callback to overwrite the first one." << std::endl; + drmSessionManager.RegisterProfilingUpdateCb(secondCallback); + std::cout << "Second callback registration completed." << std::endl; + + // Invoke the stored callback to test that only the second callback is triggered + if (drmSessionManager.ProfileUpdateCb) { + std::cout << "Invoking stored ProfileUpdateCb which should trigger second callback only." << std::endl; + drmSessionManager.ProfileUpdateCb(); + } else { + std::cout << "Stored ProfileUpdateCb is empty." << std::endl; + } + + std::cout << "Flag1 value after invoking callback: " << flag1 << std::endl; + std::cout << "Flag2 value after invoking callback: " << flag2 << std::endl; + EXPECT_FALSE(flag1); + EXPECT_TRUE(flag2); + + std::cout << "Exiting OverwritingPreviouslyRegisteredCallback test" << std::endl; +} +/** + * @brief Validate that SetCommonKeyDuration API updates the internal common key duration with a valid positive input + * + * This test verifies that when a valid positive key duration value is provided, the DrmSessionManager correctly updates its internal common key duration. The test involves creating an instance of DrmSessionManager, setting a key duration, invoking the SetCommonKeyDuration API, and validating that the API completes successfully. + * + * **Test Group ID:** Basic: 01@n + * **Test Case ID:** 035@n + * **Priority:** High@n + * + * **Pre-Conditions:** None@n + * **Dependencies:** None@n + * **User Interaction:** None@n + * + * **Test Procedure:**@n + * | Variation / Step | Description | Test Data | Expected Result | Notes | + * | :--------------: | ----------------------------------------------------------------- | ------------------------------------------ | ------------------------------------------------ | ------------- | + * | 01 | Create DrmSessionManager instance using custom constructor | input1 = 5, input2 = nullptr | Instance created successfully | Should be successful | + * | 02 | Set keyDuration variable with a valid positive integer | keyDuration = 30 | keyDuration variable is set to 30 | Should be successful | + * | 03 | Invoke SetCommonKeyDuration API with keyDuration | keyDuration = 30 | Internal common key duration is updated | Should Pass | + * | 04 | Validate the outcome using EXPECT_TRUE assertion | return value = true | Test assertion passes as EXPECT_TRUE evaluates to true | Should Pass | + */ +TEST(DrmSessionManager, SetCommonKeyDuration_validPositive) { + std::cout << "Entering SetCommonKeyDuration_validPositive test" << std::endl; + + // Create DrmSessionManager object using custom constructor + DrmSessionManager drmSessionManager(5, nullptr); + + int keyDuration = 30; + std::cout << "Invoking DrmSessionManager::SetCommonKeyDuration with argument: " << keyDuration << std::endl; + + drmSessionManager.SetCommonKeyDuration(keyDuration); + + // Log assumed internal state change + std::cout << "Internal common key duration updated to: " << keyDuration << std::endl; + + // Validate that method call completes successfully + EXPECT_TRUE(true); + + std::cout << "Exiting SetCommonKeyDuration_validPositive test" << std::endl; +} +/** + * @brief Test if DrmSessionManager correctly handles setting a common key duration of zero. + * + * This test verifies that when the SetCommonKeyDuration API is invoked with a key duration of zero, + * the internal state is assumed to be updated accordingly and the method call completes successfully. + * + * **Test Group ID:** Basic: 01@n + * **Test Case ID:** 036@n + * **Priority:** High@n + * + * **Pre-Conditions:** None@n + * **Dependencies:** None@n + * **User Interaction:** None@n + * + * **Test Procedure:**@n + * | Variation / Step | Description | Test Data | Expected Result | Notes | + * | :--------------: | ----------- | --------- | ------------- | ----- | + * | 01 | Instantiate DrmSessionManager object using custom constructor | input1 = 5, input2 = nullptr | Object is instantiated successfully | Should be successful | + * | 02 | Invoke SetCommonKeyDuration with keyDuration = 0 | keyDuration = 0 | Internal common key duration is updated to 0 without error | Should Pass | + * | 03 | Validate method execution by checking assertion | Expected assertion: true | EXPECT_TRUE(true) passes confirming successful execution | Should be successful | + */ +TEST(DrmSessionManager, SetCommonKeyDuration_zero) { + std::cout << "Entering SetCommonKeyDuration_zero test" << std::endl; + + // Create DrmSessionManager object using custom constructor + DrmSessionManager drmSessionManager(5, nullptr); + + int keyDuration = 0; + std::cout << "Invoking DrmSessionManager::SetCommonKeyDuration with argument: " << keyDuration << std::endl; + + drmSessionManager.SetCommonKeyDuration(keyDuration); + + // Log assumed internal state change + std::cout << "Internal common key duration updated to: " << keyDuration << std::endl; + + // Validate that method call completes successfully + EXPECT_TRUE(true); + + std::cout << "Exiting SetCommonKeyDuration_zero test" << std::endl; +} +/** + * @brief Test the behavior of SetCommonKeyDuration when a negative key duration is provided. + * + * This test invokes the SetCommonKeyDuration function of the DrmSessionManager class with a negative key duration value (-10) to verify that the API properly handles invalid negative duration values without causing a crash or unexpected behavior. + * + * **Test Group ID:** Basic: 01 + * **Test Case ID:** 037 + * **Priority:** High + * + * **Pre-Conditions:** None + * **Dependencies:** None + * **User Interaction:** None + * + * **Test Procedure:** + * | Variation / Step | Description | Test Data | Expected Result | Notes | + * | :----: | --------------------------------------------------------------- | ------------------------------------------ | ----------------------------------------------------------------------- | ------------- | + * | 01 | Create a DrmSessionManager instance using a custom constructor | input1 = 5, input2 = nullptr | Instance is created successfully | Should be successful | + * | 02 | Call SetCommonKeyDuration with a negative key duration value | input1 = keyDuration, keyDuration = -10 | API properly handles the negative value without causing a crash | Should Pass | + * | 03 | Validate that the method call completes execution without exceptions| output1 = completion status (implicit) | Method completes execution successfully without throwing any exceptions | Should Pass | + */ +TEST(DrmSessionManager, SetCommonKeyDuration_negative) { + std::cout << "Entering SetCommonKeyDuration_negative test" << std::endl; + + // Create DrmSessionManager object using custom constructor + DrmSessionManager drmSessionManager(5, nullptr); + + int keyDuration = -10; + std::cout << "Invoking DrmSessionManager::SetCommonKeyDuration with argument: " << keyDuration << std::endl; + + drmSessionManager.SetCommonKeyDuration(keyDuration); + + // Log assumed internal state change or handling of negative value. + std::cout << "Internal handling of negative key duration: " << keyDuration << std::endl; + + // Validate that method call completes successfully without crash. + EXPECT_TRUE(true); + + std::cout << "Exiting SetCommonKeyDuration_negative test" << std::endl; +} +/** + * @brief Verify that DrmSessionManager correctly handles maximum integer key duration. + * + * This test invokes DrmSessionManager::SetCommonKeyDuration() with the maximum integer value (INT_MAX) to ensure the API can handle extreme key duration values. It verifies that the method call completes successfully and the internal state is assumed to be updated accordingly. + * + * **Test Group ID:** Basic: 01@n + * **Test Case ID:** 038@n + * **Priority:** High@n + * + * **Pre-Conditions:** None@n + * **Dependencies:** None@n + * **User Interaction:** None@n + * + * **Test Procedure:** + * | Variation / Step | Description | Test Data | Expected Result | Notes | + * | :----: | --------- | ---------- |-------------- | ----- | + * | 01 | Create DrmSessionManager object using custom constructor | input1 = 5, input2 = nullptr | Object is created successfully | Should be successful | + * | 02 | Set keyDuration to maximum integer value | keyDuration = INT_MAX | keyDuration is correctly set to INT_MAX | Should be successful | + * | 03 | Invoke SetCommonKeyDuration with keyDuration | keyDuration = INT_MAX, internal update expected | API call completes successfully and internal state is updated | Should Pass | + * | 04 | Validate API call completes successfully using assertion | ASSERT: EXPECT_TRUE(true) | Assertion passes confirming the expected behavior | Should Pass | + */ +TEST(DrmSessionManager, SetCommonKeyDuration_maxInt) { + std::cout << "Entering SetCommonKeyDuration_maxInt test" << std::endl; + + // Create DrmSessionManager object using custom constructor + DrmSessionManager drmSessionManager(5, nullptr); + + int keyDuration = INT_MAX; + std::cout << "Invoking DrmSessionManager::SetCommonKeyDuration with argument: " << keyDuration << std::endl; + + drmSessionManager.SetCommonKeyDuration(keyDuration); + + // Log assumed internal state change + std::cout << "Internal common key duration updated to: " << keyDuration << std::endl; + + // Validate that method call completes successfully. + EXPECT_TRUE(true); + + std::cout << "Exiting SetCommonKeyDuration_maxInt test" << std::endl; +} +/** + * @brief Test to verify that DrmSessionManager::SetCommonKeyDuration correctly handles the minimum integer value for the key duration. + * + * This test checks if the API properly processes a negative duration by setting the key duration to INT_MIN. + * The objective is to ensure that the method call completes without error even for boundary value input. + * + * **Test Group ID:** Basic: 01@n + * **Test Case ID:** 039@n + * **Priority:** High@n + * + * **Pre-Conditions:** None@n + * **Dependencies:** None@n + * **User Interaction:** None@n + * + * **Test Procedure:**@n + * | Variation / Step | Description | Test Data | Expected Result | Notes | + * | :----: | --------- | ---------- |-------------- | ----- | + * | 01 | Log the start of the test execution. | None | "Entering SetCommonKeyDuration_minInt test" message is printed. | Should be successful | + * | 02 | Construct DrmSessionManager using the custom constructor. | param1 = 5, param2 = nullptr | Instance of DrmSessionManager is created successfully. | Should be successful | + * | 03 | Initialize keyDuration with INT_MIN. | keyDuration = INT_MIN | keyDuration is correctly set to INT_MIN. | Should be successful | + * | 04 | Invoke SetCommonKeyDuration with keyDuration. | keyDuration = INT_MIN | API processes the minimum key duration, handling the negative value appropriately. | Should Pass | + * | 05 | Validate API execution through assertion check. | Assertion: true | EXPECT_TRUE(true) assertion passes confirming successful API call. | Should Pass | + * | 06 | Log the exit of the test execution. | None | "Exiting SetCommonKeyDuration_minInt test" message is printed. | Should be successful | + */ +TEST(DrmSessionManager, SetCommonKeyDuration_minInt) { + std::cout << "Entering SetCommonKeyDuration_minInt test" << std::endl; + + // Create DrmSessionManager object using custom constructor + DrmSessionManager drmSessionManager(5, nullptr); + + int keyDuration = INT_MIN; + std::cout << "Invoking DrmSessionManager::SetCommonKeyDuration with argument: " << keyDuration << std::endl; + + drmSessionManager.SetCommonKeyDuration(keyDuration); + + // Log assumed internal state change or error handling of the negative duration. + std::cout << "Internal handling of minimum key duration: " << keyDuration << std::endl; + + // Validate that method call completes successfully. + EXPECT_TRUE(true); + + std::cout << "Exiting SetCommonKeyDuration_minInt test" << std::endl; +} +/** + * @brief Validate that calling SetSendErrorOnFailure with true updates the internal configuration without errors + * + * This test verifies that when the DrmSessionManager is configured with a valid set of parameters and the + * SetSendErrorOnFailure method is invoked with the boolean value true, the method executes without throwing + * any exceptions and updates the internal configuration accordingly. + * + * **Test Group ID:** Basic: 01@n + * **Test Case ID:** 040@n + * **Priority:** High@n + * + * **Pre-Conditions:** None@n + * **Dependencies:** None@n + * **User Interaction:** None@n + * + * **Test Procedure:** + * | Variation / Step | Description | Test Data | Expected Result | Notes | + * | :--------------: | --------------------------------------------------------------- | -------------------------------------------------- | ----------------------------------------------------------------------- | ------------- | + * | 01 | Construct DrmSessionManager instance with valid parameters | maxDrmSessions = 5, player = nullptr | Instance is successfully constructed without throwing any exceptions | Should be successful | + * | 02 | Invoke SetSendErrorOnFailure with sendErrorOnFailure set to true | sendErrorOnFailure = true | Method executes without throwing exceptions and updates configuration | Should Pass | + */ +TEST(DrmSessionManager, SetSendErrorOnFailure_true) { + std::cout << "Entering SetSendErrorOnFailure_true test" << std::endl; + + // Create an instance of DrmSessionManager with custom parameters. + int maxDrmSessions = 5; + void* player = nullptr; + std::cout << "Constructed DrmSessionManager with maxDrmSessions = " << maxDrmSessions + << " and player = " << player << std::endl; + DrmSessionManager drmSessionManager(maxDrmSessions, player); + + // Invoke the method with sendErrorOnFailure = true. + bool sendErrorOnFailure = true; + std::cout << "Invoking DrmSessionManager::SetSendErrorOnFailure with argument: " + << (sendErrorOnFailure ? "true" : "false") << std::endl; + EXPECT_NO_THROW({ + drmSessionManager.SetSendErrorOnFailure(sendErrorOnFailure); + }); + + // Log the expected internal configuration update. + std::cout << "SetSendErrorOnFailure successfully updated internal configuration to: " + << (sendErrorOnFailure ? "true" : "false") << std::endl; + + std::cout << "Exiting SetSendErrorOnFailure_true test" << std::endl; +} +/** + * @brief Test verifying that setting sendErrorOnFailure to false does not throw exceptions and updates internal configuration correctly. + * + * This test creates an instance of DrmSessionManager with specific parameters, invokes SetSendErrorOnFailure(false), + * and verifies that no exceptions are thrown during the method call. It also logs the internal configuration change + * to ensure that the API behaves as expected when disabling error reporting on failure. + * + * **Test Group ID:** Basic: 01@n + * **Test Case ID:** 041@n + * **Priority:** High@n + * + * **Pre-Conditions:** None@n + * **Dependencies:** None@n + * **User Interaction:** None@n + * + * **Test Procedure:**@n + * | Variation / Step | Description | Test Data | Expected Result | Notes | + * | :----: | :------------------------------------------------------------------ | :---------------------------------------- | :----------------------------------------------- | :-------------- | + * | 01 | Instantiate DrmSessionManager with maxDrmSessions and player | maxDrmSessions = 5, player = nullptr | DrmSessionManager instance is successfully created | Should be successful | + * | 02 | Invoke SetSendErrorOnFailure with sendErrorOnFailure set to false | sendErrorOnFailure = false | API call does not throw an exception | Should Pass | + * | 03 | Validate internal configuration is updated to reflect the false value | internal configuration = false | Internal configuration update is logged correctly | Should be successful | + */ +TEST(DrmSessionManager, SetSendErrorOnFailure_false) { + std::cout << "Entering SetSendErrorOnFailure_false test" << std::endl; + + // Create an instance of DrmSessionManager with custom parameters. + int maxDrmSessions = 5; + void* player = nullptr; + std::cout << "Constructed DrmSessionManager with maxDrmSessions = " << maxDrmSessions + << " and player = " << player << std::endl; + DrmSessionManager drmSessionManager(maxDrmSessions, player); + + // Invoke the method with sendErrorOnFailure = false. + bool sendErrorOnFailure = false; + std::cout << "Invoking DrmSessionManager::SetSendErrorOnFailure with argument: " + << (sendErrorOnFailure ? "true" : "false") << std::endl; + EXPECT_NO_THROW({ + drmSessionManager.SetSendErrorOnFailure(sendErrorOnFailure); + }); + + // Log the expected internal configuration update. + std::cout << "SetSendErrorOnFailure successfully updated internal configuration to: " + << (sendErrorOnFailure ? "true" : "false") << std::endl; + + std::cout << "Exiting SetSendErrorOnFailure_false test" << std::endl; +} +/** + * @brief Validates that UpdateMaxDRMSessions method correctly updates the maximum DRM sessions count. + * + * This test creates a DrmSessionManager instance with an initial value of 0 for maximum DRM sessions. + * It then updates the maximum DRM sessions to a new value (5) and verifies that the internal state is updated accordingly. + * + * **Test Group ID:** Basic: 01@n + * **Test Case ID:** 042@n + * **Priority:** (High) This test is essential for ensuring proper session management functionality. + * + * **Pre-Conditions:** None@n + * **Dependencies:** None@n + * **User Interaction:** None@n + * + * **Test Procedure:**@n + * | Variation / Step | Description | Test Data | Expected Result | Notes | + * | :----: | ----------------------------------------------------------------------------- | --------------------------------------------------- | --------------------------------------------------- | --------------- | + * | 01 | Create DrmSessionManager instance with initial max DRM sessions value of 0. | input: mMaxDrmSessions = 0, player = nullptr | Instance is created with mMaxDrmSessions set to 0. | Should be successful | + * | 02 | Invoke UpdateMaxDRMSessions to update the maximum DRM sessions to 5. | input: newMaxSessions = 5 | The internal mMaxDrmSessions is updated to 5. | Should Pass | + */ +TEST(DrmSessionManager, UpdateMaxDRMSessionsPositive) { + std::cout << "Entering UpdateMaxDRMSessionsPositive test" << std::endl; + + DrmSessionManager drmManager(0, nullptr); + + int newMaxSessions = 5; + std::cout << "Invoking UpdateMaxDRMSessions with value: " << newMaxSessions << std::endl; + drmManager.UpdateMaxDRMSessions(newMaxSessions); + + // Log the updated internal state; expecting the internal mMaxDrmSessions to be updated to newMaxSessions (5) + std::cout << "Updated max DRM sessions value" << std::endl; + + std::cout << "Exiting UpdateMaxDRMSessionsPositive test" << std::endl; +} +/** + * @brief Validate that UpdateMaxDRMSessions correctly updates the maximum DRM sessions to zero. + * + * This test verifies that when the UpdateMaxDRMSessions API is invoked with a value of zero, + * the internal state variable mMaxDrmSessions of the DrmSessionManager instance is updated from a non-zero initial value to 0. + * + * **Test Group ID:** Basic: 01@n + * **Test Case ID:** 043@n + * **Priority:** High@n + * + * **Pre-Conditions:** None@n + * **Dependencies:** None@n + * **User Interaction:** None@n + * + * **Test Procedure:** + * | Variation / Step | Description | Test Data | Expected Result | Notes | + * | :----: | --------- | ---------- |-------------- | ----- | + * |01|Initialize DrmSessionManager instance with a non-zero max DRM sessions value|input: mMaxDrmSessions = 10|Instance created with mMaxDrmSessions set to 10|Should be successful| + * |02|Invoke UpdateMaxDRMSessions with a zero value to update the max DRM sessions|input: newMaxSessions = 0, initial mMaxDrmSessions = 10|mMaxDrmSessions is updated to 0|Should Pass| + */ +TEST(DrmSessionManager, UpdateMaxDRMSessionsZero) { + std::cout << "Entering UpdateMaxDRMSessionsZero test" << std::endl; + + // Initialize with a non-zero value to see the change after update. + DrmSessionManager drmManager(10, nullptr); + + int newMaxSessions = 0; + std::cout << "Invoking UpdateMaxDRMSessions with value: " << newMaxSessions << std::endl; + drmManager.UpdateMaxDRMSessions(newMaxSessions); + + std::cout << "Updated max DRM sessions value"<< std::endl; + + std::cout << "Exiting UpdateMaxDRMSessionsZero test" << std::endl; +} +/** + * @brief Validate that UpdateMaxDRMSessions rejects negative input values. + * + * This test verifies that when a negative value is provided to UpdateMaxDRMSessions, the internal maximum DRM sessions value remains unchanged. The objective is to ensure that the API correctly handles invalid input by not updating the default valid state. + * + * **Test Group ID:** Basic: 01@n + * **Test Case ID:** 044@n + * **Priority:** High@n + * + * **Pre-Conditions:** None@n + * **Dependencies:** None@n + * **User Interaction:** None@n + * + * **Test Procedure:**@n + * | Variation / Step | Description | Test Data | Expected Result | Notes | + * | :----: | --------- | ---------- |-------------- | ----- | + * | 01 | Initialize DrmSessionManager with an initialMaxSessions value of 3, invoke UpdateMaxDRMSessions with a negative value (-1), and verify that the max sessions value remains unchanged. | initialMaxSessions = 3, newMaxSessions = -1 | | Should Fail | + */ +TEST(DrmSessionManager, UpdateMaxDRMSessionsNegative) { + std::cout << "Entering UpdateMaxDRMSessionsNegative test" << std::endl; + + // Initialize with a known positive value. + int initialMaxSessions = 3; + DrmSessionManager drmManager(initialMaxSessions, nullptr); + + int newMaxSessions = -1; + std::cout << "Invoking UpdateMaxDRMSessions with negative value: " << newMaxSessions << std::endl; + drmManager.UpdateMaxDRMSessions(newMaxSessions); + + std::cout << "Exiting UpdateMaxDRMSessionsNegative test" << std::endl; +} +/** + * @brief Validate that UpdateMaxDRMSessions correctly updates the maximum DRM sessions when a high value is provided. + * + * This test case creates a DrmSessionManager instance with an initial maximum session value, then updates the maximum DRM sessions using the UpdateMaxDRMSessions API with a high integer value (2147483647). The objective is to ensure that the manager's internal state reflects this updated high value correctly. + * + * **Test Group ID:** Basic: 01 + * **Test Case ID:** 045 + * **Priority:** High + * + * **Pre-Conditions:** None + * **Dependencies:** None + * **User Interaction:** None + * + * **Test Procedure:** + * | Variation / Step | Description | Test Data | Expected Result | Notes | + * | :----: | --------- | ---------- |-------------- | ----- | + * | 01 | Initialize DrmSessionManager with an initial max value of 1 | input1 = initialMax = 1, input2 = pointer = nullptr, output1 = mMaxDrmSessions = 1 | DrmSessionManager instance is created with mMaxDrmSessions set to 1 | Should be successful | + * | 02 | Update the max DRM sessions to 2147483647 using UpdateMaxDRMSessions method | input1 = newMaxSessions = 2147483647, output1 = mMaxDrmSessions = 2147483647 | | Should Pass | + */ +TEST(DrmSessionManager, UpdateMaxDRMSessionsHighValue) { + std::cout << "Entering UpdateMaxDRMSessionsHighValue test" << std::endl; + + // Start with an initial value for clarity. + DrmSessionManager drmManager(1, nullptr); + + int newMaxSessions = 2147483647; + std::cout << "Invoking UpdateMaxDRMSessions with high value: " << newMaxSessions << std::endl; + drmManager.UpdateMaxDRMSessions(newMaxSessions); + + // Log the internal state after update. + std::cout << "Updated max DRM sessions value" << std::endl; + + std::cout << "Exiting UpdateMaxDRMSessionsHighValue test" << std::endl; +} +/** + * @brief Test for clearing a valid access token from DrmSessionManager + * + * This test verifies that when the clearAccessToken() method is invoked on a DrmSessionManager + * instance containing a valid access token, the access token is properly cleared (set to NULL) + * and its length reset to 0. This ensures that the clearAccessToken() method correctly frees the token. + * + * **Test Group ID:** Basic: 01 + * **Test Case ID:** 046 + * **Priority:** High + * + * **Pre-Conditions:** None + * **Dependencies:** None + * **User Interaction:** None + * + * **Test Procedure:** + * | Variation / Step | Description | Test Data | Expected Result | Notes | + * | :--------------: | -------------------------------------------------------------------------------------- | --------------------------------------------------------------------------------------------------- | --------------------------------------------------------------------- | ---------------- | + * | 01 | Create a DrmSessionManager instance | maxDrmSessions = 5, player = nullptr | Instance created | Should be successful | + * | 02 | Invoke clearAccessToken() on the instance | | | Should Pass | + */ +TEST(DrmSessionManager, Clearing_a_valid_access_token) +{ + std::cout << "Entering Clearing_a_valid_access_token test" << std::endl; + + // Create instance using custom constructor (maxDrmSessions = 5, player = nullptr) + DrmSessionManager manager(5, nullptr); + + // Invoke clearAccessToken method + std::cout << "Invoking clearAccessToken()" << std::endl; + manager.clearAccessToken(); + + std::cout << "Invoked clearAccessToken() " << std::endl; + + std::cout << "Exiting Clearing_a_valid_access_token test" << std::endl; +} +/** + * @brief Verify that repeated calls to clearAccessToken correctly maintain a cleared state in the DRM session manager. + * + * This test sets a valid access token in a DrmSessionManager instance and then calls clearAccessToken twice to ensure the method is idempotent. It validates that the accessToken is set to nullptr and accessTokenLen is 0 after repeated invocations, ensuring proper resource cleanup. + * + * **Test Group ID:** Basic: 01@n + * **Test Case ID:** 047@n + * **Priority:** High@n + * + * **Pre-Conditions:** None@n + * **Dependencies:** None@n + * **User Interaction:** None@n + * + * **Test Procedure:**@n + * | Variation / Step | Description | Test Data | Expected Result | Notes | + * | :--------------: | ------------------------------------------------------------------------------------- | --------------------------------------------------------------------------------------------------- | --------------------------------------------------------------------- | ----------------- | + * | 01 | Create an instance of DrmSessionManager with custom parameters. | maxDrmSessions = 5, player = nullptr | Instance is created with maxDrmSessions set to 5 and player as nullptr. | Should be successful | + * | 02 | Invoke clearAccessToken() for the first time to clear the access token. | clearAccessToken() call | | Should Pass | + * | 03 | Invoke clearAccessToken() for the second time to confirm state remains cleared. | clearAccessToken() call | | Should Pass | + */ +TEST(DrmSessionManager, Repeated_calls_to_clearAccessToken) +{ + std::cout << "Entering Repeated_calls_to_clearAccessToken test" << std::endl; + + // Create instance using custom constructor (maxDrmSessions = 5, player = nullptr) + DrmSessionManager manager(5, nullptr); + + // First call to clearAccessToken + std::cout << "Invoking clearAccessToken() first time" << std::endl; + manager.clearAccessToken(); + std::cout << "After first clearAccessToken(): accessToken = " << std::endl; + + // Second call to clearAccessToken + std::cout << "Invoking clearAccessToken() second time" << std::endl; + manager.clearAccessToken(); + std::cout << "After second clearAccessToken() " << std::endl; + + std::cout << "Exiting Repeated_calls_to_clearAccessToken test" << std::endl; +} +/** + * @brief Test to validate that the clearDrmSession method operates correctly when forceClearSession is set to false. + * + * This test verifies that invoking clearDrmSession with forceClearSession explicitly set to false correctly clears the DRM session under + * normal conditions and processes failed keys per standard procedures. It confirms that the DrmSessionManager is properly instantiated and + * that the method executes without forcing an explicit session clear. + * + * **Test Group ID:** Basic: 01@n + * **Test Case ID:** 048@n + * **Priority:** High@n + * + * **Pre-Conditions:** None@n + * **Dependencies:** None@n + * **User Interaction:** None@n + * + * **Test Procedure:** + * | Variation / Step | Description | Test Data | Expected Result | Notes | + * | :--------------: | -------------------------------------------------------------------------------------------- | ----------------------------------------------------- | --------------------------------------------------------------------------------------- | --------------- | + * | 01 | Create DrmSessionManager object using custom constructor with dummy parameters. | maxDrmSessions = 5, player = nullptr | DrmSessionManager object is successfully instantiated. | Should be successful | + * | 02 | Invoke clearDrmSession with forceClearSession parameter set to false. | forceClearSession = false | The clearDrmSession method executes clearing the DRM session under normal conditions. | Should Pass | + * | 03 | Log the execution state to verify that internal state changes are correctly simulated. | forceClearSession = false | Log indicates that DRM session cleared normally and failed keys handled per standard. | Should be successful | + */ +TEST(DrmSessionManager, ClearDRMSessionForceFalse) +{ + std::cout << "Entering ClearDRMSessionForceFalse test" << std::endl; + + // Create DrmSessionManager object using custom constructor with dummy parameters (e.g., maxDrmSessions = 5 and player = nullptr) + DrmSessionManager drmManager(5, nullptr); + std::cout << "Created DrmSessionManager object with maxDrmSessions=5 and player=nullptr" << std::endl; + + // Log the invocation and the explicit value passed to clearDrmSession (forceClearSession = false) + bool forceClear = false; + std::cout << "Invoking clearDrmSession(forceClearSession = " << (forceClear ? "true" : "false") << ")" << std::endl; + + drmManager.clearDrmSession(forceClear); + + std::cout << "Method clearDrmSession(forceClearSession = false) executed"<< std::endl; + + std::cout << "Exiting ClearDRMSessionForceFalse test" << std::endl; +} +/** + * @brief Verify that clearDrmSession clears DRM session when forceClear is true + * + * This test verifies the behavior of DrmSessionManager::clearDrmSession when invoked with forceClearSession set to true. It ensures that the DRM session is cleared irrespective of the existence of failed keys and that the internal state is reset accordingly. + * + * **Test Group ID:** Basic: 01@n + * **Test Case ID:** 049@n + * **Priority:** High@n + * + * **Pre-Conditions:** None@n + * **Dependencies:** None@n + * **User Interaction:** None@n + * + * **Test Procedure:**@n + * | Variation / Step | Description | Test Data | Expected Result | Notes | + * | :----: | --------- | ---------- |-------------- | ----- | + * | 01 | Create DrmSessionManager object with dummy parameters maxDrmSessions = 5 and player = nullptr | input1 = maxDrmSessions 5, input2 = player nullptr | Object is created successfully | Should be successful | + * | 02 | Log the test entry message | No parameters | Console logs "Entering ClearDRMSessionForceTrue test" | Should be successful | + * | 03 | Set forceClear flag to true and log invoking message | forceClear = true | Console logs "Invoking clearDrmSession(forceClearSession = true)" | Should Pass | + * | 04 | Call clearDrmSession with forceClear flag | function argument: forceClear = true | clearDrmSession executes and resets internal state | Should Pass | + * | 05 | Log internal state simulation after method execution | No parameters | Console logs message indicating DRM session cleared and internal state reset | Should be successful | + * | 06 | Log the test exit message | No parameters | Console logs "Exiting ClearDRMSessionForceTrue test" | Should be successful | + */ +TEST(DrmSessionManager, ClearDRMSessionForceTrue) +{ + std::cout << "Entering ClearDRMSessionForceTrue test" << std::endl; + + // Create DrmSessionManager object using custom constructor with dummy parameters (e.g., maxDrmSessions = 5 and player = nullptr) + DrmSessionManager drmManager(5, nullptr); + std::cout << "Created DrmSessionManager object with maxDrmSessions=5 and player=nullptr" << std::endl; + + // Log the invocation and the explicit value passed to clearDrmSession (forceClearSession = true) + bool forceClear = true; + std::cout << "Invoking clearDrmSession(forceClearSession = " << (forceClear ? "true" : "false") << ")" << std::endl; + + drmManager.clearDrmSession(forceClear); + + // Log internal state simulation (printing expected internal state changes) + std::cout << "Method clearDrmSession(forceClearSession = true) executed" << std::endl; + + std::cout << "Exiting ClearDRMSessionForceTrue test" << std::endl; +} +/** + * @brief Test clearFailedKeyIds on a DrmSessionManager instance with no failed keys. + * + * This test verifies that calling clearFailedKeyIds on a freshly instantiated DrmSessionManager (with no prior failed key IDs) + * executes successfully without throwing exceptions and that the internal container tracking failed key IDs remains empty. + * + * **Test Group ID:** Basic: 01@n + * **Test Case ID:** 050@n + * **Priority:** High@n + * + * **Pre-Conditions:** None@n + * **Dependencies:** None@n + * **User Interaction:** None@n + * + * **Test Procedure:** + * | Variation / Step | Description | Test Data | Expected Result | Notes | + * | :----: | ----------- | --------- | --------------- | ----- | + * | 01 | Create an instance of DrmSessionManager using the custom constructor with dummy values. | maxDrmSessions = 5, player = 0x1234 | Instance is created successfully. | Should be successful | + * | 02 | Invoke clearFailedKeyIds and log the invocation to verify the API is called. | None | clearFailedKeyIds() executes without throwing exceptions. | Should Pass | + * | 03 | Verify that the internal container for failed key IDs is empty by checking the logged state. | None | Internal failed key IDs container remains empty. | Should be successful | + */ +TEST(DrmSessionManager, clearFailedKeyIds_noFailedKeys) { + std::cout << "Entering clearFailedKeyIds_noFailedKeys test" << std::endl; + + // Create an instance of DrmSessionManager using the custom constructor. + // Using dummy values: maxDrmSessions = 5, and a dummy pointer for player. + void* dummyPlayer = reinterpret_cast(0x1234); + DrmSessionManager drmSessionManager(5, dummyPlayer); + std::cout << "Created DrmSessionManager with maxDrmSessions = 5 and player = " + << dummyPlayer << std::endl; + + // Log invocation of clearFailedKeyIds + std::cout << "Invoking clearFailedKeyIds()" << std::endl; + // Call clearFailedKeyIds and expect no exceptions. + EXPECT_NO_THROW({ + drmSessionManager.clearFailedKeyIds(); + std::cout << "clearFailedKeyIds() returned successfully" << std::endl; + }); + + // Print an internal state status (assuming internal failed key IDs container is empty) + std::cout << "After invocation, internal failed key IDs container is expected to be empty" + << std::endl; + + std::cout << "Exiting clearFailedKeyIds_noFailedKeys test" << std::endl; +} +/** + * @brief Test the idempotency of the clearFailedKeyIds function in DrmSessionManager + * + * This test case verifies that calling clearFailedKeyIds multiple times does not lead to unexpected behavior and that the internal container remains empty after consecutive calls. + * + * **Test Group ID:** Basic: 01@n + * **Test Case ID:** 051@n + * **Priority:** High@n + * + * **Pre-Conditions:** None@n + * **Dependencies:** None@n + * **User Interaction:** None@n + * + * **Test Procedure:** + * | Variation / Step | Description | Test Data | Expected Result | Notes | + * | :----: | --------- | ---------- |-------------- | ----- | + * | 01 | Create a DrmSessionManager instance using dummy values. | maxDrmSessions = 10, player = 0x5678 | Instance created successfully with the provided parameters. | Should be successful | + * | 02 | Invoke the first call to clearFailedKeyIds() on the DrmSessionManager instance. | No input arguments, output: internal failed key IDs container | No exception is thrown and the internal container is cleared (empty). | Should Pass | + * | 03 | Invoke the second call to clearFailedKeyIds() to verify idempotency. | No input arguments, output: internal failed key IDs container remains unchanged | No exception is thrown and the internal container remains empty, confirming idempotency. | Should Pass | + */ +TEST(DrmSessionManager, clearFailedKeyIds_Idempotency) { + std::cout << "Entering clearFailedKeyIds_Idempotency test" << std::endl; + + // Create an instance of DrmSessionManager using the custom constructor. + // Using dummy values: maxDrmSessions = 10, and a dummy pointer for player. + void* dummyPlayer = reinterpret_cast(0x5678); + DrmSessionManager drmSessionManager(10, dummyPlayer); + std::cout << "Created DrmSessionManager with maxDrmSessions = 10 and player = " + << dummyPlayer << std::endl; + + // First invocation of clearFailedKeyIds + std::cout << "Invoking first clearFailedKeyIds() call" << std::endl; + EXPECT_NO_THROW({ + drmSessionManager.clearFailedKeyIds(); + std::cout << "First clearFailedKeyIds() call returned successfully" << std::endl; + }); + std::cout << "After first call, internal failed key IDs container is expected to be empty" + << std::endl; + + // Second invocation of clearFailedKeyIds to verify idempotency + std::cout << "Invoking second clearFailedKeyIds() call" << std::endl; + EXPECT_NO_THROW({ + drmSessionManager.clearFailedKeyIds(); + std::cout << "Second clearFailedKeyIds() call returned successfully" << std::endl; + }); + std::cout << "After second call, internal failed key IDs container remains empty, verifying idempotency" + << std::endl; + + std::cout << "Exiting clearFailedKeyIds_Idempotency test" << std::endl; +} +/** + * @brief Verify that clearSessionData() resets DRM session data for a new instance. + * + * This test creates a new instance of DrmSessionManager with specific initial parameters, + * prints its initial state, invokes clearSessionData(), and then verifies via assertions that + * the internal DRM session data (pointers and custom data) have been properly reset. + * + * **Test Group ID:** Basic: 01@n + * **Test Case ID:** 052@n + * **Priority:** High@n + * + * **Pre-Conditions:** None@n + * **Dependencies:** None@n + * **User Interaction:** None@n + * + * **Test Procedure:**@n + * | Variation / Step | Description | Test Data | Expected Result | Notes | + * | :--------------: | ------------------------------------------------------------------------------------------- | --------------------------------------------------------------- | -------------------------------------------------------------------------------------------------------- | --------------- | + * | 01 | Instantiate DrmSessionManager with maxDrmSessions = 5 and player = nullptr | maxDrmSessions = 5, player = nullptr | New instance created with initial values | Should be successful | + * | 02 | Print initial public state values of the manager | drmSessionContexts = initial value, m_drmConfigParam = initial value, playerSecInstance = initial value, mCustomData = initial value | Initial state logged to console | Should be successful | + * | 03 | Invoke clearSessionData() to reset the DRM session data | Method invocation: clearSessionData() | Method executes and resets internal DRM session data | Should Pass | + * | 04 | Print state values after clearSessionData() is called | Updated state values after clearSessionData() invocation | Console output shows cleared pointers and empty mCustomData | Should be successful | + * | 05 | Verify internal DRM session data is reset using assertions | EXPECT_EQ for drmSessionContexts, m_drmConfigParam, playerSecInstance; EXPECT_TRUE for mCustomData.empty() | drmSessionContexts, m_drmConfigParam, and playerSecInstance are nullptr; mCustomData is empty; assertions pass | Should Pass | + */ +TEST(DrmSessionManager, ClearSessionData_NewInstance) { + std::cout << "Entering ClearSessionData_NewInstance test" << std::endl; + + // Create an instance of DrmSessionManager using the custom constructor. + // Using maxDrmSessions = 5 and player = nullptr. + DrmSessionManager manager(5, nullptr); + + // Debug: Print initial public state values. + std::cout << "Initial drmSessionContexts: " << manager.drmSessionContexts << std::endl; + std::cout << "Initial m_drmConfigParam: " << manager.m_drmConfigParam << std::endl; + std::cout << "Initial playerSecInstance: " << manager.playerSecInstance << std::endl; + std::cout << "Initial mCustomData: " << manager.mCustomData << std::endl; + + // Log the method invocation. + std::cout << "Invoking clearSessionData()" << std::endl; + manager.clearSessionData(); + std::cout << "clearSessionData() invoked" << std::endl; + + // Debug: Print state values after clearSessionData is called. + std::cout << "Post-clear drmSessionContexts: " << manager.drmSessionContexts << std::endl; + std::cout << "Post-clear m_drmConfigParam: " << manager.m_drmConfigParam << std::endl; + std::cout << "Post-clear playerSecInstance: " << manager.playerSecInstance << std::endl; + std::cout << "Post-clear mCustomData: " << manager.mCustomData << std::endl; + + // Verify that the internal DRM session data has been reset. + // Assuming the reset state implies that pointers are set to nullptr and custom data is cleared. + EXPECT_EQ(manager.drmSessionContexts, nullptr); + EXPECT_EQ(manager.m_drmConfigParam, nullptr); + EXPECT_EQ(manager.playerSecInstance, nullptr); + EXPECT_TRUE(manager.mCustomData.empty()); + + std::cout << "Exiting ClearSessionData_NewInstance test" << std::endl; +} +/** + * @brief Verify that multiple calls to clearSessionData do not alter the cleared state of the DrmSessionManager + * + * This test validates that invoking clearSessionData() on the DrmSessionManager more than once preserves the state + * that was achieved after the first invocation. It ensures that subsequent calls do not inadvertently modify + * the already cleared state of the internal session data. + * + * **Test Group ID:** Basic: 01@n + * **Test Case ID:** 053@n + * **Priority:** High@n + * + * **Pre-Conditions:** None@n + * **Dependencies:** None@n + * **User Interaction:** None@n + * + * **Test Procedure:** + * | Variation / Step | Description | Test Data | Expected Result | Notes | + * | :--------------: | ----------------------------------------------------------------------------------------------- | ---------------------------------------------------------------- | -------------------------------------------------------------------------------------------------------------------------------------- | --------------- | + * | 01 | Instantiate DrmSessionManager with valid parameters | input1 = 5, input2 = nullptr | Instance created with initial state values correctly set | Should be successful | + * | 02 | Invoke clearSessionData() for the first time | Method = clearSessionData() first call | The session data is cleared and the state is updated accordingly | Should Pass | + * | 03 | Capture the state after the first call | Captured state from drmSessionContexts, m_drmConfigParam, playerSecInstance, mCustomData | State captured and stored for later comparison | Should be successful | + * | 04 | Invoke clearSessionData() for the second time | Method = clearSessionData() second call | The state remains unchanged from the first call (subsequent calls do not modify the cleared state) | Should Pass | + * | 05 | Validate that the state remains unchanged after the second call | Compared captured state with current state values | EXPECT_EQ assertion passes confirming that subsequent calls did not alter the state | Should be successful | + */ +TEST(DrmSessionManager, ClearSessionData_MultipleCalls) { + std::cout << "Entering ClearSessionData_MultipleCalls test" << std::endl; + + // Create an instance of DrmSessionManager using the custom constructor. + DrmSessionManager manager(5, nullptr); + + // Debug: Print initial public state values. + std::cout << "Initial drmSessionContexts: " << manager.drmSessionContexts << std::endl; + std::cout << "Initial m_drmConfigParam: " << manager.m_drmConfigParam << std::endl; + std::cout << "Initial playerSecInstance: " << manager.playerSecInstance << std::endl; + std::cout << "Initial mCustomData: " << manager.mCustomData << std::endl; + + // First call to clearSessionData. + std::cout << "Invoking clearSessionData() first call" << std::endl; + manager.clearSessionData(); + std::cout << "clearSessionData() first call invoked" << std::endl; + + // Capture state after the first call. + auto state_drmSessionContexts = manager.drmSessionContexts; + auto state_m_drmConfigParam = manager.m_drmConfigParam; + auto state_playerSecInstance = manager.playerSecInstance; + auto state_mCustomData = manager.mCustomData; + + std::cout << "State after first call - drmSessionContexts: " << state_drmSessionContexts << std::endl; + std::cout << "State after first call - m_drmConfigParam: " << state_m_drmConfigParam << std::endl; + std::cout << "State after first call - playerSecInstance: " << state_playerSecInstance << std::endl; + std::cout << "State after first call - mCustomData: " << state_mCustomData << std::endl; + + // Second call to clearSessionData. + std::cout << "Invoking clearSessionData() second call" << std::endl; + manager.clearSessionData(); + std::cout << "clearSessionData() second call invoked" << std::endl; + + // Debug: Print state values after the second call. + std::cout << "Post-second call - drmSessionContexts: " << manager.drmSessionContexts << std::endl; + std::cout << "Post-second call - m_drmConfigParam: " << manager.m_drmConfigParam << std::endl; + std::cout << "Post-second call - playerSecInstance: " << manager.playerSecInstance << std::endl; + std::cout << "Post-second call - mCustomData: " << manager.mCustomData << std::endl; + + // Verify that subsequent calls do not alter the cleared state. + EXPECT_EQ(manager.drmSessionContexts, state_drmSessionContexts); + EXPECT_EQ(manager.m_drmConfigParam, state_m_drmConfigParam); + EXPECT_EQ(manager.playerSecInstance, state_playerSecInstance); + EXPECT_EQ(manager.mCustomData, state_mCustomData); + + std::cout << "Exiting ClearSessionData_MultipleCalls test" << std::endl; +} + +/** + * @brief Validate functionality of valid DrmSession creation + * + * This test case validates that the createDrmSession API successfully creates a DRM session when provided with valid input values. The test ensures that the API returns a non-null DRM session pointer and that the error value is set to 0. + * + * **Test Group ID:** Basic: 01@n + * **Test Case ID:** 054@n + * **Priority:** High@n + * + * **Pre-Conditions:** None@n + * **Dependencies:** None@n + * **User Interaction:** None@n + * + * **Test Procedure:** + * | Variation / Step | Description | Test Data | Expected Result |Notes | + * | :----: | --------- | ---------- |-------------- | ----- | + * | 01 | Initialize test variables with dummy valid data for pointers and integer values. | err = -1, drmHelper pointer = non-null (0x1), drmCallbacks pointer = non-null (0x1), streamType = 1, metaDataPtr = address of metaDataValue (123) | All test variables are initialized with dummy valid values. | Should be successful | + * | 02 | Create DrmSessionManager object using a custom constructor. | maxDrmSessions = 5, player = nullptr | DrmSessionManager object is created successfully. | Should Pass | + * | 03 | Invoke createDrmSession API with the prepared valid input values. | err initial: -1, drmHelper pointer: valid, drmCallbacks pointer: valid, streamType = 1, metaDataPtr = valid | Returns a non-null session pointer and updates err to 0. | Should Pass | + * | 04 | Validate the outputs using assertions. | EXPECT_NE(session, nullptr), EXPECT_EQ(err, 0) | Assertions pass confirming the correct session creation and error code update. | Should Pass | + */ +TEST(DrmSessionManager, ValidDrmSessionCreation) { + std::cout << "Entering ValidDrmSessionCreation test" << std::endl; + + int err = -1; + // Creating a valid DrmHelperPtr + std::shared_ptr drmHelper = std::make_shared(); + + // Creating a valid DrmCallbacks pointer + DrmCallbacks drmCallbacksInstance; + DrmCallbacks* drmCallbacksPtr = &drmCallbacks; + int streamType = 1; + + // Prepare metaData with some dummy valid data. + int metaDataValue = 123; + void* metaDataPtr = &metaDataValue; + + // Log input values. + std::cout << "Invoking createDrmSession with:" << std::endl; + std::cout << " err initial: " << err << std::endl; + std::cout << " drmHelper pointer: " << drmHelper.get() << std::endl; + std::cout << " drmCallbacks pointer: " << drmCallbacksPtr << std::endl; + std::cout << " streamType: " << streamType << std::endl; + std::cout << " metaDataPtr: " << metaDataPtr << std::endl; + + // Create DrmSessionManager object with a custom constructor. + DrmSessionManager manager(5, nullptr); + std::cout << "DrmSessionManager object created with maxDrmSessions=5 and player=nullptr" << std::endl; + + // Invoke the method under test. + DrmSession* session = manager.createDrmSession(err, drmHelper, drmCallbacksPtr, streamType, metaDataPtr); + std::cout << "Method createDrmSession returned pointer: " << session << std::endl; + std::cout << "Value of err after invocation: " << err << std::endl; + + // Validate expected outputs. + EXPECT_NE(session, nullptr); + EXPECT_EQ(err, 0); + + std::cout << "Exiting ValidDrmSessionCreation test" << std::endl; +} +/** + * @brief Verify the behavior of createDrmSession when provided with a null DrmHelper pointer. + * + * This test ensures that when the API createDrmSession is invoked with a null DrmHelper pointer, + * it returns a null session pointer and updates the error code to a non-zero value as expected. + * + * **Test Group ID:** Basic: 01 + * **Test Case ID:** 055 + * **Priority:** High + * + * **Pre-Conditions:** None + * **Dependencies:** None + * **User Interaction:** None + * + * **Test Procedure:** + * | Variation / Step | Description | Test Data | Expected Result | Notes | + * | :--------------: | --------------------------------------------------------------------------- | -------------------------------------------------------------------------- | ---------------------------------------------- | ---------- | + * | 01 | Call createDrmSession with a null DrmHelper pointer and valid DrmCallbacks | err = -1, drmHelper = nullptr, drmCallbacks = 0x1, streamType = 1, metaDataPtr = metaDataValue:456 | Returns nullptr session and err != 0 | Should Fail | + */ +TEST(DrmSessionManager, NullDrmHelperPointer) { + std::cout << "Entering NullDrmHelperPointer test" << std::endl; + + int err = -1; + // Provide null drmHelper pointer. + std::shared_ptr drmHelper(nullptr); + // Creating a valid DrmCallbacks pointer + DrmCallbacks drmCallbacksInstance; + DrmCallbacks* drmCallbacksPtr = &drmCallbacks; + int streamType = 1; + + int metaDataValue = 456; + void* metaDataPtr = &metaDataValue; + + std::cout << "Invoking createDrmSession with:" << std::endl; + std::cout << " err initial: " << err << std::endl; + std::cout << " drmHelper pointer: " << drmHelper.get() << " (expected nullptr)" << std::endl; + std::cout << " drmCallbacks pointer: " << drmCallbacksPtr << std::endl; + std::cout << " streamType: " << streamType << std::endl; + std::cout << " metaDataPtr: " << metaDataPtr << std::endl; + + DrmSessionManager manager(5, nullptr); + std::cout << "DrmSessionManager object created." << std::endl; + + DrmSession* session = manager.createDrmSession(err, drmHelper, drmCallbacksPtr, streamType, metaDataPtr); + std::cout << "Method createDrmSession returned pointer: " << session << std::endl; + std::cout << "Value of err after invocation: " << err << std::endl; + + EXPECT_EQ(session, nullptr); + EXPECT_NE(err, 0); + + std::cout << "Exiting NullDrmHelperPointer test" << std::endl; +} +/** + * @brief Verifies that createDrmSession fails when a null DrmCallbacks pointer is provided. + * + * This test provides a valid DrmHelper pointer along with a null DrmCallbacks pointer while invoking the createDrmSession API. + * The objective of the test is to ensure that the API returns a nullptr session and updates the error code when an invalid (null) DrmCallbacks pointer is used. + * + * **Test Group ID:** Basic: 01@n + * **Test Case ID:** 056@n + * **Priority:** High@n + * + * **Pre-Conditions:** None@n + * **Dependencies:** None@n + * **User Interaction:** None@n + * + * **Test Procedure:**@n + * | Variation / Step | Description | Test Data | Expected Result | Notes | + * | :----: | --------- | ---------- |-------------- | ----- | + * | 01 | Initialize parameters including a valid DrmHelper pointer, a null DrmCallbacks pointer, and invoke createDrmSession API. | err = -1, drmHelper = valid pointer (0x1), drmCallbacks = nullptr, streamType = 1, metaDataPtr = address of metaDataValue (789) | The API should return a nullptr session and err should be updated to a non-zero value. | Should Fail | + */ +TEST(DrmSessionManager, NullDrmCallbacksInstance) { + std::cout << "Entering NullDrmCallbacksInstance test" << std::endl; + + int err = -1; + // Provide valid drmHelper pointer. + std::shared_ptr drmHelper = std::make_shared(); + // Provide null pointer for DrmCallbacks. + DrmCallbacks* drmCallbacks = nullptr; + int streamType = 1; + + int metaDataValue = 789; + void* metaDataPtr = &metaDataValue; + + std::cout << "Invoking createDrmSession with:" << std::endl; + std::cout << " err initial: " << err << std::endl; + std::cout << " drmHelper pointer: " << drmHelper.get() << std::endl; + std::cout << " drmCallbacks pointer: " << drmCallbacks << " (expected nullptr)" << std::endl; + std::cout << " streamType: " << streamType << std::endl; + std::cout << " metaDataPtr: " << metaDataPtr << std::endl; + + DrmSessionManager manager(5, nullptr); + std::cout << "DrmSessionManager object created." << std::endl; + + DrmSession* session = manager.createDrmSession(err, drmHelper, drmCallbacks, streamType, metaDataPtr); + std::cout << "Method createDrmSession returned pointer: " << session << std::endl; + std::cout << "Value of err after invocation: " << err << std::endl; + + EXPECT_EQ(session, nullptr); + EXPECT_NE(err, 0); + + std::cout << "Exiting NullDrmCallbacksInstance test" << std::endl; +} +/** + * @brief Verify that createDrmSession correctly handles a null metaDataPtr. + * + * This test verifies that when a null metaDataPtr is provided to the createDrmSession API, the function returns a nullptr for the session and sets the error code to a non-zero value. Ensuring correct operation using a null metaDataPtr is critical for guarding against invalid memory access and ensuring robust error handling. + * + * **Test Group ID:** Basic: 01@n + * **Test Case ID:** 057@n + * **Priority:** High@n + * + * **Pre-Conditions:** None@n + * **Dependencies:** None@n + * **User Interaction:** None@n + * + * **Test Procedure:** + * | Variation / Step | Description | Test Data | Expected Result | Notes | + * | :--------------: | --------------------------------------------------------------------------------------------------- | -------------------------------------------------------------------- | -------------------------------------------------------------- | ------------- | + * | 01 | Setup test variables and invoke createDrmSession with a null metaDataPtr | err = -1, drmHelper = reinterpret_cast(0x1), drmCallbacks = reinterpret_cast(0x1), streamType = 1, metaDataPtr = nullptr | Returned session is nullptr and err is non-zero | Should Pass | + */ +TEST(DrmSessionManager, NullMetaDataPtr) { + std::cout << "Entering NullMetaDataPtr test" << std::endl; + + int err = -1; + // Creating a valid DrmHelperPtr + std::shared_ptr drmHelper = std::make_shared(); + // Creating a valid DrmCallbacks pointer + DrmCallbacks drmCallbacksInstance; + DrmCallbacks* drmCallbacksPtr = &drmCallbacks; + int streamType = 1; + + // Provide null metaDataPtr. + void* metaDataPtr = nullptr; + + std::cout << "Invoking createDrmSession with:" << std::endl; + std::cout << " err initial: " << err << std::endl; + std::cout << " drmHelper pointer: " << drmHelper.get() << std::endl; + std::cout << " drmCallbacks pointer: " << drmCallbacksPtr << std::endl; + std::cout << " streamType: " << streamType << std::endl; + std::cout << " metaDataPtr: " << metaDataPtr << " (expected nullptr)" << std::endl; + + DrmSessionManager manager(5, nullptr); + std::cout << "DrmSessionManager object created." << std::endl; + + DrmSession* session = manager.createDrmSession(err, drmHelper, drmCallbacksPtr, streamType, metaDataPtr); + std::cout << "Method createDrmSession returned pointer: " << session << std::endl; + std::cout << "Value of err after invocation: " << err << std::endl; + + EXPECT_EQ(session, nullptr); + EXPECT_NE(err, 0); + + std::cout << "Exiting NullMetaDataPtr test" << std::endl; +} +/** + * @brief Test the behavior of createDrmSession with an invalid negative stream type. + * + * This test validates that the DrmSessionManager::createDrmSession method properly handles an invalid negative stream type. It ensures that the API returns a nullptr for the session and sets the error value to a non-zero value, indicating failure. + * + * **Test Group ID:** Basic: 01@n + * **Test Case ID:** 058@n + * **Priority:** High@n + * + * **Pre-Conditions:** None@n + * **Dependencies:** None@n + * **User Interaction:** None@n + * + * **Test Procedure:** + * | Variation / Step | Description | Test Data | Expected Result | Notes | + * | :----: | --------- | ---------- |-------------- | ----- | + * | 01 | Initialize test variables and pointers with invalid stream type and metadata. | err = -1, drmHelper pointer = 0x1, drmCallbacks pointer = 0x1, streamType = -1, metaDataValue = 321, metaDataPtr = address of metaDataValue | Variables are initialized as expected before invoking the API | Should be successful | + * | 02 | Create DrmSessionManager and invoke createDrmSession with the above inputs. | manager constructed with (5, nullptr); Function call with: err, drmHelper, drmCallbacks, streamType, metaDataPtr | Returned session pointer is nullptr and err is non-zero after the call | Should Fail | + */ +TEST(DrmSessionManager, InvalidStreamType) { + std::cout << "Entering InvalidStreamType test" << std::endl; + + int err = -1; + // Creating a valid DrmHelperPtr + std::shared_ptr drmHelper = std::make_shared(); + // Creating a valid DrmCallbacks pointer + DrmCallbacks drmCallbacksInstance; + DrmCallbacks* drmCallbacksPtr = &drmCallbacks; + // Use an invalid negative streamType. + int streamType = -1; + + int metaDataValue = 321; + void* metaDataPtr = &metaDataValue; + + std::cout << "Invoking createDrmSession with:" << std::endl; + std::cout << " err initial: " << err << std::endl; + std::cout << " drmHelper pointer: " << drmHelper.get() << std::endl; + std::cout << " drmCallbacks pointer: " << drmCallbacks << std::endl; + std::cout << " streamType: " << streamType << " (expected negative)" << std::endl; + std::cout << " metaDataPtr: " << metaDataPtr << std::endl; + + DrmSessionManager manager(5, nullptr); + std::cout << "DrmSessionManager object created." << std::endl; + + DrmSession* session = manager.createDrmSession(err, drmHelper, drmCallbacksPtr, streamType, metaDataPtr); + std::cout << "Method createDrmSession returned pointer: " << session << std::endl; + std::cout << "Value of err after invocation: " << err << std::endl; + + EXPECT_EQ(session, nullptr); + EXPECT_NE(err, 0); + + std::cout << "Exiting InvalidStreamType test" << std::endl; +} +/** + * @brief Validates retrieval of a valid access token from DrmSessionManager with SSL peer verification enabled. + * + * This test case verifies that the getAccessToken API in DrmSessionManager returns a non-null access token while + * updating the token length to a positive value and setting the error code to 0 when SSL peer verification is enabled. + * Ensuring that these conditions are met indicates that the access token retrieval mechanism functions correctly. + * + * **Test Group ID:** Basic: 01@n + * **Test Case ID:** 059@n + * **Priority:** High@n + * + * **Pre-Conditions:** None@n + * **Dependencies:** None@n + * **User Interaction:** None@n + * + * **Test Procedure:** + * | Variation / Step | Description | Test Data | Expected Result | Notes | + * | :--------------: | ---------------------------------------------------------------- | --------------------------------------------------------------- | --------------------------------------------------------- | -------------- | + * | 01 | Create DrmSessionManager object with maxDrmSessions = 5 and player set to nullptr | maxDrmSessions = 5, player = nullptr | Object instantiated successfully | Should be successful | + * | 02 | Initialize output parameters before API invocation | tokenLength = 0, error_code = -1, bSslPeerVerify = true | Output parameters are initialized correctly | Should be successful | + * | 03 | Invoke getAccessToken API and verify return values | bSslPeerVerify = true, tokenLength initially=0, error_code initially=-1 | Access token is not null, tokenLength > 0, error_code equals 0 | Should Pass | + */ +TEST(DrmSessionManager, ValidAccessTokenRetrievalWithSslPeerVerifyEnabled) { + std::cout << "Entering ValidAccessTokenRetrievalWithSslPeerVerifyEnabled test" << std::endl; + + // Create object of DrmSessionManager using a custom constructor (maxDrmSessions set to 5, player passed as nullptr) + std::cout << "Creating DrmSessionManager object with maxDrmSessions = 5 and player = nullptr" << std::endl; + DrmSessionManager drmManager(5, nullptr); + + // Prepare output parameters + int tokenLength = 0; + int error_code = -1; + bool bSslPeerVerify = true; + + std::cout << "Before invocation: tokenLength = " << tokenLength + << ", error_code = " << error_code + << ", bSslPeerVerify = " << std::boolalpha << bSslPeerVerify << std::endl; + + // Invoke the getAccessToken method + std::cout << "Invoking getAccessToken with bSslPeerVerify = true" << std::endl; + const char* accessToken = drmManager.getAccessToken(tokenLength, error_code, bSslPeerVerify); + + // Debug logs of outputs + std::cout << "Returned accessToken pointer = " << static_cast(accessToken) << std::endl; + std::cout << "Updated tokenLength = " << tokenLength << std::endl; + std::cout << "Updated error_code = " << error_code << std::endl; + + // Check the access token is not null + EXPECT_NE(nullptr, accessToken); + // Check that tokenLength is greater than 0 + EXPECT_GT(tokenLength, 0); + // Check that error_code is 0 + EXPECT_EQ(0, error_code); + + std::cout << "Exiting ValidAccessTokenRetrievalWithSslPeerVerifyEnabled test" << std::endl; +} +/** + * @brief Validate retrieval of a valid access token when SSL peer verification is disabled + * + * This test validates that the DrmSessionManager properly initializes and returns a valid access token when invoked with SSL peer verification disabled. It ensures that the returned token pointer is not null, the token length is positive, and the error code is zero, indicating a successful API execution. + * + * **Test Group ID:** Basic: 01@n + * **Test Case ID:** 060@n + * **Priority:** High@n + * + * **Pre-Conditions:** None@n + * **Dependencies:** None@n + * **User Interaction:** None@n + * + * **Test Procedure:**@n + * | Variation / Step | Description | Test Data | Expected Result | Notes | + * | :--------------: | ---------------------------------------------------------------------------------------- | --------------------------------------------------------------- | ------------------------------------------------------------------------------- | ------------ | + * | 01 | Create DrmSessionManager object using custom constructor | maxDrmSessions = 5, player = nullptr | Object is created successfully without errors | Should be successful | + * | 02 | Invoke getAccessToken with bSslPeerVerify set to false | tokenLength = 0, error_code = -1, bSslPeerVerify = false | Returns a non-null access token pointer, tokenLength > 0, error_code == 0 | Should Pass | + */ +TEST(DrmSessionManager, ValidAccessTokenRetrievalWithSslPeerVerifyDisabled) { + std::cout << "Entering ValidAccessTokenRetrievalWithSslPeerVerifyDisabled test" << std::endl; + + // Create object of DrmSessionManager using a custom constructor (maxDrmSessions set to 5, player passed as nullptr) + std::cout << "Creating DrmSessionManager object with maxDrmSessions = 5 and player = nullptr" << std::endl; + DrmSessionManager drmManager(5, nullptr); + + // Prepare output parameters + int tokenLength = 0; + int error_code = -1; + bool bSslPeerVerify = false; + + std::cout << "Before invocation: tokenLength = " << tokenLength + << ", error_code = " << error_code + << ", bSslPeerVerify = " << std::boolalpha << bSslPeerVerify << std::endl; + + // Invoke the getAccessToken method + std::cout << "Invoking getAccessToken with bSslPeerVerify = false" << std::endl; + const char* accessToken = drmManager.getAccessToken(tokenLength, error_code, bSslPeerVerify); + + // Debug logs of outputs + std::cout << "Returned accessToken pointer = " << static_cast(accessToken) << std::endl; + std::cout << "Updated tokenLength = " << tokenLength << std::endl; + std::cout << "Updated error_code = " << error_code << std::endl; + + // Check the access token is not null + EXPECT_NE(nullptr, accessToken); + // Check that tokenLength is greater than 0 + EXPECT_GT(tokenLength, 0); + // Check that error_code is 0 + EXPECT_EQ(0, error_code); + + std::cout << "Exiting ValidAccessTokenRetrievalWithSslPeerVerifyDisabled test" << std::endl; +} +/** + * @brief Test that verifies getDrmSession when invoked as a primary session returns expected key states. + * + * This test checks the behavior of the DrmSessionManager's getDrmSession method when it is run as + * the primary session. The method is expected to process a valid DrmHelper, output proper key states + * and update error/status values during processing. + * + * **Test Group ID:** Basic: 01@n + * **Test Case ID:** 061@n + * **Priority:** High@n + * + * **Pre-Conditions:** None@n + * **Dependencies:** None@n + * **User Interaction:** None@n + * + * **Test Procedure:**@n + * | Variation / Step | Description | Test Data | Expected Result | Notes | + * | :----: | --------- | ---------- |-------------- | ----- | + * | 01 | Initialize test inputs and print initial state. | err = 0, selectedSlot = 2 | Correct initialization of error and selected slot printed | Should be successful | + * | 02 | Create a valid DrmHelper instance used for DRM operations. | drmHelper instance created | DrmHelper instance should be valid | Should Pass | + * | 03 | Create a valid DummyDrmCallbacks instance derived from DrmCallbacks. | dummyCallback instance created | DummyDrmCallbacks instance should be valid | Should Pass | + * | 04 | Instantiate DrmSessionManager with a given constructor argument. | drmSessionManager constructed with (5, nullptr) | DrmSessionManager instance should be created successfully | Should Pass | + * | 05 | Invoke getDrmSession method with isPrimarySession = true and valid inputs. | err, drmHelper, selectedSlot, pCallback, isPrimarySession = true | getDrmSession returns one of the valid states: KEY_INIT, KEY_PENDING, KEY_READY, KEY_CLOSED, or KEY_ERROR_EMPTY_SESSION_ID; error output values updated accordingly | Should Pass | + * | 06 | Validate the returned key state using EXPECT_TRUE assertion. | Returned keyState compared with acceptable values | Assertion passes if returned keyState is valid | Should Pass | + */ +TEST(DrmSessionManager, PositivePrimary) { + std::cout << "Entering PositivePrimary test" << std::endl; + + // Prepare input variables + int err = 0; + int selectedSlot = 2; + std::cout << "PositivePrimaryInitial err: " << err << ", selectedSlot: " << selectedSlot << std::endl; + + // Create a valid DrmHelper instance + std::cout << "Creating valid DrmHelper instance" << std::endl; + DrmHelperPtr drmHelper = std::make_shared(); + + // Creating a valid DrmCallbacks pointer + DrmCallbacks drmCallbacksInstance; + DrmCallbacks* drmCallbacksPtr = &drmCallbacks; + + // Create DrmSessionManager object using custom constructor + std::cout << "Creating DrmSessionManager instance" << std::endl; + DrmSessionManager drmSessionManager(5, nullptr); + + // Invoke the method with isPrimarySession = true + std::cout << "Invoking getDrmSession with isPrimarySession = true" << std::endl; + KeyState keyState = drmSessionManager.getDrmSession(err, drmHelper, selectedSlot, drmCallbacksPtr, true); + std::cout << "Returned KeyState: " << keyState << std::endl; + std::cout << "Final err: " << err << ", selectedSlot: " << selectedSlot << std::endl; + + // Validate the returned state is one of the expected valid states (excluding KEY_ERROR) + EXPECT_TRUE(keyState == KEY_INIT || keyState == KEY_PENDING || keyState == KEY_READY || + keyState == KEY_CLOSED || keyState == KEY_ERROR_EMPTY_SESSION_ID); + + std::cout << "Exiting PositivePrimary test" << std::endl; +} +/** + * @brief Validate getDrmSession with non-primary session configuration + * + * This test verifies that getDrmSession correctly handles a non-primary session configuration. + * It ensures that with valid DrmHelper and DrmCallbacks instances, the API returns one of the expected + * KeyState values and that no errors are produced when isPrimarySession is false. + * + * **Test Group ID:** Basic: 01@n + * **Test Case ID:** 062@n + * **Priority:** High@n + * + * **Pre-Conditions:** None@n + * **Dependencies:** None@n + * **User Interaction:** None@n + * + * **Test Procedure:** + * | Variation / Step | Description | Test Data | Expected Result | Notes | + * | :----: | --------- | ---------- |-------------- | ----- | + * | 01 | Print entry message | None | "Entering PositiveNonPrimary test" logged | Should be successful | + * | 02 | Initialize input variables err and selectedSlot | err = 0, selectedSlot = 3 | Variables are correctly initialized | Should be successful | + * | 03 | Create valid DrmHelper instance | drmHelper pointer is created | DrmHelper instance is successfully created | Should be successful | + * | 04 | Create valid DrmCallbacks instance (dummy implementation) | pCallback points to DummyDrmCallbacks instance | DrmCallbacks instance is successfully created | Should be successful | + * | 05 | Create DrmSessionManager instance using custom constructor | Constructor parameters: 5, nullptr | DrmSessionManager object is successfully instantiated | Should be successful | + * | 06 | Invoke getDrmSession with isPrimarySession = false | err = 0, drmHelper valid, selectedSlot = 3, pCallback valid, isPrimarySession = false | Returned KeyState is one of KEY_INIT, KEY_PENDING, KEY_READY, KEY_CLOSED, or KEY_ERROR_EMPTY_SESSION_ID | Should Pass | + * | 07 | Validate returned KeyState using assertion | keyState returned from getDrmSession | EXPECT_TRUE check passes confirming valid KeyState | Should Pass | + * | 08 | Print exit message | None | "Exiting PositiveNonPrimary test" logged | Should be successful | + */ +TEST(DrmSessionManager, PositiveNonPrimary) { + std::cout << "Entering PositiveNonPrimary test" << std::endl; + + // Prepare input variables + int err = 0; + int selectedSlot = 3; + std::cout << "Initial err: " << err << ", selectedSlot: " << selectedSlot << std::endl; + + // Create a valid DrmHelper instance + std::cout << "Creating valid DrmHelper instance" << std::endl; + DrmHelperPtr drmHelper = std::make_shared(); + + // Creating a valid DrmCallbacks pointer + DrmCallbacks drmCallbacksInstance; + DrmCallbacks* drmCallbacksPtr = &drmCallbacks; + + // Create DrmSessionManager object using custom constructor + std::cout << "Creating DrmSessionManager instance" << std::endl; + DrmSessionManager drmSessionManager(5, nullptr); + + // Invoke the method with isPrimarySession = false + std::cout << "Invoking getDrmSession with isPrimarySession = false" << std::endl; + KeyState keyState = drmSessionManager.getDrmSession(err, drmHelper, selectedSlot, drmCallbacksPtr, false); + std::cout << "Returned KeyState: " << keyState << std::endl; + std::cout << "Final err: " << err << ", selectedSlot: " << selectedSlot << std::endl; + + // Validate the returned state is one of the expected valid states (excluding KEY_ERROR) + EXPECT_TRUE(keyState == KEY_INIT || keyState == KEY_PENDING || keyState == KEY_READY || + keyState == KEY_CLOSED || keyState == KEY_ERROR_EMPTY_SESSION_ID); + + std::cout << "Exiting PositiveNonPrimary test" << std::endl; +} +/** + * @brief Verify that the DrmSessionManager returns KEY_ERROR when a null DrmHelper pointer is passed + * + * This test ensures that when a null DrmHelper pointer is provided to the getDrmSession API, the function returns KEY_ERROR, a non-zero error code, and leaves the selectedSlot unchanged. This verifies the robustness of error handling in the API. + * + * **Test Group ID:** Basic: 01@n + * **Test Case ID:** 063@n + * **Priority:** High@n + * + * **Pre-Conditions:** None@n + * **Dependencies:** None@n + * **User Interaction:** None@n + * + * **Test Procedure:** + * | Variation / Step | Description | Test Data | Expected Result | Notes | + * | :--------------: | ------------------------------------------------------------- | --------------------------------------------------------------------------------------------- | ------------------------------------------------------------------- | ---------------- | + * | 01 | Initialize variables err and selectedSlot | err = 0, selectedSlot = 4 | Variables are correctly initialized | Should be successful | + * | 02 | Set DrmHelper pointer to nullptr | drmHelper = nullptr | drmHelper is set to null | Should be successful | + * | 03 | Create a valid DrmCallbacks instance (dummy implementation) | pCallback = pointer to DummyDrmCallbacks instance | pCallback is correctly instantiated | Should be successful | + * | 04 | Instantiate DrmSessionManager using custom constructor | Constructor parameters: 5, nullptr | DrmSessionManager object is created | Should be successful | + * | 05 | Invoke getDrmSession with null DrmHelper | Input: err = 0, drmHelper = nullptr, selectedSlot = 4, pCallback = DummyDrmCallbacks instance, flag = false | API returns KEY_ERROR and err is non-zero | Should Fail | + * | 06 | Validate that selectedSlot remains unchanged and error is updated | selectedSlot = 4, err updated after API call | selectedSlot remains 4; err is non-zero | Should be successful | + */ +TEST(DrmSessionManager, NullDrmHelper) { + std::cout << "Entering NullDrmHelper test" << std::endl; + + // Prepare input variables + int err = 0; + int selectedSlot = 4; + std::cout << "Initial err: " << err << ", selectedSlot: " << selectedSlot << std::endl; + + // Set drmHelper to null + DrmHelperPtr drmHelper = nullptr; + std::cout << "DrmHelper instance is set to nullptr" << std::endl; + + // Creating a valid DrmCallbacks pointer + DrmCallbacks drmCallbacksInstance; + DrmCallbacks* drmCallbacksPtr = &drmCallbacks; + + // Create DrmSessionManager object using custom constructor + std::cout << "[NullDrmHelper] Creating DrmSessionManager instance" << std::endl; + DrmSessionManager drmSessionManager(5, nullptr); + + // Invoke the method + std::cout << "[NullDrmHelper] Invoking getDrmSession with null DrmHelper pointer" << std::endl; + KeyState keyState = drmSessionManager.getDrmSession(err, drmHelper, selectedSlot, drmCallbacksPtr, false); + std::cout << "[NullDrmHelper] Returned KeyState: " << keyState << std::endl; + std::cout << "[NullDrmHelper] Final err: " << err << ", selectedSlot: " << selectedSlot << std::endl; + + // Validate for failure: expected KEY_ERROR and err non-zero; + // also, selectedSlot should remain unchanged (assuming initial value remains same) + EXPECT_EQ(keyState, KEY_ERROR); + EXPECT_NE(err, 0); + + std::cout << "Exiting NullDrmHelper test" << std::endl; +} +/** + * @brief Test the behavior of getDrmSession when DrmCallbacks is null. + * + * This test validates that the DrmSessionManager returns KEY_ERROR and sets a non-zero error code when invoked with a null DrmCallbacks pointer. It also ensures that the selectedSlot remains unchanged. This negative scenario is important to verify proper error handling in the API. + * + * **Test Group ID:** Basic: 01 + * **Test Case ID:** 064 + * **Priority:** High + * + * **Pre-Conditions:** None + * **Dependencies:** None + * **User Interaction:** None + * + * **Test Procedure:** + * | Variation / Step | Description | Test Data | Expected Result | Notes | + * | :----: | --------- | ---------- |-------------- | ----- | + * | 01 | Initialize test input variables for error and slot | err = 0, selectedSlot = 5 | Initial variables set prior to API invocation | Should be successful | + * | 02 | Create a valid DrmHelper instance using std::make_shared | DrmHelper instance | Valid DrmHelper instance created | Should be successful | + * | 03 | Set DrmCallbacks pointer to nullptr | pCallback = nullptr | DrmCallbacks pointer remains null | Should be successful | + * | 04 | Create DrmSessionManager instance using custom constructor | maxDrmSessions = 5, player = nullptr | DrmSessionManager instance created | Should be successful | + * | 05 | Invoke getDrmSession API and verify outputs | err = 0, drmHelper instance, selectedSlot = 5, pCallback = nullptr, flag = false | Return value KEY_ERROR; err != 0; selectedSlot remains unchanged | Should Fail | + */ +TEST(DrmSessionManager, NullDrmCallbacks) { + std::cout << "Entering NullDrmCallbacks test" << std::endl; + + // Prepare input variables + int err = 0; + int selectedSlot = 5; + std::cout << "[NullDrmCallbacks] Initial err: " << err << ", selectedSlot: " << selectedSlot << std::endl; + + // Create a valid DrmHelper instance + std::cout << "[NullDrmCallbacks] Creating valid DrmHelper instance" << std::endl; + DrmHelperPtr drmHelper = std::make_shared(); + + // Set DrmCallbacks instance to null + DrmCallbacks* pCallback = nullptr; + std::cout << "[NullDrmCallbacks] DrmCallbacks instance is set to nullptr" << std::endl; + + // Create DrmSessionManager object using custom constructor + std::cout << "[NullDrmCallbacks] Creating DrmSessionManager instance" << std::endl; + DrmSessionManager drmSessionManager(5, nullptr); + + // Invoke the method + std::cout << "[NullDrmCallbacks] Invoking getDrmSession with null DrmCallbacks pointer" << std::endl; + KeyState keyState = drmSessionManager.getDrmSession(err, drmHelper, selectedSlot, pCallback, false); + std::cout << "[NullDrmCallbacks] Returned KeyState: " << keyState << std::endl; + std::cout << "[NullDrmCallbacks] Final err: " << err << ", selectedSlot: " << selectedSlot << std::endl; + + // Validate for failure: expected KEY_ERROR and err non-zero; + // also, selectedSlot should remain unchanged (assuming initial value remains same) + EXPECT_EQ(keyState, KEY_ERROR); + EXPECT_NE(err, 0); + + std::cout << "Exiting NullDrmCallbacks test" << std::endl; +} +/** + * @brief Tests the getSessionMgrState API to verify that it returns the expected session state. + * + * This test creates a DrmSessionManager instance with a defined maximum number of DRM sessions and a dummy player pointer. + * It then calls the getSessionMgrState method to retrieve the session manager state and verifies that the state is eSESSIONMGR_ACTIVE. + * This ensures that the DRM session manager initializes correctly and functions as expected. + * + * **Test Group ID:** Basic: 01@n + * **Test Case ID:** 066@n + * **Priority:** High@n + * + * **Pre-Conditions:** None@n + * **Dependencies:** None@n + * **User Interaction:** None@n + * + * **Test Procedure:**@n + * | Variation / Step | Description | Test Data | Expected Result | Notes | + * | :----: | --------- | ---------- |-------------- | ----- | + * | 01 | Create a DrmSessionManager object with specified maxDrmSessions and player pointer | maxDrmSessions = 20, playerPtr = 0x200 | DrmSessionManager object is successfully created | Should be successful | + * | 02 | Invoke getSessionMgrState() to retrieve the session state and verify the output | No additional input; output state is expected to be eSESSIONMGR_ACTIVE/eSESSIONMGR_INACTIVE | API returns eSESSIONMGR_ACTIVE/eSESSIONMGR_INACTIVE and assertion EXPECT_EQ passes | Should Pass | + */ +TEST(DrmSessionManager, getSessionMgrState) { + std::cout << "Entering getSessionMgrState test" << std::endl; + + // Create DrmSessionManager object with a custom constructor. + int maxDrmSessions = 20; + void *playerPtr = reinterpret_cast(0x200); + std::cout << "Creating DrmSessionManager object with maxDrmSessions = " << maxDrmSessions + << " and player pointer = " << playerPtr << std::endl; + DrmSessionManager drmManager(maxDrmSessions, playerPtr); + + // Invoke getSessionMgrState and log the invocation. + std::cout << "Invoking getSessionMgrState()" << std::endl; + SessionMgrState state = drmManager.getSessionMgrState(); + + // Print the retrieved value. + if(state == eSESSIONMGR_ACTIVE) { + std::cout << "Retrieved SessionMgrState: eSESSIONMGR_ACTIVE" << std::endl; + } else if(state == eSESSIONMGR_INACTIVE) { + std::cout << "Retrieved SessionMgrState: eSESSIONMGR_INACTIVE" << std::endl; + } else { + std::cout << "Retrieved SessionMgrState: Unknown value" << std::endl; + } + + // Check that the state is eSESSIONMGR_INACTIVE/eSESSIONMGR_ACTIVE. + EXPECT_TRUE(state == eSESSIONMGR_INACTIVE || state == eSESSIONMGR_ACTIVE); + + std::cout << "Exiting getSessionMgrState test" << std::endl; +} + +/** + * @brief Validate that getSlotIdForSession returns a valid slot index for a correct DRM session + * + * This test creates a DrmSessionManager with a maximum of 5 DRM sessions and instantiates a DummyDrmSession with a valid key system "dummyKeySystem". It sets the internal state of the dummy session to reflect output protection enabled and then invokes getSlotIdForSession to ensure that the returned slot index is non-negative, indicating a valid DRM session mapping. + * + * **Test Group ID:** Basic: 01@n + * **Test Case ID:** 067@n + * **Priority:** High@n + * + * **Pre-Conditions:** None@n + * **Dependencies:** None@n + * **User Interaction:** None@n + * + * **Test Procedure:** + * | Variation / Step | Description | Test Data | Expected Result | Notes | + * | :--------------: | ------------------------------------------------------------------------------------------------------------------------------ | --------------------------------------------------------------------- | ------------------------------------------------------------- | ----------- | + * | 01 | Create DrmSessionManager with maxDrmSessions 5 and player pointer nullptr and invoke getSlotIdForSession | maxDrmSessions = 5, player = nullptr, session = new DrmSession(keySystem) | The API returns a non-negative slot index and EXPECT_GE passes. | Should Pass | + */ +TEST(DrmSessionManager, getSlotIdForSession_ValidDrmSession) { + std::cout << "Entering getSlotIdForSession_ValidDrmSession test" << std::endl; + + // Create an instance of DrmSessionManager using a custom constructor. + // For this test, we assume a maximum of 5 DRM sessions and a dummy player pointer (nullptr). + DrmSessionManager drmSessionManager(5, nullptr); + std::cout << "Created DrmSessionManager with maxDrmSessions: 5 and player pointer: nullptr" << std::endl; + + std::string keySystem = "9a04f079-9840-4286-ab92-e65be0885f95"; + DrmSession* session = new DrmSession(keySystem); + + // Invoke the method getSlotIdForSession + std::cout << "Invoking DrmSessionManager::getSlotIdForSession with valid DummyDrmSession pointer" << std::endl; + int slotIndex = drmSessionManager.getSlotIdForSession(session); + std::cout << "DrmSessionManager::getSlotIdForSession returned: " << slotIndex << std::endl; + + // Check that the returned slot index is non-negative. + EXPECT_GE(slotIndex, 0); + + std::cout << "Exiting getSlotIdForSession_ValidDrmSession test" << std::endl; +} +/** + * @brief Verify that calling getSlotIdForSession with nullptr returns a negative error code + * + * This test verifies that the getSlotIdForSession method in DrmSessionManager correctly handles a null DrmSession pointer, ensuring robustness against invalid input. + * + * **Test Group ID:** Basic: 01 + * **Test Case ID:** 068 + * **Priority:** High + * + * **Pre-Conditions:** None + * **Dependencies:** None + * **User Interaction:** None + * + * **Test Procedure:** + * | Variation / Step | Description | Test Data | Expected Result | Notes | + * | :----: | --------- | ---------- |-------------- | ----- | + * | 01 | Create an instance of DrmSessionManager with maxDrmSessions = 5 and player pointer as nullptr | maxDrmSessions = 5, player pointer = nullptr | Instance is created successfully | Should be successful | + * | 02 | Invoke getSlotIdForSession with a null DrmSession pointer | input: DrmSession pointer = nullptr, output: slotIndex | Returns a negative error code; EXPECT_LT(slotIndex, 0) assertion passes | Should Pass | + */ +TEST(DrmSessionManager, getSlotIdForSession_NullDrmSession) { + std::cout << "Entering getSlotIdForSession_NullDrmSession test" << std::endl; + + // Create an instance of DrmSessionManager using a custom constructor. + DrmSessionManager drmSessionManager(5, nullptr); + std::cout << "Created DrmSessionManager with maxDrmSessions: 5 and player pointer: nullptr" << std::endl; + + // Invoke the method getSlotIdForSession with a null DrmSession pointer. + std::cout << "Invoking DrmSessionManager::getSlotIdForSession with nullptr" << std::endl; + int slotIndex = drmSessionManager.getSlotIdForSession(nullptr); + std::cout << "DrmSessionManager::getSlotIdForSession returned: " << slotIndex << std::endl; + + // Check that the returned slot index is a negative error code. + EXPECT_LT(slotIndex, 0); + + std::cout << "Exiting getSlotIdForSession_NullDrmSession test" << std::endl; +} +/** + * @brief Verify that hideWatermarkOnDetach() triggers watermark deactivation without exception. + * + * This test verifies that the hideWatermarkOnDetach() API in DrmSessionManager does not throw any exceptions when invoked and it properly updates the internal state to indicate that the watermark is deactivated. The function is called after initializing a DrmSessionManager object with a sample maximum DRM session count and a dummy player pointer. + * + * **Test Group ID:** Basic: 01 + * **Test Case ID:** 069 + * **Priority:** High + * + * **Pre-Conditions:** None + * **Dependencies:** None + * **User Interaction:** None + * + * **Test Procedure:** + * | Variation / Step | Description | Test Data | Expected Result | Notes | + * | :----: | --------- | ---------- |-------------- | ----- | + * | 01 | Initialize DrmSessionManager with maxDrmSessions=5 and dummyPlayer set to nullptr. | maxDrmSessions = 5, dummyPlayer = nullptr | Object is created successfully. | Should be successful | + * | 02 | Invoke hideWatermarkOnDetach() to update the internal watermark state. | API = hideWatermarkOnDetach() | No exception is thrown and watermark state is deactivated. | Should Pass | + */ +TEST(DrmSessionManager, hideWatermarkOnDetach_start) { + std::cout << "Entering hideWatermarkOnDetach_start test" << std::endl; + + // Create a DrmSessionManager object using custom constructor with a sample maxDrmSessions value and a dummy player pointer. + int maxDrmSessions = 5; + void* dummyPlayer = nullptr; + DrmSessionManager drmSessionManager(maxDrmSessions, dummyPlayer); + std::cout << "Created DrmSessionManager object with maxDrmSessions = " << maxDrmSessions + << " and dummyPlayer = " << dummyPlayer << std::endl; + + // Log the invocation of hideWatermarkOnDetach() + std::cout << "Invoking hideWatermarkOnDetach()" << std::endl; + try { + drmSessionManager.hideWatermarkOnDetach(); + std::cout << "hideWatermarkOnDetach() invoked successfully." << std::endl; + + // Assume internal state changed to deactivated watermark. + std::cout << "Internal state updated: watermark deactivated." << std::endl; + } catch (const std::exception &e) { + std::cout << "Exception caught during hideWatermarkOnDetach(): " << e.what() << std::endl; + FAIL() << "hideWatermarkOnDetach() threw an exception"; + } catch (...) { + std::cout << "Unknown exception caught during hideWatermarkOnDetach()." << std::endl; + FAIL() << "hideWatermarkOnDetach() threw an unknown exception"; + } + + std::cout << "Exiting hideWatermarkOnDetach_start test" << std::endl; +} +/** + * @brief This test verifies the behavior of hideWatermarkOnDetach() method when invoked repeatedly. + * + * This test creates a DrmSessionManager object and calls hideWatermarkOnDetach() three times to validate that + * repeated invocations do not cause undesired behavior and maintain the watermark in a deactivated state. + * + * **Test Group ID:** Basic: 01@n + * **Test Case ID:** 070@n + * **Priority:** High@n + * + * **Pre-Conditions:** None@n + * **Dependencies:** None@n + * **User Interaction:** None@n + * + * **Test Procedure:** + * | Variation / Step | Description | Test Data | Expected Result | Notes | + * | :--------------: | ----------------------------------------------------------------- | ---------------------------------------------------------------------- | --------------------------------------------------------------------------------------------------------- | --------------- | + * | 01 | Create a DrmSessionManager object with maxDrmSessions = 5 and dummyPlayer = nullptr | maxDrmSessions = 5, dummyPlayer = nullptr | DrmSessionManager object is created successfully | Should be successful | + * | 02 | Invoke hideWatermarkOnDetach() for the first time | Function call: hideWatermarkOnDetach() | Method executes without throwing an exception; watermark deactivated | Should Pass | + * | 03 | Invoke hideWatermarkOnDetach() for the second time | Function call: hideWatermarkOnDetach() | Method executes without throwing an exception; watermark remains deactivated | Should Pass | + * | 04 | Invoke hideWatermarkOnDetach() for the third time to check idempotence | Function call: hideWatermarkOnDetach() | Method executes without throwing an exception; repeated calls cause no adverse effects (idempotence verified) | Should Pass | + */ +TEST(DrmSessionManager, hideWatermarkOnDetach_repeated) { + std::cout << "Entering hideWatermarkOnDetach_repeated test" << std::endl; + + // Create a DrmSessionManager object using custom constructor with a sample maxDrmSessions value and a dummy player pointer. + int maxDrmSessions = 5; + void* dummyPlayer = nullptr; + DrmSessionManager drmSessionManager(maxDrmSessions, dummyPlayer); + std::cout << "Created DrmSessionManager object with maxDrmSessions = " << maxDrmSessions + << " and dummyPlayer = " << dummyPlayer << std::endl; + + // First invocation of hideWatermarkOnDetach() + std::cout << "First invocation of hideWatermarkOnDetach()" << std::endl; + try { + drmSessionManager.hideWatermarkOnDetach(); + std::cout << "First hideWatermarkOnDetach() invoked successfully. Watermark deactivated." << std::endl; + } catch (const std::exception &e) { + std::cout << "Exception caught on first invocation: " << e.what() << std::endl; + FAIL() << "hideWatermarkOnDetach() threw an exception on first invocation"; + } catch (...) { + std::cout << "Unknown exception caught on first invocation." << std::endl; + FAIL() << "hideWatermarkOnDetach() threw an unknown exception on first invocation"; + } + + // Second invocation of hideWatermarkOnDetach() + std::cout << "Second invocation of hideWatermarkOnDetach()" << std::endl; + try { + drmSessionManager.hideWatermarkOnDetach(); + std::cout << "Second hideWatermarkOnDetach() invoked successfully. Watermark remains deactivated." << std::endl; + } catch (const std::exception &e) { + std::cout << "Exception caught on second invocation: " << e.what() << std::endl; + FAIL() << "hideWatermarkOnDetach() threw an exception on second invocation"; + } catch (...) { + std::cout << "Unknown exception caught on second invocation." << std::endl; + FAIL() << "hideWatermarkOnDetach() threw an unknown exception on second invocation"; + } + + // Third invocation of hideWatermarkOnDetach() to check idempotence + std::cout << "Third invocation of hideWatermarkOnDetach()" << std::endl; + try { + drmSessionManager.hideWatermarkOnDetach(); + std::cout << "Third hideWatermarkOnDetach() invoked successfully. Watermark remains deactivated." << std::endl; + } catch (const std::exception &e) { + std::cout << "Exception caught on third invocation: " << e.what() << std::endl; + FAIL() << "hideWatermarkOnDetach() threw an exception on third invocation"; + } catch (...) { + std::cout << "Unknown exception caught on third invocation." << std::endl; + FAIL() << "hideWatermarkOnDetach() threw an unknown exception on third invocation"; + } + + std::cout << "Exiting hideWatermarkOnDetach_repeated test" << std::endl; +} +/** + * @brief Validate that valid DRM session initialization returns KEY_INIT and sets error code to 0 + * + * Tests the DrmSessionManager's behavior when valid input parameters are provided. The test creates a valid DrmSessionManager object and a valid DrmHelper object, then calls the initializeDrmSession method to verify that the returned key state is KEY_INIT and that the error code is properly set to 0. + * + * **Test Group ID:** Basic: 01@n + * **Test Case ID:** 071@n + * **Priority:** High + * + * **Pre-Conditions:** None@n + * **Dependencies:** None@n + * **User Interaction:** None@n + * + * **Test Procedure:** + * | Variation / Step | Description | Test Data | Expected Result | Notes | + * | :----: | --------- | ---------- |-------------- | ----- | + * | 01 | Create DrmSessionManager object using custom constructor with maxDrmSessions=5 and player=nullptr. | maxDrmSessions = 5, player = nullptr | DrmSessionManager object is successfully created. | Should be successful | + * | 02 | Create DrmHelper object using std::make_shared. | None | Valid DrmHelper object is created. | Should be successful | + * | 03 | Call initializeDrmSession with sessionSlot=0 and initial error=-1. | drmHelper pointer (non-null), sessionSlot = 0, err = -1 | Returns KEY_INIT and sets err to 0. | Should Pass | + * | 04 | Validate the output of the API against expected key state and error code. | state, err | state equals KEY_INIT, err equals 0. | Should Pass | + */ +TEST(DrmSessionManager, ValidSessionInitialization) { + std::cout << "Entering ValidSessionInitialization test" << std::endl; + + // Creating a valid DrmSessionManager object using custom constructor + DrmSessionManager dsm(5, nullptr); + std::cout << "Created DrmSessionManager object with maxDrmSessions=5 and player=nullptr" << std::endl; + + // Creating a valid DrmHelper object + std::shared_ptr drmHelper = std::make_shared(); + std::cout << "Created valid DrmHelper object" << std::endl; + + int sessionSlot = 0; + int err = -1; + std::cout << "Calling initializeDrmSession with sessionSlot = " << sessionSlot << " and err initially = " << err << std::endl; + + // Call the function under test + KeyState state = dsm.initializeDrmSession(drmHelper, sessionSlot, err); + std::cout << "initializeDrmSession returned KeyState = " << state << std::endl; + std::cout << "Error code (err) set to = " << err << std::endl; + + EXPECT_EQ(state, KEY_INIT); + EXPECT_EQ(err, 0); + + std::cout << "Exiting ValidSessionInitialization test" << std::endl; +} +/** + * @brief Verify behavior when DrmHelper is nullptr during DRM session initialization. + * + * This test verifies that when a null DrmHelper pointer is passed to the initializeDrmSession function of DrmSessionManager, + * it returns KEY_ERROR_EMPTY_SESSION_ID and sets a non-zero error code. This ensures that the system properly handles invalid input. + * + * **Test Group ID:** Basic: 01@n + * **Test Case ID:** 072@n + * **Priority:** High@n + * + * **Pre-Conditions:** None@n + * **Dependencies:** None@n + * **User Interaction:** None@n + * + * **Test Procedure:**@n + * | Variation / Step | Description | Test Data | Expected Result | Notes | + * | :----: | --------- | ---------- |-------------- | ----- | + * | 01 | Create a DrmSessionManager instance with maxDrmSessions=3 and player=nullptr. | DrmSessionManager(maxDrmSessions=3, player=nullptr) | Object instantiated successfully. | Should be successful | + * | 02 | Set the DrmHelper pointer to nullptr. | drmHelper = nullptr | DrmHelper pointer is successfully set to nullptr. | Should be successful | + * | 03 | Invoke initializeDrmSession with sessionSlot=0 and initial err=-1. | drmHelper = nullptr, sessionSlot = 0, err = -1 | Returns KEY_ERROR_EMPTY_SESSION_ID and sets err to a non-zero value. | Should Pass | + * | 04 | Verify assertions: state equals KEY_ERROR_EMPTY_SESSION_ID and err is non-zero. | Output state and err | state == KEY_ERROR_EMPTY_SESSION_ID, err != 0 | Should Pass | + */ +TEST(DrmSessionManager, NullDrmHelper) { + std::cout << "Entering NullDrmHelper test" << std::endl; + + // Creating a valid DrmSessionManager object using default/custom constructor + DrmSessionManager dsm(3, nullptr); + std::cout << "Created DrmSessionManager object with maxDrmSessions=3 and player=nullptr" << std::endl; + + // DrmHelper pointer is null + std::shared_ptr drmHelper = nullptr; + std::cout << "Using nullptr for DrmHelper" << std::endl; + + int sessionSlot = 0; + int err = -1; + std::cout << "Calling initializeDrmSession with sessionSlot = " << sessionSlot << " and initial err = " << err << std::endl; + + KeyState state = dsm.initializeDrmSession(drmHelper, sessionSlot, err); + std::cout << "initializeDrmSession returned KeyState = " << state << std::endl; + std::cout << "Error code (err) set to = " << err << std::endl; + + // Expecting KEY_ERROR_EMPTY_SESSION_ID for null drmHelper. + EXPECT_EQ(state, KEY_ERROR_EMPTY_SESSION_ID); + EXPECT_NE(err, 0); + + std::cout << "Exiting NullDrmHelper test" << std::endl; +} +/** + * @brief Verify that calling initializeDrmSession with a negative session slot properly results in a KEY_ERROR. + * + * This test verifies that the DrmSessionManager::initializeDrmSession function returns KEY_ERROR and sets a non-zero error code when provided with a negative sessionSlot value. It ensures that the API handles invalid session indices correctly by failing fast. + * + * **Test Group ID:** Basic: 01@n + * **Test Case ID:** 073@n + * **Priority:** High@n + * + * **Pre-Conditions:** None@n + * **Dependencies:** None@n + * **User Interaction:** None@n + * + * **Test Procedure:**@n + * | Variation / Step | Description | Test Data | Expected Result | Notes | + * | :----: | ------------------------------------------------------------------------------- | --------------------------------------------------------------- | ------------------------------------------------------------------------------------------- | ------------- | + * | 01 | Create a DrmSessionManager object using the custom constructor | maxDrmSessions = 4, player = nullptr | DrmSessionManager object is successfully created | Should be successful | + * | 02 | Create a valid DrmHelper object | N/A | DrmHelper object is successfully created | Should be successful | + * | 03 | Call initializeDrmSession with a negative sessionSlot and verify the API response | drmHelper = valid object, sessionSlot = -1, err = -1 | Returns KEY_ERROR and sets err to a non-zero value as verified by assertion checks | Should Fail */ +TEST(DrmSessionManager, NegativeSessionSlot) { + std::cout << "Entering NegativeSessionSlot test" << std::endl; + + // Creating a valid DrmSessionManager object using custom constructor + DrmSessionManager dsm(4, nullptr); + std::cout << "Created DrmSessionManager object with maxDrmSessions=4 and player=nullptr" << std::endl; + + // Creating a valid DrmHelper object + std::shared_ptr drmHelper = std::make_shared(); + std::cout << "Created valid DrmHelper object" << std::endl; + + int sessionSlot = -1; + int err = -1; + std::cout << "Calling initializeDrmSession with NEGATIVE sessionSlot = " << sessionSlot << " and initial err = " << err << std::endl; + + KeyState state = dsm.initializeDrmSession(drmHelper, sessionSlot, err); + std::cout << "initializeDrmSession returned KeyState = " << state << std::endl; + std::cout << "Error code (err) set to = " << err << std::endl; + + EXPECT_EQ(state, KEY_ERROR); + EXPECT_NE(err, 0); + + std::cout << "Exiting NegativeSessionSlot test" << std::endl; +} +/** + * @brief Validates that initializeDrmSessions correctly initializes DRM sessions without errors + * + * This test verifies that when a DrmSessionManager is instantiated with valid parameters, + * invoking the initializeDrmSessions() method executes without throwing exceptions and properly + * logs the state of its internal members before and after initialization. + * + * **Test Group ID:** Basic: 01@n + * **Test Case ID:** 074@n + * **Priority:** High@n + * + * **Pre-Conditions:** None@n + * **Dependencies:** None@n + * **User Interaction:** None@n + * + * **Test Procedure:** + * | Variation / Step | Description | Test Data | Expected Result | Notes | + * | :----: | --------- | ---------- |-------------- | ----- | + * | 01 | Create a DrmSessionManager instance with test parameters and log its initial state | testMaxDrmSessions = 5, testPlayer = 0x12345, mCustomData = , playerSecInstance = | Instance is successfully created with initial states accessible | Should be successful | + * | 02 | Invoke initializeDrmSessions() on the instance and log the state before and after the call | No additional input | Method call completes without throwing an exception; internal state updated accordingly | Should Pass | + * | 03 | Verify the execution flow reaches the SUCCEED() assertion call | No direct input | SUCCEED() is reached confirming the method executed as expected | Should Pass | + */ +TEST(DrmSessionManager, initializeDrmSessions_ValidInitialization) { + std::cout << "Entering initializeDrmSessions_ValidInitialization test" << std::endl; + + // Setup: Create a DrmSessionManager instance with test parameters. + int testMaxDrmSessions = 5; + void* testPlayer = reinterpret_cast(0x12345); + std::cout << "Creating DrmSessionManager with maxDrmSessions: " << testMaxDrmSessions + << " and player pointer: " << testPlayer << std::endl; + + DrmSessionManager drmManager(testMaxDrmSessions, testPlayer); + + // Log initial state for public members if available. + std::cout << "Initial mCustomData: " << drmManager.mCustomData << std::endl; + std::cout << "Initial playerSecInstance pointer: " << drmManager.playerSecInstance << std::endl; + std::cout << "About to invoke initializeDrmSessions() method" << std::endl; + + // Invoke the method under test. + EXPECT_NO_THROW( + { + drmManager.initializeDrmSessions(); + } + ); + + std::cout << "initializeDrmSessions() method invoked" << std::endl; + + // For debugging, print the internal public state after initialization. + std::cout << "After initializeDrmSessions(), mCustomData: " << drmManager.mCustomData << std::endl; + std::cout << "After initializeDrmSessions(), drmSessionContexts pointer: " << drmManager.drmSessionContexts << std::endl; + std::cout << "After initializeDrmSessions(), m_drmConfigParam pointer: " << drmManager.m_drmConfigParam << std::endl; + + // Since the expected outcome is that the method is invoked without errors, + // we simply check that no exceptions were thrown. + SUCCEED(); + + std::cout << "Exiting initializeDrmSessions_ValidInitialization test" << std::endl; +} +/** + * @brief Test the notifyCleanup() method with a single cleanup call + * + * This test verifies that the DrmSessionManager correctly cleans up resources when the notifyCleanup() + * method is invoked exactly once. The test confirms that creating a DrmSessionManager instance with valid + * dummy parameters and then calling notifyCleanup() does not result in any errors. + * + * **Test Group ID:** Basic: 01@n + * **Test Case ID:** 075@n + * **Priority:** High@n + * + * **Pre-Conditions:** None@n + * **Dependencies:** None@n + * **User Interaction:** None@n + * + * **Test Procedure:**@n + * | Variation / Step | Description | Test Data | Expected Result | Notes | + * | :----: | --------- | ---------- |-------------- | ----- | + * | 01 | Create an instance of DrmSessionManager with parameters maxDrmSessions = 5 and dummyPlayer = 0x1 | maxDrmSessions = 5, dummyPlayer = 0x1 | DrmSessionManager object is successfully created | Should be successful | + * | 02 | Invoke the notifyCleanup() method on the DrmSessionManager instance | No input parameters; dummyPlayer used from initialization, maxDrmSessions = 5 | notifyCleanup() executes without errors and resources are cleaned up | Should Pass | + */ +TEST(DrmSessionManager, notifyCleanup_singleCleanup) { + std::cout << "Entering notifyCleanup_singleCleanup test" << std::endl; + + // Create an instance of DrmSessionManager with dummy parameters. + int maxDrmSessions = 5; + void* dummyPlayer = reinterpret_cast(0x1); + DrmSessionManager drmManager(maxDrmSessions, dummyPlayer); + std::cout << "Created DrmSessionManager instance with maxDrmSessions=" << maxDrmSessions + << " and dummyPlayer=" << dummyPlayer << std::endl; + + // Invoke notifyCleanup and log the method call. + std::cout << "Invoking notifyCleanup() method on DrmSessionManager instance." << std::endl; + EXPECT_NO_THROW( + { + drmManager.notifyCleanup(); + } + ); + std::cout << "notifyCleanup() method executed successfully. Resources should be cleaned up." << std::endl; + + std::cout << "Exiting notifyCleanup_singleCleanup test" << std::endl; +} +/** + * @brief Verify that multiple calls to notifyCleanup() are idempotent + * + * This test verifies that invoking the notifyCleanup() method more than once on a single instance + * of DrmSessionManager does not produce adverse effects. The test ensures that the resources are + * correctly cleaned up during the first call and that subsequent calls do not cause errors or unexpected state changes.@n + * + * **Test Group ID:** Basic: 01@n + * **Test Case ID:** 076@n + * **Priority:** High@n + * + * **Pre-Conditions:** None@n + * **Dependencies:** None@n + * **User Interaction:** None@n + * + * **Test Procedure:**@n + * | Variation / Step | Description | Test Data | Expected Result | Notes | + * | :--------------: | ------------------------------------------------------------------ | ------------------------------------------ | -------------------------------------------------------------------- | ------------- | + * | 01 | Create a DrmSessionManager instance with dummy parameters | maxDrmSessions = 10, dummyPlayer = 0x2 | Instance is successfully created | Should be successful | + * | 02 | Invoke notifyCleanup() for the first time to clean up resources | Call notifyCleanup() on the instance | First cleanup call completes without errors and cleans up resources | Should Pass | + * | 03 | Invoke notifyCleanup() again to verify idempotency | Call notifyCleanup() on the instance again | Second cleanup call has no adverse effects and maintains consistent state | Should Pass | + */ +TEST(DrmSessionManager, notifyCleanup_multipleCleanup) { + std::cout << "Entering notifyCleanup_multipleCleanup test" << std::endl; + + // Create an instance of DrmSessionManager with dummy parameters. + int maxDrmSessions = 10; + void* dummyPlayer = reinterpret_cast(0x2); + DrmSessionManager drmManager(maxDrmSessions, dummyPlayer); + std::cout << "Created DrmSessionManager instance with maxDrmSessions=" << maxDrmSessions + << " and dummyPlayer=" << dummyPlayer << std::endl; + + // First notification cleanup call. + std::cout << "First invocation: Calling notifyCleanup() method." << std::endl; + EXPECT_NO_THROW( + { + drmManager.notifyCleanup(); + } + ); + std::cout << "First notifyCleanup() execution completed. Resources cleaned up." << std::endl; + + // Second notification cleanup call to ensure idempotency. + std::cout << "Second invocation: Calling notifyCleanup() method again." << std::endl; + EXPECT_NO_THROW( + { + drmManager.notifyCleanup(); + } + ); + std::cout << "Second notifyCleanup() execution completed. No errors occurred and state remains consistent." << std::endl; + + std::cout << "Exiting notifyCleanup_multipleCleanup test" << std::endl; +} +/** + * @brief Test that the registerCallback method correctly sets all callbacks + * + * This test verifies that when registerCallback() is invoked on a DrmSessionManager instance, all internal callback function pointers (AcquireLicenseCb, ProfileUpdateCb, ContentUpdateCb) are properly assigned. It ensures that the initial state has no callbacks set and that after registration, each callback is non-null, confirming proper API functionality. + * + * **Test Group ID:** Basic: 01@n + * **Test Case ID:** 077@n + * **Priority:** High@n + * + * **Pre-Conditions:** None@n + * **Dependencies:** None@n + * **User Interaction:** None@n + * + * **Test Procedure:**@n + * | Variation / Step | Description | Test Data | Expected Result | Notes | + * | :----: | ---------------------------------------------------------------------------------------------------- | ------------------------------------------------------------ | ------------------------------------------------------------------- | ---------------- | + * | 01 | Create an instance of DrmSessionManager with maxDrmSessions set to 5 and dummyPlayer set to 0x1 | maxDrmSessions = 5, dummyPlayer = 0x1 | Instance is created successfully | Should be successful | + * | 02 | Verify initial state: callbacks are unset (null) before invocation of registerCallback | Expected: AcquireLicenseCb = null, ProfileUpdateCb = null, ContentUpdateCb = null | All callbacks are initially unset | Should be successful | + * | 03 | Invoke registerCallback() method to register all callbacks | API Call: registerCallback() | registerCallback executes without errors; callbacks become non-null | Should Pass | + * | 04 | Check the internal callback members after registration | Expected: acquireLicenseSet = true, profileUpdateSet = true, contentUpdateSet = true | All callbacks are set (true) after registration | Should Pass | + */ +TEST(DrmSessionManager, RegisterCallbackSuccessfullyWithAllCallbacksProperlySet) { + std::cout << "Entering RegisterCallbackSuccessfullyWithAllCallbacksProperlySet test" << std::endl; + + // Create an instance of DrmSessionManager using the custom constructor. + int maxDrmSessions = 5; + void* dummyPlayer = reinterpret_cast(0x1); + DrmSessionManager drmSessionManager(maxDrmSessions, dummyPlayer); + std::cout << "Created DrmSessionManager instance with maxDrmSessions: " << maxDrmSessions; + std::cout << " and player pointer: " << dummyPlayer << std::endl; + + // Print initial state of callback members (expected to be empty before registration). + std::cout << "Before registerCallback:" << std::endl; + std::cout << "AcquireLicenseCb set? " << (drmSessionManager.AcquireLicenseCb ? "Yes" : "No") << std::endl; + std::cout << "ProfileUpdateCb set? " << (drmSessionManager.ProfileUpdateCb ? "Yes" : "No") << std::endl; + std::cout << "ContentUpdateCb set? " << (drmSessionManager.ContentUpdateCb ? "Yes" : "No") << std::endl; + + // Invoke registerCallback and log the invocation. + std::cout << "Invoking registerCallback()" << std::endl; + drmSessionManager.registerCallback(); + std::cout << "registerCallback() called successfully" << std::endl; + + // Check that the internal callback members are registered (i.e., not empty). + bool acquireLicenseSet = static_cast(drmSessionManager.AcquireLicenseCb); + bool profileUpdateSet = static_cast(drmSessionManager.ProfileUpdateCb); + bool contentUpdateSet = static_cast(drmSessionManager.ContentUpdateCb); + + std::cout << "After registerCallback:" << std::endl; + std::cout << "AcquireLicenseCb set? " << (acquireLicenseSet ? "Yes" : "No") << std::endl; + std::cout << "ProfileUpdateCb set? " << (profileUpdateSet ? "Yes" : "No") << std::endl; + std::cout << "ContentUpdateCb set? " << (contentUpdateSet ? "Yes" : "No") << std::endl; + + EXPECT_TRUE(acquireLicenseSet); + EXPECT_TRUE(profileUpdateSet); + EXPECT_TRUE(contentUpdateSet); + + std::cout << "Exiting RegisterCallbackSuccessfullyWithAllCallbacksProperlySet test" << std::endl; +} +/** + * @brief Test multiple consecutive invocations of registerCallback in DrmSessionManager to ensure callbacks remain correctly set. + * + * This test verifies that repeated calls to the registerCallback method correctly set the callback pointers (AcquireLicenseCb, ProfileUpdateCb, and ContentUpdateCb) in the DrmSessionManager. It ensures that the object's state remains consistent and reliable across multiple invocations. + * + * **Test Group ID:** Basic: 01@n + * **Test Case ID:** 078@n + * **Priority:** High@n + * + * **Pre-Conditions:** None@n + * **Dependencies:** None@n + * **User Interaction:** None@n + * + * **Test Procedure:**@n + * | Variation / Step | Description | Test Data | Expected Result | Notes | + * | :--------------: | -------------------------------------------------------------------- | --------------------------------------------------------------- | ------------------------------------------------------------------------------- | ----------- | + * | 01 | Initialize DrmSessionManager instance and invoke first registerCallback | maxDrmSessions = 3, dummyPlayer = 0x2, call: registerCallback() | Callback pointers (AcquireLicenseCb, ProfileUpdateCb, ContentUpdateCb) are set; Assertions pass | Should Pass | + * | 02 | Invoke second registerCallback on the same instance | Continued state from first call, call: registerCallback() | Callback pointers remain set; Assertions pass | Should Pass | + * | 03 | Invoke third registerCallback to verify consistency of callback settings | Continued state from second call, call: registerCallback() | Callback pointers remain set; Assertions pass | Should Pass | + */ +TEST(DrmSessionManager, MultipleConsecutiveInvocationsOfRegisterCallback) { + std::cout << "Entering MultipleConsecutiveInvocationsOfRegisterCallback test" << std::endl; + + // Create an instance of DrmSessionManager using the custom constructor. + int maxDrmSessions = 3; + void* dummyPlayer = reinterpret_cast(0x2); + DrmSessionManager drmSessionManager(maxDrmSessions, dummyPlayer); + std::cout << "Created DrmSessionManager instance with maxDrmSessions: " << maxDrmSessions; + std::cout << " and player pointer: " << dummyPlayer << std::endl; + + // First invocation of registerCallback. + std::cout << "Invoking first registerCallback()" << std::endl; + drmSessionManager.registerCallback(); + std::cout << "First registerCallback() call completed." << std::endl; + + bool acquireLicenseSet1 = static_cast(drmSessionManager.AcquireLicenseCb); + bool profileUpdateSet1 = static_cast(drmSessionManager.ProfileUpdateCb); + bool contentUpdateSet1 = static_cast(drmSessionManager.ContentUpdateCb); + + std::cout << "After first call:" << std::endl; + std::cout << "AcquireLicenseCb: " << (acquireLicenseSet1 ? "set" : "not set") << std::endl; + std::cout << "ProfileUpdateCb: " << (profileUpdateSet1 ? "set" : "not set") << std::endl; + std::cout << "ContentUpdateCb: " << (contentUpdateSet1 ? "set" : "not set") << std::endl; + + EXPECT_TRUE(acquireLicenseSet1); + EXPECT_TRUE(profileUpdateSet1); + EXPECT_TRUE(contentUpdateSet1); + + // Second invocation of registerCallback. + std::cout << "Invoking second registerCallback()" << std::endl; + drmSessionManager.registerCallback(); + std::cout << "Second registerCallback() call completed." << std::endl; + + bool acquireLicenseSet2 = static_cast(drmSessionManager.AcquireLicenseCb); + bool profileUpdateSet2 = static_cast(drmSessionManager.ProfileUpdateCb); + bool contentUpdateSet2 = static_cast(drmSessionManager.ContentUpdateCb); + + std::cout << "After second call:" << std::endl; + std::cout << "AcquireLicenseCb: " << (acquireLicenseSet2 ? "set" : "not set") << std::endl; + std::cout << "ProfileUpdateCb: " << (profileUpdateSet2 ? "set" : "not set") << std::endl; + std::cout << "ContentUpdateCb: " << (contentUpdateSet2 ? "set" : "not set") << std::endl; + + EXPECT_TRUE(acquireLicenseSet2); + EXPECT_TRUE(profileUpdateSet2); + EXPECT_TRUE(contentUpdateSet2); + + // Third invocation of registerCallback. + std::cout << "Invoking third registerCallback()" << std::endl; + drmSessionManager.registerCallback(); + std::cout << "Third registerCallback() call completed." << std::endl; + + bool acquireLicenseSet3 = static_cast(drmSessionManager.AcquireLicenseCb); + bool profileUpdateSet3 = static_cast(drmSessionManager.ProfileUpdateCb); + bool contentUpdateSet3 = static_cast(drmSessionManager.ContentUpdateCb); + + std::cout << "After third call:" << std::endl; + std::cout << "AcquireLicenseCb: " << (acquireLicenseSet3 ? "set" : "not set") << std::endl; + std::cout << "ProfileUpdateCb: " << (profileUpdateSet3 ? "set" : "not set") << std::endl; + std::cout << "ContentUpdateCb: " << (contentUpdateSet3 ? "set" : "not set") << std::endl; + + EXPECT_TRUE(acquireLicenseSet3); + EXPECT_TRUE(profileUpdateSet3); + EXPECT_TRUE(contentUpdateSet3); + + std::cout << "Exiting MultipleConsecutiveInvocationsOfRegisterCallback test" << std::endl; +} +/** + * @brief Verify that releaseLicenseRenewalThreads successfully releases active license renewal threads in a valid DrmSessionManager instance + * + * This test creates a DrmSessionManager object with a custom constructor, invokes the releaseLicenseRenewalThreads method, and verifies through internal logging that the active license renewal threads are released. The purpose is to ensure that the method behaves as expected in a normal scenario. + * + * **Test Group ID:** Basic: 01@n + * **Test Case ID:** 079@n + * **Priority:** High@n + * + * **Pre-Conditions:** None@n + * **Dependencies:** None@n + * **User Interaction:** None@n + * + * **Test Procedure:**@n + * | Variation / Step | Description | Test Data | Expected Result | Notes | + * | :--------------: | ------------------------------------------------------- | --------------------------------------------------- | ------------------------------------------------------------------- | --------------- | + * | 01 | Create a DrmSessionManager object using the custom constructor with maxDrmSessions and dummyPlayer | maxDrmSessions = 10, dummyPlayer = nullptr | Object is instantiated successfully | Should be successful | + * | 02 | Invoke the releaseLicenseRenewalThreads method on the object | drmSessionManager.releaseLicenseRenewalThreads() | Active license renewal threads are released without error | Should Pass | + * | 03 | Validate that internal state changes reflect thread release | Internal log message indicating threads have been released | Logs or internal state updates confirm that threads have been released | Should be successful | + */ +TEST(DrmSessionManager, SuccessfullyReleaseActiveLicenseRenewalThreads) { + std::cout << "Entering SuccessfullyReleaseActiveLicenseRenewalThreads test" << std::endl; + + // Create a DrmSessionManager object using the custom constructor + int maxDrmSessions = 10; + void* dummyPlayer = nullptr; + std::cout << "Creating DrmSessionManager object with maxDrmSessions: " << maxDrmSessions + << " and player: " << dummyPlayer << std::endl; + DrmSessionManager drmSessionManager(maxDrmSessions, dummyPlayer); + + // Log before invoking releaseLicenseRenewalThreads + std::cout << "Invoking releaseLicenseRenewalThreads method" << std::endl; + // Call the method to release active license renewal threads + drmSessionManager.releaseLicenseRenewalThreads(); + std::cout << "Executed releaseLicenseRenewalThreads method" << std::endl; + + // Log internal state changes (assumed internal thread state update) + std::cout << "Internal thread state updated to indicate threads have been released" << std::endl; + + std::cout << "Exiting SuccessfullyReleaseActiveLicenseRenewalThreads test" << std::endl; +} +/** + * @brief Verify multiple consecutive calls to releaseLicenseRenewalThreads execute without error and exhibit idempotent behavior. + * + * This test verifies that calling the releaseLicenseRenewalThreads method consecutively on a DrmSessionManager instance does not produce any errors or unexpected side effects. The test creates a DrmSessionManager instance and then calls the method twice to ensure that the license renewal threads are properly released each time and that the second call behaves idempotently. + * + * **Test Group ID:** Basic: 01@n + * **Test Case ID:** 080@n + * **Priority:** High@n + * + * **Pre-Conditions:** None@n + * **Dependencies:** None@n + * **User Interaction:** None@n + * + * **Test Procedure:** + * | Variation / Step | Description | Test Data | Expected Result | Notes | + * | :--------------: | ----------------------------------------------------------------------------------------- | ----------------------------------------------------------- | --------------------------------------------------------------------------------------------- | --------------- | + * | 01 | Create a DrmSessionManager instance using custom constructor with specified parameters | maxDrmSessions = 10, dummyPlayer = nullptr | DrmSessionManager instance is created successfully | Should be successful | + * | 02 | Invoke the first call of releaseLicenseRenewalThreads method | No input parameter | License renewal threads (if any) are released without errors | Should Pass | + * | 03 | Invoke the second call of releaseLicenseRenewalThreads method to test idempotent behavior | No input parameter | Second call executes without error and confirms idempotent behavior | Should Pass | + * | 04 | Log overall success message indicating both calls executed successfully | No input parameter | Log output confirms that both invocations of releaseLicenseRenewalThreads completed successfully | Should be successful | + */ +TEST(DrmSessionManager, MultipleConsecutiveCallsToReleaseLicenseRenewalThreads) { + std::cout << "Entering MultipleConsecutiveCallsToReleaseLicenseRenewalThreads test" << std::endl; + + // Create a DrmSessionManager object using the custom constructor + int maxDrmSessions = 10; + void* dummyPlayer = nullptr; + std::cout << "Creating DrmSessionManager object with maxDrmSessions: " << maxDrmSessions + << " and player: " << dummyPlayer << std::endl; + DrmSessionManager drmSessionManager(maxDrmSessions, dummyPlayer); + + // First invocation of releaseLicenseRenewalThreads + std::cout << "Invoking first call of releaseLicenseRenewalThreads method" << std::endl; + drmSessionManager.releaseLicenseRenewalThreads(); + std::cout << "First call executed, active license renewal threads (if any) have been released." << std::endl; + + // Second invocation of releaseLicenseRenewalThreads + std::cout << "Invoking second call of releaseLicenseRenewalThreads method" << std::endl; + drmSessionManager.releaseLicenseRenewalThreads(); + std::cout << "Second call executed, confirming idempotent behavior without errors." << std::endl; + + // Log overall success message indicating both calls executed successfully without exceptions. + std::cout << "Both invocations of releaseLicenseRenewalThreads completed successfully" << std::endl; + + std::cout << "Exiting MultipleConsecutiveCallsToReleaseLicenseRenewalThreads test" << std::endl; +} +/** + * @brief Tests that the DrmSessionManager correctly handles live playback settings. + * + * This test verifies that when setPlaybackSpeedState is invoked with parameters for live playback, + * the DrmSessionManager updates its internal state to reflect live playback at the normal speed. + * + * **Test Group ID:** Basic: 01 + * **Test Case ID:** 081 + * **Priority:** High + * + * **Pre-Conditions:** None + * **Dependencies:** None + * **User Interaction:** None + * + * **Test Procedure:** + * | Variation / Step | Description | Test Data | Expected Result | Notes | + * | :----: | --------- | ---------- |-------------- | ----- | + * | 01 | Create DrmSessionManager instance using custom constructor | drmSessionManager constructor: parameter1 = 10, parameter2 = nullptr | Instance is created successfully | Should be successful | + * | 02 | Invoke setPlaybackSpeedState with live playback parameters | live = true, currentLatency = 50.0, livepoint = true, liveOffsetMs = 0.0, speed = 1, positionMs = 1000.0, firstFrameSeen = false | API processes input and sets internal state for live playback at normal speed | Should Pass | + */ +TEST(DrmSessionManager, StandardLivePlayback) { + std::cout << "Entering StandardLivePlayback test" << std::endl; + // Create a DrmSessionManager instance using a custom constructor + DrmSessionManager drmSessionManager(10, nullptr); + std::cout << "Invoking setPlaybackSpeedState with parameters: live = true, currentLatency = 50.0, livepoint = true, liveOffsetMs = 0.0, speed = 1, positionMs = 1000.0, firstFrameSeen = false" << std::endl; + + drmSessionManager.setPlaybackSpeedState(true, 50.0, true, 0.0, 1, 1000.0, false); + + std::cout << "Method setPlaybackSpeedState executed. Internal state should reflect live playback at normal speed (live=true, speed=1, position=1000.0)" << std::endl; + std::cout << "Exiting StandardLivePlayback test" << std::endl; +} +/** + * @brief Verify VOD playback functionality by setting playback speed and position + * + * This test validates that the DrmSessionManager correctly updates the playback state for on-demand (VOD) content. The test ensures that invoking setPlaybackSpeedState with specific parameters reflects the expected on-demand playback behavior. + * + * **Test Group ID:** Basic: 01 + * **Test Case ID:** 082 + * **Priority:** High + * + * **Pre-Conditions:** None + * **Dependencies:** None + * **User Interaction:** None + * + * **Test Procedure:** + * | Variation / Step | Description | Test Data | Expected Result | Notes | + * | :----: | --------- | ---------- |-------------- | ----- | + * | 01 | Instantiate DrmSessionManager object with an initial session count and a null session listener | input1 = 10, input2 = nullptr | Object is instantiated successfully with proper initial state | Should be successful | + * | 02 | Invoke setPlaybackSpeedState to set on-demand playback parameters | live = false, currentLatency = 0.0, livepoint = false, liveOffsetMs = 0.0, speed = 1, positionMs = 5000.0, firstFrameSeen = false | Internal state is updated to reflect on-demand playback with playback speed set to 1 and position to 5000.0 | Should Pass | + */ +TEST(DrmSessionManager, VODPlayback) { + std::cout << "Entering VODPlayback test" << std::endl; + DrmSessionManager drmSessionManager(10, nullptr); + std::cout << "Invoking setPlaybackSpeedState with parameters: live = false, currentLatency = 0.0, livepoint = false, liveOffsetMs = 0.0, speed = 1, positionMs = 5000.0, firstFrameSeen = false" << std::endl; + + drmSessionManager.setPlaybackSpeedState(false, 0.0, false, 0.0, 1, 5000.0, false); + + std::cout << "Method setPlaybackSpeedState executed. Internal state should reflect on-demand playback (live=false, speed=1, position=5000.0)" << std::endl; + std::cout << "Exiting VODPlayback test" << std::endl; +} +/** + * @brief Verify correct behavior of setPlaybackSpeedState for live playback when the first frame is received + * + * This test verifies that when live playback conditions are met—specifically with live mode enabled, a valid latency, livepoint true, a positive live offset, and with the first frame seen—the API setPlaybackSpeedState correctly processes these inputs to update the internal state to reflect live playback with the first frame received. + * + * **Test Group ID:** Basic: 01 + * **Test Case ID:** 083 + * **Priority:** High + * + * **Pre-Conditions:** None + * **Dependencies:** None + * **User Interaction:** None + * + * **Test Procedure:** + * | Variation / Step | Description | Test Data | Expected Result | Notes | + * | :----: | --------- | ---------- |-------------- | ----- | + * | 01 | Instantiate DrmSessionManager with initial parameters | input: bufferSize = 10, dependency = nullptr | DrmSessionManager instance should be created successfully | Should be successful | + * | 02 | Invoke setPlaybackSpeedState with live playback parameters and firstFrameSeen true | input: live = true, currentLatency = 30.0, livepoint = true, liveOffsetMs = 10.0, speed = 1, positionMs = 1200.0, firstFrameSeen = true | Internal state of DrmSessionManager should update to reflect live playback with first frame received | Should Pass | + */ +TEST(DrmSessionManager, LiveWithFirstFrameSeen) { + std::cout << "Entering LiveWithFirstFrameSeen test" << std::endl; + DrmSessionManager drmSessionManager(10, nullptr); + std::cout << "Invoking setPlaybackSpeedState with parameters: live = true, currentLatency = 30.0, livepoint = true, liveOffsetMs = 10.0, speed = 1, positionMs = 1200.0, firstFrameSeen = true" << std::endl; + + drmSessionManager.setPlaybackSpeedState(true, 30.0, true, 10.0, 1, 1200.0, true); + + std::cout << "Method setPlaybackSpeedState executed. Internal state should reflect live playback with first frame received (firstFrameSeen=true)" << std::endl; + std::cout << "Exiting LiveWithFirstFrameSeen test" << std::endl; +} +/** + * @brief Verify that setPlaybackSpeedState handles negative currentLatency appropriately. + * + * This test verifies that when a negative value is provided as the currentLatency to the setPlaybackSpeedState method, the DrmSessionManager object handles it per the expected error handling logic. The objective is to check whether the API detects and manages the anomaly when negative latency is input. + * + * **Test Group ID:** Basic: 01@n + * **Test Case ID:** 084@n + * **Priority:** High@n + * + * **Pre-Conditions:** None@n + * **Dependencies:** None@n + * **User Interaction:** None@n + * + * **Test Procedure:**@n + * | Variation / Step | Description | Test Data | Expected Result | Notes | + * | :----: | --------- | ---------- |-------------- | ----- | + * | 01 | Initialize DrmSessionManager instance with valid parameters. | sessionId = 10, errorHandler = nullptr | Instance should be created successfully. | Should be successful | + * | 02 | Invoke setPlaybackSpeedState with negative currentLatency value. | live = true, currentLatency = -10.0, livepoint = true, liveOffsetMs = 0.0, speed = 1, positionMs = 1000.0, firstFrameSeen = false | API should handle negative latency appropriately, with error handling or corrective measures implemented. | Should Fail | + */ +TEST(DrmSessionManager, NegativeCurrentLatency) { + std::cout << "Entering NegativeCurrentLatency test" << std::endl; + DrmSessionManager drmSessionManager(10, nullptr); + std::cout << "Invoking setPlaybackSpeedState with parameters: live = true, currentLatency = -10.0, livepoint = true, liveOffsetMs = 0.0, speed = 1, positionMs = 1000.0, firstFrameSeen = false" << std::endl; + + drmSessionManager.setPlaybackSpeedState(true, -10.0, true, 0.0, 1, 1000.0, false); + + std::cout << "Method setPlaybackSpeedState executed. Negative latency should be handled appropriately while updating playback speed state" << std::endl; + std::cout << "Exiting NegativeCurrentLatency test" << std::endl; +} +/** + * @brief Test that setPlaybackSpeedState handles negative liveOffsetMs parameter correctly. + * + * This test validates that invoking setPlaybackSpeedState with a negative liveOffsetMs value is processed in a controlled manner, ensuring that the playback speed state update mechanism can handle negative offsets gracefully without causing unexpected behavior. + * + * **Test Group ID:** Basic: 01@n + * **Test Case ID:** 085@n + * **Priority:** High@n + * + * **Pre-Conditions:** None@n + * **Dependencies:** None@n + * **User Interaction:** None@n + * + * **Test Procedure:** + * | Variation / Step | Description | Test Data | Expected Result | Notes | + * | :----: | --------- | ---------- |-------------- | ----- | + * | 01 | Invoke setPlaybackSpeedState with negative liveOffsetMs to check for controlled handling of negative offset. | live = true, currentLatency = 20.0, livepoint = true, liveOffsetMs = -50.0, speed = 1, positionMs = 2000.0, firstFrameSeen = false | Method should handle the negative liveOffsetMs value gracefully, updating the playback speed state appropriately without errors. | Should Fail | + */ +TEST(DrmSessionManager, NegativeLiveOffsetMs) { + std::cout << "Entering NegativeLiveOffsetMs test" << std::endl; + DrmSessionManager drmSessionManager(10, nullptr); + std::cout << "Invoking setPlaybackSpeedState with parameters: live = true, currentLatency = 20.0, livepoint = true, liveOffsetMs = -50.0, speed = 1, positionMs = 2000.0, firstFrameSeen = false" << std::endl; + + drmSessionManager.setPlaybackSpeedState(true, 20.0, true, -50.0, 1, 2000.0, false); + + std::cout << "Method setPlaybackSpeedState executed. Negative liveOffsetMs should be processed in a controlled manner while updating playback speed state" << std::endl; + std::cout << "Exiting NegativeLiveOffsetMs test" << std::endl; +} +/** + * @brief Verify that setting playback speed to zero correctly results in a paused playback state. + * + * This test verifies that when setPlaybackSpeedState is invoked with a speed value of 0, + * the DrmSessionManager internal state correctly reflects a paused playback state. + * + * **Test Group ID:** Basic: 01@n + * **Test Case ID:** 086@n + * **Priority:** High@n + * + * **Pre-Conditions:** None@n + * **Dependencies:** None@n + * **User Interaction:** None@n + * + * **Test Procedure:** + * | Variation / Step | Description | Test Data | Expected Result | Notes | + * | :----: | -------------------------------------------------------------- | --------------------------------------------------------------------------------------------- | ------------------------------------------------- | ------------- | + * | 01 | Initialize DrmSessionManager object | constructor param1 = 10, param2 = nullptr | Object is created successfully | Should be successful | + * | 02 | Call setPlaybackSpeedState with zero playback speed | live = false, currentLatency = 0.0, livepoint = false, liveOffsetMs = 0.0, speed = 0, positionMs = 3000.0, firstFrameSeen = false | Playback speed state updated to paused (speed=0) | Should Pass | + * | 03 | Verify output logs indicating state update execution | N/A | Expected log outputs are observed | Should be successful | + */ +TEST(DrmSessionManager, ZeroPlaybackSpeed) { + std::cout << "Entering ZeroPlaybackSpeed test" << std::endl; + DrmSessionManager drmSessionManager(10, nullptr); + std::cout << "Invoking setPlaybackSpeedState with parameters: live = false, currentLatency = 0.0, livepoint = false, liveOffsetMs = 0.0, speed = 0, positionMs = 3000.0, firstFrameSeen = false" << std::endl; + + drmSessionManager.setPlaybackSpeedState(false, 0.0, false, 0.0, 0, 3000.0, false); + + std::cout << "Method setPlaybackSpeedState executed. Internal state should reflect paused playback (speed=0)" << std::endl; + std::cout << "Exiting ZeroPlaybackSpeed test" << std::endl; +} +/** + * @brief Verify that reverse playback is correctly handled by DrmSessionManager. + * + * This test validates the reverse playback functionality by invoking setPlaybackSpeedState with a negative speed value. + * It ensures that the internal state of DrmSessionManager reflects reverse playback or that proper error handling is in place + * when negative speeds are provided. + * + * **Test Group ID:** Basic: 01@n + * **Test Case ID:** 087@n + * **Priority:** High@n + * + * **Pre-Conditions:** None@n + * **Dependencies:** None@n + * **User Interaction:** None@n + * + * **Test Procedure:**@n + * | Variation / Step | Description | Test Data | Expected Result | Notes | + * | :--------------: | ------------------------------------------------------------------------------- | ----------------------------------------------------------------------------------------------------------------------------- | -------------------------------------------------------------------------------------------------- | ------------------- | + * | 01 | Instantiate DrmSessionManager with valid parameters | initialValue = 10, callback = nullptr | Instance created successfully | Should be successful| + * | 02 | Invoke setPlaybackSpeedState with reverse playback parameters | live = false, currentLatency = 10.0, livepoint = false, liveOffsetMs = 0.0, speed = -1, positionMs = 1500.0, firstFrameSeen = false | API executes and internal state reflects reverse playback or proper error handling for negative speed| Should Pass | + * | 03 | Verify logs indicate execution and test completion | Observing console outputs | Log messages confirm execution of setPlaybackSpeedState and expected behavior | Should be successful| + */ +TEST(DrmSessionManager, ReversePlayback) { + std::cout << "Entering ReversePlayback test" << std::endl; + DrmSessionManager drmSessionManager(10, nullptr); + std::cout << "Invoking setPlaybackSpeedState with parameters: live = false, currentLatency = 10.0, livepoint = false, liveOffsetMs = 0.0, speed = -1, positionMs = 1500.0, firstFrameSeen = false" << std::endl; + + drmSessionManager.setPlaybackSpeedState(false, 10.0, false, 0.0, -1, 1500.0, false); + + std::cout << "Method setPlaybackSpeedState executed. Internal state should reflect reverse playback or error handling for negative speed" << std::endl; + std::cout << "Exiting ReversePlayback test" << std::endl; +} +/** + * @brief Tests the setPlaybackSpeedState API with extreme input values + * + * This test verifies that the DrmSessionManager correctly handles extreme input values when invoking setPlaybackSpeedState. The objective is to ensure that the internal state is updated accordingly without overflow or unexpected behavior when provided with high numeric values. + * + * **Test Group ID:** Basic: 01@n + * **Test Case ID:** 088@n + * **Priority:** High@n + * + * **Pre-Conditions:** None@n + * **Dependencies:** None@n + * **User Interaction:** None@n + * + * **Test Procedure:**@n + * | Variation / Step | Description | Test Data | Expected Result | Notes | + * | :--------------: | -------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------- | ----------------------------------------------------------------------------------------- | --------------- | + * | 01 | Initialize DrmSessionManager object | capacity = 10, pointer = nullptr | Instance is created successfully without exceptions | Should be successful | + * | 02 | Invoke setPlaybackSpeedState with extreme input values | live = true, currentLatency = 1000.0, livepoint = true, liveOffsetMs = 500.0, speed = 1000, positionMs = 10000000.0, firstFrameSeen = true | Method executes without errors and internal state is updated with extreme values | Should Pass | + */ +TEST(DrmSessionManager, ExtremeValues) { + std::cout << "Entering ExtremeValues test" << std::endl; + DrmSessionManager drmSessionManager(10, nullptr); + std::cout << "Invoking setPlaybackSpeedState with parameters: live = true, currentLatency = 1000.0, livepoint = true, liveOffsetMs = 500.0, speed = 1000, positionMs = 10000000.0, firstFrameSeen = true" << std::endl; + + drmSessionManager.setPlaybackSpeedState(true, 1000.0, true, 500.0, 1000, 10000000.0, true); + + std::cout << "Method setPlaybackSpeedState executed. Internal state should reflect extreme input values without causing overflow or unexpected behavior" << std::endl; + std::cout << "Exiting ExtremeValues test" << std::endl; +} +/** + * @brief Validates that the DrmSessionManager accepts valid session manager states. + * + * This test verifies that the DrmSessionManager object correctly updates its state when provided with valid session manager states. It ensures that no errors are raised during state transitions from inactive to active. + * + * **Test Group ID:** Basic: 01@n + * **Test Case ID:** 089@n + * **Priority:** High@n + * + * **Pre-Conditions:** None@n + * **Dependencies:** None@n + * **User Interaction:** None@n + * + * **Test Procedure:** + * | Variation / Step | Description | Test Data | Expected Result | Notes | + * | :-------------: | --------------------------------------------------------------------------- | ------------------------------------------------------ | ----------------------------------------------------------------------------------- | ------------- | + * | 01 | Create a DrmSessionManager instance using a valid constructor | maxDrmSessions = 10, player = nullptr | Object is successfully created | Should be successful | + * | 02 | Define valid session manager states | validStates = { eSESSIONMGR_INACTIVE, eSESSIONMGR_ACTIVE } | Valid states are defined and available for use | Should be successful | + * | 03 | Invoke setSessionMgrState for each valid state | state = eSESSIONMGR_INACTIVE, then state = eSESSIONMGR_ACTIVE | API successfully updates the state without error | Should Pass | + * | 04 | Confirm that no error occurred using an assertion | output: true | EXPECT_TRUE returns true indicating no error | Should be successful | + */ +TEST(DrmSessionManager, SetValidSessionMgrStates) { + std::cout << "Entering SetValidSessionMgrStates test" << std::endl; + + // Create an object of DrmSessionManager using a valid constructor. + // Here, we use 10 for maxDrmSessions and nullptr for player. + DrmSessionManager drmManager(10, nullptr); + + // Define the valid states to test. + const SessionMgrState validStates[] = { eSESSIONMGR_INACTIVE, eSESSIONMGR_ACTIVE }; + + // Loop over each valid state and set it. + for (size_t i = 0; i < sizeof(validStates)/sizeof(validStates[0]); ++i) { + SessionMgrState state = validStates[i]; + std::cout << "Invoking setSessionMgrState with valid value: " << state << std::endl; + drmManager.setSessionMgrState(state); + std::cout << "DrmSessionManager state updated to: " << state << std::endl; + } + + // Confirm that no error occurred. + EXPECT_TRUE(true); + + std::cout << "Exiting SetValidSessionMgrStates test" << std::endl; +} +/** + * @brief Validate that setSessionMgrState handles invalid state inputs gracefully. + * + * This test verifies that when setSessionMgrState is called with invalid state values, + * the DrmSessionManager does not crash or misbehave. The test involves invoking the API + * with two distinct invalid states and confirming that the system remains stable. + * + * **Test Group ID:** Basic: 01@n + * **Test Case ID:** 090@n + * **Priority:** High@n + * + * **Pre-Conditions:** None@n + * **Dependencies:** None@n + * **User Interaction:** None@n + * + * **Test Procedure:**@n + * | Variation / Step | Description | Test Data | Expected Result | Notes | + * | :--------------: | ------------------------------------------------------------------ | ------------------------------------------------------------ | ------------------------------------------------------------------------- | ----------- | + * | 01 | Invoke setSessionMgrState with an invalid state value of -1 | input1 = 10, input2 = nullptr, state = -1 | API returns gracefully without crash, assertion EXPECT_TRUE(true) | Should Pass | + * | 02 | Invoke setSessionMgrState with an invalid state value of 999 | input1 = 10, input2 = nullptr, state = 999 | API returns gracefully without crash, assertion EXPECT_TRUE(true) | Should Pass | + */ +TEST(DrmSessionManager, SetInvalidSessionMgrStates) { + std::cout << "Entering SetInvalidSessionMgrStates test" << std::endl; + + // Create an object of DrmSessionManager using a valid constructor. + DrmSessionManager drmManager(10, nullptr); + + // Define the invalid state values. + SessionMgrState invalidStates[] = { static_cast(-1), static_cast(999) }; + + // Loop through each invalid state and attempt to set it. + for (size_t i = 0; i < sizeof(invalidStates)/sizeof(invalidStates[0]); ++i) { + SessionMgrState state = invalidStates[i]; + std::cout << "Invoking setSessionMgrState with invalid value: " << state << std::endl; + // Call the method which is expected to handle unexpected state values gracefully. + drmManager.setSessionMgrState(state); + std::cout << "DrmSessionManager handled the invalid value: " << state << " gracefully" << std::endl; + } + + // Confirm that no crash occurred during state setting. + EXPECT_TRUE(true); + + std::cout << "Exiting SetInvalidSessionMgrStates test" << std::endl; +} +/** + * @brief Verify that enabling video mute for live streaming functions correctly with valid parameters. + * + * This test validates that the DrmSessionManager::setVideoMute API does not throw any exceptions when invoked with valid parameters for enabling video mute during a live streaming scenario. The test ensures that the internal state update simulation is performed as expected. + * + * **Test Group ID:** Basic: 01@n + * **Test Case ID:** 091@n + * **Priority:** High@n + * + * **Pre-Conditions:** None@n + * **Dependencies:** None@n + * **User Interaction:** None@n + * + * **Test Procedure:**@n + * | Variation / Step | Description | Test Data | Expected Result | Notes | + * | :----: | --------- | ---------- |-------------- | ----- | + * | 01 | Create an instance of DrmSessionManager using the custom constructor. | input1 = 5, input2 = nullptr | Instance created successfully. | Should be successful | + * | 02 | Define the input parameters for enabling video mute in live streaming. | live = true, currentLatency = 0.5, livepoint = true, liveOffsetMs = 100.0, videoMuteStatus = true, positionMs = 50.0 | Parameters set with valid values. | Should be successful | + * | 03 | Invoke setVideoMute with the specified live streaming parameters. | live = true, currentLatency = 0.5, livepoint = true, liveOffsetMs = 100.0, videoMuteStatus = true, positionMs = 50.0 | Method executes without throwing exceptions and outputs confirmation logs. | Should Pass | + */ +TEST(DrmSessionManager, PositiveTest_EnableVideoMute_LiveStreaming) { + std::cout << "Entering PositiveTest_EnableVideoMute_LiveStreaming test" << std::endl; + + // Create object with custom constructor. + DrmSessionManager drmSessionManager(5, nullptr); + + // Define input parameters. + bool live = true; + double currentLatency = 0.5; + bool livepoint = true; + double liveOffsetMs = 100.0; + bool videoMuteStatus = true; + double positionMs = 50.0; + + std::cout << "Invoking setVideoMute with parameters:" << std::endl; + std::cout << " live: " << live << std::endl; + std::cout << " currentLatency: " << currentLatency << std::endl; + std::cout << " livepoint: " << livepoint << std::endl; + std::cout << " liveOffsetMs: " << liveOffsetMs << std::endl; + std::cout << " videoMuteStatus: " << videoMuteStatus << std::endl; + std::cout << " positionMs: " << positionMs << std::endl; + + EXPECT_NO_THROW({ + drmSessionManager.setVideoMute(live, currentLatency, livepoint, liveOffsetMs, videoMuteStatus, positionMs); + std::cout << "Method setVideoMute invoked successfully for live streaming enabling video mute." << std::endl; + // Log internal state update simulation. + std::cout << "Assuming internal state updated: video mute enabled for live stream at position " << positionMs << std::endl; + }); + + std::cout << "Exiting PositiveTest_EnableVideoMute_LiveStreaming test" << std::endl; +} +/** + * @brief Validate that video mute can be disabled for on-demand playback using setVideoMute. + * + * This test verifies that the setVideoMute API correctly disables video mute for on-demand playback. + * It checks that the method executes without throwing exceptions and that the internal state is updated + * accordingly to reflect that video mute is disabled and the playback position is tracked correctly. + * + * **Test Group ID:** Basic: 01 + * **Test Case ID:** 092 + * **Priority:** High + * + * **Pre-Conditions:** None + * **Dependencies:** None + * **User Interaction:** None + * + * **Test Procedure:** + * | Variation / Step | Description | Test Data | Expected Result | Notes | + * | :----: | --------- | ---------- |-------------- | ----- | + * | 01 | Create DrmSessionManager object using custom constructor. | drmSessionManager: {arg1 = 5, arg2 = nullptr} | Object instantiation succeeds without exceptions. | Should be successful | + * | 02 | Define input parameters for on-demand playback scenario. | live = false, currentLatency = 0.0, livepoint = false, liveOffsetMs = 0.0, videoMuteStatus = false, positionMs = 120.0 | Input parameters are set correctly. | Should be successful | + * | 03 | Invoke setVideoMute API with defined parameters to disable video mute. | live = false, currentLatency = 0.0, livepoint = false, liveOffsetMs = 0.0, videoMuteStatus = false, positionMs = 120.0 | Method setVideoMute executes without throwing exceptions. | Should Pass | + * | 04 | Log appropriate messages indicating the test progress and success. | Console output messages | Logs are printed to indicate test entry, execution, and exit. | Should be successful | + */ + +TEST(DrmSessionManager, PositiveTest_DisableVideoMute_OnDemand) { + std::cout << "Entering PositiveTest_DisableVideoMute_OnDemand test" << std::endl; + + // Create object with custom constructor. + DrmSessionManager drmSessionManager(5, nullptr); + + // Define input parameters. + bool live = false; + double currentLatency = 0.0; + bool livepoint = false; + double liveOffsetMs = 0.0; + bool videoMuteStatus = false; + double positionMs = 120.0; + + std::cout << "Invoking setVideoMute with parameters:" << std::endl; + std::cout << " live: " << live << std::endl; + std::cout << " currentLatency: " << currentLatency << std::endl; + std::cout << " livepoint: " << livepoint << std::endl; + std::cout << " liveOffsetMs: " << liveOffsetMs << std::endl; + std::cout << " videoMuteStatus: " << videoMuteStatus << std::endl; + std::cout << " positionMs: " << positionMs << std::endl; + + EXPECT_NO_THROW({ + drmSessionManager.setVideoMute(live, currentLatency, livepoint, liveOffsetMs, videoMuteStatus, positionMs); + std::cout << "Method setVideoMute invoked successfully for on-demand playback disabling video mute." << std::endl; + std::cout << "Assuming internal state updated: video mute disabled and playback position tracked correctly." << std::endl; + }); + + std::cout << "Exiting PositiveTest_DisableVideoMute_OnDemand test" << std::endl; +} +/** + * @brief Test setVideoMute with negative currentLatency input to ensure the API handles negative latency without throwing exceptions. + * + * This test verifies that providing a negative value for currentLatency to the setVideoMute API does not cause any exceptions or crashes, and that the internal state is handled appropriately. The test uses a DrmSessionManager object constructed with predefined parameters and invokes the function with a negative currentLatency value. + * + * **Test Group ID:** Basic: 01@n + * **Test Case ID:** 093@n + * **Priority:** High@n + * + * **Pre-Conditions:** None@n + * **Dependencies:** None@n + * **User Interaction:** None@n + * + * **Test Procedure:**@n + * | Variation / Step | Description | Test Data | Expected Result | Notes | + * | :--------------: | --------------------------------------------------------------------------- | -------------------------------------------------------------------------------------------------------------- | --------------------------------------------------------- | --------------- | + * | 01 | Initialize DrmSessionManager with a custom constructor | constructorArg1 = 5, constructorArg2 = nullptr | Object is created successfully | Should be successful | + * | 02 | Define input parameters for setVideoMute including negative currentLatency | live = true, currentLatency = -10.0, livepoint = true, liveOffsetMs = 100.0, videoMuteStatus = true, positionMs = 30.0 | Parameters are assigned correctly | Should be successful | + * | 03 | Invoke setVideoMute and verify that no exceptions are thrown | live = true, currentLatency = -10.0, livepoint = true, liveOffsetMs = 100.0, videoMuteStatus = true, positionMs = 30.0 | No exception is thrown; API handles negative latency as expected | Should Pass | + */ +TEST(DrmSessionManager, NegativeTest_NegativeLatency) { + std::cout << "Entering NegativeTest_NegativeLatency test" << std::endl; + + // Create object with custom constructor. + DrmSessionManager drmSessionManager(5, nullptr); + + // Define input parameters with negative currentLatency. + bool live = true; + double currentLatency = -10.0; + bool livepoint = true; + double liveOffsetMs = 100.0; + bool videoMuteStatus = true; + double positionMs = 30.0; + + std::cout << "Invoking setVideoMute with parameters (including negative currentLatency):" << std::endl; + std::cout << " live: " << live << std::endl; + std::cout << " currentLatency: " << currentLatency << std::endl; + std::cout << " livepoint: " << livepoint << std::endl; + std::cout << " liveOffsetMs: " << liveOffsetMs << std::endl; + std::cout << " videoMuteStatus: " << videoMuteStatus << std::endl; + std::cout << " positionMs: " << positionMs << std::endl; + + EXPECT_NO_THROW({ + drmSessionManager.setVideoMute(live, currentLatency, livepoint, liveOffsetMs, videoMuteStatus, positionMs); + std::cout << "Method setVideoMute invoked successfully with negative currentLatency." << std::endl; + std::cout << "Assuming internal state handled negative latency appropriately." << std::endl; + }); + + std::cout << "Exiting NegativeTest_NegativeLatency test" << std::endl; +} +/** + * @brief Validate that setVideoMute gracefully handles negative live offset values. + * + * This test verifies that when a negative liveOffsetMs value is passed to setVideoMute, the API method handles the input + * without throwing any exceptions, thereby ensuring that the internal state manages negative offsets gracefully. + * + * **Test Group ID:** Basic: 01@n + * **Test Case ID:** 094@n + * **Priority:** (High) + * @n + * **Pre-Conditions:** None@n + * **Dependencies:** None@n + * **User Interaction:** None@n + * @n + * **Test Procedure:**@n + * | Variation / Step | Description | Test Data | Expected Result | Notes | + * | :----: | --------- | ---------- |-------------- | ----- | + * | 01 | Instantiate DrmSessionManager using custom constructor. | constructor arg1 = 5, arg2 = nullptr | Object instantiated successfully | Should be successful | + * | 02 | Define input parameters with negative liveOffsetMs. | live = true, currentLatency = 1.0, livepoint = true, liveOffsetMs = -50.0, videoMuteStatus = true, positionMs = 30.0 | Parameters initialized for API invocation | Should be successful | + * | 03 | Invoke setVideoMute API with negative liveOffsetMs. | live = true, currentLatency = 1.0, livepoint = true, liveOffsetMs = -50.0, videoMuteStatus = true, positionMs = 30.0 | API call completes without throwing an exception | Should Pass | + * | 04 | Log method invocation completion. | No input | Log messages indicate successful API invocation | Should be successful | + */ +TEST(DrmSessionManager, NegativeTest_NegativeLiveOffset) { + std::cout << "Entering NegativeTest_NegativeLiveOffset test" << std::endl; + + // Create object with custom constructor. + DrmSessionManager drmSessionManager(5, nullptr); + + // Define input parameters with negative liveOffsetMs. + bool live = true; + double currentLatency = 1.0; + bool livepoint = true; + double liveOffsetMs = -50.0; + bool videoMuteStatus = true; + double positionMs = 30.0; + + std::cout << "Invoking setVideoMute with parameters (including negative liveOffsetMs):" << std::endl; + std::cout << " live: " << live << std::endl; + std::cout << " currentLatency: " << currentLatency << std::endl; + std::cout << " livepoint: " << livepoint << std::endl; + std::cout << " liveOffsetMs: " << liveOffsetMs << std::endl; + std::cout << " videoMuteStatus: " << videoMuteStatus << std::endl; + std::cout << " positionMs: " << positionMs << std::endl; + + EXPECT_NO_THROW({ + drmSessionManager.setVideoMute(live, currentLatency, livepoint, liveOffsetMs, videoMuteStatus, positionMs); + std::cout << "Method setVideoMute invoked successfully with negative liveOffsetMs." << std::endl; + std::cout << "Assuming internal state handled negative live offset gracefully." << std::endl; + }); + + std::cout << "Exiting NegativeTest_NegativeLiveOffset test" << std::endl; +} +/** + * @brief Test setVideoMute function with zero latency, offset, and position. + * + * This test verifies that the setVideoMute function in the DrmSessionManager class correctly handles edge case input values where latency, offset, and position are zero. It ensures that the method does not throw exceptions and updates the internal state appropriately. + * + * **Test Group ID:** Basic: 01 + * **Test Case ID:** 095 + * **Priority:** High + * + * **Pre-Conditions:** None + * **Dependencies:** None + * **User Interaction:** None + * + * **Test Procedure:** + * | Variation / Step | Description | Test Data | Expected Result | Notes | + * | :----: | --------- | ---------- | -------------- | ----- | + * | 01 | Create DrmSessionManager instance and invoke setVideoMute with zero latency, offset, and position | drmSessionManager(5, nullptr), live = false, currentLatency = 0.0, livepoint = false, liveOffsetMs = 0.0, videoMuteStatus = true, positionMs = 0.0 | Method setVideoMute completes without throwing exceptions and updates internal state correctly | Should Pass | + */ +TEST(DrmSessionManager, EdgeTest_ZeroLatencyOffsetPosition) { + std::cout << "Entering EdgeTest_ZeroLatencyOffsetPosition test" << std::endl; + + // Create object with custom constructor. + DrmSessionManager drmSessionManager(5, nullptr); + + // Define input parameters with zero latency, offset, and position. + bool live = false; + double currentLatency = 0.0; + bool livepoint = false; + double liveOffsetMs = 0.0; + bool videoMuteStatus = true; + double positionMs = 0.0; + + std::cout << "Invoking setVideoMute with zero latency, offset and position:" << std::endl; + std::cout << " live: " << live << std::endl; + std::cout << " currentLatency: " << currentLatency << std::endl; + std::cout << " livepoint: " << livepoint << std::endl; + std::cout << " liveOffsetMs: " << liveOffsetMs << std::endl; + std::cout << " videoMuteStatus: " << videoMuteStatus << std::endl; + std::cout << " positionMs: " << positionMs << std::endl; + + EXPECT_NO_THROW({ + drmSessionManager.setVideoMute(live, currentLatency, livepoint, liveOffsetMs, videoMuteStatus, positionMs); + std::cout << "Method setVideoMute invoked successfully with zero values." << std::endl; + std::cout << "Assuming internal state updated correctly despite zero latency, offset, and position." << std::endl; + }); + + std::cout << "Exiting EdgeTest_ZeroLatencyOffsetPosition test" << std::endl; +} +/** + * @brief Verify that setVideoMute handles negative playback position gracefully + * + * This test verifies that when the setVideoMute API is invoked with a negative positionMs value, + * it does not throw an exception and assumes proper internal handling of the negative playback position. + * + * **Test Group ID:** Basic: 01 + * **Test Case ID:** 096 + * **Priority:** High + * + * **Pre-Conditions:** None + * **Dependencies:** None + * **User Interaction:** None + * + * **Test Procedure:** + * | Variation / Step | Description | Test Data | Expected Result | Notes | + * | :--------------: | ------------------------------------------------------------ | ------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------ | ------------------ | + * | 01 | Create DrmSessionManager object with custom constructor | constructorArg1 = 5, constructorArg2 = nullptr | Object is created without throwing an exception | Should be successful | + * | 02 | Invoke setVideoMute with negative positionMs | live = false, currentLatency = 2.0, livepoint = false, liveOffsetMs = 200.0, videoMuteStatus = false, positionMs = -5.0 | Method executes without throwing and handles negative playback position correctly | Should Pass | + */ +TEST(DrmSessionManager, NegativeTest_NegativePositionMs) { + std::cout << "Entering NegativeTest_NegativePositionMs test" << std::endl; + + // Create object with custom constructor. + DrmSessionManager drmSessionManager(5, nullptr); + + // Define input parameters with negative positionMs. + bool live = false; + double currentLatency = 2.0; + bool livepoint = false; + double liveOffsetMs = 200.0; + bool videoMuteStatus = false; + double positionMs = -5.0; + + std::cout << "Invoking setVideoMute with parameters (including negative positionMs):" << std::endl; + std::cout << " live: " << live << std::endl; + std::cout << " currentLatency: " << currentLatency << std::endl; + std::cout << " livepoint: " << livepoint << std::endl; + std::cout << " liveOffsetMs: " << liveOffsetMs << std::endl; + std::cout << " videoMuteStatus: " << videoMuteStatus << std::endl; + std::cout << " positionMs: " << positionMs << std::endl; + + EXPECT_NO_THROW({ + drmSessionManager.setVideoMute(live, currentLatency, livepoint, liveOffsetMs, videoMuteStatus, positionMs); + std::cout << "Method setVideoMute invoked successfully with negative positionMs." << std::endl; + std::cout << "Assuming internal state handled negative playback position appropriately." << std::endl; + }); + + std::cout << "Exiting NegativeTest_NegativePositionMs test" << std::endl; +} +/** + * @brief Validate that setVideoWindowSize correctly updates video window dimensions when provided with positive values. + * + * This test verifies that the DrmSessionManager's setVideoWindowSize method properly updates the internal video window size when supplied with valid, positive width and height dimensions. The test ensures the DrmSessionManager is correctly instantiated and that the method call executes as expected, reflecting the updated dimensions. + * + * **Test Group ID:** Basic: 01@n + * **Test Case ID:** 097@n + * **Priority:** High@n + * + * **Pre-Conditions:** None@n + * **Dependencies:** None@n + * **User Interaction:** None@n + * + * **Test Procedure:** + * | Variation / Step | Description | Test Data | Expected Result | Notes | + * | :----: | --------- | ---------- |-------------- | ----- | + * | 01 | Instantiate DrmSessionManager and invoke setVideoWindowSize with valid positive dimensions | maxDrmSessions = 5, player = nullptr, width = 640, height = 480 | Internal video window size updated to 640 x 480 as per method execution | Should Pass | + */ +TEST(DrmSessionManager, SetValidVideoWindowSizePositiveDimensions) { + std::cout << "Entering SetValidVideoWindowSizePositiveDimensions test" << std::endl; + + // Create object using custom constructor (maxDrmSessions = 5, player = nullptr) + DrmSessionManager drmManager(5, nullptr); + std::cout << "Created DrmSessionManager object with maxDrmSessions = 5 and player = nullptr" << std::endl; + + // Log method invocation and input values + int width = 640; + int height = 480; + std::cout << "Invoking setVideoWindowSize with width = " << width << " and height = " << height << std::endl; + + // Invoke the method + drmManager.setVideoWindowSize(width, height); + std::cout << "Method setVideoWindowSize executed with values width: " << width << " and height: " << height << std::endl; + + // Debug log for expected internal state update + std::cout << "Expected: Video window size updated to " << width << " x " << height << std::endl; + + std::cout << "Exiting SetValidVideoWindowSizePositiveDimensions test" << std::endl; +} +/** + * @brief Validate functionality of setVideoWindowSize when passed zero dimensions. + * + * This test checks whether the DrmSessionManager correctly handles the case when both width and height are set to zero. It verifies that the method is invoked with the provided zero values and that the video window size is updated to 0 x 0 without errors. + * + * **Test Group ID:** Basic: 01 + * **Test Case ID:** 098 + * **Priority:** High + * + * **Pre-Conditions:** None + * **Dependencies:** None + * **User Interaction:** None + * + * **Test Procedure:** + * | Variation / Step | Description | Test Data | Expected Result | Notes | + * | :----: | --------- | ---------- |-------------- | ----- | + * | 01 | Create DrmSessionManager object with maxDrmSessions = 5 and player = nullptr | maxDrmSessions = 5, player = nullptr | Object is created successfully | Should be successful | + * | 02 | Invoke setVideoWindowSize with width = 0 and height = 0 | width = 0, height = 0 | Method executes without error and video window size is updated to 0 x 0 | Should Pass | + */ +TEST(DrmSessionManager, SetVideoWindowSizeWithZeroDimensions) { + std::cout << "Entering SetVideoWindowSizeWithZeroDimensions test" << std::endl; + + // Create object using custom constructor (maxDrmSessions = 5, player = nullptr) + DrmSessionManager drmManager(5, nullptr); + std::cout << "Created DrmSessionManager object with maxDrmSessions = 5 and player = nullptr" << std::endl; + + // Log method invocation and input values + int width = 0; + int height = 0; + std::cout << "Invoking setVideoWindowSize with width = " << width << " and height = " << height << std::endl; + + // Invoke the method + drmManager.setVideoWindowSize(width, height); + std::cout << "Method setVideoWindowSize executed with values width: " << width << " and height: " << height << std::endl; + + // Debug log for expected internal state update + std::cout << "Expected: Video window size updated to " << width << " x " << height << std::endl; + + std::cout << "Exiting SetVideoWindowSizeWithZeroDimensions test" << std::endl; +} +/** + * @brief Test negative width input for setting video window size ensures invalid width is handled properly + * + * This test verifies that providing a negative value for the video window width is handled appropriately by the DrmSessionManager. + * It confirms that the internal state remains unchanged or an error status is logged when an invalid width is passed. + * + * **Test Group ID:** Basic: 01@n + * **Test Case ID:** 099@n + * **Priority:** (High) + * + * **Pre-Conditions:** None@n + * **Dependencies:** None@n + * **User Interaction:** None@n + * + * **Test Procedure:** + * | Variation / Step | Description | Test Data | Expected Result | Notes | + * | :--------------: | ----------------------------------------------------------------------------- | ---------------------------------------------- | ------------------------------------------------------------------------------------------------ | --------------- | + * | 01 | Construct DrmSessionManager object using maxDrmSessions=5 and player=nullptr | maxDrmSessions = 5, player = nullptr | Object is created successfully | Should be successful | + * | 02 | Initialize video window size with valid parameters (width = 640, height = 480) | initWidth = 640, initHeight = 480 | Video window size updated successfully | Should Pass | + * | 03 | Invoke setVideoWindowSize with negative width (-640) and valid height (480) | width = -640, height = 480 | Invalid width input handled appropriately; internal state remains unchanged or error logged | Should Fail | + */ +TEST(DrmSessionManager, SetVideoWindowSizeWithNegativeWidth) { + std::cout << "Entering SetVideoWindowSizeWithNegativeWidth test" << std::endl; + + // Create object using custom constructor (maxDrmSessions = 5, player = nullptr) + DrmSessionManager drmManager(5, nullptr); + std::cout << "Created DrmSessionManager object with maxDrmSessions = 5 and player = nullptr" << std::endl; + + // Optionally, set an initial valid state + int initWidth = 640, initHeight = 480; + std::cout << "Initializing video window size to width = " << initWidth << " and height = " << initHeight << std::endl; + drmManager.setVideoWindowSize(initWidth, initHeight); + + // Log method invocation and input values for invalid test input + int width = -640; + int height = 480; + std::cout << "Invoking setVideoWindowSize with invalid width = " << width << " and valid height = " << height << std::endl; + + // Invoke the method with negative width + drmManager.setVideoWindowSize(width, height); + std::cout << "Method setVideoWindowSize executed with values width: " << width << " and height: " << height << std::endl; + + // Debug log indicating expected behavior (internal state should be handled appropriately) + std::cout << "Expected: Invalid width input handled appropriately; internal state should remain unchanged or error status logged" << std::endl; + + std::cout << "Exiting SetVideoWindowSizeWithNegativeWidth test" << std::endl; +} +/** + * @brief Verify that setVideoWindowSize correctly handles negative height values. + * + * This test validates that when a negative height is provided to the setVideoWindowSize API, the method handles it appropriately by either rejecting the value or not updating the internal state. The test creates a valid initial state with positive dimensions, then applies a negative height to examine API behavior. + * + * **Test Group ID:** Basic: 01@n + * **Test Case ID:** 100@n + * **Priority:** High@n + * + * **Pre-Conditions:** None@n + * **Dependencies:** None@n + * **User Interaction:** None@n + * + * **Test Procedure:** + * | Variation / Step | Description | Test Data | Expected Result | Notes | + * | :--------------: | --------------------------------------------------------------------------------------------------- | ----------------------------------------------------------------- | ---------------------------------------------------------------------------------------------------------------------------- | ------------- | + * | 01 | Create DrmSessionManager object with maxDrmSessions = 5 and player = nullptr | maxDrmSessions = 5, player = nullptr | DrmSessionManager object is successfully created | Should be successful | + * | 02 | Initialize video window size to width = 640 and height = 480 | initWidth = 640, initHeight = 480 | Video window size is set to a valid state (width = 640, height = 480) | Should be successful | + * | 03 | Invoke setVideoWindowSize with valid width = 640 and invalid negative height = -480 | width = 640, height = -480 | API handles the negative height appropriately; internal state remains unchanged or an error status is logged | Should Fail | + */ +TEST(DrmSessionManager, SetVideoWindowSizeWithNegativeHeight) { + std::cout << "Entering SetVideoWindowSizeWithNegativeHeight test" << std::endl; + + // Create object using custom constructor (maxDrmSessions = 5, player = nullptr) + DrmSessionManager drmManager(5, nullptr); + std::cout << "Created DrmSessionManager object with maxDrmSessions = 5 and player = nullptr" << std::endl; + + // Set an initial valid state + int initWidth = 640, initHeight = 480; + std::cout << "Initializing video window size to width = " << initWidth << " and height = " << initHeight << std::endl; + drmManager.setVideoWindowSize(initWidth, initHeight); + + // Log method invocation and input values for invalid test input + int width = 640; + int height = -480; + std::cout << "Invoking setVideoWindowSize with valid width = " << width << " and invalid height = " << height << std::endl; + + // Invoke the method with negative height + drmManager.setVideoWindowSize(width, height); + std::cout << "Method setVideoWindowSize executed with values width: " << width << " and height: " << height << std::endl; + + // Debug log indicating expected behavior (invalid height should be handled appropriately) + std::cout << "Expected: Invalid height input handled appropriately; internal state should remain unchanged or error status logged" << std::endl; + + std::cout << "Exiting SetVideoWindowSizeWithNegativeHeight test" << std::endl; +} +/** + * @brief Tests setVideoWindowSize with extremely large integer dimensions. + * + * This test verifies that the setVideoWindowSize API can handle extreme dimension values by invoking it with maximum integer values for width and height, ensuring the method performs the update correctly without failure. + * + * **Test Group ID:** Basic: 01@n + * **Test Case ID:** 101@n + * **Priority:** High@n + * + * **Pre-Conditions:** None@n + * **Dependencies:** None@n + * **User Interaction:** None@n + * + * **Test Procedure:** + * | Variation / Step | Description | Test Data | Expected Result | Notes | + * | :--------------: | --------------------------------------------------------------- | ---------------------------------------------- | ------------------------------------------------------------------------------- | ------------------ | + * | 01 | Create a DrmSessionManager object using a custom constructor | maxDrmSessions = 5, player = nullptr | Object is successfully created | Should be successful | + * | 02 | Invoke setVideoWindowSize with maximum integer dimensions | input: width = INT_MAX, height = INT_MAX | Method executes without error and updates the video window size accordingly | Should Pass | + */ +TEST(DrmSessionManager, SetVideoWindowSizeWithLargeDimensions) { + std::cout << "Entering SetVideoWindowSizeWithLargeDimensions test" << std::endl; + + // Create object using custom constructor (maxDrmSessions = 5, player = nullptr) + DrmSessionManager drmManager(5, nullptr); + std::cout << "Created DrmSessionManager object with maxDrmSessions = 5 and player = nullptr" << std::endl; + + // Log method invocation and input values for large dimensions + int width = INT_MAX; + int height = INT_MAX; + std::cout << "Invoking setVideoWindowSize with extremely large dimensions: width = " << width << " and height = " << height << std::endl; + + // Invoke the method + drmManager.setVideoWindowSize(width, height); + std::cout << "Method setVideoWindowSize executed with values width: " << width << " and height: " << height << std::endl; + + // Debug log for expected internal state update + std::cout << "Expected: Video window size updated to maximum allowable values (" << width << " x " << height << ")" << std::endl; + + std::cout << "Exiting SetVideoWindowSizeWithLargeDimensions test" << std::endl; +} +/** + * @brief Verify valid session handle and proper system data for DRM session manager. + * + * This test validates that the DRM session manager correctly handles a valid session handle and proper system data + * by successfully invoking the watermarkSessionHandlerWrapper method. The objective is to ensure the API executes + * without error when provided with a correctly initialized DRM session manager, a valid session handle, a successful + * status, and valid system data. + * + * **Test Group ID:** Basic: 01@n + * **Test Case ID:** 102@n + * **Priority:** High@n + * + * **Pre-Conditions:** None@n + * **Dependencies:** None@n + * **User Interaction:** None@n + * + * **Test Procedure:**@n + * | Variation / Step | Description | Test Data | Expected Result | Notes | + * | :--------------: | ---------------------------------------------------------------------- | --------------------------------------------------------------- | ----------------------------------------------------------- | ----------------- | + * | 01 | Construct the DrmSessionManager object using a custom constructor. | input1 = 10, input2 = nullptr | Object is created successfully. | Should be successful | + * | 02 | Set up the input parameters for the API invocation. | sessionHndle = 1, status = 200, systemData = "ValidSystemData" | Input parameters are initialized correctly. | Should be successful | + * | 03 | Invoke watermarkSessionHandlerWrapper with the prepared input parameters. | sessionHndle = 1, status = 200, systemData = "ValidSystemData" | API invoked successfully, returns void without errors. | Should Pass | + */ +TEST(DrmSessionManager, ValidSessionHandleAndProperSystemData) +{ + std::cout << "Entering ValidSessionHandleAndProperSystemData test" << std::endl; + + // Construct the object using custom constructor. + DrmSessionManager drmManager(10, nullptr); + + // Set up input parameters. + uint32_t sessionHndle = 1; + uint32_t status = 200; + std::string systemData = "ValidSystemData"; + + std::cout << "Invoking watermarkSessionHandlerWrapper with sessionHndle = " + << sessionHndle << ", status = " << status + << ", systemData = " << systemData << std::endl; + + // Invoke method. + drmManager.watermarkSessionHandlerWrapper(sessionHndle, status, systemData); + + std::cout << "Exiting ValidSessionHandleAndProperSystemData test" << std::endl; +} +/** + * @brief Validate behavior with minimum boundary values for session handle and status + * + * This test verifies that the DrmSessionManager API correctly handles the minimal boundary values for session handle and status. It creates a manager instance with dummy parameters, sets the session handle and status to their boundary minimum value (0), and invokes the watermarkSessionHandlerWrapper function to ensure the API call is made successfully. + * + * **Test Group ID:** Basic: 01@n + * **Test Case ID:** 103@n + * **Priority:** High@n + * + * **Pre-Conditions:** None@n + * **Dependencies:** None@n + * **User Interaction:** None@n + * + * **Test Procedure:**@n + * | Variation / Step | Description | Test Data | Expected Result | Notes | + * | :--------------: | ------------------------------------------------------------- | ------------------------------------------------------ | ----------------------------------------------------------------------- | ------------- | + * | 01 | Create an instance of DrmSessionManager with dummy parameters | Parameter1 = 10, Parameter2 = nullptr | Instance created successfully | Should be successful | + * | 02 | Set the session handle, status, and systemData with boundary minimum values | sessionHndle = 0, status = 0, systemData = MinimalData | Variables set to expected boundary values | Should be successful | + * | 03 | Invoke watermarkSessionHandlerWrapper function with the prepared inputs | sessionHndle = 0, status = 0, systemData = MinimalData | Function executed without error; API returns expected behavior (if applicable) | Should Pass | + */ +TEST(DrmSessionManager, BoundaryValuesWithMinimumSessionHandleAndStatus) +{ + std::cout << "Entering BoundaryValuesWithMinimumSessionHandleAndStatus test" << std::endl; + + // Create instance with dummy parameters. + DrmSessionManager drmManager(10, nullptr); + + // Set boundary input parameters. + uint32_t sessionHndle = 0; + uint32_t status = 0; + std::string systemData = "MinimalData"; + + std::cout << "Invoking watermarkSessionHandlerWrapper with sessionHndle = " + << sessionHndle << ", status = " << status + << ", systemData = " << systemData << std::endl; + + drmManager.watermarkSessionHandlerWrapper(sessionHndle, status, systemData); + + std::cout << "Exiting BoundaryValuesWithMinimumSessionHandleAndStatus test" << std::endl; +} +/** + * @brief Validate handling of maximum uint32_t values for session handle and status + * + * This test evaluates the API’s capability to manage the maximum boundary values for both session handle and status by passing the maximum uint32_t values (4294967295) along with a sample system data string. The objective is to ensure that watermarkSessionHandlerWrapper handles edge cases correctly without any errors. + * + * **Test Group ID:** Basic: 01@n + * **Test Case ID:** 104@n + * **Priority:** High@n + * + * **Pre-Conditions:** None@n + * **Dependencies:** None@n + * **User Interaction:** None@n + * + * **Test Procedure:**@n + * | Variation / Step | Description | Test Data | Expected Result | Notes | + * | :----: | --------- | ---------- | -------------- | ----- | + * | 01 | Initialize DrmSessionManager with dummy parameters and invoke watermarkSessionHandlerWrapper with max uint32_t values for session handle and status along with a sample system data string | sessionHndle = 4294967295, status = 4294967295, systemData = MaximalData | API call handles maximum values correctly without errors | Should Pass | + */ +TEST(DrmSessionManager, MaximumValuesForSessionHandleAndStatus) +{ + std::cout << "Entering MaximumValuesForSessionHandleAndStatus test" << std::endl; + + // Create instance with dummy parameters. + DrmSessionManager drmManager(10, nullptr); + + // Maximum values for uint32_t. + uint32_t sessionHndle = 4294967295u; + uint32_t status = 4294967295u; + std::string systemData = "MaximalData"; + + std::cout << "Invoking watermarkSessionHandlerWrapper with sessionHndle = " + << sessionHndle << ", status = " << status + << ", systemData = " << systemData << std::endl; + + drmManager.watermarkSessionHandlerWrapper(sessionHndle, status, systemData); + + std::cout << "Exiting MaximumValuesForSessionHandleAndStatus test" << std::endl; +} +/** + * @brief Test the handling of an empty systemData string in the watermarkSessionHandlerWrapper API. + * + * This test verifies that the watermarkSessionHandlerWrapper API can handle an empty string for the systemData parameter appropriately. The test constructs a DrmSessionManager instance with a custom constructor and calls the API with an empty systemData string to ensure it processes this scenario without errors. + * + * **Test Group ID:** Basic: 01@n + * **Test Case ID:** 105@n + * **Priority:** High@n + * + * **Pre-Conditions:** None@n + * **Dependencies:** None@n + * **User Interaction:** None@n + * + * **Test Procedure:** + * | Variation / Step | Description | Test Data | Expected Result | Notes | + * | :--------------: | ------------------------------------------------------------------------------------ | -------------------------------------------------- | ---------------------------------------------------- | ------------- | + * | 01 | Create an instance of DrmSessionManager using the custom constructor. | constructor param1 = 10, param2 = nullptr | Instance created successfully. | Should be successful | + * | 02 | Invoke watermarkSessionHandlerWrapper with sessionHndle, status, and empty systemData. | sessionHndle = 100, status = 50, systemData = "" | API call completes without errors. | Should Pass | + */ +TEST(DrmSessionManager, HandlingEmptySystemDataString) +{ + std::cout << "Entering HandlingEmptySystemDataString test" << std::endl; + + // Create instance using custom constructor. + DrmSessionManager drmManager(10, nullptr); + + // Inputs with empty system data. + uint32_t sessionHndle = 100; + uint32_t status = 50; + std::string systemData = ""; + + std::cout << "Invoking watermarkSessionHandlerWrapper with sessionHndle = " + << sessionHndle << ", status = " << status + << ", systemData (empty string)" << std::endl; + + drmManager.watermarkSessionHandlerWrapper(sessionHndle, status, systemData); + + std::cout << "Exiting HandlingEmptySystemDataString test" << std::endl; +} +/** + * @brief Test DrmSessionManager API for handling unsupported status codes. + * + * This test verifies that the DrmSessionManager::watermarkSessionHandlerWrapper function correctly handles an unsupported status code by invoking the API with a deliberately invalid status value along with valid session handle and system data. + * + * **Test Group ID:** Basic: 01@n + * **Test Case ID:** 106@n + * **Priority:** High@n + * + * **Pre-Conditions:** None@n + * **Dependencies:** None@n + * **User Interaction:** None@n + * + * **Test Procedure:**@n + * | Variation / Step | Description | Test Data | Expected Result | Notes | + * | :----: | ------------------------------------------------------------------- | ---------------------------------------------------------------------- | ------------------------------------------------------------------------------- | -------------- | + * | 01 | Create an instance of DrmSessionManager using the custom constructor | input1 = 10, input2 = nullptr | Instance of DrmSessionManager is created successfully | Should be successful | + * | 02 | Prepare test data with an unsupported status code | input1 = sessionHndle, value = 10; input2 = status, value = 9999; input3 = systemData, value = "InvalidStatusData" | Test data is correctly prepared | Should be successful | + * | 03 | Invoke watermarkSessionHandlerWrapper with the prepared test data | sessionHndle = 10, status = 9999, systemData = "InvalidStatusData" | The API should process the unsupported status code scenario as per design specifications | Should Pass | + */ +TEST(DrmSessionManager, UnsupportedStatusCodeScenario) +{ + std::cout << "Entering UnsupportedStatusCodeScenario test" << std::endl; + + // Create instance using custom constructor. + DrmSessionManager drmManager(10, nullptr); + + // Input with unsupported status code. + uint32_t sessionHndle = 10; + uint32_t status = 9999; + std::string systemData = "InvalidStatusData"; + + std::cout << "Invoking watermarkSessionHandlerWrapper with sessionHndle = " + << sessionHndle << ", status = " << status + << ", systemData = " << systemData << std::endl; + + drmManager.watermarkSessionHandlerWrapper(sessionHndle, status, systemData); + + std::cout << "Exiting UnsupportedStatusCodeScenario test" << std::endl; +} +/** + * @brief Validate that watermarkSessionHandlerWrapper correctly processes system data containing special or corrupt characters. + * + * This test validates that watermarkSessionHandlerWrapper successfully handles system data, which contains special characters. + * It constructs a DrmSessionManager instance, prepares a special characters string using strncpy, and invokes the API + * using predefined session handle and status values. + * + * **Test Group ID:** Basic: 01@n + * **Test Case ID:** 107@n + * **Priority:** High@n + * + * **Pre-Conditions:** None@n + * **Dependencies:** None@n + * **User Interaction:** None@n + * + * **Test Procedure:**@n + * | Variation / Step | Description | Test Data | Expected Result | Notes | + * | :----: | --------- | ---------- |-------------- | ----- | + * | 01 | Create DrmSessionManager instance using the custom constructor | input1 = sessionSize: 10, input2 = nullptr, output: instance created | Instance is created successfully | Should be successful | + * | 02 | Prepare systemData containing special characters using strncpy | input1 = srcData: "!@#$%^&*()_+-=[]{}|;':,./<>?", output: specialData buffer filled and null terminated | Buffer contains the expected special characters string | Should be successful | + * | 03 | Invoke watermarkSessionHandlerWrapper with sessionHndle, status, and systemData | input1 = sessionHndle: 10, input2 = status: 400, input3 = systemData: string with special characters, output: API call result | API call is executed without errors and processes the input correctly | Should Pass | + */ +TEST(DrmSessionManager, SystemDataContainingSpecialOrCorruptCharacters) +{ + std::cout << "Entering SystemDataContainingSpecialOrCorruptCharacters test" << std::endl; + + // Create instance using custom constructor. + DrmSessionManager drmManager(10, nullptr); + + // Input with special characters in systemData. + uint32_t sessionHndle = 10; + uint32_t status = 400; + + // Assign fixed-size array value using strncpy. + char specialData[64]; + const char* srcData = "!@#$%^&*()_+-=[]{}|;':,./<>?"; + strncpy(specialData, srcData, sizeof(specialData) - 1); + specialData[sizeof(specialData) - 1] = '\0'; + + std::string systemData(specialData); + + std::cout << "Invoking watermarkSessionHandlerWrapper with sessionHndle = " + << sessionHndle << ", status = " << status + << ", systemData = " << systemData << std::endl; + + drmManager.watermarkSessionHandlerWrapper(sessionHndle, status, systemData); + + std::cout << "Exiting SystemDataContainingSpecialOrCorruptCharacters test" << std::endl; +} +/** + * @brief Test for verifying valid destruction of a DrmSessionManager object + * + * This test verifies that a DrmSessionManager object is constructed with valid parameters (maxDrmSessions = 5 and player = nullptr) and that its destructor is implicitly invoked without throwing exceptions when the object goes out of scope. The test ensures that the internal state logs are printed correctly during construction and destruction. + * + * **Test Group ID:** Basic: 01@n + * **Test Case ID:** 108@n + * **Priority:** High@n + * + * **Pre-Conditions:** None@n + * **Dependencies:** None@n + * **User Interaction:** None@n + * + * **Test Procedure:** + * | Variation / Step | Description | Test Data | Expected Result | Notes | + * | :----: | --------- | ---------- |-------------- | ----- | + * | 01 | Invoke DrmSessionManager constructor with maxDrmSessions = 5 and player set to nullptr, then allow the object to go out of scope to invoke the destructor implicitly | input1 = 5, input2 = nullptr, output1 = internal log outputs | DrmSessionManager object is constructed successfully and its destructor is invoked on scope exit without exceptions | Should Pass | + */ +TEST(DrmSessionManager, Destructor_ValidDestruction) { + std::cout << "Entering Destructor_ValidDestruction test" << std::endl; + + { + std::cout << "Invoking DrmSessionManager constructor with maxDrmSessions = 5 and player = nullptr" << std::endl; + DrmSessionManager drmSessionManager(5, nullptr); + std::cout << "DrmSessionManager object constructed successfully. Internal state:" << std::endl; + std::cout << " maxDrmSessions: 5" << std::endl; + std::cout << " player pointer: " << static_cast(nullptr) << std::endl; + // Additional internal state logs can be added here as needed. + std::cout << "Leaving local scope to invoke destructor implicitly" << std::endl; + } + + std::cout << "DrmSessionManager destructor was invoked as object went out of scope without throwing exceptions" << std::endl; + std::cout << "Exiting Destructor_ValidDestruction test" << std::endl; +} + +/** + * @brief Validate that a valid LAProfileBegin callback is registered and correctly invoked. + * + * This test verifies that the DrmSessionManager can register a valid lambda callback for LAProfileBegin, + * and upon simulating the callback invocation, it updates the status variable as expected. The objective + * is to ensure that the registration mechanism works correctly in a positive scenario. + * + * **Test Group ID:** Basic: 01@n + * **Test Case ID:** 109@n + * **Priority:** High@n + * + * **Pre-Conditions:** None@n + * **Dependencies:** None@n + * **User Interaction:** None@n + * + * **Test Procedure:**@n + * | Variation / Step | Description | Test Data | Expected Result | Notes | + * | :----: | --------- | ---------- |-------------- | ----- | + * | 01 | Create a DrmSessionManager instance using a custom constructor | maxDrmSessions = 3, player = nullptr | DrmSessionManager object is created successfully | Should be successful | + * | 02 | Initialize the callbackStatus variable to -1 | callbackStatus = -1 | callbackStatus is set to -1 | Should be successful | + * | 03 | Define a lambda callback that updates callbackStatus when invoked | lambdaCallback defined to update callbackStatus with received status | Lambda callback is defined correctly | Should be successful | + * | 04 | Register the lambda callback using RegisterLAProfBegin | callback = lambdaCallback | LAProfileBegin callback is successfully registered in laprofileBeginCb | Should Pass | + * | 05 | Simulate the invocation of the registered callback with testStatus = 10 | testStatus = 10 | The lambda callback is invoked and updates callbackStatus to 10 | Should Pass | + * | 06 | Validate the callback invocation by asserting callbackStatus equals testStatus | callbackStatus expected value = 10, testStatus = 10 | ASSERT_EQ verifies that callbackStatus equals 10 | Should Pass | + */ +TEST(DrmSessionManager, RegisterValidLAProfileBegin) { + std::cout << "Entering RegisterValidLAProfileBegin test" << std::endl; + + // Create DrmSessionManager object using a custom constructor (maxDrmSessions=3, dummy player pointer) + DrmSessionManager drmManager(3, nullptr); + std::cout << "Created DrmSessionManager object with maxDrmSessions=3 and player=nullptr" << std::endl; + + // Define a variable to capture the status value from the callback + int callbackStatus = -1; + std::cout << "Initialized callbackStatus to " << callbackStatus << std::endl; + + // Define a lambda callback that takes an int parameter and updates callbackStatus + auto lambdaCallback = [&callbackStatus](int status) { + std::cout << "Inside lambda callback: received status = " << status << std::endl; + callbackStatus = status; + }; + std::cout << "Defined lambda callback for LAProfileBegin with expected behavior" << std::endl; + + // Invoke RegisterLAProfBegin to register the lambda callback + std::cout << "Invoking DrmSessionManager::RegisterLAProfBegin with lambda callback" << std::endl; + drmManager.RegisterLAProfBegin(lambdaCallback); + std::cout << "Registered lambda callback to laprofileBeginCb" << std::endl; + + // Simulate invocation of the registered callback with an int argument (e.g., 10) + int testStatus = 10; + std::cout << "Invoking the registered laprofileBeginCb with test status " << testStatus << std::endl; + drmManager.laprofileBeginCb(testStatus); + + // Verify that the callback updated callbackStatus appropriately + std::cout << "After callback invocation, callbackStatus = " << callbackStatus << std::endl; + ASSERT_EQ(callbackStatus, testStatus); + + std::cout << "Exiting RegisterValidLAProfileBegin test" << std::endl; +} +/** + * @brief Test to validate handling of an empty (null) LAProfileBegin callback registration + * + * This test verifies that when an empty (null) callback is registered with the DrmSessionManager, + * the internal callback (laprofileBeginCb) remains empty. It ensures that the system correctly handles + * registration of a null callback without causing unexpected behavior. + * + * **Test Group ID:** Basic: 01@n + * **Test Case ID:** 110@n + * **Priority:** High@n + * + * **Pre-Conditions:** None@n + * **Dependencies:** None@n + * **User Interaction:** None@n + * + * **Test Procedure:** + * | Variation / Step | Description | Test Data | Expected Result | Notes | + * | :--------------: | ---------------------------------------------------------------------------------------- | ----------------------------------------------------------------- | --------------------------------------------------------------------------- | ------------- | + * | 01 | Create DrmSessionManager object using a custom constructor | maxDrmSessions = 3, player = nullptr | Object is created successfully | Should be successful | + * | 02 | Define an empty (null) LAProfileBegin callback | emptyCallback = nullptr | Empty callback is defined | Should be successful | + * | 03 | Invoke RegisterLAProfBegin with the empty callback | callback parameter = nullptr | Internal callback (laprofileBeginCb) is set to empty | Should Pass | + * | 04 | Verify that the internal callback is empty via assertion | No direct input; check internal state | ASSERT_FALSE confirms that laprofileBeginCb evaluates to false | Should Pass | + */ +TEST(DrmSessionManager, RegisterEmptyLAProfileBegin) { + std::cout << "Entering RegisterEmptyLAProfileBegin test" << std::endl; + + // Create DrmSessionManager object using a custom constructor (maxDrmSessions=3, dummy player pointer) + DrmSessionManager drmManager(3, nullptr); + std::cout << "Created DrmSessionManager object with maxDrmSessions=3 and player=nullptr" << std::endl; + + // Define an empty (null) LAProfileBegin callback + std::function emptyCallback = nullptr; + std::cout << "Defined an empty (null) callback" << std::endl; + + // Invoke RegisterLAProfBegin with the empty callback + std::cout << "Invoking DrmSessionManager::RegisterLAProfBegin with empty callback" << std::endl; + drmManager.RegisterLAProfBegin(emptyCallback); + std::cout << "Registered empty callback to laprofileBeginCb" << std::endl; + + // Verify that the internal callback is empty + if (!drmManager.laprofileBeginCb) { + std::cout << "laprofileBeginCb is empty as expected" << std::endl; + } else { + std::cout << "laprofileBeginCb is not empty, unexpected behavior" << std::endl; + } + + // Attempting to invoke an empty callback should not be performed, but we confirm its emptiness via the bool operator. + ASSERT_FALSE(static_cast(drmManager.laprofileBeginCb)); + + std::cout << "Exiting RegisterEmptyLAProfileBegin test" << std::endl; +} +/** + * @brief Validate that RegisterLAProfEnd correctly registers and invokes a valid callback. + * + * This test creates an instance of DrmSessionManager with specific parameters, registers a valid lambda callback that updates a flag, and then invokes the callback to verify that it updates the flag as expected. The objective is to ensure that the API correctly assigns and executes the provided callback. + * + * **Test Group ID:** Basic: 01 + * **Test Case ID:** 111 + * **Priority:** High + * + * **Pre-Conditions:** None + * **Dependencies:** None + * **User Interaction:** None + * + * **Test Procedure:** + * | Variation / Step | Description | Test Data | Expected Result | Notes | + * | :--------------: | ----------- | --------- | --------------- | ----- | + * | 01 | Instantiate DrmSessionManager with maxDrmSessions = 10 and player = nullptr. | input: maxDrmSessions = 10, player = nullptr | Instance is created successfully. | Should be successful | + * | 02 | Define a lambda callback that sets a flag (callbackInvoked) to true upon invocation with a streamType parameter. | input: lambda callback, streamType parameter; output: callbackInvoked flag = false initially, then true after invocation | Lambda callback is defined correctly. | Should be successful | + * | 03 | Register the defined valid callback using RegisterLAProfEnd. | input: callback = lambda callback | Callback is registered and assigned to laprofileEndCb. | Should be successful | + * | 04 | Invoke the registered callback with streamType = 1. | input: streamType = 1 | callbackInvoked flag is updated to true. | Should Pass | + * | 05 | Validate that callbackInvoked is true via the EXPECT_TRUE assertion. | input: callbackInvoked flag | EXPECT_TRUE(callbackInvoked) passes confirming the callback was invoked. | Should Pass | + */ +TEST(DrmSessionManager, RegisterLAProfEnd_ValidCallback) +{ + std::cout << "Entering RegisterLAProfEnd_ValidCallback test" << std::endl; + + // Create an instance of DrmSessionManager with dummy parameters. + DrmSessionManager drmSessionManager(10, nullptr); + std::cout << "Created DrmSessionManager instance with maxDrmSessions = 10 and player = nullptr" << std::endl; + + // Prepare a flag to be updated by the lambda callback and define the lambda. + bool callbackInvoked = false; + auto callback = [&callbackInvoked](int streamType) + { + std::cout << "Lambda callback invoked with streamType: " << streamType << std::endl; + callbackInvoked = true; + std::cout << "Flag updated to: " << std::boolalpha << callbackInvoked << std::endl; + }; + + std::cout << "Invoking RegisterLAProfEnd with valid callback lambda" << std::endl; + drmSessionManager.RegisterLAProfEnd(callback); + std::cout << "Callback registered. Now invoking the registered callback with streamType 1" << std::endl; + + // Invoke the callback via the object's member to verify assignment. + if (drmSessionManager.laprofileEndCb) + { + drmSessionManager.laprofileEndCb(1); + std::cout << "After invocation, flag is: " << std::boolalpha << callbackInvoked << std::endl; + } + else + { + std::cout << "Error: Callback was not registered properly." << std::endl; + } + + EXPECT_TRUE(callbackInvoked); + std::cout << "Exiting RegisterLAProfEnd_ValidCallback test" << std::endl; +} +/** + * @brief Verify that the RegisterLAProfEnd method correctly handles an empty callback. + * + * This test validates that when an empty callback is passed to the RegisterLAProfEnd method of the DrmSessionManager, the internal callback remains empty and does not result in any unexpected behavior or exceptions. It ensures that even if the callback is empty, the system can safely attempt to invoke it without causing an error. + * + * **Test Group ID:** Basic: 01@n + * **Test Case ID:** 112@n + * **Priority:** High@n + * + * **Pre-Conditions:** None@n + * **Dependencies:** None@n + * **User Interaction:** None@n + * + * **Test Procedure:**@n + * | Variation / Step | Description | Test Data | Expected Result | Notes | + * | :----: | --------- | ---------- |-------------- | ----- | + * | 01 | Create an instance of DrmSessionManager with dummy parameters | maxDrmSessions = 10, player = nullptr | Instance is created successfully | Should be successful | + * | 02 | Create an empty (default constructed) callback | emptyCallback = default constructed std::function | Empty callback is successfully created | Should be successful | + * | 03 | Invoke RegisterLAProfEnd with the empty callback | callback = emptyCallback | laprofileEndCb remains empty in the DrmSessionManager | Should Pass | + * | 04 | Check if the callback is empty using EXPECT_FALSE | drmSessionManager.laprofileEndCb evaluated as boolean false | EXPECT_FALSE confirms the callback is empty | Should Pass | + * | 05 | Safely attempt to call the empty callback within a try-catch block | Invocation of laprofileEndCb with a sample value (1) if exists | No exception is thrown; invocation is a no-op | Should Pass | + */ +TEST(DrmSessionManager, RegisterLAProfEnd_EmptyCallback) +{ + std::cout << "Entering RegisterLAProfEnd_EmptyCallback test" << std::endl; + + // Create an instance of DrmSessionManager with dummy parameters. + DrmSessionManager drmSessionManager(10, nullptr); + std::cout << "Created DrmSessionManager instance with maxDrmSessions = 10 and player = nullptr" << std::endl; + + // Create an empty (default constructed) callback. + std::function emptyCallback; + std::cout << "Empty callback created" << std::endl; + + std::cout << "Invoking RegisterLAProfEnd with empty callback" << std::endl; + drmSessionManager.RegisterLAProfEnd(emptyCallback); + std::cout << "Empty callback registered" << std::endl; + + // Check if the callback is empty. + if (drmSessionManager.laprofileEndCb) + { + std::cout << "Error: Expected empty callback, but callback is not empty." << std::endl; + } + else + { + std::cout << "Verified that the registered callback is empty" << std::endl; + } + + EXPECT_FALSE(static_cast(drmSessionManager.laprofileEndCb)); + // Safely attempt to call the empty callback if needed. + try + { + std::cout << "Attempting to invoke the empty callback (should be a no-op)" << std::endl; + if(drmSessionManager.laprofileEndCb) + { + drmSessionManager.laprofileEndCb(1); + } + std::cout << "Invocation of empty callback completed without errors" << std::endl; + } + catch(const std::exception &e) + { + std::cout << "Exception caught when invoking empty callback: " << e.what() << std::endl; + FAIL() << "Empty callback invocation threw an exception"; + } + + std::cout << "Exiting RegisterLAProfEnd_EmptyCallback test" << std::endl; +} +/** + * @brief Verify that RegisterLAProfEnd correctly registers a lambda callback and correctly processes multiple stream types. + * + * This test registers a lambda callback using the RegisterLAProfEnd API of the DrmSessionManager. It then invokes the registered callback with various stream type values (0, -1, INT_MAX) to ensure that all provided values are captured in the internal container. This test validates the functionality of the callback registration and its correct execution for multiple stream inputs. + * + * **Test Group ID:** Basic: 01@n + * **Test Case ID:** 113@n + * **Priority:** High@n + * + * **Pre-Conditions:** None@n + * **Dependencies:** None@n + * **User Interaction:** None@n + * + * **Test Procedure:**@n + * | Variation / Step | Description | Test Data | Expected Result | Notes | + * | :--------------: | ------------------------------------------------------------------------------------------------ | ----------------------------------------------------------------- | -------------------------------------------------------------------------------------------------- | --------------- | + * | 01 | Create an instance of DrmSessionManager with dummy parameters. | input: maxDrmSessions = 10, player = nullptr | Instance is created with the specified parameters. | Should be successful | + * | 02 | Initialize a container to record received streamType values. | No input arguments. | A container (vector) is initialized and is empty. | Should be successful | + * | 03 | Define a lambda callback that records the streamType values into the container. | Callback = lambda capturing recordedStreamTypes | Lambda is defined successfully. | Should be successful | + * | 04 | Register the lambda callback using the RegisterLAProfEnd API. | input: callback = lambda | The callback is registered without error. | Should Pass | + * | 05 | Invoke the registered callback with multiple streamType values. | input: streamType values = 0, -1, INT_MAX | The callback is invoked for each streamType value leading to all values being recorded. | Should Pass | + * | 06 | Verify that the container has recorded all the streamType values in the correct order using assertions. | input: expected values = 0, -1, INT_MAX; output: container size should be 3 | The container size is 3 and the individual values are recorded as expected (0, -1, INT_MAX). | Should Pass | + * | 07 | Print the recorded streamType values to the console. | input: recordedStreamTypes vector | The streamType values are printed on the console correctly. | Should be successful | + */ +TEST(DrmSessionManager, RegisterLAProfEnd_MultiStreamTypes) +{ + std::cout << "Entering RegisterLAProfEnd_MultiStreamTypes test" << std::endl; + + // Create an instance of DrmSessionManager with dummy parameters. + DrmSessionManager drmSessionManager(10, nullptr); + std::cout << "Created DrmSessionManager instance with maxDrmSessions = 10 and player = nullptr" << std::endl; + + // Container to record received streamType values. + std::vector recordedStreamTypes; + std::cout << "Initialized container to record streamType values." << std::endl; + + // Define a lambda that records the streamType into the container. + auto callback = [&recordedStreamTypes](int streamType) + { + std::cout << "Lambda callback invoked with streamType: " << streamType << std::endl; + recordedStreamTypes.push_back(streamType); + std::cout << "Recorded streamType: " << streamType << " into container." << std::endl; + }; + + std::cout << "Invoking RegisterLAProfEnd with multi streamType callback lambda" << std::endl; + drmSessionManager.RegisterLAProfEnd(callback); + std::cout << "Callback registered. Now invoking the registered callback with various streamType values." << std::endl; + + // Test streamType values to invoke. + int testValues[] = {0, -1, INT_MAX}; + for (int value : testValues) + { + std::cout << "Invoking callback with streamType value: " << value << std::endl; + drmSessionManager.laprofileEndCb(value); + } + + // Verify that all streamType values were recorded. + ASSERT_EQ(recordedStreamTypes.size(), 3u); + EXPECT_EQ(recordedStreamTypes[0], 0); + EXPECT_EQ(recordedStreamTypes[1], -1); + EXPECT_EQ(recordedStreamTypes[2], INT_MAX); + + std::cout << "Recorded streamType values:"; + for (int value : recordedStreamTypes) + { + std::cout << " " << value; + } + std::cout << std::endl; + + std::cout << "Exiting RegisterLAProfEnd_MultiStreamTypes test" << std::endl; +} +/** + * @brief Test registering a valid LAProfileError callback in DrmSessionManager. + * + * This test verifies that providing a valid lambda as an LAProfileError callback to the DrmSessionManager successfully sets the internal callback and that the callback is callable. The test invokes the callback with a test pointer to confirm proper functionality. + * + * **Test Group ID:** Basic: 01 + * **Test Case ID:** 114 + * **Priority:** High + * + * **Pre-Conditions:** None + * **Dependencies:** None + * **User Interaction:** None + * + * **Test Procedure:** + * | Variation / Step | Description | Test Data | Expected Result | Notes | + * | :--------------: | ------------------------------------------------------------------------------------------ | --------------------------------------------------------------------------------------------------- | -------------------------------------------------------------------------------------- | ----------- | + * | 01 | Create DrmSessionManager, register valid LAProfileError callback and verify callback is set | maxDrmSessions = 10, playerPtr = 0x1234, callback = valid lambda, testPtr = 0xDEADBEEF | The callback should be properly set and callable with EXPECT_TRUE asserting its set state | Should Pass | + */ +TEST(DrmSessionManager, RegisterValidLAProfileErrorCallback) +{ + std::cout << "Entering RegisterValidLAProfileErrorCallback test" << std::endl; + + // Create a DrmSessionManager object using custom constructor. + int maxDrmSessions = 10; + void* playerPtr = reinterpret_cast(0x1234); + std::cout << "[DEBUG] Creating DrmSessionManager with maxDrmSessions=" << maxDrmSessions + << ", player pointer=" << playerPtr << std::endl; + DrmSessionManager drmSessionManager(maxDrmSessions, playerPtr); + + // Define a valid LAProfileError callback lambda. + auto validCallback = [](void* ptr) + { + std::cout << "[DEBUG] LAProfileError callback invoked with ptr: " << ptr << std::endl; + }; + std::cout << "[DEBUG] Valid LAProfileError callback lambda created." << std::endl; + + // Invoke RegisterLAProfError with the valid lambda. + std::cout << "[DEBUG] Invoking RegisterLAProfError with the valid callback." << std::endl; + drmSessionManager.RegisterLAProfError(validCallback); + + // Verify that the internal laprofileErrorCb is set (callable). + if (drmSessionManager.laprofileErrorCb) + { + std::cout << "[DEBUG] laprofileErrorCb is set. Now invoking the callback with test pointer 0xDEADBEEF." << std::endl; + void* testPtr = reinterpret_cast(0xDEADBEEF); + drmSessionManager.laprofileErrorCb(testPtr); + std::cout << "[DEBUG] Callback invocation completed." << std::endl; + EXPECT_TRUE(static_cast(drmSessionManager.laprofileErrorCb)); + } + else + { + std::cout << "[DEBUG] Error: laprofileErrorCb is not set as expected." << std::endl; + FAIL() << "laprofileErrorCb not set"; + } + + std::cout << "Exiting RegisterValidLAProfileErrorCallback test" << std::endl; +} +/** + * @brief Test to verify that registering an empty LAProfile error callback does not set the internal callback in DrmSessionManager + * + * This test validates that when a default-constructed (empty) LAProfile error callback is registered using the RegisterLAProfError method of DrmSessionManager, the internal callback remains uninitialized. The test ensures that the implementation behaves correctly when provided with an empty callback, effectively verifying defensive programming and error handling. + * + * **Test Group ID:** Basic: 01 + * **Test Case ID:** 115 + * **Priority:** High + * + * **Pre-Conditions:** None + * **Dependencies:** None + * **User Interaction:** None + * + * **Test Procedure:** + * | Variation / Step | Description | Test Data | Expected Result | Notes | + * | :----: | --------- | ---------- |-------------- | ----- | + * | 01 | Create a DrmSessionManager instance with specific parameters | input: maxDrmSessions = 5, playerPtr = nullptr | DrmSessionManager instance is created successfully | Should be successful | + * | 02 | Create a default-constructed (empty) LAProfileError callback | input: emptyCallback default constructed | Empty callback is created | Should be successful | + * | 03 | Invoke RegisterLAProfError using the empty callback | input: LAProfileError callback = emptyCallback | Internal laprofileErrorCb remains empty after invocation | Should Pass | + * | 04 | Verify that laprofileErrorCb remains empty using EXPECT_FALSE check | output: laprofileErrorCb value | Callback is verified to be empty | Should Pass | + */ +TEST(DrmSessionManager, RegisterEmptyLAProfileErrorCallback) +{ + std::cout << "Entering RegisterEmptyLAProfileErrorCallback test" << std::endl; + + // Create a DrmSessionManager object using custom constructor. + int maxDrmSessions = 5; + void* playerPtr = nullptr; + std::cout << "[DEBUG] Creating DrmSessionManager with maxDrmSessions=" << maxDrmSessions + << ", player pointer=" << playerPtr << std::endl; + DrmSessionManager drmSessionManager(maxDrmSessions, playerPtr); + + // Create a default-constructed (empty) LAProfileError callback. + std::function emptyCallback; + std::cout << "[DEBUG] Default-constructed (empty) LAProfileError callback created." << std::endl; + + // Invoke RegisterLAProfError with the empty callback. + std::cout << "[DEBUG] Invoking RegisterLAProfError with the empty callback." << std::endl; + drmSessionManager.RegisterLAProfError(emptyCallback); + + // Verify that the internal laprofileErrorCb is empty (not callable). + if (!drmSessionManager.laprofileErrorCb) + { + std::cout << "[DEBUG] laprofileErrorCb is empty as expected." << std::endl; + } + else + { + std::cout << "[DEBUG] Error: laprofileErrorCb is unexpectedly set." << std::endl; + } + EXPECT_FALSE(static_cast(drmSessionManager.laprofileErrorCb)); + + std::cout << "Exiting RegisterEmptyLAProfileErrorCallback test" << std::endl; +} +/** + * @brief Validate successful registration and invocation of a valid callback in DrmSessionManager. + * + * Validate registration and execution of a non-null callback that returns a shared_ptr with an int value of 42. This test checks that the callback is stored correctly and when invoked, produces the correct output. + * + * **Test Group ID:** Basic: 01 + * **Test Case ID:** 115 + * **Priority:** High + * + * **Pre-Conditions:** None + * **Dependencies:** None + * **User Interaction:** None + * + * **Test Procedure:** + * | Variation / Step | Description | Test Data | Expected Result |Notes | + * | :----: | --------- | ---------- |-------------- | ----- | + * | 01 | Create a DrmSessionManager instance with maxDrmSessions=5 and player=nullptr | input: maxDrmSessions = 5, player = nullptr | Instance is created successfully |Should be successful | + * | 02 | Define a valid callback that returns a non-null shared_ptr with int value 42 | input: callback lambda, output: shared_ptr with value = 42 | Callback returns non-null shared_ptr with expected value |Should Pass | + * | 03 | Register the callback using RegisterMetaDataCb | input: callback function | Callback is stored successfully in DrmMetaDataCb |Should Pass | + * | 04 | Invoke the registered callback and verify the returned value | output from callback invocation: non-null shared_ptr with value = 42, ASSERT_EQ check | Return pointer is non-null and int value equals 42 |Should Pass | + */ +TEST(DrmSessionManager, RegisterValidCallbackNonNull) { + std::cout << "Entering RegisterValidCallbackNonNull test" << std::endl; + + // Create an instance of DrmSessionManager using the custom constructor + DrmSessionManager manager(5, nullptr); + std::cout << "Created DrmSessionManager instance with maxDrmSessions = 5 and player = nullptr" << std::endl; + + // Define a valid callback that returns a non-null shared pointer containing an int value 42 + auto callback = []() -> std::shared_ptr { + auto spInt = std::make_shared(42); + std::cout << "Inside callback: Created shared_ptr with value " << *spInt << std::endl; + return spInt; + }; + std::cout << "Invoking RegisterMetaDataCb with callback that returns non-null shared_ptr (int value 42)" << std::endl; + + // Register the callback + manager.RegisterMetaDataCb(callback); + std::cout << "Callback registered successfully" << std::endl; + + // Invoke the registered callback and check that the returned pointer is non-null and holds the expected value + if (manager.DrmMetaDataCb) { + std::cout << "DrmMetaDataCb is valid. Invoking the callback." << std::endl; + std::shared_ptr result = manager.DrmMetaDataCb(); + if (result) { + // Cast the void pointer to int pointer and check value + std::shared_ptr intResult = std::static_pointer_cast(result); + std::cout << "Callback returned a valid shared_ptr. Retrieved int value: " << *intResult << std::endl; + ASSERT_EQ(*intResult, 42); + } else { + std::cout << "Callback returned a null shared_ptr." << std::endl; + FAIL() << "Expected non-null shared_ptr but got null."; + } + } else { + std::cout << "DrmMetaDataCb is empty after registration." << std::endl; + FAIL() << "Expected valid callback stored in DrmMetaDataCb."; + } + + std::cout << "Exiting RegisterValidCallbackNonNull test" << std::endl; +} +/** + * @brief Test RegisterEmptyCallback functionality in DrmSessionManager + * + * This test validates that the DrmSessionManager correctly handles registration of an empty (null) callback by ensuring that after registering such a callback, the internal callback (DrmMetaDataCb) remains empty. This is to confirm that the API does not erroneously assign a non-empty callback when an empty one is provided. + * + * **Test Group ID:** Basic: 01@n + * **Test Case ID:** 116@n + * **Priority:** High@n + * + * **Pre-Conditions:** None@n + * **Dependencies:** None@n + * **User Interaction:** None@n + * + * **Test Procedure:**@n + * | Variation / Step | Description | Test Data | Expected Result | Notes | + * | :----: | --------- | ---------- |-------------- | ----- | + * | 01 | Create a DrmSessionManager instance using a custom constructor. | maxDrmSessions = 5, player = nullptr | Instance is created without exceptions. | Should be successful | + * | 02 | Define an empty callback using a default constructed std::function. | emptyCallback = default constructed std::function()> | emptyCallback is empty. | Should be successful | + * | 03 | Register the empty callback using RegisterMetaDataCb. | input callback = emptyCallback | DrmMetaDataCb stored in manager remains empty. | Should Pass | + * | 04 | Verify that the stored DrmMetaDataCb is empty. | internal state check | DrmMetaDataCb is empty; assertion check passes. | Should Pass | + */ +TEST(DrmSessionManager, RegisterEmptyCallback) { + std::cout << "Entering RegisterEmptyCallback test" << std::endl; + + // Create an instance of DrmSessionManager using the custom constructor + DrmSessionManager manager(5, nullptr); + std::cout << "Created DrmSessionManager instance with maxDrmSessions = 5 and player = nullptr" << std::endl; + + // Define an empty callback using default constructed function + std::function()> emptyCallback; + std::cout << "Invoking RegisterMetaDataCb with an empty (null) callback" << std::endl; + + // Register the empty callback + manager.RegisterMetaDataCb(emptyCallback); + std::cout << "Empty callback registered successfully" << std::endl; + + // Verify that the stored callback is empty + if (!manager.DrmMetaDataCb) { + std::cout << "DrmMetaDataCb is empty as expected after registering an empty callback" << std::endl; + } else { + std::cout << "DrmMetaDataCb is not empty, which is unexpected" << std::endl; + FAIL() << "Expected DrmMetaDataCb to be empty after registering an empty callback."; + } + + std::cout << "Exiting RegisterEmptyCallback test" << std::endl; +} +/** + * @brief Validate that registering a callback returning a null shared pointer behaves correctly. + * + * This test verifies the functionality of the DrmSessionManager when a valid callback that returns a null shared pointer is registered. It checks that the callback is correctly stored and, upon invocation, returns a null shared pointer as expected. + * + * **Test Group ID:** Basic: 01 + * **Test Case ID:** 117 + * **Priority:** High + * + * **Pre-Conditions:** None + * **Dependencies:** None + * **User Interaction:** None + * + * **Test Procedure:** + * | Variation / Step | Description | Test Data | Expected Result | Notes | + * | :--------------: | --------------------------------------------------------------------------- | ----------------------------------------------------------------- | --------------------------------------------------------------------------------------------------------- | ------------- | + * | 01 | Instantiate DrmSessionManager with maxDrmSessions = 5 and player = nullptr | input: maxDrmSessions = 5, player = nullptr | DrmSessionManager instance is created successfully | Should be successful | + * | 02 | Define a callback that returns a null shared_ptr | input: callback -> returns std::shared_ptr() as null | A valid callback is defined that returns a null shared pointer | Should be successful | + * | 03 | Register the defined callback using RegisterMetaDataCb | input: callback reference | Callback is registered successfully and assigned to DrmMetaDataCb | Should be successful | + * | 04 | Invoke the registered callback and verify it returns a null shared pointer | output from callback invocation | The callback, when invoked, returns a null shared pointer as expected; assertion check passes | Should Pass | + */ +TEST(DrmSessionManager, RegisterCallbackReturningNullSharedPtr) { + std::cout << "Entering RegisterCallbackReturningNullSharedPtr test" << std::endl; + + // Create an instance of DrmSessionManager using the custom constructor + DrmSessionManager manager(5, nullptr); + std::cout << "Created DrmSessionManager instance with maxDrmSessions = 5 and player = nullptr" << std::endl; + + // Define a valid callback that returns a null shared pointer + auto nullCallback = []() -> std::shared_ptr { + std::cout << "Inside callback: Returning a null shared_ptr" << std::endl; + return std::shared_ptr(); + }; + std::cout << "Invoking RegisterMetaDataCb with callback that returns null shared_ptr" << std::endl; + + // Register the callback + manager.RegisterMetaDataCb(nullCallback); + std::cout << "Callback registered successfully" << std::endl; + + // Invoke the registered callback and check that the returned shared pointer is null + if (manager.DrmMetaDataCb) { + std::cout << "DrmMetaDataCb is valid. Invoking the callback." << std::endl; + std::shared_ptr result = manager.DrmMetaDataCb(); + if (!result) { + std::cout << "Callback returned a null shared_ptr as expected" << std::endl; + } else { + std::cout << "Callback returned a non-null shared_ptr unexpectedly" << std::endl; + FAIL() << "Expected callback to return a null shared_ptr."; + } + } else { + std::cout << "DrmMetaDataCb is empty, which is unexpected since a valid callback was provided" << std::endl; + FAIL() << "Expected DrmMetaDataCb to be valid even if its invocation returns null."; + } + + std::cout << "Exiting RegisterCallbackReturningNullSharedPtr test" << std::endl; +} +/** + * @brief Verify that re-registering metadata callbacks in DrmSessionManager updates the callback successfully + * + * This test verifies that when a metadata callback is registered and then updated by invoking RegisterMetaDataCb again, the second callback replaces the first and returns the expected shared_ptr with the updated integer value. + * + * **Test Group ID:** Basic: 01@n + * **Test Case ID:** 118@n + * **Priority:** High@n + * + * **Pre-Conditions:** None@n + * **Dependencies:** None@n + * **User Interaction:** None@n + * + * **Test Procedure:**@n + * | Variation / Step | Description | Test Data | Expected Result | Notes | + * | :----: | --------- | ---------- |-------------- | ----- | + * | 01 | Create an instance of DrmSessionManager using custom constructor | maxDrmSessions = 5, player = nullptr | Instance of DrmSessionManager created successfully | Should be successful | + * | 02 | Define and register the first callback that returns a shared_ptr with value 10 | input: firstCallback function (returns shared_ptr with value 10) | DrmMetaDataCb updated with firstCallback | Should Pass | + * | 03 | Invoke the first registered callback via DrmMetaDataCb and verify the return value | Output: firstResult (expected int = 10) | Returns shared_ptr pointing to integer 10; ASSERT_EQ verifies value == 10 | Should Pass | + * | 04 | Define and register the second callback that returns a shared_ptr with value 20 | input: secondCallback function (returns shared_ptr with value 20) | DrmMetaDataCb updated with secondCallback | Should Pass | + * | 05 | Invoke the second registered callback via DrmMetaDataCb and verify the return value | Output: secondResult (expected int = 20) | Returns shared_ptr pointing to integer 20; ASSERT_EQ verifies value == 20 | Should Pass | + */ +TEST(DrmSessionManager, ReRegisterCallbackUpdate) { + std::cout << "Entering ReRegisterCallbackUpdate test" << std::endl; + + // Create an instance of DrmSessionManager using the custom constructor + DrmSessionManager manager(5, nullptr); + std::cout << "Created DrmSessionManager instance with maxDrmSessions = 5 and player = nullptr" << std::endl; + + // Define and register the first callback that returns a shared pointer with int value 10 + auto firstCallback = []() -> std::shared_ptr { + auto spInt = std::make_shared(10); + std::cout << "Inside first callback: Created shared_ptr with value " << *spInt << std::endl; + return spInt; + }; + std::cout << "Invoking RegisterMetaDataCb with first callback that returns int value 10" << std::endl; + manager.RegisterMetaDataCb(firstCallback); + std::cout << "First callback registered successfully" << std::endl; + + // Verify the first callback invocation + if (manager.DrmMetaDataCb) { + std::cout << "DrmMetaDataCb is valid. Invoking the first callback." << std::endl; + std::shared_ptr firstResult = manager.DrmMetaDataCb(); + if (firstResult) { + std::shared_ptr intResult = std::static_pointer_cast(firstResult); + std::cout << "First callback returned shared_ptr with int value: " << *intResult << std::endl; + ASSERT_EQ(*intResult, 10); + } else { + std::cout << "First callback returned a null shared_ptr unexpectedly" << std::endl; + FAIL() << "Expected first callback to return a non-null shared_ptr with value 10."; + } + } else { + std::cout << "DrmMetaDataCb is empty after registering first callback" << std::endl; + FAIL() << "Expected valid first callback in DrmMetaDataCb."; + } + + // Define and register the second callback that returns a shared pointer with int value 20 + auto secondCallback = []() -> std::shared_ptr { + auto spInt = std::make_shared(20); + std::cout << "Inside second callback: Created shared_ptr with value " << *spInt << std::endl; + return spInt; + }; + std::cout << "Invoking RegisterMetaDataCb with second callback that returns int value 20" << std::endl; + manager.RegisterMetaDataCb(secondCallback); + std::cout << "Second callback registered successfully" << std::endl; + + // Verify that the callback has been updated to the second callback + if (manager.DrmMetaDataCb) { + std::cout << "DrmMetaDataCb is valid. Invoking the second callback." << std::endl; + std::shared_ptr secondResult = manager.DrmMetaDataCb(); + if (secondResult) { + std::shared_ptr intResult = std::static_pointer_cast(secondResult); + std::cout << "Second callback returned shared_ptr with int value: " << *intResult << std::endl; + ASSERT_EQ(*intResult, 20); + } else { + std::cout << "Second callback returned a null shared_ptr unexpectedly" << std::endl; + FAIL() << "Expected second callback to return a non-null shared_ptr with value 20."; + } + } else { + std::cout << "DrmMetaDataCb is empty after re-registering second callback" << std::endl; + FAIL() << "Expected valid second callback in DrmMetaDataCb."; + } + + std::cout << "Exiting ReRegisterCallbackUpdate test" << std::endl; +} +/** + * @brief Validates that RegisterProfBegin correctly registers and invokes a valid callback + * + * This test verifies that a valid callback lambda is successfully registered using RegisterProfBegin of the DrmSessionManager. + * It checks that when the stored callback is invoked with the value 5, the callbackResult is properly updated to 5. + * + * **Test Group ID:** Basic: 01 + * **Test Case ID:** 119 + * **Priority:** High + * + * **Pre-Conditions:** None + * **Dependencies:** None + * **User Interaction:** None + * + * **Test Procedure:** + * | Variation / Step | Description | Test Data | Expected Result | Notes | + * | :----: | --------- | ---------- |-------------- | ----- | + * | 01 | Define a valid callback lambda that updates callbackResult | callbackResult = 0 | Lambda is defined successfully and ready to update callbackResult | Should be successful | + * | 02 | Create DrmSessionManager object with maxDrmSessions=3 and player=nullptr | maxDrmSessions = 3, player = nullptr | DrmSessionManager instance is created successfully | Should be successful | + * | 03 | Register the valid callback lambda using RegisterProfBegin | callback = validCallback | profileBeginCb is set to the valid callback lambda | Should Pass | + * | 04 | Invoke the stored callback with value 5 | input value = 5 | callbackResult is updated to 5 | Should Pass | + * | 05 | Validate that callbackResult equals 5 using EXPECT_EQ | callbackResult = 5 (expected) | Assertion passes ensuring callbackResult equals 5 | Should Pass | + */ +TEST(DrmSessionManager, RegisterProfBegin_ValidCallbackTest) +{ + std::cout << "Entering RegisterProfBegin_ValidCallbackTest test" << std::endl; + + int callbackResult = 0; + auto validCallback = [&callbackResult](int value) { + std::cout << "Inside callback lambda, received value: " << value << std::endl; + callbackResult = value; + }; + + std::cout << "Creating DrmSessionManager object with maxDrmSessions=3 and player=nullptr" << std::endl; + DrmSessionManager drmManager(3, nullptr); + + std::cout << "Invoking RegisterProfBegin with valid callback lambda" << std::endl; + drmManager.RegisterProfBegin(validCallback); + std::cout << "Callback registered in profileBeginCb" << std::endl; + + std::cout << "Invoking stored callback with value 5" << std::endl; + drmManager.profileBeginCb(5); + std::cout << "Callback invocation complete, callbackResult: " << callbackResult << std::endl; + + EXPECT_EQ(callbackResult, 5); + + std::cout << "Exiting RegisterProfBegin_ValidCallbackTest test" << std::endl; +} +/** + * @brief Verify that RegisterProfBegin registers an empty callback correctly. + * + * This test verifies that invoking the RegisterProfBegin method of DrmSessionManager with an empty callback does not register any callback function. It confirms that the profileBeginCb remains empty and ensures that no unintended operations are performed when an empty callback is provided. + * + * **Test Group ID:** Basic: 01@n + * **Test Case ID:** 120@n + * **Priority:** High@n + * + * **Pre-Conditions:** None@n + * **Dependencies:** None@n + * **User Interaction:** None@n + * + * **Test Procedure:** + * | Variation / Step | Description | Test Data | Expected Result | Notes | + * | :----: | ---------------------------------------------------------------------------------------- | ---------------------------------------------------------------------- | ------------------------------------------------------------------------------------- | -------------- | + * | 01 | Create DrmSessionManager object with maxDrmSessions=3 and player=nullptr. | maxDrmSessions = 3, player = nullptr | Object is initialized successfully. | Should be successful | + * | 02 | Create an empty ProfileBeginCallback. | emptyCallback = std::function (empty) | Callback remains empty. | Should be successful | + * | 03 | Invoke RegisterProfBegin with an empty callback. | callback = emptyCallback | API assigns an empty callback to profileBeginCb. | Should Pass | + * | 04 | Verify that profileBeginCb is empty using the EXPECT_FALSE assertion. | profileBeginCb = empty | The EXPECT_FALSE assertion passes confirming profileBeginCb is empty. | Should be successful | + */ +TEST(DrmSessionManager, RegisterProfBegin_EmptyCallbackTest) +{ + std::cout << "Entering RegisterProfBegin_EmptyCallbackTest test" << std::endl; + + std::cout << "Creating DrmSessionManager object with maxDrmSessions=3 and player=nullptr" << std::endl; + DrmSessionManager drmManager(3, nullptr); + + std::cout << "Creating an empty ProfileBeginCallback" << std::endl; + std::function emptyCallback; + + std::cout << "Invoking RegisterProfBegin with empty callback" << std::endl; + drmManager.RegisterProfBegin(emptyCallback); + std::cout << "Empty callback stored in profileBeginCb" << std::endl; + + if (!drmManager.profileBeginCb) { + std::cout << "profileBeginCb is empty as expected, no operation will be executed if invoked." << std::endl; + } else { + std::cout << "profileBeginCb is not empty, which is unexpected for an empty callback." << std::endl; + } + + EXPECT_FALSE(drmManager.profileBeginCb); + + std::cout << "Exiting RegisterProfBegin_EmptyCallbackTest test" << std::endl; +} +/** + * @brief Test whether valid callback registration and invocation correctly sets the flag. + * + * This test registers a valid callback that captures an external flag. The callback is then invoked using the profileEndCb function with a streamType argument. The test verifies that the flag is set to true, ensuring that the callback registration and invocation mechanism in the DrmSessionManager works as expected. + * + * **Test Group ID:** Basic: 01@n + * **Test Case ID:** 121@n + * **Priority:** High@n + * + * **Pre-Conditions:** None@n + * **Dependencies:** None@n + * **User Interaction:** None@n + * + * **Test Procedure:**@n + * | Variation / Step | Description | Test Data | Expected Result | Notes | + * | :----: | --------- | ---------- |-------------- | ----- | + * | 01 | Initialize flag, create callback, and instantiate DrmSessionManager. | flag = false, capacity = 10, callback captures flag | Instance created with uninvoked callback, flag remains false | Should be successful | + * | 02 | Register the valid callback using RegisterProfEnd. | callback = lambda capturing flag | Callback stored in profileEndCb; internal state updated accordingly | Should Pass | + * | 03 | Invoke the stored callback via profileEndCb with streamType = 1. | streamType = 1 | Flag is set to true and ASSERT_TRUE validates the condition | Should Pass | + */ +TEST(DrmSessionManager, RegisterProfEnd_ValidCallbackSetsFlag) { + std::cout << "Entering RegisterProfEnd_ValidCallbackSetsFlag test" << std::endl; + + // Create a flag that gets set when the callback is invoked + bool flag = false; + auto callback = [&flag](int streamType) { + flag = true; + std::cout << "Inside callback: Received streamType = " << streamType + << ", setting flag to " << flag << std::endl; + }; + + // Create DrmSessionManager object using custom constructor + DrmSessionManager drmManager(10, nullptr); + std::cout << "Invoking RegisterProfEnd with valid callback" << std::endl; + drmManager.RegisterProfEnd(callback); + std::cout << "Callback registered in profileEndCb" << std::endl; + + // Invoke the stored callback with streamType = 1 + std::cout << "Invoking profileEndCb with streamType = 1" << std::endl; + drmManager.profileEndCb(1); + std::cout << "Flag value after callback invocation: " << flag << std::endl; + + ASSERT_TRUE(flag); + + std::cout << "Exiting RegisterProfEnd_ValidCallbackSetsFlag test" << std::endl; +} +/** + * @brief Test to verify that the profile end callback correctly updates an external variable. + * + * This test validates that when a callback is registered with the DrmSessionManager, + * invoking the stored callback with a specific streamType (2) correctly updates the external variable. + * The test ensures that the callback mechanism is functioning as expected. + * + * **Test Group ID:** Basic: 01@n + * **Test Case ID:** 122@n + * **Priority:** High@n + * + * **Pre-Conditions:** None@n + * **Dependencies:** None@n + * **User Interaction:** None@n + * + * **Test Procedure:**@n + * | Variation / Step | Description | Test Data | Expected Result | Notes | + * | :----: | --------- | ---------- | -------------- | ----- | + * | 01 | Initialize external variable and define callback lambda to update it based on streamType | flag = false | External variable initialized to false | Should be successful | + * | 02 | Create DrmSessionManager instance and register the defined callback using RegisterProfEnd() | input: maxSessions = 10, callback = lambda, output: callback registered in profileEndCb | Callback is stored in the DrmSessionManager | Should Pass | + * | 03 | Invoke the stored callback in profileEndCb with streamType = 2 | input: streamType = 2 | The callback updates the external flag to true | Should Pass | + * | 04 | Assert that the external flag has been updated to true after callback invocation | output: flag value, expected value = true | ASSERT_TRUE verifies the flag is true | Should Pass | + */ +TEST(DrmSessionManager, RegisterProfEnd_UpdateExternalVariable) { + std::cout << "Entering RegisterProfEnd_UpdateExternalVariable test" << std::endl; + + // Using a shared pointer to allow lambda to update the external variable and reflect changes externally + auto flag = std::make_shared(false); + auto callback = [flag](int streamType) { + *flag = (streamType == 2); + std::cout << "Inside callback: Received streamType = " << streamType + << ", updating flag to " << *flag << std::endl; + }; + + // Create DrmSessionManager object using custom constructor + DrmSessionManager drmManager(10, nullptr); + std::cout << "Invoking RegisterProfEnd with callback capturing external variable" << std::endl; + drmManager.RegisterProfEnd(callback); + std::cout << "Callback registered in profileEndCb" << std::endl; + + // Invoke the stored callback with streamType = 2 + std::cout << "Invoking profileEndCb with streamType = 2" << std::endl; + drmManager.profileEndCb(2); + std::cout << "External flag value after callback invocation: " << *flag << std::endl; + + ASSERT_TRUE(*flag); + + std::cout << "Exiting RegisterProfEnd_UpdateExternalVariable test" << std::endl; +} +/** + * @brief Test the RegisterProfEnd API with an empty callback + * + * This test verifies that when an empty std::function callback is passed to the RegisterProfEnd method of the DrmSessionManager, the internal callback (profileEndCb) remains empty. This ensures that the API handles empty callbacks correctly and does not register an invalid callback. + * + * **Test Group ID:** Basic: 01@n + * **Test Case ID:** 123@n + * **Priority:** High@n + * + * **Pre-Conditions:** None@n + * **Dependencies:** None@n + * **User Interaction:** None@n + * + * **Test Procedure:**@n + * | Variation / Step | Description | Test Data | Expected Result | Notes | + * | :----: | --------- | ---------- |-------------- | ----- | + * | 01 | Create an empty std::function callback variable. | emptyCallback = default constructed std::function | Callback variable is empty. | Should be successful | + * | 02 | Create DrmSessionManager object using custom constructor. | sessionId = 10, dependency = nullptr | DrmSessionManager object is initialized successfully. | Should be successful | + * | 03 | Invoke RegisterProfEnd with the empty callback. | callback = emptyCallback (empty) | API call registers an empty callback (profileEndCb remains empty). | Should Pass | + * | 04 | Verify that profileEndCb is empty by checking its state. | internal state: profileEndCb is empty | ASSERT_TRUE(isEmpty) passes confirming the callback is empty. | Should Pass | + */ +TEST(DrmSessionManager, RegisterProfEnd_EmptyCallback) { + std::cout << "Entering RegisterProfEnd_EmptyCallback test" << std::endl; + + // Create an empty std::function callback (default constructed) + std::function emptyCallback; + std::cout << "Empty callback created" << std::endl; + + // Create DrmSessionManager object using custom constructor + DrmSessionManager drmManager(10, nullptr); + std::cout << "Invoking RegisterProfEnd with empty callback" << std::endl; + drmManager.RegisterProfEnd(emptyCallback); + std::cout << "Empty callback registered in profileEndCb" << std::endl; + + // Check whether profileEndCb is empty + bool isEmpty = (!drmManager.profileEndCb); + std::cout << "profileEndCb is " << (isEmpty ? "empty" : "not empty") << std::endl; + + ASSERT_TRUE(isEmpty); + + std::cout << "Exiting RegisterProfEnd_EmptyCallback test" << std::endl; +} +/** + * @brief Validate registration and overwrite functionality of callback in DrmSessionManager + * + * This test verifies that the DrmSessionManager object's RegisterProfEnd API correctly registers a callback and that when the callback is overwritten with a new one, the new callback is invoked while the old one is not. The test ensures that after invoking profileEndCb, the appropriate callback sets the corresponding flag as expected. + * + * **Test Group ID:** Basic: 01@n + * **Test Case ID:** 124@n + * **Priority:** High@n + * + * **Pre-Conditions:** None@n + * **Dependencies:** None@n + * **User Interaction:** None@n + * + * **Test Procedure:** + * | Variation / Step | Description | Test Data | Expected Result | Notes | + * | :--------------: | ----------- | --------- | --------------- | ----- | + * | 01 | Register the first callback and verify its invocation | RegisterProfEnd(firstCallback), profileEndCb(streamType = 0), firstInvoked = false, secondInvoked = false | firstInvoked becomes true; secondInvoked remains false; ASSERT_TRUE(firstInvoked) and ASSERT_FALSE(secondInvoked) pass | Should Pass | + * | 02 | Reset flags, overwrite the callback with second callback, and verify the overwritten callback's behavior | RegisterProfEnd(secondCallback), profileEndCb(streamType = 5), firstInvoked = false, secondInvoked = false | secondInvoked becomes true; firstInvoked remains false; ASSERT_FALSE(firstInvoked) and ASSERT_TRUE(secondInvoked) pass | Should Pass | + */ +TEST(DrmSessionManager, RegisterProfEnd_OverwriteCallback) { + std::cout << "Entering RegisterProfEnd_OverwriteCallback test" << std::endl; + + bool firstInvoked = false; + bool secondInvoked = false; + + // First callback lambda that sets firstInvoked flag + auto firstCallback = [&firstInvoked](int streamType) { + firstInvoked = true; + std::cout << "Inside firstCallback: Received streamType = " << streamType + << ", setting firstInvoked to " << firstInvoked << std::endl; + }; + + // Second callback lambda that sets secondInvoked flag + auto secondCallback = [&secondInvoked](int streamType) { + secondInvoked = true; + std::cout << "Inside secondCallback: Received streamType = " << streamType + << ", setting secondInvoked to " << secondInvoked << std::endl; + }; + + // Create DrmSessionManager object using custom constructor + DrmSessionManager drmManager(10, nullptr); + + // Register the first callback + std::cout << "Registering first callback via RegisterProfEnd" << std::endl; + drmManager.RegisterProfEnd(firstCallback); + std::cout << "First callback registered in profileEndCb" << std::endl; + + // Invoke the currently stored callback + std::cout << "Invoking profileEndCb with streamType = 0 (expecting firstCallback behavior)" << std::endl; + drmManager.profileEndCb(0); + std::cout << "firstInvoked: " << firstInvoked << ", secondInvoked: " << secondInvoked << std::endl; + ASSERT_TRUE(firstInvoked); + ASSERT_FALSE(secondInvoked); + + // Reset flags to check overwrite behavior + firstInvoked = false; + secondInvoked = false; + + // Overwrite with the second callback + std::cout << "Registering second callback via RegisterProfEnd, overwriting first callback" << std::endl; + drmManager.RegisterProfEnd(secondCallback); + std::cout << "Second callback registered in profileEndCb" << std::endl; + + // Invoke the overwritten callback + std::cout << "Invoking profileEndCb with streamType = 5 (expecting secondCallback behavior)" << std::endl; + drmManager.profileEndCb(5); + std::cout << "firstInvoked: " << firstInvoked << ", secondInvoked: " << secondInvoked << std::endl; + ASSERT_FALSE(firstInvoked); + ASSERT_TRUE(secondInvoked); + + std::cout << "Exiting RegisterProfEnd_OverwriteCallback test" << std::endl; +} +/** + * @brief Test the registration of a valid profile error callback and its invocation + * + * This test verifies that when a valid lambda function is registered as a ProfileError callback using the RegisterProfError API, + * the callback is properly stored and subsequently invoked when profileErrorCb is called. The test confirms the functionality by checking the callbackInvoked flag. + * + * **Test Group ID:** Basic: 01@n + * **Test Case ID:** 125@n + * **Priority:** High@n + * + * **Pre-Conditions:** None@n + * **Dependencies:** None@n + * **User Interaction:** None@n + * + * **Test Procedure:**@n + * | Variation / Step | Description | Test Data | Expected Result | Notes | + * | :--------------: | -------------------------------------------------------------------------- | ----------------------------------------------------------------- | ------------------------------------------------------------------------------------ | --------------- | + * | 01 | Create DrmSessionManager object using custom constructor. | maxDrmSessions = 5, player = nullptr | DrmSessionManager object is created successfully. | Should be successful | + * | 02 | Initialize the callbackInvoked flag. | callbackInvoked = false | The flag is initialized to false. | Should be successful | + * | 03 | Create a valid lambda function for the ProfileError callback. | lambda callback creation | Lambda callback is defined successfully. | Should be successful | + * | 04 | Register the valid callback using RegisterProfError API. | RegisterProfError(validCallback) | Callback is registered in the DrmSessionManager instance. | Should Pass | + * | 05 | Invoke profileErrorCb with streamType = 2 and result = 999 to trigger callback.| profileErrorCb(streamType = 2, result = 999) | Callback is invoked, setting callbackInvoked flag to true. | Should Pass | + * | 06 | Validate the callback invocation via EXPECT_TRUE assertion. | EXPECT_TRUE(callbackInvoked) | EXPECT_TRUE assertion passes confirming the callback was invoked. | Should Pass | + */ +TEST(DrmSessionManager, RegisterValidProfileErrorCallback) { + std::cout << "Entering RegisterValidProfileErrorCallback test" << std::endl; + + // Create DrmSessionManager object using custom constructor with dummy parameters. + DrmSessionManager drmSessionManager(5, nullptr); + std::cout << "Created DrmSessionManager object with maxDrmSessions = 5 and player = nullptr" << std::endl; + + // Flag to check if the callback is invoked. + bool callbackInvoked = false; + + // Create a valid lambda function as a ProfileError callback. + auto validCallback = [&callbackInvoked](int streamType, int result) { + std::cout << "Invoked validCallback with streamType: " << streamType << " and result: " << result << std::endl; + callbackInvoked = true; + }; + std::cout << "Created validProfileErrorCallback lambda" << std::endl; + + // Register the valid callback. + std::cout << "Invoking RegisterProfError with validCallback" << std::endl; + drmSessionManager.RegisterProfError(validCallback); + std::cout << "Registered validCallback successfully" << std::endl; + + // Validate by invoking the callback through the public member. + std::cout << "Invoking profileErrorCb callback with streamType = 2 and result = 999" << std::endl; + drmSessionManager.profileErrorCb(2, 999); + std::cout << "Callback invocation complete; callbackInvoked flag = " << callbackInvoked << std::endl; + EXPECT_TRUE(callbackInvoked); + + std::cout << "Exiting RegisterValidProfileErrorCallback test" << std::endl; +} +/** + * @brief Verify that registering an empty ProfileError callback results in an empty callback in DrmSessionManager + * + * This test creates a DrmSessionManager instance and attempts to register an empty ProfileError callback. + * The objective is to ensure that when an empty callback is provided, the internal callback remains unset. + * + * **Test Group ID:** Basic: 01@n + * **Test Case ID:** 126@n + * **Priority:** High@n + * + * **Pre-Conditions:** None@n + * **Dependencies:** None@n + * **User Interaction:** None@n + * + * **Test Procedure:**@n + * | Variation / Step | Description | Test Data | Expected Result | Notes | + * | :--------------: | ----------------------------------------------------------------------- | ------------------------------------------------------- | ----------------------------------------------------------------------------------- | ------------- | + * | 01 | Create DrmSessionManager object using custom constructor | maxDrmSessions = 5, player = nullptr | DrmSessionManager object created successfully | Should be successful | + * | 02 | Create an empty ProfileError callback | emptyCallback = empty | Empty callback created successfully | Should be successful | + * | 03 | Register the empty ProfileError callback | callback = emptyCallback | Callback registration invoked successfully | Should Pass | + * | 04 | Verify that the profileErrorCb is empty after registration | profileErrorCb expected to be empty | EXPECT_TRUE assertion passes confirming the callback remains unset | Should Pass | + */ +TEST(DrmSessionManager, RegisterEmptyProfileErrorCallback) { + std::cout << "Entering RegisterEmptyProfileErrorCallback test" << std::endl; + + // Create DrmSessionManager object using custom constructor with dummy parameters. + DrmSessionManager drmSessionManager(5, nullptr); + std::cout << "Created DrmSessionManager object with maxDrmSessions = 5 and player = nullptr" << std::endl; + + // Create an empty ProfileError callback. + std::function emptyCallback; + std::cout << "Created an empty ProfileError callback" << std::endl; + + // Register the empty callback. + std::cout << "Invoking RegisterProfError with emptyCallback" << std::endl; + drmSessionManager.RegisterProfError(emptyCallback); + std::cout << "Registered empty callback successfully" << std::endl; + + // Check that the callback is empty. + bool isCallbackEmpty = !static_cast(drmSessionManager.profileErrorCb); + std::cout << "profileErrorCb is " << (isCallbackEmpty ? "empty" : "not empty") << std::endl; + EXPECT_TRUE(isCallbackEmpty); + + std::cout << "Exiting RegisterEmptyProfileErrorCallback test" << std::endl; +} +/** + * @brief Test the behavior of overwriting an existing profile error callback + * + * This test verifies that when a profile error callback is overwritten with a new callback, + * the new callback is invoked instead of the previous one. It tests the creation of a DrmSessionManager, + * registration and invocation of the first callback, and then overwriting that callback with a second one. + * + * **Test Group ID:** Basic: 01@n + * **Test Case ID:** 127@n + * **Priority:** High@n + * + * **Pre-Conditions:** None@n + * **Dependencies:** None@n + * **User Interaction:** None@n + * + * **Test Procedure:**@n + * | Variation / Step | Description | Test Data | Expected Result | Notes | + * | :----: | --------- | ---------- |-------------- | ----- | + * | 01 | Create DrmSessionManager object using custom constructor | maxDrmSessions = 5, player = nullptr | Object is created successfully | Should be successful | + * | 02 | Create first lambda callback | firstCallback captures firstCallbackResult | Lambda callback is created | Should be successful | + * | 03 | Register first callback function using RegisterProfError | firstCallback | Callback is registered successfully | Should Pass | + * | 04 | Invoke profileErrorCb callback with streamType = 1 and result = 1 | streamType = 1, result = 1 | firstCallbackResult equals 2 and assertion passes | Should Pass | + * | 05 | Create second lambda callback | secondCallback captures secondCallbackResult | Lambda callback is created | Should be successful | + * | 06 | Overwrite the existing callback by registering second callback using RegisterProfError | secondCallback | Existing callback is overwritten successfully | Should Pass | + * | 07 | Invoke profileErrorCb callback with streamType = 2 and result = 2 | streamType = 2, result = 2 | secondCallbackResult equals 4 and assertion passes | Should Pass | + */ +TEST(DrmSessionManager, OverwriteExistingProfileErrorCallback) { + std::cout << "Entering OverwriteExistingProfileErrorCallback test" << std::endl; + + // Create DrmSessionManager object using custom constructor with dummy parameters. + DrmSessionManager drmSessionManager(5, nullptr); + std::cout << "Created DrmSessionManager object with maxDrmSessions = 5 and player = nullptr" << std::endl; + + // Variables to track callback invocations. + int firstCallbackResult = 0; + int secondCallbackResult = 0; + + // Create first lambda callback. + auto firstCallback = [&firstCallbackResult](int streamType, int result) { + std::cout << "Invoked firstCallback with streamType: " << streamType << " and result: " << result << std::endl; + firstCallbackResult = streamType + result; + }; + std::cout << "Created firstCallback lambda" << std::endl; + + // Register the first callback. + std::cout << "Invoking RegisterProfError with firstCallback" << std::endl; + drmSessionManager.RegisterProfError(firstCallback); + std::cout << "Registered firstCallback successfully" << std::endl; + + // Invoke the first callback. + std::cout << "Invoking profileErrorCb callback with streamType = 1 and result = 1" << std::endl; + drmSessionManager.profileErrorCb(1, 1); + std::cout << "After first callback invocation, firstCallbackResult = " << firstCallbackResult << std::endl; + EXPECT_EQ(firstCallbackResult, 2); + + // Create second lambda callback. + auto secondCallback = [&secondCallbackResult](int streamType, int result) { + std::cout << "Invoked secondCallback with streamType: " << streamType << " and result: " << result << std::endl; + secondCallbackResult = streamType + result; + }; + std::cout << "Created secondCallback lambda" << std::endl; + + // Overwrite the existing callback with the second callback. + std::cout << "Invoking RegisterProfError with secondCallback to overwrite first callback" << std::endl; + drmSessionManager.RegisterProfError(secondCallback); + std::cout << "Overwritten callback with secondCallback successfully" << std::endl; + + // Invoke the callback after overwrite. + std::cout << "Invoking profileErrorCb callback with streamType = 2 and result = 2" << std::endl; + drmSessionManager.profileErrorCb(2, 2); + std::cout << "After second callback invocation, secondCallbackResult = " << secondCallbackResult << std::endl; + EXPECT_EQ(secondCallbackResult, 4); + + std::cout << "Exiting OverwriteExistingProfileErrorCallback test" << std::endl; +} +/** + * @brief Register a valid callback function and verify its invocation using a lambda callback. + * + * This test verifies that the DrmSessionManager's RegisterSetFailure function correctly registers a valid lambda callback. It then triggers the callback with predefined test parameters to ensure that the callback updates the internal flags and data as expected. + * + * **Test Group ID:** Basic: 01 + * **Test Case ID:** 128 + * **Priority:** High + * + * **Pre-Conditions:** None + * **Dependencies:** None + * **User Interaction:** None + * + * **Test Procedure:** + * | Variation / Step | Description | Test Data | Expected Result | Notes | + * | :--------------: | ---------------------------------------------------------------------- | --------------------------------------------------------------- | ------------------------------------------------------------------------------- | --------------- | + * | 01 | Create an instance of DrmSessionManager using custom constructor. | size = 10, handle = 0x1234 | Instance is created successfully. | Should be successful | + * | 02 | Initialize callback invocation variables and define lambda callback. | callbackInvoked = false, callbackErr = 0, callbackPtr = nullptr | Lambda callback is defined and variables are initialized. | Should be successful | + * | 03 | Register the lambda callback using the RegisterSetFailure API. | callback = lambdaCallback | Callback is registered successfully. | Should Pass | + * | 04 | Invoke the registered callback with test parameters. | ptr = 0xdeadbeef, err = 42 | Lambda callback execution sets callbackInvoked = true, callbackErr = 42, callbackPtr = 0xdeadbeef. | Should Pass | + * | 05 | Verify callback invocation and check output values. | Expected: callbackInvoked = true, callbackErr = 42, callbackPtr = 0xdeadbeef | Assertions pass confirming the callback was invoked with expected results. | Should Pass | + */ +TEST(DrmSessionManager, RegisterValidCallbackFunction) { + std::cout << "Entering RegisterValidCallbackFunction test" << std::endl; + + // Create an object of DrmSessionManager using custom constructor. + DrmSessionManager drmSessionManager(10, reinterpret_cast(0x1234)); + + // Variables to record callback invocation. + bool callbackInvoked = false; + int callbackErr = 0; + void* callbackPtr = nullptr; + + // Define a lambda callback. + auto lambdaCallback = [&callbackInvoked, &callbackErr, &callbackPtr](void* ptr, int err) { + std::cout << "Lambda callback invoked with ptr: " << ptr << " and err: " << err << std::endl; + callbackInvoked = true; + callbackErr = err; + callbackPtr = ptr; + }; + std::cout << "Invoking RegisterSetFailure with a valid lambda callback" << std::endl; + drmSessionManager.RegisterSetFailure(lambdaCallback); + + std::cout << "Callback registered. Invoking the registered callback with test parameters: ptr = " + << reinterpret_cast(0xdeadbeef) << ", err = 42" << std::endl; + if (drmSessionManager.setfailureCb) { + drmSessionManager.setfailureCb(reinterpret_cast(0xdeadbeef), 42); + } + + std::cout << "After invocation, callbackInvoked: " << callbackInvoked + << ", callbackErr: " << callbackErr + << ", callbackPtr: " << callbackPtr << std::endl; + EXPECT_TRUE(callbackInvoked); + EXPECT_EQ(callbackErr, 42); + EXPECT_EQ(callbackPtr, reinterpret_cast(0xdeadbeef)); + + std::cout << "Exiting RegisterValidCallbackFunction test" << std::endl; +} +/** + * @brief Test for verifying that registering an empty callback function results in an empty internal callback. + * + * This test ensures that when an empty std::function callback is passed to the RegisterSetFailure API, the internal callback (setfailureCb) remains unset. + * This behavior is crucial to ensure that the system does not inadvertently execute any callback logic when a null/empty callback is registered. + * + * **Test Group ID:** Basic: 01@n + * **Test Case ID:** 129@n + * **Priority:** High@n + * + * **Pre-Conditions:** None@n + * **Dependencies:** None@n + * **User Interaction:** None@n + * + * **Test Procedure:**@n + * | Variation / Step | Description | Test Data | Expected Result | Notes | + * | :----: | --------- | ---------- |-------------- | ----- | + * | 01 | Initialize DrmSessionManager with parameters. | input1 = 10, input2 = 0x1234 | DrmSessionManager object is successfully created. | Should be successful | + * | 02 | Create an empty std::function callback. | callback = empty | Empty callback function object is created. | Should be successful | + * | 03 | Call RegisterSetFailure with the empty callback. | callback = empty | API registers an empty callback without error. | Should Pass | + * | 04 | Assert that the internal setfailureCb is empty. | result = !drmSessionManager.setfailureCb | EXPECT_TRUE(isEmpty) returns true. | Should Pass | + */ +TEST(DrmSessionManager, RegisterEmptyCallbackFunction) { + std::cout << "Entering RegisterEmptyCallbackFunction test" << std::endl; + + // Create an object of DrmSessionManager using default/custom constructor. + DrmSessionManager drmSessionManager(10, reinterpret_cast(0x1234)); + + // Create an empty std::function callback. + std::function emptyCallback; + std::cout << "Invoking RegisterSetFailure with an empty callback function object" << std::endl; + drmSessionManager.RegisterSetFailure(emptyCallback); + + std::cout << "Callback registered. Checking if the internal callback is empty." << std::endl; + bool isEmpty = !drmSessionManager.setfailureCb; + std::cout << "Internal setfailureCb empty state: " << isEmpty << std::endl; + EXPECT_TRUE(isEmpty); + + std::cout << "Exiting RegisterEmptyCallbackFunction test" << std::endl; +} +/** + * @brief Verify that overwriting an existing callback function works correctly + * + * This test verifies that the DrmSessionManager correctly overwrites an already registered callback function. Initially, a callback is registered and invoked, and its successful execution is verified. Then, a second callback is registered to replace the first one, and its successful invocation is confirmed. This ensures that the implementation allows updating the callback function reliably. + * + * **Test Group ID:** Basic: 01@n + * **Test Case ID:** 130@n + * **Priority:** High@n + * + * **Pre-Conditions:** None@n + * **Dependencies:** None@n + * **User Interaction:** None@n + * + * **Test Procedure:** + * | Variation / Step | Description | Test Data | Expected Result | Notes | + * | :----: | --------- | ---------- |-------------- | ----- | + * | 01 | Instantiate DrmSessionManager with capacity 10 and context pointer 0x1234. | input1 = capacity: 10, input2 = context: reinterpret_cast(0x1234) | Instance should be created successfully. | Should be successful | + * | 02 | Register the first callback using a lambda capturing firstCallbackInvoked. | input = firstLambda, output = setfailureCb referencing firstLambda | Callback registration should succeed and setfailureCb should point to first callback. | Should Pass | + * | 03 | Invoke the first registered callback with ptr = 0x1111 and err = 10. | input = ptr: reinterpret_cast(0x1111), err: 10 | firstCallbackInvoked should be true and EXPECT_TRUE(firstCallbackInvoked) should pass. | Should Pass | + * | 04 | Overwrite the callback by registering a second lambda capturing secondCallbackInvoked. | input = secondLambda, output = setfailureCb referencing secondLambda | The previously registered callback should be overwritten successfully. | Should Pass | + * | 05 | Invoke the newly registered callback with ptr = 0x2222 and err = 20. | input = ptr: reinterpret_cast(0x2222), err: 20 | secondCallbackInvoked should be true and EXPECT_TRUE(secondCallbackInvoked) should pass. | Should Pass | + */ +TEST(DrmSessionManager, OverwriteExistingCallbackFunction) { + std::cout << "Entering OverwriteExistingCallbackFunction test" << std::endl; + + // Create an instance of DrmSessionManager. + DrmSessionManager drmSessionManager(10, reinterpret_cast(0x1234)); + + // First callback records its invocation. + bool firstCallbackInvoked = false; + auto firstLambda = [&firstCallbackInvoked](void* ptr, int err) { + std::cout << "First lambda callback invoked with ptr: " << ptr << " and err: " << err << std::endl; + firstCallbackInvoked = true; + }; + std::cout << "Invoking RegisterSetFailure with the first lambda callback" << std::endl; + drmSessionManager.RegisterSetFailure(firstLambda); + + std::cout << "Invoking the registered first lambda callback with test parameters: ptr = " + << reinterpret_cast(0x1111) << ", err = 10" << std::endl; + if (drmSessionManager.setfailureCb) { + drmSessionManager.setfailureCb(reinterpret_cast(0x1111), 10); + } + std::cout << "After invocation, firstCallbackInvoked: " << firstCallbackInvoked << std::endl; + EXPECT_TRUE(firstCallbackInvoked); + + // Second callback to overwrite the first one. + bool secondCallbackInvoked = false; + auto secondLambda = [&secondCallbackInvoked](void* ptr, int err) { + std::cout << "Second lambda callback invoked with ptr: " << ptr << " and err: " << err << std::endl; + secondCallbackInvoked = true; + }; + std::cout << "Overwriting the callback by invoking RegisterSetFailure with the second lambda callback" << std::endl; + drmSessionManager.RegisterSetFailure(secondLambda); + + std::cout << "Invoking the registered second lambda callback with test parameters: ptr = " + << reinterpret_cast(0x2222) << ", err = 20" << std::endl; + if (drmSessionManager.setfailureCb) { + drmSessionManager.setfailureCb(reinterpret_cast(0x2222), 20); + } + std::cout << "After invocation, secondCallbackInvoked: " << secondCallbackInvoked << std::endl; + EXPECT_TRUE(secondCallbackInvoked); + + std::cout << "Exiting OverwriteExistingCallbackFunction test" << std::endl; +} +/** + * @brief Verify callback mechanism in DrmSessionManager works with a lambda capturing a null pointer. + * + * This test verifies that the DrmSessionManager correctly registers and invokes a callback function defined as a lambda that captures a null pointer. The test ensures that once the callback is registered, invoking it with specific test parameters successfully triggers the lambda, setting the expected flag. + * + * **Test Group ID:** Basic: 01@n + * **Test Case ID:** 131@n + * **Priority:** High@n + * + * **Pre-Conditions:** None@n + * **Dependencies:** None@n + * **User Interaction:** None@n + * + * **Test Procedure:**@n + * | Variation / Step | Description | Test Data | Expected Result | Notes | + * | :----: | --------- | ---------- |-------------- | ----- | + * | 01 | Create DrmSessionManager instance. | maxSessions = 10, ptr = 0x1234 | Instance created successfully. | Should be successful | + * | 02 | Define lambda capturing a null pointer and a reference variable callbackInvoked. | capturedPtr = nullptr, callbackInvoked = false | Lambda defined successfully. | Should be successful | + * | 03 | Register the lambda as callback using RegisterSetFailure. | callback = lambdaWithNullCapture | Callback is set in drmSessionManager.setfailureCb. | Should Pass | + * | 04 | Invoke the registered callback with test parameters. | ptr = nullptr, err = 0 | Lambda is invoked and callbackInvoked becomes true. | Should Pass | + * | 05 | Verify that callbackInvoked is true using an assertion. | callbackInvoked expected = true | EXPECT_TRUE(callbackInvoked) passes. | Should Pass | + */ +TEST(DrmSessionManager, RegisterValidCallbackWithCapturedNullPointer) { + std::cout << "Entering RegisterValidCallbackWithCapturedNullPointer test" << std::endl; + + // Create an object of DrmSessionManager. + DrmSessionManager drmSessionManager(10, reinterpret_cast(0x1234)); + + // Define a lambda that captures a null pointer. + bool callbackInvoked = false; + auto lambdaWithNullCapture = [capturedPtr = static_cast(nullptr), &callbackInvoked](void* ptr, int err) { + std::cout << "Lambda with captured null pointer invoked. CapturedPtr: " << capturedPtr + << ", Parameters: ptr: " << ptr << ", err: " << err << std::endl; + callbackInvoked = true; + }; + std::cout << "Invoking RegisterSetFailure with lambda capturing a null pointer" << std::endl; + drmSessionManager.RegisterSetFailure(lambdaWithNullCapture); + + std::cout << "Callback registered. Invoking the callback with test parameters: ptr = nullptr, err = 0" << std::endl; + if (drmSessionManager.setfailureCb) { + drmSessionManager.setfailureCb(nullptr, 0); + } + std::cout << "After invocation, callbackInvoked: " << callbackInvoked << std::endl; + EXPECT_TRUE(callbackInvoked); + + std::cout << "Exiting RegisterValidCallbackWithCapturedNullPointer test" << std::endl; +} +/** + * @brief Verify that UpdateDRMConfig correctly updates DRM configuration when all input flags are true + * + * This test case ensures that invoking UpdateDRMConfig with all flags set to true updates the DRM configuration as expected and that the operations are logged for diagnostic purposes@n + * + * **Test Group ID:** Basic: 01@n + * **Test Case ID:** 132@n + * **Priority:** High@n + * + * **Pre-Conditions:** None@n + * **Dependencies:** None@n + * **User Interaction:** None@n + * + * **Test Procedure:**@n + * | Variation / Step | Description | Test Data | Expected Result | Notes | + * | :----: | --------- | ---------- |-------------- | ----- | + * | 01 | Construct the DrmSessionManager object | maxDrmSessions = 10, player = nullptr | Object is created successfully | Should be successful | + * | 02 | Log the input parameters before invoking UpdateDRMConfig | useSecManager = true, enablePROutputProtection = true, propagateURIParam = true, isFakeTune = true, wideVineKIDWorkaround = true | Parameters are printed as expected | Should be successful | + * | 03 | Invoke the UpdateDRMConfig method with all flags set to true | useSecManager = true, enablePROutputProtection = true, propagateURIParam = true, isFakeTune = true, wideVineKIDWorkaround = true | DRM configuration is updated without errors | Should Pass | + * | 04 | Log the completion of the test | N/A | Completion message is logged | Should be successful | + */ +TEST(DrmSessionManager, UpdateDRMConfig_AllTrue) { + std::cout << "Entering UpdateDRMConfig_AllTrue test" << std::endl; + + // Construct DrmSessionManager object using custom constructor. + DrmSessionManager drmManager(10, nullptr); + std::cout << "Created DrmSessionManager with maxDrmSessions = 10 and player = nullptr" << std::endl; + + // Log the input parameters. + bool useSecManager = true; + bool enablePROutputProtection = true; + bool propagateURIParam = true; + bool isFakeTune = true; + bool wideVineKIDWorkaround = true; + std::cout << "Invoking UpdateDRMConfig with parameters: " + << "useSecManager=" << useSecManager << ", " + << "enablePROutputProtection=" << enablePROutputProtection << ", " + << "propagateURIParam=" << propagateURIParam << ", " + << "isFakeTune=" << isFakeTune << ", " + << "wideVineKIDWorkaround=" << wideVineKIDWorkaround << std::endl; + + // Invoke the method. + drmManager.UpdateDRMConfig(useSecManager, enablePROutputProtection, propagateURIParam, isFakeTune, wideVineKIDWorkaround); + std::cout << "UpdateDRMConfig executed. DRM configuration updated to all true values." << std::endl; + + std::cout << "Exiting UpdateDRMConfig_AllTrue test" << std::endl; +} +/** + * @brief Verifies that the UpdateDRMConfig method correctly updates the DRM configuration when all input parameters are false + * + * This test ensures that when all the boolean parameters passed to UpdateDRMConfig are false, the DRM configuration of the DrmSessionManager is updated as expected. This is important to validate the basic functionality of the DRM configuration update operation under a minimal configuration scenario where security and protection features are disabled.@n + * + * **Test Group ID:** Basic: 01@n + * **Test Case ID:** 133@n + * **Priority:** High@n + * @n + * **Pre-Conditions:** None@n + * **Dependencies:** None@n + * **User Interaction:** None@n + * @n + * **Test Procedure:**@n + * | Variation / Step | Description | Test Data | Expected Result | Notes | + * | :--------------: | ------------------------------------------------------------------------------------ | -------------------------------------------------------------------------------------------------------------------------------------------------------- | ---------------------------------------------------------------- | ----------- | + * | 01 | Construct DrmSessionManager and invoke UpdateDRMConfig with all false parameters | Constructor: maxDrmSessions = 10, player = nullptr; UpdateDRMConfig: useSecManager = false, enablePROutputProtection = false, propagateURIParam = false, isFakeTune = false, wideVineKIDWorkaround = false | DRM configuration is updated with all false values with no errors | Should Pass | + */ +TEST(DrmSessionManager, UpdateDRMConfig_AllFalse) { + std::cout << "Entering UpdateDRMConfig_AllFalse test" << std::endl; + + // Construct DrmSessionManager object using custom constructor. + DrmSessionManager drmManager(10, nullptr); + std::cout << "Created DrmSessionManager with maxDrmSessions = 10 and player = nullptr" << std::endl; + + // Log the input parameters. + bool useSecManager = false; + bool enablePROutputProtection = false; + bool propagateURIParam = false; + bool isFakeTune = false; + bool wideVineKIDWorkaround = false; + std::cout << "Invoking UpdateDRMConfig with parameters: " + << "useSecManager=" << useSecManager << ", " + << "enablePROutputProtection=" << enablePROutputProtection << ", " + << "propagateURIParam=" << propagateURIParam << ", " + << "isFakeTune=" << isFakeTune << ", " + << "wideVineKIDWorkaround=" << wideVineKIDWorkaround << std::endl; + + // Invoke the method. + drmManager.UpdateDRMConfig(useSecManager, enablePROutputProtection, propagateURIParam, isFakeTune, wideVineKIDWorkaround); + std::cout << "UpdateDRMConfig executed. DRM configuration updated to all false values." << std::endl; + + std::cout << "Exiting UpdateDRMConfig_AllFalse test" << std::endl; +} +/** + * @brief Verify UpdateDRMConfig API handles a mixed configuration pattern correctly. + * + * This test verifies that the UpdateDRMConfig API is invoked on a DrmSessionManager object constructed with custom parameters and that the DRM configuration is updated according to a mixed pattern of boolean flags (true, false, true, false, true). The purpose of this test is to validate the proper behavior of the API when provided with a combination of true and false flags. + * + * **Test Group ID:** Basic: 01@n + * **Test Case ID:** 134@n + * **Priority:** High@n + * + * **Pre-Conditions:** None@n + * **Dependencies:** None@n + * **User Interaction:** None@n + * + * **Test Procedure:** + * | Variation / Step | Description | Test Data | Expected Result | Notes | + * | :--------------: | ----------------------------------------------------------------------------------------------------- | -------------------------------------------------------------------------------------------------------------------- | -------------------------------------------------------------------------------------------------------------- | --------------- | + * | 01 | Construct DrmSessionManager using custom constructor. | input: maxDrmSessions = 10, player = nullptr | DrmSessionManager object is created successfully. | Should be successful | + * | 02 | Log the input parameters for the UpdateDRMConfig method invocation. | input: useSecManager = true, enablePROutputProtection = false, propagateURIParam = true, isFakeTune = false, wideVineKIDWorkaround = true | The input parameters are printed correctly to the console. | Should be successful | + * | 03 | Invoke the UpdateDRMConfig API with the specified boolean flag configuration. | input: useSecManager = true, enablePROutputProtection = false, propagateURIParam = true, isFakeTune = false, wideVineKIDWorkaround = true | DRM configuration is updated with the pattern (true, false, true, false, true) and returns normally. | Should Pass | + * | 04 | Log the exit message indicating the completion of the test. | No additional input | Exit message is printed to indicate the end of the test execution. | Should be successful | + */ +TEST(DrmSessionManager, UpdateDRMConfig_Mixed1) { + std::cout << "Entering UpdateDRMConfig_Mixed1 test" << std::endl; + + // Construct DrmSessionManager object using custom constructor. + DrmSessionManager drmManager(10, nullptr); + std::cout << "Created DrmSessionManager with maxDrmSessions = 10 and player = nullptr" << std::endl; + + // Log the input parameters. + bool useSecManager = true; + bool enablePROutputProtection = false; + bool propagateURIParam = true; + bool isFakeTune = false; + bool wideVineKIDWorkaround = true; + std::cout << "Invoking UpdateDRMConfig with parameters: " + << "useSecManager=" << useSecManager << ", " + << "enablePROutputProtection=" << enablePROutputProtection << ", " + << "propagateURIParam=" << propagateURIParam << ", " + << "isFakeTune=" << isFakeTune << ", " + << "wideVineKIDWorkaround=" << wideVineKIDWorkaround << std::endl; + + // Invoke the method. + drmManager.UpdateDRMConfig(useSecManager, enablePROutputProtection, propagateURIParam, isFakeTune, wideVineKIDWorkaround); + std::cout << "UpdateDRMConfig executed. DRM configuration updated with pattern (true, false, true, false, true)." << std::endl; + + std::cout << "Exiting UpdateDRMConfig_Mixed1 test" << std::endl; +} +/** + * @brief Verify that UpdateDRMConfig correctly applies mixed boolean configuration parameters. + * + * This test verifies that the UpdateDRMConfig method of the DrmSessionManager class is capable of correctly updating its DRM configuration when provided with a specific combination of boolean parameters. The test logs each significant step, ensuring that constructor initialization and subsequent configuration update behave as expected. + * + * **Test Group ID:** Basic: 01@n + * **Test Case ID:** 135@n + * **Priority:** High@n + * + * **Pre-Conditions:** None@n + * **Dependencies:** None@n + * **User Interaction:** None@n + * + * **Test Procedure:** + * | Variation / Step | Description | Test Data | Expected Result | Notes | + * | :----: | --------- | ---------- |-------------- | ----- | + * | 01 | Create DRM session manager object with custom constructor. | maxDrmSessions = 10, player = nullptr | drmManager object successfully created. | Should be successful | + * | 02 | Log input parameters for UpdateDRMConfig method. | useSecManager = false, enablePROutputProtection = true, propagateURIParam = false, isFakeTune = true, wideVineKIDWorkaround = false | Parameters logged correctly. | Should be successful | + * | 03 | Invoke UpdateDRMConfig method with mixed boolean parameters. | useSecManager = false, enablePROutputProtection = true, propagateURIParam = false, isFakeTune = true, wideVineKIDWorkaround = false | DRM configuration updated correctly; method executed without errors. | Should Pass | + */ +TEST(DrmSessionManager, UpdateDRMConfig_Mixed2) { + std::cout << "Entering UpdateDRMConfig_Mixed2 test" << std::endl; + + // Construct DrmSessionManager object using custom constructor. + DrmSessionManager drmManager(10, nullptr); + std::cout << "Created DrmSessionManager with maxDrmSessions = 10 and player = nullptr" << std::endl; + + // Log the input parameters. + bool useSecManager = false; + bool enablePROutputProtection = true; + bool propagateURIParam = false; + bool isFakeTune = true; + bool wideVineKIDWorkaround = false; + std::cout << "Invoking UpdateDRMConfig with parameters: " + << "useSecManager=" << useSecManager << ", " + << "enablePROutputProtection=" << enablePROutputProtection << ", " + << "propagateURIParam=" << propagateURIParam << ", " + << "isFakeTune=" << isFakeTune << ", " + << "wideVineKIDWorkaround=" << wideVineKIDWorkaround << std::endl; + + // Invoke the method. + drmManager.UpdateDRMConfig(useSecManager, enablePROutputProtection, propagateURIParam, isFakeTune, wideVineKIDWorkaround); + std::cout << "UpdateDRMConfig executed. DRM configuration updated with pattern (false, true, false, true, false)." << std::endl; + + std::cout << "Exiting UpdateDRMConfig_Mixed2 test" << std::endl; +} + +int main(int argc, char **argv) { + ::testing::InitGoogleTest(&argc, argv); + return RUN_ALL_TESTS(); +} \ No newline at end of file diff --git a/drm/test/test_l1_PlayerHlsDrmSessionInterface.cpp b/drm/test/test_l1_PlayerHlsDrmSessionInterface.cpp new file mode 100755 index 0000000..9dc12f9 --- /dev/null +++ b/drm/test/test_l1_PlayerHlsDrmSessionInterface.cpp @@ -0,0 +1,374 @@ +/* + * If not stated otherwise in this file or this component's LICENSE file the + * following copyright and licenses apply: + * + * Copyright 2025 RDK Management + * + * 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. + */ + + /** +* @file test_l1_PlayerHlsDrmSessionInterface.cpp +* @page PlayerHlsDrmSessionInterface Level 1 Tests +* +* ## Module's Role +* This module includes Level 1 functional tests (success and failure scenarios). +* This is to ensure that the PlayerHlsDrmSessionInterface methods meet the requirements. +* +* **Pre-Conditions:** None @n +* **Dependencies:** None @n +* +*/ + +#include +#include +#include +#include "PlayerHlsDrmSessionInterface.h" + +/** + * @brief Positive test for createSession with a valid positive stream type. + * + * This test validates that invoking createSession with a valid drmInfo and a positive stream type returns the expected result as confirmed by the ASSERT_EQ check, ensuring the manager's behavior aligns with the expectations under normal conditions. + * + * **Test Group ID:** Basic: 01 + * **Test Case ID:** 001 + * **Priority:** High + * + * **Pre-Conditions:** None + * **Dependencies:** None + * **User Interaction:** None + * + * **Test Procedure:** + * | Variation / Step | Description | Test Data | Expected Result | Notes | + * | :---------------:| -------------------------------------------------------------------- | ----------------------------------------- | ---------------------------------------------------- | ----------- | + * | 01 | Invoke createSession with drmInfo (default) and streamType = 10 | drmInfo = default, streamType = 10 | API returns nullptr and ASSERT_EQ validates the result | Should Pass | + */ +TEST(FakeHlsDrmSessionManager, PositiveStreamType) { + std::cout << "Entering PositiveStreamType test" << std::endl; + DrmInfo drmInfo; + int streamType = 10; + + std::cout << "Invoking createSession with positive streamType = " << streamType << std::endl; + FakeHlsDrmSessionManager manager; + auto session = manager.createSession(drmInfo, streamType); + std::cout << "createSession returned: " << (session == nullptr ? "nullptr" : "non-null") << std::endl; + + ASSERT_EQ(session, nullptr); + + std::cout << "Exiting PositiveStreamType test" << std::endl; +} + +/** + * @brief Verify that createSession returns nullptr when provided with a negative stream type + * + * This test case validates the behavior of FakeHlsDrmSessionManager's createSession method when an invalid, negative stream type is provided. The test confirms that the API correctly handles invalid input by returning a nullptr, ensuring robust error handling in the session creation process. + * + * **Test Group ID:** Basic: 01@n + * **Test Case ID:** 002@n + * **Priority:** High@n + * + * **Pre-Conditions:** None@n + * **Dependencies:** None@n + * **User Interaction:** None@n + * + * **Test Procedure:** + * | Variation / Step | Description | Test Data | Expected Result | Notes | + * | :----: | --------- | ---------- |-------------- | ----- | + * | 01 | Initialize drmInfo and streamType with invalid negative value | drmInfo = default, streamType = -1 | Inputs initialized correctly | Should be successful | + * | 02 | Invoke createSession API with invalid streamType | drmInfo = default, streamType = -1 | API returns nullptr indicating failure for invalid stream type input | Should Fail | + * | 03 | Verify that the returned session is nullptr using ASSERT_EQ | session == nullptr | Assertion passes confirming the API's correct error handling | Should be successful | + */ +TEST(FakeHlsDrmSessionManager, NegativeStreamType) { + std::cout << "Entering NegativeStreamType test" << std::endl; + DrmInfo drmInfo; + int streamType = -1; + + std::cout << "Invoking createSession with negative streamType = " << streamType << std::endl; + FakeHlsDrmSessionManager manager; + auto session = manager.createSession(drmInfo, streamType); + std::cout << "createSession returned: " << (session == nullptr ? "nullptr" : "non-null") << std::endl; + + ASSERT_EQ(session, nullptr); + + std::cout << "Exiting NegativeStreamType test" << std::endl; +} + +/** + * @brief Verify that default constructed DRM objects return expected support status + * + * This test verifies that a default constructed FakeHlsDrmSessionManager and a default constructed DrmInfo object behave as expected when passed to isDrmSupported. This ensures that the default initialization state provides the correct support status. + * + * **Test Group ID:** Basic: 01@n + * **Test Case ID:** 003@n + * **Priority:** High@n + * + * **Pre-Conditions:** None@n + * **Dependencies:** None@n + * **User Interaction:** None@n + * + * **Test Procedure:** + * | Variation / Step | Description | Test Data | Expected Result | Notes | + * | :--------------: | ----------------------------------------------------------------------- | ----------------------------------------------------------- | ----------------------------------------------------------------------------- | --------------- | + * | 01 | Create default constructed FakeHlsDrmSessionManager and DrmInfo objects | manager = FakeHlsDrmSessionManager(), drmInfo = DrmInfo() | Objects instantiated with default values | Should be successful | + * | 02 | Invoke isDrmSupported with default DrmInfo | input: drmInfo.method = default, drmInfo.mediaFormat = default| Returns boolean value indicating whether DRM is supported (expected to pass) | Should Pass | + */ +TEST(FakeHlsDrmSessionManager, DefaultConstructedDrmInfo) { + std::cout << "Entering DefaultConstructedDrmInfo test" << std::endl; + // Create a default instance of FakeHlsDrmSessionManager using default constructor + FakeHlsDrmSessionManager manager; + // Create default constructed DrmInfo + DrmInfo drmInfo; + + std::cout << "Created default DrmInfo with method = " << drmInfo.method + << " and mediaFormat = " << drmInfo.mediaFormat << std::endl; + // Invoke the method isDrmSupported + std::cout << "Invoking isDrmSupported with default DrmInfo" << std::endl; + bool support = manager.isDrmSupported(drmInfo); + + std::cout << "Returned value from isDrmSupported: " << support << std::endl; + + std::cout << "Exiting DefaultConstructedDrmInfo test" << std::endl; +} + +/** + * @brief Verify that registering a valid callback correctly saves the callback for later use within FakeHlsDrmSessionManager + * + * This test ensures that when a valid callback lambda is registered to the FakeHlsDrmSessionManager, it is properly stored. + * The test verifies the registration mechanism by checking the internal state update through a callback mechanism. + * + * **Test Group ID:** Basic: 01@n + * **Test Case ID:** 004@n + * **Priority:** High@n + * + * **Pre-Conditions:** None@n + * **Dependencies:** None@n + * **User Interaction:** None@n + * + * **Test Procedure:**@n + * | Variation / Step | Description | Test Data | Expected Result | Notes | + * | :----: | --------- | ---------- |-------------- | ----- | + * | 01 | Log the entry into RegisterValidCallbackAndVerifyStorage test | No inputs, output: "Entering RegisterValidCallbackAndVerifyStorage test" printed | Log message printed indicating start of test | Should be successful | + * | 02 | Create an instance of FakeHlsDrmSessionManager | No inputs, output: instance of FakeHlsDrmSessionManager created | Instance successfully created | Should be successful | + * | 03 | Define and initialize callbackInvoked variable and a valid callback lambda | callbackInvoked = 0; validCallback lambda defined with input: bridge, drmHelper, session, streamType | Lambda is defined and callbackInvoked set to 0, expected to be updated when invoked | Should be successful | + * | 04 | Register the valid callback lambda via RegisterGetHlsDrmSessionCb | Input: validCallback; output: callback registration within fakeManager | Callback is registered correctly within FakeHlsDrmSessionManager | Should Pass | + * | 05 | Log the exit from the test case | No inputs, output: "Exiting RegisterValidCallbackAndVerifyStorage test" printed | Log message printed indicating end of test | Should be successful | + */ +TEST(FakeHlsDrmSessionManager, RegisterValidCallbackAndVerifyStorage) { + std::cout << "Entering RegisterValidCallbackAndVerifyStorage test" << std::endl; + FakeHlsDrmSessionManager fakeManager; + int callbackInvoked = 0; + auto validCallback = [&callbackInvoked](std::shared_ptr& bridge, + std::shared_ptr& drmHelper, + DrmSession*& session, + int streamType) { + std::cout << "Invoking validCallback lambda with streamType: " << streamType << std::endl; + callbackInvoked = 1; + }; + std::cout << "Invoking RegisterGetHlsDrmSessionCb with valid callback lambda" << std::endl; + fakeManager.RegisterGetHlsDrmSessionCb(validCallback); + std::cout << "Exiting RegisterValidCallbackAndVerifyStorage test" << std::endl; +} + +/** + * @brief Verify that registering an empty callback does not alter internal storage behavior. + * + * This test verifies the behavior of FakeHlsDrmSessionManager when an empty (default constructed) callback is registered. + * It ensures that the API accepts an empty callback without errors and that the storage for callbacks remains consistent. + * + * **Test Group ID:** Basic: 01@n + * **Test Case ID:** 005@n + * **Priority:** High@n + * + * **Pre-Conditions:** None@n + * **Dependencies:** None@n + * **User Interaction:** None@n + * + * **Test Procedure:** + * | Variation / Step | Description | Test Data | Expected Result | Notes | + * | :--------------: | --------------------------------------------------------------------------- | ---------------------------------------------------------------------------------------------- | ----------------------------------------------------------------------------------------------- | ------------- | + * | 01 | Print the entering test log message. | Message = "Entering RegisterEmptyCallbackAndVerifyStorage test" | The entering log is printed. | Should be successful | + * | 02 | Invoke RegisterGetHlsDrmSessionCb with an empty callback on fakeManager. | input: emptyCallback = default constructed, fakeManager instance registered via API call | The empty callback is registered with fakeManager without errors (API returns void). | Should Pass | + * | 03 | Print the exiting test log message. | Message = "Exiting RegisterEmptyCallbackAndVerifyStorage test" | The exiting log is printed. | Should be successful | + */ +TEST(FakeHlsDrmSessionManager, RegisterEmptyCallbackAndVerifyStorage) { + std::cout << "Entering RegisterEmptyCallbackAndVerifyStorage test" << std::endl; + FakeHlsDrmSessionManager fakeManager; + std::function&, std::shared_ptr&, DrmSession*&, int)> emptyCallback; + std::cout << "Invoking RegisterGetHlsDrmSessionCb with empty callback (default constructed)" << std::endl; + fakeManager.RegisterGetHlsDrmSessionCb(emptyCallback); + std::cout << "Exiting RegisterEmptyCallbackAndVerifyStorage test" << std::endl; +} + +/** + * @brief Verifies that registering a valid callback successfully registers it in PlayerHlsDrmSessionInterface. + * + * This test ensures that a valid callback lambda can be registered with the PlayerHlsDrmSessionInterface. It validates that the registration method accepts the callback and that the corresponding console outputs are produced, indicating the correct functioning of the callback registration mechanism. + * + * **Test Group ID:** Basic: 01@n + * **Test Case ID:** 006@n + * **Priority:** High@n + * + * **Pre-Conditions:** None@n + * **Dependencies:** None@n + * **User Interaction:** None@n + * + * **Test Procedure:**@n + * | Variation / Step | Description | Test Data | Expected Result | Notes | + * | :----: | ------------------------------------------------------------------ | --------------------------------------------------------------------- | ---------------------------------------------------------------------- | ----------- | + * | 01 | Invoke RegisterGetHlsDrmSessionCb with a valid callback lambda | playerHlsDrmSessionInterface = instance, validCallback = lambda | Callback registered successfully; appropriate output messages displayed | Should Pass | + */ +TEST(PlayerHlsDrmSessionInterface, RegisterValidCallback) { + std::cout << "Entering RegisterValidCallback test" << std::endl; + PlayerHlsDrmSessionInterface playerHlsDrmSessionInterface; + std::cout << "Created PlayerHlsDrmSessionInterface object" << std::endl; + auto validCallback = [] (std::shared_ptr& bridge, + std::shared_ptr& drmHelper, + DrmSession*& session, + int streamType) { + std::cout << "Invoking RegisterGetHlsDrmSessionCb with valid callback lambda" << std::endl; + }; + playerHlsDrmSessionInterface.RegisterGetHlsDrmSessionCb(validCallback); + std::cout << "Exiting RegisterValidCallback test" << std::endl; +} + +/** + * @brief Verify that an empty callback is registered safely without errors. + * + * This test verifies whether the RegisterGetHlsDrmSessionCb method of PlayerHlsDrmSessionInterface can accept an empty callback and execute without any errors. + * + * **Test Group ID:** Basic: 01@n + * **Test Case ID:** 007@n + * **Priority:** High@n + * + * **Pre-Conditions:** None@n + * **Dependencies:** None@n + * **User Interaction:** None@n + * + * **Test Procedure:**@n + * | Variation / Step | Description | Test Data | Expected Result | Notes | + * | :----: | --------- | ---------- |-------------- | ----- | + * | 01 | Log entry message indicating the start of the test | None | "Entering RegisterEmptyCallback test" message printed | Should be successful | + * | 02 | Create an instance of PlayerHlsDrmSessionInterface and declare an empty callback | PlayerHlsDrmSessionInterface instance, emptyCallback = uninitialized | Instance created and empty callback declared successfully | Should be successful | + * | 03 | Log message before API invocation | None | "Invoking RegisterGetHlsDrmSessionCb with empty callback" message printed | Should be successful | + * | 04 | Invoke RegisterGetHlsDrmSessionCb with an empty callback | input: emptyCallback = empty | API accepts empty callback without error | Should Pass | + * | 05 | Log exit message indicating the end of the test | None | "Exiting RegisterEmptyCallback test" message printed | Should be successful | + */ +TEST(PlayerHlsDrmSessionInterface, RegisterEmptyCallback) { + std::cout << "Entering RegisterEmptyCallback test" << std::endl; + PlayerHlsDrmSessionInterface playerHlsDrmSessionInterface; + std::function&, std::shared_ptr&, DrmSession*&, int)> emptyCallback; + std::cout << "Invoking RegisterGetHlsDrmSessionCb with empty callback" << std::endl; + playerHlsDrmSessionInterface.RegisterGetHlsDrmSessionCb(emptyCallback); + std::cout << "Exiting RegisterEmptyCallback test" << std::endl; +} + +/** + * @brief Verify that a valid DRM session is created when a positive stream type is provided. + * + * This test validates that the createSession() method of the PlayerHlsDrmSessionInterface class returns a non-null session pointer when invoked with a default initialized DrmInfo and a positive stream type value (15). It ensures that the DRM session creation functionality behaves correctly in a positive scenario. + * + * **Test Group ID:** Basic: 01@n + * **Test Case ID:** 008@n + * **Priority:** High@n + * + * **Pre-Conditions:** None@n + * **Dependencies:** None@n + * **User Interaction:** None@n + * + * **Test Procedure:** + * | Variation / Step | Description | Test Data | Expected Result | Notes | + * | :--------------: | ----------------------------------------------------------------------------------------------- | --------------------------------------------------------- | -------------------------------------------------------------------------------- | ------------- | + * | 01 | Create an instance of PlayerHlsDrmSessionInterface using its default constructor. | drmSessionInterface: default constructed instance | Instance is created successfully. | Should be successful | + * | 02 | Prepare input parameters including a default DrmInfo and setting streamType to 15. | drmInfo: default, streamType = 15 | Input parameters are ready for API invocation. | Should be successful | + * | 03 | Invoke the createSession method with the prepared drmInfo and positive streamType, and capture output. | drmInfo: default, streamType = 15 | A session pointer is returned which is not null. | Should Pass | + * | 04 | Validate that the returned session pointer is not null using the EXPECT_NE assertion check. | session pointer from createSession invocation | Assertion confirms that the session pointer is non-null. | Should Pass | + */ +TEST(PlayerHlsDrmSessionInterface, ValidDRMSession_PositiveType) +{ + std::cout << "Entering ValidDRMSession_PositiveType test" << std::endl; + // Create instance of PlayerHlsDrmSessionInterface using default constructor + PlayerHlsDrmSessionInterface drmSessionInterface; + // Prepare DrmInfo input + DrmInfo drmInfo; + int streamType = 15; + std::cout << "Invoking createSession with valid drminfo and positive streamType: " << streamType << std::endl; + // Invoke the method under test + std::shared_ptr session = drmSessionInterface.createSession(drmInfo, streamType); + EXPECT_NE(session, nullptr); + std::cout << "Exiting ValidDRMSession_PositiveType test" << std::endl; +} + +/** + * @brief Test to ensure DRM session creation fails for negative stream type. + * + * This test verifies that invoking the createSession method of PlayerHlsDrmSessionInterface with a valid DrmInfo and an invalid negative streamType (-1) results in a null session pointer. It ensures that the API correctly handles negative stream types as an error scenario. + * + * **Test Group ID:** Basic: 01@n + * **Test Case ID:** 009@n + * **Priority:** High@n + * + * **Pre-Conditions:** None@n + * **Dependencies:** None@n + * **User Interaction:** None@n + * + * **Test Procedure:**@n + * | Variation / Step | Description | Test Data | Expected Result | Notes | + * | :----: | --------- | ---------- |-------------- | ----- | + * | 01 | Print entering test message | N/A | "Entering DRMSession_NegativeStreamType test" printed to console | Should be successful | + * | 02 | Instantiate PlayerHlsDrmSessionInterface and DrmInfo objects | drmSessionInterface = instance, drmInfo = instance | Objects are created successfully | Should be successful | + * | 03 | Invoke createSession with a valid drmInfo and negative streamType (-1) | drmInfo, streamType = -1 | API returns nullptr | Should Fail | + * | 04 | Assert that the return value is nullptr and print exiting test message | EXPECT_EQ(session, nullptr) check, exit message printed | EXPECT_EQ passes confirming no session is created | Should be successful | + */ +TEST(PlayerHlsDrmSessionInterface, DRMSession_NegativeStreamType) +{ + std::cout << "Entering DRMSession_NegativeStreamType test" << std::endl; + PlayerHlsDrmSessionInterface drmSessionInterface; + DrmInfo drmInfo; + int streamType = -1; + std::cout << "Invoking createSession with with valid drminfo and negative streamType: " << streamType << std::endl; + std::shared_ptr session = drmSessionInterface.createSession(drmInfo, streamType); + EXPECT_EQ(session, nullptr); + std::cout << "Exiting DRMSession_NegativeStreamType test" << std::endl; +} + +/** + * @brief Verify valid instance creation of PlayerHlsDrmSessionInterface. + * + * This test verifies that calling PlayerHlsDrmSessionInterface::getInstance() returns a valid, non-null pointer, ensuring the proper creation and access to the singleton instance. + * + * **Test Group ID:** Basic: 01@n + * **Test Case ID:** 010@n + * **Priority:** High@n + * + * **Pre-Conditions:** None@n + * **Dependencies:** None@n + * **User Interaction:** None@n + * + * **Test Procedure:**@n + * | Variation / Step | Description | Test Data | Expected Result | Notes | + * | :----: | --------- | ---------- |-------------- | ----- | + * | 01 | Invoke PlayerHlsDrmSessionInterface::getInstance() to create the instance | input: None, output: instance pointer | The returned instance pointer should not be nullptr and the assertion check passes | Should Pass | + */ +TEST(PlayerHlsDrmSessionInterface, ValidInstanceCreation) { + std::cout << "Entering ValidInstanceCreation test" << std::endl; + std::cout << "Invoking PlayerHlsDrmSessionInterface::getInstance()" << std::endl; + PlayerHlsDrmSessionInterface* instance = PlayerHlsDrmSessionInterface::getInstance(); + std::cout << "Returned instance pointer: " << instance << std::endl; + ASSERT_NE(instance, nullptr); + std::cout << "Exiting ValidInstanceCreation test" << std::endl; +} + +int main(int argc, char **argv) { + ::testing::InitGoogleTest(&argc, argv); + return RUN_ALL_TESTS(); +} \ No newline at end of file From 7af930f80da2e2134bb3caea436c7f17f01bfc78 Mon Sep 17 00:00:00 2001 From: joyal Date: Mon, 21 Jul 2025 17:53:24 +0530 Subject: [PATCH 8/9] gh #2: Generate_L1_tests --- .../test/test_l1_PlayerSubtecCCManager.cpp | 1943 +++++++++++++++++ 1 file changed, 1943 insertions(+) create mode 100755 closedcaptions/subtec/test/test_l1_PlayerSubtecCCManager.cpp diff --git a/closedcaptions/subtec/test/test_l1_PlayerSubtecCCManager.cpp b/closedcaptions/subtec/test/test_l1_PlayerSubtecCCManager.cpp new file mode 100755 index 0000000..7be7dbb --- /dev/null +++ b/closedcaptions/subtec/test/test_l1_PlayerSubtecCCManager.cpp @@ -0,0 +1,1943 @@ + +/* + * If not stated otherwise in this file or this component's LICENSE file the + * following copyright and licenses apply: + * + * Copyright 2025 RDK Management + * + * 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. + */ + +/** +* @file test_l1_PlayerSubtecCCManager.cpp +* @page PlayerSubtecCCManager Level 1 Tests +* +* ## Module's Role +* This module includes Level 1 functional tests (success and failure scenarios). +* This is to ensure that the PlayerSubtecCCManager methods meet the requirements. +* +* **Pre-Conditions:** None @n +* **Dependencies:** None @n +* +*/ + +#include +#include +#include +#include "PlayerSubtecCCManager.h" + + +// Test case: Verify GetId returns a valid unique identifier for a properly instantiated object +/** + * @brief Verify that GetId returns a valid unique identifier from a PlayerSubtecCCManager object + * + * This test case creates a PlayerSubtecCCManager instance, invokes the GetId method, and validates that the returned identifier is a non-negative integer. It ensures that the unique identifier generation works correctly for a default constructed object. + * + * **Test Group ID:** Basic: 01@n + * **Test Case ID:** 001@n + * **Priority:** High@n + * + * **Pre-Conditions:** None@n + * **Dependencies:** None@n + * **User Interaction:** None@n + * + * **Test Procedure:**@n + * | Variation / Step | Description | Test Data | Expected Result | Notes | + * | :--------------: | ----------------------------------------------------- | ---------------------------------------------------------------- | -------------------------------------------------- | --------------- | + * | 01 | Create an instance of PlayerSubtecCCManager using default constructor | No input, output: instance created | Instance is created successfully | Should be successful | + * | 02 | Invoke the GetId method on the PlayerSubtecCCManager instance | input: instance, method call: GetId(), output: id value | GetId returns a valid identifier (non-negative integer) | Should Pass | + * | 03 | Validate the returned id is a non-negative integer | input: id value from GetId = retrieved id | Assertion EXPECT_GE(id, 0) passes | Should Pass | + */ +TEST(PlayerSubtecCCManager, GetId_returns_valid_unique_identifier) { + std::cout << "Entering GetId_returns_valid_unique_identifier test" << std::endl; + + // Create an object of PlayerSubtecCCManager using default constructor + PlayerSubtecCCManager manager; + std::cout << "Invoking GetId on a valid PlayerSubtecCCManager instance." << std::endl; + + // Call GetId and capture the returned id + int id = manager.GetId(); + std::cout << "Retrieved ID from GetId(): " << id << std::endl; + + // Check that the id is a non-negative integer + EXPECT_GE(id, 0); + + std::cout << "Exiting GetId_returns_valid_unique_identifier test" << std::endl; +} +/** + * @brief Validate that GetId returns unique identifiers for different instances of PlayerSubtecCCManager + * + * This test creates two separate instances of PlayerSubtecCCManager and verifies that calling GetId on each instance returns a non-negative integer and that the two identifiers are distinct. This ensures that each instance is uniquely identifiable. + * + * **Test Group ID:** Basic: 01@n + * **Test Case ID:** 002@n + * **Priority:** High@n + * + * **Pre-Conditions:** None@n + * **Dependencies:** None@n + * **User Interaction:** None@n + * + * **Test Procedure:**@n + * | Variation / Step | Description | Test Data | Expected Result | Notes | + * | :----: | ------------------------------------------------------------------- | -------------------------------------------------------------------- | ------------------------------------------------------------------------- | ------------- | + * | 01 | Create two separate instances of PlayerSubtecCCManager | manager1 = PlayerSubtecCCManager instance, manager2 = PlayerSubtecCCManager instance | Two distinct objects are instantiated successfully | Should be successful | + * | 02 | Invoke GetId() on the first instance to retrieve its identifier | input: manager1, output: id1 = manager1.GetId() | id1 is non-negative | Should Pass | + * | 03 | Invoke GetId() on the second instance to retrieve its identifier | input: manager2, output: id2 = manager2.GetId() | id2 is non-negative | Should Pass | + * | 04 | Assert that the two identifiers are different | input: id1, id2, expected: id1 != id2 | The IDs from the two instances are distinct | Should Pass | + */ +TEST(PlayerSubtecCCManager, GetId_return_different_ids_for_different_instances) { + std::cout << "Entering GetId_return_different_ids_for_different_instances test" << std::endl; + + // Create two separate PlayerSubtecCCManager objects + PlayerSubtecCCManager manager1; + PlayerSubtecCCManager manager2; + std::cout << "Created two separate PlayerSubtecCCManager instances." << std::endl; + + // Call GetId on the first instance and log the id + std::cout << "Invoking GetId on the first instance." << std::endl; + int id1 = manager1.GetId(); + std::cout << "Retrieved ID from first instance: " << id1 << std::endl; + + // Call GetId on the second instance and log the id + std::cout << "Invoking GetId on the second instance." << std::endl; + int id2 = manager2.GetId(); + std::cout << "Retrieved ID from second instance: " << id2 << std::endl; + + // Verify that both IDs are non-negative and different from each other + EXPECT_GE(id1, 0); + EXPECT_GE(id2, 0); + EXPECT_NE(id1, id2); + + std::cout << "Exiting GetId_return_different_ids_for_different_instances test" << std::endl; +} +/** + * @brief Verify successful default construction of PlayerSubtecCCManager + * + * This test verifies that the default constructor of PlayerSubtecCCManager properly creates an instance without throwing exceptions. It also checks that the internal state is correctly default initialized. + * + * **Test Group ID:** Basic: 01@n + * **Test Case ID:** 003@n + * **Priority:** (High) This test is critical as it ensures object instantiation works as expected@n + * + * **Pre-Conditions:** None@n + * **Dependencies:** None@n + * **User Interaction:** None@n + * + * **Test Procedure:** + * | Variation / Step | Description | Test Data | Expected Result | Notes | + * | :----: | :------------------------------------------------------------------------------- | :--------------------------------------------- | :-------------------------------------------------------------------------------------------- | :--------: | + * | 01 | Invoke the default constructor of PlayerSubtecCCManager and verify no exception is thrown | No inputs, no outputs | Instance is successfully created with default initialized internal members and no exceptions occur | Should Pass | + */ +TEST(PlayerSubtecCCManager, SuccessfulDefaultConstruction) +{ + std::cout << "Entering SuccessfulDefaultConstruction test" << std::endl; + + // Log invocation of default constructor + std::cout << "Invoking PlayerSubtecCCManager default constructor." << std::endl; + try + { + PlayerSubtecCCManager manager; + std::cout << "PlayerSubtecCCManager instance created successfully." << std::endl; + + // Debug log for internal state check: + // (Since internal members are default initialized and not accessible outside, we rely on the successful construction.) + std::cout << "Internal member mLastTextTracks is default initialized." << std::endl; + } + catch(const std::exception& e) + { + std::cout << "Exception caught during construction: " << e.what() << std::endl; + FAIL(); + } + + std::cout << "Exiting SuccessfulDefaultConstruction test" << std::endl; +} +/** + * @brief Test to validate that Release method succeeds when invoked with a valid existing ID. + * + * This test verifies that invoking the Release method on an instance of PlayerSubtecCCManager with an existing ID (1) does not throw an exception, ensuring that the associated track is correctly released. + * + * **Test Group ID:** Basic: 01@n + * **Test Case ID:** 004@n + * **Priority:** High@n + * + * **Pre-Conditions:** None@n + * **Dependencies:** None@n + * **User Interaction:** None@n + * + * **Test Procedure:** + * | Variation / Step | Description | Test Data | Expected Result | Notes | + * | :----: | --------- | ---------- |-------------- | ----- | + * | 01 | Create an instance of PlayerSubtecCCManager using its default constructor. | (no input required) | Instance of PlayerSubtecCCManager successfully created. | Should be successful | + * | 02 | Define a valid track ID for the test. | iID = 1 | A valid track ID is set with value 1. | Should be successful | + * | 03 | Invoke the Release method with the provided valid iID and check for exceptions. | iID = 1, output from Release = none | Release method executes without throwing any exception; EXPECT_NO_THROW assertion passes. | Should Pass | + * | 04 | Log the successful release of the associated track with the valid iID. | iID = 1, console log = release messages | Console logs display successful execution indicating the track associated with iID 1 has been released. | Should be successful | + */ +TEST(PlayerSubtecCCManager, ValidReleaseWithExistingID) { + std::cout << "Entering ValidReleaseWithExistingID test" << std::endl; + + int iID = 1; + std::cout << "Creating PlayerSubtecCCManager object using default constructor." << std::endl; + PlayerSubtecCCManager manager; + + std::cout << "Invoking Release with iID: " << iID << std::endl; + EXPECT_NO_THROW({ + manager.Release(iID); + }); + std::cout << "Release invoked with iID: " << iID << std::endl; + std::cout << "Track associated with ID " << iID << " is expected to be released successfully." << std::endl; + + std::cout << "Exiting ValidReleaseWithExistingID test" << std::endl; +} +/** + * @brief Validate that calling Release with a non-existent ID does not throw exceptions. + * + * This test case is designed to verify that the Release method of the PlayerSubtecCCManager class handles a non-existent track ID gracefully by not throwing any exceptions. The test ensures that the API call to Release with an ID that is not associated with any track performs the operation safely. + * + * **Test Group ID:** Basic: 01 / Module (L2): 02 / Stress (L2): 03 + * **Test Case ID:** 005 + * **Priority:** High + * + * **Pre-Conditions:** None + * **Dependencies:** None + * **User Interaction:** None + * + * **Test Procedure:** + * | Variation / Step | Description | Test Data | Expected Result | Notes | + * | :--------------: | ----------------------------------------------------------------- | ---------------------------------------- | ------------------------------------------------------------ | --------------- | + * | 01 | Create a PlayerSubtecCCManager instance using the default constructor. | output1 = instance created successfully | Manager object is instantiated without error. | Should be successful | + * | 02 | Invoke Release() with a non-existent ID (iID = 999). | input1 = iID = 999, output1 = void | Release method completes execution without throwing any exception. | Should Pass | + */ +TEST(PlayerSubtecCCManager, ReleaseWithNonExistentID) { + std::cout << "Entering ReleaseWithNonExistentID test" << std::endl; + + int iID = 999; + std::cout << "Creating PlayerSubtecCCManager object using default constructor." << std::endl; + PlayerSubtecCCManager manager; + + std::cout << "Invoking Release with non-existent iID: " << iID << std::endl; + EXPECT_NO_THROW({ + manager.Release(iID); + }); + std::cout << "Release method completed for non-existent iID: " << iID << std::endl; + std::cout << "No track release is expected as there is no track associated with ID " << iID << "." << std::endl; + + std::cout << "Exiting ReleaseWithNonExistentID test" << std::endl; +} +/** + * @brief Verify that the Release method handles negative ID inputs gracefully. + * + * This test verifies that invoking the Release method with a negative ID does not throw an exception. It ensures that the PlayerSubtecCCManager properly handles an invalid negative identifier without performing any release actions. + * + * **Test Group ID:** Basic: 01@n + * **Test Case ID:** 006@n + * **Priority:** High@n + * + * **Pre-Conditions:** None@n + * **Dependencies:** None@n + * **User Interaction:** None@n + * + * **Test Procedure:** + * | Variation / Step | Description | Test Data | Expected Result | Notes | + * | :--------------: | -------------------------------------------------------------------------------- | --------------------------------------- | ------------------------------------------------------------------------------------------ | ----------- | + * | 01 | Initialize negative ID and create a PlayerSubtecCCManager instance. | iID = -1, manager = default constructed | Instance is created successfully and iID is set to -1. | Should be successful | + * | 02 | Invoke the Release method with the negative ID to check error-free handling. | iID = -1 | No exception is thrown; the method handles the negative ID gracefully without releasing any track. | Should Pass | + */ +TEST(PlayerSubtecCCManager, ReleaseWithNegativeID) { + std::cout << "Entering ReleaseWithNegativeID test" << std::endl; + + int iID = -1; + std::cout << "Creating PlayerSubtecCCManager object using default constructor." << std::endl; + PlayerSubtecCCManager manager; + + std::cout << "Invoking Release with negative iID: " << iID << std::endl; + EXPECT_NO_THROW({ + manager.Release(iID); + }); + std::cout << "Release method completed for negative iID: " << iID << std::endl; + std::cout << "Method is expected to handle negative ID gracefully without releasing any track." << std::endl; + + std::cout << "Exiting ReleaseWithNegativeID test" << std::endl; +} +/** + * @brief Verify that invoking Release with an ID of zero completes gracefully without throwing exceptions. + * + * This test validates that when the Release method of PlayerSubtecCCManager is called with an identifier value of 0, + * the method does not throw any exceptions. It ensures that if a track with ID 0 exists, it is released, otherwise, + * the method exits gracefully, thereby confirming robust handling of boundary input. + * + * **Test Group ID:** Basic: 01@n + * **Test Case ID:** 007@n + * **Priority:** High@n + * + * **Pre-Conditions:** None@n + * **Dependencies:** None@n + * **User Interaction:** None@n + * + * **Test Procedure:**@n + * | Variation / Step | Description | Test Data | Expected Result | Notes | + * | :--------------: | ------------------------------------------------------------------------- | ---------------------------------- | --------------------------------------------------------------------------------------------- | ------------- | + * | 01 | Creating PlayerSubtecCCManager object using default constructor. | No input; output: manager object | Object is successfully instantiated. | Should be successful | + * | 02 | Invoking Release method with iID zero. | iID = 0 | Release method is called without throwing an exception. | Should Pass | + * | 03 | Confirming that Release method execution completes gracefully. | iID = 0, no additional outputs | If a track with ID 0 exists, it is released; otherwise, the method exits gracefully without error.| Should be successful | + */ +TEST(PlayerSubtecCCManager, ReleaseWithIDZero) { + std::cout << "Entering ReleaseWithIDZero test" << std::endl; + + int iID = 0; + std::cout << "Creating PlayerSubtecCCManager object using default constructor." << std::endl; + PlayerSubtecCCManager manager; + + std::cout << "Invoking Release with iID zero: " << iID << std::endl; + EXPECT_NO_THROW({ + manager.Release(iID); + }); + std::cout << "Release method completed for iID: " << iID << std::endl; + std::cout << "If a track with ID 0 exists, it is expected to be released; otherwise, the method exits gracefully." << std::endl; + + std::cout << "Exiting ReleaseWithIDZero test" << std::endl; +} +/** + * @brief Test the repeated release of the same ID to validate method idempotency + * + * This test validates that calling the Release method twice on the same object identifier does not throw an exception and behaves gracefully. The test ensures that even if the same ID is released repeatedly, the first call releases the associated track successfully and the second call recognizes the absence of an associated track without error. + * + * **Test Group ID:** Basic: 01@n + * **Test Case ID:** 008@n + * **Priority:** High@n + * + * **Pre-Conditions:** None@n + * **Dependencies:** None@n + * **User Interaction:** None@n + * + * **Test Procedure:**@n + * | Variation / Step | Description | Test Data | Expected Result | Notes | + * | :--------------: | -------------------------------------------------------------------------------------------------------- | ---------------------------------------- | ------------------------------------------------------------------------------------------------- | ------------- | + * | 01 | Create a PlayerSubtecCCManager object with default constructor and set iID to 1 | iID = 1 | Manager instance is created successfully | Should be successful | + * | 02 | Invoke the first Release with iID = 1 to release the associated track | iID = 1 | Release method should complete without throwing an exception | Should Pass | + * | 03 | Invoke the second Release with the same iID = 1 to ensure graceful handling when no track is associated | iID = 1 | Release method should complete gracefully without exception despite the track already being released | Should Pass | + */ +TEST(PlayerSubtecCCManager, RepeatedReleaseOfSameID) { + std::cout << "Entering RepeatedReleaseOfSameID test" << std::endl; + + int iID = 1; + std::cout << "Creating PlayerSubtecCCManager object using default constructor." << std::endl; + PlayerSubtecCCManager manager; + + // First release + std::cout << "Invoking first Release with iID: " << iID << std::endl; + EXPECT_NO_THROW({ + manager.Release(iID); + }); + std::cout << "First Release call completed for iID: " << iID << std::endl; + std::cout << "Track associated with ID " << iID << " is expected to be released successfully in the first call." << std::endl; + + // Second release + std::cout << "Invoking second Release with the same iID: " << iID << std::endl; + EXPECT_NO_THROW({ + manager.Release(iID); + }); + std::cout << "Second Release call completed for iID: " << iID << std::endl; + std::cout << "No associated track is expected in the second call, method should complete gracefully." << std::endl; + + std::cout << "Exiting RepeatedReleaseOfSameID test" << std::endl; +} +/** + * @brief Verify that the Release method handles the maximum integer value without exceptions + * + * This test confirms that invoking the Release method with a boundary value (INT_MAX) for the track ID completes gracefully. The test ensures that even if the associated track does not exist, the method does not throw any exceptions and processes the request appropriately. + * + * **Test Group ID:** Basic: 01@n + * **Test Case ID:** 009@n + * **Priority:** High@n + * + * **Pre-Conditions:** None@n + * **Dependencies:** None@n + * **User Interaction:** None@n + * + * **Test Procedure:** + * | Variation / Step | Description | Test Data | Expected Result | Notes | + * | :----: | --------- | ---------- |-------------- | ----- | + * | 01 | Create PlayerSubtecCCManager object using default constructor | No input; output: instance creation | Object is successfully created without errors | Should be successful | + * | 02 | Invoke Release method with iID set to INT_MAX | iID = INT_MAX | Release method completes without throwing any exceptions | Should Pass | + * | 03 | Verify the execution via console log outputs | Log messages printed during test execution | Expected log outputs reflect the proper flow of method execution | Should be successful | + */ +TEST(PlayerSubtecCCManager, ReleaseWithMaxIntegerValue) { + std::cout << "Entering ReleaseWithMaxIntegerValue test" << std::endl; + + int iID = INT_MAX; + std::cout << "Creating PlayerSubtecCCManager object using default constructor." << std::endl; + PlayerSubtecCCManager manager; + + std::cout << "Invoking Release with iID (INT_MAX): " << iID << std::endl; + EXPECT_NO_THROW({ + manager.Release(iID); + }); + std::cout << "Release method completed for iID: " << iID << std::endl; + std::cout << "If a track with ID INT_MAX exists, it is expected to be released; otherwise, the method completes gracefully." << std::endl; + + std::cout << "Exiting ReleaseWithMaxIntegerValue test" << std::endl; +} +/** + * @brief Ensure proper automatic destruction of a local PlayerSubtecCCManager instance + * + * This test verifies that a PlayerSubtecCCManager object created on the stack is properly constructed and subsequently destroyed when it goes out of scope. The test ensures that internal states are initialized via the default constructor and that resource cleanup occurs without explicit destructor calls. + * + * **Test Group ID:** Basic: 01@n + * **Test Case ID:** 010@n + * **Priority:** High@n + * + * **Pre-Conditions:** None@n + * **Dependencies:** None@n + * **User Interaction:** None@n + * + * **Test Procedure:** + * | Variation / Step | Description | Test Data | Expected Result | Notes | + * | :----: | ----------------------------------------------------------------------------------------------- | --------------------------------------------------------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------ | ----------- | + * | 01 | Invoke the default constructor of PlayerSubtecCCManager and verify creation via debug logs. | input: none, output_log1 = "PlayerSubtecCCManager object created successfully", output_log2 = "internal state is initialized" | PlayerSubtecCCManager object is created and its initial state is properly set, then destructed automatically when going out of scope | Should Pass | + */ +TEST(PlayerSubtecCCManager, LocalInstanceDestruction) { + std::cout << "Entering LocalInstanceDestruction test" << std::endl; + + { + std::cout << "Invoking PlayerSubtecCCManager default constructor" << std::endl; + PlayerSubtecCCManager obj; + std::cout << "PlayerSubtecCCManager object created successfully" << std::endl; + + // Since no methods are called on the object, we print debug logs for the object's initial state. + std::cout << "Debug: PlayerSubtecCCManager internal state is initialized via default constructor" << std::endl; + + std::cout << "Exiting inner scope; destructor will be invoked automatically" << std::endl; + } + + std::cout << "Exiting LocalInstanceDestruction test" << std::endl; +} +/** + * @brief Verifies that the GetStatus method returns a valid boolean status. + * + * This test verifies that invoking the GetStatus method of PlayerSubtecCCManager returns a boolean value (true or false) as expected. + * + * **Test Group ID:** Basic: 01@n + * **Test Case ID:** 011@n + * **Priority:** High@n + * + * **Pre-Conditions:** None@n + * **Dependencies:** None@n + * **User Interaction:** None@n + * + * **Test Procedure:**@n + * | Variation / Step | Description | Test Data | Expected Result | Notes | + * | :--------------: | -------------------------------------------------------------------------- | ------------------------------------------------------------------ | ------------------------------------------------------------- | ----------: | + * | 01 | Create a PlayerSubtecCCManager object, invoke GetStatus, and validate output | object: PlayerSubtecCCManager (mEnabled = true), method: GetStatus() | Boolean value (true/false) is returned and assertion passes | Should Pass | + */ +TEST(PlayerSubtecCCManager, VerifyGetStatusReturnsTrue) { + std::cout << "Entering VerifyGetStatusReturnsTrue test" << std::endl; + + // Create an object using the derived class PlayerSubtecCCManager + PlayerSubtecCCManager player(); + std::cout << "Created PlayerSubtecCCManager object with mEnabled set to true" << std::endl; + + // Invoking GetStatus() method. + std::cout << "Invoking GetStatus on PlayerSubtecCCManager object" << std::endl; + bool status = player.GetStatus(); + std::cout << "GetStatus() returned: " << (status ? "true" : "false") << std::endl; + + // Check the returned status is true. + EXPECT_TRUE(status == true || status == false); + + std::cout << "Exiting VerifyGetStatusReturnsTrue test" << std::endl; +} +/** + * @brief Verify that the default style of PlayerSubtecCCManager is empty. + * + * This test verifies that when a PlayerSubtecCCManager object is created using the default constructor, the method GetStyle() returns an empty string as the default style. + * + * **Test Group ID:** Basic: 01@n + * **Test Case ID:** 012@n + * **Priority:** High@n + * + * **Pre-Conditions:** None@n + * **Dependencies:** None@n + * **User Interaction:** None@n + * + * **Test Procedure:**@n + * | Variation / Step | Description | Test Data | Expected Result | Notes | + * | :----: | --------- | ---------- |-------------- | ----- | + * | 01 | Create PlayerSubtecCCManager object using default constructor | constructor = default | Object is successfully constructed | Should be successful | + * | 02 | Invoke GetStyle() method on the object to retrieve the default style | no input, output style = empty string | Returns an empty string | Should Pass | + * | 03 | Validate that the returned style is empty using ASSERT_EQ | expected = empty string, actual = style | Assertion passes confirming default style is empty | Should be successful | + */ +TEST(PlayerSubtecCCManager, VerifyDefaultStyleIsEmpty) +{ + std::cout << "Entering VerifyDefaultStyleIsEmpty test" << std::endl; + + // Create derived class object (assuming default constructor is available) + PlayerSubtecCCManager obj; + std::cout << "Constructed PlayerSubtecCCManager object." << std::endl; + + // Invoke the method GetStyle and log the invocation. + std::cout << "Invoking GetStyle() method." << std::endl; + const std::string &style = obj.GetStyle(); + std::cout << "GetStyle() returned value: \"" << style << "\"" << std::endl; + + // Check that the default style is an empty string. + ASSERT_EQ(style, "") << "Expected default style to be an empty string."; + + std::cout << "Exiting VerifyDefaultStyleIsEmpty test" << std::endl; +} +/** + * @brief Verify that GetTrack() returns a non-empty string. + * + * This test verifies that the GetTrack() method of the PlayerSubtecCCManager class returns a non-empty string. It creates an instance of the class, invokes the GetTrack() method, and asserts that the returned string is not empty. This ensures that the method consistently retrieves valid track data. + * + * **Test Group ID:** Basic: 01 + * **Test Case ID:** 013 + * **Priority:** High + * + * **Pre-Conditions:** None + * **Dependencies:** None + * **User Interaction:** None + * + * **Test Procedure:** + * | Variation / Step | Description | Test Data | Expected Result | Notes | + * | :--------------: | ----------- | --------- | -------------- | ----- | + * | 01 | Log entering test and instantiate PlayerSubtecCCManager object. | Invocation: object = PlayerSubtecCCManager() | PlayerSubtecCCManager object is created successfully. | Should be successful | + * | 02 | Invoke the GetTrack() method on the PlayerSubtecCCManager object. | Invocation: retrievedTrack = player.GetTrack() | The GetTrack() call returns a non-empty string. | Should Pass | + * | 03 | Assert that the returned track is non-empty. | Invocation: ASSERT_FALSE(retrievedTrack.empty()) | The assertion passes when retrievedTrack is not empty. | Should Pass | + * | 04 | Log the completion of the test. | Invocation: logging the exit message | The test exit message is logged. | Should be successful | + */ +TEST(PlayerSubtecCCManager, GetTrackReturnsNonEmpty) { + std::cout << "Entering GetTrackReturnsNonEmpty test" << std::endl; + + // Create an object of the derived class + PlayerSubtecCCManager player(); + + std::cout << "Invoking GetTrack() method on PlayerSubtecCCManager object." << std::endl; + const std::string &retrievedTrack = player.GetTrack(); + std::cout << "Retrieved track value: " << retrievedTrack << std::endl; + + // Check that the returned track string is non empty. + ASSERT_FALSE(retrievedTrack.empty()); + + std::cout << "Exiting GetTrackReturnsNonEmpty test" << std::endl; +} +/** + * @brief Test to verify that GetTrack() method returns a consistent track value + * + * This test ensures that multiple invocations of the GetTrack() method on the PlayerSubtecCCManager instance return the same track value. This consistency is crucial for the reliability of dependent functionality. + * + * **Test Group ID:** Basic: 01 + * **Test Case ID:** 014 + * **Priority:** High + * + * **Pre-Conditions:** None + * **Dependencies:** None + * **User Interaction:** None + * + * **Test Procedure:** + * | Variation / Step | Description | Test Data | Expected Result |Notes | + * | :---------------: | ----------------------------------------------------------------- | ------------------------------------------------------------------------------------------ | ------------------------------------------------ | ---------------- | + * | 01 | Create an instance of PlayerSubtecCCManager | N/A | Instance created successfully | Should be successful | + * | 02 | Invoke GetTrack() method for the first time | output1 (firstCallResult) = value returned by GetTrack() | Returns a valid track string | Should Pass | + * | 03 | Invoke GetTrack() method for the second time | output1 (secondCallResult) = value returned by GetTrack() | Returns a valid track string | Should Pass | + * | 04 | Validate that both GetTrack() calls return identical values | firstCallResult = value, secondCallResult = value | Both track values are equal | Should be successful | + */ +TEST(PlayerSubtecCCManager, GetTrackReturnsConsistently) { + std::cout << "Entering GetTrackReturnsConsistently test" << std::endl; + + // Create an object of the derived class + PlayerSubtecCCManager player(); + + std::cout << "Invoking GetTrack() method for the first time." << std::endl; + const std::string &firstCallResult = player.GetTrack(); + std::cout << "First call returned track value: " << firstCallResult << std::endl; + + std::cout << "Invoking GetTrack() method for the second time." << std::endl; + const std::string &secondCallResult = player.GetTrack(); + std::cout << "Second call returned track value: " << secondCallResult << std::endl; + + // Validate that both calls returned the same track value. + ASSERT_EQ(firstCallResult, secondCallResult); + + std::cout << "Exiting GetTrackReturnsConsistently test" << std::endl; +} +/** + * @brief Validate that the PlayerSubtecCCManager::Init function correctly initializes with a valid decoder handle. + * + * This test verifies that when a valid decoder handle is provided, the PlayerSubtecCCManager::Init function returns 0 as expected. It is crucial to ensure the initialization routine handles valid inputs appropriately, thereby establishing baseline functionality. + * + * **Test Group ID:** Basic: 01@n + * **Test Case ID:** 015@n + * **Priority:** High@n + * + * **Pre-Conditions:** None@n + * **Dependencies:** None@n + * **User Interaction:** None@n + * + * **Test Procedure:**@n + * | Variation / Step | Description | Test Data | Expected Result | Notes | + * | :----: | --------- | ---------- |-------------- | ----- | + * | 01 | Create a dummy decoder and generate a valid decoder handle | dummyDecoder = 42, validHandle = address of dummyDecoder | Valid decoder handle is created | Should be successful | + * | 02 | Instantiate a PlayerSubtecCCManager object and invoke Init with the valid decoder handle | input: validHandle = address of dummyDecoder, output: retVal from Init | Init returns a value indicating success (0) | Should Pass | + * | 03 | Verify that the Init function returns the expected value of 0 | retVal = [result from Init call] | ASSERT_EQ confirms retVal equals 0 | Should be successful | + */ +TEST(PlayerSubtecCCManager, ValidDecoderHandleInit) { + std::cout << "Entering ValidDecoderHandleInit test" << std::endl; + + // Create a dummy decoder handle as a valid pointer + int dummyDecoder = 42; + void* validHandle = static_cast(&dummyDecoder); + std::cout << "Created dummy decoder with value: " << dummyDecoder << " at address: " << validHandle << std::endl; + + // Create object of derived class using default constructor + PlayerSubtecCCManager playerCCManager; + std::cout << "Invoking PlayerCCManagerBase::Init with valid handle: " << validHandle << std::endl; + + int retVal = playerCCManager.Init(validHandle); + std::cout << "PlayerCCManagerBase::Init returned: " << retVal << std::endl; + + // Check the expected return value for a valid handle + ASSERT_EQ(retVal, 0); + + std::cout << "Exiting ValidDecoderHandleInit test" << std::endl; +} +/** + * @brief Test the behavior of PlayerSubtecCCManager::Init when provided with a NULL decoder handle. + * + * This test verifies that calling PlayerSubtecCCManager::Init with a NULL decoder handle properly fails by returning an error value (-1). It ensures that the API robustly handles invalid input and does not proceed with initialization using a null handle. + * + * **Test Group ID:** Basic: 01@n + * **Test Case ID:** 016@n + * **Priority:** High@n + * + * **Pre-Conditions:** None@n + * **Dependencies:** None@n + * **User Interaction:** None@n + * + * **Test Procedure:**@n + * | Variation / Step | Description | Test Data | Expected Result | Notes | + * | :--------------: | --------------------------------------------------------------------------- | --------------------------------------------------------------- | ------------------------------------------------------------- | --------------- | + * | 01 | Create a NULL decoder handle. | nullHandle = nullptr | NULL handle successfully created. | Should be successful | + * | 02 | Instantiate PlayerSubtecCCManager object using default constructor. | No input parameters | Object created successfully. | Should be successful | + * | 03 | Invoke PlayerSubtecCCManager::Init with the NULL decoder handle. | input: nullHandle = nullptr, output: retVal = value returned by Init | API returns -1 indicating failure for null handle. | Should Fail | + * | 04 | Validate the return value of Init using ASSERT_EQ. | output: retVal, expected value = -1 | Assertion passes confirming correct error handling. | Should be successful | + */ +TEST(PlayerSubtecCCManager, NullDecoderHandleInit) { + std::cout << "Entering NullDecoderHandleInit test" << std::endl; + + // Create a NULL decoder handle + void* nullHandle = nullptr; + std::cout << "Created NULL decoder handle: " << nullHandle << std::endl; + + // Create object of derived class using default constructor + PlayerSubtecCCManager playerCCManager; + std::cout << "Invoking PlayerCCManagerBase::Init with NULL handle: " << nullHandle << std::endl; + + int retVal = playerCCManager.Init(nullHandle); + std::cout << "PlayerCCManagerBase::Init returned: " << retVal << std::endl; + + // Check the expected return value for a NULL handle indicating failure + ASSERT_EQ(retVal, -1); + + std::cout << "Exiting NullDecoderHandleInit test" << std::endl; +} +/** + * @brief Test the functionality of PlayerSubtecCCManager::IsOOBCCRenderingSupported method. + * + * This test verifies that the IsOOBCCRenderingSupported method of the PlayerSubtecCCManager instance returns a boolean value. + * It creates a PlayerSubtecCCManager object using the default constructor, invokes the method, logs the outputs, and asserts + * that the return value satisfies the expected boolean condition. + * + * **Test Group ID:** Basic: 01@n + * **Test Case ID:** 017@n + * **Priority:** High@n + * + * **Pre-Conditions:** None@n + * **Dependencies:** None@n + * **User Interaction:** None@n + * + * **Test Procedure:**@n + * | Variation / Step | Description | Test Data | Expected Result | Notes | + * | :----: | --------- | ---------- |-------------- | ----- | + * | 01 | Log the entry message indicating the start of the test | none | "Entering PlayerSubtecCCManager::IsOOBCCRenderingSupported()_start test" printed on console | Should be successful | + * | 02 | Create a PlayerSubtecCCManager object using the default constructor | none | Object is successfully created | Should be successful | + * | 03 | Invoke the IsOOBCCRenderingSupported method and print debug logs | No parameters, output: result = boolean value | Method returns either true or false and the returned value is printed | Should Pass | + * | 04 | Verify the returned value using EXPECT_TRUE assertion | result from IsOOBCCRenderingSupported = boolean value | EXPECT_TRUE check passes if result is either true or false | Should Pass | + * | 05 | Log the exit message indicating the end of the test | none | "Exiting PlayerCCManagerBase::IsOOBCCRenderingSupported()_start test" printed on console | Should be successful | + */ +TEST(PlayerSubtecCCManager, PlayerCCManagerBase_IsOOBCCRenderingSupported_start) { + std::cout << "Entering PlayerSubtecCCManager::IsOOBCCRenderingSupported()_start test" << std::endl; + + // Create an object of the derived class using the default constructor. + PlayerSubtecCCManager player; + std::cout << "Created PlayerSubtecCCManager object using default constructor" << std::endl; + + // Invoke the method and print debug logs. + std::cout << "Invoking IsOOBCCRenderingSupported method" << std::endl; + bool result = player.IsOOBCCRenderingSupported(); + std::cout << "IsOOBCCRenderingSupported returned value: " << (result ? "true" : "false") << std::endl; + + // Verify the return value meets the expected output. + EXPECT_TRUE(result == true || result == false); + + std::cout << "Exiting PlayerCCManagerBase::IsOOBCCRenderingSupported()_start test" << std::endl; +} +/** + * @brief Validate the RestoreCC functionality for an empty mLastTextTracks scenario + * + * This test verifies that the RestoreCC method of PlayerSubtecCCManager executes successfully when mLastTextTracks is empty. It ensures that invoking RestoreCC does not throw an exception in this case. + * + * **Test Group ID:** Basic: 01@n + * **Test Case ID:** 018@n + * **Priority:** High@n + * + * **Pre-Conditions:** None@n + * **Dependencies:** None@n + * **User Interaction:** None@n + * + * **Test Procedure:** + * | Variation / Step | Description | Test Data | Expected Result | Notes | + * | :--------------: | ---------------------------------------------------------------------------------------- | ---------------------------------------------- | ----------------------------------------------------------------- | ------------- | + * | 01 | Create a PlayerSubtecCCManager object using the default constructor | input: none, output: ccManager object | ccManager object created successfully | Should be successful | + * | 02 | Call RestoreCC method on the object when mLastTextTracks is empty | input: mLastTextTracks = empty, output: none | No exception thrown; RestoreCC completes without error | Should Pass | + */ +TEST(PlayerSubtecCCManager, RestoreCC_with_empty_mLastTextTracks) { + std::cout << "Entering RestoreCC_with_empty_mLastTextTracks test" << std::endl; + + std::cout << "Creating PlayerSubtecCCManager object using default constructor" << std::endl; + PlayerSubtecCCManager ccManager; + + std::cout << "Before invoking RestoreCC, calling RestoreCC() on the object" << std::endl; + std::cout << "Invoking RestoreCC method" << std::endl; + // Since mLastTextTracks is initially empty, the restore operation is expected to complete without error. + ASSERT_NO_THROW(ccManager.RestoreCC()); + std::cout << "RestoreCC method invoked successfully. Operation completed without crashing" << std::endl; + + std::cout << "Exiting RestoreCC_with_empty_mLastTextTracks test" << std::endl; +} +/** + * @brief Validate that parental control status is enabled when SetParentalControlStatus is invoked with true. + * + * This test verifies that calling SetParentalControlStatus(true) correctly enables the parental control status in the PlayerSubtecCCManager object. The test ensures that the API call executes without errors and that the object's internal state reflects the change. + * + * **Test Group ID:** Basic: 01@n + * **Test Case ID:** 019@n + * **Priority:** High@n + * + * **Pre-Conditions:** None@n + * **Dependencies:** None@n + * **User Interaction:** None@n + * + * **Test Procedure:**@n + * | Variation / Step | Description | Test Data | Expected Result | Notes | + * | :----: | --------- | ---------- |-------------- | ----- | + * | 01 | Create an instance of PlayerSubtecCCManager using its default constructor. | Constructor call: PlayerSubtecCCManager() | Object is created successfully. | Should be successful | + * | 02 | Invoke SetParentalControlStatus with true to enable parental control. | input locked = true | Parental control status is updated successfully, and the method executes without error. | Should Pass | + */ +TEST(PlayerSubtecCCManager, SetParentalControlStatus_True) { + std::cout << "Entering SetParentalControlStatus_True test" << std::endl; + + // Create object for derived class PlayerSubtecCCManager using its default constructor. + PlayerSubtecCCManager obj; + std::cout << "PlayerSubtecCCManager object created." << std::endl; + + // Invoke SetParentalControlStatus with locked set to true. + std::cout << "Invoking SetParentalControlStatus with value: true" << std::endl; + obj.SetParentalControlStatus(true); + std::cout << "SetParentalControlStatus(true) has been called; parental control status set to enabled." << std::endl; + + std::cout << "Exiting SetParentalControlStatus_True test" << std::endl; +} +/** + * @brief Validate that SetParentalControlStatus disables parental control when passed false. + * + * This test validates that invoking SetParentalControlStatus with a false value correctly disables the parental control status in the PlayerSubtecCCManager. It ensures that the method call updates the object's internal state as expected. + * + * **Test Group ID:** Basic: 01@n + * **Test Case ID:** 020@n + * **Priority:** High@n + * + * **Pre-Conditions:** None@n + * **Dependencies:** None@n + * **User Interaction:** None@n + * + * **Test Procedure:** + * | Variation / Step | Description | Test Data | Expected Result | Notes | + * | :--------------: | ----------------------------------------------------------------------- | --------------------------------------------------- | ---------------------------------------------------------------------- | ------------------ | + * | 01 | Create a PlayerSubtecCCManager instance using the default constructor | No inputs, output_obj = valid instance | Instance of PlayerSubtecCCManager is successfully created | Should be successful | + * | 02 | Invoke SetParentalControlStatus with parameter false to disable parental control | input1 = false, no output argument | The method call completes and parental control is set to disabled | Should Pass | + */ +TEST(PlayerSubtecCCManager, SetParentalControlStatus_False) { + std::cout << "Entering SetParentalControlStatus_False test" << std::endl; + + // Create object for derived class PlayerSubtecCCManager using its default constructor. + PlayerSubtecCCManager obj; + std::cout << "PlayerSubtecCCManager object created." << std::endl; + + // Invoke SetParentalControlStatus with locked set to false. + std::cout << "Invoking SetParentalControlStatus with value: false" << std::endl; + obj.SetParentalControlStatus(false); + std::cout << "SetParentalControlStatus(false) has been called; parental control status set to disabled." << std::endl; + + std::cout << "Exiting SetParentalControlStatus_False test" << std::endl; +} +/** + * @brief Verifies that repeatedly enabling parental control using SetParentalControlStatus(true) consistently maintains the enabled state. + * + * This test validates the idempotency of the SetParentalControlStatus API when repeatedly invoked with the value true. The expected behavior is that the parental control status remains enabled on subsequent calls, confirming that no adverse side effects occur from repeated invocations. + * + * **Test Group ID:** Basic: 01@n + * **Test Case ID:** 021@n + * **Priority:** High@n + * + * **Pre-Conditions:** None@n + * **Dependencies:** None@n + * **User Interaction:** None@n + * + * **Test Procedure:** + * | Variation / Step | Description | Test Data | Expected Result | Notes | + * | :--------------: | --------------------------------------------------------------------------------------------- | ---------------------------------------------- | -------------------------------------------------------------------------------- | ------------ | + * | 01 | Create a PlayerSubtecCCManager object and invoke SetParentalControlStatus with true | input = true | Method executes without error; parental control status enabled | Should Pass | + * | 02 | Repeatedly invoke SetParentalControlStatus with true to verify idempotency of enabling parental control | input = true | Method executes without error; parental control status remains enabled | Should Pass | + */ +TEST(PlayerSubtecCCManager, SetParentalControlStatus_True_Repeated) { + std::cout << "Entering SetParentalControlStatus_True_Repeated test" << std::endl; + + // Create object for derived class PlayerSubtecCCManager using its default constructor. + PlayerSubtecCCManager obj; + std::cout << "PlayerSubtecCCManager object created." << std::endl; + + // First invocation with locked = true. + std::cout << "First invocation: Calling SetParentalControlStatus with value: true" << std::endl; + obj.SetParentalControlStatus(true); + std::cout << "First call completed; expected parental control status: enabled." << std::endl; + + // Second invocation with locked = true. + std::cout << "Second invocation: Calling SetParentalControlStatus with value: true" << std::endl; + obj.SetParentalControlStatus(true); + std::cout << "Second call completed; expected parental control status remains enabled." << std::endl; + + std::cout << "Exiting SetParentalControlStatus_True_Repeated test" << std::endl; +} +/** + * @brief Validate that calling SetParentalControlStatus repeatedly with false disables parental control correctly. + * + * This test case verifies that when the SetParentalControlStatus method is invoked twice with false, the parental control is disabled as expected on the first call and remains disabled on the subsequent call. This ensures that the API behaves idempotently when the same input is provided repeatedly. + * + * **Test Group ID:** Basic: 01@n + * **Test Case ID:** 022@n + * **Priority:** High@n + * + * **Pre-Conditions:** None@n + * **Dependencies:** None@n + * **User Interaction:** None@n + * + * **Test Procedure:** + * | Variation / Step | Description | Test Data | Expected Result | Notes | + * | :--------------: | --------------------------------------------------------------------------- | ------------------------------------------ | ---------------------------------------------------------------------- | -------------- | + * | 01 | Create a PlayerSubtecCCManager object using its default constructor. | None | Object is instantiated successfully. | Should be successful | + * | 02 | Invoke SetParentalControlStatus method with parameter false (first call). | input: locked = false | Parental control status is set to disabled. | Should Pass | + * | 03 | Invoke SetParentalControlStatus method with parameter false (second call). | input: locked = false | Parental control status remains disabled, confirming idempotency. | Should Pass | + */ +TEST(PlayerSubtecCCManager, SetParentalControlStatus_False_Repeated) { + std::cout << "Entering SetParentalControlStatus_False_Repeated test" << std::endl; + + // Create object for derived class PlayerSubtecCCManager using its default constructor. + PlayerSubtecCCManager obj; + std::cout << "PlayerSubtecCCManager object created." << std::endl; + + // First invocation with locked = false. + std::cout << "First invocation: Calling SetParentalControlStatus with value: false" << std::endl; + obj.SetParentalControlStatus(false); + std::cout << "First call completed; expected parental control status: disabled." << std::endl; + + // Second invocation with locked = false. + std::cout << "Second invocation: Calling SetParentalControlStatus with value: false" << std::endl; + obj.SetParentalControlStatus(false); + std::cout << "Second call completed; expected parental control status remains disabled." << std::endl; + + std::cout << "Exiting SetParentalControlStatus_False_Repeated test" << std::endl; +} +/** + * @brief Test enabling of CC rendering by setting status to true + * + * This test case verifies that invoking the SetStatus method of PlayerSubtecCCManager with a true parameter correctly enables the closed-caption rendering and returns 0 indicating success. + * + * **Test Group ID:** Basic: 01@n + * **Test Case ID:** 023@n + * **Priority:** High@n + * + * **Pre-Conditions:** None@n + * **Dependencies:** None@n + * **User Interaction:** None@n + * + * **Test Procedure:**@n + * | Variation / Step | Description | Test Data | Expected Result | Notes | + * | :----: | --------- | ---------- |-------------- | ----- | + * | 01 | Instantiate PlayerSubtecCCManager object using default constructor | No input parameters | Object is created successfully | Should be successful | + * | 02 | Invoke SetStatus with true to enable CC rendering | input = true, output = ret | API returns 0 indicating success and assertion EXPECT_EQ(ret, 0) passes | Should Pass | + */ +TEST(PlayerSubtecCCManager, EnableCCRenderingTrue) { + std::cout << "Entering EnableCCRenderingTrue test" << std::endl; + + // Create an object of the derived class using its default constructor + PlayerSubtecCCManager player; + std::cout << "Created PlayerSubtecCCManager object using default constructor" << std::endl; + + // Invoking SetStatus with true to enable CC rendering + std::cout << "Invoking PlayerCCManagerBase::SetStatus with parameter: true" << std::endl; + int ret = player.SetStatus(true); + std::cout << "Returned value from SetStatus(true): " << ret << std::endl; + + // Here, 0 indicates success as expected. + EXPECT_EQ(ret, 0); + std::cout << "Internal state change logged: CC rendering set to enabled" << std::endl; + + std::cout << "Exiting EnableCCRenderingTrue test" << std::endl; +} +/** + * @brief Validates that disabling closed caption (CC) rendering works as expected. + * + * This test verifies that invoking the SetStatus method with a value of false effectively disables CC rendering. + * It ensures that the API returns a success code (0) when the status is set to false. + * + * **Test Group ID:** Basic: 01@n + * **Test Case ID:** 024@n + * **Priority:** High@n + * + * **Pre-Conditions:** None@n + * **Dependencies:** None@n + * **User Interaction:** None@n + * + * **Test Procedure:** + * | Variation / Step | Description | Test Data | Expected Result | Notes | + * | :----: | ------------------------------------------------------------------ | ---------------------------------------------------------------- | -------------------------------------------------------- | ---------------- | + * | 01 | Create a PlayerSubtecCCManager object using the default constructor | input: none, output: instance of PlayerSubtecCCManager created | Object instantiation is successful | Should be successful | + * | 02 | Invoke SetStatus with parameter false to disable CC rendering | input: false, output: ret = value returned from SetStatus | Return value should equal 0 indicating success | Should Pass | + * | 03 | Validate the API's return value using EXPECT_EQ | input: ret = value from SetStatus, expected ret = 0 | EXPECT_EQ check passes confirming ret equals 0 | Should Pass | + */ +TEST(PlayerSubtecCCManager, DisableCCRenderingFalse) { + std::cout << "Entering DisableCCRenderingFalse test" << std::endl; + + // Create an object of the derived class using its default constructor + PlayerSubtecCCManager player; + std::cout << "Created PlayerSubtecCCManager object using default constructor" << std::endl; + + // Invoking SetStatus with false to disable CC rendering + std::cout << "Invoking PlayerCCManagerBase::SetStatus with parameter: false" << std::endl; + int ret = player.SetStatus(false); + std::cout << "Returned value from SetStatus(false): " << ret << std::endl; + + // Here, 0 indicates success as expected. + EXPECT_EQ(ret, 0); + std::cout << "Internal state change logged: CC rendering set to disabled" << std::endl; + + std::cout << "Exiting DisableCCRenderingFalse test" << std::endl; +} +/** + * @brief Validate that the PlayerSubtecCCManager properly handles the default style option. + * + * This test verifies that when the default style option ("default") is provided to the SetStyle API, the method returns a success status (0). It ensures that the default style setting functionality in the PlayerSubtecCCManager class works as expected. + * + * **Test Group ID:** Basic: 01@n + * **Test Case ID:** 025@n + * **Priority:** High@n + * + * **Pre-Conditions:** None@n + * **Dependencies:** None@n + * **User Interaction:** None@n + * + * **Test Procedure:**@n + * | Variation / Step | Description | Test Data | Expected Result | Notes | + * | :--------------: | ----------------------------------------------------------------------- | ----------------------------------------- | -------------------------------------------------------------- | -------------- | + * | 01 | Instantiate PlayerSubtecCCManager using its default constructor. | N/A | Object is created successfully. | Should be successful | + * | 02 | Initialize style option string to "default". | options = default | Options variable is set to "default". | Should be successful | + * | 03 | Invoke SetStyle API with the option string "default". | input: options = default | API returns 0 indicating successful operation. | Should Pass | + * | 04 | Verify the return value is 0 to confirm success of the operation. | result = return from SetStyle | EXPECT_EQ(result, 0) assertion passes. | Should Pass | + */ +TEST(PlayerSubtecCCManager, ValidStyleOptionDefault) +{ + std::cout << "Entering ValidStyleOptionDefault test" << std::endl; + + // Create an instance of the derived class using the default constructor. + PlayerSubtecCCManager manager; + + // Define the option string to be passed. + std::string options = "default"; + std::cout << "Invoking SetStyle with options: " << options << std::endl; + + // Call the method SetStyle. + int result = manager.SetStyle(options); + std::cout << "Method SetStyle returned: " << result << std::endl; + + // Check the expected status, 0 indicates success. + EXPECT_EQ(result, 0); + + std::cout << "Exiting ValidStyleOptionDefault test" << std::endl; +} +/** + * @brief Tests that the PlayerSubtecCCManager processes a valid complex style option string successfully + * + * This test verifies that the PlayerSubtecCCManager correctly processes a complex style options string containing multiple style attributes and returns a success code (0). The test ensures that the SetStyle API works as expected with valid, well-formed input. + * + * **Test Group ID:** Basic: 01 + * **Test Case ID:** 026 + * **Priority:** High + * + * **Pre-Conditions:** None + * **Dependencies:** None + * **User Interaction:** None + * + * **Test Procedure:** + * | Variation / Step | Description | Test Data | Expected Result | Notes | + * | :----: | --------- | ---------- |-------------- | ----- | + * | 01 | Create an instance of PlayerSubtecCCManager and define a valid complex style options string | manager instance created, options = "font-size: 16px; font-family: Arial; color: red;" | Instance created successfully and options string defined | Should be successful | + * | 02 | Invoke the SetStyle method with the defined options and validate the returned result | input: options = "font-size: 16px; font-family: Arial; color: red;", output: result expected = 0 | API returns 0 indicating successful processing; EXPECT_EQ assertion passes | Should Pass | + */ +TEST(PlayerSubtecCCManager, ValidStyleOptionComplex) +{ + std::cout << "Entering ValidStyleOptionComplex test" << std::endl; + + // Create an instance of the derived class. + PlayerSubtecCCManager manager; + + // Define a complex style options string. + std::string options = "font-size: 16px; font-family: Arial; color: red;"; + std::cout << "Invoking SetStyle with options: " << options << std::endl; + + // Call the SetStyle method. + int result = manager.SetStyle(options); + std::cout << "Method SetStyle returned: " << result << std::endl; + + // Validate that the method returns success (0). + EXPECT_EQ(result, 0); + + std::cout << "Exiting ValidStyleOptionComplex test" << std::endl; +} +/** + * @brief Test to verify that the SetStyle API fails when provided with an empty style options string. + * + * This test case is designed to ensure that the SetStyle method of the PlayerSubtecCCManager class correctly handles an empty string input by returning a failure status (-1). The test verifies proper error handling in boundary conditions. + * + * **Test Group ID:** Basic: 01 + * **Test Case ID:** 027 + * **Priority:** High + * + * **Pre-Conditions:** None + * **Dependencies:** None + * **User Interaction:** None + * + * **Test Procedure:** + * | Variation / Step | Description | Test Data | Expected Result | Notes | + * | :----: | --------- | ---------- |-------------- | ----- | + * | 01 | Log entering test and create instance of PlayerSubtecCCManager | No input; output: instance created | Manager instance is successfully created and log entry message printed | Should be successful | + * | 02 | Define empty style options string | options = "" | options variable is an empty string | Should be successful | + * | 03 | Invoke SetStyle API with empty style options string | input: options = "", instance: manager; output: result value from API | API returns -1 indicating failure for empty style options | Should Fail | + * | 04 | Validate that SetStyle returns -1 using an assertion | result = -1; expected value = -1 | Assertion passes confirming failure status (-1) | Should be successful | + */ +TEST(PlayerSubtecCCManager, EmptyStyleOptions) +{ + std::cout << "Entering EmptyStyleOptions test" << std::endl; + + // Create an instance of the derived class. + PlayerSubtecCCManager manager; + + // Define an empty style options string. + std::string options = ""; + std::cout << "Invoking SetStyle with options: '" << options << "'" << std::endl; + + // Call the SetStyle method. + int result = manager.SetStyle(options); + std::cout << "Method SetStyle returned: " << result << std::endl; + + // Validate that an empty input results in a failure status (-1). + EXPECT_EQ(result, -1); + + std::cout << "Exiting EmptyStyleOptions test" << std::endl; +} +/** + * @brief Verify that SetStyle API returns failure when a whitespace-only style options string is provided. + * + * This test ensures that the SetStyle method in the PlayerSubtecCCManager class correctly identifies a style options string + * that contains only whitespace and returns a failure code (-1) accordingly. Detecting such invalid inputs is critical + * for ensuring the robustness and proper error handling of the API. + * + * **Test Group ID:** Basic: 01@n + * **Test Case ID:** 028@n + * **Priority:** High@n + * + * **Pre-Conditions:** None@n + * **Dependencies:** None@n + * **User Interaction:** None@n + * + * **Test Procedure:** + * | Variation / Step | Description | Test Data | Expected Result | Notes | + * | :--------------: | --------------------------------------------------------------------------- | -------------------------------------------------------------- | ------------------------------------------------------- | ---------------- | + * | 01 | Create an instance of PlayerSubtecCCManager. | No input, output: instance created | Instance is successfully created. | Should be successful | + * | 02 | Define a whitespace-only style options string. | options = " " | Options string is assigned with whitespace only. | Should be successful | + * | 03 | Invoke the SetStyle API with the whitespace-only options string. | input: options = " ", output: result variable | SetStyle returns -1, indicating failure. | Should Fail | + * | 04 | Validate the returned result from SetStyle using EXPECT_EQ. | result = -1 | EXPECT_EQ assertion passes as result equals -1. | Should be successful | + */ +TEST(PlayerSubtecCCManager, WhitespaceOnlyStyleOptions) +{ + std::cout << "Entering WhitespaceOnlyStyleOptions test" << std::endl; + + // Create an instance of the derived class. + PlayerSubtecCCManager manager; + + // Define a whitespace-only style options string. + std::string options = " "; + std::cout << "Invoking SetStyle with options: '" << options << "'" << std::endl; + + // Call the SetStyle method. + int result = manager.SetStyle(options); + std::cout << "Method SetStyle returned: " << result << std::endl; + + // Validate that a whitespace-only input returns failure (-1). + EXPECT_EQ(result, -1); + + std::cout << "Exiting WhitespaceOnlyStyleOptions test" << std::endl; +} +/** + * @brief Validate that invalid style options result in a failure. + * + * This test case verifies that when an invalid style option string is provided to the SetStyle method of the PlayerSubtecCCManager, the method returns a failure status (-1). + * + * **Test Group ID:** Basic: 01@n + * **Test Case ID:** 029@n + * **Priority:** High@n + * + * **Pre-Conditions:** None@n + * **Dependencies:** None@n + * **User Interaction:** None@n + * + * **Test Procedure:** + * | Variation / Step | Description | Test Data | Expected Result | Notes | + * | :--------------: | --------------------------------------------------------- | -------------------------------------- | --------------------------------------------------------- | ----------- | + * | 01 | Invoke SetStyle with an invalid style option and verify the return value. | options = invalid_style_option | Returns -1 and EXPECT_EQ assertion passes (invalid option detected). | Should Fail | + */ +TEST(PlayerSubtecCCManager, InvalidStyleOptions) +{ + std::cout << "Entering InvalidStyleOptions test" << std::endl; + + // Create an instance of the derived class. + PlayerSubtecCCManager manager; + + // Define an invalid style options string. + std::string options = "invalid_style_option"; + std::cout << "Invoking SetStyle with options: " << options << std::endl; + + // Call the SetStyle method. + int result = manager.SetStyle(options); + std::cout << "Method SetStyle returned: " << result << std::endl; + + // Validate that an invalid option returns a failure status (-1). + EXPECT_EQ(result, -1); + + std::cout << "Exiting InvalidStyleOptions test" << std::endl; +} +/** + * @brief Test that SetTrack successfully sets a valid non-empty track string + * + * This test ensures that the PlayerSubtecCCManager::SetTrack API successfully sets a non-empty valid track string when provided with various valid CCFormat types. The function is expected to return 0 for each valid input, confirming that the track is set correctly. + * + * **Test Group ID:** Basic: 01@n + * **Test Case ID:** 030@n + * **Priority:** High@n + * + * **Pre-Conditions:** None@n + * **Dependencies:** None@n + * **User Interaction:** None@n + * + * **Test Procedure:**@n + * | Variation / Step | Description | Test Data | Expected Result | Notes | + * | :----: | --------- | ---------- |-------------- | ----- | + * | 01 | Invoke PlayerSubtecCCManager::SetTrack with track "ValidTrack" and CCFormat eCLOSEDCAPTION_FORMAT_608 | track = ValidTrack, CCFormat = eCLOSEDCAPTION_FORMAT_608, ExpectedReturn = 0 | API returns 0 indicating success and assertion passes | Should Pass | + * | 02 | Invoke PlayerSubtecCCManager::SetTrack with track "ValidTrack" and CCFormat eCLOSEDCAPTION_FORMAT_708 | track = ValidTrack, CCFormat = eCLOSEDCAPTION_FORMAT_708, ExpectedReturn = 0 | API returns 0 indicating success and assertion passes | Should Pass | + * | 03 | Invoke PlayerSubtecCCManager::SetTrack with track "ValidTrack" and CCFormat eCLOSEDCAPTION_FORMAT_DEFAULT | track = ValidTrack, CCFormat = eCLOSEDCAPTION_FORMAT_DEFAULT, ExpectedReturn = 0 | API returns 0 indicating success and assertion passes | Should Pass | + */ +TEST(PlayerSubtecCCManager, ValidNonEmptyTrack) { + std::cout << "Entering ValidNonEmptyTrack test" << std::endl; + + // Array of valid CCFormat types to test + CCFormat formats[] = { eCLOSEDCAPTION_FORMAT_608, eCLOSEDCAPTION_FORMAT_708, eCLOSEDCAPTION_FORMAT_DEFAULT }; + + // Use a fixed size array for the track value and assign using strncpy + char trackArr[50] = {0}; + const char* inputTrack = "ValidTrack"; + std::strncpy(trackArr, inputTrack, sizeof(trackArr)-1); + std::string track(trackArr); + std::cout << "Prepared track string: " << track << std::endl; + + for (CCFormat format : formats) { + // Create object of derived class using default constructor + PlayerSubtecCCManager manager; + std::cout << "Invoking SetTrack with track: \"" << track << "\" and format: " << format << std::endl; + + int ret = manager.SetTrack(track, format); + std::cout << "SetTrack returned: " << ret << std::endl; + + // Expect success (0) for valid non-empty track string for each valid CCFormat type. + EXPECT_EQ(0, ret); + } + + std::cout << "Exiting ValidNonEmptyTrack test" << std::endl; +} +/** + * @brief Verify that PlayerSubtecCCManager::SetTrack returns an error for an empty track input. + * + * This test creates an empty track string and tests it against all valid CCFormat types to ensure that the SetTrack function fails (returns -1) when provided with an empty track string. This behavior is critical to prevent the manager from processing invalid track data. + * + * **Test Group ID:** Basic: 01@n + * **Test Case ID:** 031@n + * **Priority:** High@n + * + * **Pre-Conditions:** None@n + * **Dependencies:** None@n + * **User Interaction:** None@n + * + * **Test Procedure:**@n + * | Variation / Step | Description | Test Data | Expected Result | Notes | + * | :--------------: | ----------------------------------------------------------------------- | ----------------------------------------------------------------- | ----------------------------------------- | ---------- | + * | 01 | Invoke SetTrack with an empty track and CCFormat eCLOSEDCAPTION_FORMAT_608 | track = "", format = eCLOSEDCAPTION_FORMAT_608 | return value is -1 and assertion passes | Should Fail| + * | 02 | Invoke SetTrack with an empty track and CCFormat eCLOSEDCAPTION_FORMAT_708 | track = "", format = eCLOSEDCAPTION_FORMAT_708 | return value is -1 and assertion passes | Should Fail| + * | 03 | Invoke SetTrack with an empty track and CCFormat eCLOSEDCAPTION_FORMAT_DEFAULT| track = "", format = eCLOSEDCAPTION_FORMAT_DEFAULT | return value is -1 and assertion passes | Should Fail| + */ +TEST(PlayerSubtecCCManager, EmptyTrack) { + std::cout << "Entering EmptyTrack test" << std::endl; + + // Array of valid CCFormat types to test + CCFormat formats[] = { eCLOSEDCAPTION_FORMAT_608, eCLOSEDCAPTION_FORMAT_708, eCLOSEDCAPTION_FORMAT_DEFAULT }; + + // Use a fixed size array for the track value for an empty string + char trackArr[50] = {0}; + const char* inputTrack = ""; + std::strncpy(trackArr, inputTrack, sizeof(trackArr)-1); + std::string track(trackArr); + std::cout << "Prepared track string (empty): \"" << track << "\"" << std::endl; + + for (CCFormat format : formats) { + // Create object of derived class using default constructor + PlayerSubtecCCManager manager; + std::cout << "Invoking SetTrack with an empty track and format: " << format << std::endl; + + int ret = manager.SetTrack(track, format); + std::cout << "SetTrack returned: " << ret << std::endl; + + // Expect failure (-1) for empty track string for each valid CCFormat type. + EXPECT_EQ(-1, ret); + } + + std::cout << "Exiting EmptyTrack test" << std::endl; +} +/** + * @brief Verify that SetTrack fails when provided a whitespace-only track string. + * + * This test validates the behavior of the SetTrack API when a track string consisting solely of whitespace is passed. The test iterates over a set of valid CCFormat types and confirms that each invocation of SetTrack returns -1, indicating a failure due to invalid input. + * + * **Test Group ID:** Basic: 01@n + * **Test Case ID:** 032@n + * **Priority:** High@n + * + * **Pre-Conditions:** None@n + * **Dependencies:** None@n + * **User Interaction:** None@n + * + * **Test Procedure:**@n + * | Variation / Step | Description | Test Data | Expected Result | Notes | + * | :----: | --------- | ---------- |-------------- | ----- | + * | 01 | Prepare a track string containing only whitespace (i.e., " ") and copy it into a fixed-size array. | inputTrack = " ", trackArr = fixed size array (50 elements) | The whitespace-only track string is successfully prepared. | Should be successful | + * | 02 | For each valid CCFormat (eCLOSEDCAPTION_FORMAT_608, eCLOSEDCAPTION_FORMAT_708, eCLOSEDCAPTION_FORMAT_DEFAULT), create a PlayerSubtecCCManager object and invoke SetTrack with the prepared track and format. | track = " ", format = eCLOSEDCAPTION_FORMAT_608, eCLOSEDCAPTION_FORMAT_708, eCLOSEDCAPTION_FORMAT_DEFAULT | API returns -1 indicating failure and the assertion EXPECT_EQ(-1, ret) passes. | Should Fail | + */ +TEST(PlayerSubtecCCManager, WhitespaceOnlyTrack) { + std::cout << "Entering WhitespaceOnlyTrack test" << std::endl; + + // Array of valid CCFormat types to test + CCFormat formats[] = { eCLOSEDCAPTION_FORMAT_608, eCLOSEDCAPTION_FORMAT_708, eCLOSEDCAPTION_FORMAT_DEFAULT }; + + // Use a fixed size array for the track value for whitespace-only string + char trackArr[50] = {0}; + const char* inputTrack = " "; + std::strncpy(trackArr, inputTrack, sizeof(trackArr)-1); + std::string track(trackArr); + std::cout << "Prepared track string (whitespace only): \"" << track << "\"" << std::endl; + + for (CCFormat format : formats) { + // Create object of derived class using default constructor + PlayerSubtecCCManager manager; + std::cout << "Invoking SetTrack with whitespace track: \"" << track << "\" and format: " << format << std::endl; + + int ret = manager.SetTrack(track, format); + std::cout << "SetTrack returned: " << ret << std::endl; + + // Expect failure (-1) for whitespace-only track string for each valid CCFormat type. + EXPECT_EQ(-1, ret); + } + + std::cout << "Exiting WhitespaceOnlyTrack test" << std::endl; +} +/** + * @brief Test PlayerSubtecCCManager::SetTrickplayStatus functionality for a true positive scenario + * + * This test verifies that the PlayerSubtecCCManager::SetTrickplayStatus method correctly updates the trickplay status when invoked with a true value. The test ensures that the object is created successfully, the method is invoked with the proper input, and the internal state update is logged. + * + * **Test Group ID:** Basic: 01@n + * **Test Case ID:** 033@n + * **Priority:** High@n + * + * **Pre-Conditions:** None@n + * **Dependencies:** None@n + * **User Interaction:** None@n + * + * **Test Procedure:**@n + * | Variation / Step | Description | Test Data | Expected Result | Notes | + * | :----: | --------- | ---------- |-------------- | ----- | + * | 01 | Create object using default constructor | No input parameters, output: valid PlayerSubtecCCManager object | Object is created successfully | Should be successful | + * | 02 | Log the invocation of SetTrickplayStatus with true | input1 = enableValue, enableValue = true | Log displays message indicating invocation with true | Should be successful | + * | 03 | Invoke PlayerSubtecCCManager::SetTrickplayStatus method | input1 = enableValue, enableValue = true | Method executes without errors and updates internal state | Should Pass | + * | 04 | Simulate checking internal state change | No direct input, output: log confirmation "Trickplay mode enabled" | Log confirms the trickplay mode is enabled | Should be successful | + */ +TEST(PlayerSubtecCCManager, SetTrickplayStatus_true_positive) { + std::cout << "Entering SetTrickplayStatus_true_positive test" << std::endl; + + // Create object using default constructor + PlayerSubtecCCManager playerManager; + std::cout << "Created PlayerSubtecCCManager object." << std::endl; + + // Log method invocation with true value + bool enableValue = true; + std::cout << "Invoking PlayerSubtecCCManager::SetTrickplayStatus with value: " + << (enableValue ? "true" : "false") << std::endl; + + // Call method + playerManager.SetTrickplayStatus(enableValue); + std::cout << "PlayerSubtecCCManager::SetTrickplayStatus invoked successfully with value: " + << (enableValue ? "true" : "false") << std::endl; + + // Simulate checking internal state change (if applicable) + std::cout << "Assumed internal state update: Trickplay mode enabled." << std::endl; + + std::cout << "Exiting SetTrickplayStatus_true_positive test" << std::endl; +} +/** + * @brief Test that verifies the behavior of SetTrickplayStatus when invoked with false. + * + * This test ensures that when the PlayerSubtecCCManager::SetTrickplayStatus API is called with a false value, the internal state is updated accordingly to disable trickplay mode. This is important to confirm that trickplay is not enabled when it should be disabled. + * + * **Test Group ID:** Basic: 01@n + * **Test Case ID:** 034@n + * **Priority:** High@n + * + * **Pre-Conditions:** None@n + * **Dependencies:** None@n + * **User Interaction:** None@n + * + * **Test Procedure:** + * | Variation / Step | Description | Test Data | Expected Result | Notes | + * | :--------------: | ------------------------------------------------------------------ | -------------------------- | -------------------------------------------------------------- | ------------------ | + * | 01 | Create PlayerSubtecCCManager object using default constructor. | None | Object is created successfully. | Should be successful | + * | 02 | Invoke SetTrickplayStatus with false value. | enableValue = false | Trickplay status updated to disabled and method invocation succeeds. | Should Pass | + * | 03 | Validate internal state reflects trickplay mode is disabled. | None | Internal state indicates trickplay mode is disabled. | Should be successful | + */ +TEST(PlayerSubtecCCManager, SetTrickplayStatus_false_positive) { + std::cout << "Entering SetTrickplayStatus_false_positive test" << std::endl; + + // Create object using default constructor + PlayerSubtecCCManager playerManager; + std::cout << "Created PlayerSubtecCCManager object." << std::endl; + + // Log method invocation with false value + bool enableValue = false; + std::cout << "Invoking PlayerSubtecCCManager::SetTrickplayStatus with value: " + << (enableValue ? "true" : "false") << std::endl; + + // Call method + playerManager.SetTrickplayStatus(enableValue); + std::cout << "PlayerSubtecCCManager::SetTrickplayStatus invoked successfully with value: " + << (enableValue ? "true" : "false") << std::endl; + + // Simulate checking internal state change (if applicable) + std::cout << "Assumed internal state update: Trickplay mode disabled." << std::endl; + + std::cout << "Exiting SetTrickplayStatus_false_positive test" << std::endl; +} +/** + * @brief Verify negative behavior when repeatedly setting TrickplayStatus to true + * + * This test verifies that invoking PlayerSubtecCCManager::SetTrickplayStatus with a true value more than once is handled as a negative scenario. The first call is expected to set the internal trickplay mode to enabled, while the second duplicate call should be handled as an error case. + * + * **Test Group ID:** Basic: 01 + * **Test Case ID:** 035 + * **Priority:** High + * + * **Pre-Conditions:** None + * **Dependencies:** None + * **User Interaction:** None + * + * **Test Procedure:** + * | Variation / Step | Description | Test Data | Expected Result | Notes | + * | :--------------: | ------------------------------------------------------------------- | ---------------------------- | --------------------------------------------------------------------------- | ------------- | + * | 01 | Create PlayerSubtecCCManager object using default constructor | None | Object is created successfully | Should be successful | + * | 02 | First invocation: Call SetTrickplayStatus with enableValue true | enableValue = true | Internal state set to Trickplay mode enabled | Should Pass | + * | 03 | Second invocation: Call SetTrickplayStatus with enableValue true | enableValue = true | Internal state remains enabled; duplicate setting handled as an error | Should Fail | + */ +TEST(PlayerSubtecCCManager, SetTrickplayStatus_repeated_true_negative) { + std::cout << "Entering SetTrickplayStatus_repeated_true_negative test" << std::endl; + + // Create object using default constructor + PlayerSubtecCCManager playerManager; + std::cout << "Created PlayerSubtecCCManager object." << std::endl; + + // First invocation with true value + bool enableValue = true; + std::cout << "First invocation: Calling PlayerSubtecCCManager::SetTrickplayStatus with value: " + << (enableValue ? "true" : "false") << std::endl; + playerManager.SetTrickplayStatus(enableValue); + std::cout << "First call completed. Assumed internal state: Trickplay mode enabled." << std::endl; + + // Second invocation with true value + std::cout << "Second invocation: Calling PlayerSubtecCCManager::SetTrickplayStatus with value: " + << (enableValue ? "true" : "false") << std::endl; + playerManager.SetTrickplayStatus(enableValue); + std::cout << "Second call completed. Assumed internal state remains: Trickplay mode enabled." << std::endl; + + std::cout << "Exiting SetTrickplayStatus_repeated_true_negative test" << std::endl; +} +/** + * @brief Tests the negative scenario for repeated calls to SetTrickplayStatus with a false value + * + * This test verifies that calling PlayerSubtecCCManager::SetTrickplayStatus consecutively with a false value maintains the disabled state and does not alter internal state on subsequent invocations. The first call is expected to update (disable) the trickplay mode, while the second call should be treated as a negative scenario because it attempts to redundantly disable an already disabled mode. + * + * **Test Group ID:** Basic: 01@n + * **Test Case ID:** 036@n + * **Priority:** High@n + * + * **Pre-Conditions:** None@n + * **Dependencies:** None@n + * **User Interaction:** None@n + * + * **Test Procedure:**@n + * | Variation / Step | Description | Test Data | Expected Result | Notes | + * | :--------------: | ----------------------------------------------------------------- | ----------------------------------------------------- | -------------------------------------------------------------------- | ------------------- | + * | 01 | Print entering test message | N/A | "Entering SetTrickplayStatus_repeated_false_negative test" printed | Should be successful| + * | 02 | Create PlayerSubtecCCManager object using default constructor | output1 = PlayerSubtecCCManager object | Object instantiated successfully | Should be successful| + * | 03 | First invocation of SetTrickplayStatus with false value | input1 = false, output1 = trickplay mode disabled | API call sets trickplay mode to disabled | Should Pass | + * | 04 | Print message after first API invocation | N/A | "First call completed. Assumed internal state: Trickplay mode disabled." printed | Should be successful| + * | 05 | Second invocation of SetTrickplayStatus with false value | input1 = false, output1 = trickplay mode remains disabled| API call does not change the state; internal state remains disabled | Should Fail | + * | 06 | Print message after second API invocation | N/A | "Second call completed. Assumed internal state remains: Trickplay mode disabled." printed | Should be successful| + * | 07 | Print exiting test message | N/A | "Exiting SetTrickplayStatus_repeated_false_negative test" printed | Should be successful| + */ +TEST(PlayerSubtecCCManager, SetTrickplayStatus_repeated_false_negative) { + std::cout << "Entering SetTrickplayStatus_repeated_false_negative test" << std::endl; + + // Create object using default constructor + PlayerSubtecCCManager playerManager; + std::cout << "Created PlayerSubtecCCManager object." << std::endl; + + // First invocation with false value + bool enableValue = false; + std::cout << "First invocation: Calling PlayerSubtecCCManager::SetTrickplayStatus with value: " + << (enableValue ? "true" : "false") << std::endl; + playerManager.SetTrickplayStatus(enableValue); + std::cout << "First call completed. Assumed internal state: Trickplay mode disabled." << std::endl; + + // Second invocation with false value + std::cout << "Second invocation: Calling PlayerSubtecCCManager::SetTrickplayStatus with value: " + << (enableValue ? "true" : "false") << std::endl; + playerManager.SetTrickplayStatus(enableValue); + std::cout << "Second call completed. Assumed internal state remains: Trickplay mode disabled." << std::endl; + + std::cout << "Exiting SetTrickplayStatus_repeated_false_negative test" << std::endl; +} +/** + * @brief Validate that getLastTextTracks returns a single valid CCTrackInfo entry. + * + * This test verifies that the getLastTextTracks method correctly returns exactly one CCTrackInfo entry when provided with a vector containing a single valid track. It ensures that the track's instreamId and language fields match the expected values. + * + * **Test Group ID:** Basic: 01@n + * **Test Case ID:** 037@n + * **Priority:** High@n + * + * **Pre-Conditions:** None@n + * **Dependencies:** None@n + * **User Interaction:** None@n + * + * **Test Procedure:**@n + * | Variation / Step | Description | Test Data | Expected Result | Notes | + * | :----: | --------- | ---------- |-------------- | ----- | + * | 01 | Prepare valid CCTrackInfo with valid instreamId and language fields using strncpy. | instreamId = "track1", language = "en" | CCTrackInfo object is constructed with instreamId "track1" and language "en". | Should be successful | + * | 02 | Create a vector and add the valid CCTrackInfo entry. | tracks vector = [track with instreamId "track1", language = "en"] | Vector contains 1 valid track entry. | Should be successful | + * | 03 | Construct the PlayerSubtecCCManager object. | No input arguments | Manager object is successfully constructed. | Should be successful | + * | 04 | Call getLastTextTracks method and validate the returned track entry. | API call: getLastTextTracks(), output: vector size, returnedTracks[0].instreamId, returnedTracks[0].language | Returned vector size is 1, with track entry having instreamId "track1" and language "en". | Should Pass | + */ +TEST(PlayerSubtecCCManager, getLastTextTracks_singleValidEntry) { + std::cout << "Entering getLastTextTracks_singleValidEntry test" << std::endl; + + // Prepare a single valid CCTrackInfo using strncpy for char arrays + // Even though CCTrackInfo uses std::string, we simulate assignment via strncpy. + char instreamIdArr[64]; + char languageArr[64]; + std::strncpy(instreamIdArr, "track1", sizeof(instreamIdArr)); + instreamIdArr[sizeof(instreamIdArr)-1] = '\0'; + std::strncpy(languageArr, "en", sizeof(languageArr)); + languageArr[sizeof(languageArr)-1] = '\0'; + + // Create a CCTrackInfo object and assign values + CCTrackInfo track; + track.instreamId = instreamIdArr; + track.language = languageArr; + + // Create a vector with a single track entry + std::vector tracks; + tracks.push_back(track); + std::cout << "Prepared vector with single track: instreamId = " << track.instreamId + << ", language = " << track.language << std::endl; + + // Construct the derived class object + PlayerSubtecCCManager manager(); + std::cout << "Constructed PlayerSubtecCCManager" << std::endl; + + // Invoke the method getLastTextTracks() + std::cout << "Invoking getLastTextTracks() method" << std::endl; + const std::vector& returnedTracks = manager.getLastTextTracks(); + std::cout << "Returned vector size: " << returnedTracks.size() << std::endl; + + // Validate the returned vector has exactly one entry and matching values + EXPECT_EQ(returnedTracks.size(), 1u); + if (returnedTracks.size() == 1) { + std::cout << "Track 0 - instreamId: " << returnedTracks[0].instreamId + << ", language: " << returnedTracks[0].language << std::endl; + EXPECT_EQ(returnedTracks[0].instreamId, std::string("track1")); + EXPECT_EQ(returnedTracks[0].language, std::string("en")); + } + + std::cout << "Exiting getLastTextTracks_singleValidEntry test" << std::endl; +} +/** + * @brief Validate the behavior of getLastTextTracks() method with multiple valid track entries + * + * This test verifies that when multiple valid closed caption track entries are provided, + * the PlayerSubtecCCManager correctly returns a vector containing all inserted tracks with the expected instreamId and language values. + * + * **Test Group ID:** Basic: 01@n + * **Test Case ID:** 038@n + * **Priority:** High@n + * + * **Pre-Conditions:** None@n + * **Dependencies:** None@n + * **User Interaction:** None@n + * + * **Test Procedure:** + * | Variation / Step | Description | Test Data | Expected Result | Notes | + * | :--------------: | -------------------------------------------------------------------------------------------- | -------------------------------------------------------------------------------------------------- | --------------------------------------------------------------------------------------------------------------- | -------------- | + * | 01 | Prepare first valid track entry by initializing instreamId with "track1" and language with "en". | input: instreamId = "track1", language = "en" | instreamIdArr1 and languageArr1 are correctly set. | Should be successful | + * | 02 | Prepare second valid track entry by initializing instreamId with "track2" and language with "fr". | input: instreamId = "track2", language = "fr" | instreamIdArr2 and languageArr2 are correctly set. | Should be successful | + * | 03 | Push both track entries into a vector and log the information. | input: vector contains track1 and track2 | Vector is populated with two track entries. | Should be successful | + * | 04 | Construct the PlayerSubtecCCManager object using the vector with track entries. | input: tracks vector = [track1, track2] | Manager object is created using the provided tracks vector. | Should be successful | + * | 05 | Invoke the getLastTextTracks() method on the manager object. | input: method invocation with no additional arguments | Returned vector should mirror the input tracks vector. | Should Pass | + * | 06 | Validate that the returned vector has exactly two entries with matching instreamId and language values. | input: returnedTracks = [ {instreamId = "track1", language = "en"}, {instreamId = "track2", language = "fr"} ] | EXPECT_EQ confirms vector size is 2 and track values exactly match the expected entries. | Should Pass | + */ +TEST(PlayerSubtecCCManager, getLastTextTracks_multipleValidEntries) { + std::cout << "Entering getLastTextTracks_multipleValidEntries test" << std::endl; + + // Prepare first valid track entry + char instreamIdArr1[64]; + char languageArr1[64]; + std::strncpy(instreamIdArr1, "track1", sizeof(instreamIdArr1)); + instreamIdArr1[sizeof(instreamIdArr1)-1] = '\0'; + std::strncpy(languageArr1, "en", sizeof(languageArr1)); + languageArr1[sizeof(languageArr1)-1] = '\0'; + + CCTrackInfo track1; + track1.instreamId = instreamIdArr1; + track1.language = languageArr1; + + // Prepare second valid track entry + char instreamIdArr2[64]; + char languageArr2[64]; + std::strncpy(instreamIdArr2, "track2", sizeof(instreamIdArr2)); + instreamIdArr2[sizeof(instreamIdArr2)-1] = '\0'; + std::strncpy(languageArr2, "fr", sizeof(languageArr2)); + languageArr2[sizeof(languageArr2)-1] = '\0'; + + CCTrackInfo track2; + track2.instreamId = instreamIdArr2; + track2.language = languageArr2; + + // Create a vector with multiple track entries + std::vector tracks; + tracks.push_back(track1); + tracks.push_back(track2); + std::cout << "Prepared vector with multiple tracks:" << std::endl; + std::cout << "Track 0 - instreamId: " << track1.instreamId + << ", language: " << track1.language << std::endl; + std::cout << "Track 1 - instreamId: " << track2.instreamId + << ", language: " << track2.language << std::endl; + + // Construct the derived class object using a custom constructor that accepts track list + PlayerSubtecCCManager manager(tracks); + std::cout << "Constructed PlayerSubtecCCManager with custom tracks vector" << std::endl; + + // Invoke the method getLastTextTracks() + std::cout << "Invoking getLastTextTracks() method" << std::endl; + const std::vector& returnedTracks = manager.getLastTextTracks(); + std::cout << "Returned vector size: " << returnedTracks.size() << std::endl; + + // Validate the returned vector has exactly two entries and matching values for each + EXPECT_EQ(returnedTracks.size(), 2u); + if (returnedTracks.size() >= 2) { + std::cout << "Track 0 - instreamId: " << returnedTracks[0].instreamId + << ", language: " << returnedTracks[0].language << std::endl; + std::cout << "Track 1 - instreamId: " << returnedTracks[1].instreamId + << ", language: " << returnedTracks[1].language << std::endl; + EXPECT_EQ(returnedTracks[0].instreamId, std::string("track1")); + EXPECT_EQ(returnedTracks[0].language, std::string("en")); + EXPECT_EQ(returnedTracks[1].instreamId, std::string("track2")); + EXPECT_EQ(returnedTracks[1].language, std::string("fr")); + } + + std::cout << "Exiting getLastTextTracks_multipleValidEntries test" << std::endl; +} +/** + * @brief Test updateLastTextTracks API with an empty track list to ensure proper handling. + * + * This test verifies that calling updateLastTextTracks with an empty vector correctly handles the empty input without errors, ensuring that the API does not update any tracks when given no data. + * + * **Test Group ID:** Basic: 01@n + * **Test Case ID:** 039@n + * **Priority:** High@n + * + * **Pre-Conditions:** None@n + * **Dependencies:** None@n + * **User Interaction:** None@n + * + * **Test Procedure:**@n + * | Variation / Step | Description | Test Data | Expected Result | Notes | + * | :--------------: | ------------------------------------------------------------------ | -------------------------------------------------- | ------------------------------------------------------------------- | ------------- | + * | 01 | Instantiate PlayerSubtecCCManager using its default constructor | output1 = player object created | PlayerSubtecCCManager instance is created successfully | Should be successful | + * | 02 | Prepare an empty vector of CCTrackInfo | input1 = newTextTracks size = 0 | newTextTracks is empty | Should be successful | + * | 03 | Invoke updateLastTextTracks with the empty track list | input1 = newTextTracks = [] | updateLastTextTracks completes execution without errors | Should Pass | + * | 04 | Log entry and exit messages for the test execution | N/A | Log messages printed indicating test entry and exit | Should be successful | + */ +TEST(PlayerSubtecCCManager, UpdateWithEmptyTrackList) { + std::cout << "Entering UpdateWithEmptyTrackList test" << std::endl; + + // Create an object of the derived class using its default constructor. + PlayerSubtecCCManager player; + + // Prepare an empty vector of CCTrackInfo. + std::vector newTextTracks; + std::cout << "Prepared empty track list with size: " << newTextTracks.size() << std::endl; + + // Invoke updateLastTextTracks with empty vector. + std::cout << "Invoking updateLastTextTracks with empty track list" << std::endl; + player.updateLastTextTracks(newTextTracks); + + std::cout << "Exiting UpdateWithEmptyTrackList test" << std::endl; +} +/** + * @brief Validate updateLastTextTracks API with a single valid track info. + * + * This test verifies that the updateLastTextTracks function of the PlayerSubtecCCManager class correctly updates its internal state when provided with a valid single text track info. + * + * **Test Group ID:** Basic: 01@n + * **Test Case ID:** 040@n + * **Priority:** High@n + * + * **Pre-Conditions:** None@n + * **Dependencies:** None@n + * **User Interaction:** None@n + * + * **Test Procedure:** + * | Variation / Step | Description | Test Data | Expected Result | Notes | + * | :--------------: | ----------------------------------------------------------------- | ------------------------------------------------------------- | ---------------------------------------------------------------------------- | --------------- | + * | 01 | Instantiate the PlayerSubtecCCManager class | None | PlayerSubtecCCManager instance created successfully | Should be successful | + * | 02 | Populate a CCTrackInfo structure with valid track details | instreamId = Track1, language = en | CCTrackInfo object's instreamId is "Track1" and language is "en" | Should be successful | + * | 03 | Invoke updateLastTextTracks with a vector containing the track info | vector size = 1, track.instreamId = Track1, track.language = en | updateLastTextTracks executed and internal state updated appropriately, assertions pass | Should Pass | + */ +TEST(PlayerSubtecCCManager, UpdateWithSingleValidTrackInfo) { + std::cout << "Entering UpdateWithSingleValidTrackInfo test" << std::endl; + + PlayerSubtecCCManager player; + + std::vector newTextTracks; + CCTrackInfo track; + { + // Using strncpy to assign value to fixed size character buffer then converting to std::string. + char idBuf[32] = {0}; + char langBuf[32] = {0}; + std::strncpy(idBuf, "Track1", sizeof(idBuf)-1); + std::strncpy(langBuf, "en", sizeof(langBuf)-1); + track.instreamId = std::string(idBuf); + track.language = std::string(langBuf); + } + newTextTracks.push_back(track); + std::cout << "Added track: instreamId = " << track.instreamId << ", language = " << track.language << std::endl; + + std::cout << "Invoking updateLastTextTracks with a single track info" << std::endl; + player.updateLastTextTracks(newTextTracks); + + std::cout << "Exiting UpdateWithSingleValidTrackInfo test" << std::endl; +} +/** + * @brief Validate that updateLastTextTracks handles multiple valid track info entries correctly + * + * This test verifies that the updateLastTextTracks method of the PlayerSubtecCCManager class can successfully update its track list when provided with multiple valid CCTrackInfo objects. The test ensures that valid data for two different track entries ("Track1" with language "en" and "Track2" with language "fr") is correctly added and processed by the API. + * + * **Test Group ID:** Basic: 01@n + * **Test Case ID:** 041@n + * **Priority:** High@n + * + * **Pre-Conditions:** None@n + * **Dependencies:** None@n + * **User Interaction:** None@n + * + * **Test Procedure:**@n + * | Variation / Step | Description | Test Data | Expected Result | Notes | + * | :--------------: | ------------------------------------------------------------------------------------ | -------------------------------------------------------------------------------------------------- | ------------------------------------------------------------------ | ------------ | + * | 01 | Instantiate the PlayerSubtecCCManager object | None | Object instantiated successfully | Should be successful | + * | 02 | Create and add the first valid track info (Track1 with language en) | instreamId = Track1, language = en | First track info added to vector successfully | Should Pass | + * | 03 | Create and add the second valid track info (Track2 with language fr) | instreamId = Track2, language = fr | Second track info added to vector successfully | Should Pass | + * | 04 | Invoke updateLastTextTracks API with the vector containing multiple track info entries | newTextTracks = { {instreamId = Track1, language = en}, {instreamId = Track2, language = fr} } | API processes the vector and updates the internal track list without error | Should Pass | + */ +TEST(PlayerSubtecCCManager, UpdateWithMultipleValidTrackInfos) { + std::cout << "Entering UpdateWithMultipleValidTrackInfos test" << std::endl; + + PlayerSubtecCCManager player; + + std::vector newTextTracks; + + CCTrackInfo track1; + { + char idBuf[32] = {0}; + char langBuf[32] = {0}; + std::strncpy(idBuf, "Track1", sizeof(idBuf)-1); + std::strncpy(langBuf, "en", sizeof(langBuf)-1); + track1.instreamId = std::string(idBuf); + track1.language = std::string(langBuf); + } + newTextTracks.push_back(track1); + std::cout << "Added track: instreamId = " << track1.instreamId << ", language = " << track1.language << std::endl; + + CCTrackInfo track2; + { + char idBuf[32] = {0}; + char langBuf[32] = {0}; + std::strncpy(idBuf, "Track2", sizeof(idBuf)-1); + std::strncpy(langBuf, "fr", sizeof(langBuf)-1); + track2.instreamId = std::string(idBuf); + track2.language = std::string(langBuf); + } + newTextTracks.push_back(track2); + std::cout << "Added track: instreamId = " << track2.instreamId << ", language = " << track2.language << std::endl; + + std::cout << "Invoking updateLastTextTracks with multiple track infos" << std::endl; + player.updateLastTextTracks(newTextTracks); + + std::cout << "Exiting UpdateWithMultipleValidTrackInfos test" << std::endl; +} +/** + * @brief Verify that updateLastTextTracks correctly processes track info with empty strings. + * + * This test verifies that when a vector containing a CCTrackInfo with empty instreamId and language strings is provided to the updateLastTextTracks method, the function processes the input gracefully without errors. This ensures that the edge case of empty track data is handled properly. + * + * **Test Group ID:** Basic: 01@n + * **Test Case ID:** 042@n + * **Priority:** High@n + * + * **Pre-Conditions:** None@n + * **Dependencies:** None@n + * **User Interaction:** None@n + * + * **Test Procedure:** + * | Variation / Step | Description | Test Data | Expected Result |Notes | + * | :----: | --------- | ---------- |-------------- | ----- | + * | 01 | Initialize the test environment and instantiate PlayerSubtecCCManager | None | Instance is created successfully | Should be successful | + * | 02 | Prepare CCTrackInfo with empty instreamId and language and add it to vector | instreamId = "", language = "" | CCTrackInfo is initialized with empty strings | Should Pass | + * | 03 | Invoke updateLastTextTracks with the prepared vector | newTextTracks = vector containing one CCTrackInfo with instreamId = "", language = "" | updateLastTextTracks processes the empty strings correctly | Should Pass | + */ +TEST(PlayerSubtecCCManager, UpdateWithTrackInfoHavingEmptyStrings) { + std::cout << "Entering UpdateWithTrackInfoHavingEmptyStrings test" << std::endl; + + PlayerSubtecCCManager player; + + std::vector newTextTracks; + CCTrackInfo track; + { + char idBuf[32] = {0}; + char langBuf[32] = {0}; + // Empty strings copied using strncpy. + std::strncpy(idBuf, "", sizeof(idBuf)-1); + std::strncpy(langBuf, "", sizeof(langBuf)-1); + track.instreamId = std::string(idBuf); + track.language = std::string(langBuf); + } + newTextTracks.push_back(track); + std::cout << "Added track with empty instreamId and language" << std::endl; + + std::cout << "Invoking updateLastTextTracks with track info having empty strings" << std::endl; + player.updateLastTextTracks(newTextTracks); + + std::cout << "Exiting UpdateWithTrackInfoHavingEmptyStrings test" << std::endl; +} +/** + * @brief Test the updateLastTextTracks API with duplicate track entries + * + * This test constructs a vector containing two identical CCTrackInfo entries and passes it to the updateLastTextTracks method to evaluate how the function handles duplicate text tracks. The goal is to ensure that duplicate track entries do not cause any adverse effects. + * + * **Test Group ID:** Basic: 01@n + * **Test Case ID:** 043@n + * **Priority:** High@n + * + * **Pre-Conditions:** None@n + * **Dependencies:** None@n + * **User Interaction:** None@n + * + * **Test Procedure:**@n + * | Variation / Step | Description | Test Data | Expected Result | Notes | + * | :----: | --------- | ---------- |-------------- | ----- | + * | 01 | Initialize a CCTrackInfo object with instreamId as "Duplicate" and language as "en". | instreamId = Duplicate, language = en | Track info is correctly initialized. | Should be successful | + * | 02 | Add the first duplicate track to the newTextTracks vector. | newTextTracks: one element with instreamId = Duplicate, language = en | Vector size becomes 1 with the correct track info. | Should Pass | + * | 03 | Add the second duplicate track to the newTextTracks vector. | newTextTracks: two elements where both have instreamId = Duplicate, language = en | Vector size becomes 2 with both tracks identical. | Should Pass | + * | 04 | Invoke the updateLastTextTracks API with the duplicate track entries. | player object, newTextTracks = vector with two duplicate tracks | API handles duplicate entries gracefully without adverse effects. | Should Pass | + */ +TEST(PlayerSubtecCCManager, UpdateWithDuplicateTrackEntries) { + std::cout << "Entering UpdateWithDuplicateTrackEntries test" << std::endl; + + PlayerSubtecCCManager player; + + std::vector newTextTracks; + + CCTrackInfo track; + { + char idBuf[32] = {0}; + char langBuf[32] = {0}; + std::strncpy(idBuf, "Duplicate", sizeof(idBuf)-1); + std::strncpy(langBuf, "en", sizeof(langBuf)-1); + track.instreamId = std::string(idBuf); + track.language = std::string(langBuf); + } + newTextTracks.push_back(track); + std::cout << "Added first duplicate track: instreamId = " << track.instreamId + << ", language = " << track.language << std::endl; + + newTextTracks.push_back(track); + std::cout << "Added second duplicate track: instreamId = " << track.instreamId + << ", language = " << track.language << std::endl; + + std::cout << "Invoking updateLastTextTracks with duplicate track entries" << std::endl; + player.updateLastTextTracks(newTextTracks); + + std::cout << "Exiting UpdateWithDuplicateTrackEntries test" << std::endl; +} +/** + * @brief Tests subsequent calls to update the track list in PlayerSubtecCCManager. + * + * This test verifies that multiple invocations of updateLastTextTracks correctly update the internal track list. It first sends an initial track list and then sends an updated track list. The test ensures that the state of the track list is updated as expected with each call. + * + * **Test Group ID:** Basic: 01@n + * **Test Case ID:** 044@n + * **Priority:** High@n + * + * **Pre-Conditions:** None@n + * **Dependencies:** None@n + * **User Interaction:** None@n + * + * **Test Procedure:**@n + * | Variation / Step | Description | Test Data | Expected Result | Notes | + * | :--------------: | ------------------------------------------------------------------------ | ------------------------------------------------------------------------------------------------- | ----------------------------------------------------------------------------------------- | ----------- | + * | 01 | Initialize PlayerSubtecCCManager and create first track info | player = instance, firstTextTracks = [instreamId = "Initial", language = "en"] | PlayerSubtecCCManager is instantiated and firstTextTracks is constructed successfully | Should Pass | + * | 02 | Call updateLastTextTracks with the first track list | firstTextTracks = [instreamId = "Initial", language = "en"] | updateLastTextTracks processes the first track list correctly | Should Pass | + * | 03 | Create second track info and call updateLastTextTracks with the updated list | secondTextTracks = [instreamId = "Updated", language = "es"] | updateLastTextTracks processes the second track list, updating the state to the new track info | Should Pass | + */ +TEST(PlayerSubtecCCManager, SubsequentCallsToUpdateTheTrackList) { + std::cout << "Entering SubsequentCallsToUpdateTheTrackList test" << std::endl; + + PlayerSubtecCCManager player; + + // First update call + std::vector firstTextTracks; + { + CCTrackInfo track; + char idBuf[32] = {0}; + char langBuf[32] = {0}; + std::strncpy(idBuf, "Initial", sizeof(idBuf)-1); + std::strncpy(langBuf, "en", sizeof(langBuf)-1); + track.instreamId = std::string(idBuf); + track.language = std::string(langBuf); + firstTextTracks.push_back(track); + std::cout << "First call - Added track: instreamId = " << track.instreamId + << ", language = " << track.language << std::endl; + } + std::cout << "Invoking updateLastTextTracks for the first time" << std::endl; + player.updateLastTextTracks(firstTextTracks); + + // Second update call + std::vector secondTextTracks; + { + CCTrackInfo track; + char idBuf[32] = {0}; + char langBuf[32] = {0}; + std::strncpy(idBuf, "Updated", sizeof(idBuf)-1); + std::strncpy(langBuf, "es", sizeof(langBuf)-1); + track.instreamId = std::string(idBuf); + track.language = std::string(langBuf); + secondTextTracks.push_back(track); + std::cout << "Second call - Added track: instreamId = " << track.instreamId + << ", language = " << track.language << std::endl; + } + std::cout << "Invoking updateLastTextTracks for the second time" << std::endl; + player.updateLastTextTracks(secondTextTracks); + + std::cout << "Exiting SubsequentCallsToUpdateTheTrackList test" << std::endl; +} +/** + * @brief Verify that the destructor of a default constructed PlayerSubtecCCManager does not throw exceptions + * + * This test confirms that creating an instance of PlayerSubtecCCManager using its default constructor + * and subsequently deleting the instance successfully invokes the destructor (including its base class destructor) + * without causing any exceptions. + * + * **Test Group ID:** Basic: 01@n + * **Test Case ID:** 045@n + * **Priority:** High@n + * + * **Pre-Conditions:** None@n + * **Dependencies:** None@n + * **User Interaction:** None@n + * + * **Test Procedure:** + * | Variation / Step | Description | Test Data | Expected Result | Notes | + * | :--------------: | ----------------------------------------------------------------- | ------------------------------------------------------------------ | ---------------------------------------------------------------------- | ------------- | + * | 01 | Invoke default constructor of PlayerSubtecCCManager | output instance = uninitialized pointer | Instance is created successfully with a valid memory address | Should Pass | + * | 02 | Delete the instance to trigger the destructor of PlayerSubtecCCManager | input: instance pointer = valid address | Destructor executes without throwing any exceptions | Should Pass | + */ +TEST(PlayerSubtecCCManager, DestructionOfDefaultConstructedInstance) +{ + std::cout << "Entering DestructionOfDefaultConstructedInstance test" << std::endl; + + EXPECT_NO_THROW({ + std::cout << "Invoking default constructor of PlayerSubtecCCManager" << std::endl; + PlayerSubtecCCManager* instance = new PlayerSubtecCCManager(); + std::cout << "PlayerSubtecCCManager instance created at address: " << instance << std::endl; + std::cout << "Deleting PlayerSubtecCCManager instance to invoke destructor (PlayerCCManagerBase::~PlayerCCManagerBase())" << std::endl; + delete instance; + std::cout << "Destructor for PlayerSubtecCCManager (and its base PlayerCCManagerBase) executed successfully" << std::endl; + }); + + std::cout << "Exiting DestructionOfDefaultConstructedInstance test" << std::endl; +} + +int main(int argc, char **argv) { + ::testing::InitGoogleTest(&argc, argv); + return RUN_ALL_TESTS(); +} \ No newline at end of file From 54d3411fac6e7a67c234f3f987d95a301c4182e6 Mon Sep 17 00:00:00 2001 From: joyal Date: Wed, 23 Jul 2025 13:14:29 +0530 Subject: [PATCH 9/9] gh #2: Generate_L1_tests --- baseConversion/test/test_l1__base64.cpp | 799 ++++++++++++++++ baseConversion/test/test_l1_base16.cpp | 510 +++++++++++ closedcaptions/test/test_l1_CCTrackInfo.cpp | 81 ++ drm/test/test_l1_DrmSessionFactory.cpp | 189 ++++ drm/test/test_l1_DrmUtils.cpp | 959 ++++++++++++++++++++ 5 files changed, 2538 insertions(+) create mode 100644 baseConversion/test/test_l1__base64.cpp create mode 100644 baseConversion/test/test_l1_base16.cpp create mode 100644 closedcaptions/test/test_l1_CCTrackInfo.cpp create mode 100644 drm/test/test_l1_DrmSessionFactory.cpp create mode 100644 drm/test/test_l1_DrmUtils.cpp diff --git a/baseConversion/test/test_l1__base64.cpp b/baseConversion/test/test_l1__base64.cpp new file mode 100644 index 0000000..2e6d447 --- /dev/null +++ b/baseConversion/test/test_l1__base64.cpp @@ -0,0 +1,799 @@ + +/* + * If not stated otherwise in this file or this component's LICENSE file the + * following copyright and licenses apply: + * + * Copyright 2025 RDK Management + * + * 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. + */ + +/** +* @file test_l1__base64.cpp +* @page _base64 Level 1 Tests +* +* ## Module's Role +* This module includes Level 1 functional tests (success and failure scenarios). +* This is to ensure that the _base64 methods meet the requirements. +* +* **Pre-Conditions:** None @n +* **Dependencies:** None @n +* +*/ + +#include +#include +#include +#include "_base64.h" + +/** + * @brief Test the base64 encoding functionality for a typical string input. + * + * This test verifies that the base64_Encode API correctly encodes a typical string "Hello" without throwing exceptions. It checks that the returned encoded string matches the expected value "SGVsbG8=". + * + * **Test Group ID:** Basic: 01@n + * **Test Case ID:** 001@n + * **Priority:** High@n + * + * **Pre-Conditions:** None@n + * **Dependencies:** None@n + * **User Interaction:** None@n + * + * **Test Procedure:** + * | Variation / Step | Description | Test Data | Expected Result | Notes | + * | :--------------: | ------------------------------------------------------------------------ | ------------------------------------------------------------------------------------------------ | ----------------------------------------------------------------------------------------- | ------------- | + * | 01 | Initialize the input buffer with the string "Hello" | input = "Hello", length = 5 | Input buffer is correctly initialized with "Hello" | Should be successful | + * | 02 | Invoke base64_Encode with the initialized input | input buffer ("Hello"), length = 5 | Function returns a base64 encoded string "SGVsbG8=" without throwing exceptions | Should Pass | + * | 03 | Compare the returned encoded string with the expected value ("SGVsbG8=") | expected = "SGVsbG8=", result from base64_Encode | EXPECT_STREQ check validates that the returned string equals "SGVsbG8=" | Should Pass | + * | 04 | Free the allocated memory for the result | result pointer allocated by base64_Encode | Memory is freed properly without leaking | Should be successful | + */ +TEST(Base64EncodeTest, EncodeTypicalStringHello) { + std::cout << "Entering EncodeTypicalStringHello test" << std::endl; + + char input[10]; + memset(input, 0, sizeof(input)); + strncpy(input, "Hello", sizeof(input) - 1); + std::cout << "Input string: " << input << ", length: " << 5 << std::endl; + + std::cout << "Invoking base64_Encode with input value: " << input << std::endl; + char* result = nullptr; + EXPECT_NO_THROW(result = base64_Encode(reinterpret_cast(input), 5)); + std::cout << "Returned value from base64_Encode: " << (result ? result : "NULL") << std::endl; + + const char* expected = "SGVsbG8="; + EXPECT_STREQ(expected, result); + + // Free the allocated memory if necessary + if(result) { + free(result); + } + + std::cout << "Exiting EncodeTypicalStringHello test" << std::endl; +} +/** + * @brief Validate that the base64_Encode function correctly handles an empty input. + * + * This test verifies that when provided with an empty string as input, the base64_Encode API does not throw an exception and returns an empty string as output. This test ensures the function gracefully handles edge cases. + * + * **Test Group ID:** Basic: 01@n + * **Test Case ID:** 002@n + * **Priority:** High@n + * + * **Pre-Conditions:** None@n + * **Dependencies:** None@n + * **User Interaction:** None@n + * + * **Test Procedure:**@n + * | Variation / Step | Description | Test Data | Expected Result | Notes | + * | :---------------: | ----------- | --------- | --------------- | ----- | + * | 01 | Initialize an empty input buffer for encoding. | input = "", output = NULL | Empty input is prepared without error. | Should be successful | + * | 02 | Invoke base64_Encode with the empty input. | input = "", length = 0, output = result pointer | API does not throw an exception and returns an empty string. | Should Pass | + */ +TEST(Base64EncodeTest, EncodeEmptyInput) { + std::cout << "Entering EncodeEmptyInput test" << std::endl; + + char input[1]; + memset(input, 0, sizeof(input)); + strncpy(input, "", sizeof(input) - 1); + std::cout << "Input string: \"" << input << "\" (empty), length: " << 0 << std::endl; + + std::cout << "Invoking base64_Encode with empty input" << std::endl; + char* result = nullptr; + EXPECT_NO_THROW(result = base64_Encode(reinterpret_cast(input), 0)); + std::cout << "Returned value from base64_Encode: " << (result ? result : "NULL") << std::endl; + + const char* expected = ""; + EXPECT_STREQ(expected, result); + + if(result) { + free(result); + } + + std::cout << "Exiting EncodeEmptyInput test" << std::endl; +} +/** + * @brief Test the base64_Encode API with a valid input string. + * + * This test verifies that the base64_Encode function correctly encodes a valid input string "Ma". It checks for no exceptions during the function call, validates that the returned pointer is allocated, and confirms that the output matches the expected Base64 encoding "TWE=". The test also ensures proper memory deallocation to prevent leaks. + * + * **Test Group ID:** Basic: 01@n + * **Test Case ID:** 003@n + * **Priority:** High@n + * + * **Pre-Conditions:** None@n + * **Dependencies:** None@n + * **User Interaction:** None@n + * + * **Test Procedure:** + * | Variation / Step | Description | Test Data | Expected Result | Notes | + * | :--------------: | -------------------------------------------------------------------- | --------------------------------------------------------------- | -------------------------------------------------------------------- | -------------- | + * | 01 | Initialize the input array with "Ma" and set its length to 2 | input = "Ma", length = 2 | Input array is properly initialized | Should be successful | + * | 02 | Invoke base64_Encode API with the prepared input | input pointer = address of input, input length = 2 | No exception is thrown and result pointer is allocated | Should Pass | + * | 03 | Compare the returned Base64 encoded string with expected "TWE=" | expected = "TWE=", result = returned value | The result string matches the expected string "TWE=" | Should Pass | + * | 04 | Free the allocated memory for the result pointer | result pointer freed | Memory is freed without issues | Should be successful | + */ +TEST(Base64EncodeTest, EncodeStringvalidvalue) { + std::cout << "Entering EncodeStringvalidvalue test" << std::endl; + + char input[10]; + memset(input, 0, sizeof(input)); + strncpy(input, "Ma", sizeof(input) - 1); + std::cout << "Input string: " << input << ", length: " << 2 << std::endl; + + std::cout << "Invoking base64_Encode with input value: " << input << std::endl; + char* result = nullptr; + EXPECT_NO_THROW(result = base64_Encode(reinterpret_cast(input), 2)); + std::cout << "Returned value from base64_Encode: " << (result ? result : "NULL") << std::endl; + + const char* expected = "TWE="; + EXPECT_STREQ(expected, result); + + if(result) { + free(result); + } + + std::cout << "Exiting EncodeStringvalidvalue test" << std::endl; +} +/** + * @brief Validates the base64_Encode API with binary data containing special bytes. + * + * This test verifies that the base64_Encode function correctly encodes binary data that includes special bytes such as 0x00, 0xFF, 0xAA, and 0x55. The expected base64 encoded result is compared against a known correct value. + * + * **Test Group ID:** Basic: 01@n + * **Test Case ID:** 004@n + * **Priority:** High@n + * + * **Pre-Conditions:** None@n + * **Dependencies:** None@n + * **User Interaction:** None@n + * + * **Test Procedure:**@n + * | Variation / Step | Description | Test Data | Expected Result | Notes | + * | :----: | --------- | ---------- |-------------- | ----- | + * | 01 | Initialize binary data with special bytes (0x00, 0xFF, 0xAA, 0x55) | input[0]=0x00, input[1]=0xFF, input[2]=0xAA, input[3]=0x55 | Binary data array is properly populated with the expected values | Should be successful | + * | 02 | Invoke base64_Encode with the prepared binary data | input pointer, length=4 | Returns a non-null pointer to a valid base64 encoded string without throwing exceptions | Should Pass | + * | 03 | Verify the returned base64 encoded string matches the expected value | expected="AP+qVQ==", result from base64_Encode | The returned string equals "AP+qVQ==" as asserted by EXPECT_STREQ | Should Pass | + * | 04 | Free the allocated memory for the encoded result | result pointer | Memory is freed without causing any issues | Should be successful | + */ +TEST(Base64EncodeTest, EncodeBinaryDataWithSpecialBytes) { + std::cout << "Entering EncodeBinaryDataWithSpecialBytes test" << std::endl; + + unsigned char input[10]; + memset(input, 0, sizeof(input)); + // Create binary data: 0x00, 0xFF, 0xAA, 0x55 + input[0] = 0x00; + input[1] = 0xFF; + input[2] = 0xAA; + input[3] = 0x55; + std::cout << "Input binary data bytes: "; + for (size_t i = 0; i < 4; i++) { + std::cout << "0x" << std::hex << static_cast(input[i]) << " "; + } + std::cout << std::dec << ", length: " << 4 << std::endl; + + std::cout << "Invoking base64_Encode with binary data" << std::endl; + char* result = nullptr; + EXPECT_NO_THROW(result = base64_Encode(input, 4)); + std::cout << "Returned value from base64_Encode: " << (result ? result : "NULL") << std::endl; + + const char* expected = "AP+qVQ=="; + EXPECT_STREQ(expected, result); + + if(result) { + free(result); + } + + std::cout << "Exiting EncodeBinaryDataWithSpecialBytes test" << std::endl; +} +/** + * @brief Verify base64_Encode gracefully handles a null input pointer. + * + * This test verifies that the base64_Encode API correctly processes a null input pointer by not throwing any exception and returning a null result pointer. The test is essential to ensure the API can handle invalid input without causing crashes. + * + * **Test Group ID:** Basic: 01@n + * **Test Case ID:** 005@n + * **Priority:** High@n + * + * **Pre-Conditions:** None@n + * **Dependencies:** None@n + * **User Interaction:** None@n + * + * **Test Procedure:**@n + * | Variation / Step | Description | Test Data | Expected Result | Notes | + * | :------------: | ----------------------------------------------------------------------- | ---------------------------------------- | --------------------------------------------------------------------- | --------------- | + * | 01 | Initialize test variables with a null pointer for input and a fixed length. | input = nullptr, len = 5 | Variables initialized as expected | Should be successful | + * | 02 | Invoke base64_Encode with the null input pointer ensuring no exceptions are thrown. | input = nullptr, len = 5 | Function returns a null pointer without throwing exceptions | Should Pass | + * | 03 | Check that the returned result pointer is null. | result (output) = nullptr | Assertion confirms that the result equals nullptr | Should Pass | + */ +TEST(Base64EncodeTest, HandleNullPointerInput) { + std::cout << "Entering HandleNullPointerInput test" << std::endl; + + unsigned char* input = nullptr; + size_t len = 5; + std::cout << "Input pointer is NULL, length: " << len << std::endl; + + std::cout << "Invoking base64_Encode with NULL pointer" << std::endl; + char* result = nullptr; + EXPECT_NO_THROW(result = base64_Encode(input, len)); + std::cout << "Returned value from base64_Encode: " << (result ? result : "NULL") << std::endl; + + EXPECT_EQ(result, nullptr); + + std::cout << "Exiting HandleNullPointerInput test" << std::endl; +} +/** + * @brief Validate correct decoding of a valid Base64 encoded string. + * + * This test verifies that the base64_Decode API correctly decodes a valid Base64 encoded input. It checks that the returned decoded pointer is non-null, that the decoded length is properly set to 5, and that the decoded content exactly matches the expected string "Hello". This functionality is critical for ensuring the reliability of the Base64 decoding process. + * + * **Test Group ID:** Basic: 01@n + * **Test Case ID:** 006@n + * **Priority:** High@n + * + * **Pre-Conditions:** None@n + * **Dependencies:** None@n + * **User Interaction:** None@n + * + * **Test Procedure:**@n + * | Variation / Step | Description | Test Data | Expected Result | Notes | + * | :--------------: | ------------------------------------------------- | -------------------------------------------------------- | ------------------------------------------------------------------------------------------ | ------------------- | + * | 01 | Assign Base64 encoded string to src | src = "SGVsbG8=" | src holds the value "SGVsbG8=" | Should be successful| + * | 02 | Invoke base64_Decode with src and &decodedLen | src = "SGVsbG8=", decodedLen pointer = address of decodedLen | API returns a non-null pointer and decodedLen equals 5 | Should Pass | + * | 03 | Compare decoded result with expected string "Hello" | decodedResult content from API, expected "Hello" | std::strncmp returns 0 indicating decoded string matches "Hello" | Should Pass | + */ +TEST(Base64DecodeTests, ValidBase64StringDecoding) { + std::cout << "Entering ValidBase64StringDecoding test" << std::endl; + + char src[16]; + std::cout << "Assigning Base64 encoded string 'SGVsbG8=' to src" << std::endl; + std::strncpy(src, "SGVsbG8=", sizeof(src)); + + size_t decodedLen = 0; + std::cout << "Invoking base64_Decode with src: " << src << " and address of decodedLen: " << &decodedLen << std::endl; + unsigned char* decodedResult = base64_Decode(src, &decodedLen); + std::cout << "base64_Decode returned pointer: " << static_cast(decodedResult) << " with decodedLen: " << decodedLen << std::endl; + + EXPECT_NE(decodedResult, nullptr); + EXPECT_EQ(decodedLen, 5); + if(decodedResult != nullptr) { + std::cout << "Comparing decoded result with expected 'Hello'" << std::endl; + EXPECT_EQ(std::strncmp(reinterpret_cast(decodedResult), "Hello", 5), 0); + std::cout << "Decoded string is: " << std::string(reinterpret_cast(decodedResult), decodedLen) << std::endl; + free(decodedResult); + } + + std::cout << "Exiting ValidBase64StringDecoding test" << std::endl; +} +/** + * @brief Verify that base64_Decode correctly handles an empty string input. + * + * This test ensures that when provided with an empty string as input, the base64_Decode function returns a non-null pointer and sets the decoded length to 0. This is essential to confirm that the function can gracefully handle cases without any data. + * + * **Test Group ID:** Basic: 01@n + * **Test Case ID:** 007@n + * **Priority:** High@n + * + * **Pre-Conditions:** None@n + * **Dependencies:** None@n + * **User Interaction:** None@n + * + * **Test Procedure:**@n + * | Variation / Step | Description | Test Data | Expected Result | Notes | + * | :--------------: | ----------------------------------------------------------------- | ------------------------------------------------------ | -------------------------------------------- | ------------- | + * | 01 | Initialize a character buffer and assign it an empty string ('') | src = "", buffer size = 16 | src contains empty string | Should be successful | + * | 02 | Invoke base64_Decode with the empty input string and address of decodedLen | src = "", decodedLen pointer = &decodedLen | Function returns non-null pointer and decodedLen equals 0 | Should Pass | + * | 03 | Free the allocated memory if base64_Decode returned a non-null pointer | decodedResult pointer as returned by base64_Decode | Memory freed without error | Should be successful | + */ +TEST(Base64DecodeTests, EmptyStringInput) { + std::cout << "Entering EmptyStringInput test" << std::endl; + + char src[16]; + std::cout << "Assigning empty string '' to src" << std::endl; + std::strncpy(src, "", sizeof(src)); + + size_t decodedLen = 0; + std::cout << "Invoking base64_Decode with empty src and address of decodedLen: " << &decodedLen << std::endl; + unsigned char* decodedResult = base64_Decode(src, &decodedLen); + std::cout << "base64_Decode returned pointer: " << static_cast(decodedResult) << " with decodedLen: " << decodedLen << std::endl; + + EXPECT_NE(decodedResult, nullptr); + EXPECT_EQ(decodedLen, 0); + + if(decodedResult != nullptr) { + free(decodedResult); + } + + std::cout << "Exiting EmptyStringInput test" << std::endl; +} +/** + * @brief Verifies that base64_Decode handles a NULL source pointer gracefully. + * + * This test case checks whether the base64_Decode function correctly returns a NULL pointer and sets the decoded length to zero when provided with a NULL source pointer. It ensures robust error handling for invalid input. + * + * **Test Group ID:** Basic: 01 + * **Test Case ID:** 008 + * **Priority:** High + * + * **Pre-Conditions:** None + * **Dependencies:** None + * **User Interaction:** None + * + * **Test Procedure:** + * | Variation / Step | Description | Test Data | Expected Result | Notes | + * | :----: | --------- | ---------- |-------------- | ----- | + * | 01 | Invoke base64_Decode with a NULL source pointer and a valid pointer for decodedLen | src = NULL, decodedLen pointer = valid, initial decodedLen = 0 | Returns a NULL pointer and decodedLen remains 0; Assertions: decodedResult == NULL and decodedLen == 0 | Should Pass | + */ +TEST(Base64DecodeTests, NullSourcePointer) { + std::cout << "Entering NullSourcePointer test" << std::endl; + + size_t decodedLen = 0; + std::cout << "Invoking base64_Decode with src: NULL and address of decodedLen: " << &decodedLen << std::endl; + unsigned char* decodedResult = base64_Decode(NULL, &decodedLen); + std::cout << "base64_Decode returned pointer: " << static_cast(decodedResult) << " with decodedLen: " << decodedLen << std::endl; + + EXPECT_EQ(decodedResult, nullptr); + EXPECT_EQ(decodedLen, 0); + + std::cout << "Exiting NullSourcePointer test" << std::endl; +} +/** + * @brief Validate base64_Decode API handling when len pointer is NULL with valid input. + * + * This test verifies that the base64_Decode function correctly returns a nullptr when provided with a valid Base64 encoded string and a NULL pointer for the length parameter. It ensures that the API can handle cases where the length of the decoded output is not required, hence improving robustness. + * + * **Test Group ID:** Basic: 01@n + * **Test Case ID:** 009@n + * **Priority:** High@n + * + * **Pre-Conditions:** None@n + * **Dependencies:** None@n + * **User Interaction:** None@n + * + * **Test Procedure:**@n + * | Variation / Step | Description | Test Data | Expected Result | Notes | + * | :--------------: | ---------------------------------------------------------------------------------------- | ----------------------------------------------- | ------------------------------------------------------ | -------------- | + * | 01 | Initialize src with Base64 encoded string 'SGVsbG8=' | src = "SGVsbG8=" | src is correctly populated | Should be successful | + * | 02 | Invoke base64_Decode with src: "SGVsbG8=" and NULL length pointer | input: src = "SGVsbG8=", len = NULL | Returns nullptr | Should Pass | + * | 03 | Validate via EXPECT_EQ that the returned decodedResult is nullptr | output: decodedResult = nullptr | Assertion returns true confirming decodedResult is nullptr | Should be successful | + */ +TEST(Base64DecodeTests, NullLenPointerWithValidInput) { + std::cout << "Entering NullLenPointerWithValidInput test" << std::endl; + + char src[16]; + std::cout << "Assigning Base64 encoded string 'SGVsbG8=' to src" << std::endl; + std::strncpy(src, "SGVsbG8=", sizeof(src)); + + std::cout << "Invoking base64_Decode with src: " << src << " and len pointer: NULL" << std::endl; + unsigned char* decodedResult = base64_Decode(src, NULL); + std::cout << "base64_Decode returned pointer: " << static_cast(decodedResult) << std::endl; + + EXPECT_EQ(decodedResult, nullptr); + + std::cout << "Exiting NullLenPointerWithValidInput test" << std::endl; +} +/** + * @brief Test for proper handling of illegal characters in a Base64 string + * + * This test verifies that the base64_Decode function returns a null pointer and sets decodedLen to 0 when provided with an input string that contains characters not allowed in Base64 encoding. + * + * **Test Group ID:** Basic: 01@n + * **Test Case ID:** 010@n + * **Priority:** High@n + * + * **Pre-Conditions:** None@n + * **Dependencies:** None@n + * **User Interaction:** None@n + * + * **Test Procedure:**@n + * | Variation / Step | Description | Test Data | Expected Result | Notes | + * | :----: | --------- | ---------- | -------------- | ----- | + * | 01 | Assign an invalid Base64 string "Invalid!!" to the src buffer | src = "Invalid!!" | src contains "Invalid!!" correctly | Should be successful | + * | 02 | Invoke base64_Decode with src and the address of decodedLen | input: src = "Invalid!!", decodedLen address; output: decodedResult pointer, decodedLen value | base64_Decode returns nullptr and decodedLen equals 0 | Should Pass | + * | 03 | Validate API behavior by asserting the result pointer and decoded length | EXPECT_EQ(decodedResult, nullptr), EXPECT_EQ(decodedLen, 0) | Both assertions pass confirming proper error handling | Should Pass | + */ +TEST(Base64DecodeTests, InvalidBase64StringIllegalCharacters) { + std::cout << "Entering InvalidBase64StringIllegalCharacters test" << std::endl; + + char src[16]; + std::cout << "Assigning invalid Base64 string 'Invalid!!' to src" << std::endl; + std::strncpy(src, "Invalid!!", sizeof(src)); + + size_t decodedLen = 0; + std::cout << "Invoking base64_Decode with src: " << src << " and address of decodedLen: " << &decodedLen << std::endl; + unsigned char* decodedResult = base64_Decode(src, &decodedLen); + std::cout << "base64_Decode returned pointer: " << static_cast(decodedResult) << " with decodedLen: " << decodedLen << std::endl; + + EXPECT_EQ(decodedResult, nullptr); + EXPECT_EQ(decodedLen, 0); + + if(decodedResult != nullptr) { + free(decodedResult); + } + + std::cout << "Exiting InvalidBase64StringIllegalCharacters test" << std::endl; +} +/** + * @brief Validate that base64_Decode returns nullptr and zero decoded length for a Base64 string with missing padding. + * + * This test verifies that when a valid Base64 string missing the necessary padding is decoded by base64_Decode, the function returns a nullptr and the decoded length remains zero. This ensures the API properly handles input errors related to incorrect padding. + * + * **Test Group ID:** Basic: 01@n + * **Test Case ID:** 011@n + * **Priority:** High@n + * + * **Pre-Conditions:** None@n + * **Dependencies:** None@n + * **User Interaction:** None@n + * + * **Test Procedure:**@n + * | Variation / Step | Description | Test Data | Expected Result | Notes | + * | :----: | --------- | ---------- |-------------- | ----- | + * | 01 | Log entering the test message | None | Console outputs "Entering ValidBase64StringWithIncorrectPadding test" | Should be successful | + * | 02 | Assign a Base64 string with missing padding "SGVsbG8" to src | src = SGVsbG8 | src is correctly assigned with the value "SGVsbG8" | Should be successful | + * | 03 | Invoke base64_Decode with src and pointer to decodedLen | src = SGVsbG8, decodedLen = 0 | Returns nullptr and decodedLen remains 0 | Should Pass | + * | 04 | Validate the returned pointer and decoded length using assertions | decodedResult = nullptr, decodedLen = 0 | EXPECT_EQ assertions pass confirming nullptr and zero length | Should Pass | + * | 05 | Free the decoded memory if it is allocated | decodedResult pointer | Memory is freed if allocated; No action if decodedResult is nullptr | Should be successful | + */ +TEST(Base64DecodeTests, ValidBase64StringWithIncorrectPadding) { + std::cout << "Entering ValidBase64StringWithIncorrectPadding test" << std::endl; + + char src[16]; + std::cout << "Assigning Base64 string with missing padding 'SGVsbG8' to src" << std::endl; + std::strncpy(src, "SGVsbG8", sizeof(src)); + + size_t decodedLen = 0; + std::cout << "Invoking base64_Decode with src: " << src << " and address of decodedLen: " << &decodedLen << std::endl; + unsigned char* decodedResult = base64_Decode(src, &decodedLen); + std::cout << "base64_Decode returned pointer: " << static_cast(decodedResult) << " with decodedLen: " << decodedLen << std::endl; + + EXPECT_EQ(decodedResult, nullptr); + EXPECT_EQ(decodedLen, 0); + + if(decodedResult != nullptr) { + free(decodedResult); + } + + std::cout << "Exiting ValidBase64StringWithIncorrectPadding test" << std::endl; +} +/** + * @brief Test the proper decoding of a valid Base64 encoded string. + * + * This test verifies that the base64_Decode function correctly decodes a valid Base64 encoded input ("TWFu") to the expected output ("Man"). + * It confirms that the function does not throw exceptions, returns a non-null pointer, and produces the correct decoded length and string value. + * + * **Test Group ID:** Basic: 01@n + * **Test Case ID:** 012@n + * **Priority:** High@n + * + * **Pre-Conditions:** None@n + * **Dependencies:** None@n + * **User Interaction:** None@n + * + * **Test Procedure:** + * | Variation / Step | Description | Test Data | Expected Result | Notes | + * | :--------------: | ------------------------------------------------------------------------------------- | ------------------------------------------------------------------ | ----------------------------------------------------------------------------------------- | ------------- | + * | 01 | Initialize the src array with the value "TWFu". | src = "TWFu" | src array contains "TWFu" with proper null termination. | Should be successful | + * | 02 | Invoke base64_Decode with src "TWFu" and srcLen 4. | input: src = "TWFu", srcLen = 4 | Function does not throw an exception and returns a valid pointer with decodedLen updated. | Should Pass | + * | 03 | Validate that the decoded pointer is not null and the decoded length equals 3. | output: decoded pointer, decodedLen = 3 | decoded pointer is not nullptr and decodedLen equals 3. | Should be successful | + * | 04 | Verify that the decoded string equals "Man" and free the allocated memory. | output: decoded string = "Man" | Decoded string matches "Man". | Should be successful | + */ +TEST(Base64DecodeTest, ValidBase64DecodeProperInput) { + std::cout << "Entering ValidBase64DecodeProperInput test" << std::endl; + + char src[10]; + std::cout << "Initializing src with value \"TWFu\"" << std::endl; + strncpy(src, "TWFu", sizeof(src) - 1); + src[sizeof(src) - 1] = '\0'; + + size_t decodedLen = 0; + std::cout << "Calling base64_Decode with src: " << src << ", srcLen: 4" << std::endl; + unsigned char *decoded = nullptr; + EXPECT_NO_THROW(decoded = base64_Decode(src, &decodedLen, 4)); + + std::cout << "Returned pointer: " << static_cast(decoded) << ", decodedLen: " << decodedLen << std::endl; + + EXPECT_NE(decoded, nullptr); + EXPECT_EQ(decodedLen, 3); + std::string result(reinterpret_cast(decoded), decodedLen); + std::cout << "Decoded string: " << result << std::endl; + EXPECT_EQ(result, "Man"); + + // Free the memory if allocated by base64_Decode + if(decoded) { + free(decoded); + decoded = nullptr; + } + + std::cout << "Exiting ValidBase64DecodeProperInput test" << std::endl; +} +/** + * @brief Validate proper decoding of a Base64 string with padding via base64_Decode API. + * + * This test validates that the base64_Decode API correctly decodes a valid Base64 encoded string "U29mdHdhcmU=" with proper padding. + * It verifies that the decoded output length matches the expected value (8), ensures the decoded pointer is not null, + * and confirms that the decoded string matches "Software". + * + * **Test Group ID:** Basic: 01 + * **Test Case ID:** 013 + * **Priority:** High + * + * **Pre-Conditions:** None + * **Dependencies:** None + * **User Interaction:** None + * + * **Test Procedure:** + * | Variation / Step | Description | Test Data | Expected Result | Notes | + * | :----: | --------- | ---------- |-------------- | ----- | + * | 01 | Initialize the source buffer with the Base64 encoded string. | src = "U29mdHdhcmU=" (copied into a char array of size 20) | src is properly initialized with the expected string. | Should be successful | + * | 02 | Invoke base64_Decode API with the source string. | input: src = "U29mdHdhcmU=", srcLen = 12; output: decodedLen pointer | base64_Decode returns a non-null pointer and sets decodedLen to 8. | Should Pass | + * | 03 | Validate the decoded output by converting the buffer to a string. | output: result = "Software", decodedLen = 8 | The decoded string matches "Software". | Should Pass | + * | 04 | Free the allocated memory for the decoded output. | decoded pointer to be freed | Memory is released successfully and decoded pointer is reset to nullptr. | Should be successful | + */ +TEST(Base64DecodeTest, ValidBase64DecodeWithPadding) { + std::cout << "Entering ValidBase64DecodeWithPadding test" << std::endl; + + char src[20]; + std::cout << "Initializing src with value \"U29mdHdhcmU=\"" << std::endl; + strncpy(src, "U29mdHdhcmU=", sizeof(src) - 1); + src[sizeof(src) - 1] = '\0'; + + size_t decodedLen = 0; + std::cout << "Calling base64_Decode with src: " << src << ", srcLen: 12" << std::endl; + unsigned char *decoded = nullptr; + EXPECT_NO_THROW(decoded = base64_Decode(src, &decodedLen, 12)); + + std::cout << "Returned pointer: " << static_cast(decoded) << ", decodedLen: " << decodedLen << std::endl; + + EXPECT_NE(decoded, nullptr); + EXPECT_EQ(decodedLen, 8); + std::string result(reinterpret_cast(decoded), decodedLen); + std::cout << "Decoded string: " << result << std::endl; + EXPECT_EQ(result, "Software"); + + if(decoded) { + free(decoded); + decoded = nullptr; + } + + std::cout << "Exiting ValidBase64DecodeWithPadding test" << std::endl; +} +/** + * @brief Verify that providing an empty Base64 string returns a valid pointer with a decoded length of 0 + * + * This test validates that when an empty string is provided to the base64_Decode function, the function returns a non-null pointer and sets the decoded length to 0. This ensures that the API handles empty inputs gracefully without crashing. + * + * **Test Group ID:** Basic: 01@n + * **Test Case ID:** 014@n + * **Priority:** High@n + * + * **Pre-Conditions:** None@n + * **Dependencies:** None@n + * **User Interaction:** None@n + * + * **Test Procedure:**@n + * | Variation / Step | Description | Test Data | Expected Result | Notes | + * | :----: | --------- | ---------- |-------------- | ----- | + * | 01 | Initialize the source with an empty string and set a non-zero initial value for decodedLen | src = "", decodedLen = 123 | src is empty and decodedLen is initialized | Should be successful | + * | 02 | Call base64_Decode with the empty src and a src length of 0, then verify that the function returns a valid pointer and decodedLen is updated to 0 | input: src = "", input: srcLen = 0, initial decodedLen = 123; output: decoded pointer, updated decodedLen = 0 | Base64 decoding returns a valid pointer and decodedLen equals 0 | Should Pass | + * | 03 | Free the allocated memory for the decoded pointer, if any | decoded pointer | Memory is freed without errors | Should be successful | + */ +TEST(Base64DecodeTest, EmptyBase64String) { + std::cout << "Entering EmptyBase64String test" << std::endl; + + char src[1]; + std::cout << "Initializing src with empty string \"\"" << std::endl; + strncpy(src, "", sizeof(src) - 1); + src[sizeof(src) - 1] = '\0'; + + size_t decodedLen = 123; // arbitrary initial non-zero value + std::cout << "Calling base64_Decode with empty src, srcLen: 0" << std::endl; + unsigned char *decoded = nullptr; + EXPECT_NO_THROW(decoded = base64_Decode(src, &decodedLen, 0)); + + std::cout << "Returned pointer: " << static_cast(decoded) << ", decodedLen: " << decodedLen << std::endl; + + // For empty input, a valid empty pointer is expected; decoded pointer can be non-NULL representing empty data, + // but *len must be 0. + EXPECT_NE(decoded, nullptr); + EXPECT_EQ(decodedLen, 0); + + if(decoded) { + free(decoded); + decoded = nullptr; + } + + std::cout << "Exiting EmptyBase64String test" << std::endl; +} +/** + * @brief Verify that base64_Decode properly handles a NULL source pointer input. + * + * This test verifies that when a NULL source pointer is passed to base64_Decode with a srcLen of 0, the function does not throw any exceptions and returns a null pointer with the decoded length set to 0. This confirms that the API gracefully handles null inputs. + * + * **Test Group ID:** Basic: 01@n + * **Test Case ID:** 015@n + * **Priority:** High@n + * + * **Pre-Conditions:** None@n + * **Dependencies:** None@n + * **User Interaction:** None@n + * + * **Test Procedure:**@n + * | Variation / Step | Description | Test Data | Expected Result | Notes | + * | :--------------: | --------------------------------------------------------------------- | ----------------------------------------------------- | -------------------------------------------------------------- | --------------- | + * | 01 | Initialize decodedLen with 999 and src pointer as NULL | decodedLen = 999, src = NULL | Variables initialized correctly | Should be successful | + * | 02 | Invoke base64_Decode with src as NULL and srcLen as 0 | src = NULL, srcLen = 0, decodedLen initial value = 999 | API does not throw, processes input | Should Pass | + * | 03 | Verify that the returned decoded pointer is nullptr | output: decoded pointer from API | decoded equals nullptr | Should Pass | + * | 04 | Verify that the decoded length is set to 0 | output: decodedLen from API | decodedLen equals 0 | Should Pass | + */ +TEST(Base64DecodeTest, NullSrcPointer) { + std::cout << "Entering NullSrcPointer test" << std::endl; + + size_t decodedLen = 999; // initial non-zero value to see if it gets set to 0 + const char *src = NULL; + std::cout << "Calling base64_Decode with src as NULL and srcLen: 0" << std::endl; + unsigned char *decoded = nullptr; + EXPECT_NO_THROW(decoded = base64_Decode(src, &decodedLen, 0)); + + std::cout << "Returned pointer: " << static_cast(decoded) << ", decodedLen: " << decodedLen << std::endl; + + EXPECT_EQ(decoded, nullptr); + EXPECT_EQ(decodedLen, 0); + + std::cout << "Exiting NullSrcPointer test" << std::endl; +} +/** + * @brief Test the base64_Decode API when the len pointer is NULL + * + * This test verifies that when a NULL pointer is passed for the length parameter to base64_Decode along with a valid source string "TWFu" and a source length of 4, the function does not throw an exception and returns a nullptr. This confirms that the function handles NULL len pointers gracefully. + * + * **Test Group ID:** Basic: 01@n + * **Test Case ID:** 016@n + * **Priority:** High@n + * + * **Pre-Conditions:** None@n + * **Dependencies:** None@n + * **User Interaction:** None@n + * + * **Test Procedure:** + * | Variation / Step | Description | Test Data | Expected Result | Notes | + * | :----: | --------- | ---------- |-------------- | ----- | + * | 01 | Initialize src array with the value "TWFu" ensuring null termination | src = "TWFu", array size = 10 | src properly contains "TWFu" with null termination | Should be successful | + * | 02 | Invoke base64_Decode with len pointer as NULL and srcLen as 4 | input1 = src ("TWFu"), input2 = NULL, input3 = 4 | API should not throw an exception and returns a nullptr | Should Pass | + * | 03 | Validate the returned decoded pointer equals nullptr | decoded = returned pointer | EXPECT_EQ(decoded, nullptr) passes | Should Pass | + */ +TEST(Base64DecodeTest, NullLenPointer) { + std::cout << "Entering NullLenPointer test" << std::endl; + + char src[10]; + std::cout << "Initializing src with value \"TWFu\"" << std::endl; + strncpy(src, "TWFu", sizeof(src) - 1); + src[sizeof(src) - 1] = '\0'; + + std::cout << "Calling base64_Decode with len pointer as NULL and srcLen: 4" << std::endl; + unsigned char *decoded = nullptr; + EXPECT_NO_THROW(decoded = base64_Decode(src, NULL, 4)); + + std::cout << "Returned pointer: " << static_cast(decoded) << std::endl; + EXPECT_EQ(decoded, nullptr); + + std::cout << "Exiting NullLenPointer test" << std::endl; +} +/** + * @brief Verify that the base64_Decode function handles a source length that is too short. + * + * This test checks whether the base64_Decode API correctly returns a nullptr for the decoded buffer and a decoded length of 0 when the provided source length is less than required, ensuring proper handling of invalid input lengths. + * + * **Test Group ID:** Basic: 01@n + * **Test Case ID:** 017@n + * **Priority:** High@n + * + * **Pre-Conditions:** None@n + * **Dependencies:** None@n + * **User Interaction:** None@n + * + * **Test Procedure:**@n + * | Variation / Step | Description | Test Data | Expected Result | Notes | + * | :--------------: | --------------------------------------------------------------------------------- | --------------------------------------------------- | -------------------------------------------------------------------------------- | ------------- | + * | 01 | Initialize src array with the value "TWFu". | src = "TWFu" | src array is correctly initialized with the string "TWFu". | Should be successful | + * | 02 | Call base64_Decode with src, initial decodedLen = 555, and srcLen = 2 (too short). | src = "TWFu", decodedLen = 555, srcLen = 2 | Returned pointer is nullptr and decodedLen is set to 0 with no exception thrown. | Should Pass | + * | 03 | Verify that the returned pointer is nullptr and decodedLen equals 0 using EXPECT. | Returned pointer, decodedLen | The EXPECT_EQ checks confirm that decoded is nullptr and decodedLen is 0. | Should be successful | + */ +TEST(Base64DecodeTest, SrcLenTooShort) { + std::cout << "Entering SrcLenTooShort test" << std::endl; + + char src[10]; + std::cout << "Initializing src with value \"TWFu\"" << std::endl; + strncpy(src, "TWFu", sizeof(src) - 1); + src[sizeof(src) - 1] = '\0'; + + size_t decodedLen = 555; // initial non-zero value + std::cout << "Calling base64_Decode with src: " << src << " and srcLen: 2 (too short)" << std::endl; + unsigned char *decoded = nullptr; + EXPECT_NO_THROW(decoded = base64_Decode(src, &decodedLen, 2)); + + std::cout << "Returned pointer: " << static_cast(decoded) << ", decodedLen: " << decodedLen << std::endl; + + EXPECT_EQ(decoded, nullptr); + EXPECT_EQ(decodedLen, 0); + + std::cout << "Exiting SrcLenTooShort test" << std::endl; +} +/** + * @brief Verify that base64_Decode handles invalid base64 characters correctly + * + * This test case evaluates the handling of invalid characters in a base64 encoded string. + * The function base64_Decode is called with an input containing invalid base64 characters ("??=="). + * The test ensures that no exception is thrown during the call, and that the function returns a null pointer + * while setting the decoded length to 0. + * + * **Test Group ID:** Basic: 01@n + * **Test Case ID:** 018@n + * **Priority:** High@n + * + * **Pre-Conditions:** None@n + * **Dependencies:** None@n + * **User Interaction:** None@n + * + * **Test Procedure:**@n + * | Variation / Step | Description | Test Data | Expected Result | Notes | + * | :----: | --------- | ---------- |-------------- | ----- | + * | 01 | Initialize the src array with the invalid base64 string "??==" | src = "??==", buffer size = 10, initial decodedLen = 321 | src contains "??==" properly terminated with '\0' | Should be successful | + * | 02 | Call base64_Decode with the invalid src and srcLen of 4 | input: src = "??==", srcLen = 4, decodedLen = 321 | Function does not throw any exception and returns a decoded pointer | Should Pass | + * | 03 | Validate that the returned decoded pointer is null | decoded pointer returned from base64_Decode | decoded pointer is nullptr | Should Pass | + * | 04 | Validate that decodedLen is updated to 0 | decodedLen after function call | decodedLen equals 0 | Should Pass | + */ +TEST(Base64DecodeTest, InvalidBase64Characters) { + std::cout << "Entering InvalidBase64Characters test" << std::endl; + + char src[10]; + std::cout << "Initializing src with value \"??==\"" << std::endl; + strncpy(src, "??==", sizeof(src) - 1); + src[sizeof(src) - 1] = '\0'; + + size_t decodedLen = 321; // initial arbitrary value + std::cout << "Calling base64_Decode with src: " << src << ", srcLen: 4" << std::endl; + unsigned char *decoded = nullptr; + EXPECT_NO_THROW(decoded = base64_Decode(src, &decodedLen, 4)); + + std::cout << "Returned pointer: " << static_cast(decoded) << ", decodedLen: " << decodedLen << std::endl; + + EXPECT_EQ(decoded, nullptr); + EXPECT_EQ(decodedLen, 0); + + std::cout << "Exiting InvalidBase64Characters test" << std::endl; +} + +int main(int argc, char **argv) { + ::testing::InitGoogleTest(&argc, argv); + return RUN_ALL_TESTS(); +} diff --git a/baseConversion/test/test_l1_base16.cpp b/baseConversion/test/test_l1_base16.cpp new file mode 100644 index 0000000..bfb4bb9 --- /dev/null +++ b/baseConversion/test/test_l1_base16.cpp @@ -0,0 +1,510 @@ + +/* + * If not stated otherwise in this file or this component's LICENSE file the + * following copyright and licenses apply: + * + * Copyright 2025 RDK Management + * + * 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. + */ + +/** +* @file test_l1_base16.cpp +* @page base16 Level 1 Tests +* +* ## Module's Role +* This module includes Level 1 functional tests (success and failure scenarios). +* This is to ensure that the base16 methods meet the requirements. +* +* **Pre-Conditions:** None @n +* **Dependencies:** None @n +* +*/ + +#include +#include +#include +#include "base16.h" + +/** + * @brief Test base16_Encode with a valid non-empty input array to verify correct hexadecimal conversion + * + * This test case verifies that when base16_Encode is provided with a valid non-empty byte array (representing "ABC"), + * it correctly converts the input to its hexadecimal string equivalent ("414243"). The test ensures that the function call + * does not throw an exception, that the returned pointer is not NULL, and that the resulting string matches the expected output. + * + * **Test Group ID:** Basic: 01@n + * **Test Case ID:** 001@n + * **Priority:** High@n + * + * **Pre-Conditions:** None@n + * **Dependencies:** None@n + * **User Interaction:** None@n + * + * **Test Procedure:** + * | Variation / Step | Description | Test Data | Expected Result | Notes | + * | :--------------: | --------------------------------------------------------------------------- | ------------------------------------------------------------- | ---------------------------------------------- | --------------- | + * | 01 | Initialize test: log entry message and prepare input array | src = {0x41, 0x42, 0x43}, len = 3 | Input array is prepared | Should be successful | + * | 02 | Invoke base16_Encode with the given input | input: src = {0x41, 0x42, 0x43}, len = 3; output: result pointer | No exception thrown; valid result pointer | Should Pass | + * | 03 | Compare the returned result with the expected hexadecimal string "414243" | result pointer, expected = "414243" | result equals "414243" | Should Pass | + * | 04 | Deallocate the allocated memory for result if not NULL | result pointer | Memory is freed successfully | Should be successful | + * | 05 | Log exit message for test completion | None | Exit message logged | Should be successful | + */ +TEST(Base16Encode_ValidNonEmpty, TestCase1) { + std::cout << "Entering Base16Encode_ValidNonEmpty test\n"; + unsigned char src[] = {0x41, 0x42, 0x43}; // "ABC" + size_t len = sizeof(src); + std::cout << "Invoking base16_Encode with src bytes: [0x41, 0x42, 0x43] and len: " << len << "\n"; + + char* result = nullptr; + EXPECT_NO_THROW(result = base16_Encode(src, len)); + std::cout << "Returned string pointer: " << (result ? result : (char*)"NULL") << "\n"; + + // Validate that result is not NULL and matches "414243" + EXPECT_NE(result, nullptr); + std::cout << "Comparing result with expected \"414243\"\n"; + EXPECT_STREQ(result, "414243"); + + // Free the allocated memory if result is not NULL + if(result) { + free(result); + std::cout << "Freed allocated memory for result\n"; + } + std::cout << "Exiting Base16Encode_ValidNonEmpty test\n"; +} +/** + * @brief Verify that base16_Encode returns an empty string for zero-length input. + * + * This test verifies that when a valid non-NULL pointer is provided with a length of zero, + * the base16_Encode function does not throw an exception, returns a non-NULL pointer, + * and produces an empty string. This behavior ensures that the API correctly handles empty input. + * + * **Test Group ID:** Basic: 01@n + * **Test Case ID:** 002@n + * **Priority:** High@n + * + * **Pre-Conditions:** None@n + * **Dependencies:** None@n + * **User Interaction:** None@n + * + * **Test Procedure:** + * | Variation / Step | Description | Test Data | Expected Result | Notes | + * | :--------------: | --------------------------------------------------------------------------- | ------------------------------------------------------------- | ---------------------------------------------------------------------------------------- | ----------------- | + * | 01 | Initialize valid pointer and set input length to zero | dummy = 0, src = address of dummy, len = 0 | Variables properly initialized | Should be successful | + * | 02 | Invoke base16_Encode with valid pointer and zero length | input: src = &dummy, len = 0 | No exception thrown and valid non-NULL result pointer returned | Should Pass | + * | 03 | Validate that the returned string is empty | output: result, expected output = "" | Function returns a non-NULL pointer with an empty string | Should Pass | + * | 04 | Free allocated memory for result | output: result pointer, free(result) | Memory freed without errors | Should be successful | + */ +TEST(Base16Encode_ValidEmpty, TestCase2) { + std::cout << "Entering Base16Encode_ValidEmpty test\n"; + // Provide a valid non-NULL pointer even though there is no data to encode. + unsigned char dummy = 0; + unsigned char *src = &dummy; + size_t len = 0; + std::cout << "Invoking base16_Encode with valid pointer and len: " << len << "\n"; + + char* result = nullptr; + EXPECT_NO_THROW(result = base16_Encode(src, len)); + std::cout << "Returned string pointer: " << (result ? result : (char*)"NULL") << "\n"; + + // Validate that result is not NULL and is an empty string + EXPECT_NE(result, nullptr); + std::cout << "Comparing result with expected empty string \"\"\n"; + EXPECT_STREQ(result, ""); + + if(result) { + free(result); + std::cout << "Freed allocated memory for result\n"; + } + std::cout << "Exiting Base16Encode_ValidEmpty test\n"; +} +/** + * @brief Verify that base16_Encode returns a NULL pointer when provided with a NULL input parameter. + * + * This test checks the behavior of the base16_Encode API when the input source pointer is NULL. + * The function is expected to handle the invalid input gracefully by returning a NULL pointer. + * + * **Test Group ID:** Basic: 01@n + * **Test Case ID:** 003@n + * **Priority:** High@n + * + * **Pre-Conditions:** None@n + * **Dependencies:** None@n + * **User Interaction:** None@n + * + * **Test Procedure:** + * | Variation / Step | Description | Test Data | Expected Result | Notes | + * | :--------------: | ---------------------------------------------------------------------- | ----------------------------------- | ---------------------------------------------------------------------------- | ----------- | + * | 01 | Invoke base16_Encode with NULL as the source pointer and length 5 | src = NULL, len = 5, output = result | Expect the API to return a NULL pointer and the assertion EXPECT_EQ to pass | Should Fail | + */ +TEST(Base16Encode_NegativeNullInput, TestCase3) { + std::cout << "Entering Base16Encode_NegativeNullInput test\n"; + size_t len = 5; + std::cout << "Invoking base16_Encode with src: NULL and len: " << len << "\n"; + + char* result = nullptr; + EXPECT_NO_THROW(result = base16_Encode(NULL, len)); + std::cout << "Returned string pointer: " << (result ? result : (char*)"NULL") << "\n"; + + // Expecting a NULL pointer due to invalid input parameter. + EXPECT_EQ(result, nullptr); + std::cout << "Exiting Base16Encode_NegativeNullInput test\n"; +} +/** + * @brief Verify that base16_Encode returns a NULL pointer when an invalid length is provided. + * + * This test case verifies that the base16_Encode function handles an invalid input combination properly. + * Specifically, it tests the function with a source byte array of three characters ("ABC") and an + * incorrect length parameter (1), which should result in an error condition by returning a NULL pointer. + * + * **Test Group ID:** Basic: 01@n + * **Test Case ID:** 004@n + * **Priority:** High@n + * + * **Pre-Conditions:** None@n + * **Dependencies:** None@n + * **User Interaction:** None@n + * + * **Test Procedure:**@n + * | Variation / Step | Description | Test Data | Expected Result | Notes | + * | :----: | --------- | ---------- |-------------- | ----- | + * | 01 | Initialize test inputs including source byte array and invalid length. | src = {0x41, 0x42, 0x43}, len = 1, result = uninitialized | Variables are initialized correctly. | Should be successful | + * | 02 | Invoke base16_Encode API and validate that no exception is thrown and the returned pointer is NULL. | input: src = {0x41, 0x42, 0x43}, input: len = 1, output: result = nullptr | Function returns a NULL pointer indicating an error for invalid parameter combination, assertion passes. | Should Fail | + */ +TEST(Base16Encode_NegativeWrongLength, TestCase4) { + std::cout << "Entering Base16Encode_NegativeWrongLength test\n"; + + unsigned char src[] = {0x41, 0x42, 0x43}; // "ABC" + size_t len = 1; + std::cout << "Invoking base16_Encode with src bytes: [0x41, 0x42, 0x43] and len: " << len << "\n"; + + char* result = nullptr; + EXPECT_NO_THROW(result = base16_Encode(src, len)); + std::cout << "Returned string pointer: " << (result ? result : (char*)"NULL") << "\n"; + + // Expected to return an error i.e. NULL pointer due to invalid parameter combination. + EXPECT_EQ(result, nullptr); + std::cout << "Exiting Base16Encode_NegativeWrongLength test\n"; +} +/** + * @brief Validate base16_Encode correctly encodes a full range of byte values into its hexadecimal string representation + * + * This test validates that the base16_Encode function properly encodes an array containing all 256 possible byte values (0-255) into a 512-character uppercase hexadecimal string. It ensures that the memory is allocated as expected, the encoding is accurate, and the output string matches the expected result generated within the test. + * + * **Test Group ID:** Basic: 01@n + * **Test Case ID:** 005@n + * **Priority:** High@n + * + * **Pre-Conditions:** None@n + * **Dependencies:** None@n + * **User Interaction:** None@n + * + * **Test Procedure:** + * | Variation / Step | Description | Test Data | Expected Result | Notes | + * | :--------------: | ----------------------------------------------------------------------------------------------------------------------- | -------------------------------------------------------------------------- | ---------------------------------------------------------------------------------------------------------- | -------------- | + * | 01 | Initialize source array with ascending byte values from 0 to 255 and set length to 256 | src = array{0,1,...,255}, len = 256 | Array is correctly initialized with values 0-255 | Should be successful | + * | 02 | Invoke base16_Encode using the initialized array and length | input: src = array{0,1,...,255}, len = 256 | API returns a non-NULL string pointer containing the encoded hexadecimal string | Should Pass | + * | 03 | Generate the expected hexadecimal string by converting each byte to its two-digit uppercase hex representation | For each byte i: value = i in src, using format "%02X" for conversion | Expected string is a 512-character string representing each byte in uppercase hexadecimal format | Should be successful | + * | 04 | Compare the returned result from base16_Encode to the generated expected hexadecimal string | result = output of base16_Encode, expected = generated expected string | Test passes if result is non-NULL and exactly matches the expected hexadecimal string | Should Pass | + * | 05 | Free the allocated memory for the returned result | result pointer | Memory is successfully freed without any errors | Should be successful | + */ +TEST(Base16Encode_ValidAllBytes, TestCase5) { + std::cout << "Entering Base16Encode_ValidAllBytes test\n"; + unsigned char src[256]; + for (size_t i = 0; i < 256; i++) { + src[i] = static_cast(i); + } + size_t len = 256; + std::cout << "Invoking base16_Encode with an array of 256 ascending byte values and len: " << len << "\n"; + + char* result = nullptr; + EXPECT_NO_THROW(result = base16_Encode(src, len)); + if(result) { + std::cout << "Returned string pointer is non-NULL\n"; + } else { + std::cout << "Returned string pointer is NULL\n"; + } + + // Generate the expected string which is 512 hex characters representing each byte in two-digit uppercase hex. + char expected[513]; + expected[512] = '\0'; + for (size_t i = 0; i < 256; i++) { + char buf[3]; + std::snprintf(buf, sizeof(buf), "%02X", static_cast(src[i])); + // Use strncpy to copy 2 characters into expected array at correct offset. + std::strncpy(&expected[i*2], buf, 2); + std::cout << "Byte " << i << " value: " << static_cast(src[i]) << " encoded as: " << buf << "\n"; + } + std::cout << "Expected encoded string: " << expected << "\n"; + + // Check that result is not NULL and matches the expected hex string. + EXPECT_NE(result, nullptr); + std::cout << "Comparing returned string with expected hex encoded string.\n"; + EXPECT_STREQ(result, expected); + + if(result) { + free(result); + std::cout << "Freed allocated memory for result\n"; + } + std::cout << "Exiting Base16Encode_ValidAllBytes test\n"; +} +/** + * @brief Verify that a valid single byte hexadecimal string is correctly decoded. + * + * This test validates that the base16_Decode function correctly converts a valid single byte hexadecimal string ("4A") to its corresponding byte value. + * It also ensures that the output length is updated appropriately (from the initial value of 100 to 1), and that the returned pointer is not null. + * + * **Test Group ID:** Basic: 01@n + * **Test Case ID:** 006@n + * **Priority:** High@n + * + * **Pre-Conditions:** None@n + * **Dependencies:** None@n + * **User Interaction:** None@n + * + * **Test Procedure:** + * | Variation / Step | Description | Test Data | Expected Result | Notes | + * | :----: | ----------------------------------------------------------------------------------------------- | ----------------------------------------------------- | ----------------------------------------------------------------------------- | ----------- | + * | 01 | Prepare a valid single byte hex input and invoke the base16_Decode API. | src = "4A", srcLen = 2, resultLen (initial) = 100 | Returns a non-null pointer, resultLen updated to 1, decoded byte equals 0x4A | Should Pass | + */ +TEST(Base16DecodeTest, ValidSingleByteHex) { + std::cout << "Entering ValidSingleByteHex test" << std::endl; + + char src[3] = {0}; + strncpy(src, "4A", sizeof(src)-1); + size_t srcLen = 2; + size_t resultLen = 100; // initialize to a non-zero value to check update + + std::cout << "Invoking base16_Decode with srcPtr: " << src + << ", srcLen: " << srcLen + << ", len pointer address: " << &resultLen << std::endl; + unsigned char *decoded = base16_Decode(src, srcLen, &resultLen); + std::cout << "Returned pointer: " << static_cast(decoded) + << ", resultLen: " << resultLen << std::endl; + + EXPECT_NE(decoded, nullptr); + EXPECT_EQ(resultLen, 1); + if (decoded) { + std::cout << "Decoded byte value: 0x" << std::hex << static_cast(decoded[0]) << std::dec << std::endl; + EXPECT_EQ(decoded[0], 0x4A); + } + + std::cout << "Exiting ValidSingleByteHex test" << std::endl; +} +/** + * @brief Verifies that base16_Decode correctly decodes a valid multi-byte hex encoded string. + * + * This test validates the base16_Decode API by providing a valid multi-byte hexadecimal string "48656C6C6F" as input. + * It verifies that the function returns a non-null pointer, updates the result length to the expected value, and each decoded byte matches the expected ASCII representation for "Hello". + * + * **Test Group ID:** Basic: 01@n + * **Test Case ID:** 007@n + * **Priority:** High@n + * + * **Pre-Conditions:** None@n + * **Dependencies:** None@n + * **User Interaction:** None@n + * + * **Test Procedure:** + * | Variation / Step | Description | Test Data | Expected Result | Notes | + * | :----: | --------- | ---------- |-------------- | ----- | + * | 01 | Initialize input parameters for the test. | src = "48656C6C6F", srcLen = 10, resultLen = 100 | Variables initialized as expected. | Should be successful | + * | 02 | Invoke base16_Decode with the initialized inputs. | input: src = "48656C6C6F", srcLen = 10, resultLen pointer = address of resultLen | Returned decoded pointer is not nullptr. | Should Pass | + * | 03 | Verify the result length after decoding. | resultLen updated by API | resultLen equals 5. | Should Pass | + * | 04 | Validate each byte of the decoded output against expected values. | decoded bytes, expected bytes = 0x48,0x65,0x6C,0x6C,0x6F | Each decoded byte matches the corresponding expected value. | Should Pass | + */ +TEST(Base16DecodeTest, ValidMultiByteHex) { + std::cout << "Entering ValidMultiByteHex test" << std::endl; + + char src[20] = {0}; + strncpy(src, "48656C6C6F", sizeof(src)-1); + size_t srcLen = 10; + size_t resultLen = 100; + + std::cout << "Invoking base16_Decode with srcPtr: " << src + << ", srcLen: " << srcLen + << ", len pointer address: " << &resultLen << std::endl; + unsigned char *decoded = base16_Decode(src, srcLen, &resultLen); + std::cout << "Returned pointer: " << static_cast(decoded) + << ", resultLen: " << resultLen << std::endl; + + EXPECT_NE(decoded, nullptr); + EXPECT_EQ(resultLen, 5); + unsigned char expected[5] = {0x48, 0x65, 0x6C, 0x6C, 0x6F}; + for (size_t i = 0; i < resultLen; ++i) { + std::cout << "Byte " << i << " of decoded output: 0x" + << std::hex << static_cast(decoded[i]) << std::dec << std::endl; + EXPECT_EQ(decoded[i], expected[i]); + } + + std::cout << "Exiting ValidMultiByteHex test" << std::endl; +} +/** + * @brief Validate base16_Decode function behavior with an odd-length hexadecimal string + * + * This test verifies that the base16_Decode function correctly handles an input hexadecimal string of odd length, which is considered invalid. The test ensures the function returns a nullptr and resets the output length to 0. + * + * **Test Group ID:** Basic: 01@n + * **Test Case ID:** 008@n + * **Priority:** High@n + * + * **Pre-Conditions:** None@n + * **Dependencies:** None@n + * **User Interaction:** None@n + * + * **Test Procedure:**@n + * | Variation / Step | Description | Test Data | Expected Result | Notes | + * | :----: | --------- | ---------- |-------------- | ----- | + * | 01 | Initialize input with odd-length hex string "ABC" and call base16_Decode | src = "ABC", srcLen = 3, resultLen = 100 | Decoded pointer is nullptr and resultLen is 0 | Should Fail | + */ +TEST(Base16DecodeTest, OddLengthHexString) { + std::cout << "Entering OddLengthHexString test" << std::endl; + + char src[10] = {0}; + strncpy(src, "ABC", sizeof(src)-1); + size_t srcLen = 3; + size_t resultLen = 100; + + std::cout << "Invoking base16_Decode with srcPtr: " << src + << ", srcLen: " << srcLen + << ", len pointer address: " << &resultLen << std::endl; + unsigned char *decoded = base16_Decode(src, srcLen, &resultLen); + std::cout << "Returned pointer: " << static_cast(decoded) + << ", resultLen: " << resultLen << std::endl; + + EXPECT_EQ(decoded, nullptr); + EXPECT_EQ(resultLen, 0); + + std::cout << "Exiting OddLengthHexString test" << std::endl; +} +/** + * @brief Test base16_Decode API with an empty input string + * + * This test validates that base16_Decode returns a non-null pointer and updates the result length to 0 when provided with an empty input string. It ensures proper handling of an edge case where no data is available to decode. + * + * **Test Group ID:** Basic: 01@n + * **Test Case ID:** 009@n + * **Priority:** High@n + * + * **Pre-Conditions:** None@n + * **Dependencies:** None@n + * **User Interaction:** None@n + * + * **Test Procedure:** + * | Variation / Step | Description | Test Data | Expected Result | Notes | + * | :----: | --------- | ---------- |-------------- | ----- | + * | 01 | Initialize input data with an empty string and set length parameters | src = "", srcLen = 0, resultLen = 100 | Input parameters are correctly initialized | Should be successful | + * | 02 | Invoke base16_Decode and verify that the decoded pointer is not null and resultLen is updated to 0 | src = "", srcLen = 0, &resultLen provided | decoded pointer is not nullptr, resultLen equals 0, assertions pass | Should Pass | + */ +TEST(Base16DecodeTest, EmptyInputString) { + std::cout << "Entering EmptyInputString test" << std::endl; + + char src[2] = {0}; + strncpy(src, "", sizeof(src)-1); + size_t srcLen = 0; + size_t resultLen = 100; + + std::cout << "Invoking base16_Decode with srcPtr: \"" << src << "\"" + << ", srcLen: " << srcLen + << ", len pointer address: " << &resultLen << std::endl; + unsigned char *decoded = base16_Decode(src, srcLen, &resultLen); + std::cout << "Returned pointer: " << static_cast(decoded) + << ", resultLen: " << resultLen << std::endl; + + EXPECT_NE(decoded, nullptr); + EXPECT_EQ(resultLen, 0); + + std::cout << "Exiting EmptyInputString test" << std::endl; +} +/** + * @brief Test the base16_Decode API with a null source pointer. + * + * This test verifies that when a null pointer is passed as the source for decoding, + * the base16_Decode API returns a null pointer and correctly sets the result length to zero. + * It ensures that the API handles invalid input gracefully. + * + * **Test Group ID:** Basic: 01@n + * **Test Case ID:** 010@n + * **Priority:** High@n + * + * **Pre-Conditions:** None@n + * **Dependencies:** None@n + * **User Interaction:** None@n + * + * **Test Procedure:** + * | Variation / Step | Description | Test Data | Expected Result | Notes | + * | :----: | --------- | ---------- |-------------- | ----- | + * | 01 | Invoke base16_Decode with a null source pointer | input: src = nullptr, srcLen = 0, resultLen = 100 | Returns a null pointer and resultLen is set to 0 | Should Pass | + */ +TEST(Base16DecodeTest, NullSrcPtr) { + std::cout << "Entering NullSrcPtr test" << std::endl; + + const char *src = nullptr; + size_t srcLen = 0; + size_t resultLen = 100; + + std::cout << "Invoking base16_Decode with srcPtr: " << src + << " (NULL), srcLen: " << srcLen + << ", len pointer address: " << &resultLen << std::endl; + unsigned char *decoded = base16_Decode(src, srcLen, &resultLen); + std::cout << "Returned pointer: " << static_cast(decoded) + << ", resultLen: " << resultLen << std::endl; + + EXPECT_EQ(decoded, nullptr); + EXPECT_EQ(resultLen, 0); + + std::cout << "Exiting NullSrcPtr test" << std::endl; +} +/** + * @brief Verify that base16_Decode returns nullptr when the len pointer parameter is NULL + * + * This test verifies that the base16_Decode API correctly handles a NULL length pointer by returning a nullptr. + * It checks the proper initialization of the input parameters, invokes the API with a NULL len pointer, and asserts that the function returns a nullptr. + * + * **Test Group ID:** Basic: 01@n + * **Test Case ID:** 011@n + * **Priority:** High@n + * + * **Pre-Conditions:** None@n + * **Dependencies:** None@n + * **User Interaction:** None@n + * + * **Test Procedure:** + * | Variation / Step | Description | Test Data | Expected Result | Notes | + * | :--------------: | ----------------------------------------------------------- | ----------------------------------------------------- | ---------------------------------------------------------- | -------------- | + * | 01 | Setup test input variables, initialize src and srcLen | input: src = "4A", srcLen = 2, len pointer = NULL | Input parameters successfully initialized | Should be successful | + * | 02 | Invoke base16_Decode API with provided input | input: src = "4A", srcLen = 2, len pointer = NULL | API returns nullptr due to NULL len pointer handling | Should Pass | + * | 03 | Assert that the returned value is nullptr using EXPECT_EQ | output: decoded pointer value = nullptr | EXPECT_EQ(decoded, nullptr) passes | Should be successful | + */ +TEST(Base16DecodeTest, NullLenPointer) { + std::cout << "Entering NullLenPointer test" << std::endl; + + char src[3] = {0}; + strncpy(src, "4A", sizeof(src)-1); + size_t srcLen = 2; + + std::cout << "Invoking base16_Decode with srcPtr: " << src + << ", srcLen: " << srcLen + << ", len pointer: NULL" << std::endl; + unsigned char *decoded = base16_Decode(src, srcLen, nullptr); + std::cout << "Returned pointer: " << static_cast(decoded) << std::endl; + + EXPECT_EQ(decoded, nullptr); + + std::cout << "Exiting NullLenPointer test" << std::endl; +} + +int main(int argc, char **argv) { + ::testing::InitGoogleTest(&argc, argv); + return RUN_ALL_TESTS(); +} diff --git a/closedcaptions/test/test_l1_CCTrackInfo.cpp b/closedcaptions/test/test_l1_CCTrackInfo.cpp new file mode 100644 index 0000000..810cd4c --- /dev/null +++ b/closedcaptions/test/test_l1_CCTrackInfo.cpp @@ -0,0 +1,81 @@ + +/* + * If not stated otherwise in this file or this component's LICENSE file the + * following copyright and licenses apply: + * + * Copyright 2025 RDK Management + * + * 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. + */ + +/** +* @file test_l1_CCTrackInfo.cpp +* @page CCTrackInfo Level 1 Tests +* +* ## Module's Role +* This module includes Level 1 functional tests (success and failure scenarios). +* This is to ensure that the CCTrackInfo methods meet the requirements. +* +* **Pre-Conditions:** None @n +* **Dependencies:** None @n +* +*/ + +#include +#include +#include +#include "CCTrackInfo.h" + + +// Test Case: Verify default constructor initializes instreamId and language without exceptions +/** + * @brief Verify that default CCTrackInfo constructor initializes instreamId and language members to empty strings without throwing any exceptions. + * + * This test creates an instance of CCTrackInfo using its default constructor and verifies that the members instreamId and language are initialized as empty strings. It ensures that the construction process does not throw any exceptions and that the object's default state is valid. + * + * **Test Group ID:** Basic: 01@n + * **Test Case ID:** 001@n + * **Priority:** High@n + * @n + * **Pre-Conditions:** None@n + * **Dependencies:** None@n + * **User Interaction:** None@n + * @n + * **Test Procedure:**@n + * | Variation / Step | Description | Test Data | Expected Result | Notes | + * | :----: | --------- | ---------- |-------------- | ----- | + * | 01 | Invoke default constructor of CCTrackInfo and verify instreamId and language are empty strings | input: none, output: instreamId = "", language = "" | Default constructed object has instreamId = "" and language = "" verified using EXPECT_EQ | Should Pass | + */ +TEST(CCTrackInfo, VerifyDefaultConstructorInitializesInstreamIdAndLanguageWithoutExceptions) { + std::cout << "Entering VerifyDefaultConstructorInitializesInstreamIdAndLanguageWithoutExceptions test" << std::endl; + + // Invoke the default constructor of CCTrackInfo + std::cout << "Invoking CCTrackInfo default constructor" << std::endl; + CCTrackInfo ccTrackInfo; + std::cout << "After construction: instreamId = \"" << ccTrackInfo.instreamId << "\", language = \"" << ccTrackInfo.language << "\"" << std::endl; + + // Debug logs for expected default values from getters (here using direct access members) + std::cout << "Retrieved value of instreamId: \"" << ccTrackInfo.instreamId << "\"" << std::endl; + std::cout << "Retrieved value of language: \"" << ccTrackInfo.language << "\"" << std::endl; + + // Validate that the default constructed values are empty strings + EXPECT_EQ(ccTrackInfo.instreamId, ""); + EXPECT_EQ(ccTrackInfo.language, ""); + + std::cout << "Exiting VerifyDefaultConstructorInitializesInstreamIdAndLanguageWithoutExceptions test" << std::endl; +} + +int main(int argc, char **argv) { + ::testing::InitGoogleTest(&argc, argv); + return RUN_ALL_TESTS(); +} diff --git a/drm/test/test_l1_DrmSessionFactory.cpp b/drm/test/test_l1_DrmSessionFactory.cpp new file mode 100644 index 0000000..c77b7d9 --- /dev/null +++ b/drm/test/test_l1_DrmSessionFactory.cpp @@ -0,0 +1,189 @@ + +/* + * If not stated otherwise in this file or this component's LICENSE file the + * following copyright and licenses apply: + * + * Copyright 2025 RDK Management + * + * 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. + */ + +/** +* @file test_l1_DrmSessionFactory.cpp +* @page DrmSessionFactory Level 1 Tests +* +* ## Module's Role +* This module includes Level 1 functional tests (success and failure scenarios). +* This is to ensure that the DrmSessionFactory methods meet the requirements. +* +* **Pre-Conditions:** None @n +* **Dependencies:** None @n +* +*/ + +#include +#include +#include +#include "DrmSessionFactory.h" + +/** + * @brief Validate that a valid DrmSession is created when using a valid DrmHelper and valid DrmCallbacks. + * + * This test verifies that DrmSessionFactory::GetDrmSession returns a non-null DrmSession pointer when supplied + * with a valid DrmHelper instance and a valid DrmCallbacks implementation. It checks the proper instantiation of + * the session and the retrieval of the key system from the session. + * + * **Test Group ID:** Basic: 01 + * **Test Case ID:** 001 + * **Priority:** High + * + * **Pre-Conditions:** None + * **Dependencies:** None + * **User Interaction:** None + * + * **Test Procedure:** + * | Variation / Step | Description | Test Data | Expected Result | Notes | + * | :----: | --------- | ---------- |-------------- | ----- | + * | 01 | Create a valid DrmHelper instance using default constructor | validDrmHelper = instance created using std::make_shared() | Instance created with a valid pointer | Should be successful | + * | 02 | Create a valid DrmCallbacks instance using dummy implementation | drmCallbacksInstance = instance of DummyDrmCallbacks; address valid | Instance created with a valid address | Should be successful | + * | 03 | Invoke DrmSessionFactory::GetDrmSession with valid DrmHelper and DrmCallbacks | validDrmHelper = valid instance pointer, drmCallbacksInstance = pointer to instance | Return value is a non-null DrmSession pointer | Should Pass | + * | 04 | Retrieve the key system from the DrmSession if session is valid | session pointer from previous step | Key system successfully retrieved from session | Should be successful | + */ +TEST(DrmSessionFactory, ValidDrmHelperValidDrmCallbacks) { + std::cout << "Entering ValidDrmHelperValidDrmCallbacks test" << std::endl; + + // Create a valid DrmHelper instance (assuming default constructor is available) + std::shared_ptr validDrmHelper = std::make_shared(); + std::cout << "Created valid DrmHelper instance at address: " << validDrmHelper.get() << std::endl; + + // Create a valid DrmCallbacks instance using a local dummy implementation. + class DummyDrmCallbacks : public DrmCallbacks { + public: + void Individualization(const std::string &payload) override { + std::cout << "DummyDrmCallbacks::Individualization invoked with payload: " << payload << std::endl; + } + void LicenseRenewal(std::shared_ptr drmHelper, void* userData) override { + std::cout << "DummyDrmCallbacks::LicenseRenewal invoked with drmHelper address: " << drmHelper.get() + << " and userData: " << userData << std::endl; + } + } drmCallbacksInstance; + std::cout << "Created valid DrmCallbacks instance at address: " << &drmCallbacksInstance << std::endl; + + std::cout << "Invoking DrmSessionFactory::GetDrmSession with valid DrmHelper and valid DrmCallbacks" << std::endl; + DrmSession* session = DrmSessionFactory::GetDrmSession(validDrmHelper, &drmCallbacksInstance); + std::cout << "DrmSessionFactory::GetDrmSession returned pointer: " << session << std::endl; + + EXPECT_NE(session, nullptr); + if (session) { + std::string keySystem = session->getKeySystem(); + std::cout << "Retrieved key system from DrmSession: " << keySystem << std::endl; + } + + std::cout << "Exiting ValidDrmHelperValidDrmCallbacks test" << std::endl; +} +/** + * @brief Validate GetDrmSession behavior with a null DrmHelper and a valid DrmCallbacks instance + * + * This test ensures that the DrmSessionFactory::GetDrmSession method correctly handles a scenario where the DrmHelper pointer is null, + * even when provided with a valid DrmCallbacks instance. The expected behavior is that the function will return a null session pointer, + * thereby preventing the creation of an invalid or unintended DRM session. + * + * **Test Group ID:** Basic: 01@n + * **Test Case ID:** 002@n + * **Priority:** High@n + * + * **Pre-Conditions:** None@n + * **Dependencies:** None@n + * **User Interaction:** None@n + * + * **Test Procedure:** + * | Variation / Step | Description | Test Data | Expected Result | Notes | + * | :----: | --------------------------------------------------------- | --------------------------------------------------------------------------------------------------- | -------------------------------------------------- | ----------------- | + * | 01 | Create a nullptr for DrmHelper | DrmHelper = nullptr | DrmHelper pointer is null | Should be successful | + * | 02 | Create a valid DrmCallbacks instance using a dummy implementation | drmCallbacksInstance = DummyDrmCallbacks instance, address provided by local scope | DrmCallbacks instance is successfully created | Should be successful | + * | 03 | Invoke DrmSessionFactory::GetDrmSession with the above instances | input: DrmHelper = nullptr, drmCallbacks = address of drmCallbacksInstance; output: session pointer | Returns nullptr session pointer as per expectation | Should Pass | + */ +TEST(DrmSessionFactory, NullDrmHelperValidDrmCallbacks) { + std::cout << "Entering NullDrmHelperValidDrmCallbacks test" << std::endl; + + // Create a nullptr for DrmHelper + std::shared_ptr nullDrmHelper = nullptr; + std::cout << "Created null DrmHelper instance." << std::endl; + + // Create a valid DrmCallbacks instance using a local dummy implementation. + class DummyDrmCallbacks : public DrmCallbacks { + public: + void Individualization(const std::string &payload) override { + std::cout << "DummyDrmCallbacks::Individualization invoked with payload: " << payload << std::endl; + } + void LicenseRenewal(std::shared_ptr drmHelper, void* userData) override { + std::cout << "DummyDrmCallbacks::LicenseRenewal invoked with drmHelper address: " + << (drmHelper ? drmHelper.get() : nullptr) + << " and userData: " << userData << std::endl; + } + } drmCallbacksInstance; + std::cout << "Created valid DrmCallbacks instance at address: " << &drmCallbacksInstance << std::endl; + + std::cout << "Invoking DrmSessionFactory::GetDrmSession with null DrmHelper and valid DrmCallbacks" << std::endl; + DrmSession* session = DrmSessionFactory::GetDrmSession(nullDrmHelper, &drmCallbacksInstance); + std::cout << "DrmSessionFactory::GetDrmSession returned pointer: " << session << std::endl; + + EXPECT_EQ(session, nullptr); + + std::cout << "Exiting NullDrmHelperValidDrmCallbacks test" << std::endl; +} +/** + * @brief Test that GetDrmSession returns nullptr when provided with a valid DrmHelper and null DrmCallbacks + * + * This test verifies that the DrmSessionFactory::GetDrmSession method correctly handles a scenario where a valid DrmHelper instance is provided but the DrmCallbacks pointer is null, ensuring that the API returns a null pointer as expected. + * + * **Test Group ID:** Basic: 01@n + * **Test Case ID:** 003@n + * **Priority:** High@n + * + * **Pre-Conditions:** None@n + * **Dependencies:** None@n + * **User Interaction:** None@n + * + * **Test Procedure:**@n + * | Variation / Step | Description | Test Data | Expected Result | Notes | + * | :----: | --------- | ---------- | -------------- | ----- | + * | 01 | Create a valid DrmHelper instance using its default constructor | validDrmHelper = std::make_shared() | A valid DrmHelper instance is created | Should be successful | + * | 02 | Set DrmCallbacks pointer to nullptr | nullDrmCallbacks = nullptr | DrmCallbacks pointer is set to null | Should be successful | + * | 03 | Invoke DrmSessionFactory::GetDrmSession with the valid DrmHelper and null DrmCallbacks | validDrmHelper, nullDrmCallbacks = nullptr | DrmSession pointer returned is nullptr | Should Pass | + * | 04 | Verify the returned DrmSession pointer is nullptr using EXPECT_EQ | session = GetDrmSession(validDrmHelper, nullDrmCallbacks) | Assertion passes confirming session is nullptr | Should Pass | + */ +TEST(DrmSessionFactory, ValidDrmHelperNullDrmCallbacks) { + std::cout << "Entering ValidDrmHelperNullDrmCallbacks test" << std::endl; + + // Create a valid DrmHelper instance (assuming default constructor is available) + std::shared_ptr validDrmHelper = std::make_shared(); + std::cout << "Created valid DrmHelper instance at address: " << validDrmHelper.get() << std::endl; + + // Use a nullptr for DrmCallbacks + DrmCallbacks* nullDrmCallbacks = nullptr; + std::cout << "Using null DrmCallbacks instance." << std::endl; + + std::cout << "Invoking DrmSessionFactory::GetDrmSession with valid DrmHelper and null DrmCallbacks" << std::endl; + DrmSession* session = DrmSessionFactory::GetDrmSession(validDrmHelper, nullDrmCallbacks); + std::cout << "DrmSessionFactory::GetDrmSession returned pointer: " << session << std::endl; + + EXPECT_EQ(session, nullptr); + + std::cout << "Exiting ValidDrmHelperNullDrmCallbacks test" << std::endl; +} + +int main(int argc, char **argv) { + ::testing::InitGoogleTest(&argc, argv); + return RUN_ALL_TESTS(); +} diff --git a/drm/test/test_l1_DrmUtils.cpp b/drm/test/test_l1_DrmUtils.cpp new file mode 100644 index 0000000..3fd4e4e --- /dev/null +++ b/drm/test/test_l1_DrmUtils.cpp @@ -0,0 +1,959 @@ + +/* + * If not stated otherwise in this file or this component's LICENSE file the + * following copyright and licenses apply: + * + * Copyright 2025 RDK Management + * + * 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. + */ + +/** +* @file test_l1_DrmUtils.cpp +* @page DrmUtils Level 1 Tests +* +* ## Module's Role +* This module includes Level 1 functional tests (success and failure scenarios). +* This is to ensure that the DrmUtils methods meet the requirements. +* +* **Pre-Conditions:** None @n +* **Dependencies:** None @n +* +*/ + +#include +#include +#include +#include "DrmUtils.h" + +/** + * @brief Verify that the convertEndianness function correctly converts a valid 16-byte input array by swapping bytes as expected. + * + * This test checks whether the DrmUtils::convertEndianness function handles a valid pointer to a 16-byte input array and produces the reversed endianness output without throwing an exception. The test sets up the original and destination arrays, invokes the function, and confirms that each byte in the destination array matches the manually computed expected result. + * + * **Test Group ID:** Basic: 01@n + * **Test Case ID:** 001@n + * **Priority:** High@n + * + * **Pre-Conditions:** None@n + * **Dependencies:** None@n + * **User Interaction:** None@n + * + * **Test Procedure:**@n + * | Variation / Step | Description | Test Data | Expected Result | Notes | + * | :----: | --------- | ---------- |-------------- | ----- | + * | 01 | Prepare the original input array with 16 bytes using strncpy from a predefined source string. | original = {0}, origSource = "\x01\x02\x03\x04\x05\x06\x07\x08\x09\x0A\x0B\x0C\x0D\x0E\x0F\x10" | Original array correctly set with byte values from the source string. | Should be successful | + * | 02 | Prepare the destination array (guidBytes) initialized to zero for storing the converted output. | guidBytes = {0} | Destination array allocated and initialized to zero. | Should be successful | + * | 03 | Invoke the DrmUtils::convertEndianness function with valid pointers for the original and destination arrays, ensuring no exceptions are thrown. | input: original (16 bytes), output: guidBytes (initially all zeros) | Function call does not throw an exception. | Should Pass | + * | 04 | Compare each element in the guidBytes array against the expected output array after conversion. | expected = {0x04,0x03,0x02,0x01,0x06,0x05,0x08,0x07,0x09,0x0A,0x0B,0x0C,0x0D,0x0E,0x0F,0x10} | Each index in guidBytes matches the corresponding index in the expected array. | Should Pass | + */ +TEST(ConvertEndiannessTest, PositiveValidConversion) { + std::cout << "Entering PositiveValidConversion test" << std::endl; + + // Prepare input original (16 bytes) using strncpy + unsigned char original[16] = {0}; + const char* origSource = "\x01\x02\x03\x04\x05\x06\x07\x08\x09\x0A\x0B\x0C\x0D\x0E\x0F\x10"; + // Use strncpy to fill the original array + strncpy((char*)original, origSource, 16); + std::cout << "Original array set with values:" << std::endl; + for (int i = 0; i < 16; i++) { + std::cout << "original[" << i << "] = 0x" + << std::hex << (int)original[i] << std::dec << std::endl; + } + + // Prepare destination array + unsigned char guidBytes[16] = {0}; + + // Invoke convertEndianness, ensuring no throw + EXPECT_NO_THROW({ + std::cout << "Invoking DrmUtils::convertEndianness with valid pointers" << std::endl; + DrmUtils::convertEndianness(original, guidBytes); + }); + + std::cout << "After conversion, guidBytes contains:" << std::endl; + for (int i = 0; i < 16; i++) { + std::cout << "guidBytes[" << i << "] = 0x" + << std::hex << (int)guidBytes[i] << std::dec << std::endl; + } + + // Expected result array after conversion: + unsigned char expected[16] = { + 0x04, 0x03, 0x02, 0x01, + 0x06, 0x05, 0x08, 0x07, + 0x09, 0x0A, 0x0B, 0x0C, + 0x0D, 0x0E, 0x0F, 0x10 + }; + + for (int i = 0; i < 16; i++) { + EXPECT_EQ(guidBytes[i], expected[i]) << "Mismatch at index " << i; + } + + std::cout << "Exiting PositiveValidConversion test" << std::endl; +} +/** + * @brief Test that DrmUtils::convertEndianness correctly handles a null original pointer without modifying the destination data. + * + * This test verifies that when a null pointer is passed as the original pointer to DrmUtils::convertEndianness, the function does not alter the destination array (guidBytes) and no exception is thrown. This is important to ensure that the function gracefully handles invalid input without causing unexpected behavior. + * + * **Test Group ID:** Basic: 01@n + * **Test Case ID:** 002@n + * **Priority:** High@n + * + * **Pre-Conditions:** None@n + * **Dependencies:** None@n + * **User Interaction:** None@n + * + * **Test Procedure:**@n + * | Variation / Step | Description | Test Data | Expected Result | Notes | + * | :----: | --------- | ---------- |-------------- | ----- | + * | 01 | Setup input arguments by setting the original pointer to nullptr and initializing guidBytes with 0xAA values. | original = nullptr, guidBytes[0-15] = 0xAA | guidBytes is correctly initialized with 0xAA before the function call. | Should be successful | + * | 02 | Display the initial values of guidBytes to confirm proper initialization. | guidBytes initial printout: each index = 0xAA | Initial values of guidBytes are printed as expected. | Should be successful | + * | 03 | Invoke DrmUtils::convertEndianness with the null original pointer and the initialized guidBytes array. | API call: DrmUtils::convertEndianness(original, guidBytes) with original = nullptr, guidBytes[0-15] = 0xAA | The function does not throw any exceptions and handles the null pointer gracefully. | Should Fail | + * | 04 | Verify that guidBytes remains unchanged after the conversion attempt. | guidBytes after call: each index expected value = 0xAA | All elements of guidBytes remain 0xAA; assertions pass. | Should be successful | + */ +TEST(ConvertEndiannessTest, NegativeNullOriginalPointer) { + std::cout << "Entering NegativeNullOriginalPointer test" << std::endl; + + // original is nullptr + unsigned char *original = nullptr; + + // Prepare destination array with initial known values using strncpy + unsigned char guidBytes[16] = {0}; + char guidSource[17] = "\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA"; + strncpy((char*)guidBytes, guidSource, 16); + std::cout << "guidBytes initially set with values:" << std::endl; + for (int i = 0; i < 16; i++) { + std::cout << "guidBytes[" << i << "] = 0x" + << std::hex << (int)guidBytes[i] << std::dec << std::endl; + } + + // Invoke method with null original, expecting no throw (as per test instructions) + EXPECT_NO_THROW({ + std::cout << "Invoking DrmUtils::convertEndianness with original pointer as nullptr" << std::endl; + DrmUtils::convertEndianness(original, guidBytes); + }); + + std::cout << "After conversion attempt, guidBytes contains:" << std::endl; + for (int i = 0; i < 16; i++) { + std::cout << "guidBytes[" << i << "] = 0x" + << std::hex << (int)guidBytes[i] << std::dec << std::endl; + } + + // Expect that guidBytes remains unchanged + for (int i = 0; i < 16; i++) { + EXPECT_EQ(guidBytes[i], (unsigned char)0xAA) << "Mismatch at index " << i; + } + + std::cout << "Exiting NegativeNullOriginalPointer test" << std::endl; +} +/** + * @brief Validate that DrmUtils::convertEndianness handles a nullptr for guidBytes without throwing an exception + * + * This test verifies that when a valid original array is passed to DrmUtils::convertEndianness along with a null pointer for guidBytes, + * the function does not throw any exceptions. This ensures proper handling of invalid output pointers. + * + * **Test Group ID:** Basic: 01@n + * **Test Case ID:** 003@n + * **Priority:** High@n + * + * **Pre-Conditions:** None@n + * **Dependencies:** None@n + * **User Interaction:** None@n + * + * **Test Procedure:** + * | Variation / Step | Description | Test Data | Expected Result | Notes | + * | :--------------: | -------------------------------------------------------------------------------------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------- | --------------------------------- | ------------ | + * | 01 | Prepare valid original array using strncpy | original = {0x11,0x22,0x33,0x44,0x55,0x66,0x77,0x88,0x99,0xAA,0xBB,0xCC,0xDD,0xEE,0xFF,0x00}, origSource = "\x11\x22\x33\x44\x55\x66\x77\x88\x99\xAA\xBB\xCC\xDD\xEE\xFF\x00" | original array correctly set | Should be successful | + * | 02 | Set guidBytes pointer to nullptr | guidBytes = nullptr | guidBytes remains nullptr | Should be successful | + * | 03 | Invoke DrmUtils::convertEndianness with provided original array and null guidBytes pointer | input original = {0x11,0x22,0x33,0x44,0x55,0x66,0x77,0x88,0x99,0xAA,0xBB,0xCC,0xDD,0xEE,0xFF,0x00}, guidBytes = nullptr | No exception thrown | Should Pass | + */ +TEST(ConvertEndiannessTest, NegativeNullGuidBytesPointer) { + std::cout << "Entering NegativeNullGuidBytesPointer test" << std::endl; + + // Prepare valid original array using strncpy + unsigned char original[16] = {0}; + const char* origSource = "\x11\x22\x33\x44\x55\x66\x77\x88\x99\xAA\xBB\xCC\xDD\xEE\xFF\x00"; + strncpy((char*)original, origSource, 16); + std::cout << "Original array set with values:" << std::endl; + for (int i = 0; i < 16; i++) { + std::cout << "original[" << i << "] = 0x" + << std::hex << (int)original[i] << std::dec << std::endl; + } + + // guidBytes is nullptr + unsigned char *guidBytes = nullptr; + + // Invoke method with null guidBytes, expecting no throw (per test instructions) + EXPECT_NO_THROW({ + std::cout << "Invoking DrmUtils::convertEndianness with guidBytes pointer as nullptr" << std::endl; + DrmUtils::convertEndianness(original, guidBytes); + }); + + std::cout << "Exiting NegativeNullGuidBytesPointer test" << std::endl; +} +/** + * @brief Validate endianness conversion for boundary value arrays. + * + * This test verifies that the function DrmUtils::convertEndianness correctly rearranges the bytes in an array containing boundary values. The test ensures that the conversion is performed without throwing exceptions and that the resulting byte order matches the expected transformation from the original boundary input. + * + * **Test Group ID:** Basic: 01@n + * **Test Case ID:** 004@n + * **Priority:** High@n + * + * **Pre-Conditions:** None@n + * **Dependencies:** None@n + * **User Interaction:** None@n + * + * **Test Procedure:** + * | Variation / Step | Description | Test Data | Expected Result | Notes | + * | :----: | --------- | ---------- |-------------- | ----- | + * | 01 | Prepare original array with boundary values using strncpy. | original = "\x00, \x00, \x00, \x00, \xFF, \xFF, \xFF, \xFF, \xAA, \xBB, \xCC, \xDD, \x11, \x22, \x33, \x44" | Original array is populated with the provided boundary bytes. | Should be successful | + * | 02 | Initialize destination array to store the converted bytes. | guidBytes = "Array of 16 bytes initialized to 0" | Destination array is set to zero before conversion. | Should be successful | + * | 03 | Invoke DrmUtils::convertEndianness with prepared arrays. | input1 = original, output1 = guidBytes | API call completes without throwing any exceptions. | Should Pass | + * | 04 | Compute expected result using specific byte reordering and verify each element. | expected = "[ original[3], original[2], original[1], original[0], original[5], original[4], original[7], original[6], original[8], original[9], original[10], original[11], original[12], original[13], original[14], original[15] ]" | Each element in guidBytes matches the corresponding element in the expected array. | Should be successful | + */ +TEST(ConvertEndiannessTest, PositiveBoundaryValuesConversion) { + std::cout << "Entering PositiveBoundaryValuesConversion test" << std::endl; + + // Prepare original array with boundary values using strncpy + unsigned char original[16] = {0}; + const char* origSource = "\x00\x00\x00\x00\xFF\xFF\xFF\xFF\xAA\xBB\xCC\xDD\x11\x22\x33\x44"; + strncpy((char*)original, origSource, 16); + std::cout << "Original array set with boundary values:" << std::endl; + for (int i = 0; i < 16; i++) { + std::cout << "original[" << i << "] = 0x" + << std::hex << (int)original[i] << std::dec << std::endl; + } + + // Prepare destination array + unsigned char guidBytes[16] = {0}; + + // Invoke conversion and log the invocation + EXPECT_NO_THROW({ + std::cout << "Invoking DrmUtils::convertEndianness with boundary values" << std::endl; + DrmUtils::convertEndianness(original, guidBytes); + }); + + std::cout << "After conversion, guidBytes contains:" << std::endl; + for (int i = 0; i < 16; i++) { + std::cout << "guidBytes[" << i << "] = 0x" + << std::hex << (int)guidBytes[i] << std::dec << std::endl; + } + + unsigned char expected[16] = { + original[3], original[2], original[1], original[0], + original[5], original[4], original[7], original[6], + original[8], original[9], original[10], original[11], + original[12], original[13], original[14], original[15] + }; + + for (int i = 0; i < 16; i++) { + EXPECT_EQ(guidBytes[i], expected[i]) << "Mismatch at index " << i; + } + + std::cout << "Exiting PositiveBoundaryValuesConversion test" << std::endl; +} +/** + * @brief Validate successful extraction of text from PSSH input when proper delimiters are provided + * + * This test verifies that the function DrmUtils::extractDataFromPssh correctly extracts the substring "extracted_text" from the given psshData when valid start and end delimiters are provided. It ensures that the extracted text matches the expected output and that the output length is updated correctly. + * + * **Test Group ID:** Basic: 01@n + * **Test Case ID:** 005@n + * **Priority:** High@n + * + * **Pre-Conditions:** None@n + * **Dependencies:** None@n + * **User Interaction:** None@n + * + * **Test Procedure:**@n + * | Variation / Step | Description | Test Data | Expected Result | Notes | + * | :----: | --------- | ---------- |-------------- | ----- | + * | 01 | Initialize input data with proper delimiters for extraction | psshData = "XYZextracted_textABC", dataLength = 31, startStr = "", endStr = "", verStr = "v1" | Input parameters are set as expected | Should be successful | + * | 02 | Invoke DrmUtils::extractDataFromPssh and validate the extracted output | API call with: psshData, dataLength, startStr, endStr, len pointer, verStr | Returned pointer is not nullptr, extracted text equals "extracted_text", and updated length equals 14 | Should Pass | + */ +TEST(DrmUtilsExtractDataTest, ValidExtractionWithProperDelimiters) { + std::cout << "Entering ValidExtractionWithProperDelimiters test" << std::endl; + + char psshData[50]; + strncpy(psshData, "XYZextracted_textABC", sizeof(psshData)-1); + psshData[sizeof(psshData)-1] = '\0'; + int dataLength = 31; + char startStr[20]; + strncpy(startStr, "", sizeof(startStr)-1); + startStr[sizeof(startStr)-1] = '\0'; + char endStr[20]; + strncpy(endStr, "", sizeof(endStr)-1); + endStr[sizeof(endStr)-1] = '\0'; + int extractedLen = 0; + int* len = &extractedLen; + char verStr[10]; + strncpy(verStr, "v1", sizeof(verStr)-1); + verStr[sizeof(verStr)-1] = '\0'; + + std::cout << "Invoking DrmUtils::extractDataFromPssh with:" << std::endl; + std::cout << "psshData: " << psshData << ", dataLength: " << dataLength << std::endl; + std::cout << "startStr: " << startStr << ", endStr: " << endStr << ", verStr: " << verStr << std::endl; + unsigned char* result = DrmUtils::extractDataFromPssh(psshData, dataLength, startStr, endStr, len, verStr); + std::cout << "Returned pointer: " << static_cast(result) << std::endl; + if(result) { + std::cout << "Extracted text: " << result << ", updated length: " << extractedLen << std::endl; + } + EXPECT_NE(result, nullptr); + if(result) { + EXPECT_EQ(std::string(reinterpret_cast(result)), "extracted_text"); + EXPECT_EQ(extractedLen, 14); + delete [] result; + } + + std::cout << "Exiting ValidExtractionWithProperDelimiters test" << std::endl; +} +/** + * @brief Verify that DrmUtils::extractDataFromPssh correctly handles a missing start delimiter scenario. + * + * This test verifies that when the input psshData does not contain the specified start delimiter, the API + * DrmUtils::extractDataFromPssh returns a nullptr and leaves the extracted length unchanged. This ensures that + * the function fails gracefully in the absence of expected delimiters. + * + * **Test Group ID:** Basic: 01@n + * **Test Case ID:** 006@n + * **Priority:** High@n + * + * **Pre-Conditions:** None@n + * **Dependencies:** None@n + * **User Interaction:** None@n + * + * **Test Procedure:**@n + * | Variation / Step | Description | Test Data | Expected Result | Notes | + * | :--------------: | --------------------------------------------------------------------------------------------------------- | -------------------------------------------------------------------------------------------------------------------------------- | ------------------------------------------------------------------ | ------------- | + * | 01 | Initialize input and output buffers and variables | psshData = "XYZextracted_textABC", dataLength = 27, startStr = "", endStr = "", verStr = "v1", extractedLen = -1 | Buffers and variables are initialized with the expected values | Should be successful | + * | 02 | Invoke DrmUtils::extractDataFromPssh to attempt data extraction with a missing start delimiter | psshData = "XYZextracted_textABC", dataLength = 27, startStr = "", endStr = "", verStr = "v1", len pointer to extractedLen | API returns a nullptr indicating extraction failure due to missing start delimiter | Should Fail | + * | 03 | Assert that the extracted length remains unchanged | extractedLen = -1 | extractedLen remains -1 | Should be successful | + */ +TEST(DrmUtilsExtractDataTest, MissingStartDelimiter) { + std::cout << "Entering MissingStartDelimiter test" << std::endl; + + char psshData[50]; + strncpy(psshData, "XYZextracted_textABC", sizeof(psshData)-1); + psshData[sizeof(psshData)-1] = '\0'; + int dataLength = 27; + char startStr[20]; + strncpy(startStr, "", sizeof(startStr)-1); + startStr[sizeof(startStr)-1] = '\0'; + char endStr[20]; + strncpy(endStr, "", sizeof(endStr)-1); + endStr[sizeof(endStr)-1] = '\0'; + int extractedLen = -1; // initialize with a known value + int* len = &extractedLen; + char verStr[10]; + strncpy(verStr, "v1", sizeof(verStr)-1); + verStr[sizeof(verStr)-1] = '\0'; + + std::cout << "Invoking DrmUtils::extractDataFromPssh with:" << std::endl; + std::cout << "psshData: " << psshData << ", dataLength: " << dataLength << std::endl; + std::cout << "startStr: " << startStr << ", endStr: " << endStr << ", verStr: " << verStr << std::endl; + unsigned char* result = DrmUtils::extractDataFromPssh(psshData, dataLength, startStr, endStr, len, verStr); + std::cout << "Returned pointer: " << static_cast(result) << std::endl; + EXPECT_EQ(result, nullptr); + EXPECT_EQ(extractedLen, -1); + + std::cout << "Exiting MissingStartDelimiter test" << std::endl; +} +/** + * @brief Verify that DrmUtils::extractDataFromPssh returns nullptr and leaves extracted length unchanged when the end delimiter is missing. + * + * This test case checks the scenario where the input string (psshData) contains a valid start delimiter but lacks the corresponding end delimiter. The function is expected to detect the missing end delimiter and return a nullptr pointer while keeping the extracted length (extractedLen) at its initialized value (-1). This validation is critical to ensure robustness in data extraction logic with incomplete delimiter specifications.@n + * + * **Test Group ID:** Basic: 01@n + * **Test Case ID:** 007@n + * **Priority:** High@n + * @n + * **Pre-Conditions:** None@n + * **Dependencies:** None@n + * **User Interaction:** None@n + * @n + * **Test Procedure:** + * | Variation / Step | Description | Test Data | Expected Result | Notes | + * | :----: | --------- | ---------- |-------------- | ----- | + * | 01 | Initialize input parameters with missing end delimiter | psshData = "XYZextracted_textABC", dataLength = 28, startStr = "", endStr = "", verStr = "v1", extractedLen = -1 | Input buffers are initialized correctly | Should be successful | + * | 02 | Invoke DrmUtils::extractDataFromPssh and validate response | Invocation with psshData, dataLength, startStr, endStr, pointer to extractedLen, verStr | Returns nullptr and extractedLen remains -1 | Should Fail | + */ + +TEST(DrmUtilsExtractDataTest, MissingEndDelimiter) { + std::cout << "Entering MissingEndDelimiter test" << std::endl; + + char psshData[50]; + strncpy(psshData, "XYZextracted_textABC", sizeof(psshData)-1); + psshData[sizeof(psshData)-1] = '\0'; + int dataLength = 28; + char startStr[20]; + strncpy(startStr, "", sizeof(startStr)-1); + startStr[sizeof(startStr)-1] = '\0'; + char endStr[20]; + strncpy(endStr, "", sizeof(endStr)-1); + endStr[sizeof(endStr)-1] = '\0'; + int extractedLen = -1; + int* len = &extractedLen; + char verStr[10]; + strncpy(verStr, "v1", sizeof(verStr)-1); + verStr[sizeof(verStr)-1] = '\0'; + + std::cout << "Invoking DrmUtils::extractDataFromPssh with:" << std::endl; + std::cout << "psshData: " << psshData << ", dataLength: " << dataLength << std::endl; + std::cout << "startStr: " << startStr << ", endStr: " << endStr << ", verStr: " << verStr << std::endl; + unsigned char* result = DrmUtils::extractDataFromPssh(psshData, dataLength, startStr, endStr, len, verStr); + std::cout << "Returned pointer: " << static_cast(result) << std::endl; + EXPECT_EQ(result, nullptr); + EXPECT_EQ(extractedLen, -1); + + std::cout << "Exiting MissingEndDelimiter test" << std::endl; +} +/** + * @brief Validate that extractDataFromPssh returns nullptr and does not modify extractedLen when provided with an empty psshData string + * + * This test verifies that the DrmUtils::extractDataFromPssh API properly handles an empty psshData input by returning a nullptr and leaving the extractedLen value unchanged. This ensures that the API correctly handles and returns expected values for edge case input. + * + * **Test Group ID:** Basic: 01@n + * **Test Case ID:** 008@n + * **Priority:** High@n + * + * **Pre-Conditions:** None@n + * **Dependencies:** None@n + * **User Interaction:** None@n + * + * **Test Procedure:**@n + * | Variation / Step | Description | Test Data | Expected Result | Notes | + * | :----: | --------- | ---------- |-------------- | ----- | + * | 01 | Initialize test variables with an empty psshData and valid start and end strings | psshData = "", dataLength = 0, startStr = "", endStr = "", extractedLen = -1, verStr = "v1" | Variables are correctly initialized before API invocation | Should be successful | + * | 02 | Invoke DrmUtils::extractDataFromPssh with the provided parameters | psshData = "", dataLength = 0, startStr = "", endStr = "", len pointer to extractedLen, verStr = "v1" | API returns a nullptr | Should Pass | + * | 03 | Validate that extractedLen remains unchanged after API call | extractedLen initial = -1, API result = nullptr | extractedLen equals -1 | Should Pass | + */ +TEST(DrmUtilsExtractDataTest, EmptyPsshDataString) { + std::cout << "Entering EmptyPsshDataString test" << std::endl; + + char psshData[50]; + strncpy(psshData, "", sizeof(psshData)-1); + psshData[sizeof(psshData)-1] = '\0'; + int dataLength = 0; + char startStr[20]; + strncpy(startStr, "", sizeof(startStr)-1); + startStr[sizeof(startStr)-1] = '\0'; + char endStr[20]; + strncpy(endStr, "", sizeof(endStr)-1); + endStr[sizeof(endStr)-1] = '\0'; + int extractedLen = -1; + int* len = &extractedLen; + char verStr[10]; + strncpy(verStr, "v1", sizeof(verStr)-1); + verStr[sizeof(verStr)-1] = '\0'; + + std::cout << "Invoking DrmUtils::extractDataFromPssh with empty psshData." << std::endl; + unsigned char* result = DrmUtils::extractDataFromPssh(psshData, dataLength, startStr, endStr, len, verStr); + std::cout << "Returned pointer: " << static_cast(result) << std::endl; + EXPECT_EQ(result, nullptr); + EXPECT_EQ(extractedLen, -1); + + std::cout << "Exiting EmptyPsshDataString test" << std::endl; +} +/** + * @brief Validate API behavior when provided with a NULL psshData pointer. + * + * This test verifies that when DrmUtils::extractDataFromPssh is invoked with a NULL pointer + * for psshData, the API returns a nullptr and does not modify the length parameter (remains -1). + * Ensuring the API handles null inputs gracefully is critical for robustness. + * + * **Test Group ID:** Basic: 01 + * **Test Case ID:** 009 + * **Priority:** High + * + * **Pre-Conditions:** None + * **Dependencies:** None + * **User Interaction:** None + * + * **Test Procedure:** + * | Variation / Step | Description | Test Data | Expected Result | Notes | + * | :---------------:| ---------------------------------------------------------------------------------------------------- | ----------------------------------------------------------------------------------------------------------------------------------- | ------------------------------------------------------------------------- | -------------- | + * | 01 | Initialize input parameters with NULL psshData and set start/end markers along with version and length pointer. | psshData = NULL, dataLength = 0, startStr = , endStr = , verStr = v1, len pointing to extractedLen (-1) | Inputs are initialized correctly for API invocation. | Should be successful | + * | 02 | Invoke DrmUtils::extractDataFromPssh API with the initialized inputs. | psshData = NULL, dataLength = 0, startStr = , endStr = , verStr = v1, len pointing to extractedLen (-1) | API returns a nullptr. | Should Pass | + * | 03 | Validate that the extracted length remains unchanged after API invocation. | extractedLen = -1 | extractedLen remains -1 confirming no modification occurred. | Should Pass | + */ +TEST(DrmUtilsExtractDataTest, NullPsshData) { + std::cout << "Entering NullPsshData test" << std::endl; + + const char* psshData = NULL; + int dataLength = 0; + char startStr[20]; + strncpy(startStr, "", sizeof(startStr)-1); + startStr[sizeof(startStr)-1] = '\0'; + char endStr[20]; + strncpy(endStr, "", sizeof(endStr)-1); + endStr[sizeof(endStr)-1] = '\0'; + int extractedLen = -1; + int* len = &extractedLen; + char verStr[10]; + strncpy(verStr, "v1", sizeof(verStr)-1); + verStr[sizeof(verStr)-1] = '\0'; + + std::cout << "Invoking DrmUtils::extractDataFromPssh with psshData as NULL." << std::endl; + unsigned char* result = DrmUtils::extractDataFromPssh(psshData, dataLength, startStr, endStr, len, verStr); + std::cout << "Returned pointer: " << static_cast(result) << std::endl; + EXPECT_EQ(result, nullptr); + EXPECT_EQ(extractedLen, -1); + + std::cout << "Exiting NullPsshData test" << std::endl; +} +/** + * @brief Test handling of NULL start string in the extractDataFromPssh API + * + * This test verifies that when a NULL start string is provided to DrmUtils::extractDataFromPssh, + * the API correctly returns a nullptr and the extracted length remains unchanged. This ensures that + * the function gracefully handles invalid input parameters which is critical for preventing potential + * crashes or undefined behaviors. + * + * **Test Group ID:** Basic: 01@n + * **Test Case ID:** 010@n + * **Priority:** High@n + * + * **Pre-Conditions:** None@n + * **Dependencies:** None@n + * **User Interaction:** None@n + * + * **Test Procedure:** + * | Variation / Step | Description | Test Data | Expected Result | Notes | + * | :--------------: | -------------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------ | ---------------------------------------------------------------------- | -------------- | + * | 01 | Initialize all input buffers and parameters with their appropriate values | psshData = "XYZdataABC", dataLength = 23, startStr = NULL, endStr = "", verStr = "v1", extractedLen = -1 | All inputs initialized correctly | Should be successful | + * | 02 | Invoke DrmUtils::extractDataFromPssh with the prepared parameters | Same as above | The API returns a nullptr | Should Pass | + * | 03 | Validate the extracted length does not change after API invocation | extractedLen initially set to -1 | extractedLen remains -1 | Should Pass | + */ +TEST(DrmUtilsExtractDataTest, NullStartStr) { + std::cout << "Entering NullStartStr test" << std::endl; + + char psshData[50]; + strncpy(psshData, "XYZdataABC", sizeof(psshData)-1); + psshData[sizeof(psshData)-1] = '\0'; + int dataLength = 23; + const char* startStr = NULL; + char endStr[20]; + strncpy(endStr, "", sizeof(endStr)-1); + endStr[sizeof(endStr)-1] = '\0'; + int extractedLen = -1; + int* len = &extractedLen; + char verStr[10]; + strncpy(verStr, "v1", sizeof(verStr)-1); + verStr[sizeof(verStr)-1] = '\0'; + + std::cout << "Invoking DrmUtils::extractDataFromPssh with startStr as NULL." << std::endl; + unsigned char* result = DrmUtils::extractDataFromPssh(psshData, dataLength, startStr, endStr, len, verStr); + std::cout << "Returned pointer: " << static_cast(result) << std::endl; + EXPECT_EQ(result, nullptr); + EXPECT_EQ(extractedLen, -1); + + std::cout << "Exiting NullStartStr test" << std::endl; +} +/** + * @brief Validates that DrmUtils::extractDataFromPssh returns nullptr when endStr is NULL. + * + * This test checks if the extractDataFromPssh API correctly handles a NULL endStr input by returning a nullptr + * and leaving the extracted length unchanged (i.e., -1). It ensures that the function fails gracefully with invalid parameters. + * + * **Test Group ID:** Basic: 01@n + * **Test Case ID:** 011@n + * **Priority:** High@n + * + * **Pre-Conditions:** None@n + * **Dependencies:** None@n + * **User Interaction:** None@n + * + * **Test Procedure:**@n + * | Variation / Step | Description | Test Data | Expected Result | Notes | + * | :--------------: | ------------------------------------------------------------------------------------------------------------- | ---------------------------------------------------------------------------------------------------------------------------- | ----------------------------------------------------------------------------------------------- | ------------- | + * | 01 | Invoke DrmUtils::extractDataFromPssh with psshData="XYZdataABC", dataLength=23, startStr="", endStr=NULL, verStr="v1". Validate that the function returns a nullptr and that the extracted length remains -1. | psshData = "XYZdataABC", dataLength = 23, startStr = "", endStr = NULL, verStr = "v1", extractedLen = -1 | Function returns nullptr; extractedLen remains -1; EXPECT_EQ(result, nullptr) and EXPECT_EQ(extractedLen, -1) | Should Fail | + */ +TEST(DrmUtilsExtractDataTest, NullEndStr) { + std::cout << "Entering NullEndStr test" << std::endl; + + char psshData[50]; + strncpy(psshData, "XYZdataABC", sizeof(psshData)-1); + psshData[sizeof(psshData)-1] = '\0'; + int dataLength = 23; + char startStr[20]; + strncpy(startStr, "", sizeof(startStr)-1); + startStr[sizeof(startStr)-1] = '\0'; + const char* endStr = NULL; + int extractedLen = -1; + int* len = &extractedLen; + char verStr[10]; + strncpy(verStr, "v1", sizeof(verStr)-1); + verStr[sizeof(verStr)-1] = '\0'; + + std::cout << "Invoking DrmUtils::extractDataFromPssh with endStr as NULL." << std::endl; + unsigned char* result = DrmUtils::extractDataFromPssh(psshData, dataLength, startStr, endStr, len, verStr); + std::cout << "Returned pointer: " << static_cast(result) << std::endl; + EXPECT_EQ(result, nullptr); + EXPECT_EQ(extractedLen, -1); + + std::cout << "Exiting NullEndStr test" << std::endl; +} +/** + * @brief Verify that DrmUtils::extractDataFromPssh returns a nullptr when the len pointer is NULL + * + * This test verifies that when a NULL pointer is provided for the len parameter, the function + * DrmUtils::extractDataFromPssh correctly handles the invalid input scenario by returning a nullptr. + * This behavior ensures stability and prevents potential segmentation faults or undefined behavior in the API. + * + * **Test Group ID:** Basic: 01@n + * **Test Case ID:** 012@n + * **Priority:** High@n + * + * **Pre-Conditions:** None@n + * **Dependencies:** None@n + * **User Interaction:** None@n + * + * **Test Procedure:** + * | Variation / Step | Description | Test Data | Expected Result | Notes | + * | :--------------: | ---------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------ | ----------------------------------------------- | ------------- | + * | 01 | Initialize input data and parameters including psshData, dataLength, startStr, endStr, verStr | psshData = "XYZdataABC", dataLength = 23, startStr = "", endStr = "", verStr = "v1" | Variables set correctly | Should be successful | + * | 02 | Set the length pointer to NULL | len = NULL | len remains NULL | Should be successful | + * | 03 | Invoke DrmUtils::extractDataFromPssh with the provided parameters | Function call with: psshData, dataLength, startStr, endStr, len = NULL, verStr = "v1" | Function is called and returns a pointer | Should Pass | + * | 04 | Validate that the returned pointer is NULL using EXPECT_EQ | result = DrmUtils::extractDataFromPssh(...) | EXPECT_EQ(result, nullptr) passes | Should Pass | + */ +TEST(DrmUtilsExtractDataTest, NullLenPointer) { + std::cout << "Entering NullLenPointer test" << std::endl; + + char psshData[50]; + strncpy(psshData, "XYZdataABC", sizeof(psshData)-1); + psshData[sizeof(psshData)-1] = '\0'; + int dataLength = 23; + char startStr[20]; + strncpy(startStr, "", sizeof(startStr)-1); + startStr[sizeof(startStr)-1] = '\0'; + char endStr[20]; + strncpy(endStr, "", sizeof(endStr)-1); + endStr[sizeof(endStr)-1] = '\0'; + // len pointer is NULL + int* len = NULL; + char verStr[10]; + strncpy(verStr, "v1", sizeof(verStr)-1); + verStr[sizeof(verStr)-1] = '\0'; + + std::cout << "Invoking DrmUtils::extractDataFromPssh with len pointer as NULL." << std::endl; + unsigned char* result = DrmUtils::extractDataFromPssh(psshData, dataLength, startStr, endStr, len, verStr); + std::cout << "Returned pointer: " << static_cast(result) << std::endl; + EXPECT_EQ(result, nullptr); + + std::cout << "Exiting NullLenPointer test" << std::endl; +} +/** + * @brief Validate the extraction failure when version string is NULL. + * + * This test verifies that the DrmUtils::extractDataFromPssh API handles the case where the version string (verStr) is passed as NULL. The test checks if the API returns a NULL pointer and if the output data length remains unchanged (-1) when the verStr is invalid. + * + * **Test Group ID:** Basic: 01@n + * **Test Case ID:** 013@n + * **Priority:** High@n + * + * **Pre-Conditions:** None@n + * **Dependencies:** None@n + * **User Interaction:** None@n + * + * **Test Procedure:**@n + * | Variation / Step | Description | Test Data | Expected Result | Notes | + * | :----: | --------- | ---------- |-------------- | ----- | + * | 01 | Initialize input data and invoke extractDataFromPssh with verStr as NULL | psshData = "XYZdataABC", dataLength = 23, startStr = "", endStr = "", extractedLen = -1, verStr = NULL | API returns a NULL pointer and extractedLen remains -1 | Should Pass | + */ +TEST(DrmUtilsExtractDataTest, NullVerStr) { + std::cout << "Entering NullVerStr test" << std::endl; + + char psshData[50]; + strncpy(psshData, "XYZdataABC", sizeof(psshData)-1); + psshData[sizeof(psshData)-1] = '\0'; + int dataLength = 23; + char startStr[20]; + strncpy(startStr, "", sizeof(startStr)-1); + startStr[sizeof(startStr)-1] = '\0'; + char endStr[20]; + strncpy(endStr, "", sizeof(endStr)-1); + endStr[sizeof(endStr)-1] = '\0'; + int extractedLen = -1; + int* len = &extractedLen; + const char* verStr = NULL; + + std::cout << "Invoking DrmUtils::extractDataFromPssh with verStr as NULL." << std::endl; + unsigned char* result = DrmUtils::extractDataFromPssh(psshData, dataLength, startStr, endStr, len, verStr); + std::cout << "Returned pointer: " << static_cast(result) << std::endl; + EXPECT_EQ(result, nullptr); + EXPECT_EQ(extractedLen, -1); + + std::cout << "Exiting NullVerStr test" << std::endl; +} +/** + * @brief Tests the extraction function's behavior when provided with a truncated input data length. + * + * This test validates that when a truncated data length is provided to the DrmUtils::extractDataFromPssh API, the function returns a nullptr and leaves the output length unchanged (-1). This ensures that the API robustly handles incomplete input data without extracting erroneous information. + * + * **Test Group ID:** Basic: 01@n + * **Test Case ID:** 014@n + * **Priority:** High@n + * + * **Pre-Conditions:** None@n + * **Dependencies:** None@n + * **User Interaction:** None@n + * + * **Test Procedure:**@n + * | Variation / Step | Description | Test Data | Expected Result | Notes | + * | :----: | --------- | ---------- |-------------- | ----- | + * | 01 | Initialize test inputs including psshData, dataLength, startStr, endStr, verStr, and len pointer for extracted length. | psshData = "XYZdataABC", dataLength = 10, startStr = "", endStr = "", verStr = "v1", extractedLen = -1 | Test inputs are correctly initialized | Should be successful | + * | 02 | Invoke DrmUtils::extractDataFromPssh with truncated dataLength input and validate the output. | psshData = "XYZdataABC", dataLength = 10, startStr = "", endStr = "", verStr = "v1", len pointer = address of extractedLen (-1) | API returns nullptr and extractedLen remains -1 | Should Fail | + */ +TEST(DrmUtilsExtractDataTest, TruncatedInputDataLength) { + std::cout << "Entering TruncatedInputDataLength test" << std::endl; + + char psshData[50]; + strncpy(psshData, "XYZdataABC", sizeof(psshData)-1); + psshData[sizeof(psshData)-1] = '\0'; + int dataLength = 10; // truncated length + char startStr[20]; + strncpy(startStr, "", sizeof(startStr)-1); + startStr[sizeof(startStr)-1] = '\0'; + char endStr[20]; + strncpy(endStr, "", sizeof(endStr)-1); + endStr[sizeof(endStr)-1] = '\0'; + int extractedLen = -1; + int* len = &extractedLen; + char verStr[10]; + strncpy(verStr, "v1", sizeof(verStr)-1); + verStr[sizeof(verStr)-1] = '\0'; + + std::cout << "Invoking DrmUtils::extractDataFromPssh with truncated dataLength: " << dataLength << std::endl; + std::cout << "psshData: " << psshData << ", startStr: " << startStr << ", endStr: " << endStr << ", verStr: " << verStr << std::endl; + unsigned char* result = DrmUtils::extractDataFromPssh(psshData, dataLength, startStr, endStr, len, verStr); + std::cout << "Returned pointer: " << static_cast(result) << std::endl; + EXPECT_EQ(result, nullptr); + EXPECT_EQ(extractedLen, -1); + + std::cout << "Exiting TruncatedInputDataLength test" << std::endl; +} +/** + * @brief Verify that DrmUtils::extractWVContentMetadataFromPssh extracts valid WV metadata from a correct PSSH input. + * + * This test verifies the functionality of DrmUtils::extractWVContentMetadataFromPssh by providing a valid PSSH data string and data length. + * It ensures the API successfully processes the input without throwing exceptions and returns the expected metadata string. + * + * **Test Group ID:** Basic: 01 + * **Test Case ID:** 015 + * **Priority:** High + * + * **Pre-Conditions:** None + * **Dependencies:** None + * **User Interaction:** None + * + * **Test Procedure:** + * | Variation / Step | Description | Test Data | Expected Result | Notes | + * | :--------------: | --------------------------------------------------------------------------------------------------- | -------------------------------------------------------------- | ---------------------------------------------------------------------- | ------------- | + * | 01 | Prepare input data by copying a valid source string into a fixed-size array and setting dataLength | inputStr = valid_wv_pssh_data, psshData = {valid_wv_pssh_data}, dataLength = 18 | psshData is correctly initialized | Should be successful | + * | 02 | Invoke DrmUtils::extractWVContentMetadataFromPssh using the prepared input | psshData = valid_wv_pssh_data, dataLength = 18 | No exception thrown and function is executed | Should Pass | + * | 03 | Validate the output by checking that the returned metadata equals "ExtractedWVContentMetadata" | result (output) = value from API call | result equals "ExtractedWVContentMetadata" | Should Pass | + */ +TEST(ExtractWVContentMetadata, ValidWVMetadataExtraction) { + std::cout << "Entering ValidWVMetadataExtraction test" << std::endl; + + // Prepare input using fixed-size array and strncpy + const char* inputStr = "valid_wv_pssh_data"; + char psshData[256] = {0}; + std::strncpy(psshData, inputStr, sizeof(psshData) - 1); + int dataLength = 18; + + std::cout << "Invoking DrmUtils::extractWVContentMetadataFromPssh with psshData: " << psshData + << " and dataLength: " << dataLength << std::endl; + + std::string result; + EXPECT_NO_THROW(result = DrmUtils::extractWVContentMetadataFromPssh(psshData, dataLength)); + + std::cout << "Received result: " << result << std::endl; + + EXPECT_EQ(result, "ExtractedWVContentMetadata"); + + std::cout << "Exiting ValidWVMetadataExtraction test" << std::endl; +} +/** + * @brief Validates extraction of Widevine metadata when provided with a null psshData pointer. + * + * This test case checks that the function DrmUtils::extractWVContentMetadataFromPssh handles a null pointer for psshData without throwing an exception. It ensures that an empty string is returned when no valid data is provided, thus verifying robust error handling. + * + * **Test Group ID:** Basic: 01 + * **Test Case ID:** 016 + * **Priority:** High + * + * **Pre-Conditions:** None + * **Dependencies:** None + * **User Interaction:** None + * + * **Test Procedure:** + * | Variation / Step | Description | Test Data |Expected Result |Notes | + * | :----: | --------- | ---------- |-------------- | ----- | + * | 01 | Log the entry message for the test start | No data input | "Entering NullPsshData test" printed to console | Should be successful | + * | 02 | Initialize inputs by setting psshData to nullptr and dataLength to 10 | psshData = nullptr, dataLength = 10 | Variables initialized correctly | Should be successful | + * | 03 | Invoke DrmUtils::extractWVContentMetadataFromPssh with the initialized inputs | psshData = nullptr, dataLength = 10 | Function does not throw exception and returns an empty string | Should Pass | + * | 04 | Validate that the returned result is an empty string | output result = "" | EXPECT_EQ(result, "") passes | Should Pass | + * | 05 | Log the exit message for the test end | No data input | "Exiting NullPsshData test" printed to console | Should be successful | + */ +TEST(ExtractWVContentMetadata, NullPsshData) { + std::cout << "Entering NullPsshData test" << std::endl; + + // Passing null pointer for psshData + const char* psshData = nullptr; + int dataLength = 10; + + std::cout << "Invoking DrmUtils::extractWVContentMetadataFromPssh with psshData: nullptr and dataLength: " + << dataLength << std::endl; + + std::string result; + EXPECT_NO_THROW(result = DrmUtils::extractWVContentMetadataFromPssh(psshData, dataLength)); + + std::cout << "Received result: " << result << std::endl; + + EXPECT_EQ(result, ""); + + std::cout << "Exiting NullPsshData test" << std::endl; +} +/** + * @brief Test to validate extraction of Widevine content metadata when provided a non-null psshData with zero data length. + * + * This test verifies that when a non-null psshData is provided with a zero data length, the + * DrmUtils::extractWVContentMetadataFromPssh function does not throw an exception and returns an empty string. + * This ensures proper handling of edge cases with minimal or missing data. + * + * **Test Group ID:** Basic: 01@n + * **Test Case ID:** 017@n + * **Priority:** High@n + * + * **Pre-Conditions:** None@n + * **Dependencies:** None@n + * **User Interaction:** None@n + * + * **Test Procedure:**@n + * | Variation / Step | Description | Test Data | Expected Result | Notes | + * | :----: | --------- | ---------- |-------------- | ----- | + * | 01 | Prepare input buffer with valid non-null psshData and zero data length | inputStr = any_data, psshData = any_data, dataLength = 0 | psshData is correctly initialized with "any_data" and dataLength is set to 0 | Should be successful | + * | 02 | Invoke extractWVContentMetadataFromPssh API and capture result | psshData = any_data, dataLength = 0, output: result | API does not throw an exception and returns an empty string | Should Pass | + */ +TEST(ExtractWVContentMetadata, ZeroDataLengthNonNullPsshData) { + std::cout << "Entering ZeroDataLengthNonNullPsshData test" << std::endl; + + // Prepare input using fixed-size array and strncpy + const char* inputStr = "any_data"; + char psshData[256] = {0}; + std::strncpy(psshData, inputStr, sizeof(psshData) - 1); + int dataLength = 0; + + std::cout << "Invoking DrmUtils::extractWVContentMetadataFromPssh with psshData: " << psshData + << " and dataLength: " << dataLength << std::endl; + + std::string result; + EXPECT_NO_THROW(result = DrmUtils::extractWVContentMetadataFromPssh(psshData, dataLength)); + + std::cout << "Received result: " << result << std::endl; + + EXPECT_EQ(result, ""); + + std::cout << "Exiting ZeroDataLengthNonNullPsshData test" << std::endl; +} +/** + * @brief Verify that DrmUtils::extractWVContentMetadataFromPssh handles negative data length appropriately. + * + * This test ensures that when a negative value is provided for dataLength while invoking + * DrmUtils::extractWVContentMetadataFromPssh with valid psshData, the function does not throw an exception + * and returns an empty string. This behavior is critical to validate the function's robustness against invalid input. + * + * **Test Group ID:** Basic: 01@n + * **Test Case ID:** 018@n + * **Priority:** High@n + * + * **Pre-Conditions:** None@n + * **Dependencies:** None@n + * **User Interaction:** None@n + * + * **Test Procedure:** + * | Variation / Step | Description | Test Data | Expected Result | Notes | + * | :--------------: | --------------------------------------------------------------------------------------------------- | ------------------------------------------------------- | ---------------------------------------------------------------------------------------------------- | -------------- | + * | 01 | Prepare input: create a constant input string, copy it into a fixed-size character array, and set a negative data length. | inputStr = "any_data", psshData = "any_data", dataLength = -5 | Input parameters are prepared correctly. | Should be successful | + * | 02 | Invoke DrmUtils::extractWVContentMetadataFromPssh with the prepared psshData and negative dataLength. | psshData = "any_data", dataLength = -5 | The API does not throw an exception upon invocation. | Should Pass | + * | 03 | Validate the result: check that the returned string is empty. | result = output string from API | The result should be an empty string as the negative data length is invalid. | Should Pass | + */ +TEST(ExtractWVContentMetadata, NegativeDataLengthValidPsshData) { + std::cout << "Entering NegativeDataLengthValidPsshData test" << std::endl; + + // Prepare input using fixed-size array and strncpy + const char* inputStr = "any_data"; + char psshData[256] = {0}; + std::strncpy(psshData, inputStr, sizeof(psshData) - 1); + int dataLength = -5; + + std::cout << "Invoking DrmUtils::extractWVContentMetadataFromPssh with psshData: " << psshData + << " and dataLength: " << dataLength << std::endl; + + std::string result; + EXPECT_NO_THROW(result = DrmUtils::extractWVContentMetadataFromPssh(psshData, dataLength)); + + std::cout << "Received result: " << result << std::endl; + + EXPECT_EQ(result, ""); + + std::cout << "Exiting NegativeDataLengthValidPsshData test" << std::endl; +} +/** + * @brief Test that extractWVContentMetadataFromPssh returns an empty string when provided with an empty psshData and zero dataLength + * + * This test verifies that when psshData is an empty string and dataLength is set to 0, the API DrmUtils::extractWVContentMetadataFromPssh executes without throwing any exceptions and returns an empty string as output. This ensures that the function correctly handles edge cases with minimal input. + * + * **Test Group ID:** Basic: 01@n + * **Test Case ID:** 019@n + * **Priority:** High@n + * + * **Pre-Conditions:** None@n + * **Dependencies:** None@n + * **User Interaction:** None@n + * + * **Test Procedure:** + * | Variation / Step | Description | Test Data | Expected Result | Notes | + * | :--------------: | -------------------------------------------------------------------------------------------- | ------------------------------------------- | ----------------------------------------------------------- | ------------- | + * | 01 | Prepare the input by initializing psshData with an empty string and setting dataLength to 0 | psshData = "", dataLength = 0 | Input is correctly initialized | Should be successful | + * | 02 | Invoke DrmUtils::extractWVContentMetadataFromPssh with the prepared psshData and dataLength | psshData = "", dataLength = 0 | The API does not throw any exceptions | Should Pass | + * | 03 | Validate that the result returned by the API is an empty string | Output result from API call, expected "" | The returned string equals "" as verified using EXPECT_EQ | Should Pass | + */ +TEST(ExtractWVContentMetadata, EmptyStringPsshDataZeroDataLength) { + std::cout << "Entering EmptyStringPsshDataZeroDataLength test" << std::endl; + + // Prepare input using fixed-size array and strncpy + const char* inputStr = ""; + char psshData[256] = {0}; + std::strncpy(psshData, inputStr, sizeof(psshData) - 1); + int dataLength = 0; + + std::cout << "Invoking DrmUtils::extractWVContentMetadataFromPssh with psshData: \"" << psshData + << "\" and dataLength: " << dataLength << std::endl; + + std::string result; + EXPECT_NO_THROW(result = DrmUtils::extractWVContentMetadataFromPssh(psshData, dataLength)); + + std::cout << "Received result: " << result << std::endl; + + EXPECT_EQ(result, ""); + + std::cout << "Exiting EmptyStringPsshDataZeroDataLength test" << std::endl; +} + +int main(int argc, char **argv) { + ::testing::InitGoogleTest(&argc, argv); + return RUN_ALL_TESTS(); +}