Skip to content

Commit

Permalink
Add some c api unit tests
Browse files Browse the repository at this point in the history
  • Loading branch information
erer1243 committed Oct 9, 2024
1 parent bc1c92f commit f79df58
Show file tree
Hide file tree
Showing 12 changed files with 317 additions and 21 deletions.
4 changes: 4 additions & 0 deletions common/c-api/dbconnector.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,10 @@ SWSSDBConnector SWSSDBConnector_new_unix(int32_t dbId, const char *sock_path, ui
SWSSTry(return (SWSSDBConnector) new DBConnector(dbId, string(sock_path), timeout));
}

SWSSDBConnector SWSSDBConnector_new_named(const char *dbName, uint32_t timeout_ms, uint8_t isTcpConn) {
SWSSTry(return (SWSSDBConnector) new DBConnector(string(dbName), timeout_ms, isTcpConn));
}

void SWSSDBConnector_free(SWSSDBConnector db) {
delete (DBConnector *)db;
}
Expand Down
13 changes: 8 additions & 5 deletions common/c-api/dbconnector.h
Original file line number Diff line number Diff line change
Expand Up @@ -16,10 +16,13 @@ typedef struct SWSSDBConnectorOpaque *SWSSDBConnector;

// Pass 0 to timeout for infinity
SWSSDBConnector SWSSDBConnector_new_tcp(int32_t dbId, const char *hostname, uint16_t port,
uint32_t timeout);
uint32_t timeout_ms);

// Pass 0 to timeout for infinity
SWSSDBConnector SWSSDBConnector_new_unix(int32_t dbId, const char *sock_path, uint32_t timeout);
SWSSDBConnector SWSSDBConnector_new_unix(int32_t dbId, const char *sock_path, uint32_t timeout_ms);

// Pass 0 to timeout for infinity
SWSSDBConnector SWSSDBConnector_new_named(const char *dbName, uint32_t timeout_ms, uint8_t isTcpConn);

void SWSSDBConnector_free(SWSSDBConnector db);

Expand All @@ -28,7 +31,7 @@ int8_t SWSSDBConnector_del(SWSSDBConnector db, const char *key);

void SWSSDBConnector_set(SWSSDBConnector db, const char *key, const char *value);

// Returns NULL if key doesn't exist
// Returns NULL if key doesn't exist.
// Result must be freed using free()
char *SWSSDBConnector_get(SWSSDBConnector db, const char *key);

Expand All @@ -41,11 +44,11 @@ int8_t SWSSDBConnector_hdel(SWSSDBConnector db, const char *key, const char *fie
void SWSSDBConnector_hset(SWSSDBConnector db, const char *key, const char *field,
const char *value);

// Returns NULL if key or field doesn't exist
// Returns NULL if key or field doesn't exist.
// Result must be freed using free()
char *SWSSDBConnector_hget(SWSSDBConnector db, const char *key, const char *field);

// Returns an empty map when the key doesn't exist
// Returns an empty map when the key doesn't exist.
// Result array and all of its elements must be freed using free()
SWSSFieldValueArray SWSSDBConnector_hgetall(SWSSDBConnector db, const char *key);

Expand Down
7 changes: 4 additions & 3 deletions common/c-api/subscriberstatetable.cpp
Original file line number Diff line number Diff line change
@@ -1,9 +1,9 @@
#include <cstdlib>
#include <cstring>
#include <deque>
#include <system_error>

#include "../dbconnector.h"
#include "../rediscommand.h"
#include "../subscriberstatetable.h"
#include "../table.h"
#include "subscriberstatetable.h"
Expand Down Expand Up @@ -46,6 +46,7 @@ uint8_t SWSSSubscriberStateTable_initializedWithData(SWSSSubscriberStateTable tb
SWSSTry(return ((SubscriberStateTable *)tbl)->initializedWithData() ? 1 : 0);
}

void SWSSSubscriberStateTable_readData(SWSSSubscriberStateTable tbl) {
SWSSTry(((SubscriberStateTable *)tbl)->readData());
SWSSSelectResult SWSSSubscriberStateTable_readData(SWSSSubscriberStateTable tbl,
unsigned int timeout_ms) {
SWSSTry(return selectOne((SubscriberStateTable *)tbl, timeout_ms));
}
5 changes: 4 additions & 1 deletion common/c-api/subscriberstatetable.h
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,10 @@ uint8_t SWSSSubscriberStateTable_hasCachedData(SWSSSubscriberStateTable tbl);
// Returns 0 for false, 1 for true
uint8_t SWSSSubscriberStateTable_initializedWithData(SWSSSubscriberStateTable tbl);

void SWSSSubscriberStateTable_readData(SWSSSubscriberStateTable tbl);
// Block until data is available to read or until a timeout elapses.
// A timeout of 0 means the call will return immediately.
SWSSSelectResult SWSSSubscriberStateTable_readData(SWSSSubscriberStateTable tbl,
unsigned int timeout_ms);

#ifdef __cplusplus
}
Expand Down
2 changes: 2 additions & 0 deletions common/c-api/util.cpp
Original file line number Diff line number Diff line change
@@ -1 +1,3 @@
#include "util.h"

bool swss::cApiTestingDisableAbort = false;
46 changes: 41 additions & 5 deletions common/c-api/util.h
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,12 @@ typedef struct {
const SWSSKeyOpFieldValues *data;
} SWSSKeyOpFieldValuesArray;

typedef enum {
SWSSSelectResult_DATA = 0,
SWSSSelectResult_TIMEOUT = 1,
SWSSSelectResult_SIGNAL = 2,
} SWSSSelectResult;

#ifdef __cplusplus
}
#endif
Expand All @@ -44,21 +50,49 @@ typedef struct {

#include "../logger.h"
#include "../rediscommand.h"
#include "../select.h"

using boost::numeric_cast;

namespace swss {

extern bool cApiTestingDisableAbort;

// In the catch block, we must abort because passing an exception across an ffi boundary is
// undefined behavior. It was also decided that no exceptions in swss-common are recoverable, so
// there is no reason to convert exceptions into a returnable type.
#define SWSSTry(...) \
try { \
if (cApiTestingDisableAbort) { \
{ __VA_ARGS__; } \
} catch (std::exception & e) { \
std::cerr << "Aborting due to exception: " << e.what() << std::endl; \
SWSS_LOG_ERROR("Aborting due to exception: %s", e.what()); \
std::abort(); \
} else { \
try { \
{ __VA_ARGS__; } \
} catch (std::exception & e) { \
std::cerr << "Aborting due to exception: " << e.what() << std::endl; \
SWSS_LOG_ERROR("Aborting due to exception: %s", e.what()); \
std::abort(); \
} \
}

static inline SWSSSelectResult selectOne(swss::Selectable *s, unsigned int timeout_ms) {
Select select;
Selectable *sOut;
select.addSelectable(s);
int ret = select.select(&sOut, numeric_cast<int>(timeout_ms));
switch (ret) {
case Select::OBJECT:
return SWSSSelectResult_DATA;
case Select::ERROR:
throw std::system_error(errno, std::generic_category());
case Select::TIMEOUT:
return SWSSSelectResult_TIMEOUT;
case Select::SIGNALINT:
return SWSSSelectResult_SIGNAL;
default:
SWSS_LOG_THROW("impossible: unhandled Select::select() return value: %d", ret);
}
}

// malloc() with safe numeric casting of the size parameter
template <class N> static inline void *mallocN(N size) {
return malloc(numeric_cast<size_t>(size));
Expand Down Expand Up @@ -141,5 +175,7 @@ takeKeyOpFieldValuesArray(const SWSSKeyOpFieldValuesArray &in) {
return out;
}

} // namespace swss

#endif
#endif
8 changes: 5 additions & 3 deletions common/c-api/zmqconsumerstatetable.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -36,8 +36,9 @@ int32_t SWSSZmqConsumerStateTable_getFd(SWSSZmqConsumerStateTable tbl) {
SWSSTry(return numeric_cast<int32_t>(((ZmqConsumerStateTable *)tbl)->getFd()));
}

uint64_t SWSSZmqConsumerStateTable_readData(SWSSZmqConsumerStateTable tbl) {
SWSSTry(return numeric_cast<uint64_t>(((ZmqConsumerStateTable *)tbl)->readData()));
SWSSSelectResult SWSSZmqConsumerStateTable_readData(SWSSZmqConsumerStateTable tbl,
unsigned int timeout_ms) {
SWSSTry(return selectOne((ZmqConsumerStateTable *)tbl, timeout_ms));
}

// Returns 0 for false, 1 for true
Expand All @@ -55,7 +56,8 @@ uint8_t SWSSZmqConsumerStateTable_initializedWithData(SWSSZmqConsumerStateTable
SWSSTry(return ((ZmqConsumerStateTable *)tbl)->hasData() ? 1 : 0);
}

const struct SWSSDBConnectorOpaque *SWSSZmqConsumerStateTable_getDbConnector(SWSSZmqConsumerStateTable tbl) {
const struct SWSSDBConnectorOpaque *
SWSSZmqConsumerStateTable_getDbConnector(SWSSZmqConsumerStateTable tbl) {
SWSSTry(return (const SWSSDBConnectorOpaque *)((ZmqConsumerStateTable *)tbl)->getDbConnector());
}

Expand Down
8 changes: 6 additions & 2 deletions common/c-api/zmqconsumerstatetable.h
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,10 @@ SWSSKeyOpFieldValuesArray SWSSZmqConsumerStateTable_pops(SWSSZmqConsumerStateTab

int32_t SWSSZmqConsumerStateTable_getFd(SWSSZmqConsumerStateTable tbl);

uint64_t SWSSZmqConsumerStateTable_readData(SWSSZmqConsumerStateTable tbl);
// Block until data is available to read or until a timeout elapses.
// A timeout of 0 means the call will return immediately.
SWSSSelectResult SWSSZmqConsumerStateTable_readData(SWSSZmqConsumerStateTable tbl,
unsigned int timeout_ms);

// Returns 0 for false, 1 for true
uint8_t SWSSZmqConsumerStateTable_hasData(SWSSZmqConsumerStateTable tbl);
Expand All @@ -37,7 +40,8 @@ uint8_t SWSSZmqConsumerStateTable_hasCachedData(SWSSZmqConsumerStateTable tbl);
// Returns 0 for false, 1 for true
uint8_t SWSSZmqConsumerStateTable_initializedWithData(SWSSZmqConsumerStateTable tbl);

const struct SWSSDBConnectorOpaque *SWSSZmqConsumerStateTable_getDbConnector(SWSSZmqConsumerStateTable tbl);
const struct SWSSDBConnectorOpaque *
SWSSZmqConsumerStateTable_getDbConnector(SWSSZmqConsumerStateTable tbl);

uint64_t SWSSZmqConsumerStateTable_dbUpdaterQueueSize(SWSSZmqConsumerStateTable tbl);

Expand Down
5 changes: 3 additions & 2 deletions common/zmqserver.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -106,9 +106,10 @@ void ZmqServer::mqPollThread()
int rc = zmq_bind(socket, m_endpoint.c_str());
if (rc != 0)
{
SWSS_LOG_THROW("zmq_bind failed on endpoint: %s, zmqerrno: %d",
SWSS_LOG_THROW("zmq_bind failed on endpoint: %s, zmqerrno: %d, message: %s",
m_endpoint.c_str(),
zmq_errno());
zmq_errno(),
strerror(zmq_errno()));
}

// zmq_poll will use less CPU
Expand Down
1 change: 1 addition & 0 deletions tests/Makefile.am
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,7 @@ tests_tests_SOURCES = tests/redis_ut.cpp \
tests/binary_serializer_ut.cpp \
tests/zmq_state_ut.cpp \
tests/profileprovider_ut.cpp \
tests/c_api_ut.cpp \
tests/main.cpp

tests_tests_CFLAGS = $(DBGFLAGS) $(AM_CFLAGS) $(CFLAGS_COMMON) $(CFLAGS_GTEST) $(LIBNL_CFLAGS)
Expand Down
Loading

0 comments on commit f79df58

Please sign in to comment.