Skip to content

Commit

Permalink
feat: add new support for testing with environment variables (googlea…
Browse files Browse the repository at this point in the history
…pis/google-cloud-cpp-common#180)

`ScopedEnvironment` is an RAII object that will, upon destruction,
restore the previous state of the environment variable it modified.
For example:
```
  // ${VAR} has some initial state.
  {
    ScopedEnvironment env("VAR", "value");
    // ${VAR} now holds "value".
  }
  // The initial state of ${VAR} has been restored.
```
  • Loading branch information
devbww authored Feb 21, 2020
1 parent d1d08d1 commit 5ae175e
Show file tree
Hide file tree
Showing 6 changed files with 164 additions and 1 deletion.
5 changes: 4 additions & 1 deletion google/cloud/testing_util/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,8 @@ if (BUILD_TESTING OR GOOGLE_CLOUD_CPP_TESTING_UTIL_ENABLE_INSTALL)
expect_future_error.h
init_google_mock.cc
init_google_mock.h
scoped_environment.cc
scoped_environment.h
testing_types.cc
testing_types.h)
target_link_libraries(
Expand All @@ -41,7 +43,8 @@ if (BUILD_TESTING OR GOOGLE_CLOUD_CPP_TESTING_UTIL_ENABLE_INSTALL)

create_bazel_config(google_cloud_cpp_testing YEAR 2019)

set(google_cloud_cpp_testing_unit_tests assert_ok_test.cc)
set(google_cloud_cpp_testing_unit_tests assert_ok_test.cc
scoped_environment_test.cc)

# Export the list of unit tests so the Bazel BUILD file can pick it up.
export_list_to_bazel("google_cloud_cpp_testing_unit_tests.bzl"
Expand Down
2 changes: 2 additions & 0 deletions google/cloud/testing_util/google_cloud_cpp_testing.bzl
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@ google_cloud_cpp_testing_hdrs = [
"expect_exception.h",
"expect_future_error.h",
"init_google_mock.h",
"scoped_environment.h",
"testing_types.h",
]

Expand All @@ -34,5 +35,6 @@ google_cloud_cpp_testing_srcs = [
"custom_google_mock_main.cc",
"environment_variable_restore.cc",
"init_google_mock.cc",
"scoped_environment.cc",
"testing_types.cc",
]
Original file line number Diff line number Diff line change
Expand Up @@ -18,4 +18,5 @@

google_cloud_cpp_testing_unit_tests = [
"assert_ok_test.cc",
"scoped_environment_test.cc",
]
38 changes: 38 additions & 0 deletions google/cloud/testing_util/scoped_environment.cc
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
// Copyright 2020 Google LLC
//
// 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 "google/cloud/testing_util/scoped_environment.h"
#include "google/cloud/internal/getenv.h"
#include "google/cloud/internal/setenv.h"

namespace google {
namespace cloud {
inline namespace GOOGLE_CLOUD_CPP_NS {
namespace testing_util {

ScopedEnvironment::ScopedEnvironment(std::string variable,
optional<std::string> const& value)
: variable_(std::move(variable)),
prev_value_(internal::GetEnv(variable_.c_str())) {
internal::SetEnv(variable_.c_str(), value);
}

ScopedEnvironment::~ScopedEnvironment() {
internal::SetEnv(variable_.c_str(), std::move(prev_value_));
}

} // namespace testing_util
} // namespace GOOGLE_CLOUD_CPP_NS
} // namespace cloud
} // namespace google
57 changes: 57 additions & 0 deletions google/cloud/testing_util/scoped_environment.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,57 @@
// Copyright 2020 Google LLC
//
// 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.

#ifndef GOOGLE_CLOUD_CPP_GOOGLE_CLOUD_TESTING_UTIL_SCOPED_ENVIRONMENT_H
#define GOOGLE_CLOUD_CPP_GOOGLE_CLOUD_TESTING_UTIL_SCOPED_ENVIRONMENT_H

#include "google/cloud/optional.h"
#include "google/cloud/version.h"
#include <string>

namespace google {
namespace cloud {
inline namespace GOOGLE_CLOUD_CPP_NS {
namespace testing_util {

/**
* Helper class to (un)set and restore the value of an environment variable.
*/
class ScopedEnvironment {
public:
/**
* Set the @p variable environment variable to @p value. If @value is
* an unset optional then the variable is unset. The previous value of
* the variable will be restored upon destruction.
*/
ScopedEnvironment(std::string variable, optional<std::string> const& value);

~ScopedEnvironment();

// Movable, but not copyable.
ScopedEnvironment(ScopedEnvironment const&) = delete;
ScopedEnvironment(ScopedEnvironment&&) = default;
ScopedEnvironment& operator=(ScopedEnvironment const&) = delete;
ScopedEnvironment& operator=(ScopedEnvironment&&) = default;

private:
std::string variable_;
optional<std::string> prev_value_;
};

} // namespace testing_util
} // namespace GOOGLE_CLOUD_CPP_NS
} // namespace cloud
} // namespace google

#endif // GOOGLE_CLOUD_CPP_GOOGLE_CLOUD_TESTING_UTIL_SCOPED_ENVIRONMENT_H
62 changes: 62 additions & 0 deletions google/cloud/testing_util/scoped_environment_test.cc
Original file line number Diff line number Diff line change
@@ -0,0 +1,62 @@
// Copyright 2020 Google LLC
//
// 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 "google/cloud/testing_util/scoped_environment.h"
#include "google/cloud/internal/getenv.h"
#include "google/cloud/internal/setenv.h"
#include <gtest/gtest.h>

namespace google {
namespace cloud {
inline namespace GOOGLE_CLOUD_CPP_NS {
namespace testing_util {
namespace {

constexpr auto kVarName = "SCOPED_ENVIRONMENT_TEST";

TEST(ScopedEnvironment, SetOverSet) {
ScopedEnvironment env_outer(kVarName, "foo");
EXPECT_EQ(*internal::GetEnv(kVarName), "foo");
{
ScopedEnvironment env_inner(kVarName, "bar");
EXPECT_EQ(*internal::GetEnv(kVarName), "bar");
}
EXPECT_EQ(*internal::GetEnv(kVarName), "foo");
}

TEST(ScopedEnvironment, SetOverUnset) {
ScopedEnvironment env_outer(kVarName, {});
EXPECT_FALSE(internal::GetEnv(kVarName).has_value());
{
ScopedEnvironment env_inner(kVarName, "bar");
EXPECT_EQ(*internal::GetEnv(kVarName), "bar");
}
EXPECT_FALSE(internal::GetEnv(kVarName).has_value());
}

TEST(ScopedEnvironment, UnsetOverSet) {
ScopedEnvironment env_outer(kVarName, "foo");
EXPECT_EQ(*internal::GetEnv(kVarName), "foo");
{
ScopedEnvironment env_inner(kVarName, {});
EXPECT_FALSE(internal::GetEnv(kVarName).has_value());
}
EXPECT_EQ(*internal::GetEnv(kVarName), "foo");
}

} // namespace
} // namespace testing_util
} // namespace GOOGLE_CLOUD_CPP_NS
} // namespace cloud
} // namespace google

0 comments on commit 5ae175e

Please sign in to comment.