diff options
Diffstat (limited to 'qa/mockup/mockup-config.cxx')
-rw-r--r-- | qa/mockup/mockup-config.cxx | 409 |
1 files changed, 409 insertions, 0 deletions
diff --git a/qa/mockup/mockup-config.cxx b/qa/mockup/mockup-config.cxx new file mode 100644 index 0000000..7678518 --- /dev/null +++ b/qa/mockup/mockup-config.cxx @@ -0,0 +1,409 @@ +/* libcmis + * Version: MPL 1.1 / GPLv2+ / LGPLv2+ + * + * The contents of this file are subject to the Mozilla Public License Version + * 1.1 (the "License"); you may not use this file except in compliance with + * the License or as specified alternatively below. You may obtain a copy of + * the License at http://www.mozilla.org/MPL/ + * + * Software distributed under the License is distributed on an "AS IS" basis, + * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License + * for the specific language governing rights and limitations under the + * License. + * + * Major Contributor(s): + * Copyright (C) 2011 SUSE <cbosdonnat@suse.com> + * + * + * All Rights Reserved. + * + * For minor contributions see the git repository. + * + * Alternatively, the contents of this file may be used under the terms of + * either the GNU General Public License Version 2 or later (the "GPLv2+"), or + * the GNU Lesser General Public License Version 2 or later (the "LGPLv2+"), + * in which case the provisions of the GPLv2+ or the LGPLv2+ are applicable + * instead of those above. + */ + +#include "mockup-config.h" + +#include <memory> +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include <iostream> + +#include <boost/algorithm/string.hpp> + +#include "internals.hxx" + +using namespace std; + +namespace +{ + void lcl_splitUrl( const string& url, string& urlBase, string& params ) + { + size_t pos = url.find( "?" ); + urlBase = url; + if ( pos != string::npos ) + { + urlBase = url.substr( 0, pos ); + params = url.substr( pos + 1 ); + } + } + + const char** lcl_toStringArray( const vector< string >& vect ) + { + const char** array = new const char*[vect.size() + 1]; + for ( size_t i = 0; i < vect.size( ); i++ ) + array[i] = vect[i].c_str(); + array[vect.size()] = NULL; + return array; + } +} + +namespace mockup +{ + Response::Response( string response, unsigned int status, bool isFilePath, string headers ) : + m_response( response ), + m_status( status ), + m_isFilePath( isFilePath ), + m_headers( headers ) + { + } + + Request::Request( string url, string method, string body, vector< string > headers ) : + m_url( url ), + m_method( method ), + m_body( body ), + m_headers( headers ) + { + } + + RequestMatcher::RequestMatcher( string baseUrl, string matchParam, string method, string matchBody ) : + m_baseUrl( baseUrl ), + m_matchParam( matchParam ), + m_method( method ), + m_matchBody( matchBody ) + { + } + + bool RequestMatcher::operator< ( const RequestMatcher& compare ) const + { + int cmpBaseUrl = m_baseUrl.compare( compare.m_baseUrl ) ; + if ( cmpBaseUrl != 0 ) + return cmpBaseUrl < 0; + + int cmpMatchParam = m_matchParam.compare( compare.m_matchParam ); + if ( cmpMatchParam != 0 ) + return cmpMatchParam < 0; + + int cmpMatchMethod = m_method.compare( compare.m_method ); + if ( cmpMatchMethod != 0 ) + return cmpMatchMethod < 0; + + int cmpMatchBody = m_matchBody.compare( compare.m_matchBody ); + return cmpMatchBody < 0; + } + + Configuration::Configuration( ) : + m_responses( ), + m_requests( ), + m_username( ), + m_password( ), + m_badSSLCertificate( ) + { + } + + bool Configuration::hasCredentials( ) + { + return !m_username.empty( ) && !m_password.empty( ); + } + + /** Find a suitable response + * using the request as a search key + */ + CURLcode Configuration::writeResponse( CurlHandle* handle ) + { + CURLcode code = CURLE_OK; + + string headers; + string response; + bool foundResponse = false; + bool isFilePath = true; + const string& url = handle->m_url; + + string urlBase = url; + string params; + lcl_splitUrl( url, urlBase, params ); + string method = handle->m_method; + string body = m_requests.back().m_body; + + for ( map< RequestMatcher, Response >::iterator it = m_responses.begin( ); + it != m_responses.end( ) && response.empty( ); ++it ) + { + RequestMatcher matcher = it->first; + string& paramFind = matcher.m_matchParam; + bool matchBaseUrl = matcher.m_baseUrl.empty() || ( urlBase == matcher.m_baseUrl ); + bool matchParams = paramFind.empty( ) || ( params.find( paramFind ) != string::npos ); + bool matchMethod = it->first.m_method.empty( ) || ( it->first.m_method == method ); + bool matchBody = matcher.m_matchBody.empty( ) || ( body.find( matcher.m_matchBody ) != string::npos ); + + if ( matchBaseUrl && matchParams && matchMethod && matchBody ) + { + foundResponse = true; + response = it->second.m_response; + handle->m_httpError = it->second.m_status; + isFilePath = it->second.m_isFilePath; + headers = it->second.m_headers; + } + } + + // Output headers is any + if ( !headers.empty() ) + { + char* buf = strdup( headers.c_str() ); + handle->m_headersFn( buf, 1, headers.size( ), handle->m_headersData ); + free( buf ); + } + + // If nothing matched, then send a 404 HTTP error instead + if ( !foundResponse || ( foundResponse && isFilePath && response.empty() ) ) + handle->m_httpError = 404; + else + { + if ( isFilePath ) + { + FILE* fd = fopen( response.c_str( ), "r" ); + if ( !fd ) { + cerr << "Missing test file: " << response << endl; + handle->m_httpError = 500; + return CURLE_HTTP_RETURNED_ERROR; + } + + + size_t bufSize = 2048; + char* buf = new char[bufSize]; + + size_t read = 0; + size_t written = 0; + do + { + read = fread( buf, 1, bufSize, fd ); + written = handle->m_writeFn( buf, 1, read, handle->m_writeData ); + } while ( read == bufSize && written == read ); + + fclose( fd ); + delete[] buf; + } + else + { + if ( !response.empty() ) + { + char* buf = strdup( response.c_str() ); + handle->m_writeFn( buf, 1, response.size( ), handle->m_writeData ); + free( buf ); + } + } + } + + // What curl error code to give? + if ( handle->m_httpError == 0 ) + handle->m_httpError = 200; + + if ( handle->m_httpError < 200 || handle->m_httpError >= 300 ) + code = CURLE_HTTP_RETURNED_ERROR; + + return code; + } + + unique_ptr<Configuration> config{ new Configuration( ) }; +} + +void curl_mockup_reset( ) +{ + mockup::config.reset( new mockup::Configuration( ) ); +} + +void curl_mockup_addResponse( const char* urlBase, const char* matchParam, const char* method, + const char* response, unsigned int status, bool isFilePath, + const char* headers, const char* matchBody ) +{ + string matchBodyStr; + if ( matchBody ) + matchBodyStr = matchBody; + mockup::RequestMatcher matcher( urlBase, matchParam, method, matchBodyStr ); + map< mockup::RequestMatcher, mockup::Response >::iterator it = mockup::config->m_responses.find( matcher ); + if ( it != mockup::config->m_responses.end( ) ) + mockup::config->m_responses.erase( it ); + + string headersStr; + if ( headers != NULL ) + headersStr = headers; + mockup::Response responseDesc( response, status, isFilePath, headersStr ); + mockup::config->m_responses.insert( pair< mockup::RequestMatcher, mockup::Response >( matcher, responseDesc ) ); +} + +void curl_mockup_setResponse( const char* filepath ) +{ + mockup::config->m_responses.clear( ); + curl_mockup_addResponse( "", "", "", filepath ); +} + +void curl_mockup_setCredentials( const char* username, const char* password ) +{ + mockup::config->m_username = string( username ); + mockup::config->m_password = string( password ); +} + +const struct HttpRequest* curl_mockup_getRequest( const char* urlBase, + const char* matchParam, + const char* method, + const char* matchBody ) +{ + struct HttpRequest* request = NULL; + + string urlBaseString( urlBase ); + string matchParamString( matchParam ); + + string matchBodyStr; + if ( matchBody ) + matchBodyStr = matchBody; + + for ( vector< mockup::Request >::iterator it = mockup::config->m_requests.begin( ); + it != mockup::config->m_requests.end( ) && request == NULL; ++it ) + { + string url; + string params; + if ( it->m_method == string( method ) ) + { + lcl_splitUrl( it->m_url, url, params ); + + bool matchBaseUrl = urlBaseString.empty() || boost::starts_with( url, urlBaseString ); + bool matchParams = matchParamString.empty( ) || ( params.find( matchParamString ) != string::npos ); + bool matchBodyPart = !matchBody || ( it->m_body.find( matchBodyStr ) != string::npos ); + + if ( matchBaseUrl && matchParams && matchBodyPart ) + { + request = new HttpRequest; + request->url = it->m_url.c_str(); + request->body = it->m_body.c_str(); + request->headers = lcl_toStringArray( it->m_headers ); + } + } + } + + return request; +} + +const char* curl_mockup_getRequestBody( const char* urlBase, + const char* matchParam, + const char* method, + const char* matchBody ) +{ + const struct HttpRequest* request = curl_mockup_getRequest( urlBase, matchParam, method, matchBody ); + if ( request ) + { + const char* body = request->body; + curl_mockup_HttpRequest_free( request ); + return body; + } + return NULL; +} + +int curl_mockup_getRequestsCount( const char* urlBase, + const char* matchParam, + const char* method, + const char* matchBody ) +{ + int count = 0; + + string urlBaseString( urlBase ); + string matchParamString( matchParam ); + string matchBodyStr( matchBody ); + + for ( vector< mockup::Request >::iterator it = mockup::config->m_requests.begin( ); + it != mockup::config->m_requests.end( ); ++it ) + { + string url; + string params; + if ( it->m_method == string( method ) ) + { + lcl_splitUrl( it->m_url, url, params ); + + bool matchBaseUrl = urlBaseString.empty() || boost::starts_with( url, urlBaseString ); + bool matchParams = matchParamString.empty( ) || + ( params.find( matchParamString ) != string::npos ); + bool matchBodyPart = matchBodyStr.empty() || + ( it->m_body.find( matchBodyStr ) != string::npos ); + + if ( matchBaseUrl && matchParams && matchBodyPart ) + { + count++; + } + } + } + return count; +} + +void curl_mockup_HttpRequest_free( const struct HttpRequest* request ) +{ + delete[] request->headers; + delete request; +} + +char* curl_mockup_HttpRequest_getHeader( const struct HttpRequest* request, const char* name ) +{ + char* value = NULL; + size_t i = 0; + while ( request->headers[i] != NULL && value == NULL ) + { + string header = request->headers[i]; + const string prefix = string( name ) + ":"; + size_t pos = header.find( prefix ); + if ( pos == 0 ) + { + value = strdup( header.substr( prefix.size() ).c_str() ); + } + ++i; + } + return value; +} + +const char* curl_mockup_getProxy( CURL* curl ) +{ + CurlHandle* handle = static_cast< CurlHandle* >( curl ); + if ( NULL != handle ) + return handle->m_proxy.c_str(); + return NULL; +} + +const char* curl_mockup_getNoProxy( CURL* curl ) +{ + CurlHandle* handle = static_cast< CurlHandle* >( curl ); + if ( NULL != handle ) + return handle->m_noProxy.c_str(); + return NULL; +} + +const char* curl_mockup_getProxyUser( CURL* curl ) +{ + CurlHandle* handle = static_cast< CurlHandle* >( curl ); + if ( NULL != handle ) + return handle->m_proxyUser.c_str(); + return NULL; +} + +const char* curl_mockup_getProxyPass( CURL* curl ) +{ + CurlHandle* handle = static_cast< CurlHandle* >( curl ); + if ( NULL != handle ) + return handle->m_proxyPass.c_str(); + return NULL; +} + +void curl_mockup_setSSLBadCertificate( const char* certificate ) +{ + mockup::config->m_badSSLCertificate = string( certificate ); +} |