From cf890bc58eb28d5f1f6ce3f90d4e541983042369 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Peter=20Bostr=C3=B6m?= Date: Mon, 7 Dec 2015 16:44:58 +0100 Subject: [PATCH] Roll gtest-parallel. Brings in fixes that save log output to disk instead of piping them through Python. Should fix problem where output from tests stall for more than 10 seconds. Also enabling JsepPeerConnectionP2PTestClient on all platforms again. BUG=webrtc:5231 R=kjellander@webrtc.org Review URL: https://codereview.webrtc.org/1509463002 . Cr-Commit-Position: refs/heads/master@{#10917} --- talk/app/webrtc/peerconnection_unittest.cc | 78 ++++++++++------------ third_party/gtest-parallel/README.webrtc | 2 +- third_party/gtest-parallel/gtest-parallel | 59 ++++++++++------ 3 files changed, 75 insertions(+), 64 deletions(-) diff --git a/talk/app/webrtc/peerconnection_unittest.cc b/talk/app/webrtc/peerconnection_unittest.cc index 9ecf08014c..175996511e 100644 --- a/talk/app/webrtc/peerconnection_unittest.cc +++ b/talk/app/webrtc/peerconnection_unittest.cc @@ -908,19 +908,11 @@ class PeerConnectionTestClient : public webrtc::PeerConnectionObserver, rtc::scoped_ptr data_observer_; }; -// Flaky on Mac Debug bots. See webrtc:5231 -#if defined(WEBRTC_MAC) && !defined(WEBRTC_IOS) -#define MAYBE_JsepPeerConnectionP2PTestClient \ - DISABLED_JsepPeerConnectionP2PTestClient -#else -#define MAYBE_JsepPeerConnectionP2PTestClient JsepPeerConnectionP2PTestClient -#endif - // TODO(deadbeef): Rename this to P2PTestConductor once the Linux memcheck and // Windows DrMemory Full bots' blacklists are updated. -class MAYBE_JsepPeerConnectionP2PTestClient : public testing::Test { +class JsepPeerConnectionP2PTestClient : public testing::Test { public: - MAYBE_JsepPeerConnectionP2PTestClient() + JsepPeerConnectionP2PTestClient() : pss_(new rtc::PhysicalSocketServer), ss_(new rtc::VirtualSocketServer(pss_.get())), ss_scope_(ss_.get()) {} @@ -975,7 +967,7 @@ class MAYBE_JsepPeerConnectionP2PTestClient : public testing::Test { receiving_client_->VerifyLocalIceUfragAndPassword(); } - ~MAYBE_JsepPeerConnectionP2PTestClient() { + ~JsepPeerConnectionP2PTestClient() { if (initiating_client_) { initiating_client_->set_signaling_message_receiver(nullptr); } @@ -1161,7 +1153,7 @@ class MAYBE_JsepPeerConnectionP2PTestClient : public testing::Test { // This test sets up a Jsep call between two parties and test Dtmf. // TODO(holmer): Disabled due to sometimes crashing on buildbots. // See issue webrtc/2378. -TEST_F(MAYBE_JsepPeerConnectionP2PTestClient, DISABLED_LocalP2PTestDtmf) { +TEST_F(JsepPeerConnectionP2PTestClient, DISABLED_LocalP2PTestDtmf) { ASSERT_TRUE(CreateTestClients()); LocalP2PTest(); VerifyDtmf(); @@ -1169,7 +1161,7 @@ TEST_F(MAYBE_JsepPeerConnectionP2PTestClient, DISABLED_LocalP2PTestDtmf) { // This test sets up a Jsep call between two parties and test that we can get a // video aspect ratio of 16:9. -TEST_F(MAYBE_JsepPeerConnectionP2PTestClient, LocalP2PTest16To9) { +TEST_F(JsepPeerConnectionP2PTestClient, LocalP2PTest16To9) { ASSERT_TRUE(CreateTestClients()); FakeConstraints constraint; double requested_ratio = 640.0/360; @@ -1194,7 +1186,7 @@ TEST_F(MAYBE_JsepPeerConnectionP2PTestClient, LocalP2PTest16To9) { // received video has a resolution of 1280*720. // TODO(mallinath): Enable when // http://code.google.com/p/webrtc/issues/detail?id=981 is fixed. -TEST_F(MAYBE_JsepPeerConnectionP2PTestClient, DISABLED_LocalP2PTest1280By720) { +TEST_F(JsepPeerConnectionP2PTestClient, DISABLED_LocalP2PTest1280By720) { ASSERT_TRUE(CreateTestClients()); FakeConstraints constraint; constraint.SetMandatoryMinWidth(1280); @@ -1206,13 +1198,13 @@ TEST_F(MAYBE_JsepPeerConnectionP2PTestClient, DISABLED_LocalP2PTest1280By720) { // This test sets up a call between two endpoints that are configured to use // DTLS key agreement. As a result, DTLS is negotiated and used for transport. -TEST_F(MAYBE_JsepPeerConnectionP2PTestClient, LocalP2PTestDtls) { +TEST_F(JsepPeerConnectionP2PTestClient, LocalP2PTestDtls) { SetupAndVerifyDtlsCall(); } // This test sets up a audio call initially and then upgrades to audio/video, // using DTLS. -TEST_F(MAYBE_JsepPeerConnectionP2PTestClient, LocalP2PTestDtlsRenegotiate) { +TEST_F(JsepPeerConnectionP2PTestClient, LocalP2PTestDtlsRenegotiate) { MAYBE_SKIP_TEST(rtc::SSLStreamAdapter::HaveDtlsSrtp); FakeConstraints setup_constraints; setup_constraints.AddMandatory(MediaConstraintsInterface::kEnableDtlsSrtp, @@ -1226,7 +1218,7 @@ TEST_F(MAYBE_JsepPeerConnectionP2PTestClient, LocalP2PTestDtlsRenegotiate) { // This test sets up a call transfer to a new caller with a different DTLS // fingerprint. -TEST_F(MAYBE_JsepPeerConnectionP2PTestClient, LocalP2PTestDtlsTransferCallee) { +TEST_F(JsepPeerConnectionP2PTestClient, LocalP2PTestDtlsTransferCallee) { MAYBE_SKIP_TEST(rtc::SSLStreamAdapter::HaveDtlsSrtp); SetupAndVerifyDtlsCall(); @@ -1244,7 +1236,7 @@ TEST_F(MAYBE_JsepPeerConnectionP2PTestClient, LocalP2PTestDtlsTransferCallee) { // This test sets up a call transfer to a new callee with a different DTLS // fingerprint. -TEST_F(MAYBE_JsepPeerConnectionP2PTestClient, LocalP2PTestDtlsTransferCaller) { +TEST_F(JsepPeerConnectionP2PTestClient, LocalP2PTestDtlsTransferCaller) { MAYBE_SKIP_TEST(rtc::SSLStreamAdapter::HaveDtlsSrtp); SetupAndVerifyDtlsCall(); @@ -1263,7 +1255,7 @@ TEST_F(MAYBE_JsepPeerConnectionP2PTestClient, LocalP2PTestDtlsTransferCaller) { // This test sets up a call between two endpoints that are configured to use // DTLS key agreement. The offerer don't support SDES. As a result, DTLS is // negotiated and used for transport. -TEST_F(MAYBE_JsepPeerConnectionP2PTestClient, LocalP2PTestOfferDtlsButNotSdes) { +TEST_F(JsepPeerConnectionP2PTestClient, LocalP2PTestOfferDtlsButNotSdes) { MAYBE_SKIP_TEST(rtc::SSLStreamAdapter::HaveDtlsSrtp); FakeConstraints setup_constraints; setup_constraints.AddMandatory(MediaConstraintsInterface::kEnableDtlsSrtp, @@ -1276,7 +1268,7 @@ TEST_F(MAYBE_JsepPeerConnectionP2PTestClient, LocalP2PTestOfferDtlsButNotSdes) { // This test sets up a Jsep call between two parties, and the callee only // accept to receive video. -TEST_F(MAYBE_JsepPeerConnectionP2PTestClient, LocalP2PTestAnswerVideo) { +TEST_F(JsepPeerConnectionP2PTestClient, LocalP2PTestAnswerVideo) { ASSERT_TRUE(CreateTestClients()); receiving_client()->SetReceiveAudioVideo(false, true); LocalP2PTest(); @@ -1284,7 +1276,7 @@ TEST_F(MAYBE_JsepPeerConnectionP2PTestClient, LocalP2PTestAnswerVideo) { // This test sets up a Jsep call between two parties, and the callee only // accept to receive audio. -TEST_F(MAYBE_JsepPeerConnectionP2PTestClient, LocalP2PTestAnswerAudio) { +TEST_F(JsepPeerConnectionP2PTestClient, LocalP2PTestAnswerAudio) { ASSERT_TRUE(CreateTestClients()); receiving_client()->SetReceiveAudioVideo(true, false); LocalP2PTest(); @@ -1292,7 +1284,7 @@ TEST_F(MAYBE_JsepPeerConnectionP2PTestClient, LocalP2PTestAnswerAudio) { // This test sets up a Jsep call between two parties, and the callee reject both // audio and video. -TEST_F(MAYBE_JsepPeerConnectionP2PTestClient, LocalP2PTestAnswerNone) { +TEST_F(JsepPeerConnectionP2PTestClient, LocalP2PTestAnswerNone) { ASSERT_TRUE(CreateTestClients()); receiving_client()->SetReceiveAudioVideo(false, false); LocalP2PTest(); @@ -1303,7 +1295,7 @@ TEST_F(MAYBE_JsepPeerConnectionP2PTestClient, LocalP2PTestAnswerNone) { // being rejected. Once the re-negotiation is done, the video flow should stop // and the audio flow should continue. // Disabled due to b/14955157. -TEST_F(MAYBE_JsepPeerConnectionP2PTestClient, +TEST_F(JsepPeerConnectionP2PTestClient, DISABLED_UpdateOfferWithRejectedContent) { ASSERT_TRUE(CreateTestClients()); LocalP2PTest(); @@ -1313,7 +1305,7 @@ TEST_F(MAYBE_JsepPeerConnectionP2PTestClient, // This test sets up a Jsep call between two parties. The MSID is removed from // the SDP strings from the caller. // Disabled due to b/14955157. -TEST_F(MAYBE_JsepPeerConnectionP2PTestClient, +TEST_F(JsepPeerConnectionP2PTestClient, DISABLED_LocalP2PTestWithoutMsid) { ASSERT_TRUE(CreateTestClients()); receiving_client()->RemoveMsidFromReceivedSdp(true); @@ -1329,7 +1321,7 @@ TEST_F(MAYBE_JsepPeerConnectionP2PTestClient, // sends two steams. // TODO(perkj): Disabled due to // https://code.google.com/p/webrtc/issues/detail?id=1454 -TEST_F(MAYBE_JsepPeerConnectionP2PTestClient, DISABLED_LocalP2PTestTwoStreams) { +TEST_F(JsepPeerConnectionP2PTestClient, DISABLED_LocalP2PTestTwoStreams) { ASSERT_TRUE(CreateTestClients()); // Set optional video constraint to max 320pixels to decrease CPU usage. FakeConstraints constraint; @@ -1343,7 +1335,7 @@ TEST_F(MAYBE_JsepPeerConnectionP2PTestClient, DISABLED_LocalP2PTestTwoStreams) { } // Test that we can receive the audio output level from a remote audio track. -TEST_F(MAYBE_JsepPeerConnectionP2PTestClient, GetAudioOutputLevelStats) { +TEST_F(JsepPeerConnectionP2PTestClient, GetAudioOutputLevelStats) { ASSERT_TRUE(CreateTestClients()); LocalP2PTest(); @@ -1362,7 +1354,7 @@ TEST_F(MAYBE_JsepPeerConnectionP2PTestClient, GetAudioOutputLevelStats) { } // Test that an audio input level is reported. -TEST_F(MAYBE_JsepPeerConnectionP2PTestClient, GetAudioInputLevelStats) { +TEST_F(JsepPeerConnectionP2PTestClient, GetAudioInputLevelStats) { ASSERT_TRUE(CreateTestClients()); LocalP2PTest(); @@ -1373,7 +1365,7 @@ TEST_F(MAYBE_JsepPeerConnectionP2PTestClient, GetAudioInputLevelStats) { } // Test that we can get incoming byte counts from both audio and video tracks. -TEST_F(MAYBE_JsepPeerConnectionP2PTestClient, GetBytesReceivedStats) { +TEST_F(JsepPeerConnectionP2PTestClient, GetBytesReceivedStats) { ASSERT_TRUE(CreateTestClients()); LocalP2PTest(); @@ -1395,7 +1387,7 @@ TEST_F(MAYBE_JsepPeerConnectionP2PTestClient, GetBytesReceivedStats) { } // Test that we can get outgoing byte counts from both audio and video tracks. -TEST_F(MAYBE_JsepPeerConnectionP2PTestClient, GetBytesSentStats) { +TEST_F(JsepPeerConnectionP2PTestClient, GetBytesSentStats) { ASSERT_TRUE(CreateTestClients()); LocalP2PTest(); @@ -1417,7 +1409,7 @@ TEST_F(MAYBE_JsepPeerConnectionP2PTestClient, GetBytesSentStats) { } // Test that DTLS 1.0 is used if both sides only support DTLS 1.0. -TEST_F(MAYBE_JsepPeerConnectionP2PTestClient, GetDtls12None) { +TEST_F(JsepPeerConnectionP2PTestClient, GetDtls12None) { PeerConnectionFactory::Options init_options; init_options.ssl_max_version = rtc::SSL_PROTOCOL_DTLS_10; PeerConnectionFactory::Options recv_options; @@ -1448,7 +1440,7 @@ TEST_F(MAYBE_JsepPeerConnectionP2PTestClient, GetDtls12None) { } // Test that DTLS 1.2 is used if both ends support it. -TEST_F(MAYBE_JsepPeerConnectionP2PTestClient, GetDtls12Both) { +TEST_F(JsepPeerConnectionP2PTestClient, GetDtls12Both) { PeerConnectionFactory::Options init_options; init_options.ssl_max_version = rtc::SSL_PROTOCOL_DTLS_12; PeerConnectionFactory::Options recv_options; @@ -1480,7 +1472,7 @@ TEST_F(MAYBE_JsepPeerConnectionP2PTestClient, GetDtls12Both) { // Test that DTLS 1.0 is used if the initator supports DTLS 1.2 and the // received supports 1.0. -TEST_F(MAYBE_JsepPeerConnectionP2PTestClient, GetDtls12Init) { +TEST_F(JsepPeerConnectionP2PTestClient, GetDtls12Init) { PeerConnectionFactory::Options init_options; init_options.ssl_max_version = rtc::SSL_PROTOCOL_DTLS_12; PeerConnectionFactory::Options recv_options; @@ -1512,7 +1504,7 @@ TEST_F(MAYBE_JsepPeerConnectionP2PTestClient, GetDtls12Init) { // Test that DTLS 1.0 is used if the initator supports DTLS 1.0 and the // received supports 1.2. -TEST_F(MAYBE_JsepPeerConnectionP2PTestClient, GetDtls12Recv) { +TEST_F(JsepPeerConnectionP2PTestClient, GetDtls12Recv) { PeerConnectionFactory::Options init_options; init_options.ssl_max_version = rtc::SSL_PROTOCOL_DTLS_10; PeerConnectionFactory::Options recv_options; @@ -1544,7 +1536,7 @@ TEST_F(MAYBE_JsepPeerConnectionP2PTestClient, GetDtls12Recv) { // This test sets up a call between two parties with audio, video and an RTP // data channel. -TEST_F(MAYBE_JsepPeerConnectionP2PTestClient, LocalP2PTestRtpDataChannel) { +TEST_F(JsepPeerConnectionP2PTestClient, LocalP2PTestRtpDataChannel) { FakeConstraints setup_constraints; setup_constraints.SetAllowRtpDataChannels(); ASSERT_TRUE(CreateTestClients(&setup_constraints, &setup_constraints)); @@ -1576,7 +1568,7 @@ TEST_F(MAYBE_JsepPeerConnectionP2PTestClient, LocalP2PTestRtpDataChannel) { // This test sets up a call between two parties with audio, video and an SCTP // data channel. -TEST_F(MAYBE_JsepPeerConnectionP2PTestClient, LocalP2PTestSctpDataChannel) { +TEST_F(JsepPeerConnectionP2PTestClient, LocalP2PTestSctpDataChannel) { ASSERT_TRUE(CreateTestClients()); initializing_client()->CreateDataChannel(); LocalP2PTest(); @@ -1610,7 +1602,7 @@ TEST_F(MAYBE_JsepPeerConnectionP2PTestClient, LocalP2PTestSctpDataChannel) { // transport has detected that a channel is writable and thus data can be // received before the data channel state changes to open. That is hard to test // but the same buffering is used in that case. -TEST_F(MAYBE_JsepPeerConnectionP2PTestClient, RegisterDataChannelObserver) { +TEST_F(JsepPeerConnectionP2PTestClient, RegisterDataChannelObserver) { FakeConstraints setup_constraints; setup_constraints.SetAllowRtpDataChannels(); ASSERT_TRUE(CreateTestClients(&setup_constraints, &setup_constraints)); @@ -1640,7 +1632,7 @@ TEST_F(MAYBE_JsepPeerConnectionP2PTestClient, RegisterDataChannelObserver) { // This test sets up a call between two parties with audio, video and but only // the initiating client support data. -TEST_F(MAYBE_JsepPeerConnectionP2PTestClient, +TEST_F(JsepPeerConnectionP2PTestClient, LocalP2PTestReceiverDoesntSupportData) { FakeConstraints setup_constraints_1; setup_constraints_1.SetAllowRtpDataChannels(); @@ -1660,7 +1652,7 @@ TEST_F(MAYBE_JsepPeerConnectionP2PTestClient, // This test sets up a call between two parties with audio, video. When audio // and video is setup and flowing and data channel is negotiated. -TEST_F(MAYBE_JsepPeerConnectionP2PTestClient, +TEST_F(JsepPeerConnectionP2PTestClient, AddDataChannelAfterRenegotiation) { FakeConstraints setup_constraints; setup_constraints.SetAllowRtpDataChannels(); @@ -1680,7 +1672,7 @@ TEST_F(MAYBE_JsepPeerConnectionP2PTestClient, // This test sets up a Jsep call with SCTP DataChannel and verifies the // negotiation is completed without error. #ifdef HAVE_SCTP -TEST_F(MAYBE_JsepPeerConnectionP2PTestClient, CreateOfferWithSctpDataChannel) { +TEST_F(JsepPeerConnectionP2PTestClient, CreateOfferWithSctpDataChannel) { MAYBE_SKIP_TEST(rtc::SSLStreamAdapter::HaveDtlsSrtp); FakeConstraints constraints; constraints.SetMandatory( @@ -1694,7 +1686,7 @@ TEST_F(MAYBE_JsepPeerConnectionP2PTestClient, CreateOfferWithSctpDataChannel) { // This test sets up a call between two parties with audio, and video. // During the call, the initializing side restart ice and the test verifies that // new ice candidates are generated and audio and video still can flow. -TEST_F(MAYBE_JsepPeerConnectionP2PTestClient, IceRestart) { +TEST_F(JsepPeerConnectionP2PTestClient, IceRestart) { ASSERT_TRUE(CreateTestClients()); // Negotiate and wait for ice completion and make sure audio and video plays. @@ -1744,7 +1736,7 @@ TEST_F(MAYBE_JsepPeerConnectionP2PTestClient, IceRestart) { // This test sets up a call between two parties with audio, and video. // It then renegotiates setting the video m-line to "port 0", then later // renegotiates again, enabling video. -TEST_F(MAYBE_JsepPeerConnectionP2PTestClient, LocalP2PTestVideoDisableEnable) { +TEST_F(JsepPeerConnectionP2PTestClient, LocalP2PTestVideoDisableEnable) { ASSERT_TRUE(CreateTestClients()); // Do initial negotiation. Will result in video and audio sendonly m-lines. @@ -1768,7 +1760,7 @@ TEST_F(MAYBE_JsepPeerConnectionP2PTestClient, LocalP2PTestVideoDisableEnable) { // VideoDecoderFactory. // TODO(holmer): Disabled due to sometimes crashing on buildbots. // See issue webrtc/2378. -TEST_F(MAYBE_JsepPeerConnectionP2PTestClient, +TEST_F(JsepPeerConnectionP2PTestClient, DISABLED_LocalP2PTestWithVideoDecoderFactory) { ASSERT_TRUE(CreateTestClients()); EnableVideoDecoderFactory(); @@ -1778,7 +1770,7 @@ TEST_F(MAYBE_JsepPeerConnectionP2PTestClient, // This tests that if we negotiate after calling CreateSender but before we // have a track, then set a track later, frames from the newly-set track are // received end-to-end. -TEST_F(MAYBE_JsepPeerConnectionP2PTestClient, EarlyWarmupTest) { +TEST_F(JsepPeerConnectionP2PTestClient, EarlyWarmupTest) { ASSERT_TRUE(CreateTestClients()); auto audio_sender = initializing_client()->pc()->CreateSender("audio"); auto video_sender = initializing_client()->pc()->CreateSender("video"); diff --git a/third_party/gtest-parallel/README.webrtc b/third_party/gtest-parallel/README.webrtc index acea04fb6e..eafdf66d48 100644 --- a/third_party/gtest-parallel/README.webrtc +++ b/third_party/gtest-parallel/README.webrtc @@ -1,5 +1,5 @@ URL: https://github.com/google/gtest-parallel -Version: c0f8ded77566c657ccc7f745fd9cb070750cccf8 +Version: 34ae4d7ed77fe2ac22d5b444a8468c9d847ed9d2 License: Apache 2.0 License File: LICENSE diff --git a/third_party/gtest-parallel/gtest-parallel b/third_party/gtest-parallel/gtest-parallel index 0be59e4b4e..64fbb1c4c2 100755 --- a/third_party/gtest-parallel/gtest-parallel +++ b/third_party/gtest-parallel/gtest-parallel @@ -13,12 +13,14 @@ # See the License for the specific language governing permissions and # limitations under the License. import cPickle +import errno import gzip import multiprocessing import optparse import os import subprocess import sys +import tempfile import threading import time import zlib @@ -62,6 +64,10 @@ class Outputter(object): stdout_lock = threading.Lock() class FilterFormat: + if sys.stdout.isatty(): + # stdout needs to be unbuffered since the output is interactive. + sys.stdout = os.fdopen(sys.stdout.fileno(), 'w', 0) + out = Outputter(sys.stdout) total_tests = 0 finished_tests = 0 @@ -80,7 +86,6 @@ class FilterFormat: if command == "TEST": (binary, test) = arg.split(' ', 1) self.tests[job_id] = (binary, test.strip()) - self.outputs[job_id] = [] elif command == "EXIT": (exit_code, time_ms) = [int(x) for x in arg.split(' ', 1)] self.finished_tests += 1 @@ -88,8 +93,9 @@ class FilterFormat: self.print_test_status(test, time_ms) if exit_code != 0: self.failures.append(self.tests[job_id]) - for line in self.outputs[job_id]: - self.out.permanent_line(line) + with open(self.outputs[job_id]) as f: + for line in f.readlines(): + self.out.permanent_line(line.rstrip()) self.out.permanent_line( "[%d/%d] %s returned/aborted with exit code %d (%d ms)" % (self.finished_tests, self.total_tests, test, exit_code, time_ms)) @@ -97,17 +103,15 @@ class FilterFormat: self.total_tests = int(arg.split(' ', 1)[1]) self.out.transient_line("[0/%d] Running tests..." % self.total_tests) - def add_stdout(self, job_id, output): - self.outputs[job_id].append(output) + def logfile(self, job_id, name): + self.outputs[job_id] = name def log(self, line): stdout_lock.acquire() (prefix, output) = line.split(' ', 1) - if prefix[-1] == ':': - self.handle_meta(int(prefix[:-1]), output) - else: - self.add_stdout(int(prefix[:-1]), output) + assert prefix[-1] == ':' + self.handle_meta(int(prefix[:-1]), output) stdout_lock.release() def end(self): @@ -123,6 +127,10 @@ class RawFormat: sys.stdout.write(line + "\n") sys.stdout.flush() stdout_lock.release() + def logfile(self, job_id, name): + with open(self.outputs[job_id]) as f: + for line in f.readlines(): + self.log(str(job_id) + '> ' + line.rstrip()) def end(self): pass @@ -184,6 +192,9 @@ for i in range(len(sys.argv)): parser = optparse.OptionParser( usage = 'usage: %prog [options] binary [binary ...] -- [additional args]') +parser.add_option('-d', '--output_dir', type='string', + default=os.path.join(tempfile.gettempdir(), "gtest-parallel"), + help='output directory for test logs') parser.add_option('-r', '--repeat', type='int', default=1, help='repeat tests') parser.add_option('-w', '--workers', type='int', @@ -260,25 +271,33 @@ logger.log(str(-1) + ': TESTCNT ' + ' ' + str(len(tests))) exit_code = 0 +# Create directory for test log output. +try: + os.makedirs(options.output_dir) +except OSError as e: + # Ignore errors if this directory already exists. + if e.errno != errno.EEXIST or not os.path.isdir(options.output_dir): + raise e +# Remove files from old test runs. +for logfile in os.listdir(options.output_dir): + os.remove(os.path.join(options.output_dir, logfile)) + # Run the specified job. Return the elapsed time in milliseconds if # the job succeeds, or a very large number (larger than any reasonable # elapsed time) if the job fails. (This ensures that failing tests # will run first the next time.) def run_job((command, job_id, test)): begin = time.time() - sub = subprocess.Popen(command + ['--gtest_filter=' + test] + - ['--gtest_color=' + options.gtest_color], - stdout = subprocess.PIPE, - stderr = subprocess.STDOUT) - while True: - line = sub.stdout.readline() - if line == '': - break - logger.log(str(job_id) + '> ' + line.rstrip()) + with tempfile.NamedTemporaryFile(dir=options.output_dir, delete=False) as log: + sub = subprocess.Popen(command + ['--gtest_filter=' + test] + + ['--gtest_color=' + options.gtest_color], + stdout=log.file, + stderr=log.file) + code = sub.wait() + runtime_ms = int(1000 * (time.time() - begin)) + logger.logfile(job_id, log.name) - code = sub.wait() - runtime_ms = int(1000 * (time.time() - begin)) logger.log("%s: EXIT %s %d" % (job_id, code, runtime_ms)) if code == 0: return runtime_ms