EnvUtilTest.cpp 5.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189
  1. /*
  2. * Copyright 2017-present Facebook, Inc.
  3. *
  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
  7. *
  8. * http://www.apache.org/licenses/LICENSE-2.0
  9. *
  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.
  15. */
  16. #include <folly/experimental/EnvUtil.h>
  17. #include <boost/algorithm/string.hpp>
  18. #include <folly/Memory.h>
  19. #include <folly/Subprocess.h>
  20. #include <folly/portability/Fcntl.h>
  21. #include <folly/portability/GTest.h>
  22. #include <folly/portability/Stdlib.h>
  23. #include <glog/logging.h>
  24. #include <spawn.h>
  25. #include <system_error>
  26. using namespace folly;
  27. using folly::experimental::EnvironmentState;
  28. using folly::experimental::MalformedEnvironment;
  29. using folly::test::EnvVarSaver;
  30. DEFINE_string(
  31. env_util_subprocess_binary,
  32. "./env_util_subprocess",
  33. "Location of the `env_util_subprocess` test helper program");
  34. TEST(EnvVarSaverTest, ExampleNew) {
  35. auto key = "hahahahaha";
  36. EXPECT_EQ(nullptr, getenv(key));
  37. PCHECK(0 == setenv(key, "", true));
  38. EXPECT_STREQ("", getenv(key));
  39. PCHECK(0 == unsetenv(key));
  40. EXPECT_EQ(nullptr, getenv(key));
  41. auto saver = std::make_unique<EnvVarSaver>();
  42. PCHECK(0 == setenv(key, "blah", true));
  43. EXPECT_STREQ("blah", getenv(key));
  44. saver = nullptr;
  45. EXPECT_EQ(nullptr, getenv(key));
  46. }
  47. TEST(EnvVarSaverTest, ExampleExisting) {
  48. auto key = "PATH";
  49. EXPECT_NE(nullptr, getenv(key));
  50. auto value = std::string{getenv(key)};
  51. auto saver = std::make_unique<EnvVarSaver>();
  52. PCHECK(0 == setenv(key, "blah", true));
  53. EXPECT_STREQ("blah", getenv(key));
  54. saver = nullptr;
  55. EXPECT_EQ(value, getenv(key));
  56. }
  57. TEST(EnvVarSaverTest, Movable) {
  58. Optional<EnvVarSaver> pSaver1;
  59. pSaver1.emplace();
  60. auto key = "PATH";
  61. EXPECT_NE(nullptr, getenv(key));
  62. auto value = std::string{getenv(key)};
  63. Optional<EnvVarSaver> pSaver2;
  64. pSaver2.emplace(std::move(*pSaver1));
  65. pSaver1.clear();
  66. PCHECK(0 == setenv(key, "blah", true));
  67. EXPECT_STREQ("blah", getenv(key));
  68. pSaver2.clear();
  69. EXPECT_EQ(value, getenv(key));
  70. }
  71. TEST(EnvironmentStateTest, FailOnEmptyString) {
  72. EnvVarSaver saver{};
  73. char test[4] = "A=B";
  74. PCHECK(0 == putenv(test));
  75. auto okState = EnvironmentState::fromCurrentEnvironment();
  76. test[0] = 0;
  77. EXPECT_THROW(
  78. EnvironmentState::fromCurrentEnvironment(), MalformedEnvironment);
  79. }
  80. TEST(EnvironmentStateTest, MovableAndCopyable) {
  81. auto initialState = EnvironmentState::fromCurrentEnvironment();
  82. auto copiedState1 = EnvironmentState::empty();
  83. copiedState1.operator=(initialState);
  84. EnvironmentState copiedState2{initialState};
  85. EXPECT_EQ(*initialState, *copiedState1);
  86. EXPECT_EQ(*initialState, *copiedState2);
  87. (*initialState)["foo"] = "bar";
  88. EXPECT_EQ(0, copiedState1->count("foo"));
  89. EXPECT_EQ(0, copiedState2->count("foo"));
  90. auto movedState1 = EnvironmentState::empty();
  91. movedState1.operator=(std::move(copiedState1));
  92. EnvironmentState movedState2{std::move(copiedState2)};
  93. EXPECT_EQ(0, movedState1->count("foo"));
  94. EXPECT_EQ(0, movedState2->count("foo"));
  95. initialState->erase("foo");
  96. EXPECT_EQ(*initialState, *movedState1);
  97. EXPECT_EQ(*initialState, *movedState2);
  98. }
  99. TEST(EnvironmentStateTest, FailOnDuplicate) {
  100. EnvVarSaver saver{};
  101. char test[7] = "PATG=B";
  102. PCHECK(0 == putenv(test));
  103. auto okState = EnvironmentState::fromCurrentEnvironment();
  104. test[3] = 'H';
  105. EXPECT_THROW(
  106. EnvironmentState::fromCurrentEnvironment(), MalformedEnvironment);
  107. }
  108. TEST(EnvironmentStateTest, Separation) {
  109. EnvVarSaver saver{};
  110. auto initialState = EnvironmentState::fromCurrentEnvironment();
  111. PCHECK(0 == setenv("spork", "foon", true));
  112. auto updatedState = EnvironmentState::fromCurrentEnvironment();
  113. EXPECT_EQ(0, initialState->count("spork"));
  114. EXPECT_EQ(1, updatedState->count("spork"));
  115. EXPECT_EQ("foon", (*updatedState)["spork"]);
  116. updatedState->erase("spork");
  117. EXPECT_EQ(0, updatedState->count("spork"));
  118. EXPECT_STREQ("foon", getenv("spork"));
  119. }
  120. TEST(EnvironmentStateTest, Update) {
  121. EnvVarSaver saver{};
  122. auto env = EnvironmentState::fromCurrentEnvironment();
  123. EXPECT_EQ(nullptr, getenv("spork"));
  124. (*env)["spork"] = "foon";
  125. EXPECT_EQ(nullptr, getenv("spork"));
  126. env.setAsCurrentEnvironment();
  127. EXPECT_STREQ("foon", getenv("spork"));
  128. }
  129. TEST(EnvironmentStateTest, forSubprocess) {
  130. auto env = EnvironmentState::empty();
  131. (*env)["spork"] = "foon";
  132. std::vector<std::string> expected = {"spork=foon"};
  133. auto vec = env.toVector();
  134. EXPECT_EQ(expected, vec);
  135. Subprocess subProcess{{fLS::FLAGS_env_util_subprocess_binary},
  136. {},
  137. fLS::FLAGS_env_util_subprocess_binary.c_str(),
  138. &vec};
  139. EXPECT_EQ(0, subProcess.wait().exitStatus());
  140. }
  141. TEST(EnvironmentStateTest, forC) {
  142. auto env = EnvironmentState::empty();
  143. (*env)["spork"] = "foon";
  144. EXPECT_STREQ("spork=foon", env.toPointerArray().get()[0]);
  145. EXPECT_EQ(nullptr, env.toPointerArray().get()[1]);
  146. char const* program = fLS::FLAGS_env_util_subprocess_binary.c_str();
  147. pid_t pid;
  148. PCHECK(
  149. 0 ==
  150. posix_spawn(
  151. &pid,
  152. program,
  153. nullptr,
  154. nullptr,
  155. nullptr,
  156. env.toPointerArray().get()));
  157. int result;
  158. PCHECK(pid == waitpid(pid, &result, 0));
  159. EXPECT_EQ(0, result);
  160. }
  161. TEST(EnvVarSaverTest, ExampleDeleting) {
  162. auto key = "PATH";
  163. EXPECT_NE(nullptr, getenv(key));
  164. auto value = std::string{getenv(key)};
  165. auto saver = std::make_unique<EnvVarSaver>();
  166. PCHECK(0 == unsetenv(key));
  167. EXPECT_EQ(nullptr, getenv(key));
  168. saver = nullptr;
  169. EXPECT_TRUE(value == getenv(key));
  170. }