summaryrefslogtreecommitdiff
diff options
authorSergio Cazzolato <sergio.cazzolato@canonical.com>2023-07-07 12:17:41 -0300
committerGitHub <noreply@github.com>2023-07-07 17:17:41 +0200
commit7ba95e3a7a22c56e730aa05f0609f37ab3b92036 (patch)
tree96b07b84aa76c2ced6557c80c3027d881a09d06d
parent4640067371757e901795e664b5f24a7d4b386deb (diff)
tests: speed up the prepare phase through a new tool to manage initial snapd env (#12707)
* New tool to manage initial env in spread tests This is used to know in spread tests the initial value for the vars and be able to repeat not needed steps * test fixed * Minor fixes con docs and env var removed * improve tests.env tool
-rw-r--r--spread.yaml3
l---------tests/bin/tests.env1
-rwxr-xr-xtests/lib/prepare.sh60
-rwxr-xr-xtests/lib/state.sh2
-rw-r--r--tests/lib/tools/suite/tests.env/task.yaml59
-rwxr-xr-xtests/lib/tools/tests.env130
6 files changed, 227 insertions, 28 deletions
diff --git a/spread.yaml b/spread.yaml
index 0ba63a201e..10fadaca57 100644
--- a/spread.yaml
+++ b/spread.yaml
@@ -15,6 +15,7 @@ environment:
TESTSLIB: $PROJECT_PATH/tests/lib
TESTSTOOLS: $PROJECT_PATH/tests/lib/tools
TESTSTMP: /var/tmp/snapd-tools
+ RUNTIME_STATE_PATH: $TESTSTMP/runtime-state
# turn debug off so that we don't get errant debug messages while running
# tests, and in some cases like on UC20 we have the kernel command line
# parameter, snapd.debug=1 turned on to enable early boot debugging before
@@ -73,6 +74,8 @@ environment:
# Use the installed snapd and reset the systems without removing snapd
REUSE_SNAPD: '$(HOST: echo "${SPREAD_REUSE_SNAPD:-0}")'
EXPERIMENTAL_FEATURES: '$(HOST: echo "${SPREAD_EXPERIMENTAL_FEATURES:-}")'
+ # set to 1 when the snapd memory limit has to be removed
+ SNAPD_NO_MEMORY_LIMIT: '$(HOST: echo "${SPREAD_SNAPD_NO_MEMORY_LIMIT:-}")'
SNAPD_PUBLISHED_VERSION: '$(HOST: echo "$SPREAD_SNAPD_PUBLISHED_VERSION")'
# Build and use snapd from current branch
diff --git a/tests/bin/tests.env b/tests/bin/tests.env
new file mode 120000
index 0000000000..fd2854638f
--- /dev/null
+++ b/tests/bin/tests.env
@@ -0,0 +1 @@
+../lib/tools/tests.env \ No newline at end of file
diff --git a/tests/lib/prepare.sh b/tests/lib/prepare.sh
index fd70674521..42aa27fbc9 100755
--- a/tests/lib/prepare.sh
+++ b/tests/lib/prepare.sh
@@ -215,6 +215,14 @@ update_core_snap_for_classic_reexec() {
}
prepare_memory_limit_override() {
+ # First time it is needed to save the initial env var value
+ if not tests.env is-set initial SNAPD_NO_MEMORY_LIMIT; then
+ tests.env set initial SNAPD_NO_MEMORY_LIMIT "$SNAPD_NO_MEMORY_LIMIT"
+ # Then if the new value is the same than the initial, then no new configuration needed
+ elif [ "$(tests.env get initial SNAPD_NO_MEMORY_LIMIT)" = "$SNAPD_NO_MEMORY_LIMIT" ]; then
+ return
+ fi
+
# set up memory limits for snapd bu default unless explicit requested not to
# or the system is known to be problematic
local set_limit=1
@@ -232,7 +240,7 @@ prepare_memory_limit_override() {
set_limit=0
;;
*)
- if [ -n "${SNAPD_NO_MEMORY_LIMIT:-}" ]; then
+ if [ "$SNAPD_NO_MEMORY_LIMIT" = 1 ]; then
set_limit=0
fi
;;
@@ -254,8 +262,7 @@ prepare_memory_limit_override() {
# systemd is backwards compatible so the limit is still set.
cat <<EOF > /etc/systemd/system/snapd.service.d/memory-max.conf
[Service]
-# mvo: disabled because of many failures in restore, e.g. in PR#11014
-#MemoryLimit=100M
+MemoryLimit=150M
EOF
fi
# the service setting may have changed in the service so we need
@@ -264,38 +271,31 @@ EOF
systemctl restart snapd
}
-create_reexec_file(){
- local reexec_file=$1
- cat <<EOF > "$reexec_file"
-[Service]
-Environment=SNAP_REEXEC=$SNAP_REEXEC
-EOF
-}
-
prepare_reexec_override() {
local reexec_file=/etc/systemd/system/snapd.service.d/reexec.conf
- local updated=false
+
+ # First time it is needed to save the initial env var value
+ if not tests.env is-set initial SNAP_REEXEC; then
+ tests.env set initial SNAP_REEXEC "$SNAP_REEXEC"
+ # Then if the new value is the same than the initial, then no new configuration needed
+ elif [ "$(tests.env get initial SNAP_REEXEC)" = "$SNAP_REEXEC" ]; then
+ return
+ fi
# Just update reexec configuration when the SNAP_REEXEC var has been updated
# Otherwise it is used the configuration set during project preparation
mkdir -p /etc/systemd/system/snapd.service.d
- if [ -z "${SNAP_REEXEC:-}" ] && [ -f "$reexec_file" ] ; then
+ if [ -z "${SNAP_REEXEC:-}" ]; then
rm -f "$reexec_file"
- updated=true
- elif [ -n "${SNAP_REEXEC:-}" ] && [ ! -f "$reexec_file" ]; then
- create_reexec_file "$reexec_file"
- updated=true
- elif [ -n "${SNAP_REEXEC:-}" ] && NOMATCH "Environment=SNAP_REEXEC=$SNAP_REEXEC" < "$reexec_file"; then
- create_reexec_file "$reexec_file"
- updated=true
+ else
+ cat <<EOF > "$reexec_file"
+[Service]
+Environment=SNAP_REEXEC=$SNAP_REEXEC
+EOF
fi
- if [ "$updated" = true ]; then
- # the re-exec setting may have changed in the service so we need
- # to ensure snapd is reloaded
- systemctl daemon-reload
- systemctl restart snapd
- fi
+ systemctl daemon-reload
+ systemctl restart snapd
}
prepare_each_classic() {
@@ -303,7 +303,9 @@ prepare_each_classic() {
echo "/etc/systemd/system/snapd.service.d/local.conf vanished!"
exit 1
fi
+
prepare_reexec_override
+ prepare_memory_limit_override
}
prepare_classic() {
@@ -360,6 +362,9 @@ prepare_classic() {
# Snapshot the state including core.
if ! is_snapd_state_saved; then
+ # Create the file with the initial environment before saving the state
+ tests.env start initial
+
# need to be seeded to proceed with snap install
# also make sure the captured state is seeded
snap wait system seed.loaded
@@ -1420,6 +1425,9 @@ prepare_ubuntu_core() {
# Snapshot the fresh state (including boot/bootenv)
if ! is_snapd_state_saved; then
+ # Create the file with the initial environment before saving the state
+ tests.env start initial
+
# important to remove disabled snaps before calling save_snapd_state
# or restore will break
remove_disabled_snaps
diff --git a/tests/lib/state.sh b/tests/lib/state.sh
index 73cdad0b87..6188cb4a60 100755
--- a/tests/lib/state.sh
+++ b/tests/lib/state.sh
@@ -2,10 +2,8 @@
SNAPD_STATE_PATH="$TESTSTMP/snapd-state"
SNAPD_STATE_FILE="$TESTSTMP/snapd-state/snapd-state.tar"
-RUNTIME_STATE_PATH="$TESTSTMP/runtime-state"
SNAPD_ACTIVE_UNITS="$RUNTIME_STATE_PATH/snapd-active-units"
-
delete_snapd_state() {
rm -rf "$SNAPD_STATE_PATH"
}
diff --git a/tests/lib/tools/suite/tests.env/task.yaml b/tests/lib/tools/suite/tests.env/task.yaml
new file mode 100644
index 0000000000..dcfc6be923
--- /dev/null
+++ b/tests/lib/tools/suite/tests.env/task.yaml
@@ -0,0 +1,59 @@
+summary: tests for tests.env
+
+restore: |
+ rm -f "$RUNTIME_STATE_PATH"/test1.env "$RUNTIME_STATE_PATH"/test2.env
+
+execute: |
+ # Both -h and --help are also recognized.
+ tests.env --help | MATCH "usage: tests.env start <ENV_NAME>"
+ tests.env -h | MATCH "usage: tests.env start <ENV_NAME>"
+
+ # check start env file
+ tests.env start test1
+ test -f "$RUNTIME_STATE_PATH"/test1.env
+
+ # check commands is-set and set
+ not tests.env is-set test1 var1
+ tests.env set test1 var1 val1
+ tests.env is-set test1 var1
+ tests.env set test1 var3
+ tests.env set test1 var4 ""
+
+ # check command get
+ test "$(tests.env get test1 var1)" = "val1"
+ test "$(tests.env get test1 var3)" = ""
+ test "$(tests.env get test1 var4)" = ""
+
+ # check set another value
+ not tests.env is-set test1 var2
+ tests.env set test1 var2 val2
+ tests.env is-set test1 var2
+ test "$(tests.env get test1 var2)" = "val2"
+ test "$(tests.env get test1 var1)" = "val1"
+
+ # check update the value
+ tests.env set test1 var1 val3
+ test "$(tests.env get test1 var1)" = "val3"
+
+ # create another env
+ tests.env start test2
+ tests.env set test2 var1 val1
+ test "$(tests.env get test1 var1)" = "val3"
+ test "$(tests.env get test2 var1)" = "val1"
+
+ # check errors
+ tests.env test 2>&1 | MATCH "tests.env: no such command: test"
+
+ tests.env start 2>&1 | MATCH "tests.env: name for the env file is required"
+
+ tests.env is-set 2>&1 | MATCH "tests.env: name for the env file is required"
+ tests.env is-set test1 2>&1 | MATCH "tests.env: variable to check in env file is required"
+ tests.env is-set test10 var1 2>&1 | MATCH "tests.env: env file $RUNTIME_STATE_PATH/test10.env does not exist"
+
+ tests.env get 2>&1 | MATCH "tests.env: name for the env file is required"
+ tests.env get test1 2>&1 | MATCH "tests.env: variable to check in env file is required"
+ tests.env get test10 var1 2>&1 | MATCH "tests.env: env file $RUNTIME_STATE_PATH/test10.env does not exist"
+
+ tests.env set 2>&1 | MATCH "tests.env: name for the env file is required"
+ tests.env set test1 2>&1 | MATCH "tests.env: variable to set in env file is required"
+ tests.env set test10 var1 val1 2>&1 | MATCH "tests.env: env file $RUNTIME_STATE_PATH/test10.env does not exist"
diff --git a/tests/lib/tools/tests.env b/tests/lib/tools/tests.env
new file mode 100755
index 0000000000..a302a254e3
--- /dev/null
+++ b/tests/lib/tools/tests.env
@@ -0,0 +1,130 @@
+#!/bin/bash
+
+show_help() {
+ echo "usage: tests.env start <ENV_NAME>"
+ echo " tests.env is-set <ENV_NAME> <VAR>"
+ echo " tests.env get <ENV_NAME> <VAR>"
+ echo " tests.env set <ENV_NAME> <VAR> <VAL>"
+ echo ""
+ echo "The tool is used to create an environment file"
+ echo " which can be shared across different tests and suites"
+}
+
+start() {
+ local NAME=$1
+ if [ -z "$NAME" ]; then
+ echo "tests.env: name for the env file is required"
+ exit 1
+ fi
+
+ if [ -f "$RUNTIME_STATE_PATH/$NAME.env" ]; then
+ echo "tests.env: env file $RUNTIME_STATE_PATH/$NAME.env already exists, deleting..."
+ rm -f "$RUNTIME_STATE_PATH/$NAME.env"
+ fi
+ mkdir -p "$RUNTIME_STATE_PATH"
+ touch "$RUNTIME_STATE_PATH/$NAME.env"
+}
+
+is_set() {
+ local NAME=$1
+ local VAR=$2
+
+ if [ -z "$NAME" ]; then
+ echo "tests.env: name for the env file is required"
+ exit 1
+ fi
+ if [ -z "$VAR" ]; then
+ echo "tests.env: variable to check in env file is required"
+ exit 1
+ fi
+
+ if [ ! -f "$RUNTIME_STATE_PATH/$NAME.env" ]; then
+ echo "tests.env: env file $RUNTIME_STATE_PATH/$NAME.env does not exist"
+ exit 1
+ fi
+
+ grep -Eq "^${VAR}=" "$RUNTIME_STATE_PATH/$NAME.env"
+}
+
+get() {
+ local NAME=$1
+ local VAR=$2
+
+ if [ -z "$NAME" ]; then
+ echo "tests.env: name for the env file is required"
+ exit 1
+ fi
+ if [ -z "$VAR" ]; then
+ echo "tests.env: variable to check in env file is required"
+ exit 1
+ fi
+
+ if [ ! -f "$RUNTIME_STATE_PATH/$NAME.env" ]; then
+ echo "tests.env: env file $RUNTIME_STATE_PATH/$NAME.env does not exist"
+ exit 1
+ fi
+
+ if is_set "$NAME" "$VAR"; then
+ grep -E "^${VAR}=" "$RUNTIME_STATE_PATH/$NAME.env" | cut -d "=" -f2-
+ fi
+}
+
+set() {
+ local NAME=$1
+ local VAR=$2
+ local VAL=$3
+
+ if [ -z "$NAME" ]; then
+ echo "tests.env: name for the env file is required"
+ exit 1
+ fi
+ if [ -z "$VAR" ]; then
+ echo "tests.env: variable to set in env file is required"
+ exit 1
+ fi
+
+ if [ ! -f "$RUNTIME_STATE_PATH/$NAME.env" ]; then
+ echo "tests.env: env file $RUNTIME_STATE_PATH/$NAME.env does not exist"
+ exit 1
+ fi
+
+ if is_set "$NAME" "$VAR"; then
+ sed -i -E "s/^${VAR}=.*/${VAR}=${VAL}/" "$RUNTIME_STATE_PATH/$NAME.env"
+ else
+ echo "${VAR}=${VAL}" >> "$RUNTIME_STATE_PATH/$NAME.env"
+ fi
+
+}
+
+main() {
+ if [ $# -eq 0 ]; then
+ show_help
+ exit 0
+ fi
+
+ local subcommand="$1"
+ local action=
+ while [ $# -gt 0 ]; do
+ case "$subcommand" in
+ -h|--help)
+ show_help
+ exit 0
+ ;;
+ *)
+ action=$(echo "$subcommand" | tr '-' '_')
+ shift
+ break
+ ;;
+ esac
+ done
+
+ if [ -z "$(declare -f "$action")" ]; then
+ echo "tests.env: no such command: $subcommand"
+ show_help
+ exit 1
+ fi
+
+ "$action" "$@"
+}
+
+main "$@"