Skip to content
Merged
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: 9 additions & 0 deletions source/protocol/http/curlinterface.c
Original file line number Diff line number Diff line change
Expand Up @@ -639,6 +639,15 @@ typedef size_t (*WriteToFileFunc)(void *, size_t, size_t, void *);
typedef T2ERROR (*SetHeaderFunc)(CURL *, const char *, struct curl_slist **, childResponse *);
typedef T2ERROR (*SetMtlsHeadersFunc)(CURL *, const char *, const char *, childResponse *);
typedef T2ERROR (*SetPayloadFunc)(CURL *, const char *, childResponse *);
pthread_mutex_t* getCurlFileMutex(void)
{
return &curlFileMutex;
}
typedef void (*sendOverHTTPInitFunc)();
sendOverHTTPInitFunc sendOverHTTPInitFuncCallback()
{
return sendOverHTTPInit;
}
WriteToFileFunc getWriteToFileCallback()
{
return writeToFile;
Expand Down
13 changes: 13 additions & 0 deletions source/protocol/rbusMethod/rbusmethodinterface.c
Original file line number Diff line number Diff line change
Expand Up @@ -175,3 +175,16 @@ T2ERROR sendCachedReportsOverRBUSMethod(char *methodName, Vector* inputParams, V
T2Debug("%s --out\n", __FUNCTION__);
return T2ERROR_SUCCESS;
}

#ifdef GTEST_ENABLE
pthread_mutex_t* getRbusMethodMutex(void)
{
return &rbusMethodMutex;
}

typedef void (*asyncMethodHandlerFunc)(rbusHandle_t, char const*, rbusError_t, rbusObject_t);
asyncMethodHandlerFunc asyncMethodHandlerFuncCallback(void)
{
return asyncMethodHandler;
}
#endif
105 changes: 105 additions & 0 deletions source/test/protocol/ProtocolTest.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -626,6 +626,29 @@ TEST_F(protocolTestFixture, CURLINTERFACE_STATIC_SetHeader_setopt_failure)
EXPECT_EQ(resp.curlSetopCode, CURLE_FAILED_INIT);
}

TEST_F(protocolTestFixture, CURLINTERFACE_STATIC_SetHeader_FirstSetopt_failure_lineNumber)
{
SetHeaderFunc setHeaderCb = getSetHeaderCallback();
ASSERT_NE(setHeaderCb, nullptr);

CURL *curl = (CURL*)0x1;
const char *destURL = "http://localhost";
struct curl_slist *headerList = nullptr;
childResponse resp;
memset(&resp, 0, sizeof(resp));

// The very first curl_easy_setopt_mock call returns CURLE_FAILED_INIT.
EXPECT_CALL(*g_fileIOMock, curl_easy_setopt_mock(_,_,_))
.Times(1)
.WillOnce(Return(CURLE_FAILED_INIT));

T2ERROR code = setHeaderCb(curl, destURL, &headerList, &resp);
EXPECT_EQ(code, T2ERROR_FAILURE);
EXPECT_EQ(resp.curlSetopCode, CURLE_FAILED_INIT);
// Assert that lineNumber field gets set. (Should match the __LINE__ where the macro is expanded; we test it's nonzero.)
EXPECT_NE(resp.lineNumber, 0);
}

TEST_F(protocolTestFixture, CURLINTERFACE_STATIC_SetMtlsHeaders_setopt_failure)
{
SetMtlsHeadersFunc cb = getSetMtlsHeadersCallback();
Expand Down Expand Up @@ -764,6 +787,40 @@ TEST_F(protocolTestFixture, CURLINTERFACE_STATIC_SetHeader_HTTPHEADER_failure)
EXPECT_EQ(resp.curlSetopCode, CURLE_COULDNT_CONNECT);
}

TEST_F(protocolTestFixture, CURLINTERFACE_STATIC_SetHeader_HTTPHEADER_failure_block)
{
SetHeaderFunc setHeaderCb = getSetHeaderCallback();
ASSERT_NE(setHeaderCb, nullptr);

CURL *curl = (CURL*)0x1;
const char *destURL = "http://localhost";
struct curl_slist *headerList = nullptr;
childResponse resp;
memset(&resp, 0, sizeof(resp));

// Simulate curl_slist_append returns
EXPECT_CALL(*g_fileIOMock, curl_slist_append(_, _))
.Times(2)
.WillRepeatedly(Return((struct curl_slist*)0x1));

// Mock all prior curl_easy_setopt calls to return OK, only HTTPHEADER fails
::testing::Sequence s;
EXPECT_CALL(*g_fileIOMock, curl_easy_setopt_mock(_, ::testing::Ne(CURLOPT_HTTPHEADER), _))
.Times(::testing::AtLeast(1))
.InSequence(s)
.WillRepeatedly(Return(CURLE_OK));
EXPECT_CALL(*g_fileIOMock, curl_easy_setopt_mock(_, CURLOPT_HTTPHEADER, _))
.InSequence(s)
.WillOnce(Return(CURLE_COULDNT_CONNECT)); // Simulate failure at HTTPHEADER

T2ERROR result = setHeaderCb(curl, destURL, &headerList, &resp);

EXPECT_EQ(result, T2ERROR_FAILURE);
EXPECT_EQ(resp.curlSetopCode, CURLE_COULDNT_CONNECT);
// Should be set to a non-zero line number corresponding to line 166 in your source
EXPECT_NE(resp.lineNumber, 0);
}

TEST_F(protocolTestFixture, CURLINTERFACE_STATIC_SetHeader_WRITEFUNCTION_failure)
{
SetHeaderFunc setHeaderCb = getSetHeaderCallback();
Expand Down Expand Up @@ -958,3 +1015,51 @@ TEST_F(protocolTestFixture, CURLINTERFACE_STATIC_SetHeader_SUCCESS)
EXPECT_NE(headerList, nullptr);
}
#endif

#ifdef GTEST_ENABLE
extern "C" {
pthread_mutex_t* getRbusMethodMutex(void);
pthread_mutex_t* getCurlFileMutex(void);
typedef void (*sendOverHTTPInitFunc)();
sendOverHTTPInitFunc sendOverHTTPInitFuncCallback();

typedef void (*asyncMethodHandlerFunc)(rbusHandle_t,char const*,rbusError_t,rbusObject_t);
asyncMethodHandlerFunc asyncMethodHandlerFuncCallback(void);
}

TEST(CurlInterface_Static, SendOverHTTPInit_CoversMutexInit)
{
// Get function pointer to static sendOverHTTPInit
auto fn = sendOverHTTPInitFuncCallback();
ASSERT_NE(fn, nullptr);
fn();
// Check that the mutex is initialized (trylock succeeds or returns expected error if already locked)
pthread_mutex_t *pmutex = getCurlFileMutex();
int trylock_result = pthread_mutex_trylock(pmutex);
// Accept either success (0) or busy (EBUSY) as initialized.
EXPECT_TRUE(trylock_result == 0 || trylock_result == EBUSY);

if (trylock_result == 0) { // If locked, unlock for cleanup
pthread_mutex_unlock(pmutex);
}

pthread_mutex_destroy(pmutex);
}
TEST(AsyncMethodHandlerFunc, CoversAllBranches)
{
// Access and initialize the mutex defined in the C module
pthread_mutex_t* pmutex = getRbusMethodMutex();
pthread_mutex_init(pmutex, NULL);

// Get function pointer for static asyncMethodHandler
auto fn = asyncMethodHandlerFuncCallback();
ASSERT_NE(fn, nullptr);

// Success branch: sets isRbusMethod = true and unlocks
fn(NULL, "TestMethodSuccess", RBUS_ERROR_SUCCESS, NULL);
// Error branch: sets isRbusMethod = false and unlocks
fn(NULL, "TestMethodFail", RBUS_ERROR_BUS_ERROR, NULL);

pthread_mutex_destroy(pmutex);
}
#endif
Loading