1 //===-- GDBRemoteCommunicationClientTest.cpp --------------------*- C++ -*-===// 2 // 3 // The LLVM Compiler Infrastructure 4 // 5 // This file is distributed under the University of Illinois Open Source 6 // License. See LICENSE.TXT for details. 7 // 8 //===----------------------------------------------------------------------===// 9 #include "Plugins/Process/gdb-remote/GDBRemoteCommunicationClient.h" 10 #include "GDBRemoteTestUtils.h" 11 #include "lldb/Core/ModuleSpec.h" 12 #include "lldb/Host/XML.h" 13 #include "lldb/Target/MemoryRegionInfo.h" 14 #include "lldb/Utility/DataBuffer.h" 15 #include "lldb/Utility/StructuredData.h" 16 #include "lldb/Utility/TraceOptions.h" 17 #include "lldb/lldb-enumerations.h" 18 #include "llvm/ADT/ArrayRef.h" 19 #include "llvm/Testing/Support/Error.h" 20 #include "gmock/gmock.h" 21 #include <future> 22 23 using namespace lldb_private::process_gdb_remote; 24 using namespace lldb_private; 25 using namespace lldb; 26 using namespace llvm; 27 28 namespace { 29 30 typedef GDBRemoteCommunication::PacketResult PacketResult; 31 32 struct TestClient : public GDBRemoteCommunicationClient { 33 TestClient() { m_send_acks = false; } 34 }; 35 36 void Handle_QThreadSuffixSupported(MockServer &server, bool supported) { 37 StringExtractorGDBRemote request; 38 ASSERT_EQ(PacketResult::Success, server.GetPacket(request)); 39 ASSERT_EQ("QThreadSuffixSupported", request.GetStringRef()); 40 if (supported) 41 ASSERT_EQ(PacketResult::Success, server.SendOKResponse()); 42 else 43 ASSERT_EQ(PacketResult::Success, server.SendUnimplementedResponse(nullptr)); 44 } 45 46 void HandlePacket(MockServer &server, 47 const testing::Matcher<const std::string &> &expected, 48 StringRef response) { 49 StringExtractorGDBRemote request; 50 ASSERT_EQ(PacketResult::Success, server.GetPacket(request)); 51 ASSERT_THAT(request.GetStringRef(), expected); 52 ASSERT_EQ(PacketResult::Success, server.SendPacket(response)); 53 } 54 55 uint8_t all_registers[] = {'@', 'A', 'B', 'C', 'D', 'E', 'F', 'G', 56 'H', 'I', 'J', 'K', 'L', 'M', 'N', 'O'}; 57 std::string all_registers_hex = "404142434445464748494a4b4c4d4e4f"; 58 uint8_t one_register[] = {'A', 'B', 'C', 'D'}; 59 std::string one_register_hex = "41424344"; 60 61 } // end anonymous namespace 62 63 class GDBRemoteCommunicationClientTest : public GDBRemoteTest { 64 public: 65 void SetUp() override { 66 ASSERT_THAT_ERROR(Connect(client, server), llvm::Succeeded()); 67 } 68 69 protected: 70 TestClient client; 71 MockServer server; 72 }; 73 74 TEST_F(GDBRemoteCommunicationClientTest, WriteRegister) { 75 const lldb::tid_t tid = 0x47; 76 const uint32_t reg_num = 4; 77 std::future<bool> write_result = std::async(std::launch::async, [&] { 78 return client.WriteRegister(tid, reg_num, one_register); 79 }); 80 81 Handle_QThreadSuffixSupported(server, true); 82 83 HandlePacket(server, "P4=" + one_register_hex + ";thread:0047;", "OK"); 84 ASSERT_TRUE(write_result.get()); 85 86 write_result = std::async(std::launch::async, [&] { 87 return client.WriteAllRegisters(tid, all_registers); 88 }); 89 90 HandlePacket(server, "G" + all_registers_hex + ";thread:0047;", "OK"); 91 ASSERT_TRUE(write_result.get()); 92 } 93 94 TEST_F(GDBRemoteCommunicationClientTest, WriteRegisterNoSuffix) { 95 const lldb::tid_t tid = 0x47; 96 const uint32_t reg_num = 4; 97 std::future<bool> write_result = std::async(std::launch::async, [&] { 98 return client.WriteRegister(tid, reg_num, one_register); 99 }); 100 101 Handle_QThreadSuffixSupported(server, false); 102 HandlePacket(server, "Hg47", "OK"); 103 HandlePacket(server, "P4=" + one_register_hex, "OK"); 104 ASSERT_TRUE(write_result.get()); 105 106 write_result = std::async(std::launch::async, [&] { 107 return client.WriteAllRegisters(tid, all_registers); 108 }); 109 110 HandlePacket(server, "G" + all_registers_hex, "OK"); 111 ASSERT_TRUE(write_result.get()); 112 } 113 114 TEST_F(GDBRemoteCommunicationClientTest, ReadRegister) { 115 const lldb::tid_t tid = 0x47; 116 const uint32_t reg_num = 4; 117 std::future<bool> async_result = std::async( 118 std::launch::async, [&] { return client.GetpPacketSupported(tid); }); 119 Handle_QThreadSuffixSupported(server, true); 120 HandlePacket(server, "p0;thread:0047;", one_register_hex); 121 ASSERT_TRUE(async_result.get()); 122 123 std::future<DataBufferSP> read_result = std::async( 124 std::launch::async, [&] { return client.ReadRegister(tid, reg_num); }); 125 HandlePacket(server, "p4;thread:0047;", "41424344"); 126 auto buffer_sp = read_result.get(); 127 ASSERT_TRUE(bool(buffer_sp)); 128 ASSERT_EQ(0, 129 memcmp(buffer_sp->GetBytes(), one_register, sizeof one_register)); 130 131 read_result = std::async(std::launch::async, 132 [&] { return client.ReadAllRegisters(tid); }); 133 HandlePacket(server, "g;thread:0047;", all_registers_hex); 134 buffer_sp = read_result.get(); 135 ASSERT_TRUE(bool(buffer_sp)); 136 ASSERT_EQ(0, 137 memcmp(buffer_sp->GetBytes(), all_registers, sizeof all_registers)); 138 } 139 140 TEST_F(GDBRemoteCommunicationClientTest, SaveRestoreRegistersNoSuffix) { 141 const lldb::tid_t tid = 0x47; 142 uint32_t save_id; 143 std::future<bool> async_result = std::async(std::launch::async, [&] { 144 return client.SaveRegisterState(tid, save_id); 145 }); 146 Handle_QThreadSuffixSupported(server, false); 147 HandlePacket(server, "Hg47", "OK"); 148 HandlePacket(server, "QSaveRegisterState", "1"); 149 ASSERT_TRUE(async_result.get()); 150 EXPECT_EQ(1u, save_id); 151 152 async_result = std::async(std::launch::async, [&] { 153 return client.RestoreRegisterState(tid, save_id); 154 }); 155 HandlePacket(server, "QRestoreRegisterState:1", "OK"); 156 ASSERT_TRUE(async_result.get()); 157 } 158 159 TEST_F(GDBRemoteCommunicationClientTest, SyncThreadState) { 160 const lldb::tid_t tid = 0x47; 161 std::future<bool> async_result = std::async( 162 std::launch::async, [&] { return client.SyncThreadState(tid); }); 163 HandlePacket(server, "qSyncThreadStateSupported", "OK"); 164 HandlePacket(server, "QSyncThreadState:0047;", "OK"); 165 ASSERT_TRUE(async_result.get()); 166 } 167 168 TEST_F(GDBRemoteCommunicationClientTest, GetModulesInfo) { 169 llvm::Triple triple("i386-pc-linux"); 170 171 FileSpec file_specs[] = { 172 FileSpec("/foo/bar.so", false, FileSpec::ePathSyntaxPosix), 173 FileSpec("/foo/baz.so", false, FileSpec::ePathSyntaxPosix), 174 175 // This is a bit dodgy but we currently depend on GetModulesInfo not 176 // performing denormalization. It can go away once the users 177 // (DynamicLoaderPOSIXDYLD, at least) correctly set the path syntax for 178 // the FileSpecs they create. 179 FileSpec("/foo/baw.so", false, FileSpec::ePathSyntaxWindows), 180 }; 181 std::future<llvm::Optional<std::vector<ModuleSpec>>> async_result = 182 std::async(std::launch::async, 183 [&] { return client.GetModulesInfo(file_specs, triple); }); 184 HandlePacket( 185 server, "jModulesInfo:[" 186 R"({"file":"/foo/bar.so","triple":"i386-pc-linux"},)" 187 R"({"file":"/foo/baz.so","triple":"i386-pc-linux"},)" 188 R"({"file":"/foo/baw.so","triple":"i386-pc-linux"}])", 189 R"([{"uuid":"404142434445464748494a4b4c4d4e4f","triple":"i386-pc-linux",)" 190 R"("file_path":"/foo/bar.so","file_offset":0,"file_size":1234}]])"); 191 192 auto result = async_result.get(); 193 ASSERT_TRUE(result.hasValue()); 194 ASSERT_EQ(1u, result->size()); 195 EXPECT_EQ("/foo/bar.so", result.getValue()[0].GetFileSpec().GetPath()); 196 EXPECT_EQ(triple, result.getValue()[0].GetArchitecture().GetTriple()); 197 EXPECT_EQ(UUID("@ABCDEFGHIJKLMNO", 16), result.getValue()[0].GetUUID()); 198 EXPECT_EQ(0u, result.getValue()[0].GetObjectOffset()); 199 EXPECT_EQ(1234u, result.getValue()[0].GetObjectSize()); 200 } 201 202 TEST_F(GDBRemoteCommunicationClientTest, GetModulesInfo_UUID20) { 203 llvm::Triple triple("i386-pc-linux"); 204 205 FileSpec file_spec("/foo/bar.so", false, FileSpec::ePathSyntaxPosix); 206 std::future<llvm::Optional<std::vector<ModuleSpec>>> async_result = 207 std::async(std::launch::async, 208 [&] { return client.GetModulesInfo(file_spec, triple); }); 209 HandlePacket( 210 server, 211 "jModulesInfo:[" 212 R"({"file":"/foo/bar.so","triple":"i386-pc-linux"}])", 213 R"([{"uuid":"404142434445464748494a4b4c4d4e4f50515253","triple":"i386-pc-linux",)" 214 R"("file_path":"/foo/bar.so","file_offset":0,"file_size":1234}]])"); 215 216 auto result = async_result.get(); 217 ASSERT_TRUE(result.hasValue()); 218 ASSERT_EQ(1u, result->size()); 219 EXPECT_EQ("/foo/bar.so", result.getValue()[0].GetFileSpec().GetPath()); 220 EXPECT_EQ(triple, result.getValue()[0].GetArchitecture().GetTriple()); 221 EXPECT_EQ(UUID("@ABCDEFGHIJKLMNOPQRS", 20), result.getValue()[0].GetUUID()); 222 EXPECT_EQ(0u, result.getValue()[0].GetObjectOffset()); 223 EXPECT_EQ(1234u, result.getValue()[0].GetObjectSize()); 224 } 225 226 TEST_F(GDBRemoteCommunicationClientTest, GetModulesInfoInvalidResponse) { 227 llvm::Triple triple("i386-pc-linux"); 228 FileSpec file_spec("/foo/bar.so", false, FileSpec::ePathSyntaxPosix); 229 230 const char *invalid_responses[] = { 231 // no UUID 232 R"([{"triple":"i386-pc-linux",)" 233 R"("file_path":"/foo/bar.so","file_offset":0,"file_size":1234}]])", 234 // invalid UUID 235 R"([{"uuid":"XXXXXX","triple":"i386-pc-linux",)" 236 R"("file_path":"/foo/bar.so","file_offset":0,"file_size":1234}]])", 237 // no triple 238 R"([{"uuid":"404142434445464748494a4b4c4d4e4f",)" 239 R"("file_path":"/foo/bar.so","file_offset":0,"file_size":1234}]])", 240 // no file_path 241 R"([{"uuid":"404142434445464748494a4b4c4d4e4f","triple":"i386-pc-linux",)" 242 R"("file_offset":0,"file_size":1234}]])", 243 // no file_offset 244 R"([{"uuid":"404142434445464748494a4b4c4d4e4f","triple":"i386-pc-linux",)" 245 R"("file_path":"/foo/bar.so","file_size":1234}]])", 246 // no file_size 247 R"([{"uuid":"404142434445464748494a4b4c4d4e4f","triple":"i386-pc-linux",)" 248 R"("file_path":"/foo/bar.so","file_offset":0}]])", 249 }; 250 251 for (const char *response : invalid_responses) { 252 std::future<llvm::Optional<std::vector<ModuleSpec>>> async_result = 253 std::async(std::launch::async, 254 [&] { return client.GetModulesInfo(file_spec, triple); }); 255 HandlePacket( 256 server, 257 R"(jModulesInfo:[{"file":"/foo/bar.so","triple":"i386-pc-linux"}])", 258 response); 259 260 auto result = async_result.get(); 261 ASSERT_TRUE(result); 262 ASSERT_EQ(0u, result->size()) << "response was: " << response; 263 } 264 } 265 266 TEST_F(GDBRemoteCommunicationClientTest, TestPacketSpeedJSON) { 267 std::thread server_thread([this] { 268 for (;;) { 269 StringExtractorGDBRemote request; 270 PacketResult result = server.GetPacket(request); 271 if (result == PacketResult::ErrorDisconnected) 272 return; 273 ASSERT_EQ(PacketResult::Success, result); 274 StringRef ref = request.GetStringRef(); 275 ASSERT_TRUE(ref.consume_front("qSpeedTest:response_size:")); 276 int size; 277 ASSERT_FALSE(ref.consumeInteger(10, size)) << "ref: " << ref; 278 std::string response(size, 'X'); 279 ASSERT_EQ(PacketResult::Success, server.SendPacket(response)); 280 } 281 }); 282 283 StreamString ss; 284 client.TestPacketSpeed(10, 32, 32, 4096, true, ss); 285 client.Disconnect(); 286 server_thread.join(); 287 288 GTEST_LOG_(INFO) << "Formatted output: " << ss.GetData(); 289 auto object_sp = StructuredData::ParseJSON(ss.GetString()); 290 ASSERT_TRUE(bool(object_sp)); 291 auto dict_sp = object_sp->GetAsDictionary(); 292 ASSERT_TRUE(bool(dict_sp)); 293 294 object_sp = dict_sp->GetValueForKey("packet_speeds"); 295 ASSERT_TRUE(bool(object_sp)); 296 dict_sp = object_sp->GetAsDictionary(); 297 ASSERT_TRUE(bool(dict_sp)); 298 299 int num_packets; 300 ASSERT_TRUE(dict_sp->GetValueForKeyAsInteger("num_packets", num_packets)) 301 << ss.GetString(); 302 ASSERT_EQ(10, num_packets); 303 } 304 305 TEST_F(GDBRemoteCommunicationClientTest, SendSignalsToIgnore) { 306 std::future<Status> result = std::async(std::launch::async, [&] { 307 return client.SendSignalsToIgnore({2, 3, 5, 7, 0xB, 0xD, 0x11}); 308 }); 309 310 HandlePacket(server, "QPassSignals:02;03;05;07;0b;0d;11", "OK"); 311 EXPECT_TRUE(result.get().Success()); 312 313 result = std::async(std::launch::async, [&] { 314 return client.SendSignalsToIgnore(std::vector<int32_t>()); 315 }); 316 317 HandlePacket(server, "QPassSignals:", "OK"); 318 EXPECT_TRUE(result.get().Success()); 319 } 320 321 TEST_F(GDBRemoteCommunicationClientTest, GetMemoryRegionInfo) { 322 const lldb::addr_t addr = 0xa000; 323 MemoryRegionInfo region_info; 324 std::future<Status> result = std::async(std::launch::async, [&] { 325 return client.GetMemoryRegionInfo(addr, region_info); 326 }); 327 328 HandlePacket(server, 329 "qMemoryRegionInfo:a000", 330 "start:a000;size:2000;permissions:rx;name:2f666f6f2f6261722e736f;"); 331 if (XMLDocument::XMLEnabled()) { 332 // In case we have XML support, this will also do a "qXfer:memory-map". 333 // Preceeded by a query for supported extensions. Pretend we don't support 334 // that. 335 HandlePacket(server, testing::StartsWith("qSupported:"), ""); 336 } 337 EXPECT_TRUE(result.get().Success()); 338 EXPECT_EQ(addr, region_info.GetRange().GetRangeBase()); 339 EXPECT_EQ(0x2000u, region_info.GetRange().GetByteSize()); 340 EXPECT_EQ(MemoryRegionInfo::eYes, region_info.GetReadable()); 341 EXPECT_EQ(MemoryRegionInfo::eNo, region_info.GetWritable()); 342 EXPECT_EQ(MemoryRegionInfo::eYes, region_info.GetExecutable()); 343 EXPECT_EQ("/foo/bar.so", region_info.GetName().GetStringRef()); 344 } 345 346 TEST_F(GDBRemoteCommunicationClientTest, GetMemoryRegionInfoInvalidResponse) { 347 const lldb::addr_t addr = 0x4000; 348 MemoryRegionInfo region_info; 349 std::future<Status> result = std::async(std::launch::async, [&] { 350 return client.GetMemoryRegionInfo(addr, region_info); 351 }); 352 353 HandlePacket(server, "qMemoryRegionInfo:4000", "start:4000;size:0000;"); 354 if (XMLDocument::XMLEnabled()) { 355 // In case we have XML support, this will also do a "qXfer:memory-map". 356 // Preceeded by a query for supported extensions. Pretend we don't support 357 // that. 358 HandlePacket(server, testing::StartsWith("qSupported:"), ""); 359 } 360 EXPECT_FALSE(result.get().Success()); 361 } 362 363 TEST_F(GDBRemoteCommunicationClientTest, SendStartTracePacket) { 364 TraceOptions options; 365 Status error; 366 367 options.setType(lldb::TraceType::eTraceTypeProcessorTrace); 368 options.setMetaDataBufferSize(8192); 369 options.setTraceBufferSize(8192); 370 options.setThreadID(0x23); 371 372 StructuredData::DictionarySP custom_params = 373 std::make_shared<StructuredData::Dictionary>(); 374 custom_params->AddStringItem("tracetech", "intel-pt"); 375 custom_params->AddIntegerItem("psb", 0x01); 376 377 options.setTraceParams(custom_params); 378 379 std::future<lldb::user_id_t> result = std::async(std::launch::async, [&] { 380 return client.SendStartTracePacket(options, error); 381 }); 382 383 // Since the line is exceeding 80 characters. 384 std::string expected_packet1 = 385 R"(jTraceStart:{"buffersize" : 8192,"metabuffersize" : 8192,"params" :)"; 386 std::string expected_packet2 = 387 R"( {"psb" : 1,"tracetech" : "intel-pt"},"threadid" : 35,"type" : 1})"; 388 HandlePacket(server, (expected_packet1 + expected_packet2), "1"); 389 ASSERT_TRUE(error.Success()); 390 ASSERT_EQ(result.get(), 1u); 391 392 error.Clear(); 393 result = std::async(std::launch::async, [&] { 394 return client.SendStartTracePacket(options, error); 395 }); 396 397 HandlePacket(server, (expected_packet1 + expected_packet2), "E23"); 398 ASSERT_EQ(result.get(), LLDB_INVALID_UID); 399 ASSERT_FALSE(error.Success()); 400 } 401 402 TEST_F(GDBRemoteCommunicationClientTest, SendStopTracePacket) { 403 lldb::tid_t thread_id = 0x23; 404 lldb::user_id_t trace_id = 3; 405 406 std::future<Status> result = std::async(std::launch::async, [&] { 407 return client.SendStopTracePacket(trace_id, thread_id); 408 }); 409 410 const char *expected_packet = 411 R"(jTraceStop:{"threadid" : 35,"traceid" : 3})"; 412 HandlePacket(server, expected_packet, "OK"); 413 ASSERT_TRUE(result.get().Success()); 414 415 result = std::async(std::launch::async, [&] { 416 return client.SendStopTracePacket(trace_id, thread_id); 417 }); 418 419 HandlePacket(server, expected_packet, "E23"); 420 ASSERT_FALSE(result.get().Success()); 421 } 422 423 TEST_F(GDBRemoteCommunicationClientTest, SendGetDataPacket) { 424 lldb::tid_t thread_id = 0x23; 425 lldb::user_id_t trace_id = 3; 426 427 uint8_t buf[32] = {}; 428 llvm::MutableArrayRef<uint8_t> buffer(buf, 32); 429 size_t offset = 0; 430 431 std::future<Status> result = std::async(std::launch::async, [&] { 432 return client.SendGetDataPacket(trace_id, thread_id, buffer, offset); 433 }); 434 435 std::string expected_packet1 = 436 R"(jTraceBufferRead:{"buffersize" : 32,"offset" : 0,"threadid" : 35,)"; 437 std::string expected_packet2 = R"("traceid" : 3})"; 438 HandlePacket(server, expected_packet1+expected_packet2, "123456"); 439 ASSERT_TRUE(result.get().Success()); 440 ASSERT_EQ(buffer.size(), 3u); 441 ASSERT_EQ(buf[0], 0x12); 442 ASSERT_EQ(buf[1], 0x34); 443 ASSERT_EQ(buf[2], 0x56); 444 445 llvm::MutableArrayRef<uint8_t> buffer2(buf, 32); 446 result = std::async(std::launch::async, [&] { 447 return client.SendGetDataPacket(trace_id, thread_id, buffer2, offset); 448 }); 449 450 HandlePacket(server, expected_packet1+expected_packet2, "E23"); 451 ASSERT_FALSE(result.get().Success()); 452 ASSERT_EQ(buffer2.size(), 0u); 453 } 454 455 TEST_F(GDBRemoteCommunicationClientTest, SendGetMetaDataPacket) { 456 lldb::tid_t thread_id = 0x23; 457 lldb::user_id_t trace_id = 3; 458 459 uint8_t buf[32] = {}; 460 llvm::MutableArrayRef<uint8_t> buffer(buf, 32); 461 size_t offset = 0; 462 463 std::future<Status> result = std::async(std::launch::async, [&] { 464 return client.SendGetMetaDataPacket(trace_id, thread_id, buffer, offset); 465 }); 466 467 std::string expected_packet1 = 468 R"(jTraceMetaRead:{"buffersize" : 32,"offset" : 0,"threadid" : 35,)"; 469 std::string expected_packet2 = R"("traceid" : 3})"; 470 HandlePacket(server, expected_packet1+expected_packet2, "123456"); 471 ASSERT_TRUE(result.get().Success()); 472 ASSERT_EQ(buffer.size(), 3u); 473 ASSERT_EQ(buf[0], 0x12); 474 ASSERT_EQ(buf[1], 0x34); 475 ASSERT_EQ(buf[2], 0x56); 476 477 llvm::MutableArrayRef<uint8_t> buffer2(buf, 32); 478 result = std::async(std::launch::async, [&] { 479 return client.SendGetMetaDataPacket(trace_id, thread_id, buffer2, offset); 480 }); 481 482 HandlePacket(server, expected_packet1+expected_packet2, "E23"); 483 ASSERT_FALSE(result.get().Success()); 484 ASSERT_EQ(buffer2.size(), 0u); 485 } 486 487 TEST_F(GDBRemoteCommunicationClientTest, SendGetTraceConfigPacket) { 488 lldb::tid_t thread_id = 0x23; 489 lldb::user_id_t trace_id = 3; 490 TraceOptions options; 491 options.setThreadID(thread_id); 492 493 std::future<Status> result = std::async(std::launch::async, [&] { 494 return client.SendGetTraceConfigPacket(trace_id, options); 495 }); 496 497 const char *expected_packet = 498 R"(jTraceConfigRead:{"threadid" : 35,"traceid" : 3})"; 499 std::string response1 = 500 R"({"buffersize" : 8192,"params" : {"psb" : 1,"tracetech" : "intel-pt"})"; 501 std::string response2 = 502 R"(],"metabuffersize" : 8192,"threadid" : 35,"type" : 1}])"; 503 HandlePacket(server, expected_packet, response1+response2); 504 ASSERT_TRUE(result.get().Success()); 505 ASSERT_EQ(options.getTraceBufferSize(), 8192u); 506 ASSERT_EQ(options.getMetaDataBufferSize(), 8192u); 507 ASSERT_EQ(options.getType(), 1); 508 509 auto custom_params = options.getTraceParams(); 510 511 uint64_t psb_value; 512 llvm::StringRef trace_tech_value; 513 514 ASSERT_TRUE(custom_params); 515 ASSERT_EQ(custom_params->GetType(), eStructuredDataTypeDictionary); 516 ASSERT_TRUE(custom_params->GetValueForKeyAsInteger("psb", psb_value)); 517 ASSERT_EQ(psb_value, 1u); 518 ASSERT_TRUE( 519 custom_params->GetValueForKeyAsString("tracetech", trace_tech_value)); 520 ASSERT_STREQ(trace_tech_value.data(), "intel-pt"); 521 522 // Checking error response. 523 std::future<Status> result2 = std::async(std::launch::async, [&] { 524 return client.SendGetTraceConfigPacket(trace_id, options); 525 }); 526 527 HandlePacket(server, expected_packet, "E23"); 528 ASSERT_FALSE(result2.get().Success()); 529 530 // Wrong JSON as response. 531 std::future<Status> result3 = std::async(std::launch::async, [&] { 532 return client.SendGetTraceConfigPacket(trace_id, options); 533 }); 534 535 std::string incorrect_json1 = 536 R"("buffersize" : 8192,"params" : {"psb" : 1,"tracetech" : "intel-pt"})"; 537 std::string incorrect_json2 = 538 R"(],"metabuffersize" : 8192,"threadid" : 35,"type" : 1}])"; 539 HandlePacket(server, expected_packet, incorrect_json1+incorrect_json2); 540 ASSERT_FALSE(result3.get().Success()); 541 542 // Wrong JSON as custom_params. 543 std::future<Status> result4 = std::async(std::launch::async, [&] { 544 return client.SendGetTraceConfigPacket(trace_id, options); 545 }); 546 547 std::string incorrect_custom_params1 = 548 R"({"buffersize" : 8192,"params" : "psb" : 1,"tracetech" : "intel-pt"})"; 549 std::string incorrect_custom_params2 = 550 R"(],"metabuffersize" : 8192,"threadid" : 35,"type" : 1}])"; 551 HandlePacket(server, expected_packet, incorrect_custom_params1+ 552 incorrect_custom_params2); 553 ASSERT_FALSE(result4.get().Success()); 554 } 555