diff options
author | Craig Tiller <ctiller@google.com> | 2017-01-17 12:23:05 -0800 |
---|---|---|
committer | Craig Tiller <ctiller@google.com> | 2017-01-17 12:23:05 -0800 |
commit | a66243d38e986df75fc6d9c6420267bda587dc04 (patch) | |
tree | e648c2688b4609408106fa4536f19aeccfd1e2e2 /test/core | |
parent | d4257124272290e8bb47b60127428a30cf9c8dbd (diff) | |
parent | c2079f37643d71ac7f787be40f42557e69d0819e (diff) |
Merge github.com:grpc/grpc into bwest
Diffstat (limited to 'test/core')
48 files changed, 1335 insertions, 0 deletions
diff --git a/test/core/end2end/end2end_nosec_tests.c b/test/core/end2end/end2end_nosec_tests.c index 663489082f..b162bf2f40 100644 --- a/test/core/end2end/end2end_nosec_tests.c +++ b/test/core/end2end/end2end_nosec_tests.c @@ -135,6 +135,10 @@ extern void streaming_error_response(grpc_end2end_test_config config); extern void streaming_error_response_pre_init(void); extern void trailing_metadata(grpc_end2end_test_config config); extern void trailing_metadata_pre_init(void); +extern void write_buffering(grpc_end2end_test_config config); +extern void write_buffering_pre_init(void); +extern void write_buffering_at_end(grpc_end2end_test_config config); +extern void write_buffering_at_end_pre_init(void); void grpc_end2end_tests_pre_init(void) { GPR_ASSERT(!g_pre_init_called); @@ -185,6 +189,8 @@ void grpc_end2end_tests_pre_init(void) { simple_request_pre_init(); streaming_error_response_pre_init(); trailing_metadata_pre_init(); + write_buffering_pre_init(); + write_buffering_at_end_pre_init(); } void grpc_end2end_tests(int argc, char **argv, @@ -240,6 +246,8 @@ void grpc_end2end_tests(int argc, char **argv, simple_request(config); streaming_error_response(config); trailing_metadata(config); + write_buffering(config); + write_buffering_at_end(config); return; } @@ -428,6 +436,14 @@ void grpc_end2end_tests(int argc, char **argv, trailing_metadata(config); continue; } + if (0 == strcmp("write_buffering", argv[i])) { + write_buffering(config); + continue; + } + if (0 == strcmp("write_buffering_at_end", argv[i])) { + write_buffering_at_end(config); + continue; + } gpr_log(GPR_DEBUG, "not a test: '%s'", argv[i]); abort(); } diff --git a/test/core/end2end/end2end_tests.c b/test/core/end2end/end2end_tests.c index 25c7c62fde..9bca0c81f6 100644 --- a/test/core/end2end/end2end_tests.c +++ b/test/core/end2end/end2end_tests.c @@ -137,6 +137,10 @@ extern void streaming_error_response(grpc_end2end_test_config config); extern void streaming_error_response_pre_init(void); extern void trailing_metadata(grpc_end2end_test_config config); extern void trailing_metadata_pre_init(void); +extern void write_buffering(grpc_end2end_test_config config); +extern void write_buffering_pre_init(void); +extern void write_buffering_at_end(grpc_end2end_test_config config); +extern void write_buffering_at_end_pre_init(void); void grpc_end2end_tests_pre_init(void) { GPR_ASSERT(!g_pre_init_called); @@ -188,6 +192,8 @@ void grpc_end2end_tests_pre_init(void) { simple_request_pre_init(); streaming_error_response_pre_init(); trailing_metadata_pre_init(); + write_buffering_pre_init(); + write_buffering_at_end_pre_init(); } void grpc_end2end_tests(int argc, char **argv, @@ -244,6 +250,8 @@ void grpc_end2end_tests(int argc, char **argv, simple_request(config); streaming_error_response(config); trailing_metadata(config); + write_buffering(config); + write_buffering_at_end(config); return; } @@ -436,6 +444,14 @@ void grpc_end2end_tests(int argc, char **argv, trailing_metadata(config); continue; } + if (0 == strcmp("write_buffering", argv[i])) { + write_buffering(config); + continue; + } + if (0 == strcmp("write_buffering_at_end", argv[i])) { + write_buffering_at_end(config); + continue; + } gpr_log(GPR_DEBUG, "not a test: '%s'", argv[i]); abort(); } diff --git a/test/core/end2end/fuzzers/api_fuzzer_corpus/08455b3ef9d516deb8155d8db7d51c43ce0ff07a b/test/core/end2end/fuzzers/api_fuzzer_corpus/08455b3ef9d516deb8155d8db7d51c43ce0ff07a Binary files differnew file mode 100644 index 0000000000..4b698ba9ee --- /dev/null +++ b/test/core/end2end/fuzzers/api_fuzzer_corpus/08455b3ef9d516deb8155d8db7d51c43ce0ff07a diff --git a/test/core/end2end/fuzzers/api_fuzzer_corpus/0d19e60f4eb1b729e272dd5dec68e8b67f03a5f4 b/test/core/end2end/fuzzers/api_fuzzer_corpus/0d19e60f4eb1b729e272dd5dec68e8b67f03a5f4 Binary files differnew file mode 100644 index 0000000000..2889e7040e --- /dev/null +++ b/test/core/end2end/fuzzers/api_fuzzer_corpus/0d19e60f4eb1b729e272dd5dec68e8b67f03a5f4 diff --git a/test/core/end2end/fuzzers/api_fuzzer_corpus/14064ac4844c709b247a4345a92d8be9766785c4 b/test/core/end2end/fuzzers/api_fuzzer_corpus/14064ac4844c709b247a4345a92d8be9766785c4 Binary files differnew file mode 100644 index 0000000000..fa731d4a05 --- /dev/null +++ b/test/core/end2end/fuzzers/api_fuzzer_corpus/14064ac4844c709b247a4345a92d8be9766785c4 diff --git a/test/core/end2end/fuzzers/api_fuzzer_corpus/1901234bd7c9cb6ee19ff8b17179c481bdc7c5f2 b/test/core/end2end/fuzzers/api_fuzzer_corpus/1901234bd7c9cb6ee19ff8b17179c481bdc7c5f2 Binary files differnew file mode 100644 index 0000000000..ef09a0eaf5 --- /dev/null +++ b/test/core/end2end/fuzzers/api_fuzzer_corpus/1901234bd7c9cb6ee19ff8b17179c481bdc7c5f2 diff --git a/test/core/end2end/fuzzers/api_fuzzer_corpus/20ff1f8d5d34cb01d58aa334dc46a6644e6e1d12 b/test/core/end2end/fuzzers/api_fuzzer_corpus/20ff1f8d5d34cb01d58aa334dc46a6644e6e1d12 Binary files differnew file mode 100644 index 0000000000..fc747d4a72 --- /dev/null +++ b/test/core/end2end/fuzzers/api_fuzzer_corpus/20ff1f8d5d34cb01d58aa334dc46a6644e6e1d12 diff --git a/test/core/end2end/fuzzers/api_fuzzer_corpus/2378c3f1206f20711468391ce739116ffe58374b b/test/core/end2end/fuzzers/api_fuzzer_corpus/2378c3f1206f20711468391ce739116ffe58374b Binary files differnew file mode 100644 index 0000000000..ca3ce31cbe --- /dev/null +++ b/test/core/end2end/fuzzers/api_fuzzer_corpus/2378c3f1206f20711468391ce739116ffe58374b diff --git a/test/core/end2end/fuzzers/api_fuzzer_corpus/40640a91fda4e4e42d3063a28b9ffbba1b8c3701 b/test/core/end2end/fuzzers/api_fuzzer_corpus/40640a91fda4e4e42d3063a28b9ffbba1b8c3701 Binary files differnew file mode 100644 index 0000000000..f11821acc9 --- /dev/null +++ b/test/core/end2end/fuzzers/api_fuzzer_corpus/40640a91fda4e4e42d3063a28b9ffbba1b8c3701 diff --git a/test/core/end2end/fuzzers/api_fuzzer_corpus/49f564289c79de9e0342f8b0821a167bc8c5ec00 b/test/core/end2end/fuzzers/api_fuzzer_corpus/49f564289c79de9e0342f8b0821a167bc8c5ec00 Binary files differnew file mode 100644 index 0000000000..c846377f0a --- /dev/null +++ b/test/core/end2end/fuzzers/api_fuzzer_corpus/49f564289c79de9e0342f8b0821a167bc8c5ec00 diff --git a/test/core/end2end/fuzzers/api_fuzzer_corpus/507865c4a5ce880b80400d93fa85def2682581cb b/test/core/end2end/fuzzers/api_fuzzer_corpus/507865c4a5ce880b80400d93fa85def2682581cb Binary files differnew file mode 100644 index 0000000000..c4473eacbb --- /dev/null +++ b/test/core/end2end/fuzzers/api_fuzzer_corpus/507865c4a5ce880b80400d93fa85def2682581cb diff --git a/test/core/end2end/fuzzers/api_fuzzer_corpus/5f2fdb01d8ff632803ca2b732a7c088c6843d7d3 b/test/core/end2end/fuzzers/api_fuzzer_corpus/5f2fdb01d8ff632803ca2b732a7c088c6843d7d3 Binary files differnew file mode 100644 index 0000000000..b91a052534 --- /dev/null +++ b/test/core/end2end/fuzzers/api_fuzzer_corpus/5f2fdb01d8ff632803ca2b732a7c088c6843d7d3 diff --git a/test/core/end2end/fuzzers/api_fuzzer_corpus/61de97a9d6c4b082602c02277d8d763921f5f95b b/test/core/end2end/fuzzers/api_fuzzer_corpus/61de97a9d6c4b082602c02277d8d763921f5f95b Binary files differnew file mode 100644 index 0000000000..a24008b1d4 --- /dev/null +++ b/test/core/end2end/fuzzers/api_fuzzer_corpus/61de97a9d6c4b082602c02277d8d763921f5f95b diff --git a/test/core/end2end/fuzzers/api_fuzzer_corpus/62b039b8a318cc08471f13629da08c68c414d8e7 b/test/core/end2end/fuzzers/api_fuzzer_corpus/62b039b8a318cc08471f13629da08c68c414d8e7 Binary files differnew file mode 100644 index 0000000000..e5e218acc3 --- /dev/null +++ b/test/core/end2end/fuzzers/api_fuzzer_corpus/62b039b8a318cc08471f13629da08c68c414d8e7 diff --git a/test/core/end2end/fuzzers/api_fuzzer_corpus/641739453f7d4d3b55a1c7b79bed7da6dfd62ae0 b/test/core/end2end/fuzzers/api_fuzzer_corpus/641739453f7d4d3b55a1c7b79bed7da6dfd62ae0 Binary files differnew file mode 100644 index 0000000000..9dcc5c578c --- /dev/null +++ b/test/core/end2end/fuzzers/api_fuzzer_corpus/641739453f7d4d3b55a1c7b79bed7da6dfd62ae0 diff --git a/test/core/end2end/fuzzers/api_fuzzer_corpus/6589505362ffb5164a3c7cb1b9feadcddfba44e9 b/test/core/end2end/fuzzers/api_fuzzer_corpus/6589505362ffb5164a3c7cb1b9feadcddfba44e9 Binary files differnew file mode 100644 index 0000000000..10625da2ff --- /dev/null +++ b/test/core/end2end/fuzzers/api_fuzzer_corpus/6589505362ffb5164a3c7cb1b9feadcddfba44e9 diff --git a/test/core/end2end/fuzzers/api_fuzzer_corpus/724f5400f19e5a0be97022341c39eeaaaffeb390 b/test/core/end2end/fuzzers/api_fuzzer_corpus/724f5400f19e5a0be97022341c39eeaaaffeb390 Binary files differnew file mode 100644 index 0000000000..1dbc538192 --- /dev/null +++ b/test/core/end2end/fuzzers/api_fuzzer_corpus/724f5400f19e5a0be97022341c39eeaaaffeb390 diff --git a/test/core/end2end/fuzzers/api_fuzzer_corpus/7254b9ff59ab3fcf345effdabbc25ebd2e907b23 b/test/core/end2end/fuzzers/api_fuzzer_corpus/7254b9ff59ab3fcf345effdabbc25ebd2e907b23 Binary files differnew file mode 100644 index 0000000000..92371e031f --- /dev/null +++ b/test/core/end2end/fuzzers/api_fuzzer_corpus/7254b9ff59ab3fcf345effdabbc25ebd2e907b23 diff --git a/test/core/end2end/fuzzers/api_fuzzer_corpus/784d6f5c093ab5360670173ce001e1a446f95822 b/test/core/end2end/fuzzers/api_fuzzer_corpus/784d6f5c093ab5360670173ce001e1a446f95822 Binary files differnew file mode 100644 index 0000000000..79885b7f2a --- /dev/null +++ b/test/core/end2end/fuzzers/api_fuzzer_corpus/784d6f5c093ab5360670173ce001e1a446f95822 diff --git a/test/core/end2end/fuzzers/api_fuzzer_corpus/79328fdc89d0af0e38da089dab062fd3ea5aae59 b/test/core/end2end/fuzzers/api_fuzzer_corpus/79328fdc89d0af0e38da089dab062fd3ea5aae59 Binary files differnew file mode 100644 index 0000000000..4a5cbfd654 --- /dev/null +++ b/test/core/end2end/fuzzers/api_fuzzer_corpus/79328fdc89d0af0e38da089dab062fd3ea5aae59 diff --git a/test/core/end2end/fuzzers/api_fuzzer_corpus/7a2569f4daf4480ad142cb4ee7c675bed82db74c b/test/core/end2end/fuzzers/api_fuzzer_corpus/7a2569f4daf4480ad142cb4ee7c675bed82db74c Binary files differnew file mode 100644 index 0000000000..75b55e7e10 --- /dev/null +++ b/test/core/end2end/fuzzers/api_fuzzer_corpus/7a2569f4daf4480ad142cb4ee7c675bed82db74c diff --git a/test/core/end2end/fuzzers/api_fuzzer_corpus/87a300cd25d2e57745bd00499d4d2352a10a2fa1 b/test/core/end2end/fuzzers/api_fuzzer_corpus/87a300cd25d2e57745bd00499d4d2352a10a2fa1 Binary files differnew file mode 100644 index 0000000000..c8f79862bc --- /dev/null +++ b/test/core/end2end/fuzzers/api_fuzzer_corpus/87a300cd25d2e57745bd00499d4d2352a10a2fa1 diff --git a/test/core/end2end/fuzzers/api_fuzzer_corpus/8a1c629910280f8beebb88687696de98da988ecc b/test/core/end2end/fuzzers/api_fuzzer_corpus/8a1c629910280f8beebb88687696de98da988ecc Binary files differnew file mode 100644 index 0000000000..ce3377fdc1 --- /dev/null +++ b/test/core/end2end/fuzzers/api_fuzzer_corpus/8a1c629910280f8beebb88687696de98da988ecc diff --git a/test/core/end2end/fuzzers/api_fuzzer_corpus/8ff7b1568d2da2e4196c2e28617e1911d62021e6 b/test/core/end2end/fuzzers/api_fuzzer_corpus/8ff7b1568d2da2e4196c2e28617e1911d62021e6 Binary files differnew file mode 100644 index 0000000000..321520b870 --- /dev/null +++ b/test/core/end2end/fuzzers/api_fuzzer_corpus/8ff7b1568d2da2e4196c2e28617e1911d62021e6 diff --git a/test/core/end2end/fuzzers/api_fuzzer_corpus/982f375b183d984958667461c7767206062eb4cb b/test/core/end2end/fuzzers/api_fuzzer_corpus/982f375b183d984958667461c7767206062eb4cb Binary files differnew file mode 100644 index 0000000000..01d07d6408 --- /dev/null +++ b/test/core/end2end/fuzzers/api_fuzzer_corpus/982f375b183d984958667461c7767206062eb4cb diff --git a/test/core/end2end/fuzzers/api_fuzzer_corpus/98739af631223fa05ad88f1e63a52052a9bb4b1c b/test/core/end2end/fuzzers/api_fuzzer_corpus/98739af631223fa05ad88f1e63a52052a9bb4b1c Binary files differnew file mode 100644 index 0000000000..a4adb7aee6 --- /dev/null +++ b/test/core/end2end/fuzzers/api_fuzzer_corpus/98739af631223fa05ad88f1e63a52052a9bb4b1c diff --git a/test/core/end2end/fuzzers/api_fuzzer_corpus/a78bca1ef8829d720dd5dedac3a9d4d12684da34 b/test/core/end2end/fuzzers/api_fuzzer_corpus/a78bca1ef8829d720dd5dedac3a9d4d12684da34 Binary files differnew file mode 100644 index 0000000000..322d4ae019 --- /dev/null +++ b/test/core/end2end/fuzzers/api_fuzzer_corpus/a78bca1ef8829d720dd5dedac3a9d4d12684da34 diff --git a/test/core/end2end/fuzzers/api_fuzzer_corpus/ac763d89466ebfad676e75be0076831c03fe2a5d b/test/core/end2end/fuzzers/api_fuzzer_corpus/ac763d89466ebfad676e75be0076831c03fe2a5d Binary files differnew file mode 100644 index 0000000000..64c9720c9b --- /dev/null +++ b/test/core/end2end/fuzzers/api_fuzzer_corpus/ac763d89466ebfad676e75be0076831c03fe2a5d diff --git a/test/core/end2end/fuzzers/api_fuzzer_corpus/b165523f699e6ae9b2ad15873b9d56465d1af546 b/test/core/end2end/fuzzers/api_fuzzer_corpus/b165523f699e6ae9b2ad15873b9d56465d1af546 Binary files differnew file mode 100644 index 0000000000..b0b7452924 --- /dev/null +++ b/test/core/end2end/fuzzers/api_fuzzer_corpus/b165523f699e6ae9b2ad15873b9d56465d1af546 diff --git a/test/core/end2end/fuzzers/api_fuzzer_corpus/b2a5ec3ef40c68d594638218e3c943a479f82215 b/test/core/end2end/fuzzers/api_fuzzer_corpus/b2a5ec3ef40c68d594638218e3c943a479f82215 Binary files differnew file mode 100644 index 0000000000..ac2b154407 --- /dev/null +++ b/test/core/end2end/fuzzers/api_fuzzer_corpus/b2a5ec3ef40c68d594638218e3c943a479f82215 diff --git a/test/core/end2end/fuzzers/api_fuzzer_corpus/b92b1c5e0dba009a9516e7185f5df019c62c5cc9 b/test/core/end2end/fuzzers/api_fuzzer_corpus/b92b1c5e0dba009a9516e7185f5df019c62c5cc9 Binary files differnew file mode 100644 index 0000000000..3d542f38ec --- /dev/null +++ b/test/core/end2end/fuzzers/api_fuzzer_corpus/b92b1c5e0dba009a9516e7185f5df019c62c5cc9 diff --git a/test/core/end2end/fuzzers/api_fuzzer_corpus/c5cd7af16e7bc0049445d5a0b92a3d4b7e5e3533 b/test/core/end2end/fuzzers/api_fuzzer_corpus/c5cd7af16e7bc0049445d5a0b92a3d4b7e5e3533 Binary files differnew file mode 100644 index 0000000000..c8fca17ad3 --- /dev/null +++ b/test/core/end2end/fuzzers/api_fuzzer_corpus/c5cd7af16e7bc0049445d5a0b92a3d4b7e5e3533 diff --git a/test/core/end2end/fuzzers/api_fuzzer_corpus/crash-da39a3ee5e6b4b0d3255bfef95601890afd80709 b/test/core/end2end/fuzzers/api_fuzzer_corpus/crash-da39a3ee5e6b4b0d3255bfef95601890afd80709 new file mode 100644 index 0000000000..e69de29bb2 --- /dev/null +++ b/test/core/end2end/fuzzers/api_fuzzer_corpus/crash-da39a3ee5e6b4b0d3255bfef95601890afd80709 diff --git a/test/core/end2end/fuzzers/api_fuzzer_corpus/e28ffd8c2816f12f6395805199c792d1718191df b/test/core/end2end/fuzzers/api_fuzzer_corpus/e28ffd8c2816f12f6395805199c792d1718191df Binary files differnew file mode 100644 index 0000000000..a867a8b0be --- /dev/null +++ b/test/core/end2end/fuzzers/api_fuzzer_corpus/e28ffd8c2816f12f6395805199c792d1718191df diff --git a/test/core/end2end/fuzzers/api_fuzzer_corpus/ec823f4018389e64a99f6580277fba28df6bd136 b/test/core/end2end/fuzzers/api_fuzzer_corpus/ec823f4018389e64a99f6580277fba28df6bd136 Binary files differnew file mode 100644 index 0000000000..2e6d409d39 --- /dev/null +++ b/test/core/end2end/fuzzers/api_fuzzer_corpus/ec823f4018389e64a99f6580277fba28df6bd136 diff --git a/test/core/end2end/fuzzers/api_fuzzer_corpus/ee2c1ac1e668f22836cf25a59495e778b0e2c7a8 b/test/core/end2end/fuzzers/api_fuzzer_corpus/ee2c1ac1e668f22836cf25a59495e778b0e2c7a8 Binary files differnew file mode 100644 index 0000000000..f1990ac231 --- /dev/null +++ b/test/core/end2end/fuzzers/api_fuzzer_corpus/ee2c1ac1e668f22836cf25a59495e778b0e2c7a8 diff --git a/test/core/end2end/fuzzers/api_fuzzer_corpus/ee6855178435d2046d8763ecae46e1e0a71a95f4 b/test/core/end2end/fuzzers/api_fuzzer_corpus/ee6855178435d2046d8763ecae46e1e0a71a95f4 Binary files differnew file mode 100644 index 0000000000..6badaf36dc --- /dev/null +++ b/test/core/end2end/fuzzers/api_fuzzer_corpus/ee6855178435d2046d8763ecae46e1e0a71a95f4 diff --git a/test/core/end2end/fuzzers/api_fuzzer_corpus/eeb310d91038cb02862e187e68c5d6578233485b b/test/core/end2end/fuzzers/api_fuzzer_corpus/eeb310d91038cb02862e187e68c5d6578233485b Binary files differnew file mode 100644 index 0000000000..1b05cfb036 --- /dev/null +++ b/test/core/end2end/fuzzers/api_fuzzer_corpus/eeb310d91038cb02862e187e68c5d6578233485b diff --git a/test/core/end2end/fuzzers/api_fuzzer_corpus/f07bc2907c95f2aeb79ca60e2ad826e13b848f45 b/test/core/end2end/fuzzers/api_fuzzer_corpus/f07bc2907c95f2aeb79ca60e2ad826e13b848f45 Binary files differnew file mode 100644 index 0000000000..313d456262 --- /dev/null +++ b/test/core/end2end/fuzzers/api_fuzzer_corpus/f07bc2907c95f2aeb79ca60e2ad826e13b848f45 diff --git a/test/core/end2end/fuzzers/api_fuzzer_corpus/fb655905396b768cf3ff015afdb0b564dae2cdfd b/test/core/end2end/fuzzers/api_fuzzer_corpus/fb655905396b768cf3ff015afdb0b564dae2cdfd Binary files differnew file mode 100644 index 0000000000..b02dabe03a --- /dev/null +++ b/test/core/end2end/fuzzers/api_fuzzer_corpus/fb655905396b768cf3ff015afdb0b564dae2cdfd diff --git a/test/core/end2end/fuzzers/api_fuzzer_corpus/fdb038087233cd176746558875932029f779221d b/test/core/end2end/fuzzers/api_fuzzer_corpus/fdb038087233cd176746558875932029f779221d Binary files differnew file mode 100644 index 0000000000..017fdbf661 --- /dev/null +++ b/test/core/end2end/fuzzers/api_fuzzer_corpus/fdb038087233cd176746558875932029f779221d diff --git a/test/core/end2end/gen_build_yaml.py b/test/core/end2end/gen_build_yaml.py index 201a92a1fd..bcb7136eaa 100755 --- a/test/core/end2end/gen_build_yaml.py +++ b/test/core/end2end/gen_build_yaml.py @@ -143,6 +143,8 @@ END2END_TESTS = { 'streaming_error_response': default_test_options, 'trailing_metadata': default_test_options, 'authority_not_supported': default_test_options, + 'write_buffering': default_test_options, + 'write_buffering_at_end': default_test_options, } diff --git a/test/core/end2end/generate_tests.bzl b/test/core/end2end/generate_tests.bzl index ed1ba3eea9..95c06de73f 100755 --- a/test/core/end2end/generate_tests.bzl +++ b/test/core/end2end/generate_tests.bzl @@ -131,6 +131,8 @@ END2END_TESTS = { 'trailing_metadata': test_options(), 'authority_not_supported': test_options(), 'filter_latency': test_options(), + 'write_buffering': test_options(), + 'write_buffering_at_end': test_options(), } diff --git a/test/core/end2end/tests/write_buffering.c b/test/core/end2end/tests/write_buffering.c new file mode 100644 index 0000000000..856e9f0306 --- /dev/null +++ b/test/core/end2end/tests/write_buffering.c @@ -0,0 +1,291 @@ +/* + * + * Copyright 2017, Google Inc. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following disclaimer + * in the documentation and/or other materials provided with the + * distribution. + * * Neither the name of Google Inc. nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + */ + +#include "test/core/end2end/end2end_tests.h" + +#include <stdio.h> +#include <string.h> + +#include <grpc/byte_buffer.h> +#include <grpc/support/alloc.h> +#include <grpc/support/log.h> +#include <grpc/support/time.h> +#include <grpc/support/useful.h> +#include "test/core/end2end/cq_verifier.h" + +static void *tag(intptr_t t) { return (void *)t; } + +static grpc_end2end_test_fixture begin_test(grpc_end2end_test_config config, + const char *test_name, + grpc_channel_args *client_args, + grpc_channel_args *server_args) { + grpc_end2end_test_fixture f; + gpr_log(GPR_INFO, "%s/%s", test_name, config.name); + f = config.create_fixture(client_args, server_args); + config.init_server(&f, server_args); + config.init_client(&f, client_args); + return f; +} + +static gpr_timespec n_seconds_time(int n) { + return GRPC_TIMEOUT_SECONDS_TO_DEADLINE(n); +} + +static gpr_timespec five_seconds_time(void) { return n_seconds_time(5); } + +static void drain_cq(grpc_completion_queue *cq) { + grpc_event ev; + do { + ev = grpc_completion_queue_next(cq, five_seconds_time(), NULL); + } while (ev.type != GRPC_QUEUE_SHUTDOWN); +} + +static void shutdown_server(grpc_end2end_test_fixture *f) { + if (!f->server) return; + grpc_server_shutdown_and_notify(f->server, f->cq, tag(1000)); + GPR_ASSERT(grpc_completion_queue_pluck( + f->cq, tag(1000), GRPC_TIMEOUT_SECONDS_TO_DEADLINE(5), NULL) + .type == GRPC_OP_COMPLETE); + grpc_server_destroy(f->server); + f->server = NULL; +} + +static void shutdown_client(grpc_end2end_test_fixture *f) { + if (!f->client) return; + grpc_channel_destroy(f->client); + f->client = NULL; +} + +static void end_test(grpc_end2end_test_fixture *f) { + shutdown_server(f); + shutdown_client(f); + + grpc_completion_queue_shutdown(f->cq); + drain_cq(f->cq); + grpc_completion_queue_destroy(f->cq); +} + +/* Client sends a request with payload, server reads then returns status. */ +static void test_invoke_request_with_payload(grpc_end2end_test_config config) { + grpc_call *c; + grpc_call *s; + grpc_slice request_payload_slice1 = + grpc_slice_from_copied_string("hello world"); + grpc_byte_buffer *request_payload1 = + grpc_raw_byte_buffer_create(&request_payload_slice1, 1); + grpc_slice request_payload_slice2 = grpc_slice_from_copied_string("abc123"); + grpc_byte_buffer *request_payload2 = + grpc_raw_byte_buffer_create(&request_payload_slice2, 1); + gpr_timespec deadline = five_seconds_time(); + grpc_end2end_test_fixture f = + begin_test(config, "test_invoke_request_with_payload", NULL, NULL); + cq_verifier *cqv = cq_verifier_create(f.cq); + grpc_op ops[6]; + grpc_op *op; + grpc_metadata_array initial_metadata_recv; + grpc_metadata_array trailing_metadata_recv; + grpc_metadata_array request_metadata_recv; + grpc_byte_buffer *request_payload_recv1 = NULL; + grpc_byte_buffer *request_payload_recv2 = NULL; + grpc_call_details call_details; + grpc_status_code status; + grpc_call_error error; + char *details = NULL; + size_t details_capacity = 0; + int was_cancelled = 2; + + c = grpc_channel_create_call( + f.client, NULL, GRPC_PROPAGATE_DEFAULTS, f.cq, "/foo", + get_host_override_string("foo.test.google.fr:1234", config), deadline, + NULL); + GPR_ASSERT(c); + + grpc_metadata_array_init(&initial_metadata_recv); + grpc_metadata_array_init(&trailing_metadata_recv); + grpc_metadata_array_init(&request_metadata_recv); + grpc_call_details_init(&call_details); + + memset(ops, 0, sizeof(ops)); + op = ops; + op->op = GRPC_OP_SEND_INITIAL_METADATA; + op->data.send_initial_metadata.count = 0; + op++; + error = grpc_call_start_batch(c, ops, (size_t)(op - ops), tag(1), NULL); + GPR_ASSERT(GRPC_CALL_OK == error); + + memset(ops, 0, sizeof(ops)); + op = ops; + op->op = GRPC_OP_RECV_INITIAL_METADATA; + op->data.recv_initial_metadata = &initial_metadata_recv; + op->flags = 0; + op->reserved = NULL; + op++; + error = grpc_call_start_batch(c, ops, (size_t)(op - ops), tag(2), NULL); + GPR_ASSERT(GRPC_CALL_OK == error); + + GPR_ASSERT(GRPC_CALL_OK == grpc_server_request_call( + f.server, &s, &call_details, + &request_metadata_recv, f.cq, f.cq, tag(101))); + CQ_EXPECT_COMPLETION(cqv, tag(1), true); /* send message is buffered */ + CQ_EXPECT_COMPLETION(cqv, tag(101), true); + cq_verify(cqv); + + memset(ops, 0, sizeof(ops)); + op = ops; + op->op = GRPC_OP_SEND_MESSAGE; + op->data.send_message = request_payload1; + op->flags = GRPC_WRITE_BUFFER_HINT; + op++; + error = grpc_call_start_batch(c, ops, (size_t)(op - ops), tag(3), NULL); + GPR_ASSERT(GRPC_CALL_OK == error); + + memset(ops, 0, sizeof(ops)); + op = ops; + op->op = GRPC_OP_SEND_INITIAL_METADATA; + op->data.send_initial_metadata.count = 0; + op++; + error = grpc_call_start_batch(s, ops, (size_t)(op - ops), tag(102), NULL); + GPR_ASSERT(GRPC_CALL_OK == error); + + /* recv message should not succeed yet - it's buffered at the client still */ + memset(ops, 0, sizeof(ops)); + op = ops; + op->op = GRPC_OP_RECV_MESSAGE; + op->data.recv_message = &request_payload_recv1; + op++; + error = grpc_call_start_batch(s, ops, (size_t)(op - ops), tag(103), NULL); + GPR_ASSERT(GRPC_CALL_OK == error); + + CQ_EXPECT_COMPLETION(cqv, tag(2), true); + CQ_EXPECT_COMPLETION(cqv, tag(3), true); + CQ_EXPECT_COMPLETION(cqv, tag(102), true); + cq_verify(cqv); + + /* send another message, this time not buffered */ + memset(ops, 0, sizeof(ops)); + op = ops; + op->op = GRPC_OP_SEND_MESSAGE; + op->data.send_message = request_payload2; + op->flags = 0; + op++; + error = grpc_call_start_batch(c, ops, (size_t)(op - ops), tag(4), NULL); + GPR_ASSERT(GRPC_CALL_OK == error); + + /* now the first send should match up with the first recv */ + CQ_EXPECT_COMPLETION(cqv, tag(103), true); + CQ_EXPECT_COMPLETION(cqv, tag(4), true); + cq_verify(cqv); + + /* and the next recv should be ready immediately also */ + memset(ops, 0, sizeof(ops)); + op = ops; + op->op = GRPC_OP_RECV_MESSAGE; + op->data.recv_message = &request_payload_recv2; + op++; + error = grpc_call_start_batch(s, ops, (size_t)(op - ops), tag(104), NULL); + GPR_ASSERT(GRPC_CALL_OK == error); + + CQ_EXPECT_COMPLETION(cqv, tag(104), true); + cq_verify(cqv); + + memset(ops, 0, sizeof(ops)); + op = ops; + op->op = GRPC_OP_SEND_CLOSE_FROM_CLIENT; + op->flags = 0; + op->reserved = NULL; + op++; + op->op = GRPC_OP_RECV_STATUS_ON_CLIENT; + op->data.recv_status_on_client.trailing_metadata = &trailing_metadata_recv; + op->data.recv_status_on_client.status = &status; + op->data.recv_status_on_client.status_details = &details; + op->data.recv_status_on_client.status_details_capacity = &details_capacity; + op->flags = 0; + op->reserved = NULL; + op++; + error = grpc_call_start_batch(c, ops, (size_t)(op - ops), tag(4), NULL); + + memset(ops, 0, sizeof(ops)); + op = ops; + op->op = GRPC_OP_RECV_CLOSE_ON_SERVER; + op->data.recv_close_on_server.cancelled = &was_cancelled; + op->flags = 0; + op->reserved = NULL; + op++; + op->op = GRPC_OP_SEND_STATUS_FROM_SERVER; + op->data.send_status_from_server.trailing_metadata_count = 0; + op->data.send_status_from_server.status = GRPC_STATUS_OK; + op->data.send_status_from_server.status_details = "xyz"; + op->flags = 0; + op->reserved = NULL; + op++; + error = grpc_call_start_batch(s, ops, (size_t)(op - ops), tag(105), NULL); + GPR_ASSERT(GRPC_CALL_OK == error); + + CQ_EXPECT_COMPLETION(cqv, tag(105), 1); + CQ_EXPECT_COMPLETION(cqv, tag(4), 1); + cq_verify(cqv); + + GPR_ASSERT(status == GRPC_STATUS_OK); + GPR_ASSERT(0 == strcmp(details, "xyz")); + GPR_ASSERT(0 == strcmp(call_details.method, "/foo")); + validate_host_override_string("foo.test.google.fr:1234", call_details.host, + config); + GPR_ASSERT(was_cancelled == 0); + GPR_ASSERT(byte_buffer_eq_string(request_payload_recv1, "hello world")); + GPR_ASSERT(byte_buffer_eq_string(request_payload_recv2, "abc123")); + + gpr_free(details); + grpc_metadata_array_destroy(&initial_metadata_recv); + grpc_metadata_array_destroy(&trailing_metadata_recv); + grpc_metadata_array_destroy(&request_metadata_recv); + grpc_call_details_destroy(&call_details); + + grpc_call_destroy(c); + grpc_call_destroy(s); + + cq_verifier_destroy(cqv); + + grpc_byte_buffer_destroy(request_payload1); + grpc_byte_buffer_destroy(request_payload_recv1); + grpc_byte_buffer_destroy(request_payload2); + grpc_byte_buffer_destroy(request_payload_recv2); + + end_test(&f); + config.tear_down_data(&f); +} + +void write_buffering(grpc_end2end_test_config config) { + test_invoke_request_with_payload(config); +} + +void write_buffering_pre_init(void) {} diff --git a/test/core/end2end/tests/write_buffering_at_end.c b/test/core/end2end/tests/write_buffering_at_end.c new file mode 100644 index 0000000000..43aefcbdbc --- /dev/null +++ b/test/core/end2end/tests/write_buffering_at_end.c @@ -0,0 +1,280 @@ +/* + * + * Copyright 2017, Google Inc. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following disclaimer + * in the documentation and/or other materials provided with the + * distribution. + * * Neither the name of Google Inc. nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + */ + +#include "test/core/end2end/end2end_tests.h" + +#include <stdio.h> +#include <string.h> + +#include <grpc/byte_buffer.h> +#include <grpc/support/alloc.h> +#include <grpc/support/log.h> +#include <grpc/support/time.h> +#include <grpc/support/useful.h> +#include "test/core/end2end/cq_verifier.h" + +static void *tag(intptr_t t) { return (void *)t; } + +static grpc_end2end_test_fixture begin_test(grpc_end2end_test_config config, + const char *test_name, + grpc_channel_args *client_args, + grpc_channel_args *server_args) { + grpc_end2end_test_fixture f; + gpr_log(GPR_INFO, "%s/%s", test_name, config.name); + f = config.create_fixture(client_args, server_args); + config.init_server(&f, server_args); + config.init_client(&f, client_args); + return f; +} + +static gpr_timespec n_seconds_time(int n) { + return GRPC_TIMEOUT_SECONDS_TO_DEADLINE(n); +} + +static gpr_timespec five_seconds_time(void) { return n_seconds_time(5); } + +static void drain_cq(grpc_completion_queue *cq) { + grpc_event ev; + do { + ev = grpc_completion_queue_next(cq, five_seconds_time(), NULL); + } while (ev.type != GRPC_QUEUE_SHUTDOWN); +} + +static void shutdown_server(grpc_end2end_test_fixture *f) { + if (!f->server) return; + grpc_server_shutdown_and_notify(f->server, f->cq, tag(1000)); + GPR_ASSERT(grpc_completion_queue_pluck( + f->cq, tag(1000), GRPC_TIMEOUT_SECONDS_TO_DEADLINE(5), NULL) + .type == GRPC_OP_COMPLETE); + grpc_server_destroy(f->server); + f->server = NULL; +} + +static void shutdown_client(grpc_end2end_test_fixture *f) { + if (!f->client) return; + grpc_channel_destroy(f->client); + f->client = NULL; +} + +static void end_test(grpc_end2end_test_fixture *f) { + shutdown_server(f); + shutdown_client(f); + + grpc_completion_queue_shutdown(f->cq); + drain_cq(f->cq); + grpc_completion_queue_destroy(f->cq); +} + +/* Client sends a request with payload, server reads then returns status. */ +static void test_invoke_request_with_payload(grpc_end2end_test_config config) { + grpc_call *c; + grpc_call *s; + grpc_slice request_payload_slice = + grpc_slice_from_copied_string("hello world"); + grpc_byte_buffer *request_payload = + grpc_raw_byte_buffer_create(&request_payload_slice, 1); + gpr_timespec deadline = five_seconds_time(); + grpc_end2end_test_fixture f = + begin_test(config, "test_invoke_request_with_payload", NULL, NULL); + cq_verifier *cqv = cq_verifier_create(f.cq); + grpc_op ops[6]; + grpc_op *op; + grpc_metadata_array initial_metadata_recv; + grpc_metadata_array trailing_metadata_recv; + grpc_metadata_array request_metadata_recv; + grpc_byte_buffer *request_payload_recv1 = NULL; + grpc_byte_buffer *request_payload_recv2 = NULL; + grpc_call_details call_details; + grpc_status_code status; + grpc_call_error error; + char *details = NULL; + size_t details_capacity = 0; + int was_cancelled = 2; + + c = grpc_channel_create_call( + f.client, NULL, GRPC_PROPAGATE_DEFAULTS, f.cq, "/foo", + get_host_override_string("foo.test.google.fr:1234", config), deadline, + NULL); + GPR_ASSERT(c); + + grpc_metadata_array_init(&initial_metadata_recv); + grpc_metadata_array_init(&trailing_metadata_recv); + grpc_metadata_array_init(&request_metadata_recv); + grpc_call_details_init(&call_details); + + memset(ops, 0, sizeof(ops)); + op = ops; + op->op = GRPC_OP_SEND_INITIAL_METADATA; + op->data.send_initial_metadata.count = 0; + op++; + error = grpc_call_start_batch(c, ops, (size_t)(op - ops), tag(1), NULL); + GPR_ASSERT(GRPC_CALL_OK == error); + + memset(ops, 0, sizeof(ops)); + op = ops; + op->op = GRPC_OP_RECV_INITIAL_METADATA; + op->data.recv_initial_metadata = &initial_metadata_recv; + op->flags = 0; + op->reserved = NULL; + op++; + error = grpc_call_start_batch(c, ops, (size_t)(op - ops), tag(2), NULL); + GPR_ASSERT(GRPC_CALL_OK == error); + + GPR_ASSERT(GRPC_CALL_OK == grpc_server_request_call( + f.server, &s, &call_details, + &request_metadata_recv, f.cq, f.cq, tag(101))); + CQ_EXPECT_COMPLETION(cqv, tag(1), true); /* send message is buffered */ + CQ_EXPECT_COMPLETION(cqv, tag(101), true); + cq_verify(cqv); + + memset(ops, 0, sizeof(ops)); + op = ops; + op->op = GRPC_OP_SEND_MESSAGE; + op->data.send_message = request_payload; + op->flags = GRPC_WRITE_BUFFER_HINT; + op++; + error = grpc_call_start_batch(c, ops, (size_t)(op - ops), tag(3), NULL); + GPR_ASSERT(GRPC_CALL_OK == error); + + memset(ops, 0, sizeof(ops)); + op = ops; + op->op = GRPC_OP_SEND_INITIAL_METADATA; + op->data.send_initial_metadata.count = 0; + op++; + error = grpc_call_start_batch(s, ops, (size_t)(op - ops), tag(102), NULL); + GPR_ASSERT(GRPC_CALL_OK == error); + + /* recv message should not succeed yet - it's buffered at the client still */ + memset(ops, 0, sizeof(ops)); + op = ops; + op->op = GRPC_OP_RECV_MESSAGE; + op->data.recv_message = &request_payload_recv1; + op++; + error = grpc_call_start_batch(s, ops, (size_t)(op - ops), tag(103), NULL); + GPR_ASSERT(GRPC_CALL_OK == error); + + CQ_EXPECT_COMPLETION(cqv, tag(2), true); + CQ_EXPECT_COMPLETION(cqv, tag(3), true); + CQ_EXPECT_COMPLETION(cqv, tag(102), true); + cq_verify(cqv); + + /* send end of stream: should release the buffering */ + memset(ops, 0, sizeof(ops)); + op = ops; + op->op = GRPC_OP_SEND_CLOSE_FROM_CLIENT; + op++; + error = grpc_call_start_batch(c, ops, (size_t)(op - ops), tag(4), NULL); + GPR_ASSERT(GRPC_CALL_OK == error); + + /* now the first send should match up with the first recv */ + CQ_EXPECT_COMPLETION(cqv, tag(103), true); + CQ_EXPECT_COMPLETION(cqv, tag(4), true); + cq_verify(cqv); + + /* and the next recv should be ready immediately also (and empty) */ + memset(ops, 0, sizeof(ops)); + op = ops; + op->op = GRPC_OP_RECV_MESSAGE; + op->data.recv_message = &request_payload_recv2; + op++; + error = grpc_call_start_batch(s, ops, (size_t)(op - ops), tag(104), NULL); + GPR_ASSERT(GRPC_CALL_OK == error); + + CQ_EXPECT_COMPLETION(cqv, tag(104), true); + cq_verify(cqv); + + memset(ops, 0, sizeof(ops)); + op = ops; + op->op = GRPC_OP_RECV_STATUS_ON_CLIENT; + op->data.recv_status_on_client.trailing_metadata = &trailing_metadata_recv; + op->data.recv_status_on_client.status = &status; + op->data.recv_status_on_client.status_details = &details; + op->data.recv_status_on_client.status_details_capacity = &details_capacity; + op->flags = 0; + op->reserved = NULL; + op++; + error = grpc_call_start_batch(c, ops, (size_t)(op - ops), tag(4), NULL); + + memset(ops, 0, sizeof(ops)); + op = ops; + op->op = GRPC_OP_RECV_CLOSE_ON_SERVER; + op->data.recv_close_on_server.cancelled = &was_cancelled; + op->flags = 0; + op->reserved = NULL; + op++; + op->op = GRPC_OP_SEND_STATUS_FROM_SERVER; + op->data.send_status_from_server.trailing_metadata_count = 0; + op->data.send_status_from_server.status = GRPC_STATUS_OK; + op->data.send_status_from_server.status_details = "xyz"; + op->flags = 0; + op->reserved = NULL; + op++; + error = grpc_call_start_batch(s, ops, (size_t)(op - ops), tag(105), NULL); + GPR_ASSERT(GRPC_CALL_OK == error); + + CQ_EXPECT_COMPLETION(cqv, tag(105), 1); + CQ_EXPECT_COMPLETION(cqv, tag(4), 1); + cq_verify(cqv); + + GPR_ASSERT(status == GRPC_STATUS_OK); + GPR_ASSERT(0 == strcmp(details, "xyz")); + GPR_ASSERT(0 == strcmp(call_details.method, "/foo")); + validate_host_override_string("foo.test.google.fr:1234", call_details.host, + config); + GPR_ASSERT(was_cancelled == 0); + GPR_ASSERT(byte_buffer_eq_string(request_payload_recv1, "hello world")); + GPR_ASSERT(request_payload_recv2 == NULL); + + gpr_free(details); + grpc_metadata_array_destroy(&initial_metadata_recv); + grpc_metadata_array_destroy(&trailing_metadata_recv); + grpc_metadata_array_destroy(&request_metadata_recv); + grpc_call_details_destroy(&call_details); + + grpc_call_destroy(c); + grpc_call_destroy(s); + + cq_verifier_destroy(cqv); + + grpc_byte_buffer_destroy(request_payload); + grpc_byte_buffer_destroy(request_payload_recv1); + + end_test(&f); + config.tear_down_data(&f); +} + +void write_buffering_at_end(grpc_end2end_test_config config) { + test_invoke_request_with_payload(config); +} + +void write_buffering_at_end_pre_init(void) {} diff --git a/test/core/memory_usage/client.c b/test/core/memory_usage/client.c new file mode 100644 index 0000000000..9fc122b4c3 --- /dev/null +++ b/test/core/memory_usage/client.c @@ -0,0 +1,314 @@ +/* + * + * Copyright 2016, Google Inc. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following disclaimer + * in the documentation and/or other materials provided with the + * distribution. + * * Neither the name of Google Inc. nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + */ + +#include <grpc/grpc.h> + +#include <stdio.h> +#include <string.h> + +#include <grpc/byte_buffer.h> +#include <grpc/byte_buffer_reader.h> +#include <grpc/support/alloc.h> +#include <grpc/support/cmdline.h> +#include <grpc/support/log.h> +#include <grpc/support/time.h> +#include <grpc/support/useful.h> +#include "src/core/lib/support/string.h" +#include "test/core/util/memory_counters.h" +#include "test/core/util/test_config.h" + +static grpc_channel *channel; +static grpc_completion_queue *cq; +static grpc_op metadata_ops[2]; +static grpc_op status_ops[2]; +static grpc_op snapshot_ops[6]; +static grpc_op *op; + +typedef struct { + grpc_call *call; + grpc_metadata_array initial_metadata_recv; + grpc_status_code status; + char *details; + size_t details_capacity; + grpc_metadata_array trailing_metadata_recv; +} fling_call; + +// Statically allocate call data structs. Enough to accomodate 10000 ping-pong +// calls and 1 extra for the snapshot calls. +static fling_call calls[10001]; + +static void *tag(intptr_t t) { return (void *)t; } + +// A call is intentionally divided into two steps. First step is to initiate a +// call (i.e send and recv metadata). A call is outstanding after we initated, +// so we can measure the call memory usage. +static void init_ping_pong_request(int call_idx) { + grpc_metadata_array_init(&calls[call_idx].initial_metadata_recv); + + memset(metadata_ops, 0, sizeof(metadata_ops)); + op = metadata_ops; + op->op = GRPC_OP_SEND_INITIAL_METADATA; + op->data.send_initial_metadata.count = 0; + op++; + op->op = GRPC_OP_RECV_INITIAL_METADATA; + op->data.recv_initial_metadata = &calls[call_idx].initial_metadata_recv; + op++; + + calls[call_idx].call = grpc_channel_create_call( + channel, NULL, GRPC_PROPAGATE_DEFAULTS, cq, "/Reflector/reflectUnary", + "localhost", gpr_inf_future(GPR_CLOCK_REALTIME), NULL); + + GPR_ASSERT(GRPC_CALL_OK == grpc_call_start_batch(calls[call_idx].call, + metadata_ops, + (size_t)(op - metadata_ops), + tag(call_idx), NULL)); + grpc_completion_queue_next(cq, gpr_inf_future(GPR_CLOCK_REALTIME), NULL); +} + +// Second step is to finish the call (i.e recv status) and destroy the call. +static void finish_ping_pong_request(int call_idx) { + grpc_metadata_array_init(&calls[call_idx].trailing_metadata_recv); + + memset(status_ops, 0, sizeof(status_ops)); + op = status_ops; + op->op = GRPC_OP_RECV_STATUS_ON_CLIENT; + op->data.recv_status_on_client.trailing_metadata = + &calls[call_idx].trailing_metadata_recv; + op->data.recv_status_on_client.status = &calls[call_idx].status; + op->data.recv_status_on_client.status_details = &calls[call_idx].details; + op->data.recv_status_on_client.status_details_capacity = + &calls[call_idx].details_capacity; + op++; + + GPR_ASSERT(GRPC_CALL_OK == grpc_call_start_batch(calls[call_idx].call, + status_ops, + (size_t)(op - status_ops), + tag(call_idx), NULL)); + grpc_completion_queue_next(cq, gpr_inf_future(GPR_CLOCK_REALTIME), NULL); + grpc_metadata_array_destroy(&calls[call_idx].initial_metadata_recv); + grpc_metadata_array_destroy(&calls[call_idx].trailing_metadata_recv); + gpr_free(calls[call_idx].details); + grpc_call_destroy(calls[call_idx].call); + calls[call_idx].call = NULL; +} + +static struct grpc_memory_counters send_snapshot_request( + int call_idx, const char *call_type) { + grpc_metadata_array_init(&calls[call_idx].initial_metadata_recv); + grpc_metadata_array_init(&calls[call_idx].trailing_metadata_recv); + + grpc_byte_buffer *response_payload_recv = NULL; + memset(snapshot_ops, 0, sizeof(snapshot_ops)); + op = snapshot_ops; + + op->op = GRPC_OP_SEND_INITIAL_METADATA; + op->data.send_initial_metadata.count = 0; + op++; + op->op = GRPC_OP_SEND_CLOSE_FROM_CLIENT; + op++; + op->op = GRPC_OP_RECV_INITIAL_METADATA; + op->data.recv_initial_metadata = &calls[call_idx].initial_metadata_recv; + op++; + op->op = GRPC_OP_RECV_MESSAGE; + op->data.recv_message = &response_payload_recv; + op++; + op->op = GRPC_OP_RECV_STATUS_ON_CLIENT; + op->data.recv_status_on_client.trailing_metadata = + &calls[call_idx].trailing_metadata_recv; + op->data.recv_status_on_client.status = &calls[call_idx].status; + op->data.recv_status_on_client.status_details = &calls[call_idx].details; + op->data.recv_status_on_client.status_details_capacity = + &calls[call_idx].details_capacity; + op++; + + calls[call_idx].call = grpc_channel_create_call( + channel, NULL, GRPC_PROPAGATE_DEFAULTS, cq, call_type, "localhost", + gpr_inf_future(GPR_CLOCK_REALTIME), NULL); + GPR_ASSERT(GRPC_CALL_OK == grpc_call_start_batch( + calls[call_idx].call, snapshot_ops, + (size_t)(op - snapshot_ops), (void *)0, NULL)); + grpc_completion_queue_next(cq, gpr_inf_future(GPR_CLOCK_REALTIME), NULL); + + grpc_byte_buffer_reader reader; + grpc_byte_buffer_reader_init(&reader, response_payload_recv); + grpc_slice response = grpc_byte_buffer_reader_readall(&reader); + + struct grpc_memory_counters snapshot; + snapshot.total_size_absolute = + ((struct grpc_memory_counters *)GRPC_SLICE_START_PTR(response)) + ->total_size_absolute; + snapshot.total_allocs_absolute = + ((struct grpc_memory_counters *)GRPC_SLICE_START_PTR(response)) + ->total_allocs_absolute; + snapshot.total_size_relative = + ((struct grpc_memory_counters *)GRPC_SLICE_START_PTR(response)) + ->total_size_relative; + snapshot.total_allocs_relative = + ((struct grpc_memory_counters *)GRPC_SLICE_START_PTR(response)) + ->total_allocs_relative; + + grpc_metadata_array_destroy(&calls[call_idx].initial_metadata_recv); + grpc_metadata_array_destroy(&calls[call_idx].trailing_metadata_recv); + grpc_slice_unref(response); + grpc_byte_buffer_reader_destroy(&reader); + grpc_byte_buffer_destroy(response_payload_recv); + gpr_free(calls[call_idx].details); + calls[call_idx].details = NULL; + calls[call_idx].details_capacity = 0; + grpc_call_destroy(calls[call_idx].call); + calls[call_idx].call = NULL; + + return snapshot; +} + +int main(int argc, char **argv) { + grpc_memory_counters_init(); + grpc_slice slice = grpc_slice_from_copied_string("x"); + char *fake_argv[1]; + + char *target = "localhost:443"; + gpr_cmdline *cl; + grpc_event event; + + grpc_init(); + + GPR_ASSERT(argc >= 1); + fake_argv[0] = argv[0]; + grpc_test_init(1, fake_argv); + + int warmup_iterations = 100; + int benchmark_iterations = 1000; + + cl = gpr_cmdline_create("memory profiling client"); + gpr_cmdline_add_string(cl, "target", "Target host:port", &target); + gpr_cmdline_add_int(cl, "warmup", "Warmup iterations", &warmup_iterations); + gpr_cmdline_add_int(cl, "benchmark", "Benchmark iterations", + &benchmark_iterations); + gpr_cmdline_parse(cl, argc, argv); + gpr_cmdline_destroy(cl); + + for (int k = 0; k < (int)(sizeof(calls) / sizeof(fling_call)); k++) { + calls[k].details = NULL; + calls[k].details_capacity = 0; + } + + cq = grpc_completion_queue_create(NULL); + + struct grpc_memory_counters client_channel_start = + grpc_memory_counters_snapshot(); + channel = grpc_insecure_channel_create(target, NULL, NULL); + + int call_idx = 0; + + struct grpc_memory_counters before_server_create = + send_snapshot_request(0, "Reflector/GetBeforeSvrCreation"); + struct grpc_memory_counters after_server_create = + send_snapshot_request(0, "Reflector/GetAfterSvrCreation"); + + // warmup period + for (call_idx = 0; call_idx < warmup_iterations; ++call_idx) { + init_ping_pong_request(call_idx + 1); + } + + struct grpc_memory_counters server_benchmark_calls_start = + send_snapshot_request(0, "Reflector/SimpleSnapshot"); + + struct grpc_memory_counters client_benchmark_calls_start = + grpc_memory_counters_snapshot(); + + // benchmark period + for (; call_idx < warmup_iterations + benchmark_iterations; ++call_idx) { + init_ping_pong_request(call_idx + 1); + } + + struct grpc_memory_counters client_calls_inflight = + grpc_memory_counters_snapshot(); + + struct grpc_memory_counters server_calls_inflight = + send_snapshot_request(0, "Reflector/DestroyCalls"); + + do { + event = grpc_completion_queue_next( + cq, gpr_time_add(gpr_now(GPR_CLOCK_REALTIME), + gpr_time_from_micros(10000, GPR_TIMESPAN)), + NULL); + } while (event.type != GRPC_QUEUE_TIMEOUT); + + // second step - recv status and destroy call + for (call_idx = 0; call_idx < warmup_iterations + benchmark_iterations; + ++call_idx) { + finish_ping_pong_request(call_idx + 1); + } + + struct grpc_memory_counters server_calls_end = + send_snapshot_request(0, "Reflector/SimpleSnapshot"); + + struct grpc_memory_counters client_channel_end = + grpc_memory_counters_snapshot(); + + grpc_channel_destroy(channel); + grpc_completion_queue_shutdown(cq); + + do { + event = grpc_completion_queue_next(cq, gpr_inf_future(GPR_CLOCK_REALTIME), + NULL); + } while (event.type != GRPC_QUEUE_SHUTDOWN); + grpc_slice_unref(slice); + + grpc_completion_queue_destroy(cq); + grpc_shutdown(); + + gpr_log(GPR_INFO, "---------client stats--------"); + gpr_log(GPR_INFO, "client call memory usage: %f bytes per call", + (double)(client_calls_inflight.total_size_relative - + client_benchmark_calls_start.total_size_relative) / + benchmark_iterations); + gpr_log(GPR_INFO, "client channel memory usage %zi bytes", + client_channel_end.total_size_relative - + client_channel_start.total_size_relative); + + gpr_log(GPR_INFO, "---------server stats--------"); + gpr_log(GPR_INFO, "server create: %zi bytes", + after_server_create.total_size_relative - + before_server_create.total_size_relative); + gpr_log(GPR_INFO, "server call memory usage: %f bytes per call", + (double)(server_calls_inflight.total_size_relative - + server_benchmark_calls_start.total_size_relative) / + benchmark_iterations); + gpr_log(GPR_INFO, "server channel memory usage %zi bytes", + server_calls_end.total_size_relative - + after_server_create.total_size_relative); + + grpc_memory_counters_destroy(); + return 0; +} diff --git a/test/core/memory_usage/memory_usage_test.c b/test/core/memory_usage/memory_usage_test.c new file mode 100644 index 0000000000..7e7a9d050d --- /dev/null +++ b/test/core/memory_usage/memory_usage_test.c @@ -0,0 +1,93 @@ +/* + * + * Copyright 2015, Google Inc. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following disclaimer + * in the documentation and/or other materials provided with the + * distribution. + * * Neither the name of Google Inc. nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + */ + +#include <stdio.h> +#include <string.h> + +#include <grpc/support/alloc.h> +#include <grpc/support/host_port.h> +#include <grpc/support/string_util.h> +#include <grpc/support/subprocess.h> +#include "src/core/lib/support/string.h" +#include "test/core/util/port.h" + +int main(int argc, char **argv) { + char *me = argv[0]; + char *lslash = strrchr(me, '/'); + char root[1024]; + int port = grpc_pick_unused_port_or_die(); + char *args[10]; + int status; + gpr_subprocess *svr, *cli; + /* figure out where we are */ + if (lslash) { + memcpy(root, me, (size_t)(lslash - me)); + root[lslash - me] = 0; + } else { + strcpy(root, "."); + } + /* start the server */ + gpr_asprintf(&args[0], "%s/memory_profile_server%s", root, + gpr_subprocess_binary_extension()); + args[1] = "--bind"; + gpr_join_host_port(&args[2], "::", port); + args[3] = "--no-secure"; + svr = gpr_subprocess_create(4, (const char **)args); + gpr_free(args[0]); + gpr_free(args[2]); + + /* start the client */ + gpr_asprintf(&args[0], "%s/memory_profile_client%s", root, + gpr_subprocess_binary_extension()); + args[1] = "--target"; + gpr_join_host_port(&args[2], "127.0.0.1", port); + args[3] = "--warmup=1000"; + args[4] = "--benchmark=9000"; + cli = gpr_subprocess_create(5, (const char **)args); + gpr_free(args[0]); + gpr_free(args[2]); + + /* wait for completion */ + printf("waiting for client\n"); + if ((status = gpr_subprocess_join(cli))) { + gpr_subprocess_destroy(cli); + gpr_subprocess_destroy(svr); + return status; + } + gpr_subprocess_destroy(cli); + + gpr_subprocess_interrupt(svr); + status = gpr_subprocess_join(svr); + gpr_subprocess_destroy(svr); + return status; +} diff --git a/test/core/memory_usage/server.c b/test/core/memory_usage/server.c new file mode 100644 index 0000000000..c0710930b0 --- /dev/null +++ b/test/core/memory_usage/server.c @@ -0,0 +1,321 @@ +/* + * + * Copyright 2016, Google Inc. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following disclaimer + * in the documentation and/or other materials provided with the + * distribution. + * * Neither the name of Google Inc. nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + */ + +#include <grpc/grpc.h> +#include <grpc/grpc_security.h> + +#include <signal.h> +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include <time.h> +#ifndef _WIN32 +/* This is for _exit() below, which is temporary. */ +#include <unistd.h> +#endif + +#include <grpc/support/alloc.h> +#include <grpc/support/cmdline.h> +#include <grpc/support/host_port.h> +#include <grpc/support/log.h> +#include <grpc/support/time.h> +#include "test/core/end2end/data/ssl_test_data.h" +#include "test/core/util/memory_counters.h" +#include "test/core/util/port.h" +#include "test/core/util/test_config.h" + +static grpc_completion_queue *cq; +static grpc_server *server; +static grpc_op metadata_ops[2]; +static grpc_op snapshot_ops[5]; +static grpc_op status_op; +static int got_sigint = 0; +static grpc_byte_buffer *payload_buffer = NULL; +static grpc_byte_buffer *terminal_buffer = NULL; +static int was_cancelled = 2; + +static void *tag(intptr_t t) { return (void *)t; } + +typedef enum { + FLING_SERVER_NEW_REQUEST = 1, + FLING_SERVER_SEND_INIT_METADATA, + FLING_SERVER_WAIT_FOR_DESTROY, + FLING_SERVER_SEND_STATUS_FLING_CALL, + FLING_SERVER_SEND_STATUS_SNAPSHOT, + FLING_SERVER_BATCH_SEND_STATUS_FLING_CALL +} fling_server_tags; + +typedef struct { + fling_server_tags state; + grpc_call *call; + grpc_call_details call_details; + grpc_metadata_array request_metadata_recv; + grpc_metadata_array initial_metadata_send; +} fling_call; + +// hold up to 10000 calls and 6 snaphost calls +static fling_call calls[100006]; + +static void request_call_unary(int call_idx) { + if (call_idx == (int)(sizeof(calls) / sizeof(fling_call))) { + gpr_log(GPR_INFO, "Used all call slots (10000) on server. Server exit."); + _exit(0); + } + grpc_metadata_array_init(&calls[call_idx].request_metadata_recv); + grpc_server_request_call( + server, &calls[call_idx].call, &calls[call_idx].call_details, + &calls[call_idx].request_metadata_recv, cq, cq, &calls[call_idx]); +} + +static void send_initial_metadata_unary(void *tag) { + grpc_metadata_array_init(&(*(fling_call *)tag).initial_metadata_send); + metadata_ops[0].op = GRPC_OP_SEND_INITIAL_METADATA; + metadata_ops[0].data.send_initial_metadata.count = 0; + + GPR_ASSERT(GRPC_CALL_OK == grpc_call_start_batch((*(fling_call *)tag).call, + metadata_ops, 1, tag, NULL)); +} + +static void send_status(void *tag) { + status_op.op = GRPC_OP_SEND_STATUS_FROM_SERVER; + status_op.data.send_status_from_server.status = GRPC_STATUS_OK; + status_op.data.send_status_from_server.trailing_metadata_count = 0; + status_op.data.send_status_from_server.status_details = ""; + + GPR_ASSERT(GRPC_CALL_OK == grpc_call_start_batch((*(fling_call *)tag).call, + &status_op, 1, tag, NULL)); +} + +static void send_snapshot(void *tag, struct grpc_memory_counters *snapshot) { + grpc_op *op; + + grpc_slice snapshot_slice = + grpc_slice_new(snapshot, sizeof(*snapshot), gpr_free); + payload_buffer = grpc_raw_byte_buffer_create(&snapshot_slice, 1); + grpc_metadata_array_init(&(*(fling_call *)tag).initial_metadata_send); + + op = snapshot_ops; + op->op = GRPC_OP_SEND_INITIAL_METADATA; + op->data.send_initial_metadata.count = 0; + op++; + op->op = GRPC_OP_RECV_MESSAGE; + op->data.recv_message = &terminal_buffer; + op++; + op->op = GRPC_OP_SEND_MESSAGE; + if (payload_buffer == NULL) { + gpr_log(GPR_INFO, "NULL payload buffer !!!"); + } + op->data.send_message = payload_buffer; + op++; + op->op = GRPC_OP_SEND_STATUS_FROM_SERVER; + op->data.send_status_from_server.status = GRPC_STATUS_OK; + op->data.send_status_from_server.trailing_metadata_count = 0; + op->data.send_status_from_server.status_details = ""; + op++; + op->op = GRPC_OP_RECV_CLOSE_ON_SERVER; + op->data.recv_close_on_server.cancelled = &was_cancelled; + op++; + + GPR_ASSERT(GRPC_CALL_OK == + grpc_call_start_batch((*(fling_call *)tag).call, snapshot_ops, + (size_t)(op - snapshot_ops), tag, NULL)); +} +/* We have some sort of deadlock, so let's not exit gracefully for now. + When that is resolved, please remove the #include <unistd.h> above. */ +static void sigint_handler(int x) { _exit(0); } + +int main(int argc, char **argv) { + grpc_memory_counters_init(); + grpc_event ev; + char *addr_buf = NULL; + gpr_cmdline *cl; + int shutdown_started = 0; + int shutdown_finished = 0; + + int secure = 0; + char *addr = NULL; + + char *fake_argv[1]; + + GPR_ASSERT(argc >= 1); + fake_argv[0] = argv[0]; + grpc_test_init(1, fake_argv); + + grpc_init(); + srand((unsigned)clock()); + + cl = gpr_cmdline_create("fling server"); + gpr_cmdline_add_string(cl, "bind", "Bind host:port", &addr); + gpr_cmdline_add_flag(cl, "secure", "Run with security?", &secure); + gpr_cmdline_parse(cl, argc, argv); + gpr_cmdline_destroy(cl); + + if (addr == NULL) { + gpr_join_host_port(&addr_buf, "::", grpc_pick_unused_port_or_die()); + addr = addr_buf; + } + gpr_log(GPR_INFO, "creating server on: %s", addr); + + cq = grpc_completion_queue_create(NULL); + + struct grpc_memory_counters before_server_create = + grpc_memory_counters_snapshot(); + if (secure) { + grpc_ssl_pem_key_cert_pair pem_key_cert_pair = {test_server1_key, + test_server1_cert}; + grpc_server_credentials *ssl_creds = grpc_ssl_server_credentials_create( + NULL, &pem_key_cert_pair, 1, 0, NULL); + server = grpc_server_create(NULL, NULL); + GPR_ASSERT(grpc_server_add_secure_http2_port(server, addr, ssl_creds)); + grpc_server_credentials_release(ssl_creds); + } else { + server = grpc_server_create(NULL, NULL); + GPR_ASSERT(grpc_server_add_insecure_http2_port(server, addr)); + } + + grpc_server_register_completion_queue(server, cq, NULL); + grpc_server_start(server); + + struct grpc_memory_counters after_server_create = + grpc_memory_counters_snapshot(); + + gpr_free(addr_buf); + addr = addr_buf = NULL; + + // initialize call instances + for (int i = 0; i < (int)(sizeof(calls) / sizeof(fling_call)); i++) { + grpc_call_details_init(&calls[i].call_details); + calls[i].state = FLING_SERVER_NEW_REQUEST; + } + + int next_call_idx = 0; + struct grpc_memory_counters current_snapshot; + + request_call_unary(next_call_idx); + + signal(SIGINT, sigint_handler); + + while (!shutdown_finished) { + if (got_sigint && !shutdown_started) { + gpr_log(GPR_INFO, "Shutting down due to SIGINT"); + grpc_server_shutdown_and_notify(server, cq, tag(1000)); + GPR_ASSERT(grpc_completion_queue_pluck( + cq, tag(1000), GRPC_TIMEOUT_SECONDS_TO_DEADLINE(5), NULL) + .type == GRPC_OP_COMPLETE); + grpc_completion_queue_shutdown(cq); + shutdown_started = 1; + } + ev = grpc_completion_queue_next( + cq, gpr_time_add(gpr_now(GPR_CLOCK_REALTIME), + gpr_time_from_micros(1000000, GPR_TIMESPAN)), + NULL); + fling_call *s = ev.tag; + switch (ev.type) { + case GRPC_OP_COMPLETE: + switch (s->state) { + case FLING_SERVER_NEW_REQUEST: + request_call_unary(++next_call_idx); + if (0 == + strcmp(s->call_details.method, "/Reflector/reflectUnary")) { + s->state = FLING_SERVER_SEND_INIT_METADATA; + send_initial_metadata_unary(s); + } else if (0 == strcmp(s->call_details.method, + "Reflector/GetBeforeSvrCreation")) { + s->state = FLING_SERVER_SEND_STATUS_SNAPSHOT; + send_snapshot(s, &before_server_create); + } else if (0 == strcmp(s->call_details.method, + "Reflector/GetAfterSvrCreation")) { + s->state = FLING_SERVER_SEND_STATUS_SNAPSHOT; + send_snapshot(s, &after_server_create); + } else if (0 == strcmp(s->call_details.method, + "Reflector/SimpleSnapshot")) { + s->state = FLING_SERVER_SEND_STATUS_SNAPSHOT; + current_snapshot = grpc_memory_counters_snapshot(); + send_snapshot(s, ¤t_snapshot); + } else if (0 == strcmp(s->call_details.method, + "Reflector/DestroyCalls")) { + s->state = FLING_SERVER_BATCH_SEND_STATUS_FLING_CALL; + current_snapshot = grpc_memory_counters_snapshot(); + send_snapshot(s, ¤t_snapshot); + } else { + gpr_log(GPR_ERROR, "Wrong call method"); + } + break; + case FLING_SERVER_SEND_INIT_METADATA: + s->state = FLING_SERVER_WAIT_FOR_DESTROY; + break; + case FLING_SERVER_WAIT_FOR_DESTROY: + break; + case FLING_SERVER_SEND_STATUS_FLING_CALL: + grpc_call_destroy(s->call); + grpc_call_details_destroy(&s->call_details); + grpc_metadata_array_destroy(&s->initial_metadata_send); + grpc_metadata_array_destroy(&s->request_metadata_recv); + break; + case FLING_SERVER_BATCH_SEND_STATUS_FLING_CALL: + for (int k = 0; k < (int)(sizeof(calls) / sizeof(fling_call)); + ++k) { + if (calls[k].state == FLING_SERVER_WAIT_FOR_DESTROY) { + calls[k].state = FLING_SERVER_SEND_STATUS_FLING_CALL; + send_status(&calls[k]); + } + } + // no break here since we want to continue to case + // FLING_SERVER_SEND_STATUS_SNAPSHOT to destroy the snapshot call + case FLING_SERVER_SEND_STATUS_SNAPSHOT: + grpc_byte_buffer_destroy(payload_buffer); + grpc_byte_buffer_destroy(terminal_buffer); + grpc_call_destroy(s->call); + grpc_call_details_destroy(&s->call_details); + grpc_metadata_array_destroy(&s->initial_metadata_send); + grpc_metadata_array_destroy(&s->request_metadata_recv); + terminal_buffer = NULL; + payload_buffer = NULL; + break; + } + break; + case GRPC_QUEUE_SHUTDOWN: + GPR_ASSERT(shutdown_started); + shutdown_finished = 1; + break; + case GRPC_QUEUE_TIMEOUT: + break; + } + } + + grpc_server_destroy(server); + grpc_completion_queue_destroy(cq); + grpc_shutdown(); + grpc_memory_counters_destroy(); + return 0; +} |