From f53440fe66b36741cd85c6040f20ecadefc0719a Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?D=C4=81vis=20Mos=C4=81ns?= <davispuh@gmail.com>
Date: Sat, 17 Sep 2016 03:37:53 +0300
Subject: [PATCH] ConsoleBuf: Improve test error messages

Print more information about each failure.

Change-Id: I9c9a0ad628fba6452894eb80251e6fa2bdf1a87f
---
 testConsoleBuf.cxx | 114 ++++++++++++++++++++++++++++++---------------
 1 file changed, 77 insertions(+), 37 deletions(-)

diff --git a/testConsoleBuf.cxx b/testConsoleBuf.cxx
index 3dec097..6c79d89 100644
--- a/testConsoleBuf.cxx
+++ b/testConsoleBuf.cxx
@@ -48,6 +48,25 @@ static HANDLE syncEvent;
 static std::string encodedInputTestString;
 static std::string encodedTestString;
 
+static void displayError(DWORD errorCode) {
+  std::cerr.setf(std::ios::hex, std::ios::basefield);
+  std::cerr << "Failed with error: 0x" << errorCode << "!" << std::endl;
+  LPWSTR message;
+  if (FormatMessageW(FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM,
+                     NULL,
+                     errorCode,
+                     0,
+                     (LPWSTR)&message, 0,
+                     NULL)
+  ) {
+    std::cerr << "Error message: " << kwsys::Encoding::ToNarrow(message) << std::endl;
+    HeapFree(GetProcessHeap(), 0, message);
+  } else {
+    std::cerr << "FormatMessage() failed with error: 0x" << GetLastError() << "!" << std::endl;
+  }
+  std::cerr.unsetf(std::ios::hex);
+}
+
 //----------------------------------------------------------------------------
 static bool createProcess(HANDLE hIn, HANDLE hOut, HANDLE hErr)
 {
@@ -89,23 +108,8 @@ static bool createProcess(HANDLE hIn, HANDLE hOut, HANDLE hErr)
                                 &processInfo) != 0; // Pointer to PROCESS_INFORMATION structure
   if (!success) {
     DWORD lastError = GetLastError();
-    std::cerr.setf(std::ios::hex, std::ios::basefield);
-    std::cerr << "CreateProcess(" << kwsys::Encoding::ToNarrow(cmd)
-              << ") failed with error: 0x" << lastError << "!" << std::endl;
-    LPWSTR message;
-    if (FormatMessageW(FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM,
-                       NULL,
-                       lastError,
-                       0,
-                       (LPWSTR)&message, 0,
-                       NULL)
-    ) {
-      std::cerr << "Error message: " << kwsys::Encoding::ToNarrow(message) << std::endl;
-      HeapFree(GetProcessHeap(), 0, message);
-    } else {
-      std::cerr << "FormatMessage() failed with error: 0x" << GetLastError() << "!" << std::endl;
-    }
-    std::cerr.unsetf(std::ios::hex);
+    std::cerr << "CreateProcess(" << kwsys::Encoding::ToNarrow(cmd) << ")" << std::endl;
+    displayError(lastError);
   }
   return success;
 }
@@ -162,8 +166,9 @@ static HANDLE createFile(LPCWSTR fileName)
                             FILE_ATTRIBUTE_TEMPORARY | FILE_FLAG_DELETE_ON_CLOSE,
                             NULL);                // no template
   if (file == INVALID_HANDLE_VALUE) {
-    std::cerr << "CreateFile(" << kwsys::Encoding::ToNarrow(fileName)
-              << ") failed!" << std::endl;
+    DWORD lastError = GetLastError();
+    std::cerr << "CreateFile(" << kwsys::Encoding::ToNarrow(fileName) << ")" << std::endl;
+    displayError(lastError);
   }
   return file;
 }
@@ -255,19 +260,23 @@ static int testPipe()
     if (createProcess(inPipeRead, outPipeWrite, errPipeWrite)) {
       try {
         Sleep(100);
-        if (WaitForSingleObject(syncEvent, waitTimeout) != WAIT_OBJECT_0) {
+        DWORD status;
+        if ((status = WaitForSingleObject(syncEvent, waitTimeout)) != WAIT_OBJECT_0) {
+          std::cerr.setf(std::ios::hex, std::ios::basefield);
+          std::cerr << "WaitForSingleObject returned unexpected status 0x" << status << std::endl;
+          std::cerr.unsetf(std::ios::hex);
           throw std::runtime_error("WaitForSingleObject failed!");
         }
         DWORD bytesRead = 0;
         if (!ReadFile(outPipeRead, buffer, sizeof(buffer), &bytesRead, NULL)
             || bytesRead == 0) {
-          throw std::runtime_error("ReadFile failed!");
+          throw std::runtime_error("ReadFile#1 failed!");
         }
         if ((bytesRead < encodedTestString.size() + 1 + encodedInputTestString.size()
              && !ReadFile(outPipeRead, buffer + bytesRead,
                           sizeof(buffer) - bytesRead, &bytesRead, NULL))
             || bytesRead == 0) {
-          throw std::runtime_error("ReadFile failed!");
+          throw std::runtime_error("ReadFile#2 failed!");
         }
         if (memcmp(buffer, encodedTestString.c_str(),
                    encodedTestString.size()) == 0 &&
@@ -277,7 +286,7 @@ static int testPipe()
           bytesRead = 0;
           if (!ReadFile(errPipeRead, buffer, sizeof(buffer), &bytesRead, NULL)
               || bytesRead == 0) {
-            throw std::runtime_error("ReadFile failed!");
+            throw std::runtime_error("ReadFile#3 failed!");
           }
           buffer[bytesRead - 1] = 0;
           didFail = encodedTestString.compare(buffer) == 0 ? 0 : 1;
@@ -286,12 +295,16 @@ static int testPipe()
           std::cerr << "Pipe's output didn't match expected output!" << std::endl << std::flush;
         }
       } catch (const std::runtime_error &ex) {
-        std::cerr << ex.what() << std::endl << std::flush;
+        DWORD lastError = GetLastError();
+        std::cerr << "In function " << __FUNCTION__ << ":" << ex.what() << std::endl << std::flush;
+        displayError(lastError);
       }
       finishProcess(didFail == 0);
     }
   } catch (const std::runtime_error &ex) {
-    std::cerr << ex.what() << std::endl << std::flush;
+    DWORD lastError = GetLastError();
+    std::cerr << "In function " << __FUNCTION__ << ":" << ex.what() << std::endl << std::flush;
+    displayError(lastError);
   }
   finishPipe(inPipeRead, inPipeWrite);
   finishPipe(outPipeRead, outPipeWrite);
@@ -335,16 +348,20 @@ static int testFile()
       DWORD bytesRead = 0;
       try {
         Sleep(100);
-        if (WaitForSingleObject(syncEvent, waitTimeout) != WAIT_OBJECT_0) {
+        DWORD status;
+        if ((status = WaitForSingleObject(syncEvent, waitTimeout)) != WAIT_OBJECT_0) {
+          std::cerr.setf(std::ios::hex, std::ios::basefield);
+          std::cerr << "WaitForSingleObject returned unexpected status 0x" << status << std::endl;
+          std::cerr.unsetf(std::ios::hex);
           throw std::runtime_error("WaitForSingleObject failed!");
         }
         if (SetFilePointer(outFile, 0, 0, FILE_BEGIN)
             == INVALID_SET_FILE_POINTER) {
-          throw std::runtime_error("SetFilePointer failed!");
+          throw std::runtime_error("SetFilePointer#1 failed!");
         }
         if (!ReadFile(outFile, buffer, sizeof(buffer), &bytesRead, NULL)
             || bytesRead == 0) {
-          throw std::runtime_error("ReadFile failed!");
+          throw std::runtime_error("ReadFile#1 failed!");
         }
         buffer[bytesRead - 1] = 0;
         if (memcmp(buffer, encodedTestString.c_str(),
@@ -355,11 +372,11 @@ static int testFile()
           bytesRead = 0;
           if (SetFilePointer(errFile, 0, 0, FILE_BEGIN)
               == INVALID_SET_FILE_POINTER) {
-            throw std::runtime_error("SetFilePointer failed!");
+            throw std::runtime_error("SetFilePointer#2 failed!");
           }
           if (!ReadFile(errFile, buffer, sizeof(buffer), &bytesRead, NULL)
               || bytesRead == 0) {
-            throw std::runtime_error("ReadFile failed!");
+            throw std::runtime_error("ReadFile#2 failed!");
           }
           buffer[bytesRead - 1] = 0;
           didFail = encodedTestString.compare(buffer) == 0 ? 0 : 1;
@@ -368,12 +385,16 @@ static int testFile()
           std::cerr << "File's output didn't match expected output!" << std::endl << std::flush;
         }
       } catch (const std::runtime_error &ex) {
-        std::cerr << ex.what() << std::endl << std::flush;
+        DWORD lastError = GetLastError();
+        std::cerr << "In function " << __FUNCTION__ << ":" << ex.what() << std::endl << std::flush;
+        displayError(lastError);
       }
       finishProcess(didFail == 0);
     }
   } catch (const std::runtime_error &ex) {
-    std::cerr << ex.what() << std::endl << std::flush;
+    DWORD lastError = GetLastError();
+    std::cerr << "In function " << __FUNCTION__ << ":" << ex.what() << std::endl << std::flush;
+    displayError(lastError);
   }
   finishFile(inFile);
   finishFile(outFile);
@@ -462,7 +483,17 @@ static int testConsole()
     hIn  = CreateFileW(L"CONIN$", GENERIC_READ | GENERIC_WRITE, 0,
                        &securityAttributes, OPEN_EXISTING, 0, NULL);
     hOut = CreateFileW(L"CONOUT$", GENERIC_READ | GENERIC_WRITE, 0,
+    if (hIn == INVALID_HANDLE_VALUE) {
+      DWORD lastError = GetLastError();
+      std::cerr << "CreateFile(CONIN$)" << std::endl;
+      displayError(lastError);
+    }
                        &securityAttributes, OPEN_EXISTING, 0, NULL);
+    if (hOut == INVALID_HANDLE_VALUE) {
+      DWORD lastError = GetLastError();
+      std::cerr << "CreateFile(CONOUT$)" << std::endl;
+      displayError(lastError);
+    }
     SetStdHandle(STD_INPUT_HANDLE, hIn);
     SetStdHandle(STD_OUTPUT_HANDLE, hOut);
     SetStdHandle(STD_ERROR_HANDLE, hOut);
@@ -508,8 +539,12 @@ static int testConsole()
 
   if (createProcess(NULL, NULL, NULL)) {
     try {
-      if (WaitForSingleObject(syncEvent, waitTimeout) != WAIT_OBJECT_0) {
-        throw std::runtime_error("WaitForSingleObject failed!");
+      DWORD status;
+      if ((status = WaitForSingleObject(syncEvent, waitTimeout)) != WAIT_OBJECT_0) {
+        std::cerr.setf(std::ios::hex, std::ios::basefield);
+        std::cerr << "WaitForSingleObject returned unexpected status 0x" << status << std::endl;
+        std::cerr.unsetf(std::ios::hex);
+        throw std::runtime_error("WaitForSingleObject#1 failed!");
       }
       INPUT_RECORD inputBuffer[(sizeof(UnicodeInputTestString) /
                                 sizeof(UnicodeInputTestString[0])) * 2];
@@ -526,8 +561,11 @@ static int testConsole()
                               &eventsWritten) || eventsWritten == 0) {
         throw std::runtime_error("WriteConsoleInput failed!");
       }
-      if (WaitForSingleObject(syncEvent, waitTimeout) != WAIT_OBJECT_0) {
-        throw std::runtime_error("WaitForSingleObject failed!");
+      if ((status = WaitForSingleObject(syncEvent, waitTimeout)) != WAIT_OBJECT_0) {
+        std::cerr.setf(std::ios::hex, std::ios::basefield);
+        std::cerr << "WaitForSingleObject returned unexpected status 0x" << status << std::endl;
+        std::cerr.unsetf(std::ios::hex);
+        throw std::runtime_error("WaitForSingleObject#2 failed!");
       }
       CONSOLE_SCREEN_BUFFER_INFO screenBufferInfo;
       if (!GetConsoleScreenBufferInfo(hOut, &screenBufferInfo)) {
@@ -562,7 +600,9 @@ static int testConsole()
       }
       delete[] outputBuffer;
     } catch (const std::runtime_error &ex) {
-      std::cerr << ex.what() << std::endl << std::flush;
+      DWORD lastError = GetLastError();
+      std::cerr << "In function " << __FUNCTION__ << ":" << ex.what() << std::endl << std::flush;
+      displayError(lastError);
     }
     finishProcess(didFail == 0);
   }
-- 
GitLab