Skip to content
Open
Show file tree
Hide file tree
Changes from all 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
9 changes: 7 additions & 2 deletions source/bulkdata/profile.c
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@
#include <time.h>
#include <fcntl.h>
#include <errno.h>
#include <ctype.h>

#include "profile.h"
#include "reportprofiles.h"
Expand Down Expand Up @@ -73,11 +74,15 @@ static bool isEmptySubscriberValue(const char *value)
{
return true;
}
if(strlen(value) < 1 || value[0] == ' ' || strncmp(value, "NULL", 4) == 0)
if(strncmp(value, "NULL", sizeof("NULL")) == 0)
Comment thread
tabbas651 marked this conversation as resolved.
Resolved
{
return true;
}
return false;
while(*value != '\0' && isspace((unsigned char) * value))
{
value++;
}
return (*value == '\0');
}

static void freeRequestURIparam(void *data)
Expand Down
9 changes: 7 additions & 2 deletions source/bulkdata/profilexconf.c
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@
#include <malloc.h>
#include <string.h>
#include <signal.h>
#include <ctype.h>
#include <cjson/cJSON.h>

#include "profilexconf.h"
Expand Down Expand Up @@ -63,11 +64,15 @@ static bool isEmptySubscriberValue(const char *value)
{
return true;
}
if(strlen(value) < 1 || value[0] == ' ' || strncmp(value, "NULL", 4) == 0)
if(strncmp(value, "NULL", sizeof("NULL")) == 0)
Comment thread
tabbas651 marked this conversation as resolved.
Resolved
{
return true;
}
return false;
while(*value != '\0' && isspace((unsigned char) * value))
{
value++;
}
return (*value == '\0');
}

#ifdef GTEST_ENABLE
Expand Down
18 changes: 17 additions & 1 deletion source/reportgen/reportgen.c
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@
#include <time.h>
#include <stdlib.h>
#include <string.h>
#include <ctype.h>
#include <curl/curl.h>
#include <stdbool.h>

Expand Down Expand Up @@ -55,6 +56,20 @@ static bool checkForEmptyString( char* valueString )
return isEmpty;
}

// Unlike checkForEmptyString, a value with leading/trailing spaces but real content is not empty.
static bool isEmptyMarkerValue(const char *value)
{
if(value == NULL || strncmp(value, "NULL", sizeof("NULL")) == 0)
{
return true;
}
while(*value != '\0' && isspace((unsigned char) * value))
{
value++;
}
return (*value == '\0');
}

void freeParamValueSt(tr181ValStruct_t **valStructs, int valSize)
{
int i;
Expand Down Expand Up @@ -141,6 +156,7 @@ void trimLeadingAndTrailingws(char* string)
string[j++] = string[i];
}
string[j] = '\0';
j = -1;

for(i = 0; string[i] != '\0'; i++)
{
Expand Down Expand Up @@ -1567,7 +1583,7 @@ T2ERROR encodeEventMarkersInJSON(cJSON *valArray, Vector *eventMarkerList)
default:
if(eventMarker->u.markerValue != NULL)
{
if(!eventMarker->reportEmptyParam && checkForEmptyString(eventMarker->u.markerValue))
if(!eventMarker->reportEmptyParam && isEmptyMarkerValue(eventMarker->u.markerValue))
Comment thread
tabbas651 marked this conversation as resolved.
Resolved
{
T2Debug("Skipping empty/\"NULL\" marker value for : %s\n", eventMarker->markerName);
free(eventMarker->u.markerValue);
Expand Down
81 changes: 81 additions & 0 deletions source/test/bulkdata/profileTest.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@
#include "test/mocks/VectorMock.h"
#include "test/bulkdata/SchedulerMock.h"
#include "test/bulkdata/profileMock.h"
#include <tuple>

using namespace std;

Expand Down Expand Up @@ -371,6 +372,86 @@ TEST_F(ProfileTest, TriggerReportOnCondition_SchedulerFailureKeepsActiveMutexOwn
test_reset_profile_list();
}

class ProfileMarkerStorageTest : public ProfileTest,
public ::testing::WithParamInterface<std::tuple<MarkerType, bool>> {
protected:
Profile profile = {};
EventMarker marker = {};
Vector *profiles = nullptr;

void SetUp() override {
ProfileTest::SetUp();
delete g_vectorMock;
g_vectorMock = nullptr;
ASSERT_EQ(Vector_Create(&profiles), T2ERROR_SUCCESS);
ASSERT_EQ(Vector_Create(&profile.eMarkerList), T2ERROR_SUCCESS);
profile.name = strdup("StorageProfile");
profile.enable = true;
ASSERT_EQ(pthread_mutex_init(&profile.eventMutex, nullptr), 0);
marker.markerName = strdup("StorageMarker");
marker.mType = std::get<0>(GetParam());
marker.reportEmptyParam = std::get<1>(GetParam());
if(marker.mType == MTYPE_ACCUMULATE) {
ASSERT_EQ(Vector_Create(&marker.u.accumulatedValues), T2ERROR_SUCCESS);
}
ASSERT_EQ(Vector_PushBack(profile.eMarkerList, &marker), T2ERROR_SUCCESS);
ASSERT_EQ(Vector_PushBack(profiles, &profile), T2ERROR_SUCCESS);
test_set_profile_list(profiles);
}

void TearDown() override {
test_reset_profile_list();
if(marker.mType == MTYPE_ACCUMULATE) {
Vector_Destroy(marker.u.accumulatedValues, free);
} else {
free(marker.u.markerValue);
}
free(marker.markerName);
Vector_Destroy(profile.eMarkerList, nullptr);
Vector_Destroy(profiles, nullptr);
pthread_mutex_destroy(&profile.eventMutex);
free(profile.name);
ProfileTest::TearDown();
}
};

TEST_P(ProfileMarkerStorageTest, StoresClassifiedValuesWithoutTrimming) {
const struct {
const char *value;
bool empty;
} cases[] = {
{" test log ", false}, {" xyz ", false}, {"NULLify", false},
{"", true}, {" ", true}, {"\t\r\n", true}, {"NULL", true}
};
for(const auto &testCase : cases) {
SCOPED_TRACE(testCase.value);
const bool retained = marker.reportEmptyParam || !testCase.empty;
if(marker.mType == MTYPE_ACCUMULATE) {
Vector_Clear(marker.u.accumulatedValues, free);
ASSERT_EQ(Vector_PushBack(marker.u.accumulatedValues, strdup("previous")), T2ERROR_SUCCESS);
} else {
free(marker.u.markerValue);
marker.u.markerValue = strdup("previous");
}
T2Event event = {};
event.name = marker.markerName;
event.value = const_cast<char *>(testCase.value);
EXPECT_EQ(Profile_storeMarkerEvent(profile.name, &event), T2ERROR_SUCCESS);
if(marker.mType == MTYPE_ACCUMULATE) {
ASSERT_EQ(Vector_Size(marker.u.accumulatedValues), retained ? 2u : 1u);
EXPECT_STREQ(static_cast<char *>(Vector_At(marker.u.accumulatedValues, 0)), "previous");
if(retained) {
EXPECT_STREQ(static_cast<char *>(Vector_At(marker.u.accumulatedValues, 1)), testCase.value);
}
} else {
EXPECT_STREQ(marker.u.markerValue, retained ? testCase.value : "previous");
}
}
}

INSTANTIATE_TEST_SUITE_P(SubscriberValues, ProfileMarkerStorageTest,
::testing::Combine(::testing::Values(MTYPE_ABSOLUTE, MTYPE_ACCUMULATE), ::testing::Bool()));

TEST_F(ProfileTest, getMinThresholdDuration_Failure) {
EXPECT_CALL(*g_vectorMock, Vector_Size(_)).Times(::testing::AtMost(1)).WillRepeatedly(Return(0));
EXPECT_EQ(getMinThresholdDuration("profile1"), 0);
Expand Down
74 changes: 74 additions & 0 deletions source/test/bulkdata/profilexconfTest.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -551,6 +551,80 @@ TEST_F(profileXconfTestFixture, ReportProfiles_storeMarkerEvent_success_2)
free(eventInfo);
}

class XconfMarkerStorageTest : public profileXconfTestFixture,
public ::testing::WithParamInterface<std::tuple<MarkerType, bool>> {
protected:
ProfileXConf *profile = nullptr;
EventMarker *marker = nullptr;

void SetUp() override {
profileXconfTestFixture::SetUp();
delete g_fileIOMock;
g_fileIOMock = new ::testing::NiceMock<FileMock>();
EXPECT_CALL(*g_fileIOMock, opendir(_))
.WillRepeatedly(Return(nullptr));
ASSERT_EQ(ProfileXConf_init(false), T2ERROR_SUCCESS);
profile = static_cast<ProfileXConf *>(calloc(1, sizeof(ProfileXConf)));
ASSERT_NE(profile, nullptr);
profile->name = strdup("StorageProfile");
ASSERT_EQ(Vector_Create(&profile->eMarkerList), T2ERROR_SUCCESS);
EXPECT_CALL(*g_schedulerMock, registerProfileWithScheduler(_, _, _, _, _, _, _, _))
.WillOnce(Return(T2ERROR_SUCCESS));
ASSERT_EQ(ProfileXConf_set(profile), T2ERROR_SUCCESS);
marker = static_cast<EventMarker *>(calloc(1, sizeof(EventMarker)));
ASSERT_NE(marker, nullptr);
marker->markerName = strdup("StorageMarker");
marker->mType = std::get<0>(GetParam());
marker->reportEmptyParam = std::get<1>(GetParam());
if(marker->mType == MTYPE_XCONF_ACCUMULATE) {
ASSERT_EQ(Vector_Create(&marker->u.accumulatedValues), T2ERROR_SUCCESS);
}
ASSERT_EQ(Vector_PushBack(profile->eMarkerList, marker), T2ERROR_SUCCESS);
}

void TearDown() override {
EXPECT_EQ(ProfileXConf_uninit(), T2ERROR_SUCCESS);
profileXconfTestFixture::TearDown();
}
};

TEST_P(XconfMarkerStorageTest, StoresClassifiedValuesWithoutTrimming) {
const struct {
const char *value;
bool empty;
} cases[] = {
{" test log ", false}, {" xyz ", false}, {"NULLify", false},
{"", true}, {" ", true}, {"\t\r\n", true}, {"NULL", true}
};
for(const auto &testCase : cases) {
SCOPED_TRACE(testCase.value);
const bool retained = marker->reportEmptyParam || !testCase.empty;
if(marker->mType == MTYPE_XCONF_ACCUMULATE) {
Vector_Clear(marker->u.accumulatedValues, free);
ASSERT_EQ(Vector_PushBack(marker->u.accumulatedValues, strdup("previous")), T2ERROR_SUCCESS);
} else {
free(marker->u.markerValue);
marker->u.markerValue = strdup("previous");
}
T2Event event = {};
event.name = marker->markerName;
event.value = const_cast<char *>(testCase.value);
EXPECT_EQ(ProfileXConf_storeMarkerEvent(&event), T2ERROR_SUCCESS);
if(marker->mType == MTYPE_XCONF_ACCUMULATE) {
ASSERT_EQ(Vector_Size(marker->u.accumulatedValues), retained ? 2u : 1u);
EXPECT_STREQ(static_cast<char *>(Vector_At(marker->u.accumulatedValues, 0)), "previous");
if(retained) {
EXPECT_STREQ(static_cast<char *>(Vector_At(marker->u.accumulatedValues, 1)), testCase.value);
}
} else {
EXPECT_STREQ(marker->u.markerValue, retained ? testCase.value : "previous");
}
}
}

INSTANTIATE_TEST_SUITE_P(SubscriberValues, XconfMarkerStorageTest,
::testing::Combine(::testing::Values(MTYPE_XCONF_ABSOLUTE, MTYPE_XCONF_ACCUMULATE), ::testing::Bool()));

TEST_F(profileXconfTestFixture, ProfileXConf_OnDemandStatusSnapshot)
{
testing::InSequence sequence;
Expand Down
97 changes: 97 additions & 0 deletions source/test/reportgen/reportgenTest.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,8 @@ sigset_t blocking_signal;
#include "../mocks/rdklogMock.h"
#include <iostream>
#include <stdexcept>
#include <dlfcn.h>
#include <tuple>

using namespace std;
using ::testing::_;
Expand Down Expand Up @@ -1526,6 +1528,101 @@ TEST_F(reportgenTestFixture, encodeEventMarkersInJSON7)
Vector_Destroy(eventMarkerList, freeEMarker);
}

class MarkerReportFilterTest : public reportgenTestFixture,
public ::testing::WithParamInterface<std::tuple<bool, bool>> {
protected:
EventMarker marker = {};
Vector *markers = nullptr;
cJSON *report = nullptr;
void *jsonLibrary = nullptr;
cJSON *(*createArray)() = nullptr;
void (*deleteJson)(cJSON *) = nullptr;

void SetUp() override {
jsonLibrary = dlopen("libcjson.so.1", RTLD_NOW | RTLD_LOCAL);
ASSERT_NE(jsonLibrary, nullptr) << dlerror();
createArray = reinterpret_cast<cJSON *(*)()>(dlsym(jsonLibrary, "cJSON_CreateArray"));
auto createObject = reinterpret_cast<cJSON *(*)()>(dlsym(jsonLibrary, "cJSON_CreateObject"));
auto createString = reinterpret_cast<cJSON *(*)(const char *)>(
dlsym(jsonLibrary, "cJSON_CreateString"));
auto addString = reinterpret_cast<cJSON *(*)(cJSON *, const char *, const char *)>(
dlsym(jsonLibrary, "cJSON_AddStringToObject"));
auto addItem = reinterpret_cast<cJSON_bool (*)(cJSON *, cJSON *)>(
dlsym(jsonLibrary, "cJSON_AddItemToArray"));
deleteJson = reinterpret_cast<void (*)(cJSON *)>(dlsym(jsonLibrary, "cJSON_Delete"));
ASSERT_NE(createArray, nullptr);
ASSERT_NE(createObject, nullptr);
ASSERT_NE(createString, nullptr);
ASSERT_NE(addString, nullptr);
ASSERT_NE(addItem, nullptr);
ASSERT_NE(deleteJson, nullptr);
EXPECT_CALL(mock_IO, cJSON_CreateObject()).Times(::testing::AnyNumber())
.WillRepeatedly(::testing::Invoke(createObject));
EXPECT_CALL(mock_IO, cJSON_CreateString(_)).Times(::testing::AnyNumber())
.WillRepeatedly(::testing::Invoke(createString));
EXPECT_CALL(mock_IO, cJSON_AddStringToObject(_, _, _)).Times(::testing::AnyNumber())
.WillRepeatedly(::testing::Invoke(addString));
EXPECT_CALL(mock_IO, cJSON_AddItemToArray(_, _)).Times(::testing::AnyNumber())
.WillRepeatedly(::testing::Invoke(addItem));
EXPECT_CALL(mock_IO, cJSON_Delete(_)).Times(::testing::AnyNumber())
.WillRepeatedly(::testing::Invoke(deleteJson));
ASSERT_EQ(Vector_Create(&markers), T2ERROR_SUCCESS);
marker.markerName = strdup("StorageMarker");
marker.mType = MTYPE_ABSOLUTE;
marker.reportEmptyParam = std::get<0>(GetParam());
marker.trimParam = std::get<1>(GetParam());
ASSERT_EQ(Vector_PushBack(markers, &marker), T2ERROR_SUCCESS);
}

void TearDown() override {
if(deleteJson) {
deleteJson(report);
}
free(marker.u.markerValue);
free(marker.markerName);
Vector_Destroy(markers, nullptr);
if(jsonLibrary) {
dlclose(jsonLibrary);
}
}
};

TEST_P(MarkerReportFilterTest, SerializesRetainedValuesWithOptionalTrimming) {
const struct {
const char *value;
const char *trimmed;
bool empty;
} cases[] = {
{" test log ", "test log", false}, {" xyz ", "xyz", false},
{"NULLsuffix", "NULLsuffix", false}, {"", "", true},
{" ", "", true}, {"\t\r\n", "\r\n", true}, {"NULL", "NULL", true}
};
for(const auto &testCase : cases) {
SCOPED_TRACE(testCase.value);
report = createArray();
ASSERT_NE(report, nullptr);
marker.u.markerValue = strdup(testCase.value);
ASSERT_NE(marker.u.markerValue, nullptr);
EXPECT_EQ(encodeEventMarkersInJSON(report, markers), T2ERROR_SUCCESS);
Comment on lines +1604 to +1606
EXPECT_EQ(marker.u.markerValue, nullptr);
if(marker.reportEmptyParam || !testCase.empty) {
ASSERT_NE(report->child, nullptr);
EXPECT_EQ(report->child->next, nullptr);
ASSERT_NE(report->child->child, nullptr);
EXPECT_STREQ(report->child->child->string, marker.markerName);
EXPECT_STREQ(report->child->child->valuestring,
marker.trimParam ? testCase.trimmed : testCase.value);
} else {
EXPECT_EQ(report->child, nullptr);
}
deleteJson(report);
report = nullptr;
}
}

INSTANTIATE_TEST_SUITE_P(SubscriberValues, MarkerReportFilterTest,
::testing::Combine(::testing::Bool(), ::testing::Bool()));

TEST_F(reportgenTestFixture, encodeEventMarkersInJSON8)
{
cJSON *valArray = (cJSON *)malloc(sizeof(cJSON));
Expand Down
6 changes: 3 additions & 3 deletions test/functional-tests/tests/test_multiprofile_msgpacket.py
Original file line number Diff line number Diff line change
Expand Up @@ -272,9 +272,9 @@ def test_for_invalid_activation_timeout():
assert "TR_AC88" in grep_T2logs(ERROR_PROFILE_TIMEOUT) # Verify profile not set if activation timeout is less than reporting interval
assert "MODEL_NAME\":\"NULL" in grep_T2logs("cJSON Report ") # 239 - Support for reportEmpty of profiles
assert "TR_AC6919" in grep_T2logs("firstreporting interval is given") # 240 - Support for First Reporting Interval -1
assert "5 sec" in grep_T2logs("firstreporting interval is given") # 240 - Support for First Reporting Interval - 2
assert "NEW TEST PROFILE" in grep_T2logs(LOG_PROFILE_SET) # 101 - Report fetch and parse via HTTP
assert "60 sec" in grep_T2logs("reporting interval is taken - NEW TEST PROFILE") # 107 - Configurable reporting interval
assert "5 sec" in grep_T2logs("firstreporting interval is given") # 240 - Support for First Reporting Interval - 2/
assert "NEW_TEST_PROFILE" in grep_T2logs(LOG_PROFILE_SET) # 101 - Report fetch and parse via HTTP
assert "60 sec" in grep_T2logs("reporting interval is taken - NEW_TEST_PROFILE") # 107 - Configurable reporting interval
# 241 - Support for DCM profile and multiprofile parallel execution
assert "AccountId\":\"Platform_Container_Test_DEVICE" in grep_T2logs("cJSON Report ") # 102 - Include data from data source as TR181 Parameter
assert "SYS_GREP_TEST" in grep_T2logs("cJSON Report ") # 110, 111 - Data harvesting from previous logs folder for DCA profiles with log file search markers.
Expand Down
Loading
Loading