1 // Copyright 2020 The Bazel Authors. 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 <cstdlib>
16 #include <fstream>
17 #include <iostream>
18 #include <string>
19
basic_part1_test(std::string current_dir_arg)20 void basic_part1_test(std::string current_dir_arg) {
21 if (current_dir_arg != "--current-dir") {
22 std::cerr << "error: argument \"--current-dir\" not found.\n";
23 std::exit(1);
24 }
25 }
26
basic_part2_test(std::string current_dir,const char * envp[])27 void basic_part2_test(std::string current_dir, const char* envp[]) {
28 if (current_dir != "${pwd}") {
29 std::cerr << "error: unsubsituted ${pwd} not found.\n";
30 std::exit(1);
31 }
32 const std::string current_dir_env = "CURRENT_DIR=${pwd}/test_path";
33 bool found = false;
34 for (int i = 0; envp[i] != nullptr; ++i) {
35 if (current_dir_env == envp[i]) {
36 found = true;
37 break;
38 }
39 }
40 if (!found) {
41 std::cerr << "unsubsituted CURRENT_DIR not found.\n";
42 std::exit(1);
43 }
44 }
45
subst_pwd_test(int argc,const char * argv[],const char * envp[])46 void subst_pwd_test(int argc, const char* argv[], const char* envp[]) {
47 std::string current_dir = argv[3];
48 if (current_dir.find("${pwd}") != std::string::npos) {
49 std::cerr << "error: argument ${pwd} substitution failed.\n";
50 std::exit(1);
51 }
52 // find the param file using its "@" prefix
53 std::string param_file;
54 for (int i = 1; i < argc; ++i) {
55 if (argv[i][0] == '@') {
56 param_file = std::string(argv[i] + 1);
57 break;
58 }
59 }
60 if (param_file.empty()) {
61 std::cerr << "error: no param file.\n";
62 std::exit(1);
63 }
64 std::string param_file_line;
65 getline(std::ifstream(param_file), param_file_line);
66 if (param_file_line != current_dir) {
67 std::cerr << "error: param file " << param_file << " should contain "
68 << current_dir << ", found " << param_file_line << ".\n";
69 std::exit(1);
70 }
71 bool found = false;
72 for (int i = 0; envp[i] != nullptr; ++i) {
73 const std::string env = envp[i];
74 if (env.rfind("CURRENT_DIR", 0) == 0) {
75 found = true;
76 if (env.find("${pwd}") != std::string::npos) {
77 std::cerr << "error: environment variable ${pwd} substitution "
78 "failed.\n";
79 std::exit(1);
80 }
81 break;
82 }
83 }
84 if (!found) {
85 std::cerr << "CURRENT_DIR not found.\n";
86 std::exit(1);
87 }
88 }
89
env_files_test(const char * envp[])90 void env_files_test(const char* envp[]) {
91 const std::string must_exist[] = {
92 "FOO=BAR",
93 "FOOBAR=BARFOO",
94 "BAR=FOO",
95 "ENV_ESCAPE=with\nnew line",
96 "ENV_NO_ESCAPE=with no new line\\",
97 "ENV_ESCAPE_WITH_BACKSLASH=new line\\\nhere",
98 };
99 for (const std::string& env : must_exist) {
100 bool found = false;
101 for (int i = 0; envp[i] != nullptr; ++i) {
102 if (env == envp[i]) {
103 found = true;
104 break;
105 }
106 }
107 if (!found) {
108 std::cerr << "error: environment variable \"" << env
109 << "\" not found.\n";
110 std::exit(1);
111 }
112 }
113 }
114
arg_files_test(int argc,const char * argv[])115 void arg_files_test(int argc, const char* argv[]) {
116 const std::string must_exist[] = {
117 "--arg1=foo",
118 "--arg2",
119 "foo bar",
120 "--arg2=bar",
121 "--arg3",
122 "foobar",
123 "arg with\nnew line",
124 "arg with\\",
125 "no new line",
126 "arg with\\\nnew line and a trailing backslash",
127 };
128
129 for (const std::string& arg : must_exist) {
130 bool found = false;
131 for (int i = 0; i < argc; ++i) {
132 if (arg == argv[i]) {
133 found = true;
134 break;
135 }
136 }
137 if (!found) {
138 std::cerr << "error: argument \"" << arg << "\" not found.\n";
139 std::exit(1);
140 }
141 }
142 }
143
test_stdout()144 void test_stdout() {
145 for (int i = 0; i < 10000; ++i) {
146 // On windows writing LF to any stream in text mode gets changed to CRLF
147 // Since the test file is saved using CRLF, we are forcing the same on
148 // non windows systems
149 #if defined(_WIN32)
150 std::cout << "Child process to stdout : " << i << "\n";
151 #else
152 std::cout << "Child process to stdout : " << i << "\r\n";
153 #endif // defined(_WIN32)
154 }
155 }
156
test_stderr()157 void test_stderr() { std::cerr << "This is the stderr output"; }
158
main(int argc,const char * argv[],const char * envp[])159 int main(int argc, const char* argv[], const char* envp[]) {
160 if (argc < 4) {
161 std::cerr << "error: Invalid number of args exected at least 4 got "
162 << argc << ".\n";
163 return 1;
164 }
165 std::string test_config = argv[1];
166 bool combined = test_config == "combined";
167 if (combined || test_config == "basic") {
168 basic_part1_test(argv[2]);
169 }
170
171 if (combined || test_config == "subst-pwd") {
172 subst_pwd_test(argc, argv, envp);
173 } else if (test_config == "basic") {
174 basic_part2_test(argv[3], envp);
175 }
176
177 if (combined || test_config == "env-files") {
178 env_files_test(envp);
179 }
180
181 if (combined || test_config == "arg-files") {
182 arg_files_test(argc, argv);
183 }
184
185 if (combined || test_config == "stdout") {
186 test_stdout();
187 }
188
189 if (combined || test_config == "stderr") {
190 test_stderr();
191 }
192 }
193