/* * Copyright (C) 2017 The Android Open Source Project * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ #include <fstream> #include <set> #include <sstream> #include <string> #include "gmock/gmock.h" #include "gtest/gtest.h" #include "perfetto/base/file_utils.h" #include "perfetto/ftrace_reader/ftrace_controller.h" #include "src/ftrace_reader/ftrace_procfs.h" using testing::HasSubstr; using testing::Not; using testing::Contains; namespace perfetto { namespace { constexpr char kTracingPath[] = "/sys/kernel/debug/tracing/"; void ResetFtrace(FtraceProcfs* ftrace) { ftrace->DisableAllEvents(); ftrace->ClearTrace(); ftrace->EnableTracing(); } std::string ReadFile(const std::string& name) { std::string result; PERFETTO_CHECK(base::ReadFile(kTracingPath + name, &result)); return result; } std::string GetTraceOutput() { std::string output = ReadFile("trace"); if (output.empty()) { ADD_FAILURE() << "Could not read trace output"; } return output; } } // namespace // TODO(lalitm): reenable these tests (see b/72306171). #if PERFETTO_BUILDFLAG(PERFETTO_OS_ANDROID) #define MAYBE_CreateWithGoodPath CreateWithGoodPath #else #define MAYBE_CreateWithGoodPath DISABLED_CreateWithGoodPath #endif TEST(FtraceProcfsIntegrationTest, MAYBE_CreateWithGoodPath) { EXPECT_TRUE(FtraceProcfs::Create(kTracingPath)); } #if PERFETTO_BUILDFLAG(PERFETTO_OS_ANDROID) #define MAYBE_CreateWithBadPath CreateWithBadPath #else #define MAYBE_CreateWithBadPath DISABLED_CreateWithBadath #endif TEST(FtraceProcfsIntegrationTest, MAYBE_CreateWithBadPath) { EXPECT_FALSE(FtraceProcfs::Create(kTracingPath + std::string("bad_path"))); } #if PERFETTO_BUILDFLAG(PERFETTO_OS_ANDROID) #define MAYBE_ClearTrace ClearTrace #else #define MAYBE_ClearTrace DISABLED_ClearTrace #endif TEST(FtraceProcfsIntegrationTest, MAYBE_ClearTrace) { FtraceProcfs ftrace(kTracingPath); ResetFtrace(&ftrace); ftrace.WriteTraceMarker("Hello, World!"); ftrace.ClearTrace(); EXPECT_THAT(GetTraceOutput(), Not(HasSubstr("Hello, World!"))); } #if PERFETTO_BUILDFLAG(PERFETTO_OS_ANDROID) #define MAYBE_TraceMarker TraceMarker #else #define MAYBE_TraceMarker DISABLED_TraceMarker #endif TEST(FtraceProcfsIntegrationTest, MAYBE_TraceMarker) { FtraceProcfs ftrace(kTracingPath); ResetFtrace(&ftrace); ftrace.WriteTraceMarker("Hello, World!"); EXPECT_THAT(GetTraceOutput(), HasSubstr("Hello, World!")); } #if PERFETTO_BUILDFLAG(PERFETTO_OS_ANDROID) #define MAYBE_EnableDisableEvent EnableDisableEvent #else #define MAYBE_EnableDisableEvent DISABLED_EnableDisableEvent #endif TEST(FtraceProcfsIntegrationTest, MAYBE_EnableDisableEvent) { FtraceProcfs ftrace(kTracingPath); ResetFtrace(&ftrace); ftrace.EnableEvent("sched", "sched_switch"); sleep(1); EXPECT_THAT(GetTraceOutput(), HasSubstr("sched_switch")); ftrace.DisableEvent("sched", "sched_switch"); ftrace.ClearTrace(); sleep(1); EXPECT_THAT(GetTraceOutput(), Not(HasSubstr("sched_switch"))); } #if PERFETTO_BUILDFLAG(PERFETTO_OS_ANDROID) #define MAYBE_EnableDisableTracing EnableDisableTracing #else #define MAYBE_EnableDisableTracing DISABLED_EnableDisableTracing #endif TEST(FtraceProcfsIntegrationTest, MAYBE_EnableDisableTracing) { FtraceProcfs ftrace(kTracingPath); ResetFtrace(&ftrace); EXPECT_TRUE(ftrace.IsTracingEnabled()); ftrace.WriteTraceMarker("Before"); ftrace.DisableTracing(); EXPECT_FALSE(ftrace.IsTracingEnabled()); ftrace.WriteTraceMarker("During"); ftrace.EnableTracing(); EXPECT_TRUE(ftrace.IsTracingEnabled()); ftrace.WriteTraceMarker("After"); EXPECT_THAT(GetTraceOutput(), HasSubstr("Before")); EXPECT_THAT(GetTraceOutput(), Not(HasSubstr("During"))); EXPECT_THAT(GetTraceOutput(), HasSubstr("After")); } #if PERFETTO_BUILDFLAG(PERFETTO_OS_ANDROID) #define MAYBE_ReadFormatFile ReadFormatFile #else #define MAYBE_ReadFormatFile DISABLED_ReadFormatFile #endif TEST(FtraceProcfsIntegrationTest, MAYBE_ReadFormatFile) { FtraceProcfs ftrace(kTracingPath); std::string format = ftrace.ReadEventFormat("ftrace", "print"); EXPECT_THAT(format, HasSubstr("name: print")); EXPECT_THAT(format, HasSubstr("field:char buf")); } #if PERFETTO_BUILDFLAG(PERFETTO_OS_ANDROID) #define MAYBE_CanOpenTracePipeRaw CanOpenTracePipeRaw #else #define MAYBE_CanOpenTracePipeRaw DISABLED_CanOpenTracePipeRaw #endif TEST(FtraceProcfsIntegrationTest, MAYBE_CanOpenTracePipeRaw) { FtraceProcfs ftrace(kTracingPath); EXPECT_TRUE(ftrace.OpenPipeForCpu(0)); } #if PERFETTO_BUILDFLAG(PERFETTO_OS_ANDROID) #define MAYBE_Clock Clock #else #define MAYBE_Clock DISABLED_Clock #endif TEST(FtraceProcfsIntegrationTest, MAYBE_Clock) { FtraceProcfs ftrace(kTracingPath); std::set<std::string> clocks = ftrace.AvailableClocks(); EXPECT_THAT(clocks, Contains("local")); EXPECT_THAT(clocks, Contains("global")); EXPECT_TRUE(ftrace.SetClock("global")); EXPECT_EQ(ftrace.GetClock(), "global"); EXPECT_TRUE(ftrace.SetClock("local")); EXPECT_EQ(ftrace.GetClock(), "local"); } #if PERFETTO_BUILDFLAG(PERFETTO_OS_ANDROID) #define MAYBE_CanSetBufferSize CanSetBufferSize #else #define MAYBE_CanSetBufferSize DISABLED_CanSetBufferSize #endif TEST(FtraceProcfsIntegrationTest, MAYBE_CanSetBufferSize) { FtraceProcfs ftrace(kTracingPath); EXPECT_TRUE(ftrace.SetCpuBufferSizeInPages(4ul)); EXPECT_EQ(ReadFile("buffer_size_kb"), "16\n"); // (4096 * 4) / 1024 EXPECT_TRUE(ftrace.SetCpuBufferSizeInPages(5ul)); EXPECT_EQ(ReadFile("buffer_size_kb"), "20\n"); // (4096 * 5) / 1024 } #if PERFETTO_BUILDFLAG(PERFETTO_OS_ANDROID) #define MAYBE_FtraceControllerHardReset FtraceControllerHardReset #else #define MAYBE_FtraceControllerHardReset DISABLED_FtraceControllerHardReset #endif TEST(FtraceProcfsIntegrationTest, MAYBE_FtraceControllerHardReset) { FtraceProcfs ftrace(kTracingPath); ResetFtrace(&ftrace); ftrace.SetCpuBufferSizeInPages(4ul); ftrace.EnableTracing(); ftrace.EnableEvent("sched", "sched_switch"); ftrace.WriteTraceMarker("Hello, World!"); EXPECT_EQ(ReadFile("buffer_size_kb"), "16\n"); EXPECT_EQ(ReadFile("tracing_on"), "1\n"); EXPECT_EQ(ReadFile("events/enable"), "X\n"); EXPECT_THAT(GetTraceOutput(), HasSubstr("Hello")); HardResetFtraceState(); EXPECT_EQ(ReadFile("buffer_size_kb"), "4\n"); EXPECT_EQ(ReadFile("tracing_on"), "0\n"); EXPECT_EQ(ReadFile("events/enable"), "0\n"); EXPECT_THAT(GetTraceOutput(), Not(HasSubstr("Hello"))); } } // namespace perfetto