Skip to content

Commit 292b79d

Browse files
committed
tests: improve automated testing framework
This patch modifies number of shell and Python scripts under scripts/tests/ directory to improve and enhance automated testing framework that is described in this [Wiki page](https://github.com/cloudius-systems/osv/wiki/Automated-Testing-Framework) in following ways: - refine compose_and_test_selected_apps.sh to properly build and independently run ZFS and ROFS images - refine compose_and_test_selected_apps.sh to log success/fail messages to summary files under /tmp - refine compose_and_test_selected_apps.sh to support running both ZFS and ROFS unit test images as well as httpserver API tests - refine python test scripts to support running test images with arbitrary OSv kernel (kernel.elf) - revamp python script intended to test http apps (new name test_http_app.py) to support both ab (Apache Bench) and wrk stress test tools Signed-off-by: Waldemar Kozaczuk <jwkozaczuk@gmail.com>
1 parent 2c3537e commit 292b79d

File tree

6 files changed

+408
-181
lines changed

6 files changed

+408
-181
lines changed

scripts/tests/compose_and_test_selected_apps.sh

Lines changed: 159 additions & 41 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,18 @@ usage() {
2222
-R Compose test app image with RoFS (ZFS is the default)
2323
-l Use latest OSv kernel from build/last to build test image
2424
-f Run OSv on firecracker
25+
26+
Test groups:
27+
simple - simple apps like golang-example
28+
http - httpserver apps
29+
http-java - java httpserver apps
30+
java <name> - java app
31+
http-node - node http apps
32+
node <name> - node app
33+
with_tester - apps tested with extra tester script like redis
34+
unit_tests - unit tests
35+
httpserver_api_tests - httpserver API unit tests
36+
all - all apps
2537
EOF
2638
exit ${1:-0}
2739
}
@@ -68,7 +80,7 @@ compose_test_app()
6880
local DEPENDANT_PKG1=$2
6981
local DEPENDANT_PKG2=$3
7082

71-
local IMAGE_PATH="$CAPSTAN_REPO/repository/test-$APP_NAME/test-$APP_NAME.qemu"
83+
local IMAGE_PATH="$CAPSTAN_REPO/repository/test-$APP_NAME-$FS/test-$APP_NAME-$FS.qemu"
7284

7385
if [ $RUN_ONLY == false ]; then
7486
local DEPENDENCIES="--require osv.$APP_NAME"
@@ -100,15 +112,22 @@ EOF
100112
echo "Using latest OSv kernel from $OSV_DIR/build/last/loader.img !"
101113
fi
102114

115+
if [ "$FS" == "rofs" ]; then
116+
FSTAB=static/etc/fstab_rofs
117+
else
118+
FSTAB=static/etc/fstab
119+
fi
120+
103121
TEMPDIR=$(mktemp -d) && pushd $TEMPDIR > /dev/null && \
104-
capstan package compose $DEPENDENCIES --fs $FS $LOADER_OPTION "test-$APP_NAME" && \
105-
rmdir $TEMPDIR && popd > /dev/null
122+
mkdir -p etc && cp $OSV_DIR/$FSTAB etc/fstab && \
123+
$HOME/projects/go/src/github.com/cloudius-systems/capstan/capstan package compose $DEPENDENCIES --fs $FS $LOADER_OPTION "test-$APP_NAME-$FS" && \
124+
rm -rf $TEMPDIR && popd > /dev/null
106125
else
107126
echo "Reusing the test image: $IMAGE_PATH that must have been composed before!"
108127
fi
109128

110129
if [ -f "$IMAGE_PATH" ]; then
111-
cp $CAPSTAN_REPO/repository/"test-$APP_NAME"/"test-$APP_NAME".qemu $OSV_DIR/build/last/usr.img
130+
cp $CAPSTAN_REPO/repository/"test-$APP_NAME-$FS"/"test-$APP_NAME-$FS".qemu $OSV_DIR/build/last/usr.img
112131
else
113132
echo "Could not find test image: $IMAGE_PATH!"
114133
exit 1
@@ -121,15 +140,16 @@ run_test_app()
121140
local TEST_PARAMETER=$2
122141

123142
if [ $COMPOSE_ONLY == false ]; then
124-
echo "-------------------------------------------------------"
125-
echo " Testing $OSV_APP_NAME ... "
126-
echo "-------------------------------------------------------"
143+
echo "-------------------------------------------------------" | tee -a $STATUS_FILE
144+
echo " Testing $OSV_APP_NAME ... " | tee -a $STATUS_FILE
127145

128146
if [ -f $OSV_DIR/apps/$OSV_APP_NAME/test.sh ]; then
129147
$OSV_DIR/apps/$OSV_APP_NAME/test.sh $TEST_PARAMETER
130148
elif [ -f $OSV_DIR/modules/$OSV_APP_NAME/test.sh ]; then
131149
$OSV_DIR/modules/$OSV_APP_NAME/test.sh $TEST_PARAMETER
132150
fi
151+
152+
echo "-------------------------------------------------------" | tee -a $STATUS_FILE
133153
fi
134154
echo ''
135155
}
@@ -141,86 +161,184 @@ compose_and_run_test_app()
141161
run_test_app $APP_NAME
142162
}
143163

144-
test_simple_apps()
164+
# Simple stateless apps that should work with both ZFS and ROFS
165+
test_simple_apps() #stateless
145166
{
146167
compose_and_run_test_app "golang-example"
147168
compose_and_run_test_app "golang-pie-example"
148169
compose_and_run_test_app "graalvm-example"
149-
compose_and_run_test_app "graalvm-example"
150170
compose_and_run_test_app "lua-hello-from-host"
151171
compose_and_run_test_app "rust-example"
152172
compose_and_run_test_app "stream"
153173
compose_test_app "python2-from-host" && run_test_app "python-from-host"
154174
compose_test_app "python3-from-host" && run_test_app "python-from-host"
155175
}
156176

157-
test_http_apps()
177+
test_java_app()
178+
{
179+
compose_test_app "$1" "run-java" "openjdk8-zulu-compact3-with-java-beans" && run_test_app "$1"
180+
}
181+
182+
# Stateless http java apps that should work with both ZFS and ROFS
183+
test_http_java_apps()
184+
{
185+
#TODO: Test with multiple versions of java
186+
test_java_app "jetty"
187+
test_java_app "tomcat"
188+
test_java_app "vertx"
189+
test_java_app "spring-boot-example" #Really slow
190+
}
191+
192+
test_node_app()
193+
{
194+
compose_test_app "$1" "node-from-host" && run_test_app "$1"
195+
}
196+
197+
# Stateless node apps that should work with both ZFS and ROFS
198+
test_http_node_apps()
199+
{
200+
#TODO: Test with multiple versions of node
201+
test_node_app "node-express-example"
202+
test_node_app "node-socketio-example"
203+
}
204+
205+
# Stateless http apps that should work with both ZFS and ROFS except for nginx
206+
test_http_apps() #stateless
158207
{
159208
compose_and_run_test_app "golang-httpserver"
160209
compose_and_run_test_app "golang-pie-httpserver"
161210
compose_and_run_test_app "graalvm-httpserver"
162211
compose_and_run_test_app "lighttpd"
163-
compose_and_run_test_app "nginx"
212+
if [ "$FS" == "zfs" ]; then #TODO: Fix configuration to make it work with ROFS
213+
compose_and_run_test_app "nginx" #Not ROFS
214+
fi
164215
compose_and_run_test_app "rust-httpserver"
165-
#TODO: Test with multiple versions of java
166-
compose_test_app "jetty" "run-java" "openjdk8-zulu-compact3-with-java-beans" && run_test_app "jetty"
167-
compose_test_app "tomcat" "run-java" "openjdk8-zulu-compact3-with-java-beans" && run_test_app "tomcat"
168-
compose_test_app "vertx" "run-java" "openjdk8-zulu-compact3-with-java-beans" && run_test_app "vertx"
169-
compose_test_app "spring-boot-example" "run-java" "openjdk8-zulu-compact3-with-java-beans" && run_test_app "spring-boot-example" #Really slow
170-
#TODO: Test with multiple versions of node
171-
compose_test_app "node-express-example" "node-from-host" && run_test_app "node-express-example"
172-
compose_test_app "node-socketio-example" "node-from-host" && run_test_app "node-socketio-example"
216+
test_http_java_apps
217+
test_http_node_apps
218+
}
219+
220+
test_ffmpeg()
221+
{
222+
if [ "$OSV_HYPERVISOR" == "firecracker" ]; then
223+
echo "Skipping ffmpeg as at this time it cannot run on Firecracker. Needs to chenge this script to setup bridge parameter"
224+
else
225+
compose_test_app "ffmpeg" && run_test_app "ffmpeg" "video_subclip" && run_test_app "ffmpeg" "video_transcode"
226+
fi
227+
}
228+
229+
test_redis()
230+
{
231+
compose_and_run_test_app "redis-memonly" && run_test_app "redis-memonly" "ycsb"
232+
}
233+
234+
test_keydb()
235+
{
236+
compose_and_run_test_app "keydb" && run_test_app "keydb" "ycsb"
173237
}
174238

175-
test_apps_with_tester()
239+
test_apps_with_tester() #most stateless
176240
{
177241
compose_and_run_test_app "iperf3"
178242
compose_and_run_test_app "graalvm-netty-plot"
179-
compose_test_app "ffmpeg" && run_test_app "ffmpeg" "video_subclip" && run_test_app "ffmpeg" "video_transcode"
180-
compose_and_run_test_app "redis-memonly"
243+
test_ffmpeg
244+
test_redis
245+
test_keydb
181246
compose_and_run_test_app "cli"
182-
compose_and_run_test_app "mysql"
183-
compose_test_app "apache-derby" "run-java" "openjdk8-zulu-compact3-with-java-beans" && run_test_app "apache-derby"
184-
compose_test_app "apache-kafka" "run-java" "openjdk8-zulu-compact3-with-java-beans" && run_test_app "apache-kafka"
185-
compose_and_run_test_app "elasticsearch"
247+
if [ "$FS" == "zfs" ]; then #These are stateful apps
248+
compose_and_run_test_app "mysql"
249+
test_java_app "apache-derby"
250+
test_java_app "apache-kafka"
251+
compose_and_run_test_app "elasticsearch"
252+
fi
186253
}
187254

188-
run_unit_tests()
255+
run_unit_tests() #regular unit tests are stateful
189256
{
190257
# Unit tests are special as the unit tests runner depends on usr.manifest which
191258
# needs to be placed in the tests module. So let us gegnerate it on the fly from the unit tests mpm
192-
capstan package describe osv.unit-tests -c | grep "/tests/tst-" | grep -o "/tests/tst-.*" | sed 's/$/: dummy/' > $OSV_DIR/modules/tests/usr.manifest
193-
compose_test_app "unit-tests" && run_test_app "tests"
194-
compose_test_app "httpserver-api-tests" && run_test_app "httpserver-api" "http"
195-
#compose_test_app "httpserver-api-https-tests" "httpserver-api-tests" && run_test_app "httpserver-api" "https"
259+
capstan package describe osv.common-tests -c | grep "/tests/tst-" | grep -o "/tests/tst-.*" | sed 's/$/: dummy/' > $OSV_DIR/modules/tests/usr.manifest
260+
capstan package describe "osv.$FS-tests" -c | grep "/tests/tst-" | grep -o "/tests/tst-.*" | sed 's/$/: dummy/' >> $OSV_DIR/modules/tests/usr.manifest
261+
compose_test_app "$FS-tests" "openjdk8-from-host" "common-tests" && run_test_app "tests"
262+
}
263+
264+
run_httpserver_api_tests()
265+
{
266+
if [ "$FS" == "zfs" ]; then #These are stateful apps
267+
compose_test_app "httpserver-api-tests" && run_test_app "httpserver-api" "http"
268+
rm -rf $OSV_DIR/modules/certs/build && mkdir -p $OSV_DIR/modules/certs/build && pushd $OSV_DIR/modules/certs/build
269+
tar xf $CAPSTAN_REPO/packages/osv.httpserver-api-tests.mpm /client/client.key && \
270+
tar xf $CAPSTAN_REPO/packages/osv.httpserver-api-tests.mpm /etc/pki/CA/cacert.pem && \
271+
tar xf $CAPSTAN_REPO/packages/osv.httpserver-api-tests.mpm /client/client.pem && \
272+
mv client/* . && mv etc/pki/CA/cacert.pem .
273+
popd
274+
compose_test_app "httpserver-api-https-tests" "httpserver-api-tests" && run_test_app "httpserver-api" "https"
275+
fi
196276
}
197277

278+
export STATUS_FILE="/tmp/$TEST_APP_PACKAGE_NAME"
279+
rm -f $STATUS_FILE
198280

199281
case "$TEST_APP_PACKAGE_NAME" in
200282
simple)
201-
echo "Testing simple apps ..."
202-
echo "-----------------------------------"
283+
echo "Testing simple apps ..." | tee -a $STATUS_FILE
284+
echo "-----------------------------------" | tee -a $STATUS_FILE
203285
test_simple_apps;;
204286
http)
205-
echo "Testing HTTP apps ..."
206-
echo "-----------------------------------"
287+
echo "Testing HTTP apps ..." | tee -a $STATUS_FILE
288+
echo "-----------------------------------" | tee -a $STATUS_FILE
207289
test_http_apps;;
290+
http-java)
291+
echo "Testing HTTP Java apps ..." | tee -a $STATUS_FILE
292+
echo "-----------------------------------" | tee -a $STATUS_FILE
293+
test_http_java_apps;;
294+
java)
295+
echo "Testing Java app ..." | tee -a $STATUS_FILE
296+
echo "-----------------------------------" | tee -a $STATUS_FILE
297+
test_java_app $TEST_OSV_APP_NAME;;
298+
http-node)
299+
echo "Testing HTTP Node apps ..." | tee -a $STATUS_FILE
300+
echo "-----------------------------------" | tee -a $STATUS_FILE
301+
test_http_node_apps;;
302+
node)
303+
echo "Testing Node app ..." | tee -a $STATUS_FILE
304+
echo "-----------------------------------" | tee -a $STATUS_FILE
305+
test_node_app $TEST_OSV_APP_NAME;;
208306
with_tester)
209-
echo "Testing apps with custom tester ..."
210-
echo "-----------------------------------"
307+
echo "Testing apps with custom tester ..." | tee -a $STATUS_FILE
308+
echo "-----------------------------------" | tee -a $STATUS_FILE
211309
test_apps_with_tester;;
212310
unit_tests)
213-
echo "Running unit tests ..."
214-
echo "-----------------------------------"
311+
echo "Running unit tests ..." | tee -a $STATUS_FILE
312+
echo "-----------------------------------" | tee -a $STATUS_FILE
215313
run_unit_tests;;
314+
redis)
315+
echo "Running redis test..." | tee -a $STATUS_FILE
316+
echo "-----------------------------------" | tee -a $STATUS_FILE
317+
test_redis;;
318+
keydb)
319+
echo "Running keydb test..." | tee -a $STATUS_FILE
320+
echo "-----------------------------------" | tee -a $STATUS_FILE
321+
test_keydb;;
322+
ffmpeg)
323+
echo "Running ffmpeg test..." | tee -a $STATUS_FILE
324+
echo "-----------------------------------" | tee -a $STATUS_FILE
325+
test_ffmpeg;;
326+
httpserver_api_tests)
327+
echo "Running httpserver api tests ..." | tee -a $STATUS_FILE
328+
echo "-----------------------------------" | tee -a $STATUS_FILE
329+
run_httpserver_api_tests;;
216330
all)
217-
echo "Running all tests ..."
218-
echo "-----------------------------------"
331+
echo "Running all tests ..." | tee -a $STATUS_FILE
332+
echo "-----------------------------------" | tee -a $STATUS_FILE
219333
run_unit_tests
334+
run_httpserver_api_tests
220335
test_simple_apps
221336
test_http_apps
337+
compose_and_run_test_app specjvm
222338
test_apps_with_tester;;
223339
*)
340+
echo "Running $TEST_APP_PACKAGE_NAME ..." | tee -a $STATUS_FILE
341+
echo "-----------------------------------" | tee -a $STATUS_FILE
224342
if [ "$TEST_OSV_APP_NAME" == "" ]; then
225343
compose_and_run_test_app "$TEST_APP_PACKAGE_NAME"
226344
else

scripts/tests/test_app.py

Lines changed: 31 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,18 +1,30 @@
11
#!/usr/bin/python3
22
from testing import *
33
import argparse
4+
import os
45
from time import sleep
56

6-
def run(command, hypervisor_name, image_path=None, line=None, guest_port=None, host_port=None, input_lines=[], kill_app=False):
7+
def run(command, hypervisor_name, image_path=None, line=None, guest_port=None, host_port=None,
8+
input_lines=[], kill_app=False, kernel_path=None):
9+
710
py_args = []
811
if image_path != None:
912
py_args = ['--image', image_path]
1013

14+
if kernel_path != None:
15+
print('Using kernel at %s' % kernel_path)
16+
if hypervisor_name == 'firecracker':
17+
py_args += ['-k', kernel_path]
18+
else:
19+
py_args += ['-k', '--kernel-path', kernel_path]
20+
1121
pipe_guest_stdin= len(input_lines) > 0
1222
if guest_port != None and host_port != None:
13-
app = run_command_in_guest(command, hypervisor=hypervisor_name, run_py_args=py_args, forward=[(host_port, guest_port)], pipe_stdin=pipe_guest_stdin)
23+
app = run_command_in_guest(command, hypervisor=hypervisor_name, run_py_args=py_args,
24+
forward=[(host_port, guest_port)], pipe_stdin=pipe_guest_stdin)
1425
else:
15-
app = run_command_in_guest(command, hypervisor=hypervisor_name, run_py_args=py_args, pipe_stdin=pipe_guest_stdin)
26+
app = run_command_in_guest(command, hypervisor=hypervisor_name, run_py_args=py_args,
27+
pipe_stdin=pipe_guest_stdin)
1628

1729
if line != None:
1830
if len(input_lines) > 0:
@@ -28,7 +40,12 @@ def run(command, hypervisor_name, image_path=None, line=None, guest_port=None, h
2840
app.join()
2941

3042
print('----------')
31-
print('SUCCESS')
43+
print(' SUCCESS')
44+
45+
status_file_name = os.getenv('STATUS_FILE')
46+
if status_file_name:
47+
with open(status_file_name, "a+") as status_file:
48+
status_file.write(' SUCCESS\n')
3249

3350
if __name__ == "__main__":
3451
parser = argparse.ArgumentParser(prog='test_app')
@@ -44,6 +61,7 @@ def run(command, hypervisor_name, image_path=None, line=None, guest_port=None, h
4461
parser.add_argument("--host_port", action="store", default=None, help="host port")
4562
parser.add_argument("--input_line", action="append", default=[], help="input line")
4663
parser.add_argument("--kill", action="store_true", help="kill the app instead of waiting until terminates itself")
64+
parser.add_argument("--kernel_path", action="store", help="path to kernel.elf.")
4765

4866
cmdargs = parser.parse_args()
4967

@@ -55,6 +73,14 @@ def run(command, hypervisor_name, image_path=None, line=None, guest_port=None, h
5573
if hypervisor_from_env != None:
5674
hypervisor_name = hypervisor_from_env
5775

76+
kernel_path = cmdargs.kernel_path
77+
if not kernel_path and os.getenv('OSV_KERNEL'):
78+
kernel_path = os.getenv('OSV_KERNEL')
79+
80+
if kernel_path and not os.path.exists(kernel_path):
81+
print("The file %s does not exist!" % kernel_path)
82+
sys.exit(-1)
83+
5884
set_verbose_output(True)
5985
run(cmdargs.execute, hypervisor_name, cmdargs.image, cmdargs.line,
60-
cmdargs.guest_port, cmdargs.host_port, cmdargs.input_line, cmdargs.kill)
86+
cmdargs.guest_port, cmdargs.host_port, cmdargs.input_line, cmdargs.kill, kernel_path)

0 commit comments

Comments
 (0)