1 : // Copyright 2012 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 : // Declares a handful of common unittest helper functions.
16 :
17 : #ifndef SYZYGY_COMMON_UNITTEST_UTIL_H_
18 : #define SYZYGY_COMMON_UNITTEST_UTIL_H_
19 :
20 : #include <string>
21 : #include <vector>
22 :
23 : #include "base/environment.h"
24 : #include "base/logging.h"
25 : #include "base/files/file_path.h"
26 : #include "base/files/file_util.h"
27 : #include "base/memory/scoped_ptr.h"
28 : #include "gtest/gtest.h"
29 :
30 : namespace testing {
31 :
32 : const char kNtSymbolPathEnvVar[] = "_NT_SYMBOL_PATH";
33 :
34 : // Helper class to make sure that a test that plays with the log level doesn't
35 : // change it for other tests.
36 : class ScopedLogLevelSaver {
37 : public:
38 E : ScopedLogLevelSaver() : level_(logging::GetMinLogLevel()) {
39 E : }
40 :
41 E : ~ScopedLogLevelSaver() {
42 E : logging::SetMinLogLevel(level_);
43 E : }
44 :
45 : int level() const { return level_; }
46 :
47 : private:
48 : int level_;
49 : };
50 :
51 : // An intermediate class to add helper streams to a unit-test fixture.
52 : class ApplicationTestBase : public testing::Test {
53 : public:
54 E : ApplicationTestBase()
55 : : log_level_(0), log_handler_(NULL), log_to_console_(false) { }
56 :
57 : // @name IO Stream Accessors.
58 : // Call InitStreams() to route the IO streams to/from specific files;
59 : // otherwise, they will be routed to/from the NUL device on first use.
60 : // @{
61 E : FILE* in() const { return GetOrInitFile(&in_, "r"); }
62 E : FILE* out() const { return GetOrInitFile(&out_, "w"); }
63 E : FILE* err() const { return GetOrInitFile(&err_, "w"); }
64 : // @}
65 :
66 : // Initialize the IO Streams to send output to specific files. Also intercepts
67 : // logging messages.
68 : void InitStreams(const base::FilePath& in_path,
69 : const base::FilePath& out_path,
70 : const base::FilePath& err_path);
71 :
72 : // Manually tear down the various streams.
73 : void TearDownStreams();
74 :
75 : // Creates a temporary directory, which is cleaned up after the test runs.
76 E : void CreateTemporaryDir(base::FilePath* temp_dir) {
77 E : ASSERT_TRUE(base::CreateNewTempDirectory(L"", temp_dir));
78 E : temp_dirs_.push_back(*temp_dir);
79 E : }
80 :
81 : // Sets up before each test invocation.
82 : void SetUp() override;
83 :
84 : // Cleans up after each test invocation.
85 : void TearDown() override;
86 :
87 : // Disables logging for the test in which this is called.
88 E : void DisableLogging() {
89 E : logging::SetMinLogLevel(logging::LOG_FATAL);
90 E : }
91 :
92 : // Enables logging to screen for the test in which this is called.
93 : void EnableLoggingToConsole() {
94 : log_to_console_ = true;
95 : }
96 :
97 : protected:
98 : typedef testing::Test Super;
99 :
100 : // Used for logging interception, redirecting via err().
101 : static bool HandleLogMessage(int severity, const char* file, int line,
102 : size_t message_start, const std::string& str);
103 :
104 : // Tears down the given stream.
105 : static void TearDownStream(base::ScopedFILE* stream);
106 :
107 : // Helper to initialize a given stream to refer to the NUL device on first
108 : // use if it hasn't already been associated with a file.
109 : static FILE* GetOrInitFile(base::ScopedFILE* f, const char* mode);
110 :
111 : // List of temporary directories created during this test invocation.
112 : typedef std::vector<const base::FilePath> DirList;
113 : DirList temp_dirs_;
114 :
115 : // @name Replacements for the standard IO streams.
116 : //
117 : // By default they are routed to the NUL device (on first uninitialized use).
118 : //
119 : // @{
120 : mutable base::ScopedFILE in_;
121 : mutable base::ScopedFILE out_;
122 : mutable base::ScopedFILE err_;
123 : // @}
124 :
125 : // The logging level saved during SetUp. We restore this on TearDown.
126 : int log_level_;
127 :
128 : // The log message handler that was intercepted.
129 : logging::LogMessageHandlerFunction log_handler_;
130 :
131 : // If this is true then log messages handled by this fixture will be repeated
132 : // to the console rather than simply going to the wrapped stderr. Defaults to
133 : // false.
134 : bool log_to_console_;
135 :
136 : // The instance of this test that is redirecting logging. This only works for
137 : // a single instance at a time, but only one test is running at a time so
138 : // this is not really an issue.
139 : static ApplicationTestBase* self_;
140 : };
141 :
142 : // Helper class for setting an environment variable, then restoring it on
143 : // destruction.
144 : class ScopedEnvironmentVariable {
145 : public:
146 : ScopedEnvironmentVariable();
147 : ScopedEnvironmentVariable(base::StringPiece name, base::StringPiece value);
148 : ~ScopedEnvironmentVariable();
149 :
150 : // Overrides the environment variable.
151 : // @param name the name of the variable to override.
152 : // @param value the value of the override.
153 : // @returns true for the first call, false on subsequent calls.
154 : bool Set(base::StringPiece name, base::StringPiece value);
155 :
156 : private:
157 : std::string name_;
158 : bool should_restore_;
159 : std::string restore_value_;
160 :
161 : scoped_ptr<base::Environment> env_;
162 :
163 : DISALLOW_COPY_AND_ASSIGN(ScopedEnvironmentVariable);
164 : };
165 :
166 : // Helper class for setting up a symbol path that points to the output
167 : // directory.
168 : class ScopedSymbolPath {
169 : public:
170 E : ScopedSymbolPath() {}
171 E : ~ScopedSymbolPath() {}
172 :
173 : // Constructs the symbol path and sets the kNtSymbolPathEnvVar variable.
174 : bool Setup();
175 :
176 : private:
177 : ScopedEnvironmentVariable nt_symbol_path_;
178 :
179 : DISALLOW_COPY_AND_ASSIGN(ScopedSymbolPath);
180 : };
181 :
182 : } // namespace testing
183 :
184 : #endif // SYZYGY_COMMON_UNITTEST_UTIL_H_
|