// Copyright 2024 The Chromium Authors
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#ifdef UNSAFE_BUFFERS_BUILD
// TODO(crbug.com/40285824): Remove this and convert code to safer constructs.
#pragma allow_unsafe_buffers
#endif
#include "components/tracing/common/etw_system_data_source_win.h"
#include <vector>
#include "base/containers/span.h"
#include "base/logging.h"
#include "testing/gtest/include/gtest/gtest.h"
#include "third_party/perfetto/include/perfetto/protozero/scattered_heap_buffer.h"
#include "third_party/perfetto/protos/perfetto/trace/etw/etw.pbzero.h"
#include "third_party/perfetto/protos/perfetto/trace/etw/etw_event.pbzero.h"
namespace tracing {
TEST(EtwSystemDataSource, DecodeCSwitchEvent_Empty) {
std::vector<uint8_t> data = {};
protozero::HeapBuffered<perfetto::protos::pbzero::EtwTraceEvent> event;
EXPECT_FALSE(
EtwSystemDataSource::DecodeCSwitchEvent({data.data(), 0U}, *event.get()));
}
TEST(EtwSystemDataSource, DecodeCSwitchEvent_TooShort) {
std::vector<uint8_t> data(0x00, 23);
protozero::HeapBuffered<perfetto::protos::pbzero::EtwTraceEvent> event;
EXPECT_FALSE(EtwSystemDataSource::DecodeCSwitchEvent(
{data.data(), data.size()}, *event.get()));
}
TEST(EtwSystemDataSource, DecodeCSwitchEvent) {
std::vector<uint8_t> data = {
0x55, 0x00, 0x00, 0x00, // new_thread_id
0x44, 0x00, 0x00, 0x00, // old_thread_id
0x01, // new_thread_priority
0x02, // old_thread_priority
0x03, // previous_c_state
0x42, // SpareByte
36, // old_thread_wait_reason = WR_RUNDOWN
1, // old_thread_wait_mode = USER_MODE
7, // old_thread_state = DEFERRED_READY
0x04, // old_thread_wait_ideal_processor
0x05, 0x00, 0x00, 0x00, // new_thread_wait_time
0x42, 0x42, 0x42, 0x42, // Reserved
};
protozero::HeapBuffered<perfetto::protos::pbzero::EtwTraceEvent> event;
ASSERT_TRUE(EtwSystemDataSource::DecodeCSwitchEvent(
{data.data(), data.size()}, *event.get()));
auto serialized = event.SerializeAsString();
perfetto::protos::pbzero::EtwTraceEvent::Decoder decoded_event(serialized);
ASSERT_TRUE(decoded_event.has_c_switch());
perfetto::protos::pbzero::CSwitchEtwEvent::Decoder c_switch(
decoded_event.c_switch());
EXPECT_EQ(0x55u, c_switch.new_thread_id());
EXPECT_EQ(0x44u, c_switch.old_thread_id());
EXPECT_EQ(0x01, c_switch.new_thread_priority());
EXPECT_EQ(0x02, c_switch.old_thread_priority());
EXPECT_EQ(0x03u, c_switch.previous_c_state());
EXPECT_EQ(perfetto::protos::pbzero::CSwitchEtwEvent::WR_RUNDOWN,
c_switch.old_thread_wait_reason());
EXPECT_EQ(perfetto::protos::pbzero::CSwitchEtwEvent::USER_MODE,
c_switch.old_thread_wait_mode());
EXPECT_EQ(perfetto::protos::pbzero::CSwitchEtwEvent::DEFERRED_READY,
c_switch.old_thread_state());
EXPECT_EQ(0x04, c_switch.old_thread_wait_ideal_processor());
EXPECT_EQ(0x05u, c_switch.new_thread_wait_time());
}
} // namespace tracing