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

mendersoftware / mender / 1071875915

14 Nov 2023 11:46AM UTC coverage: 80.182% (+0.08%) from 80.107%
1071875915

push

gitlab-ci

kacf
chore: Get rid of direct comparisons with `Error::code`.

Such comparisons are dangerous, because if you don't also compare the
category, you can get false positives.

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

12 of 12 new or added lines in 3 files covered. (100.0%)

79 existing lines in 9 files now uncovered.

6967 of 8689 relevant lines covered (80.18%)

9263.44 hits per line

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

68.67
/src/artifact/v3/header/header_info.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 <artifact/v3/header/header.hpp>
16

17
#include <vector>
18

19
#include <common/expected.hpp>
20
#include <common/error.hpp>
21
#include <common/io.hpp>
22
#include <common/log.hpp>
23
#include <common/json.hpp>
24

25
#include <artifact/error.hpp>
26

27
namespace mender {
28
namespace artifact {
29
namespace v3 {
30
namespace header {
31
namespace info {
32

33
namespace expected = mender::common::expected;
34
namespace io = mender::common::io;
35
namespace error = mender::common::error;
36
namespace log = mender::common::log;
37
namespace json = mender::common::json;
38

39
using ExpectedPayloadType = expected::expected<vector<PayloadType>, error::Error>;
40

41
ExpectedPayloadType ToPayloadTypes(const json::Json &j) {
141✔
42
        if (!j.IsArray()) {
141✔
43
                return expected::unexpected(parser_error::MakeError(
×
44
                        parser_error::Code::ParseError, "The JSON object is not an array"));
×
45
        }
46
        vector<PayloadType> vector_elements {};
141✔
47
        size_t vector_size {j.GetArraySize().value()};
141✔
48
        for (size_t i = 0; i < vector_size; ++i) {
282✔
49
                auto expected_element =
50
                        j.Get(i).and_then([](const json::Json &j) { return j.Get("type"); });
423✔
51
                if (!expected_element) {
141✔
52
                        return expected::unexpected(parser_error::MakeError(
×
53
                                parser_error::Code::ParseError,
54
                                "Failed to get the type from the payload: " + expected_element.error().message));
×
55
                }
56
                auto json_element = expected_element.value();
141✔
57
                if (json_element.IsString()) {
141✔
58
                        string payload_type = json_element.GetString().value();
137✔
59
                        if (payload_type == "") {
137✔
60
                                return expected::unexpected(
×
61
                                        parser_error::MakeError(parser_error::Code::ParseError, "Empty Payload type"));
×
62
                        }
63
                        Payload type {Payload::RootfsImage};
64
                        if (payload_type != "rootfs-image") {
137✔
65
                                type = Payload::ModuleImage;
66
                        }
67
                        vector_elements.push_back({type, payload_type});
274✔
68
                } else if (json_element.IsNull()) {
4✔
69
                        vector_elements.push_back({Payload::EmptyPayload, ""});
8✔
70
                } else {
71
                        return expected::unexpected(
×
72
                                parser_error::MakeError(parser_error::Code::ParseError, "Unexpected payload type"));
×
73
                }
74
        }
75
        return vector_elements;
141✔
76
}
77

78
ExpectedHeaderInfo Parse(io::Reader &reader) {
141✔
79
        log::Trace("Parse(header-info)");
282✔
80

81
        Info info {};
282✔
82

83
        auto expected_json = json::Load(reader);
141✔
84

85
        if (!expected_json) {
141✔
86
                return expected::unexpected(parser_error::MakeError(
×
87
                        parser_error::Code::ParseError,
88
                        "Failed to parse the header JSON: " + expected_json.error().message));
×
89
        }
90

91
        const auto header_info_json = expected_json.value();
141✔
92
        info.verbatim = header_info_json;
141✔
93

94
        //
95
        // Payloads (required)
96
        //
97
        log::Trace("Parsing the payloads");
282✔
98

99
        auto payloads = header_info_json.Get("payloads").and_then(ToPayloadTypes);
282✔
100
        if (!payloads) {
141✔
101
                return expected::unexpected(parser_error::MakeError(
×
102
                        parser_error::Code::ParseError,
103
                        "Failed to parse the header-info payloads JSON: " + payloads.error().message));
×
104
        }
105
        info.payloads = payloads.value();
141✔
106

107
        //
108
        // provides (required)
109
        //
110
        log::Trace("Parsing the header-info artifact_provides");
282✔
111

112
        auto provides = header_info_json.Get("artifact_provides");
141✔
113
        if (!provides) {
141✔
114
                return expected::unexpected(parser_error::MakeError(
×
115
                        parser_error::Code::ParseError,
116
                        "Failed to parse the header-info artifact_provides JSON: " + provides.error().message));
×
117
        }
118

119
        // provides:artifact_name (required)
120
        log::Trace("Parsing the header-info provides:artifact_name");
282✔
121
        auto artifact_name = provides.value().Get("artifact_name").and_then(json::ToString);
282✔
122

123
        if (!artifact_name) {
141✔
124
                return expected::unexpected(
×
125
                        parser_error::MakeError(parser_error::Code::ParseError, artifact_name.error().message));
×
126
        }
127
        info.provides.artifact_name = artifact_name.value();
141✔
128

129
        // provides:artifact_group (optional)
130
        log::Trace("Parsing the header-info provides:artifact_group (if any)");
282✔
131
        auto artifact_group = provides.value().Get("artifact_group").and_then(json::ToString);
282✔
132
        if (!artifact_group
141✔
133
                && artifact_group.error().code != json::MakeError(json::KeyError, "").code) {
558✔
UNCOV
134
                return expected::unexpected(parser_error::MakeError(
×
135
                        parser_error::Code::ParseError,
136
                        "Failed to parse the header-info artifact_group provides JSON: "
137
                                + artifact_group.error().message));
×
138
        }
139
        if (artifact_group) {
141✔
140
                info.provides.artifact_group = artifact_group.value();
2✔
141
        }
142

143
        //
144
        // depends (required)
145
        //
146
        log::Trace("Parsing the header-info depends:artifact_depends (if any)");
282✔
147

148
        auto depends = header_info_json.Get("artifact_depends");
141✔
149
        if (!depends) {
141✔
150
                return expected::unexpected(parser_error::MakeError(
×
151
                        parser_error::Code::ParseError,
152
                        "Failed to parse the header-info artifact_depends JSON: " + depends.error().message));
×
153
        }
154

155
        // device_type[string] (required)
156
        auto device_type = depends.value().Get("device_type").and_then(json::ToStringVector);
282✔
157
        if (!device_type) {
141✔
158
                return expected::unexpected(
×
159
                        parser_error::MakeError(parser_error::Code::ParseError, device_type.error().message));
×
160
        }
161
        info.depends.device_type = device_type.value();
141✔
162

163

164
        // depends::artifact_name (optional)
165
        auto artifact_name_depends =
166
                depends.value().Get("artifact_name").and_then(json::ToStringVector);
282✔
167
        if (!artifact_name_depends
141✔
168
                && artifact_name_depends.error().code != json::MakeError(json::KeyError, "").code) {
558✔
UNCOV
169
                return expected::unexpected(parser_error::MakeError(
×
170
                        parser_error::Code::ParseError,
171
                        "Failed to parse the header-info artifact_name depends JSON: "
172
                                + artifact_name_depends.error().message));
×
173
        }
174
        if (artifact_name_depends) {
141✔
175
                info.depends.artifact_name = artifact_name_depends.value();
2✔
176
        }
177

178
        // depends::artifact_group (optional)
179
        auto artifact_group_depends =
180
                depends.value().Get("artifact_group").and_then(json::ToStringVector);
282✔
181
        if (!artifact_group_depends
141✔
182
                && artifact_group_depends.error().code != json::MakeError(json::KeyError, "").code) {
558✔
UNCOV
183
                return expected::unexpected(parser_error::MakeError(
×
184
                        parser_error::Code::ParseError,
185
                        "Failed to parse the header-info artifact_group_depends JSON: "
186
                                + artifact_group_depends.error().message));
×
187
        }
188
        if (artifact_group_depends) {
141✔
189
                info.depends.artifact_group = artifact_group_depends.value();
2✔
190
        }
191

192
        return info;
141✔
193
}
194

195
} // namespace info
196
} // namespace header
197
} // namespace v3
198
} // namespace artifact
199
} // 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