1f08c3bdfSopenharmony_ci#!/bin/sh
2f08c3bdfSopenharmony_ci# SPDX-License-Identifier: GPL-2.0-or-later
3f08c3bdfSopenharmony_ci# Copyright (c) 2008 FUJITSU LIMITED
4f08c3bdfSopenharmony_ci# Copyright (c) 2021 Joerg Vehlow <joerg.vehlow@aox-tech.de>
5f08c3bdfSopenharmony_ci# Copyright (c) 2021 Petr Vorel <pvorel@suse.cz>
6f08c3bdfSopenharmony_ci#
7f08c3bdfSopenharmony_ci# Author: Li Zefan <lizf@cn.fujitsu.com>
8f08c3bdfSopenharmony_ci#
9f08c3bdfSopenharmony_ci# Process event connector is a netlink connector that reports process events
10f08c3bdfSopenharmony_ci# to userspace. It sends events such as fork, exec, id change and exit.
11f08c3bdfSopenharmony_ci
12f08c3bdfSopenharmony_ciTST_OPTS="n:"
13f08c3bdfSopenharmony_ciTST_SETUP=setup
14f08c3bdfSopenharmony_ciTST_TESTFUNC=do_test
15f08c3bdfSopenharmony_ciTST_PARSE_ARGS=parse_args
16f08c3bdfSopenharmony_ciTST_USAGE=usage
17f08c3bdfSopenharmony_ciTST_NEEDS_ROOT=1
18f08c3bdfSopenharmony_ciTST_NEEDS_TMPDIR=1
19f08c3bdfSopenharmony_ciTST_NEEDS_CHECKPOINTS=1
20f08c3bdfSopenharmony_ciTST_TEST_DATA="fork exec exit uid gid"
21f08c3bdfSopenharmony_ci
22f08c3bdfSopenharmony_cinum_events=10
23f08c3bdfSopenharmony_ci
24f08c3bdfSopenharmony_ciLISTENER_ID=0
25f08c3bdfSopenharmony_ciGENERATOR_ID=1
26f08c3bdfSopenharmony_ci
27f08c3bdfSopenharmony_ciusage()
28f08c3bdfSopenharmony_ci{
29f08c3bdfSopenharmony_ci	cat << EOF
30f08c3bdfSopenharmony_ciusage: $0 [-n <nevents>]
31f08c3bdfSopenharmony_ci
32f08c3bdfSopenharmony_ciOPTIONS
33f08c3bdfSopenharmony_ci-n      The number of evetns to generate per test (default 10)
34f08c3bdfSopenharmony_ciEOF
35f08c3bdfSopenharmony_ci}
36f08c3bdfSopenharmony_ci
37f08c3bdfSopenharmony_ciparse_args()
38f08c3bdfSopenharmony_ci{
39f08c3bdfSopenharmony_ci	case $1 in
40f08c3bdfSopenharmony_ci	n) num_events=$2;;
41f08c3bdfSopenharmony_ci	esac
42f08c3bdfSopenharmony_ci}
43f08c3bdfSopenharmony_ci
44f08c3bdfSopenharmony_ci# Find a free file handle
45f08c3bdfSopenharmony_cifree_fd()
46f08c3bdfSopenharmony_ci{
47f08c3bdfSopenharmony_ci	local fd
48f08c3bdfSopenharmony_ci
49f08c3bdfSopenharmony_ci	for fd in $(seq 200); do
50f08c3bdfSopenharmony_ci		# Sapwn a new sh, because redirecting to a non existing file handle
51f08c3bdfSopenharmony_ci		# will trigger a syntax error.
52f08c3bdfSopenharmony_ci		sh -c ": 2>/dev/null >&$fd || : 2>/dev/null <&$fd" 2>/dev/null
53f08c3bdfSopenharmony_ci		if [ $? -ne 0 ]; then
54f08c3bdfSopenharmony_ci			echo $fd
55f08c3bdfSopenharmony_ci			return
56f08c3bdfSopenharmony_ci		fi
57f08c3bdfSopenharmony_ci	done
58f08c3bdfSopenharmony_ci}
59f08c3bdfSopenharmony_ci
60f08c3bdfSopenharmony_cisetup()
61f08c3bdfSopenharmony_ci{
62f08c3bdfSopenharmony_ci	if ! grep -q cn_proc /proc/net/connector; then
63f08c3bdfSopenharmony_ci		tst_brk TCONF "Process Event Connector is not supported or kernel < 2.6.26"
64f08c3bdfSopenharmony_ci	fi
65f08c3bdfSopenharmony_ci
66f08c3bdfSopenharmony_ci	tst_res TINFO "Test process events connector"
67f08c3bdfSopenharmony_ci}
68f08c3bdfSopenharmony_ci
69f08c3bdfSopenharmony_cido_test()
70f08c3bdfSopenharmony_ci{
71f08c3bdfSopenharmony_ci	local event=$2
72f08c3bdfSopenharmony_ci	local gen_pid list_pid gen_rc lis_rc
73f08c3bdfSopenharmony_ci	local expected_events fd_act failed act_nevents exp act
74f08c3bdfSopenharmony_ci
75f08c3bdfSopenharmony_ci	tst_res TINFO "Testing $2 event (nevents=$num_events)"
76f08c3bdfSopenharmony_ci
77f08c3bdfSopenharmony_ci	event_generator -n $num_events -e $event -c $GENERATOR_ID >gen.log &
78f08c3bdfSopenharmony_ci	gen_pid=$!
79f08c3bdfSopenharmony_ci
80f08c3bdfSopenharmony_ci	pec_listener -p $gen_pid -c $LISTENER_ID >lis.log &
81f08c3bdfSopenharmony_ci	lis_pid=$!
82f08c3bdfSopenharmony_ci
83f08c3bdfSopenharmony_ci	TST_CHECKPOINT_WAIT $LISTENER_ID
84f08c3bdfSopenharmony_ci	TST_CHECKPOINT_WAKE $GENERATOR_ID
85f08c3bdfSopenharmony_ci
86f08c3bdfSopenharmony_ci	wait $gen_pid
87f08c3bdfSopenharmony_ci	gen_rc=$?
88f08c3bdfSopenharmony_ci	wait $lis_pid
89f08c3bdfSopenharmony_ci	lis_rc=$?
90f08c3bdfSopenharmony_ci
91f08c3bdfSopenharmony_ci	if [ $gen_rc -ne 0 ]; then
92f08c3bdfSopenharmony_ci		tst_brk TBROK "failed to execute event_generator"
93f08c3bdfSopenharmony_ci	fi
94f08c3bdfSopenharmony_ci
95f08c3bdfSopenharmony_ci	if [ $lis_rc -ne 0 ]; then
96f08c3bdfSopenharmony_ci		tst_brk TBROK "failed to execute pec_listener"
97f08c3bdfSopenharmony_ci	fi
98f08c3bdfSopenharmony_ci
99f08c3bdfSopenharmony_ci	# The listener writes the same messages as the generator, but it can
100f08c3bdfSopenharmony_ci	# also see more events (e.g. for testing exit, a fork is generated).
101f08c3bdfSopenharmony_ci	# So: The events generated by the generator have to be in the same order
102f08c3bdfSopenharmony_ci	# as the events printed by the listener, but my interleaved with other
103f08c3bdfSopenharmony_ci	# messages. To correctly compare them, we have to open both logs
104f08c3bdfSopenharmony_ci	# and iterate over both of them at the same time, skipping messages
105f08c3bdfSopenharmony_ci	# in the listener log, that are not of interest.
106f08c3bdfSopenharmony_ci	# Because some messages may be multiple times in the listener log,
107f08c3bdfSopenharmony_ci	# we have to open it only once!
108f08c3bdfSopenharmony_ci	# This however does not check, if the listener sees more messages,
109f08c3bdfSopenharmony_ci	# than expected.
110f08c3bdfSopenharmony_ci
111f08c3bdfSopenharmony_ci	fd_act=$(free_fd)
112f08c3bdfSopenharmony_ci	[ -z "$fd_act" ] && tst_brk TBROK "No free filehandle found"
113f08c3bdfSopenharmony_ci	eval "exec ${fd_act}<lis.log"
114f08c3bdfSopenharmony_ci
115f08c3bdfSopenharmony_ci	failed=0
116f08c3bdfSopenharmony_ci	act_nevents=0
117f08c3bdfSopenharmony_ci	while read -r exp; do
118f08c3bdfSopenharmony_ci		local found=0
119f08c3bdfSopenharmony_ci		act_nevents=$((act_nevents + 1))
120f08c3bdfSopenharmony_ci		while read -r act; do
121f08c3bdfSopenharmony_ci			if [ "$exp" = "$act" ]; then
122f08c3bdfSopenharmony_ci				found=1
123f08c3bdfSopenharmony_ci				break
124f08c3bdfSopenharmony_ci			fi
125f08c3bdfSopenharmony_ci		done <&${fd_act}
126f08c3bdfSopenharmony_ci		if [ $found -ne 1 ]; then
127f08c3bdfSopenharmony_ci			failed=1
128f08c3bdfSopenharmony_ci			tst_res TFAIL "Event was not detected by the event listener: $exp"
129f08c3bdfSopenharmony_ci			break
130f08c3bdfSopenharmony_ci		fi
131f08c3bdfSopenharmony_ci	done <gen.log
132f08c3bdfSopenharmony_ci
133f08c3bdfSopenharmony_ci	eval "exec ${fd_act}<&-"
134f08c3bdfSopenharmony_ci
135f08c3bdfSopenharmony_ci	if [ $failed -eq 0 ]; then
136f08c3bdfSopenharmony_ci		if [ $act_nevents -ne $num_events ]; then
137f08c3bdfSopenharmony_ci			tst_res TBROK "Expected $num_events, but $act_nevents generated"
138f08c3bdfSopenharmony_ci		else
139f08c3bdfSopenharmony_ci			tst_res TPASS "All events detected"
140f08c3bdfSopenharmony_ci		fi
141f08c3bdfSopenharmony_ci	else
142f08c3bdfSopenharmony_ci		# TFAIL message is already printed in the loop above
143f08c3bdfSopenharmony_ci		cat lis.log
144f08c3bdfSopenharmony_ci	fi
145f08c3bdfSopenharmony_ci}
146f08c3bdfSopenharmony_ci
147f08c3bdfSopenharmony_ci. tst_test.sh
148f08c3bdfSopenharmony_citst_run
149