* Copyright (c) 2025 Huawei Technologies Co., Ltd.
* This program is free software, you can redistribute it and/or modify it under the terms and conditions of
* CANN Open Software License Agreement Version 2.0 (the "License").
* Please refer to the License for details. You may not use this file except in compliance with the License.
* THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND, EITHER EXPRESS OR IMPLIED,
* INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT, MERCHANTABILITY, OR FITNESS FOR A PARTICULAR PURPOSE.
* See LICENSE in the root of the software repository for the full text of the License.
*/
#include <memory>
#include <fstream>
#include <string>
#include "json_parser.h"
using namespace testing;
class UtestJsonParseTest : public testing::Test {
protected:
void SetUp() {
}
void TearDown() {
}
};
TEST_F(UtestJsonParseTest, JsonParseCaseBasicNull) {
const char *json = "null";
CJsonObj *jsonObj = CJsonParse(json, strlen(json));
ASSERT_TRUE((jsonObj != NULL));
ASSERT_TRUE(CJsonIsNull(jsonObj));
FreeCJsonObj(jsonObj);
}
TEST_F(UtestJsonParseTest, JsonParseCaseBasicTrue) {
const char *json = "true";
CJsonObj *jsonObj = CJsonParse(json, strlen(json));
ASSERT_TRUE((jsonObj != NULL));
ASSERT_TRUE(CJsonIsBool(jsonObj));
ASSERT_TRUE(GetCJsonBool(jsonObj));
FreeCJsonObj(jsonObj);
}
TEST_F(UtestJsonParseTest, JsonParseCaseBasicFalse) {
const char *json = "false";
CJsonObj *jsonObj = CJsonParse(json, strlen(json));
ASSERT_TRUE((jsonObj != NULL));
ASSERT_TRUE(CJsonIsBool(jsonObj));
ASSERT_FALSE(GetCJsonBool(jsonObj));
FreeCJsonObj(jsonObj);
}
TEST_F(UtestJsonParseTest, JsonParseCaseBasicNumber) {
const char *json = "123";
CJsonObj *jsonObj = CJsonParse(json, strlen(json));
ASSERT_TRUE((jsonObj != NULL));
ASSERT_TRUE(CJsonIsInt(jsonObj));
EXPECT_EQ(GetCJsonInt(jsonObj), 123);
FreeCJsonObj(jsonObj);
}
TEST_F(UtestJsonParseTest, JsonParseCaseBasicNegativeNumber) {
const char *json = "-123";
CJsonObj *jsonObj = CJsonParse(json, strlen(json));
ASSERT_TRUE((jsonObj != NULL));
ASSERT_TRUE(CJsonIsInt(jsonObj));
EXPECT_EQ(GetCJsonInt(jsonObj), -123);
FreeCJsonObj(jsonObj);
}
TEST_F(UtestJsonParseTest, JsonParseCaseBasicPositiveNumber) {
const char *json = "+123";
CJsonObj *jsonObj = CJsonParse(json, strlen(json));
ASSERT_TRUE((jsonObj != NULL));
ASSERT_TRUE(CJsonIsInt(jsonObj));
EXPECT_EQ(GetCJsonInt(jsonObj), 123);
FreeCJsonObj(jsonObj);
}
TEST_F(UtestJsonParseTest, JsonParseCaseBasicDecimal) {
const char *json = "1.23";
CJsonObj *jsonObj = CJsonParse(json, strlen(json));
ASSERT_TRUE((jsonObj != NULL));
ASSERT_TRUE(CJsonIsDouble(jsonObj));
EXPECT_EQ(GetCJsonDouble(jsonObj), 1.23);
FreeCJsonObj(jsonObj);
}
TEST_F(UtestJsonParseTest, JsonParseCaseBasicNegativeExp) {
const char *json = "1.23e-2";
CJsonObj *jsonObj = CJsonParse(json, strlen(json));
ASSERT_TRUE((jsonObj != NULL));
ASSERT_TRUE(CJsonIsDouble(jsonObj));
double value = GetCJsonDouble(jsonObj);
EXPECT_TRUE(((value > 0.0122) && (value < 0.0124)));
FreeCJsonObj(jsonObj);
}
TEST_F(UtestJsonParseTest, JsonParseCaseBasicPositiveExp) {
const char *json = "1.23e2";
CJsonObj *jsonObj = CJsonParse(json, strlen(json));
ASSERT_TRUE((jsonObj != NULL));
ASSERT_TRUE(CJsonIsDouble(jsonObj));
double value = GetCJsonDouble(jsonObj);
EXPECT_TRUE(((value > 122) && (value < 124)));
FreeCJsonObj(jsonObj);
}
TEST_F(UtestJsonParseTest, JsonParseCaseBasicUpperExp) {
const char *json = "1.23E2";
CJsonObj *jsonObj = CJsonParse(json, strlen(json));
ASSERT_TRUE((jsonObj != NULL));
ASSERT_TRUE(CJsonIsDouble(jsonObj));
double value = GetCJsonDouble(jsonObj);
EXPECT_TRUE(((value > 122) && (value < 124)));
FreeCJsonObj(jsonObj);
}
TEST_F(UtestJsonParseTest, JsonParseCaseBasicString) {
const char *json = "\"123\"";
CJsonObj *jsonObj = CJsonParse(json, strlen(json));
ASSERT_TRUE((jsonObj != NULL));
ASSERT_TRUE(CJsonIsString(jsonObj));
ASSERT_STREQ(GetCJsonString(jsonObj), "123");
FreeCJsonObj(jsonObj);
}
TEST_F(UtestJsonParseTest, JsonParseCaseBasicInvalidString) {
const char *json = "\"\\123\"";
CJsonObj *jsonObj = CJsonParse(json, strlen(json));
ASSERT_TRUE((jsonObj == NULL));
}
TEST_F(UtestJsonParseTest, JsonParseCaseBasicStringWithFrontQuotation) {
const char *json = "\"\\\"123\"";
CJsonObj *jsonObj = CJsonParse(json, strlen(json));
ASSERT_TRUE((jsonObj != NULL));
ASSERT_TRUE(CJsonIsString(jsonObj));
ASSERT_STREQ(GetCJsonString(jsonObj), "\"123");
FreeCJsonObj(jsonObj);
}
TEST_F(UtestJsonParseTest, JsonParseCaseBasicInvalidWithBackQuotation) {
const char *json = "123\"";
CJsonObj *jsonObj = CJsonParse(json, strlen(json));
ASSERT_TRUE((jsonObj == NULL));
}
TEST_F(UtestJsonParseTest, JsonParseCaseBasicInvalidWithFrontBracket) {
const char *json = "[123";
CJsonObj *jsonObj = CJsonParse(json, strlen(json));
ASSERT_TRUE((jsonObj == NULL));
}
TEST_F(UtestJsonParseTest, JsonParseCaseBasicInvalidWithFrontCurlyBraces) {
const char *json = "{123";
CJsonObj *jsonObj = CJsonParse(json, strlen(json));
ASSERT_TRUE((jsonObj == NULL));
}
TEST_F(UtestJsonParseTest, JsonParseCaseBasicInvalidWithSlash) {
const char *json = "\\123";
CJsonObj *jsonObj = CJsonParse(json, strlen(json));
ASSERT_TRUE((jsonObj == NULL));
}
#if 0
TEST_F(UtestJsonParseTest, JsonParseCaseBasicInvalidWithDecimalPoint) {
const char *json = ".123";
CJsonObj *jsonObj = CJsonParse(json, strlen(json));
ASSERT_TRUE((jsonObj == NULL));
}
TEST_F(UtestJsonParseTest, JsonParseCaseBasicInvalidWithMinusSign) {
const char *json = "1-23";
CJsonObj *jsonObj = CJsonParse(json, strlen(json));
ASSERT_TRUE((jsonObj == NULL));
}
TEST_F(UtestJsonParseTest, JsonParseCaseBasicInvalidWithPlusSign) {
const char *json = "1+23";
CJsonObj *jsonObj = CJsonParse(json, strlen(json));
ASSERT_TRUE((jsonObj == NULL));
}
#endif
TEST_F(UtestJsonParseTest, JsonParseCaseBasicObj) {
const char *json = "{\"a\" : true, \"b\" : false, \"c\" : 123, \"d\" : \"123\"}";
CJsonObj *jsonObj = CJsonParse(json, strlen(json));
ASSERT_TRUE((jsonObj != NULL));
ASSERT_TRUE(CJsonIsObj(jsonObj));
CJsonObj *jsonObjValue = GetCJsonSubObj(jsonObj, "a");
ASSERT_TRUE((jsonObjValue != NULL));
ASSERT_TRUE(CJsonIsBool(jsonObjValue));
ASSERT_TRUE(GetCJsonBool(jsonObjValue));
jsonObjValue = GetCJsonSubObj(jsonObj, "b");
ASSERT_TRUE((jsonObjValue != NULL));
ASSERT_TRUE(CJsonIsBool(jsonObjValue));
ASSERT_FALSE(GetCJsonBool(jsonObjValue));
jsonObjValue = GetCJsonSubObj(jsonObj, "c");
ASSERT_TRUE((jsonObjValue != NULL));
ASSERT_TRUE(CJsonIsInt(jsonObjValue));
ASSERT_EQ(GetCJsonInt(jsonObjValue), 123);
jsonObjValue = GetCJsonSubObj(jsonObj, "d");
ASSERT_TRUE((jsonObjValue != NULL));
ASSERT_TRUE(CJsonIsString(jsonObjValue));
ASSERT_STREQ(GetCJsonString(jsonObjValue), "123");
FreeCJsonObj(jsonObj);
}
TEST_F(UtestJsonParseTest, JsonParseCaseBasicObjInvalid) {
const char *json = "{\"a\" : true; \"b\" : false, \"c\" : 123, \"d\" : \"123\"}";
CJsonObj *jsonObj = CJsonParse(json, strlen(json));
ASSERT_TRUE((jsonObj == NULL));
}
TEST_F(UtestJsonParseTest, JsonParseCaseBasicObjInvalidWithComma) {
const char *json = "{\"a\" : true, \"b\" : false, \"c\" : 123, \"d\" : \"123\",}";
CJsonObj *jsonObj = CJsonParse(json, strlen(json));
ASSERT_TRUE((jsonObj == NULL));
}
TEST_F(UtestJsonParseTest, JsonParseCaseBasicArray) {
const char *json = "[0, 1, 2]";
CJsonObj *jsonObj = CJsonParse(json, strlen(json));
ASSERT_TRUE((jsonObj != NULL));
ASSERT_TRUE(CJsonIsArray(jsonObj));
ASSERT_EQ(GetCJsonArraySize(jsonObj), 3);
for (int i = 0; i < 3; i++) {
CJsonObj *jsonObjValue = CJsonArrayAt(jsonObj, i);
ASSERT_TRUE((jsonObjValue != NULL));
ASSERT_TRUE(CJsonIsInt(jsonObjValue));
ASSERT_EQ(GetCJsonInt(jsonObjValue), i);
}
CJsonObj *jsonObjValue = CJsonArrayAt(jsonObj, 4);
ASSERT_TRUE((jsonObjValue == NULL));
FreeCJsonObj(jsonObj);
}
TEST_F(UtestJsonParseTest, JsonParseCaseBasicArrayObj) {
const char *json = "[{\"a\" : true, \"b\" : false, \"c\" : 123, \"d\" : \"123\"}, "
"{\"a\" : true, \"b\" : false, \"c\" : 123, \"d\" : \"123\"}, "
"{\"a\" : true, \"b\" : false, \"c\" : 123, \"d\" : \"123\"}]";
CJsonObj *jsonObj = CJsonParse(json, strlen(json));
ASSERT_TRUE((jsonObj != NULL));
ASSERT_TRUE(CJsonIsArray(jsonObj));
ASSERT_EQ(GetCJsonArraySize(jsonObj), 3);
for (int i = 0; i < 3; i++) {
CJsonObj *jsonObjIt = CJsonArrayAt(jsonObj, i);
CJsonObj *jsonObjValue = GetCJsonSubObj(jsonObjIt, "a");
ASSERT_TRUE((jsonObjValue != NULL));
ASSERT_TRUE(CJsonIsBool(jsonObjValue));
ASSERT_TRUE(GetCJsonBool(jsonObjValue));
jsonObjValue = GetCJsonSubObj(jsonObjIt, "b");
ASSERT_TRUE((jsonObjValue != NULL));
ASSERT_TRUE(CJsonIsBool(jsonObjValue));
ASSERT_FALSE(GetCJsonBool(jsonObjValue));
jsonObjValue = GetCJsonSubObj(jsonObjIt, "c");
ASSERT_TRUE((jsonObjValue != NULL));
ASSERT_TRUE(CJsonIsInt(jsonObjValue));
ASSERT_EQ(GetCJsonInt(jsonObjValue), 123);
jsonObjValue = GetCJsonSubObj(jsonObjIt, "d");
ASSERT_TRUE((jsonObjValue != NULL));
ASSERT_TRUE(CJsonIsString(jsonObjValue));
ASSERT_STREQ(GetCJsonString(jsonObjValue), "123");
}
CJsonObj *jsonObjValue = CJsonArrayAt(jsonObj, 4);
ASSERT_TRUE((jsonObjValue == NULL));
FreeCJsonObj(jsonObj);
}
TEST_F(UtestJsonParseTest, JsonParseCaseBasicObjArray) {
const char *json = "{\"a\" : [0, 1, 2]}";
CJsonObj *jsonObj = CJsonParse(json, strlen(json));
ASSERT_TRUE((jsonObj != NULL));
ASSERT_TRUE(CJsonIsObj(jsonObj));
CJsonObj *jsonObjValue = GetCJsonSubObj(jsonObj, "a");
ASSERT_TRUE((jsonObjValue != NULL));
ASSERT_TRUE(CJsonIsArray(jsonObjValue));
ASSERT_EQ(GetCJsonArraySize(jsonObjValue), 3);
for (int i = 0; i < 3; i++) {
CJsonObj *jsonObjIt = CJsonArrayAt(jsonObjValue, i);
ASSERT_TRUE((jsonObjIt != NULL));
ASSERT_TRUE(CJsonIsInt(jsonObjIt));
ASSERT_EQ(GetCJsonInt(jsonObjIt), i);
}
FreeCJsonObj(jsonObj);
}
TEST_F(UtestJsonParseTest, JsonParseCaseJsonFile) {
const char *json = "{\"a\" : [{\"a\" : true, \"b\" : false, \"c\" : 123, \"d\" : \"123\"}, "
"{\"a\" : true, \"b\" : false, \"c\" : 123, \"d\" : \"123\"}, "
"{\"a\" : true, \"b\" : false, \"c\" : 123, \"d\" : \"123\"}]}";
const char *filePath = "test.json";
std::ofstream stream(filePath);
stream << json;
stream.close();
CJsonObj *jsonObj = CJsonFileParse(filePath);
ASSERT_TRUE((jsonObj != NULL));
ASSERT_TRUE(CJsonIsObj(jsonObj));
CJsonObj *jsonObjA1 = GetCJsonSubObj(jsonObj, "a");
ASSERT_TRUE((jsonObjA1 != NULL));
ASSERT_TRUE(CJsonIsArray(jsonObjA1));
ASSERT_EQ(GetCJsonArraySize(jsonObjA1), 3);
for (int i = 0; i < 3; i++) {
CJsonObj *jsonObjIt = CJsonArrayAt(jsonObjA1, i);
CJsonObj *jsonObjValue = GetCJsonSubObj(jsonObjIt, "a");
ASSERT_TRUE((jsonObjValue != NULL));
ASSERT_TRUE(CJsonIsBool(jsonObjValue));
ASSERT_TRUE(GetCJsonBool(jsonObjValue));
jsonObjValue = GetCJsonSubObj(jsonObjIt, "b");
ASSERT_TRUE((jsonObjValue != NULL));
ASSERT_TRUE(CJsonIsBool(jsonObjValue));
ASSERT_FALSE(GetCJsonBool(jsonObjValue));
jsonObjValue = GetCJsonSubObj(jsonObjIt, "c");
ASSERT_TRUE((jsonObjValue != NULL));
ASSERT_TRUE(CJsonIsInt(jsonObjValue));
ASSERT_EQ(GetCJsonInt(jsonObjValue), 123);
jsonObjValue = GetCJsonSubObj(jsonObjIt, "d");
ASSERT_TRUE((jsonObjValue != NULL));
ASSERT_TRUE(CJsonIsString(jsonObjValue));
ASSERT_STREQ(GetCJsonString(jsonObjValue), "123");
}
FreeCJsonObj(jsonObj);
}
TEST_F(UtestJsonParseTest, JsonParseCaseJsonKey) {
const char *json = "{\"a\" : [{\"a\" : true, \"b\" : false, \"c\" : 123, \"d\" : \"123\"}, "
"{\"a\" : true, \"b\" : false, \"c\" : 123, \"d\" : \"123\"}, "
"{\"a\" : true, \"b\" : false, \"c\" : 123, \"d\" : \"123\"}]}";
size_t offset;
size_t len = CJsonParseKeyPosition(json, strlen(json), "a", &offset);
ASSERT_EQ(offset, 7);
ASSERT_EQ(len, strlen("[{\"a\" : true, \"b\" : false, \"c\" : 123, \"d\" : \"123\"}, "
"{\"a\" : true, \"b\" : false, \"c\" : 123, \"d\" : \"123\"}, "
"{\"a\" : true, \"b\" : false, \"c\" : 123, \"d\" : \"123\"}]"));
}
TEST_F(UtestJsonParseTest, JsonParseCaseJsonFileKey) {
const char *json = "{\"a\" : [{\"a\" : true, \"b\" : false, \"c\" : 123, \"d\" : \"123\"}, "
"{\"a\" : true, \"b\" : false, \"c\" : 123, \"d\" : \"123\"}, "
"{\"a\" : true, \"b\" : false, \"c\" : 123, \"d\" : \"123\"}]}";
const char *filePath = "test.json";
std::ofstream stream(filePath);
stream << json;
stream.close();
char *subJson = CJsonFileParseKey(filePath, "a");
ASSERT_TRUE((subJson != NULL));
ASSERT_STREQ(subJson, "[{\"a\" : true, \"b\" : false, \"c\" : 123, \"d\" : \"123\"}, "
"{\"a\" : true, \"b\" : false, \"c\" : 123, \"d\" : \"123\"}, "
"{\"a\" : true, \"b\" : false, \"c\" : 123, \"d\" : \"123\"}]");
free(subJson);
}
TEST_F(UtestJsonParseTest, JsonParseCaseJsonFileKeyWithTwoKey) {
const char *json = "{\"a\" : 123, \"b\": [{\"a\" : true, \"b\" : false, \"c\" : 123, \"d\" : \"123\"}, "
"{\"a\" : true, \"b\" : false, \"c\" : 123, \"d\" : \"123\"}, "
"{\"a\" : true, \"b\" : false, \"c\" : 123, \"d\" : \"123\"}]}";
const char *filePath = "test.json";
std::ofstream stream(filePath);
stream << json;
stream.close();
char *subJson = CJsonFileParseKey(filePath, "a");
ASSERT_TRUE((subJson != NULL));
ASSERT_STREQ(subJson, "123");
free(subJson);
subJson = CJsonFileParseKey(filePath, "b");
ASSERT_TRUE((subJson != NULL));
ASSERT_STREQ(subJson, "[{\"a\" : true, \"b\" : false, \"c\" : 123, \"d\" : \"123\"}, "
"{\"a\" : true, \"b\" : false, \"c\" : 123, \"d\" : \"123\"}, "
"{\"a\" : true, \"b\" : false, \"c\" : 123, \"d\" : \"123\"}]");
free(subJson);
}
TEST_F(UtestJsonParseTest, JsonParseCaseJsonFileKeyFail) {
const char *json = "{\"a\" : 123, \"b\": [{\"a\" : true, \"b\" : false, \"c\" : 123, \"d\" : \"123\"}, "
"{\"a\" : true, \"b\" : false; \"c\" : 123, \"d\" : \"123\"}, "
"{\"a\" : true, \"b\" : false, \"c\" : 123, \"d\" : \"123\"}]}";
const char *filePath = "test.json";
std::ofstream stream(filePath);
stream << json;
stream.close();
char *subJson = CJsonFileParseKey(filePath, "a");
ASSERT_TRUE((subJson == NULL));
subJson = CJsonFileParseKey(filePath, "b");
ASSERT_TRUE((subJson == NULL));
}
TEST_F(UtestJsonParseTest, JsonParseCaseJsonFileKeyFailNull) {
const char *json = "null";
const char *filePath = "test.json";
std::ofstream stream(filePath);
stream << json;
stream.close();
char *subJson = CJsonFileParseKey(filePath, "null");
ASSERT_TRUE((subJson == NULL));
}
TEST_F(UtestJsonParseTest, JsonParseCaseJsonFileKeyFailNumber) {
const char *json = "123";
const char *filePath = "test.json";
std::ofstream stream(filePath);
stream << json;
stream.close();
char *subJson = CJsonFileParseKey(filePath, "123");
ASSERT_TRUE((subJson == NULL));
}
TEST_F(UtestJsonParseTest, JsonParseCaseJsonFileKeyFailString) {
const char *json = "\"123\"";
const char *filePath = "test.json";
std::ofstream stream(filePath);
stream << json;
stream.close();
char *subJson = CJsonFileParseKey(filePath, "123");
ASSERT_TRUE((subJson == NULL));
}