Lhaz
読み取り中…
検索中…
一致する文字列を見つけられません
WinUnit.h
[詳解]
1/* -------------------------------------------------------------------------- *
2 WinUnit - Maria Blees (maria.blees@microsoft.com)
3
4 Version: 1.2.0909.1
5 * -------------------------------------------------------------------------- */
6
7#pragma once
8
9// Compiler version check:
10// WinUnit supports Visual C++ compiler version 9 and subsequent versions
11#if _MSC_VER < 1500
12#error "Compiler not supported. WinUnit requires at least Microsoft Visual C++ compiler version 9"
13#endif
14
21
70
90
91#include <windows.h>
92#include <tchar.h>
93#include <wchar.h>
94#include <stdarg.h>
95#include <stdio.h>
96#include <stdlib.h> // for _countof
97#include <locale> // for isprint
98
99// This is the max buffer length for the message assigned to an assert exception.
100#define MAX_ASSERT_MESSAGE_LENGTH 1024
101
102// This is the max buffer length for a single trace string.
103#define MAX_TRACE_MESSAGE_LENGTH 1024
104
105// This is the max buffer length for the string form of a single expression
106// (used when displaying the expression as part of an error message)
107#define MAX_EXPRESSION_STRING 256
108
109// This is the max buffer length to hold an error string from GetLastError.
110// (80 was suggested in the sample code for the FormatMessage function, but was
111// too small for at least one error message.)
112#define MAX_SYSERROR_STRING 120
113
114#define EMIT_ERROR(...) ¥
115 ::_snwprintf_s(__winUnit_buffer, __winUnit_cchBuffer, _TRUNCATE, __VA_ARGS__); ¥
116 return false;
117
118#define BEGIN_TEST_FUNC(x) extern "C" __declspec(dllexport) bool __cdecl TEST_##x(wchar_t* __winUnit_buffer, size_t __winUnit_cchBuffer) {
119#define BEGIN_FIXTURE_BLOCK(fixtureName) try { FIXTURE_##fixtureName __fixture_##fixtureName;
120#define BEGIN_TEST_BLOCK try
121#define END_TEST_BLOCK ¥
123 { ¥
124 EMIT_ERROR(L"%s", e.Message()); ¥
125 } ¥
126 catch(...) ¥
127 { ¥
128 EMIT_ERROR(L"%s(%d): Exception thrown.", ¥
129 __WFILE__, __LINE__); ¥
130 } ¥
131
132#define END_FIXTURE_BLOCK ¥
133 } ¥
135 { ¥
136 EMIT_ERROR(e.Message()); ¥
137 } ¥
138 catch(...) ¥
139 { ¥
140 EMIT_ERROR(L"%s(%d): Exception thrown in fixture.", ¥
141 __WFILE__, __LINE__); ¥
142 } ¥
143
144#define END_TEST_FUNC return true; }
145
152#define BEGIN_TEST(x) BEGIN_TEST_FUNC(x) BEGIN_TEST_BLOCK
153
162#define END_TEST END_TEST_BLOCK END_TEST_FUNC
163
169#define BEGIN_TESTF(x, f) BEGIN_TEST_FUNC(x) BEGIN_FIXTURE_BLOCK(f) BEGIN_TEST_BLOCK
170
173#define END_TESTF END_TEST_BLOCK END_FIXTURE_BLOCK END_TEST_FUNC
174
175namespace WinUnit
176{
180 template<class T>
181 inline const TCHAR* ToString(
182 const T& object,
183 TCHAR buffer[],
184 size_t bufferSize);
185}
186
187// The macros and functions in this file are designed to work whether or not
188// _UNICODE is defined. The following are helper macros that give certain
189// strings the right character width.
190//
191#define WINUNIT_WIDEN2(x) L ## x
192#define WINUNIT_WIDEN(x) WINUNIT_WIDEN2(x)
193
194#ifndef __WFILE__
195#define __WFILE__ WINUNIT_WIDEN(__FILE__)
196#else
197#pragma message("WinUnit.h: __WFILE__ already defined")
198#endif
199
200#ifndef __WFUNCTION__
201#define __WFUNCTION__ WINUNIT_WIDEN(__FUNCTION__)
202#else
203#pragma message("WinUnit.h: __WFUNCTION__ already defined")
204#endif
205
206//
207#ifdef _UNICODE
208#define TSTRING(x) WINUNIT_WIDEN(#x)
209#define __TFILE__ __WFILE__
210#define __TFUNCTION__ __WFUNCTION__
211#else
212#define TSTRING(x) #x
213#define __TFILE__ __FILE__
214#define __TFUNCTION__ __FUNCTION__
215#endif
216
217#pragma region WIN_ASSERT_* macros
218
230#define WIN_ASSERT_EQUAL(expected, actual, ...) WinUnit::Assert::AreEqual(TSTRING(expected), expected, TSTRING(actual), actual, __TFILE__, __LINE__, __VA_ARGS__)
231
243#define WIN_ASSERT_NOT_EQUAL(notExpected, actual, ...) WinUnit::Assert::AreNotEqual(TSTRING(notExpected), notExpected, TSTRING(actual), actual, __TFILE__, __LINE__, __VA_ARGS__)
244
257#define WIN_ASSERT_STRING_EQUAL(expected, actual, ...) WinUnit::Assert::StringEqual(expected, actual, __TFILE__, __LINE__, __VA_ARGS__)
258
263#define WIN_ASSERT_ZERO(zeroExpression, ...) WinUnit::Assert::IsZero(TSTRING(zeroExpression), zeroExpression, __TFILE__, __LINE__, __VA_ARGS__)
264
269#define WIN_ASSERT_NOT_ZERO(nonzeroExpression, ...) WinUnit::Assert::IsNotZero(TSTRING(nonzeroExpression), nonzeroExpression, __TFILE__, __LINE__, __VA_ARGS__)
270
278#define WIN_ASSERT_NULL(nullExpression, ...) WinUnit::Assert::IsNull(TSTRING(nullExpression), nullExpression, __TFILE__, __LINE__, __VA_ARGS__)
279
287#define WIN_ASSERT_NOT_NULL(notNullExpression, ...) WinUnit::Assert::IsNotNull(TSTRING(notNullExpression), notNullExpression, __TFILE__, __LINE__, __VA_ARGS__)
288
294#define WIN_ASSERT_FAIL(message, ...) WinUnit::Assert::Fail(__TFILE__, __LINE__, message, __VA_ARGS__)
295
300#define WIN_ASSERT_TRUE(trueExpression, ...) WinUnit::Assert::IsTrue(TSTRING(trueExpression), (trueExpression ? true : false), __TFILE__, __LINE__, __VA_ARGS__)
301
306#define WIN_ASSERT_FALSE(falseExpression, ...) WinUnit::Assert::IsFalse(TSTRING(falseExpression), (falseExpression ? true : false), __TFILE__, __LINE__, __VA_ARGS__)
307
319#define WIN_ASSERT_WINAPI_SUCCESS(trueExpression, ...) WinUnit::Assert::WinapiSucceeded(TSTRING(trueExpression), (trueExpression ? true : false), __TFILE__, __LINE__, __VA_ARGS__)
320
329#define WIN_ASSERT_THROWS(expression, exceptionType, ...) ¥
330{ ¥
331 bool __thrown = false; ¥
332 try { (expression); } ¥
333 catch(exceptionType&) { __thrown = true; } ¥
335 TSTRING(expression), TSTRING(exceptionType), ¥
336 __thrown, __TFILE__, __LINE__, __VA_ARGS__); ¥
337}
338
339#pragma endregion
340
341#pragma region Setup/Teardown helpers
342
349#define FIXTURE(x) ¥
350class FIXTURE_##x ¥
351{ ¥
352public: ¥
353 void Setup(); ¥
354 void Teardown(); ¥
355public: ¥
356 FIXTURE_##x() { Setup(); } ¥
357 ‾FIXTURE_##x() { Teardown(); } ¥
358};
359
369#define SETUP(x) void FIXTURE_##x::Setup()
370
380#define TEARDOWN(x) void FIXTURE_##x::Teardown()
381
382#pragma endregion
383
384#pragma region AssertException and friends
385
386namespace WinUnit
387{
410 {
411 public:
413 virtual const wchar_t* Message() = 0;
414 public:
415 virtual ‾AssertException() = 0 {}
416 };
417}
418
419// AssertExceptionT is used within the Assert::* methods, all of which
420// use strings of type TCHAR*.
421#ifdef _UNICODE
422#define AssertExceptionT AssertExceptionW<MAX_ASSERT_MESSAGE_LENGTH>
423#else
424#define AssertExceptionT AssertExceptionA<MAX_ASSERT_MESSAGE_LENGTH>
425#endif
426
427#ifndef EXCLUDE_FROM_DOCUMENTATION
428// (The details about the implementations of these classes don't need to be part
429// of the documentation on how to use this file.)
430namespace WinUnit
431{
432 // The derived classes of AssertException are templated with a buffer size
433 // (size in characters) to make them easier to test.
434 //
435 // AssertExceptionW is the version with the wide-character interface.
436 template<size_t size=MAX_ASSERT_MESSAGE_LENGTH>
438 {
439 private:
440 size_t _messageLength; // The length of the message as filled in so far (starts at 0)
441 const size_t _cchBuffer; // The size of the buffer in characters (same as "size")
442 wchar_t _buffer[size]; // The wide-character buffer that holds the message
443
444 public:
446
447 // Append a formatted message to the exception's Message string. "message"
448 // is a printf-style format string; "..." and "args" are two ways of passing
449 // in the variable-length argument list.
450 void AppendMessage(const wchar_t* message, ...);
451 void AppendMessage(const wchar_t* message, va_list args);
452 public:
453 virtual const wchar_t* Message();
454
455 protected:
456 // This property is used for clarity when manipulating the buffers; it
457 // returns a pointer to where additional text should be appended.
459 wchar_t* AvailableBufferStart;
461
462 // This property is used for clarity when manipulating the buffers; it
463 // returns the length left in the buffer, to be used when appending.
465 size_t AvailableBufferLength;
467
468 // This property encapsulates the _messageLength member, for symmetry
469 // with the other properties.
471 size_t MessageLength;
472 size_t GetMessageLength() { return _messageLength; }
473 void SetMessageLength(size_t messageLength) { _messageLength = messageLength; }
474
475 private:
477 };
478
479 // This one extends AssertExceptionW to deal with ANSI strings.
480 template<size_t size=MAX_ASSERT_MESSAGE_LENGTH>
482 {
483 public:
484 void AppendMessage(const char* message, ...);
485 void AppendMessage(const char* message, va_list args);
486 private:
488 };
489}
490#endif // EXCLUDE_FROM_DOCUMENTATION
491
492#pragma endregion
493
494#pragma region Assert class definition
495
496namespace WinUnit
497{
502 class Assert
503 {
504 public:
505 // AreEqual
506 template <class T, class U>
507 static void AreEqual(
508 const TCHAR* expectedExpressionString, const T& expectedExpressionValue,
509 const TCHAR* actualExpressionString, const U& actualExpressionValue,
510 const TCHAR* fileName, int lineNumber,
511 const TCHAR* message = NULL, ...);
512
513 // AreNotEqual
514 template <class T, class U>
515 static void AreNotEqual(
516 const TCHAR* notExpectedExpressionString, const T& notExpectedExpressionValue,
517 const TCHAR* actualExpressionString, const U& actualExpressionValue,
518 const TCHAR* fileName, int lineNumber,
519 const TCHAR* message = NULL, ...);
520
521 // StringEqual
522 static void StringEqual(
523 const wchar_t* expected, const wchar_t* actual,
524 const TCHAR* fileName, int lineNumber,
525 const TCHAR* message = NULL, ...);
526
527 static void StringEqual(
528 const char* expected, const char* actual,
529 const TCHAR* fileName, int lineNumber,
530 const TCHAR* message = NULL, ...);
531
532 // IsZero
533 template<class T>
534 static void IsZero(const TCHAR* zeroExpressionString, const T& zeroExpression,
535 const TCHAR* fileName, int lineNumber,
536 const TCHAR* message = NULL, ...);
537
538 // IsNotZero
539 template<class T>
540 static void IsNotZero(const TCHAR* nonzeroExpressionString, const T& nonzeroExpression,
541 const TCHAR* fileName, int lineNumber,
542 const TCHAR* message = NULL, ...);
543
544 // IsNull
545 template<class T>
546 static void IsNull(const TCHAR* expressionString, T* nullExpression,
547 const TCHAR* fileName, int lineNumber,
548 const TCHAR* message = NULL, ...);
549
550 // IsNotNull
551 template<class T>
552 static void IsNotNull(const TCHAR* notNullExpressionString, T* notNullExpression,
553 const TCHAR* fileName, int lineNumber,
554 const TCHAR* message = NULL, ...);
555
556 // Fail
557 static void Fail(const TCHAR* fileName, int lineNumber,
558 const TCHAR* message = NULL, ...);
559
560 // IsTrue
561 static void IsTrue(const TCHAR* expressionString, bool trueExpression,
562 const TCHAR* fileName, int lineNumber,
563 const TCHAR* message = NULL, ...);
564
565 // IsFalse
566 static void IsFalse(const TCHAR* expressionString, bool falseExpression,
567 const TCHAR* fileName, int lineNumber,
568 const TCHAR* message = NULL, ...);
569
570 // WinapiSucceeded
571 static void WinapiSucceeded(const TCHAR* expressionString,
572 bool success,
573 const TCHAR* fileName, int lineNumber,
574 const TCHAR* message = NULL, ...);
575
576 // ThrowsException
577 static void ThrowsException(
578 const TCHAR* expressionString,
579 const TCHAR* exceptionType,
580 bool exceptionWasThrown,
581 const TCHAR* fileName, int lineNumber,
582 const TCHAR* message = NULL, ...);
583
584 private:
586 };
587}
588#pragma endregion
589
590#pragma region Assert implementation
591
592namespace WinUnit
593{
594// AreEqual
595template <class T, class U>
597 const TCHAR* expectedExpressionString, const T& expectedExpressionValue,
598 const TCHAR* actualExpressionString, const U& actualExpressionValue,
599 const TCHAR* fileName, int lineNumber,
600 const TCHAR* message /* NULL */, ...)
601{
602 // Unfortunately if a numeric literal was passed in as one of the values
603 // and an unsigned number as the other, you'll get a signed/unsigned mismatch,
604 // as numeric literal integers always template-match to int. To get around
605 // this, postfix numeric literals with 'U' so they will match as unsigned.
606 if (expectedExpressionValue == actualExpressionValue) { return; }
607
608 TCHAR buffer1[MAX_EXPRESSION_STRING] = _T("");
609 TCHAR buffer2[MAX_EXPRESSION_STRING] = _T("");
610
611 AssertExceptionT exception;
612 exception.AppendMessage(_T("%s(%d): error : WIN_ASSERT_EQUAL failed. Expected: <%s> (¥"%s¥"); Actual: <%s> (¥"%s¥"). "),
613 fileName,
614 lineNumber,
615 ToString(expectedExpressionValue, buffer1, ARRAYSIZE(buffer1)),
616 expectedExpressionString,
617 ToString(actualExpressionValue, buffer2, ARRAYSIZE(buffer2)),
618 actualExpressionString);
619
620 if (message)
621 {
622 va_list args;
623 va_start(args, message);
624 exception.AppendMessage(message, args);
625 va_end(args);
626 }
627
628 throw exception;
629}
630
631// AreNotEqual
632template <class T, class U>
634 const TCHAR* notExpectedExpressionString, const T& notExpectedExpressionValue,
635 const TCHAR* actualExpressionString, const U& actualExpressionValue,
636 const TCHAR* fileName, int lineNumber,
637 const TCHAR* message /* NULL */, ...)
638{
639 // Unfortunately if a numeric literal was passed in as one of the values
640 // and an unsigned number as the other, you'll get a signed/unsigned mismatch,
641 // as numeric literal integers always template-match to int. To get around
642 // this, postfix numeric literals with 'U' so they will match as unsigned.
643 if (notExpectedExpressionValue != actualExpressionValue) { return; }
644
645 TCHAR buffer1[MAX_EXPRESSION_STRING] = _T("");
646
647 AssertExceptionT exception;
648 exception.AppendMessage(_T("%s(%d): error : WIN_ASSERT_NOT_EQUAL failed. ¥"%s¥" and ¥"%s¥" were expected different, but were same (<%s>). "),
649 fileName,
650 lineNumber,
651 notExpectedExpressionString,
652 actualExpressionString,
653 ToString(notExpectedExpressionValue, buffer1, ARRAYSIZE(buffer1)));
654
655 if (message)
656 {
657 va_list args;
658 va_start(args, message);
659 exception.AppendMessage(message, args);
660 va_end(args);
661 }
662
663 throw exception;
664}
665
666// StringEqual
668 const wchar_t* expected, const wchar_t* actual,
669 const TCHAR* fileName, int lineNumber,
670 const TCHAR* message /* NULL */, ...)
671{
672 if (::wcscmp(expected, actual) == 0) { return; }
673
674 AssertExceptionT exception;
675 exception.AppendMessage(_T("%s(%d): error : WIN_ASSERT_STRING_EQUAL failed. "),
676 fileName, lineNumber);
677#ifdef _UNICODE
678 wchar_t* formatString = L"Expected: <¥"%s¥">; Actual: <¥"%s¥">. ";
679#else
680 char* formatString = "Expected: <¥"%S¥">; Actual: <¥"%S¥">. ";
681#endif
682 exception.AppendMessage(formatString, expected, actual);
683
684 if (message)
685 {
686 va_list args;
687 va_start(args, message);
688 exception.AppendMessage(message, args);
689 va_end(args);
690 }
691
692 throw exception;
693}
694
696 const char* expected, const char* actual,
697 const TCHAR* fileName, int lineNumber,
698 const TCHAR* message /* NULL */, ...)
699{
700 if (::strcmp(expected, actual) == 0) { return; }
701
702 AssertExceptionT exception;
703 exception.AppendMessage(_T("%s(%d): error : WIN_ASSERT_STRING_EQUAL failed. "),
704 fileName, lineNumber);
705#ifdef _UNICODE
706 wchar_t* formatString = L"Expected: <¥"%S¥">; Actual: <¥"%S¥">. ";
707#else
708 char* formatString = "Expected: <¥"%s¥">; Actual: <¥"%s¥">. ";
709#endif
710 exception.AppendMessage(formatString, expected, actual);
711
712 if (message)
713 {
714 va_list args;
715 va_start(args, message);
716 exception.AppendMessage(message, args);
717 va_end(args);
718 }
719
720 throw exception;
721}
722
723// IsZero
724template<class T>
725inline void Assert::IsZero(const TCHAR* zeroExpressionString, const T& zeroExpression,
726 const TCHAR* fileName, int lineNumber,
727 const TCHAR* message /* NULL */, ...)
728{
729 if (zeroExpression == 0) { return; }
730
731 TCHAR buffer[MAX_EXPRESSION_STRING] = _T("");
732
733 AssertExceptionT exception;
734 exception.AppendMessage(_T("%s(%d): error : WIN_ASSERT_ZERO failed: ¥"%s¥" expected to be zero, but was <%s>. "),
735 fileName, lineNumber,
736 zeroExpressionString,
737 ToString(zeroExpression, buffer, ARRAYSIZE(buffer)));
738
739 if (message)
740 {
741 va_list args;
742 va_start(args, message);
743 exception.AppendMessage(message, args);
744 va_end(args);
745 }
746
747 throw exception;
748}
749
750// IsNotZero
751template<class T>
753 const TCHAR* nonzeroExpressionString, const T& nonzeroExpression,
754 const TCHAR* fileName, int lineNumber,
755 const TCHAR* message /* NULL */, ...)
756{
757 if (nonzeroExpression != 0) { return; }
758
759 AssertExceptionT exception;
760 exception.AppendMessage(_T("%s(%d): error : WIN_ASSERT_NOT_ZERO failed: ¥"%s¥". "),
761 fileName, lineNumber,
762 nonzeroExpressionString);
763
764 if (message)
765 {
766 va_list args;
767 va_start(args, message);
768 exception.AppendMessage(message, args);
769 va_end(args);
770 }
771
772 throw exception;
773}
774
775// IsNull
776template<class T>
777inline void Assert::IsNull(const TCHAR* expressionString, T* nullExpression,
778 const TCHAR* fileName, int lineNumber,
779 const TCHAR* message /* NULL */, ...)
780{
781 if (nullExpression == NULL) { return; }
782
783 TCHAR buffer[MAX_EXPRESSION_STRING] = _T("");
784
785 AssertExceptionT exception;
786 exception.AppendMessage(_T("%s(%d): error : WIN_ASSERT_NULL failed: ¥"%s¥" expected to be NULL, but was <%s>. "),
787 fileName, lineNumber,
788 expressionString,
789 ToString(nullExpression, buffer, _countof(buffer)));
790
791 if (message)
792 {
793 va_list args;
794 va_start(args, message);
795 exception.AppendMessage(message, args);
796 va_end(args);
797 }
798
799 throw exception;
800}
801
802// IsNotNull
803template<class T>
805 const TCHAR* notNullExpressionString, T* notNullExpression,
806 const TCHAR* fileName, int lineNumber,
807 const TCHAR* message /* NULL */, ...)
808{
809 if (notNullExpression != NULL) { return; }
810
811 AssertExceptionT exception;
812 exception.AppendMessage(_T("%s(%d): error : WIN_ASSERT_NOT_NULL failed: ¥"%s¥". "),
813 fileName, lineNumber,
814 notNullExpressionString);
815
816 if (message)
817 {
818 va_list args;
819 va_start(args, message);
820 exception.AppendMessage(message, args);
821 va_end(args);
822 }
823
824 throw exception;
825}
826
827// Fail
828inline void Assert::Fail(const TCHAR* fileName, int lineNumber,
829 const TCHAR* message, ...)
830{
831 AssertExceptionT exception;
832 exception.AppendMessage(_T("%s(%d): error : WIN_ASSERT_FAIL failed. "),
833 fileName,
834 lineNumber);
835
836 va_list args;
837 va_start(args, message);
838 exception.AppendMessage(message, args);
839 va_end(args);
840
841 throw exception;
842}
843
844// IsTrue
845inline void Assert::IsTrue(
846 const TCHAR* expressionString, bool expression,
847 const TCHAR* fileName, int lineNumber,
848 const TCHAR* message, ...)
849{
850 if (expression) { return; }
851
852 AssertExceptionT exception;
853 exception.AppendMessage(_T("%s(%d): error : WIN_ASSERT_TRUE failed: ¥"%s¥". "), fileName, lineNumber, expressionString);
854
855 if (message)
856 {
857 va_list args;
858 va_start(args, message);
859 exception.AppendMessage(message, args);
860 va_end(args);
861 }
862
863 throw exception;
864}
865
866// IsFalse
867inline void Assert::IsFalse(const TCHAR* expressionString, bool falseExpression,
868 const TCHAR* fileName, int lineNumber,
869 const TCHAR* message /* NULL */, ...)
870{
871 if (!falseExpression) { return; }
872
873 AssertExceptionT exception;
874 exception.AppendMessage(_T("%s(%d): error : WIN_ASSERT_FALSE failed: ¥"%s¥". "), fileName, lineNumber, expressionString);
875
876 if (message)
877 {
878 va_list args;
879 va_start(args, message);
880 exception.AppendMessage(message, args);
881 va_end(args);
882 }
883
884 throw exception;
885}
886
887// WinapiSucceeded
889 const TCHAR* expressionString,
890 bool success,
891 const TCHAR* fileName, int lineNumber,
892 const TCHAR* message /* NULL */, ...)
893{
894 if (success) { return; }
895
896 // Get error string associated with GetLastError().
897 DWORD error = ::GetLastError();
898 TCHAR errorBuffer[MAX_SYSERROR_STRING] = _T("");
899
900 DWORD charsWritten = FormatMessage(
901 FORMAT_MESSAGE_FROM_SYSTEM,
902 NULL,
903 error,
904 MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT),
905 errorBuffer,
906 MAX_SYSERROR_STRING, NULL );
907
908 // These error strings tend to end with ¥r¥n
909 if (charsWritten > 0 &&
910 errorBuffer[charsWritten - 1] == _T('¥n') &&
911 errorBuffer[charsWritten - 2] == _T('¥r'))
912 {
913 errorBuffer[charsWritten - 2] = _T('¥0');
914 }
915
916 AssertExceptionT exception;
917 exception.AppendMessage(_T("%s(%d): error : WIN_ASSERT_WINAPI_SUCCESS failed: ¥"%s¥". (%s) "),
918 fileName, lineNumber, expressionString, errorBuffer);
919
920 if (message)
921 {
922 va_list args;
923 va_start(args, message);
924 exception.AppendMessage(message, args);
925 va_end(args);
926 }
927
928 throw exception;
929}
930
931// ThrowsException
933 const TCHAR* expressionString,
934 const TCHAR* exceptionType,
935 bool exceptionWasThrown,
936 const TCHAR* fileName, int lineNumber,
937 const TCHAR* message /* NULL */, ...)
938{
939 if (exceptionWasThrown) { return; }
940
941 AssertExceptionT exception;
942
943 exception.AppendMessage(_T("%s(%d): error : WIN_ASSERT_THROWS failed: Exception %s not thrown by ¥"%s¥". "),
944 fileName, lineNumber,
945 exceptionType, expressionString);
946
947 if (message)
948 {
949 va_list args;
950 va_start(args, message);
951 exception.AppendMessage(message, args);
952 va_end(args);
953 }
954
955 throw exception;
956}
957}
958
959#pragma endregion
960
961#pragma region AssertExceptionT implementation
962
963#ifndef EXCLUDE_FROM_DOCUMENTATION
964namespace WinUnit
965{
966template<size_t size>
968 :
969_messageLength(0),
970_cchBuffer(size)
971{
972 wmemset(_buffer, L'¥0', size);
973}
974
975template<size_t size>
976inline const wchar_t* AssertExceptionW<size>::Message()
977{
978 return _buffer;
979}
980
981template<size_t size>
982inline void AssertExceptionW<size>::AppendMessage(const wchar_t* message, ...)
983{
984 va_list args;
985 va_start(args, message);
986
987 this->AppendMessage(message, args);
988
989 va_end(args);
990}
991
992template<size_t size>
993inline void AssertExceptionW<size>::AppendMessage(const wchar_t* message, va_list args)
994{
995 if (this->AvailableBufferLength == 0) { return; }
996
997 int cchWritten = _vsnwprintf_s(
998 this->AvailableBufferStart,
999 this->AvailableBufferLength,
1000 _TRUNCATE,
1001 message,
1002 args);
1003
1004 // If _vsnwprintf_s returns -1, it means a truncation occurred. Therefore
1005 // the buffer is now completely full--so set MessageLength appropriately.
1006 // Note that it's not set to "size" since MessageLength does not include
1007 // the null terminator.
1008 if (cchWritten == -1)
1009 {
1010 this->MessageLength = size - 1;
1011 }
1012 else
1013 {
1014 this->MessageLength += cchWritten;
1015 }
1016}
1017
1018template<size_t size>
1019inline void AssertExceptionA<size>::AppendMessage(const char* message, ...)
1020{
1021 va_list args;
1022 va_start(args, message);
1023 this->AppendMessage(message, args);
1024 va_end(args);
1025}
1026
1027template<size_t size>
1028inline void AssertExceptionA<size>::AppendMessage(const char* message, va_list args)
1029{
1030 // For the ANSI versions of AppendMessage, we first print the formatted
1031 // message into an ANSI buffer, then use MultiByteToWideChar to copy it
1032 // (append it) into the wide character buffer.
1033 //
1034 // (Avoiding "min" macro for NOMINMAX compatibility.)
1035 const int bufferSize = (size < INT_MAX) ? size : INT_MAX;
1036 char bufferA[bufferSize] = "";
1037
1038 int cchWritten = ::vsnprintf_s(
1039 bufferA, bufferSize, _TRUNCATE, message, args);
1040
1041 int availableBufferLength = (int)(this->AvailableBufferLength);
1042 int bytesToWrite =
1043 ((cchWritten == -1 || cchWritten > availableBufferLength - 1) ?
1044 availableBufferLength - 1 :
1045 cchWritten);
1046
1047 int cchConverted = ::MultiByteToWideChar(CP_ACP, 0,
1048 bufferA, bytesToWrite,
1049 this->AvailableBufferStart, availableBufferLength);
1050
1051 // If it was 0, nothing was copied
1052 if (cchConverted != 0)
1053 {
1054 this->MessageLength += cchConverted;
1055 }
1056}
1057}
1058#endif // EXCLUDE_FROM_DOCUMENTATION
1059#pragma endregion
1060
1061#pragma region ToString implementation
1062
1063namespace WinUnit
1064{
1065// Objects of an unknown type are shown as [OBJECT]. If you see this
1066// in your error message and want something clearer, you can implement
1067// ToString for your type.
1068template<class T>
1069inline const TCHAR* ToString(const T& /* object */, TCHAR buffer[], size_t bufferSize)
1070{
1071 ::_sntprintf_s(buffer, bufferSize, _TRUNCATE, _T("%s"), _T("[OBJECT]"));
1072 return buffer;
1073}
1074
1075// Pointers are represented by their hex value.
1076template<class T>
1077inline const TCHAR* ToString(T* object, TCHAR buffer[], size_t bufferSize)
1078{
1079 ::_sntprintf_s(buffer, bufferSize, _TRUNCATE, _T("0x%0*p"), sizeof(void*) * 2, (void*)object);
1080 return buffer;
1081}
1082
1083// Define BOOL_NOT_DEFINED if you get a compiler error with this one.
1084#ifndef BOOL_NOT_DEFINED
1085template<>
1086inline const TCHAR* ToString(const bool& object, TCHAR buffer[], size_t bufferSize)
1087{
1088 ::_sntprintf_s(buffer, bufferSize, _TRUNCATE, _T("%s"), (object ? _T("true") : _T("false")));
1089 return buffer;
1090}
1091#endif
1092
1093template<>
1094inline const TCHAR* ToString(const signed char& object, TCHAR buffer[], size_t bufferSize)
1095{
1096 bool isPrintable = (int)object >= 0 && (int)object <= 0xFF && isprint((int)object);
1097 ::_sntprintf_s(buffer, bufferSize, _TRUNCATE, _T("'%lc' [%i]"),
1098 isPrintable ? object : '.', object);
1099 return buffer;
1100}
1101
1102template<>
1103inline const TCHAR* ToString(const unsigned char& object, TCHAR buffer[], size_t bufferSize)
1104{
1105 bool isPrintable = (int)object >= 0 && (int)object <= 0xFF && isprint((int)object);
1106 ::_sntprintf_s(buffer, bufferSize, _TRUNCATE, _T("'%lc' [0x%02X]"),
1107 isPrintable ? object : '.', object);
1108 return buffer;
1109}
1110
1111template<>
1112inline const TCHAR* ToString(const char& object, TCHAR buffer[], size_t bufferSize)
1113{
1114 bool isPrintable = (int)object >= 0 && (int)object <= 0xFF && isprint((int)object);
1115 ::_sntprintf_s(buffer, bufferSize, _TRUNCATE, _T("'%lc' [%i]"),
1116 isPrintable ? object : '.', object);
1117 return buffer;
1118}
1119
1120#ifdef _NATIVE_WCHAR_T_DEFINED
1121template<>
1122inline const TCHAR* ToString(const wchar_t& object, TCHAR buffer[], size_t bufferSize)
1123{
1124 ::_sntprintf_s(buffer, bufferSize, _TRUNCATE, _T("'%wc' [0x%04X]"),
1125 iswprint(object) ? object : L'.', object);
1126 return buffer;
1127}
1128#endif
1129
1130template<>
1131inline const TCHAR* ToString(const __int16& object, TCHAR buffer[], size_t bufferSize)
1132{
1133 ::_sntprintf_s(buffer, bufferSize, _TRUNCATE, _T("%ld"), object);
1134 return buffer;
1135}
1136
1137template<>
1138inline const TCHAR* ToString(const unsigned __int16& object, TCHAR buffer[], size_t bufferSize)
1139{
1140 ::_sntprintf_s(buffer, bufferSize, _TRUNCATE, _T("%lu [0x%04lX]"), object, object);
1141 return buffer;
1142}
1143
1144template<>
1145inline const TCHAR* ToString(const __int32& object, TCHAR buffer[], size_t bufferSize)
1146{
1147 ::_sntprintf_s(buffer, bufferSize, _TRUNCATE, _T("%d"), object);
1148 return buffer;
1149}
1150
1151template<>
1152inline const TCHAR* ToString(const unsigned __int32& object, TCHAR buffer[], size_t bufferSize)
1153{
1154 ::_sntprintf_s(buffer, bufferSize, _TRUNCATE, _T("%u [0x%08X]"), object, object);
1155 return buffer;
1156}
1157
1158template<>
1159inline const TCHAR* ToString(const long& object, TCHAR buffer[], size_t bufferSize)
1160{
1161 ::_sntprintf_s(buffer, bufferSize, _TRUNCATE, _T("%d"), object);
1162 return buffer;
1163}
1164
1165template<>
1166inline const TCHAR* ToString(const unsigned long& object, TCHAR buffer[], size_t bufferSize)
1167{
1168 ::_sntprintf_s(buffer, bufferSize, _TRUNCATE, _T("%u [0x%0*X]"), object, sizeof(object) * 2, object);
1169 return buffer;
1170}
1171
1172template<>
1173inline const TCHAR* ToString(const __int64& object, TCHAR buffer[], size_t bufferSize)
1174{
1175 ::_sntprintf_s(buffer, bufferSize, _TRUNCATE, _T("%I64i"), object);
1176 return buffer;
1177}
1178
1179template<>
1180inline const TCHAR* ToString(const unsigned __int64& object, TCHAR buffer[], size_t bufferSize)
1181{
1182 ::_sntprintf_s(buffer, bufferSize, _TRUNCATE, _T("%I64u [0x%0*I64X]"), object, sizeof(object) * 2, object);
1183 return buffer;
1184}
1185
1186template<>
1187inline const TCHAR* ToString(const float& object, TCHAR buffer[], size_t bufferSize)
1188{
1189 ::_sntprintf_s(buffer, bufferSize, _TRUNCATE, _T("%G"), object);
1190 return buffer;
1191}
1192
1193template<>
1194inline const TCHAR* ToString(const double& object, TCHAR buffer[], size_t bufferSize)
1195{
1196 ::_sntprintf_s(buffer, bufferSize, _TRUNCATE, _T("%G"), object);
1197 return buffer;
1198}
1199
1200template<>
1201inline const TCHAR* ToString(const long double& object, TCHAR buffer[], size_t bufferSize)
1202{
1203 ::_sntprintf_s(buffer, bufferSize, _TRUNCATE, _T("%G"), object);
1204 return buffer;
1205}
1206
1207}
1208#pragma endregion
1209
1210#pragma region Trace
1211
1214
1223#define WIN_TRACE(x, ...) WinUnit::Trace(x, __VA_ARGS__)
1224
1226
1227namespace WinUnit
1228{
1229 void Trace(const wchar_t* formatString, ...);
1230 void Trace(const char* formatString, ...);
1231
1233 inline void Trace(const wchar_t* formatString, ...)
1234 {
1235 wchar_t buffer[MAX_TRACE_MESSAGE_LENGTH] = L"";
1236 va_list args;
1237 va_start(args, formatString);
1238
1239 ::_vsnwprintf_s(buffer, _countof(buffer), _TRUNCATE,
1240 formatString, args);
1241
1242 va_end(args);
1243 OutputDebugStringW(buffer);
1244 }
1245
1247 inline void Trace(const char* formatString, ...)
1248 {
1249 char buffer[MAX_TRACE_MESSAGE_LENGTH] = "";
1250 va_list args;
1251 va_start(args, formatString);
1252
1253 _vsnprintf_s(buffer, _countof(buffer), _TRUNCATE,
1254 formatString, args);
1255
1256 va_end(args);
1257 OutputDebugStringA(buffer);
1258 }
1259}
1260
1261#pragma endregion
1262
1263#pragma region Environment
1264
1265namespace WinUnit
1266{
1270 {
1271 public:
1272 static bool GetVariable(const TCHAR* variableName,
1273 TCHAR buffer[], DWORD bufferSize,
1274 DWORD* pSizeNeeded = NULL);
1275 private:
1277 };
1278
1282 const TCHAR* variableName,
1283 TCHAR buffer[],
1284 DWORD bufferSize,
1285 DWORD* pSizeNeeded /* NULL */ )
1287 {
1288 DWORD charCount = GetEnvironmentVariable(variableName, buffer, bufferSize);
1289 if (pSizeNeeded != NULL)
1290 {
1291 *pSizeNeeded = charCount;
1292 }
1293 return (charCount > 0 && charCount < bufferSize);
1294 }
1295}
1296
1297#pragma endregion
#define TSTRING(x)
Definition WinUnit.h:212
#define AssertExceptionT
Definition WinUnit.h:424
#define MAX_SYSERROR_STRING
Definition WinUnit.h:112
#define MAX_TRACE_MESSAGE_LENGTH
Definition WinUnit.h:103
#define __WFILE__
Definition WinUnit.h:195
#define MAX_EXPRESSION_STRING
Definition WinUnit.h:107
#define EMIT_ERROR(...)
Definition WinUnit.h:114
#define __TFILE__
Definition WinUnit.h:213
Definition WinUnit.h:482
AssertExceptionA & operator=(AssertExceptionA &)
void AppendMessage(const char *message,...)
Definition WinUnit.h:1019
Definition WinUnit.h:438
wchar_t _buffer[size]
Definition WinUnit.h:442
wchar_t * GetAvailableBufferStart()
Definition WinUnit.h:460
AssertExceptionW & operator=(AssertExceptionW &)
__declspec(property(get=GetAvailableBufferStart)) wchar_t *AvailableBufferStart
size_t GetAvailableBufferLength()
Definition WinUnit.h:466
void AppendMessage(const wchar_t *message, va_list args)
Definition WinUnit.h:993
void AppendMessage(const wchar_t *message,...)
Definition WinUnit.h:982
virtual const wchar_t * Message()
Returns the message associated with this exception.
Definition WinUnit.h:976
size_t _messageLength
Definition WinUnit.h:440
__declspec(property(get=GetMessageLength, put=SetMessageLength)) size_t MessageLength
size_t GetMessageLength()
Definition WinUnit.h:472
__declspec(property(get=GetAvailableBufferLength)) size_t AvailableBufferLength
void SetMessageLength(size_t messageLength)
Definition WinUnit.h:473
AssertExceptionW()
Definition WinUnit.h:967
const size_t _cchBuffer
Definition WinUnit.h:441
Definition WinUnit.h:410
virtual ‾AssertException()=0
Definition WinUnit.h:415
virtual const wchar_t * Message()=0
Returns the message associated with this exception.
Definition WinUnit.h:503
static void AreNotEqual(const TCHAR *notExpectedExpressionString, const T &notExpectedExpressionValue, const TCHAR *actualExpressionString, const U &actualExpressionValue, const TCHAR *fileName, int lineNumber, const TCHAR *message=NULL,...)
Definition WinUnit.h:633
static void StringEqual(const wchar_t *expected, const wchar_t *actual, const TCHAR *fileName, int lineNumber, const TCHAR *message=NULL,...)
Definition WinUnit.h:667
static void IsFalse(const TCHAR *expressionString, bool falseExpression, const TCHAR *fileName, int lineNumber, const TCHAR *message=NULL,...)
Definition WinUnit.h:867
static void IsNull(const TCHAR *expressionString, T *nullExpression, const TCHAR *fileName, int lineNumber, const TCHAR *message=NULL,...)
Definition WinUnit.h:777
static void WinapiSucceeded(const TCHAR *expressionString, bool success, const TCHAR *fileName, int lineNumber, const TCHAR *message=NULL,...)
Definition WinUnit.h:888
static void AreEqual(const TCHAR *expectedExpressionString, const T &expectedExpressionValue, const TCHAR *actualExpressionString, const U &actualExpressionValue, const TCHAR *fileName, int lineNumber, const TCHAR *message=NULL,...)
Definition WinUnit.h:596
static void ThrowsException(const TCHAR *expressionString, const TCHAR *exceptionType, bool exceptionWasThrown, const TCHAR *fileName, int lineNumber, const TCHAR *message=NULL,...)
Definition WinUnit.h:932
static void IsNotNull(const TCHAR *notNullExpressionString, T *notNullExpression, const TCHAR *fileName, int lineNumber, const TCHAR *message=NULL,...)
Definition WinUnit.h:804
static void IsTrue(const TCHAR *expressionString, bool trueExpression, const TCHAR *fileName, int lineNumber, const TCHAR *message=NULL,...)
Definition WinUnit.h:845
static void Fail(const TCHAR *fileName, int lineNumber, const TCHAR *message=NULL,...)
Definition WinUnit.h:828
static void IsZero(const TCHAR *zeroExpressionString, const T &zeroExpression, const TCHAR *fileName, int lineNumber, const TCHAR *message=NULL,...)
Definition WinUnit.h:725
static void IsNotZero(const TCHAR *nonzeroExpressionString, const T &nonzeroExpression, const TCHAR *fileName, int lineNumber, const TCHAR *message=NULL,...)
Definition WinUnit.h:752
Definition WinUnit.h:1270
static bool GetVariable(const TCHAR *variableName, TCHAR buffer[], DWORD bufferSize, DWORD *pSizeNeeded=NULL)
Definition WinUnit.h:1281
Definition WinUnit.h:351
¥ void Setup()
¥ void Teardown()
Definition WinUnit.h:176
void Trace(const wchar_t *formatString,...)
Wide-character version of function called by WIN_TRACE macro.
Definition WinUnit.h:1233
const TCHAR * ToString(const T &object, TCHAR buffer[], size_t bufferSize)
Size of buffer in TCHARs
Definition WinUnit.h:1069