blob: d3c9a2306f772b7e6f5a434f1fab9debf6b40004 [file] [log] [blame]
Bertrand SIMONNET52e5b992015-08-10 15:18:00 -07001/*
2 * Copyright (C) 2015 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
Darin Petkov2ccef012010-05-05 16:06:37 -070016
Daniel Eratb9b05e62010-11-09 12:18:51 -080017#include <vector>
18
Luigi Semenzato859b3f02014-02-05 15:33:19 -080019#include <base/at_exit.h>
Ben Chan51bf92a2014-09-05 08:21:06 -070020#include <base/files/file_util.h>
Bertrand SIMONNET12531862015-08-31 11:11:57 -070021#include <base/files/scoped_temp_dir.h>
Luigi Semenzato96360192014-06-04 10:53:35 -070022#include <base/strings/string_number_conversions.h>
Alex Vakulenko74dc6242015-10-13 09:23:34 -070023#include <brillo/flag_helper.h>
Darin Petkovf1e85e42010-06-10 15:59:53 -070024#include <gtest/gtest.h>
25
Bertrand SIMONNET12531862015-08-31 11:11:57 -070026#include "constants.h"
Bertrand SIMONNET4b915ae2015-07-28 15:38:14 -070027#include "metrics_daemon.h"
Samuel Tan28a78b72015-09-23 14:39:35 -070028#include "metrics/metrics_library_mock.h"
Bertrand SIMONNET4b915ae2015-07-28 15:38:14 -070029#include "persistent_integer_mock.h"
Darin Petkov2ccef012010-05-05 16:06:37 -070030
Ben Chan2e6543d2014-02-05 23:26:25 -080031using base::FilePath;
Daniel Eratc83975a2014-04-04 08:53:44 -070032using base::TimeDelta;
Daniel Eratb9b05e62010-11-09 12:18:51 -080033using std::string;
34using std::vector;
Darin Petkovf1e85e42010-06-10 15:59:53 -070035using ::testing::_;
Steve Funge86591e2014-12-01 13:38:21 -080036using ::testing::AnyNumber;
Daniel Eratc83975a2014-04-04 08:53:44 -070037using ::testing::AtLeast;
Darin Petkovfc91b422010-05-12 13:05:45 -070038using ::testing::Return;
39using ::testing::StrictMock;
Luigi Semenzato2fd51cc2014-02-26 11:53:16 -080040using chromeos_metrics::PersistentIntegerMock;
Darin Petkovfc91b422010-05-12 13:05:45 -070041
Luigi Semenzato5bd764f2011-10-14 12:03:35 -070042
Darin Petkov2ccef012010-05-05 16:06:37 -070043class MetricsDaemonTest : public testing::Test {
44 protected:
45 virtual void SetUp() {
Alex Vakulenko74dc6242015-10-13 09:23:34 -070046 brillo::FlagHelper::Init(0, nullptr, "");
Bertrand SIMONNET12531862015-08-31 11:11:57 -070047 EXPECT_TRUE(temp_dir_.CreateUniqueTempDir());
48 scaling_max_freq_path_ = temp_dir_.path().Append("scaling_max");
49 cpu_max_freq_path_ = temp_dir_.path().Append("cpu_freq_max");
Bertrand SIMONNET12531862015-08-31 11:11:57 -070050
Bertrand SIMONNET12531862015-08-31 11:11:57 -070051 CreateUint64ValueFile(cpu_max_freq_path_, 10000000);
52 CreateUint64ValueFile(scaling_max_freq_path_, 10000000);
53
54 chromeos_metrics::PersistentInteger::SetMetricsDirectory(
55 temp_dir_.path().value());
Bertrand SIMONNET46b49da2014-06-25 14:38:07 -070056 daemon_.Init(true,
57 false,
Bertrand SIMONNET12531862015-08-31 11:11:57 -070058 true,
Bertrand SIMONNET46b49da2014-06-25 14:38:07 -070059 &metrics_lib_,
Bertrand SIMONNET7a964052015-09-29 11:07:24 -070060 "",
Bertrand SIMONNET12531862015-08-31 11:11:57 -070061 scaling_max_freq_path_.value(),
62 cpu_max_freq_path_.value(),
Bertrand SIMONNETcac74e12014-10-09 10:14:13 -070063 base::TimeDelta::FromMinutes(30),
Bertrand SIMONNET12531862015-08-31 11:11:57 -070064 metrics::kMetricsServer,
Bertrand SIMONNET2765d0a2015-09-09 10:38:20 -070065 temp_dir_.path());
Darin Petkov2ccef012010-05-05 16:06:37 -070066 }
67
Darin Petkovfc91b422010-05-12 13:05:45 -070068 // Adds a metrics library mock expectation that the specified metric
69 // will be generated.
Daniel Eratc83975a2014-04-04 08:53:44 -070070 void ExpectSample(const std::string& name, int sample) {
71 EXPECT_CALL(metrics_lib_, SendToUMA(name, sample, _, _, _))
Darin Petkovfc91b422010-05-12 13:05:45 -070072 .Times(1)
73 .WillOnce(Return(true))
74 .RetiresOnSaturation();
Darin Petkov2ccef012010-05-05 16:06:37 -070075 }
76
Daniel Eratb9b05e62010-11-09 12:18:51 -080077 // Creates a new DBus signal message with zero or more string arguments.
78 // The message can be deallocated through DeleteDBusMessage.
Darin Petkove579d662010-05-05 16:19:39 -070079 //
80 // |path| is the object emitting the signal.
81 // |interface| is the interface the signal is emitted from.
82 // |name| is the name of the signal.
Daniel Eratb9b05e62010-11-09 12:18:51 -080083 // |arg_values| contains the values of the string arguments.
84 DBusMessage* NewDBusSignalString(const string& path,
85 const string& interface,
86 const string& name,
87 const vector<string>& arg_values) {
Darin Petkove579d662010-05-05 16:19:39 -070088 DBusMessage* msg = dbus_message_new_signal(path.c_str(),
89 interface.c_str(),
90 name.c_str());
91 DBusMessageIter iter;
92 dbus_message_iter_init_append(msg, &iter);
Daniel Eratb9b05e62010-11-09 12:18:51 -080093 for (vector<string>::const_iterator it = arg_values.begin();
94 it != arg_values.end(); ++it) {
95 const char* str_value = it->c_str();
96 dbus_message_iter_append_basic(&iter, DBUS_TYPE_STRING, &str_value);
97 }
Darin Petkove579d662010-05-05 16:19:39 -070098 return msg;
99 }
100
101 // Deallocates the DBus message |msg| previously allocated through
102 // dbus_message_new*.
103 void DeleteDBusMessage(DBusMessage* msg) {
104 dbus_message_unref(msg);
105 }
106
Luigi Semenzatoc88e42d2011-02-17 10:21:16 -0800107
Luigi Semenzato96360192014-06-04 10:53:35 -0700108 // Creates or overwrites the file in |path| so that it contains the printable
109 // representation of |value|.
Ben Chanf05ab402014-08-07 00:54:59 -0700110 void CreateUint64ValueFile(const base::FilePath& path, uint64_t value) {
Luigi Semenzato96360192014-06-04 10:53:35 -0700111 std::string value_string = base::Uint64ToString(value);
112 ASSERT_EQ(value_string.length(),
113 base::WriteFile(path, value_string.c_str(),
114 value_string.length()));
Luigi Semenzatofb3a8212013-05-07 16:55:00 -0700115 }
116
Darin Petkov2ccef012010-05-05 16:06:37 -0700117 // The MetricsDaemon under test.
118 MetricsDaemon daemon_;
119
Bertrand SIMONNET12531862015-08-31 11:11:57 -0700120 // Temporary directory used for tests.
121 base::ScopedTempDir temp_dir_;
122
123 // Path for the fake files.
124 base::FilePath scaling_max_freq_path_;
125 base::FilePath cpu_max_freq_path_;
Bertrand SIMONNET12531862015-08-31 11:11:57 -0700126
Luigi Semenzato2fd51cc2014-02-26 11:53:16 -0800127 // Mocks. They are strict mock so that all unexpected
128 // calls are marked as failures.
Darin Petkovfc91b422010-05-12 13:05:45 -0700129 StrictMock<MetricsLibraryMock> metrics_lib_;
Darin Petkov2ccef012010-05-05 16:06:37 -0700130};
131
Darin Petkove579d662010-05-05 16:19:39 -0700132TEST_F(MetricsDaemonTest, MessageFilter) {
Luigi Semenzato2fd51cc2014-02-26 11:53:16 -0800133 // Ignore calls to SendToUMA.
Steve Funge86591e2014-12-01 13:38:21 -0800134 EXPECT_CALL(metrics_lib_, SendToUMA(_, _, _, _, _)).Times(AnyNumber());
Luigi Semenzato2fd51cc2014-02-26 11:53:16 -0800135
Darin Petkove579d662010-05-05 16:19:39 -0700136 DBusMessage* msg = dbus_message_new(DBUS_MESSAGE_TYPE_METHOD_CALL);
137 DBusHandlerResult res =
Alex Vakulenko14595032014-08-28 14:59:56 -0700138 MetricsDaemon::MessageFilter(/* connection */ nullptr, msg, &daemon_);
Darin Petkove579d662010-05-05 16:19:39 -0700139 EXPECT_EQ(DBUS_HANDLER_RESULT_NOT_YET_HANDLED, res);
140 DeleteDBusMessage(msg);
141
Daniel Eratb9b05e62010-11-09 12:18:51 -0800142 vector<string> signal_args;
Darin Petkov1bb904e2010-06-16 15:58:06 -0700143 msg = NewDBusSignalString("/",
144 "org.chromium.CrashReporter",
145 "UserCrash",
Daniel Eratb9b05e62010-11-09 12:18:51 -0800146 signal_args);
Alex Vakulenko14595032014-08-28 14:59:56 -0700147 res = MetricsDaemon::MessageFilter(/* connection */ nullptr, msg, &daemon_);
Darin Petkov1bb904e2010-06-16 15:58:06 -0700148 EXPECT_EQ(DBUS_HANDLER_RESULT_HANDLED, res);
149 DeleteDBusMessage(msg);
150
Daniel Eratb9b05e62010-11-09 12:18:51 -0800151 signal_args.clear();
Daniel Eratb9b05e62010-11-09 12:18:51 -0800152 signal_args.push_back("randomstate");
153 signal_args.push_back("bob"); // arbitrary username
Darin Petkove579d662010-05-05 16:19:39 -0700154 msg = NewDBusSignalString("/",
155 "org.chromium.UnknownService.Manager",
156 "StateChanged",
Daniel Eratb9b05e62010-11-09 12:18:51 -0800157 signal_args);
Alex Vakulenko14595032014-08-28 14:59:56 -0700158 res = MetricsDaemon::MessageFilter(/* connection */ nullptr, msg, &daemon_);
Darin Petkove579d662010-05-05 16:19:39 -0700159 EXPECT_EQ(DBUS_HANDLER_RESULT_NOT_YET_HANDLED, res);
160 DeleteDBusMessage(msg);
161}
162
Luigi Semenzato2fd51cc2014-02-26 11:53:16 -0800163TEST_F(MetricsDaemonTest, SendSample) {
Daniel Eratc83975a2014-04-04 08:53:44 -0700164 ExpectSample("Dummy.Metric", 3);
Luigi Semenzato2fd51cc2014-02-26 11:53:16 -0800165 daemon_.SendSample("Dummy.Metric", /* sample */ 3,
Darin Petkov11b8eb32010-05-18 11:00:59 -0700166 /* min */ 1, /* max */ 100, /* buckets */ 50);
167}
168
Luigi Semenzato29c7ef92011-04-12 14:12:35 -0700169TEST_F(MetricsDaemonTest, ProcessMeminfo) {
Bertrand SIMONNETe6cfd642014-07-09 16:35:23 -0700170 string meminfo =
171 "MemTotal: 2000000 kB\nMemFree: 500000 kB\n"
172 "Buffers: 1000000 kB\nCached: 213652 kB\n"
173 "SwapCached: 0 kB\nActive: 133400 kB\n"
174 "Inactive: 183396 kB\nActive(anon): 92984 kB\n"
175 "Inactive(anon): 58860 kB\nActive(file): 40416 kB\n"
176 "Inactive(file): 124536 kB\nUnevictable: 0 kB\n"
177 "Mlocked: 0 kB\nSwapTotal: 0 kB\n"
178 "SwapFree: 0 kB\nDirty: 40 kB\n"
179 "Writeback: 0 kB\nAnonPages: 92652 kB\n"
180 "Mapped: 59716 kB\nShmem: 59196 kB\n"
181 "Slab: 16656 kB\nSReclaimable: 6132 kB\n"
182 "SUnreclaim: 10524 kB\nKernelStack: 1648 kB\n"
183 "PageTables: 2780 kB\nNFS_Unstable: 0 kB\n"
184 "Bounce: 0 kB\nWritebackTmp: 0 kB\n"
185 "CommitLimit: 970656 kB\nCommitted_AS: 1260528 kB\n"
186 "VmallocTotal: 122880 kB\nVmallocUsed: 12144 kB\n"
187 "VmallocChunk: 103824 kB\nDirectMap4k: 9636 kB\n"
188 "DirectMap2M: 1955840 kB\n";
189
Luigi Semenzato8accd332011-05-17 16:37:18 -0700190 // All enum calls must report percents.
Bertrand SIMONNETe6cfd642014-07-09 16:35:23 -0700191 EXPECT_CALL(metrics_lib_, SendEnumToUMA(_, _, 100)).Times(AtLeast(1));
Luigi Semenzato8accd332011-05-17 16:37:18 -0700192 // Check that MemFree is correctly computed at 25%.
193 EXPECT_CALL(metrics_lib_, SendEnumToUMA("Platform.MeminfoMemFree", 25, 100))
194 .Times(AtLeast(1));
195 // Check that we call SendToUma at least once (log histogram).
Luigi Semenzato29c7ef92011-04-12 14:12:35 -0700196 EXPECT_CALL(metrics_lib_, SendToUMA(_, _, _, _, _))
197 .Times(AtLeast(1));
Luigi Semenzato8accd332011-05-17 16:37:18 -0700198 // Make sure we don't report fields not in the list.
199 EXPECT_CALL(metrics_lib_, SendToUMA("Platform.MeminfoMlocked", _, _, _, _))
Luigi Semenzato29c7ef92011-04-12 14:12:35 -0700200 .Times(0);
Luigi Semenzato8accd332011-05-17 16:37:18 -0700201 EXPECT_CALL(metrics_lib_, SendEnumToUMA("Platform.MeminfoMlocked", _, _))
Luigi Semenzato29c7ef92011-04-12 14:12:35 -0700202 .Times(0);
203 EXPECT_TRUE(daemon_.ProcessMeminfo(meminfo));
204}
205
206TEST_F(MetricsDaemonTest, ProcessMeminfo2) {
Bertrand SIMONNETe6cfd642014-07-09 16:35:23 -0700207 string meminfo = "MemTotal: 2000000 kB\nMemFree: 1000000 kB\n";
Luigi Semenzatofb3a8212013-05-07 16:55:00 -0700208 // Not enough fields.
Luigi Semenzato29c7ef92011-04-12 14:12:35 -0700209 EXPECT_FALSE(daemon_.ProcessMeminfo(meminfo));
210}
211
Luigi Semenzatofb3a8212013-05-07 16:55:00 -0700212TEST_F(MetricsDaemonTest, ReadFreqToInt) {
213 const int fake_scaled_freq = 1666999;
214 const int fake_max_freq = 2000000;
215 int scaled_freq = 0;
216 int max_freq = 0;
Bertrand SIMONNET12531862015-08-31 11:11:57 -0700217 CreateUint64ValueFile(scaling_max_freq_path_, fake_scaled_freq);
218 CreateUint64ValueFile(cpu_max_freq_path_, fake_max_freq);
Luigi Semenzatofb3a8212013-05-07 16:55:00 -0700219 EXPECT_TRUE(daemon_.testing_);
Bertrand SIMONNET12531862015-08-31 11:11:57 -0700220 EXPECT_TRUE(daemon_.ReadFreqToInt(scaling_max_freq_path_.value(),
221 &scaled_freq));
222 EXPECT_TRUE(daemon_.ReadFreqToInt(cpu_max_freq_path_.value(), &max_freq));
Luigi Semenzatofb3a8212013-05-07 16:55:00 -0700223 EXPECT_EQ(fake_scaled_freq, scaled_freq);
224 EXPECT_EQ(fake_max_freq, max_freq);
225}
226
227TEST_F(MetricsDaemonTest, SendCpuThrottleMetrics) {
Bertrand SIMONNET12531862015-08-31 11:11:57 -0700228 CreateUint64ValueFile(cpu_max_freq_path_, 2001000);
Luigi Semenzatofb3a8212013-05-07 16:55:00 -0700229 // Test the 101% and 100% cases.
Bertrand SIMONNET12531862015-08-31 11:11:57 -0700230 CreateUint64ValueFile(scaling_max_freq_path_, 2001000);
Luigi Semenzatofb3a8212013-05-07 16:55:00 -0700231 EXPECT_TRUE(daemon_.testing_);
232 EXPECT_CALL(metrics_lib_, SendEnumToUMA(_, 101, 101));
233 daemon_.SendCpuThrottleMetrics();
Bertrand SIMONNET12531862015-08-31 11:11:57 -0700234 CreateUint64ValueFile(scaling_max_freq_path_, 2000000);
Luigi Semenzatofb3a8212013-05-07 16:55:00 -0700235 EXPECT_CALL(metrics_lib_, SendEnumToUMA(_, 100, 101));
236 daemon_.SendCpuThrottleMetrics();
237}
238
Luigi Semenzato96360192014-06-04 10:53:35 -0700239TEST_F(MetricsDaemonTest, SendZramMetrics) {
240 EXPECT_TRUE(daemon_.testing_);
241
242 // |compr_data_size| is the size in bytes of compressed data.
Ben Chanf05ab402014-08-07 00:54:59 -0700243 const uint64_t compr_data_size = 50 * 1000 * 1000;
Luigi Semenzato96360192014-06-04 10:53:35 -0700244 // The constant '3' is a realistic but random choice.
245 // |orig_data_size| does not include zero pages.
Ben Chanf05ab402014-08-07 00:54:59 -0700246 const uint64_t orig_data_size = compr_data_size * 3;
247 const uint64_t page_size = 4096;
248 const uint64_t zero_pages = 10 * 1000 * 1000 / page_size;
Luigi Semenzato96360192014-06-04 10:53:35 -0700249
Bertrand SIMONNET12531862015-08-31 11:11:57 -0700250 CreateUint64ValueFile(
251 temp_dir_.path().Append(MetricsDaemon::kComprDataSizeName),
252 compr_data_size);
253 CreateUint64ValueFile(
254 temp_dir_.path().Append(MetricsDaemon::kOrigDataSizeName),
255 orig_data_size);
256 CreateUint64ValueFile(
257 temp_dir_.path().Append(MetricsDaemon::kZeroPagesName), zero_pages);
Luigi Semenzato96360192014-06-04 10:53:35 -0700258
Ben Chanf05ab402014-08-07 00:54:59 -0700259 const uint64_t real_orig_size = orig_data_size + zero_pages * page_size;
260 const uint64_t zero_ratio_percent =
Luigi Semenzato96360192014-06-04 10:53:35 -0700261 zero_pages * page_size * 100 / real_orig_size;
262 // Ratio samples are in percents.
Ben Chanf05ab402014-08-07 00:54:59 -0700263 const uint64_t actual_ratio_sample = real_orig_size * 100 / compr_data_size;
Luigi Semenzato96360192014-06-04 10:53:35 -0700264
265 EXPECT_CALL(metrics_lib_, SendToUMA(_, compr_data_size >> 20, _, _, _));
266 EXPECT_CALL(metrics_lib_,
267 SendToUMA(_, (real_orig_size - compr_data_size) >> 20, _, _, _));
268 EXPECT_CALL(metrics_lib_, SendToUMA(_, actual_ratio_sample, _, _, _));
269 EXPECT_CALL(metrics_lib_, SendToUMA(_, zero_pages, _, _, _));
270 EXPECT_CALL(metrics_lib_, SendToUMA(_, zero_ratio_percent, _, _, _));
271
Bertrand SIMONNET12531862015-08-31 11:11:57 -0700272 EXPECT_TRUE(daemon_.ReportZram(temp_dir_.path()));
Darin Petkov2ccef012010-05-05 16:06:37 -0700273}