blob: 54ae84ef1d93b5562af065d858840fa5bcdc0086 [file] [log] [blame]
// 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");
}