diff --git a/src/Makefile b/src/Makefile index 81dc663f..8360733a 100644 --- a/src/Makefile +++ b/src/Makefile @@ -31,8 +31,8 @@ SED_EXTRA=-e 's/-Wall/-Wall -Wno-deprecated/' UNAME_S=$(shell uname -s) ifeq ($(UNAME_S),Darwin) - CXXFLAGS+= -Wno-deprecated-declarations -Wno-c++14-extensions \ - -I/usr/local/include + CPPFLAGS+= -I/usr/local/include + CXXFLAGS+= -Wno-deprecated-declarations -Wno-c++14-extensions LDFLAGS+= -L/usr/local/lib SED_I+= '' SED_EXTRA+= -e \ diff --git a/src/environment.h b/src/environment.h index 7f5d7206..aa356b61 100644 --- a/src/environment.h +++ b/src/environment.h @@ -44,6 +44,8 @@ class Environment { } private: + friend class EnvironmentTest; + void ReadApplicationDefaultCredentials() const; const Configuration& config_; diff --git a/src/json.cc b/src/json.cc index 1ad7b660..2876544b 100644 --- a/src/json.cc +++ b/src/json.cc @@ -513,7 +513,7 @@ Parser::~Parser() = default; std::size_t Parser::ParseStream(std::istream& stream) throw(Exception) { const int kMax = 65536; - unsigned char data[kMax]; + unsigned char data[kMax] = {0}; size_t total_bytes_consumed = 0; yajl_handle handle = state_->handle(); diff --git a/test/Makefile b/test/Makefile index 51bf89d3..e46b57ab 100644 --- a/test/Makefile +++ b/test/Makefile @@ -33,6 +33,13 @@ LDLIBS=\ -lboost_program_options -lboost_system -lboost_thread -lboost_filesystem \ -lpthread -lyajl -lssl -lcrypto -lyaml-cpp +UNAME_S=$(shell uname -s) +ifeq ($(UNAME_S),Darwin) + CPPFLAGS+= -I/usr/local/include + CXXFLAGS+= -Wno-deprecated-declarations -Wno-c++14-extensions + LDFLAGS+= -L/usr/local/lib +endif + # Where to find code under test. SRC_DIR=../src @@ -42,6 +49,7 @@ TEST_OBJS=$(TEST_SOURCES:$(TEST_DIR)/%.cc=%.o) TESTS=\ base64_unittest \ configuration_unittest \ + environment_unittest \ format_unittest \ health_checker_unittest \ instance_unittest \ @@ -100,12 +108,14 @@ $(TESTS): $(GTEST_LIB) $(CPP_NETLIB_LIBS) $(YAML_CPP_LIBS) # All unittest objects depend on GTEST_LIB. $(TESTS:%=%.o): $(GTEST_LIB) -format_unittest: format_unittest.o $(SRC_DIR)/format.o - $(CXX) $(LDFLAGS) $^ $(LDLIBS) -o $@ base64_unittest: base64_unittest.o $(SRC_DIR)/base64.o $(CXX) $(LDFLAGS) $^ $(LDLIBS) -o $@ configuration_unittest: configuration_unittest.o $(SRC_DIR)/configuration.o $(CXX) $(LDFLAGS) $^ $(LDLIBS) -o $@ +environment_unittest: environment_unittest.o $(SRC_DIR)/environment.o $(SRC_DIR)/configuration.o $(SRC_DIR)/format.o $(SRC_DIR)/json.o $(SRC_DIR)/logging.o $(SRC_DIR)/time.o + $(CXX) $(LDFLAGS) $^ $(LDLIBS) -o $@ +format_unittest: format_unittest.o $(SRC_DIR)/format.o + $(CXX) $(LDFLAGS) $^ $(LDLIBS) -o $@ health_checker_unittest: health_checker_unittest.o $(SRC_DIR)/health_checker.o $(SRC_DIR)/configuration.o $(CXX) $(LDFLAGS) $^ $(LDLIBS) -lboost_filesystem -lboost_system -o $@ instance_unittest: instance_unittest.o $(SRC_DIR)/instance.o $(SRC_DIR)/configuration.o $(SRC_DIR)/environment.o $(SRC_DIR)/format.o $(SRC_DIR)/json.o $(SRC_DIR)/logging.o $(SRC_DIR)/resource.o $(SRC_DIR)/store.o $(SRC_DIR)/time.o diff --git a/test/environment_unittest.cc b/test/environment_unittest.cc new file mode 100644 index 00000000..09ab5655 --- /dev/null +++ b/test/environment_unittest.cc @@ -0,0 +1,101 @@ +#include "../src/environment.h" +#include "gtest/gtest.h" + +#include +#include +#include + +namespace google { + +class EnvironmentTest : public ::testing::Test { + protected: + static void ReadApplicationDefaultCredentials(const Environment& environment) { + environment.ReadApplicationDefaultCredentials(); + } +}; + +namespace { +// A file with a given name in a temporary (unique) directory. +boost::filesystem::path TempPath(const std::string& filename) { + boost::filesystem::path path = boost::filesystem::temp_directory_path(); + path.append(boost::filesystem::unique_path().native()); + path.append(filename); + return path; +} + +// Creates a file for the lifetime of the object and removes it after. +class TemporaryFile { + public: + TemporaryFile(const std::string& filename, const std::string& contents) + : path_(TempPath(filename)) { + boost::filesystem::create_directories(path_.parent_path()); + SetContents(contents); + } + ~TemporaryFile() { + boost::filesystem::remove_all(path_.parent_path()); + } + void SetContents(const std::string& contents) const { + std::ofstream file(path_.native()); + file << contents << std::flush; + } + const boost::filesystem::path& FullPath() const { return path_; } + private: + boost::filesystem::path path_; +}; +} // namespace + +TEST(TemporaryFile, Basic) { + boost::filesystem::path path; + { + TemporaryFile f("foo", "bar"); + path = f.FullPath(); + EXPECT_TRUE(boost::filesystem::exists(path)); + std::string contents; + { + std::ifstream in(path.native()); + in >> contents; + } + EXPECT_EQ("bar", contents); + f.SetContents("xyz"); + { + std::ifstream in(path.native()); + in >> contents; + } + EXPECT_EQ("xyz", contents); + } + EXPECT_FALSE(boost::filesystem::exists(path)); +} + +TEST_F(EnvironmentTest, ReadApplicationDefaultCredentialsSucceeds) { + TemporaryFile credentials_file( + std::string(test_info_->name()) + "_creds.json", + "{\"client_email\":\"user@example.com\",\"private_key\":\"some_key\"}"); + std::string cfg; + Configuration config(std::istringstream( + "CredentialsFile: '" + credentials_file.FullPath().native() + "'\n" + )); + Environment environment(config); + EXPECT_NO_THROW(ReadApplicationDefaultCredentials(environment)); + EXPECT_EQ("user@example.com", environment.CredentialsClientEmail()); + EXPECT_EQ("some_key", environment.CredentialsPrivateKey()); +} + +TEST_F(EnvironmentTest, ReadApplicationDefaultCredentialsCaches) { + TemporaryFile credentials_file( + std::string(test_info_->name()) + "_creds.json", + "{\"client_email\":\"user@example.com\",\"private_key\":\"some_key\"}"); + Configuration config(std::istringstream( + "CredentialsFile: '" + credentials_file.FullPath().native() + "'\n" + )); + Environment environment(config); + EXPECT_NO_THROW(ReadApplicationDefaultCredentials(environment)); + credentials_file.SetContents( + "{\"client_email\":\"changed@example.com\",\"private_key\":\"12345\"}" + ); + EXPECT_EQ("user@example.com", environment.CredentialsClientEmail()); + credentials_file.SetContents( + "{\"client_email\":\"extra@example.com\",\"private_key\":\"09876\"}" + ); + EXPECT_EQ("some_key", environment.CredentialsPrivateKey()); +} +} // namespace google diff --git a/test/health_checker_unittest.cc b/test/health_checker_unittest.cc index a6df3b1e..d1d83bd8 100644 --- a/test/health_checker_unittest.cc +++ b/test/health_checker_unittest.cc @@ -1,6 +1,5 @@ #include "../src/health_checker.h" #include "gtest/gtest.h" -#include #include #include