#ifndef PLS_TEST_TEST_HELPERS_H_
#define PLS_TEST_TEST_HELPERS_H_

#include <sys/types.h>
#include <sys/wait.h>
#include <unistd.h>

#include <cstdlib>
#include <csignal>

// Source: https://stackoverflow.com/questions/15749071/fork-and-wait-in-c
// Works well enough for our purpose.
void abort_handler(int) {
  std::exit(1);
}

template<class F>
bool CHECK_ABORT(F &&f) {
  //spawn a new process
  auto child_pid = fork();

  //if the fork succeed
  if (child_pid >= 0) {

    //if we are in the child process
    if (child_pid == 0) {
      // Re-direct the signal handlers added by catch to simply exit with an error code
      std::signal(SIGABRT, abort_handler);
      std::signal(SIGFPE, abort_handler);
      std::signal(SIGSEGV, abort_handler);
      std::signal(SIGILL, abort_handler);

      //call the lambda that we expect to abort
      f();

      //if the function didn't abort, we'll exit cleanly
      std::exit(EXIT_SUCCESS);
    }
  }

  //determine if the child process aborted
  int exit_status;
  wait(&exit_status);

  //we check the exit status instead of a signal interrupt, because
  //Catch is going to catch the signal and exit with an error
  bool aborted = exit_status != 0;

  return aborted;
}

#endif //PLS_TEST_TEST_HELPERS_H_
