Coverage for /Syzygy/kasko/testing/safe_pipe_reader.cc

CoverageLines executed / instrumented / missingexe / inst / missLanguageGroup
100.0%46460.C++test

Line-by-line coverage:

   1    :  // Copyright 2015 Google Inc. All Rights Reserved.
   2    :  //
   3    :  // Licensed under the Apache License, Version 2.0 (the "License");
   4    :  // you may not use this file except in compliance with the License.
   5    :  // You may obtain a copy of the License at
   6    :  //
   7    :  //     http://www.apache.org/licenses/LICENSE-2.0
   8    :  //
   9    :  // Unless required by applicable law or agreed to in writing, software
  10    :  // distributed under the License is distributed on an "AS IS" BASIS,
  11    :  // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  12    :  // See the License for the specific language governing permissions and
  13    :  // limitations under the License.
  14    :  
  15    :  #include "syzygy/kasko/testing/safe_pipe_reader.h"
  16    :  
  17    :  #include "base/bind.h"
  18    :  #include "base/location.h"
  19    :  #include "base/logging.h"
  20    :  
  21    :  namespace kasko {
  22    :  namespace testing {
  23    :  namespace {
  24    :  
  25    :  // Writes |size| bytes to |handle| and sets |*unblocked| to true.
  26    :  // Used as a crude timeout mechanism by ReadData().
  27  E :  void UnblockPipe(HANDLE handle, size_t size, bool* unblocked) {
  28  E :    std::string unblock_data(size, '\0');
  29    :    // Unblock the ReadFile in LocalTestServer::WaitToStart by writing to the
  30    :    // pipe. Make sure the call succeeded, otherwise we are very likely to hang.
  31  E :    DWORD bytes_written = 0;
  32  E :    LOG(WARNING) << "Timeout reached; unblocking pipe by writing " << size
  33    :                 << " bytes";
  34  E :    *unblocked = true;
  35  E :    CHECK(::WriteFile(handle, unblock_data.data(), size, &bytes_written, NULL));
  36  E :    CHECK_EQ(size, bytes_written);
  37  E :  }
  38    :  
  39    :  }  // namespace
  40    :  
  41    :  SafePipeReader::SafePipeReader()
  42    :      : thread_("SafePipeReader watcher"),
  43    :        write_handle_(INVALID_HANDLE_VALUE),
  44  E :        read_handle_(INVALID_HANDLE_VALUE) {
  45  E :    thread_.Start();
  46  E :    DCHECK(thread_.IsRunning());
  47    :  
  48  E :    if (thread_.IsRunning()) {
  49  E :      HANDLE child_read = NULL;
  50  E :      HANDLE child_write = NULL;
  51  E :      BOOL result = ::CreatePipe(&child_read, &child_write, NULL, 0);
  52  E :      DCHECK(result);
  53  E :      if (result) {
  54  E :        read_handle_ = child_read;
  55  E :        write_handle_ = child_write;
  56    :  
  57    :        // Make the write half inheritable.
  58    :        result = ::SetHandleInformation(write_handle_, HANDLE_FLAG_INHERIT,
  59  E :                                        HANDLE_FLAG_INHERIT);
  60  E :        DCHECK(result);
  61    :      }
  62    :    }
  63  E :  }
  64    :  
  65  E :  SafePipeReader::~SafePipeReader() {
  66  E :    if (read_handle_ != INVALID_HANDLE_VALUE)
  67  E :      ::CloseHandle(read_handle_);
  68  E :    if (write_handle_ != INVALID_HANDLE_VALUE)
  69  E :      ::CloseHandle(write_handle_);
  70  E :  }
  71    :  
  72    :  bool SafePipeReader::ReadData(base::TimeDelta timeout,
  73    :                                size_t length,
  74  E :                                void* buffer) {
  75  E :    size_t bytes_read = 0;
  76  E :    DCHECK(IsValid());
  77  E :    if (IsValid()) {
  78    :      // Prepare a timeout in case the server fails to start.
  79  E :      bool unblocked = false;
  80    :      thread_.message_loop()->PostDelayedTask(
  81    :          FROM_HERE,
  82    :          base::Bind(&UnblockPipe, write_handle_, length, &unblocked),
  83  E :          timeout);
  84    :  
  85  E :      DWORD num_bytes = 0;
  86    :      do {
  87  E :        num_bytes = 0;
  88    :        bool result = ::ReadFile(read_handle_,
  89    :                                 reinterpret_cast<uint8_t*>(buffer) + bytes_read,
  90  E :                                 length - bytes_read, &num_bytes, NULL);
  91  E :        DCHECK(result);
  92  E :        if (result && !unblocked)
  93  E :          bytes_read += num_bytes;
  94  E :      } while (num_bytes > 0 && bytes_read < length && !unblocked);
  95    :    }
  96    :  
  97  E :    return bytes_read == length;
  98  E :  }
  99    :  
 100  E :  bool SafePipeReader::IsValid() {
 101    :    return read_handle_ != INVALID_HANDLE_VALUE &&
 102  E :           write_handle_ != INVALID_HANDLE_VALUE && thread_.IsRunning();
 103  E :  }
 104    :  
 105    :  }  // namespace testing
 106    :  }  // namespace kasko

Coverage information generated Thu Jan 14 17:40:38 2016.