Skip to content

Commit 94745a9

Browse files
committed
CR changes
1 parent 93b27f2 commit 94745a9

File tree

6 files changed

+95
-14
lines changed

6 files changed

+95
-14
lines changed

book/src/SUMMARY.md

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -54,11 +54,11 @@
5454
- [Stateful test](./libs/wasp/stateful_test.md)
5555
- [User Journey test](./libs/wasp/user_journey_test.md)
5656
- [Profile test](./libs/wasp/profile_test.md)
57-
- [Testing alerts](./libs/wasp/testing_alerts.md)
57+
- [Testing alerts]()
5858
- [Configuration](./libs/wasp/configuration.md)
5959
- [k8s](./libs/wasp/k8s.md)
6060
- [Components](./libs/wasp/components/overview.md)
61-
- [Alert Checker](./libs/wasp/components/alert_checker.md)
61+
- [Alert Checker]()
6262
- [Dashboard](./libs/wasp/components/dashboard.md)
6363
- [Generator](./libs/wasp/components/generator.md)
6464
- [Loki](./libs/wasp/components/loki.md)

book/src/libs/wasp/components/generator.md

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -20,18 +20,19 @@ A **Generator** is a component that encapsulates all the characteristics of load
2020
#### **`Gun`**
2121
* Best for **stateless protocols** (e.g., HTTP).
2222
* Simplistic in nature; ideal for executing a single operation that does not require setup or teardown.
23-
* Operates using a **closed model**, where:
23+
* Operates using an **open model**, where:
2424
* The number of requests is fixed.
2525
* The load adjusts to meet the target RPS, regardless of the system's response time.
26+
* There's no feedback from the system.
2627
* Recommended for scenarios focused on measuring **throughput**.
2728

2829
#### **`VirtualUser`**
2930
* Designed for **stateful protocols** (e.g., `WebSocket`) or workflows involving multiple operations (e.g., authenticating, executing tasks, and logging out).
3031
* More complex, with dedicated methods for setup and teardown.
31-
* Operates using an **open model**, where:
32+
* Operates using a **closed model**, where:
3233
* New iterations start only after the previous one completes.
3334
* The RPS fluctuates based on the system's response time. Longer response times reduce RPS.
34-
35+
* Feedback from the system is used to adjust the load.
3536
---
3637

3738
### Closed vs. Open Models

book/src/libs/wasp/components/profile.md

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,9 @@
33
A **Profile** allows you to combine load from different generators. Each generator operates according to its own schedule, and you can even mix RPS and VU load types, as shown in [this example](https://github.com/smartcontractkit/chainlink-testing-framework/blob/main/wasp/examples/profiles/node_mixed_test.go).
44

55
> [!NOTE]
6-
> The `error` returned by the `.Run(true)` function of a `Profile` only indicates if any dashboard alerts were triggered.
6+
> The `error` returned by the `.Run(true)` function of a `Profile` might indicate the following:
7+
> * load generator did not start and instead returned an error
8+
> * or **if** `Profile` was created with `WithGrafana` option that enabled `CheckDashboardAlertsAfterRun` that at some alerts fired.
79
> To check for errors during load generation, you need to call the `Errors()` method on each `Generator` within the `Profile`.
810
911
---

book/src/libs/wasp/how-to/chose_rps_vu.md

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@ When writing a test, you need to decide whether to use **RPS** or **VUs** as you
99

1010
## RPS (Requests Per Second)
1111

12-
You should use **RPS** when your goal is to measure **throughput**. This load type implements a **closed model**, where:
12+
You should use **RPS** when your goal is to measure **throughput**. This load type implements an **open model**, where:
1313
* The number of requests is fixed.
1414
* The load is adjusted to meet the target RPS.
1515
* The system's response time has no impact on the rate of load generation.
@@ -50,7 +50,7 @@ sequenceDiagram
5050

5151
Use **VUs** when working with **stateful protocols** or workflows. With `VirtualUser`, the **requests per second** rate cannot be guaranteed because:
5252
* Each iteration begins only after the previous one finishes.
53-
* The load follows an **open model**, where the system's response time affects the RPS.
53+
* The load follows a **closed model**, where the system's response time affects the RPS.
5454

5555
If the system takes longer to respond, iterations take longer, and the RPS decreases.
5656

book/src/libs/wasp/profile_test.md

Lines changed: 7 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -95,11 +95,15 @@ You can find the full example [here](https://github.com/smartcontractkit/chainli
9595
---
9696

9797
> [!NOTE]
98-
> The `error` returned by the `.Run(true)` method only indicates if any dashboard alerts were triggered.
99-
> To check for load generation errors, call the `Errors()` method on each `Generator` in the `Profile`.
98+
> The `error` returned by the `.Run(true)` function of a `Profile` might indicate the following:
99+
> * load generator did not start and instead returned an error
100+
> * or **if** `Profile` was created with `WithGrafana` option that enabled `CheckDashboardAlertsAfterRun` that at some alerts fired.
101+
> To check for errors during load generation, you need to call the `Errors()` method on each `Generator` within the `Profile`.
100102
101103
> [!NOTE]
102-
> Currently, it’s not possible to have a "waiting" schedule that doesn’t generate any load. To implement such logic, start one `Profile` in a goroutine and use `time.Sleep` before starting the second `Profile`. An example of this can be found [here](https://github.com/smartcontractkit/chainlink-testing-framework/tree/main/wasp/examples/profiles/node_background_load_test.go).
104+
> Currently, it’s not possible to have a "waiting" schedule that doesn’t generate any load.
105+
> To implement such logic, start one `Profile` in a goroutine and use `time.Sleep` before starting the second `Profile` or start use a combination `.Run(false)` and `.Wait()` methods.
106+
> Both examples of can be found [here](https://github.com/smartcontractkit/chainlink-testing-framework/tree/main/wasp/examples/profiles/node_background_load_test.go).
103107
104108
---
105109

wasp/examples/profiles/node_background_load_test.go

Lines changed: 77 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -8,13 +8,87 @@ import (
88
"time"
99
)
1010

11-
func TestBackgroundLoad(t *testing.T) {
11+
func TestBackgroundLoadSimple(t *testing.T) {
1212
srv := wasp.NewHTTPMockServer(nil)
1313
srv.Run()
1414

1515
labels := map[string]string{
16-
"branch": "background_load",
17-
"commit": "background_load",
16+
"branch": "background_load_simple",
17+
"commit": "background_load_simple",
18+
}
19+
20+
zetaSchedule := wasp.Combine(
21+
wasp.Steps(1, 1, 4, 20*time.Second),
22+
wasp.Plain(5, 50*time.Second),
23+
wasp.Steps(5, -1, 4, 20*time.Second))
24+
25+
rpsProfile := wasp.NewProfile().
26+
Add(wasp.NewGenerator(&wasp.Config{
27+
T: t,
28+
LoadType: wasp.RPS,
29+
GenName: "Zeta",
30+
Schedule: zetaSchedule,
31+
Gun: NewExampleHTTPGun(srv.URL()),
32+
Labels: labels,
33+
LokiConfig: wasp.NewEnvLokiConfig(),
34+
}))
35+
36+
// start load generation without waiting for it to finish
37+
_, err := rpsProfile.Run(false)
38+
39+
// Wait for the first generator enter the steady state
40+
time.Sleep(20 * time.Second)
41+
42+
etaSchedule := wasp.Combine(
43+
wasp.Steps(1, 1, 10, 20*time.Second),
44+
wasp.Plain(10, 20*time.Second),
45+
wasp.Steps(10, -1, 10, 10*time.Second))
46+
47+
iotaSchedule := wasp.Combine(
48+
wasp.Steps(1, 1, 10, 20*time.Second),
49+
wasp.Plain(10, 20*time.Second),
50+
wasp.Steps(10, -1, 10, 10*time.Second))
51+
52+
vuProfile, err := wasp.NewProfile().
53+
Add(wasp.NewGenerator(&wasp.Config{
54+
T: t,
55+
LoadType: wasp.VU,
56+
GenName: "Eta",
57+
Schedule: etaSchedule,
58+
VU: NewExampleScenario(srv.URL()),
59+
Labels: labels,
60+
LokiConfig: wasp.NewEnvLokiConfig(),
61+
})).
62+
Add(wasp.NewGenerator(&wasp.Config{
63+
T: t,
64+
LoadType: wasp.VU,
65+
GenName: "Iota",
66+
Schedule: iotaSchedule,
67+
VU: NewExampleScenario(srv.URL()),
68+
Labels: labels,
69+
LokiConfig: wasp.NewEnvLokiConfig(),
70+
})).
71+
Run(true)
72+
// check if VU Profile did not return an error (e.g. due to invalid configuration or alerts triggered)
73+
require.NoError(t, err)
74+
75+
// wait until RPS Profile finishes
76+
rpsProfile.Wait()
77+
// check if RPS Profile did not return an error (e.g. due to invalid configuration or alerts triggered)
78+
require.NoError(t, err)
79+
80+
require.Equal(t, 0, len(rpsProfile.Generators[0].Errors()), "RPS generator had errors errors")
81+
require.Equal(t, 0, len(vuProfile.Generators[0].Errors()), "first VU generator had errors")
82+
require.Equal(t, 0, len(vuProfile.Generators[1].Errors()), "second VU generator had errors")
83+
}
84+
85+
func TestBackgroundLoadGoRoutines(t *testing.T) {
86+
srv := wasp.NewHTTPMockServer(nil)
87+
srv.Run()
88+
89+
labels := map[string]string{
90+
"branch": "background_load_goroutines",
91+
"commit": "background_load_goroutines",
1892
}
1993

2094
zetaSchedule := wasp.Combine(

0 commit comments

Comments
 (0)