Sam Jaffe hace 6 años
padre
commit
e9536e7b00

+ 18 - 12
include/logger/format.h

@@ -28,8 +28,8 @@ namespace logging {
     std::vector<generator> gen;
   };
   
-  inline void format_msg( std::stringstream & msg,
-                         std::string const & interp, size_t pos) {
+  inline void format_msg(std::stringstream & msg, std::string const & interp,
+                         size_t pos) {
     msg << interp.substr(pos);
   }
   
@@ -38,22 +38,28 @@ namespace logging {
     size_t end;
   };
   
-  format_point_t get_next_format_specifier( std::string const & interp, size_t pos );
+  format_point_t get_next_format_specifier(std::string const & interp,
+                                           size_t pos );
   
   template <typename Arg0, typename... Args>
-  inline void format_msg( std::stringstream & msg,
-                         std::string const & interp, size_t pos,
-                         Arg0 && arg0, Args && ...args ) {
+  inline void format_msg(std::stringstream & msg, std::string const & interp,
+                         size_t pos, Arg0 && arg0, Args && ...args) {
     format_point_t next = get_next_format_specifier( interp, pos );
-    msg << interp.substr(pos, next.start) << arg0;
-    if ( next.start == std::string::npos ) return; // throw?
-    format_msg( msg, interp, next.end,
-               std::forward<Args>(args)... );
+    msg << interp.substr(pos, next.start);
+    if (next.start == std::string::npos) {
+      return; // throw?
+    } else if (!strncmp(interp.c_str() + next.start - 1, "{{}}", 4)) {
+      format_msg(msg, interp, next.end, std::forward<Arg0>(arg0),
+                 std::forward<Args>(args)... );
+    } else {
+      msg << arg0;
+      format_msg(msg, interp, next.end, std::forward<Args>(args)... );
+    }
   }
   
   template <typename... Args>
-  inline std::string format_msg( std::string const & interp,
-                                Args && ...args ) {
+  inline std::string format_msg(std::string const & interp,
+                                Args && ...args) {
     std::stringstream msg;
     format_msg<Args...>( msg, interp, 0, std::forward<Args>(args)... );
     return msg.str();

+ 57 - 0
logger.xcodeproj/xcshareddata/xcschemes/logger_test.xcscheme

@@ -0,0 +1,57 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<Scheme
+   LastUpgradeVersion = "1010"
+   version = "1.3">
+   <BuildAction
+      parallelizeBuildables = "YES"
+      buildImplicitDependencies = "YES">
+   </BuildAction>
+   <TestAction
+      buildConfiguration = "Debug"
+      selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB"
+      selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB"
+      codeCoverageEnabled = "YES"
+      shouldUseLaunchSchemeArgsEnv = "YES">
+      <Testables>
+         <TestableReference
+            skipped = "NO">
+            <BuildableReference
+               BuildableIdentifier = "primary"
+               BlueprintIdentifier = "CD6F7400225187F40081ED74"
+               BuildableName = "logger_test.xctest"
+               BlueprintName = "logger_test"
+               ReferencedContainer = "container:logger.xcodeproj">
+            </BuildableReference>
+         </TestableReference>
+      </Testables>
+      <AdditionalOptions>
+      </AdditionalOptions>
+   </TestAction>
+   <LaunchAction
+      buildConfiguration = "Debug"
+      selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB"
+      selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB"
+      launchStyle = "0"
+      useCustomWorkingDirectory = "NO"
+      ignoresPersistentStateOnLaunch = "NO"
+      debugDocumentVersioning = "YES"
+      debugServiceExtension = "internal"
+      allowLocationSimulation = "YES">
+      <AdditionalOptions>
+      </AdditionalOptions>
+   </LaunchAction>
+   <ProfileAction
+      buildConfiguration = "Release"
+      shouldUseLaunchSchemeArgsEnv = "YES"
+      savedToolIdentifier = ""
+      useCustomWorkingDirectory = "NO"
+      debugDocumentVersioning = "YES">
+   </ProfileAction>
+   <AnalyzeAction
+      buildConfiguration = "Debug">
+   </AnalyzeAction>
+   <ArchiveAction
+      buildConfiguration = "Release"
+      revealArchiveInOrganizer = "YES">
+   </ArchiveAction>
+</Scheme>

+ 5 - 0
logger.xcodeproj/xcuserdata/samjaffe.xcuserdatad/xcschemes/xcschememanagement.plist

@@ -29,6 +29,11 @@
 			<key>primary</key>
 			<true/>
 		</dict>
+		<key>CD6F7400225187F40081ED74</key>
+		<dict>
+			<key>primary</key>
+			<true/>
+		</dict>
 	</dict>
 </dict>
 </plist>

+ 4 - 9
src/format.cxx

@@ -199,14 +199,9 @@ namespace logging {
 }
 
 namespace logging {
-  format_point_t get_next_format_specifier( std::string const & interp, size_t pos ) {
-    size_t next = pos;
-    char const * str = interp.c_str();
-    do {
-      pos = interp.find("{}", next);
-      next = pos + 2;
-    } while ( pos > 0 && pos != std::string::npos &&
-             ! strncmp(str + pos - 1, "{{}}", 4) );
-    return { pos, next };
+  format_point_t get_next_format_specifier(std::string const & interp,
+                                           size_t pos) {
+    size_t next = interp.find("{}", pos);
+    return { next, next + 2 };
   }
 }

+ 35 - 4
test/logger_test.cxx

@@ -9,9 +9,28 @@
 
 #include "logger/logger.h"
 
+namespace logging {
+  void PrintTo(location_info const & info, std::ostream * os) {
+    if (info.line) {
+      (*os) << "{\"" << info.filename << "\", \"" <<
+          info.function << "\", " << info.line << "}";
+    } else {
+      (*os) << "NULL";
+    }
+  }
+  void PrintTo(logpacket const & pkt, std::ostream * os) {
+    (*os) << "{ " << logging::level_header(pkt.level) << ", ";
+    PrintTo(pkt.info, os);
+    (*os) << ", \"" << pkt.logger << "\", \"" << pkt.message << "\" }";
+  }
+}
+
 struct MockLoggerImpl : public logging::logger_impl {
   MockLoggerImpl() {
-    min_log_level = logging::LTRACE;
+    SetLogLevel(logging::LTRACE);
+  }
+  void SetLogLevel(logging::log_level ll) {
+    min_log_level = ll;
   }
   MOCK_METHOD0(flush, void());
   MOCK_METHOD1(write, void(logging::logpacket const &));
@@ -25,7 +44,6 @@ struct LoggerTest : public testing::Test {
 };
 
 using namespace logging;
-using namespace testing;
 
 struct t_logger : public logger {
   t_logger(std::string const & name, std::shared_ptr<logger_impl> impl)
@@ -34,6 +52,7 @@ struct t_logger : public logger {
 
 void LoggerTest::SetUp() {
   pimpl.reset(new MockLoggerImpl);
+  using testing::AnyNumber;
   EXPECT_CALL(*pimpl, flush()).Times(AnyNumber());
 }
 
@@ -44,6 +63,18 @@ void LoggerTest::TearDown() {
 TEST_F(LoggerTest, LogsWithBraceFmtCode) {
   using testing::Field;
   EXPECT_CALL(*pimpl, write(Field(&logpacket::message, "5"))).Times(1);
-  logger LOG = t_logger("", pimpl);
-  LOG.log(LERROR, "{}", 5);
+  t_logger("", pimpl).log(LERROR, "{}", 5);
+}
+
+TEST_F(LoggerTest, DoesNotLogAboveLevel) {
+  using testing::_;
+  pimpl->SetLogLevel(LFATAL);
+  EXPECT_CALL(*pimpl, write(_)).Times(0);
+  t_logger("", pimpl).log(LERROR, "{}", 5);
+}
+
+TEST_F(LoggerTest, LogCurlyBraceLiteralByDoubling) {
+  using testing::Field;
+  EXPECT_CALL(*pimpl, write(Field(&logpacket::message, "{}"))).Times(1);
+  t_logger("", pimpl).log(LERROR, "{{}}", 5);
 }