@@ -799,7 +799,7 @@ impl Expr for ComparisonExpr {
799799mod tests {
800800 use super :: * ;
801801 use crate :: {
802- BytesFormat , FieldRef , LhsValue , ParserSettings , TypedMap ,
802+ BytesFormat , FieldRef , LhsValue , ParserSettings , SchemeBuilder , TypedMap ,
803803 ast:: {
804804 function_expr:: { FunctionCallArgExpr , FunctionCallExpr } ,
805805 logical_expr:: LogicalExpr ,
@@ -3040,4 +3040,211 @@ mod tests {
30403040 assert_eq ! ( expr. execute_one( ctx) , expected, "failed test case {t:?}" ) ;
30413041 }
30423042 }
3043+
3044+ #[ test]
3045+ fn test_optional_fields ( ) {
3046+ let mut builder = SchemeBuilder :: new ( ) ;
3047+ builder
3048+ . add_optional_field ( "tcp.srcport" , Type :: Int )
3049+ . unwrap ( ) ;
3050+ builder
3051+ . add_optional_field ( "tcp.dstport" , Type :: Int )
3052+ . unwrap ( ) ;
3053+ builder
3054+ . add_optional_field ( "tcp.flags.syn" , Type :: Bool )
3055+ . unwrap ( ) ;
3056+ builder
3057+ . add_optional_field ( "udp.srcport" , Type :: Int )
3058+ . unwrap ( ) ;
3059+ builder
3060+ . add_optional_field ( "udp.dstport" , Type :: Int )
3061+ . unwrap ( ) ;
3062+ builder. set_nil_not_equal_behavior ( false ) ;
3063+ let scheme = builder. build ( ) ;
3064+
3065+ macro_rules! test_case {
3066+ ( $filter: ident { $( $name: ident $( . $suffix: ident) * : $value: literal) ,* } => $outcome: literal) => { {
3067+ #[ allow( unused_mut) ]
3068+ let mut ctx = ExecutionContext :: <( ) >:: new( & scheme) ;
3069+ $(
3070+ ctx. set_field_value( scheme. get_field( stringify!( $name $( . $suffix) * ) ) . unwrap( ) , $value) . unwrap( ) ;
3071+ ) *
3072+
3073+ assert_eq!( $filter. execute( & ctx) , Ok ( $outcome) ) ;
3074+ } } ;
3075+ }
3076+
3077+ let filter = scheme
3078+ . parse ( "(tcp.dstport != 80) or (udp.dstport != 80)" )
3079+ . unwrap ( )
3080+ . compile ( ) ;
3081+
3082+ test_case ! ( filter { tcp. dstport: 443 } => true ) ;
3083+
3084+ test_case ! ( filter { tcp. dstport: 80 } => false ) ;
3085+
3086+ test_case ! ( filter { udp. dstport: 53 } => true ) ;
3087+
3088+ test_case ! ( filter { udp. dstport: 80 } => false ) ;
3089+
3090+ test_case ! ( filter { } => false ) ;
3091+
3092+ let filter = scheme
3093+ . parse ( "(tcp.dstport != 80) and (udp.dstport != 80)" )
3094+ . unwrap ( )
3095+ . compile ( ) ;
3096+
3097+ test_case ! ( filter { tcp. dstport: 443 } => false ) ;
3098+
3099+ test_case ! ( filter { tcp. dstport: 80 } => false ) ;
3100+
3101+ test_case ! ( filter { udp. dstport: 53 } => false ) ;
3102+
3103+ test_case ! ( filter { udp. dstport: 80 } => false ) ;
3104+
3105+ test_case ! ( filter { } => false ) ;
3106+
3107+ let filter = scheme
3108+ . parse ( "(tcp.srcport == 1337) or ((tcp.dstport != 80) or (udp.dstport != 80))" )
3109+ . unwrap ( )
3110+ . compile ( ) ;
3111+
3112+ test_case ! ( filter { tcp. srcport: 1337 , tcp. dstport: 80 } => true ) ;
3113+
3114+ test_case ! ( filter { tcp. srcport: 1337 , tcp. dstport: 443 } => true ) ;
3115+
3116+ test_case ! ( filter { tcp. srcport: 1234 , tcp. dstport: 80 } => false ) ;
3117+
3118+ test_case ! ( filter { tcp. srcport: 1234 , tcp. dstport: 443 } => true ) ;
3119+
3120+ test_case ! ( filter { udp. dstport: 80 } => false ) ;
3121+
3122+ test_case ! ( filter { udp. dstport: 444 } => true ) ;
3123+
3124+ test_case ! ( filter { } => false ) ;
3125+
3126+ let filter = scheme
3127+ . parse ( "(tcp.srcport == 1337) and ((tcp.dstport != 80) or (udp.dstport != 80))" )
3128+ . unwrap ( )
3129+ . compile ( ) ;
3130+
3131+ test_case ! ( filter { tcp. srcport: 1337 , tcp. dstport: 80 } => false ) ;
3132+
3133+ test_case ! ( filter { tcp. srcport: 1337 , tcp. dstport: 443 } => true ) ;
3134+
3135+ test_case ! ( filter { tcp. srcport: 1234 , tcp. dstport: 80 } => false ) ;
3136+
3137+ test_case ! ( filter { tcp. srcport: 1234 , tcp. dstport: 443 } => false ) ;
3138+
3139+ test_case ! ( filter { udp. dstport: 80 } => false ) ;
3140+
3141+ test_case ! ( filter { udp. dstport: 444 } => false ) ;
3142+
3143+ test_case ! ( filter { } => false ) ;
3144+
3145+ let filter = scheme
3146+ . parse ( "(tcp.srcport == 1337) or ((tcp.dstport != 80) and (udp.dstport != 80))" )
3147+ . unwrap ( )
3148+ . compile ( ) ;
3149+
3150+ test_case ! ( filter { tcp. srcport: 1337 , tcp. dstport: 80 } => true ) ;
3151+
3152+ test_case ! ( filter { tcp. srcport: 1337 , tcp. dstport: 443 } => true ) ;
3153+
3154+ test_case ! ( filter { tcp. srcport: 1234 , tcp. dstport: 80 } => false ) ;
3155+
3156+ test_case ! ( filter { tcp. srcport: 1234 , tcp. dstport: 443 } => false ) ;
3157+
3158+ test_case ! ( filter { udp. dstport: 80 } => false ) ;
3159+
3160+ test_case ! ( filter { udp. dstport: 444 } => false ) ;
3161+
3162+ test_case ! ( filter { } => false ) ;
3163+
3164+ let filter = scheme
3165+ . parse ( "(tcp.srcport == 1337) and ((tcp.dstport != 80) and (udp.dstport != 80))" )
3166+ . unwrap ( )
3167+ . compile ( ) ;
3168+
3169+ test_case ! ( filter { tcp. srcport: 1337 , tcp. dstport: 80 } => false ) ;
3170+
3171+ test_case ! ( filter { tcp. srcport: 1337 , tcp. dstport: 443 } => false ) ;
3172+
3173+ test_case ! ( filter { tcp. srcport: 1234 , tcp. dstport: 80 } => false ) ;
3174+
3175+ test_case ! ( filter { tcp. srcport: 1234 , tcp. dstport: 443 } => false ) ;
3176+
3177+ test_case ! ( filter { udp. dstport: 80 } => false ) ;
3178+
3179+ test_case ! ( filter { udp. dstport: 444 } => false ) ;
3180+
3181+ test_case ! ( filter { } => false ) ;
3182+
3183+ let filter = scheme
3184+ . parse ( "(tcp.srcport == 1337) and ((tcp.dstport != 80) and ((tcp.flags.syn) or (udp.dstport != 80)))" )
3185+ . unwrap ( )
3186+ . compile ( ) ;
3187+
3188+ test_case ! ( filter { tcp. srcport: 1337 , tcp. dstport: 80 , tcp. flags. syn: true } => false ) ;
3189+
3190+ test_case ! ( filter { tcp. srcport: 1337 , tcp. dstport: 443 , tcp. flags. syn: true } => true ) ;
3191+
3192+ test_case ! ( filter { tcp. srcport: 1234 , tcp. dstport: 80 , tcp. flags. syn: true } => false ) ;
3193+
3194+ test_case ! ( filter { tcp. srcport: 1234 , tcp. dstport: 443 , tcp. flags. syn: true } => false ) ;
3195+
3196+ test_case ! ( filter { tcp. srcport: 1337 , tcp. dstport: 80 , tcp. flags. syn: false } => false ) ;
3197+
3198+ test_case ! ( filter { tcp. srcport: 1337 , tcp. dstport: 443 , tcp. flags. syn: false } => false ) ;
3199+
3200+ test_case ! ( filter { tcp. srcport: 1234 , tcp. dstport: 80 , tcp. flags. syn: false } => false ) ;
3201+
3202+ test_case ! ( filter { tcp. srcport: 1234 , tcp. dstport: 443 , tcp. flags. syn: false } => false ) ;
3203+
3204+ test_case ! ( filter { udp. dstport: 80 } => false ) ;
3205+
3206+ test_case ! ( filter { udp. dstport: 444 } => false ) ;
3207+
3208+ test_case ! ( filter { } => false ) ;
3209+
3210+ let filter = scheme. parse ( "tcp.flags.syn" ) . unwrap ( ) . compile ( ) ;
3211+
3212+ test_case ! ( filter { tcp. flags. syn: true } => true ) ;
3213+
3214+ test_case ! ( filter { tcp. flags. syn: false } => false ) ;
3215+
3216+ test_case ! ( filter { } => false ) ;
3217+
3218+ let filter = scheme. parse ( "not tcp.flags.syn" ) . unwrap ( ) . compile ( ) ;
3219+
3220+ test_case ! ( filter { tcp. flags. syn: true } => false ) ;
3221+
3222+ test_case ! ( filter { tcp. flags. syn: false } => true ) ;
3223+
3224+ test_case ! ( filter { } => true ) ;
3225+
3226+ let filter = scheme. parse ( "not (not tcp.flags.syn)" ) . unwrap ( ) . compile ( ) ;
3227+
3228+ test_case ! ( filter { tcp. flags. syn: true } => true ) ;
3229+
3230+ test_case ! ( filter { tcp. flags. syn: false } => false ) ;
3231+
3232+ test_case ! ( filter { } => false ) ;
3233+
3234+ let filter = scheme. parse ( "not (tcp.dstport eq 80)" ) . unwrap ( ) . compile ( ) ;
3235+
3236+ test_case ! ( filter { tcp. dstport: 80 } => false ) ;
3237+
3238+ test_case ! ( filter { tcp. dstport: 443 } => true ) ;
3239+
3240+ test_case ! ( filter { } => true ) ;
3241+
3242+ let filter = scheme. parse ( "not (tcp.dstport ne 80)" ) . unwrap ( ) . compile ( ) ;
3243+
3244+ test_case ! ( filter { tcp. dstport: 80 } => true ) ;
3245+
3246+ test_case ! ( filter { tcp. dstport: 443 } => false ) ;
3247+
3248+ test_case ! ( filter { } => true ) ;
3249+ }
30433250}
0 commit comments