NUnit does not write std :: cerr output

I have a nunit test in C # that calls the C # wrapper for a function in a C ++ DLL. C ++ code uses std :: cerr to output various messages.

These messages cannot be redirected using the nunit-console / out / err or / xml switch. In nunit (GUI version), the output does not appear anywhere.

I would like to see this output in nunit (GUI version). Ideally, I would like to have access to this conclusion in a test.

Thanks for any help.

+4
source share
2 answers

Redirecting std :: cerr is a matter of replacing the stream buffer with your own. Before we exit, it is important to restore the original buffer. I don't know what your wrapper looks like, but you can probably figure out how to get it to read output.str ().

#include <iostream> #include <sstream> #include <cassert> using namespace std; int main() { streambuf* buf(cerr.rdbuf()); stringstream output; cerr.rdbuf(output.rdbuf()); cerr << "Hello, world!" << endl; assert(output.str() == "Hello, world!\n"); cerr.rdbuf(buf); return 0; } 
+1
source

Thanks for the tip. This is what I ended up with:

.CPP file ------------------------

 #include <iostream> #include <sstream> static std::stringstream buffer; static std::streambuf * savedBuffer = NULL; extern "C" __declspec(dllexport) bool Redirect() { if (savedBuffer) { return false; } std::streambuf * buf(std::cerr.rdbuf()); std::cerr.rdbuf(buffer.rdbuf()); // This two lines are for illustration purposes only! std::cerr << "Hello world" << std::endl; return true; } extern "C" __declspec(dllexport) void Revert() { if (savedBuffer) { std::cerr.rdbuf(savedBuffer); } savedBuffer = NULL; } extern "C" __declspec(dllexport) const char * getCerr() { return _strdup(buffer.str().c_str()); } extern "C" __declspec(dllexport) void freeCharPtr(char *ptr) { free(ptr); } 

.CS file ------------------------------------------

 public static class Redirector { // PRIVATE ------------------------------------------------------------ private const String LibraryName = "MyCpp.dll"; [DllImport(LibraryName, CharSet = CharSet.Ansi)] private static extern IntPtr getCerr(); // PUBLIC ------------------------------------------------------------- [DllImport(LibraryName, CharSet = CharSet.Ansi)] public static extern bool Redirect(); [DllImport(LibraryName, CharSet = CharSet.Ansi)] public static extern void Revert(); [DllImport(LibraryName, CharSet = CharSet.Ansi)] internal static extern void freeCharPtr(IntPtr ptr); public static string GetCerr() { IntPtr temp = getCerr(); string result = System.Runtime.InteropServices.Marshal.PtrToStringAnsi(temp); freeCharPtr(temp); return result; } } 

NUnit Test -----------------------

  [Test] // [Ignore] public void TestRedirect() { Redirector.Redirect(); // Call more functions that output to std::cerr here. Redirector.Revert(); System.Console.WriteLine(Redirector.GetCerr()); } 

The freeCharPtr () file is needed to free allocated memory from _strdup (), since I could not work (if it was possible) how to marshal std :: string.

Note. It is not safe for threads!

+1
source

Source: https://habr.com/ru/post/1305068/


All Articles