[Orxonox-commit 4875] r9544 - in code/branches/testing: src/libraries/util/output test/util/output

landauf at orxonox.net landauf at orxonox.net
Mon Mar 11 23:13:21 CET 2013


Author: landauf
Date: 2013-03-11 23:13:21 +0100 (Mon, 11 Mar 2013)
New Revision: 9544

Modified:
   code/branches/testing/src/libraries/util/output/LogWriter.cc
   code/branches/testing/src/libraries/util/output/LogWriter.h
   code/branches/testing/test/util/output/LogWriterTest.cc
Log:
added archive feature to LogWriter which archives up to nine old log-files (orxonox.log.1 to orxonox.log.9)

Modified: code/branches/testing/src/libraries/util/output/LogWriter.cc
===================================================================
--- code/branches/testing/src/libraries/util/output/LogWriter.cc	2013-03-10 18:22:59 UTC (rev 9543)
+++ code/branches/testing/src/libraries/util/output/LogWriter.cc	2013-03-11 22:13:21 UTC (rev 9544)
@@ -38,9 +38,12 @@
 
 #include "OutputManager.h"
 #include "MemoryWriter.h"
+#include "util/Convert.h"
 
 namespace orxonox
 {
+    static const int MAX_ARCHIVED_FILES = 9;
+
     /**
         @brief Constructor, initializes the desired output levels and the name and path of the log-file, and opens the log-file.
 
@@ -81,6 +84,9 @@
     */
     void LogWriter::openFile()
     {
+        // archive the old log file
+        this->archive();
+
         // open the file
         this->file_.open(this->getPath().c_str(), std::fstream::out);
 
@@ -104,6 +110,50 @@
     }
 
     /**
+     * @brief Archives old copies of the log file by adding increasing numbers to the filename.
+     */
+    void LogWriter::archive(int index)
+    {
+        std::string oldPath = this->getArchivedPath(index);
+
+        // see if the file already exists, otherwise return
+        std::ifstream stream(oldPath.c_str());
+        bool exists = stream.is_open();
+        stream.close();
+
+        if (!exists)
+            return;
+
+        if (index < MAX_ARCHIVED_FILES)
+        {
+            // increment the index and archive the file with the next higher index
+            this->archive(++index);
+
+            // create the new path based on the incremented index
+            std::string newPath = this->getArchivedPath(index);
+
+            // move the file
+            std::rename(oldPath.c_str(), newPath.c_str());
+        }
+        else
+        {
+            // delete the file
+            std::remove(oldPath.c_str());
+        }
+    }
+    
+    /**
+     * @brief Returns the path for archived copies of the logfile (based on the archive index)
+     */
+    std::string LogWriter::getArchivedPath(int index) const
+    {
+        std::string path = this->getPath();
+        if (index > 0)
+            path += '.' + multi_cast<std::string>(index);
+        return path;
+    }
+
+    /**
         @brief Changes the path of the log-file. Re-writes the log-file by using MemoryWriter.
     */
     void LogWriter::setLogDirectory(const std::string& directory)

Modified: code/branches/testing/src/libraries/util/output/LogWriter.h
===================================================================
--- code/branches/testing/src/libraries/util/output/LogWriter.h	2013-03-10 18:22:59 UTC (rev 9543)
+++ code/branches/testing/src/libraries/util/output/LogWriter.h	2013-03-11 22:13:21 UTC (rev 9544)
@@ -75,6 +75,9 @@
             void openFile();
             void closeFile();
 
+            void archive(int index = 0);
+            std::string getArchivedPath(int index) const;
+
             std::string filename_;  ///< The name of the log-file (without directory)
             std::string directory_; ///< The directory where the log-file resided (without file-name)
             std::ofstream file_;    ///< The output file stream.

Modified: code/branches/testing/test/util/output/LogWriterTest.cc
===================================================================
--- code/branches/testing/test/util/output/LogWriterTest.cc	2013-03-10 18:22:59 UTC (rev 9543)
+++ code/branches/testing/test/util/output/LogWriterTest.cc	2013-03-11 22:13:21 UTC (rev 9544)
@@ -1,9 +1,20 @@
 #include <gtest/gtest.h>
 #include "util/Output.h"
 #include "util/output/LogWriter.h"
+#include "util/Convert.h"
 
 namespace orxonox
 {
+    namespace
+    {
+        class MockLogWriter : public LogWriter
+        {
+            public:
+                virtual void printLine(const std::string& line, OutputLevel level)
+                    { this->LogWriter::printLine(line, level); }
+        };
+    }
+
     // test constructor opens file
     TEST(LogWriterTest, ConstructorOpensFile)
     {
@@ -14,23 +25,50 @@
     // setLogDirectory changes file, opens correct file
     bool fileExists(const std::string& path)
     {
-        std::ifstream stream(path.c_str(), std::fstream::in);
-        bool exists = stream.is_open();
+        std::ifstream stream(path.c_str());
+        bool exists = stream.is_open() && stream.good();
         stream.close();
         return exists;
     }
 
-    bool fileSuccessfullyDeleted(const std::string& path)
+    std::string getLineWhichContains(const std::string& path, const std::string& message)
     {
-        return std::remove(path.c_str()) == 0;
+        std::ifstream file(path.c_str());
+        EXPECT_TRUE(file.is_open());
+        EXPECT_TRUE(file.good());
+        EXPECT_FALSE(file.eof());
+
+        while (file.is_open() && file.good() && !file.eof())
+        {
+            std::string line;
+            std::getline(file, line);
+
+            // see if we find the output and return
+            if (line.find(message) == (line.size() - message.size()))
+                return line;
+        }
+
+        return std::string();
     }
 
+    bool fileContains(const std::string& path, const std::string& message)
+    {
+        return !getLineWhichContains(path, message).empty();
+    }
+
+    bool deleteFile(const std::string& path)
+    {
+        bool result = std::remove(path.c_str()) == 0;
+        EXPECT_FALSE(fileExists(path));
+        return result;
+    }
+
     TEST(LogWriterTest, SetLogDirectoryOpensNewFile)
     {
         std::string path = "./orxonox.log";
 
         // cleanup before test
-        fileSuccessfullyDeleted(path);
+        deleteFile(path);
 
         {
             LogWriter logWriter;
@@ -40,7 +78,7 @@
         }
 
         // cleanup after test
-        EXPECT_TRUE(fileSuccessfullyDeleted(path));
+        EXPECT_TRUE(deleteFile(path));
     }
 
     // prints output to logfile
@@ -60,25 +98,7 @@
             path = logWriter.getPath();
         }
 
-        {
-            std::ifstream file(path.c_str(), std::fstream::in);
-            ASSERT_TRUE(file.is_open());
-            ASSERT_TRUE(file.good());
-            ASSERT_FALSE(file.eof());
-
-            while (!file.eof())
-            {
-                std::string line;
-                std::getline(file, line);
-
-                // see if we find the output and return
-                if (line.find("mytestoutput") != std::string::npos)
-                    return;
-            }
-
-            // output not found - failure!
-            FAIL();
-        }
+        EXPECT_TRUE(fileContains(path, "mytestoutput"));
     }
 
     // prints time to logfile
@@ -98,35 +118,106 @@
             path = logWriter.getPath();
         }
 
+        std::string line = getLineWhichContains(path, "myothertestoutput");
+        EXPECT_FALSE(line.empty());
+        EXPECT_TRUE(std::isdigit(line[0]));
+        EXPECT_TRUE(std::isdigit(line[1]));
+        EXPECT_EQ(':', line[2]);
+        EXPECT_TRUE(std::isdigit(line[3]));
+        EXPECT_TRUE(std::isdigit(line[4]));
+        EXPECT_EQ(':', line[5]);
+        EXPECT_TRUE(std::isdigit(line[6]));
+        EXPECT_TRUE(std::isdigit(line[7]));
+        EXPECT_EQ(' ', line[8]);
+    }
+
+    void deleteAllLogFiles()
+    {
+        std::string path;
         {
-            std::ifstream file(path.c_str(), std::fstream::in);
-            ASSERT_TRUE(file.is_open());
-            ASSERT_TRUE(file.good());
-            ASSERT_FALSE(file.eof());
+            LogWriter writer;
+            path = writer.getPath();
+        }
 
-            while (!file.eof())
-            {
-                std::string line;
-                std::getline(file, line);
+        deleteFile(path);
+        deleteFile(path + ".1");
+        deleteFile(path + ".2");
+        deleteFile(path + ".3");
+        deleteFile(path + ".4");
+        deleteFile(path + ".5");
+        deleteFile(path + ".6");
+        deleteFile(path + ".7");
+        deleteFile(path + ".8");
+        deleteFile(path + ".9");
+    }
 
-                // see if we find the output and return
-                if (line.find("myothertestoutput") != std::string::npos)
-                {
-                    EXPECT_TRUE(std::isdigit(line[0]));
-                    EXPECT_TRUE(std::isdigit(line[1]));
-                    EXPECT_EQ(':', line[2]);
-                    EXPECT_TRUE(std::isdigit(line[3]));
-                    EXPECT_TRUE(std::isdigit(line[4]));
-                    EXPECT_EQ(':', line[5]);
-                    EXPECT_TRUE(std::isdigit(line[6]));
-                    EXPECT_TRUE(std::isdigit(line[7]));
-                    EXPECT_EQ(' ', line[8]);
-                    return;
-                }
-            }
+    TEST(LogWriterTest, ArchivesOldLogFile)
+    {
+        deleteAllLogFiles();
 
-            // output not found - failure!
-            FAIL();
+        std::string path;
+
+        {
+            MockLogWriter writer;
+            path = writer.getPath();
+            writer.printLine("test1", level::message);
         }
+
+        EXPECT_TRUE(fileExists(path));
+        EXPECT_TRUE(fileContains(path, "test1"));
+        EXPECT_FALSE(fileExists(path + ".1"));
+        EXPECT_FALSE(fileExists(path + ".2"));
+        EXPECT_FALSE(fileExists(path + ".3"));
+
+        {
+            MockLogWriter writer;
+            writer.printLine("test2", level::message);
+        }
+
+        EXPECT_TRUE(fileExists(path));
+        EXPECT_TRUE(fileContains(path, "test2"));
+        EXPECT_TRUE(fileExists(path + ".1"));
+        EXPECT_TRUE(fileContains(path + ".1", "test1"));
+        EXPECT_FALSE(fileExists(path + ".2"));
+        EXPECT_FALSE(fileExists(path + ".3"));
+
+        {
+            MockLogWriter writer;
+            writer.printLine("test3", level::message);
+        }
+
+        EXPECT_TRUE(fileExists(path));
+        EXPECT_TRUE(fileContains(path, "test3"));
+        EXPECT_TRUE(fileExists(path + ".1"));
+        EXPECT_TRUE(fileContains(path + ".1", "test2"));
+        EXPECT_TRUE(fileExists(path + ".2"));
+        EXPECT_TRUE(fileContains(path + ".2", "test1"));
+        EXPECT_FALSE(fileExists(path + ".3"));
     }
+
+    TEST(LogWriterTest, ArchivesNineLogFiles)
+    {
+        deleteAllLogFiles();
+
+        std::string path;
+        for (int i = 0; i < 20; ++i)
+        {
+            MockLogWriter writer;
+            path = writer.getPath();
+            writer.printLine("test" + multi_cast<std::string>(i), level::message);
+        }
+
+        EXPECT_TRUE(fileContains(path, "test19"));
+        EXPECT_TRUE(fileContains(path + ".1", "test18"));
+        EXPECT_TRUE(fileContains(path + ".2", "test17"));
+        EXPECT_TRUE(fileContains(path + ".3", "test16"));
+        EXPECT_TRUE(fileContains(path + ".4", "test15"));
+        EXPECT_TRUE(fileContains(path + ".5", "test14"));
+        EXPECT_TRUE(fileContains(path + ".6", "test13"));
+        EXPECT_TRUE(fileContains(path + ".7", "test12"));
+        EXPECT_TRUE(fileContains(path + ".8", "test11"));
+        EXPECT_TRUE(fileContains(path + ".9", "test10"));
+        EXPECT_FALSE(fileExists(path + ".10"));
+        EXPECT_FALSE(fileExists(path + ".11"));
+    }
 }




More information about the Orxonox-commit mailing list