blob: cb3d6ad5240abfb3002045436d16766d708487b2 [file] [log] [blame]
// Copyright 2018 The Fuchsia Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
use {
fidl::{endpoints::RequestStream, Error as FidlError},
fidl_fuchsia_bluetooth_snoop::{
PacketType, SnoopMarker, SnoopPacket, SnoopProxy, SnoopRequestStream, Timestamp,
},
fuchsia_async::{Channel, Executor},
fuchsia_inspect::{assert_inspect_tree, Inspector},
fuchsia_zircon as zx,
std::task::Poll,
};
use super::*;
fn setup() -> (
Executor,
ConcurrentSnooperPacketFutures,
PacketLogs,
SubscriptionManager,
ConcurrentClientRequestFutures,
Inspector,
) {
let inspect = Inspector::new();
(
fasync::Executor::new().unwrap(),
ConcurrentSnooperPacketFutures::new(),
PacketLogs::new(10, 10, Duration::new(10, 0), inspect.root().create_child("packet_log")),
SubscriptionManager::new(),
ConcurrentClientRequestFutures::new(),
inspect,
)
}
#[test]
fn test_id_generator() {
let mut id_gen = IdGenerator::new();
assert_eq!(id_gen.next(), ClientId(0));
assert_eq!(id_gen.next(), ClientId(1));
}
#[test]
fn test_register_new_client() {
let (_exec, _snoopers, _logs, _subscribers, mut requests, _inspect) = setup();
assert_eq!(requests.len(), 0);
let (_tx, rx) = zx::Channel::create().unwrap();
let stream = SnoopRequestStream::from_channel(Channel::from_channel(rx).unwrap());
register_new_client(stream, &mut requests, ClientId(0));
assert_eq!(requests.len(), 1);
}
fn fidl_endpoints() -> (SnoopProxy, SnoopRequestStream) {
let (proxy, server) = fidl::endpoints::create_proxy::<SnoopMarker>().unwrap();
let request_stream = server.into_stream().unwrap();
(proxy, request_stream)
}
fn unwrap_request<T, E>(request: Poll<Option<Result<T, E>>>) -> T {
if let Poll::Ready(Some(Ok(request))) = request {
return request;
}
panic!("Failed to receive request");
}
fn unwrap_response<T, E>(response: Poll<Result<T, E>>) -> T {
if let Poll::Ready(Ok(response)) = response {
return response;
}
panic!("Failed to receive response");
}
#[test]
fn test_snoop_default_command_line_args() {
let args = Args::from_args(&["bt-snoop.cmx"], &[]).expect("Args created from empty args");
assert_eq!(args.log_size_kib, 256);
assert_eq!(args.log_time_seconds, 60);
assert_eq!(args.max_device_count, 8);
assert_eq!(args.truncate_payload, None);
assert_eq!(args.verbosity, 0);
}
#[test]
fn test_snoop_command_line_args() {
let log_size_kib = 1;
let log_time_seconds = 2;
let max_device_count = 3;
let truncate_payload = 4;
let verbosity = 2;
let raw_args = &[
"--log-size-kib",
&log_size_kib.to_string(),
"--log-time-seconds",
&log_time_seconds.to_string(),
"--max-device-count",
&max_device_count.to_string(),
"--truncate-payload",
&truncate_payload.to_string(),
"-v",
"-v",
];
let args = Args::from_args(&["bt-snoop.cmx"], raw_args).expect("Args created from args");
assert_eq!(args.log_size_kib, log_size_kib);
assert_eq!(args.log_time_seconds, log_time_seconds);
assert_eq!(args.max_device_count, max_device_count);
assert_eq!(args.truncate_payload, Some(truncate_payload));
assert_eq!(args.verbosity, verbosity);
}
#[test]
fn test_packet_logs_inspect() {
// This is a test that basic inspect data is plumbed through from the inspect root.
// More comprehensive testing of possible permutations of packet log inspect data
// is found in bounded_queue.rs
let inspect = Inspector::new();
let runtime_metrics_node = inspect.root().create_child("runtime_metrics");
let mut packet_logs = PacketLogs::new(2, 256, Duration::from_secs(60), runtime_metrics_node);
assert_inspect_tree!(inspect, root: {
runtime_metrics: {
logging_active_for_devices: "",
}
});
let id_1 = String::from("001");
packet_logs.add_device(id_1.clone());
assert_inspect_tree!(inspect, root: {
runtime_metrics: {
logging_active_for_devices: "\"001\"",
device_001: {
size_in_bytes: 0u64,
number_of_items: 0u64,
},
}
});
let packet = SnoopPacket {
is_received: false,
type_: PacketType::Data,
timestamp: Timestamp { subsec_nanos: 0, seconds: 123 },
original_len: 3,
payload: vec![3, 2, 1],
};
packet_logs.log_packet(&id_1, packet);
assert_inspect_tree!(inspect, root: {
runtime_metrics: {
logging_active_for_devices: "\"001\"",
device_001: {
size_in_bytes: 75u64,
number_of_items: 1u64,
"0": vec![0u8, 0, 0, 123, 0, 0, 0, 0, 0, 0, 0, 8, 0, 0, 0, 8, 0, 0, 0, 0, 2, 3, 2, 1],
},
}
});
drop(packet_logs);
}
#[test]
fn test_snoop_config_inspect() {
let args = Args {
log_size_kib: 1,
log_time_seconds: 2,
max_device_count: 3,
truncate_payload: Some(4),
verbosity: 5,
};
let inspect = Inspector::new();
let snoop_config_node = inspect.root().create_child("configuration");
let config = SnoopConfig::from_args(args, snoop_config_node);
assert_inspect_tree!(inspect, root: {
configuration: {
log_size_bytes: 1024u64,
log_time: 2u64,
max_device_count: 3u64,
truncate_payload: "4 bytes",
hci_dir: HCI_DEVICE_CLASS_PATH,
}
});
drop(config);
}
#[test]
fn test_handle_client_request() {
let (mut exec, mut _snoopers, mut logs, mut subscribers, mut requests, _inspect) = setup();
// unrecognized device returns an error to the client
let (proxy, mut request_stream) = fidl_endpoints();
let mut client_fut = proxy.start(true, Some(""));
let _ = exec.run_until_stalled(&mut client_fut);
let request = unwrap_request(exec.run_until_stalled(&mut request_stream.next()));
let request = (ClientId(0), (Some(Ok(request)), request_stream));
handle_client_request(request, &mut requests, &mut subscribers, &mut logs).unwrap();
let response = unwrap_response(exec.run_until_stalled(&mut client_fut));
assert!(response.error.is_some());
assert_eq!(subscribers.number_of_subscribers(), 0);
// valid device returns no errors to a client subscribed to that device
let (proxy, mut request_stream) = fidl_endpoints();
logs.add_device(String::new());
let mut client_fut = proxy.start(true, Some(""));
let _ = exec.run_until_stalled(&mut client_fut);
let request = unwrap_request(exec.run_until_stalled(&mut request_stream.next()));
let request = (ClientId(1), (Some(Ok(request)), request_stream));
handle_client_request(request, &mut requests, &mut subscribers, &mut logs).unwrap();
let response = unwrap_response(exec.run_until_stalled(&mut client_fut));
assert!(response.error.is_none());
assert_eq!(subscribers.number_of_subscribers(), 1);
// valid device returns no errors to a client subscribed globally
let (proxy, mut request_stream) = fidl_endpoints();
let mut client_fut = proxy.start(true, None);
let _ = exec.run_until_stalled(&mut client_fut);
let request = unwrap_request(exec.run_until_stalled(&mut request_stream.next()));
let request = (ClientId(2), (Some(Ok(request)), request_stream));
handle_client_request(request, &mut requests, &mut subscribers, &mut logs).unwrap();
let response = unwrap_response(exec.run_until_stalled(&mut client_fut));
println!("{:?}", response.error);
assert!(response.error.is_none());
assert_eq!(subscribers.number_of_subscribers(), 2);
// second request by the same client returns an error
let (proxy, mut request_stream) = fidl_endpoints();
let mut client_fut = proxy.start(true, None);
let _ = exec.run_until_stalled(&mut client_fut);
let request = unwrap_request(exec.run_until_stalled(&mut request_stream.next()));
let request = (ClientId(2), (Some(Ok(request)), request_stream));
handle_client_request(request, &mut requests, &mut subscribers, &mut logs).unwrap();
let response = unwrap_response(exec.run_until_stalled(&mut client_fut));
println!("{:?}", response.error);
assert!(response.error.is_some());
assert_eq!(subscribers.number_of_subscribers(), 2);
// valid device returns no errors to a client requesting a dump
let (proxy, mut request_stream) = fidl_endpoints();
let mut client_fut = proxy.start(false, None);
let _ = exec.run_until_stalled(&mut client_fut);
let request = unwrap_request(exec.run_until_stalled(&mut request_stream.next()));
let request = (ClientId(3), (Some(Ok(request)), request_stream));
handle_client_request(request, &mut requests, &mut subscribers, &mut logs).unwrap();
let response = unwrap_response(exec.run_until_stalled(&mut client_fut));
println!("{:?}", response.error);
assert!(response.error.is_none());
assert_eq!(subscribers.number_of_subscribers(), 2);
}
#[test]
fn test_handle_bad_client_request() {
let (_exec, mut _snoopers, mut logs, mut subscribers, mut requests, _inspect) = setup();
let id = ClientId(0);
let err = Some(Err(FidlError::Invalid));
let (_proxy, req_stream) = fidl_endpoints();
let handle = req_stream.control_handle();
let request = (id, (err, req_stream));
subscribers.register(id, handle, None).unwrap();
assert!(subscribers.is_registered(&id));
handle_client_request(request, &mut requests, &mut subscribers, &mut logs).unwrap();
assert!(!subscribers.is_registered(&id));
let id = ClientId(1);
let err = Some(Err(FidlError::Invalid));
let (_proxy, req_stream) = fidl_endpoints();
let handle = req_stream.control_handle();
let request = (id, (err, req_stream));
subscribers.register(id, handle, None).unwrap();
assert!(subscribers.is_registered(&id));
handle_client_request(request, &mut requests, &mut subscribers, &mut logs).unwrap();
assert!(!subscribers.is_registered(&id));
}