Skip to content

Commit

Permalink
Merge pull request #38 from gedaiu/35-catch-seg-faults
Browse files Browse the repository at this point in the history
35 catch seg faults
  • Loading branch information
gedaiu authored Sep 26, 2017
2 parents 70f1765 + 6cb7171 commit e40379e
Show file tree
Hide file tree
Showing 2 changed files with 101 additions and 0 deletions.
96 changes: 96 additions & 0 deletions lifecycle/trial/runner.d
Original file line number Diff line number Diff line change
Expand Up @@ -130,6 +130,7 @@ const(TestCase)[][string] describeTests(const(TestCase)[] tests) {
return groupedTests;
}

///
string toJSONHierarchy(T)(const(T)[][string] items) {
struct Node {
Node[string] nodes;
Expand Down Expand Up @@ -222,6 +223,8 @@ unittest {

/// Runs the tests and returns the results
auto runTests(const(TestCase)[] tests, string testName = "") {
setupSegmentationHandler!true();

const(TestCase)[] filteredTests = tests;

if(testName != "") {
Expand Down Expand Up @@ -295,8 +298,19 @@ class LifeCycleListeners {
ITestDiscovery[] testDiscoveryListeners;
IAttachmentListener[] attachmentListeners;
ITestExecutor executor;

string currentTest;
}

@property {
/// Return an unique name for the current running test. If there is no test running it
/// will return an empty string
string runningTest() const nothrow {
return currentTest;
}
}

///
TestCase[] getTestCases() {
return testDiscoveryListeners.map!(a => a.getTestCases).join;
}
Expand Down Expand Up @@ -370,21 +384,25 @@ class LifeCycleListeners {

/// Send the begin test event to all listeners
void begin(string suite, ref TestResult test) {
currentTest = suite ~ "." ~ test.name;
testListeners.each!(a => a.begin(suite, test));
}

/// Send the end test event to all listeners
void end(string suite, ref TestResult test) {
currentTest = "";
testListeners.each!(a => a.end(suite, test));
}

/// Send the begin step event to all listeners
void begin(string suite, string test, ref StepResult step) {
currentTest = suite ~ "." ~ test ~ "." ~ step.name;
stepListeners.each!(a => a.begin(suite, test, step));
}

/// Send the end step event to all listeners
void end(string suite, string test, ref StepResult step) {
currentTest = "";
stepListeners.each!(a => a.end(suite, test, step));
}

Expand All @@ -402,4 +420,82 @@ class LifeCycleListeners {
SuiteResult[] endExecution() {
return executor.endExecution();
}
}

/// It should return the name of this test
unittest {
LifeCycleListeners.instance.runningTest.should.equal("trial.runner.It should return the name of this test");
}

void setupSegmentationHandler(bool testRunner)()
{
import core.runtime;

// backtrace
version( CRuntime_Glibc )
import core.sys.linux.execinfo;
else version( OSX )
import core.sys.darwin.execinfo;
else version( FreeBSD )
import core.sys.freebsd.execinfo;
else version( NetBSD )
import core.sys.netbsd.execinfo;
else version( Windows )
import core.sys.windows.stacktrace;
else version( Solaris )
import core.sys.solaris.execinfo;

static if( __traits( compiles, backtrace ) )
{
import core.sys.posix.signal; // segv handler

static extern (C) void unittestSegvHandler(int signum, siginfo_t* info, void* ptr ) nothrow
{
import core.stdc.stdio;

core.stdc.stdio.printf("\n\n");

static if(testRunner) {
if(signum == SIGSEGV) {
core.stdc.stdio.printf("Got a Segmentation Fault running ");
}

if(signum == SIGBUS) {
core.stdc.stdio.printf("Got a bus error running ");
}


if(LifeCycleListeners.instance.runningTest != "") {
core.stdc.stdio.printf("%s\n\n", LifeCycleListeners.instance.runningTest.ptr);
} else {
core.stdc.stdio.printf("some setup step. This is probably a Trial bug. Please create an issue on github.\n\n");
}
} else {
if(signum == SIGSEGV) {
core.stdc.stdio.printf("Got a Segmentation Fault! ");
}

if(signum == SIGBUS) {
core.stdc.stdio.printf("Got a bus error! ");
}

core.stdc.stdio.printf(" This is probably a Trial bug. Please create an issue on github.\n\n");
}

static enum MAXFRAMES = 128;
void*[MAXFRAMES] callstack;
int numframes;

numframes = backtrace( callstack.ptr, MAXFRAMES );
backtrace_symbols_fd( callstack.ptr, numframes, 2);
}

sigaction_t action = void;
(cast(byte*) &action)[0 .. action.sizeof] = 0;
sigfillset( &action.sa_mask ); // block other signals
action.sa_flags = SA_SIGINFO | SA_RESETHAND;
action.sa_sigaction = &unittestSegvHandler;
sigaction( SIGSEGV, &action, null );
sigaction( SIGBUS, &action, null );
}
}
5 changes: 5 additions & 0 deletions runner/app.d
Original file line number Diff line number Diff line change
Expand Up @@ -89,6 +89,11 @@ void showVersion() {

version(unitttest) {} else {
int main(string[] arguments) {
import trial.runner;
setupSegmentationHandler!false;

arguments = arguments.map!(a => a.strip).filter!(a => a != "").array;

version(Windows) {
environment["TEMP"] = environment["TEMP"].replace("/", "\\");
}
Expand Down

0 comments on commit e40379e

Please sign in to comment.