Skip to main content

toasty_driver_integration_suite/
stmt.rs

1//! Expression utilities for testing with assert_struct!
2//!
3//! This module provides test utilities like the Any wildcard
4//! for use with the Like trait in assert_struct! macros.
5
6use assert_struct::Like;
7use toasty_core::stmt::{Expr, Value, ValueStream};
8
9/// Wildcard type that matches any expression - useful for ignoring fields in patterns
10#[derive(Debug, Clone)]
11pub struct Any;
12
13/// Any wildcard matches any expression
14impl Like<Any> for Expr {
15    fn like(&self, _pattern: &Any) -> bool {
16        true // Any matches everything
17    }
18}
19
20impl PartialEq<Any> for Expr {
21    fn eq(&self, _: &Any) -> bool {
22        true
23    }
24}
25
26/// Any wildcard matches any value
27impl Like<Any> for Value {
28    fn like(&self, _pattern: &Any) -> bool {
29        true // Any matches everything
30    }
31}
32
33impl PartialEq<Any> for Value {
34    fn eq(&self, _: &Any) -> bool {
35        true
36    }
37}
38
39/// Matches either an extracted bind-parameter placeholder (`Expr::Arg`, emitted
40/// by SQL drivers after parameter extraction) at a specific position, or an
41/// inline `Expr::Value` matching the contained pattern (emitted by non-SQL
42/// drivers like DynamoDB).
43///
44/// Use this when a single assertion needs to cover both representations:
45///
46/// ```ignore
47/// let val = if test.capability().sql {
48///     ArgOr::Arg(0)
49/// } else {
50///     ArgOr::Value(1i64)
51/// };
52/// assert_struct!(op, ..., rows: [=~ (Any, Any, val)]);
53/// ```
54pub enum ArgOr<V> {
55    /// Matches `Expr::Arg(_)` whose `position` equals the given index.
56    Arg(usize),
57    /// Matches `Expr::Value(_)` using the inner pattern via `Like<V>`.
58    Value(V),
59}
60
61impl<V> Like<ArgOr<V>> for Expr
62where
63    Expr: Like<V>,
64{
65    fn like(&self, pattern: &ArgOr<V>) -> bool {
66        match pattern {
67            ArgOr::Arg(pos) => matches!(self, Expr::Arg(arg) if arg.position == *pos),
68            ArgOr::Value(v) => self.like(v),
69        }
70    }
71}
72
73/// Extension trait for ValueStream providing convenient testing methods
74pub trait ValueStreamExt {
75    /// Returns buffered values, asserting that the stream is fully buffered
76    ///
77    /// This method will panic if the stream is not fully buffered (i.e., if there
78    /// are still pending values in the stream that haven't been loaded into the buffer).
79    /// Use this in tests when you want to access buffered values synchronously.
80    fn buffered(&self) -> Vec<Value>;
81}
82
83/// Blanket implementation of ValueStreamExt for ValueStream
84impl ValueStreamExt for ValueStream {
85    fn buffered(&self) -> Vec<Value> {
86        assert!(
87            self.is_buffered(),
88            "ValueStream is not fully buffered - call .buffer().await first"
89        );
90        self.buffered_to_vec()
91    }
92}