summaryrefslogtreecommitdiffstats
path: root/qa/mockup/mockup-config.cxx
diff options
context:
space:
mode:
Diffstat (limited to 'qa/mockup/mockup-config.cxx')
-rw-r--r--qa/mockup/mockup-config.cxx409
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 );
+}