-
Notifications
You must be signed in to change notification settings - Fork 1
/
Copy pathlog_pipe_test.cc
140 lines (105 loc) · 4.3 KB
/
log_pipe_test.cc
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
// Copyright 2020 The Chromium OS Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include <sys/socket.h>
#include <utility>
#include <base/files/file_util.h>
#include <base/run_loop.h>
#include <base/strings/stringprintf.h>
#include <base/test/task_environment.h>
#include <base/threading/thread_task_runner_handle.h>
#include <chromeos/dbus/service_constants.h>
#include <dbus/message.h>
#include <gtest/gtest.h>
#include <vm_concierge/proto_bindings/concierge_service.pb.h>
#include "vm_tools/syslog/log_pipe.h"
namespace vm_tools {
namespace syslog {
// Size of the largest syslog record as defined by RFC3164.
constexpr size_t kMaxSyslogRecord = 1024;
class LogPipeTest : public ::testing::Test {
public:
LogPipeTest()
: task_environment_(base::test::TaskEnvironment::MainThreadType::IO) {}
void SendVmStartingUpSignal(int cid, LogPipeManager* manager) {
concierge::VmStartedSignal vm_starting_up_signal;
vm_starting_up_signal.set_owner_id("test-owner");
vm_starting_up_signal.set_name(base::StringPrintf("vm-%d", cid));
vm_starting_up_signal.mutable_vm_info()->set_cid(cid);
dbus::Signal dbus_signal(concierge::kVmConciergeInterface,
concierge::kVmStartingUpSignal);
dbus::MessageWriter writer(&dbus_signal);
writer.AppendProtoAsArrayOfBytes(vm_starting_up_signal);
manager->OnVmStartingUpSignal(&dbus_signal);
}
void SendVmStoppedSignal(int cid, LogPipeManager* manager) {
concierge::VmStoppedSignal vm_stopped_signal;
vm_stopped_signal.set_cid(cid);
dbus::Signal dbus_signal(concierge::kVmConciergeInterface,
concierge::kVmStoppedSignal);
dbus::MessageWriter writer(&dbus_signal);
writer.AppendProtoAsArrayOfBytes(vm_stopped_signal);
manager->OnVmStoppedSignal(&dbus_signal);
}
void CreateTestLogPipe(int cid, LogPipeManager* log_pipe_manager) {
int log_fds[2];
auto ret = socketpair(AF_UNIX, SOCK_DGRAM | SOCK_CLOEXEC, 0, log_fds);
EXPECT_EQ(ret, 0);
int dest_fds[2];
ret = socketpair(AF_UNIX, SOCK_DGRAM | SOCK_CLOEXEC, 0, dest_fds);
log_pipe_manager->CreateLogPipeForTesting(
cid, vm_tools::VmId("test-owner", base::StringPrintf("vm-%d", cid)),
base::ScopedFD(dest_fds[0]), base::ScopedFD(log_fds[0]));
log_sockets_[cid] = base::ScopedFD(log_fds[1]);
dest_sockets_[cid] = base::ScopedFD(dest_fds[1]);
}
void SendOnLogSocket(int64_t cid, const std::string& line) {
ASSERT_EQ(
send(log_sockets_[cid].get(), line.c_str(), line.size(), MSG_NOSIGNAL),
line.size());
}
std::string RecvOnDestSocket(int64_t cid) {
char buf[kMaxSyslogRecord + 1];
auto ret =
recv(dest_sockets_[cid].get(), buf, kMaxSyslogRecord, MSG_DONTWAIT);
return ret > 0 ? std::string(buf) : std::string();
}
private:
std::map<int64_t, base::ScopedFD> log_sockets_;
std::map<int64_t, base::ScopedFD> dest_sockets_;
base::test::TaskEnvironment task_environment_;
};
TEST_F(LogPipeTest, ShutdownNoCrash) {
base::RunLoop run_loop;
auto manager = std::make_unique<LogPipeManager>(run_loop.QuitClosure());
SendVmStartingUpSignal(4, manager.get());
SendVmStartingUpSignal(5, manager.get());
CreateTestLogPipe(4, manager.get());
CreateTestLogPipe(5, manager.get());
std::string log4 = "Log message for cid 4";
std::string log5 = "Log message for cid 5";
SendOnLogSocket(4, log4);
SendOnLogSocket(5, log5);
base::RunLoop().RunUntilIdle();
SendVmStoppedSignal(5, manager.get());
// Logs for cid 4 aren't yet flushed.
std::string fwd_log4 = RecvOnDestSocket(4);
EXPECT_TRUE(fwd_log4.empty());
// Logs for cid 5 are flushed when the VM stops.
std::string fwd_log5 = RecvOnDestSocket(5);
EXPECT_NE(fwd_log5.find(log5), std::string::npos);
base::RunLoop().RunUntilIdle();
base::ThreadTaskRunnerHandle::Get()->PostTask(
FROM_HERE,
base::BindOnce(
[](std::unique_ptr<LogPipeManager> manager) { manager->OnSigterm(); },
std::move(manager)));
run_loop.Run();
// Logs for cid 4 are flushed when the we SIGTERM.
fwd_log4 = RecvOnDestSocket(4);
EXPECT_NE(fwd_log4.find(log4), std::string::npos);
// No crashing when the destructor runs.
manager.reset();
}
} // namespace syslog
} // namespace vm_tools