diff options
Diffstat (limited to 'lib/xray/tests')
-rw-r--r-- | lib/xray/tests/CMakeLists.txt | 46 | ||||
-rw-r--r-- | lib/xray/tests/unit/buffer_queue_test.cc | 4 | ||||
-rw-r--r-- | lib/xray/tests/unit/fdr_logging_test.cc | 107 |
3 files changed, 103 insertions, 54 deletions
diff --git a/lib/xray/tests/CMakeLists.txt b/lib/xray/tests/CMakeLists.txt index a1eb4a030ccc..e54e63f27890 100644 --- a/lib/xray/tests/CMakeLists.txt +++ b/lib/xray/tests/CMakeLists.txt @@ -11,47 +11,23 @@ set(XRAY_UNITTEST_CFLAGS -I${COMPILER_RT_SOURCE_DIR}/lib/xray -I${COMPILER_RT_SOURCE_DIR}/lib) -macro(xray_compile obj_list source arch) - get_filename_component(basename ${source} NAME) - set(output_obj "${basename}.${arch}.o") - get_target_flags_for_arch(${arch} TARGET_CFLAGS) - if(NOT COMPILER_RT_STANDALONE_BUILD) - list(APPEND COMPILE_DEPS gtest_main xray) - endif() - clang_compile(${output_obj} ${source} - CFLAGS ${XRAY_UNITTEST_CFLAGS} ${TARGET_CFLAGS} - DEPS ${COMPILE_DEPS}) - list(APPEND ${obj_list} ${output_obj}) -endmacro() - +set(XRAY_TEST_ARCH ${XRAY_SUPPORTED_ARCH}) macro(add_xray_unittest testname) - set(XRAY_TEST_ARCH ${XRAY_SUPPORTED_ARCH}) - if (APPLE) - darwin_filter_host_archs(XRAY_SUPPORTED_ARCH) - endif() - if(UNIX) + cmake_parse_arguments(TEST "" "" "SOURCES;HEADERS" ${ARGN}) + if(UNIX AND NOT APPLE) foreach(arch ${XRAY_TEST_ARCH}) - cmake_parse_arguments(TEST "" "" "SOURCES;HEADERS" ${ARGN}) set(TEST_OBJECTS) - foreach(SOURCE ${TEST_SOURCES} ${COMPILER_RT_GTEST_SOURCE}) - xray_compile(TEST_OBJECTS ${SOURCE} ${arch} ${TEST_HEADERS}) - endforeach() - get_target_flags_for_arch(${arch} TARGET_LINK_FLAGS) - set(TEST_DEPS ${TEST_OBJECTS}) - if(NOT COMPILER_RT_STANDALONE_BUILD) - list(APPEND TEST_DEPS gtest_main xray) - endif() - if(NOT APPLE) - add_compiler_rt_test(XRayUnitTests ${testname}-${arch} - OBJECTS ${TEST_OBJECTS} - DEPS ${TEST_DEPS} - LINK_FLAGS ${TARGET_LINK_FLAGS} + generate_compiler_rt_tests(TEST_OBJECTS + XRayUnitTests "${testname}-${arch}-Test" "${arch}" + SOURCES ${TEST_SOURCES} ${COMPILER_RT_GTEST_SOURCE} + DEPS gtest xray llvm-xray + CFLAGS ${XRAY_UNITTEST_CFLAGS} + LINK_FLAGS -fxray-instrument + ${TARGET_LINK_FLAGS} -lstdc++ -lm ${CMAKE_THREAD_LIBS_INIT} -lpthread - -L${COMPILER_RT_LIBRARY_OUTPUT_DIR} -lclang_rt.xray-${arch} -ldl -lrt) - endif() - # FIXME: Figure out how to run even just the unit tests on APPLE. + set_target_properties(XRayUnitTests PROPERTIES RUNTIME_OUTPUT_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}) endforeach() endif() endmacro() diff --git a/lib/xray/tests/unit/buffer_queue_test.cc b/lib/xray/tests/unit/buffer_queue_test.cc index ac89a8dbc50e..1ec7469ce187 100644 --- a/lib/xray/tests/unit/buffer_queue_test.cc +++ b/lib/xray/tests/unit/buffer_queue_test.cc @@ -68,9 +68,9 @@ TEST(BufferQueueTest, ErrorsWhenFinalising) { ASSERT_NE(nullptr, Buf.Buffer); ASSERT_EQ(Buffers.finalize(), BufferQueue::ErrorCode::Ok); BufferQueue::Buffer OtherBuf; - ASSERT_EQ(BufferQueue::ErrorCode::AlreadyFinalized, + ASSERT_EQ(BufferQueue::ErrorCode::QueueFinalizing, Buffers.getBuffer(OtherBuf)); - ASSERT_EQ(BufferQueue::ErrorCode::AlreadyFinalized, + ASSERT_EQ(BufferQueue::ErrorCode::QueueFinalizing, Buffers.finalize()); ASSERT_EQ(Buffers.releaseBuffer(Buf), BufferQueue::ErrorCode::Ok); } diff --git a/lib/xray/tests/unit/fdr_logging_test.cc b/lib/xray/tests/unit/fdr_logging_test.cc index 0d5e99a74334..1009d56a43b3 100644 --- a/lib/xray/tests/unit/fdr_logging_test.cc +++ b/lib/xray/tests/unit/fdr_logging_test.cc @@ -17,8 +17,10 @@ #include <iostream> #include <sys/mman.h> #include <sys/stat.h> +#include <sys/syscall.h> #include <sys/types.h> #include <system_error> +#include <thread> #include <unistd.h> #include "xray/xray_records.h" @@ -34,14 +36,23 @@ struct ScopedFileCloserAndDeleter { : Fd(Fd), Filename(Filename) {} ~ScopedFileCloserAndDeleter() { + if (Map) + munmap(Map, Size); if (Fd) { close(Fd); unlink(Filename); } } + void registerMap(void *M, size_t S) { + Map = M; + Size = S; + } + int Fd; const char *Filename; + void *Map = nullptr; + size_t Size = 0; }; TEST(FDRLoggingTest, Simple) { @@ -51,13 +62,12 @@ TEST(FDRLoggingTest, Simple) { Options.Fd = mkstemp(TmpFilename); ASSERT_NE(Options.Fd, -1); ASSERT_EQ(fdrLoggingInit(kBufferSize, kBufferMax, &Options, - sizeof(FDRLoggingOptions)), + sizeof(FDRLoggingOptions)), XRayLogInitStatus::XRAY_LOG_INITIALIZED); fdrLoggingHandleArg0(1, XRayEntryType::ENTRY); fdrLoggingHandleArg0(1, XRayEntryType::EXIT); ASSERT_EQ(fdrLoggingFinalize(), XRayLogInitStatus::XRAY_LOG_FINALIZED); ASSERT_EQ(fdrLoggingFlush(), XRayLogFlushStatus::XRAY_LOG_FLUSHED); - ASSERT_EQ(fdrLoggingReset(), XRayLogInitStatus::XRAY_LOG_UNINITIALIZED); // To do this properly, we have to close the file descriptor then re-open the // file for reading this time. @@ -68,20 +78,25 @@ TEST(FDRLoggingTest, Simple) { auto Size = lseek(Fd, 0, SEEK_END); ASSERT_NE(Size, 0); // Map the file contents. - const char *Contents = static_cast<const char *>( - mmap(NULL, Size, PROT_READ, MAP_PRIVATE, Fd, 0)); + void *Map = mmap(NULL, Size, PROT_READ, MAP_PRIVATE, Fd, 0); + const char *Contents = static_cast<const char *>(Map); + Guard.registerMap(Map, Size); ASSERT_NE(Contents, nullptr); XRayFileHeader H; memcpy(&H, Contents, sizeof(XRayFileHeader)); - ASSERT_EQ(H.Version, 1); + ASSERT_EQ(H.Version, 2); ASSERT_EQ(H.Type, FileTypes::FDR_LOG); - // We require one buffer at least to have the "start of buffer" metadata - // record. - MetadataRecord MDR; - memcpy(&MDR, Contents + sizeof(XRayFileHeader), sizeof(MetadataRecord)); - ASSERT_EQ(MDR.RecordKind, uint8_t(MetadataRecord::RecordKinds::NewBuffer)); + // We require one buffer at least to have the "extents" metadata record, + // followed by the NewBuffer record. + MetadataRecord MDR0, MDR1; + memcpy(&MDR0, Contents + sizeof(XRayFileHeader), sizeof(MetadataRecord)); + memcpy(&MDR1, Contents + sizeof(XRayFileHeader) + sizeof(MetadataRecord), + sizeof(MetadataRecord)); + ASSERT_EQ(MDR0.RecordKind, + uint8_t(MetadataRecord::RecordKinds::BufferExtents)); + ASSERT_EQ(MDR1.RecordKind, uint8_t(MetadataRecord::RecordKinds::NewBuffer)); } TEST(FDRLoggingTest, Multiple) { @@ -90,7 +105,7 @@ TEST(FDRLoggingTest, Multiple) { Options.Fd = mkstemp(TmpFilename); ASSERT_NE(Options.Fd, -1); ASSERT_EQ(fdrLoggingInit(kBufferSize, kBufferMax, &Options, - sizeof(FDRLoggingOptions)), + sizeof(FDRLoggingOptions)), XRayLogInitStatus::XRAY_LOG_INITIALIZED); for (uint64_t I = 0; I < 100; ++I) { fdrLoggingHandleArg0(1, XRayEntryType::ENTRY); @@ -98,7 +113,6 @@ TEST(FDRLoggingTest, Multiple) { } ASSERT_EQ(fdrLoggingFinalize(), XRayLogInitStatus::XRAY_LOG_FINALIZED); ASSERT_EQ(fdrLoggingFlush(), XRayLogFlushStatus::XRAY_LOG_FLUSHED); - ASSERT_EQ(fdrLoggingReset(), XRayLogInitStatus::XRAY_LOG_UNINITIALIZED); // To do this properly, we have to close the file descriptor then re-open the // file for reading this time. @@ -109,18 +123,77 @@ TEST(FDRLoggingTest, Multiple) { auto Size = lseek(Fd, 0, SEEK_END); ASSERT_NE(Size, 0); // Map the file contents. - const char *Contents = static_cast<const char *>( - mmap(NULL, Size, PROT_READ, MAP_PRIVATE, Fd, 0)); + void *Map = mmap(NULL, Size, PROT_READ, MAP_PRIVATE, Fd, 0); + const char *Contents = static_cast<const char *>(Map); + Guard.registerMap(Map, Size); + ASSERT_NE(Contents, nullptr); + + XRayFileHeader H; + memcpy(&H, Contents, sizeof(XRayFileHeader)); + ASSERT_EQ(H.Version, 2); + ASSERT_EQ(H.Type, FileTypes::FDR_LOG); + + MetadataRecord MDR0, MDR1; + memcpy(&MDR0, Contents + sizeof(XRayFileHeader), sizeof(MetadataRecord)); + memcpy(&MDR1, Contents + sizeof(XRayFileHeader) + sizeof(MetadataRecord), + sizeof(MetadataRecord)); + ASSERT_EQ(MDR0.RecordKind, + uint8_t(MetadataRecord::RecordKinds::BufferExtents)); + ASSERT_EQ(MDR1.RecordKind, uint8_t(MetadataRecord::RecordKinds::NewBuffer)); +} + +TEST(FDRLoggingTest, MultiThreadedCycling) { + FDRLoggingOptions Options; + char TmpFilename[] = "fdr-logging-test.XXXXXX"; + Options.Fd = mkstemp(TmpFilename); + ASSERT_NE(Options.Fd, -1); + ASSERT_EQ(fdrLoggingInit(kBufferSize, 1, &Options, sizeof(FDRLoggingOptions)), + XRayLogInitStatus::XRAY_LOG_INITIALIZED); + + // Now we want to create one thread, do some logging, then create another one, + // in succession and making sure that we're able to get thread records from + // the latest thread (effectively being able to recycle buffers). + std::array<pid_t, 2> Threads; + for (uint64_t I = 0; I < 2; ++I) { + std::thread t{[I, &Threads] { + fdrLoggingHandleArg0(I + 1, XRayEntryType::ENTRY); + fdrLoggingHandleArg0(I + 1, XRayEntryType::EXIT); + Threads[I] = syscall(SYS_gettid); + }}; + t.join(); + } + ASSERT_EQ(fdrLoggingFinalize(), XRayLogInitStatus::XRAY_LOG_FINALIZED); + ASSERT_EQ(fdrLoggingFlush(), XRayLogFlushStatus::XRAY_LOG_FLUSHED); + + // To do this properly, we have to close the file descriptor then re-open the + // file for reading this time. + ASSERT_EQ(close(Options.Fd), 0); + int Fd = open(TmpFilename, O_RDONLY); + ASSERT_NE(-1, Fd); + ScopedFileCloserAndDeleter Guard(Fd, TmpFilename); + auto Size = lseek(Fd, 0, SEEK_END); + ASSERT_NE(Size, 0); + // Map the file contents. + void *Map = mmap(NULL, Size, PROT_READ, MAP_PRIVATE, Fd, 0); + const char *Contents = static_cast<const char *>(Map); + Guard.registerMap(Map, Size); ASSERT_NE(Contents, nullptr); XRayFileHeader H; memcpy(&H, Contents, sizeof(XRayFileHeader)); - ASSERT_EQ(H.Version, 1); + ASSERT_EQ(H.Version, 2); ASSERT_EQ(H.Type, FileTypes::FDR_LOG); - MetadataRecord MDR0; + MetadataRecord MDR0, MDR1; memcpy(&MDR0, Contents + sizeof(XRayFileHeader), sizeof(MetadataRecord)); - ASSERT_EQ(MDR0.RecordKind, uint8_t(MetadataRecord::RecordKinds::NewBuffer)); + memcpy(&MDR1, Contents + sizeof(XRayFileHeader) + sizeof(MetadataRecord), + sizeof(MetadataRecord)); + ASSERT_EQ(MDR0.RecordKind, + uint8_t(MetadataRecord::RecordKinds::BufferExtents)); + ASSERT_EQ(MDR1.RecordKind, uint8_t(MetadataRecord::RecordKinds::NewBuffer)); + pid_t Latest = 0; + memcpy(&Latest, MDR1.Data, sizeof(pid_t)); + ASSERT_EQ(Latest, Threads[1]); } } // namespace |