GCC Code Coverage Report


Directory: ./
File: src/validators/validators_store.cpp
Date: 2024-07-09 12:21:25
Exec Total Coverage
Lines: 75 89 84.3%
Functions: 8 8 100.0%
Branches: 82 162 50.6%

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/validators_store.hpp"
8
9 #include <set>
10
11 126 ValidatorsStore::ValidatorsStore(const rapidjson::Value& schema_val, const std::vector<std::string>& ref_keys)
12
1/2
✓ Branch 2 taken 126 times.
✗ Branch 3 not taken.
126 : body_validator_(new BodyValidator(schema_val, ref_keys))
13 {
14 126 }
15
16 396 void ValidatorsStore::AddParamValidators(const std::string& path, const rapidjson::Value& params,
17 std::vector<std::string>& ref_keys)
18 {
19
1/2
✓ Branch 1 taken 396 times.
✗ Branch 2 not taken.
396 auto path_param_idxs = GetPathParamIndices(path);
20
5/8
✓ Branch 1 taken 396 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 396 times.
✗ Branch 5 not taken.
✓ Branch 7 taken 396 times.
✗ Branch 8 not taken.
✓ Branch 9 taken 666 times.
✓ Branch 10 taken 396 times.
1062 for (const auto& param_val : params.GetArray()) {
21
3/6
✓ Branch 2 taken 666 times.
✗ Branch 3 not taken.
✓ Branch 5 taken 666 times.
✗ Branch 6 not taken.
✓ Branch 8 taken 666 times.
✗ Branch 9 not taken.
666 std::string in(param_val["in"].GetString());
22
3/6
✓ Branch 2 taken 666 times.
✗ Branch 3 not taken.
✓ Branch 5 taken 666 times.
✗ Branch 6 not taken.
✓ Branch 8 taken 666 times.
✗ Branch 9 not taken.
666 std::string name(param_val["name"].GetString());
23
1/2
✓ Branch 1 taken 666 times.
✗ Branch 2 not taken.
666 ref_keys.emplace_back(name);
24
2/2
✓ Branch 1 taken 210 times.
✓ Branch 2 taken 456 times.
666 if ("path" == in) {
25
1/2
✓ Branch 1 taken 210 times.
✗ Branch 2 not taken.
210 path_param_validators_.emplace_back(
26
3/6
✓ Branch 1 taken 210 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 210 times.
✗ Branch 5 not taken.
✓ Branch 7 taken 210 times.
✗ Branch 8 not taken.
420 PathParamValidatorInfo{path_param_idxs.at(name), new PathParamValidator(param_val, ref_keys)});
27
2/2
✓ Branch 1 taken 258 times.
✓ Branch 2 taken 198 times.
456 } else if ("query" == in) {
28
1/2
✓ Branch 1 taken 258 times.
✗ Branch 2 not taken.
258 query_param_validators_.emplace_back(
29
3/6
✓ Branch 1 taken 258 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 258 times.
✗ Branch 5 not taken.
✓ Branch 7 taken 258 times.
✗ Branch 8 not taken.
516 QueryParamValidatorInfo{name, new QueryParamValidator(param_val, ref_keys)});
30
1/2
✓ Branch 1 taken 198 times.
✗ Branch 2 not taken.
198 } else if ("header" == in) {
31
3/6
✓ Branch 1 taken 198 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 198 times.
✗ Branch 5 not taken.
✓ Branch 7 taken 198 times.
✗ Branch 8 not taken.
198 header_param_validators_.emplace(name, new HeaderParamValidator(param_val, ref_keys));
32 } else {
33 throw ValidatorInitExc("Invalid 'in' value '" + in + "' for parameter '" + name + "'");
34 }
35 666 ref_keys.pop_back();
36 1062 }
37 396 }
38
39 8 ValidationError ValidatorsStore::ValidateBody(const std::string& json_body, std::string& error_msg)
40 {
41
2/2
✓ Branch 0 taken 6 times.
✓ Branch 1 taken 2 times.
8 if (body_validator_) {
42 6 return body_validator_->Validate(json_body, error_msg);
43 }
44 2 return ValidationError::NONE; // No validator, no error
45 }
46
47 33 ValidationError ValidatorsStore::ValidatePathParams(std::unordered_map<size_t, ParamRange>& param_idxs,
48 std::string& error_msg)
49 {
50
2/2
✓ Branch 5 taken 33 times.
✓ Branch 6 taken 19 times.
52 for (auto& param_validator : path_param_validators_) {
51 try {
52
1/2
✓ Branch 1 taken 33 times.
✗ Branch 2 not taken.
33 auto const& range = param_idxs.at(param_validator.idx);
53
1/2
✓ Branch 1 taken 33 times.
✗ Branch 2 not taken.
33 auto err_code = param_validator.validator->ValidateParam(range.beg, range.end, error_msg);
54
2/2
✓ Branch 0 taken 14 times.
✓ Branch 1 taken 19 times.
33 CHECK_ERROR(err_code)
55 } catch (const std::out_of_range&) {
56 return param_validator.validator->ErrorOnMissing(error_msg);
57 }
58 }
59
60 19 return ValidationError::NONE;
61 }
62
63 20 ValidationError ValidatorsStore::ValidateQueryParams(const std::string& query, std::string& error_msg)
64 {
65 20 std::set<size_t> starts;
66 20 std::unordered_map<std::string, size_t> start_map;
67
2/2
✓ Branch 5 taken 22 times.
✓ Branch 6 taken 20 times.
42 for (const auto& param_validator : query_param_validators_) {
68 22 auto start = query.find(param_validator.name);
69
2/2
✓ Branch 0 taken 2 times.
✓ Branch 1 taken 20 times.
22 if (std::string::npos == start) {
70
2/4
✓ Branch 1 taken 2 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
✓ Branch 4 taken 2 times.
2 if (param_validator.validator->IsRequired()) {
71 return param_validator.validator->ErrorOnMissing(error_msg);
72 } else {
73 2 continue;
74 }
75 }
76
4/6
✓ Branch 1 taken 11 times.
✓ Branch 2 taken 9 times.
✗ Branch 4 not taken.
✓ Branch 5 taken 11 times.
✗ Branch 6 not taken.
✓ Branch 7 taken 20 times.
20 if (query[start - 1] != '?' && query[start - 1] != '&') {
77 error_msg = param_validator.validator->GetErrHeader() + R"("description": "Query parameter ')" +
78 param_validator.name + R"(' should start with '?' or '&'"}})";
79 return ValidationError::INVALID_QUERY_PARAM;
80 }
81
1/2
✓ Branch 1 taken 20 times.
✗ Branch 2 not taken.
20 starts.emplace(start);
82
1/2
✓ Branch 1 taken 20 times.
✗ Branch 2 not taken.
20 start_map.emplace(param_validator.name, start);
83 }
84
1/2
✓ Branch 2 taken 20 times.
✗ Branch 3 not taken.
20 starts.emplace(query.length() + 1);
85
86
2/2
✓ Branch 5 taken 22 times.
✓ Branch 6 taken 18 times.
40 for (auto& param_validator : query_param_validators_) {
87 try {
88
2/2
✓ Branch 1 taken 20 times.
✓ Branch 2 taken 2 times.
22 auto start = start_map.at(param_validator.name);
89
2/4
✓ Branch 1 taken 20 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 20 times.
✗ Branch 5 not taken.
20 auto end = (*std::next(starts.find(start))) - 1;
90
1/2
✓ Branch 3 taken 20 times.
✗ Branch 4 not taken.
20 auto err_code = param_validator.validator->ValidateParam(query.data() + start, query.data() + end,
91 error_msg);
92
2/2
✓ Branch 0 taken 2 times.
✓ Branch 1 taken 18 times.
20 CHECK_ERROR(err_code)
93
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 2 times.
2 } catch (const std::out_of_range&) {
94
2/4
✓ Branch 1 taken 2 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
✓ Branch 4 taken 2 times.
2 if (param_validator.validator->IsRequired()) {
95 return param_validator.validator->ErrorOnMissing(error_msg);
96 }
97
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 2 times.
2 }
98 }
99 18 return ValidationError::NONE;
100 20 }
101
102 9 ValidationError ValidatorsStore::ValidateHeaderParams(const std::unordered_map<std::string, std::string>& headers,
103 std::string& error_msg)
104 {
105
2/2
✓ Branch 5 taken 12 times.
✓ Branch 6 taken 6 times.
18 for (auto& header_validator : header_param_validators_) {
106 try {
107
1/2
✓ Branch 1 taken 12 times.
✗ Branch 2 not taken.
12 const auto& param = headers.at(header_validator.first);
108
1/2
✓ Branch 4 taken 12 times.
✗ Branch 5 not taken.
12 auto err_code = header_validator.second->ValidateParam(param.data(), param.data() + param.size(),
109 error_msg);
110
2/2
✓ Branch 0 taken 3 times.
✓ Branch 1 taken 9 times.
12 CHECK_ERROR(err_code)
111 } catch (const std::out_of_range&) {
112 if (header_validator.second->IsRequired()) {
113 return header_validator.second->ErrorOnMissing(error_msg);
114 }
115 }
116 }
117 6 return ValidationError::NONE;
118 }
119 528 ValidatorsStore::~ValidatorsStore()
120 {
121 #ifndef LUA_OAS_VALIDATOR // LUA manages garbage collection itself
122
2/2
✓ Branch 5 taken 258 times.
✓ Branch 6 taken 528 times.
786 for (auto& param_validator : query_param_validators_) {
123
1/2
✓ Branch 0 taken 258 times.
✗ Branch 1 not taken.
258 delete param_validator.validator;
124 }
125
2/2
✓ Branch 0 taken 126 times.
✓ Branch 1 taken 402 times.
528 delete body_validator_;
126 #endif
127 528 }
128
129 396 std::unordered_map<std::string, size_t> ValidatorsStore::GetPathParamIndices(const std::string& path)
130 {
131 396 std::unordered_map<std::string, size_t> param_idxs;
132 396 const char* dir_start = path.data();
133 396 const char* const path_end = dir_start + path.length();
134 const char* dir_end;
135 396 int frag_idx = 0;
136
137
2/2
✓ Branch 0 taken 1410 times.
✓ Branch 1 taken 396 times.
1806 while (dir_start < path_end) {
138 1410 dir_end = Seek(dir_start, path_end, '/');
139
140
3/4
✓ Branch 0 taken 210 times.
✓ Branch 1 taken 1200 times.
✓ Branch 2 taken 210 times.
✗ Branch 3 not taken.
1410 if (*dir_start == '{' && *(dir_end - 1) == '}') {
141
2/4
✓ Branch 2 taken 210 times.
✗ Branch 3 not taken.
✓ Branch 5 taken 210 times.
✗ Branch 6 not taken.
210 param_idxs.emplace(std::string(dir_start + 1, dir_end - 1), frag_idx);
142 }
143 1410 dir_start = dir_end + 1; // skip '/'
144 1410 frag_idx++;
145 }
146 792 return param_idxs;
147 }
148