diff --git a/dlls/wininet/tests/http.c b/dlls/wininet/tests/http.c index f4d0b43b731..1682b0553aa 100644 --- a/dlls/wininet/tests/http.c +++ b/dlls/wininet/tests/http.c @@ -188,8 +188,9 @@ static BOOL proxy_active(void) return proxy_enable != 0; } -#define test_status_code(a,b) _test_status_code(__LINE__,a,b) -static void _test_status_code(unsigned line, HINTERNET req, DWORD excode) +#define test_status_code(a,b) _test_status_code(__LINE__,a,b, FALSE) +#define test_status_code_todo(a,b) _test_status_code(__LINE__,a,b, TRUE) +static void _test_status_code(unsigned line, HINTERNET req, DWORD excode, BOOL is_todo) { DWORD code, size, index; char exbuf[10], bufa[10]; @@ -200,7 +201,10 @@ static void _test_status_code(unsigned line, HINTERNET req, DWORD excode) size = sizeof(code); res = HttpQueryInfoA(req, HTTP_QUERY_STATUS_CODE|HTTP_QUERY_FLAG_NUMBER, &code, &size, NULL); ok_(__FILE__,line)(res, "[1] HttpQueryInfoA(HTTP_QUERY_STATUS_CODE|number) failed: %u\n", GetLastError()); - ok_(__FILE__,line)(code == excode, "code = %d, expected %d\n", code, excode); + if (is_todo) + todo_wine ok_(__FILE__,line)(code == excode, "code = %d, expected %d\n", code, excode); + else + ok_(__FILE__,line)(code == excode, "code = %d, expected %d\n", code, excode); ok_(__FILE__,line)(size == sizeof(code), "size = %u\n", size); code = 0xdeadbeef; @@ -208,8 +212,10 @@ static void _test_status_code(unsigned line, HINTERNET req, DWORD excode) size = sizeof(code); res = HttpQueryInfoA(req, HTTP_QUERY_STATUS_CODE|HTTP_QUERY_FLAG_NUMBER, &code, &size, &index); ok_(__FILE__,line)(res, "[2] HttpQueryInfoA(HTTP_QUERY_STATUS_CODE|number index) failed: %u\n", GetLastError()); - ok_(__FILE__,line)(code == excode, "code = %d, expected %d\n", code, excode); - ok_(__FILE__,line)(!index, "index = %d, expected 0\n", code); + if (is_todo) + todo_wine ok_(__FILE__,line)(code == excode, "code = %d, expected %d\n", code, excode); + else + ok_(__FILE__,line)(!index, "index = %d, expected 0\n", code); ok_(__FILE__,line)(size == sizeof(code), "size = %u\n", size); sprintf(exbuf, "%u", excode); @@ -217,7 +223,10 @@ static void _test_status_code(unsigned line, HINTERNET req, DWORD excode) size = sizeof(bufa); res = HttpQueryInfoA(req, HTTP_QUERY_STATUS_CODE, bufa, &size, NULL); ok_(__FILE__,line)(res, "[3] HttpQueryInfoA(HTTP_QUERY_STATUS_CODE) failed: %u\n", GetLastError()); - ok_(__FILE__,line)(!strcmp(bufa, exbuf), "unexpected status code %s, expected %s\n", bufa, exbuf); + if (is_todo) + todo_wine ok_(__FILE__,line)(!strcmp(bufa, exbuf), "unexpected status code %s, expected %s\n", bufa, exbuf); + else + ok_(__FILE__,line)(!strcmp(bufa, exbuf), "unexpected status code %s, expected %s\n", bufa, exbuf); ok_(__FILE__,line)(size == strlen(exbuf), "unexpected size %d for \"%s\"\n", size, exbuf); size = 0; @@ -229,7 +238,10 @@ static void _test_status_code(unsigned line, HINTERNET req, DWORD excode) size = sizeof(bufw); res = HttpQueryInfoW(req, HTTP_QUERY_STATUS_CODE, bufw, &size, NULL); ok_(__FILE__,line)(res, "[5] HttpQueryInfoW(HTTP_QUERY_STATUS_CODE) failed: %u\n", GetLastError()); - ok_(__FILE__,line)(!strcmp_wa(bufw, exbuf), "unexpected status code %s, expected %s\n", bufa, exbuf); + if (is_todo) + todo_wine ok_(__FILE__,line)(!strcmp_wa(bufw, exbuf), "unexpected status code %s, expected %s\n", bufa, exbuf); + else + ok_(__FILE__,line)(!strcmp_wa(bufw, exbuf), "unexpected status code %s, expected %s\n", bufa, exbuf); ok_(__FILE__,line)(size == strlen(exbuf)*sizeof(WCHAR), "unexpected size %d for \"%s\"\n", size, exbuf); size = 0; @@ -1810,6 +1822,18 @@ static const char page1[] = "The quick brown fox jumped over the lazy dog

\r\n" "\r\n\r\n"; +static const char ok_with_length[] = +"HTTP/1.1 200 OK\r\n" +"Connection: Keep-Alive\r\n" +"Content-Length: 23\r\n\r\n" +"abc\r\nHTTP/1.1 211 OK\r\n\r\n"; + +static const char ok_with_length2[] = +"HTTP/1.1 210 OK\r\n" +"Connection: Keep-Alive\r\n" +"Content-Length: 24\r\n\r\n" +"abc\r\nHTTP/1.1 211 OK\r\n\r\n"; + struct server_info { HANDLE hEvent; int port; @@ -1820,7 +1844,7 @@ static int test_cache_gzip; static DWORD CALLBACK server_thread(LPVOID param) { struct server_info *si = param; - int r, c, i, on; + int r, c, i, on, count = 0; SOCKET s; struct sockaddr_in sa; char buffer[0x100]; @@ -2006,6 +2030,21 @@ static DWORD CALLBACK server_thread(LPVOID param) { send(c, page1, sizeof page1-1, 0); } + + if (strstr(buffer, "GET /testJ")) + { + if (count == 0) + { + count++; + send(c, ok_with_length, sizeof(ok_with_length)-1, 0); + } + else + { + send(c, ok_with_length2, sizeof(ok_with_length2)-1, 0); + count = 0; + } + } + if (strstr(buffer, "GET /test_no_content")) { static const char nocontentmsg[] = "HTTP/1.1 204 No Content\r\nConnection: close\r\n\r\n"; @@ -2587,6 +2626,129 @@ static void test_http1_1(int port) InternetCloseHandle(ses); } +static void test_connection_closing(int port) +{ + HINTERNET session, connection, req; + DWORD res; + + hCompleteEvent = CreateEvent(NULL, FALSE, FALSE, NULL); + + session = InternetOpenA("", INTERNET_OPEN_TYPE_DIRECT, NULL, NULL, INTERNET_FLAG_ASYNC); + ok(session != NULL,"InternetOpen failed with error %u\n", GetLastError()); + + pInternetSetStatusCallbackA(session, callback); + + SET_EXPECT(INTERNET_STATUS_HANDLE_CREATED); + connection = InternetConnectA(session, "localhost", port, NULL, NULL, INTERNET_SERVICE_HTTP, 0x0, 0xdeadbeef); + ok(connection != NULL,"InternetConnect failed with error %u\n", GetLastError()); + CHECK_NOTIFIED(INTERNET_STATUS_HANDLE_CREATED); + + SET_EXPECT(INTERNET_STATUS_HANDLE_CREATED); + req = HttpOpenRequestA(connection, "GET", "/testJ", NULL, NULL, NULL, INTERNET_FLAG_KEEP_CONNECTION, 0xdeadbeaf); + ok(req != NULL, "HttpOpenRequest failed: %u\n", GetLastError()); + CHECK_NOTIFIED(INTERNET_STATUS_HANDLE_CREATED); + + SET_OPTIONAL(INTERNET_STATUS_COOKIE_SENT); + SET_OPTIONAL(INTERNET_STATUS_DETECTING_PROXY); + SET_EXPECT(INTERNET_STATUS_CONNECTING_TO_SERVER); + SET_EXPECT(INTERNET_STATUS_CONNECTED_TO_SERVER); + SET_EXPECT(INTERNET_STATUS_SENDING_REQUEST); + SET_EXPECT(INTERNET_STATUS_REQUEST_SENT); + SET_EXPECT(INTERNET_STATUS_RECEIVING_RESPONSE); + SET_EXPECT(INTERNET_STATUS_RESPONSE_RECEIVED); + SET_OPTIONAL(INTERNET_STATUS_CLOSING_CONNECTION); + SET_OPTIONAL(INTERNET_STATUS_CONNECTION_CLOSED); + SET_EXPECT(INTERNET_STATUS_REQUEST_COMPLETE); + + res = HttpSendRequestA(req, NULL, 0, NULL, 0); + ok(!res && (GetLastError() == ERROR_IO_PENDING), + "Asynchronous HttpSendRequest NOT returning 0 with error ERROR_IO_PENDING\n"); + WaitForSingleObject(hCompleteEvent, INFINITE); + ok(req_error == ERROR_SUCCESS, "req_error = %u\n", req_error); + + CLEAR_NOTIFIED(INTERNET_STATUS_COOKIE_SENT); + CLEAR_NOTIFIED(INTERNET_STATUS_DETECTING_PROXY); + CHECK_NOTIFIED(INTERNET_STATUS_CONNECTING_TO_SERVER); + CHECK_NOTIFIED(INTERNET_STATUS_CONNECTED_TO_SERVER); + CHECK_NOTIFIED(INTERNET_STATUS_SENDING_REQUEST); + CHECK_NOTIFIED(INTERNET_STATUS_REQUEST_SENT); + CHECK_NOTIFIED(INTERNET_STATUS_RECEIVING_RESPONSE); + CHECK_NOTIFIED(INTERNET_STATUS_RESPONSE_RECEIVED); + CLEAR_NOTIFIED(INTERNET_STATUS_CLOSING_CONNECTION); + CLEAR_NOTIFIED(INTERNET_STATUS_CONNECTION_CLOSED); + CHECK_NOTIFIED(INTERNET_STATUS_REQUEST_COMPLETE); + + test_status_code(req, 200); + + SET_OPTIONAL(INTERNET_STATUS_COOKIE_SENT); + SET_OPTIONAL(INTERNET_STATUS_DETECTING_PROXY); + SET_EXPECT(INTERNET_STATUS_CONNECTING_TO_SERVER); + SET_EXPECT(INTERNET_STATUS_CONNECTED_TO_SERVER); + SET_EXPECT(INTERNET_STATUS_SENDING_REQUEST); + SET_EXPECT(INTERNET_STATUS_REQUEST_SENT); + SET_EXPECT(INTERNET_STATUS_RECEIVING_RESPONSE); + SET_EXPECT(INTERNET_STATUS_RESPONSE_RECEIVED); + SET_EXPECT(INTERNET_STATUS_REQUEST_COMPLETE); + + res = HttpSendRequestA(req, NULL, 0, NULL, 0); + ok(!res && (GetLastError() == ERROR_IO_PENDING), + "Asynchronous HttpSendRequest NOT returning 0 with error ERROR_IO_PENDING\n"); + WaitForSingleObject(hCompleteEvent, INFINITE); + ok(req_error == ERROR_SUCCESS, "req_error = %u\n", req_error); + + CLEAR_NOTIFIED(INTERNET_STATUS_COOKIE_SENT); + CLEAR_NOTIFIED(INTERNET_STATUS_DETECTING_PROXY); + todo_wine CHECK_NOTIFIED(INTERNET_STATUS_CONNECTING_TO_SERVER); + todo_wine CHECK_NOTIFIED(INTERNET_STATUS_CONNECTED_TO_SERVER); + CHECK_NOTIFIED(INTERNET_STATUS_SENDING_REQUEST); + CHECK_NOTIFIED(INTERNET_STATUS_REQUEST_SENT); + CHECK_NOTIFIED(INTERNET_STATUS_RECEIVING_RESPONSE); + CHECK_NOTIFIED(INTERNET_STATUS_RESPONSE_RECEIVED); + CHECK_NOTIFIED(INTERNET_STATUS_REQUEST_COMPLETE); + + test_status_code_todo(req, 210); + + SET_OPTIONAL(INTERNET_STATUS_COOKIE_SENT); + SET_OPTIONAL(INTERNET_STATUS_DETECTING_PROXY); + SET_EXPECT(INTERNET_STATUS_CONNECTING_TO_SERVER); + SET_EXPECT(INTERNET_STATUS_CONNECTED_TO_SERVER); + SET_EXPECT(INTERNET_STATUS_SENDING_REQUEST); + SET_WINE_ALLOW(INTERNET_STATUS_SENDING_REQUEST); + SET_EXPECT(INTERNET_STATUS_REQUEST_SENT); + SET_EXPECT(INTERNET_STATUS_RECEIVING_RESPONSE); + SET_EXPECT(INTERNET_STATUS_RESPONSE_RECEIVED); + SET_OPTIONAL(INTERNET_STATUS_CLOSING_CONNECTION); + SET_OPTIONAL(INTERNET_STATUS_CONNECTION_CLOSED); + SET_EXPECT(INTERNET_STATUS_REQUEST_COMPLETE); + + res = HttpSendRequestA(req, NULL, 0, NULL, 0); + ok(!res && (GetLastError() == ERROR_IO_PENDING), + "Asynchronous HttpSendRequest NOT returning 0 with error ERROR_IO_PENDING\n"); + WaitForSingleObject(hCompleteEvent, INFINITE); + ok(req_error == ERROR_SUCCESS, "req_error = %u\n", req_error); + + CLEAR_NOTIFIED(INTERNET_STATUS_COOKIE_SENT); + CLEAR_NOTIFIED(INTERNET_STATUS_DETECTING_PROXY); + CHECK_NOTIFIED(INTERNET_STATUS_CONNECTING_TO_SERVER); + CHECK_NOTIFIED(INTERNET_STATUS_CONNECTED_TO_SERVER); + todo_wine CHECK_NOTIFIED(INTERNET_STATUS_SENDING_REQUEST); + CHECK_NOTIFIED(INTERNET_STATUS_REQUEST_SENT); + CHECK_NOTIFIED(INTERNET_STATUS_RECEIVING_RESPONSE); + CHECK_NOTIFIED(INTERNET_STATUS_RESPONSE_RECEIVED); + CLEAR_NOTIFIED(INTERNET_STATUS_CLOSING_CONNECTION); + CLEAR_NOTIFIED(INTERNET_STATUS_CONNECTION_CLOSED); + CHECK_NOTIFIED(INTERNET_STATUS_REQUEST_COMPLETE); + + test_status_code_todo(req, 200); + + SET_WINE_ALLOW(INTERNET_STATUS_CLOSING_CONNECTION); + SET_WINE_ALLOW(INTERNET_STATUS_CONNECTION_CLOSED); + + close_async_handle(session, hCompleteEvent, 2); + CloseHandle(hCompleteEvent); +} + + static void test_no_content(int port) { HINTERNET session, connection, req; @@ -3436,6 +3598,7 @@ static void test_http_connection(void) test_no_cache(si.port); test_cache_read_gzipped(si.port); test_premature_disconnect(si.port); + test_connection_closing(si.port); /* send the basic request again to shutdown the server thread */ test_basic_request(si.port, "GET", "/quit");