Skip to content
GitLab
Menu
Projects
Groups
Snippets
Loading...
Help
Help
Support
Community forum
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in / Register
Toggle navigation
Menu
Open sidebar
ruanhaishen
hiredis
Commits
aa1b9c12
Commit
aa1b9c12
authored
Jan 05, 2012
by
Pieter Noordhuis
Browse files
Test write timeout on context
parent
300b3d32
Changes
8
Hide whitespace changes
Inline
Side-by-side
context.c
View file @
aa1b9c12
...
...
@@ -129,9 +129,22 @@ int redis_context_flush(redis_context *ctx) {
while
(
!
drained
)
{
rv
=
redis_handle_write_from_buffer
(
&
ctx
->
handle
,
&
drained
);
if
(
rv
!=
REDIS_OK
)
{
return
rv
;
if
(
rv
==
REDIS_OK
)
{
continue
;
}
/* Wait for the socket to become writable on EAGAIN */
if
(
rv
==
REDIS_ESYS
&&
errno
==
EAGAIN
)
{
rv
=
redis_handle_wait_writable
(
&
ctx
->
handle
);
if
(
rv
!=
REDIS_OK
)
{
return
rv
;
}
continue
;
}
return
rv
;
}
return
REDIS_OK
;
...
...
test/Makefile
View file @
aa1b9c12
include
../Makefile.common
TESTS
=
test-format test-parser test-object test-handle test-context
OBJ
=
spawn.o net-helper.o
all
:
$(TESTS)
../$(STLIBNAME)
:
cd
..
&&
$(MAKE)
$(STLIBNAME)
test-%
:
test-%.o ../$(STLIBNAME)
test-%
:
test-%.o
$(OBJ)
../$(STLIBNAME)
$(CC)
-o
$@
$(REAL_LDFLAGS)
$^
.c.o
:
...
...
test/net-helper.c
0 → 100644
View file @
aa1b9c12
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <errno.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/tcp.h>
#include "net-helper.h"
void
accept_and_ignore
(
void
*
ptr
)
{
accept_and_ignore_args
*
args
=
ptr
;
int
fd
,
rv
;
fd
=
socket
(
args
->
address
.
sa_family
,
SOCK_STREAM
,
0
);
if
(
fd
==
-
1
)
{
fprintf
(
stderr
,
"socket: %s
\n
"
,
strerror
(
errno
));
exit
(
1
);
}
rv
=
bind
(
fd
,
&
args
->
address
.
sa_addr
.
addr
,
args
->
address
.
sa_addrlen
);
if
(
rv
==
-
1
)
{
fprintf
(
stderr
,
"bind: %s
\n
"
,
strerror
(
errno
));
exit
(
1
);
}
rv
=
listen
(
fd
,
128
);
if
(
rv
==
-
1
)
{
fprintf
(
stderr
,
"listen: %s
\n
"
,
strerror
(
errno
));
exit
(
1
);
}
while
(
1
)
{
redis_address
remote
;
remote
.
sa_addrlen
=
sizeof
(
remote
.
sa_addr
);
rv
=
accept
(
fd
,
&
remote
.
sa_addr
.
addr
,
&
remote
.
sa_addrlen
);
if
(
rv
==
-
1
)
{
fprintf
(
stderr
,
"accept: %s
\n
"
,
strerror
(
errno
));
exit
(
1
);
}
/* Ignore the new connection */
}
}
test/net-helper.h
0 → 100644
View file @
aa1b9c12
#ifndef TEST_NET_HELPER
#define TEST_NET_HELPER 1
#include "../handle.h"
typedef
struct
accept_and_ignore_args_s
accept_and_ignore_args
;
struct
accept_and_ignore_args_s
{
redis_address
address
;
};
void
accept_and_ignore
(
void
*
ptr
);
#endif
test/spawn.c
0 → 100644
View file @
aa1b9c12
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <errno.h>
#include <unistd.h>
#include <sys/wait.h>
#include <signal.h>
#include <assert.h>
#include "spawn.h"
int
pidc
=
0
;
pid_t
*
pidv
=
NULL
;
void
spawn_init
(
void
)
{
assert
(
pidc
==
0
);
assert
(
pidv
==
NULL
);
}
void
spawn_destroy
(
void
)
{
pid_t
pid
;
int
i
;
int
rv
;
/* Kill children */
for
(
i
=
0
;
i
<
pidc
;
i
++
)
{
int
status
;
pid
=
waitpid
(
pidv
[
i
],
&
status
,
WNOHANG
);
if
(
pid
)
{
continue
;
}
rv
=
kill
(
pidv
[
i
],
SIGKILL
);
if
(
rv
==
-
1
)
{
fprintf
(
stderr
,
"kill: %s
\n
"
,
strerror
(
errno
));
exit
(
1
);
}
pid
=
waitpid
(
pidv
[
i
],
&
status
,
0
);
assert
(
pid
==
pidv
[
i
]);
}
free
(
pidv
);
pidc
=
0
;
pidv
=
NULL
;
}
void
spawn
(
spawn_function
*
fn
,
void
*
ptr
)
{
pid_t
pid
;
pid
=
fork
();
if
(
pid
)
{
pidv
=
realloc
(
pidv
,
sizeof
(
pid_t
)
*
(
pidc
+
1
));
pidv
[
pidc
++
]
=
pid
;
}
else
{
fn
(
ptr
);
exit
(
0
);
}
/* Give the fork some time to boot... */
usleep
(
1000
);
}
test/spawn.h
0 → 100644
View file @
aa1b9c12
#ifndef TEST_SPAWN_H
#define TEST_SPAWN_H 1
typedef
void
(
spawn_function
)(
void
*
);
void
spawn_init
(
void
);
void
spawn_destroy
(
void
);
void
spawn
(
spawn_function
*
fn
,
void
*
ptr
);
#endif
test/test-context.c
View file @
aa1b9c12
...
...
@@ -19,6 +19,7 @@
#include "../context.h"
#include "../object.h"
#include "test-helper.h"
#include "net-helper.h"
#define SETUP_CONNECT() \
redis_context c; \
...
...
@@ -32,6 +33,7 @@ TEST(connect_in_refused) {
SETUP_CONNECT
();
struct
sockaddr_in
sa
;
memset
(
&
sa
,
0
,
sizeof
(
sa
));
sa
.
sin_family
=
AF_INET
;
sa
.
sin_port
=
htons
(
redis_port
()
+
1
);
assert
(
inet_pton
(
AF_INET
,
"127.0.0.1"
,
&
sa
.
sin_addr
)
==
1
);
...
...
@@ -50,6 +52,7 @@ TEST(connect_in6_refused) {
SETUP_CONNECT
();
struct
sockaddr_in6
sa
;
memset
(
&
sa
,
0
,
sizeof
(
sa
));
sa
.
sin6_family
=
AF_INET6
;
sa
.
sin6_port
=
htons
(
redis_port
()
+
1
);
assert
(
inet_pton
(
AF_INET6
,
"::1"
,
&
sa
.
sin6_addr
)
==
1
);
...
...
@@ -68,6 +71,7 @@ TEST(connect_un_noent) {
SETUP_CONNECT
();
struct
sockaddr_un
sa
;
memset
(
&
sa
,
0
,
sizeof
(
sa
));
sa
.
sun_family
=
AF_LOCAL
;
strcpy
((
char
*
)
&
sa
.
sun_path
,
"/tmp/idontexist.sock"
);
...
...
@@ -85,6 +89,7 @@ TEST(connect_timeout) {
SETUP_CONNECT
();
struct
sockaddr_in
sa
;
memset
(
&
sa
,
0
,
sizeof
(
sa
));
sa
.
sin_family
=
AF_INET
;
sa
.
sin_port
=
htons
(
redis_port
());
assert
(
inet_pton
(
AF_INET
,
"10.255.255.254"
,
&
sa
.
sin_addr
)
==
1
);
...
...
@@ -108,6 +113,7 @@ TEST(connect_success) {
SETUP_CONNECT
();
struct
sockaddr_in
sa
;
memset
(
&
sa
,
0
,
sizeof
(
sa
));
sa
.
sin_family
=
AF_INET
;
sa
.
sin_port
=
htons
(
redis_port
());
assert
(
inet_pton
(
AF_INET
,
"127.0.0.1"
,
&
sa
.
sin_addr
)
==
1
);
...
...
@@ -269,6 +275,42 @@ TEST(call_command_argv) {
redis_context_destroy
(
&
c
);
}
TEST
(
flush_against_full_kernel_buffer
)
{
SETUP_CONNECT
();
struct
sockaddr_in
sa
;
memset
(
&
sa
,
0
,
sizeof
(
sa
));
sa
.
sin_family
=
AF_INET
;
sa
.
sin_port
=
htons
(
redis_port
()
+
1
);
assert
(
inet_pton
(
AF_INET
,
"127.0.0.1"
,
&
sa
.
sin_addr
)
==
1
);
accept_and_ignore_args
args
;
args
.
address
.
sa_family
=
sa
.
sin_family
;
args
.
address
.
sa_addrlen
=
sizeof
(
sa
);
args
.
address
.
sa_addr
.
in
=
sa
;
spawn
(
accept_and_ignore
,
&
args
);
rv
=
redis_context_connect_in
(
&
c
,
sa
);
assert_equal_return
(
rv
,
REDIS_OK
);
/* Now write and flush until error */
while
(
1
)
{
rv
=
redis_context_write_command
(
&
c
,
"ping"
);
assert_equal_return
(
rv
,
REDIS_OK
);
rv
=
redis_context_flush
(
&
c
);
if
(
rv
!=
REDIS_OK
)
{
break
;
}
}
/* When the write buffer cannot be flushed, the operation should time out
* instead of directly returning EAGAIN to the caller */
assert_equal_int
(
rv
,
REDIS_ESYS
);
assert_equal_int
(
errno
,
ETIMEDOUT
);
}
int
main
(
void
)
{
test_connect_in_refused
();
test_connect_in6_refused
();
...
...
@@ -283,4 +325,5 @@ int main(void) {
test_write_command_argv
();
test_call_command
();
test_call_command_argv
();
test_flush_against_full_kernel_buffer
();
}
test/test-helper.h
View file @
aa1b9c12
...
...
@@ -14,6 +14,7 @@
#include <netdb.h>
/* local */
#include "spawn.h"
#include "../handle.h"
/******************************************************************************/
...
...
@@ -103,7 +104,9 @@ static const char *current_test = NULL;
static void test__##name(void); \
static void test_##name(void) { \
current_test = #name; \
spawn_init(); \
test__##name(); \
spawn_destroy(); \
printf("%s: PASSED\n", current_test); \
} \
static void test__##name(void)
...
...
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
.
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment