/*
* 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