Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Enhancement add modulo func to sync template #488

Merged
merged 4 commits into from
Aug 5, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
30 changes: 30 additions & 0 deletions docs/settingup.md
Original file line number Diff line number Diff line change
Expand Up @@ -2437,6 +2437,7 @@ The following functions are supported:
* `env`: Retrieve a specific environment variable. Takes one argument - the name of the environment variable to expand.
* `add`: Adds two integer values together and outputs the sum. E.g. `{{ add 1 2 }}`.
* `join`: Joins array elements together to a string separated by defined separator. E.g. `{{ join .ScriptVars.MyArray \",\" }}`.
* `modulo`: Returns modulo of two integer values and output the result. E.g. `{{ modulo 10 4 }}` (will return 2)

### Example

Expand Down Expand Up @@ -2499,6 +2500,35 @@ The following functions are supported:
}
```

Let's assume the case there are 4 apps to be used in the test, all ending with number 0 to 3. The use of modulo in the example will cycle through the app suffix number in following order: 1, 2, 3, 0.

```json
{
"action": "elastictriggersubscription",
"label": "trigger reporting task",
"settings": {
"subscriptiontype": "template-sharing",
"limitperpage": 100,
"appname": "PS-18566_Test_Levels_Pages- {{ modulo .Session 4}}",
"subscriptionmode": "random",
}
}
```

Very similar case as above but apps have number suffix from 1 to 4. This can be handled combining `modulo` and `add` functions. The cycle through the suffix number will be done in following order: 2, 3, 4, 1.
```json
{
"action": "elastictriggersubscription",
"label": "trigger reporting task",
"settings": {
"subscriptiontype": "template-sharing",
"limitperpage": 100,
"appname": "PS-18566_Test_Levels_Pages- {{ modulo .Session 4 | add 1 }}",
"subscriptionmode": "random",
}
}
```

</details>


Expand Down
30 changes: 30 additions & 0 deletions generatedocs/data/extra/sessionvariables/description.md
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,7 @@ The following functions are supported:
* `env`: Retrieve a specific environment variable. Takes one argument - the name of the environment variable to expand.
* `add`: Adds two integer values together and outputs the sum. E.g. `{{ add 1 2 }}`.
* `join`: Joins array elements together to a string separated by defined separator. E.g. `{{ join .ScriptVars.MyArray \",\" }}`.
* `modulo`: Returns modulo of two integer values and output the result. E.g. `{{ modulo 10 4 }}` (will return 2)

### Example

Expand Down Expand Up @@ -96,4 +97,33 @@ The following functions are supported:
}
```

Let's assume the case there are 4 apps to be used in the test, all ending with number 0 to 3. The use of modulo in the example will cycle through the app suffix number in following order: 1, 2, 3, 0.

```json
{
"action": "elastictriggersubscription",
"label": "trigger reporting task",
"settings": {
"subscriptiontype": "template-sharing",
"limitperpage": 100,
"appname": "PS-18566_Test_Levels_Pages- {{ modulo .Session 4}}",
"subscriptionmode": "random",
}
}
```

Very similar case as above but apps have number suffix from 1 to 4. This can be handled combining `modulo` and `add` functions. The cycle through the suffix number will be done in following order: 2, 3, 4, 1.
```json
{
"action": "elastictriggersubscription",
"label": "trigger reporting task",
"settings": {
"subscriptiontype": "template-sharing",
"limitperpage": 100,
"appname": "PS-18566_Test_Levels_Pages- {{ modulo .Session 4 | add 1 }}",
"subscriptionmode": "random",
}
}
```

</details>
2 changes: 1 addition & 1 deletion generatedocs/generated/documentation.go
Original file line number Diff line number Diff line change
Expand Up @@ -423,7 +423,7 @@ var (

Extra = map[string]common.DocEntry{
"sessionvariables": {
Description: "\n## Session variables\n\nThis section describes the session variables that can be used with some of the actions.\n\n<details>\n<summary><a name=\"session_variables\"></a>Session variables</summary>\n\nSome action parameters support session variables. A session variable is defined by putting the variable, prefixed by a dot, within double curly brackets, such as `{{.UserName}}`.\n\nThe following session variables are supported in actions:\n\n* `UserName`: The simulated username. This is not the same as the authenticated user, but rather how the username was defined by [Login settings](#login_settings). \n* `Session`: The enumeration of the currently simulated session.\n* `Thread`: The enumeration of the currently simulated \"thread\" or \"concurrent user\".\n* `ScriptVars`: A map containing script variables added by the action `setscriptvar`.\n* `Artifacts`:\n * `GetIDByTypeAndName`: A function that accepts the two string arguments,\n `artifactType` and `artifactName`, and returns the resource id of the artifact.\n * `GetNameByTypeAndID`: A function that accepts the two string arguments,\n `artifactType` and `artifactID`, and returns the name of the artifact.\n\n\nThe following variable is supported in the filename of the log file:\n\n* `ConfigFile`: The filename of the config file, without file extension.\n\nThe following functions are supported:\n\n* `now`: Evaluates Golang [time.Now()](https://golang.org/pkg/time/). \n* `hostname`: Hostname of the local machine.\n* `timestamp`: Timestamp in `yyyyMMddhhmmss` format.\n* `uuid`: Generate an uuid.\n* `env`: Retrieve a specific environment variable. Takes one argument - the name of the environment variable to expand.\n* `add`: Adds two integer values together and outputs the sum. E.g. `{{ add 1 2 }}`.\n* `join`: Joins array elements together to a string separated by defined separator. E.g. `{{ join .ScriptVars.MyArray \\\",\\\" }}`.\n\n### Example\n\n```json\n{\n \"label\" : \"Create bookmark\",\n \"action\": \"createbookmark\",\n \"settings\": {\n \"title\": \"my bookmark {{.Thread}}-{{.Session}} ({{.UserName}})\",\n \"description\": \"This bookmark contains some interesting selections\"\n }\n},\n{\n \"label\" : \"Publish created bookmark\",\n \"action\": \"publishbookmark\",\n \"disabled\" : false,\n \"settings\" : {\n \"title\": \"my bookmark {{.Thread}}-{{.Session}} ({{.UserName}})\",\n }\n}\n\n```\n\n```json\n{\n \"action\": \"createbookmark\",\n \"settings\": {\n \"title\": \"{{env \\\"TITLE\\\"}}\",\n \"description\": \"This bookmark contains some interesting selections\"\n }\n}\n```\n\n```json\n{\n \"action\": \"setscriptvar\",\n \"settings\": {\n \"name\": \"BookmarkCounter\",\n \"type\": \"int\",\n \"value\": \"1\"\n }\n},\n{\n \"action\": \"createbookmark\",\n \"settings\": {\n \"title\": \"Bookmark no {{ add .ScriptVars.BookmarkCounter 1 }}\",\n \"description\": \"This bookmark will have the title Bookmark no 2\"\n }\n}\n```\n\n```json\n{\n \"action\": \"setscriptvar\",\n \"settings\": {\n \"name\": \"MyAppId\",\n \"type\": \"string\",\n \"value\": \"{{.Artifacts.GetIDByTypeAndName \\\"app\\\" (print \\\"an-app-\\\" .Session)}}\"\n }\n}\n```\n\n</details>\n",
Description: "\n## Session variables\n\nThis section describes the session variables that can be used with some of the actions.\n\n<details>\n<summary><a name=\"session_variables\"></a>Session variables</summary>\n\nSome action parameters support session variables. A session variable is defined by putting the variable, prefixed by a dot, within double curly brackets, such as `{{.UserName}}`.\n\nThe following session variables are supported in actions:\n\n* `UserName`: The simulated username. This is not the same as the authenticated user, but rather how the username was defined by [Login settings](#login_settings). \n* `Session`: The enumeration of the currently simulated session.\n* `Thread`: The enumeration of the currently simulated \"thread\" or \"concurrent user\".\n* `ScriptVars`: A map containing script variables added by the action `setscriptvar`.\n* `Artifacts`:\n * `GetIDByTypeAndName`: A function that accepts the two string arguments,\n `artifactType` and `artifactName`, and returns the resource id of the artifact.\n * `GetNameByTypeAndID`: A function that accepts the two string arguments,\n `artifactType` and `artifactID`, and returns the name of the artifact.\n\n\nThe following variable is supported in the filename of the log file:\n\n* `ConfigFile`: The filename of the config file, without file extension.\n\nThe following functions are supported:\n\n* `now`: Evaluates Golang [time.Now()](https://golang.org/pkg/time/). \n* `hostname`: Hostname of the local machine.\n* `timestamp`: Timestamp in `yyyyMMddhhmmss` format.\n* `uuid`: Generate an uuid.\n* `env`: Retrieve a specific environment variable. Takes one argument - the name of the environment variable to expand.\n* `add`: Adds two integer values together and outputs the sum. E.g. `{{ add 1 2 }}`.\n* `join`: Joins array elements together to a string separated by defined separator. E.g. `{{ join .ScriptVars.MyArray \\\",\\\" }}`.\n* `modulo`: Returns modulo of two integer values and output the result. E.g. `{{ modulo 10 4 }}` (will return 2)\n\n### Example\n\n```json\n{\n \"label\" : \"Create bookmark\",\n \"action\": \"createbookmark\",\n \"settings\": {\n \"title\": \"my bookmark {{.Thread}}-{{.Session}} ({{.UserName}})\",\n \"description\": \"This bookmark contains some interesting selections\"\n }\n},\n{\n \"label\" : \"Publish created bookmark\",\n \"action\": \"publishbookmark\",\n \"disabled\" : false,\n \"settings\" : {\n \"title\": \"my bookmark {{.Thread}}-{{.Session}} ({{.UserName}})\",\n }\n}\n\n```\n\n```json\n{\n \"action\": \"createbookmark\",\n \"settings\": {\n \"title\": \"{{env \\\"TITLE\\\"}}\",\n \"description\": \"This bookmark contains some interesting selections\"\n }\n}\n```\n\n```json\n{\n \"action\": \"setscriptvar\",\n \"settings\": {\n \"name\": \"BookmarkCounter\",\n \"type\": \"int\",\n \"value\": \"1\"\n }\n},\n{\n \"action\": \"createbookmark\",\n \"settings\": {\n \"title\": \"Bookmark no {{ add .ScriptVars.BookmarkCounter 1 }}\",\n \"description\": \"This bookmark will have the title Bookmark no 2\"\n }\n}\n```\n\n```json\n{\n \"action\": \"setscriptvar\",\n \"settings\": {\n \"name\": \"MyAppId\",\n \"type\": \"string\",\n \"value\": \"{{.Artifacts.GetIDByTypeAndName \\\"app\\\" (print \\\"an-app-\\\" .Session)}}\"\n }\n}\n```\n\nLet's assume the case there are 4 apps to be used in the test, all ending with number 0 to 3. The use of modulo in the example will cycle through the app suffix number in following order: 1, 2, 3, 0.\n\n```json\n{\n \"action\": \"elastictriggersubscription\",\n \"label\": \"trigger reporting task\",\n \"settings\": {\n \"subscriptiontype\": \"template-sharing\",\n \"limitperpage\": 100,\n \"appname\": \"PS-18566_Test_Levels_Pages- {{ modulo .Session 4}}\",\n \"subscriptionmode\": \"random\",\n }\n}\n```\n\nVery similar case as above but apps have number suffix from 1 to 4. This can be handled combining `modulo` and `add` functions. The cycle through the suffix number will be done in following order: 2, 3, 4, 1.\n```json\n{\n \"action\": \"elastictriggersubscription\",\n \"label\": \"trigger reporting task\",\n \"settings\": {\n \"subscriptiontype\": \"template-sharing\",\n \"limitperpage\": 100,\n \"appname\": \"PS-18566_Test_Levels_Pages- {{ modulo .Session 4 | add 1 }}\",\n \"subscriptionmode\": \"random\",\n }\n}\n```\n\n</details>\n",
Examples: "",
},
}
Expand Down
14 changes: 14 additions & 0 deletions synced/template.go
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,7 @@ var (
"env": os.Getenv,
"add": add,
"join": strings.Join,
"modulo": modulo,
}
)

Expand Down Expand Up @@ -142,6 +143,19 @@ func add(iVal1 interface{}, iVal2 interface{}) (int64, error) {
return val1 + val2, nil
}

func modulo(iVal1 interface{}, iVal2 interface{}) (int64, error) {
val1, err := parseToInt64(iVal1)
if err != nil {
return 0, err
}
val2, err := parseToInt64(iVal2)
if err != nil {
return 0, err
}

return val1 % val2, nil
}

func parseToInt64(val interface{}) (int64, error) {
switch val := val.(type) {
case string:
Expand Down
5 changes: 4 additions & 1 deletion synced/template_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -56,6 +56,7 @@ func TestTemplate(t *testing.T) {
Param2 Template `json:"param2"`
Param3 Template `json:"param3"`
Param4 Template `json:"param4"`
Param5 Template `json:"param5"`
}

_ = os.Setenv("test-env", "val2")
Expand All @@ -64,7 +65,8 @@ func TestTemplate(t *testing.T) {
"param1" : "val1 is {{.Val1}} and val2 is {{env \"test-env\"}}",
"param2" : "{{ add 1 \"3\" }}",
"param3" : "{{ join .Val2 \",\" }},elem4",
"param4" : "{{ join (slice .Val2 0 (add (len .Val2) -1)) \",\" }}"
"param4" : "{{ join (slice .Val2 0 (add (len .Val2) -1)) \",\" }}",
"param5" : "{{ modulo 10 \"4\" }}"
}`

if err := json.Unmarshal([]byte(jsn), &myStruct); err != nil {
Expand All @@ -75,6 +77,7 @@ func TestTemplate(t *testing.T) {
testParam(t, &myStruct.Param2, "4")
testParam(t, &myStruct.Param3, "elem1,elem2,elem3,elem4")
testParam(t, &myStruct.Param4, "elem1,elem2")
testParam(t, &myStruct.Param5, "2")
}

func testParam(t *testing.T, tmpl *Template, expected string) {
Expand Down
4 changes: 3 additions & 1 deletion synced/templatemap_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,8 @@ func TestMap(t *testing.T) {
"param1" : "val1 is {{.Val1}} and val2 is {{env \"test-env\"}}",
"param2" : "{{ add 1 \"3\" }}",
"param3" : "{{ join .Val2 \",\" }},elem4",
"param4" : "{{ join (slice .Val2 0 (add (len .Val2) -1)) \",\" }}"
"param4" : "{{ join (slice .Val2 0 (add (len .Val2) -1)) \",\" }}",
"param5" : "{{ modulo 10 \"4\" }}"
}`

var tmplMap TemplateMap
Expand All @@ -31,6 +32,7 @@ func TestMap(t *testing.T) {
"param2": "4",
"param3": "elem1,elem2,elem3,elem4",
"param4": "elem1,elem2",
"param5": "2",
}

for k, v := range cmpMap {
Expand Down