@@ -1453,3 +1453,91 @@ mod proto_helper_tests {
14531453 ) ) ;
14541454 }
14551455}
1456+
1457+ /// Tests for the erroring defaults of the dispatch traits' capability
1458+ /// channels: a serialization layer that implements only the required
1459+ /// `encode`/`decode` must reject function-codec and session-config requests
1460+ /// with errors naming the requested type, not panic or silently succeed.
1461+ #[ cfg( all( test, feature = "proto" ) ) ]
1462+ mod proto_capability_default_tests {
1463+ use std:: sync:: Arc ;
1464+
1465+ use arrow:: datatypes:: Schema ;
1466+ use datafusion_common:: { DataFusionError , Result } ;
1467+ use datafusion_proto_models:: protobuf:: PhysicalExprNode ;
1468+
1469+ use crate :: physical_expr:: PhysicalExpr ;
1470+ use crate :: physical_expr:: proto_decode:: { PhysicalExprDecode , PhysicalExprDecodeCtx } ;
1471+ use crate :: physical_expr:: proto_encode:: { PhysicalExprEncode , PhysicalExprEncodeCtx } ;
1472+
1473+ struct DefaultOnlyEncoder ;
1474+
1475+ impl PhysicalExprEncode for DefaultOnlyEncoder {
1476+ fn encode ( & self , _expr : & Arc < dyn PhysicalExpr > ) -> Result < PhysicalExprNode > {
1477+ unreachable ! ( "child encoding must not be reached" )
1478+ }
1479+ }
1480+
1481+ struct DefaultOnlyDecoder ;
1482+
1483+ impl PhysicalExprDecode for DefaultOnlyDecoder {
1484+ fn decode (
1485+ & self ,
1486+ _node : & PhysicalExprNode ,
1487+ _schema : & Schema ,
1488+ ) -> Result < Arc < dyn PhysicalExpr > > {
1489+ unreachable ! ( "child decoding must not be reached" )
1490+ }
1491+ }
1492+
1493+ /// Stands in for a function type (e.g. `ScalarUDF`) the layer was never
1494+ /// taught about.
1495+ #[ derive( Debug ) ]
1496+ struct NotAFunction ;
1497+
1498+ #[ test]
1499+ fn encode_function_default_errors_naming_requested_type ( ) {
1500+ let encoder = DefaultOnlyEncoder ;
1501+ let ctx = PhysicalExprEncodeCtx :: new ( & encoder) ;
1502+
1503+ let err = ctx. encode_function ( & NotAFunction ) . unwrap_err ( ) ;
1504+ assert ! ( matches!(
1505+ err,
1506+ DataFusionError :: Internal ( msg)
1507+ if msg. contains( "does not support encoding function objects" )
1508+ && msg. contains( "NotAFunction" )
1509+ ) ) ;
1510+ }
1511+
1512+ #[ test]
1513+ fn decode_function_default_errors_naming_requested_type_and_name ( ) {
1514+ let schema = Schema :: empty ( ) ;
1515+ let decoder = DefaultOnlyDecoder ;
1516+ let ctx = PhysicalExprDecodeCtx :: new ( & schema, & decoder) ;
1517+
1518+ let err = ctx
1519+ . decode_function :: < NotAFunction > ( "my_udf" , None )
1520+ . unwrap_err ( ) ;
1521+ assert ! ( matches!(
1522+ err,
1523+ DataFusionError :: Internal ( msg)
1524+ if msg. contains( "does not support resolving function objects" )
1525+ && msg. contains( "NotAFunction" )
1526+ && msg. contains( "'my_udf'" )
1527+ ) ) ;
1528+ }
1529+
1530+ #[ test]
1531+ fn config_options_default_errors ( ) {
1532+ let schema = Schema :: empty ( ) ;
1533+ let decoder = DefaultOnlyDecoder ;
1534+ let ctx = PhysicalExprDecodeCtx :: new ( & schema, & decoder) ;
1535+
1536+ let err = ctx. config_options ( ) . unwrap_err ( ) ;
1537+ assert ! ( matches!(
1538+ err,
1539+ DataFusionError :: Internal ( msg)
1540+ if msg. contains( "does not provide session configuration" )
1541+ ) ) ;
1542+ }
1543+ }
0 commit comments