@@ -3302,3 +3302,148 @@ return "ok"
33023302 let stderr = wrk. output_stderr ( & mut cmd) ;
33033303 assert ! ( stderr. contains( "Invalid shell command" ) ) ;
33043304}
3305+
3306+ #[ test]
3307+ fn luau_string_find_with_parentheses_escaped ( ) {
3308+ let wrk = Workdir :: new ( "luau_string_find_parentheses_escaped" ) ;
3309+ wrk. create (
3310+ "data.csv" ,
3311+ vec ! [
3312+ svec![ "No" , "Name" , "Points" ] ,
3313+ svec![ "1" , "DNE (2)" , "1" ] ,
3314+ svec![ "2" , "Eberhard Lisse" , "1" ] ,
3315+ svec![ "3" , "Jane (Smith)" , "2" ] ,
3316+ ] ,
3317+ ) ;
3318+
3319+ let mut cmd = wrk. command ( "luau" ) ;
3320+ cmd. arg ( "map" )
3321+ . arg ( "newpoints" )
3322+ . arg ( r#"if string.find(Name, 'DNE %(2%)') then return 0 elseif string.find(Name, 'Jane %(Smith%)') then return 10 else return Points end"# )
3323+ . arg ( "data.csv" ) ;
3324+
3325+ let got: Vec < Vec < String > > = wrk. read_stdout ( & mut cmd) ;
3326+ let expected = vec ! [
3327+ svec![ "No" , "Name" , "Points" , "newpoints" ] ,
3328+ svec![ "1" , "DNE (2)" , "1" , "0" ] ,
3329+ svec![ "2" , "Eberhard Lisse" , "1" , "1" ] ,
3330+ svec![ "3" , "Jane (Smith)" , "2" , "10" ] ,
3331+ ] ;
3332+ assert_eq ! ( got, expected) ;
3333+ }
3334+
3335+ #[ test]
3336+ fn luau_string_find_with_parentheses_plain_mode ( ) {
3337+ let wrk = Workdir :: new ( "luau_string_find_parentheses_plain" ) ;
3338+ wrk. create (
3339+ "data.csv" ,
3340+ vec ! [
3341+ svec![ "No" , "Name" , "Points" ] ,
3342+ svec![ "1" , "DNE (2)" , "1" ] ,
3343+ svec![ "2" , "Eberhard Lisse" , "1" ] ,
3344+ svec![ "3" , "Jane (Smith)" , "2" ] ,
3345+ ] ,
3346+ ) ;
3347+
3348+ let mut cmd = wrk. command ( "luau" ) ;
3349+ cmd. arg ( "map" )
3350+ . arg ( "newpoints" )
3351+ . arg ( r#"if string.find(Name, 'DNE (2)', 1, true) then return 0 elseif string.find(Name, 'Jane (Smith)', 1, true) then return 10 else return Points end"# )
3352+ . arg ( "data.csv" ) ;
3353+
3354+ let got: Vec < Vec < String > > = wrk. read_stdout ( & mut cmd) ;
3355+ let expected = vec ! [
3356+ svec![ "No" , "Name" , "Points" , "newpoints" ] ,
3357+ svec![ "1" , "DNE (2)" , "1" , "0" ] ,
3358+ svec![ "2" , "Eberhard Lisse" , "1" , "1" ] ,
3359+ svec![ "3" , "Jane (Smith)" , "2" , "10" ] ,
3360+ ] ;
3361+ assert_eq ! ( got, expected) ;
3362+ }
3363+
3364+ #[ test]
3365+ fn luau_string_find_special_characters_dots ( ) {
3366+ let wrk = Workdir :: new ( "luau_string_find_dots" ) ;
3367+ wrk. create (
3368+ "data.csv" ,
3369+ vec ! [
3370+ svec![ "email" , "valid" ] ,
3371+ svec![ "user@example.com" , "yes" ] ,
3372+ svec![ "test@testdotcom" , "no" ] ,
3373+ svec![ "admin@site.org" , "yes" ] ,
3374+ ] ,
3375+ ) ;
3376+
3377+ // Using plain text mode to find literal dots in email addresses
3378+ let mut cmd = wrk. command ( "luau" ) ;
3379+ cmd. arg ( "filter" )
3380+ . arg ( r#"string.find(email, '.com', 1, true)"# )
3381+ . arg ( "data.csv" ) ;
3382+
3383+ let got: Vec < Vec < String > > = wrk. read_stdout ( & mut cmd) ;
3384+ let expected = vec ! [ svec![ "email" , "valid" ] , svec![ "user@example.com" , "yes" ] ] ;
3385+ assert_eq ! ( got, expected) ;
3386+ }
3387+
3388+ #[ test]
3389+ fn luau_string_find_special_characters_escaped_dots ( ) {
3390+ let wrk = Workdir :: new ( "luau_string_find_escaped_dots" ) ;
3391+ wrk. create (
3392+ "data.csv" ,
3393+ vec ! [
3394+ svec![ "text" ] ,
3395+ svec![ "Version 1.0" ] ,
3396+ svec![ "Version 2.5" ] ,
3397+ svec![ "No version" ] ,
3398+ ] ,
3399+ ) ;
3400+
3401+ // Using escaped dot to match literal dot in version numbers
3402+ let mut cmd = wrk. command ( "luau" ) ;
3403+ cmd. arg ( "filter" )
3404+ . arg ( r#"string.find(text, '%d%.%d')"# )
3405+ . arg ( "data.csv" ) ;
3406+
3407+ let got: Vec < Vec < String > > = wrk. read_stdout ( & mut cmd) ;
3408+ let expected = vec ! [ svec![ "text" ] , svec![ "Version 1.0" ] , svec![ "Version 2.5" ] ] ;
3409+ assert_eq ! ( got, expected) ;
3410+ }
3411+
3412+ #[ test]
3413+ fn luau_string_find_issue_3089 ( ) {
3414+ // Reproducing the exact issue from GitHub issue #3089
3415+ let wrk = Workdir :: new ( "luau_issue_3089" ) ;
3416+ wrk. create (
3417+ "a.csv" ,
3418+ vec ! [
3419+ svec![ "No" , "Name" , "Minutes" , "Points" ] ,
3420+ svec![ "1" , "DNE (2)" , "16" , "1" ] ,
3421+ svec![ "2" , "Eberhard Lisse" , "33" , "1" ] ,
3422+ ] ,
3423+ ) ;
3424+
3425+ // Test with escaped parentheses
3426+ let mut cmd = wrk. command ( "luau" ) ;
3427+ cmd. arg ( "map" )
3428+ . arg ( "newpoints" )
3429+ . arg ( r#"if string.find(Name,'DNE %(2%)') then return 0 else return Points end"# )
3430+ . arg ( "a.csv" ) ;
3431+
3432+ let got: Vec < Vec < String > > = wrk. read_stdout ( & mut cmd) ;
3433+ let expected = vec ! [
3434+ svec![ "No" , "Name" , "Minutes" , "Points" , "newpoints" ] ,
3435+ svec![ "1" , "DNE (2)" , "16" , "1" , "0" ] ,
3436+ svec![ "2" , "Eberhard Lisse" , "33" , "1" , "1" ] ,
3437+ ] ;
3438+ assert_eq ! ( got, expected) ;
3439+
3440+ // Test with plain text mode
3441+ let mut cmd2 = wrk. command ( "luau" ) ;
3442+ cmd2. arg ( "map" )
3443+ . arg ( "newpoints" )
3444+ . arg ( r#"if string.find(Name,'DNE (2)', 1, true) then return 0 else return Points end"# )
3445+ . arg ( "a.csv" ) ;
3446+
3447+ let got2: Vec < Vec < String > > = wrk. read_stdout ( & mut cmd2) ;
3448+ assert_eq ! ( got2, expected) ;
3449+ }
0 commit comments