• Home
  • Features
  • Pricing
  • Docs
  • Announcements
  • Sign In

mendersoftware / mender / 947394036

pending completion
947394036

push

gitlab-ci

kacf
chore: Treat events with no state transitions as fatal.

This was discussed with the team members. Since an unhandled event is
almost guaranteed to hang the state machine, then it's better to
terminate and let systemd try to restart us, in the hopes that
recovery will still work.

Signed-off-by: Kristian Amlie <kristian.amlie@northern.tech>

3 of 3 new or added lines in 1 file covered. (100.0%)

4268 of 5997 relevant lines covered (71.17%)

148.52 hits per line

Source File
Press 'n' to go to next uncovered line, 'b' for previous

68.18
/common/json/json.cpp
1
// Copyright 2023 Northern.tech AS
2
//
3
//    Licensed under the Apache License, Version 2.0 (the "License");
4
//    you may not use this file except in compliance with the License.
5
//    You may obtain a copy of the License at
6
//
7
//        http://www.apache.org/licenses/LICENSE-2.0
8
//
9
//    Unless required by applicable law or agreed to in writing, software
10
//    distributed under the License is distributed on an "AS IS" BASIS,
11
//    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12
//    See the License for the specific language governing permissions and
13
//    limitations under the License.
14

15
#include <common/json.hpp>
16

17
#include <string>
18
#include <unordered_map>
19
#include <vector>
20

21
namespace mender {
22
namespace common {
23
namespace json {
24

25
const JsonErrorCategoryClass JsonErrorCategory;
26

27
const char *JsonErrorCategoryClass::name() const noexcept {
×
28
        return "JsonErrorCategory";
×
29
}
30

31
string JsonErrorCategoryClass::message(int code) const {
×
32
        switch (code) {
×
33
        case NoError:
×
34
                return "Success";
×
35
        case ParseError:
×
36
                return "Parse error";
×
37
        case KeyError:
×
38
                return "Key error";
×
39
        case IndexError:
×
40
                return "Index error";
×
41
        case TypeError:
×
42
                return "Type error";
×
43
        default:
×
44
                return "Unknown";
×
45
        }
46
}
47

48
error::Error MakeError(JsonErrorCode code, const string &msg) {
481✔
49
        return error::Error(error_condition(code, JsonErrorCategory), msg);
962✔
50
}
51

52
template <>
53
expected::expected<KeyValueMap, error::Error> Json::Get<KeyValueMap>() const {
8✔
54
        return ToKeyValuesMap(*this);
8✔
55
}
56

57
template <>
58
expected::expected<vector<string>, error::Error> Json::Get<vector<string>>() const {
16✔
59
        return ToStringVector(*this);
16✔
60
}
61

62
template <>
63
expected::expected<string, error::Error> Json::Get<string>() const {
17✔
64
        return GetString();
17✔
65
}
66

67
template <>
68
expected::expected<int64_t, error::Error> Json::Get<int64_t>() const {
9✔
69
        return GetInt();
9✔
70
}
71

72
template <>
73
expected::expected<double, error::Error> Json::Get<double>() const {
1✔
74
        return GetDouble();
1✔
75
}
76

77
template <>
78
expected::expected<bool, error::Error> Json::Get<bool>() const {
1✔
79
        return GetBool();
1✔
80
}
81

82
inline void StringReplaceAll(string &str, const string &what, const string &with) {
672✔
83
        for (string::size_type pos {}; str.npos != (pos = str.find(what.data(), pos, what.length()));
685✔
84
                 pos += with.length()) {
13✔
85
                str.replace(pos, what.length(), with);
13✔
86
        }
87
}
672✔
88

89
string EscapeString(const string &str) {
96✔
90
        string ret {str};
96✔
91

92
        // see https://www.json.org/json-en.html
93
        StringReplaceAll(ret, "\\", "\\\\");
96✔
94
        StringReplaceAll(ret, "\"", "\\\"");
96✔
95
        StringReplaceAll(ret, "\n", "\\n");
96✔
96
        StringReplaceAll(ret, "\t", "\\t");
96✔
97
        StringReplaceAll(ret, "\r", "\\r");
96✔
98
        StringReplaceAll(ret, "\f", "\\f");
96✔
99
        StringReplaceAll(ret, "\b", "\\b");
96✔
100

101
        return ret;
96✔
102
}
103

104
ExpectedString ToString(const json::Json &j) {
328✔
105
        return j.GetString();
328✔
106
}
107

108
ExpectedStringVector ToStringVector(const json::Json &j) {
158✔
109
        if (!j.IsArray()) {
158✔
110
                return expected::unexpected(
×
111
                        MakeError(JsonErrorCode::ParseError, "The JSON object is not an array"));
×
112
        }
113
        vector<string> vector_elements {};
316✔
114
        size_t vector_size {j.GetArraySize().value()};
158✔
115
        for (size_t i = 0; i < vector_size; ++i) {
409✔
116
                auto element = j.Get(i).and_then(ToString);
251✔
117
                if (!element) {
251✔
118
                        return expected::unexpected(element.error());
×
119
                }
120
                vector_elements.push_back(element.value());
251✔
121
        }
122
        return vector_elements;
158✔
123
}
124

125
ExpectedKeyValueMap ToKeyValuesMap(const json::Json &j) {
77✔
126
        if (!j.IsObject()) {
77✔
127
                return expected::unexpected(
×
128
                        MakeError(JsonErrorCode::ParseError, "The JSON is not an object"));
×
129
        }
130

131
        auto expected_children = j.GetChildren();
154✔
132
        if (!expected_children) {
77✔
133
                return expected::unexpected(expected_children.error());
×
134
        }
135

136
        unordered_map<string, string> kv_map {};
154✔
137

138
        for (const auto &kv : expected_children.value()) {
200✔
139
                string key = kv.first;
123✔
140
                auto expected_value = kv.second.GetString();
123✔
141
                if (!expected_value) {
123✔
142
                        return expected::unexpected(expected_value.error());
×
143
                }
144
                kv_map[key] = expected_value.value();
123✔
145
        }
146

147
        return kv_map;
77✔
148
}
149

150
ExpectedInt64 ToInt(const json::Json &j) {
×
151
        return j.GetInt();
×
152
}
153

154
ExpectedBool ToBool(const json::Json &j) {
×
155
        return j.GetBool();
×
156
}
157

158
template <typename T>
159
expected::expected<T, error::Error> Get(
8✔
160
        const json::Json &json, const string &key, MissingOk missing_ok) {
161
        auto exp_value = json.Get(key);
16✔
162
        if (!exp_value) {
8✔
163
                if (missing_ok == MissingOk::Yes
1✔
164
                        && exp_value.error().code != json::MakeError(json::KeyError, "").code) {
1✔
165
                        return T();
×
166
                } else {
167
                        auto err = exp_value.error();
1✔
168
                        err.message += ": Could not get `" + key + "` from state data";
1✔
169
                        return expected::unexpected(err);
2✔
170
                }
171
        }
172
        return exp_value.value().Get<T>();
7✔
173
}
174
// The number of instantiations is pretty much set in stone since it depends on the number of JSON
175
// types, which isn't going to change. So use explicit instantiation for compile time efficiency.
176
template expected::expected<KeyValueMap, error::Error> Get(
177
        const json::Json &json, const string &key, MissingOk missing_ok);
178
template expected::expected<vector<string>, error::Error> Get(
179
        const json::Json &json, const string &key, MissingOk missing_ok);
180
template expected::expected<string, error::Error> Get(
181
        const json::Json &json, const string &key, MissingOk missing_ok);
182
template expected::expected<int64_t, error::Error> Get(
183
        const json::Json &json, const string &key, MissingOk missing_ok);
184
template expected::expected<double, error::Error> Get(
185
        const json::Json &json, const string &key, MissingOk missing_ok);
186
template expected::expected<bool, error::Error> Get(
187
        const json::Json &json, const string &key, MissingOk missing_ok);
188

189
} // namespace json
190
} // namespace common
191
} // namespace mender
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2025 Coveralls, Inc