All of lore.kernel.org
 help / color / mirror / Atom feed
* [Fuego] [PATCH] Optimize the code of assert_has_program.
@ 2019-09-04  1:09 Wang Mingyu
  2019-09-04  1:09 ` [Fuego] [PATCH] ltrace: Add test cases for command ltrace Wang Mingyu
                   ` (2 more replies)
  0 siblings, 3 replies; 9+ messages in thread
From: Wang Mingyu @ 2019-09-04  1:09 UTC (permalink / raw)
  To: fuego

It is faster to check the prgoram or file on the target.

Usage:
before:
    assert_has_program AAA
    assert_has_program BBB

after:
    assert_has_program "AAA BBB"
    assert_has_program "AAA BBB" SEARCH_PATH

Note: SEARCH_PATH is optional.

Signed-off-by: Wang Mingyu <wangmy@cn.fujitsu.com>
---
 scripts/functions.sh  | 65 +++++++++++++++++++++++++++++++++++++++----
 scripts/need_check.sh | 11 ++------
 2 files changed, 61 insertions(+), 15 deletions(-)

diff --git a/scripts/functions.sh b/scripts/functions.sh
index 0fa80b8..3aea0c8 100755
--- a/scripts/functions.sh
+++ b/scripts/functions.sh
@@ -1010,6 +1010,57 @@ function is_on_target_path {
     is_on_target $1 $2 $TARGET_PATH
 }
 
+# check for a program or file on the target, and set a variable if it's present
+# $1 - file, dir or program on target
+# $2 is the path of target to search the program/file
+# $3 - tmpfile to save the detect result
+function set_cmd_str {
+   tmpfile=$3
+   cmd_str="touch $tmpfile
+         # split $1 on whitespace, without file globbing
+         for prg in \$(echo $1 | tr \" \" \"\\n\") ; do
+             # split search path on colon
+             for d in \$(echo $2 | tr \":\" \"\\n\") ; do
+                 # execute a command on the target to detect \$d/\$prg
+                 if [ -z \"\$(cat $tmpfile)\" -a -e \"\$d/\$prg\" ]
+                 then
+                     echo \"\$d/\$prg\" >$tmpfile ;break;
+                 fi
+             done
+             if [ ! -s $tmpfile ]
+             then
+                 find / -name \"\$prg\" | head -n 1 >$tmpfile
+             fi
+             if [ ! -s $tmpfile ]
+             then
+                 echo \"\$prg\" >$tmpfile ; break;
+             else
+                 > $tmpfile
+             fi
+         done"
+}
+
+# check for a program or file on the target, and set a variable if it's present
+# $1 - file, dir or program on target
+# $2 - variable to set during the build
+# $3 is the path of target to search the program/file (optional, default: $PATH)
+function assert_on_target {
+    local TARGET_PATH=${3}
+    if [ -z "$TARGET_PATH" ]; then
+       TARGET_PATH=$(cmd "echo \$PATH")
+    fi
+
+    tmpfile=$(mktemp /tmp/found_loc.XXXXXX)
+    set_cmd_str "$1" $TARGET_PATH $tmpfile
+    cmd "$cmd_str"
+    get $tmpfile $tmpfile
+    if [ -s $tmpfile ] ; then
+        export $2=$(cat $tmpfile)
+    fi
+    cmd "rm $tmpfile"
+    rm -f $tmpfile # -f for tests running on the host
+}
+
 # check for a library on the SDK, and set a variable if it's present
 # $1 - the file (library) we want to search for in the SDK
 # $2 - variable to set the location (if the file is found)
@@ -1036,13 +1087,15 @@ function is_on_sdk {
 
 # check for a program or file on the target, and send message if the program or file is missing
 # $1 has the program that is required on the target board
-# this has the side effect of defining PROGRAM_$1 (uppercased)
-# with the value as the directory where $1 is found on the board.
+# $2 is the path of target to search the program/file (optional, default: $PATH)
 function assert_has_program {
-   upName=${1^^}
-   progVar=PROGRAM_${upName//[-,.]/_}
-   is_on_target_path $1 ${progVar}
-   assert_define ${progVar} "Missing '$1' program on target board"
+   assert_on_target "$1" prgName $2
+   if [ -n "$prgName" ]
+   then
+       upName=${prgName^^}
+       progVar=PROGRAM_${upName//[-,.]/_}
+       assert_define ${progVar} "Missing '$prgName' program on target board"
+   fi
 }
 
 # check for a module on the target, and abort if it is missing
diff --git a/scripts/need_check.sh b/scripts/need_check.sh
index c9bbb75..9bb0098 100755
--- a/scripts/need_check.sh
+++ b/scripts/need_check.sh
@@ -319,18 +319,11 @@ function check_root {
 # check if those specified commands exist on board
 # $1 has single string with a list of command entries to check for
 function check_program {
-  # split $1 on whitespace, without file globbing
-  set -f
-  arg_array=($1)
-  set +f
-
-  for prg in "${arg_array[@]}" ; do
-    is_on_target_path $prg prg_path
-    if [ -z "$prg_path" ] ; then
+    assert_on_target "$1" prg
+    if [ -n "$prg" ] ; then
       echo -e "\n\nABORTED: Expected command \"$prg\" on the target, but it's not there!"
       return 1
     fi
-  done
 
   # return OK if all necessary commands exist on the target
   return 0
-- 
2.17.1




^ permalink raw reply related	[flat|nested] 9+ messages in thread

* [Fuego] [PATCH] ltrace: Add test cases for command ltrace.
  2019-09-04  1:09 [Fuego] [PATCH] Optimize the code of assert_has_program Wang Mingyu
@ 2019-09-04  1:09 ` Wang Mingyu
  2019-09-11 17:28   ` Tim.Bird
  2019-09-04  1:09 ` [Fuego] [PATCH] nfs: Add test cases for nfs Wang Mingyu
  2019-09-21  2:24 ` [Fuego] [PATCH] Optimize the code of assert_has_program Tim.Bird
  2 siblings, 1 reply; 9+ messages in thread
From: Wang Mingyu @ 2019-09-04  1:09 UTC (permalink / raw)
  To: fuego

ltrace is a program that simply runs the specified command until it exits.
This test set is used to check the ountput syscall/time/count/help of command to trace and check if can be saved to file.

Signed-off-by: Wang Mingyu <wangmy@cn.fujitsu.com>
---
 tests/Functional.ltrace/fuego_test.sh           | 17 +++++++++++++++++
 tests/Functional.ltrace/ltrace_test.sh          |  4 ++++
 tests/Functional.ltrace/spec.json               |  6 ++++++
 tests/Functional.ltrace/tests/ltrace_count.sh   | 15 +++++++++++++++
 tests/Functional.ltrace/tests/ltrace_help.sh    | 13 +++++++++++++
 tests/Functional.ltrace/tests/ltrace_output.sh  | 15 +++++++++++++++
 tests/Functional.ltrace/tests/ltrace_syscall.sh | 15 +++++++++++++++
 tests/Functional.ltrace/tests/ltrace_time.sh    | 15 +++++++++++++++
 8 files changed, 100 insertions(+)
 create mode 100644 tests/Functional.ltrace/fuego_test.sh
 create mode 100755 tests/Functional.ltrace/ltrace_test.sh
 create mode 100644 tests/Functional.ltrace/spec.json
 create mode 100644 tests/Functional.ltrace/tests/ltrace_count.sh
 create mode 100644 tests/Functional.ltrace/tests/ltrace_help.sh
 create mode 100644 tests/Functional.ltrace/tests/ltrace_output.sh
 create mode 100644 tests/Functional.ltrace/tests/ltrace_syscall.sh
 create mode 100644 tests/Functional.ltrace/tests/ltrace_time.sh

diff --git a/tests/Functional.ltrace/fuego_test.sh b/tests/Functional.ltrace/fuego_test.sh
new file mode 100644
index 0000000..ecfc4e7
--- /dev/null
+++ b/tests/Functional.ltrace/fuego_test.sh
@@ -0,0 +1,17 @@
+function test_pre_check {
+    assert_has_program ltrace
+}
+
+function test_deploy {
+    put $TEST_HOME/ltrace_test.sh $BOARD_TESTDIR/fuego.$TESTDIR/
+    put -r $TEST_HOME/tests $BOARD_TESTDIR/fuego.$TESTDIR/
+}
+
+function test_run {
+    report "cd $BOARD_TESTDIR/fuego.$TESTDIR;\
+    ./ltrace_test.sh"
+}
+
+function test_processing {
+    log_compare "$TESTDIR" "0" "TEST-FAIL" "n"
+}
diff --git a/tests/Functional.ltrace/ltrace_test.sh b/tests/Functional.ltrace/ltrace_test.sh
new file mode 100755
index 0000000..dd5ce37
--- /dev/null
+++ b/tests/Functional.ltrace/ltrace_test.sh
@@ -0,0 +1,4 @@
+#!/bin/sh
+for i in tests/*.sh; do
+    sh $i
+done
diff --git a/tests/Functional.ltrace/spec.json b/tests/Functional.ltrace/spec.json
new file mode 100644
index 0000000..fce7a19
--- /dev/null
+++ b/tests/Functional.ltrace/spec.json
@@ -0,0 +1,6 @@
+{
+    "testName": "Functional.ltrace",
+    "specs": {
+        "default": {}
+    }
+}
diff --git a/tests/Functional.ltrace/tests/ltrace_count.sh b/tests/Functional.ltrace/tests/ltrace_count.sh
new file mode 100644
index 0000000..5a277fc
--- /dev/null
+++ b/tests/Functional.ltrace/tests/ltrace_count.sh
@@ -0,0 +1,15 @@
+#!/bin/sh
+
+#  In target, run comannd ltrace to count time and calls.
+#  option: -c
+
+test="count"
+
+ltrace -c dd if=/dev/urandom of=/dev/null count=1000 > log 2>&1
+if cat log | grep "usecs/call"
+then
+    echo " -> $test: TEST-PASS"
+else
+    echo " -> $test: TEST-FAIL"
+fi
+rm log
diff --git a/tests/Functional.ltrace/tests/ltrace_help.sh b/tests/Functional.ltrace/tests/ltrace_help.sh
new file mode 100644
index 0000000..ea45a7e
--- /dev/null
+++ b/tests/Functional.ltrace/tests/ltrace_help.sh
@@ -0,0 +1,13 @@
+#!/bin/sh
+
+#  In target, run comannd ltrace to display help message.
+#  option: -h/--help
+
+test="help"
+
+if ltrace -h | grep [uU]sage
+then
+    echo " -> $test: TEST-PASS"
+else
+    echo " -> $test: TEST-FAIL"
+fi
diff --git a/tests/Functional.ltrace/tests/ltrace_output.sh b/tests/Functional.ltrace/tests/ltrace_output.sh
new file mode 100644
index 0000000..2d941b0
--- /dev/null
+++ b/tests/Functional.ltrace/tests/ltrace_output.sh
@@ -0,0 +1,15 @@
+#!/bin/sh
+
+#  Write the trace output to the file filename rather than to stderr.
+#  option: -o/--output
+
+test="output"
+
+ltrace -o log ls
+if cat log | grep "+++ exited (status 0) +++"
+then
+    echo " -> $test: TEST-PASS"
+else
+    echo " -> $test: TEST-FAIL"
+fi
+rm log
diff --git a/tests/Functional.ltrace/tests/ltrace_syscall.sh b/tests/Functional.ltrace/tests/ltrace_syscall.sh
new file mode 100644
index 0000000..34d1dc5
--- /dev/null
+++ b/tests/Functional.ltrace/tests/ltrace_syscall.sh
@@ -0,0 +1,15 @@
+#!/bin/sh
+
+#  In target, run comannd ltrace to display system calls.
+#  option: -S
+
+test="syscall"
+
+ltrace -S ls > log 2>&1
+if cat log | grep "+++ exited (status 0) +++"
+then
+    echo " -> $test: TEST-PASS"
+else
+    echo " -> $test: TEST-FAIL"
+fi
+rm log
diff --git a/tests/Functional.ltrace/tests/ltrace_time.sh b/tests/Functional.ltrace/tests/ltrace_time.sh
new file mode 100644
index 0000000..fc09108
--- /dev/null
+++ b/tests/Functional.ltrace/tests/ltrace_time.sh
@@ -0,0 +1,15 @@
+#!/bin/sh
+
+#  In target, run comannd ltrace to show the time spent inside each call.
+#  option: -T
+
+test="time"
+
+ltrace -T ls > log 2>&1
+if cat log | grep "<[0-9].[0-9]\{6\}>"
+then
+    echo " -> $test: TEST-PASS"
+else
+    echo " -> $test: TEST-FAIL"
+fi
+rm log
-- 
2.17.1




^ permalink raw reply related	[flat|nested] 9+ messages in thread

* [Fuego] [PATCH] nfs: Add test cases for nfs.
  2019-09-04  1:09 [Fuego] [PATCH] Optimize the code of assert_has_program Wang Mingyu
  2019-09-04  1:09 ` [Fuego] [PATCH] ltrace: Add test cases for command ltrace Wang Mingyu
@ 2019-09-04  1:09 ` Wang Mingyu
  2019-09-21  1:40   ` Tim.Bird
  2019-09-21  2:24 ` [Fuego] [PATCH] Optimize the code of assert_has_program Tim.Bird
  2 siblings, 1 reply; 9+ messages in thread
From: Wang Mingyu @ 2019-09-04  1:09 UTC (permalink / raw)
  To: fuego

This test set is used to check service(nfs-mountd/nfs-statd) and commands(nfsiostat/nfsserver/nfsstat) of nfs.

Signed-off-by: Wang Mingyu <wangmy@cn.fujitsu.com>
---
 tests/Functional.nfs/fuego_test.sh          | 22 +++++
 tests/Functional.nfs/nfs_test.sh            |  4 +
 tests/Functional.nfs/spec.json              |  7 ++
 tests/Functional.nfs/tests/nfs-mountd_ps.sh | 69 +++++++++++++++
 tests/Functional.nfs/tests/nfs-statd_ps.sh  | 50 +++++++++++
 tests/Functional.nfs/tests/nfsiostat.sh     | 60 +++++++++++++
 tests/Functional.nfs/tests/nfsserver_ps.sh  | 96 +++++++++++++++++++++
 tests/Functional.nfs/tests/nfsstat.sh       | 32 +++++++
 8 files changed, 340 insertions(+)
 create mode 100644 tests/Functional.nfs/fuego_test.sh
 create mode 100755 tests/Functional.nfs/nfs_test.sh
 create mode 100644 tests/Functional.nfs/spec.json
 create mode 100644 tests/Functional.nfs/tests/nfs-mountd_ps.sh
 create mode 100644 tests/Functional.nfs/tests/nfs-statd_ps.sh
 create mode 100644 tests/Functional.nfs/tests/nfsiostat.sh
 create mode 100644 tests/Functional.nfs/tests/nfsserver_ps.sh
 create mode 100644 tests/Functional.nfs/tests/nfsstat.sh

diff --git a/tests/Functional.nfs/fuego_test.sh b/tests/Functional.nfs/fuego_test.sh
new file mode 100644
index 0000000..624c25f
--- /dev/null
+++ b/tests/Functional.nfs/fuego_test.sh
@@ -0,0 +1,22 @@
+function test_pre_check {
+    assert_has_program nfsstat
+    assert_has_program nfsiostat
+    assert_has_program rpc.nfsd
+    assert_has_program rpc.statd
+    assert_has_program rpc.mountd
+}
+
+function test_deploy {
+    put $TEST_HOME/nfs_test.sh $BOARD_TESTDIR/fuego.$TESTDIR/
+    put $FUEGO_CORE/scripts/fuego_board_function_lib.sh $BOARD_TESTDIR/fuego.$TESTDIR
+    put -r $TEST_HOME/tests $BOARD_TESTDIR/fuego.$TESTDIR/
+}
+
+function test_run {
+    report "cd $BOARD_TESTDIR/fuego.$TESTDIR;\
+    ./nfs_test.sh"
+}
+
+function test_processing {
+    log_compare "$TESTDIR" "0" "TEST-FAIL" "n"
+}
diff --git a/tests/Functional.nfs/nfs_test.sh b/tests/Functional.nfs/nfs_test.sh
new file mode 100755
index 0000000..dd5ce37
--- /dev/null
+++ b/tests/Functional.nfs/nfs_test.sh
@@ -0,0 +1,4 @@
+#!/bin/sh
+for i in tests/*.sh; do
+    sh $i
+done
diff --git a/tests/Functional.nfs/spec.json b/tests/Functional.nfs/spec.json
new file mode 100644
index 0000000..69a241c
--- /dev/null
+++ b/tests/Functional.nfs/spec.json
@@ -0,0 +1,7 @@
+{
+    "testName": "Functional.nfs",
+    "specs": {
+        "default": {}
+    }
+}
+
diff --git a/tests/Functional.nfs/tests/nfs-mountd_ps.sh b/tests/Functional.nfs/tests/nfs-mountd_ps.sh
new file mode 100644
index 0000000..c24345e
--- /dev/null
+++ b/tests/Functional.nfs/tests/nfs-mountd_ps.sh
@@ -0,0 +1,69 @@
+#!/bin/sh
+
+#  In the target start nfs-mountd, and confirm the process condition by command ps.
+
+test="nfs-mountd_ps"
+
+. ./fuego_board_function_lib.sh
+
+set_init_manager
+
+service_status=$(get_service_status nfs-mountd)
+exec_service_on_target nfs-mountd stop
+
+if [ -f /etc/exports ]
+then
+    mv /etc/exports /etc/exports_bak
+fi
+
+touch /etc/exports
+
+restore_target() {
+    if [ -f /etc/exports_bak ]
+    then
+        mv /etc/exports_bak /etc/exports
+    else
+        rm -f /etc/exports
+    fi
+}
+
+if exec_service_on_target nfs-mountd start
+then
+    echo " -> start of nfs-mountd succeeded."
+else
+    echo " -> start of nfs-mountd failed."
+    echo " -> $test: TEST-FAIL"
+    restore_target
+    exit
+fi
+
+sleep 5
+
+if ps aux | grep "[/]usr/sbin/rpc.mountd"
+then
+    echo " -> get the process of rpc.mountd."
+else
+    echo " -> can't get the process of rpc.mountd."
+    echo " -> $test: TEST-FAIL"
+    if [ "$service_status" = "inactive" ]
+    then
+        exec_service_on_target nfs-mountd stop
+    fi
+    restore_target
+    exit
+fi
+
+exec_service_on_target nfs-mountd stop
+
+if ps aux | grep "[/]usr/sbin/rpc.mountd"
+then
+    echo " -> $test: TEST-FAIL"
+else
+    echo " -> $test: TEST-PASS"
+fi
+
+if [ "$service_status" = "active" -o "$service_status" = "unknown"]
+then
+    exec_service_on_target nfs-mountd start
+fi
+restore_target
diff --git a/tests/Functional.nfs/tests/nfs-statd_ps.sh b/tests/Functional.nfs/tests/nfs-statd_ps.sh
new file mode 100644
index 0000000..43dc43b
--- /dev/null
+++ b/tests/Functional.nfs/tests/nfs-statd_ps.sh
@@ -0,0 +1,50 @@
+#!/bin/sh
+
+#  In the target start nfs-statd, and confirm the process condition by command ps.
+
+test="nfs-statd_ps"
+
+. ./fuego_board_function_lib.sh
+
+set_init_manager
+
+service_status=$(get_service_status nfs-statd)
+exec_service_on_target nfs-statd stop
+
+if exec_service_on_target nfs-statd start
+then
+    echo " -> start of nfs-statd succeeded."
+else
+    echo " -> start of nfs-statd failed."
+    echo " -> $test: TEST-FAIL"
+    exit
+fi
+
+sleep 5
+
+if ps aux | grep "[/]usr/sbin/rpc.statd"
+then
+    echo " -> get the process of rpc.statd."
+else
+    echo " -> can't get the process of rpc.statd."
+    echo " -> $test: TEST-FAIL"
+    if [ "$service_status" = "inactive" ]
+    then
+        exec_service_on_target nfs-statd stop
+    fi
+    exit
+fi
+
+exec_service_on_target nfs-statd stop
+
+if ps aux | grep "[/]usr/sbin/rpc.statd"
+then
+    echo " -> $test: TEST-FAIL"
+else
+    echo " -> $test: TEST-PASS"
+fi
+
+if [ "$service_status" = "active" -o "$service_status" = "unknown" ]
+then
+    exec_service_on_target nfs-statd start
+fi
diff --git a/tests/Functional.nfs/tests/nfsiostat.sh b/tests/Functional.nfs/tests/nfsiostat.sh
new file mode 100644
index 0000000..c1a683d
--- /dev/null
+++ b/tests/Functional.nfs/tests/nfsiostat.sh
@@ -0,0 +1,60 @@
+#!/bin/sh
+
+#  In the target run the command nfiosstat, and displays NFS client per-mount statisitics..
+#  option : -a, -d, -h, -p, -s, --version
+
+test="nfsiostat"
+
+if nfsiostat -a | grep "attribute cache"
+then
+    echo " -> Display statistics related to the attribute cache succeeded."
+else
+    echo " -> Display statistics related to the attribute cache failed."
+    echo " -> $test: TEST-FAIL"
+    exit
+fi
+
+if nfsiostat -d | grep "lookup"
+then
+    echo " -> Display statistics related to directory operations succeeded."
+else
+    echo " -> Display statistics related to directory operations failed."
+    echo " -> $test: TEST-FAIL"
+    exit
+fi
+
+if nfsiostat -h | grep "Usage"
+then
+    echo " -> Show help message succeeded."
+else
+    echo " -> Show help message failed."
+    echo " -> $test: TEST-FAIL"
+    exit
+fi
+
+if nfsiostat -p | grep "page"
+then
+    echo " -> Display statistics related to the page cache succeeded."
+else
+    echo " -> Display statistics related to the page cache failed."
+    echo " -> $test: TEST-FAIL"
+    exit
+fi
+
+
+if nfsiostat -s | grep "ops"
+then
+    echo " -> Sort NFS mount points by ops/second succeeded."
+else
+    echo " -> Sort NFS mount points by ops/second failed."
+    echo " -> $test: TEST-FAIL"
+    exit
+fi
+
+if nfsiostat --version | grep "version"
+then
+    echo " -> $test: TEST-PASS"
+else
+    echo " -> Show version number failed."
+    echo " -> $test: TEST-FAIL"
+fi
diff --git a/tests/Functional.nfs/tests/nfsserver_ps.sh b/tests/Functional.nfs/tests/nfsserver_ps.sh
new file mode 100644
index 0000000..ddb4483
--- /dev/null
+++ b/tests/Functional.nfs/tests/nfsserver_ps.sh
@@ -0,0 +1,96 @@
+#!/bin/sh
+
+#  In the target start nfsserver, and confirm the process condition by command ps.
+
+test="nfsserver_ps"
+
+. ./fuego_board_function_lib.sh
+
+set_init_manager
+
+if [ "$init_manager" = "systemd" ]
+then
+    service_name="nfs-server"
+else
+    service_name="nfsserver"
+fi
+
+nfs_status=$(get_service_status $service_name)
+
+rpcbind_status=$(get_service_status rpcbind)
+
+exec_service_on_target $service_name stop
+exec_service_on_target rpcbind stop
+
+if [ -f /etc/exports ]
+then
+    mv /etc/exports /etc/exports_bak
+fi
+
+touch /etc/exports
+
+restore_target() {
+    if [ -f /etc/exports_bak ]
+    then
+        mv /etc/exports_bak /etc/exports
+    else
+        rm -f /etc/exports
+    fi
+}
+
+exec_service_on_target rpcbind start
+if exec_service_on_target $service_name start
+then
+    echo " -> start of nfsserver succeeded."
+else
+    echo " -> start of nfsserver failed."
+    echo " -> $test: TEST-FAIL"
+    if [ "$rpcbind_status" = "inactive" ]
+    then
+        exec_service_on_target rpcbind stop
+    fi
+    restore_target
+    exit
+fi
+
+sleep 5
+
+if ps aux | grep "[\[]nfsd"
+then
+    echo " -> get the process of nfsd."
+else
+    echo " -> can't get the process of nfsd."
+    echo " -> $test: TEST-FAIL"
+    if [ "$rpcbind_status" = "inactive" ]
+    then
+        exec_service_on_target rpcbind stop
+    fi
+    if [ "$nfs_status" = "inactive" ]
+    then
+        exec_service_on_target $service_name stop
+    fi
+    restore_target
+    exit
+fi
+
+exec_service_on_target rpcbind stop
+exec_service_on_target $service_name stop
+
+sleep 5
+
+if ps aux | grep "[\[]nfsd"
+then
+    echo " -> $test: TEST-FAIL"
+else
+    echo " -> $test: TEST-PASS"
+fi
+restore_target
+if [ "$rpcbind_status" = "active" -o "$rpcbind_status" = "unknown" ]
+then
+    exec_service_on_target rpcbind start
+fi
+
+if [ "$nfs_status" = "active" -o "$nfs_status" = "unknown" ]
+then
+    exec_service_on_target $service_name start
+fi
diff --git a/tests/Functional.nfs/tests/nfsstat.sh b/tests/Functional.nfs/tests/nfsstat.sh
new file mode 100644
index 0000000..b579206
--- /dev/null
+++ b/tests/Functional.nfs/tests/nfsstat.sh
@@ -0,0 +1,32 @@
+#!/bin/sh
+
+#  In the target run the command nfsstat, and display statistics kept about NFS client and server activity.
+#  option : -r, -c, -s
+
+test="nfsstat"
+
+if nfsstat -c | grep "Client"
+then
+    echo " -> Print only client-side statistics succeeded."
+else
+    echo " -> Print only client-side statistics failed."
+    echo " -> $test: TEST-FAIL"
+    exit
+fi
+
+if nfsstat -r | grep "rpc"
+then
+    echo " -> Print only RPC statistics succeeded."
+else
+    echo " -> Print only RPC statistics failed."
+    echo " -> $test: TEST-FAIL"
+    exit
+fi
+
+if nfsstat -s | grep "Server"
+then
+    echo " -> $test: TEST-PASS"
+else
+    echo " -> Print only server-side statistics failed."
+    echo " -> $test: TEST-FAIL"
+fi
-- 
2.17.1




^ permalink raw reply related	[flat|nested] 9+ messages in thread

* Re: [Fuego] [PATCH] ltrace: Add test cases for command ltrace.
  2019-09-04  1:09 ` [Fuego] [PATCH] ltrace: Add test cases for command ltrace Wang Mingyu
@ 2019-09-11 17:28   ` Tim.Bird
  0 siblings, 0 replies; 9+ messages in thread
From: Tim.Bird @ 2019-09-11 17:28 UTC (permalink / raw)
  To: wangmy, fuego

Sorry for the slow response.  I'm traveling at the moment, and my
processes for handling patches while I'm traveling are not good yet.
I hope I can improve these in the near future.

See inline comments below.

> -----Original Message-----
> From: Wang Mingyu
> 
> ltrace is a program that simply runs the specified command until it exits.
> This test set is used to check the ountput syscall/time/count/help of
> command to trace and check if can be saved to file.
> 
> Signed-off-by: Wang Mingyu <wangmy@cn.fujitsu.com>
> ---
>  tests/Functional.ltrace/fuego_test.sh           | 17 +++++++++++++++++
>  tests/Functional.ltrace/ltrace_test.sh          |  4 ++++
>  tests/Functional.ltrace/spec.json               |  6 ++++++
>  tests/Functional.ltrace/tests/ltrace_count.sh   | 15 +++++++++++++++
>  tests/Functional.ltrace/tests/ltrace_help.sh    | 13 +++++++++++++
>  tests/Functional.ltrace/tests/ltrace_output.sh  | 15 +++++++++++++++
>  tests/Functional.ltrace/tests/ltrace_syscall.sh | 15 +++++++++++++++
>  tests/Functional.ltrace/tests/ltrace_time.sh    | 15 +++++++++++++++
>  8 files changed, 100 insertions(+)
>  create mode 100644 tests/Functional.ltrace/fuego_test.sh
>  create mode 100755 tests/Functional.ltrace/ltrace_test.sh
>  create mode 100644 tests/Functional.ltrace/spec.json
>  create mode 100644 tests/Functional.ltrace/tests/ltrace_count.sh
>  create mode 100644 tests/Functional.ltrace/tests/ltrace_help.sh
>  create mode 100644 tests/Functional.ltrace/tests/ltrace_output.sh
>  create mode 100644 tests/Functional.ltrace/tests/ltrace_syscall.sh
>  create mode 100644 tests/Functional.ltrace/tests/ltrace_time.sh
> 
> diff --git a/tests/Functional.ltrace/fuego_test.sh
> b/tests/Functional.ltrace/fuego_test.sh
> new file mode 100644
> index 0000000..ecfc4e7
> --- /dev/null
> +++ b/tests/Functional.ltrace/fuego_test.sh
> @@ -0,0 +1,17 @@
> +function test_pre_check {
> +    assert_has_program ltrace
> +}
> +
> +function test_deploy {
> +    put $TEST_HOME/ltrace_test.sh $BOARD_TESTDIR/fuego.$TESTDIR/
> +    put -r $TEST_HOME/tests $BOARD_TESTDIR/fuego.$TESTDIR/
> +}
> +
> +function test_run {
> +    report "cd $BOARD_TESTDIR/fuego.$TESTDIR;\
> +    ./ltrace_test.sh"
> +}
> +
> +function test_processing {
> +    log_compare "$TESTDIR" "0" "TEST-FAIL" "n"
> +}
> diff --git a/tests/Functional.ltrace/ltrace_test.sh
> b/tests/Functional.ltrace/ltrace_test.sh
> new file mode 100755
> index 0000000..dd5ce37
> --- /dev/null
> +++ b/tests/Functional.ltrace/ltrace_test.sh
> @@ -0,0 +1,4 @@
> +#!/bin/sh
> +for i in tests/*.sh; do
> +    sh $i
> +done
> diff --git a/tests/Functional.ltrace/spec.json
> b/tests/Functional.ltrace/spec.json
> new file mode 100644
> index 0000000..fce7a19
> --- /dev/null
> +++ b/tests/Functional.ltrace/spec.json
> @@ -0,0 +1,6 @@
> +{
> +    "testName": "Functional.ltrace",
> +    "specs": {
> +        "default": {}
> +    }
> +}
> diff --git a/tests/Functional.ltrace/tests/ltrace_count.sh
> b/tests/Functional.ltrace/tests/ltrace_count.sh
> new file mode 100644
> index 0000000..5a277fc
> --- /dev/null
> +++ b/tests/Functional.ltrace/tests/ltrace_count.sh
> @@ -0,0 +1,15 @@
> +#!/bin/sh
> +
> +#  In target, run comannd ltrace to count time and calls.
> +#  option: -c
> +
> +test="count"
> +
> +ltrace -c dd if=/dev/urandom of=/dev/null count=1000 > log 2>&1
> +if cat log | grep "usecs/call"
This can be 'if grep "usecs/call" log', and avoid the use of 'cat' and extra process invocation.

Please do this here, and for the other uses of 'grep' below.

> +then
> +    echo " -> $test: TEST-PASS"
> +else
> +    echo " -> $test: TEST-FAIL"
> +fi
> +rm log
> diff --git a/tests/Functional.ltrace/tests/ltrace_help.sh
> b/tests/Functional.ltrace/tests/ltrace_help.sh
> new file mode 100644
> index 0000000..ea45a7e
> --- /dev/null
> +++ b/tests/Functional.ltrace/tests/ltrace_help.sh
> @@ -0,0 +1,13 @@
> +#!/bin/sh
> +
> +#  In target, run comannd ltrace to display help message.
> +#  option: -h/--help
> +
> +test="help"
> +
> +if ltrace -h | grep [uU]sage
> +then
> +    echo " -> $test: TEST-PASS"
> +else
> +    echo " -> $test: TEST-FAIL"
> +fi
> diff --git a/tests/Functional.ltrace/tests/ltrace_output.sh
> b/tests/Functional.ltrace/tests/ltrace_output.sh
> new file mode 100644
> index 0000000..2d941b0
> --- /dev/null
> +++ b/tests/Functional.ltrace/tests/ltrace_output.sh
> @@ -0,0 +1,15 @@
> +#!/bin/sh
> +
> +#  Write the trace output to the file filename rather than to stderr.
> +#  option: -o/--output
> +
> +test="output"

I would put 'rm log || true' here, to eliminate any
pre-existing 'log' file (and ignore the error if there is no 'log' file).

> +
> +ltrace -o log ls
> +if cat log | grep "+++ exited (status 0) +++"
Please remove the 'cat' here, as described above.

> +then
> +    echo " -> $test: TEST-PASS"
> +else
> +    echo " -> $test: TEST-FAIL"
> +fi
> +rm log
> diff --git a/tests/Functional.ltrace/tests/ltrace_syscall.sh
> b/tests/Functional.ltrace/tests/ltrace_syscall.sh
> new file mode 100644
> index 0000000..34d1dc5
> --- /dev/null
> +++ b/tests/Functional.ltrace/tests/ltrace_syscall.sh
> @@ -0,0 +1,15 @@
> +#!/bin/sh
> +
> +#  In target, run comannd ltrace to display system calls.
> +#  option: -S
> +
> +test="syscall"
> +
> +ltrace -S ls > log 2>&1
> +if cat log | grep "+++ exited (status 0) +++"
Please remove the 'cat' here, as described above.

Also, can you please check that the trace has some piece
of valid data related to syscall tracing here (maybe in addition 
to the check of the final line that you already have).

For example, you could do a grep for SYS_getdents, and that would
show that the -S option worked and syscalls were showing
up in the log.

> +then
> +    echo " -> $test: TEST-PASS"
> +else
> +    echo " -> $test: TEST-FAIL"
> +fi
> +rm log
> diff --git a/tests/Functional.ltrace/tests/ltrace_time.sh
> b/tests/Functional.ltrace/tests/ltrace_time.sh
> new file mode 100644
> index 0000000..fc09108
> --- /dev/null
> +++ b/tests/Functional.ltrace/tests/ltrace_time.sh
> @@ -0,0 +1,15 @@
> +#!/bin/sh
> +
> +#  In target, run comannd ltrace to show the time spent inside each call.
> +#  option: -T
> +
> +test="time"
> +
> +ltrace -T ls > log 2>&1
> +if cat log | grep "<[0-9].[0-9]\{6\}>"
Please avoid use of 'cat', as described above.

> +then
> +    echo " -> $test: TEST-PASS"
> +else
> +    echo " -> $test: TEST-FAIL"
> +fi
> +rm log
> --
> 2.17.1


Thanks.  This looks good.  Please address my comments and resubmit.
 -- Tim

^ permalink raw reply	[flat|nested] 9+ messages in thread

* Re: [Fuego] [PATCH] nfs: Add test cases for nfs.
  2019-09-04  1:09 ` [Fuego] [PATCH] nfs: Add test cases for nfs Wang Mingyu
@ 2019-09-21  1:40   ` Tim.Bird
  0 siblings, 0 replies; 9+ messages in thread
From: Tim.Bird @ 2019-09-21  1:40 UTC (permalink / raw)
  To: wangmy, fuego



> -----Original Message-----
> From: Wang Mingyu
> 
> This test set is used to check service(nfs-mountd/nfs-statd) and
> commands(nfsiostat/nfsserver/nfsstat) of nfs.
> 
> Signed-off-by: Wang Mingyu <wangmy@cn.fujitsu.com>
> ---
>  tests/Functional.nfs/fuego_test.sh          | 22 +++++
>  tests/Functional.nfs/nfs_test.sh            |  4 +
>  tests/Functional.nfs/spec.json              |  7 ++
>  tests/Functional.nfs/tests/nfs-mountd_ps.sh | 69 +++++++++++++++
>  tests/Functional.nfs/tests/nfs-statd_ps.sh  | 50 +++++++++++
>  tests/Functional.nfs/tests/nfsiostat.sh     | 60 +++++++++++++
>  tests/Functional.nfs/tests/nfsserver_ps.sh  | 96 +++++++++++++++++++++
>  tests/Functional.nfs/tests/nfsstat.sh       | 32 +++++++
>  8 files changed, 340 insertions(+)
>  create mode 100644 tests/Functional.nfs/fuego_test.sh
>  create mode 100755 tests/Functional.nfs/nfs_test.sh
>  create mode 100644 tests/Functional.nfs/spec.json
>  create mode 100644 tests/Functional.nfs/tests/nfs-mountd_ps.sh
>  create mode 100644 tests/Functional.nfs/tests/nfs-statd_ps.sh
>  create mode 100644 tests/Functional.nfs/tests/nfsiostat.sh
>  create mode 100644 tests/Functional.nfs/tests/nfsserver_ps.sh
>  create mode 100644 tests/Functional.nfs/tests/nfsstat.sh
> 
> diff --git a/tests/Functional.nfs/fuego_test.sh
> b/tests/Functional.nfs/fuego_test.sh
> new file mode 100644
> index 0000000..624c25f
> --- /dev/null
> +++ b/tests/Functional.nfs/fuego_test.sh
> @@ -0,0 +1,22 @@
> +function test_pre_check {
> +    assert_has_program nfsstat
> +    assert_has_program nfsiostat
> +    assert_has_program rpc.nfsd
> +    assert_has_program rpc.statd
> +    assert_has_program rpc.mountd
> +}
> +
> +function test_deploy {
> +    put $TEST_HOME/nfs_test.sh $BOARD_TESTDIR/fuego.$TESTDIR/
> +    put $FUEGO_CORE/scripts/fuego_board_function_lib.sh
> $BOARD_TESTDIR/fuego.$TESTDIR
> +    put -r $TEST_HOME/tests $BOARD_TESTDIR/fuego.$TESTDIR/
> +}
> +
> +function test_run {
> +    report "cd $BOARD_TESTDIR/fuego.$TESTDIR;\
> +    ./nfs_test.sh"
> +}
> +
> +function test_processing {
> +    log_compare "$TESTDIR" "0" "TEST-FAIL" "n"
> +}
> diff --git a/tests/Functional.nfs/nfs_test.sh
> b/tests/Functional.nfs/nfs_test.sh
> new file mode 100755
> index 0000000..dd5ce37
> --- /dev/null
> +++ b/tests/Functional.nfs/nfs_test.sh
> @@ -0,0 +1,4 @@
> +#!/bin/sh
> +for i in tests/*.sh; do
> +    sh $i
> +done
> diff --git a/tests/Functional.nfs/spec.json b/tests/Functional.nfs/spec.json
> new file mode 100644
> index 0000000..69a241c
> --- /dev/null
> +++ b/tests/Functional.nfs/spec.json
> @@ -0,0 +1,7 @@
> +{
> +    "testName": "Functional.nfs",
> +    "specs": {
> +        "default": {}
> +    }
> +}
> +
> diff --git a/tests/Functional.nfs/tests/nfs-mountd_ps.sh
> b/tests/Functional.nfs/tests/nfs-mountd_ps.sh
> new file mode 100644
> index 0000000..c24345e
> --- /dev/null
> +++ b/tests/Functional.nfs/tests/nfs-mountd_ps.sh
> @@ -0,0 +1,69 @@
> +#!/bin/sh
> +
> +#  In the target start nfs-mountd, and confirm the process condition by
> command ps.
> +
> +test="nfs-mountd_ps"
> +
> +. ./fuego_board_function_lib.sh
> +
> +set_init_manager
> +
> +service_status=$(get_service_status nfs-mountd)
> +exec_service_on_target nfs-mountd stop
> +
> +if [ -f /etc/exports ]
> +then
> +    mv /etc/exports /etc/exports_bak
> +fi
> +
> +touch /etc/exports
> +
> +restore_target() {
> +    if [ -f /etc/exports_bak ]
> +    then
> +        mv /etc/exports_bak /etc/exports
> +    else
> +        rm -f /etc/exports
> +    fi
> +}
> +
> +if exec_service_on_target nfs-mountd start
> +then
> +    echo " -> start of nfs-mountd succeeded."
> +else
> +    echo " -> start of nfs-mountd failed."
> +    echo " -> $test: TEST-FAIL"
> +    restore_target
> +    exit
> +fi
> +
> +sleep 5
> +
> +if ps aux | grep "[/]usr/sbin/rpc.mountd"
> +then
> +    echo " -> get the process of rpc.mountd."
Different wording would be more clear here.
Maybe "rpc.mountd process is running"?

> +else
> +    echo " -> can't get the process of rpc.mountd."
Maybe change to "rpc.mountd process is not running"
> +    echo " -> $test: TEST-FAIL"
> +    if [ "$service_status" = "inactive" ]
> +    then
> +        exec_service_on_target nfs-mountd stop
> +    fi
> +    restore_target
> +    exit
> +fi
> +
> +exec_service_on_target nfs-mountd stop
> +
> +if ps aux | grep "[/]usr/sbin/rpc.mountd"
> +then
> +    echo " -> $test: TEST-FAIL"
> +else
> +    echo " -> $test: TEST-PASS"
> +fi
> +
> +if [ "$service_status" = "active" -o "$service_status" = "unknown"]
> +then
> +    exec_service_on_target nfs-mountd start
> +fi
> +restore_target
> diff --git a/tests/Functional.nfs/tests/nfs-statd_ps.sh
> b/tests/Functional.nfs/tests/nfs-statd_ps.sh
> new file mode 100644
> index 0000000..43dc43b
> --- /dev/null
> +++ b/tests/Functional.nfs/tests/nfs-statd_ps.sh
> @@ -0,0 +1,50 @@
> +#!/bin/sh
> +
> +#  In the target start nfs-statd, and confirm the process condition by
> command ps.
> +
> +test="nfs-statd_ps"
> +
> +. ./fuego_board_function_lib.sh
> +
> +set_init_manager
> +
> +service_status=$(get_service_status nfs-statd)
> +exec_service_on_target nfs-statd stop
> +
> +if exec_service_on_target nfs-statd start
> +then
> +    echo " -> start of nfs-statd succeeded."
> +else
> +    echo " -> start of nfs-statd failed."
> +    echo " -> $test: TEST-FAIL"
> +    exit
> +fi
> +
> +sleep 5
> +
> +if ps aux | grep "[/]usr/sbin/rpc.statd"
> +then
> +    echo " -> get the process of rpc.statd."
same here.  I would like to see a more clear message.

> +else
> +    echo " -> can't get the process of rpc.statd."
> +    echo " -> $test: TEST-FAIL"
> +    if [ "$service_status" = "inactive" ]
> +    then
> +        exec_service_on_target nfs-statd stop
> +    fi
> +    exit
> +fi
> +
> +exec_service_on_target nfs-statd stop
> +
> +if ps aux | grep "[/]usr/sbin/rpc.statd"
> +then
> +    echo " -> $test: TEST-FAIL"
> +else
> +    echo " -> $test: TEST-PASS"
> +fi
> +
> +if [ "$service_status" = "active" -o "$service_status" = "unknown" ]
> +then
> +    exec_service_on_target nfs-statd start
> +fi
> diff --git a/tests/Functional.nfs/tests/nfsiostat.sh
> b/tests/Functional.nfs/tests/nfsiostat.sh
> new file mode 100644
> index 0000000..c1a683d
> --- /dev/null
> +++ b/tests/Functional.nfs/tests/nfsiostat.sh
> @@ -0,0 +1,60 @@
> +#!/bin/sh
> +
> +#  In the target run the command nfiosstat, and displays NFS client per-
> mount statisitics..
> +#  option : -a, -d, -h, -p, -s, --version
> +
> +test="nfsiostat"
> +
> +if nfsiostat -a | grep "attribute cache"
> +then
> +    echo " -> Display statistics related to the attribute cache succeeded."
> +else
> +    echo " -> Display statistics related to the attribute cache failed."
> +    echo " -> $test: TEST-FAIL"
> +    exit
> +fi
> +
> +if nfsiostat -d | grep "lookup"
> +then
> +    echo " -> Display statistics related to directory operations succeeded."
> +else
> +    echo " -> Display statistics related to directory operations failed."
> +    echo " -> $test: TEST-FAIL"
> +    exit
> +fi
> +
> +if nfsiostat -h | grep "Usage"
> +then
> +    echo " -> Show help message succeeded."
> +else
> +    echo " -> Show help message failed."
> +    echo " -> $test: TEST-FAIL"
> +    exit
> +fi
> +
> +if nfsiostat -p | grep "page"
> +then
> +    echo " -> Display statistics related to the page cache succeeded."
> +else
> +    echo " -> Display statistics related to the page cache failed."
> +    echo " -> $test: TEST-FAIL"
> +    exit
> +fi
> +
> +
> +if nfsiostat -s | grep "ops"
> +then
> +    echo " -> Sort NFS mount points by ops/second succeeded."
> +else
> +    echo " -> Sort NFS mount points by ops/second failed."
> +    echo " -> $test: TEST-FAIL"
> +    exit
> +fi
> +
> +if nfsiostat --version | grep "version"
> +then
> +    echo " -> $test: TEST-PASS"
> +else
> +    echo " -> Show version number failed."
> +    echo " -> $test: TEST-FAIL"
> +fi
> diff --git a/tests/Functional.nfs/tests/nfsserver_ps.sh
> b/tests/Functional.nfs/tests/nfsserver_ps.sh
> new file mode 100644
> index 0000000..ddb4483
> --- /dev/null
> +++ b/tests/Functional.nfs/tests/nfsserver_ps.sh
> @@ -0,0 +1,96 @@
> +#!/bin/sh
> +
> +#  In the target start nfsserver, and confirm the process condition by
> command ps.
> +
> +test="nfsserver_ps"
> +
> +. ./fuego_board_function_lib.sh
> +
> +set_init_manager
> +
> +if [ "$init_manager" = "systemd" ]
> +then
> +    service_name="nfs-server"
> +else
> +    service_name="nfsserver"
> +fi
> +
> +nfs_status=$(get_service_status $service_name)
> +
> +rpcbind_status=$(get_service_status rpcbind)
> +
> +exec_service_on_target $service_name stop
> +exec_service_on_target rpcbind stop
> +
> +if [ -f /etc/exports ]
> +then
> +    mv /etc/exports /etc/exports_bak
> +fi
> +
> +touch /etc/exports
> +
> +restore_target() {
> +    if [ -f /etc/exports_bak ]
> +    then
> +        mv /etc/exports_bak /etc/exports
> +    else
> +        rm -f /etc/exports
> +    fi
> +}
> +
> +exec_service_on_target rpcbind start
> +if exec_service_on_target $service_name start
> +then
> +    echo " -> start of nfsserver succeeded."
> +else
> +    echo " -> start of nfsserver failed."
> +    echo " -> $test: TEST-FAIL"
> +    if [ "$rpcbind_status" = "inactive" ]
> +    then
> +        exec_service_on_target rpcbind stop
> +    fi
> +    restore_target
> +    exit
> +fi
> +
> +sleep 5
> +
> +if ps aux | grep "[\[]nfsd"
> +then
> +    echo " -> get the process of nfsd."
> +else
> +    echo " -> can't get the process of nfsd."
> +    echo " -> $test: TEST-FAIL"
> +    if [ "$rpcbind_status" = "inactive" ]
> +    then
> +        exec_service_on_target rpcbind stop
> +    fi
> +    if [ "$nfs_status" = "inactive" ]
> +    then
> +        exec_service_on_target $service_name stop
> +    fi
> +    restore_target
> +    exit
> +fi
> +
> +exec_service_on_target rpcbind stop
> +exec_service_on_target $service_name stop
> +
> +sleep 5
> +
> +if ps aux | grep "[\[]nfsd"
> +then
> +    echo " -> $test: TEST-FAIL"
> +else
> +    echo " -> $test: TEST-PASS"
> +fi
> +restore_target
> +if [ "$rpcbind_status" = "active" -o "$rpcbind_status" = "unknown" ]
> +then
> +    exec_service_on_target rpcbind start
> +fi
> +
> +if [ "$nfs_status" = "active" -o "$nfs_status" = "unknown" ]
> +then
> +    exec_service_on_target $service_name start
> +fi
> diff --git a/tests/Functional.nfs/tests/nfsstat.sh
> b/tests/Functional.nfs/tests/nfsstat.sh
> new file mode 100644
> index 0000000..b579206
> --- /dev/null
> +++ b/tests/Functional.nfs/tests/nfsstat.sh
> @@ -0,0 +1,32 @@
> +#!/bin/sh
> +
> +#  In the target run the command nfsstat, and display statistics kept about
> NFS client and server activity.
line length too long.

> +#  option : -r, -c, -s
> +
> +test="nfsstat"
> +
> +if nfsstat -c | grep "Client"
> +then
> +    echo " -> Print only client-side statistics succeeded."
> +else
> +    echo " -> Print only client-side statistics failed."
> +    echo " -> $test: TEST-FAIL"
> +    exit
> +fi
> +
> +if nfsstat -r | grep "rpc"
> +then
> +    echo " -> Print only RPC statistics succeeded."
> +else
> +    echo " -> Print only RPC statistics failed."
> +    echo " -> $test: TEST-FAIL"
> +    exit
> +fi
> +
> +if nfsstat -s | grep "Server"
> +then
> +    echo " -> $test: TEST-PASS"
> +else
> +    echo " -> Print only server-side statistics failed."
> +    echo " -> $test: TEST-FAIL"
> +fi
> --
> 2.17.1


This looks mostly OK.  If you don't mind, I'm going to change a few
of the echo lines to wording that I think is more clear, and maybe
wrap some long lines of comments.

Applied to the 'master' branch.

Thanks,
 -- Tim


^ permalink raw reply	[flat|nested] 9+ messages in thread

* Re: [Fuego] [PATCH] Optimize the code of assert_has_program.
  2019-09-04  1:09 [Fuego] [PATCH] Optimize the code of assert_has_program Wang Mingyu
  2019-09-04  1:09 ` [Fuego] [PATCH] ltrace: Add test cases for command ltrace Wang Mingyu
  2019-09-04  1:09 ` [Fuego] [PATCH] nfs: Add test cases for nfs Wang Mingyu
@ 2019-09-21  2:24 ` Tim.Bird
  2019-10-16  5:52   ` Wang, Mingyu
  2 siblings, 1 reply; 9+ messages in thread
From: Tim.Bird @ 2019-09-21  2:24 UTC (permalink / raw)
  To: wangmy, fuego

I'm not sure this gives the same results at the original code.
See my comments inline below.

Also, combining multiple programs into a single 'assert_has_program'
lines will make it a bit more difficult to implement a cache system
for programs detected on the board.

I will have to think about this one.

> -----Original Message-----
> From: Wang Mingyu on Tuesday, September 03, 2019 3:09 PM
> 
> It is faster to check the prgoram or file on the target.
prgoram -> program

> 
> Usage:
> before:
>     assert_has_program AAA
>     assert_has_program BBB
> 
> after:
>     assert_has_program "AAA BBB"
>     assert_has_program "AAA BBB" SEARCH_PATH
> 
> Note: SEARCH_PATH is optional.

Can you explain when SEARCH_PATH is needed?

> 
> Signed-off-by: Wang Mingyu <wangmy@cn.fujitsu.com>
> ---
>  scripts/functions.sh  | 65
> +++++++++++++++++++++++++++++++++++++++----
>  scripts/need_check.sh | 11 ++------
>  2 files changed, 61 insertions(+), 15 deletions(-)
> 
> diff --git a/scripts/functions.sh b/scripts/functions.sh
> index 0fa80b8..3aea0c8 100755
> --- a/scripts/functions.sh
> +++ b/scripts/functions.sh
> @@ -1010,6 +1010,57 @@ function is_on_target_path {
>      is_on_target $1 $2 $TARGET_PATH
>  }
> 
> +# check for a program or file on the target, and set a variable if it's present
> +# $1 - file, dir or program on target
> +# $2 is the path of target to search the program/file
> +# $3 - tmpfile to save the detect result
> +function set_cmd_str {
In general, I like this approach of executing a command on the
target that does the search loop.

> +   tmpfile=$3
> +   cmd_str="touch $tmpfile
> +         # split $1 on whitespace, without file globbing
> +         for prg in \$(echo $1 | tr \" \" \"\\n\") ; do
> +             # split search path on colon
> +             for d in \$(echo $2 | tr \":\" \"\\n\") ; do
> +                 # execute a command on the target to detect \$d/\$prg
> +                 if [ -z \"\$(cat $tmpfile)\" -a -e \"\$d/\$prg\" ]
> +                 then
> +                     echo \"\$d/\$prg\" >$tmpfile ;break;
> +                 fi
> +             done
> +             if [ ! -s $tmpfile ]
> +             then
> +                 find / -name \"\$prg\" | head -n 1 >$tmpfile
> +             fi
This will detect the program anywhere in the filesystem, not just on the PATH.
That changes the behavior of assert_has_program, which currently only
looks on the target's PATH.

> +             if [ ! -s $tmpfile ]
> +             then
> +                 echo \"\$prg\" >$tmpfile ; break;
This would put the program name into tmpfile, which means that even
if the program was not detected, tmpfile will have a non-empty result.
I don't understand this.

> +             else
> +                 > $tmpfile
I also don't understand why this is needed.  The file is always touched
above, so it exists as an empty file.  Why does it need to have
the empty redirection into it?

> +             fi
> +         done"
> +}
> +
> +# check for a program or file on the target, and set a variable if it's present
> +# $1 - file, dir or program on target
> +# $2 - variable to set during the build
> +# $3 is the path of target to search the program/file (optional, default:
> $PATH)
> +function assert_on_target {
> +    local TARGET_PATH=${3}
> +    if [ -z "$TARGET_PATH" ]; then
> +       TARGET_PATH=$(cmd "echo \$PATH")
> +    fi
> +
> +    tmpfile=$(mktemp /tmp/found_loc.XXXXXX)
> +    set_cmd_str "$1" $TARGET_PATH $tmpfile
> +    cmd "$cmd_str"
> +    get $tmpfile $tmpfile
> +    if [ -s $tmpfile ] ; then
> +        export $2=$(cat $tmpfile)
> +    fi
> +    cmd "rm $tmpfile"
> +    rm -f $tmpfile # -f for tests running on the host
> +}
> +
>  # check for a library on the SDK, and set a variable if it's present
>  # $1 - the file (library) we want to search for in the SDK
>  # $2 - variable to set the location (if the file is found)
> @@ -1036,13 +1087,15 @@ function is_on_sdk {
> 
>  # check for a program or file on the target, and send message if the program
> or file is missing
>  # $1 has the program that is required on the target board
> -# this has the side effect of defining PROGRAM_$1 (uppercased)
> -# with the value as the directory where $1 is found on the board.
> +# $2 is the path of target to search the program/file (optional, default:
> $PATH)
>  function assert_has_program {
> -   upName=${1^^}
> -   progVar=PROGRAM_${upName//[-,.]/_}
> -   is_on_target_path $1 ${progVar}
> -   assert_define ${progVar} "Missing '$1' program on target board"
> +   assert_on_target "$1" prgName $2
> +   if [ -n "$prgName" ]
> +   then
> +       upName=${prgName^^}
> +       progVar=PROGRAM_${upName//[-,.]/_}
> +       assert_define ${progVar} "Missing '$prgName' program on target board"
> +   fi
>  }
> 
>  # check for a module on the target, and abort if it is missing
> diff --git a/scripts/need_check.sh b/scripts/need_check.sh
> index c9bbb75..9bb0098 100755
> --- a/scripts/need_check.sh
> +++ b/scripts/need_check.sh
> @@ -319,18 +319,11 @@ function check_root {
>  # check if those specified commands exist on board
>  # $1 has single string with a list of command entries to check for
>  function check_program {
> -  # split $1 on whitespace, without file globbing
> -  set -f
> -  arg_array=($1)
> -  set +f
> -
> -  for prg in "${arg_array[@]}" ; do
> -    is_on_target_path $prg prg_path
> -    if [ -z "$prg_path" ] ; then
> +    assert_on_target "$1" prg
> +    if [ -n "$prg" ] ; then
>        echo -e "\n\nABORTED: Expected command \"$prg\" on the target, but
> it's not there!"
>        return 1
>      fi
> -  done
> 
>    # return OK if all necessary commands exist on the target
>    return 0
> --
> 2.17.1

I'm not sure this does the same thing as the original assert_has_program.

I can't tell what happens if I provide the name of a file which isn't on
the path, but is in the filesystem, or which isn't in the filesystem at all.
Did you test for these cases?
 -- Tim


^ permalink raw reply	[flat|nested] 9+ messages in thread

* Re: [Fuego] [PATCH] Optimize the code of assert_has_program.
  2019-09-21  2:24 ` [Fuego] [PATCH] Optimize the code of assert_has_program Tim.Bird
@ 2019-10-16  5:52   ` Wang, Mingyu
  2019-10-18  4:46     ` Tim.Bird
  0 siblings, 1 reply; 9+ messages in thread
From: Wang, Mingyu @ 2019-10-16  5:52 UTC (permalink / raw)
  To: fuego

Hi Tim,

>> Usage:
>> before:
> >    assert_has_program AAA
> >    assert_has_program BBB
>> 
> >after:
> >    assert_has_program "AAA BBB"
> >    assert_has_program "AAA BBB" SEARCH_PATH
>> 
> >Note: SEARCH_PATH is optional.
>Can you explain when SEARCH_PATH is needed?

It is not necessary.
I see that the original is_on_target can search in the specified path, so I added SEARCH_PATH here.
If need to do the same thing with the original assert_has_program, this variable can be deleted.


>> +             if [ ! -s $tmpfile ]
>> +             then
>> +                 find / -name \"\$prg\" | head -n 1 >$tmpfile
>> +             fi
>This will detect the program anywhere in the filesystem, not just on the PATH.
>That changes the behavior of assert_has_program, which currently only looks on the target's PATH.

This code is still used to consider the user-specified path.
If need to do the same thing with the original assert_has_program, this code can be deleted.

>> +             if [ ! -s $tmpfile ]
>> +             then
> >+                 echo \"\$prg\" >$tmpfile ; break;
>This would put the program name into tmpfile, which means that even if the program was not detected, tmpfile will have a non-empty result.
>I don't understand this.
The program was not detected will be saved into tmpfile.
And assert_on_target will get the program and transform to assert_has_program to show  an error  message.


>> +             else
> >+                 > $tmpfile
>I also don't understand why this is needed.  The file is always touched above, so it exists as an empty file.  Why does it need to have the empty redirection into it?
Consider the case where assert_has_program specifies multiple programs at the same time. 

>I can't tell what happens if I provide the name of a file which isn't on the path, but is in the filesystem, or which isn't in the filesystem at all.
>Did you test for these cases?
I tested a variety of situations, including specifying multiple programs at the same time。
And existing or non-existent  program  is also tested.

When I designed assert_has_program, I considered the existing is_on_target and is_on_target_path and wanted to be as compatible as possible with them so that they could be replaced in the future.

best regards!



-----Original Message-----
From: Tim.Bird@sony.com [mailto:Tim.Bird@sony.com] 
Sent: Saturday, September 21, 2019 10:25 AM
To: Wang, Mingyu/王 鸣瑜 <wangmy@cn.fujitsu.com>; fuego@lists.linuxfoundation.org
Subject: RE: [Fuego] [PATCH] Optimize the code of assert_has_program.

I'm not sure this gives the same results at the original code.
See my comments inline below.

Also, combining multiple programs into a single 'assert_has_program'
lines will make it a bit more difficult to implement a cache system for programs detected on the board.

I will have to think about this one.

> -----Original Message-----
> From: Wang Mingyu on Tuesday, September 03, 2019 3:09 PM
> 
> It is faster to check the prgoram or file on the target.
prgoram -> program

> 
> Usage:
> before:
>     assert_has_program AAA
>     assert_has_program BBB
> 
> after:
>     assert_has_program "AAA BBB"
>     assert_has_program "AAA BBB" SEARCH_PATH
> 
> Note: SEARCH_PATH is optional.

Can you explain when SEARCH_PATH is needed?

> 
> Signed-off-by: Wang Mingyu <wangmy@cn.fujitsu.com>
> ---
>  scripts/functions.sh  | 65
> +++++++++++++++++++++++++++++++++++++++----
>  scripts/need_check.sh | 11 ++------
>  2 files changed, 61 insertions(+), 15 deletions(-)
> 
> diff --git a/scripts/functions.sh b/scripts/functions.sh index 
> 0fa80b8..3aea0c8 100755
> --- a/scripts/functions.sh
> +++ b/scripts/functions.sh
> @@ -1010,6 +1010,57 @@ function is_on_target_path {
>      is_on_target $1 $2 $TARGET_PATH
>  }
> 
> +# check for a program or file on the target, and set a variable if 
> +it's present # $1 - file, dir or program on target # $2 is the path 
> +of target to search the program/file # $3 - tmpfile to save the 
> +detect result function set_cmd_str {
In general, I like this approach of executing a command on the target that does the search loop.

> +   tmpfile=$3
> +   cmd_str="touch $tmpfile
> +         # split $1 on whitespace, without file globbing
> +         for prg in \$(echo $1 | tr \" \" \"\\n\") ; do
> +             # split search path on colon
> +             for d in \$(echo $2 | tr \":\" \"\\n\") ; do
> +                 # execute a command on the target to detect \$d/\$prg
> +                 if [ -z \"\$(cat $tmpfile)\" -a -e \"\$d/\$prg\" ]
> +                 then
> +                     echo \"\$d/\$prg\" >$tmpfile ;break;
> +                 fi
> +             done
> +             if [ ! -s $tmpfile ]
> +             then
> +                 find / -name \"\$prg\" | head -n 1 >$tmpfile
> +             fi
This will detect the program anywhere in the filesystem, not just on the PATH.
That changes the behavior of assert_has_program, which currently only looks on the target's PATH.

> +             if [ ! -s $tmpfile ]
> +             then
> +                 echo \"\$prg\" >$tmpfile ; break;
This would put the program name into tmpfile, which means that even if the program was not detected, tmpfile will have a non-empty result.
I don't understand this.

> +             else
> +                 > $tmpfile
I also don't understand why this is needed.  The file is always touched above, so it exists as an empty file.  Why does it need to have the empty redirection into it?

> +             fi
> +         done"
> +}
> +
> +# check for a program or file on the target, and set a variable if 
> +it's present # $1 - file, dir or program on target # $2 - variable to 
> +set during the build # $3 is the path of target to search the 
> +program/file (optional, default:
> $PATH)
> +function assert_on_target {
> +    local TARGET_PATH=${3}
> +    if [ -z "$TARGET_PATH" ]; then
> +       TARGET_PATH=$(cmd "echo \$PATH")
> +    fi
> +
> +    tmpfile=$(mktemp /tmp/found_loc.XXXXXX)
> +    set_cmd_str "$1" $TARGET_PATH $tmpfile
> +    cmd "$cmd_str"
> +    get $tmpfile $tmpfile
> +    if [ -s $tmpfile ] ; then
> +        export $2=$(cat $tmpfile)
> +    fi
> +    cmd "rm $tmpfile"
> +    rm -f $tmpfile # -f for tests running on the host }
> +
>  # check for a library on the SDK, and set a variable if it's present  
> # $1 - the file (library) we want to search for in the SDK  # $2 - 
> variable to set the location (if the file is found) @@ -1036,13 
> +1087,15 @@ function is_on_sdk {
> 
>  # check for a program or file on the target, and send message if the 
> program or file is missing  # $1 has the program that is required on 
> the target board -# this has the side effect of defining PROGRAM_$1 
> (uppercased) -# with the value as the directory where $1 is found on 
> the board.
> +# $2 is the path of target to search the program/file (optional, default:
> $PATH)
>  function assert_has_program {
> -   upName=${1^^}
> -   progVar=PROGRAM_${upName//[-,.]/_}
> -   is_on_target_path $1 ${progVar}
> -   assert_define ${progVar} "Missing '$1' program on target board"
> +   assert_on_target "$1" prgName $2
> +   if [ -n "$prgName" ]
> +   then
> +       upName=${prgName^^}
> +       progVar=PROGRAM_${upName//[-,.]/_}
> +       assert_define ${progVar} "Missing '$prgName' program on target board"
> +   fi
>  }
> 
>  # check for a module on the target, and abort if it is missing diff 
> --git a/scripts/need_check.sh b/scripts/need_check.sh index 
> c9bbb75..9bb0098 100755
> --- a/scripts/need_check.sh
> +++ b/scripts/need_check.sh
> @@ -319,18 +319,11 @@ function check_root {  # check if those 
> specified commands exist on board  # $1 has single string with a list 
> of command entries to check for  function check_program {
> -  # split $1 on whitespace, without file globbing
> -  set -f
> -  arg_array=($1)
> -  set +f
> -
> -  for prg in "${arg_array[@]}" ; do
> -    is_on_target_path $prg prg_path
> -    if [ -z "$prg_path" ] ; then
> +    assert_on_target "$1" prg
> +    if [ -n "$prg" ] ; then
>        echo -e "\n\nABORTED: Expected command \"$prg\" on the target, 
> but it's not there!"
>        return 1
>      fi
> -  done
> 
>    # return OK if all necessary commands exist on the target
>    return 0
> --
> 2.17.1

I'm not sure this does the same thing as the original assert_has_program.

I can't tell what happens if I provide the name of a file which isn't on the path, but is in the filesystem, or which isn't in the filesystem at all.
Did you test for these cases?
 -- Tim






^ permalink raw reply	[flat|nested] 9+ messages in thread

* Re: [Fuego] [PATCH] Optimize the code of assert_has_program.
  2019-10-16  5:52   ` Wang, Mingyu
@ 2019-10-18  4:46     ` Tim.Bird
  2019-10-21  6:47       ` Wang, Mingyu
  0 siblings, 1 reply; 9+ messages in thread
From: Tim.Bird @ 2019-10-18  4:46 UTC (permalink / raw)
  To: wangmy, fuego

The TL;DR version:
There's a  new much faster version of assert_has_program() in fuego-core,
in the master branch. Please try it out.

Ok - now the longer version...

I have re-written the assert_has_program code in the fuego core
so that this patch no longer applies.  Sorry about that.

But I'd like to discuss my solution to this problem, and the roadmap
for what I've implemented so far, and maybe get some feedback
on it before going further with it.

I modified assert_has_program to call a new routine:
check_has_program, that uses the command 'command -v'
on the target to find programs on the PATH.  This is a POSIX-compatible
command, which is built in to all POSIX shells.  I tested with
busybox ash, dash and bash.

The busybox version of 'command -v' does not give the full path, but it
does give a value if the  command is on the path, which is sufficient for
assert_has_program.

This is much faster than the old method of searching through the path
using a loop on the host.  Instead of many invocations of 'cmd' per item being
checked, there is only one.

Also, I have implemented a dependency cache feature.  It is possible to 
run a program once, after provisioning the board, to accumulate the
program installation status for programs required by all tests.  The data
for this is placed in variables in the stored variable file at:
/fuego-rw/board/<board>.vars

All these program variables become part of the prolog.sh file for a test during
overlay generation, and they can be tested very quickly, without having
to communicate with the target board.  This takes the cost of doing a single
assert_has_program from many seconds (the original cost) to 
under 3 seconds (using 'command -v', when the data is not in cache) to
under .1 second, if the data is in cache.

This introduces an issue, however: the dependency cache needs
to be cleared and re-populated when the board is provisioned, so that
stale data is not used for tests run after the board is re-installed.

This adds an extra step to the CI loop.  By default, if you never populate the
dependency cache by running the new program (populate_board_cache.sh),
then fuego core will use 'command -v' for each assert_has_program in a test's
test_pre_check() function.   This means the new system should be completely
backward compatible with the old system.  Without the cache, test_pre_check
with multiple calls to assert_has_program will still take over 10 seconds.
However, if populate_board_cache.sh is run,
then the dependency checks runs very quickly, for all tests.  However, executing this
script after installing a board is now required in order to avoid using stale cache
data.  It should only need to be run once per after the board is re-provisioned.
This is something that seems like it might be error-prone, and might need
some additional support (in the way of messages or other help notices) to make
sure that when people set up their CI loop with Fuego, they include a call
this this script.  I'm still thinking about the exact method of invoking this
whether through an external script, as it is now, or via a special "action"
script implemented similar to a Fuego test.

Note that I'm also looking into re-factoring the pre_test functionality
to remove or consolidate pre-test operations on the board, to save
time and reduce test overhead.

This system could be improved further by supporting multiple arguments to 
assert_has_program (and check_program), and implementing the loop
over them on the target, as Mingyu did in this patch.  I haven't had time
to go back and refactor this initial implementation to do that.  Theoretically,
this could result in a check for multiple programs only requiring a single
call to 'cmd' to communicate with the target, which would speed things
up (in the non-cache case) even more.  I’m considering writing a little
function as part of need_check.sh, which would do all the data accumulation
for all dependencies listed in a test with a single communication with the
target.  This would use a somewhat complicated shell snippet to gather all
the data at once.  The downside is that it would be a bit complicated.
The upside would be that there would be no need to maintain the
dependency cache in order to have correct operation.

Let me know what you think about this new system.
Please try it out and make sure that nothing breaks in your tests.

Finally - this dependency cache feature actually has a dual purpose.
I've been working on implementing a remote testing feature for Fuego 
using fserver.  Likely, the server will eventually support adding meta-data
information (including supported hardware, board features, and installed
memory and programs) for a board, so that a remote scheduler can select
a board for a test based on the board's attributes.  That feature is still a ways
off in terms of implementation.  But it's on the roadmap, and may help
explain why I'd like to gather this dependency data (as one element of
that board information.)

Regards,
 -- Tim

> -----Original Message-----
> From: Wang, Mingyu on  Tuesday, October 15, 2019 7:52 PM
> To: fuego@lists.linuxfoundation.org
> Subject: Re: [Fuego] [PATCH] Optimize the code of assert_has_program.
> 
> Hi Tim,
> 
> >> Usage:
> >> before:
> > >    assert_has_program AAA
> > >    assert_has_program BBB
> >>
> > >after:
> > >    assert_has_program "AAA BBB"
> > >    assert_has_program "AAA BBB" SEARCH_PATH
> >>
> > >Note: SEARCH_PATH is optional.
> >Can you explain when SEARCH_PATH is needed?
> 
> It is not necessary.
> I see that the original is_on_target can search in the specified path, so I
> added SEARCH_PATH here.
> If need to do the same thing with the original assert_has_program, this
> variable can be deleted.
> 
> 
> >> +             if [ ! -s $tmpfile ]
> >> +             then
> >> +                 find / -name \"\$prg\" | head -n 1 >$tmpfile
> >> +             fi
> >This will detect the program anywhere in the filesystem, not just on the
> PATH.
> >That changes the behavior of assert_has_program, which currently only
> looks on the target's PATH.
> 
> This code is still used to consider the user-specified path.
> If need to do the same thing with the original assert_has_program, this code
> can be deleted.
> 
> >> +             if [ ! -s $tmpfile ]
> >> +             then
> > >+                 echo \"\$prg\" >$tmpfile ; break;
> >This would put the program name into tmpfile, which means that even if
> the program was not detected, tmpfile will have a non-empty result.
> >I don't understand this.
> The program was not detected will be saved into tmpfile.
> And assert_on_target will get the program and transform to
> assert_has_program to show  an error  message.
> 
> 
> >> +             else
> > >+                 > $tmpfile
> >I also don't understand why this is needed.  The file is always touched
> above, so it exists as an empty file.  Why does it need to have the empty
> redirection into it?
> Consider the case where assert_has_program specifies multiple programs at
> the same time.
> 
> >I can't tell what happens if I provide the name of a file which isn't on the
> path, but is in the filesystem, or which isn't in the filesystem at all.
> >Did you test for these cases?
> I tested a variety of situations, including specifying multiple programs at the
> same time。
> And existing or non-existent  program  is also tested.
> 
> When I designed assert_has_program, I considered the existing is_on_target
> and is_on_target_path and wanted to be as compatible as possible with
> them so that they could be replaced in the future.
> 
> best regards!
> 
> 
> 
> -----Original Message-----
> From: Tim.Bird@sony.com [mailto:Tim.Bird@sony.com]
> Sent: Saturday, September 21, 2019 10:25 AM
> To: Wang, Mingyu/王 鸣瑜 <wangmy@cn.fujitsu.com>;
> fuego@lists.linuxfoundation.org
> Subject: RE: [Fuego] [PATCH] Optimize the code of assert_has_program.
> 
> I'm not sure this gives the same results at the original code.
> See my comments inline below.
> 
> Also, combining multiple programs into a single 'assert_has_program'
> lines will make it a bit more difficult to implement a cache system for
> programs detected on the board.
> 
> I will have to think about this one.
> 
> > -----Original Message-----
> > From: Wang Mingyu on Tuesday, September 03, 2019 3:09 PM
> >
> > It is faster to check the prgoram or file on the target.
> prgoram -> program
> 
> >
> > Usage:
> > before:
> >     assert_has_program AAA
> >     assert_has_program BBB
> >
> > after:
> >     assert_has_program "AAA BBB"
> >     assert_has_program "AAA BBB" SEARCH_PATH
> >
> > Note: SEARCH_PATH is optional.
> 
> Can you explain when SEARCH_PATH is needed?
> 
> >
> > Signed-off-by: Wang Mingyu <wangmy@cn.fujitsu.com>
> > ---
> >  scripts/functions.sh  | 65
> > +++++++++++++++++++++++++++++++++++++++----
> >  scripts/need_check.sh | 11 ++------
> >  2 files changed, 61 insertions(+), 15 deletions(-)
> >
> > diff --git a/scripts/functions.sh b/scripts/functions.sh index
> > 0fa80b8..3aea0c8 100755
> > --- a/scripts/functions.sh
> > +++ b/scripts/functions.sh
> > @@ -1010,6 +1010,57 @@ function is_on_target_path {
> >      is_on_target $1 $2 $TARGET_PATH
> >  }
> >
> > +# check for a program or file on the target, and set a variable if
> > +it's present # $1 - file, dir or program on target # $2 is the path
> > +of target to search the program/file # $3 - tmpfile to save the
> > +detect result function set_cmd_str {
> In general, I like this approach of executing a command on the target that
> does the search loop.
> 
> > +   tmpfile=$3
> > +   cmd_str="touch $tmpfile
> > +         # split $1 on whitespace, without file globbing
> > +         for prg in \$(echo $1 | tr \" \" \"\\n\") ; do
> > +             # split search path on colon
> > +             for d in \$(echo $2 | tr \":\" \"\\n\") ; do
> > +                 # execute a command on the target to detect \$d/\$prg
> > +                 if [ -z \"\$(cat $tmpfile)\" -a -e \"\$d/\$prg\" ]
> > +                 then
> > +                     echo \"\$d/\$prg\" >$tmpfile ;break;
> > +                 fi
> > +             done
> > +             if [ ! -s $tmpfile ]
> > +             then
> > +                 find / -name \"\$prg\" | head -n 1 >$tmpfile
> > +             fi
> This will detect the program anywhere in the filesystem, not just on the
> PATH.
> That changes the behavior of assert_has_program, which currently only
> looks on the target's PATH.
> 
> > +             if [ ! -s $tmpfile ]
> > +             then
> > +                 echo \"\$prg\" >$tmpfile ; break;
> This would put the program name into tmpfile, which means that even if the
> program was not detected, tmpfile will have a non-empty result.
> I don't understand this.
> 
> > +             else
> > +                 > $tmpfile
> I also don't understand why this is needed.  The file is always touched above,
> so it exists as an empty file.  Why does it need to have the empty redirection
> into it?
> 
> > +             fi
> > +         done"
> > +}
> > +
> > +# check for a program or file on the target, and set a variable if
> > +it's present # $1 - file, dir or program on target # $2 - variable to
> > +set during the build # $3 is the path of target to search the
> > +program/file (optional, default:
> > $PATH)
> > +function assert_on_target {
> > +    local TARGET_PATH=${3}
> > +    if [ -z "$TARGET_PATH" ]; then
> > +       TARGET_PATH=$(cmd "echo \$PATH")
> > +    fi
> > +
> > +    tmpfile=$(mktemp /tmp/found_loc.XXXXXX)
> > +    set_cmd_str "$1" $TARGET_PATH $tmpfile
> > +    cmd "$cmd_str"
> > +    get $tmpfile $tmpfile
> > +    if [ -s $tmpfile ] ; then
> > +        export $2=$(cat $tmpfile)
> > +    fi
> > +    cmd "rm $tmpfile"
> > +    rm -f $tmpfile # -f for tests running on the host }
> > +
> >  # check for a library on the SDK, and set a variable if it's present
> > # $1 - the file (library) we want to search for in the SDK  # $2 -
> > variable to set the location (if the file is found) @@ -1036,13
> > +1087,15 @@ function is_on_sdk {
> >
> >  # check for a program or file on the target, and send message if the
> > program or file is missing  # $1 has the program that is required on
> > the target board -# this has the side effect of defining PROGRAM_$1
> > (uppercased) -# with the value as the directory where $1 is found on
> > the board.
> > +# $2 is the path of target to search the program/file (optional, default:
> > $PATH)
> >  function assert_has_program {
> > -   upName=${1^^}
> > -   progVar=PROGRAM_${upName//[-,.]/_}
> > -   is_on_target_path $1 ${progVar}
> > -   assert_define ${progVar} "Missing '$1' program on target board"
> > +   assert_on_target "$1" prgName $2
> > +   if [ -n "$prgName" ]
> > +   then
> > +       upName=${prgName^^}
> > +       progVar=PROGRAM_${upName//[-,.]/_}
> > +       assert_define ${progVar} "Missing '$prgName' program on target
> board"
> > +   fi
> >  }
> >
> >  # check for a module on the target, and abort if it is missing diff
> > --git a/scripts/need_check.sh b/scripts/need_check.sh index
> > c9bbb75..9bb0098 100755
> > --- a/scripts/need_check.sh
> > +++ b/scripts/need_check.sh
> > @@ -319,18 +319,11 @@ function check_root {  # check if those
> > specified commands exist on board  # $1 has single string with a list
> > of command entries to check for  function check_program {
> > -  # split $1 on whitespace, without file globbing
> > -  set -f
> > -  arg_array=($1)
> > -  set +f
> > -
> > -  for prg in "${arg_array[@]}" ; do
> > -    is_on_target_path $prg prg_path
> > -    if [ -z "$prg_path" ] ; then
> > +    assert_on_target "$1" prg
> > +    if [ -n "$prg" ] ; then
> >        echo -e "\n\nABORTED: Expected command \"$prg\" on the target,
> > but it's not there!"
> >        return 1
> >      fi
> > -  done
> >
> >    # return OK if all necessary commands exist on the target
> >    return 0
> > --
> > 2.17.1
> 
> I'm not sure this does the same thing as the original assert_has_program.
> 
> I can't tell what happens if I provide the name of a file which isn't on the
> path, but is in the filesystem, or which isn't in the filesystem at all.
> Did you test for these cases?
>  -- Tim
> 
> 
> 
> 
> 
> _______________________________________________
> Fuego mailing list
> Fuego@lists.linuxfoundation.org
> https://lists.linuxfoundation.org/mailman/listinfo/fuego

^ permalink raw reply	[flat|nested] 9+ messages in thread

* Re: [Fuego] [PATCH] Optimize the code of assert_has_program.
  2019-10-18  4:46     ` Tim.Bird
@ 2019-10-21  6:47       ` Wang, Mingyu
  0 siblings, 0 replies; 9+ messages in thread
From: Wang, Mingyu @ 2019-10-21  6:47 UTC (permalink / raw)
  To: fuego

Hi Tim,

I also thought about using command -v to judge whether the command exists before. This method will speed up the search (relative to the PATH search).
But because command -v needs to execute commands on the target, I think this also affects performance, so this method is not used.

In the current version, I have tried built-in commands, alias, ash, and some common commands, and the test passed smoothly.

Also I tried the following tests:
There is no ll on my x86_64 system, so I execute the following command:
#alias ​​ll='ls -l --color=auto'
This will allow you to use the ll command.
But in the check_has_program function, when it is judged that ll is alias, it will go to PATH to find ll.
Since it is an alias I added manually, so can't find it under PATH.
In this case, is it should make the test fail, or let the function judge whether the ls exists? 
This issue also exists in previous versions. Of course, maybe this situation is completely unnecessary.

In addition, calling cmd for each object it finds is still time consuming. So it's really need to call cmd just once to handle all the programs.


Best regards
Wangmy

-----Original Message-----
From: Tim.Bird@sony.com [mailto:Tim.Bird@sony.com] 
Sent: Friday, October 18, 2019 12:47 PM
To: Wang, Mingyu/王 鸣瑜 <wangmy@cn.fujitsu.com>; fuego@lists.linuxfoundation.org
Subject: RE: [Fuego] [PATCH] Optimize the code of assert_has_program.

The TL;DR version:
There's a  new much faster version of assert_has_program() in fuego-core, in the master branch. Please try it out.

Ok - now the longer version...

I have re-written the assert_has_program code in the fuego core so that this patch no longer applies.  Sorry about that.

But I'd like to discuss my solution to this problem, and the roadmap for what I've implemented so far, and maybe get some feedback on it before going further with it.

I modified assert_has_program to call a new routine:
check_has_program, that uses the command 'command -v'
on the target to find programs on the PATH.  This is a POSIX-compatible command, which is built in to all POSIX shells.  I tested with busybox ash, dash and bash.

The busybox version of 'command -v' does not give the full path, but it does give a value if the  command is on the path, which is sufficient for assert_has_program.

This is much faster than the old method of searching through the path using a loop on the host.  Instead of many invocations of 'cmd' per item being checked, there is only one.

Also, I have implemented a dependency cache feature.  It is possible to run a program once, after provisioning the board, to accumulate the program installation status for programs required by all tests.  The data for this is placed in variables in the stored variable file at:
/fuego-rw/board/<board>.vars

All these program variables become part of the prolog.sh file for a test during overlay generation, and they can be tested very quickly, without having to communicate with the target board.  This takes the cost of doing a single assert_has_program from many seconds (the original cost) to under 3 seconds (using 'command -v', when the data is not in cache) to under .1 second, if the data is in cache.

This introduces an issue, however: the dependency cache needs to be cleared and re-populated when the board is provisioned, so that stale data is not used for tests run after the board is re-installed.

This adds an extra step to the CI loop.  By default, if you never populate the dependency cache by running the new program (populate_board_cache.sh), then fuego core will use 'command -v' for each assert_has_program in a test's
test_pre_check() function.   This means the new system should be completely
backward compatible with the old system.  Without the cache, test_pre_check with multiple calls to assert_has_program will still take over 10 seconds.
However, if populate_board_cache.sh is run, then the dependency checks runs very quickly, for all tests.  However, executing this script after installing a board is now required in order to avoid using stale cache data.  It should only need to be run once per after the board is re-provisioned.
This is something that seems like it might be error-prone, and might need some additional support (in the way of messages or other help notices) to make sure that when people set up their CI loop with Fuego, they include a call this this script.  I'm still thinking about the exact method of invoking this whether through an external script, as it is now, or via a special "action"
script implemented similar to a Fuego test.

Note that I'm also looking into re-factoring the pre_test functionality to remove or consolidate pre-test operations on the board, to save time and reduce test overhead.

This system could be improved further by supporting multiple arguments to assert_has_program (and check_program), and implementing the loop over them on the target, as Mingyu did in this patch.  I haven't had time to go back and refactor this initial implementation to do that.  Theoretically, this could result in a check for multiple programs only requiring a single call to 'cmd' to communicate with the target, which would speed things up (in the non-cache case) even more.  I’m considering writing a little function as part of need_check.sh, which would do all the data accumulation for all dependencies listed in a test with a single communication with the target.  This would use a somewhat complicated shell snippet to gather all the data at once.  The downside is that it would be a bit complicated.
The upside would be that there would be no need to maintain the dependency cache in order to have correct operation.

Let me know what you think about this new system.
Please try it out and make sure that nothing breaks in your tests.

Finally - this dependency cache feature actually has a dual purpose.
I've been working on implementing a remote testing feature for Fuego using fserver.  Likely, the server will eventually support adding meta-data information (including supported hardware, board features, and installed memory and programs) for a board, so that a remote scheduler can select a board for a test based on the board's attributes.  That feature is still a ways off in terms of implementation.  But it's on the roadmap, and may help explain why I'd like to gather this dependency data (as one element of that board information.)

Regards,
 -- Tim

> -----Original Message-----
> From: Wang, Mingyu on  Tuesday, October 15, 2019 7:52 PM
> To: fuego@lists.linuxfoundation.org
> Subject: Re: [Fuego] [PATCH] Optimize the code of assert_has_program.
> 
> Hi Tim,
> 
> >> Usage:
> >> before:
> > >    assert_has_program AAA
> > >    assert_has_program BBB
> >>
> > >after:
> > >    assert_has_program "AAA BBB"
> > >    assert_has_program "AAA BBB" SEARCH_PATH
> >>
> > >Note: SEARCH_PATH is optional.
> >Can you explain when SEARCH_PATH is needed?
> 
> It is not necessary.
> I see that the original is_on_target can search in the specified path, 
> so I added SEARCH_PATH here.
> If need to do the same thing with the original assert_has_program, 
> this variable can be deleted.
> 
> 
> >> +             if [ ! -s $tmpfile ]
> >> +             then
> >> +                 find / -name \"\$prg\" | head -n 1 >$tmpfile
> >> +             fi
> >This will detect the program anywhere in the filesystem, not just on 
> >the
> PATH.
> >That changes the behavior of assert_has_program, which currently only
> looks on the target's PATH.
> 
> This code is still used to consider the user-specified path.
> If need to do the same thing with the original assert_has_program, 
> this code can be deleted.
> 
> >> +             if [ ! -s $tmpfile ]
> >> +             then
> > >+                 echo \"\$prg\" >$tmpfile ; break;
> >This would put the program name into tmpfile, which means that even 
> >if
> the program was not detected, tmpfile will have a non-empty result.
> >I don't understand this.
> The program was not detected will be saved into tmpfile.
> And assert_on_target will get the program and transform to 
> assert_has_program to show  an error  message.
> 
> 
> >> +             else
> > >+                 > $tmpfile
> >I also don't understand why this is needed.  The file is always 
> >touched
> above, so it exists as an empty file.  Why does it need to have the 
> empty redirection into it?
> Consider the case where assert_has_program specifies multiple programs 
> at the same time.
> 
> >I can't tell what happens if I provide the name of a file which isn't 
> >on the
> path, but is in the filesystem, or which isn't in the filesystem at all.
> >Did you test for these cases?
> I tested a variety of situations, including specifying multiple 
> programs at the same time。
> And existing or non-existent  program  is also tested.
> 
> When I designed assert_has_program, I considered the existing 
> is_on_target and is_on_target_path and wanted to be as compatible as 
> possible with them so that they could be replaced in the future.
> 
> best regards!
> 
> 
> 
> -----Original Message-----
> From: Tim.Bird@sony.com [mailto:Tim.Bird@sony.com]
> Sent: Saturday, September 21, 2019 10:25 AM
> To: Wang, Mingyu/王 鸣瑜 <wangmy@cn.fujitsu.com>; 
> fuego@lists.linuxfoundation.org
> Subject: RE: [Fuego] [PATCH] Optimize the code of assert_has_program.
> 
> I'm not sure this gives the same results at the original code.
> See my comments inline below.
> 
> Also, combining multiple programs into a single 'assert_has_program'
> lines will make it a bit more difficult to implement a cache system 
> for programs detected on the board.
> 
> I will have to think about this one.
> 
> > -----Original Message-----
> > From: Wang Mingyu on Tuesday, September 03, 2019 3:09 PM
> >
> > It is faster to check the prgoram or file on the target.
> prgoram -> program
> 
> >
> > Usage:
> > before:
> >     assert_has_program AAA
> >     assert_has_program BBB
> >
> > after:
> >     assert_has_program "AAA BBB"
> >     assert_has_program "AAA BBB" SEARCH_PATH
> >
> > Note: SEARCH_PATH is optional.
> 
> Can you explain when SEARCH_PATH is needed?
> 
> >
> > Signed-off-by: Wang Mingyu <wangmy@cn.fujitsu.com>
> > ---
> >  scripts/functions.sh  | 65
> > +++++++++++++++++++++++++++++++++++++++----
> >  scripts/need_check.sh | 11 ++------
> >  2 files changed, 61 insertions(+), 15 deletions(-)
> >
> > diff --git a/scripts/functions.sh b/scripts/functions.sh index
> > 0fa80b8..3aea0c8 100755
> > --- a/scripts/functions.sh
> > +++ b/scripts/functions.sh
> > @@ -1010,6 +1010,57 @@ function is_on_target_path {
> >      is_on_target $1 $2 $TARGET_PATH  }
> >
> > +# check for a program or file on the target, and set a variable if 
> > +it's present # $1 - file, dir or program on target # $2 is the path 
> > +of target to search the program/file # $3 - tmpfile to save the 
> > +detect result function set_cmd_str {
> In general, I like this approach of executing a command on the target 
> that does the search loop.
> 
> > +   tmpfile=$3
> > +   cmd_str="touch $tmpfile
> > +         # split $1 on whitespace, without file globbing
> > +         for prg in \$(echo $1 | tr \" \" \"\\n\") ; do
> > +             # split search path on colon
> > +             for d in \$(echo $2 | tr \":\" \"\\n\") ; do
> > +                 # execute a command on the target to detect \$d/\$prg
> > +                 if [ -z \"\$(cat $tmpfile)\" -a -e \"\$d/\$prg\" ]
> > +                 then
> > +                     echo \"\$d/\$prg\" >$tmpfile ;break;
> > +                 fi
> > +             done
> > +             if [ ! -s $tmpfile ]
> > +             then
> > +                 find / -name \"\$prg\" | head -n 1 >$tmpfile
> > +             fi
> This will detect the program anywhere in the filesystem, not just on 
> the PATH.
> That changes the behavior of assert_has_program, which currently only 
> looks on the target's PATH.
> 
> > +             if [ ! -s $tmpfile ]
> > +             then
> > +                 echo \"\$prg\" >$tmpfile ; break;
> This would put the program name into tmpfile, which means that even if 
> the program was not detected, tmpfile will have a non-empty result.
> I don't understand this.
> 
> > +             else
> > +                 > $tmpfile
> I also don't understand why this is needed.  The file is always 
> touched above, so it exists as an empty file.  Why does it need to 
> have the empty redirection into it?
> 
> > +             fi
> > +         done"
> > +}
> > +
> > +# check for a program or file on the target, and set a variable if 
> > +it's present # $1 - file, dir or program on target # $2 - variable 
> > +to set during the build # $3 is the path of target to search the 
> > +program/file (optional, default:
> > $PATH)
> > +function assert_on_target {
> > +    local TARGET_PATH=${3}
> > +    if [ -z "$TARGET_PATH" ]; then
> > +       TARGET_PATH=$(cmd "echo \$PATH")
> > +    fi
> > +
> > +    tmpfile=$(mktemp /tmp/found_loc.XXXXXX)
> > +    set_cmd_str "$1" $TARGET_PATH $tmpfile
> > +    cmd "$cmd_str"
> > +    get $tmpfile $tmpfile
> > +    if [ -s $tmpfile ] ; then
> > +        export $2=$(cat $tmpfile)
> > +    fi
> > +    cmd "rm $tmpfile"
> > +    rm -f $tmpfile # -f for tests running on the host }
> > +
> >  # check for a library on the SDK, and set a variable if it's 
> > present # $1 - the file (library) we want to search for in the SDK  
> > # $2 - variable to set the location (if the file is found) @@ 
> > -1036,13
> > +1087,15 @@ function is_on_sdk {
> >
> >  # check for a program or file on the target, and send message if 
> > the program or file is missing  # $1 has the program that is 
> > required on the target board -# this has the side effect of defining 
> > PROGRAM_$1
> > (uppercased) -# with the value as the directory where $1 is found on 
> > the board.
> > +# $2 is the path of target to search the program/file (optional, default:
> > $PATH)
> >  function assert_has_program {
> > -   upName=${1^^}
> > -   progVar=PROGRAM_${upName//[-,.]/_}
> > -   is_on_target_path $1 ${progVar}
> > -   assert_define ${progVar} "Missing '$1' program on target board"
> > +   assert_on_target "$1" prgName $2
> > +   if [ -n "$prgName" ]
> > +   then
> > +       upName=${prgName^^}
> > +       progVar=PROGRAM_${upName//[-,.]/_}
> > +       assert_define ${progVar} "Missing '$prgName' program on 
> > + target
> board"
> > +   fi
> >  }
> >
> >  # check for a module on the target, and abort if it is missing diff 
> > --git a/scripts/need_check.sh b/scripts/need_check.sh index
> > c9bbb75..9bb0098 100755
> > --- a/scripts/need_check.sh
> > +++ b/scripts/need_check.sh
> > @@ -319,18 +319,11 @@ function check_root {  # check if those 
> > specified commands exist on board  # $1 has single string with a 
> > list of command entries to check for  function check_program {
> > -  # split $1 on whitespace, without file globbing
> > -  set -f
> > -  arg_array=($1)
> > -  set +f
> > -
> > -  for prg in "${arg_array[@]}" ; do
> > -    is_on_target_path $prg prg_path
> > -    if [ -z "$prg_path" ] ; then
> > +    assert_on_target "$1" prg
> > +    if [ -n "$prg" ] ; then
> >        echo -e "\n\nABORTED: Expected command \"$prg\" on the 
> > target, but it's not there!"
> >        return 1
> >      fi
> > -  done
> >
> >    # return OK if all necessary commands exist on the target
> >    return 0
> > --
> > 2.17.1
> 
> I'm not sure this does the same thing as the original assert_has_program.
> 
> I can't tell what happens if I provide the name of a file which isn't 
> on the path, but is in the filesystem, or which isn't in the filesystem at all.
> Did you test for these cases?
>  -- Tim
> 
> 
> 
> 
> 
> _______________________________________________
> Fuego mailing list
> Fuego@lists.linuxfoundation.org
> https://lists.linuxfoundation.org/mailman/listinfo/fuego





^ permalink raw reply	[flat|nested] 9+ messages in thread

end of thread, other threads:[~2019-10-21  6:47 UTC | newest]

Thread overview: 9+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2019-09-04  1:09 [Fuego] [PATCH] Optimize the code of assert_has_program Wang Mingyu
2019-09-04  1:09 ` [Fuego] [PATCH] ltrace: Add test cases for command ltrace Wang Mingyu
2019-09-11 17:28   ` Tim.Bird
2019-09-04  1:09 ` [Fuego] [PATCH] nfs: Add test cases for nfs Wang Mingyu
2019-09-21  1:40   ` Tim.Bird
2019-09-21  2:24 ` [Fuego] [PATCH] Optimize the code of assert_has_program Tim.Bird
2019-10-16  5:52   ` Wang, Mingyu
2019-10-18  4:46     ` Tim.Bird
2019-10-21  6:47       ` Wang, Mingyu

This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.