aboutsummaryrefslogtreecommitdiff
path: root/lldb/unittests/Utility/TraceGDBRemotePacketsTest.cpp
blob: 06063aa32ded2d3c831bbb9d9c94ebe6612b3e44 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
//===-- 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 <limits>

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<uint64_t>(std::numeric_limits<int64_t>::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<TraceIntelPTGetStateResponse> deserialized_response =
      json::parse<TraceIntelPTGetStateResponse>(
          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<uint32_t>::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<TraceIntelPTGetStateResponse> deserialized_response =
      json::parse<TraceIntelPTGetStateResponse>(
          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);
}