| 272 if(client->req_content_length != 0) { |
272 if(client->req_content_length != 0) { |
| 273 if(client_send_request_body(client)) { |
273 if(client_send_request_body(client)) { |
| 274 return client->error == 0; |
274 return client->error == 0; |
| 275 } |
275 } |
| 276 } |
276 } |
| |
277 |
| |
278 client->transfer_buffer_pos = 0; |
| |
279 client->transfer_buffer_len = 0; |
| 277 } |
280 } |
| 278 |
281 |
| 279 // writing complete, switch to read events |
282 // writing complete, switch to read events |
| 280 event->events = EVENT_POLLIN; |
283 event->events = EVENT_POLLIN; |
| 281 client->stage = 1; |
284 client->stage = 1; |
| 282 client->transfer_buffer_pos = 0; |
|
| 283 client->transfer_buffer_len = 0; |
|
| 284 |
285 |
| 285 if(client_read_response_header(client)) { |
286 if(client_read_response_header(client)) { |
| 286 return client->error == 0; |
287 return client->error == 0; |
| 287 } |
288 } |
| 288 if(client_read_response_body(client)) { |
289 if(client_read_response_body(client)) { |
| 666 return 0; |
669 return 0; |
| 667 } |
670 } |
| 668 |
671 |
| 669 static ssize_t test_response_body_write(HttpClient *client, void *buf, size_t size, void *userdata) { |
672 static ssize_t test_response_body_write(HttpClient *client, void *buf, size_t size, void *userdata) { |
| 670 TestResponse *test = userdata; |
673 TestResponse *test = userdata; |
| |
674 if(test->error_interval > 0 && test->error_test >= test->error_interval) { |
| |
675 test->error_test = 0; |
| |
676 return HTTP_CLIENT_CALLBACK_WOULD_BLOCK; |
| |
677 } |
| |
678 test->error_test++; |
| |
679 |
| 671 cxBufferWrite(buf, 1, size, test->response); |
680 cxBufferWrite(buf, 1, size, test->response); |
| 672 return size; |
681 return size; |
| 673 } |
682 } |
| 674 |
683 |
| 675 |
684 |
| 963 |
972 |
| 964 size_t req_header_len = client->transfer_buffer_len; |
973 size_t req_header_len = client->transfer_buffer_len; |
| 965 |
974 |
| 966 TestResponse testr = { 0 }; |
975 TestResponse testr = { 0 }; |
| 967 testr.response = out_buf; |
976 testr.response = out_buf; |
| |
977 testr.error_interval = error_interval; |
| 968 client->response_start = test_response_start; |
978 client->response_start = test_response_start; |
| 969 client->response_start_userdata = &testr; |
979 client->response_start_userdata = &testr; |
| 970 client->response_body_write = test_response_body_write; |
980 client->response_body_write = test_response_body_write; |
| 971 client->response_body_write_userdata = &testr; |
981 client->response_body_write_userdata = &testr; |
| 972 |
982 |
| 996 const char *response_str = response.ptr; |
1006 const char *response_str = response.ptr; |
| 997 size_t response_str_len = response.length; |
1007 size_t response_str_len = response.length; |
| 998 size_t response_str_pos = 0; |
1008 size_t response_str_pos = 0; |
| 999 |
1009 |
| 1000 // send response and do IO |
1010 // send response and do IO |
| 1001 while(response_str_pos < response_str_len) { |
1011 int in_progress = 1; |
| |
1012 while(in_progress) { |
| 1002 size_t len = response_str_len - response_str_pos; |
1013 size_t len = response_str_len - response_str_pos; |
| 1003 if(len > write_blocksz) { |
1014 if(len > 0) { |
| 1004 len = write_blocksz; |
1015 if(len > write_blocksz) { |
| 1005 } |
1016 len = write_blocksz; |
| 1006 ssize_t w = write(sock, response_str + response_str_pos, len); |
1017 } |
| 1007 if(w == 0) { |
1018 ssize_t w = write(sock, response_str + response_str_pos, len); |
| 1008 break; |
1019 if(w == 0) { |
| 1009 } |
1020 break; |
| 1010 CX_TEST_ASSERT(w > 0); |
1021 } |
| 1011 response_str_pos += w; |
1022 CX_TEST_ASSERT(w > 0); |
| 1012 |
1023 response_str_pos += w; |
| |
1024 } |
| |
1025 |
| 1013 ret = client_io(&dummy, &event); |
1026 ret = client_io(&dummy, &event); |
| |
1027 if(ret == 0) { |
| |
1028 in_progress = 0; |
| |
1029 } |
| 1014 |
1030 |
| 1015 CX_TEST_ASSERT(!client->error); |
1031 CX_TEST_ASSERT(!client->error); |
| 1016 } |
1032 } |
| 1017 CX_TEST_ASSERT(response_str_pos == response_str_len); |
1033 CX_TEST_ASSERT(response_str_pos == response_str_len); |
| 1018 CX_TEST_ASSERT(testr.status == status_code); |
1034 CX_TEST_ASSERT(testr.status == status_code); |
| 1024 close(fds[0]); |
1040 close(fds[0]); |
| 1025 close(fds[1]); |
1041 close(fds[1]); |
| 1026 http_client_free(client); |
1042 http_client_free(client); |
| 1027 } |
1043 } |
| 1028 |
1044 |
| 1029 static CX_TEST_SUBROUTINE(test_http_client_io_simple, size_t blocksz) { |
1045 static CX_TEST_SUBROUTINE(test_http_client_io_simple, size_t blocksz, int error_interval) { |
| 1030 cxstring response_str = cx_str( |
1046 cxstring response_str = cx_str( |
| 1031 "HTTP/1.1 200 OK\r\n" |
1047 "HTTP/1.1 200 OK\r\n" |
| 1032 "Host: localhost\r\n" |
1048 "Host: localhost\r\n" |
| 1033 "Content-length: 13\r\n" |
1049 "Content-length: 13\r\n" |
| 1034 "\r\n" |
1050 "\r\n" |
| 1035 "Hello World!\n"); |
1051 "Hello World!\n"); |
| 1036 CxBuffer *buf = cxBufferCreate(NULL, NULL, 1024, CX_BUFFER_AUTO_EXTEND|CX_BUFFER_FREE_CONTENTS); |
1052 CxBuffer *buf = cxBufferCreate(NULL, NULL, 1024, CX_BUFFER_AUTO_EXTEND|CX_BUFFER_FREE_CONTENTS); |
| 1037 |
1053 |
| 1038 CX_TEST_CALL_SUBROUTINE(test_http_client_io, response_str, 200, "OK", buf, blocksz); |
1054 CX_TEST_CALL_SUBROUTINE(test_http_client_io, response_str, 200, "OK", buf, blocksz, error_interval); |
| 1039 CX_TEST_ASSERT(buf->size == 13); |
1055 CX_TEST_ASSERT(buf->size == 13); |
| 1040 CX_TEST_ASSERT(!cx_strcmp(cx_strn(buf->space, buf->size), "Hello World!\n")); |
1056 CX_TEST_ASSERT(!cx_strcmp(cx_strn(buf->space, buf->size), "Hello World!\n")); |
| 1041 |
1057 |
| 1042 cxBufferFree(buf); |
1058 cxBufferFree(buf); |
| 1043 } |
1059 } |
| 1044 |
1060 |
| 1045 static CX_TEST(test_http_client_io_simple_1b) { |
1061 static CX_TEST(test_http_client_io_simple_1b) { |
| 1046 CX_TEST_DO { |
1062 CX_TEST_DO { |
| 1047 CX_TEST_CALL_SUBROUTINE(test_http_client_io_simple, 1); |
1063 CX_TEST_CALL_SUBROUTINE(test_http_client_io_simple, 1, 0); |
| 1048 } |
1064 } |
| 1049 } |
1065 } |
| 1050 |
1066 |
| 1051 static CX_TEST(test_http_client_io_simple_2b) { |
1067 static CX_TEST(test_http_client_io_simple_2b) { |
| 1052 CX_TEST_DO { |
1068 CX_TEST_DO { |
| 1053 CX_TEST_CALL_SUBROUTINE(test_http_client_io_simple, 2); |
1069 CX_TEST_CALL_SUBROUTINE(test_http_client_io_simple, 2, 0); |
| 1054 } |
1070 } |
| 1055 } |
1071 } |
| 1056 |
1072 |
| 1057 static CX_TEST(test_http_client_io_simple_3b) { |
1073 static CX_TEST(test_http_client_io_simple_3b) { |
| 1058 CX_TEST_DO { |
1074 CX_TEST_DO { |
| 1059 CX_TEST_CALL_SUBROUTINE(test_http_client_io_simple, 3); |
1075 CX_TEST_CALL_SUBROUTINE(test_http_client_io_simple, 3, 0); |
| 1060 } |
1076 } |
| 1061 } |
1077 } |
| 1062 |
1078 |
| 1063 static CX_TEST(test_http_client_io_simple_16b) { |
1079 static CX_TEST(test_http_client_io_simple_16b) { |
| 1064 CX_TEST_DO { |
1080 CX_TEST_DO { |
| 1065 CX_TEST_CALL_SUBROUTINE(test_http_client_io_simple, 16); |
1081 CX_TEST_CALL_SUBROUTINE(test_http_client_io_simple, 16, 0); |
| 1066 } |
1082 } |
| 1067 } |
1083 } |
| 1068 |
1084 |
| 1069 static CX_TEST(test_http_client_io_simple_512b) { |
1085 static CX_TEST(test_http_client_io_simple_512b) { |
| 1070 CX_TEST_DO { |
1086 CX_TEST_DO { |
| 1071 CX_TEST_CALL_SUBROUTINE(test_http_client_io_simple, 512); |
1087 CX_TEST_CALL_SUBROUTINE(test_http_client_io_simple, 512, 0); |
| 1072 } |
1088 } |
| 1073 } |
1089 } |
| 1074 |
1090 |
| 1075 static CX_TEST_SUBROUTINE(test_http_client_io_large, size_t blocksz) { |
1091 static CX_TEST_SUBROUTINE(test_http_client_io_large, size_t blocksz) { |
| 1076 int ctlen = 1024*1024*32; |
1092 int ctlen = 1024*1024*32; |
| 1087 resp->pos += ctlen; |
1103 resp->pos += ctlen; |
| 1088 resp->size += ctlen; |
1104 resp->size += ctlen; |
| 1089 |
1105 |
| 1090 CxBuffer *buf = cxBufferCreate(NULL, NULL, 1024, CX_BUFFER_AUTO_EXTEND|CX_BUFFER_FREE_CONTENTS); |
1106 CxBuffer *buf = cxBufferCreate(NULL, NULL, 1024, CX_BUFFER_AUTO_EXTEND|CX_BUFFER_FREE_CONTENTS); |
| 1091 |
1107 |
| 1092 CX_TEST_CALL_SUBROUTINE(test_http_client_io, cx_strn(resp->space, resp->size), 200, "OK", buf, blocksz); |
1108 CX_TEST_CALL_SUBROUTINE(test_http_client_io, cx_strn(resp->space, resp->size), 200, "OK", buf, blocksz, 0); |
| 1093 CX_TEST_ASSERT(buf->size == ctlen); |
1109 CX_TEST_ASSERT(buf->size == ctlen); |
| 1094 CX_TEST_ASSERT(!memcmp(buf->space, resp->space + content_start, ctlen)); |
1110 CX_TEST_ASSERT(!memcmp(buf->space, resp->space + content_start, ctlen)); |
| 1095 |
1111 |
| 1096 cxBufferFree(resp); |
1112 cxBufferFree(resp); |
| 1097 cxBufferFree(buf); |
1113 cxBufferFree(buf); |
| 1107 CX_TEST_DO { |
1123 CX_TEST_DO { |
| 1108 CX_TEST_CALL_SUBROUTINE(test_http_client_io_large, 1024); |
1124 CX_TEST_CALL_SUBROUTINE(test_http_client_io_large, 1024); |
| 1109 } |
1125 } |
| 1110 } |
1126 } |
| 1111 |
1127 |
| 1112 static CX_TEST_SUBROUTINE(test_http_client_io_chunked_transfer, size_t blocksz) { |
1128 static CX_TEST_SUBROUTINE(test_http_client_io_chunked_transfer, size_t blocksz, int error_interval) { |
| 1113 cxstring response_str = cx_str( |
1129 cxstring response_str = cx_str( |
| 1114 "HTTP/1.1 200 OK\r\n" |
1130 "HTTP/1.1 200 OK\r\n" |
| 1115 "Host: localhost\r\n" |
1131 "Host: localhost\r\n" |
| 1116 "Transfer-encoding: chunked\r\n" |
1132 "Transfer-encoding: chunked\r\n" |
| 1117 "\r\n" |
1133 "\r\n" |
| 1119 "Hello World!\n" |
1135 "Hello World!\n" |
| 1120 "\r\n" |
1136 "\r\n" |
| 1121 "0\r\n\r\n"); |
1137 "0\r\n\r\n"); |
| 1122 CxBuffer *buf = cxBufferCreate(NULL, NULL, 1024, CX_BUFFER_AUTO_EXTEND|CX_BUFFER_FREE_CONTENTS); |
1138 CxBuffer *buf = cxBufferCreate(NULL, NULL, 1024, CX_BUFFER_AUTO_EXTEND|CX_BUFFER_FREE_CONTENTS); |
| 1123 |
1139 |
| 1124 CX_TEST_CALL_SUBROUTINE(test_http_client_io, response_str, 200, "OK", buf, blocksz); |
1140 CX_TEST_CALL_SUBROUTINE(test_http_client_io, response_str, 200, "OK", buf, blocksz, error_interval); |
| 1125 CX_TEST_ASSERT(buf->size == 13); |
1141 CX_TEST_ASSERT(buf->size == 13); |
| 1126 CX_TEST_ASSERT(!cx_strcmp(cx_strn(buf->space, buf->size), "Hello World!\n")); |
1142 CX_TEST_ASSERT(!cx_strcmp(cx_strn(buf->space, buf->size), "Hello World!\n")); |
| 1127 |
1143 |
| 1128 cxBufferFree(buf); |
1144 cxBufferFree(buf); |
| 1129 } |
1145 } |
| 1130 |
1146 |
| 1131 static CX_TEST(test_http_client_io_chunked_transfer_1b) { |
1147 static CX_TEST(test_http_client_io_chunked_transfer_1b) { |
| 1132 CX_TEST_DO { |
1148 CX_TEST_DO { |
| 1133 CX_TEST_CALL_SUBROUTINE(test_http_client_io_chunked_transfer, 1); |
1149 CX_TEST_CALL_SUBROUTINE(test_http_client_io_chunked_transfer, 1, 0); |
| 1134 } |
1150 } |
| 1135 } |
1151 } |
| 1136 |
1152 |
| 1137 static CX_TEST(test_http_client_io_chunked_transfer_2b) { |
1153 static CX_TEST(test_http_client_io_chunked_transfer_2b) { |
| 1138 CX_TEST_DO { |
1154 CX_TEST_DO { |
| 1139 CX_TEST_CALL_SUBROUTINE(test_http_client_io_chunked_transfer, 2); |
1155 CX_TEST_CALL_SUBROUTINE(test_http_client_io_chunked_transfer, 2, 0); |
| 1140 } |
1156 } |
| 1141 } |
1157 } |
| 1142 |
1158 |
| 1143 static CX_TEST(test_http_client_io_chunked_transfer_8b) { |
1159 static CX_TEST(test_http_client_io_chunked_transfer_8b) { |
| 1144 CX_TEST_DO { |
1160 CX_TEST_DO { |
| 1145 CX_TEST_CALL_SUBROUTINE(test_http_client_io_chunked_transfer, 16); |
1161 CX_TEST_CALL_SUBROUTINE(test_http_client_io_chunked_transfer, 16, 0); |
| 1146 } |
1162 } |
| 1147 } |
1163 } |
| 1148 |
1164 |
| 1149 static CX_TEST(test_http_client_io_chunked_transfer_64b) { |
1165 static CX_TEST(test_http_client_io_chunked_transfer_64b) { |
| 1150 CX_TEST_DO { |
1166 CX_TEST_DO { |
| 1151 CX_TEST_CALL_SUBROUTINE(test_http_client_io_chunked_transfer, 64); |
1167 CX_TEST_CALL_SUBROUTINE(test_http_client_io_chunked_transfer, 64, 0); |
| 1152 } |
1168 } |
| 1153 } |
1169 } |
| 1154 |
1170 |
| 1155 static CX_TEST_SUBROUTINE(test_http_client_io_large_chunked_transfer, size_t blocksz) { |
1171 static CX_TEST_SUBROUTINE(test_http_client_io_large_chunked_transfer, size_t blocksz, int error_interval) { |
| 1156 int chunk1 = 1024*1024*2; |
1172 int chunk1 = 1024*1024*2; |
| 1157 int chunk2 = 1024*128; |
1173 int chunk2 = 1024*128; |
| 1158 int chunk3 = 123; |
1174 int chunk3 = 123; |
| 1159 int chunk4 = 1024*1024*5; |
1175 int chunk4 = 1024*1024*5; |
| 1160 int chunk5 = 1024*16; |
1176 int chunk5 = 1024*16; |
| 1202 cxBufferPutString(resp, "\r\n0\r\n\r\n"); |
1218 cxBufferPutString(resp, "\r\n0\r\n\r\n"); |
| 1203 |
1219 |
| 1204 |
1220 |
| 1205 CxBuffer *buf = cxBufferCreate(NULL, NULL, 1024, CX_BUFFER_AUTO_EXTEND|CX_BUFFER_FREE_CONTENTS); |
1221 CxBuffer *buf = cxBufferCreate(NULL, NULL, 1024, CX_BUFFER_AUTO_EXTEND|CX_BUFFER_FREE_CONTENTS); |
| 1206 |
1222 |
| 1207 CX_TEST_CALL_SUBROUTINE(test_http_client_io, cx_strn(resp->space, resp->size), 200, "OK", buf, blocksz); |
1223 CX_TEST_CALL_SUBROUTINE(test_http_client_io, cx_strn(resp->space, resp->size), 200, "OK", buf, blocksz, error_interval); |
| 1208 CX_TEST_ASSERT(buf->size == ctlen); |
1224 CX_TEST_ASSERT(buf->size == ctlen); |
| 1209 CX_TEST_ASSERT(!memcmp(buf->space, resp->space + chunk1_pos, chunk1)); |
1225 CX_TEST_ASSERT(!memcmp(buf->space, resp->space + chunk1_pos, chunk1)); |
| 1210 CX_TEST_ASSERT(!memcmp(buf->space + chunk1, resp->space + chunk2_pos, chunk2)); |
1226 CX_TEST_ASSERT(!memcmp(buf->space + chunk1, resp->space + chunk2_pos, chunk2)); |
| 1211 CX_TEST_ASSERT(!memcmp(buf->space + chunk1 + chunk2, resp->space + chunk3_pos, chunk3)); |
1227 CX_TEST_ASSERT(!memcmp(buf->space + chunk1 + chunk2, resp->space + chunk3_pos, chunk3)); |
| 1212 CX_TEST_ASSERT(!memcmp(buf->space + chunk1 + chunk2 + chunk3, resp->space + chunk4_pos, chunk4)); |
1228 CX_TEST_ASSERT(!memcmp(buf->space + chunk1 + chunk2 + chunk3, resp->space + chunk4_pos, chunk4)); |
| 1216 cxBufferFree(buf); |
1232 cxBufferFree(buf); |
| 1217 } |
1233 } |
| 1218 |
1234 |
| 1219 static CX_TEST(test_http_client_io_large_chunked_transfer_1024b) { |
1235 static CX_TEST(test_http_client_io_large_chunked_transfer_1024b) { |
| 1220 CX_TEST_DO { |
1236 CX_TEST_DO { |
| 1221 CX_TEST_CALL_SUBROUTINE(test_http_client_io_large_chunked_transfer, 1024); |
1237 CX_TEST_CALL_SUBROUTINE(test_http_client_io_large_chunked_transfer, 1024, 0); |
| |
1238 } |
| |
1239 } |
| |
1240 |
| |
1241 static CX_TEST(test_http_client_io_write_error1) { |
| |
1242 CX_TEST_DO { |
| |
1243 CX_TEST_CALL_SUBROUTINE(test_http_client_io_simple, 1, 1); |
| |
1244 } |
| |
1245 } |
| |
1246 |
| |
1247 static CX_TEST(test_http_client_io_write_error2) { |
| |
1248 CX_TEST_DO { |
| |
1249 CX_TEST_CALL_SUBROUTINE(test_http_client_io_simple, 1, 2); |
| |
1250 } |
| |
1251 } |
| |
1252 |
| |
1253 static CX_TEST(test_http_client_io_write_error3) { |
| |
1254 CX_TEST_DO { |
| |
1255 CX_TEST_CALL_SUBROUTINE(test_http_client_io_simple, 1, 3); |
| |
1256 } |
| |
1257 } |
| |
1258 |
| |
1259 static CX_TEST(test_http_client_io_write_blsz8_error1) { |
| |
1260 CX_TEST_DO { |
| |
1261 CX_TEST_CALL_SUBROUTINE(test_http_client_io_simple, 8, 1); |
| |
1262 } |
| |
1263 } |
| |
1264 |
| |
1265 static CX_TEST(test_http_client_io_write_blsz8_error2) { |
| |
1266 CX_TEST_DO { |
| |
1267 CX_TEST_CALL_SUBROUTINE(test_http_client_io_simple, 8, 2); |
| |
1268 } |
| |
1269 } |
| |
1270 |
| |
1271 static CX_TEST(test_http_client_io_write_blsz8_error3) { |
| |
1272 CX_TEST_DO { |
| |
1273 CX_TEST_CALL_SUBROUTINE(test_http_client_io_simple, 8, 3); |
| 1222 } |
1274 } |
| 1223 } |
1275 } |
| 1224 |
1276 |
| 1225 void http_client_add_tests(CxTestSuite *suite) { |
1277 void http_client_add_tests(CxTestSuite *suite) { |
| 1226 cx_test_register(suite, test_http_client_send_request); |
1278 cx_test_register(suite, test_http_client_send_request); |
| 1238 cx_test_register(suite, test_http_client_io_chunked_transfer_1b); |
1290 cx_test_register(suite, test_http_client_io_chunked_transfer_1b); |
| 1239 cx_test_register(suite, test_http_client_io_chunked_transfer_2b); |
1291 cx_test_register(suite, test_http_client_io_chunked_transfer_2b); |
| 1240 cx_test_register(suite, test_http_client_io_chunked_transfer_8b); |
1292 cx_test_register(suite, test_http_client_io_chunked_transfer_8b); |
| 1241 cx_test_register(suite, test_http_client_io_chunked_transfer_64b); |
1293 cx_test_register(suite, test_http_client_io_chunked_transfer_64b); |
| 1242 cx_test_register(suite, test_http_client_io_large_chunked_transfer_1024b); |
1294 cx_test_register(suite, test_http_client_io_large_chunked_transfer_1024b); |
| 1243 } |
1295 cx_test_register(suite, test_http_client_io_write_error1); |
| |
1296 cx_test_register(suite, test_http_client_io_write_error2); |
| |
1297 cx_test_register(suite, test_http_client_io_write_error3); |
| |
1298 cx_test_register(suite, test_http_client_io_write_blsz8_error1); |
| |
1299 cx_test_register(suite, test_http_client_io_write_blsz8_error2); |
| |
1300 cx_test_register(suite, test_http_client_io_write_blsz8_error3); |
| |
1301 } |