1 //===-- TraceGDBRemotePacketsTest.cpp -------------------------------------===//
2 //
3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4 // See https://llvm.org/LICENSE.txt for license information.
5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6 //
7 //===----------------------------------------------------------------------===//
8 
9 #include "lldb/Utility/TraceIntelPTGDBRemotePackets.h"
10 
11 #include "gtest/gtest.h"
12 
13 #include <limits>
14 
15 using namespace lldb_private;
16 using namespace llvm;
17 
18 // Test serialization and deserialization of a non-empty
19 // TraceIntelPTGetStateResponse.
20 TEST(TraceGDBRemotePacketsTest, IntelPTGetStateResponse) {
21   // This test works as follows:
22   //  1. Create a non-empty TraceIntelPTGetStateResponse
23   //  2. Serialize to JSON
24   //  3. Deserialize the serialized JSON value
25   //  4. Ensure the original value and the deserialized value are equivalent
26   //
27   //  Notes:
28   //    - We intentionally set an integer value out of its signed range
29   //      to ensure the serialization/deserialization isn't lossy since JSON
30   //      operates on signed values
31 
32   // Choose arbitrary values for time_mult and time_shift
33   uint32_t test_time_mult = 1076264588;
34   uint16_t test_time_shift = 31;
35   // Intentionally set time_zero value out of the signed type's range.
36   uint64_t test_time_zero =
37       static_cast<uint64_t>(std::numeric_limits<int64_t>::max()) + 1;
38 
39   // Create TraceIntelPTGetStateResponse.
40   TraceIntelPTGetStateResponse response;
41   response.tsc_conversion = std::make_unique<LinuxPerfZeroTscConversion>(
42       test_time_mult, test_time_shift, test_time_zero);
43 
44   // Serialize then deserialize.
45   Expected<TraceIntelPTGetStateResponse> deserialized_response =
46       json::parse<TraceIntelPTGetStateResponse>(
47           llvm::formatv("{0}", toJSON(response)).str(),
48           "TraceIntelPTGetStateResponse");
49   if (!deserialized_response)
50     FAIL() << toString(deserialized_response.takeError());
51 
52   // Choose arbitrary TSC value to test the Convert function.
53   const uint64_t TSC = std::numeric_limits<uint32_t>::max();
54   // Expected nanosecond value pre calculated using the TSC to wall time
55   // conversion formula located in the time_zero section of
56   // https://man7.org/linux/man-pages/man2/perf_event_open.2.html
57   const uint64_t EXPECTED_NANOS = 9223372039007304983u;
58 
59   uint64_t pre_serialization_conversion =
60       response.tsc_conversion->Convert(TSC).count();
61   uint64_t post_serialization_conversion =
62       deserialized_response->tsc_conversion->Convert(TSC).count();
63 
64   // Check equality:
65   // Ensure that both the TraceGetStateResponse and TraceIntelPTGetStateResponse
66   // portions of the JSON representation are unchanged.
67   ASSERT_EQ(toJSON(response), toJSON(*deserialized_response));
68   // Ensure the result of the Convert function is unchanged.
69   ASSERT_EQ(EXPECTED_NANOS, pre_serialization_conversion);
70   ASSERT_EQ(EXPECTED_NANOS, post_serialization_conversion);
71 }
72 
73 // Test serialization and deserialization of an empty
74 // TraceIntelPTGetStateResponse.
75 TEST(TraceGDBRemotePacketsTest, IntelPTGetStateResponseEmpty) {
76   // This test works as follows:
77   //  1. Create an empty TraceIntelPTGetStateResponse
78   //  2. Serialize to JSON
79   //  3. Deserialize the serialized JSON value
80   //  4. Ensure the original value and the deserialized value are equivalent
81 
82   // Create TraceIntelPTGetStateResponse.
83   TraceIntelPTGetStateResponse response;
84 
85   // Serialize then deserialize.
86   Expected<TraceIntelPTGetStateResponse> deserialized_response =
87       json::parse<TraceIntelPTGetStateResponse>(
88           llvm::formatv("{0}", toJSON(response)).str(),
89           "TraceIntelPTGetStateResponse");
90   if (!deserialized_response)
91     FAIL() << toString(deserialized_response.takeError());
92 
93   // Check equality:
94   // Ensure that both the TraceGetStateResponse and TraceIntelPTGetStateResponse
95   // portions of the JSON representation are unchanged.
96   ASSERT_EQ(toJSON(response), toJSON(*deserialized_response));
97   // Ensure that the tsc_conversion's are nullptr.
98   ASSERT_EQ(response.tsc_conversion.get(), nullptr);
99   ASSERT_EQ(response.tsc_conversion.get(),
100             deserialized_response->tsc_conversion.get());
101 }
102