Skip to content

Commit

Permalink
Treat unknown complex member as error when parsing and refactor json …
Browse files Browse the repository at this point in the history
…deserialization.
  • Loading branch information
PengZheng committed Jan 15, 2024
1 parent 86a9095 commit 4c2b4d4
Show file tree
Hide file tree
Showing 6 changed files with 141 additions and 173 deletions.
1 change: 1 addition & 0 deletions libs/dfi/gtest/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,7 @@ if (EI_TESTS)
src/dyn_type_ei_tests.cc
src/dyn_message_ei_tests.cc
src/dyn_function_ei_tests.cc
src/json_serializer_ei_tests.cc
)
target_link_libraries(test_dfi_with_ei PRIVATE
dfi_cut
Expand Down
54 changes: 1 addition & 53 deletions libs/dfi/gtest/src/json_rpc_tests.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -879,54 +879,6 @@ extern "C" {
free(result);


dynInterface_destroy(intf);
}

void testResponseForwardCompatibility(void) {
dyn_interface_type *intf = nullptr;
FILE *desc = fopen("descriptors/example6.descriptor", "r");
ASSERT_TRUE(desc != nullptr);
int rc = dynInterface_parse(desc, &intf);
ASSERT_EQ(0, rc);
fclose(desc);

const struct methods_head* head = dynInterface_methods(intf);
dyn_function_type *func = nullptr;
struct method_entry *entry = nullptr;
TAILQ_FOREACH(entry, head, entries) {
if (strcmp(dynFunction_getName(entry->dynFunc), "cpt") == 0) {
func = entry->dynFunc;
break;
}
}
ASSERT_TRUE(func != nullptr);

struct tst_CptData *cptData{nullptr};
void *out = &cptData;

void *args[3];
args[0] = nullptr;
args[1] = nullptr;
args[2] = &out;
int rsErrno = 0;

//provider has more reply
rc = jsonRpc_handleReply(func, R"({"r":{"d":1.0, "t":"hello compatibility", "s":[1.0,2.0,3.0], "e":"v1", "e2":"v2"}})", args, &rsErrno);
EXPECT_EQ(0, rc);
EXPECT_EQ(0, rsErrno);
EXPECT_NE(cptData , nullptr);
EXPECT_EQ(cptData->d , 1.0);
EXPECT_STREQ(cptData->t , "hello compatibility");
EXPECT_EQ(cptData->s.len , 3);
EXPECT_EQ(cptData->s.cap , 3);
EXPECT_EQ(cptData->s.buf[0] , 1.0);
EXPECT_EQ(cptData->s.buf[1] , 2.0);
EXPECT_EQ(cptData->s.buf[2] , 3.0);
EXPECT_EQ(cptData->e , v1);
free(cptData->t);
free(cptData->s.buf);
free(cptData);

dynInterface_destroy(intf);
}
}
Expand Down Expand Up @@ -1035,8 +987,4 @@ TEST_F(JsonRpcTests, callTestConstChar) {

TEST_F(JsonRpcTests, testRequestBackwardCompatibility) {
testRequestBackwardCompatibility();
}

TEST_F(JsonRpcTests, testResponseForwardCompatibility) {
testResponseForwardCompatibility();
}
}
53 changes: 53 additions & 0 deletions libs/dfi/gtest/src/json_serializer_ei_tests.cc
Original file line number Diff line number Diff line change
@@ -0,0 +1,53 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*/

#include "json_serializer.h"
#include "dyn_type.h"
#include "celix_err.h"
#include "malloc_ei.h"

#include <gtest/gtest.h>

class JsonSerializerErrorInjectionTestSuite : public ::testing::Test {
public:
JsonSerializerErrorInjectionTestSuite() = default;
~JsonSerializerErrorInjectionTestSuite() override {
celix_ei_expect_calloc(nullptr, 0, nullptr);
celix_err_resetErrors();
}
};

TEST_F(JsonSerializerErrorInjectionTestSuite, SerilizationError) {
int rc;
dyn_type *type;
void *inst;

//simple string
type = nullptr;
inst = nullptr;
rc = dynType_parseWithStr("t", nullptr, nullptr, &type);
ASSERT_EQ(0, rc);
auto inputStr = R"("hello")";
celix_ei_expect_calloc((void*) dynType_alloc, 0, nullptr);
rc = jsonSerializer_deserialize(type, inputStr, strlen(inputStr), &inst);
ASSERT_NE(0, rc);
EXPECT_STREQ("Error cannot deserialize json. Input is '\"hello\"'", celix_err_popLastError());
EXPECT_STREQ("Error allocating memory for type 't'", celix_err_popLastError());
dynType_destroy(type);
}
19 changes: 19 additions & 0 deletions libs/dfi/gtest/src/json_serializer_tests.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -559,6 +559,25 @@ static void parseTests() {
ASSERT_EQ(1, rc);
celix_err_printErrors(stderr, nullptr, nullptr);
dynType_destroy(type);

// unknown member
rc = dynType_parseWithStr("{t a}", nullptr, nullptr, &type);
ASSERT_EQ(0, rc);
inputStr = R"({"a":"hello", "b":"world"})";
rc = jsonSerializer_deserialize(type, inputStr, strlen(inputStr), &inst);
ASSERT_EQ(1, rc);
celix_err_printErrors(stderr, nullptr, nullptr);
dynType_destroy(type);

//simple string
rc = dynType_parseWithStr("t", nullptr, nullptr, &type);
ASSERT_EQ(0, rc);
inputStr = R"("hello")";
rc = jsonSerializer_deserialize(type, inputStr, strlen(inputStr), &inst);
ASSERT_EQ(0, rc);
EXPECT_STREQ("hello", *(char**)inst);
dynType_free(type, inst);
dynType_destroy(type);
}

/*********** write example 1 ************************/
Expand Down
16 changes: 9 additions & 7 deletions libs/dfi/include/json_serializer.h
Original file line number Diff line number Diff line change
Expand Up @@ -31,19 +31,21 @@ extern "C" {
#endif

/**
* @brief Deserialize a JSON string to a given type.
* @brief Deserialize a JSON string buffer to a given type.
* @note The string buffer doesn't need to be null-terminated.
*
* Caller is the owner of the out parameter and should release it using dynType_free.
*
* In case of an error, an error message is added to celix_err.
*
* @param[in] type The type to deserialize to.
* @param[in] input The JSON string to deserialize.
* @param[out] out The deserialized result.
* @param[in] input The JSON string buffer to deserialize.
* @param[in] length The length of the given JSON string buffer.
* @param[out] result The deserialized result.
* @return 0 if successful, otherwise 1.
*
*/
CELIX_DFI_EXPORT int jsonSerializer_deserialize(dyn_type *type, const char *input, size_t length, void **result);
CELIX_DFI_EXPORT int jsonSerializer_deserialize(const dyn_type* type, const char* input, size_t length, void** result);

/**
* @brief Deserialize a JSON object to a given type.
Expand All @@ -58,7 +60,7 @@ CELIX_DFI_EXPORT int jsonSerializer_deserialize(dyn_type *type, const char *inpu
* @return 0 if successful, otherwise 1.
*
*/
CELIX_DFI_EXPORT int jsonSerializer_deserializeJson(const dyn_type *type, json_t *input, void **result);
CELIX_DFI_EXPORT int jsonSerializer_deserializeJson(const dyn_type* type, json_t* input, void** result);

/**
* @brief Serialize a given type to a JSON string.
Expand All @@ -73,7 +75,7 @@ CELIX_DFI_EXPORT int jsonSerializer_deserializeJson(const dyn_type *type, json_t
* @return 0 if successful, otherwise 1.
*
*/
CELIX_DFI_EXPORT int jsonSerializer_serialize(dyn_type *type, const void* input, char **output);
CELIX_DFI_EXPORT int jsonSerializer_serialize(const dyn_type* type, const void* input, char** output);

/**
* @brief Serialize a given type to a JSON object.
Expand All @@ -88,7 +90,7 @@ CELIX_DFI_EXPORT int jsonSerializer_serialize(dyn_type *type, const void* input,
* @return 0 if successful, otherwise 1.
*
*/
CELIX_DFI_EXPORT int jsonSerializer_serializeJson(const dyn_type *type, const void* input, json_t **out);
CELIX_DFI_EXPORT int jsonSerializer_serializeJson(const dyn_type* type, const void* input, json_t** out);

#ifdef __cplusplus
}
Expand Down
Loading

0 comments on commit 4c2b4d4

Please sign in to comment.