From ff916b48bda3f7083d7bad8dd23728161d8d820e Mon Sep 17 00:00:00 2001 From: Zach Mullen Date: Thu, 17 Dec 2009 11:14:49 -0500 Subject: [PATCH] CTest output submitted to the dashboard is now compressed by default. --- Source/CTest/cmCTestRunTest.cxx | 78 ++++++++++++++++++++++++++++- Source/CTest/cmCTestRunTest.h | 5 ++ Source/CTest/cmCTestTestHandler.cxx | 5 +- Source/CTest/cmCTestTestHandler.h | 1 + 4 files changed, 86 insertions(+), 3 deletions(-) diff --git a/Source/CTest/cmCTestRunTest.cxx b/Source/CTest/cmCTestRunTest.cxx index 273dc1b9d..53424890f 100644 --- a/Source/CTest/cmCTestRunTest.cxx +++ b/Source/CTest/cmCTestRunTest.cxx @@ -15,6 +15,9 @@ #include "cmCTest.h" #include "cmSystemTools.h" +#include +#include + cmCTestRunTest::cmCTestRunTest(cmCTestTestHandler* handler) { this->CTest = handler->CTest; @@ -26,6 +29,9 @@ cmCTestRunTest::cmCTestRunTest(cmCTestTestHandler* handler) this->TestResult.Status = 0; this->TestResult.TestCount = 0; this->TestResult.Properties = 0; + this->ProcessOutput = ""; + this->CompressedOutput = ""; + this->CompressionRatio = 2; } cmCTestRunTest::~cmCTestRunTest() @@ -52,7 +58,7 @@ bool cmCTestRunTest::CheckOutput() { // Store this line of output. cmCTestLog(this->CTest, HANDLER_VERBOSE_OUTPUT, - this->GetIndex() << ": " << line << std::endl); + this->GetIndex() << ": " << line << std::endl); this->ProcessOutput += line; this->ProcessOutput += "\n"; } @@ -64,9 +70,72 @@ bool cmCTestRunTest::CheckOutput() return true; } +//--------------------------------------------------------- +// Streamed compression of test output. The compressed data +// is appended to this->CompressedOutput +void cmCTestRunTest::CompressOutput() +{ + int ret; + z_stream strm; + + unsigned char* in = + reinterpret_cast( + const_cast(this->ProcessOutput.c_str())); + //zlib makes the guarantee that this is the maximum output size + int outSize = static_cast(this->ProcessOutput.size() * 1.001 + 13); + unsigned char* out = new unsigned char[outSize]; + + strm.zalloc = Z_NULL; + strm.zfree = Z_NULL; + strm.opaque = Z_NULL; + ret = deflateInit(&strm, -1); //default compression level + if (ret != Z_OK) + { + //log deflate init error? + return; + } + + strm.avail_in = this->ProcessOutput.size(); + strm.next_in = in; + strm.avail_out = outSize; + strm.next_out = out; + ret = deflate(&strm, Z_FINISH); + + if(ret == Z_STREAM_ERROR || ret != Z_STREAM_END) + { + cmCTestLog(this->CTest, ERROR_MESSAGE, "Error initializing stream " + "compression. Sending uncompressed output." << std::endl); + return; + } + + (void)deflateEnd(&strm); + + unsigned char *encoded_buffer + = new unsigned char[static_cast(outSize * 1.5)]; + + unsigned long rlen + = cmsysBase64_Encode(out, strm.total_out, encoded_buffer, 1); + + for(unsigned long i = 0; i < rlen; i++) + { + this->CompressedOutput += encoded_buffer[i]; + } + + this->CompressionRatio = static_cast(strm.total_out) / + static_cast(strm.total_in); + + delete [] encoded_buffer; + delete [] out; +} + //--------------------------------------------------------- bool cmCTestRunTest::EndTest(size_t completed, size_t total, bool started) { + if (this->CTest->ShouldCompressTestOutput()) + { + this->CompressOutput(); + } + //restore the old environment if (this->ModifyEnv) { @@ -261,7 +330,11 @@ bool cmCTestRunTest::EndTest(size_t completed, size_t total, bool started) // record the results in TestResult if(started) { - this->TestResult.Output = this->ProcessOutput; + bool compress = this->CompressionRatio < 1 && + this->CTest->ShouldCompressTestOutput(); + this->TestResult.Output = compress ? this->CompressedOutput + : this->ProcessOutput; + this->TestResult.CompressOutput = compress; this->TestResult.ReturnValue = this->TestProcess->GetExitValue(); this->TestResult.CompletionStatus = "Completed"; this->TestResult.ExecutionTime = this->TestProcess->GetTotalTime(); @@ -310,6 +383,7 @@ bool cmCTestRunTest::StartTest(size_t total) std::vector& args = this->TestProperties->Args; this->TestResult.Properties = this->TestProperties; this->TestResult.ExecutionTime = 0; + this->TestResult.CompressOutput = false; this->TestResult.ReturnValue = -1; this->TestResult.CompletionStatus = "Failed to start"; this->TestResult.Status = cmCTestTestHandler::BAD_COMMAND; diff --git a/Source/CTest/cmCTestRunTest.h b/Source/CTest/cmCTestRunTest.h index fa0e8af7e..108464356 100644 --- a/Source/CTest/cmCTestRunTest.h +++ b/Source/CTest/cmCTestRunTest.h @@ -45,6 +45,9 @@ public: // Read and store output. Returns true if it must be called again. bool CheckOutput(); + // Compresses the output, writing to CompressedOutput + void CompressOutput(); + //launch the test process, return whether it started correctly bool StartTest(size_t total); //capture and report the test results @@ -79,6 +82,8 @@ private: //stores the original environment if we are modifying it std::vector OrigEnv; std::string ProcessOutput; + std::string CompressedOutput; + double CompressionRatio; //The test results cmCTestTestHandler::cmCTestTestResult TestResult; int Index; diff --git a/Source/CTest/cmCTestTestHandler.cxx b/Source/CTest/cmCTestTestHandler.cxx index 900165eb9..8af281507 100644 --- a/Source/CTest/cmCTestTestHandler.cxx +++ b/Source/CTest/cmCTestTestHandler.cxx @@ -1186,7 +1186,10 @@ void cmCTestTestHandler::GenerateDartOutput(std::ostream& os) } os << "\t\t\t\n" - << "\t\t\t\t"; + << "\t\t\t\tCompressOutput ? + " encoding=\"base64\" compression=\"gzip\">" + : ">"); os << cmXMLSafe(result->Output); os << "\n" diff --git a/Source/CTest/cmCTestTestHandler.h b/Source/CTest/cmCTestTestHandler.h index a78cada67..1513410e9 100644 --- a/Source/CTest/cmCTestTestHandler.h +++ b/Source/CTest/cmCTestTestHandler.h @@ -114,6 +114,7 @@ public: double ExecutionTime; int ReturnValue; int Status; + bool CompressOutput; std::string CompletionStatus; std::string Output; std::string RegressionImages;