2019-09-12 03:56:54 -04:00
source tests/ support/ cli.tcl
2021-06-09 08:13:24 -04:00
if { $::singledb } {
set : : dbnum 0
} else {
set : : dbnum 9
}
2010-08-04 08:15:52 -04:00
start_server { tags { " c l i " } } {
2021-06-09 08:13:24 -04:00
proc open_cli { { opts " " } { infile " " } } {
if { $opts == " " } {
set opts " - n $ : : d b n u m "
}
2010-08-04 08:15:52 -04:00
set : : env( TERM ) dumb
2020-08-23 03:17:43 -04:00
set cmdline [ rediscli [ srv host] [ srv port] $opts ]
2020-07-21 07:17:14 -04:00
if { $infile ne " " } {
set cmdline " $ c m d l i n e < $ i n f i l e "
set mode " r "
} else {
set mode " r + "
}
set fd [ open " | $ c m d l i n e " $mode ]
2010-08-04 08:15:52 -04:00
fconfigure $fd - buffering none
fconfigure $fd - blocking false
fconfigure $fd - translation binary
set _ $fd
}
proc close_cli { fd } {
close $fd
}
proc read_cli { fd } {
2021-08-01 08:07:27 -04:00
set ret [ read $fd ]
while { [ string length $ret ] == 0 } {
2010-08-04 08:15:52 -04:00
after 10
2021-08-01 08:07:27 -04:00
set ret [ read $fd ]
}
# We may have a short read, try to read some more.
set empty_reads 0
while { $empty_reads < 5 } {
2010-08-04 08:15:52 -04:00
set buf [ read $fd ]
2021-08-01 08:07:27 -04:00
if { [ string length $buf ] == 0 } {
after 10
incr empty_reads
} else {
append ret $buf
set empty_reads 0
}
2010-08-04 08:15:52 -04:00
}
2021-08-01 08:07:27 -04:00
return $ret
2010-08-04 08:15:52 -04:00
}
proc write_cli { fd buf} {
puts $fd $buf
flush $fd
}
2010-08-25 08:08:32 -04:00
# Helpers to run tests in interactive mode
2020-07-10 03:25:55 -04:00
proc format_output { output } {
2023-03-19 06:56:54 -04:00
set _ [ string trimright $output " \n " ]
2020-07-10 03:25:55 -04:00
}
2010-08-04 08:15:52 -04:00
proc run_command { fd cmd} {
write_cli $fd $cmd
2020-07-10 03:25:55 -04:00
set _ [ format_output [ read_cli $fd ] ]
2010-08-04 08:15:52 -04:00
}
proc test_interactive_cli { name code} {
2010-08-25 07:39:11 -04:00
set : : env( FAKETTY ) 1
2010-08-04 08:15:52 -04:00
set fd [ open_cli ]
test " I n t e r a c t i v e C L I : $ n a m e " $code
close_cli $fd
2010-08-25 07:39:11 -04:00
unset : : env( FAKETTY )
2010-08-04 08:15:52 -04:00
}
2023-03-19 06:56:54 -04:00
proc test_interactive_nontty_cli { name code} {
set fd [ open_cli ]
test " I n t e r a c t i v e n o n - T T Y C L I : $ n a m e " $code
close_cli $fd
}
2010-08-25 08:08:32 -04:00
# Helpers to run tests where stdout is not a tty
2010-08-25 08:48:50 -04:00
proc write_tmpfile { contents } {
set tmp [ tmpfile " c l i " ]
set tmpfd [ open $tmp " w " ]
puts - nonewline $tmpfd $contents
close $tmpfd
set _ $tmp
}
2021-08-02 07:59:08 -04:00
proc _run_cli { host port db opts args} {
set cmd [ rediscli $host $port [ list - n $db { * } $args ] ]
2020-07-10 03:25:55 -04:00
foreach { key value} $opts {
2010-08-25 08:48:50 -04:00
if { $key eq " p i p e " } {
set cmd " s h - c \" $ v a l u e | $ c m d \" "
}
if { $key eq " p a t h " } {
set cmd " $ c m d < $ v a l u e "
}
}
set fd [ open " | $ c m d " " r " ]
2010-08-04 11:02:13 -04:00
fconfigure $fd - buffering none
fconfigure $fd - translation binary
set resp [ read $fd 1048576 ]
close $fd
2020-07-10 03:25:55 -04:00
set _ [ format_output $resp ]
2010-08-04 11:02:13 -04:00
}
2010-08-25 08:48:50 -04:00
proc run_cli { args } {
2021-08-02 07:59:08 -04:00
_run_cli [ srv host] [ srv port] $::dbnum { } { * } $args
2010-08-25 08:48:50 -04:00
}
2021-12-30 05:10:04 -05:00
proc run_cli_with_input_pipe { mode cmd args} {
if { $mode == " x " } {
_run_cli [ srv host] [ srv port] $::dbnum [ list pipe $cmd ] - x { * } $args
} elseif { $mode == " X " } {
_run_cli [ srv host] [ srv port] $::dbnum [ list pipe $cmd ] - X tag { * } $args
}
2010-08-25 08:48:50 -04:00
}
2021-12-30 05:10:04 -05:00
proc run_cli_with_input_file { mode path args} {
if { $mode == " x " } {
_run_cli [ srv host] [ srv port] $::dbnum [ list path $path ] - x { * } $args
} elseif { $mode == " X " } {
_run_cli [ srv host] [ srv port] $::dbnum [ list path $path ] - X tag { * } $args
}
2021-08-02 07:59:08 -04:00
}
proc run_cli_host_port_db { host port db args} {
_run_cli $host $port $db { } { * } $args
2010-08-25 08:48:50 -04:00
}
2010-08-04 11:16:05 -04:00
proc test_nontty_cli { name code} {
test " N o n - i n t e r a c t i v e n o n - T T Y C L I : $ n a m e " $code
}
2010-08-25 08:15:41 -04:00
# Helpers to run tests where stdout is a tty (fake it)
2010-08-04 11:16:05 -04:00
proc test_tty_cli { name code} {
2010-08-25 08:15:41 -04:00
set : : env( FAKETTY ) 1
2010-08-04 11:16:05 -04:00
test " N o n - i n t e r a c t i v e T T Y C L I : $ n a m e " $code
2010-08-25 08:15:41 -04:00
unset : : env( FAKETTY )
2010-08-04 11:02:13 -04:00
}
2010-08-04 08:15:52 -04:00
test_interactive_cli " I N F O r e s p o n s e s h o u l d b e p r i n t e d r a w " {
set lines [ split [ run_command $fd info] " \n " ]
foreach line $lines {
2023-03-19 06:56:54 -04:00
# Info lines end in \r\n, so they now end in \r.
if { ! [ regexp { ^ \ r $ | ^ # | ^ [ ^ # :]+:} $line]} {
2021-06-03 13:34:54 -04:00
fail " M a l f o r m e d i n f o l i n e : $ l i n e "
}
2010-08-04 08:15:52 -04:00
}
}
test_interactive_cli " S t a t u s r e p l y " {
assert_equal " O K " [ run_command $fd " s e t k e y f o o " ]
}
test_interactive_cli " I n t e g e r r e p l y " {
assert_equal " ( i n t e g e r ) 1 " [ run_command $fd " i n c r c o u n t e r " ]
}
test_interactive_cli " B u l k r e p l y " {
r set key foo
assert_equal " \" f o o \" " [ run_command $fd " g e t k e y " ]
}
test_interactive_cli " M u l t i - b u l k r e p l y " {
r rpush list foo
r rpush list bar
2020-07-10 03:25:55 -04:00
assert_equal " 1 ) \" f o o \" \n 2 ) \" b a r \" " [ run_command $fd " l r a n g e l i s t 0 - 1 " ]
2010-08-04 08:15:52 -04:00
}
2010-08-04 09:29:28 -04:00
test_interactive_cli " P a r s i n g q u o t e s " {
assert_equal " O K " [ run_command $fd " s e t k e y \" b a r \" " ]
assert_equal " b a r " [ r get key]
assert_equal " O K " [ run_command $fd " s e t k e y \" b a r \" " ]
assert_equal " b a r " [ r get key]
assert_equal " O K " [ run_command $fd " s e t k e y \" \\ \" b a r \\ \" \" " ]
assert_equal " \" b a r \" " [ r get key]
assert_equal " O K " [ run_command $fd " s e t k e y \" \t b a r \t \" " ]
assert_equal " \t b a r \t " [ r get key]
# invalid quotation
assert_equal " I n v a l i d a r g u m e n t ( s ) " [ run_command $fd " g e t \" \" k e y " ]
assert_equal " I n v a l i d a r g u m e n t ( s ) " [ run_command $fd " g e t \" k e y \" x " ]
# quotes after the argument are weird, but should be allowed
assert_equal " O K " [ run_command $fd " s e t k e y \" \" b a r " ]
assert_equal " b a r " [ r get key]
}
2010-08-04 11:02:13 -04:00
2023-03-19 06:56:54 -04:00
test_interactive_cli " S u b s c r i b e d m o d e " {
set reading " R e a d i n g m e s s a g e s . . . ( p r e s s C t r l - C t o q u i t o r a n y k e y t o t y p e c o m m a n d ) \r "
set erase " \033 \[ K " ; # Erases the "Reading messages..." line.
# Subscribe to some channels.
set sub1 " 1 ) \" s u b s c r i b e \" \n 2 ) \" c h 1 \" \n 3 ) ( i n t e g e r ) 1 \n "
set sub2 " 1 ) \" s u b s c r i b e \" \n 2 ) \" c h 2 \" \n 3 ) ( i n t e g e r ) 2 \n "
set sub3 " 1 ) \" s u b s c r i b e \" \n 2 ) \" c h 3 \" \n 3 ) ( i n t e g e r ) 3 \n "
assert_equal $sub1 $sub2 $sub3 $reading \
[ run_command $fd " s u b s c r i b e c h 1 c h 2 c h 3 " ]
# Receive pubsub message.
r publish ch2 hello
set message " 1 ) \" m e s s a g e \" \n 2 ) \" c h 2 \" \n 3 ) \" h e l l o \" \n "
assert_equal $erase $message $reading [ read_cli $fd ]
# Unsubscribe some.
set unsub1 " 1 ) \" u n s u b s c r i b e \" \n 2 ) \" c h 1 \" \n 3 ) ( i n t e g e r ) 2 \n "
set unsub2 " 1 ) \" u n s u b s c r i b e \" \n 2 ) \" c h 2 \" \n 3 ) ( i n t e g e r ) 1 \n "
assert_equal $erase $unsub1 $unsub2 $reading \
[ run_command $fd " u n s u b s c r i b e c h 1 c h 2 " ]
# Command forbidden in subscribed mode (RESP2).
set err " ( e r r o r ) E R R C a n ' t e x e c u t e ' g e t ' : o n l y ( P | S ) S U B S C R I B E / ( P | S ) U N S U B S C R I B E / P I N G / Q U I T / R E S E T a r e a l l o w e d i n t h i s c o n t e x t \n "
assert_equal $erase $err $reading [ run_command $fd " g e t k " ]
# Command allowed in subscribed mode.
set pong " 1 ) \" p o n g \" \n 2 ) \" \" \n "
assert_equal $erase $pong $reading [ run_command $fd " p i n g " ]
# Reset exits subscribed mode.
assert_equal $ { erase } RESET [ run_command $fd " r e s e t " ]
assert_equal PONG [ run_command $fd " p i n g " ]
# Check TTY output of push messages in RESP3 has ")" prefix (to be changed to ">" in the future).
assert_match " 1 # * " [ run_command $fd " h e l l o 3 " ]
set sub1 " 1 ) \" s u b s c r i b e \" \n 2 ) \" c h 1 \" \n 3 ) ( i n t e g e r ) 1 \n "
assert_equal $sub1 $reading \
[ run_command $fd " s u b s c r i b e c h 1 " ]
}
test_interactive_nontty_cli " S u b s c r i b e d m o d e " {
# Raw output and no "Reading messages..." info message.
# Use RESP3 in this test case.
assert_match { * proto 3 * } [ run_command $fd " h e l l o 3 " ]
# Subscribe to some channels.
set sub1 " s u b s c r i b e \n c h 1 \n 1 "
set sub2 " s u b s c r i b e \n c h 2 \n 2 "
assert_equal $sub1 \ n$sub2 \
[ run_command $fd " s u b s c r i b e c h 1 c h 2 " ]
assert_equal OK [ run_command $fd " c l i e n t t r a c k i n g o n " ]
assert_equal OK [ run_command $fd " s e t k 4 2 " ]
assert_equal 42 [ run_command $fd " g e t k " ]
# Interleaving invalidate and pubsub messages.
r publish ch1 hello
r del k
r publish ch2 world
set message1 " m e s s a g e \n c h 1 \n h e l l o "
set invalidate " i n v a l i d a t e \n k "
set message2 " m e s s a g e \n c h 2 \n w o r l d "
assert_equal $message1 \ n$invalidate \ n$message2 \ n [ read_cli $fd ]
# Unsubscribe all.
set unsub1 " u n s u b s c r i b e \n c h 1 \n 1 "
set unsub2 " u n s u b s c r i b e \n c h 2 \n 0 "
assert_equal $unsub1 \ n$unsub2 [ run_command $fd " u n s u b s c r i b e c h 1 c h 2 " ]
}
2010-08-04 11:16:05 -04:00
test_tty_cli " S t a t u s r e p l y " {
2020-07-10 03:25:55 -04:00
assert_equal " O K " [ run_cli set key bar]
2010-08-04 11:02:13 -04:00
assert_equal " b a r " [ r get key]
}
2010-08-04 11:16:05 -04:00
test_tty_cli " I n t e g e r r e p l y " {
2010-08-04 11:02:13 -04:00
r del counter
2020-07-10 03:25:55 -04:00
assert_equal " ( i n t e g e r ) 1 " [ run_cli incr counter]
2010-08-04 11:02:13 -04:00
}
2010-08-04 11:16:05 -04:00
test_tty_cli " B u l k r e p l y " {
2010-08-04 11:02:13 -04:00
r set key " t a b \t n e w l i n e \n "
2020-07-10 03:25:55 -04:00
assert_equal " \" t a b \\ t n e w l i n e \\ n \" " [ run_cli get key]
2010-08-04 11:02:13 -04:00
}
2010-08-04 11:16:05 -04:00
test_tty_cli " M u l t i - b u l k r e p l y " {
2010-08-04 11:02:13 -04:00
r del list
r rpush list foo
r rpush list bar
2020-07-10 03:25:55 -04:00
assert_equal " 1 ) \" f o o \" \n 2 ) \" b a r \" " [ run_cli lrange list 0 - 1 ]
2010-08-04 11:02:13 -04:00
}
2010-08-04 11:46:56 -04:00
2010-08-25 08:48:50 -04:00
test_tty_cli " R e a d l a s t a r g u m e n t f r o m p i p e " {
2021-12-30 05:10:04 -05:00
assert_equal " O K " [ run_cli_with_input_pipe x " e c h o f o o " set key]
2010-08-25 08:48:50 -04:00
assert_equal " f o o \n " [ r get key]
2021-12-30 05:10:04 -05:00
assert_equal " O K " [ run_cli_with_input_pipe X " e c h o f o o " set key2 tag]
assert_equal " f o o \n " [ r get key2]
2010-08-25 08:48:50 -04:00
}
test_tty_cli " R e a d l a s t a r g u m e n t f r o m f i l e " {
set tmpfile [ write_tmpfile " f r o m f i l e " ]
2021-12-30 05:10:04 -05:00
assert_equal " O K " [ run_cli_with_input_file x $tmpfile set key]
2010-08-25 08:48:50 -04:00
assert_equal " f r o m f i l e " [ r get key]
2021-12-30 05:10:04 -05:00
assert_equal " O K " [ run_cli_with_input_file X $tmpfile set key2 tag]
assert_equal " f r o m f i l e " [ r get key2]
2020-09-09 05:30:43 -04:00
file delete $tmpfile
2010-08-25 08:48:50 -04:00
}
redis-cli: Better --json Unicode support and --quoted-json (#10286)
Normally, `redis-cli` escapes non-printable data received from Redis, using a custom scheme (which is also used to handle quoted input). When using `--json` this is not desired as it is not compatible with RFC 7159, which specifies JSON strings are assumed to be Unicode and how they should be escaped.
This commit changes `--json` to follow RFC 7159, which means that properly encoded Unicode strings in Redis will result with a valid Unicode JSON.
However, this introduces a new problem with `--json` and data that is not valid Unicode (e.g., random binary data, text that follows other encoding, etc.). To address this, we add `--quoted-json` which produces JSON strings that follow the original redis-cli quoting scheme.
For example, a value that consists of only null (0x00) bytes will show up as:
* `"\u0000\u0000\u0000"` when using `--json`
* `"\\x00\\x00\\x00"` when using `--quoted-json`
2022-03-05 14:25:52 -05:00
test_tty_cli " E s c a p e c h a r a c t e r i n J S O N m o d e " {
# reverse solidus
r hset solidus \ / \ /
assert_equal \ / \ / [ run_cli hgetall solidus]
set escaped_reverse_solidus \ " \\ "
assert_equal $escaped_reverse_solidus $escaped_reverse_solidus [ run_cli - - json hgetall \ / ]
# non printable (0xF0 in ISO-8859-1, not UTF-8(0xC3 0xB0))
2022-03-06 06:02:35 -05:00
set eth " \u 0 0 f 0 \u 0 0 6 5 "
redis-cli: Better --json Unicode support and --quoted-json (#10286)
Normally, `redis-cli` escapes non-printable data received from Redis, using a custom scheme (which is also used to handle quoted input). When using `--json` this is not desired as it is not compatible with RFC 7159, which specifies JSON strings are assumed to be Unicode and how they should be escaped.
This commit changes `--json` to follow RFC 7159, which means that properly encoded Unicode strings in Redis will result with a valid Unicode JSON.
However, this introduces a new problem with `--json` and data that is not valid Unicode (e.g., random binary data, text that follows other encoding, etc.). To address this, we add `--quoted-json` which produces JSON strings that follow the original redis-cli quoting scheme.
For example, a value that consists of only null (0x00) bytes will show up as:
* `"\u0000\u0000\u0000"` when using `--json`
* `"\\x00\\x00\\x00"` when using `--quoted-json`
2022-03-05 14:25:52 -05:00
r hset eth test $eth
assert_equal \ " \\ x f 0 e \" [ r u n _ c l i h g e t e t h t e s t ]
2022-03-06 06:02:35 -05:00
assert_equal \ " \u 0 0 f 0 e \" [ r u n _ c l i - - j s o n h g e t e t h t e s t ]
redis-cli: Better --json Unicode support and --quoted-json (#10286)
Normally, `redis-cli` escapes non-printable data received from Redis, using a custom scheme (which is also used to handle quoted input). When using `--json` this is not desired as it is not compatible with RFC 7159, which specifies JSON strings are assumed to be Unicode and how they should be escaped.
This commit changes `--json` to follow RFC 7159, which means that properly encoded Unicode strings in Redis will result with a valid Unicode JSON.
However, this introduces a new problem with `--json` and data that is not valid Unicode (e.g., random binary data, text that follows other encoding, etc.). To address this, we add `--quoted-json` which produces JSON strings that follow the original redis-cli quoting scheme.
For example, a value that consists of only null (0x00) bytes will show up as:
* `"\u0000\u0000\u0000"` when using `--json`
* `"\\x00\\x00\\x00"` when using `--quoted-json`
2022-03-05 14:25:52 -05:00
assert_equal \ " \\ \\ x f 0 e \" [ r u n _ c l i - - q u o t e d - j s o n h g e t e t h t e s t ]
# control characters
r hset control test " H e l l o \x 0 0 \x 0 1 \x 0 2 \x 0 3 W o r l d "
assert_equal \ " H e l l o \\ u 0 0 0 0 \\ u 0 0 0 1 \\ u 0 0 0 2 \\ u 0 0 0 3 W o r l d " [ run_cli - - json hget control test]
# non-string keys
r hset numkey 1 One
assert_equal \ { \ " 1 \" : \" O n e \" \} [ r u n _ c l i - - j s o n h g e t a l l n u m k e y ]
# non-string, non-printable keys
2022-03-06 06:02:35 -05:00
r hset npkey " K \u 0 0 0 0 \u 0 0 0 1 e y " " V \u 0 0 0 0 \u 0 0 0 1 a l u e "
redis-cli: Better --json Unicode support and --quoted-json (#10286)
Normally, `redis-cli` escapes non-printable data received from Redis, using a custom scheme (which is also used to handle quoted input). When using `--json` this is not desired as it is not compatible with RFC 7159, which specifies JSON strings are assumed to be Unicode and how they should be escaped.
This commit changes `--json` to follow RFC 7159, which means that properly encoded Unicode strings in Redis will result with a valid Unicode JSON.
However, this introduces a new problem with `--json` and data that is not valid Unicode (e.g., random binary data, text that follows other encoding, etc.). To address this, we add `--quoted-json` which produces JSON strings that follow the original redis-cli quoting scheme.
For example, a value that consists of only null (0x00) bytes will show up as:
* `"\u0000\u0000\u0000"` when using `--json`
* `"\\x00\\x00\\x00"` when using `--quoted-json`
2022-03-05 14:25:52 -05:00
assert_equal \ { \ " K \\ u 0 0 0 0 \\ u 0 0 0 1 e y \" : \" V \\ u 0 0 0 0 \\ u 0 0 0 1 a l u e \" \} [ r u n _ c l i - - j s o n h g e t a l l n p k e y ]
assert_equal \ { \ " K \\ \\ x 0 0 \\ \\ x 0 1 e y \" : \" V \\ \\ x 0 0 \\ \\ x 0 1 a l u e \" \} [ r u n _ c l i - - q u o t e d - j s o n h g e t a l l n p k e y ]
}
2010-08-04 11:46:56 -04:00
test_nontty_cli " S t a t u s r e p l y " {
2010-08-25 08:15:41 -04:00
assert_equal " O K " [ run_cli set key bar]
2010-08-04 11:46:56 -04:00
assert_equal " b a r " [ r get key]
}
test_nontty_cli " I n t e g e r r e p l y " {
r del counter
2010-08-25 08:15:41 -04:00
assert_equal " 1 " [ run_cli incr counter]
2010-08-04 11:46:56 -04:00
}
test_nontty_cli " B u l k r e p l y " {
r set key " t a b \t n e w l i n e \n "
2020-07-10 03:25:55 -04:00
assert_equal " t a b \t n e w l i n e " [ run_cli get key]
2010-08-04 11:46:56 -04:00
}
test_nontty_cli " M u l t i - b u l k r e p l y " {
r del list
r rpush list foo
r rpush list bar
2010-08-25 08:15:41 -04:00
assert_equal " f o o \n b a r " [ run_cli lrange list 0 - 1 ]
2010-08-04 11:46:56 -04:00
}
2010-08-25 08:48:50 -04:00
2021-08-03 16:19:03 -04:00
if { ! $::tls } { ; # fake_redis_node doesn't support TLS
2021-08-02 07:59:08 -04:00
test_nontty_cli " A S K r e d i r e c t t e s t " {
# Set up two fake Redis nodes.
set tclsh [ info nameofexecutable]
set script " t e s t s / h e l p e r s / f a k e _ r e d i s _ n o d e . t c l "
set port1 [ find_available_port $::baseport $::portcount ]
set port2 [ find_available_port $::baseport $::portcount ]
set p1 [ exec $tclsh $script $port1 \
" S E T f o o b a r " " - A S K 1 2 1 8 2 1 2 7 . 0 . 0 . 1 : $ p o r t 2 " & ]
set p2 [ exec $tclsh $script $port2 \
" A S K I N G " " + O K " \
" S E T f o o b a r " " + O K " & ]
2021-08-05 01:20:30 -04:00
# Make sure both fake nodes have started listening
wait_for_condition 50 50 {
[ catch { close [ socket " 1 2 7 . 0 . 0 . 1 " $port1 ] } ] == 0 && \
[ catch { close [ socket " 1 2 7 . 0 . 0 . 1 " $port2 ] } ] == 0
} else {
fail " F a i l e d t o s t a r t f a k e R e d i s n o d e s "
}
2021-08-02 07:59:08 -04:00
# Run the cli
assert_equal " O K " [ run_cli_host_port_db " 1 2 7 . 0 . 0 . 1 " $port1 0 - c SET foo bar]
}
2021-08-03 16:19:03 -04:00
}
2021-08-02 07:59:08 -04:00
2021-03-04 08:03:49 -05:00
test_nontty_cli " Q u o t e d i n p u t a r g u m e n t s " {
r set " \x 0 0 \x 0 0 " " v a l u e "
assert_equal " v a l u e " [ run_cli - - quoted-input get { " \x 0 0 \x 0 0 " } ]
}
test_nontty_cli " N o a c c i d e n t a l u n q u o t i n g o f i n p u t a r g u m e n t s " {
run_cli - - quoted-input set { " \x 4 1 \x 4 1 " } quoted-val
run_cli set { " \x 4 1 \x 4 1 " } unquoted-val
assert_equal " q u o t e d - v a l " [ r get AA]
assert_equal " u n q u o t e d - v a l " [ r get { " \x 4 1 \x 4 1 " } ]
}
test_nontty_cli " I n v a l i d q u o t e d i n p u t a r g u m e n t s " {
catch { run_cli - - quoted-input set { " U n t e r m i n a t e d } } e r r
assert_match { * exited abnormally* } $err
# A single arg that unquotes to two arguments is also not expected
catch { run_cli - - quoted-input set { " a r g 1 " " a r g 2 " } } err
assert_match { * exited abnormally* } $err
}
2010-08-25 08:48:50 -04:00
test_nontty_cli " R e a d l a s t a r g u m e n t f r o m p i p e " {
2021-12-30 05:10:04 -05:00
assert_equal " O K " [ run_cli_with_input_pipe x " e c h o f o o " set key]
2010-08-25 08:48:50 -04:00
assert_equal " f o o \n " [ r get key]
2021-12-30 05:10:04 -05:00
assert_equal " O K " [ run_cli_with_input_pipe X " e c h o f o o " set key2 tag]
assert_equal " f o o \n " [ r get key2]
2010-08-25 08:48:50 -04:00
}
test_nontty_cli " R e a d l a s t a r g u m e n t f r o m f i l e " {
set tmpfile [ write_tmpfile " f r o m f i l e " ]
2021-12-30 05:10:04 -05:00
assert_equal " O K " [ run_cli_with_input_file x $tmpfile set key]
2010-08-25 08:48:50 -04:00
assert_equal " f r o m f i l e " [ r get key]
2021-12-30 05:10:04 -05:00
assert_equal " O K " [ run_cli_with_input_file X $tmpfile set key2 tag]
assert_equal " f r o m f i l e " [ r get key2]
2020-09-09 05:30:43 -04:00
file delete $tmpfile
2010-08-25 08:48:50 -04:00
}
2020-07-10 03:25:55 -04:00
2022-01-02 02:39:01 -05:00
proc test_redis_cli_rdb_dump { functions_only } {
2020-07-10 03:25:55 -04:00
r flushdb
2022-01-02 02:39:01 -05:00
r function flush
2020-07-10 03:25:55 -04:00
set dir [ lindex [ r config get dir] 1 ]
assert_equal " O K " [ r debug populate 100000 key 1000 ]
2022-04-05 03:27:24 -04:00
assert_equal " l i b 1 " [ r function load " # ! l u a n a m e = l i b 1 \n r e d i s . r e g i s t e r _ f u n c t i o n ( ' f u n c 1 ' , f u n c t i o n ( ) r e t u r n 1 2 3 e n d ) " ]
2022-01-02 02:39:01 -05:00
if { $functions_only } {
set args " - - f u n c t i o n s - r d b $ d i r / c l i . r d b "
} else {
set args " - - r d b $ d i r / c l i . r d b "
}
catch { run_cli { * } $args } output
2020-07-10 03:25:55 -04:00
assert_match { * Transfer finished with success* } $output
file delete " $ d i r / d u m p . r d b "
file rename " $ d i r / c l i . r d b " " $ d i r / d u m p . r d b "
assert_equal " O K " [ r set should-not-exist 1 ]
2022-04-05 03:27:24 -04:00
assert_equal " s h o u l d _ n o t _ e x i s t _ f u n c " [ r function load " # ! l u a n a m e = s h o u l d _ n o t _ e x i s t _ f u n c \n r e d i s . r e g i s t e r _ f u n c t i o n ( ' s h o u l d _ n o t _ e x i s t _ f u n c ' , f u n c t i o n ( ) r e t u r n 4 5 6 e n d ) " ]
2020-07-10 03:25:55 -04:00
assert_equal " O K " [ r debug reload nosave]
assert_equal { } [ r get should-not-exist]
2022-04-05 03:27:24 -04:00
assert_equal { { library_name lib1 engine LUA functions { { name func1 description { } flags { } } } } } [ r function list]
2022-01-02 02:39:01 -05:00
if { $functions_only } {
assert_equal 0 [ r dbsize]
} else {
assert_equal 100000 [ r dbsize]
}
2020-07-10 03:25:55 -04:00
}
2022-01-02 02:39:01 -05:00
foreach { functions_only } { no yes} {
test " D u m p i n g a n R D B - f u n c t i o n s o n l y : $ f u n c t i o n s _ o n l y " {
2020-07-10 03:25:55 -04:00
# Disk-based master
assert_match " O K " [ r config set repl-diskless-sync no]
2022-01-02 02:39:01 -05:00
test_redis_cli_rdb_dump $functions_only
2020-07-10 03:25:55 -04:00
# Disk-less master
assert_match " O K " [ r config set repl-diskless-sync yes]
assert_match " O K " [ r config set repl-diskless-sync-delay 0 ]
2022-01-02 02:39:01 -05:00
test_redis_cli_rdb_dump $functions_only
2021-12-19 10:41:51 -05:00
} { } { needs : repl needs:debug}
2020-07-10 03:25:55 -04:00
2022-01-02 02:39:01 -05:00
} ; # foreach functions_only
2021-03-04 08:03:49 -05:00
test " S c a n m o d e " {
r flushdb
populate 1000 key: 1
# basic use
assert_equal 1000 [ llength [ split [ run_cli - - scan] ] ]
# pattern
assert_equal { key : 2 } [ run_cli - - scan - - pattern " * : 2 " ]
# pattern matching with a quoted string
assert_equal { key : 2 } [ run_cli - - scan - - quoted-pattern { " * : \x 3 2 " } ]
}
2021-07-07 01:26:26 -04:00
proc test_redis_cli_repl { } {
2020-07-10 03:25:55 -04:00
set fd [ open_cli " - - r e p l i c a " ]
2021-07-07 01:26:26 -04:00
wait_for_condition 500 100 {
2020-07-10 03:25:55 -04:00
[ string match { * slave0 : * state= online* } [ r info] ]
} else {
fail " r e d i s - c l i - - r e p l i c a d i d n o t c o n n e c t "
}
for { set i 0 } { $i < 100 } { incr i} {
r set test-key test-value-$i
}
2021-07-07 01:26:26 -04:00
wait_for_condition 500 100 {
[ string match { * test-value-99 * } [ read_cli $fd ] ]
} else {
fail " r e d i s - c l i - - r e p l i c a d i d n ' t r e a d c o m m a n d s "
2020-07-10 03:25:55 -04:00
}
2021-07-07 01:26:26 -04:00
fconfigure $fd - blocking true
r client kill type slave
catch { close_cli $fd } err
assert_match { * Server closed the connection* } $err
}
test " C o n n e c t i n g a s a r e p l i c a " {
# Disk-based master
assert_match " O K " [ r config set repl-diskless-sync no]
test_redis_cli_repl
# Disk-less master
assert_match " O K " [ r config set repl-diskless-sync yes]
assert_match " O K " [ r config set repl-diskless-sync-delay 0 ]
test_redis_cli_repl
2021-06-09 08:13:24 -04:00
} { } { needs : repl}
2020-07-10 03:25:55 -04:00
2020-07-21 07:17:14 -04:00
test " P i p i n g r a w p r o t o c o l " {
set cmds [ tmpfile " c l i _ c m d s " ]
set cmds_fd [ open $cmds " w " ]
2020-07-10 03:25:55 -04:00
2021-06-09 08:13:24 -04:00
set cmds_count 2101
if { ! $::singledb } {
puts $cmds_fd [ formatCommand select 9 ]
incr cmds_count
}
2020-07-21 07:17:14 -04:00
puts $cmds_fd [ formatCommand del test-counter]
2020-07-10 03:25:55 -04:00
2020-07-21 07:17:14 -04:00
for { set i 0 } { $i < 1000 } { incr i} {
puts $cmds_fd [ formatCommand incr test-counter]
puts $cmds_fd [ formatCommand set large-key [ string repeat " x " 20000 ] ]
2020-07-10 03:25:55 -04:00
}
2020-07-21 07:17:14 -04:00
for { set i 0 } { $i < 100 } { incr i} {
puts $cmds_fd [ formatCommand set very-large-key [ string repeat " x " 512000 ] ]
2020-07-10 03:25:55 -04:00
}
2020-07-21 07:17:14 -04:00
close $cmds_fd
2020-07-10 03:25:55 -04:00
2020-07-21 07:17:14 -04:00
set cli_fd [ open_cli " - - p i p e " $cmds ]
fconfigure $cli_fd - blocking true
set output [ read_cli $cli_fd ]
2020-07-10 03:25:55 -04:00
2020-07-21 07:17:14 -04:00
assert_equal { 1000 } [ r get test-counter]
2021-06-09 08:13:24 -04:00
assert_match " * A l l d a t a t r a n s f e r r e d * e r r o r s : 0 * r e p l i e s : $ { c m d s _ c o u n t } * " $output
2020-07-10 03:25:55 -04:00
2020-07-21 07:17:14 -04:00
file delete $cmds
2020-07-10 03:25:55 -04:00
}
2021-12-30 05:10:04 -05:00
test " O p t i o n s - X w i t h i l l e g a l a r g u m e n t " {
assert_error " * - x a n d - X a r e m u t u a l l y e x c l u s i v e * " { run_cli - x - X tag}
assert_error " * U n r e c o g n i z e d o p t i o n o r b a d n u m b e r * " { run_cli - X}
assert_error " * t a g n o t m a t c h * " { run_cli_with_input_pipe X " e c h o f o o " set key wrong_tag}
}
2022-01-02 06:58:22 -05:00
test " D U M P R E S T O R E w i t h - x o p t i o n " {
set cmdline [ rediscli [ srv host] [ srv port] ]
exec { * } $cmdline DEL set new_set
exec { * } $cmdline SADD set 1 2 3 4 5 6
assert_equal 6 [ exec { * } $cmdline SCARD set]
assert_equal " O K " [ exec { * } $cmdline - D " " - - raw DUMP set | \
{ * } $cmdline -x RESTORE new_set 0 ]
assert_equal 6 [ exec { * } $cmdline SCARD new_set]
assert_equal " 1 \n 2 \n 3 \n 4 \n 5 \n 6 " [ exec { * } $cmdline SMEMBERS new_set]
}
test " D U M P R E S T O R E w i t h - X o p t i o n " {
set cmdline [ rediscli [ srv host] [ srv port] ]
exec { * } $cmdline DEL zset new_zset
exec { * } $cmdline ZADD zset 1 a 2 b 3 c
assert_equal 3 [ exec { * } $cmdline ZCARD zset]
assert_equal " O K " [ exec { * } $cmdline - D " " - - raw DUMP zset | \
{ * } $cmdline -X dump_tag RESTORE new_zset 0 dump_tag REPLACE]
assert_equal 3 [ exec { * } $cmdline ZCARD new_zset]
assert_equal " a \n 1 \n b \n 2 \n c \n 3 " [ exec { * } $cmdline ZRANGE new_zset 0 - 1 WITHSCORES]
}
2010-08-04 08:15:52 -04:00
}