[netstack] Integration test for stats

Bug: 36206
Test: This is an integration test CL.
Change-Id: I31931d55086eb4fcfa2d26bffdc79c2e205a4b17
diff --git a/src/connectivity/network/tests/BUILD.gn b/src/connectivity/network/tests/BUILD.gn
index 928b2bc..4dc2dbf 100644
--- a/src/connectivity/network/tests/BUILD.gn
+++ b/src/connectivity/network/tests/BUILD.gn
@@ -14,6 +14,7 @@
   deps = [
     "//garnet/lib/rust/fidl_fuchsia_net_stack_ext",
     "//garnet/lib/rust/files_async",
+    "//garnet/lib/rust/io_util",
     "//garnet/public/lib/fidl/rust/fidl",
     "//garnet/public/rust/fuchsia-async",
     "//garnet/public/rust/fuchsia-component",
@@ -25,6 +26,7 @@
     "//src/connectivity/network/testing/netemul/lib/fidl:environment-rustc",
     "//src/connectivity/network/testing/netemul/lib/fidl:network-rustc",
     "//src/connectivity/network/testing/netemul/lib/fidl:sandbox-rustc",
+    "//third_party/rust_crates:byteorder",
     "//third_party/rust_crates:failure",
     "//third_party/rust_crates:futures-preview",
     "//zircon/system/fidl/fuchsia-hardware-ethernet:fuchsia-hardware-ethernet-rustc",
diff --git a/src/connectivity/network/tests/src/lib.rs b/src/connectivity/network/tests/src/lib.rs
index 687deac..13ce422 100644
--- a/src/connectivity/network/tests/src/lib.rs
+++ b/src/connectivity/network/tests/src/lib.rs
@@ -149,6 +149,30 @@
     async_fn(netstack_proxy, device).await
 }
 
+async fn read_stat_counter(
+    file_proxy: fidl_fuchsia_io::FileProxy,
+) -> std::result::Result<u64, failure::Error> {
+    let expected_len = std::mem::size_of::<u64>(); // 8 bytes
+
+    // Ask for one byte more than expected to ensure the content is exactly the right size.
+    let (status, content) = file_proxy
+        .read(expected_len as u64 + 1)
+        .await
+        .context("failed to call fuchsia.io.File.Read")?;
+    let () = fuchsia_zircon::Status::ok(status).context("failed to read file")?;
+
+    // try_into() will fail if content.len() != expected_len;
+    let content: [u8; 8] =
+        content[..].try_into().with_context(|std::array::TryFromSliceError { .. }| {
+            format!(
+                "expected {}-byte counter value, observed {} bytes",
+                expected_len,
+                content.len()
+            )
+        })?;
+    Ok(u64::from_le_bytes(content))
+}
+
 #[fuchsia_async::run_singlethreaded(test)]
 async fn get_aggregate_stats() -> Result {
     let name = stringify!(get_aggregate_stats);
@@ -174,6 +198,25 @@
     // TODO(tamird): use into_iter after
     // https://github.com/rust-lang/rust/issues/25725.
     assert_eq!(path_segments, [1, 2, 3].iter().cloned().collect());
+
+    {
+        // Aggregate stats' initial values should be zero, before any packet can be exchanged.
+        for e in &dir_entries {
+            let file_proxy = io_util::open_file(
+                &client,
+                &std::path::Path::new(&e.name),
+                fidl_fuchsia_io::OPEN_RIGHT_READABLE,
+            )?;
+            assert_eq!(0, read_stat_counter(file_proxy).await.context("failed to read stats")?);
+        }
+
+        // Make sure interesting stats exist.
+        assert!(dir_entries.iter().any(|e| e.name == "IP/PacketsReceived"));
+        assert!(dir_entries.iter().any(|e| e.name == "IP/PacketsSent"));
+        assert!(dir_entries.iter().any(|e| e.name == "ICMP/V4PacketsReceived/Echo"));
+        assert!(dir_entries.iter().any(|e| e.name == "ICMP/V4PacketsSent/Echo"));
+    }
+
     Ok(())
 }