@ -16,8 +16,7 @@
# include "test/cpp/interop/pre_stop_hook_server.h"
# include <map>
# include <memory>
# include <thread>
# include <gmock/gmock.h>
# include <gtest/gtest.h>
@ -26,7 +25,11 @@
# include <grpc/grpc.h>
# include <grpcpp/grpcpp.h>
# include <grpcpp/support/status.h>
# include "src/core/lib/gprpp/sync.h"
# include "src/proto/grpc/testing/empty.pb.h"
# include "src/proto/grpc/testing/messages.pb.h"
# include "src/proto/grpc/testing/test.grpc.pb.h"
# include "test/core/util/port.h"
# include "test/core/util/test_config.h"
@ -44,9 +47,7 @@ struct CallInfo {
absl : : optional < Status > WaitForStatus (
absl : : Duration timeout = absl : : Seconds ( 1 ) ) {
grpc_core : : MutexLock lock ( & mu ) ;
if ( ! status_ . has_value ( ) ) {
cv . WaitWithTimeout ( & mu , timeout ) ;
}
cv . WaitWithTimeout ( & mu , timeout ) ;
return status_ ;
}
@ -62,7 +63,22 @@ struct CallInfo {
absl : : optional < Status > status_ ;
} ;
TEST ( PreStopHookServer , StartDoRequestStop ) {
void ServerLoop ( HookServiceImpl * service , int port , Server * * server ,
grpc_core : : Mutex * mu , grpc_core : : CondVar * condition ) {
ServerBuilder builder ;
builder . AddListeningPort ( absl : : StrFormat ( " 0.0.0.0:%d " , port ) ,
grpc : : InsecureServerCredentials ( ) ) ;
builder . RegisterService ( service ) ;
auto s = builder . BuildAndStart ( ) ;
{
grpc_core : : MutexLock lock ( mu ) ;
* server = s . get ( ) ;
condition - > SignalAll ( ) ;
}
s - > Wait ( ) ;
}
TEST ( StandalonePreStopHookServer , StartDoRequestStop ) {
int port = grpc_pick_unused_port_or_die ( ) ;
PreStopHookServerManager server ;
Status start_status = server . Start ( port , 15 ) ;
@ -73,8 +89,8 @@ TEST(PreStopHookServer, StartDoRequestStop) {
CallInfo info ;
HookService : : Stub stub ( std : : move ( channel ) ) ;
stub . async ( ) - > Hook ( & info . context , & info . request , & info . response ,
[ & info ] ( Status status ) { info . SetStatus ( status ) ; } ) ;
ASSERT_EQ ( server . TestOnlyExpectRequests ( 1 ) , 1 ) ;
[ & info ] ( const Status & status ) { info . SetStatus ( status ) ; } ) ;
ASSERT_TRU E ( server . TestOnlyExpectRequests ( 1 ) ) ;
server . Return ( StatusCode : : INTERNAL , " Just a test " ) ;
auto status = info . WaitForStatus ( ) ;
ASSERT_TRUE ( status . has_value ( ) ) ;
@ -82,7 +98,7 @@ TEST(PreStopHookServer, StartDoRequestStop) {
EXPECT_EQ ( status - > error_message ( ) , " Just a test " ) ;
}
TEST ( PreStopHookServer , StartServerWhileAlreadyRunning ) {
TEST ( Standalone PreStopHookServer, StartServerWhileAlreadyRunning ) {
int port = grpc_pick_unused_port_or_die ( ) ;
PreStopHookServerManager server ;
Status status = server . Start ( port , 15 ) ;
@ -92,7 +108,7 @@ TEST(PreStopHookServer, StartServerWhileAlreadyRunning) {
< < status . error_message ( ) ;
}
TEST ( PreStopHookServer , StopServerWhileRequestPending ) {
TEST ( Standalone PreStopHookServer, StopServerWhileRequestPending ) {
int port = grpc_pick_unused_port_or_die ( ) ;
PreStopHookServerManager server ;
Status start_status = server . Start ( port , 15 ) ;
@ -103,15 +119,15 @@ TEST(PreStopHookServer, StopServerWhileRequestPending) {
CallInfo info ;
HookService : : Stub stub ( std : : move ( channel ) ) ;
stub . async ( ) - > Hook ( & info . context , & info . request , & info . response ,
[ & info ] ( Status status ) { info . SetStatus ( status ) ; } ) ;
ASSERT_EQ ( server . TestOnlyExpectRequests ( 1 ) , 1 ) ;
[ & info ] ( const Status & status ) { info . SetStatus ( status ) ; } ) ;
ASSERT_TRU E ( server . TestOnlyExpectRequests ( 1 ) ) ;
ASSERT_TRUE ( server . Stop ( ) . ok ( ) ) ;
auto status = info . WaitForStatus ( ) ;
ASSERT_TRUE ( status . has_value ( ) ) ;
EXPECT_EQ ( status - > error_code ( ) , StatusCode : : ABORTED ) ;
}
TEST ( PreStopHookServer , MultipleRequests ) {
TEST ( Standalone PreStopHookServer, MultipleRequests ) {
int port = grpc_pick_unused_port_or_die ( ) ;
PreStopHookServerManager server ;
Status start_status = server . Start ( port , 15 ) ;
@ -123,16 +139,16 @@ TEST(PreStopHookServer, MultipleRequests) {
CallInfo info1 , info2 , info3 ;
server . Return ( StatusCode : : INTERNAL , " First " ) ;
stub . async ( ) - > Hook ( & info1 . context , & info1 . request , & info1 . response ,
[ & ] ( Status status ) { info1 . SetStatus ( status ) ; } ) ;
[ & ] ( const Status & status ) { info1 . SetStatus ( status ) ; } ) ;
auto status = info1 . WaitForStatus ( ) ;
ASSERT_TRUE ( status . has_value ( ) ) ;
EXPECT_EQ ( status - > error_code ( ) , StatusCode : : INTERNAL ) ;
EXPECT_EQ ( status - > error_message ( ) , " First " ) ;
stub . async ( ) - > Hook ( & info2 . context , & info2 . request , & info2 . response ,
[ & ] ( Status status ) { info2 . SetStatus ( status ) ; } ) ;
ASSERT_EQ ( server . TestOnlyExpectRequests ( 1 , absl : : Milliseconds ( 500 ) ) , 1 ) ;
[ & ] ( const Status & status ) { info2 . SetStatus ( status ) ; } ) ;
ASSERT_TRU E ( server . TestOnlyExpectRequests ( 1 , absl : : Milliseconds ( 500 ) ) ) ;
stub . async ( ) - > Hook ( & info3 . context , & info3 . request , & info3 . response ,
[ & ] ( Status status ) { info3 . SetStatus ( status ) ; } ) ;
[ & ] ( const Status & status ) { info3 . SetStatus ( status ) ; } ) ;
server . Return ( StatusCode : : RESOURCE_EXHAUSTED , " Second " ) ;
server . Return ( StatusCode : : DEADLINE_EXCEEDED , " Third " ) ;
status = info2 . WaitForStatus ( ) ;
@ -145,14 +161,14 @@ TEST(PreStopHookServer, MultipleRequests) {
EXPECT_EQ ( status - > error_message ( ) , " Third " ) ;
}
TEST ( PreStopHookServer , StopServerThatNotStarted ) {
TEST ( Standalone PreStopHookServer, StopServerThatNotStarted ) {
PreStopHookServerManager server ;
Status status = server . Stop ( ) ;
EXPECT_EQ ( status . error_code ( ) , StatusCode : : UNAVAILABLE )
< < status . error_message ( ) ;
}
TEST ( PreStopHookServer , SetStatusBeforeRequestReceived ) {
TEST ( Standalone PreStopHookServer, SetStatusBeforeRequestReceived ) {
int port = grpc_pick_unused_port_or_die ( ) ;
PreStopHookServerManager server ;
Status start_status = server . Start ( port , 15 ) ;
@ -163,12 +179,71 @@ TEST(PreStopHookServer, SetStatusBeforeRequestReceived) {
ASSERT_TRUE ( channel ) ;
HookService : : Stub stub ( std : : move ( channel ) ) ;
CallInfo info ;
stub . async ( ) - > Hook ( & info . context , & info . request , & info . response ,
[ & info ] ( Status status ) { info . SetStatus ( status ) ; } ) ;
auto status = info . WaitForStatus ( ) ;
auto status = stub . Hook ( & info . context , info . request , & info . response ) ;
EXPECT_EQ ( status . error_code ( ) , StatusCode : : INTERNAL ) ;
EXPECT_EQ ( status . error_message ( ) , " Just a test " ) ;
}
TEST ( PreStopHookService , StartDoRequestStop ) {
int port = grpc_pick_unused_port_or_die ( ) ;
grpc_core : : Mutex mu ;
grpc_core : : CondVar condition ;
Server * server = nullptr ;
HookServiceImpl service ;
std : : thread server_thread ( ServerLoop , & service , port , & server , & mu ,
& condition ) ;
{
grpc_core : : MutexLock lock ( & mu ) ;
while ( server = = nullptr ) {
condition . Wait ( & mu ) ;
}
}
auto channel = CreateChannel ( absl : : StrFormat ( " 127.0.0.1:%d " , port ) ,
InsecureChannelCredentials ( ) ) ;
ASSERT_TRUE ( channel ) ;
CallInfo infos [ 3 ] ;
HookService : : Stub stub ( std : : move ( channel ) ) ;
stub . async ( ) - > Hook (
& infos [ 0 ] . context , & infos [ 0 ] . request , & infos [ 0 ] . response ,
[ & infos ] ( const Status & status ) { infos [ 0 ] . SetStatus ( status ) ; } ) ;
stub . async ( ) - > Hook (
& infos [ 1 ] . context , & infos [ 1 ] . request , & infos [ 1 ] . response ,
[ & infos ] ( const Status & status ) { infos [ 1 ] . SetStatus ( status ) ; } ) ;
ASSERT_TRUE ( service . TestOnlyExpectRequests ( 2 , absl : : Milliseconds ( 100 ) ) ) ;
ClientContext ctx ;
SetReturnStatusRequest request ;
request . set_grpc_code_to_return ( StatusCode : : INTERNAL ) ;
request . set_grpc_status_description ( " Just a test " ) ;
Empty response ;
ASSERT_EQ ( stub . SetReturnStatus ( & ctx , request , & response ) . error_code ( ) ,
StatusCode : : OK ) ;
auto status = infos [ 0 ] . WaitForStatus ( ) ;
ASSERT_TRUE ( status . has_value ( ) ) ;
EXPECT_EQ ( status - > error_code ( ) , StatusCode : : INTERNAL ) ;
EXPECT_EQ ( status - > error_message ( ) , " Just a test " ) ;
status = infos [ 1 ] . WaitForStatus ( ) ;
ASSERT_TRUE ( status . has_value ( ) ) ;
EXPECT_EQ ( status - > error_code ( ) , StatusCode : : INTERNAL ) ;
EXPECT_EQ ( status - > error_message ( ) , " Just a test " ) ;
status = stub . Hook ( & infos [ 2 ] . context , infos [ 2 ] . request , & infos [ 2 ] . response ) ;
ASSERT_TRUE ( status . has_value ( ) ) ;
EXPECT_EQ ( status - > error_code ( ) , StatusCode : : INTERNAL ) ;
EXPECT_EQ ( status - > error_message ( ) , " Just a test " ) ;
CallInfo reset_call_info ;
ASSERT_TRUE ( stub . ClearReturnStatus ( & reset_call_info . context ,
reset_call_info . request ,
& reset_call_info . response )
. ok ( ) ) ;
CallInfo call_hangs ;
stub . async ( ) - > Hook (
& call_hangs . context , & call_hangs . request , & call_hangs . response ,
[ & ] ( const Status & status ) { call_hangs . SetStatus ( status ) ; } ) ;
ASSERT_TRUE ( service . TestOnlyExpectRequests ( 1 , absl : : Milliseconds ( 100 ) ) ) ;
status = call_hangs . WaitForStatus ( absl : : Milliseconds ( 100 ) ) ;
EXPECT_FALSE ( status . has_value ( ) ) < < status - > error_message ( ) ;
service . Stop ( ) ;
server - > Shutdown ( ) ;
server_thread . join ( ) ;
}
} // namespace