github.com/markusbkk/elvish@v0.0.0-20231204143114-91dc52438621/pkg/eval/builtin_fn_io_test.go (about)

     1  package eval_test
     2  
     3  import (
     4  	"encoding/json"
     5  	"os"
     6  	"testing"
     7  
     8  	"github.com/markusbkk/elvish/pkg/eval"
     9  	"github.com/markusbkk/elvish/pkg/eval/errs"
    10  	. "github.com/markusbkk/elvish/pkg/eval/evaltest"
    11  	"github.com/markusbkk/elvish/pkg/eval/vals"
    12  )
    13  
    14  func TestPut(t *testing.T) {
    15  	Test(t,
    16  		That(`put foo bar`).Puts("foo", "bar"),
    17  		That(`put $nil`).Puts(nil),
    18  
    19  		thatOutputErrorIsBubbled("put foo"),
    20  	)
    21  }
    22  
    23  func TestReadUpto(t *testing.T) {
    24  	Test(t,
    25  		That("print abcd | read-upto c").Puts("abc"),
    26  		// read-upto does not consume more than needed
    27  		That("print abcd | { read-upto c; slurp }").Puts("abc", "d"),
    28  		// read-upto reads up to EOF
    29  		That("print abcd | read-upto z").Puts("abcd"),
    30  		That("print abcd | read-upto cd").Throws(
    31  			errs.BadValue{What: "terminator",
    32  				Valid: "a single ASCII character", Actual: "cd"}),
    33  		thatOutputErrorIsBubbled("print abcd | read-upto c"),
    34  	)
    35  }
    36  
    37  func TestReadLine(t *testing.T) {
    38  	Test(t,
    39  		That(`print eof-ending | read-line`).Puts("eof-ending"),
    40  		That(`print "lf-ending\n" | read-line`).Puts("lf-ending"),
    41  		That(`print "crlf-ending\r\n" | read-line`).Puts("crlf-ending"),
    42  		That(`print "extra-cr\r\r\n" | read-line`).Puts("extra-cr\r"),
    43  		thatOutputErrorIsBubbled(`print eof-ending | read-line`),
    44  	)
    45  }
    46  
    47  func TestPrint(t *testing.T) {
    48  	Test(t,
    49  		That(`print [foo bar]`).Prints("[foo bar]"),
    50  		That(`print foo bar &sep=,`).Prints("foo,bar"),
    51  		thatOutputErrorIsBubbled("print foo"),
    52  	)
    53  }
    54  
    55  func TestEcho(t *testing.T) {
    56  	Test(t,
    57  		That(`echo [foo bar]`).Prints("[foo bar]\n"),
    58  		thatOutputErrorIsBubbled("echo foo"),
    59  	)
    60  }
    61  
    62  func TestPprint(t *testing.T) {
    63  	Test(t,
    64  		That(`pprint [foo bar]`).Prints("[\n foo\n bar\n]\n"),
    65  		thatOutputErrorIsBubbled("pprint foo"),
    66  	)
    67  }
    68  
    69  func TestReprCmd(t *testing.T) {
    70  	Test(t,
    71  		That(`repr foo bar ['foo bar']`).Prints("foo bar ['foo bar']\n"),
    72  		thatOutputErrorIsBubbled("repr foo"),
    73  	)
    74  }
    75  
    76  func TestShow(t *testing.T) {
    77  	Test(t,
    78  		// A sanity test that show writes something.
    79  		That(`show ?(fail foo) | !=s (slurp) ''`).Puts(true),
    80  		thatOutputErrorIsBubbled("repr ?(fail foo)"),
    81  	)
    82  }
    83  
    84  func TestOnlyBytesAndOnlyValues(t *testing.T) {
    85  	Test(t,
    86  		// Baseline
    87  		That(`{ print bytes; put values }`).Prints("bytes").Puts("values"),
    88  		That(`{ print bytes; put values } | only-bytes`).Prints("bytes").Puts(),
    89  		thatOutputErrorIsBubbled("{ print bytes; put values } | only-bytes"),
    90  	)
    91  }
    92  
    93  func TestOnlyValues(t *testing.T) {
    94  	Test(t,
    95  		// Baseline
    96  		That(`{ print bytes; put values }`).Prints("bytes").Puts("values"),
    97  		That(`{ print bytes; put values } | only-values`).Prints("").Puts("values"),
    98  		thatOutputErrorIsBubbled("{ print bytes; put values } | only-values"),
    99  	)
   100  }
   101  
   102  func TestSlurp(t *testing.T) {
   103  	Test(t,
   104  		That(`print "a\nb" | slurp`).Puts("a\nb"),
   105  		thatOutputErrorIsBubbled(`print "a\nb" | slurp`),
   106  	)
   107  }
   108  
   109  func TestFromLines(t *testing.T) {
   110  	Test(t,
   111  		That(`print "a\nb" | from-lines`).Puts("a", "b"),
   112  		That(`print "a\nb\n" | from-lines`).Puts("a", "b"),
   113  		thatOutputErrorIsBubbled(`print "a\nb\n" | from-lines`),
   114  	)
   115  }
   116  
   117  func TestFromTerminated(t *testing.T) {
   118  	Test(t,
   119  		That(`print "a\nb\x00\x00c\x00d" | from-terminated "\x00"`).Puts("a\nb", "", "c", "d"),
   120  		That(`print "a\x00b\x00" | from-terminated "\x00"`).Puts("a", "b"),
   121  		That(`print aXbXcXXd | from-terminated "X"`).Puts("a", "b", "c", "", "d"),
   122  		That(`from-terminated "xyz"`).Throws(
   123  			errs.BadValue{What: "terminator",
   124  				Valid: "a single ASCII character", Actual: "xyz"}),
   125  		thatOutputErrorIsBubbled("print aXbX | from-terminated X"),
   126  	)
   127  }
   128  
   129  func TestFromJson(t *testing.T) {
   130  	Test(t,
   131  		That(`echo '{"k": "v", "a": [1, 2]}' '"foo"' | from-json`).
   132  			Puts(vals.MakeMap("k", "v", "a", vals.MakeList(1.0, 2.0)),
   133  				"foo"),
   134  		That(`echo '[null, "foo"]' | from-json`).Puts(
   135  			vals.MakeList(nil, "foo")),
   136  		That(`echo 'invalid' | from-json`).Throws(ErrorWithType(&json.SyntaxError{})),
   137  		thatOutputErrorIsBubbled(`echo '[]' | from-json`),
   138  	)
   139  }
   140  
   141  func TestToLines(t *testing.T) {
   142  	Test(t,
   143  		That(`put "l\norem" ipsum | to-lines`).Prints("l\norem\nipsum\n"),
   144  		thatOutputErrorIsBubbled("to-lines [foo]"),
   145  	)
   146  }
   147  
   148  func TestToTerminated(t *testing.T) {
   149  	Test(t,
   150  		That(`put "l\norem" ipsum | to-terminated "\x00"`).Prints("l\norem\x00ipsum\x00"),
   151  		That(`to-terminated "X" [a b c]`).Prints("aXbXcX"),
   152  		That(`to-terminated "XYZ" [a b c]`).Throws(
   153  			errs.BadValue{What: "terminator",
   154  				Valid: "a single ASCII character", Actual: "XYZ"}),
   155  		thatOutputErrorIsBubbled(`to-terminated "X" [a b c]`),
   156  	)
   157  }
   158  
   159  func TestToJson(t *testing.T) {
   160  	Test(t,
   161  		That(`put [&k=v &a=[1 2]] foo | to-json`).
   162  			Prints(`{"a":["1","2"],"k":"v"}
   163  "foo"
   164  `),
   165  		That(`put [$nil foo] | to-json`).Prints("[null,\"foo\"]\n"),
   166  		thatOutputErrorIsBubbled("to-json [foo]"),
   167  	)
   168  }
   169  
   170  func TestPrintf(t *testing.T) {
   171  	Test(t,
   172  		That(`printf abcd`).Prints("abcd"),
   173  
   174  		That(`printf "%s\n%s\n" abc xyz`).Prints("abc\nxyz\n"),
   175  		That(`printf "%q" "abc xyz"`).Prints(`'abc xyz'`),
   176  		That(`printf "%q" ['a b']`).Prints(`['a b']`),
   177  		That(`printf "%v" abc`).Prints("abc"),
   178  		That(`printf "%#v" "abc xyz"`).Prints(`'abc xyz'`),
   179  		That(`printf '%5.3s' 3.1415`).Prints("  3.1"),
   180  		That(`printf '%5.3s' (float64 3.1415)`).Prints("  3.1"),
   181  
   182  		That(`printf '%t' $true`).Prints("true"),
   183  		That(`printf '%t' $nil`).Prints("false"),
   184  
   185  		That(`printf '%3d' (num 5)`).Prints("  5"),
   186  		That(`printf '%3d' 5`).Prints("  5"),
   187  		That(`printf '%08b' (num 5)`).Prints("00000101"),
   188  		That(`printf '%08b' 5`).Prints("00000101"),
   189  
   190  		That(`printf '%.1f' 3.1415`).Prints("3.1"),
   191  		That(`printf '%.1f' (float64 3.1415)`).Prints("3.1"),
   192  
   193  		// Does not interpret escape sequences
   194  		That(`printf '%s\n%s\n' abc xyz`).Prints("abc\\nxyz\\n"),
   195  
   196  		// Error cases
   197  
   198  		// Float verb with argument that can't be converted to float
   199  		That(`printf '%f' 1.3x`).Prints("%!f(cannot parse as number: 1.3x)"),
   200  		// Integer verb with argument that can't be converted to integer
   201  		That(`printf '%d' 3.5`).Prints("%!d(cannot parse as integer: 3.5)"),
   202  		// Unsupported verb
   203  		That(`printf '%A' foo`).Prints("%!A(unsupported formatting verb)"),
   204  
   205  		thatOutputErrorIsBubbled("printf foo"),
   206  	)
   207  }
   208  
   209  func thatOutputErrorIsBubbled(code string) Case {
   210  	return That(code + " >&-").Throws(OneOfErrors(os.ErrInvalid, eval.ErrNoValueOutput))
   211  }