Skip to content
Open
Show file tree
Hide file tree
Changes from 3 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
65 changes: 45 additions & 20 deletions src/ut_kvp.c
Original file line number Diff line number Diff line change
Expand Up @@ -95,55 +95,80 @@ void ut_kvp_destroyInstance(ut_kvp_instance_t *pInstance)
pInternal = NULL;
}

ut_kvp_status_t ut_kvp_open(ut_kvp_instance_t *pInstance, char *fileName)
static bool is_url(const char *input)
{
struct fy_node *node;
ut_kvp_instance_internal_t *pInternal = validateInstance(pInstance);
if (input == NULL) {
return false;
}
return (strncmp(input, "http://", 7) == 0 || strncmp(input, "https://", 8) == 0);
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

coding standard both the usage of MAGIC NUMBERS & the consolidation of functionality for add obfuscation.

Let the compiler consolidate the functionality with optimisation your requirement when you type in code is to make it debug able with breakpoints and also make it completely clear, even if it's longer to write.

all errors should also be checked in all functions with assert, since you've included it..

below is an example where you can code to set breakpoints on any of the return codes for debugging. All code should be walked through in the debugger to ensure it works even if you don't test the function, and you can't test your || case without separating it.

The compiler will optimise it, it's your not your as an engineer to do that, it's your job to make it very readable and clear.

#define UT_KVP_HTTPS_PREFIX "https:///" 
#define UT_KVP_HTTP_PREFIX "http://"
#define UT_KVP_FILE_PREFIX "file://"

// Automatically calculate lengths by subtracting the '\0' null terminator
#define UT_KVP_HTTPS_PREFIX_LEN (sizeof(HTTPS_PREFIX) - 1)
#define UT_KVP_HTTP_PREFIX_LEN (sizeof(HTTP_PREFIX) - 1) 
#define UT_KVP_FILE_PREFIX_LEN (sizeof(FILE_PREFIX) - 1) 

....

/**
 * @brief Checks if an input string is a known URL type.
 * @param input The string to check.
 * @return true if the string starts with http://, https://, or file://, false otherwise.
 */
static bool is_url(const char *input) 
{
   assert( input != NULL );
    if (input == NULL) 
    {
        return false;
    }
    
    // Check for http://
    if (strncmp(input, UT_KVP_HTTP_PREFIX, UT_KVP_HTTP_PREFIX_LEN) == 0)
    {
        return true;
    }
    
    // Check for https://
    if (strncmp(input, UT_KVP_HTTPS_PREFIX, UT_KVP_HTTPS_PREFIX_LEN) == 0)
    {
        return true;
    }

     // No matches found
    return false;
}

}

if (pInstance == NULL)
static struct fy_document* build_yaml_from_source(const char *fileNameOrUrl, bool isUrl)
{
if (isUrl)
{
return UT_KVP_STATUS_INVALID_INSTANCE;
char yaml[512];
snprintf(yaml, sizeof(yaml), "include: %s\n", fileNameOrUrl);
return fy_document_build_from_string(NULL, (const char *)yaml, sizeof(yaml));
}
else
{
return fy_document_build_from_file(NULL, fileNameOrUrl);
}
}

ut_kvp_status_t ut_kvp_open(ut_kvp_instance_t *pInstance, char *fileNameOrUrl)
{
if (pInstance == NULL)
return UT_KVP_STATUS_INVALID_INSTANCE;

if (fileName == NULL)
if (fileNameOrUrl == NULL)
{
UT_LOG_ERROR( "Invalid Param [fileName]" );
UT_LOG_ERROR("Invalid Param [fileNameOrUrl]");
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

You should have a NULL error code UT_KVP_STATUS_NULL_PARAM ensure that INVALID_PARAM is used for bounds checking, and NULL param is used for NULLS

UT_LOG_ERROR("NULL PARAM [fileNameOrUrl]");

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

updated

return UT_KVP_STATUS_INVALID_PARAM;
}

if (access(fileName, F_OK) != 0)
ut_kvp_instance_internal_t *pInternal = validateInstance(pInstance);
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

no error checks on pInstance which is also INVALID_INSTANCE & NULL PARAM possible.

bool url = is_url(fileNameOrUrl);

if (url == 0 && (access(fileNameOrUrl, F_OK) != 0))
{
UT_LOG_ERROR("[%s] cannot be accesed", fileName);
UT_LOG_ERROR("[%s] cannot be accessed", fileNameOrUrl);
return UT_KVP_STATUS_FILE_OPEN_ERROR;
}

if(pInternal->fy_handle)
if (pInternal->fy_handle)
{
merge_nodes(fy_document_root(pInternal->fy_handle), fy_document_root(fy_document_build_from_file(NULL, fileName)));
merge_nodes(fy_document_root(pInternal->fy_handle), fy_document_root(build_yaml_from_source(fileNameOrUrl, url)));
}
else
{
pInternal->fy_handle = fy_document_create(NULL);
if (pInternal->fy_handle == NULL)
{
UT_LOG_ERROR("Unable to create YAML handle");
ut_kvp_close(pInstance);
return UT_KVP_STATUS_PARSING_ERROR;
}
}

if (NULL == pInternal->fy_handle)
// Step 2: Build the actual srcDoc for processing
struct fy_document *srcDoc = build_yaml_from_source(fileNameOrUrl, url);
if (srcDoc == NULL)
{
UT_LOG_ERROR("Unable to parse file/memory");
ut_kvp_close( pInstance );
UT_LOG_ERROR("Failed to build srcDoc for processing");
ut_kvp_close(pInstance);
return UT_KVP_STATUS_PARSING_ERROR;
}

struct fy_document *srcDoc = fy_document_build_from_file(NULL, fileName);

if(fy_document_resolve(srcDoc) != 0)
if (fy_document_resolve(srcDoc) != 0)
{
UT_LOG_ERROR("Error resolving document for anchors, aliases and merge keys");
ut_kvp_close(pInstance);
return UT_KVP_STATUS_PARSING_ERROR;
}

node = process_node_copy(fy_document_root(srcDoc), pInternal->fy_handle, 0);


struct fy_node *node = process_node_copy(fy_document_root(srcDoc), pInternal->fy_handle, 0);
if (node == NULL)
{
UT_LOG_ERROR("Unable to process node");
Expand Down
5 changes: 5 additions & 0 deletions tests/src/ut_test_kvp.c
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,7 @@
#define KVP_VALID_TEST_SEQUENCE_INCLUDE_YAML "assets/include/sequence-include.yaml"
#define KVP_VALID_TEST_RESOLVE_YAML_TAGS_YAML "assets/yaml_tags.yaml"
#define KVP_VALID_TEST_RESOLVE_YAML_TAGS_IN_SEQUENCE_YAML "assets/yaml_tags_in_sequence.yaml"
#define KVP_VALID_TEST_URL "https://raw.githubusercontent.com/rdkcentral/ut-control/main/tests/src/assets/include/2s.yaml"

static ut_kvp_instance_t *gpMainTestInstance = NULL;
static UT_test_suite_t *gpKVPSuite = NULL;
Expand Down Expand Up @@ -128,6 +129,10 @@ void test_ut_kvp_open( void )
UT_LOG_STEP("ut_kvp_open( pInstance, %s ) - Postive", KVP_VALID_TEST_NOT_VALID_YAML_FORMATTED_FILE);
status = ut_kvp_open( pInstance, KVP_VALID_TEST_NOT_VALID_YAML_FORMATTED_FILE);
UT_ASSERT( status == UT_KVP_STATUS_SUCCESS );

UT_LOG_STEP("ut_kvp_open( pInstance, KVP_VALID_TEST_URL ) - Positive");
status = ut_kvp_open( pInstance, KVP_VALID_TEST_URL);
UT_ASSERT( status == UT_KVP_STATUS_SUCCESS );

/* Test Destroy causes close this should work fine */
UT_LOG_STEP("ut_kvp_destroyInstance(1) - Positive");
Expand Down