Skip to content

Commit

Permalink
Merge branch 'jl/LH-8/debug-function-guards' into pu
Browse files Browse the repository at this point in the history
* jl/LH-8/debug-function-guards:
  Debug function guards: implement the guard.

Conflicts:
	PowerEditor/visual.net/notepadPlus.8.vcproj
	PowerEditor/visual.net/notepadPlus.9.vcproj

[#8 state:proposed responsible:npp-community]

Signed-off-by: Thell Fowler <git@tbfowler.name>
  • Loading branch information
Thell Fowler committed Oct 21, 2009
2 parents 2fb94f7 + fe52743 commit dec005f
Show file tree
Hide file tree
Showing 6 changed files with 296 additions and 23 deletions.
4 changes: 2 additions & 2 deletions PowerEditor/src/MISC/Common/Common.h
Original file line number Diff line number Diff line change
Expand Up @@ -131,10 +131,10 @@ class WcharMbcsConvertor

#define ERROR_MSG_SIZE 1024

#ifdef DEBUG
#ifdef _DEBUG
#define NO_DEFAULT_CASE default: {\
TCHAR errorMsg[ERROR_MSG_SIZE];\
sprintf_s(errorMsg, ERROR_MSG_SIZE, "Unhanded default case in %s, line %d", __FILE__, __LINE__ );\
_stprintf_s(errorMsg, ERROR_MSG_SIZE, TEXT("Unhanded default case in %s, line %d"), __FILE__, __LINE__ );\
::MessageBox(NULL, TEXT("Unhandled default case."), errorMsg, MB_OK|MB_ICONWARNING);\
}\
break
Expand Down
88 changes: 76 additions & 12 deletions PowerEditor/src/MISC/Debug/npp_debug.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -21,21 +21,85 @@

#include "npp_debug.h"

namespace Debug
namespace NppDebug
{
void OutputF(TCHAR* format, ...)

static outputFunction debugOutput = OutputDebugString;

outputFunction setOutputFunction(outputFunction newOutputFunction)
{
outputFunction currentOutputFunc = debugOutput;
debugOutput = newOutputFunction;
return currentOutputFunc;
}

void outputF(TCHAR* format, ...)
{
va_list args;
int len;
TCHAR* buffer;

va_start( args, format );
len = _vsctprintf( format, args ) + 1; // _vscprintf doesn't count terminating '\0'
buffer = new TCHAR[len];
_vstprintf_s( buffer, len, format, args );
debugOutput(buffer);
delete [] buffer;
}

int FuncGuard::_depth = 0;
TCHAR FuncGuard::_indent[MAX_DEBUG_INDENT];

FuncGuard::FuncGuard(const TCHAR* funcsig, const TCHAR* funcname, const TCHAR* file, int line):
_funcname(funcname)
{
outputF(TEXT("%s%s(%d):\n"), getIndent(), file, line);
outputF(TEXT("%sEntering[ %s ]\n"), getIndent(), funcsig);
indent();
}

FuncGuard::~FuncGuard()
{
unindent();
outputF(TEXT("%sLeaving[ %s ]\n"), getIndent(), _funcname.c_str());
}

void FuncGuard::outputIndent()
{
outputF(getIndent());
}

void FuncGuard::indent()
{
_depth++;
if (_depth >= MAX_DEBUG_INDENT)
{
DebugBreak();
_depth = MAX_DEBUG_INDENT-1;
}
}

void FuncGuard::unindent()
{
_depth--;
if (_depth < 0)
{
DebugBreak();
_depth = 0;
}
}

TCHAR* FuncGuard::getIndent()
{
int i = 0;;
for (; i < _depth; i++)
{
va_list args;
int len;
TCHAR* buffer;

va_start( args, format );
len = _vsctprintf( format, args ) + 1; // _vscprintf doesn't count terminating '\0'
buffer = new TCHAR[len];
_vstprintf_s( buffer, len, format, args );
OutputDebugString(buffer);
delete [] buffer;
_indent[i] = TEXT('\t');
}
_indent[i] = TEXT('\0');
return _indent;
}

} // namespace Debug

#endif // #ifndef SHIPPING
50 changes: 41 additions & 9 deletions PowerEditor/src/MISC/Debug/npp_debug.h
Original file line number Diff line number Diff line change
Expand Up @@ -19,16 +19,48 @@
#define NPP_DEBUG_H

#ifndef SHIPPING
namespace Debug
{
void OutputF(TCHAR* format, ...);
}

#define debugf(format, ...) Debug::OutputF(format, __VA_ARGS__)
#define _debugf(format, ...) Debug::OutputF(TEXT("%s(%d): "), TEXT(__FILE__), __LINE__); Debug::OutputF(format, __VA_ARGS__)
#else

#define MAX_DEBUG_INDENT 1024
namespace NppDebug
{
typedef void (__stdcall *outputFunction)(const TCHAR*);

outputFunction setOutputFunction(outputFunction newOutputFunction);

void outputF(TCHAR* format, ...);

// JOCE: Nice to have: configurable indent character (' ', '\t', '_', '+', etc...)
class FuncGuard
{
public:
FuncGuard(const TCHAR* funcsig, const TCHAR* funcname, const TCHAR* file, int line);
~FuncGuard();

void outputIndent();

private:
void indent();
void unindent();
TCHAR* getIndent();
generic_string _funcname;

static int _depth;
static TCHAR _indent[MAX_DEBUG_INDENT];
};

} // namespace NppDebug

#define debugf(format, ...) NppDebug::outputF(format, __VA_ARGS__)
// JOCE: modify to make that a single call to OutputF
#define line_debugf(format, ...) NppDebug::outputF(TEXT("%s(%d): "), TEXT(__FILE__), __LINE__); NppDebug::outputF(format, __VA_ARGS__)
// JOCE: modify to make that a single call to OutputF
#define guard_debugf(format, ...) __npp_func_guard__.outputIndent(); NppDebug::outputF(format, __VA_ARGS__)
#define func_guard() NppDebug::FuncGuard __npp_func_guard__(TEXT(__FUNCSIG__), TEXT(__FUNCTION__), TEXT(__FILE__), __LINE__)

#else // if !SHIPPING
#define debugf(format, ...) void(0)
#define _debugf(format, ...) void(0)
#endif
#define guard_func() void(0)
#endif // SHIPPING

#endif // NPP_DEBUG_H
169 changes: 169 additions & 0 deletions PowerEditor/tests/testNppDebug.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,169 @@
// This file is part of notepad++
// Copyright (C)2009 The Notepad++ Team
//
// This program is free software; you can redistribute it and/or
// modify it under the terms of the GNU General Public License
// as published by the Free Software Foundation; either
// version 2 of the License, or (at your option) any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program; if not, write to the Free Software
// Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.

#include "precompiled_headers.h"

#ifndef SHIPPING

// JOCE tests would be needed for debugf and _debugf as well.

//////////////////////////////////////////////////////////////////////////
//
// Table of Content:
// - FuncGuardTest
//
//////////////////////////////////////////////////////////////////////////



//////////////////////////////////////////////////////////////////////////
//
// FuncGuardTest
//
//////////////////////////////////////////////////////////////////////////

static generic_string s_outputResult;

static void __stdcall testOutputFunction(const TCHAR* input)
{
s_outputResult.append(input);
}

class FuncGuardTest : public ::testing::Test
{
public:
FuncGuardTest() :
originalOutput(NppDebug::setOutputFunction(testOutputFunction))
{
s_outputResult = TEXT("");
}

~FuncGuardTest()
{
NppDebug::setOutputFunction(originalOutput);
}

NppDebug::outputFunction originalOutput;
};


// JOCE: If we could make the "expected" string looking more like what the actual output is, that'd be nice.
TEST_F(FuncGuardTest, guardSimple)
{
{
NppDebug::FuncGuard guard(TEXT("sig"), TEXT("name"), TEXT("file"), 1);
ASSERT_EQ(TEXT("file(1):\nEntering[ sig ]\n"), s_outputResult);
}
ASSERT_EQ(TEXT("file(1):\nEntering[ sig ]\nLeaving[ name ]\n"), s_outputResult);
}

TEST_F(FuncGuardTest, guardSimpleIndent)
{
{
NppDebug::FuncGuard guard1(TEXT("sig"), TEXT("name"), TEXT("file"), 1);
ASSERT_EQ(TEXT("file(1):\nEntering[ sig ]\n"), s_outputResult);
{
NppDebug::FuncGuard guard2(TEXT("sig2"), TEXT("name2"), TEXT("file2"), 2);
ASSERT_EQ(TEXT("file(1):\nEntering[ sig ]\n\tfile2(2):\n\tEntering[ sig2 ]\n"), s_outputResult);
}
ASSERT_EQ(TEXT("file(1):\nEntering[ sig ]\n\tfile2(2):\n\tEntering[ sig2 ]\n\tLeaving[ name2 ]\n"), s_outputResult);
}
ASSERT_EQ(TEXT("file(1):\nEntering[ sig ]\n\tfile2(2):\n\tEntering[ sig2 ]\n\tLeaving[ name2 ]\nLeaving[ name ]\n"), s_outputResult);
}

static TCHAR TestGuardFuncOneGuardLine[8];
void TestGuardFuncOne()
{
func_guard(); int line = __LINE__; // This declaration needs to be on the same line as func_guard to get the right line number.
_itot_s(line, TestGuardFuncOneGuardLine, 10);
}

static TCHAR TestGuardFuncTwoGuardLine[8];
void TestGuardFuncTwo()
{
func_guard(); int line = __LINE__; // This declaration needs to be on the same line as func_guard to get the right line number.
_itot_s(line, TestGuardFuncTwoGuardLine, 10);
TestGuardFuncOne();
}

TEST_F(FuncGuardTest, guardFunc)
{
TestGuardFuncOne();
generic_string expected = TEXT(__FILE__);
expected += TEXT('(');
expected += TestGuardFuncOneGuardLine;
expected += TEXT("):\n");
expected += TEXT("Entering[ void __cdecl TestGuardFuncOne(void) ]\n");
expected += TEXT("Leaving[ TestGuardFuncOne ]\n");
ASSERT_EQ(expected, s_outputResult);
}

TEST_F(FuncGuardTest, guardFuncIndent)
{
TestGuardFuncTwo();
generic_string expected = TEXT(__FILE__);
expected += TEXT('(');
expected += TestGuardFuncTwoGuardLine;
expected += TEXT("):\n");
expected += TEXT("Entering[ void __cdecl TestGuardFuncTwo(void) ]\n");
expected += TEXT("\t");
expected += TEXT(__FILE__);
expected += TEXT('(');
expected += TestGuardFuncOneGuardLine;
expected += TEXT("):\n");
expected += TEXT("\tEntering[ void __cdecl TestGuardFuncOne(void) ]\n");
expected += TEXT("\tLeaving[ TestGuardFuncOne ]\n");
expected += TEXT("Leaving[ TestGuardFuncTwo ]\n");
ASSERT_EQ(expected, s_outputResult);
}

void TestGuardFuncWithCommentOne()
{
func_guard(); int line = __LINE__; // This declaration needs to be on the same line as func_guard to get the right line number.
_itot_s(line, TestGuardFuncOneGuardLine, 10);
guard_debugf(TEXT("We print a number: %d\n"), 42);
}

void TestGuardFuncWithCommentTwo()
{
func_guard(); int line = __LINE__; // This declaration needs to be on the same line as func_guard to get the right line number.
_itot_s(line, TestGuardFuncTwoGuardLine, 10);
TestGuardFuncWithCommentOne();
}

TEST_F(FuncGuardTest, guardFuncIndentWithDebugComment)
{
TestGuardFuncWithCommentTwo();
generic_string expected = TEXT(__FILE__);
expected += TEXT('(');
expected += TestGuardFuncTwoGuardLine;
expected += TEXT("):\n");
expected += TEXT("Entering[ void __cdecl TestGuardFuncWithCommentTwo(void) ]\n");
expected += TEXT("\t");
expected += TEXT(__FILE__);
expected += TEXT('(');
expected += TestGuardFuncOneGuardLine;
expected += TEXT("):\n");
expected += TEXT("\tEntering[ void __cdecl TestGuardFuncWithCommentOne(void) ]\n");
expected += TEXT("\t\tWe print a number: 42\n");
expected += TEXT("\tLeaving[ TestGuardFuncWithCommentOne ]\n");
expected += TEXT("Leaving[ TestGuardFuncWithCommentTwo ]\n");
ASSERT_EQ(expected, s_outputResult);
}


#endif // SHIPPING
4 changes: 4 additions & 0 deletions PowerEditor/visual.net/notepadPlus.8.vcproj
Original file line number Diff line number Diff line change
Expand Up @@ -1740,6 +1740,10 @@
RelativePath="..\tests\testFindHistory.cpp"
>
</File>
<File
RelativePath="..\tests\testNppDebug.cpp"
>
</File>
<File
RelativePath="..\tests\testParameters.cpp"
>
Expand Down
4 changes: 4 additions & 0 deletions PowerEditor/visual.net/notepadPlus.9.vcproj
Original file line number Diff line number Diff line change
Expand Up @@ -760,6 +760,10 @@
RelativePath="..\tests\testFindHistory.cpp"
>
</File>
<File
RelativePath="..\tests\testNppDebug.cpp"
>
</File>
<File
RelativePath="..\tests\testParameters.cpp"
>
Expand Down

0 comments on commit dec005f

Please sign in to comment.