| // 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 "process_utils.h" |
| |
| #include <stdlib.h> |
| |
| #include <string> |
| |
| #include "test.h" |
| |
| TEST(ProcessUtils, ScopedEnvironmentVariable) { |
| const char kVarName[] = "FOO_FOR_TEST"; |
| const char* prev_value = getenv(kVarName); |
| ASSERT_FALSE(prev_value); |
| |
| { |
| ScopedEnvironmentVariable scoped_var(kVarName, ""); |
| #ifdef _WIN32 |
| // On Windows, the variable was forcefully removed. |
| ASSERT_FALSE(getenv(kVarName)); |
| #else |
| // On Posix, the variable was set to the empty string. |
| ASSERT_TRUE(getenv(kVarName)); |
| EXPECT_EQ(std::string(""), getenv(kVarName)); |
| #endif |
| } |
| |
| { |
| ScopedEnvironmentVariable scoped_var(kVarName, "value1"); |
| EXPECT_EQ(std::string("value1"), getenv(kVarName)); |
| |
| { |
| ScopedEnvironmentVariable scoped_var2(kVarName, "VALUE2"); |
| EXPECT_EQ(std::string("VALUE2"), getenv(kVarName)); |
| } |
| |
| { |
| ScopedEnvironmentVariable scoped_var2(kVarName, ""); |
| #ifdef _WIN32 |
| ASSERT_FALSE(getenv(kVarName)); |
| #else |
| ASSERT_TRUE(getenv(kVarName)); |
| EXPECT_EQ(std::string(""), getenv(kVarName)); |
| #endif |
| } |
| |
| EXPECT_EQ(std::string("value1"), getenv(kVarName)); |
| } |
| |
| ASSERT_FALSE(getenv(kVarName)); |
| } |
| |
| TEST(ProcessUtils, EnvironmentBlockDefault) { |
| EnvironmentBlock empty_block; |
| #ifdef _WIN32 |
| char* b = empty_block.AsAnsiEnvironmentBlock(); |
| ASSERT_EQ(*b, '\0'); |
| ASSERT_EQ(empty_block, empty_block); |
| |
| wchar_t* wb = empty_block.AsUnicodeEnvironmentBlock(); |
| ASSERT_EQ(*wb, L'\0'); |
| #else // !_WIN32 |
| char** vec = empty_block.AsExecEnvironmentBlock(); |
| ASSERT_FALSE(vec[0]); |
| #endif // !_WIN32 |
| |
| EXPECT_EQ(empty_block.AsString(), "Environment(0)[\n]"); |
| } |
| |
| TEST(ProcessUtils, EnvironmentBlockFromCurrentEnvironment) { |
| const char kDefinedVarName[] = "DEFINED_VARIABLE_FOR_NINJA_TEST"; |
| const char kUndefinedVarName[] = "UNDEFINED_VARIABLE_FOR_NINJA_TEST"; |
| ASSERT_FALSE(getenv(kDefinedVarName)); |
| ASSERT_FALSE(getenv(kUndefinedVarName)); |
| |
| { |
| ScopedEnvironmentVariable scoped_var(kDefinedVarName, ""); |
| EnvironmentBlock block = EnvironmentBlock::CreateFromCurrentEnvironment(); |
| EXPECT_FALSE(block.Get(kUndefinedVarName)); |
| #ifdef _WIN32 |
| ASSERT_FALSE(block.Get(kDefinedVarName)); |
| #else |
| ASSERT_TRUE(block.Get(kDefinedVarName)); |
| EXPECT_EQ('\0', block.Get(kDefinedVarName)[0]); |
| #endif |
| } |
| |
| { |
| EnvironmentBlock block = EnvironmentBlock::CreateFromCurrentEnvironment(); |
| EXPECT_FALSE(block.Get(kUndefinedVarName)); |
| EXPECT_FALSE(block.Get(kDefinedVarName)); |
| } |
| } |
| |
| TEST(ProcessUtils, EnvironmentBlockMergeWith) { |
| EnvironmentBlock block; |
| block.Insert("foo", "FOO"); |
| block.Insert("bar", "BAR"); |
| block.Insert("qux", ""); |
| EXPECT_EQ(block.AsString(), |
| "Environment(3)[\n bar=BAR\n foo=FOO\n qux=\n]"); |
| |
| EXPECT_EQ(block, block); |
| |
| EnvironmentBlock block2; |
| block2.Insert("foo", "NOT_FOO"); |
| block2.Insert("qux", "QUX"); |
| block2.Insert("zoo", "ZOO"); |
| EXPECT_EQ(block2.AsString(), |
| "Environment(3)[\n foo=NOT_FOO\n qux=QUX\n zoo=ZOO\n]"); |
| |
| EXPECT_EQ(block, block); |
| EXPECT_NE(block, block2); |
| |
| block.MergeWith(block2); |
| EXPECT_EQ(block.Get("foo"), std::string("FOO")); |
| EXPECT_EQ(block.Get("bar"), std::string("BAR")); |
| EXPECT_EQ(block.Get("qux"), std::string("")); |
| ASSERT_TRUE(block.Get("zoo")); |
| EXPECT_EQ(block.Get("zoo"), std::string("ZOO")); |
| |
| EXPECT_EQ(block.AsString(), |
| "Environment(4)[\n bar=BAR\n foo=FOO\n qux=\n zoo=ZOO\n]"); |
| } |
| |
| #ifdef _WIN32 |
| |
| TEST(ProcessUtils, EnvironmentBlockAsAnsiEnvironmentBlock) { |
| EnvironmentBlock block; |
| block.Insert("foo", "FOO"); |
| block.Insert("bar", "BARBAR"); |
| block.Insert("zoo", ""); |
| |
| ASSERT_TRUE(block.Get("foo")); |
| EXPECT_EQ(std::string("FOO"), block.Get("foo")); |
| EXPECT_EQ(std::string("BARBAR"), block.Get("bar")); |
| EXPECT_EQ(std::string(""), block.Get("zoo")); |
| |
| char* b = block.AsAnsiEnvironmentBlock(); |
| ASSERT_FALSE(::memcmp(b, "bar=BARBAR\0foo=FOO\0zoo=\0\0", 25)); |
| } |
| |
| TEST(ProcessUtils, EnvironmentBlockAsUnicodeEnvironmentBlock) { |
| EnvironmentBlock block; |
| block.Insert("foo", "FOO"); |
| block.Insert("bar", "BARBAR"); |
| block.Insert("zoo", ""); |
| |
| ASSERT_TRUE(block.Get("foo")); |
| EXPECT_EQ(std::string("FOO"), block.Get("foo")); |
| EXPECT_EQ(std::string("BARBAR"), block.Get("bar")); |
| EXPECT_EQ(std::string(""), block.Get("zoo")); |
| |
| wchar_t* wb = block.AsUnicodeEnvironmentBlock(); |
| ASSERT_FALSE(::wmemcmp(wb, L"bar=BARBAR\0foo=FOO\0zoo=\0\0", 25)); |
| } |
| #else // !_WIN32 |
| TEST(ProcessUtils, EnvironmentBlockAsExecEnvironmentBlock) { |
| EnvironmentBlock block; |
| block.Insert("foo", "FOO"); |
| block.Insert("bar", "BARBAR"); |
| block.Insert("zoo", ""); |
| |
| ASSERT_TRUE(block.Get("foo")); |
| EXPECT_EQ(std::string("FOO"), block.Get("foo")); |
| EXPECT_EQ(std::string("BARBAR"), block.Get("bar")); |
| EXPECT_EQ(std::string(""), block.Get("zoo")); |
| |
| char** vec = block.AsExecEnvironmentBlock(); |
| ASSERT_TRUE(vec[0]); |
| ASSERT_TRUE(vec[1]); |
| ASSERT_TRUE(vec[2]); |
| ASSERT_FALSE(vec[3]); |
| EXPECT_EQ(std::string(vec[0]), "bar=BARBAR"); |
| EXPECT_EQ(std::string(vec[1]), "foo=FOO"); |
| EXPECT_EQ(std::string(vec[2]), "zoo="); |
| } |
| #endif // !_WIN32 |
| |
| TEST(ProcessUtils, EnvironmentBlockToEncodedString) { |
| EnvironmentBlock block; |
| block.Insert("foo", "FOO"); |
| block.Insert("bar", "BARBAR"); |
| block.Insert("zoo", ""); |
| EXPECT_EQ(block.AsString(), |
| "Environment(3)[\n bar=BARBAR\n foo=FOO\n zoo=\n]"); |
| |
| std::string encoded = block.ToEncodedString(); |
| ASSERT_FALSE(encoded.empty()); |
| |
| std::string error; |
| auto block2 = EnvironmentBlock::FromEncodedString(encoded, &error); |
| EXPECT_TRUE(error.empty()); |
| EXPECT_EQ(block.AsString(), block2.AsString()); |
| |
| // Detect errors and return empty instance when decoding truncated string. |
| auto block3 = |
| EnvironmentBlock::FromEncodedString(encoded.substr(0, 10), &error); |
| EXPECT_FALSE(error.empty()); |
| EXPECT_EQ(block3.AsString(), "Environment(0)[\n]"); |
| } |
| |
| TEST(ProcessUtils, SplitCommaOrSpaceSeparatedList) { |
| std::vector<StringPiece> result; |
| |
| // Verify empty inputs. |
| result = SplitCommaOrSpaceSeparatedList(""); |
| EXPECT_EQ(result.size(), 0u); |
| |
| result = SplitCommaOrSpaceSeparatedList(" "); |
| EXPECT_EQ(result.size(), 0u); |
| |
| result = SplitCommaOrSpaceSeparatedList(" ,,, "); |
| EXPECT_EQ(result.size(), 0u); |
| |
| result = SplitCommaOrSpaceSeparatedList(" foo,"); |
| EXPECT_EQ(result.size(), 1u); |
| EXPECT_EQ(result[0].AsString(), "foo"); |
| |
| result = SplitCommaOrSpaceSeparatedList("foo bar zoo"); |
| EXPECT_EQ(result.size(), 3u); |
| EXPECT_EQ(result[0].AsString(), "foo"); |
| EXPECT_EQ(result[1].AsString(), "bar"); |
| EXPECT_EQ(result[2].AsString(), "zoo"); |
| |
| result = SplitCommaOrSpaceSeparatedList(" foo,,bar zoo,"); |
| EXPECT_EQ(result.size(), 3u); |
| EXPECT_EQ(result[0].AsString(), "foo"); |
| EXPECT_EQ(result[1].AsString(), "bar"); |
| EXPECT_EQ(result[2].AsString(), "zoo"); |
| } |