| // Copyright 2023 Google Inc. All Rights Reserved. |
| // |
| // Licensed under the Apache License, Version 2.0 (the "License"); |
| // you may not use this file except in compliance with the License. |
| // You may obtain a copy of the License at |
| // |
| // http://www.apache.org/licenses/LICENSE-2.0 |
| // |
| // Unless required by applicable law or agreed to in writing, software |
| // distributed under the License is distributed on an "AS IS" BASIS, |
| // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
| // See the License for the specific language governing permissions and |
| // limitations under the License. |
| |
| #include "persistent_mode_test_lib.h" |
| |
| #ifdef _WIN32 |
| #include "getopt.h" |
| #elif defined(_AIX) |
| #include "getopt.h" |
| #else |
| #include <getopt.h> |
| #endif |
| |
| #include <string> |
| |
| #include "util.h" |
| |
| namespace persistent_mode_test { |
| |
| namespace { |
| |
| struct ServerState { |
| ServerState(const PersistentMode::Compatibility& compatibility, |
| int64_t connection_timeout_ms) |
| : server_(compatibility) { |
| server_.SetConnectionTimeoutMs(connection_timeout_ms); |
| } |
| |
| void RunServerThenExit() { |
| server_.RunServerThenExit( |
| [this]() { return RestartCheck(); }, |
| [this](const PersistentMode::BuildQuery& query) -> int { |
| return HandleQuery(query); |
| }); |
| } |
| |
| bool RestartCheck() { return false; }; |
| |
| int HandleQuery(const PersistentMode::BuildQuery& query) { |
| if (query.tool == "print-current-dir") { |
| fprintf(stdout, "%s", GetCurrentDir().c_str()); |
| return 0; |
| } |
| if (query.tool == "get-env-vars") { |
| for (const auto& varname : query.args) { |
| const char* varvalue = query.config.environment.Get(varname.c_str()); |
| if (!varvalue) |
| varvalue = "<UNSET>"; |
| fprintf(stdout, "%s=%s\n", varname.c_str(), varvalue); |
| } |
| return 0; |
| } |
| fprintf(stderr, "UNKNOWN QUERY TYPE!\n"); |
| return 1; |
| } |
| |
| // Create new query to print the current directory. |
| static PersistentMode::BuildQuery MakeQuery1(const std::string& build_dir) { |
| PersistentMode::BuildQuery query; |
| query.tool = "print-current-dir"; |
| return query; |
| } |
| |
| // Create a new query to print the environment variables of the server |
| // process. |
| static PersistentMode::BuildQuery MakeQuery2( |
| const std::vector<std::string>& print_variables) { |
| PersistentMode::BuildQuery query; |
| query.tool = "get-env-vars"; |
| query.args = print_variables; |
| return query; |
| } |
| PersistentMode::Server server_; |
| }; |
| |
| } // namespace |
| |
| std::string GetServerExecutable() { |
| std::string result = |
| GetCurrentExecutableDir() + "/persistent_mode_test_helper"; |
| #ifdef _WIN32 |
| result += ".exe"; |
| #endif |
| return result; |
| } |
| |
| PersistentMode::Compatibility GetClientCompatibility( |
| const std::string& build_dir) { |
| PersistentMode::Compatibility result; |
| result.SetNinjaVersionForTest("version-1.0") |
| .SetInputFile("persistent_mode.input") |
| .SetBuildDir(build_dir); |
| return result; |
| } |
| |
| PersistentMode::Compatibility GetServerCompatibility( |
| int argc, char** argv, int64_t* connection_timeout_ms) { |
| const char* progname = argv[0]; |
| |
| auto print_usage = [progname]() { |
| fprintf(stderr, |
| "Usage: %s [-C BUILD_DIR] [-f INPUT_FILE] [-t TIMEOUT_MILLIS] [-w " |
| "WARNING]+\n", |
| progname); |
| exit(1); |
| }; |
| |
| PersistentMode::Compatibility result; |
| |
| int opt; |
| while ((opt = getopt(argc, argv, const_cast<char*>("C:f:w:t:"))) != -1) { |
| fprintf(stderr, "OPT %c\n", opt); |
| switch (opt) { |
| case 'C': |
| result.SetBuildDir(optarg); |
| break; |
| case 'f': |
| result.SetInputFile(optarg); |
| break; |
| case 'w': |
| if (!strcmp(optarg, "dupbuild=err")) { |
| result.SetFlagDupeEdgesShouldErr(true); |
| } else if (!strcmp(optarg, "dupbuild=warn")) { |
| result.SetFlagDupeEdgesShouldErr(false); |
| } else if (!strcmp(optarg, "phonycycle=err")) { |
| result.SetFlagPhonyCycleShouldErr(true); |
| } else if (!strcmp(optarg, "phonycycle=warn")) { |
| result.SetFlagPhonyCycleShouldErr(false); |
| } else { |
| Fatal("Unknown -d argument value: %s", optarg); |
| } |
| break; |
| case 't': |
| *connection_timeout_ms = static_cast<int64_t>(atoll(optarg)); |
| break; |
| default: |
| print_usage(); |
| } |
| } |
| fprintf(stderr, "argc=%d optind=%d\n", argc, optind); |
| argc -= optind; |
| argv += optind; |
| if (argc > 0) |
| print_usage(); |
| |
| // Must match the version in GetClientCompatibility(). |
| result.SetNinjaVersionForTest("version-1.0"); |
| return result; |
| } |
| |
| PersistentMode::BuildQuery GetClientTestQuery1(const std::string& build_dir) { |
| return ServerState::MakeQuery1(build_dir); |
| } |
| |
| PersistentMode::BuildQuery GetClientTestQuery2( |
| const std::vector<std::string>& print_variables) { |
| return ServerState::MakeQuery2(print_variables); |
| } |
| |
| void RunServerThenExit(const PersistentMode::Compatibility& compatibility, |
| int64_t connection_timeout_ms) { |
| ServerState state(compatibility, connection_timeout_ms); |
| state.RunServerThenExit(); |
| } |
| |
| } // namespace persistent_mode_test |