Skip to content

Commit 9391669

Browse files
Merge pull request #22 from grycap/feat-add-stress-test
New service that just increases the CPU usage
2 parents 910aed9 + 2cbe36d commit 9391669

File tree

5 files changed

+396
-0
lines changed

5 files changed

+396
-0
lines changed

crates/stress-test/fdl.yml

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
functions:
2+
oscar:
3+
- oscar-cluster:
4+
name: stress-test
5+
memory: 256Mi
6+
cpu: '1.0'
7+
image: ubuntu
8+
script: script.sh
9+
allowed_users: []
10+
log_level: CRITICAL
11+
environment:
12+
variables:
13+
read_timeout: "300"
14+
write_timeout: "300"
15+
exec_timeout: "0"
16+
STRESS_DURATION_SECONDS: "10"
17+
synchronous:
18+
min_scale: 1
19+
input:
20+
- storage_provider: minio.default
21+
path: stress-test/input
22+
output:
23+
- storage_provider: minio.default
24+
path: stress-test/output

crates/stress-test/icon.png

119 KB
Loading

crates/stress-test/input.txt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
10
Lines changed: 327 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,327 @@
1+
{
2+
"@context": [
3+
"https://w3id.org/ro/crate/1.1/context"
4+
],
5+
"@graph": [
6+
{
7+
"@type": "CreativeWork",
8+
"@id": "ro-crate-metadata.json",
9+
"conformsTo": {
10+
"@id": "https://w3id.org/ro/crate/1.1"
11+
},
12+
"about": {
13+
"@id": "./"
14+
}
15+
},
16+
{
17+
"@id": "./",
18+
"@type": [
19+
"Dataset",
20+
"Service",
21+
"SoftwareApplication"
22+
],
23+
"datePublished": "2024-01-01",
24+
"URL": "https://github.com/grycap/oscar-hub/tree/main/crates/stress-test",
25+
"name": "OSCAR Stress Test Service",
26+
"description": "Example OSCAR service that stresses CPU usage for a configurable duration.",
27+
"license": {
28+
"@id": "https://www.apache.org/licenses/LICENSE-2.0"
29+
},
30+
"applicationCategory": "OSCAR Service",
31+
"memoryRequirements": "256 MiB",
32+
"processorRequirements": [
33+
"1 vCPU",
34+
"0 GPU"
35+
],
36+
"serviceType": [
37+
"asynchronous",
38+
"synchronous"
39+
],
40+
"author": {
41+
"@id": "https://orcid.org/0000-0002-8049-253X"
42+
},
43+
"subjectOf": [
44+
{
45+
"@id": "#acceptance-test-sync"
46+
},
47+
{
48+
"@id": "#acceptance-test-async"
49+
}
50+
],
51+
"hasPart": [
52+
{
53+
"@id": "fdl.yml"
54+
},
55+
{
56+
"@id": "script.sh"
57+
},
58+
{
59+
"@id": "icon.png"
60+
},
61+
{
62+
"@id": "input.txt"
63+
}
64+
]
65+
},
66+
{
67+
"@id": "fdl.yml",
68+
"@type": [
69+
"File",
70+
"SoftwareSourceCode"
71+
],
72+
"name": "OSCAR Stress Test Definition",
73+
"url": "https://raw.githubusercontent.com/grycap/oscar-hub/refs/heads/main/crates/stress-test/fdl.yml",
74+
"encodingFormat": "text/yaml"
75+
},
76+
{
77+
"@id": "script.sh",
78+
"@type": [
79+
"File",
80+
"SoftwareSourceCode"
81+
],
82+
"name": "OSCAR Stress Test Script",
83+
"url": "https://raw.githubusercontent.com/grycap/oscar-hub/refs/heads/main/crates/stress-test/script.sh",
84+
"encodingFormat": "text/x-shellscript"
85+
},
86+
{
87+
"@id": "icon.png",
88+
"@type": [
89+
"File",
90+
"ImageObject"
91+
],
92+
"name": "OSCAR Stress Test Service Icon",
93+
"url": "https://raw.githubusercontent.com/grycap/oscar-hub/refs/heads/main/crates/stress-test/icon.png",
94+
"encodingFormat": "image/png"
95+
},
96+
{
97+
"@id": "input.txt",
98+
"@type": [
99+
"File",
100+
"TextDigitalDocument"
101+
],
102+
"name": "Sample Input",
103+
"url": "https://raw.githubusercontent.com/grycap/oscar-hub/refs/heads/main/crates/stress-test/input.txt",
104+
"encodingFormat": "text/plain"
105+
},
106+
{
107+
"@id": "https://orcid.org/0000-0002-8049-253X",
108+
"@type": "Person",
109+
"name": "Germán Moltó",
110+
"affiliation": {
111+
"@id": "UPV"
112+
}
113+
},
114+
{
115+
"@id": "https://www.apache.org/licenses/LICENSE-2.0",
116+
"@type": "CreativeWork",
117+
"name": "Apache License 2.0",
118+
"identifier": "SPDX:Apache-2.0"
119+
},
120+
{
121+
"@id": "#acceptance-test-sync",
122+
"@type": "HowTo",
123+
"name": "Synchronous CLI acceptance test",
124+
"description": "Execute the service locally with the sample input and validate the output string.",
125+
"tool": [
126+
{
127+
"@id": "#tool-oscar-cli"
128+
}
129+
],
130+
"supply": [
131+
{
132+
"@id": "#supply-input-txt"
133+
}
134+
],
135+
"step": [
136+
{
137+
"@id": "#step-sync-run"
138+
}
139+
]
140+
},
141+
{
142+
"@id": "#acceptance-test-async",
143+
"@type": "HowTo",
144+
"name": "Asynchronous CLI acceptance test",
145+
"description": "Upload the sample input to the service storage and then download the most recent output to verify its contents.",
146+
"tool": [
147+
{
148+
"@id": "#tool-oscar-cli"
149+
}
150+
],
151+
"supply": [
152+
{
153+
"@id": "#supply-input-txt"
154+
}
155+
],
156+
"step": [
157+
{
158+
"@id": "#step-async-put"
159+
},
160+
{
161+
"@id": "#step-async-wait"
162+
},
163+
{
164+
"@id": "#step-async-get"
165+
}
166+
]
167+
},
168+
{
169+
"@id": "#tool-oscar-cli",
170+
"@type": "HowToTool",
171+
"name": "OSCAR CLI",
172+
"item": {
173+
"@id": "#oscar-cli"
174+
}
175+
},
176+
{
177+
"@id": "#supply-input-txt",
178+
"@type": "HowToSupply",
179+
"name": "Sample duration file",
180+
"item": {
181+
"@id": "input.txt"
182+
}
183+
},
184+
{
185+
"@id": "#expected-output-duration",
186+
"@type": "PropertyValue",
187+
"name": "expected output substring",
188+
"value": "Duration seconds: 10"
189+
},
190+
{
191+
"@id": "#step-sync-run",
192+
"@type": "HowToStep",
193+
"position": 1,
194+
"text": "Run the service using the provided sample input.",
195+
"potentialAction": {
196+
"@id": "#action-sync-run"
197+
}
198+
},
199+
{
200+
"@id": "#step-async-put",
201+
"@type": "HowToStep",
202+
"position": 1,
203+
"text": "Upload the sample input using the OSCAR CLI.",
204+
"potentialAction": {
205+
"@id": "#action-async-put"
206+
}
207+
},
208+
{
209+
"@id": "#step-async-wait",
210+
"@type": "HowToStep",
211+
"position": 2,
212+
"text": "Wait for the remote execution to complete before retrieving the result.",
213+
"timeRequired": "PT20S"
214+
},
215+
{
216+
"@id": "#step-async-get",
217+
"@type": "HowToStep",
218+
"position": 3,
219+
"text": "Download the latest output and confirm it contains the expected substring.",
220+
"potentialAction": {
221+
"@id": "#action-async-get"
222+
}
223+
},
224+
{
225+
"@id": "#action-sync-run",
226+
"@type": "ConsumeAction",
227+
"name": "Run service synchronously",
228+
"object": {
229+
"@id": "input.txt"
230+
},
231+
"target": {
232+
"@id": "#entry-sync-run"
233+
},
234+
"result": {
235+
"@id": "#expected-output-duration"
236+
},
237+
"additionalProperty": [
238+
{
239+
"@id": "#command-template-sync-run"
240+
}
241+
]
242+
},
243+
{
244+
"@id": "#entry-sync-run",
245+
"@type": "EntryPoint",
246+
"actionApplication": {
247+
"@id": "#oscar-cli"
248+
}
249+
},
250+
{
251+
"@id": "#command-template-sync-run",
252+
"@type": "PropertyValue",
253+
"propertyID": "commandTemplate",
254+
"value": "oscar-cli service run stress-test -i {input}"
255+
},
256+
{
257+
"@id": "#action-async-put",
258+
"@type": "TransferAction",
259+
"name": "Upload sample input",
260+
"object": {
261+
"@id": "input.txt"
262+
},
263+
"target": {
264+
"@id": "#entry-async-put"
265+
},
266+
"additionalProperty": [
267+
{
268+
"@id": "#command-template-async-put"
269+
}
270+
]
271+
},
272+
{
273+
"@id": "#entry-async-put",
274+
"@type": "EntryPoint",
275+
"actionApplication": {
276+
"@id": "#oscar-cli"
277+
}
278+
},
279+
{
280+
"@id": "#command-template-async-put",
281+
"@type": "PropertyValue",
282+
"propertyID": "commandTemplate",
283+
"value": "oscar-cli service put-file stress-test {source}"
284+
},
285+
{
286+
"@id": "#action-async-get",
287+
"@type": "TransferAction",
288+
"name": "Download latest output",
289+
"target": {
290+
"@id": "#entry-async-get"
291+
},
292+
"result": {
293+
"@id": "#expected-output-duration"
294+
},
295+
"additionalProperty": [
296+
{
297+
"@id": "#command-template-async-get"
298+
}
299+
]
300+
},
301+
{
302+
"@id": "#entry-async-get",
303+
"@type": "EntryPoint",
304+
"actionApplication": {
305+
"@id": "#oscar-cli"
306+
}
307+
},
308+
{
309+
"@id": "#command-template-async-get",
310+
"@type": "PropertyValue",
311+
"propertyID": "commandTemplate",
312+
"value": "oscar-cli service get-file stress-test --download-latest-into {destination}"
313+
},
314+
{
315+
"@id": "#oscar-cli",
316+
"@type": "SoftwareApplication",
317+
"name": "OSCAR CLI",
318+
"url": "https://github.com/grycap/oscar-cli"
319+
},
320+
{
321+
"@id": "UPV",
322+
"@type": "Organization",
323+
"name": "Universitat Politècnica de València",
324+
"url": "https://www.upv.es"
325+
}
326+
]
327+
}

crates/stress-test/script.sh

Lines changed: 44 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,44 @@
1+
#!/bin/bash
2+
3+
#
4+
# This script raises CPU usage for a configurable duration.
5+
# It uses environment variables set by the OSCAR framework:
6+
# - INPUT_FILE_PATH: the path to the input file containing the duration in seconds
7+
# - TMP_OUTPUT_DIR: the directory where output files should be written
8+
9+
DURATION_DEFAULT=10
10+
DURATION_RAW=""
11+
OUTPUT_BASENAME="stress-test-output"
12+
13+
if [ -n "${INPUT_FILE_PATH:-}" ] && [ -f "$INPUT_FILE_PATH" ]; then
14+
FILE_BASENAME=$(basename "$INPUT_FILE_PATH")
15+
OUTPUT_BASENAME="${FILE_BASENAME%.*}-out"
16+
DURATION_RAW=$(tr -d ' \t\n\r' < "$INPUT_FILE_PATH")
17+
fi
18+
19+
if [ -z "$DURATION_RAW" ] && [ -n "${STRESS_DURATION_SECONDS:-}" ]; then
20+
DURATION_RAW="$STRESS_DURATION_SECONDS"
21+
fi
22+
23+
if [[ "$DURATION_RAW" =~ ^[0-9]+$ ]]; then
24+
DURATION_SECONDS="$DURATION_RAW"
25+
else
26+
DURATION_SECONDS="$DURATION_DEFAULT"
27+
fi
28+
29+
START_TS=$(date +%s)
30+
END_TS=$((START_TS + DURATION_SECONDS))
31+
32+
while [ "$(date +%s)" -lt "$END_TS" ]; do
33+
:
34+
done
35+
36+
OUTPUT_FILE="$TMP_OUTPUT_DIR/${OUTPUT_BASENAME}.txt"
37+
{
38+
echo "CPU stress completed."
39+
echo "Duration seconds: $DURATION_SECONDS"
40+
echo "Start timestamp: $START_TS"
41+
echo "End timestamp: $(date +%s)"
42+
} > "$OUTPUT_FILE"
43+
44+
cat "$OUTPUT_FILE"

0 commit comments

Comments
 (0)