// Copyright 2015 The Chromium OS Authors. All rights reserved. // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. #include "perf_option_parser.h" #include "compat/string.h" #include "compat/test.h" namespace quipper { TEST(PerfOptionParserTest, GoodRecord) { EXPECT_TRUE(ValidatePerfCommandLine({"perf", "record"})); EXPECT_TRUE(ValidatePerfCommandLine({"perf", "record", "-e", "cycles"})); EXPECT_TRUE(ValidatePerfCommandLine( {"perf", "record", "-e", "-$;(*^:,.Non-sense!"})); // let perf reject it. EXPECT_TRUE(ValidatePerfCommandLine( {"perf", "record", "-a", "-e", "iTLB-misses", "-c", "1000003"})); EXPECT_TRUE(ValidatePerfCommandLine( {"perf", "record", "-a", "-e", "cycles", "-g", "-c", "4000037"})); EXPECT_TRUE(ValidatePerfCommandLine({"perf", "record", "-a", "-e", "cycles", "-j", "any_call", "-c", "1000003"})); } TEST(PerfOptionParserTest, GoodStat) { EXPECT_TRUE(ValidatePerfCommandLine( {"perf", "stat", "-a", "-e", "cpu/mem-loads/", "-e", "cpu/mem-stores/"})); } // Options that control the output format should only be specified by quipper. TEST(PerfOptionParserTest, BadRecord_OutputOptions) { EXPECT_FALSE( ValidatePerfCommandLine({"perf", "record", "-e", "cycles", "-v"})); EXPECT_FALSE( ValidatePerfCommandLine({"perf", "record", "--verbose", "-e", "cycles"})); EXPECT_FALSE( ValidatePerfCommandLine({"perf", "record", "-q", "-e", "cycles"})); EXPECT_FALSE( ValidatePerfCommandLine({"perf", "record", "-e", "cycles", "--quiet"})); EXPECT_FALSE( ValidatePerfCommandLine({"perf", "record", "-e", "cycles", "-m", "512"})); EXPECT_FALSE(ValidatePerfCommandLine( {"perf", "record", "-e", "cycles", "--mmap-pages", "512"})); } TEST(PerfOptionParserTest, BadRecord_BannedOptions) { EXPECT_FALSE( ValidatePerfCommandLine({"perf", "record", "-e", "cycles", "-D"})); EXPECT_FALSE( ValidatePerfCommandLine({"perf", "record", "-e", "cycles", "-D", "10"})); } TEST(PerfOptionParserTest, GoodMemRecord) { EXPECT_TRUE(ValidatePerfCommandLine({"perf", "mem", "record"})); EXPECT_TRUE( ValidatePerfCommandLine({"perf", "mem", "record", "-e", "cycles"})); // let perf reject it. EXPECT_TRUE(ValidatePerfCommandLine( {"perf", "mem", "record", "-e", "-$;(*^:,.Non-sense!"})); EXPECT_TRUE(ValidatePerfCommandLine( {"perf", "mem", "record", "-a", "-e", "iTLB-misses", "-c", "1000003"})); EXPECT_TRUE(ValidatePerfCommandLine( {"perf", "mem", "record", "-a", "-e", "cycles", "-g", "-c", "4000037"})); EXPECT_TRUE( ValidatePerfCommandLine({"perf", "mem", "record", "-a", "-e", "cycles", "-j", "any_call", "-c", "1000003"})); // Check perf-mem options that come before "record". // See http://man7.org/linux/man-pages/man1/perf-mem.1.html EXPECT_TRUE(ValidatePerfCommandLine( {"perf", "mem", "-t", "load", "record", "-e", "-$;(*^:,.Non-sense!"})); EXPECT_TRUE( ValidatePerfCommandLine({"perf", "mem", "--type", "load,store", "record", "-a", "-e", "iTLB-misses", "-c", "1000003"})); EXPECT_TRUE( ValidatePerfCommandLine({"perf", "mem", "-D", "-x", ":", "record", "-a", "-e", "cycles", "-g", "-c", "4000037"})); EXPECT_TRUE( ValidatePerfCommandLine({"perf", "mem", "-C", "0,1", "record", "-a", "-e", "cycles", "-j", "any_call", "-c", "1000003"})); } TEST(PerfOptionParserTest, BadMemRecord_OutputOptions) { EXPECT_FALSE(ValidatePerfCommandLine( {"perf", "mem", "-t", "load,store", "record", "-e", "cycles", "-v"})); EXPECT_FALSE(ValidatePerfCommandLine( {"perf", "mem", "-t", "load", "record", "--verbose", "-e", "cycles"})); EXPECT_FALSE(ValidatePerfCommandLine( {"perf", "mem", "-D", "-x", ":", "record", "-q", "-e", "cycles"})); EXPECT_FALSE(ValidatePerfCommandLine( {"perf", "mem", "-C", "0,1", "record", "-e", "cycles", "--quiet"})); EXPECT_FALSE(ValidatePerfCommandLine( {"perf", "mem", "record", "-e", "cycles", "-m", "512"})); EXPECT_FALSE(ValidatePerfCommandLine( {"perf", "mem", "record", "-e", "cycles", "--mmap-pages", "512"})); // Try some bad perf-mem options. EXPECT_FALSE(ValidatePerfCommandLine( {"perf", "mem", "-y", "-z", "record", "-e", "-$;(*^:,.Non-sense!"})); EXPECT_FALSE(ValidatePerfCommandLine({"perf", "mem", "--blah", "record", "-a", "-e", "iTLB-misses", "-c", "1000003"})); EXPECT_FALSE( ValidatePerfCommandLine({"perf", "mem", "--no-way", "record", "-a", "-e", "cycles", "-g", "-c", "4000037"})); EXPECT_FALSE( ValidatePerfCommandLine({"perf", "mem", "--danger", "record", "-a", "-e", "cycles", "-j", "any_call", "-c", "1000003"})); } TEST(PerfOptionParserTest, BadMemRecord_BannedOptions) { EXPECT_FALSE( ValidatePerfCommandLine({"perf", "mem", "record", "-e", "cycles", "-D"})); EXPECT_FALSE(ValidatePerfCommandLine( {"perf", "mem", "record", "-e", "cycles", "-D", "10"})); } // Options that control the output format should only be specified by quipper. TEST(PerfOptionParserTest, BadStat_OutputOptions) { EXPECT_FALSE(ValidatePerfCommandLine({"perf", "stat", "-e", "cycles", "-v"})); EXPECT_FALSE( ValidatePerfCommandLine({"perf", "stat", "--verbose", "-e", "cycles"})); EXPECT_FALSE(ValidatePerfCommandLine({"perf", "stat", "-q", "-e", "cycles"})); EXPECT_FALSE( ValidatePerfCommandLine({"perf", "stat", "-e", "cycles", "--quiet"})); EXPECT_FALSE( ValidatePerfCommandLine({"perf", "stat", "-e", "cycles", "-x", "::"})); EXPECT_FALSE(ValidatePerfCommandLine( {"perf", "stat", "-e", "cycles", "--field-separator", ","})); } TEST(PerfOptionParserTest, BadStat_BannedOptions) { EXPECT_FALSE(ValidatePerfCommandLine({"perf", "stat", "--pre", "rm -rf /"})); EXPECT_FALSE(ValidatePerfCommandLine({"perf", "stat", "--post", "rm -rf /"})); EXPECT_FALSE(ValidatePerfCommandLine({"perf", "stat", "-d"})); EXPECT_FALSE(ValidatePerfCommandLine({"perf", "stat", "--log-fd", "4"})); } TEST(PerfOptionParserTest, DontAllowOtherPerfSubcommands) { EXPECT_FALSE(ValidatePerfCommandLine({"perf", "list"})); EXPECT_FALSE(ValidatePerfCommandLine({"perf", "report"})); EXPECT_FALSE(ValidatePerfCommandLine({"perf", "trace"})); } // Unsafe command lines for either perf command. TEST(PerfOptionParserTest, Ugly) { for (const string &subcmd : {"record", "stat", "mem"}) { EXPECT_FALSE(ValidatePerfCommandLine({"perf", subcmd, "rm", "-rf", "/"})); EXPECT_FALSE( ValidatePerfCommandLine({"perf", subcmd, "--", "rm", "-rf", "/"})); EXPECT_FALSE(ValidatePerfCommandLine( {"perf", subcmd, "-e", "cycles", "rm", "-rf", "/"})); EXPECT_FALSE(ValidatePerfCommandLine( {"perf", subcmd, "-e", "cycles", "-o", "/root/haha.perf.data"})); } } // Regression test for correct past-the-end iteration. TEST(PerfOptionParserTest, ValueCommandAtEnd) { EXPECT_FALSE( ValidatePerfCommandLine({"perf", "record", "-c" /*missing value!*/})); EXPECT_FALSE( ValidatePerfCommandLine({"perf", "stat", "-e" /*missing value!*/})); EXPECT_FALSE(ValidatePerfCommandLine({"perf", "mem", "record" "-j" /*missing value!*/})); EXPECT_FALSE(ValidatePerfCommandLine( {"perf", "mem", "-t", "load", "record", "-e" /*missing value!*/})); } } // namespace quipper