blob: 58d8dd320f0e5905dd711f4b5a28d82232c0b31b [file] [log] [blame]
// Copyright 2022 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_next::{
Client, ClientEnd, Flexible, FlexibleResult, Request, Responder, Response, Server, ServerEnd,
Transport,
};
use fidl_next_examples_calculator::calculator::prelude::*;
struct MyCalculatorClient {
error: Option<u32>,
}
impl<T: Transport> CalculatorClientHandler<T> for MyCalculatorClient {
async fn on_error(
&mut self,
client: &Client<Calculator, T>,
response: Response<calculator::OnError, T>,
) {
self.error = Some(*response.status_code);
client.close();
}
}
impl MyCalculatorClient {
pub fn new() -> Self {
Self { error: None }
}
}
struct MyCalculatorServer {
last_result: Option<i32>,
}
impl MyCalculatorServer {
pub fn new() -> Self {
Self { last_result: None }
}
}
impl<T: Transport + 'static> CalculatorServerHandler<T> for MyCalculatorServer {
async fn add(
&mut self,
request: Request<calculator::Add, T>,
responder: Responder<calculator::Add, T>,
) {
let sum = request.a + request.b;
self.last_result = Some(sum);
let response = Flexible::Ok(CalculatorAddResponse { sum });
let _ = responder.respond(response).await;
}
async fn divide(
&mut self,
request: Request<calculator::Divide, T>,
responder: Responder<calculator::Divide, T>,
) {
let response = if request.divisor != 0 {
let quotient = request.dividend / request.divisor;
self.last_result = Some(quotient);
FlexibleResult::Ok(CalculatorDivideResponse {
quotient: request.dividend / request.divisor,
remainder: request.dividend % request.divisor,
})
} else {
FlexibleResult::Err(DivisionError::DivideByZero)
};
let _ = responder.respond(response).await;
}
async fn clear(&mut self, _: &Server<Calculator, T>) {
self.last_result = None;
}
}
#[cfg(not(target_os = "fuchsia"))]
type Endpoint = fidl_next::fuchsia_async::Mpsc;
#[cfg(target_os = "fuchsia")]
type Endpoint = zx::Channel;
fn create_endpoints() -> (ClientEnd<Calculator, Endpoint>, ServerEnd<Calculator, Endpoint>) {
#[cfg(not(target_os = "fuchsia"))]
{
fidl_next::fuchsia_async::Mpsc::new()
}
#[cfg(target_os = "fuchsia")]
{
fidl_next::fuchsia::create_channel()
}
}
async fn add(client: &Client<Calculator, Endpoint>) {
let result = client.add(16, 26).await.expect("failed to send or receive request");
let response = result.ok().expect("add request failed with an error");
assert_eq!(response.sum, 42);
}
async fn divide(client: &Client<Calculator, Endpoint>) {
// Normal division
let result = client.divide(100, 3).await.expect("failed to send or receive request");
let response = result.ok().expect("divide request failed with an error");
assert_eq!(response.quotient, 33);
assert_eq!(response.remainder, 1);
// Cause an error
let result = client.divide(42, 0).await.expect("failed to send or receive request");
let error = result.err().expect("divide request succeeded unexpectedly");
assert_eq!(DivisionError::DivideByZero, (*error).into());
}
async fn clear(client: &Client<Calculator, Endpoint>) {
client.clear().await.expect("failed to send request");
}
async fn on_error(server: &Server<Calculator, Endpoint>) {
server.on_error(100u32).await.expect("failed to send event");
}
#[fuchsia_async::run_singlethreaded]
async fn main() {
let (client_end, server_end) = create_endpoints();
let (client, client_task) = client_end.spawn_full_with_handler(MyCalculatorClient::new());
let (server_task, server) = server_end.spawn_full(MyCalculatorServer::new());
add(&client).await;
divide(&client).await;
clear(&client).await;
on_error(&server).await;
client_task.await.unwrap();
server_task.await.unwrap();
}
#[cfg(test)]
mod tests {
use super::*;
#[fuchsia_async::run_singlethreaded(test)]
async fn test_add() {
let (client_end, server_end) = create_endpoints();
let (client, client_task) = client_end.spawn_full_with_handler(MyCalculatorClient::new());
let server_task = server_end.spawn(MyCalculatorServer::new());
add(&client).await;
client.close();
assert_eq!(client_task.await.unwrap().error, None);
assert_eq!(server_task.await.unwrap().last_result, Some(42));
}
#[fuchsia_async::run_singlethreaded(test)]
async fn test_divide() {
let (client_end, server_end) = create_endpoints();
let (client, client_task) = client_end.spawn_full_with_handler(MyCalculatorClient::new());
let server_task = server_end.spawn(MyCalculatorServer::new());
divide(&client).await;
client.close();
assert_eq!(client_task.await.unwrap().error, None);
assert_eq!(server_task.await.unwrap().last_result, Some(33));
}
#[fuchsia_async::run_singlethreaded(test)]
async fn test_clear() {
let (client_end, server_end) = create_endpoints();
let (client, client_task) = client_end.spawn_full_with_handler(MyCalculatorClient::new());
let server_task = server_end.spawn(MyCalculatorServer::new());
add(&client).await;
clear(&client).await;
client.close();
assert_eq!(client_task.await.unwrap().error, None);
assert_eq!(server_task.await.unwrap().last_result, None);
}
#[fuchsia_async::run_singlethreaded(test)]
async fn test_on_error() {
let (client_end, server_end) = create_endpoints();
let (client, client_task) = client_end.spawn_full_with_handler(MyCalculatorClient::new());
let (server_task, server) = server_end.spawn_full(MyCalculatorServer::new());
on_error(&server).await;
client.close();
assert_eq!(client_task.await.unwrap().error, Some(100));
assert_eq!(server_task.await.unwrap().last_result, None);
}
}