File: TestUtilityProcess.cpp

package info (click to toggle)
firefox 149.0-1
  • links: PTS, VCS
  • area: main
  • in suites: sid
  • size: 4,767,760 kB
  • sloc: cpp: 7,416,064; javascript: 6,752,859; ansic: 3,774,850; python: 1,250,473; xml: 641,578; asm: 439,191; java: 186,617; sh: 56,634; makefile: 18,856; objc: 13,092; perl: 12,763; pascal: 5,960; yacc: 4,583; cs: 3,846; lex: 1,720; ruby: 1,002; php: 436; lisp: 258; awk: 105; sql: 66; sed: 53; csh: 10; exp: 6
file content (128 lines) | stat: -rw-r--r-- 4,420 bytes parent folder | download
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
/* This Source Code Form is subject to the terms of the Mozilla Public
 * License, v. 2.0. If a copy of the MPL was not distributed with this
 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */

#include <algorithm>
#include <type_traits>

#include "gtest/gtest.h"
#include "mozilla/gtest/ipc/TestUtilityProcess.h"
#include "mozilla/gtest/WaitFor.h"
#include "nsThreadUtils.h"

#include "mozilla/ipc/UtilityProcessManager.h"

#if defined(MOZ_WIDGET_ANDROID) || defined(XP_MACOSX)
#  include "nsIAppShellService.h"
#  include "nsServiceManagerUtils.h"
#endif  // defined(MOZ_WIDGET_ANDROID) || defined(XP_MACOSX)

#if defined(XP_WIN)
#  include "mozilla/gtest/MozHelpers.h"
#  include "mozilla/ipc/UtilityProcessImpl.h"
#endif  // defined(XP_WIN)

#ifdef MOZ_WIDGET_ANDROID
#  define NS_APPSHELLSERVICE_CONTRACTID "@mozilla.org/widget/appshell/android;1"
#endif  // MOZ_WIDGET_ANDROID

#ifdef XP_MACOSX
#  define NS_APPSHELLSERVICE_CONTRACTID "@mozilla.org/widget/appshell/mac;1"
#endif  // XP_MACOSX

using namespace mozilla;
using namespace mozilla::gtest::ipc;
using namespace mozilla::ipc;

// Note that some test suites inherit TestUtilityProcess, so any change here
// will propagate there. Please ensure compatibility.
/* static */ void TestUtilityProcess::SetUpTestSuite() {
#if defined(XP_WIN) && defined(MOZ_SANDBOX)
  // Ensure only one execution even with GTEST_REPEAT>1
  static bool sOnce = false;
  if (!sOnce) {
    mozilla::SandboxBroker::GeckoDependentInitialize();
    sOnce = true;
  }
#endif  // defined(XP_WIN) && defined(MOZ_SANDBOX)

#if defined(MOZ_WIDGET_ANDROID) || defined(XP_MACOSX)
  // Ensure that the app shell service is running
  nsCOMPtr<nsIAppShellService> appShell =
      do_GetService(NS_APPSHELLSERVICE_CONTRACTID);
#endif  // defined(MOZ_WIDGET_ANDROID) || defined(XP_MACOSX)
}

TEST_F(TestUtilityProcess, LaunchAllKinds) {
  using kind_t = std::underlying_type<SandboxingKind>::type;

  auto manager = UtilityProcessManager::GetSingleton();
  ASSERT_TRUE(manager);

  auto currentPid = base::GetCurrentProcId();
  ASSERT_GE(currentPid, base::ProcessId(1));

  // Launch all kinds
  for (kind_t i = 0; i < SandboxingKind::COUNT; ++i) {
    auto kind = static_cast<SandboxingKind>(i);
    auto res = WaitFor(manager->LaunchProcess(kind));
    ASSERT_TRUE(res.isOk())
    << "First launch LaunchError: " << res.inspectErr().FunctionName() << ", "
    << res.inspectErr().ErrorCode();
  }

  // Collect process identifiers
  std::array<base::ProcessId, SandboxingKind::COUNT> pids{};
  for (kind_t i = 0; i < SandboxingKind::COUNT; ++i) {
    auto kind = static_cast<SandboxingKind>(i);
    auto utilityPid = manager->ProcessPid(kind);
    ASSERT_TRUE(utilityPid.isSome())
    << "No PID for kind " << kind;
    ASSERT_GE(*utilityPid, base::ProcessId(1));
    ASSERT_NE(*utilityPid, currentPid);

    printf_stderr("Utility process running as PID %" PRIPID "\n", *utilityPid);

    pids[i] = *utilityPid;
  }

  // Re-launching should resolve immediately with process identifiers unchanged
  for (kind_t i = 0; i < SandboxingKind::COUNT; ++i) {
    auto kind = static_cast<SandboxingKind>(i);
    auto res = WaitFor(manager->LaunchProcess(kind));
    ASSERT_TRUE(res.isOk())
    << "Second launch LaunchError: " << res.inspectErr().FunctionName() << ", "
    << res.inspectErr().ErrorCode();

    ASSERT_TRUE(manager->ProcessPid(kind) == Some(pids[i]));
  }

  // Check that every process identifier is unique
  std::sort(pids.begin(), pids.end());
  auto adjacentEqualPids = std::adjacent_find(pids.begin(), pids.end());
  ASSERT_TRUE(adjacentEqualPids == pids.end());

  // After being individually shut down, a process is no longer referenced
  for (kind_t i = 0; i < SandboxingKind::COUNT; ++i) {
    auto kind = static_cast<SandboxingKind>(i);
    manager->CleanShutdown(kind);
    ASSERT_TRUE(manager->ProcessPid(kind).isNothing());
  }

  // Drain the event queue.
  NS_ProcessPendingEvents(nullptr);
}

#if defined(XP_WIN)
static void LoadLibraryCrash_Test() {
  mozilla::gtest::DisableCrashReporter();
  // Just a uuidgen name to have something random
  UtilityProcessImpl::LoadLibraryOrCrash(
      L"2b49036e-6ba3-400c-a297-38fa1f6c5255.dll");
}

TEST_F(TestUtilityProcess, LoadLibraryCrash) {
  ASSERT_DEATH_IF_SUPPORTED(LoadLibraryCrash_Test(), "");
}
#endif  // defined(XP_WIN)