ping: remove potential divide-by-zero in StatisticsCollector

refs #3504

Change-Id: I38c1a5079e2884e53a4fff2311c98b553f42c2a3
diff --git a/tests/ping/client/statistics-collector.t.cpp b/tests/ping/client/statistics-collector.t.cpp
index 6bcb9fb..270c576 100644
--- a/tests/ping/client/statistics-collector.t.cpp
+++ b/tests/ping/client/statistics-collector.t.cpp
@@ -120,7 +120,14 @@
   BOOST_CHECK_EQUAL(stats.prefix, pingOptions.prefix);
   BOOST_CHECK_EQUAL(stats.nSent, 2);
   BOOST_CHECK_EQUAL(stats.nReceived, 0);
+  BOOST_CHECK_EQUAL(stats.nNacked, 0);
   BOOST_CHECK_CLOSE(stats.packetLossRate, 1.0, 0.001);
+  BOOST_CHECK_CLOSE(stats.packetNackedRate, 0.0, 0.001);
+  BOOST_CHECK_CLOSE(stats.minRtt, std::numeric_limits<double>::max(), 0.001);
+  BOOST_CHECK_CLOSE(stats.maxRtt, 0.0, 0.001);
+  BOOST_CHECK_CLOSE(stats.sumRtt, 0.0, 0.001);
+  BOOST_CHECK(std::isnan(stats.avgRtt));
+  BOOST_CHECK(std::isnan(stats.stdDevRtt));
 }
 
 BOOST_AUTO_TEST_CASE(Resp50msLoss)
@@ -185,6 +192,22 @@
   BOOST_CHECK_CLOSE(stats.packetLossRate, 0.5, 0.001);
 }
 
+BOOST_AUTO_TEST_CASE(NoneSent)
+{
+  Statistics stats = sc.computeStatistics();
+  BOOST_CHECK_EQUAL(stats.prefix, pingOptions.prefix);
+  BOOST_CHECK_EQUAL(stats.nSent, 0);
+  BOOST_CHECK_EQUAL(stats.nReceived, 0);
+  BOOST_CHECK_EQUAL(stats.nNacked, 0);
+  BOOST_CHECK(std::isnan(stats.packetLossRate));
+  BOOST_CHECK(std::isnan(stats.packetNackedRate));
+  BOOST_CHECK_CLOSE(stats.minRtt, std::numeric_limits<double>::max(), 0.001);
+  BOOST_CHECK_CLOSE(stats.maxRtt, 0.0, 0.001);
+  BOOST_CHECK_CLOSE(stats.sumRtt, 0.0, 0.001);
+  BOOST_CHECK(std::isnan(stats.avgRtt));
+  BOOST_CHECK(std::isnan(stats.stdDevRtt));
+}
+
 BOOST_AUTO_TEST_SUITE_END() // TestStatisticsCollector
 BOOST_AUTO_TEST_SUITE_END() // Ping
 
diff --git a/tools/ping/client/statistics-collector.cpp b/tools/ping/client/statistics-collector.cpp
index 0e7ad2a..7954e64 100644
--- a/tools/ping/client/statistics-collector.cpp
+++ b/tools/ping/client/statistics-collector.cpp
@@ -85,11 +85,26 @@
   statistics.pingStartTime = m_pingStartTime;
   statistics.minRtt = m_minRtt;
   statistics.maxRtt = m_maxRtt;
-  statistics.packetLossRate = static_cast<double>(m_nSent - m_nReceived - m_nNacked) / static_cast<double>(m_nSent);
-  statistics.packetNackedRate = static_cast<double>(m_nNacked) / static_cast<double>(m_nSent);
+
+  if (m_nSent > 0) {
+    statistics.packetLossRate = static_cast<double>(m_nSent - m_nReceived - m_nNacked) / static_cast<double>(m_nSent);
+    statistics.packetNackedRate = static_cast<double>(m_nNacked) / static_cast<double>(m_nSent);
+  }
+  else {
+    statistics.packetLossRate = std::numeric_limits<double>::quiet_NaN();
+    statistics.packetNackedRate = std::numeric_limits<double>::quiet_NaN();
+  }
+
   statistics.sumRtt = m_sumRtt;
-  statistics.avgRtt = m_sumRtt / m_nReceived;
-  statistics.stdDevRtt = std::sqrt((m_sumRttSquared / m_nReceived) - (statistics.avgRtt * statistics.avgRtt));
+
+  if (m_nReceived > 0) {
+    statistics.avgRtt = m_sumRtt / m_nReceived;
+    statistics.stdDevRtt = std::sqrt((m_sumRttSquared / m_nReceived) - (statistics.avgRtt * statistics.avgRtt));
+  }
+  else {
+    statistics.avgRtt = std::numeric_limits<double>::quiet_NaN();
+    statistics.stdDevRtt = std::numeric_limits<double>::quiet_NaN();
+  }
 
   return statistics;
 }
@@ -97,24 +112,36 @@
 std::ostream&
 Statistics::printSummary(std::ostream& os) const
 {
-  os << nReceived << "/" << nSent << " packets, " << packetLossRate * 100.0
-     << "% loss, min/avg/max/mdev = " << minRtt << "/" << avgRtt << "/" << maxRtt << "/"
-     << stdDevRtt << " ms" << std::endl;
+  os << nReceived << "/" << nSent << " packets";
 
-  return os;
+  if (nSent > 0) {
+    os << ", " << packetLossRate * 100.0 << "% lost, " << packetNackedRate * 100.0 << "% nacked";
+  }
+
+  if (nReceived > 0) {
+    os << ", min/avg/max/mdev = " << minRtt << "/" << avgRtt << "/" << maxRtt << "/" << stdDevRtt
+       << " ms";
+  }
+
+  return os << std::endl;
 }
 
 std::ostream&
 operator<<(std::ostream& os, const Statistics& statistics)
 {
   os << "\n";
-  os << "--- " << statistics.prefix <<" ping statistics ---\n";
+  os << "--- " << statistics.prefix << " ping statistics ---\n";
   os << statistics.nSent << " packets transmitted";
   os << ", " << statistics.nReceived << " received";
   os << ", " << statistics.nNacked << " nacked";
-  os << ", " << statistics.packetLossRate * 100.0 << "% packet loss";
-  os << ", " << statistics.packetNackedRate * 100.0 << "% nacked";
+
+  if (statistics.nSent > 0) {
+    os << ", " << statistics.packetLossRate * 100.0 << "% lost";
+    os << ", " << statistics.packetNackedRate * 100.0 << "% nacked";
+  }
+
   os << ", time " << statistics.sumRtt << " ms";
+
   if (statistics.nReceived > 0) {
     os << "\n";
     os << "rtt min/avg/max/mdev = ";