#include "exception_stack_tracer.hpp"

#include "exception_stack_tracer_internal.hpp"

#include <exception>
#include <stdexcept>
#include <string>
#include <thread>  // NOLINT
#include <utility>

#include "gtest/gtest.h"

namespace {

// Depth of the synthetic throw-site call chain. Comfortably exceeds the five
// frames the capture test asserts, leaving margin under kMaxFrames.
constexpr int kThrowDepth = 6;

// Recurse to build a deep, real call stack and throw at the bottom, so the
// capture test can assert the tracer recorded several throw-site frames rather
// than just one. [[gnu::noinline]] keeps each level a distinct frame and the
// post-call barrier defeats the tail call that would otherwise elide it.
[[gnu::noinline]] void throwFromDepth(int depth) {
  if (depth <= 0) {
    throw std::runtime_error("boom-from-throw-site");
  }
  throwFromDepth(depth - 1);
  asm volatile("" ::: "memory");
}

// A distinct noinline entry so the throw site is not the test body.
[[gnu::noinline]] void throwRuntimeError() { throwFromDepth(kThrowDepth); }

// Throws and captures on a separate thread, so a later rethrow exercises the
// cross-thread exception_ptr transport that asio/sdbusplus laundering uses.
std::exception_ptr captureOnOtherThread() {
  std::exception_ptr eptr;
  std::thread thrower([&eptr] {
    try {
      throwRuntimeError();
    } catch (...) {
      eptr = std::current_exception();
    }
  });
  thrower.join();
  return eptr;
}

// Runs `fn` on a separate thread and lets any exception escape the thread's
// entry function. An exception escaping a std::thread invokes std::terminate
// directly -- this is the real uncaught path (asio io_context /sdbusplus posted
// rethrow) and the ONLY way to reach our terminate handler from inside
// EXPECT_DEATH: gtest wraps the death-test statement in a try/catch that would
// otherwise intercept a main-thread throw before std::terminate ever runs.
template <typename Fn>
void terminateViaEscapingThread(Fn fn) {
  std::thread t(std::move(fn));
  t.join();  // Not reached: the escaping exception terminates the process.
}

// All tests fork via EXPECT_DEATH and match the child's stderr, since the
// behavior under test IS the abort. threadsafe style re-executes the test
// binary for the child, which is required once threads are involved.

TEST(ExceptionStackTracerDeathTest, UncaughtThrowPrintsThrowSiteStack) {
  testing::FLAGS_gtest_death_test_style = "threadsafe";
  EXPECT_DEATH(
      {
        installExceptionStackTracer();
        terminateViaEscapingThread(throwRuntimeError);
      },
      "uncaught exception of type St13runtime_error"
      ".*what\\(\\): boom-from-throw-site"
      ".*throw-site stack \\(recorded as St13runtime_error\\)"
      // At least five frames, each resolved to a module+offset (not the
      // unresolved "[0x..]" fallback): proves a real multi-frame stack walk.
      ".*#00 [^ ]+\\+0x[0-9a-f]+"
      ".*#01 [^ ]+\\+0x[0-9a-f]+"
      ".*#02 [^ ]+\\+0x[0-9a-f]+"
      ".*#03 [^ ]+\\+0x[0-9a-f]+"
      ".*#04 [^ ]+\\+0x[0-9a-f]+");
}

TEST(ExceptionStackTracerDeathTest, RethrownExceptionPtrKeepsThrowSiteStack) {
  testing::FLAGS_gtest_death_test_style = "threadsafe";
  EXPECT_DEATH(
      {
        installExceptionStackTracer();
        std::exception_ptr eptr = captureOnOtherThread();
        // Uncaught rethrow on a third thread: the terminate happens on a
        // different thread than the throw, via a dependent exception -- the
        // record must still resolve through the primary object.
        terminateViaEscapingThread([eptr] { std::rethrow_exception(eptr); });
      },
      "what\\(\\): boom-from-throw-site"
      ".*throw-site stack \\(recorded as St13runtime_error\\)"
      ".*#00 ");
}

TEST(ExceptionStackTracerDeathTest, EvictedRecordDegradesGracefully) {
  testing::FLAGS_gtest_death_test_style = "threadsafe";
  EXPECT_DEATH(
      {
        installExceptionStackTracer();
        std::exception_ptr eptr = captureOnOtherThread();
        // Wrap the 64-slot ring so the captured exception's record is gone.
        for (int i = 0; i < 100; ++i) {
          try {
            throw std::logic_error("filler");
          } catch (const std::logic_error&) {
          }
        }
        terminateViaEscapingThread([eptr] { std::rethrow_exception(eptr); });
      },
      "what\\(\\): boom-from-throw-site"
      ".*throw-site stack unavailable");
}

TEST(ExceptionStackTracerDeathTest, DisabledTracerKeepsDefaultTerminate) {
  testing::FLAGS_gtest_death_test_style = "threadsafe";
  // libstdc++'s verbose terminate handler output, not ours.
  EXPECT_DEATH(
      {
        installExceptionStackTracer(false);
        terminateViaEscapingThread(throwRuntimeError);
      },
      "terminate called after throwing an instance of");
}

// In-process (non-death) tests. Unlike the death tests above -- whose forked
// children abort() and so never flush coverage counters -- these run the
// record, lookup, seqlock-validation and frame-printing logic in the parent
// process via the extracted logThrowSiteStackOfCurrentException() helper. That
// makes the terminate-path code visible to coverage and lets us assert on the
// captured output directly instead of only matching a dying child's stderr.

using exception_stack_tracer_internal::logThrowSiteStackOfCurrentException;
using exception_stack_tracer_internal::resetForTest;

TEST(ExceptionStackTracerTest, RecordsAndResolvesThrowSiteInProcess) {
  resetForTest();
  installExceptionStackTracer(true);
  testing::internal::CaptureStderr();
  try {
    throwRuntimeError();
  } catch (...) {
    logThrowSiteStackOfCurrentException();
  }
  const std::string err = testing::internal::GetCapturedStderr();
  EXPECT_NE(err.find("uncaught exception of type St13runtime_error"),
            std::string::npos);
  EXPECT_NE(err.find("what(): boom-from-throw-site"), std::string::npos);
  EXPECT_NE(err.find("throw-site stack (recorded as St13runtime_error)"),
            std::string::npos);
  // At least five frames captured, proving a real multi-frame stack walk.
  for (const char* frame : {"#00 ", "#01 ", "#02 ", "#03 ", "#04 "}) {
    EXPECT_NE(err.find(frame), std::string::npos) << "missing frame " << frame;
  }
}

TEST(ExceptionStackTracerTest, DisabledTracerRecordsNothingInProcess) {
  resetForTest();
  installExceptionStackTracer(false);
  testing::internal::CaptureStderr();
  try {
    throwRuntimeError();
  } catch (...) {
    logThrowSiteStackOfCurrentException();
  }
  const std::string err = testing::internal::GetCapturedStderr();
  EXPECT_NE(err.find("throw-site stack unavailable"), std::string::npos);
}

TEST(ExceptionStackTracerTest, EvictedRecordReportsUnavailableInProcess) {
  resetForTest();
  installExceptionStackTracer(true);
  std::exception_ptr eptr = captureOnOtherThread();
  // Wrap the 64-slot ring so the captured exception's record is overwritten.
  for (int i = 0; i < 100; ++i) {
    try {
      throw std::logic_error("filler");
    } catch (const std::logic_error&) {
    }
  }
  testing::internal::CaptureStderr();
  try {
    std::rethrow_exception(eptr);
  } catch (...) {
    logThrowSiteStackOfCurrentException();
  }
  const std::string err = testing::internal::GetCapturedStderr();
  EXPECT_NE(err.find("throw-site stack unavailable"), std::string::npos);
}

TEST(ExceptionStackTracerTest, NoActiveExceptionIsHandledInProcess) {
  resetForTest();
  installExceptionStackTracer(true);
  testing::internal::CaptureStderr();
  logThrowSiteStackOfCurrentException();  // no exception in flight
  const std::string err = testing::internal::GetCapturedStderr();
  EXPECT_NE(err.find("called without an active exception"), std::string::npos);
}

}  // namespace
