336 lines
11 KiB
C++
336 lines
11 KiB
C++
/***
|
|
* ==++==
|
|
*
|
|
* Copyright (c) Microsoft Corporation. All rights reserved.
|
|
* 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.
|
|
*
|
|
* ==--==
|
|
* =+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+
|
|
*
|
|
* http_asserts.cpp - Utility class to help verify assertions about http requests and responses.
|
|
*
|
|
* =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
|
|
****/
|
|
#include "stdafx.h"
|
|
#include "cpprest/details/http_helpers.h"
|
|
|
|
using namespace web; using namespace utility;
|
|
using namespace utility::conversions;
|
|
|
|
namespace tests { namespace functional { namespace http { namespace utilities {
|
|
|
|
utility::string_t percent_encode_pound(utility::string_t str)
|
|
{
|
|
size_t index;
|
|
while((index = str.find_first_of(U("#"))) != str.npos)
|
|
{
|
|
str.insert(index, U("%23"));
|
|
str.erase(index + 3, 1);
|
|
}
|
|
return str;
|
|
}
|
|
|
|
// Helper function to verify all given headers are present.
|
|
template <typename T1, typename T2>
|
|
static void verify_headers(const T1 &expected, const T2 &actual)
|
|
{
|
|
for(auto iter = expected.begin(); iter != expected.end(); ++iter)
|
|
{
|
|
VERIFY_ARE_EQUAL(iter->second, actual.find(iter->first)->second);
|
|
}
|
|
}
|
|
|
|
void http_asserts::assert_request_equals(
|
|
::http::http_request request,
|
|
const ::http::method &mtd,
|
|
const utility::string_t & relative_path)
|
|
{
|
|
VERIFY_ARE_EQUAL(mtd, request.method());
|
|
if(relative_path == U(""))
|
|
{
|
|
VERIFY_ARE_EQUAL(U("/"), request.relative_uri().to_string());
|
|
}
|
|
else
|
|
{
|
|
VERIFY_ARE_EQUAL(relative_path, request.relative_uri().to_string());
|
|
}
|
|
}
|
|
|
|
void http_asserts::assert_request_equals(
|
|
::http::http_request request,
|
|
const ::http::method &mtd,
|
|
const utility::string_t & relative_uri,
|
|
const std::map<utility::string_t, utility::string_t> &headers)
|
|
{
|
|
assert_request_equals(request, mtd, relative_uri);
|
|
verify_headers(headers, request.headers());
|
|
}
|
|
|
|
void http_asserts::assert_request_equals(
|
|
::http::http_request request,
|
|
const ::http::method &mtd,
|
|
const utility::string_t & relative_path,
|
|
const utility::string_t & body)
|
|
{
|
|
assert_request_equals(request, mtd, relative_path);
|
|
auto request_data = request.extract_string().get();
|
|
VERIFY_ARE_EQUAL(body, request_data);
|
|
}
|
|
|
|
void http_asserts::assert_response_equals(
|
|
::http::http_response response,
|
|
const ::http::status_code &code)
|
|
{
|
|
VERIFY_ARE_EQUAL(response.status_code(), code);
|
|
}
|
|
|
|
void http_asserts::assert_response_equals(
|
|
::http::http_response response,
|
|
const ::http::status_code &code,
|
|
const utility::string_t &reason)
|
|
{
|
|
VERIFY_ARE_EQUAL(code, response.status_code());
|
|
VERIFY_ARE_EQUAL(reason, response.reason_phrase());
|
|
}
|
|
|
|
void http_asserts::assert_response_equals(
|
|
::http::http_response response,
|
|
const ::http::status_code &code,
|
|
const std::map<utility::string_t, utility::string_t> &headers)
|
|
{
|
|
VERIFY_ARE_EQUAL(code, response.status_code());
|
|
verify_headers(headers, response.headers());
|
|
}
|
|
|
|
void http_asserts::assert_http_headers_equals(
|
|
const ::http::http_headers &actual,
|
|
const ::http::http_headers &expected)
|
|
{
|
|
verify_headers(actual, expected);
|
|
}
|
|
|
|
void http_asserts::assert_test_request_equals(
|
|
const test_request *const p_request,
|
|
const ::http::method &mtd,
|
|
const utility::string_t &path)
|
|
{
|
|
VERIFY_ARE_EQUAL(mtd, p_request->m_method);
|
|
VERIFY_ARE_EQUAL(path, p_request->m_path);
|
|
}
|
|
|
|
void http_asserts::assert_test_request_equals(
|
|
const test_request *const p_request,
|
|
const ::http::method &mtd,
|
|
const utility::string_t &path,
|
|
const utility::string_t &content_type)
|
|
{
|
|
VERIFY_ARE_EQUAL(mtd, p_request->m_method);
|
|
VERIFY_ARE_EQUAL(path, p_request->m_path);
|
|
|
|
// verify that content-type key exists in the header and the value matches the one provided
|
|
auto iter = p_request->m_headers.find(U("Content-Type"));
|
|
if(content_type.empty())
|
|
{
|
|
VERIFY_ARE_EQUAL(iter, p_request->m_headers.end());
|
|
}
|
|
else
|
|
{
|
|
VERIFY_IS_TRUE(iter != p_request->m_headers.end());
|
|
VERIFY_ARE_EQUAL(iter->second.find(content_type), 0);
|
|
}
|
|
}
|
|
|
|
void http_asserts::assert_test_request_contains_headers(
|
|
const test_request *const p_request,
|
|
const ::http::http_headers &headers)
|
|
{
|
|
verify_headers(headers, p_request->m_headers);
|
|
}
|
|
|
|
void http_asserts::assert_test_request_contains_headers(
|
|
const test_request *const p_request,
|
|
const std::map<utility::string_t, utility::string_t> &headers)
|
|
{
|
|
verify_headers(headers, p_request->m_headers);
|
|
}
|
|
|
|
// Helper function to parse HTTP headers from a stringstream.
|
|
static std::map<utility::string_t, utility::string_t> parse_headers(utility::istringstream_t &ss)
|
|
{
|
|
// Keep parsing until CRLF is encountered.
|
|
std::map<utility::string_t, utility::string_t> headers;
|
|
utility::string_t header_line;
|
|
while(getline(ss, header_line).good())
|
|
{
|
|
const size_t colon_index = header_line.find(U(":"));
|
|
const utility::string_t header_name = header_line.substr(0, colon_index);
|
|
utility::string_t header_value = header_line.substr(colon_index + 1);
|
|
web::http::details::trim_whitespace(header_value);
|
|
headers[header_name] = header_value;
|
|
|
|
char c1 = (char)ss.get(), c2 = (char)ss.get();
|
|
if(c1 == '\r' && c2 == '\n')
|
|
{
|
|
break;
|
|
}
|
|
ss.unget();
|
|
ss.unget();
|
|
}
|
|
return headers;
|
|
}
|
|
|
|
void http_asserts::assert_request_string_equals(
|
|
const utility::string_t &request,
|
|
const ::http::method &mtd,
|
|
const utility::string_t &path,
|
|
const utility::string_t &version,
|
|
const std::map<utility::string_t, utility::string_t> &headers,
|
|
const utility::string_t &body)
|
|
{
|
|
utility::istringstream_t ss(request);
|
|
|
|
// Parse request line.
|
|
utility::string_t actual_method, actual_path, actual_version;
|
|
ss >> actual_method >> actual_path >> actual_version;
|
|
|
|
// Parse headers.
|
|
utility::string_t temp;
|
|
getline(ss, temp);
|
|
std::map<utility::string_t, utility::string_t> actual_headers = parse_headers(ss);
|
|
|
|
// Parse in any message body
|
|
utility::string_t actual_body = ss.str().substr((size_t)ss.tellg());
|
|
|
|
VERIFY_ARE_EQUAL(mtd, actual_method);
|
|
VERIFY_ARE_EQUAL(path, actual_path);
|
|
VERIFY_ARE_EQUAL(version, actual_version);
|
|
verify_headers(headers, actual_headers);
|
|
VERIFY_ARE_EQUAL(body, actual_body);
|
|
}
|
|
|
|
void http_asserts::assert_response_string_equals(
|
|
const utility::string_t &response,
|
|
const utility::string_t &version,
|
|
const ::http::status_code &code,
|
|
const utility::string_t &phrase,
|
|
const std::map<utility::string_t, utility::string_t> &headers,
|
|
const utility::string_t &body)
|
|
{
|
|
utility::istringstream_t ss(response);
|
|
|
|
// Parse response line.
|
|
utility::string_t actual_version, actual_phrase;
|
|
::http::status_code actual_code;
|
|
ss >> actual_version >> actual_code >> actual_phrase;
|
|
|
|
// Parse headers.
|
|
utility::string_t temp;
|
|
getline(ss, temp);
|
|
std::map<utility::string_t, utility::string_t> actual_headers = parse_headers(ss);
|
|
|
|
// Prase in any message body.
|
|
utility::string_t actual_body = ss.str().substr((size_t)ss.tellg());
|
|
|
|
VERIFY_ARE_EQUAL(version, actual_version);
|
|
VERIFY_ARE_EQUAL(code, actual_code);
|
|
VERIFY_ARE_EQUAL(phrase, actual_phrase);
|
|
verify_headers(headers, actual_headers);
|
|
VERIFY_ARE_EQUAL(body, actual_body);
|
|
}
|
|
|
|
void http_asserts::assert_test_request_equals(
|
|
const test_request *const p_request,
|
|
const ::http::method &mtd,
|
|
const utility::string_t &path,
|
|
const utility::string_t &content_type,
|
|
const utility::string_t &body)
|
|
{
|
|
assert_test_request_equals(p_request, mtd, path, content_type);
|
|
// Textual response is always sent as UTF-8, hence the converison to string_t
|
|
std::string s((char*)&p_request->m_body[0], p_request->m_body.size());
|
|
utility::string_t extracted_body = to_string_t(s);
|
|
|
|
VERIFY_ARE_EQUAL(body, extracted_body);
|
|
}
|
|
|
|
void http_asserts::assert_test_response_equals(
|
|
const test_response * const p_response,
|
|
const ::http::status_code &code)
|
|
{
|
|
VERIFY_ARE_EQUAL(code, p_response->m_status_code);
|
|
}
|
|
|
|
void http_asserts::assert_test_response_equals(
|
|
const test_response * const p_response,
|
|
const ::http::status_code &code,
|
|
const std::map<utility::string_t, utility::string_t> &headers)
|
|
{
|
|
VERIFY_ARE_EQUAL(code, p_response->m_status_code);
|
|
verify_headers(headers, p_response->m_headers);
|
|
}
|
|
|
|
void http_asserts::assert_test_response_equals(
|
|
const test_response * const p_response,
|
|
const ::http::status_code &code,
|
|
const ::http::http_headers &headers)
|
|
{
|
|
VERIFY_ARE_EQUAL(code, p_response->m_status_code);
|
|
verify_headers(headers, p_response->m_headers);
|
|
}
|
|
|
|
void http_asserts::assert_test_response_equals(
|
|
test_response * p_response,
|
|
const ::http::status_code &code,
|
|
const utility::string_t &content_type)
|
|
{
|
|
VERIFY_ARE_EQUAL(code, p_response->m_status_code);
|
|
utility::string_t found_content;
|
|
p_response->match_header(U("Content-Type"), found_content);
|
|
VERIFY_ARE_EQUAL(content_type, found_content);
|
|
}
|
|
|
|
void http_asserts::assert_test_response_equals(
|
|
test_response * p_response,
|
|
const ::http::status_code &code,
|
|
const utility::string_t &content_type,
|
|
const utility::string_t data)
|
|
{
|
|
VERIFY_ARE_EQUAL(code, p_response->m_status_code);
|
|
utility::string_t found_content;
|
|
p_response->match_header(U("Content-Type"), found_content);
|
|
VERIFY_ARE_EQUAL(found_content.find(content_type), 0);
|
|
|
|
// Beware: what kind of string this is? <-- stringhack until we tighten up wide/narrow string business
|
|
utility::string_t extracted_body;
|
|
if(p_response->m_data.size() == 0)
|
|
{
|
|
extracted_body = U("");
|
|
}
|
|
else
|
|
{
|
|
auto actualRawData = (char*)&p_response->m_data[0];
|
|
if(p_response->m_data.size() > 1 && *(actualRawData+1) == '\0' )
|
|
{
|
|
// We have more than one byte of data, but it's null-terminated at byte 1.
|
|
// Therefore, this is a wide string
|
|
extracted_body.assign((utility::char_t*)actualRawData, p_response->m_data.size()/sizeof(utility::char_t));
|
|
}
|
|
else{
|
|
std::string s(actualRawData, p_response->m_data.size());
|
|
extracted_body = to_string_t(s);
|
|
}
|
|
}
|
|
|
|
VERIFY_ARE_EQUAL(data, extracted_body);
|
|
}
|
|
|
|
}}}}
|