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  } ¥
134  catch(WinUnit::AssertException& e) ¥
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 
175 namespace 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) ¥
350 class FIXTURE_##x ¥
351 { ¥
352 public: ¥
353  void Setup(); ¥
354  void Teardown(); ¥
355 public: ¥
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 
386 namespace 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.)
430 namespace 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.
458  __declspec(property(get=GetAvailableBufferStart))
459  wchar_t* AvailableBufferStart;
460  wchar_t* GetAvailableBufferStart() { return _buffer + _messageLength; }
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.
464  __declspec(property(get=GetAvailableBufferLength))
465  size_t AvailableBufferLength;
466  size_t GetAvailableBufferLength() { return _cchBuffer - _messageLength; }
467 
468  // This property encapsulates the _messageLength member, for symmetry
469  // with the other properties.
470  __declspec(property(get=GetMessageLength, put=SetMessageLength))
471  size_t MessageLength;
472  size_t GetMessageLength() { return _messageLength; }
473  void SetMessageLength(size_t messageLength) { _messageLength = messageLength; }
474 
475  private:
476  AssertExceptionW& operator=(AssertExceptionW&);
477  };
478 
479  // This one extends AssertExceptionW to deal with ANSI strings.
480  template<size_t size=MAX_ASSERT_MESSAGE_LENGTH>
481  class AssertExceptionA : public AssertExceptionW<size>
482  {
483  public:
484  void AppendMessage(const char* message, ...);
485  void AppendMessage(const char* message, va_list args);
486  private:
487  AssertExceptionA& operator=(AssertExceptionA&);
488  };
489 }
490 #endif // EXCLUDE_FROM_DOCUMENTATION
491 
492 #pragma endregion
493 
494 #pragma region Assert class definition
495 
496 namespace 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:
585  ‾Assert();
586  };
587 }
588 #pragma endregion
589 
590 #pragma region Assert implementation
591 
592 namespace WinUnit
593 {
594 // AreEqual
595 template <class T, class U>
596 inline void Assert::AreEqual(
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 
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
632 template <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 
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 
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 
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
724 template<class T>
725 inline 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 
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
751 template<class T>
752 inline void Assert::IsNotZero(
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 
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
776 template<class T>
777 inline 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 
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
803 template<class T>
804 inline void Assert::IsNotNull(
805  const TCHAR* notNullExpressionString, T* notNullExpression,
806  const TCHAR* fileName, int lineNumber,
807  const TCHAR* message /* NULL */, ...)
808 {
809  if (notNullExpression != NULL) { return; }
810 
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
828 inline void Assert::Fail(const TCHAR* fileName, int lineNumber,
829  const TCHAR* message, ...)
830 {
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
845 inline 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 
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
867 inline 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 
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 
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 
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
964 namespace WinUnit
965 {
966 template<size_t size>
968  :
969 _messageLength(0),
970 _cchBuffer(size)
971 {
972  wmemset(_buffer, L'¥0', size);
973 }
974 
975 template<size_t size>
976 inline const wchar_t* AssertExceptionW<size>::Message()
977 {
978  return _buffer;
979 }
980 
981 template<size_t size>
982 inline 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 
992 template<size_t size>
993 inline 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 
1018 template<size_t size>
1019 inline 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 
1027 template<size_t size>
1028 inline 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 
1063 namespace 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.
1068 template<class T>
1069 inline 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.
1076 template<class T>
1077 inline 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
1085 template<>
1086 inline 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 
1093 template<>
1094 inline 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 
1102 template<>
1103 inline 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 
1111 template<>
1112 inline 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
1121 template<>
1122 inline 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 
1130 template<>
1131 inline 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 
1137 template<>
1138 inline 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 
1144 template<>
1145 inline 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 
1151 template<>
1152 inline 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 
1158 template<>
1159 inline 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 
1165 template<>
1166 inline 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 
1172 template<>
1173 inline 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 
1179 template<>
1180 inline 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 
1186 template<>
1187 inline 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 
1193 template<>
1194 inline 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 
1200 template<>
1201 inline 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 
1227 namespace 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 
1265 namespace WinUnit
1266 {
1270  {
1271  public:
1272  static bool GetVariable(const TCHAR* variableName,
1273  TCHAR buffer[], DWORD bufferSize,
1274  DWORD* pSizeNeeded = NULL);
1275  private:
1276  Environment();
1277  };
1278 
1282  const TCHAR* variableName,
1283  TCHAR buffer[],
1284  DWORD bufferSize,
1285  DWORD* pSizeNeeded /* NULL */ )
1286  {
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
Definition: WinUnit.h:409
#define EMIT_ERROR(...)
Definition: WinUnit.h:114
void SetMessageLength(size_t messageLength)
Definition: WinUnit.h:473
Definition: WinUnit.h:175
void AppendMessage(const char *message,...)
Definition: WinUnit.h:1019
#define TSTRING(x)
Definition: WinUnit.h:212
Definition: WinUnit.h:437
#define MAX_SYSERROR_STRING
Definition: WinUnit.h:112
static void IsZero(const TCHAR *zeroExpressionString, const T &zeroExpression, const TCHAR *fileName, int lineNumber, const TCHAR *message=NULL,...)
Definition: WinUnit.h:725
const TCHAR * ToString(const T &object, TCHAR buffer[], size_t bufferSize)
Size of buffer in TCHARs.
Definition: WinUnit.h:1069
void AppendMessage(const wchar_t *message,...)
Definition: WinUnit.h:982
static void IsTrue(const TCHAR *expressionString, bool trueExpression, const TCHAR *fileName, int lineNumber, const TCHAR *message=NULL,...)
Definition: WinUnit.h:845
size_t GetAvailableBufferLength()
Definition: WinUnit.h:466
Definition: WinUnit.h:1269
const size_t _cchBuffer
Definition: WinUnit.h:441
static bool GetVariable(const TCHAR *variableName, TCHAR buffer[], DWORD bufferSize, DWORD *pSizeNeeded=NULL)
Definition: WinUnit.h:1281
static void IsFalse(const TCHAR *expressionString, bool falseExpression, const TCHAR *fileName, int lineNumber, const TCHAR *message=NULL,...)
Definition: WinUnit.h:867
#define __TFILE__
Definition: WinUnit.h:213
static void Fail(const TCHAR *fileName, int lineNumber, const TCHAR *message=NULL,...)
Definition: WinUnit.h:828
static void StringEqual(const wchar_t *expected, const wchar_t *actual, const TCHAR *fileName, int lineNumber, const TCHAR *message=NULL,...)
Definition: WinUnit.h:667
Definition: WinUnit.h:481
#define AssertExceptionT
Definition: WinUnit.h:424
wchar_t _buffer[size]
Definition: WinUnit.h:442
virtual const wchar_t * Message()=0
Returns the message associated with this exception.
size_t _messageLength
Definition: WinUnit.h:440
#define MAX_TRACE_MESSAGE_LENGTH
Definition: WinUnit.h:103
virtual ‾AssertException()=0
Definition: WinUnit.h:415
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
void Trace(const wchar_t *formatString,...)
Wide-character version of function called by WIN_TRACE macro.
Definition: WinUnit.h:1233
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:350
static void ThrowsException(const TCHAR *expressionString, const TCHAR *exceptionType, bool exceptionWasThrown, const TCHAR *fileName, int lineNumber, const TCHAR *message=NULL,...)
Definition: WinUnit.h:932
#define MAX_EXPRESSION_STRING
Definition: WinUnit.h:107
AssertExceptionW()
Definition: WinUnit.h:967
static void IsNotNull(const TCHAR *notNullExpressionString, T *notNullExpression, const TCHAR *fileName, int lineNumber, const TCHAR *message=NULL,...)
Definition: WinUnit.h:804
Definition: WinUnit.h:502
static void WinapiSucceeded(const TCHAR *expressionString, bool success, const TCHAR *fileName, int lineNumber, const TCHAR *message=NULL,...)
Definition: WinUnit.h:888
size_t GetMessageLength()
Definition: WinUnit.h:472
if the work is an executable linked with the with the complete machine readable work that uses the as object code and or source so that the user can modify the Library and then relink to produce a modified executable containing the modified rather than copying library functions into the if the user installs as long as the modified version is interface compatible with the version that the work was made with c Accompany the work with a written valid for at least three to give the same user the materials specified in for a charge no more than the cost of performing this distribution d If distribution of the work is made by offering access to copy from a designated offer equivalent access to copy the above specified materials from the same place e Verify that the user has already received a copy of these materials or that you have already sent this user a copy For an the required form of the work that uses the Library must include any data and utility programs needed for reproducing the executable from it as a special exception
Definition: copying.txt:303
virtual const wchar_t * Message()
Returns the message associated with this exception.
Definition: WinUnit.h:976
static void IsNull(const TCHAR *expressionString, T *nullExpression, const TCHAR *fileName, int lineNumber, const TCHAR *message=NULL,...)
Definition: WinUnit.h:777
#define __WFILE__
Definition: WinUnit.h:195
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