123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202 |
- // Copyright (C) 2015 Internet Systems Consortium, Inc. ("ISC")
- //
- // Permission to use, copy, modify, and/or distribute this software for any
- // purpose with or without fee is hereby granted, provided that the above
- // copyright notice and this permission notice appear in all copies.
- //
- // THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH
- // REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
- // AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT,
- // INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
- // LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
- // OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
- // PERFORMANCE OF THIS SOFTWARE.
- #include <util/pid_file.h>
- #include <gtest/gtest.h>
- #include <fstream>
- #include <signal.h>
- #include <stdint.h>
- namespace {
- using namespace isc::util;
- // Filenames used for testing.
- const char* TESTNAME = "pid_file.test";
- class PIDFileTest : public ::testing::Test {
- public:
- /// @brief Prepends the absolute path to the file specified
- /// as an argument.
- ///
- /// @param filename Name of the file.
- /// @return Absolute path to the test file.
- static std::string absolutePath(const std::string& filename);
- /// @brief Generate a random number for use as a PID
- ///
- /// @param start - the start of the range we want the PID in
- /// @param range - the size of the range for our PID
- ///
- /// @return returns a random value between start and start + range
- int randomizePID(const uint32_t start, const uint32_t range) {
- int pid;
- for (pid = (random() % range) + start;
- kill(pid, 0) == 0;
- ++pid)
- ;
- return (pid);
- }
- protected:
- /// @brief Removes any old test files before the test
- virtual void SetUp() {
- removeTestFile();
- }
- /// @brief Removes any remaining test files after the test
- virtual void TearDown() {
- removeTestFile();
- }
- private:
- /// @brief Removes any remaining test files
- void removeTestFile() const {
- remove(absolutePath(TESTNAME).c_str());
- }
- };
- std::string
- PIDFileTest::absolutePath(const std::string& filename) {
- std::ostringstream s;
- s << TEST_DATA_BUILDDIR << "/" << filename;
- return (s.str());
- }
- /// @brief Test file writing and deletion. Start by removing
- /// any leftover file. Then write a known PID to the file and
- /// attempt to read the file and verify the PID. Next write
- /// a second and verify a second PID to verify that an existing
- /// file is properly overwritten.
- TEST_F(PIDFileTest, writeAndDelete) {
- PIDFile pid_file(absolutePath(TESTNAME));
- std::ifstream fs;
- int pid(0);
- // Write a known process id
- pid_file.write(10);
- // Read the file and compare the pid
- fs.open(absolutePath(TESTNAME).c_str(), std::ifstream::in);
- fs >> pid;
- EXPECT_TRUE(fs.good());
- EXPECT_EQ(pid, 10);
- fs.close();
- // Write a second known process id
- pid_file.write(20);
- // And comapre the second pid
- fs.open(absolutePath(TESTNAME).c_str(), std::ifstream::in);
- fs >> pid;
- EXPECT_TRUE(fs.good());
- EXPECT_EQ(pid, 20);
- fs.close();
- // Delete the file
- pid_file.deleteFile();
- // And verify that it's gone
- fs.open(absolutePath(TESTNAME).c_str(), std::ifstream::in);
- EXPECT_FALSE(fs.good());
- fs.close();
- }
- /// @brief Test checking a PID. Write the PID of the current
- /// process to the PID file then verify that check indicates
- /// the process is running.
- TEST_F(PIDFileTest, pidInUse) {
- PIDFile pid_file(absolutePath(TESTNAME));
- // Write the current PID
- pid_file.write();
- // Check if we think the process is running
- EXPECT_TRUE(pid_file.check());
- }
- /// @brief Test checking a PID. Write a PID that isn't in use
- /// to the PID file and verify that check indicates the process
- /// isn't running. The PID may get used between when we select it
- /// and write the file and when we check it. To minimize false
- /// errors if the first call to check fails we try again with a
- /// different range of values and only if both attempts fail do
- /// we declare the test to have failed.
- TEST_F(PIDFileTest, pidNotInUse) {
- PIDFile pid_file(absolutePath(TESTNAME));
- int pid;
- // get a pid betwen 10000 and 20000
- pid = randomizePID(10000, 10000);
- // write it
- pid_file.write(pid);
- // Check to see if we think the process is running
- if (!pid_file.check()) {
- return;
- }
- // get a pid betwen 40000 and 50000
- pid = randomizePID(10000, 40000);
- // write it
- pid_file.write(pid);
- // Check to see if we think the process is running
- EXPECT_FALSE(pid_file.check());
- }
- /// @brief Test checking a PID. Write garbage to the PID file
- /// and verify that check throws an error. In this situation
- /// the caller should probably log an error and may decide to
- /// continue or not depending on the requirements.
- TEST_F(PIDFileTest, pidGarbage) {
- PIDFile pid_file(absolutePath(TESTNAME));
- std::ofstream fs;
- // Open the file and write garbage to it
- fs.open(absolutePath(TESTNAME).c_str(), std::ofstream::out);
- fs << "text" << std::endl;
- fs.close();
- // Run the check, we expect to get an execption
- EXPECT_THROW(pid_file.check(), PIDCantReadPID);
- }
- /// @brief Test failing to write a file.
- TEST_F(PIDFileTest, pidWriteFail) {
- PIDFile pid_file(absolutePath(TESTNAME));
- // Create the test file and change it's permission bits
- // so we can't write to it.
- pid_file.write(10);
- chmod(absolutePath(TESTNAME).c_str(), S_IRUSR);
- // Now try a write to the file, expecting an exception
- EXPECT_THROW(pid_file.write(10), PIDFileError);
- }
- /// @brief Test deleting a file that doesn't exist
- TEST_F(PIDFileTest, noDeleteFile) {
- PIDFile pid_file(absolutePath(TESTNAME));
- // Delete a file we haven't created
- pid_file.deleteFile();
- }
- } // end of anonymous namespace
|