[dhcpv6] Deny unused results

Bug: 73468
Change-Id: If6af09a7f00e0fddc6b44caa8211147a0559761d
Reviewed-on: https://fuchsia-review.googlesource.com/c/fuchsia/+/514740
Reviewed-by: Jay Zhuang <jayzhuang@google.com>
Commit-Queue: Tamir Duberstein <tamird@google.com>
diff --git a/build/config/rust/BUILD.gn b/build/config/rust/BUILD.gn
index d46e3d9..b9c4f52 100644
--- a/build/config/rust/BUILD.gn
+++ b/build/config/rust/BUILD.gn
@@ -142,7 +142,6 @@
     "//src/connectivity/location/*",
     "//src/connectivity/lowpan/*",
     "//src/connectivity/management/*",
-    "//src/connectivity/network/dhcpv6/*",
     "//src/connectivity/network/http-client/*",
     "//src/connectivity/network/lib/*",
     "//src/connectivity/network/netstack/*",
diff --git a/src/connectivity/network/dhcpv6/client/BUILD.gn b/src/connectivity/network/dhcpv6/client/BUILD.gn
index 31bf3f6..9d6f065 100644
--- a/src/connectivity/network/dhcpv6/client/BUILD.gn
+++ b/src/connectivity/network/dhcpv6/client/BUILD.gn
@@ -39,6 +39,8 @@
     "src/main.rs",
     "src/provider.rs",
   ]
+
+  configs -= [ "//build/config/rust:allow_unused_results" ]
 }
 
 fuchsia_component("component") {
diff --git a/src/connectivity/network/dhcpv6/client/src/main.rs b/src/connectivity/network/dhcpv6/client/src/main.rs
index f305591..58f67a3 100644
--- a/src/connectivity/network/dhcpv6/client/src/main.rs
+++ b/src/connectivity/network/dhcpv6/client/src/main.rs
@@ -12,8 +12,8 @@
     anyhow::{Context as _, Error, Result},
     fidl_fuchsia_net_dhcpv6::ClientProviderRequestStream,
     fuchsia_async as fasync,
-    fuchsia_component::server::ServiceFs,
-    futures::{future, StreamExt, TryStreamExt},
+    fuchsia_component::server::{ServiceFs, ServiceFsDir},
+    futures::{future, StreamExt as _, TryStreamExt as _},
 };
 
 enum IncomingService {
@@ -26,8 +26,9 @@
     let () = log::info!("starting");
 
     let mut fs = ServiceFs::new_local();
-    fs.dir("svc").add_fidl_service(IncomingService::ClientProvider);
-    fs.take_and_serve_directory_handle()?;
+    let _: &mut ServiceFsDir<'_, _> =
+        fs.dir("svc").add_fidl_service(IncomingService::ClientProvider);
+    let _: &mut ServiceFs<_> = fs.take_and_serve_directory_handle()?;
 
     fs.then(future::ok::<_, Error>)
         .try_for_each_concurrent(None, |request| async {
diff --git a/src/connectivity/network/dhcpv6/core/BUILD.gn b/src/connectivity/network/dhcpv6/core/BUILD.gn
index 612aeb5..82542b4 100644
--- a/src/connectivity/network/dhcpv6/core/BUILD.gn
+++ b/src/connectivity/network/dhcpv6/core/BUILD.gn
@@ -25,6 +25,8 @@
     "src/client.rs",
     "src/lib.rs",
   ]
+
+  configs -= [ "//build/config/rust:allow_unused_results" ]
 }
 
 fuchsia_unittest_package("dhcpv6-core-test") {
diff --git a/src/connectivity/network/dhcpv6/core/src/client.rs b/src/connectivity/network/dhcpv6/core/src/client.rs
index f4e76af..65c3c0b 100644
--- a/src/connectivity/network/dhcpv6/core/src/client.rs
+++ b/src/connectivity/network/dhcpv6/core/src/client.rs
@@ -115,7 +115,7 @@
 
 /// Holds data and provides methods for handling state transitions from information requesting
 /// state.
-#[derive(Debug, Default)]
+#[derive(Debug, PartialEq)]
 struct InformationRequesting {
     retrans_timeout: Duration,
 }
@@ -129,7 +129,7 @@
         options_to_request: &[v6::OptionCode],
         rng: &mut R,
     ) -> Transition {
-        let info_req: Self = Default::default();
+        let info_req = Self { retrans_timeout: Default::default() };
         info_req.send_and_schedule_retransmission(transaction_id, options_to_request, rng)
     }
 
@@ -199,11 +199,10 @@
             }
         }
 
-        let actions = vec![
+        let actions = std::array::IntoIter::new([
             Action::CancelTimer(ClientTimerType::Retransmission),
             Action::ScheduleTimer(ClientTimerType::Refresh, information_refresh_time),
-        ]
-        .into_iter()
+        ])
         .chain(dns_servers.clone().map(|server_addrs| Action::UpdateDnsServers(server_addrs)))
         .collect::<Vec<_>>();
 
@@ -217,7 +216,7 @@
 }
 
 /// Provides methods for handling state transitions from information received state.
-#[derive(Debug)]
+#[derive(Debug, PartialEq)]
 struct InformationReceived {
     /// Stores the DNS servers received from the reply.
     dns_servers: Vec<Ipv6Addr>,
@@ -238,7 +237,7 @@
 /// All possible states of a DHCPv6 client.
 ///
 /// States not found in this enum are not supported yet.
-#[derive(Debug)]
+#[derive(Debug, PartialEq)]
 enum ClientState {
     /// Creating and (re)transmitting an information request, and waiting for a reply.
     InformationRequesting(InformationRequesting),
@@ -257,7 +256,7 @@
     fn reply_message_received<B: ByteSlice>(self, msg: v6::Message<'_, B>) -> Transition {
         match self {
             ClientState::InformationRequesting(s) => s.reply_message_received(msg),
-            state => (state, vec![]),
+            state => (state, Vec::new()),
         }
     }
 
@@ -274,7 +273,7 @@
             ClientState::InformationRequesting(s) => {
                 s.retransmission_timer_expired(transaction_id, options_to_request, rng)
             }
-            state => (state, vec![]),
+            state => (state, Vec::new()),
         }
     }
 
@@ -291,7 +290,7 @@
             ClientState::InformationReceived(s) => {
                 s.refresh_timer_expired(transaction_id, options_to_request, rng)
             }
-            state => (state, vec![]),
+            state => (state, Vec::new()),
         }
     }
 
@@ -417,26 +416,28 @@
     #[test]
     fn test_information_request_and_reply() {
         // Try to start information request with different list of requested options.
-        for options in vec![
+        for options in std::array::IntoIter::new([
             Vec::new(),
             vec![v6::OptionCode::DnsServers],
             vec![v6::OptionCode::DnsServers, v6::OptionCode::DomainList],
-        ] {
+        ]) {
             let (mut client, actions) = ClientStateMachine::start_information_request(
                 [0, 1, 2],
                 options.clone(),
                 StepRng::new(std::u64::MAX / 2, 0),
             );
 
-            assert_matches!(client.state, Some(ClientState::InformationRequesting(_)));
+            assert_eq!(
+                client.state,
+                Some(ClientState::InformationRequesting(InformationRequesting {
+                    retrans_timeout: INFO_REQ_TIMEOUT,
+                }))
+            );
 
             // Start of information requesting should send a information request and schedule a
             // retransmission timer.
-            let want_options = if options.is_empty() {
-                Vec::new()
-            } else {
-                vec![v6::DhcpOption::Oro(options.clone())]
-            };
+            let want_options =
+                if options.is_empty() { Vec::new() } else { vec![v6::DhcpOption::Oro(options)] };
             let builder = v6::MessageBuilder::new(
                 v6::MessageType::InformationRequest,
                 client.transaction_id,
@@ -445,20 +446,19 @@
             let mut want_buf = vec![0; builder.bytes_len()];
             let () = builder.serialize(&mut want_buf);
             assert_eq!(
-                actions,
-                vec![
+                actions[..],
+                [
                     Action::SendMessage(want_buf),
                     Action::ScheduleTimer(ClientTimerType::Retransmission, INFO_REQ_TIMEOUT)
                 ]
             );
 
+            let dns_servers = vec![std_ip_v6!("ff01::0102"), std_ip_v6!("ff01::0304")];
+
             let test_dhcp_refresh_time = 42u32;
             let options = [
                 v6::DhcpOption::InformationRefreshTime(test_dhcp_refresh_time),
-                v6::DhcpOption::DnsServers(vec![
-                    std_ip_v6!("ff01::0102"),
-                    std_ip_v6!("ff01::0304"),
-                ]),
+                v6::DhcpOption::DnsServers(dns_servers.clone()),
             ];
             let builder =
                 v6::MessageBuilder::new(v6::MessageType::Reply, client.transaction_id, &options);
@@ -469,20 +469,23 @@
 
             let actions = client.handle_message_receive(msg);
 
-            assert_matches!(client.state, Some(ClientState::InformationReceived(_)));
+            {
+                let dns_servers = dns_servers.clone();
+                assert_eq!(
+                    client.state,
+                    Some(ClientState::InformationReceived(InformationReceived { dns_servers }))
+                );
+            }
             // Upon receiving a valid reply, client should set up for refresh based on the reply.
             assert_eq!(
-                actions,
-                vec![
+                actions[..],
+                [
                     Action::CancelTimer(ClientTimerType::Retransmission),
                     Action::ScheduleTimer(
                         ClientTimerType::Refresh,
                         Duration::from_secs(u64::from(test_dhcp_refresh_time)),
                     ),
-                    Action::UpdateDnsServers(vec![
-                        std_ip_v6!("ff01::0102"),
-                        std_ip_v6!("ff01::0304")
-                    ]),
+                    Action::UpdateDnsServers(dns_servers)
                 ]
             );
         }
@@ -511,7 +514,7 @@
         assert!(client.handle_message_receive(msg).is_empty());
 
         // Messages with unsupported/unexpected types are discarded.
-        for msg_type in vec![
+        for msg_type in std::array::IntoIter::new([
             v6::MessageType::Solicit,
             v6::MessageType::Advertise,
             v6::MessageType::Request,
@@ -524,7 +527,7 @@
             v6::MessageType::InformationRequest,
             v6::MessageType::RelayForw,
             v6::MessageType::RelayRepl,
-        ] {
+        ]) {
             let builder = v6::MessageBuilder::new(msg_type, client.transaction_id, &[]);
             let mut buf = vec![0; builder.bytes_len()];
             let () = builder.serialize(&mut buf);
@@ -544,8 +547,13 @@
         );
 
         // The client expects either a reply or retransmission timeout in the current state.
-        client.handle_timeout(ClientTimerType::Refresh);
-        assert_matches!(client.state, Some(ClientState::InformationRequesting(_)));
+        assert_eq!(client.handle_timeout(ClientTimerType::Refresh)[..], []);
+        assert_eq!(
+            client.state,
+            Some(ClientState::InformationRequesting(InformationRequesting {
+                retrans_timeout: INFO_REQ_TIMEOUT
+            }))
+        );
 
         let builder = v6::MessageBuilder::new(v6::MessageType::Reply, client.transaction_id, &[]);
         let mut buf = vec![0; builder.bytes_len()];
@@ -553,20 +561,35 @@
         let mut buf = &buf[..]; // Implements BufferView.
         let msg = v6::Message::parse(&mut buf, ()).expect("failed to parse test buffer");
         // Transition to InformationReceived state.
-        client.handle_message_receive(msg);
-        assert_matches!(client.state, Some(ClientState::InformationReceived(_)));
+        assert_eq!(
+            client.handle_message_receive(msg)[..],
+            [
+                Action::CancelTimer(ClientTimerType::Retransmission),
+                Action::ScheduleTimer(ClientTimerType::Refresh, IRT_DEFAULT)
+            ]
+        );
+        assert_eq!(
+            client.state,
+            Some(ClientState::InformationReceived(InformationReceived { dns_servers: vec![] }))
+        );
 
         let mut buf = vec![0; builder.bytes_len()];
         let () = builder.serialize(&mut buf);
         let mut buf = &buf[..]; // Implements BufferView.
         let msg = v6::Message::parse(&mut buf, ()).expect("failed to parse test buffer");
         // Extra replies received in information received state are ignored.
-        client.handle_message_receive(msg);
-        assert_matches!(client.state, Some(ClientState::InformationReceived(_)));
+        assert_eq!(client.handle_message_receive(msg)[..], []);
+        assert_eq!(
+            client.state,
+            Some(ClientState::InformationReceived(InformationReceived { dns_servers: vec![] }))
+        );
 
         // Information received state should only respond to `Refresh` timer.
-        client.handle_timeout(ClientTimerType::Retransmission);
-        assert_matches!(client.state, Some(ClientState::InformationReceived(_)));
+        assert_eq!(client.handle_timeout(ClientTimerType::Retransmission)[..], []);
+        assert_eq!(
+            client.state,
+            Some(ClientState::InformationReceived(InformationReceived { dns_servers: vec![] }))
+        );
     }
 
     #[test]
@@ -604,7 +627,13 @@
         let msg = v6::Message::parse(&mut buf, ()).expect("failed to parse test buffer");
 
         // Transition to InformationReceived state.
-        client.handle_message_receive(msg);
+        assert_eq!(
+            client.handle_message_receive(msg)[..],
+            [
+                Action::CancelTimer(ClientTimerType::Retransmission),
+                Action::ScheduleTimer(ClientTimerType::Refresh, IRT_DEFAULT)
+            ]
+        );
 
         // Refresh should start another round of information request.
         let actions = client.handle_timeout(ClientTimerType::Refresh);
@@ -616,8 +645,8 @@
         let mut want_buf = vec![0; builder.bytes_len()];
         let () = builder.serialize(&mut want_buf);
         assert_eq!(
-            actions,
-            vec![
+            actions[..],
+            [
                 Action::SendMessage(want_buf),
                 Action::ScheduleTimer(ClientTimerType::Retransmission, INFO_REQ_TIMEOUT)
             ]