2 * Copyright 2017 Facebook, Inc.
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
8 * http://www.apache.org/licenses/LICENSE-2.0
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
17 #include <folly/experimental/EnvUtil.h>
19 #include <boost/algorithm/string.hpp>
20 #include <folly/Memory.h>
21 #include <folly/Subprocess.h>
22 #include <folly/portability/Fcntl.h>
23 #include <folly/portability/GTest.h>
24 #include <folly/portability/Stdlib.h>
25 #include <glog/logging.h>
27 #include <system_error>
29 using namespace folly;
30 using folly::test::EnvVarSaver;
31 using folly::experimental::EnvironmentState;
32 using folly::experimental::MalformedEnvironment;
35 env_util_subprocess_binary,
36 "./env_util_subprocess",
37 "Location of the `env_util_subprocess` test helper program");
39 TEST(EnvVarSaverTest, ExampleNew) {
40 auto key = "hahahahaha";
41 EXPECT_EQ(nullptr, getenv(key));
43 PCHECK(0 == setenv(key, "", true));
44 EXPECT_STREQ("", getenv(key));
45 PCHECK(0 == unsetenv(key));
46 EXPECT_EQ(nullptr, getenv(key));
48 auto saver = make_unique<EnvVarSaver>();
49 PCHECK(0 == setenv(key, "blah", true));
50 EXPECT_STREQ("blah", getenv(key));
52 EXPECT_EQ(nullptr, getenv(key));
55 TEST(EnvVarSaverTest, ExampleExisting) {
57 EXPECT_NE(nullptr, getenv(key));
58 auto value = std::string{getenv(key)};
60 auto saver = make_unique<EnvVarSaver>();
61 PCHECK(0 == setenv(key, "blah", true));
62 EXPECT_STREQ("blah", getenv(key));
64 EXPECT_EQ(value, getenv(key));
67 TEST(EnvVarSaverTest, Movable) {
68 Optional<EnvVarSaver> pSaver1;
71 EXPECT_NE(nullptr, getenv(key));
72 auto value = std::string{getenv(key)};
73 Optional<EnvVarSaver> pSaver2;
74 pSaver2.emplace(std::move(*pSaver1));
76 PCHECK(0 == setenv(key, "blah", true));
77 EXPECT_STREQ("blah", getenv(key));
79 EXPECT_EQ(value, getenv(key));
82 TEST(EnvironmentStateTest, FailOnEmptyString) {
85 PCHECK(0 == putenv(test));
86 auto okState = EnvironmentState::fromCurrentEnvironment();
89 EnvironmentState::fromCurrentEnvironment(), MalformedEnvironment);
92 TEST(EnvironmentStateTest, MovableAndCopyable) {
93 auto initialState = EnvironmentState::fromCurrentEnvironment();
94 auto copiedState1 = EnvironmentState::empty();
95 copiedState1.operator=(initialState);
96 EnvironmentState copiedState2{initialState};
97 EXPECT_EQ(*initialState, *copiedState1);
98 EXPECT_EQ(*initialState, *copiedState2);
99 (*initialState)["foo"] = "bar";
100 EXPECT_EQ(0, copiedState1->count("foo"));
101 EXPECT_EQ(0, copiedState2->count("foo"));
102 auto movedState1 = EnvironmentState::empty();
103 movedState1.operator=(std::move(copiedState1));
104 EnvironmentState movedState2{std::move(copiedState2)};
105 EXPECT_EQ(0, movedState1->count("foo"));
106 EXPECT_EQ(0, movedState2->count("foo"));
107 initialState->erase("foo");
108 EXPECT_EQ(*initialState, *movedState1);
109 EXPECT_EQ(*initialState, *movedState2);
112 TEST(EnvironmentStateTest, FailOnDuplicate) {
114 char test[7] = "PATG=B";
115 PCHECK(0 == putenv(test));
116 auto okState = EnvironmentState::fromCurrentEnvironment();
119 EnvironmentState::fromCurrentEnvironment(), MalformedEnvironment);
122 TEST(EnvironmentStateTest, Separation) {
124 auto initialState = EnvironmentState::fromCurrentEnvironment();
125 PCHECK(0 == setenv("spork", "foon", true));
126 auto updatedState = EnvironmentState::fromCurrentEnvironment();
127 EXPECT_EQ(0, initialState->count("spork"));
128 EXPECT_EQ(1, updatedState->count("spork"));
129 EXPECT_EQ("foon", (*updatedState)["spork"]);
130 updatedState->erase("spork");
131 EXPECT_EQ(0, updatedState->count("spork"));
132 EXPECT_STREQ("foon", getenv("spork"));
135 TEST(EnvironmentStateTest, Update) {
137 auto env = EnvironmentState::fromCurrentEnvironment();
138 EXPECT_EQ(nullptr, getenv("spork"));
139 (*env)["spork"] = "foon";
140 EXPECT_EQ(nullptr, getenv("spork"));
141 env.setAsCurrentEnvironment();
142 EXPECT_STREQ("foon", getenv("spork"));
145 TEST(EnvironmentStateTest, forSubprocess) {
146 auto env = EnvironmentState::empty();
147 (*env)["spork"] = "foon";
148 std::vector<std::string> expected = {"spork=foon"};
149 auto vec = env.toVector();
150 EXPECT_EQ(expected, vec);
151 Subprocess subProcess{{fLS::FLAGS_env_util_subprocess_binary},
153 fLS::FLAGS_env_util_subprocess_binary.c_str(),
155 EXPECT_EQ(0, subProcess.wait().exitStatus());
158 TEST(EnvironmentStateTest, forC) {
159 auto env = EnvironmentState::empty();
160 (*env)["spork"] = "foon";
161 EXPECT_STREQ("spork=foon", env.toPointerArray().get()[0]);
162 EXPECT_EQ(nullptr, env.toPointerArray().get()[1]);
163 char const* program = fLS::FLAGS_env_util_subprocess_binary.c_str();
172 env.toPointerArray().get()));
174 PCHECK(pid == waitpid(pid, &result, 0));
175 EXPECT_EQ(0, result);
178 TEST(EnvVarSaverTest, ExampleDeleting) {
180 EXPECT_NE(nullptr, getenv(key));
181 auto value = std::string{getenv(key)};
183 auto saver = make_unique<EnvVarSaver>();
184 PCHECK(0 == unsetenv(key));
185 EXPECT_EQ(nullptr, getenv(key));
187 EXPECT_TRUE(value == getenv(key));