blob: 71b8c95c41b61c9c5049e4c3aae9fa63a8f7f9ac [file] [log] [blame]
// Copyright 2007-2009 Google Inc.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
// ========================================================================
//
// Tests Get over http and https, using direct connection and wpad proxy.
//
// TODO(omaha): missing Post unit tests
#include <windows.h>
#include <winhttp.h>
#include <atlstr.h>
#include "base/basictypes.h"
#include "omaha/common/const_addresses.h"
#include "omaha/common/error.h"
#include "omaha/common/string.h"
#include "omaha/net/network_config.h"
#include "omaha/net/simple_request.h"
#include "omaha/testing/unit_test.h"
namespace omaha {
class SimpleRequestTest : public testing::Test {
protected:
SimpleRequestTest() {}
void SimpleGet(const CString& url, const Config& config);
void SimpleGetHostNotFound(const CString& url, const Config& config);
void SimpleGetFileNotFound(const CString& url, const Config& config);
void SimpleGetRedirect(const CString& url, const Config& config);
void PrepareRequest(const CString& url,
const Config& config,
SimpleRequest* simple_request);
};
void SimpleRequestTest::PrepareRequest(const CString& url,
const Config& config,
SimpleRequest* simple_request) {
ASSERT_TRUE(simple_request);
HINTERNET handle = NetworkConfig::Instance().session().session_handle;
simple_request->set_session_handle(handle);
simple_request->set_url(url);
simple_request->set_network_configuration(config);
}
void SimpleRequestTest::SimpleGet(const CString& url, const Config& config) {
SimpleRequest simple_request;
PrepareRequest(url, config, &simple_request);
EXPECT_HRESULT_SUCCEEDED(simple_request.Send());
EXPECT_EQ(HTTP_STATUS_OK, simple_request.GetHttpStatusCode());
CString response = Utf8BufferToWideChar(simple_request.GetResponse());
// robots.txt response contains "User-agent: *". This is not the "User-Agent"
// http header.
EXPECT_NE(-1, response.Find(_T("User-agent: *")));
CString content_type;
simple_request.QueryHeadersString(WINHTTP_QUERY_CONTENT_TYPE,
NULL, &content_type);
EXPECT_STREQ(_T("text/plain"), content_type);
// Uses custom query for content type and it should match what we just got.
CString content_type_from_custom_query;
simple_request.QueryHeadersString(WINHTTP_QUERY_CUSTOM,
_T("Content-Type"),
&content_type_from_custom_query);
EXPECT_STREQ(content_type, content_type_from_custom_query);
EXPECT_FALSE(simple_request.GetResponseHeaders().IsEmpty());
// Check the user agent went out with the request.
CString user_agent;
simple_request.QueryHeadersString(
WINHTTP_QUERY_FLAG_REQUEST_HEADERS | WINHTTP_QUERY_USER_AGENT,
WINHTTP_HEADER_NAME_BY_INDEX,
&user_agent);
EXPECT_STREQ(simple_request.user_agent(), user_agent);
}
void SimpleRequestTest::SimpleGetHostNotFound(const CString& url,
const Config& config) {
SimpleRequest simple_request;
PrepareRequest(url, config, &simple_request);
HRESULT hr = simple_request.Send();
int status_code = simple_request.GetHttpStatusCode();
if (config.auto_detect) {
// Either a direct connection or a proxy will be used in the case of
// proxy auto detect.
//
// When a proxy is detected, the proxy server can return some html content
// indicating an error has occured. The status codes will be different,
// depending on how each proxy is configured. This may be a flaky unit test.
if (FAILED(hr)) {
EXPECT_EQ(HRESULT_FROM_WIN32(ERROR_WINHTTP_NAME_NOT_RESOLVED), hr);
} else {
if (String_StartsWith(url, kHttpsProtoScheme, true)) {
EXPECT_EQ(HTTP_STATUS_NOT_FOUND, status_code);
} else {
EXPECT_EQ(HTTP_STATUS_SERVICE_UNAVAIL, status_code);
}
}
} else {
EXPECT_EQ(HRESULT_FROM_WIN32(ERROR_WINHTTP_NAME_NOT_RESOLVED), hr);
EXPECT_EQ(0, status_code);
}
}
void SimpleRequestTest::SimpleGetFileNotFound(const CString& url,
const Config& config) {
SimpleRequest simple_request;
PrepareRequest(url, config, &simple_request);
EXPECT_HRESULT_SUCCEEDED(simple_request.Send());
EXPECT_EQ(HTTP_STATUS_NOT_FOUND, simple_request.GetHttpStatusCode());
}
void SimpleRequestTest::SimpleGetRedirect(const CString& url,
const Config& config) {
SimpleRequest simple_request;
PrepareRequest(url, config, &simple_request);
EXPECT_HRESULT_SUCCEEDED(simple_request.Send());
EXPECT_EQ(HTTP_STATUS_OK, simple_request.GetHttpStatusCode());
}
//
// http tests.
//
// http get, direct connection.
TEST_F(SimpleRequestTest, HttpGetDirect) {
SimpleGet(_T("http://www.google.com/robots.txt"), Config());
}
// http get, direct connection, negative test.
TEST_F(SimpleRequestTest, HttpGetDirectHostNotFound) {
SimpleGetHostNotFound(_T("http://no_such_host.google.com/"), Config());
}
// http get, direct connection, negative test.
TEST_F(SimpleRequestTest, HttpGetDirectFileNotFound) {
SimpleGetFileNotFound(_T("http://tools.google.com/no_such_file"), Config());
}
// http get, proxy wpad.
TEST_F(SimpleRequestTest, HttpGetProxy) {
Config config;
config.auto_detect = true;
SimpleGet(_T("http://www.google.com/robots.txt"), config);
}
// http get, proxy wpad, negative test.
TEST_F(SimpleRequestTest, HttpGetProxyHostNotFound) {
Config config;
config.auto_detect = true;
SimpleGetHostNotFound(_T("http://no_such_host.google.com/"), config);
}
// http get, proxy wpad.
TEST_F(SimpleRequestTest, HttpGetProxyFileNotFound) {
Config config;
config.auto_detect = true;
SimpleGetFileNotFound(_T("http://tools.google.com/no_such_file"), config);
}
//
// https tests.
//
// https get, direct.
TEST_F(SimpleRequestTest, HttpsGetDirect) {
SimpleGet(_T("https://www.google.com/robots.txt"), Config());
}
// https get, direct, negative test.
TEST_F(SimpleRequestTest, HttpsGetDirectHostNotFound) {
SimpleGetHostNotFound(_T("https://no_such_host.google.com/"), Config());
}
// https get, direct connection, negative test.
TEST_F(SimpleRequestTest, HttpsGetDirectFileNotFound) {
SimpleGetFileNotFound(_T("https://tools.google.com/no_such_file"), Config());
}
// https get, proxy wpad.
TEST_F(SimpleRequestTest, HttpsGetProxy) {
Config config;
config.auto_detect = true;
SimpleGet(_T("https://www.google.com/robots.txt"), config);
}
// https get, proxy wpad, negative test.
TEST_F(SimpleRequestTest, HttpsGetProxyHostNotFound) {
Config config;
config.auto_detect = true;
SimpleGetHostNotFound(_T("https://no_such_host.google.com/"), config);
}
// https get, proxy wpad, negative test.
TEST_F(SimpleRequestTest, HttpsGetProxyFileNotFound) {
Config config;
config.auto_detect = true;
SimpleGetFileNotFound(_T("https://tools.google.com/no_such_file"), config);
}
// Should not be able to reuse the object once canceled, even if closed.
TEST_F(SimpleRequestTest, Cancel_CannotReuse) {
SimpleRequest simple_request;
PrepareRequest(_T("http:\\foo\\"), Config(), &simple_request);
EXPECT_HRESULT_SUCCEEDED(simple_request.Cancel());
EXPECT_EQ(OMAHA_NET_E_REQUEST_CANCELLED, simple_request.Send());
EXPECT_HRESULT_SUCCEEDED(simple_request.Close());
EXPECT_EQ(OMAHA_NET_E_REQUEST_CANCELLED, simple_request.Send());
}
// Http get request should follow redirects. The url below redirects to
// https://tools.google.com/service/update2/oneclick and then it returns
// 200 OK and some xml body.
// TODO(omaha): Pick a new URL since this service is now obsolete and could
// be removed at some point.
TEST_F(SimpleRequestTest, HttpGet_Redirect) {
SimpleGetRedirect(_T("http://tools.google.com/service/update2/oneclick"),
Config());
}
} // namespace omaha