testcases/lib/test.sh: add tst_retry()

The function allows you to retry running command a few times until it
succeeds or until given amount of retries has been reached.

Signed-off-by: Hangbin Liu <liuhangbin@gmail.com>
Signed-off-by: Cyril Hrubis <chrubis@suse.cz>
diff --git a/doc/test-writing-guidelines.txt b/doc/test-writing-guidelines.txt
index edd5905..de06dc9 100644
--- a/doc/test-writing-guidelines.txt
+++ b/doc/test-writing-guidelines.txt
@@ -1247,11 +1247,34 @@
 ...
 -------------------------------------------------------------------------------
 
-The tst_fs_has_free shell interface returns 0 if the specified free space is
+The 'tst_fs_has_free' shell interface returns 0 if the specified free space is
 satisfied, 1 if not, and 2 on error.
 
 The second argument supports suffixes kB, MB and GB, the default unit is Byte.
 
+.tst_retry
+[source,sh]
+-------------------------------------------------------------------------------
+#!/bin/sh
+
+...
+
+# Retry ping command three times
+tst_retry "ping -c 1 127.0.0.1"
+
+if [ $? -ne 0 ]; then
+	tst_resm TFAIL "Failed to ping 127.0.0.1"
+else
+	tst_resm TPASS "Successfully pinged 127.0.0.1"
+fi
+
+...
+-------------------------------------------------------------------------------
+
+The 'tst_retry' function allows you to retry a command after waiting small
+amount of time until it succeeds or until given amount of retries has been
+reached (default is three attempts).
+
 2.3.3 Cleanup
 ^^^^^^^^^^^^^
 
diff --git a/testcases/lib/test.sh b/testcases/lib/test.sh
index 1c9b126..1753664 100644
--- a/testcases/lib/test.sh
+++ b/testcases/lib/test.sh
@@ -134,6 +134,33 @@
 	done
 }
 
+# tst_retry "command" [times]
+# try run command for specified times, default is 3.
+# Function returns 0 if succeed in RETRIES times or the last retcode the cmd
+# returned
+tst_retry()
+{
+	local cmd="$1"
+	local RETRIES=${2:-"3"}
+	local i=$RETRIES
+
+	while [ $i -gt 0 ]; do
+		eval "$cmd"
+		ret=$?
+		if [ $ret -eq 0 ]; then
+			break
+		fi
+		i=$((i-1))
+		sleep 1
+	done
+
+	if [ $ret -ne 0 ]; then
+		tst_resm TINFO "Failed to execute '$cmd' after $RETRIES retries"
+	fi
+
+	return $ret
+}
+
 # tst_timeout "command arg1 arg2 ..." timeout
 # Runs command for specified timeout (in seconds).
 # Function returns retcode of command or 1 if arguments are invalid.