Skip to content

Commit

Permalink
Make double-reference work for dynType, and improve dynType_print rob…
Browse files Browse the repository at this point in the history
…ustness and coverage.
  • Loading branch information
PengZheng committed Jan 9, 2024
1 parent dfc647c commit e84ac21
Show file tree
Hide file tree
Showing 4 changed files with 102 additions and 28 deletions.
18 changes: 18 additions & 0 deletions libs/dfi/gtest/src/dyn_type_ei_tests.cc
Original file line number Diff line number Diff line change
Expand Up @@ -172,3 +172,21 @@ TEST_F(DynTypeErrorInjectionTestSuite, SequenceReserveError) {
dynType_free(type, seq);
dynType_destroy(type);
}

TEST_F(DynTypeErrorInjectionTestSuite, TextAllocateError) {
dyn_type *type = NULL;
int rc = 0;
rc = dynType_parseWithStr("t", NULL, NULL, &type);
ASSERT_EQ(0, rc);
ASSERT_EQ(DYN_TYPE_TEXT, dynType_type(type));

char** val = nullptr;
rc = dynType_alloc(type, (void**)&val);
ASSERT_EQ(0, rc);
celix_ei_expect_strdup((void*)dynType_text_allocAndInit, 0, nullptr);
rc = dynType_text_allocAndInit(type, val, "test");
ASSERT_NE(0, rc);
ASSERT_STREQ("Cannot allocate memory for string", celix_err_popLastError());
dynType_free(type, val);
dynType_destroy(type);
}
55 changes: 52 additions & 3 deletions libs/dfi/gtest/src/dyn_type_tests.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -16,8 +16,9 @@
* specific language governing permissions and limitations
* under the License.
*/

#include "gtest/gtest.h"
#include "celix_stdio_cleanup.h"
#include "celix_stdlib_cleanup.h"

extern "C" {
#include "dyn_common.h"
Expand All @@ -30,6 +31,7 @@ extern "C" {
//printf("\n-- example %s with descriptor string '%s' --\n", exName, descriptorStr);
int status = dynType_parseWithStr(descriptorStr, exName, NULL, &type);
ASSERT_EQ(0, status);
ASSERT_STREQ(exName, dynType_getName(type));

//MEM check, to try to ensure no mem leaks/corruptions occur.
int i;
Expand Down Expand Up @@ -82,11 +84,17 @@ class DynTypeTests : public ::testing::Test {
#define EX15 "Tsample={jDD time val1 val2};Tresult={jDlsample; time result sample};Lresult;"
#define EX16 "Tpoi={BDD id lat lon};Lpoi;"
#define EX17 "{#v1=0;#v2=1;E#v1=9;#v2=10;E enum1 enum2}"
#define EX18 "Ttext=t;ltext;"
#define EX19 "Tsample={DD vala valb};Tref=lsample;;lref;"
#define EX20 "TINTEGER=I;Tsample={DlINTEGER; vala valb};Tref=lsample;;lref;"

#define CREATE_EXAMPLES_TEST(DESC) \
TEST_F(DynTypeTests, ParseTestExample ## DESC) { \
runTest(DESC, #DESC); \
}
} \
TEST_F(DynTypeTests, ParseTestExampleNoName ## DESC) { \
runTest(DESC, nullptr); \
}

CREATE_EXAMPLES_TEST(EX1)
CREATE_EXAMPLES_TEST(EX2)
Expand All @@ -101,10 +109,13 @@ CREATE_EXAMPLES_TEST(EX10)
CREATE_EXAMPLES_TEST(EX11)
CREATE_EXAMPLES_TEST(EX12)
CREATE_EXAMPLES_TEST(EX13)
//CREATE_EXAMPLES_TEST(EX14)
CREATE_EXAMPLES_TEST(EX14)
CREATE_EXAMPLES_TEST(EX15)
CREATE_EXAMPLES_TEST(EX16)
CREATE_EXAMPLES_TEST(EX17)
CREATE_EXAMPLES_TEST(EX18)
CREATE_EXAMPLES_TEST(EX19)
CREATE_EXAMPLES_TEST(EX20)

TEST_F(DynTypeTests, ParseRandomGarbageTest) {
/*
Expand Down Expand Up @@ -223,6 +234,17 @@ TEST_F(DynTypeTests, MetaInfoTest) {

ASSERT_EQ(0, rc);

auto entries = dynType_metaEntries(type);
struct meta_entry* entry = NULL;
size_t nbEntries = 0;
TAILQ_FOREACH(entry, entries, entries) {
nbEntries++;
ASSERT_STREQ("a", entry->name);
ASSERT_STREQ("t", entry->value);
}
ASSERT_EQ(1, nbEntries);


const char *val = NULL;
val = dynType_getMetaInfo(type, "a");
ASSERT_TRUE(val != NULL);
Expand Down Expand Up @@ -399,6 +421,33 @@ TEST_F(DynTypeTests, EnumTest) {
dynType_destroy(type);
}


TEST_F(DynTypeTests, PrintNullTypeTest) {
celix_autofree char* buf = nullptr;
size_t bufSize = 0;
celix_autoptr(FILE) result = open_memstream(&buf, &bufSize);
dynType_print(nullptr, result);
fflush(result);
ASSERT_STREQ("invalid type\n", buf);
}

TEST_F(DynTypeTests, TextTest) {
dyn_type *type = NULL;
int rc = 0;
rc = dynType_parseWithStr("t", NULL, NULL, &type);
ASSERT_EQ(0, rc);
ASSERT_EQ(DYN_TYPE_TEXT, dynType_type(type));

char** val = nullptr;
rc = dynType_alloc(type, (void**)&val);
ASSERT_EQ(0, rc);
rc = dynType_text_allocAndInit(type, val, "test");
ASSERT_EQ(0, rc);
ASSERT_STREQ("test", *val);
dynType_free(type, val);
dynType_destroy(type);
}

TEST_F(DynTypeTests, NrOfEntriesTest) {
dyn_type *type = NULL;
int rc = dynType_parseWithStr("{DD}", NULL, NULL, &type);
Expand Down
53 changes: 30 additions & 23 deletions libs/dfi/src/dyn_type.c
Original file line number Diff line number Diff line change
Expand Up @@ -59,11 +59,12 @@ static void dynType_printSequence(const char* name, const dyn_type* type, int de
static void dynType_printSimple(const char* name, const dyn_type* type, int depth, FILE* stream);
static void dynType_printEnum(const char* name, const dyn_type* type, int depth, FILE* stream);
static void dynType_printTypedPointer(const char* name, const dyn_type* type, int depth, FILE* stream);
static void dynType_printText(const char* name, const dyn_type* type, int depth, FILE* stream);
static void dynType_printDepth(int depth, FILE* stream);

static void dynType_printTypes(const dyn_type* type, FILE* stream);
static void dynType_printComplexType(dyn_type* type, FILE* stream);
static void dynType_printSimpleType(dyn_type* type, FILE* stream);
static void dynType_printComplexType(const dyn_type* type, FILE* stream);
static void dynType_printSimpleType(const dyn_type* type, FILE* stream);

static int dynType_parseText(FILE* stream, dyn_type* type);
static int dynType_parseEnum(FILE* stream, dyn_type* type);
Expand Down Expand Up @@ -534,7 +535,7 @@ const dyn_type* dynType_complex_dynTypeAt(const dyn_type* type, int index) {
assert(type->type == DYN_TYPE_COMPLEX);
assert(index >= 0);
dyn_type* sub = type->complex.types[index];
if (sub->type == DYN_TYPE_REF) {
while (sub->type == DYN_TYPE_REF) {
sub = sub->ref.ref;
}
return sub;
Expand Down Expand Up @@ -728,7 +729,7 @@ int dynType_sequence_increaseLengthAndReturnLastLoc(const dyn_type* type, void*
const dyn_type* dynType_sequence_itemType(const dyn_type* type) {
assert(type->type == DYN_TYPE_SEQUENCE);
dyn_type *itemType = type->sequence.itemType;
if (itemType->type == DYN_TYPE_REF) {
while (itemType->type == DYN_TYPE_REF) {
itemType = itemType->ref.ref;
}
return itemType;
Expand Down Expand Up @@ -835,7 +836,7 @@ static unsigned short dynType_getOffset(const dyn_type* type, int index) {

size_t dynType_size(const dyn_type* type) {
const dyn_type* rType = type;
if (type->type == DYN_TYPE_REF) {
while (rType->type == DYN_TYPE_REF) {
rType = type->ref.ref;
}
return rType->ffiType->size;
Expand All @@ -848,7 +849,7 @@ int dynType_type(const dyn_type* type) {
const dyn_type* dynType_typedPointer_getTypedType(const dyn_type* type) {
assert(type->type == DYN_TYPE_TYPED_POINTER);
dyn_type* typedType = type->typedPointer.typedType;
if (typedType->type == DYN_TYPE_REF) {
while (typedType->type == DYN_TYPE_REF) {
typedType = typedType->ref.ref;
}
return typedType;
Expand All @@ -857,22 +858,16 @@ const dyn_type* dynType_typedPointer_getTypedType(const dyn_type* type) {

int dynType_text_allocAndInit(const dyn_type* type, void* textLoc, const char* value) {
assert(type->type == DYN_TYPE_TEXT);
int status = 0;
const char* str = strdup(value);
char const** loc = textLoc;
if (str != NULL) {
*loc = str;
} else {
status = ERROR;
if (str == NULL) {
celix_err_pushf("Cannot allocate memory for string");
return MEM_ERROR;
}
return status;
*loc = str;
return OK;
}





void dynType_print(const dyn_type *type, FILE *stream) {
if (type != NULL) {
dynType_printTypes(type, stream);
Expand All @@ -893,9 +888,10 @@ static void dynType_printDepth(int depth, FILE *stream) {

static void dynType_printAny(const char* name, const dyn_type* type, int depth, FILE *stream) {
const dyn_type* toPrint = type;
if (toPrint->type == DYN_TYPE_REF) {
while (toPrint->type == DYN_TYPE_REF) {
toPrint = toPrint->ref.ref;
}
name = (name != NULL) ? name : "(unnamed)";
switch(toPrint->type) {
case DYN_TYPE_COMPLEX :
dynType_printComplex(name, toPrint, depth, stream);
Expand All @@ -909,9 +905,14 @@ static void dynType_printAny(const char* name, const dyn_type* type, int depth,
case DYN_TYPE_TYPED_POINTER :
dynType_printTypedPointer(name, toPrint, depth, stream);
break;
case DYN_TYPE_TEXT:
dynType_printText(name, toPrint, depth, stream);
break;
//LCOV_EXCL_START
default :
fprintf(stream, "TODO Unsupported type %d\n", toPrint->type);
assert(0 && "Unexpected switch case. cannot print dyn type");
break;
//LCOV_EXCL_STOP
}
}

Expand Down Expand Up @@ -990,6 +991,12 @@ static void dynType_printTypedPointer(const char* name, const dyn_type* type, in
dynType_printAny(subName, type->typedPointer.typedType, depth + 1, stream);
}

static void dynType_printText(const char* name, const dyn_type* type, int depth, FILE* stream) {
dynType_printDepth(depth, stream);
fprintf(stream, "%s: text type, size is %zu, alignment is %i, descriptor is '%c'.\n",
name, type->ffiType->size, type->ffiType->alignment, type->descriptor);
}

static void dynType_printTypes(const dyn_type* type, FILE* stream) {

dyn_type* parent = type->parent;
Expand All @@ -1006,7 +1013,7 @@ static void dynType_printTypes(const dyn_type* type, FILE* stream) {
struct type_entry* entry = NULL;
TAILQ_FOREACH(entry, &type->nestedTypesHead, entries) {
dyn_type* toPrint = entry->type;
if (toPrint->type == DYN_TYPE_REF) {
while (toPrint->type == DYN_TYPE_REF) {
toPrint = toPrint->ref.ref;
}

Expand All @@ -1018,7 +1025,7 @@ static void dynType_printTypes(const dyn_type* type, FILE* stream) {
dynType_printSimpleType(toPrint, stream);
break;
default :
printf("TODO Print Type\n");
printf("TODO Print Type %d\n", toPrint->type);
break;
}
}
Expand All @@ -1040,7 +1047,7 @@ static void dynType_printTypes(const dyn_type* type, FILE* stream) {
}
}

static void dynType_printComplexType(dyn_type *type, FILE *stream) {
static void dynType_printComplexType(const dyn_type *type, FILE *stream) {
fprintf(stream, "type '%s': complex type, size is %zu, alignment is %i, descriptor is '%c'. fields:\n", type->name, type->ffiType->size, type->ffiType->alignment, type->descriptor);

struct complex_type_entry *entry = NULL;
Expand All @@ -1051,7 +1058,7 @@ static void dynType_printComplexType(dyn_type *type, FILE *stream) {
fprintf(stream, "}\n");
}

static void dynType_printSimpleType(dyn_type *type, FILE *stream) {
fprintf(stream, "\ttype '%s': simple type, size is %zu, alignment is %i, descriptor is '%c'\n", type->name, type->ffiType->size, type->ffiType->alignment, type->descriptor);
static void dynType_printSimpleType(const dyn_type *type, FILE *stream) {
fprintf(stream, "type '%s': simple type, size is %zu, alignment is %i, descriptor is '%c'\n", type->name, type->ffiType->size, type->ffiType->alignment, type->descriptor);
}

4 changes: 2 additions & 2 deletions libs/dfi/src/dyn_type_common.c
Original file line number Diff line number Diff line change
Expand Up @@ -52,8 +52,8 @@ dyn_type* dynType_findType(dyn_type *type, char *name) {
}

ffi_type * dynType_ffiType(dyn_type * type) {
if (type->type == DYN_TYPE_REF) {
return type->ref.ref->ffiType;
while (type->type == DYN_TYPE_REF) {
type = type->ref.ref;
}
return type->ffiType;
}
Expand Down

0 comments on commit e84ac21

Please sign in to comment.