blob: 004636045995fc735d3e78d784a21f974458db5f [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 SIMONNET608e4282015-11-12 17:52:17 -080027#include "metrics_collector.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
Bertrand SIMONNET608e4282015-11-12 17:52:17 -080043class MetricsCollectorTest : public testing::Test {
Darin Petkov2ccef012010-05-05 16:06:37 -070044 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());
Bertrand SIMONNET608e4282015-11-12 17:52:17 -080048 daemon_.Init(true, &metrics_lib_, "", temp_dir_.path());
Darin Petkov2ccef012010-05-05 16:06:37 -070049 }
50
Darin Petkovfc91b422010-05-12 13:05:45 -070051 // Adds a metrics library mock expectation that the specified metric
52 // will be generated.
Daniel Eratc83975a2014-04-04 08:53:44 -070053 void ExpectSample(const std::string& name, int sample) {
54 EXPECT_CALL(metrics_lib_, SendToUMA(name, sample, _, _, _))
Darin Petkovfc91b422010-05-12 13:05:45 -070055 .Times(1)
56 .WillOnce(Return(true))
57 .RetiresOnSaturation();
Darin Petkov2ccef012010-05-05 16:06:37 -070058 }
59
Daniel Eratb9b05e62010-11-09 12:18:51 -080060 // Creates a new DBus signal message with zero or more string arguments.
61 // The message can be deallocated through DeleteDBusMessage.
Darin Petkove579d662010-05-05 16:19:39 -070062 //
63 // |path| is the object emitting the signal.
64 // |interface| is the interface the signal is emitted from.
65 // |name| is the name of the signal.
Daniel Eratb9b05e62010-11-09 12:18:51 -080066 // |arg_values| contains the values of the string arguments.
67 DBusMessage* NewDBusSignalString(const string& path,
68 const string& interface,
69 const string& name,
70 const vector<string>& arg_values) {
Darin Petkove579d662010-05-05 16:19:39 -070071 DBusMessage* msg = dbus_message_new_signal(path.c_str(),
72 interface.c_str(),
73 name.c_str());
74 DBusMessageIter iter;
75 dbus_message_iter_init_append(msg, &iter);
Daniel Eratb9b05e62010-11-09 12:18:51 -080076 for (vector<string>::const_iterator it = arg_values.begin();
77 it != arg_values.end(); ++it) {
78 const char* str_value = it->c_str();
79 dbus_message_iter_append_basic(&iter, DBUS_TYPE_STRING, &str_value);
80 }
Darin Petkove579d662010-05-05 16:19:39 -070081 return msg;
82 }
83
84 // Deallocates the DBus message |msg| previously allocated through
85 // dbus_message_new*.
86 void DeleteDBusMessage(DBusMessage* msg) {
87 dbus_message_unref(msg);
88 }
89
Luigi Semenzatoc88e42d2011-02-17 10:21:16 -080090
Luigi Semenzato96360192014-06-04 10:53:35 -070091 // Creates or overwrites the file in |path| so that it contains the printable
92 // representation of |value|.
Ben Chanf05ab402014-08-07 00:54:59 -070093 void CreateUint64ValueFile(const base::FilePath& path, uint64_t value) {
Luigi Semenzato96360192014-06-04 10:53:35 -070094 std::string value_string = base::Uint64ToString(value);
95 ASSERT_EQ(value_string.length(),
96 base::WriteFile(path, value_string.c_str(),
97 value_string.length()));
Luigi Semenzatofb3a8212013-05-07 16:55:00 -070098 }
99
Bertrand SIMONNET608e4282015-11-12 17:52:17 -0800100 // The MetricsCollector under test.
101 MetricsCollector daemon_;
Darin Petkov2ccef012010-05-05 16:06:37 -0700102
Bertrand SIMONNET12531862015-08-31 11:11:57 -0700103 // Temporary directory used for tests.
104 base::ScopedTempDir temp_dir_;
105
Luigi Semenzato2fd51cc2014-02-26 11:53:16 -0800106 // Mocks. They are strict mock so that all unexpected
107 // calls are marked as failures.
Darin Petkovfc91b422010-05-12 13:05:45 -0700108 StrictMock<MetricsLibraryMock> metrics_lib_;
Darin Petkov2ccef012010-05-05 16:06:37 -0700109};
110
Bertrand SIMONNET608e4282015-11-12 17:52:17 -0800111TEST_F(MetricsCollectorTest, MessageFilter) {
Luigi Semenzato2fd51cc2014-02-26 11:53:16 -0800112 // Ignore calls to SendToUMA.
Steve Funge86591e2014-12-01 13:38:21 -0800113 EXPECT_CALL(metrics_lib_, SendToUMA(_, _, _, _, _)).Times(AnyNumber());
Luigi Semenzato2fd51cc2014-02-26 11:53:16 -0800114
Darin Petkove579d662010-05-05 16:19:39 -0700115 DBusMessage* msg = dbus_message_new(DBUS_MESSAGE_TYPE_METHOD_CALL);
116 DBusHandlerResult res =
Bertrand SIMONNET608e4282015-11-12 17:52:17 -0800117 MetricsCollector::MessageFilter(/* connection */ nullptr, msg, &daemon_);
Darin Petkove579d662010-05-05 16:19:39 -0700118 EXPECT_EQ(DBUS_HANDLER_RESULT_NOT_YET_HANDLED, res);
119 DeleteDBusMessage(msg);
120
Daniel Eratb9b05e62010-11-09 12:18:51 -0800121 vector<string> signal_args;
Darin Petkov1bb904e2010-06-16 15:58:06 -0700122 msg = NewDBusSignalString("/",
123 "org.chromium.CrashReporter",
124 "UserCrash",
Daniel Eratb9b05e62010-11-09 12:18:51 -0800125 signal_args);
Bertrand SIMONNET608e4282015-11-12 17:52:17 -0800126 res = MetricsCollector::MessageFilter(/* connection */ nullptr, msg, &daemon_);
Darin Petkov1bb904e2010-06-16 15:58:06 -0700127 EXPECT_EQ(DBUS_HANDLER_RESULT_HANDLED, res);
128 DeleteDBusMessage(msg);
129
Daniel Eratb9b05e62010-11-09 12:18:51 -0800130 signal_args.clear();
Daniel Eratb9b05e62010-11-09 12:18:51 -0800131 signal_args.push_back("randomstate");
132 signal_args.push_back("bob"); // arbitrary username
Darin Petkove579d662010-05-05 16:19:39 -0700133 msg = NewDBusSignalString("/",
134 "org.chromium.UnknownService.Manager",
135 "StateChanged",
Daniel Eratb9b05e62010-11-09 12:18:51 -0800136 signal_args);
Bertrand SIMONNET608e4282015-11-12 17:52:17 -0800137 res = MetricsCollector::MessageFilter(/* connection */ nullptr, msg, &daemon_);
Darin Petkove579d662010-05-05 16:19:39 -0700138 EXPECT_EQ(DBUS_HANDLER_RESULT_NOT_YET_HANDLED, res);
139 DeleteDBusMessage(msg);
140}
141
Bertrand SIMONNET608e4282015-11-12 17:52:17 -0800142TEST_F(MetricsCollectorTest, SendSample) {
Daniel Eratc83975a2014-04-04 08:53:44 -0700143 ExpectSample("Dummy.Metric", 3);
Luigi Semenzato2fd51cc2014-02-26 11:53:16 -0800144 daemon_.SendSample("Dummy.Metric", /* sample */ 3,
Darin Petkov11b8eb32010-05-18 11:00:59 -0700145 /* min */ 1, /* max */ 100, /* buckets */ 50);
146}
147
Bertrand SIMONNET608e4282015-11-12 17:52:17 -0800148TEST_F(MetricsCollectorTest, ProcessMeminfo) {
Bertrand SIMONNETe6cfd642014-07-09 16:35:23 -0700149 string meminfo =
150 "MemTotal: 2000000 kB\nMemFree: 500000 kB\n"
151 "Buffers: 1000000 kB\nCached: 213652 kB\n"
152 "SwapCached: 0 kB\nActive: 133400 kB\n"
153 "Inactive: 183396 kB\nActive(anon): 92984 kB\n"
154 "Inactive(anon): 58860 kB\nActive(file): 40416 kB\n"
155 "Inactive(file): 124536 kB\nUnevictable: 0 kB\n"
156 "Mlocked: 0 kB\nSwapTotal: 0 kB\n"
157 "SwapFree: 0 kB\nDirty: 40 kB\n"
158 "Writeback: 0 kB\nAnonPages: 92652 kB\n"
159 "Mapped: 59716 kB\nShmem: 59196 kB\n"
160 "Slab: 16656 kB\nSReclaimable: 6132 kB\n"
161 "SUnreclaim: 10524 kB\nKernelStack: 1648 kB\n"
162 "PageTables: 2780 kB\nNFS_Unstable: 0 kB\n"
163 "Bounce: 0 kB\nWritebackTmp: 0 kB\n"
164 "CommitLimit: 970656 kB\nCommitted_AS: 1260528 kB\n"
165 "VmallocTotal: 122880 kB\nVmallocUsed: 12144 kB\n"
166 "VmallocChunk: 103824 kB\nDirectMap4k: 9636 kB\n"
167 "DirectMap2M: 1955840 kB\n";
168
Luigi Semenzato8accd332011-05-17 16:37:18 -0700169 // All enum calls must report percents.
Bertrand SIMONNETe6cfd642014-07-09 16:35:23 -0700170 EXPECT_CALL(metrics_lib_, SendEnumToUMA(_, _, 100)).Times(AtLeast(1));
Luigi Semenzato8accd332011-05-17 16:37:18 -0700171 // Check that MemFree is correctly computed at 25%.
172 EXPECT_CALL(metrics_lib_, SendEnumToUMA("Platform.MeminfoMemFree", 25, 100))
173 .Times(AtLeast(1));
174 // Check that we call SendToUma at least once (log histogram).
Luigi Semenzato29c7ef92011-04-12 14:12:35 -0700175 EXPECT_CALL(metrics_lib_, SendToUMA(_, _, _, _, _))
176 .Times(AtLeast(1));
Luigi Semenzato8accd332011-05-17 16:37:18 -0700177 // Make sure we don't report fields not in the list.
178 EXPECT_CALL(metrics_lib_, SendToUMA("Platform.MeminfoMlocked", _, _, _, _))
Luigi Semenzato29c7ef92011-04-12 14:12:35 -0700179 .Times(0);
Luigi Semenzato8accd332011-05-17 16:37:18 -0700180 EXPECT_CALL(metrics_lib_, SendEnumToUMA("Platform.MeminfoMlocked", _, _))
Luigi Semenzato29c7ef92011-04-12 14:12:35 -0700181 .Times(0);
182 EXPECT_TRUE(daemon_.ProcessMeminfo(meminfo));
183}
184
Bertrand SIMONNET608e4282015-11-12 17:52:17 -0800185TEST_F(MetricsCollectorTest, ProcessMeminfo2) {
Bertrand SIMONNETe6cfd642014-07-09 16:35:23 -0700186 string meminfo = "MemTotal: 2000000 kB\nMemFree: 1000000 kB\n";
Luigi Semenzatofb3a8212013-05-07 16:55:00 -0700187 // Not enough fields.
Luigi Semenzato29c7ef92011-04-12 14:12:35 -0700188 EXPECT_FALSE(daemon_.ProcessMeminfo(meminfo));
189}
190
Bertrand SIMONNET608e4282015-11-12 17:52:17 -0800191TEST_F(MetricsCollectorTest, SendZramMetrics) {
Luigi Semenzato96360192014-06-04 10:53:35 -0700192 EXPECT_TRUE(daemon_.testing_);
193
194 // |compr_data_size| is the size in bytes of compressed data.
Ben Chanf05ab402014-08-07 00:54:59 -0700195 const uint64_t compr_data_size = 50 * 1000 * 1000;
Luigi Semenzato96360192014-06-04 10:53:35 -0700196 // The constant '3' is a realistic but random choice.
197 // |orig_data_size| does not include zero pages.
Ben Chanf05ab402014-08-07 00:54:59 -0700198 const uint64_t orig_data_size = compr_data_size * 3;
199 const uint64_t page_size = 4096;
200 const uint64_t zero_pages = 10 * 1000 * 1000 / page_size;
Luigi Semenzato96360192014-06-04 10:53:35 -0700201
Bertrand SIMONNET12531862015-08-31 11:11:57 -0700202 CreateUint64ValueFile(
Bertrand SIMONNET608e4282015-11-12 17:52:17 -0800203 temp_dir_.path().Append(MetricsCollector::kComprDataSizeName),
Bertrand SIMONNET12531862015-08-31 11:11:57 -0700204 compr_data_size);
205 CreateUint64ValueFile(
Bertrand SIMONNET608e4282015-11-12 17:52:17 -0800206 temp_dir_.path().Append(MetricsCollector::kOrigDataSizeName),
Bertrand SIMONNET12531862015-08-31 11:11:57 -0700207 orig_data_size);
208 CreateUint64ValueFile(
Bertrand SIMONNET608e4282015-11-12 17:52:17 -0800209 temp_dir_.path().Append(MetricsCollector::kZeroPagesName), zero_pages);
Luigi Semenzato96360192014-06-04 10:53:35 -0700210
Ben Chanf05ab402014-08-07 00:54:59 -0700211 const uint64_t real_orig_size = orig_data_size + zero_pages * page_size;
212 const uint64_t zero_ratio_percent =
Luigi Semenzato96360192014-06-04 10:53:35 -0700213 zero_pages * page_size * 100 / real_orig_size;
214 // Ratio samples are in percents.
Ben Chanf05ab402014-08-07 00:54:59 -0700215 const uint64_t actual_ratio_sample = real_orig_size * 100 / compr_data_size;
Luigi Semenzato96360192014-06-04 10:53:35 -0700216
217 EXPECT_CALL(metrics_lib_, SendToUMA(_, compr_data_size >> 20, _, _, _));
218 EXPECT_CALL(metrics_lib_,
219 SendToUMA(_, (real_orig_size - compr_data_size) >> 20, _, _, _));
220 EXPECT_CALL(metrics_lib_, SendToUMA(_, actual_ratio_sample, _, _, _));
221 EXPECT_CALL(metrics_lib_, SendToUMA(_, zero_pages, _, _, _));
222 EXPECT_CALL(metrics_lib_, SendToUMA(_, zero_ratio_percent, _, _, _));
223
Bertrand SIMONNET12531862015-08-31 11:11:57 -0700224 EXPECT_TRUE(daemon_.ReportZram(temp_dir_.path()));
Darin Petkov2ccef012010-05-05 16:06:37 -0700225}