// Copyright 2017 The Bazel Authors. 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 #include #include #include #include #include "src/tools/launcher/util/data_parser.h" #include "gtest/gtest.h" #include "src/tools/launcher/util/launcher_util.h" namespace bazel { namespace launcher { using std::getenv; using std::ios; using std::make_unique; using std::ofstream; using std::pair; using std::string; using std::unique_ptr; using std::vector; class LaunchDataParserTest : public ::testing::Test { protected: LaunchDataParserTest() {} virtual ~LaunchDataParserTest() {} void SetUp() override { char* tmpdir = getenv("TEST_TMPDIR"); if (tmpdir != NULL) { test_tmpdir = string(tmpdir); } else { tmpdir = getenv("TEMP"); ASSERT_FALSE(tmpdir == NULL); test_tmpdir = string(tmpdir); } } void TearDown() override {} static void WriteBinaryFileWithList(const string& binary_file, const vector& launch_info) { ofstream binary_file_stream(binary_file, ios::out | ios::binary); int64_t data_size = 0; for (auto const& entry : launch_info) { binary_file_stream << entry; binary_file_stream << '\0'; data_size += entry.length() + 1; } binary_file_stream.write(reinterpret_cast(&data_size), sizeof(data_size)); } static void WriteBinaryFileWithMap( const string& binary_file, const vector>& launch_info) { ofstream binary_file_stream(binary_file, ios::out | ios::binary); int64_t data_size = 0; for (auto const& entry : launch_info) { binary_file_stream << entry.first; binary_file_stream.put('='); binary_file_stream << entry.second; binary_file_stream.put('\0'); data_size += entry.first.length() + entry.second.length() + 2; } binary_file_stream.write(reinterpret_cast(&data_size), sizeof(data_size)); } static bool ParseBinaryFile( const string& binary_file, LaunchDataParser::LaunchInfo* parsed_launch_info) { if (LaunchDataParser::GetLaunchInfo(binary_file, parsed_launch_info)) { return true; } exit(-1); } string GetLaunchInfo(const string& key) const { auto item = parsed_launch_info->find(key); if (item == parsed_launch_info->end()) { return "Cannot find key: " + key; } return item->second; } string test_tmpdir; unique_ptr parsed_launch_info; }; TEST_F(LaunchDataParserTest, GetLaunchInfoTest) { vector> launch_info = { {"binary_type", "Bash"}, {"workspace_name", "__main__"}, {"bash_bin_path", "C:\\foo\\bar\\bash.exe"}, {"bash_main_file", "./bazel-bin/foo/bar/bin.sh"}, {"empty_value_key", ""}, }; string binary_file = test_tmpdir + "/binary_file"; WriteBinaryFileWithMap(binary_file, launch_info); parsed_launch_info = make_unique(); ASSERT_TRUE(ParseBinaryFile(binary_file, parsed_launch_info.get())); for (auto const& entry : launch_info) { ASSERT_EQ(entry.second, GetLaunchInfo(entry.first)); } ASSERT_EQ(GetLaunchInfo("no_such_key"), "Cannot find key: no_such_key"); } TEST_F(LaunchDataParserTest, EmptyLaunchInfoTest) { string binary_file = test_tmpdir + "/empty_binary_file"; WriteBinaryFileWithMap(binary_file, {}); parsed_launch_info = make_unique(); // ASSERT_DEATH requires TEMP environment variable to be set. // Otherwise, it will try to write to C:/Windows, then fails. // A workaround in Bazel is to use --action_env to set TEMP. ASSERT_DEATH(ParseBinaryFile(binary_file, parsed_launch_info.get()), "LAUNCHER ERROR: No data appended, cannot launch anything!"); } TEST_F(LaunchDataParserTest, DuplicatedLaunchInfoTest) { string binary_file = test_tmpdir + "/duplicated_binary_file"; WriteBinaryFileWithMap(binary_file, { {"foo", "bar1"}, {"foo", "bar2"}, }); parsed_launch_info = make_unique(); // ASSERT_DEATH requires TEMP environment variable to be set. // Otherwise, it will try to write to C:/Windows, then fails. // A workaround in Bazel is to use --action_env to set TEMP. ASSERT_DEATH(ParseBinaryFile(binary_file, parsed_launch_info.get()), "LAUNCHER ERROR: Duplicated launch info key: foo"); } TEST_F(LaunchDataParserTest, EmptyKeyLaunchInfoTest) { string binary_file = test_tmpdir + "/empty_key_binary_file"; WriteBinaryFileWithMap(binary_file, { {"foo", "bar"}, {"", "bar2"}, }); parsed_launch_info = make_unique(); // ASSERT_DEATH requires TEMP environment variable to be set. // Otherwise, it will try to write to C:/Windows, then fails. // A workaround in Bazel is to use --action_env to set TEMP. ASSERT_DEATH(ParseBinaryFile(binary_file, parsed_launch_info.get()), "LAUNCHER ERROR: Key is empty string in line: =bar2"); } TEST_F(LaunchDataParserTest, NoEqualSignLaunchInfoTest) { string binary_file = test_tmpdir + "/no_equal_binary_file"; WriteBinaryFileWithList(binary_file, { "foo1=bar1", "foo2bar2", }); parsed_launch_info = make_unique(); // ASSERT_DEATH requires TEMP environment variable to be set. // Otherwise, it will try to write to C:/Windows, then fails. // A workaround in Bazel is to use --action_env to set TEMP. ASSERT_DEATH(ParseBinaryFile(binary_file, parsed_launch_info.get()), "LAUNCHER ERROR: Cannot find equal symbol in line: foo2bar2"); } } // namespace launcher } // namespace bazel