//===-- TraceGDBRemotePacketsTest.cpp -------------------------------------===// // // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. // See https://llvm.org/LICENSE.txt for license information. // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception // //===----------------------------------------------------------------------===// #include "lldb/Utility/TraceIntelPTGDBRemotePackets.h" #include "gtest/gtest.h" #include using namespace lldb_private; using namespace llvm; // Test serialization and deserialization of a non-empty // TraceIntelPTGetStateResponse. TEST(TraceGDBRemotePacketsTest, IntelPTGetStateResponse) { // This test works as follows: // 1. Create a non-empty TraceIntelPTGetStateResponse // 2. Serialize to JSON // 3. Deserialize the serialized JSON value // 4. Ensure the original value and the deserialized value are equivalent // // Notes: // - We intentionally set an integer value out of its signed range // to ensure the serialization/deserialization isn't lossy since JSON // operates on signed values // Choose arbitrary values for time_mult and time_shift uint32_t test_time_mult = 1076264588; uint16_t test_time_shift = 31; // Intentionally set time_zero value out of the signed type's range. uint64_t test_time_zero = static_cast(std::numeric_limits::max()) + 1; // Create TraceIntelPTGetStateResponse. TraceIntelPTGetStateResponse response; response.tsc_perf_zero_conversion = LinuxPerfZeroTscConversion{test_time_mult, test_time_shift, {test_time_zero}}; // Serialize then deserialize. Expected deserialized_response = json::parse( llvm::formatv("{0}", toJSON(response)).str(), "TraceIntelPTGetStateResponse"); if (!deserialized_response) FAIL() << toString(deserialized_response.takeError()); // Choose arbitrary TSC value to test the Convert function. const uint64_t TSC = std::numeric_limits::max(); // Expected nanosecond value pre calculated using the TSC to wall time // conversion formula located in the time_zero section of // https://man7.org/linux/man-pages/man2/perf_event_open.2.html const uint64_t EXPECTED_NANOS = 9223372039007304983u; uint64_t pre_serialization_conversion = response.tsc_perf_zero_conversion->ToNanos(TSC); uint64_t post_serialization_conversion = deserialized_response->tsc_perf_zero_conversion->ToNanos(TSC); // Check equality: // Ensure that both the TraceGetStateResponse and TraceIntelPTGetStateResponse // portions of the JSON representation are unchanged. ASSERT_EQ(toJSON(response), toJSON(*deserialized_response)); // Ensure the result of the Convert function is unchanged. ASSERT_EQ(EXPECTED_NANOS, pre_serialization_conversion); ASSERT_EQ(EXPECTED_NANOS, post_serialization_conversion); } // Test serialization and deserialization of an empty // TraceIntelPTGetStateResponse. TEST(TraceGDBRemotePacketsTest, IntelPTGetStateResponseEmpty) { // This test works as follows: // 1. Create an empty TraceIntelPTGetStateResponse // 2. Serialize to JSON // 3. Deserialize the serialized JSON value // 4. Ensure the original value and the deserialized value are equivalent // Create TraceIntelPTGetStateResponse. TraceIntelPTGetStateResponse response; // Serialize then deserialize. Expected deserialized_response = json::parse( llvm::formatv("{0}", toJSON(response)).str(), "TraceIntelPTGetStateResponse"); if (!deserialized_response) FAIL() << toString(deserialized_response.takeError()); // Check equality: // Ensure that both the TraceGetStateResponse and TraceIntelPTGetStateResponse // portions of the JSON representation are unchanged. ASSERT_EQ(toJSON(response), toJSON(*deserialized_response)); // Ensure that the tsc_conversion's are nullptr. ASSERT_FALSE((bool)response.tsc_perf_zero_conversion); ASSERT_FALSE((bool)deserialized_response->tsc_perf_zero_conversion); }