99
1010namespace Garnet . test
1111{
12+ [ NonParallelizable ]
1213 [ TestFixture ]
1314 public class InlineCommandlineTests
1415 {
@@ -33,15 +34,16 @@ public void Setup()
3334 public void TearDown ( )
3435 {
3536 server . Dispose ( ) ;
37+ client . Close ( ) ;
3638 client . Dispose ( ) ;
3739 TestUtils . DeleteDirectory ( TestUtils . MethodTestDir ) ;
3840 }
3941
4042 private async Task < string > Send ( string message , string suffix = "\r \n " )
4143 {
42- _ = await client . SendAsync ( Encoding . UTF8 . GetBytes ( message + suffix ) ) ;
44+ _ = await client . SendAsync ( Encoding . ASCII . GetBytes ( message + suffix ) ) ;
4345 var received = await client . ReceiveAsync ( buffer , SocketFlags . None ) ;
44- return Encoding . UTF8 . GetString ( buffer , 0 , received ) ;
46+ return Encoding . ASCII . GetString ( buffer , 0 , received ) ;
4547 }
4648
4749 [ Test ]
@@ -72,7 +74,7 @@ public async Task InlineCommandParseTest()
7274 // Should fail due to missing argument. We test such failures to ensure
7375 // readhead is not messed up and commands can be placed afterwards.
7476 response = await Send ( "CLIENT" ) ;
75- ClassicAssert . AreEqual ( '-' , response [ 0 ] ) ;
77+ ClassicAssert . AreEqual ( "-ERR wrong number of arguments for 'CLIENT' command \r \n " , response ) ;
7678
7779 // Test client name was actually set
7880 response = await Send ( "CLIENT GETNAME" ) ;
@@ -86,15 +88,15 @@ public async Task InlineCommandParseTest()
8688 response = await Send ( "PING\n PING" ) ;
8789 ClassicAssert . AreEqual ( "+PONG\r \n +PONG\r \n " , response ) ;
8890 // CR is a valid separator
89- response = await Send ( "PING\r PING" ) ;
91+ response = await Send ( "PING\r PING" , " \n " ) ;
9092 ClassicAssert . AreEqual ( "$4\r \n PING\r \n " , response ) ;
9193 // As is TAB
9294 response = await Send ( "PING\t PING" ) ;
9395 ClassicAssert . AreEqual ( "$4\r \n PING\r \n " , response ) ;
9496
9597 // Test command failure
9698 response = await Send ( "PIN" ) ;
97- ClassicAssert . AreEqual ( '-' , response [ 0 ] ) ;
99+ ClassicAssert . AreEqual ( "-ERR unknown command \r \n " , response ) ;
98100
99101 // Test ordinary commands
100102 response = await Send ( $ "SET { key } { value } ") ;
@@ -108,7 +110,7 @@ public async Task InlineCommandParseTest()
108110
109111 // Test command failure in normal RESP doesn't interfere
110112 response = await Send ( "*1\r \n $3\r \n PIN" ) ;
111- ClassicAssert . AreEqual ( '-' , response [ 0 ] ) ;
113+ ClassicAssert . AreEqual ( "-ERR unknown command \r \n " , response ) ;
112114
113115 // Test quit
114116 response = await Send ( "QUIT" ) ;
@@ -137,7 +139,7 @@ public async Task InlineCommandEscapeTest()
137139
138140 // This should lead to quoting failure
139141 response = await Send ( @"PING ""\\\""" ) ;
140- ClassicAssert . AreEqual ( '-' , response [ 0 ] ) ;
142+ ClassicAssert . AreEqual ( "-ERR Protocol error: unbalanced quotes in request \r \n " , response ) ;
141143 // This should work
142144 response = await Send ( @"PING ""\\\\""" ) ;
143145 ClassicAssert . AreEqual ( "$2\r \n \\ \\ \r \n " , response ) ;
@@ -158,6 +160,7 @@ public async Task InlineCommandEscapeTest()
158160 // Test escapes in command position
159161 response = await Send ( @"""\x50\x49\x4E\x47""" ) ;
160162 ClassicAssert . AreEqual ( "+PONG\r \n " , response ) ;
163+ // Test escapes for lowercase characters
161164 response = await Send ( @"""P\i\x6Eg""" ) ;
162165 ClassicAssert . AreEqual ( "+PONG\r \n " , response ) ;
163166
@@ -181,7 +184,7 @@ public async Task InlineCommandQuoteTest()
181184 // We need to test failures too to be sure readHead is reset right,
182185 // and that there are no leftovers that would interfere with future commands.
183186 response = await Send ( "PING 'unfinished quote" ) ;
184- ClassicAssert . AreEqual ( '-' , response [ 0 ] ) ;
187+ ClassicAssert . AreEqual ( "-ERR Protocol error: unbalanced quotes in request \r \n " , response ) ;
185188
186189 // Test empty and short strings
187190 response = await Send ( "ECHO ''" ) ;
@@ -191,7 +194,7 @@ public async Task InlineCommandQuoteTest()
191194 ClassicAssert . AreEqual ( "$1\r \n a\r \n " , response ) ;
192195
193196 // We can even accept commands formed like this
194- response = await Send ( "\" PING\" \t word " ) ;
197+ response = await Send ( "\" PING\" word " ) ;
195198 ClassicAssert . AreEqual ( "$4\r \n word\r \n " , response ) ;
196199 response = await Send ( "PINg \" hello 'world'!\" " ) ;
197200 ClassicAssert . AreEqual ( "$14\r \n hello 'world'!\r \n " , response ) ;
@@ -202,5 +205,60 @@ public async Task InlineCommandQuoteTest()
202205 response = await Send ( "PING '\" '\" ''" ) ;
203206 ClassicAssert . AreEqual ( "$4\r \n \" '\" '\r \n " , response ) ;
204207 }
208+
209+ [ Test ]
210+ public async Task InlineCommandShortlinesTest ( )
211+ {
212+ var oldTimeout = client . ReceiveTimeout ;
213+ client . ReceiveTimeout = 100 ;
214+
215+ await client . ConnectAsync ( TestUtils . EndPoint ) ;
216+
217+ _ = await client . SendAsync ( Encoding . ASCII . GetBytes ( "\r \n " ) ) ;
218+ try
219+ {
220+ _ = client . Receive ( buffer ) ;
221+ Assert . Fail ( "This should timeout since buffer is not long enough" ) ;
222+ }
223+ catch ( SocketException ex )
224+ {
225+ // We expect nothing to be emitted.
226+ ClassicAssert . AreEqual ( SocketError . TimedOut , ex . SocketErrorCode ) ;
227+ }
228+
229+ _ = await client . SendAsync ( Encoding . ASCII . GetBytes ( "PI" ) ) ;
230+ try
231+ {
232+ _ = client . Receive ( buffer ) ;
233+ Assert . Fail ( "This should timeout since buffer is not long enough" ) ;
234+ }
235+ catch ( SocketException ex )
236+ {
237+ // We expect nothing to be emitted.
238+ ClassicAssert . AreEqual ( SocketError . TimedOut , ex . SocketErrorCode ) ;
239+ }
240+
241+ // Because there was no linefeed separator for "PI", we should be able to
242+ // complete the command.
243+ var response = await Send ( "NG" , "\n " ) ;
244+ ClassicAssert . AreEqual ( "+PONG\r \n " , response ) ;
245+
246+ _ = await client . SendAsync ( Encoding . ASCII . GetBytes ( "A\r \n " ) ) ;
247+ try
248+ {
249+ _ = client . Receive ( buffer ) ;
250+ Assert . Fail ( "This should timeout since buffer is not long enough" ) ;
251+ }
252+ catch ( SocketException ex )
253+ {
254+ // We expect nothing to be emitted due to minimum processing length.
255+ ClassicAssert . AreEqual ( SocketError . TimedOut , ex . SocketErrorCode ) ;
256+ }
257+
258+ response = await Send ( "PING" ) ;
259+ ClassicAssert . AreEqual ( "+PONG\r \n " , response ) ;
260+
261+ client . ReceiveTimeout = oldTimeout ;
262+ }
205263 }
206264}
0 commit comments