fix(parser): ensure data is piped when using '-' argument (#1881)

fix(parser): ensure data is piped when using '-' argument

Fixes #1626.

Check to see if data was actually piped to yay, otherwise it will hang
forever. This error will give users better feedback of how to use the
'-' argument (it is also the same exact error pacman throws for invalid
piped data).

Two tests were added. However, I didn't know how to add a test for the
actual part that detects whether data was piped or not (which is
essentially what this commit adds).
This commit is contained in:
Joey H 2023-01-03 13:43:15 -06:00 committed by GitHub
parent 86bba8a289
commit 8948278568
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
2 changed files with 48 additions and 0 deletions

View file

@ -610,6 +610,16 @@ func (a *Arguments) parseLongOption(arg, param string) (usedNext bool, err error
}
func (a *Arguments) parseStdin() error {
fi, err := os.Stdin.Stat()
if err != nil {
return err
}
// Ensure data is piped
if (fi.Mode() & os.ModeCharDevice) != 0 {
return errors.New(gotext.Get("argument '-' specified without input on stdin"))
}
scanner := bufio.NewScanner(os.Stdin)
scanner.Split(bufio.ScanLines)

View file

@ -1,9 +1,11 @@
package parser
import (
"os"
"testing"
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"
)
func TestOption_Add(t *testing.T) {
@ -330,3 +332,39 @@ func Test_isArg(t *testing.T) {
got = isArg("dbpath")
assert.True(t, got)
}
func TestArguments_ParseStdin(t *testing.T) {
input := []byte("yay")
r, w, err := os.Pipe()
require.NoError(t, err)
_, err = w.Write(input)
require.NoError(t, err)
w.Close()
// Restore stdin after the test.
defer func(o *os.File) { os.Stdin = o }(os.Stdin)
os.Stdin = r
args := MakeArguments()
err = args.parseStdin()
assert.NoError(t, err)
expectedTargets := []string{string(input)}
assert.ElementsMatch(t, args.Targets, expectedTargets)
}
func TestArguments_ParseStdin_broken_pipe(t *testing.T) {
r, _, err := os.Pipe()
require.NoError(t, err)
r.Close() // Close early to break pipe
// Restore stdin after the test.
defer func(o *os.File) { os.Stdin = o }(os.Stdin)
os.Stdin = r
args := MakeArguments()
err = args.parseStdin()
assert.Error(t, err)
}