Path: blob/main/crates/wiggle/test-helpers/examples/tracing.rs
1692 views
use anyhow::Result;1use wiggle::GuestMemory;2use wiggle_test::{HostMemory, WasiCtx, impl_errno};34/// The `errors` argument to the wiggle gives us a hook to map a rich error5/// type like this one (typical of wiggle use cases in wasi-common and beyond)6/// down to the flat error enums that witx can specify.7#[derive(Debug, thiserror::Error)]8pub enum RichError {9#[error("Invalid argument: {0}")]10InvalidArg(String),11#[error("Won't cross picket line: {0}")]12PicketLine(String),13}1415// Define an errno with variants corresponding to RichError. Use it in a16// trivial function.17wiggle::from_witx!({18tracing: true disable_for {19one_error_conversion::foo,20},21witx_literal: "22(typename $errno (enum (@witx tag u8) $ok $invalid_arg $picket_line))23(typename $s (record (field $f1 (@witx usize)) (field $f2 (@witx pointer u8))))24(typename $t (record (field $f1 u32) (field $f2 f32)))25(module $one_error_conversion26(@interface func (export \"foo\")27(param $strike u32)28(param $s $s)29(result $err (expected $t (error $errno)))))30",31errors: { errno => RichError },32});3334impl_errno!(types::Errno);3536/// When the `errors` mapping in witx is non-empty, we need to impl the37/// types::UserErrorConversion trait that wiggle generates from that mapping.38impl<'a> types::UserErrorConversion for WasiCtx<'a> {39fn errno_from_rich_error(&mut self, e: RichError) -> Result<types::Errno> {40wiggle::tracing::debug!(41rich_error = wiggle::tracing::field::debug(&e),42"error conversion"43);44// WasiCtx can collect a Vec<String> log so we can test this. We're45// logging the Display impl that `thiserror::Error` provides us.46self.log.borrow_mut().push(e.to_string());47// Then do the trivial mapping down to the flat enum.48match e {49RichError::InvalidArg { .. } => Ok(types::Errno::InvalidArg),50RichError::PicketLine { .. } => Ok(types::Errno::PicketLine),51}52}53}5455impl<'a> one_error_conversion::OneErrorConversion for WasiCtx<'a> {56fn foo(57&mut self,58_: &mut GuestMemory<'_>,59strike: u32,60_s: &types::S,61) -> Result<types::T, RichError> {62// We use the argument to this function to exercise all of the63// possible error cases we could hit here64match strike {650 => Ok(types::T {66f1: 123,67f2: 456.78,68}),691 => Err(RichError::PicketLine(format!("I'm not a scab"))),70_ => Err(RichError::InvalidArg(format!("out-of-bounds: {strike}"))),71}72}73}7475fn main() {76if std::env::var("RUST_LOG").is_err() {77// with no RUST_LOG env variable: use the tracing subscriber.78let subscriber = tracing_subscriber::fmt()79// all spans/events with a level equal to or higher than TRACE (e.g, trace, debug, info, warn, etc.)80// will be written to stdout.81.with_max_level(tracing::Level::TRACE)82// builds the subscriber.83.finish();84tracing::subscriber::set_global_default(subscriber).expect("set global tracing subscriber");85} else {86// with RUST_LOG set: use the env_logger backend to tracing.87env_logger::init();88}8990let mut ctx = WasiCtx::new();91let mut host_memory = HostMemory::new();92let mut memory = host_memory.guest_memory();9394// Exercise each of the branches in `foo`.95// Start with the success case:96let r0 = one_error_conversion::foo(&mut ctx, &mut memory, 0, 0, 8).unwrap();97assert_eq!(98r0,99types::Errno::Ok as i32,100"Expected return value for strike=0"101);102assert!(ctx.log.borrow().is_empty(), "No error log for strike=0");103104// First error case:105let r1 = one_error_conversion::foo(&mut ctx, &mut memory, 1, 0, 8).unwrap();106assert_eq!(107r1,108types::Errno::PicketLine as i32,109"Expected return value for strike=1"110);111assert_eq!(112ctx.log.borrow_mut().pop().expect("one log entry"),113"Won't cross picket line: I'm not a scab",114"Expected log entry for strike=1",115);116117// Second error case:118let r2 = one_error_conversion::foo(&mut ctx, &mut memory, 2, 0, 8).unwrap();119assert_eq!(120r2,121types::Errno::InvalidArg as i32,122"Expected return value for strike=2"123);124assert_eq!(125ctx.log.borrow_mut().pop().expect("one log entry"),126"Invalid argument: out-of-bounds: 2",127"Expected log entry for strike=2",128);129}130131132