Skip to contentSkip to conversation

test.sh and ROD redirection

LTP Cyril Hrubis 2 participants 9 messages Jan 21, 2016 – Jan 25, 2016

lore
Share & tools
lore
#0 lore raw

Hi!
As I've been doing last minute fixes to shell testcases I've stambled upon this problem. We have a couple of places that do:

ROD echo foo > bar

And while this works fine if the command executes successfully it writes the error message to the file bar on failure as well (since the part that gets to the ROD as $@ is the 'echo foo' while the '> bar' is parsed by the shell.

One solution would be redirecting the messages from tst_* to stderr, so we would be able to at least see the error message, but this wouldn't catch errors when we cannot write to the 'bar' (since echo foo would executed successfully anyway).

Another solution would be to create ROD_ECHO and ROD_CAT and change ROD to abort if anybody tries to use it with these two. Which solves our usage pattern but this is clumsy and still broken as anyone can redirect output from ROD anyway.

Is there a elegant solution to this problem that I'm missing?

Signature · 2 lines
Cyril Hrubis
[email protected]
#1 lore raw

Hi,

Quoted 11 lines · Cyril Hrubis

Hi!
As I've been doing last minute fixes to shell testcases I've stambled upon this problem. We have a couple of places that do:

ROD echo foo > bar

And while this works fine if the command executes successfully it writes the error message to the file bar on failure as well (since the part that gets to the ROD as $@ is the 'echo foo' while the '> bar' is parsed by the shell.

Quoted 4 lines

One solution would be redirecting the messages from tst_* to stderr, so we would be able to at least see the error message, but this wouldn't catch errors when we cannot write to the 'bar' (since echo foo would executed successfully anyway).

This won't work in case of simple file creation: ROD >file. Quotation marks seem to
help in this case with ROD.

./testcases/network/nfs/nfs_stress/nfs03: ROD >file$j$k

can be changed to ROD ">file$j$k"

Quoted 4 lines

Another solution would be to create ROD_ECHO and ROD_CAT and change ROD to abort if anybody tries to use it with these two. Which solves our usage pattern but this is clumsy and still broken as anyone can redirect output from ROD anyway.

Could be just one ROD_RED that accepts parameters in this way: 1st for exec and
the others to set after '>' redirection.

ROD_RED()

{
     $1 > ${@:2}
     if [ $? -ne 0 ]; then
     ....
}

ROD_RED "echo 0" "file"

Best regards,
Alexey

Quoted 2 lines

Is there a elegant solution to this problem that I'm missing?

#2 lore raw

Hi!

Quoted 14 lines
Quoted 10 lines

As I've been doing last minute fixes to shell testcases I've stambled upon this problem. We have a couple of places that do:

ROD echo foo > bar

And while this works fine if the command executes successfully it writes the error message to the file bar on failure as well (since the part that gets to the ROD as $@ is the 'echo foo' while the '> bar' is parsed by the shell.

Quoted 4 lines

One solution would be redirecting the messages from tst_* to stderr, so we would be able to at least see the error message, but this wouldn't catch errors when we cannot write to the 'bar' (since echo foo would executed successfully anyway).

Quoted 6 lines

This won't work in case of simple file creation: ROD >file. Quotation marks seem to help in this case with ROD.

./testcases/network/nfs/nfs_stress/nfs03: ROD >file$j$k

can be changed to ROD ">file$j$k"

You lost me here. All I wanted to do is:

testcases/lib/test.sh +1 -1
@@ -47,7 +47,7 @@ tst_resm()
 
        local ret=$1
        shift
-       echo "$TCID $TST_COUNT $ret : $@"
+       echo "$TCID $TST_COUNT $ret : $@" >&2
 

This should not break anything. And maybe this is a good idea regardless the original problem.

Quoted 9 lines
Quoted 4 lines

Another solution would be to create ROD_ECHO and ROD_CAT and change ROD to abort if anybody tries to use it with these two. Which solves our usage pattern but this is clumsy and still broken as anyone can redirect output from ROD anyway.

Could be just one ROD_RED that accepts parameters in this way: 1st for exec and
the others to set after '>' redirection.

Quoted 8 lines

ROD_RED()

{
     $1 > ${@:2}
     if [ $? -ne 0 ]; then
     ....
}

ROD_RED "echo 0" "file"

This sounds good, but I would like to have the file as single argument so that we do not have to quote the command in question. The easiest solution would be to have the file to be the first argument, but that is counter intuitive, so I would rather go with the last even if the code ends up far more complicated.

Another option would be inventing our special syntax for redirecting for ROD. Use for example % and threat it like > i.e. split $@ on % and redirect the output to whatever is found after % which shouldn't be much more complicated than separating last parameter from $@...

Signature · 2 lines
Cyril Hrubis
[email protected]
#3 lore raw

Hi!

Quoted 4 lines

Another option would be inventing our special syntax for redirecting for ROD. Use for example % and threat it like > i.e. split $@ on % and redirect the output to whatever is found after % which shouldn't be much more complicated than separating last parameter from $@...

What about this one:

testcases/lib/test.sh +23 -1
index 074be74..ef2af14 100644
@@ -214,7 +214,29 @@ ROD_SILENT()
 
 ROD()
 {
-	$@
+	local cmd
+	local arg
+	local file
+	local flag
+
+	for arg; do
+		if [ "$arg" == ">" ]; then
+			flag=1
+			continue
+		fi
+
+		if [ -n "$flag" ]; then
+			break
+		fi
+		cmd="$cmd $arg"
+	done
+
+	if [ -n "$flag" ]; then
+		$cmd > $arg
+	else
+		$@
+	fi
+
 	if [ $? -ne 0 ]; then
 		tst_brkm TBROK "$@ failed"
 	fi

It's called as: 'ROD echo a \> b', the reason for choosing \> is that the error message will contain '>' instead of some strange char as %.

I.e. doing 'ROD echo a \> /proc/cpuinfo' yields:

test.sh: line 235: /proc/cpuinfo: Permission denied foo 1 TBROK : echo b > /proc/cpuinfo failed

Signature · 2 lines
Cyril Hrubis
[email protected]
#4 lore raw

Hi,

Quoted 13 lines · Cyril Hrubis

Hi!

Quoted 4 lines

Another option would be inventing our special syntax for redirecting for ROD. Use for example % and threat it like > i.e. split $@ on % and redirect the output to whatever is found after % which shouldn't be much more complicated than separating last parameter from $@...

What about this one:

testcases/lib/test.sh +0 -0
index 074be74..ef2af14 100644
@@ -214,7 +214,29 @@ ROD_SILENT()
 

testcases/lib/test.sh ROD_SILENT() · line 223

Quoted 10 lines
testcases/lib/test.sh +7 -1
  ROD()
  {
-	$@
+	local cmd
+	local arg
+	local file
+	local flag
+
+	for arg; do
+		if [ "$arg" == ">" ]; then

I would change it to

         if [ "${arg:0:1}" == ">" ]; then
                 arg=${arg:1}

in case '\>' is not separated by space.

e.g.:
ROD echo a \>/proc/cpuinfo

testcases/lib/test.sh ROD_SILENT() · line 225

Quoted 2 lines
testcases/lib/test.sh +2 -0
+			flag=1
+			continue

May be break here, so we don't need the next if block.

testcases/lib/test.sh ROD_SILENT() · line 231

Quoted 6 lines
testcases/lib/test.sh +6 -0
+		fi
+
+		if [ -n "$flag" ]; then
+			break
+		fi
+		cmd="$cmd $arg"

But what if the rest of args has something else, e.g. 2>&1 ?

Quoted 13 lines
testcases/lib/test.sh +8 -0
+	done
+
+	if [ -n "$flag" ]; then
+		$cmd > $arg
+	else
+		$@
+	fi
+
  	if [ $? -ne 0 ]; then
  		tst_brkm TBROK "$@ failed"
  	fi
Quoted 7 lines

It's called as: 'ROD echo a \> b', the reason for choosing \> is that the error message will contain '>' instead of some strange char as %.

I.e. doing 'ROD echo a \> /proc/cpuinfo' yields:

test.sh: line 235: /proc/cpuinfo: Permission denied foo 1 TBROK : echo b > /proc/cpuinfo failed

Best regards,
Alexey

#5 lore raw

Hi!

Quoted 6 lines

testcases/lib/test.sh ROD_SILENT() · line 223

Quoted 2 lines
testcases/lib/test.sh +2 -0
+	for arg; do
+		if [ "$arg" == ">" ]; then

I would change it to

         if [ "${arg:0:1}" == ">" ]; then
                 arg=${arg:1}

That does work only in bash.

The easiest portable way I can come up with is:

	if [ "${arg#\>}" != "$arg" ]; then
		arg=${arg#\>}
	fi
Quoted 3 lines

testcases/lib/test.sh ROD_SILENT() · line 225

Quoted 2 lines
testcases/lib/test.sh +2 -0
+			flag=1
+			continue

May be break here, so we don't need the next if block.

Right.

Quoted 8 lines

testcases/lib/test.sh ROD_SILENT() · line 231

Quoted 6 lines
testcases/lib/test.sh +6 -0
+		fi
+
+		if [ -n "$flag" ]; then
+			break
+		fi
+		cmd="$cmd $arg"

But what if the rest of args has something else, e.g. 2>&1 ?

Hmm, we can look for that in the $@ as well but nobody is using ROD with that at the moment. We can think about this later ideally when there is need for this.

Signature · 2 lines
Cyril Hrubis
[email protected]
#6 lore raw
In reply to Alexey Kodanev

Hi!

Quoted 3 lines

Review

Quoted 2 lines
(quoted diff) +2 -0
+			flag=1
+			continue

May be break here, so we don't need the next if block.

We have to do another loop just to fetch the parameter after the \> if there is space between \> and path. So the continue should stay.

Full version then would be:

testcases/lib/test.sh +29 -1
@@ -214,7 +214,35 @@ ROD_SILENT()
 
 ROD()
 {
-       $@
+       local cmd
+       local arg
+       local file
+       local flag
+
+       for arg; do
+               file="${arg#\>}"
+               if [ "$file" != "$arg" ]; then
+                       if [ -n "$file" ]; then
+                               break
+                       fi
+                       flag=1
+                       continue
+               fi
+
+               if [ -n "$flag" ]; then
+                       file="$arg"
+                       break
+               fi
+
+               cmd="$cmd $arg"
+       done
+
+       if [ -n "$file" ]; then
+               $cmd > $file
+       else
+               $@
+       fi
+
        if [ $? -ne 0 ]; then
                tst_brkm TBROK "$@ failed"
        fi

This works both with:

ROD echo a \> file
ROD echo a \>file

Signature · 2 lines
Cyril Hrubis
[email protected]
#7 lore raw
Quoted 7 lines · Cyril Hrubis

...

This works both with:

ROD echo a \> file
ROD echo a \>file

Looks good to me!

Best regards,
Alexey

#8 lore raw

Hi!

Quoted 1 line

Looks good to me!

Ok. I will push this along with documentation and fixed all uses in tests tomorrow, then tag the release.

Signature · 2 lines
Cyril Hrubis
[email protected]