From bfc1cdf8f8541d8ef8c4ff88382d3d28eae815a7 Mon Sep 17 00:00:00 2001 From: Manuel Gunther <siebenkopf@googlemail.com> Date: Wed, 19 Oct 2016 18:42:54 -0600 Subject: [PATCH] Moved the cxx_disable test case to C++ (did not get it to work with Python3 otherwise) --- bob/core/test.cpp | 68 ++++++++++++++++++-------- bob/core/test_logging.py | 100 +-------------------------------------- 2 files changed, 50 insertions(+), 118 deletions(-) diff --git a/bob/core/test.cpp b/bob/core/test.cpp index 6554760..ed6cd4d 100644 --- a/bob/core/test.cpp +++ b/bob/core/test.cpp @@ -206,7 +206,8 @@ static auto _output_disable_doc = bob::extension::FunctionDoc( "_test_output_disable", "Writes C++ messages with and without being visible" ) -.add_prototype("") +.add_prototype("", "success") +.add_return("success", "bool", "The success of the test") ; PyObject* output_disable(PyObject*, PyObject* args, PyObject* kwds) { BOB_TRY @@ -214,27 +215,56 @@ BOB_TRY if (!PyArg_ParseTupleAndKeywords(args, kwds, "", kwlist)) return 0; - bob::core::log_level(bob::core::DEBUG); - bob::core::debug << "This is a debug message" << std::endl; - bob::core::info << "This is an info message" << std::endl; - bob::core::warn << "This is a warning message" << std::endl; - bob::core::error << "This is an error message" << std::endl; - - bob::core::log_level(bob::core::ERROR); - bob::core::debug << "This is a debug message" << std::endl; - bob::core::info << "This is an info message" << std::endl; - bob::core::warn << "This is a warning message" << std::endl; - bob::core::error << "This is an error message" << std::endl; - - bob::core::log_level(bob::core::DISABLE); - bob::core::debug << "This is a debug message" << std::endl; - bob::core::info << "This is an info message" << std::endl; - bob::core::warn << "This is a warning message" << std::endl; - bob::core::error << "This is an error message" << std::endl; + // redirect std::cout and std::cerr, see http://stackoverflow.com/a/5419388/3301902 + std::stringstream out, err; + std::streambuf * oldout = std::cout.rdbuf(out.rdbuf()); + std::streambuf * olderr = std::cerr.rdbuf(err.rdbuf()); + + bool success = true; + + try { + bob::core::log_level(bob::core::DEBUG); + bob::core::debug << "This is a debug message" << std::endl; + bob::core::info << "This is an info message" << std::endl; + bob::core::warn << "This is a warning message" << std::endl; + bob::core::error << "This is an error message" << std::endl; + success = success && out.str() == "This is a debug message\nThis is an info message\n"; + success = success && err.str() == "This is a warning message\nThis is an error message\n"; + + out.str(""); + err.str(""); + bob::core::log_level(bob::core::ERROR); + bob::core::debug << "This is a debug message" << std::endl; + bob::core::info << "This is an info message" << std::endl; + bob::core::warn << "This is a warning message" << std::endl; + bob::core::error << "This is an error message" << std::endl; + success = success && out.str() == ""; + success = success && err.str() == "This is an error message\n"; + + out.str(""); + err.str(""); + bob::core::log_level(bob::core::DISABLE); + bob::core::debug << "This is a debug message" << std::endl; + bob::core::info << "This is an info message" << std::endl; + bob::core::warn << "This is a warning message" << std::endl; + bob::core::error << "This is an error message" << std::endl; + success = success && out.str() == ""; + success = success && err.str() == ""; + + } catch(...){ + success = false; + } + + // make sure that cout and cerr are redirected to their original streams + std::cout.rdbuf( oldout ); + std::cerr.rdbuf( olderr ); bob::core::log_level(bob::core::DEBUG); - Py_RETURN_NONE; + if (success) + Py_RETURN_TRUE; + else + Py_RETURN_FALSE; BOB_CATCH_FUNCTION("_test_output_disable", 0) } diff --git a/bob/core/test_logging.py b/bob/core/test_logging.py index 2f27288..71d35f5 100644 --- a/bob/core/test_logging.py +++ b/bob/core/test_logging.py @@ -77,102 +77,4 @@ def test_from_cxx_multithreaded(): def test_from_cxx_disable(): from bob.core._test import _test_output_disable - import sys, os - import threading - - class OutputGrabber(object): - """ - Class used to grab standard output or another stream. - This is a slight modification of what was proposed here: - http://stackoverflow.com/a/29834357/3301902 - """ - escape_char = "\b" - - def __init__(self, stream=None, threaded=False): - self.origstream = stream - self.threaded = threaded - if self.origstream is None: - self.origstream = sys.stdout - self.origstreamfd = self.origstream.fileno() - self.capturedtext = "" - # Create a pipe so the stream can be captured: - self.pipe_out, self.pipe_in = os.pipe() - - def start(self): - """ - Start capturing the stream data. - """ - self.capturedtext = "" - # Save a copy of the stream: - self.streamfd = os.dup(self.origstreamfd) - # Replace the Original stream with our write pipe - os.dup2(self.pipe_in, self.origstreamfd) - if self.threaded: - # Start thread that will read the stream: - self.workerThread = threading.Thread(target=self.readOutput) - self.workerThread.start() - # Make sure that the thread is running and os.read is executed: - time.sleep(0.01) - - def stop(self): - """ - Stop capturing the stream data and save the text in `capturedtext`. - """ - # Flush the stream to make sure all our data goes in before - # the escape character. - self.origstream.flush() - # Print the escape character to make the readOutput method stop: - self.origstream.write(self.escape_char) - self.origstream.flush() - if self.threaded: - # wait until the thread finishes so we are sure that - # we have until the last character: - self.workerThread.join() - else: - self.readOutput() - # Close the pipe: - os.close(self.pipe_out) - # Restore the original stream: - os.dup2(self.streamfd, self.origstreamfd) - - def readOutput(self): - """ - Read the stream data (one byte at a time) - and save the text in `capturedtext`. - """ - while True: - data = os.read(self.pipe_out, 1) # Read One Byte Only - if self.escape_char in data: - break - if not data: - break - self.capturedtext += data - - - try: - # redirect output and error streams - out = OutputGrabber(sys.stdout) - err = OutputGrabber(sys.stderr) - out.start() - err.start() - - # run our code - _test_output_disable() - - finally: - # Clean up the pipe and restore the original stdout - out.stop() - err.stop() - - # output should contain two lines - outs = out.capturedtext.rstrip().split("\n") - assert len(outs) == 2 - assert outs[0] == "This is a debug message" - assert outs[1] == "This is an info message" - - # error should contain three lines; error message is printed twice - errs = err.capturedtext.rstrip().split("\n") - assert len(errs) == 3 - assert errs[0] == "This is a warning message" - assert errs[1] == "This is an error message" - assert errs[2] == "This is an error message" + assert _test_output_disable(), "The C++ test function returned false, indicating an (unknonw) error" -- GitLab