Skip to content
GitLab
Menu
Projects
Groups
Snippets
Loading...
Help
Help
Support
Community forum
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in
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