[test][logger] Add FX_PLOGS() that logs zx_status_t as string

And also FX_VPLOGS. Similar to FXL_PLOG() recent addition, this suffixes
the message with "%d (%s)" for the zx_status_t given.

This does not handle the third style, FX_LOG() yet. It seems less-used
and more complicated to handle so it might not be worth it.

ZX-4110 #comment [test][logger] Add FX_PLOGS() that logs zx_status_t as string

Test: new tests in logger_unittest.cc
Change-Id: I7c65dbb6b110f3c0b9b785b1a1de7e5171382d26
diff --git a/garnet/public/lib/syslog/cpp/logger.cc b/garnet/public/lib/syslog/cpp/logger.cc
index 7340027a..f4ab9fd 100644
--- a/garnet/public/lib/syslog/cpp/logger.cc
+++ b/garnet/public/lib/syslog/cpp/logger.cc
@@ -5,6 +5,7 @@
 #include "logger.h"
 
 #include <lib/syslog/global.h>
+#include <zircon/status.h>
 
 namespace syslog {
 namespace {
@@ -28,8 +29,13 @@
 namespace internal {
 
 LogMessage::LogMessage(fx_log_severity_t severity, const char* file, int line,
-                       const char* tag, const char* condition)
-    : severity_(severity), file_(file), line_(line), tag_(tag) {
+                       const char* tag, zx_status_t status,
+                       const char* condition)
+    : severity_(severity),
+      file_(file),
+      line_(line),
+      tag_(tag),
+      status_(status) {
   stream_ << (severity > FX_LOG_INFO ? StripDots(file_) : StripPath(file_))
           << "(" << line_ << "): ";
 
@@ -40,6 +46,10 @@
 LogMessage::~LogMessage() {
   fx_logger_t* logger = fx_log_get_logger();
   if (logger) {
+    if (status_ != INT32_MAX) {
+      stream_ << ": " << status_ << " (" << zx_status_get_string(status_)
+              << ")";
+    }
     fx_logger_log(logger, severity_, tag_, stream_.str().c_str());
   }
 }
diff --git a/garnet/public/lib/syslog/cpp/logger.h b/garnet/public/lib/syslog/cpp/logger.h
index dfe699d..fac1ea8 100644
--- a/garnet/public/lib/syslog/cpp/logger.h
+++ b/garnet/public/lib/syslog/cpp/logger.h
@@ -6,6 +6,8 @@
 #define LIB_SYSLOG_CPP_LOGGER_H_
 
 #include <lib/syslog/global.h>
+#include <stdint.h>
+#include <zircon/types.h>
 
 #include <initializer_list>
 #include <ostream>
@@ -23,7 +25,7 @@
 class LogMessage {
  public:
   LogMessage(fx_log_severity_t severity, const char* file, int line,
-             const char* tag, const char* condition);
+             const char* tag, zx_status_t status, const char* condition);
   ~LogMessage();
 
   std::ostream& stream() { return stream_; }
@@ -34,6 +36,7 @@
   const char* file_;
   const int line_;
   const char* tag_;
+  const zx_status_t status_;
 
   LogMessage(const LogMessage&) = delete;
   LogMessage& operator=(const LogMessage&) = delete;
@@ -70,12 +73,13 @@
 
 }  // namespace syslog
 
-#define _FX_LOG_STREAM(severity, tag)                                   \
+#define _FX_LOG_STREAM(severity, tag, status)                           \
   ::syslog::internal::LogMessage((severity), __FILE__, __LINE__, (tag), \
-                                 nullptr)                               \
+                                 (status), nullptr)                     \
       .stream()
 
-#define FX_LOG_STREAM(severity, tag) _FX_LOG_STREAM(FX_LOG_##severity, (tag))
+#define FX_LOG_STREAM(severity, tag, status) \
+  _FX_LOG_STREAM(FX_LOG_##severity, (tag), (status))
 
 #define FX_LOG_LAZY_STREAM(stream, condition) \
   !(condition) ? (void)0 : ::syslog::internal::LogMessageVoidify() & (stream)
@@ -85,7 +89,7 @@
       ? (void)0                                                              \
       : FX_LOG_LAZY_STREAM(                                                  \
             ::syslog::internal::LogMessage(FX_LOG_FATAL, __FILE__, __LINE__, \
-                                           tag, #ignored)                    \
+                                           tag, INT32_MAX, #ignored)         \
                 .stream(),                                                   \
             !(ignored))
 
@@ -93,21 +97,36 @@
 // |severity| is one of DEBUG, INFO, WARNING, ERROR, FATAL
 // |tag| is a tag to associated with the message, or NULL if none.
 #define FX_LOGST(severity, tag)                      \
-  FX_LOG_LAZY_STREAM(FX_LOG_STREAM(severity, (tag)), \
+  FX_LOG_LAZY_STREAM(FX_LOG_STREAM(severity, (tag), INT32_MAX), \
+                     FX_LOG_IS_ENABLED(severity))
+
+// Writes a message to the global logger.
+// |severity| is one of DEBUG, INFO, WARNING, ERROR, FATAL
+// |tag| is a tag to associated with the message, or NULL if none.
+// |status| is a zx_status_t which will be appended in decimal and string forms
+// after the message.
+#define FX_PLOGST(severity, tag, status)                       \
+  FX_LOG_LAZY_STREAM(FX_LOG_STREAM(severity, (tag), (status)), \
                      FX_LOG_IS_ENABLED(severity))
 
 // Writes a message to the global logger.
 // |severity| is one of FX_LOG_DEBUG, FX_LOG_INFO, FX_LOG_WARNING,
 // FX_LOG_ERROR, FX_LOG_FATAL
 // |tag| is a tag to associated with the message, or NULL if none.
-#define FX_LOGST_WITH_SEVERITY(severity, tag)           \
-  FX_LOG_LAZY_STREAM(_FX_LOG_STREAM((severity), (tag)), \
+#define FX_LOGST_WITH_SEVERITY(severity, tag)                      \
+  FX_LOG_LAZY_STREAM(_FX_LOG_STREAM((severity), (tag), INT32_MAX), \
                      fx_log_is_enabled((severity)))
 
 // Writes a message to the global logger.
 // |severity| is one of DEBUG, INFO, WARNING, ERROR, FATAL
 #define FX_LOGS(severity) FX_LOGST(severity, nullptr)
 
+// Writes a message to the global logger.
+// |severity| is one of DEBUG, INFO, WARNING, ERROR, FATAL
+// |status| is a zx_status_t which will be appended in decimal and string forms
+// after the message.
+#define FX_PLOGS(severity, status) FX_PLOGST(severity, nullptr, status)
+
 // Writes a message to the global logger, the first |n| times that any callsite
 // of this macro is invoked. |n| should be a positive integer literal. If a
 // single callsite is invoked by multiple threads it is possible that the
@@ -143,11 +162,12 @@
 
 // Writes error message to the global logger if |condition| fails.
 // |tag| is a tag to associated with the message, or NULL if none.
-#define FX_CHECKT(condition, tag)                                              \
-  FX_LOG_LAZY_STREAM(::syslog::internal::LogMessage(FX_LOG_FATAL, __FILE__,    \
-                                                    __LINE__, tag, #condition) \
-                         .stream(),                                            \
-                     !(condition))
+#define FX_CHECKT(condition, tag)                                           \
+  FX_LOG_LAZY_STREAM(                                                       \
+      ::syslog::internal::LogMessage(FX_LOG_FATAL, __FILE__, __LINE__, tag, \
+                                     INT32_MAX, #condition)                 \
+          .stream(),                                                        \
+      !(condition))
 
 // Writes error message to the global logger if |condition| fails.
 #define FX_CHECK(condition) FX_CHECKT(condition, nullptr)
@@ -163,15 +183,22 @@
 #endif
 
 // VLOG macros log with negative verbosities.
-#define FX_VLOG_STREAM(verbose_level, tag)                                    \
+#define FX_VLOG_STREAM(verbose_level, tag, status)                            \
   ::syslog::internal::LogMessage(-(verbose_level), __FILE__, __LINE__, (tag), \
-                                 nullptr)                                     \
+                                 (status), nullptr)                           \
       .stream()
 
-#define FX_VLOGST(verbose_level, tag)                        \
-  FX_LOG_LAZY_STREAM(FX_VLOG_STREAM((verbose_level), (tag)), \
+#define FX_VLOGST(verbose_level, tag)                                   \
+  FX_LOG_LAZY_STREAM(FX_VLOG_STREAM((verbose_level), (tag), INT32_MAX), \
+                     FX_VLOG_IS_ENABLED((verbose_level)))
+
+#define FX_VPLOGST(verbose_level, tag, status)                         \
+  FX_LOG_LAZY_STREAM(FX_VLOG_STREAM((verbose_level), (tag), (status)), \
                      FX_VLOG_IS_ENABLED((verbose_level)))
 
 #define FX_VLOGS(verbose_level) FX_VLOGST((verbose_level), nullptr)
 
+#define FX_VPLOGS(verbose_level, status) \
+  FX_VPLOGST((verbose_level), nullptr, status)
+
 #endif  // LIB_SYSLOG_CPP_LOGGER_H_
diff --git a/garnet/public/lib/syslog/cpp/logger_unittest.cc b/garnet/public/lib/syslog/cpp/logger_unittest.cc
index 820ff79..7dc7df2 100644
--- a/garnet/public/lib/syslog/cpp/logger_unittest.cc
+++ b/garnet/public/lib/syslog/cpp/logger_unittest.cc
@@ -139,6 +139,18 @@
                         1);
 }
 
+TEST(Logger, PLogWithTag) {
+  Cleanup cleanup;
+  zx::socket local, remote;
+  EXPECT_EQ(ZX_OK, zx::socket::create(ZX_SOCKET_DATAGRAM, &local, &remote));
+  ASSERT_EQ(ZX_OK, init_helper(remote.release(), nullptr, 0));
+  FX_PLOGST(INFO, "tag", ZX_ERR_ACCESS_DENIED) << "something that failed";
+  const char* tags[] = {"tag"};
+  output_compare_helper(std::move(local), FX_LOG_INFO,
+                        "something that failed: -30 (ZX_ERR_ACCESS_DENIED)",
+                        tags, 1);
+}
+
 TEST(Logger, CheckFunction) {
   Cleanup cleanup;
   zx::socket local, remote;
@@ -194,6 +206,29 @@
   output_compare_helper(std::move(local), -1, msg, tags, 1);
 }
 
+TEST(Logger, VPLogWithTag) {
+  Cleanup cleanup;
+  zx::socket local, remote;
+  EXPECT_EQ(ZX_OK, zx::socket::create(ZX_SOCKET_DATAGRAM, &local, &remote));
+  ASSERT_EQ(ZX_OK, init_helper(remote.release(), nullptr, 0));
+  const char* msg = "with error";
+  const char* msg_suffixed = "with error: -40 (ZX_ERR_IO)";
+  const char* tags[] = {"tag"};
+  FX_VPLOGST(1, tags[0], ZX_ERR_IO) << msg;
+  size_t outstanding_bytes = 10u;  // init to non zero value.
+  ASSERT_EQ(ZX_OK, GetAvailableBytes(local, &outstanding_bytes));
+  EXPECT_EQ(0u, outstanding_bytes);
+
+  FX_LOG_SET_VERBOSITY(1);
+  FX_VPLOGST(2, tags[0], ZX_ERR_IO) << msg;
+  outstanding_bytes = 10u;  // init to non zero value.
+  ASSERT_EQ(ZX_OK, GetAvailableBytes(local, &outstanding_bytes));
+  EXPECT_EQ(0u, outstanding_bytes);
+
+  FX_VPLOGST(1, tags[0], ZX_ERR_IO) << msg;
+  output_compare_helper(std::move(local), -1, msg_suffixed, tags, 1);
+}
+
 // We invoke FX_LOGS_FIRST_N(msg, 31) 100 times and check that the message
 // was logged exactly 31 times.
 TEST(Logger, LogFirstN) {