Commits

Steven Peters committed 32a4cc3 Merge

Merged in publisher_queue_limit (pull request #230)

Fix for Issue #365: warn when messages are dropped

Comments (0)

Files changed (15)

cmake/GazeboUtils.cmake

 macro (gz_setup_apple)
   set(CMAKE_SHARED_LINKER_FLAGS "${CMAKE_SHARED_LINKER_FLAGS} -Wl,-undefined -Wl,dynamic_lookup")
 endmacro()
+
+#################################################
+macro (gz_build_tests)
+
+  # Build all the tests
+  foreach(GTEST_SOURCE_file ${ARGN})
+    string(REGEX REPLACE ".cc" "" BINARY_NAME ${GTEST_SOURCE_file})
+    add_executable(${BINARY_NAME} ${GTEST_SOURCE_file})
+
+    add_dependencies(${BINARY_NAME}
+      gtest gtest_main
+      gazebo_sdf_interface
+      gazebo_common
+      gazebo_math
+      gazebo_physics
+      gazebo_sensors
+      gazebo_rendering
+      gazebo_msgs
+      gazebo_transport)
+  
+    target_link_libraries(${BINARY_NAME}
+      libgtest.a
+      libgtest_main.a
+      gazebo_sdf_interface
+      gazebo_common
+      gazebo_math
+      gazebo_physics
+      gazebo_sensors
+      gazebo_rendering
+      gazebo_msgs
+      gazebo_transport
+      pthread
+      )
+  
+    add_test(${BINARY_NAME} ${CMAKE_CURRENT_BINARY_DIR}/${BINARY_NAME}
+      --gtest_output=xml:${CMAKE_BINARY_DIR}/test_results/${BINARY_NAME}.xml)
+  
+    set_tests_properties(${BINARY_NAME} PROPERTIES TIMEOUT 240)
+  
+    # Check that the test produced a result and create a failure if it didn't.
+    # Guards against crashed and timed out tests.
+    add_test(check_${BINARY_NAME} ${PROJECT_SOURCE_DIR}/tools/check_test_ran.py
+             ${CMAKE_BINARY_DIR}/test_results/${BINARY_NAME}.xml)
+  endforeach()
+
+endmacro()

gazebo/CMakeLists.txt

 link_directories(
   ${ogre_library_dirs}
   ${Boost_LIBRARY_DIRS}
+  ${PROJECT_BINARY_DIR}/test
 )
 
 if(HAVE_URDFDOM_HEADERS)

gazebo/common/CMakeLists.txt

   Time.hh
   Timer.hh
   Video.hh
-  )
+ )
+
+set (gtest_sources
+  Console_TEST.cc
+)
+gz_build_tests(${gtest_sources})
+
 
 set (common_headers "" CACHE INTERNAL "common headers" FORCE)
 foreach (hdr ${headers})

gazebo/common/Console.cc

  * limitations under the License.
  *
  */
-/*
- * Desc: Gazebo Console messages
- * Author: Nathan Koenig
- * Date: 09 June 2007
- */
-
 #include <string.h>
+#include <boost/filesystem.hpp>
 #include <sstream>
 
-#include "common/Exception.hh"
-#include "common/Console.hh"
+#include "gazebo/common/Exception.hh"
+#include "gazebo/common/Time.hh"
+#include "gazebo/common/Console.hh"
 
 using namespace gazebo;
 using namespace common;
 
-Console *Console::myself = NULL;
-
 //////////////////////////////////////////////////
 Console::Console()
 {
   this->msgStream = &std::cout;
   this->errStream = &std::cerr;
+  this->logStream = NULL;
 }
 
 //////////////////////////////////////////////////
 Console::~Console()
 {
+  if (this->logStream)
+    this->logStream->close();
 }
 
 //////////////////////////////////////////////////
-Console *Console::Instance()
+void Console::Init(const std::string &_logFilename)
 {
-  if (myself == NULL)
-    myself = new Console();
+  if (!getenv("HOME"))
+    gzthrow("Missing HOME environment variable");
 
-  return myself;
-}
+  boost::filesystem::path logPath(getenv("HOME"));
+  logPath = logPath / ".gazebo/" / _logFilename;
 
-//////////////////////////////////////////////////
-void Console::Load()
-{
+  this->logStream = new std::ofstream(logPath.string().c_str(), std::ios::out);
 }
 
 //////////////////////////////////////////////////
 }
 
 //////////////////////////////////////////////////
-std::ostream &Console::ColorMsg(const std::string &lbl, int color)
+std::ostream &Console::ColorMsg(const std::string &_lbl, int _color)
 {
   // if (**this->quietP)
   // return this->nullStream;
   // else
   // {
-  *this->msgStream << "\033[1;" << color << "m" << lbl << "\033[0m ";
+  *this->msgStream << "\033[1;" << _color << "m" << _lbl << "\033[0m ";
   return *this->msgStream;
   // }
 }
 
 //////////////////////////////////////////////////
+std::ofstream &Console::Log()
+{
+  if (!this->logStream)
+    gzthrow("Console has not been initialized\n");
+
+  *this->logStream << "[" << common::Time::GetWallTime() << "] ";
+  this->logStream->flush();
+  return *this->logStream;
+}
+
+//////////////////////////////////////////////////
 std::ostream &Console::ColorErr(const std::string &lbl,
                                 const std::string &file,
                                 unsigned int line, int color)

gazebo/common/Console.hh

 #include <fstream>
 #include <string>
 
-#include "common/CommonTypes.hh"
+#include "gazebo/common/SingletonT.hh"
+#include "gazebo/common/CommonTypes.hh"
 
 namespace gazebo
 {
     #define gzerr (gazebo::common::Console::Instance()->ColorErr("Error", \
           __FILE__, __LINE__, 31))
 
-    /// start marker
+    /// \brief Output a message to a log file
+    #define gzlog (gazebo::common::Console::Instance()->Log())
+
+    /// Start marker
     #define gzclr_start(clr) "\033[1;33m"
-    /// end marker
+
+    /// End marker
     #define gzclr_end "\033[0m"
 
-
-
     /// \addtogroup gazebo_common Common
     /// \{
 
     /// \class Console Console.hh common/commom.hh
     /// \brief Message, error, warning functionality
 
-    class Console
+    class Console : public SingletonT<Console>
     {
       /// \brief Default constructor
       private: Console();
       /// \brief Destructor
       private: virtual ~Console();
 
-      /// \brief Return an instance to this class
-      public: static Console *Instance();
-
       /// \brief Load the message parameters
-      public: void Load();
+      public: void Init(const std::string &_logFilename);
 
       /// \brief Set quiet output
       /// \param[in] q True to prevent warning
       /// \return Reference to an output stream
       public: std::ostream &ColorMsg(const std::string &_lbl, int _color);
 
+      /// \brief Use this to output a colored message to the terminal
+      /// \param[in] _lbl Text label
+      /// \return Reference to an output stream
+      public: std::ofstream &Log();
+
       /// \brief Use this to output an error to the terminal
       /// \param[in] _lbl Text label
       /// \param[in] _file File containing the error
       public: std::ostream &ColorErr(const std::string &_lbl,
                   const std::string &_file, unsigned int _line, int _color);
 
+
       /// \class NullStream Animation.hh common/common.hh
       /// \brief A stream that does not output anywhere
       private: class NullStream : public std::ostream
                  public: NullStream() : std::ios(0), std::ostream(0) {}
                };
 
-      /// \brief null stream
+      /// \brief Null stream
       private: NullStream nullStream;
 
-      /// \brief message stream
+      /// \brief Message stream
       private: std::ostream *msgStream;
 
-      /// \brief error stream
+      /// \brief Error stream
       private: std::ostream *errStream;
 
-      /// Pointer to myself
-      private: static Console *myself;
+      /// \brief Stream for a log file.
+      private: std::ofstream *logStream;
+
+      /// \brief This is a singleton
+      private: friend class SingletonT<Console>;
     };
     /// \}
   }

gazebo/common/Console_TEST.cc

+/*
+ * Copyright 2012 Open Source Robotics Foundation
+ *
+ * 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 <gtest/gtest.h>
+#include <boost/filesystem.hpp>
+#include <stdlib.h>
+
+#include "gazebo/common/Console.hh"
+
+/////////////////////////////////////////////////
+/// \brief Test Console::Init and Console::Log
+TEST(Console_TEST, InitAndLog)
+{
+  // Initialize Conosol
+  gazebo::common::Console::Instance()->Init("test.log");
+
+  EXPECT_TRUE(getenv("HOME") != NULL);
+
+  // Make sure that the log file has been created
+  std::string logPath = getenv("HOME");
+  boost::filesystem::path testLog(logPath);
+  testLog = testLog / ".gazebo/test.log";
+  EXPECT_TRUE(boost::filesystem::exists(testLog));
+
+  // Test Console::Log
+  {
+    std::string logString = "this is a test";
+    std::string loggedString;
+
+    // Log the string
+    gzlog << logString << std::endl;
+
+    // Open the log file, and read back the string
+    std::ifstream ifs(testLog.string().c_str(), std::ios::in);
+    std::getline(ifs, loggedString);
+    EXPECT_TRUE(loggedString.find(logString) != std::string::npos);
+  }
+}
+
+/////////////////////////////////////////////////
+/// \brief Test Console::ColorMsg
+TEST(Console_TEST, ColorMsg)
+{
+  std::ostream *stream;
+  stream = &(gazebo::common::Console::Instance()->ColorMsg("label", 20));
+
+  EXPECT_TRUE(stream != NULL);
+  EXPECT_TRUE(stream->good());
+}
+
+/////////////////////////////////////////////////
+/// \brief Test Console::ColorErr
+TEST(Console_TEST, ColorErr)
+{
+  std::ostream *stream;
+  stream = &(gazebo::common::Console::Instance()->ColorErr("label",
+        "myfile", 10, 20));
+
+  EXPECT_TRUE(stream != NULL);
+  EXPECT_TRUE(stream->good());
+}
+
+/////////////////////////////////////////////////
+int main(int argc, char **argv)
+{
+  ::testing::InitGoogleTest(&argc, argv);
+  return RUN_ALL_TESTS();
+}

gazebo/gui/Gui.cc

 #include "gazebo/gui/qt.h"
 #include "gazebo/gazebo.hh"
 
+#include "gazebo/common/Console.hh"
 #include "gazebo/common/LogRecord.hh"
 #include "gazebo/common/Plugin.hh"
 #include "gazebo/common/CommonTypes.hh"
 /////////////////////////////////////////////////
 bool gui::run(int _argc, char **_argv)
 {
-  gazebo::common::LogRecord::Instance()->Init("gui");
+  // Initialize the informational logger. This will log warnings, and errors.
+  gazebo::common::Console::Instance()->Init("gzclient.log");
+
+  // Initialize the data logger. This will log state information.
+  gazebo::common::LogRecord::Instance()->Init("gzclient");
 
   if (!parse_args(_argc, _argv))
     return false;

gazebo/msgs/test/CMakeLists.txt

   ${PROTOBUF_INCLUDE_DIR}
 )
 
-link_directories(${PROJECT_BINARY_DIR}/test)
-
 set (gtest_sources 
   MsgFactory.cc 
 )

gazebo/physics/World.cc

   this->prevStates[1].SetName(this->GetName());
 
   this->initialized = true;
+
+  // Mark the world initialization
+  gzlog << "World::Init" << std::endl;
 }
 
 //////////////////////////////////////////////////

gazebo/physics/ode/ODEJoint.cc

       if (dynamicsElem->HasElement("friction"))
       {
         sdf::ElementPtr frictionElem = dynamicsElem->GetElement("friction");
-        gzwarn << "joint friction not implemented\n";
+        gzlog << "joint friction not implemented\n";
       }
     }
   }

gazebo/server_main.cc

 */
 #include "gazebo/common/Exception.hh"
 #include "gazebo/common/LogRecord.hh"
+#include "gazebo/common/Console.hh"
 #include "gazebo/Server.hh"
 
 //////////////////////////////////////////////////
 
   try
   {
-    gazebo::common::LogRecord::Instance()->Init("server");
+    // Initialize the informational logger. This will log warnings, and
+    // errors.
+    gazebo::common::Console::Instance()->Init("gzserver.log");
+
+    // Initialize the data logger. This will log state information.
+    gazebo::common::LogRecord::Instance()->Init("gzserver");
+
+    // Output the version of Gazebo.
+    gzlog << GAZEBO_VERSION_HEADER << std::endl;
 
     server = new gazebo::Server();
     if (!server->ParseArgs(argc, argv))

gazebo/transport/Publisher.cc

   : topic(_topic), msgType(_msgType), queueLimit(_limit)
 {
   this->prevMsg = NULL;
+  this->queueLimitWarned = false;
 }
 
 //////////////////////////////////////////////////
   : topic(_topic), msgType(_msgType), queueLimit(_limit)
 {
   this->prevMsg = NULL;
+  this->queueLimitWarned = false;
 }
 
 //////////////////////////////////////////////////
 
     if (this->messages.size() > this->queueLimit)
     {
+      if (!queueLimitWarned)
+      {
+        gzwarn << "Queue limit reached for topic "
+               << this->topic
+               << ", deleting message"
+               << " (only this warning is printed to the console, "
+               << "see the ~/.gazebo/gzserver.log and "
+               << "~/.gazebo/gzclient.log files for future warnings).\n";
+        queueLimitWarned = true;
+      }
+      gzlog << "Queue limit reached for topic "
+            << this->topic
+            << ", deleting message\n";
       delete this->messages.front();
       this->messages.pop_front();
     }

gazebo/transport/Publisher.hh

       private: std::string topic;
       private: std::string msgType;
       private: unsigned int queueLimit;
+      private: bool queueLimitWarned;
       private: std::list<google::protobuf::Message *> messages;
       private: mutable boost::recursive_mutex mutex;
       private: PublicationPtr publications[2];

test/ServerFixture.hh

 #include <map>
 #include <string>
 
-#include "transport/transport.hh"
+#include "gazebo/transport/transport.hh"
 
-#include "common/SystemPaths.hh"
-#include "physics/World.hh"
-#include "physics/PhysicsTypes.hh"
-#include "physics/Physics.hh"
-#include "sensors/sensors.hh"
-#include "rendering/rendering.hh"
-#include "msgs/msgs.hh"
+#include "gazebo/common/SystemPaths.hh"
+#include "gazebo/common/Console.hh"
+#include "gazebo/physics/World.hh"
+#include "gazebo/physics/PhysicsTypes.hh"
+#include "gazebo/physics/Physics.hh"
+#include "gazebo/sensors/sensors.hh"
+#include "gazebo/rendering/rendering.hh"
+#include "gazebo/msgs/msgs.hh"
 
 #include "gazebo_config.h"
 #include "gazebo/Server.hh"
                this->imgData = NULL;
                this->serverThread = NULL;
 
+               common::Console::Instance()->Init("test.log");
                common::SystemPaths::Instance()->AddGazeboPaths(
                    TEST_REGRESSION_PATH);
 

test/unit/common.cc

   EXPECT_TRUE(mat.GetLighting());
 }
 
-TEST_F(CommonTest, Console)
-{
-  common::Console::Instance()->Load();
-  common::Console::Instance()->SetQuiet(true);
-}
-
 TEST_F(CommonTest, Exception)
 {
   try