1 /*
2  * Copyright (C) 2024 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 <gtest/gtest.h>
18 #include <pixelstats/MmMetricsReporter.h>
19 
20 #include "MmMetricsGoldenAtomFieldTypes.h"
21 #include "MmMetricsGoldenResults.h"
22 #include "MockMmMetricsReporter.h"
23 #include "VendorAtomIntValueUtil.h"
24 
25 #ifndef ARRAY_SIZE
26 #define ARRAY_SIZE(a) (sizeof(a) / sizeof((a)[0]))
27 #endif
28 
29 namespace android {
30 namespace hardware {
31 namespace google {
32 namespace pixel {
33 
34 using mm_metrics_atom_field_test_golden_results::PixelMmMetricsPerDay_field_types;
35 using mm_metrics_atom_field_test_golden_results::PixelMmMetricsPerHour_field_types;
36 using mm_metrics_reporter_test_golden_result::PixelMmMetricsPerDay_golden;
37 using mm_metrics_reporter_test_golden_result::PixelMmMetricsPerHour_golden;
38 
39 const char *data_base_path = "/data/local/tmp/test/pixelstats_mm_test/data";
40 
TEST(MmMetricsReporterTest,MmMetricsPerHourAtomFieldOffsetTypeTest)41 TEST(MmMetricsReporterTest, MmMetricsPerHourAtomFieldOffsetTypeTest) {
42     int i = -1;
43     uint64_t golden_result;
44     int field_type;
45     std::vector<VendorAtomValue> values;
46     MockMmMetricsReporter mreport;
47     const std::string data_path0 = std::string(data_base_path) + "/test_data_0";
48     const std::string data_path1 = std::string(data_base_path) + "/test_data_1";
49 
50     // Assert failure means the test case itself has a bug.
51     ASSERT_EQ(ARRAY_SIZE(PixelMmMetricsPerHour_golden),
52               ARRAY_SIZE(PixelMmMetricsPerHour_field_types));
53 
54     /**
55      * In test code we use setBasePath() to read different data sets for simulating
56      * different timing reads of a sysfs node.
57      */
58 
59     /**
60      * aggregatePixelMmMetricsPer5Min() aggregates PSI into max, min, and avg.
61      * For the regular code, it will be called 12 times per hour (i.e. once per 5min)
62      * For test code we do 6 times: enough for testing.
63      * e.g. here average  = (3 x data0 + 3 x data1) / 6 == avg of data 0, 1
64      * The following sequence simulate regular code obtaining sysfs nodes into
65      * values[] array (i.e. atom), ready to be sent to the server
66      */
67     mreport.setBasePath(data_path0);
68     mreport.aggregatePixelMmMetricsPer5Min();
69     mreport.aggregatePixelMmMetricsPer5Min();
70     mreport.aggregatePixelMmMetricsPer5Min();
71     mreport.setBasePath(data_path1);
72     mreport.aggregatePixelMmMetricsPer5Min();
73     mreport.aggregatePixelMmMetricsPer5Min();
74     mreport.aggregatePixelMmMetricsPer5Min();
75 
76     // other fields from data set #0
77     mreport.setBasePath(data_path0);
78     values = mreport.genPixelMmMetricsPerHour();
79 
80     // Validate the atom: compare with golden results
81     EXPECT_EQ(values.size(), ARRAY_SIZE(PixelMmMetricsPerHour_field_types));
82     for (auto const &v : values) {
83         i++;
84         golden_result = PixelMmMetricsPerHour_golden[i];
85         field_type = PixelMmMetricsPerHour_field_types[i];
86         if (golden_result == -1)
87             continue;  // no need to test (e.g. deprecated field)
88 
89         EXPECT_EQ(static_cast<int>(v.getTag()), field_type) << "type mismatch at offset " << i;
90         EXPECT_EQ(getVendorAtomIntValue(v), golden_result) << "value mismatch at offset " << i;
91     }
92 }
93 
TEST(MmMetricsReporterTest,MmMetricsPerDayAtomFieldOffsetTypeTest)94 TEST(MmMetricsReporterTest, MmMetricsPerDayAtomFieldOffsetTypeTest) {
95     int i = -1;
96     uint64_t golden_result;
97     int field_type;
98     std::vector<VendorAtomValue> values;
99     MockMmMetricsReporter mreport;
100     const std::string data_path0 = std::string(data_base_path) + "/test_data_0";
101     const std::string data_path1 = std::string(data_base_path) + "/test_data_1";
102 
103     // Assert failure means the test case itself has a bug.
104     ASSERT_EQ(ARRAY_SIZE(PixelMmMetricsPerDay_golden),
105               ARRAY_SIZE(PixelMmMetricsPerDay_field_types));
106 
107     mreport.setBasePath(data_path0);
108     values = mreport.genPixelMmMetricsPerDay();
109 
110     // PixelMmMetricsPerDay calculatd the difference of consecutive readings.
111     // So, it will not send values[] at the 1st read. (i.e. empty for the 1st read)
112     EXPECT_EQ(values.size(), 0);
113     values.clear();
114 
115     mreport.setBasePath(data_path1);
116     values = mreport.genPixelMmMetricsPerDay();
117 
118     // Per Day metrics (diffs) should be calculated, values[] will be non-empty now.
119     // number of data should be the same as the number of fields in the atom.
120     EXPECT_EQ(values.size(), ARRAY_SIZE(PixelMmMetricsPerDay_field_types));
121     for (auto const &v : values) {
122         i++;
123         EXPECT_LT(i, ARRAY_SIZE(PixelMmMetricsPerDay_field_types));
124 
125         golden_result = PixelMmMetricsPerDay_golden[i];
126         field_type = PixelMmMetricsPerDay_field_types[i];
127         if (golden_result == -1)
128             continue;  // no need to test (e.g. deprecated field)
129 
130         EXPECT_EQ(static_cast<int>(v.getTag()), field_type) << "type mismatch at offset " << i;
131         EXPECT_EQ(getVendorAtomIntValue(v), golden_result) << "value mismatch at offset " << i;
132     }
133 }
134 
135 }  // namespace pixel
136 }  // namespace google
137 }  // namespace hardware
138 }  // namespace android
139