File: unit_test_util_unittest.cc

package info (click to toggle)
chromium 139.0.7258.127-1
  • links: PTS, VCS
  • area: main
  • in suites:
  • size: 6,122,068 kB
  • sloc: cpp: 35,100,771; ansic: 7,163,530; javascript: 4,103,002; python: 1,436,920; asm: 946,517; xml: 746,709; pascal: 187,653; perl: 88,691; sh: 88,436; objc: 79,953; sql: 51,488; cs: 44,583; fortran: 24,137; makefile: 22,147; tcl: 15,277; php: 13,980; yacc: 8,984; ruby: 7,485; awk: 3,720; lisp: 3,096; lex: 1,327; ada: 727; jsp: 228; sed: 36
file content (186 lines) | stat: -rw-r--r-- 6,889 bytes parent folder | download | duplicates (5)
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
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
// Copyright 2020 The Chromium Authors
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#include "chrome/updater/test/unit_test_util.h"

#include <optional>
#include <string>
#include <vector>

#include "base/base_paths.h"
#include "base/command_line.h"
#include "base/files/file_path.h"
#include "base/files/file_util.h"
#include "base/files/scoped_temp_dir.h"
#include "base/logging.h"
#include "base/path_service.h"
#include "base/process/launch.h"
#include "base/process/process.h"
#include "base/strings/stringprintf.h"
#include "base/strings/utf_string_conversions.h"
#include "base/synchronization/waitable_event.h"
#include "base/test/test_timeouts.h"
#include "build/build_config.h"
#include "chrome/updater/test/integration_tests_impl.h"
#include "chrome/updater/test/test_scope.h"
#include "testing/gtest/include/gtest/gtest.h"
#include "third_party/re2/src/re2/re2.h"

#if BUILDFLAG(IS_WIN)
#include <windows.h>

#include "base/strings/string_number_conversions_win.h"
#include "chrome/updater/util/win_util.h"
#include "chrome/updater/win/test/test_executables.h"
#include "chrome/updater/win/test/test_strings.h"
#endif

namespace updater::test {
namespace {

std::string ToString(const std::string& s) {
  return s;
}

std::string ToString(const std::wstring& s) {
  return base::WideToUTF8(s);
}

}  // namespace

TEST(UnitTestUtil, ToString) {
  EXPECT_EQ(ToString("test"), ToString(L"test"));
}

TEST(UnitTestUtil, Processes) {
  auto print_processes_tester =
      [](const base::FilePath::StringType& process_name) {
        const std::string print_processes = PrintProcesses(process_name);
        const std::string regex_string = base::StringPrintf(
            R"(Found processes:\n)"
            R"(={72}\n(%s, pid=\d*, creation time=.*\n){2}={72}\n$)",
            ToString(process_name).c_str());
        bool is_match =
            re2::RE2::FullMatch(print_processes, re2::RE2(regex_string));
        if (!is_match) {
          ADD_FAILURE() << "regex:'" << regex_string << "'" << std::endl
                        << print_processes;
        }
        return is_match;
      };
#if BUILDFLAG(IS_WIN)
  // Ensure the test process is not running before the test.
  EXPECT_TRUE(KillProcesses(kTestProcessExecutableName, 0));
  EXPECT_TRUE(WaitForProcessesToExit(kTestProcessExecutableName,
                                     TestTimeouts::action_timeout()));
  EXPECT_FALSE(IsProcessRunning(kTestProcessExecutableName));

  // Start two long-lived processes and expect to find them running.
  std::vector<base::Process> long_running;
  long_running.push_back(
      LongRunningProcess(GetUpdaterScopeForTesting(), GetTestName(), nullptr));
  long_running.push_back(
      LongRunningProcess(GetUpdaterScopeForTesting(), GetTestName(), nullptr));
  for (const base::Process& p : long_running) {
    EXPECT_TRUE(p.IsValid());
  }
  EXPECT_TRUE(IsProcessRunning(kTestProcessExecutableName));

  EXPECT_TRUE(print_processes_tester(kTestProcessExecutableName));

  // Terminate the long-lived processes, expect to find them not running, then
  // inspect their exit code.
  static constexpr int kExitCode = 12345;
  EXPECT_FALSE(WaitForProcessesToExit(kTestProcessExecutableName,
                                      base::Milliseconds(1)));
  EXPECT_TRUE(KillProcesses(kTestProcessExecutableName, kExitCode));
  EXPECT_TRUE(WaitForProcessesToExit(kTestProcessExecutableName,
                                     TestTimeouts::action_timeout()));
  EXPECT_FALSE(IsProcessRunning(kTestProcessExecutableName));
  for (const base::Process& p : long_running) {
    int exit_code = 0;
    EXPECT_TRUE(
        p.WaitForExitWithTimeout(TestTimeouts::tiny_timeout(), &exit_code));
    EXPECT_EQ(exit_code, kExitCode);
  }
#else
  // Test the state of the process for the unit test process itself.
  base::FilePath::StringType unit_test = [] {
    base::FilePath unit_test_executable;
    base::PathService::Get(base::FILE_EXE, &unit_test_executable);
    return unit_test_executable.BaseName().value();
  }();
  EXPECT_TRUE(IsProcessRunning(unit_test));
  EXPECT_FALSE(WaitForProcessesToExit(unit_test, base::Milliseconds(1)));
  EXPECT_TRUE(print_processes_tester(unit_test));
#endif  // IS_WIN
}

TEST(UnitTestUtil, GetTestName) {
  EXPECT_EQ(GetTestName(), "UnitTestUtil.GetTestName");
}

// Enable the test to print the effective values for the test timeouts when
// debugging timeout issues.
TEST(UnitTestUtil, DISABLED_PrintTestTimeouts) {
  VLOG(0) << "action-timeout:"
          << TestTimeouts::action_timeout().InMilliseconds()
          << ", action-max-timeout:"
          << TestTimeouts::action_max_timeout().InMilliseconds()
          << ", test-launcher-timeout:"
          << TestTimeouts::test_launcher_timeout().InMilliseconds();
}

TEST(UnitTestUtil, DeleteFileAndEmptyParentDirectories) {
  EXPECT_FALSE(DeleteFileAndEmptyParentDirectories(std::nullopt));

  const base::FilePath path_not_found(FILE_PATH_LITERAL("path-not-found"));
  EXPECT_TRUE(DeleteFileAndEmptyParentDirectories(path_not_found));

  // Create something in temp so that `DeleteFileAndEmptyParentDirectories()`
  // does not delete the temp directory of this process because it is empty.
  base::ScopedTempDir a_temp_dir;
  ASSERT_TRUE(a_temp_dir.CreateUniqueTempDir());

  base::FilePath temp_path;
  ASSERT_TRUE(GetTempDir(&temp_path));

  // Create and delete the following path "some_dir/dir_in_dir/file_in_dir".
  base::ScopedTempDir temp_dir;
  ASSERT_TRUE(temp_dir.CreateUniqueTempDir());
  base::FilePath dir_in_dir;
  EXPECT_TRUE(base::CreateTemporaryDirInDir(
      temp_dir.GetPath(), FILE_PATH_LITERAL("UnitTestUtil"), &dir_in_dir));
  base::FilePath file_in_dir;
  EXPECT_TRUE(CreateTemporaryFileInDir(dir_in_dir, &file_in_dir));
  EXPECT_TRUE(DeleteFileAndEmptyParentDirectories(file_in_dir));
  EXPECT_FALSE(base::DirectoryExists(temp_dir.GetPath()));
  EXPECT_TRUE(base::DirectoryExists(temp_path));
}

#if BUILDFLAG(IS_WIN)
TEST(UnitTestUtil, FindProcesses) {
  base::CommandLine command_line = GetTestProcessCommandLine(
      GetUpdaterScopeForTesting(), test::GetTestName());

  // Create a unique name for a shared event to be waited for in the test
  // process and signaled in this test.
  EventHolder event_holder(CreateWaitableEventForTest());

  command_line.AppendSwitchNative(kTestEventToWaitOn, event_holder.name);

  const base::Process process = base::LaunchProcess(command_line, {});
  ASSERT_TRUE(process.IsValid());

  EXPECT_TRUE(test::WaitFor([&] { return process.IsRunning(); }));
  EXPECT_EQ(test::FindProcesses(kTestProcessExecutableName).size(), 1U);

  event_holder.event.Signal();

  EXPECT_TRUE(test::WaitFor([&] { return !process.IsRunning(); }));
  EXPECT_TRUE(test::FindProcesses(kTestProcessExecutableName).empty());
}
#endif  // BUILDFLAG(IS_WIN)

}  // namespace updater::test