Coverage for /Syzygy/kasko/api/api_tests.cc

CoverageLines executed / instrumented / missingexe / inst / missLanguageGroup
100.0%59590.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 "base/base_switches.h"
  16    :  #include "base/bind.h"
  17    :  #include "base/command_line.h"
  18    :  #include "base/logging.h"
  19    :  #include "base/files/file_path.h"
  20    :  #include "base/files/scoped_temp_dir.h"
  21    :  #include "base/process/kill.h"
  22    :  #include "base/process/launch.h"
  23    :  #include "base/process/process_handle.h"
  24    :  #include "base/strings/string16.h"
  25    :  #include "base/strings/string_number_conversions.h"
  26    :  #include "base/strings/utf_string_conversions.h"
  27    :  #include "base/synchronization/waitable_event.h"
  28    :  #include "base/test/multiprocess_test.h"
  29    :  #include "base/win/scoped_handle.h"
  30    :  #include "syzygy/kasko/api/client.h"
  31    :  #include "syzygy/kasko/api/reporter.h"
  32    :  #include "syzygy/kasko/testing/minidump_unittest_helpers.h"
  33    :  #include "syzygy/kasko/testing/test_server.h"
  34    :  #include "testing/multiprocess_func_list.h"
  35    :  #include "testing/gtest/include/gtest/gtest.h"
  36    :  
  37    :  namespace kasko {
  38    :  namespace api {
  39    :  
  40    :  namespace {
  41    :  
  42    :  const char kTestInstanceKeySwitch[] = "test-instance-key";
  43    :  const char kClientProcessIdSwitch[] = "client-process-id";
  44    :  const base::char16 kExitEventNamePrefix[] = L"kasko_api_test_exit_event_";
  45    :  const base::char16 kReadyEventNamePrefix[] = L"kasko_api_test_ready_event_";
  46    :  const base::char16 kEndpointPrefix[] = L"kasko_api_test_endpoint_";
  47    :  
  48  E :  MULTIPROCESS_TEST_MAIN(ApiTestReporterProcess) {
  49    :    // Read the client-supplied parameters.
  50  E :    base::CommandLine* cmd_line = base::CommandLine::ForCurrentProcess();
  51  E :    unsigned int client_process_id_uint = 0;
  52    :    CHECK(
  53    :        base::StringToUint(cmd_line->GetSwitchValueASCII(kClientProcessIdSwitch),
  54  E :                           &client_process_id_uint));
  55  E :    base::ProcessId client_process_id = client_process_id_uint;
  56    :    base::string16 test_instance_key =
  57  E :        base::ASCIIToUTF16(cmd_line->GetSwitchValueASCII(kTestInstanceKeySwitch));
  58  E :    base::string16 endpoint = kEndpointPrefix + test_instance_key;
  59  E :    base::ScopedTempDir permanent_failure_directory;
  60  E :    CHECK(permanent_failure_directory.CreateUniqueTempDir());
  61    :  
  62    :    // Set up a directory for the Reporter to generate and store crash dumps.
  63  E :    base::ScopedTempDir data_directory;
  64  E :    CHECK(data_directory.CreateUniqueTempDir());
  65    :  
  66    :    // Create the events used for inter-process synchronization.
  67    :    base::WaitableEvent exit_event(::CreateEvent(
  68  E :        NULL, FALSE, FALSE, (kExitEventNamePrefix + test_instance_key).c_str()));
  69    :    base::WaitableEvent ready_event(::CreateEvent(
  70  E :        NULL, FALSE, FALSE, (kReadyEventNamePrefix + test_instance_key).c_str()));
  71    :  
  72    :    // Start up a test server to receive uploads.
  73  E :    testing::TestServer server;
  74  E :    CHECK(server.Start());
  75    :    base::string16 url =
  76  E :        L"http://127.0.0.1:" + base::UintToString16(server.port()) + L"/crash";
  77    :  
  78    :  
  79    :    // Initialize the Reporter process
  80    :    InitializeReporter(endpoint.c_str(), url.c_str(),
  81    :                       data_directory.path().value().c_str(),
  82  E :                       permanent_failure_directory.path().value().c_str());
  83    :  
  84    :    // Request a dump of the client process.
  85  E :    base::char16* keys[] = {L"hello", nullptr};
  86  E :    base::char16* values[] = {L"world", nullptr};
  87    :    base::win::ScopedHandle client_process(
  88  E :        ::OpenProcess(PROCESS_QUERY_INFORMATION, FALSE, client_process_id));
  89  E :    CHECK(client_process.IsValid());
  90  E :    SendReportForProcess(client_process.Get(), SMALL_DUMP_TYPE, keys, values);
  91    :  
  92    :    // Tell the client process that we are active.
  93  E :    ready_event.Signal();
  94    :  
  95    :    // Wait until the client signals us to shut down.
  96  E :    exit_event.Wait();
  97    :  
  98    :    // Shut down the Reporter process.
  99  E :    ShutdownReporter();
 100    :  
 101  E :    return 0;
 102  E :  }
 103    :  
 104    :  }  // namespace
 105    :  
 106    :  // This test exercises all of the API methods of Kasko.dll. It does not do an
 107    :  // end-to-end test (i.e. by verifying that the requested crash report is
 108    :  // properly uploaded). The primary reason is that the delay before uploading is
 109    :  // not configurable via the public API and this test would therefore need to
 110    :  // wait 3 minutes before observing an upload.
 111  E :  TEST(ApiTest, BasicTest) {
 112    :    {
 113    :      // Verify that these constants are exported.
 114    :      base::string16 crash_keys_extension(
 115  E :          kasko::api::kPermanentFailureCrashKeysExtension);
 116    :      base::string16 minidump_extension(
 117  E :          kasko::api::kPermanentFailureMinidumpExtension);
 118  E :    }
 119    :  
 120    :    // Pick an ID used to avoid global namespace collisions.
 121    :    base::string16 test_instance_key =
 122  E :        base::UintToString16(base::GetCurrentProcId());
 123    :  
 124    :    // Create the events used for inter-process synchronization.
 125    :    base::win::ScopedHandle exit_event_handle(::CreateEvent(
 126  E :        NULL, FALSE, FALSE, (kExitEventNamePrefix + test_instance_key).c_str()));
 127  E :    ASSERT_TRUE(exit_event_handle.IsValid());
 128  E :    base::WaitableEvent exit_event(exit_event_handle.Take());
 129    :  
 130    :    base::win::ScopedHandle ready_event_handle(::CreateEvent(
 131  E :        NULL, FALSE, FALSE, (kReadyEventNamePrefix + test_instance_key).c_str()));
 132  E :    ASSERT_TRUE(ready_event_handle.IsValid());
 133  E :    base::WaitableEvent ready_event(ready_event_handle.Take());
 134    :  
 135    :    // Start building the Reporter process command line.
 136    :    base::CommandLine reporter_command_line =
 137  E :        base::GetMultiProcessTestChildBaseCommandLine();
 138    :    reporter_command_line.AppendSwitchASCII(switches::kTestChildProcess,
 139  E :                                            "ApiTestReporterProcess");
 140    :  
 141    :    // Pass the test instance ID.
 142    :    reporter_command_line.AppendSwitchASCII(
 143  E :        kTestInstanceKeySwitch, base::UTF16ToASCII(test_instance_key));
 144    :  
 145    :    // Pass the client process ID, used by the reporter to invoke
 146    :    // SendReportForProcess.
 147    :    reporter_command_line.AppendSwitchASCII(
 148  E :        kClientProcessIdSwitch, base::UintToString(base::GetCurrentProcId()));
 149    :  
 150    :    // Launch the Reporter process and wait until it is fully initialized.
 151    :    base::ProcessHandle reporter_process;
 152    :    ASSERT_TRUE(base::LaunchProcess(reporter_command_line, base::LaunchOptions(),
 153  E :                                    &reporter_process));
 154  E :    ready_event.Wait();
 155    :  
 156    :    // Initialize the Client process.
 157  E :    InitializeClient((kEndpointPrefix + test_instance_key).c_str());
 158    :  
 159    :    // Send up a crash report.
 160  E :    CONTEXT ctx = {};
 161  E :    ::RtlCaptureContext(&ctx);
 162  E :    EXCEPTION_RECORD exc_rec = {};
 163  E :    exc_rec.ExceptionAddress = reinterpret_cast<void*>(ctx.Eip);
 164  E :    exc_rec.ExceptionCode = EXCEPTION_ARRAY_BOUNDS_EXCEEDED;
 165  E :    EXCEPTION_POINTERS exc_ptrs = { &exc_rec, &ctx };
 166    :  
 167  E :    CrashKey crash_keys[] = {{L"hello", L"world"}, {L"", L"bar"}};
 168    :    SendReport(&exc_ptrs, SMALL_DUMP_TYPE, NULL, 0, crash_keys,
 169  E :               arraysize(crash_keys));
 170    :  
 171    :    // TODO(erikwright): Wait for the upload and verify the report contents.
 172    :  
 173    :    // Shut down the client.
 174  E :    ShutdownClient();
 175    :  
 176    :    // Tell the reporter process that we are done.
 177  E :    exit_event.Signal();
 178    :  
 179    :    // Wait for the reporter process to exit and verify its status code.
 180  E :    int exit_code = 0;
 181  E :    base::WaitForExitCode(reporter_process, &exit_code);
 182  E :    ASSERT_EQ(0, exit_code);
 183  E :  }
 184    :  
 185    :  }  // namespace api
 186    :  }  // namespace kasko

Coverage information generated Thu Mar 26 16:15:41 2015.