1 // Copyright 2015 The Chromium OS Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4
5 #include <string>
6
7 #include "base/logging.h"
8
9 #include "compat/string.h"
10 #include "compat/test.h"
11 #include "file_utils.h"
12 #include "perf_stat_parser.h"
13 #include "scoped_temp_path.h"
14
15 namespace quipper {
16
17 namespace {
18
19 const char kInvalidInput[] =
20 "PerfDataProto\n"
21 "Attr: Even Count BuildID\n"
22 "1.234 1234.5 time seconds\n";
23
24 const char kSmallInput[] =
25 "/uncore/reads/: 711983 1002113142 1002111143\n"
26 "/uncore/writes/: 140867 1002113864 1002113864\n"
27 " \n"; // Test parsing an empty line
28
29 // From a Peppy running:
30 // 'perf stat -v -a -e cycles -e L1-dcache-loads -e bus-cycles -e r02c4 --'
31 // ' sleep 2'
32 const char kFullInput[] =
33 "cycles: 19062079 4002390292 4002381587\n"
34 "L1-dcache-loads: 2081375 4002517554 4002511235\n"
35 "bus-cycles: 2259169 4002527446 4002523976\n"
36 "r02c4: 201584 4002518485 4002518485\n"
37 "\n"
38 " Performance counter stats for 'system wide':\n"
39 "\n"
40 " 19062079 cycles [100.00%]\n"
41 " 2081375 L1-dcache-loads [100.00%]\n"
42 " 2259169 bus-cycles [100.00%]\n"
43 " 201584 r02c4 \n"
44 "\n"
45 " 2.001402976 seconds time elapsed\n"
46 "\n";
47
48 } // namespace
49
TEST(PerfStatParserTest,InvalidStringReturnsFalse)50 TEST(PerfStatParserTest, InvalidStringReturnsFalse) {
51 PerfStatProto proto;
52 ASSERT_FALSE(ParsePerfStatOutputToProto(kInvalidInput, &proto));
53 }
54
TEST(PerfStatParserTest,ValidInputParsesCorrectly)55 TEST(PerfStatParserTest, ValidInputParsesCorrectly) {
56 // Test string input
57 PerfStatProto proto;
58 ASSERT_TRUE(ParsePerfStatOutputToProto(kSmallInput, &proto));
59
60 ASSERT_EQ(proto.line_size(), 2);
61
62 const auto& line1 = proto.line(0);
63 EXPECT_EQ("/uncore/reads/", line1.event_name());
64 EXPECT_EQ(711983, line1.count());
65 EXPECT_FALSE(line1.has_time_ms());
66
67 const auto& line2 = proto.line(1);
68 EXPECT_EQ("/uncore/writes/", line2.event_name());
69 EXPECT_EQ(140867, line2.count());
70 EXPECT_FALSE(line2.has_time_ms());
71
72 // Test file input
73 ScopedTempFile input;
74 ASSERT_FALSE(input.path().empty());
75 ASSERT_TRUE(BufferToFile(input.path(), string(kSmallInput)));
76 PerfStatProto proto2;
77 ASSERT_TRUE(ParsePerfStatFileToProto(input.path(), &proto2));
78
79 ASSERT_EQ(proto2.line_size(), 2);
80
81 const auto& line3 = proto2.line(0);
82 EXPECT_EQ("/uncore/reads/", line3.event_name());
83 EXPECT_EQ(711983, line3.count());
84 EXPECT_FALSE(line3.has_time_ms());
85
86 const auto& line4 = proto2.line(1);
87 EXPECT_EQ("/uncore/writes/", line4.event_name());
88 EXPECT_EQ(140867, line4.count());
89 EXPECT_FALSE(line4.has_time_ms());
90 }
91
TEST(PerfStatParserTest,ValidFullStringParsesCorrectly)92 TEST(PerfStatParserTest, ValidFullStringParsesCorrectly) {
93 PerfStatProto proto;
94 ASSERT_TRUE(ParsePerfStatOutputToProto(kFullInput, &proto));
95
96 ASSERT_EQ(proto.line_size(), 4);
97
98 const auto& line1 = proto.line(0);
99 EXPECT_EQ("cycles", line1.event_name());
100 EXPECT_EQ(19062079, line1.count());
101 EXPECT_EQ(2001, line1.time_ms());
102
103 const auto& line2 = proto.line(1);
104 EXPECT_EQ("L1-dcache-loads", line2.event_name());
105 EXPECT_EQ(2081375, line2.count());
106 EXPECT_EQ(2001, line2.time_ms());
107
108 const auto& line3 = proto.line(2);
109 EXPECT_EQ("bus-cycles", line3.event_name());
110 EXPECT_EQ(2259169, line3.count());
111 EXPECT_EQ(2001, line3.time_ms());
112
113 const auto& line4 = proto.line(3);
114 EXPECT_EQ("r02c4", line4.event_name());
115 EXPECT_EQ(201584, line4.count());
116 EXPECT_EQ(2001, line4.time_ms());
117 }
118
TEST(PerfStatParserTest,NonexistentFileReturnsFalse)119 TEST(PerfStatParserTest, NonexistentFileReturnsFalse) {
120 PerfStatProto proto;
121 ASSERT_FALSE(ParsePerfStatFileToProto("/dev/null/nope/nope.txt", &proto));
122 }
123
TEST(PerfStatParserTest,ParseTime)124 TEST(PerfStatParserTest, ParseTime) {
125 uint64_t out;
126 EXPECT_TRUE(SecondsStringToMillisecondsUint64("123.456", &out));
127 EXPECT_EQ(123456, out);
128 EXPECT_TRUE(SecondsStringToMillisecondsUint64("2.0014", &out));
129 EXPECT_EQ(2001, out);
130 EXPECT_TRUE(SecondsStringToMillisecondsUint64("0.0027", &out));
131 EXPECT_EQ(3, out);
132 EXPECT_FALSE(SecondsStringToMillisecondsUint64("-10.0027", &out));
133 EXPECT_FALSE(SecondsStringToMillisecondsUint64("string", &out));
134 EXPECT_FALSE(SecondsStringToMillisecondsUint64("string.string", &out));
135 EXPECT_FALSE(SecondsStringToMillisecondsUint64("23.string", &out));
136 EXPECT_FALSE(SecondsStringToMillisecondsUint64("string.23456", &out));
137 EXPECT_FALSE(SecondsStringToMillisecondsUint64("123.234.456", &out));
138 }
139
140 } // namespace quipper
141