GCC Code Coverage Report


Directory: ./
File: src/validators/json_validator.cpp
Date: 2024-07-09 12:21:25
Exec Total Coverage
Lines: 86 109 78.9%
Functions: 6 6 100.0%
Branches: 114 244 46.7%

Line Branch Exec Source
1 /*
2 * Copyright (c) 2024 Muhammad Nawaz
3 * Licensed under the MIT License. See LICENSE file for more information.
4 */
5 // [ END OF LICENSE c6bd0f49d040fca8d8a9cb05868e66aa63f0e2e0 ]
6
7 #include "validators/json_validator.hpp"
8
9 945 JsonValidator::JsonValidator(const rapidjson::Value& schema_val, const std::vector<std::string>& ref_keys,
10 945 ValidationError err_code)
11 : BaseValidator(ref_keys, err_code)
12
2/4
✓ Branch 2 taken 945 times.
✗ Branch 3 not taken.
✓ Branch 5 taken 945 times.
✗ Branch 6 not taken.
945 , schema_(new rapidjson::SchemaDocument(schema_val))
13
2/4
✓ Branch 3 taken 945 times.
✗ Branch 4 not taken.
✓ Branch 6 taken 945 times.
✗ Branch 7 not taken.
1890 , validator_(new rapidjson::SchemaValidator(*schema_))
14 {
15 945 }
16
17 166 ValidationError JsonValidator::Validate(const std::string& json_str, std::string& error_msg)
18 {
19
1/2
✓ Branch 1 taken 166 times.
✗ Branch 2 not taken.
166 rapidjson::Document doc;
20
1/2
✓ Branch 2 taken 166 times.
✗ Branch 3 not taken.
166 doc.Parse(json_str.c_str());
21
22
2/2
✓ Branch 1 taken 2 times.
✓ Branch 2 taken 164 times.
166 if (doc.HasParseError()) {
23
2/4
✓ Branch 3 taken 2 times.
✗ Branch 4 not taken.
✓ Branch 6 taken 2 times.
✗ Branch 7 not taken.
4 error_msg = err_header_ + R"("code":"parserError","description":")" +
24
2/4
✓ Branch 1 taken 2 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 2 times.
✗ Branch 5 not taken.
4 rapidjson::GetParseError_En(doc.GetParseError()) + R"(","offset":)" +
25
2/4
✓ Branch 2 taken 2 times.
✗ Branch 3 not taken.
✓ Branch 5 taken 2 times.
✗ Branch 6 not taken.
6 std::to_string(doc.GetErrorOffset()) + "}}";
26 2 return code_on_error_;
27 }
28
29
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 164 times.
164 if (!validator_) {
30 return ValidationError::NONE;
31 }
32
33
1/2
✓ Branch 1 taken 164 times.
✗ Branch 2 not taken.
164 std::unique_lock<std::mutex> lock(mutex_);
34
3/4
✓ Branch 1 taken 164 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 152 times.
✓ Branch 4 taken 12 times.
164 if (doc.Accept(*this->validator_)) {
35
1/2
✓ Branch 1 taken 152 times.
✗ Branch 2 not taken.
152 validator_->Reset();
36
1/2
✓ Branch 1 taken 152 times.
✗ Branch 2 not taken.
152 lock.unlock();
37 152 return ValidationError::NONE;
38 }
39
40
1/2
✓ Branch 1 taken 12 times.
✗ Branch 2 not taken.
12 error_msg.reserve(1024);
41
1/2
✓ Branch 1 taken 12 times.
✗ Branch 2 not taken.
12 error_msg = err_header_;
42
1/2
✓ Branch 3 taken 12 times.
✗ Branch 4 not taken.
12 CreateErrorMessages(validator_->GetError(), std::string(), error_msg);
43
1/2
✓ Branch 1 taken 12 times.
✗ Branch 2 not taken.
12 error_msg.append("}}");
44
1/2
✓ Branch 1 taken 12 times.
✗ Branch 2 not taken.
12 validator_->Reset();
45
46 12 return code_on_error_;
47 166 }
48
49 14 void JsonValidator::CreateErrorMessages(
50 const rapidjson::GenericValue<rapidjson::UTF8<>, rapidjson::CrtAllocator>& errors, const std::string& context,
51 std::string& error_msg, bool recursive)
52 {
53
5/8
✓ Branch 1 taken 14 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 14 times.
✗ Branch 5 not taken.
✓ Branch 7 taken 14 times.
✗ Branch 8 not taken.
✓ Branch 12 taken 14 times.
✓ Branch 13 taken 14 times.
28 for (const auto& error_type : errors.GetObject()) {
54
1/2
✓ Branch 1 taken 14 times.
✗ Branch 2 not taken.
14 const char* error_name = error_type.name.GetString();
55 14 const auto& error_content = error_type.value;
56
57
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 14 times.
14 if (error_content.IsArray()) {
58 for (const auto& content : error_content.GetArray()) {
59 HandleError(error_name, content, context, error_msg, recursive);
60 }
61
1/2
✓ Branch 1 taken 14 times.
✗ Branch 2 not taken.
14 } else if (error_content.IsObject()) {
62
1/2
✓ Branch 1 taken 14 times.
✗ Branch 2 not taken.
14 HandleError(error_name, error_content, context, error_msg, recursive);
63 }
64 14 }
65 14 }
66
67 14 void JsonValidator::HandleError(const char* error_name,
68 const rapidjson::GenericValue<rapidjson::UTF8<>, rapidjson::CrtAllocator>& error,
69 const std::string& context, std::string& error_msg, bool recursive)
70 {
71
1/2
✓ Branch 1 taken 14 times.
✗ Branch 2 not taken.
14 if (!error.ObjectEmpty()) {
72
1/2
✓ Branch 1 taken 14 times.
✗ Branch 2 not taken.
14 int code = error["errorCode"].GetInt();
73
1/2
✓ Branch 3 taken 14 times.
✗ Branch 4 not taken.
14 std::string message(GetValidateError_En(static_cast<rapidjson::ValidateErrorCode>(code)));
74
75
5/8
✓ Branch 1 taken 14 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 14 times.
✗ Branch 5 not taken.
✓ Branch 7 taken 14 times.
✗ Branch 8 not taken.
✓ Branch 12 taken 64 times.
✓ Branch 13 taken 14 times.
78 for (const auto& insert : error.GetObject()) {
76
3/6
✓ Branch 2 taken 64 times.
✗ Branch 3 not taken.
✓ Branch 5 taken 64 times.
✗ Branch 6 not taken.
✓ Branch 8 taken 64 times.
✗ Branch 9 not taken.
128 std::string insert_name = "%" + std::string(insert.name.GetString());
77 64 size_t insert_pos = message.find(insert_name);
78
79
2/2
✓ Branch 0 taken 21 times.
✓ Branch 1 taken 43 times.
64 if (insert_pos != std::string::npos) {
80 21 std::string insert_string;
81
82
2/2
✓ Branch 1 taken 7 times.
✓ Branch 2 taken 14 times.
21 if (insert.value.IsArray()) {
83
5/8
✓ Branch 1 taken 7 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 7 times.
✗ Branch 5 not taken.
✓ Branch 7 taken 7 times.
✗ Branch 8 not taken.
✓ Branch 9 taken 9 times.
✓ Branch 10 taken 7 times.
16 for (const auto& item : insert.value.GetArray()) {
84
2/2
✓ Branch 1 taken 2 times.
✓ Branch 2 taken 7 times.
9 if (!insert_string.empty()) {
85
1/2
✓ Branch 1 taken 2 times.
✗ Branch 2 not taken.
2 insert_string += ",";
86 }
87
2/4
✓ Branch 1 taken 9 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 9 times.
✗ Branch 5 not taken.
9 insert_string += GetString(item);
88 7 }
89 } else {
90
1/2
✓ Branch 1 taken 14 times.
✗ Branch 2 not taken.
14 insert_string = GetString(insert.value);
91 }
92
93
1/2
✓ Branch 2 taken 21 times.
✗ Branch 3 not taken.
21 message.replace(insert_pos, insert_name.length(), insert_string);
94 21 }
95 78 }
96
97
2/2
✓ Branch 0 taken 2 times.
✓ Branch 1 taken 12 times.
14 if (recursive) {
98
1/2
✓ Branch 1 taken 2 times.
✗ Branch 2 not taken.
2 error_msg.push_back('{');
99 }
100
7/14
✓ Branch 1 taken 14 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 14 times.
✗ Branch 5 not taken.
✓ Branch 7 taken 14 times.
✗ Branch 8 not taken.
✓ Branch 10 taken 14 times.
✗ Branch 11 not taken.
✓ Branch 13 taken 14 times.
✗ Branch 14 not taken.
✓ Branch 16 taken 14 times.
✗ Branch 17 not taken.
✓ Branch 19 taken 14 times.
✗ Branch 20 not taken.
28 error_msg += R"("code":")" + std::string(error_name) + R"(",)" + R"("description":")" + message + R"(",)" +
101
6/12
✓ Branch 1 taken 14 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 14 times.
✗ Branch 5 not taken.
✓ Branch 8 taken 14 times.
✗ Branch 9 not taken.
✓ Branch 11 taken 14 times.
✗ Branch 12 not taken.
✓ Branch 14 taken 14 times.
✗ Branch 15 not taken.
✓ Branch 17 taken 14 times.
✗ Branch 18 not taken.
42 R"("instance":")" + error["instanceRef"].GetString() + R"(",)" + R"("schema":")" +
102
4/8
✓ Branch 1 taken 14 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 14 times.
✗ Branch 5 not taken.
✓ Branch 7 taken 14 times.
✗ Branch 8 not taken.
✓ Branch 10 taken 14 times.
✗ Branch 11 not taken.
28 error["schemaRef"].GetString() + R"(")";
103
104
2/2
✓ Branch 1 taken 2 times.
✓ Branch 2 taken 12 times.
14 if (!context.empty()) {
105
3/6
✓ Branch 1 taken 2 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 2 times.
✗ Branch 5 not taken.
✓ Branch 7 taken 2 times.
✗ Branch 8 not taken.
2 error_msg += R"(,"context":")" + context + R"(")";
106 }
107
108
3/4
✓ Branch 1 taken 14 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 1 times.
✓ Branch 4 taken 13 times.
14 if (error.HasMember("errors")) {
109
1/2
✓ Branch 1 taken 1 times.
✗ Branch 2 not taken.
1 error_msg += R"(,"errors":[)";
110
1/2
✓ Branch 1 taken 1 times.
✗ Branch 2 not taken.
1 const auto& child_errors = error["errors"];
111
112
1/2
✓ Branch 1 taken 1 times.
✗ Branch 2 not taken.
1 if (child_errors.IsArray()) {
113
5/8
✓ Branch 1 taken 1 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 1 times.
✗ Branch 5 not taken.
✓ Branch 7 taken 1 times.
✗ Branch 8 not taken.
✓ Branch 9 taken 2 times.
✓ Branch 10 taken 1 times.
3 for (const auto& child_error : child_errors.GetArray()) {
114
2/4
✓ Branch 2 taken 2 times.
✗ Branch 3 not taken.
✓ Branch 5 taken 2 times.
✗ Branch 6 not taken.
2 CreateErrorMessages(child_error, error_name, error_msg, true);
115
1/2
✓ Branch 1 taken 2 times.
✗ Branch 2 not taken.
2 error_msg.push_back(',');
116 1 }
117
1/2
✓ Branch 1 taken 1 times.
✗ Branch 2 not taken.
1 if (error_msg.back() == ',') {
118 1 error_msg.pop_back();
119 }
120 } else if (child_errors.IsObject()) {
121 for (const auto& prop : child_errors.GetObject()) {
122 CreateErrorMessages(prop.value, error_name, error_msg, true);
123 error_msg.push_back(',');
124 }
125 if (error_msg.back() == ',') {
126 error_msg.pop_back();
127 }
128 }
129
1/2
✓ Branch 1 taken 1 times.
✗ Branch 2 not taken.
1 error_msg += "]";
130 }
131
2/2
✓ Branch 0 taken 2 times.
✓ Branch 1 taken 12 times.
14 if (recursive) {
132
1/2
✓ Branch 1 taken 2 times.
✗ Branch 2 not taken.
2 error_msg += "}";
133 }
134 14 }
135 14 }
136
137 23 std::string JsonValidator::GetString(const rapidjson::GenericValue<rapidjson::UTF8<>, rapidjson::CrtAllocator>& val)
138 {
139
2/2
✓ Branch 1 taken 15 times.
✓ Branch 2 taken 8 times.
23 if (val.IsString()) {
140
2/4
✓ Branch 2 taken 15 times.
✗ Branch 3 not taken.
✓ Branch 5 taken 15 times.
✗ Branch 6 not taken.
15 return val.GetString();
141 }
142
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 8 times.
8 if (val.IsDouble()) {
143 return std::to_string(val.GetDouble());
144 }
145
1/2
✓ Branch 1 taken 8 times.
✗ Branch 2 not taken.
8 if (val.IsUint()) {
146 8 return std::to_string(val.GetUint());
147 }
148 if (val.IsInt()) {
149 return std::to_string(val.GetInt());
150 }
151 if (val.IsUint64()) {
152 return std::to_string(val.GetUint64());
153 }
154 if (val.IsInt64()) {
155 return std::to_string(val.GetInt64());
156 }
157 if (val.IsBool()) {
158 return val.GetBool() ? "true" : "false";
159 }
160 if (val.IsFloat()) {
161 return std::to_string(val.GetFloat());
162 }
163
164 return "";
165 }
166
167 1074 JsonValidator::~JsonValidator()
168 {
169 #ifndef LUA_OAS_VALIDATOR // LUA manages garbage collection itself
170
1/2
✓ Branch 0 taken 537 times.
✗ Branch 1 not taken.
1074 delete validator_;
171
1/2
✓ Branch 0 taken 537 times.
✗ Branch 1 not taken.
1074 delete schema_;
172 #endif
173 1074 }
174