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
15namespace quipper {
16
17namespace {
18
19const char kInvalidInput[] =
20    "PerfDataProto\n"
21    "Attr: Even Count BuildID\n"
22    "1.234 1234.5 time seconds\n";
23
24const 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'
32const 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
50TEST(PerfStatParserTest, InvalidStringReturnsFalse) {
51  PerfStatProto proto;
52  ASSERT_FALSE(ParsePerfStatOutputToProto(kInvalidInput, &proto));
53}
54
55TEST(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
92TEST(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
119TEST(PerfStatParserTest, NonexistentFileReturnsFalse) {
120  PerfStatProto proto;
121  ASSERT_FALSE(ParsePerfStatFileToProto("/dev/null/nope/nope.txt", &proto));
122}
123
124TEST(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