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

mendersoftware / mender / 951586380

pending completion
951586380

push

gitlab-ci

kacf
chore: Use system reboot command when `Automatic` reboot is requested.

I won't add tests for this, because it is much better to test this
properly later when we get our acceptance tests running. It will be
untested till then...

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

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

4268 of 6026 relevant lines covered (70.83%)

147.81 hits per line

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

73.96
/common/testing.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/testing.hpp>
16

17
#include <cstdlib>
18
#include <filesystem>
19
#include <random>
20
#include <iostream>
21

22
#include <common/json.hpp>
23
#include <common/log.hpp>
24
#include <common/path.hpp>
25
#include <common/processes.hpp>
26

27
namespace mender {
28
namespace common {
29
namespace testing {
30

31
namespace fs = std::filesystem;
32

33
namespace log = mender::common::log;
34
namespace path = mender::common::path;
35

36
shared_ptr<ostream> AssertInDeathTestHelper(const char *func, const char *file, int line) {
×
37
        // Unsuccessful assert. Return a stream which prints to stderr, and which aborts when it is
38
        // destroyed (at the end of the statement evaluation).
39
        cerr << "Assert at " << func << " in " << file << ":" << line << endl;
×
40
        return shared_ptr<ostream>(new ostream(cerr.rdbuf()), [](ostream *) { std::abort(); });
×
41
}
42

43
TemporaryDirectory::TemporaryDirectory() {
216✔
44
        fs::path path = fs::temp_directory_path();
216✔
45
        path.append("mender-test-" + std::to_string(std::random_device()()));
216✔
46
        fs::create_directories(path);
216✔
47
        path_ = path;
216✔
48
}
216✔
49

50
TemporaryDirectory::~TemporaryDirectory() {
648✔
51
        fs::remove_all(path_);
216✔
52
}
216✔
53

54
std::string TemporaryDirectory::Path() const {
610✔
55
        return path_;
610✔
56
}
57

58
::testing::AssertionResult FileContains(const string &filename, const string &expected_content) {
34✔
59
        ifstream is {filename};
68✔
60
        ostringstream contents_s;
68✔
61
        contents_s << is.rdbuf();
34✔
62
        string contents {contents_s.str()};
68✔
63
        if (contents == expected_content) {
34✔
64
                return ::testing::AssertionSuccess();
34✔
65
        }
66
        return ::testing::AssertionFailure()
×
67
                   << "Expected: '" << expected_content << "' Got: '" << contents << "'";
×
68
}
69

70

71
::testing::AssertionResult FileJsonEquals(const string &filename, const string &expected_content) {
2✔
72
        ifstream is {filename};
4✔
73
        json::Json contents = json::Load(is).value();
4✔
74
        json::Json expected_contents = json::Load(expected_content).value();
6✔
75
        if (contents.Dump() == expected_contents.Dump()) {
2✔
76
                return ::testing::AssertionSuccess();
2✔
77
        }
78
        return ::testing::AssertionFailure()
×
79
                   << "Expected: '" << contents.Dump() << "' Got: '" << expected_contents.Dump() << "'";
×
80
}
81

82
::testing::AssertionResult FilesEqual(const string &filename1, const string &filename2) {
6✔
83
        processes::Process proc({"diff", "-u", filename1, filename2});
48✔
84
        auto err = proc.Run();
12✔
85
        if (err == error::NoError) {
6✔
86
                return ::testing::AssertionSuccess();
6✔
87
        }
88
        // Some extra information in case of failure.
89
        cout << "ls -l " << filename1 << " " << filename2 << endl;
×
90
        processes::Process listdir({"ls", "-l", filename1, filename2});
×
91
        listdir.Run();
×
92
        return ::testing::AssertionFailure() << filename1 << " and " << filename2 << " differ";
×
93
}
94

95
const string HttpFileServer::serve_address_ {"http://127.0.0.1:53272"};
96

97
HttpFileServer::HttpFileServer(const string &dir) :
1✔
98
        dir_(dir),
99
        server_(http::ServerConfig {}, loop_) {
1✔
100
        // The reason we need this synchronization is because of the thread sanitizer and
101
        // logging. AsyncServeUrl uses the logger internally, and the log level is also set by
102
        // certain tests. Since these things happen in two separate threads, we need to make sure
103
        // that AsyncServeUrl has returned before we leave this function.
104
        promise<bool> running;
2✔
105
        auto maybe_running = running.get_future();
2✔
106

107
        thread_ = thread([this, &running]() {
1✔
108
                auto err = server_.AsyncServeUrl(
109
                        serve_address_,
110
                        [](http::ExpectedIncomingRequestPtr exp_req) {
1✔
111
                                if (!exp_req) {
1✔
112
                                        log::Warning("HttpFileServer: " + exp_req.error().String());
×
113
                                }
114
                        },
1✔
115
                        [this](http::ExpectedIncomingRequestPtr exp_req) { Serve(exp_req); });
3✔
116
                if (err != error::NoError) {
1✔
117
                        log::Error("HttpFileServer: " + err.String());
×
118
                        return;
×
119
                }
120

121
                running.set_value(true);
1✔
122
                loop_.Run();
1✔
123
        });
1✔
124

125
        maybe_running.wait();
1✔
126
}
1✔
127

128
HttpFileServer::~HttpFileServer() {
1✔
129
        loop_.Stop();
1✔
130
        thread_.join();
1✔
131
}
1✔
132

133
void HttpFileServer::Serve(http::ExpectedIncomingRequestPtr exp_req) {
1✔
134
        if (!exp_req) {
1✔
135
                log::Warning("HttpFileServer: " + exp_req.error().String());
×
136
                return;
×
137
        }
138

139
        auto req = exp_req.value();
1✔
140

141
        if (req->GetMethod() != http::Method::GET) {
1✔
142
                log::Warning(
×
143
                        "HttpFileServer: Expected HTTP GET method, but got "
144
                        + http::MethodToString(req->GetMethod()));
×
145
                return;
×
146
        }
147

148
        auto exp_resp = req->MakeResponse();
1✔
149
        if (!exp_resp) {
1✔
150
                log::Warning("HttpFileServer: " + exp_resp.error().String());
×
151
                return;
×
152
        }
153
        auto resp = exp_resp.value();
2✔
154

155
        auto path = req->GetPath();
2✔
156
        while (path.size() > 0 && path[0] == '/') {
2✔
157
                path = string {path.begin() + 1, path.end()};
1✔
158
        }
159

160
        string file_path = path::Join(dir_, path);
2✔
161

162
        auto exp_stream = io::OpenIfstream(file_path);
2✔
163
        if (!exp_stream) {
1✔
164
                resp->SetStatusCodeAndMessage(http::StatusNotFound, exp_stream.error().String());
×
165
        } else {
166
                resp->SetStatusCodeAndMessage(http::StatusOK, "");
1✔
167
                resp->SetBodyReader(
2✔
168
                        make_shared<io::StreamReader>((make_shared<ifstream>(std::move(exp_stream.value())))));
2✔
169
        }
170

171
        auto exp_size = io::FileSize(file_path);
2✔
172
        if (!exp_size) {
1✔
173
                log::Warning("HttpFileServer: " + exp_size.error().String());
×
174
        }
175
        resp->SetHeader("Content-Length", to_string(exp_size.value()));
1✔
176

177
        auto err = resp->AsyncReply([](error::Error err) {
1✔
178
                if (err != error::NoError) {
1✔
179
                        log::Warning("HttpFileServer: " + err.String());
×
180
                }
181
        });
3✔
182
        if (err != error::NoError) {
1✔
183
                log::Warning("HttpFileServer: " + err.String());
×
184
        }
185
}
186

187
} // namespace testing
188
} // namespace common
189
} // 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