Home | History | Annotate | Download | only in metricsd
      1 /*
      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  */
     16 
     17 #include <vector>
     18 
     19 #include <base/at_exit.h>
     20 #include <base/files/file_util.h>
     21 #include <base/files/scoped_temp_dir.h>
     22 #include <base/strings/string_number_conversions.h>
     23 #include <brillo/flag_helper.h>
     24 #include <gtest/gtest.h>
     25 
     26 #include "constants.h"
     27 #include "metrics_collector.h"
     28 #include "metrics/metrics_library_mock.h"
     29 #include "persistent_integer_mock.h"
     30 
     31 using base::FilePath;
     32 using base::TimeDelta;
     33 using std::string;
     34 using std::vector;
     35 using ::testing::_;
     36 using ::testing::AnyNumber;
     37 using ::testing::AtLeast;
     38 using ::testing::Return;
     39 using ::testing::StrictMock;
     40 using chromeos_metrics::PersistentIntegerMock;
     41 
     42 
     43 class MetricsCollectorTest : public testing::Test {
     44  protected:
     45   virtual void SetUp() {
     46     brillo::FlagHelper::Init(0, nullptr, "");
     47     EXPECT_TRUE(temp_dir_.CreateUniqueTempDir());
     48 
     49     base::FilePath private_dir = temp_dir_.path().Append("private");
     50     base::FilePath shared_dir = temp_dir_.path().Append("shared");
     51 
     52     EXPECT_TRUE(base::CreateDirectory(private_dir));
     53     EXPECT_TRUE(base::CreateDirectory(shared_dir));
     54 
     55     daemon_.Init(true, &metrics_lib_, "", private_dir, shared_dir);
     56   }
     57 
     58   // Adds a metrics library mock expectation that the specified metric
     59   // will be generated.
     60   void ExpectSample(const std::string& name, int sample) {
     61     EXPECT_CALL(metrics_lib_, SendToUMA(name, sample, _, _, _))
     62         .Times(1)
     63         .WillOnce(Return(true))
     64         .RetiresOnSaturation();
     65   }
     66 
     67   // Creates or overwrites the file in |path| so that it contains the printable
     68   // representation of |value|.
     69   void CreateUint64ValueFile(const base::FilePath& path, uint64_t value) {
     70     std::string value_string = base::Uint64ToString(value);
     71     ASSERT_EQ(value_string.length(),
     72               base::WriteFile(path, value_string.c_str(),
     73                               value_string.length()));
     74   }
     75 
     76   // The MetricsCollector under test.
     77   MetricsCollector daemon_;
     78 
     79   // Temporary directory used for tests.
     80   base::ScopedTempDir temp_dir_;
     81 
     82   // Mocks. They are strict mock so that all unexpected
     83   // calls are marked as failures.
     84   StrictMock<MetricsLibraryMock> metrics_lib_;
     85 };
     86 
     87 TEST_F(MetricsCollectorTest, SendSample) {
     88   ExpectSample("Dummy.Metric", 3);
     89   daemon_.SendSample("Dummy.Metric", /* sample */ 3,
     90                      /* min */ 1, /* max */ 100, /* buckets */ 50);
     91 }
     92 
     93 TEST_F(MetricsCollectorTest, ProcessMeminfo) {
     94   string meminfo =
     95       "MemTotal:        2000000 kB\nMemFree:          500000 kB\n"
     96       "Buffers:         1000000 kB\nCached:           213652 kB\n"
     97       "SwapCached:            0 kB\nActive:           133400 kB\n"
     98       "Inactive:         183396 kB\nActive(anon):      92984 kB\n"
     99       "Inactive(anon):    58860 kB\nActive(file):      40416 kB\n"
    100       "Inactive(file):   124536 kB\nUnevictable:           0 kB\n"
    101       "Mlocked:               0 kB\nSwapTotal:             0 kB\n"
    102       "SwapFree:              0 kB\nDirty:                40 kB\n"
    103       "Writeback:             0 kB\nAnonPages:         92652 kB\n"
    104       "Mapped:            59716 kB\nShmem:             59196 kB\n"
    105       "Slab:              16656 kB\nSReclaimable:       6132 kB\n"
    106       "SUnreclaim:        10524 kB\nKernelStack:        1648 kB\n"
    107       "PageTables:         2780 kB\nNFS_Unstable:          0 kB\n"
    108       "Bounce:                0 kB\nWritebackTmp:          0 kB\n"
    109       "CommitLimit:      970656 kB\nCommitted_AS:    1260528 kB\n"
    110       "VmallocTotal:     122880 kB\nVmallocUsed:       12144 kB\n"
    111       "VmallocChunk:     103824 kB\nDirectMap4k:        9636 kB\n"
    112       "DirectMap2M:     1955840 kB\n";
    113 
    114   // All enum calls must report percents.
    115   EXPECT_CALL(metrics_lib_, SendEnumToUMA(_, _, 100)).Times(AtLeast(1));
    116   // Check that MemFree is correctly computed at 25%.
    117   EXPECT_CALL(metrics_lib_, SendEnumToUMA("Platform.MeminfoMemFree", 25, 100))
    118       .Times(AtLeast(1));
    119   // Check that we call SendToUma at least once (log histogram).
    120   EXPECT_CALL(metrics_lib_, SendToUMA(_, _, _, _, _))
    121       .Times(AtLeast(1));
    122   // Make sure we don't report fields not in the list.
    123   EXPECT_CALL(metrics_lib_, SendToUMA("Platform.MeminfoMlocked", _, _, _, _))
    124       .Times(0);
    125   EXPECT_CALL(metrics_lib_, SendEnumToUMA("Platform.MeminfoMlocked", _, _))
    126       .Times(0);
    127   EXPECT_TRUE(daemon_.ProcessMeminfo(meminfo));
    128 }
    129 
    130 TEST_F(MetricsCollectorTest, ProcessMeminfo2) {
    131   string meminfo = "MemTotal:        2000000 kB\nMemFree:         1000000 kB\n";
    132   // Not enough fields.
    133   EXPECT_FALSE(daemon_.ProcessMeminfo(meminfo));
    134 }
    135 
    136 TEST_F(MetricsCollectorTest, SendZramMetrics) {
    137   EXPECT_TRUE(daemon_.testing_);
    138 
    139   // |compr_data_size| is the size in bytes of compressed data.
    140   const uint64_t compr_data_size = 50 * 1000 * 1000;
    141   // The constant '3' is a realistic but random choice.
    142   // |orig_data_size| does not include zero pages.
    143   const uint64_t orig_data_size = compr_data_size * 3;
    144   const uint64_t page_size = 4096;
    145   const uint64_t zero_pages = 10 * 1000 * 1000 / page_size;
    146 
    147   CreateUint64ValueFile(
    148       temp_dir_.path().Append(MetricsCollector::kComprDataSizeName),
    149       compr_data_size);
    150   CreateUint64ValueFile(
    151       temp_dir_.path().Append(MetricsCollector::kOrigDataSizeName),
    152       orig_data_size);
    153   CreateUint64ValueFile(
    154       temp_dir_.path().Append(MetricsCollector::kZeroPagesName), zero_pages);
    155 
    156   const uint64_t real_orig_size = orig_data_size + zero_pages * page_size;
    157   const uint64_t zero_ratio_percent =
    158       zero_pages * page_size * 100 / real_orig_size;
    159   // Ratio samples are in percents.
    160   const uint64_t actual_ratio_sample = real_orig_size * 100 / compr_data_size;
    161 
    162   EXPECT_CALL(metrics_lib_, SendToUMA(_, compr_data_size >> 20, _, _, _));
    163   EXPECT_CALL(metrics_lib_,
    164               SendToUMA(_, (real_orig_size - compr_data_size) >> 20, _, _, _));
    165   EXPECT_CALL(metrics_lib_, SendToUMA(_, actual_ratio_sample, _, _, _));
    166   EXPECT_CALL(metrics_lib_, SendToUMA(_, zero_pages, _, _, _));
    167   EXPECT_CALL(metrics_lib_, SendToUMA(_, zero_ratio_percent, _, _, _));
    168 
    169   EXPECT_TRUE(daemon_.ReportZram(temp_dir_.path()));
    170 }
    171