/proc/self/cwd/test/test_common/environment.h
Line | Count | Source (jump to first uncovered line) |
1 | | #pragma once |
2 | | |
3 | | #include <cstdint> |
4 | | #include <string> |
5 | | #include <vector> |
6 | | |
7 | | #include "envoy/network/address.h" |
8 | | #include "envoy/server/options.h" |
9 | | |
10 | | #include "source/common/json/json_loader.h" |
11 | | |
12 | | #include "absl/container/node_hash_map.h" |
13 | | #include "absl/strings/str_cat.h" |
14 | | #include "absl/strings/string_view.h" |
15 | | #include "absl/types/optional.h" |
16 | | #include "tools/cpp/runfiles/runfiles.h" |
17 | | |
18 | | namespace Envoy { |
19 | | |
20 | | namespace Grpc { |
21 | | |
22 | | // Support parameterizing over gRPC client type. |
23 | | enum class ClientType { EnvoyGrpc, GoogleGrpc }; |
24 | | |
25 | | } // namespace Grpc |
26 | | |
27 | | class TestEnvironment { |
28 | | public: |
29 | | using PortMap = absl::node_hash_map<std::string, uint32_t>; |
30 | | |
31 | | using ParamMap = absl::node_hash_map<std::string, std::string>; |
32 | | |
33 | | /** |
34 | | * Perform common initialization steps needed to run a test binary. This |
35 | | * method should be called first in all test main functions. |
36 | | * @param program_name argv[0] test program is invoked with |
37 | | */ |
38 | | static void initializeTestMain(char* program_name); |
39 | | |
40 | | /** |
41 | | * Initialize command-line options for later access by tests in getOptions(). |
42 | | * @param argc number of command-line args. |
43 | | * @param argv array of command-line args. |
44 | | */ |
45 | | static void initializeOptions(int argc, char** argv); |
46 | | |
47 | | /** |
48 | | * Check whether testing with IP version type {v4 or v6} is enabled via |
49 | | * setting the environment variable ENVOY_IP_TEST_VERSIONS. |
50 | | * @param Network::Address::IpVersion IP address version to check. |
51 | | * @return bool if testing only with IP type addresses only. |
52 | | */ |
53 | | static bool shouldRunTestForIpVersion(Network::Address::IpVersion type); |
54 | | |
55 | | /** |
56 | | * Return a vector of IP address parameters to test. Tests can be run with |
57 | | * only IPv4 addressing or only IPv6 addressing by setting the environment |
58 | | * variable ENVOY_IP_TEST_VERSIONS to "v4only" or "v6only", respectively. |
59 | | * The default test setting runs all tests with both IPv4 and IPv6 addresses. |
60 | | * @return std::vector<Network::Address::IpVersion> vector of IP address |
61 | | * types to test. |
62 | | */ |
63 | | static std::vector<Network::Address::IpVersion> getIpVersionsForTest(); |
64 | | |
65 | | /** |
66 | | * Return a vector of spdlog loggers as parameters to test. Tests are mainly |
67 | | * for the behavior consistency between default loggers and fine-grained loggers. |
68 | | * @return std::vector<spdlog::logger*> |
69 | | */ |
70 | | static std::vector<spdlog::logger*> getSpdLoggersForTest(); |
71 | | |
72 | | /** |
73 | | * Tests can be run with Envoy Grpc and Google Grpc or Envoy Grpc alone by setting compiler option |
74 | | * `--define google_grpc=disabled`. |
75 | | * @return a vector of Grpc versions to test. |
76 | | */ |
77 | | static std::vector<Grpc::ClientType> getsGrpcVersionsForTest(); |
78 | | |
79 | | /** |
80 | | * Obtain command-line options reference. |
81 | | * @return Server::Options& with command-line options. |
82 | | */ |
83 | | static Server::Options& getOptions(); |
84 | | |
85 | | /** |
86 | | * Obtain the value of an environment variable, null if not available. |
87 | | * @return absl::optional<std::string> with the value of the environment variable. |
88 | | */ |
89 | | static absl::optional<std::string> getOptionalEnvVar(const std::string& var); |
90 | | |
91 | | /** |
92 | | * Obtain the value of an environment variable, die if not available. |
93 | | * @return std::string with the value of the environment variable. |
94 | | */ |
95 | | static std::string getCheckedEnvVar(const std::string& var); |
96 | | |
97 | | /** |
98 | | * Obtain a private writable temporary directory. |
99 | | * @return const std::string& with the path to the temporary directory. |
100 | | */ |
101 | | static const std::string& temporaryDirectory(); |
102 | | |
103 | | /** |
104 | | * Prefix a given path with the private writable test temporary directory. |
105 | | * @param path path suffix. |
106 | | * @return std::string path qualified with temporary directory. |
107 | | */ |
108 | 12.4k | static std::string temporaryPath(absl::string_view path) { |
109 | 12.4k | return absl::StrCat(temporaryDirectory(), "/", path); |
110 | 12.4k | } |
111 | | |
112 | | /** |
113 | | * Obtain platform specific new line character(s) |
114 | | * @return absl::string_view platform specific new line character(s) |
115 | | */ |
116 | | static constexpr absl::string_view newLine |
117 | | #ifdef WIN32 |
118 | | {"\r\n"}; |
119 | | #else |
120 | | {"\n"}; |
121 | | #endif |
122 | | |
123 | | /** |
124 | | * Obtain read-only test input data directory. |
125 | | * @param workspace the name of the Bazel workspace where the input data is. |
126 | | * @return const std::string& with the path to the read-only test input directory. |
127 | | */ |
128 | | static std::string runfilesDirectory(const std::string& workspace = "envoy"); |
129 | | |
130 | | /** |
131 | | * Prefix a given path with the read-only test input data directory. |
132 | | * @param path path suffix. |
133 | | * @return std::string path qualified with read-only test input data directory. |
134 | | */ |
135 | | static std::string runfilesPath(const std::string& path, const std::string& workspace = "envoy"); |
136 | | |
137 | | /** |
138 | | * Obtain Unix Domain Socket temporary directory. |
139 | | * @return std::string& with the path to the Unix Domain Socket temporary directory. |
140 | | */ |
141 | | static const std::string unixDomainSocketDirectory(); |
142 | | |
143 | | /** |
144 | | * Prefix a given path with the Unix Domain Socket temporary directory. |
145 | | * @param path path suffix. |
146 | | * @param abstract_namespace true if an abstract namespace should be returned. |
147 | | * @return std::string path qualified with the Unix Domain Socket temporary directory. |
148 | | */ |
149 | | static std::string unixDomainSocketPath(const std::string& path, |
150 | 0 | bool abstract_namespace = false) { |
151 | 0 | return (abstract_namespace ? "@" : "") + unixDomainSocketDirectory() + "/" + path; |
152 | 0 | } |
153 | | |
154 | | /** |
155 | | * String environment path, loopback, and DNS resolver type substitution. |
156 | | * @param str string with template patterns including {{ test_tmpdir }}. |
157 | | * @param version supplies the IP version to substitute for relevant templates. |
158 | | * @return std::string with patterns replaced with environment values. |
159 | | */ |
160 | | static std::string |
161 | | substitute(const std::string& str, |
162 | | Network::Address::IpVersion version = Network::Address::IpVersion::v4); |
163 | | |
164 | | /** |
165 | | * Substitute ports, paths, and IP loopback addresses in a JSON file in the |
166 | | * private writable test temporary directory. |
167 | | * @param path path prefix for the input file with port and path templates. |
168 | | * @param port_map map from port name to port number. |
169 | | * @param version IP address version to substitute. |
170 | | * @return std::string path for the generated file. |
171 | | */ |
172 | | static std::string temporaryFileSubstitute(const std::string& path, const PortMap& port_map, |
173 | | Network::Address::IpVersion version); |
174 | | /** |
175 | | * Substitute ports, paths, and IP loopback addresses in a JSON file in the |
176 | | * private writable test temporary directory. |
177 | | * @param path path prefix for the input file with port and path templates. |
178 | | * @param param_map map from parameter name to values. |
179 | | * @param port_map map from port name to port number. |
180 | | * @param version IP address version to substitute. |
181 | | * @return std::string path for the generated file. |
182 | | */ |
183 | | static std::string temporaryFileSubstitute(const std::string& path, const ParamMap& param_map, |
184 | | const PortMap& port_map, |
185 | | Network::Address::IpVersion version); |
186 | | |
187 | | /** |
188 | | * Build JSON object from a string subject to environment path, loopback, and DNS resolver type |
189 | | * substitution. |
190 | | * @param json JSON with template patterns including {{ test_certs }}. |
191 | | * @param version supplies the IP version to substitute for relevant templates. |
192 | | * @return Json::ObjectSharedPtr with built JSON object. |
193 | | */ |
194 | | static Json::ObjectSharedPtr |
195 | | jsonLoadFromString(const std::string& json, |
196 | | Network::Address::IpVersion version = Network::Address::IpVersion::v4); |
197 | | |
198 | | #ifndef TARGET_OS_IOS |
199 | | /** |
200 | | * Execute a program under ::system. Any failure is fatal. |
201 | | * @param args program path and arguments. |
202 | | */ |
203 | | |
204 | | static void exec(const std::vector<std::string>& args); |
205 | | #endif |
206 | | |
207 | | /** |
208 | | * Dumps the contents of the string into a temporary file from temporaryDirectory() + filename. |
209 | | * |
210 | | * @param filename: the name of the file to use |
211 | | * @param contents: the data to go in the file. |
212 | | * @param fully_qualified_path: if true, will write to filename without prepending the tempdir. |
213 | | * @param unlink: if true will delete any prior file before writing. |
214 | | * @return the fully qualified path of the output file. |
215 | | */ |
216 | | static std::string writeStringToFileForTest(const std::string& filename, |
217 | | const std::string& contents, |
218 | | bool fully_qualified_path = false, |
219 | | bool unlink = true); |
220 | | /** |
221 | | * Dumps the contents of the file into the string. |
222 | | * |
223 | | * @param filename: the fully qualified name of the file to use |
224 | | */ |
225 | | static std::string readFileToStringForTest(const std::string& filename); |
226 | | |
227 | | /** |
228 | | * Create a path on the filesystem (mkdir -p ... equivalent). |
229 | | * @param path. |
230 | | */ |
231 | | static void createPath(const std::string& path); |
232 | | |
233 | | /** |
234 | | * Remove a path on the filesystem (rm -rf ... equivalent). |
235 | | * @param path. |
236 | | */ |
237 | | static void removePath(const std::string& path); |
238 | | |
239 | | /** |
240 | | * Rename a file |
241 | | * @param old_name |
242 | | * @param new_name |
243 | | */ |
244 | | static void renameFile(const std::string& old_name, const std::string& new_name); |
245 | | |
246 | | /** |
247 | | * Create a symlink |
248 | | * @param target |
249 | | * @param link |
250 | | */ |
251 | | static void createSymlink(const std::string& target, const std::string& link); |
252 | | |
253 | | /** |
254 | | * Set environment variable. Same args as setenv(2). |
255 | | */ |
256 | | static void setEnvVar(const std::string& name, const std::string& value, int overwrite); |
257 | | |
258 | | /** |
259 | | * Removes environment variable. Same args as unsetenv(3). |
260 | | */ |
261 | | static void unsetEnvVar(const std::string& name); |
262 | | |
263 | | /** |
264 | | * Set runfiles with current test, this have to be called before calling path related functions. |
265 | | */ |
266 | | static void setRunfiles(bazel::tools::cpp::runfiles::Runfiles* runfiles); |
267 | | |
268 | | private: |
269 | | static bazel::tools::cpp::runfiles::Runfiles* runfiles_; |
270 | | }; |
271 | | |
272 | | /** |
273 | | * A utility class for atomically updating a file using symbolic link swap. |
274 | | * Note the file lifetime is limited to the instance of the AtomicFileUpdater |
275 | | * which erases any existing files upon creation, used for specific test |
276 | | * scenarios. See discussion at https://github.com/envoyproxy/envoy/pull/4298 |
277 | | */ |
278 | | class AtomicFileUpdater { |
279 | | public: |
280 | | AtomicFileUpdater(const std::string& filename); |
281 | | |
282 | | void update(const std::string& contents); |
283 | | |
284 | | private: |
285 | | const std::string link_; |
286 | | const std::string new_link_; |
287 | | const std::string target1_; |
288 | | const std::string target2_; |
289 | | bool use_target1_{true}; |
290 | | }; |
291 | | |
292 | | } // namespace Envoy |