pid_file_unittest.cc 5.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202
  1. // Copyright (C) 2015 Internet Systems Consortium, Inc. ("ISC")
  2. //
  3. // Permission to use, copy, modify, and/or distribute this software for any
  4. // purpose with or without fee is hereby granted, provided that the above
  5. // copyright notice and this permission notice appear in all copies.
  6. //
  7. // THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH
  8. // REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
  9. // AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT,
  10. // INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
  11. // LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
  12. // OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
  13. // PERFORMANCE OF THIS SOFTWARE.
  14. #include <util/pid_file.h>
  15. #include <gtest/gtest.h>
  16. #include <fstream>
  17. #include <signal.h>
  18. #include <stdint.h>
  19. namespace {
  20. using namespace isc::util;
  21. // Filenames used for testing.
  22. const char* TESTNAME = "pid_file.test";
  23. class PIDFileTest : public ::testing::Test {
  24. public:
  25. /// @brief Prepends the absolute path to the file specified
  26. /// as an argument.
  27. ///
  28. /// @param filename Name of the file.
  29. /// @return Absolute path to the test file.
  30. static std::string absolutePath(const std::string& filename);
  31. /// @brief Generate a random number for use as a PID
  32. ///
  33. /// @param start - the start of the range we want the PID in
  34. /// @param range - the size of the range for our PID
  35. ///
  36. /// @return returns a random value between start and start + range
  37. int randomizePID(const uint32_t start, const uint32_t range) {
  38. int pid;
  39. for (pid = (random() % range) + start;
  40. kill(pid, 0) == 0;
  41. ++pid)
  42. ;
  43. return (pid);
  44. }
  45. protected:
  46. /// @brief Removes any old test files before the test
  47. virtual void SetUp() {
  48. removeTestFile();
  49. }
  50. /// @brief Removes any remaining test files after the test
  51. virtual void TearDown() {
  52. removeTestFile();
  53. }
  54. private:
  55. /// @brief Removes any remaining test files
  56. void removeTestFile() const {
  57. remove(absolutePath(TESTNAME).c_str());
  58. }
  59. };
  60. std::string
  61. PIDFileTest::absolutePath(const std::string& filename) {
  62. std::ostringstream s;
  63. s << TEST_DATA_BUILDDIR << "/" << filename;
  64. return (s.str());
  65. }
  66. /// @brief Test file writing and deletion. Start by removing
  67. /// any leftover file. Then write a known PID to the file and
  68. /// attempt to read the file and verify the PID. Next write
  69. /// a second and verify a second PID to verify that an existing
  70. /// file is properly overwritten.
  71. TEST_F(PIDFileTest, writeAndDelete) {
  72. PIDFile pid_file(absolutePath(TESTNAME));
  73. std::ifstream fs;
  74. int pid(0);
  75. // Write a known process id
  76. pid_file.write(10);
  77. // Read the file and compare the pid
  78. fs.open(absolutePath(TESTNAME).c_str(), std::ifstream::in);
  79. fs >> pid;
  80. EXPECT_TRUE(fs.good());
  81. EXPECT_EQ(pid, 10);
  82. fs.close();
  83. // Write a second known process id
  84. pid_file.write(20);
  85. // And comapre the second pid
  86. fs.open(absolutePath(TESTNAME).c_str(), std::ifstream::in);
  87. fs >> pid;
  88. EXPECT_TRUE(fs.good());
  89. EXPECT_EQ(pid, 20);
  90. fs.close();
  91. // Delete the file
  92. pid_file.deleteFile();
  93. // And verify that it's gone
  94. fs.open(absolutePath(TESTNAME).c_str(), std::ifstream::in);
  95. EXPECT_FALSE(fs.good());
  96. fs.close();
  97. }
  98. /// @brief Test checking a PID. Write the PID of the current
  99. /// process to the PID file then verify that check indicates
  100. /// the process is running.
  101. TEST_F(PIDFileTest, pidInUse) {
  102. PIDFile pid_file(absolutePath(TESTNAME));
  103. // Write the current PID
  104. pid_file.write();
  105. // Check if we think the process is running
  106. EXPECT_TRUE(pid_file.check());
  107. }
  108. /// @brief Test checking a PID. Write a PID that isn't in use
  109. /// to the PID file and verify that check indicates the process
  110. /// isn't running. The PID may get used between when we select it
  111. /// and write the file and when we check it. To minimize false
  112. /// errors if the first call to check fails we try again with a
  113. /// different range of values and only if both attempts fail do
  114. /// we declare the test to have failed.
  115. TEST_F(PIDFileTest, pidNotInUse) {
  116. PIDFile pid_file(absolutePath(TESTNAME));
  117. int pid;
  118. // get a pid betwen 10000 and 20000
  119. pid = randomizePID(10000, 10000);
  120. // write it
  121. pid_file.write(pid);
  122. // Check to see if we think the process is running
  123. if (!pid_file.check()) {
  124. return;
  125. }
  126. // get a pid betwen 40000 and 50000
  127. pid = randomizePID(10000, 40000);
  128. // write it
  129. pid_file.write(pid);
  130. // Check to see if we think the process is running
  131. EXPECT_FALSE(pid_file.check());
  132. }
  133. /// @brief Test checking a PID. Write garbage to the PID file
  134. /// and verify that check throws an error. In this situation
  135. /// the caller should probably log an error and may decide to
  136. /// continue or not depending on the requirements.
  137. TEST_F(PIDFileTest, pidGarbage) {
  138. PIDFile pid_file(absolutePath(TESTNAME));
  139. std::ofstream fs;
  140. // Open the file and write garbage to it
  141. fs.open(absolutePath(TESTNAME).c_str(), std::ofstream::out);
  142. fs << "text" << std::endl;
  143. fs.close();
  144. // Run the check, we expect to get an execption
  145. EXPECT_THROW(pid_file.check(), PIDCantReadPID);
  146. }
  147. /// @brief Test failing to write a file.
  148. TEST_F(PIDFileTest, pidWriteFail) {
  149. PIDFile pid_file(absolutePath(TESTNAME));
  150. // Create the test file and change it's permission bits
  151. // so we can't write to it.
  152. pid_file.write(10);
  153. chmod(absolutePath(TESTNAME).c_str(), S_IRUSR);
  154. // Now try a write to the file, expecting an exception
  155. EXPECT_THROW(pid_file.write(10), PIDFileError);
  156. }
  157. /// @brief Test deleting a file that doesn't exist
  158. TEST_F(PIDFileTest, noDeleteFile) {
  159. PIDFile pid_file(absolutePath(TESTNAME));
  160. // Delete a file we haven't created
  161. pid_file.deleteFile();
  162. }
  163. } // end of anonymous namespace