@@ -699,7 +699,7 @@ TEST_F(TracingTest, LogEntriesIncludeTimingAnnotation) {
699699}
700700
701701// ---------------------------------------------------------------------------
702- // Tests: all CPPINTEROP_API functions must have INTEROP_TRACE
702+ // Tests: StartTracing / StopTracing region-based tracing
703703// ---------------------------------------------------------------------------
704704
705705#ifndef EMSCRIPTEN
@@ -709,6 +709,111 @@ static std::string ReadFileToString(const std::string& path) {
709709 std::istreambuf_iterator<char >()};
710710}
711711// This test reads source files from the build tree via CPPINTEROP_DIR.
712+ TEST_F (TracingTest, StartStopTracingWritesToFile) {
713+ // StartTracing begins recording; StopTracing writes the file.
714+ std::string Path = CppInterOp::Tracing::StartTracing ();
715+ ASSERT_FALSE (Path.empty ());
716+
717+ // Calls within the region are recorded.
718+ VoidFunc ();
719+ AnnotatedFunction (5 );
720+
721+ CppInterOp::Tracing::StopTracing ();
722+
723+ // The file should exist and contain the traced calls.
724+ std::string content = ReadFileToString (Path);
725+ ASSERT_FALSE (content.empty ());
726+ EXPECT_THAT (content, HasSubstr (" Cpp::VoidFunc()" ));
727+ EXPECT_THAT (content, HasSubstr (" Cpp::AnnotatedFunction(" ));
728+ EXPECT_THAT (content, HasSubstr (" #include <CppInterOp/CppInterOp.h>" ));
729+
730+ llvm::sys::fs::remove (Path);
731+ }
732+
733+ TEST_F (TracingTest, OnlyRegionCallsAreRecorded) {
734+ // Calls before StartTracing should not appear.
735+ VoidFunc ();
736+
737+ std::string Path = CppInterOp::Tracing::StartTracing ();
738+ ASSERT_FALSE (Path.empty ());
739+
740+ AnnotatedFunction (42 );
741+
742+ CppInterOp::Tracing::StopTracing ();
743+
744+ // Calls after StopTracing should not appear either.
745+ VoidFunc ();
746+
747+ std::string content = ReadFileToString (Path);
748+ // Should contain only the call within the region.
749+ EXPECT_THAT (content, HasSubstr (" Cpp::AnnotatedFunction(42)" ));
750+ // VoidFunc was called before and after — should NOT be in the file.
751+ // Count occurrences of VoidFunc in the reproducer body.
752+ auto bodyStart = content.find (" void reproducer()" );
753+ ASSERT_NE (bodyStart, std::string::npos);
754+ std::string body = content.substr (bodyStart);
755+ EXPECT_EQ (body.find (" VoidFunc" ), std::string::npos)
756+ << " VoidFunc should not appear in the reproducer body:\n "
757+ << body;
758+
759+ llvm::sys::fs::remove (Path);
760+ }
761+
762+ TEST_F (TracingTest, StartTracingWithEnvVarNarrowsToRegion) {
763+ // When CPPINTEROP_LOG=1 is set (tracing already active from SetUp),
764+ // StartTracing/StopTracing should still narrow to just the region.
765+ ASSERT_NE (TraceInfo::TheTraceInfo, nullptr );
766+
767+ // This call is before the region.
768+ VoidFunc ();
769+
770+ std::string Path = CppInterOp::Tracing::StartTracing ();
771+ ASSERT_FALSE (Path.empty ());
772+
773+ AnnotatedFunction (7 );
774+
775+ CppInterOp::Tracing::StopTracing ();
776+
777+ std::string content = ReadFileToString (Path);
778+ auto bodyStart = content.find (" void reproducer()" );
779+ ASSERT_NE (bodyStart, std::string::npos);
780+ std::string body = content.substr (bodyStart);
781+ EXPECT_THAT (body, HasSubstr (" Cpp::AnnotatedFunction(7)" ));
782+ EXPECT_EQ (body.find (" VoidFunc" ), std::string::npos);
783+
784+ llvm::sys::fs::remove (Path);
785+ }
786+
787+ TEST_F (TracingTest, MultipleStartStopRegions) {
788+ // Multiple regions should each produce their own file.
789+ std::string Path1 = CppInterOp::Tracing::StartTracing ();
790+ AnnotatedFunction (1 );
791+ CppInterOp::Tracing::StopTracing ();
792+
793+ std::string Path2 = CppInterOp::Tracing::StartTracing ();
794+ AnnotatedFunction (2 );
795+ CppInterOp::Tracing::StopTracing ();
796+
797+ ASSERT_NE (Path1, Path2);
798+
799+ std::string content1 = ReadFileToString (Path1);
800+ std::string content2 = ReadFileToString (Path2);
801+
802+ EXPECT_THAT (content1, HasSubstr (" Cpp::AnnotatedFunction(1)" ));
803+ EXPECT_THAT (content2, HasSubstr (" Cpp::AnnotatedFunction(2)" ));
804+
805+ // Each file should only have its own call.
806+ EXPECT_EQ (content1.find (" AnnotatedFunction(2)" ), std::string::npos);
807+ EXPECT_EQ (content2.find (" AnnotatedFunction(1)" ), std::string::npos);
808+
809+ llvm::sys::fs::remove (Path1);
810+ llvm::sys::fs::remove (Path2);
811+ }
812+
813+ // ---------------------------------------------------------------------------
814+ // Tests: all CPPINTEROP_API functions must have INTEROP_TRACE
815+ // ---------------------------------------------------------------------------
816+
712817TEST (TracingCoverageTest, AllPublicAPIsAreTraced) {
713818 // 1. Parse the header to extract all CPPINTEROP_API function names.
714819 std::string Header =
0 commit comments