1 /*===========================================================================
2 *
3 *                            PUBLIC DOMAIN NOTICE
4 *               National Center for Biotechnology Information
5 *
6 *  This software/database is a "United States Government Work" under the
7 *  terms of the United States Copyright Act.  It was written as part of
8 *  the author's official duties as a United States Government employee and
9 *  thus cannot be copyrighted.  This software/database is freely available
10 *  to the public for use. The National Library of Medicine and the U.S.
11 *  Government have not placed any restriction on its use or reproduction.
12 *
13 *  Although all reasonable efforts have been taken to ensure the accuracy
14 *  and reliability of the software and data, the NLM and the U.S.
15 *  Government do not and cannot warrant the performance or results that
16 *  may be obtained by using this software or data. The NLM and the U.S.
17 *  Government disclaim all warranties, express or implied, including
18 *  warranties of performance, merchantability or fitness for any particular
19 *  purpose.
20 *
21 *  Please cite the author in any work or product based on this material.
22 *
23 * ===========================================================================
24 *
25 * Unit tests for HttpRequest
26 */
27 
28 #include "HttpFixture.hpp"
29 
30 #include <kfg/properties.h> // KConfig_Set_Report_Cloud_Instance_Identity
31 
32 #include <klib/data-buffer.h>
33 
34 #include <kns/http.h>
35 #include <kns/http-priv.h>
36 #include <kns/manager.h>
37 #include <kns/kns-mgr-priv.h>
38 
39 #include "../libs/klib/base64-priv.h" // BASE64_PAD_ENCODING
40 #include "../libs/kns/http-priv.h"
41 #include "../libs/vfs/resolver-cgi.h" /* SDL_CGI */
42 
43 #include <kapp/args.h> // Args
44 
45 #include <ktst/unit_test.hpp>
46 
47 #define ALL
48 
49 static rc_t argsHandler ( int argc, char * argv [] );
50 TEST_SUITE_WITH_ARGS_HANDLER ( HttpRequestVerifyURLSuite, argsHandler );
51 
52 using namespace std;
53 using namespace ncbi::NK;
54 
55 #define RELEASE(type, obj) do { rc_t rc2 = type##Release(obj); if (rc2 != 0 && rc == 0) { rc = rc2; } obj = NULL; } while (false)
56 
57 class HttpRequestFixture : public HttpFixture
58 {
59 public:
MakeRequest(const char * p_urlBase)60     void MakeRequest(const char * p_urlBase)
61     {
62         m_url = MakeURL( p_urlBase );
63         if ( KNSManagerMakeClientRequest ( m_mgr, &m_req, 0x01010000, & m_stream, m_url.c_str() ) != 0 )
64         {
65             throw logic_error( "HttpRequestFixture::MakeRequest(): KNSManagerMakeClientRequest() failed" );
66         }
67     }
68 
FormatRequest()69     string FormatRequest()
70     {
71         KDataBuffer buffer;
72         THROW_ON_RC( KDataBufferMake( & buffer, 8, 0 ) );
73         if ( KClientHttpRequestFormatPostMsg(m_req, & buffer) != 0 )
74         {
75             throw logic_error( "HttpRequestFixture::FormatRequest(): KClientHttpRequestFormatPostMsg() failed" );
76         }
77         string ret = string ( (char*)buffer.base, buffer.elem_count );
78         THROW_ON_RC( KDataBufferWhack( &buffer ) );
79         return ret;
80     }
81 
82     string m_url;
83 };
84 
85 #ifdef ALL
FIXTURE_TEST_CASE(HttpRequest_POST_NoParams,HttpRequestFixture)86 FIXTURE_TEST_CASE(HttpRequest_POST_NoParams, HttpRequestFixture)
87 {   // Bug: KClientHttpRequestPOST crashed if request had no parameters
88     MakeRequest( GetName() );
89 
90     KClientHttpResult *rslt;
91     TestStream::AddResponse("HTTP/1.1 200 OK\r\n");
92     REQUIRE_RC ( KClientHttpRequestPOST ( m_req, & rslt ) );
93     REQUIRE_RC ( KClientHttpResultRelease ( rslt ) );
94 }
95 #endif
96 
FIXTURE_TEST_CASE(HttpRequest_head_as_get,HttpRequestFixture)97 FIXTURE_TEST_CASE(HttpRequest_head_as_get, HttpRequestFixture)
98 {
99     MakeRequest( GetName() );
100     m_req->payRequired = true; // triggers GET for HEAD
101 
102     TestStream::AddResponse(
103         "HTTP/1.1 206 Partial Content\r\n"
104         "Content-Range: bytes 0-6/7\r\n"
105         "Content-Length: 7\r\n"
106         "\r\n"
107         "1234567"
108         "\r\n");
109     KClientHttpResult *rslt;
110     REQUIRE_RC ( KClientHttpRequestHEAD ( m_req, & rslt ) );
111     REQUIRE_RC ( KClientHttpResultRelease ( rslt ) );
112 
113     string req = TestStream::m_requests.front();
114     // the request is a GET
115     REQUIRE_NE( string::npos, req.find("GET ") );
116     // -head is temporarily appended to the (thread-local) UserAgent string
117     REQUIRE_NE( string::npos, req.find("-head") );
118     // and then removed
119     const char * agent;
120     REQUIRE_RC( KNSManagerGetUserAgent( & agent ) );
121     REQUIRE_EQ( string::npos, string(agent).find("-head") );
122 }
123 
FIXTURE_TEST_CASE(HttpRequest_head_as_post,HttpRequestFixture)124 FIXTURE_TEST_CASE(HttpRequest_head_as_post, HttpRequestFixture)
125 {
126     MakeRequest( GetName() );
127     m_req->ceRequired = true; // triggers POST for HEAD
128 
129     TestStream::AddResponse(
130         "HTTP/1.1 206 Partial Content\r\n"
131         "Content-Range: bytes 0-6/7\r\n"
132         "Content-Length: 7\r\n"
133         "\r\n"
134         "1234567"
135         "\r\n");
136     KClientHttpResult *rslt;
137     REQUIRE_RC ( KClientHttpRequestHEAD ( m_req, & rslt ) );
138     REQUIRE_RC ( KClientHttpResultRelease ( rslt ) );
139 
140     string req = TestStream::m_requests.front();
141     // the request is a POST
142     REQUIRE_NE( string::npos, req.find("POST ") );
143     // -head is temporarily appended to the (thread-local) UserAgent string
144     REQUIRE_NE( string::npos, req.find("-head") );
145     // and then removed
146     const char * agent;
147     REQUIRE_RC( KNSManagerGetUserAgent( & agent ) );
148     REQUIRE_EQ( string::npos, string(agent).find("-head") );
149 }
150 
FIXTURE_TEST_CASE(HttpRequest_HEAD_as_POST_preserveUAsuffix,HttpRequestFixture)151 FIXTURE_TEST_CASE(HttpRequest_HEAD_as_POST_preserveUAsuffix, HttpRequestFixture)
152 {
153     KNSManagerSetUserAgentSuffix("suffix"); // has to survive KClientHttpRequestHEAD
154 
155     MakeRequest( GetName() );
156     m_req->ceRequired = true; // triggers POST for HEAD
157 
158     TestStream::AddResponse(
159         "HTTP/1.1 206 Partial Content\r\n"
160         "Content-Range: bytes 0-6/7\r\n"
161         "Content-Length: 7\r\n"
162         "\r\n"
163         "1234567"
164         "\r\n");
165     KClientHttpResult *rslt;
166     REQUIRE_RC ( KClientHttpRequestHEAD ( m_req, & rslt ) );
167     REQUIRE_RC ( KClientHttpResultRelease ( rslt ) );
168 
169     const char * agent;
170     REQUIRE_RC( KNSManagerGetUserAgent( & agent ) );
171     // the original suffix is still there
172     REQUIRE_NE( string::npos, string(agent).find("suffix") );
173 
174     string req = TestStream::m_requests.front();
175     // the request is a POST
176     REQUIRE_NE(string::npos, req.find("POST "));
177     // -head is appended to the UserAgent string with original suffix
178     REQUIRE_NE(string::npos, req.find("suffix-head"));
179 }
180 
181 // KClientHttpRequestAddQueryParam
182 
183 class HttpRequestVerifyURL : public SharedTest
184 {
185 public:
HttpRequestVerifyURL(TestCase * dad,KClientHttpRequest * req,string expectedUrl)186     HttpRequestVerifyURL( TestCase * dad, KClientHttpRequest * req, string expectedUrl )
187     : SharedTest ( dad, "" )
188     {
189         KDataBuffer rslt;
190         REQUIRE_RC ( KDataBufferMakeBytes( & rslt, 0 ) );
191         REQUIRE_RC ( KClientHttpRequestURL ( req, & rslt ) );
192         string s2 = string ( (const char*)rslt.base, (size_t)rslt.elem_count - 1); // 0 terminator is included in elem_count
193         REQUIRE_EQ ( expectedUrl, s2 );
194         KDataBufferWhack( & rslt );
195     }
196 };
197 
198 #ifdef ALL
FIXTURE_TEST_CASE(HttpRequestAddQueryParam_SelfNull,HttpRequestFixture)199 FIXTURE_TEST_CASE(HttpRequestAddQueryParam_SelfNull, HttpRequestFixture)
200 {
201     MakeRequest( GetName() );
202     REQUIRE_RC_FAIL ( KClientHttpRequestAddQueryParam ( NULL, "name", "fmt" ) );
203 }
FIXTURE_TEST_CASE(HttpRequestAddQueryParam_FmtNull,HttpRequestFixture)204 FIXTURE_TEST_CASE(HttpRequestAddQueryParam_FmtNull, HttpRequestFixture)
205 {
206     MakeRequest( GetName() );
207     REQUIRE_RC_FAIL ( KClientHttpRequestAddQueryParam ( m_req, "name", NULL ) );
208 }
FIXTURE_TEST_CASE(HttpRequestAddQueryParam_FmtEmpty,HttpRequestFixture)209 FIXTURE_TEST_CASE(HttpRequestAddQueryParam_FmtEmpty, HttpRequestFixture)
210 {
211     MakeRequest( GetName() );
212     REQUIRE_RC_FAIL ( KClientHttpRequestAddQueryParam ( m_req, "name", "" ) );
213 }
FIXTURE_TEST_CASE(HttpRequestAddQueryParam_First,HttpRequestFixture)214 FIXTURE_TEST_CASE(HttpRequestAddQueryParam_First, HttpRequestFixture)
215 {
216     MakeRequest( GetName() );
217     REQUIRE_RC ( KClientHttpRequestAddQueryParam ( m_req, "name", "value" ) );
218 
219     HttpRequestVerifyURL ( this, m_req, m_url + "?name=value" );
220 }
FIXTURE_TEST_CASE(HttpRequestAddQueryParam_Second,HttpRequestFixture)221 FIXTURE_TEST_CASE(HttpRequestAddQueryParam_Second, HttpRequestFixture)
222 {
223     MakeRequest( GetName() );
224     REQUIRE_RC ( KClientHttpRequestAddQueryParam ( m_req, "name1", "value1" ) );
225     REQUIRE_RC ( KClientHttpRequestAddQueryParam ( m_req, "name2", "value2" ) );
226 
227     HttpRequestVerifyURL ( this, m_req, m_url + "?name1=value1&name2=value2" );
228 }
FIXTURE_TEST_CASE(HttpRequestAddQueryParam_NameNull,HttpRequestFixture)229 FIXTURE_TEST_CASE(HttpRequestAddQueryParam_NameNull, HttpRequestFixture)
230 {
231     MakeRequest( GetName() );
232     REQUIRE_RC ( KClientHttpRequestAddQueryParam ( m_req, NULL, "value" ) );
233 
234     HttpRequestVerifyURL ( this, m_req, m_url + "?value" );
235 }
FIXTURE_TEST_CASE(HttpRequestAddQueryParam_NameEmpty,HttpRequestFixture)236 FIXTURE_TEST_CASE(HttpRequestAddQueryParam_NameEmpty, HttpRequestFixture)
237 {
238     MakeRequest( GetName() );
239     REQUIRE_RC ( KClientHttpRequestAddQueryParam ( m_req, "", "value" ) );
240 
241     HttpRequestVerifyURL ( this, m_req, m_url + "?value" );
242 }
FIXTURE_TEST_CASE(HttpRequestAddQueryParam_URL_encoding,HttpRequestFixture)243 FIXTURE_TEST_CASE(HttpRequestAddQueryParam_URL_encoding, HttpRequestFixture)
244 {
245     MakeRequest( GetName() );
246     REQUIRE_RC ( KClientHttpRequestAddQueryParam ( m_req, "", "value & \x1f" "a" "\x7f space \x81" ) );
247 
248     HttpRequestVerifyURL ( this, m_req, m_url + "?value%20%26%20%1fa%7f%20space%20%81" );
249 }
250 
FIXTURE_TEST_CASE(HttpRequestAddHeader,HttpRequestFixture)251 FIXTURE_TEST_CASE(HttpRequestAddHeader, HttpRequestFixture)
252 {
253     MakeRequest( GetName() );
254     REQUIRE_RC( KClientHttpRequestAddHeader(m_req, "Accept", "text/html") );
255     KDataBuffer buffer;
256     THROW_ON_RC( KDataBufferMake( & buffer, 8, 0 ) );
257     REQUIRE_RC( KClientHttpRequestFormatMsg(m_req, & buffer, "HEAD") );
258     REQUIRE( strstr((char*)buffer.base, "Accept: */*") == NULL) ;
259     REQUIRE_RC ( KDataBufferWhack( &buffer ) );
260 }
261 
262 // KClientHttpRequestAddPostParam
FIXTURE_TEST_CASE(RequestAddPostParam,HttpRequestFixture)263 FIXTURE_TEST_CASE(RequestAddPostParam, HttpRequestFixture)
264 {
265     MakeRequest( GetName() );
266     REQUIRE_RC ( KClientHttpRequestAddPostParam ( m_req, "acc=%s", "SRR2043623" ) );
267     REQUIRE_EQ ( string ("acc=SRR2043623"),  string ( KClientHttpRequestGetBody( m_req ) ) );
268 }
269 
270 // KClientHttpRequestAddPostFileParam
271 
FIXTURE_TEST_CASE(HttpRequestAddPostFileParam_SelfNull,HttpRequestFixture)272 FIXTURE_TEST_CASE(HttpRequestAddPostFileParam_SelfNull, HttpRequestFixture)
273 {
274     REQUIRE_RC_FAIL ( KClientHttpRequestAddPostFileParam ( nullptr, "name", "data/fileToPost" ) );
275 }
FIXTURE_TEST_CASE(HttpRequestAddPostFileParam_NameParamNull,HttpRequestFixture)276 FIXTURE_TEST_CASE(HttpRequestAddPostFileParam_NameParamNull, HttpRequestFixture)
277 {
278     MakeRequest( GetName() );
279     REQUIRE_RC_FAIL ( KClientHttpRequestAddPostFileParam ( m_req, nullptr, "data/fileToPost" ) );
280 }
FIXTURE_TEST_CASE(HttpRequestAddPostFileParam_PathParamNull,HttpRequestFixture)281 FIXTURE_TEST_CASE(HttpRequestAddPostFileParam_PathParamNull, HttpRequestFixture)
282 {
283     MakeRequest( GetName() );
284     REQUIRE_RC_FAIL ( KClientHttpRequestAddPostFileParam ( m_req, "name", nullptr ) );
285 }
FIXTURE_TEST_CASE(HttpRequestAddPostFileParam_PathParamEmpty,HttpRequestFixture)286 FIXTURE_TEST_CASE(HttpRequestAddPostFileParam_PathParamEmpty, HttpRequestFixture)
287 {
288     MakeRequest( GetName() );
289     REQUIRE_RC_FAIL ( KClientHttpRequestAddPostFileParam ( m_req, "name", "" ) );
290 }
291 
FIXTURE_TEST_CASE(HttpRequestAddPostFileParam_FileMissing,HttpRequestFixture)292 FIXTURE_TEST_CASE(HttpRequestAddPostFileParam_FileMissing, HttpRequestFixture)
293 {
294     MakeRequest( GetName() );
295     REQUIRE_RC_FAIL ( KClientHttpRequestAddPostFileParam ( m_req, "name", "not-there.txt" ) );
296 }
297 
FIXTURE_TEST_CASE(HttpRequestAddPostFileParam_EmptyFile,HttpRequestFixture)298 FIXTURE_TEST_CASE(HttpRequestAddPostFileParam_EmptyFile, HttpRequestFixture)
299 {
300     MakeRequest( GetName() );
301     REQUIRE_RC_FAIL ( KClientHttpRequestAddPostFileParam ( m_req, "name", "data/empty-file-to-post.txt" ) );
302 }
303 
FIXTURE_TEST_CASE(HttpRequestAddPostFileParam_NonEmptyFile,HttpRequestFixture)304 FIXTURE_TEST_CASE(HttpRequestAddPostFileParam_NonEmptyFile, HttpRequestFixture)
305 {
306     MakeRequest( GetName() );
307     REQUIRE_RC ( KClientHttpRequestAddPostFileParam ( m_req, "name", "data/file-to-post.txt" ) );
308 
309 #if BASE64_PAD_ENCODING
310 	string expected ("name=Y29udGVudHMgb2YgdGhlIGZpbGUKCg==");
311 #else
312 	string expected ("name=Y29udGVudHMgb2YgdGhlIGZpbGUKCg");
313 #endif
314 	REQUIRE_EQ (
315                  expected,
316                  string ( KClientHttpRequestGetBody( m_req ) ) );
317 }
318 
FIXTURE_TEST_CASE(HttpRequestAddPostFileParam_SendReceive,HttpRequestFixture)319 FIXTURE_TEST_CASE(HttpRequestAddPostFileParam_SendReceive, HttpRequestFixture)
320 {
321     const char * Server = SDL_CGI;
322 
323     REQUIRE_RC ( KNSManagerMakeClientRequest ( m_mgr, &m_req, 0x01010000, NULL, Server ) );
324 
325     REQUIRE_RC ( KClientHttpRequestAddQueryParam ( m_req, "acc", "SRR2043623" ) );
326     REQUIRE_RC ( KClientHttpRequestAddQueryParam ( m_req, "filetype", "run" ) );
327     REQUIRE_RC ( KClientHttpRequestAddPostFileParam ( m_req, "ngc", "data/prj_phs710EA_test.ngc" ) );
328 
329 //cout << "req=\"" << FormatRequest() << "\"" << endl;
330 
331     KClientHttpResult *rslt;
332     REQUIRE_RC ( KClientHttpRequestPOST ( m_req, & rslt ) );
333     uint32_t code;
334     char buf[1024];
335     size_t msg_size;
336     REQUIRE_RC ( KClientHttpResultStatus ( rslt, & code, buf, sizeof buf, & msg_size ) );
337     REQUIRE_EQ ( 200u, code );
338     REQUIRE_RC ( KClientHttpResultRelease ( rslt ) );
339 }
340 
FIXTURE_TEST_CASE(HttpRequestAddPostFileParam_MixedPOSTparams,HttpRequestFixture)341 FIXTURE_TEST_CASE(HttpRequestAddPostFileParam_MixedPOSTparams, HttpRequestFixture)
342 {
343     MakeRequest( GetName() );
344 
345     REQUIRE_RC ( KClientHttpRequestAddPostParam ( m_req, "acc=%s", "SRR2043623" ) );
346     REQUIRE_RC ( KClientHttpRequestAddPostFileParam ( m_req, "name", "data/file-to-post.txt" ) );
347     // the file goes into the body
348 
349 #if BASE64_PAD_ENCODING
350 	string expected ("acc=SRR2043623&name=Y29udGVudHMgb2YgdGhlIGZpbGUKCg==");
351 #else
352 	string expected ("acc=SRR2043623&name=Y29udGVudHMgb2YgdGhlIGZpbGUKCg");
353 #endif
354 	REQUIRE_EQ (
355                  expected,
356                  string ( KClientHttpRequestGetBody( m_req ) ) );
357 }
358 
FIXTURE_TEST_CASE(HttpRequestAddPostFileParam_POSTmultipleFiles,HttpRequestFixture)359 FIXTURE_TEST_CASE(HttpRequestAddPostFileParam_POSTmultipleFiles, HttpRequestFixture)
360 {
361     MakeRequest( GetName() );
362 
363     REQUIRE_RC ( KClientHttpRequestAddPostFileParam ( m_req, "name1", "data/file-to-post.txt" ) );
364     REQUIRE_RC ( KClientHttpRequestAddPostFileParam ( m_req, "name2", "data/prj_phs710EA_test.ngc" ) );
365     //TODO: verify body
366 }
367 
368 //////////////////////////
369 // Reliable HTTP request
FIXTURE_TEST_CASE(HttpReliableRequest_Make,HttpFixture)370 FIXTURE_TEST_CASE(HttpReliableRequest_Make, HttpFixture)
371 {
372     KNSManagerMakeReliableClientRequest ( m_mgr, &m_req, 0x01010000, & m_stream, MakeURL(GetName()).c_str()  );
373     REQUIRE_NOT_NULL ( m_req ) ;
374 }
375 
FIXTURE_TEST_CASE(HttpReliableRequest_POST_5xx_retry,HttpFixture)376 FIXTURE_TEST_CASE(HttpReliableRequest_POST_5xx_retry, HttpFixture)
377 {   // use default configuration for 5xx to be retried
378     KNSManagerMakeReliableClientRequest ( m_mgr, &m_req, 0x01010000, & m_stream, MakeURL(GetName()).c_str()  );
379 
380     TestStream::AddResponse("HTTP/1.1 500 Internal Server Error\r\nContent-Length: 0\r\n"); // response to GET
381     TestStream::AddResponse("HTTP/1.1 200 OK\r\n");
382 
383     KClientHttpResult *rslt;
384     REQUIRE_RC ( KClientHttpRequestPOST ( m_req, & rslt ) );
385 
386     REQUIRE_RC ( KClientHttpResultRelease ( rslt ) );
387 }
388 
389 /* VDB-3059: KHttpRequestPOST generates incorrect Content-Length after retry :
390  it makes web server to return 400 Bad Request */
FIXTURE_TEST_CASE(HttpReliableRequest_ContentLength,HttpFixture)391 FIXTURE_TEST_CASE(HttpReliableRequest_ContentLength, HttpFixture)
392 {
393     /* calling good cgi returns 200 and resolved path */
394     REQUIRE_RC ( KNSManagerMakeReliableClientRequest ( m_mgr, &m_req, 0x01010000, NULL,
395         "https://trace.ncbi.nlm.nih.gov/Traces/names/names.fcgi" ) );
396     REQUIRE_RC ( KHttpRequestAddPostParam ( m_req, "acc=AAAB01" ) );
397     REQUIRE_RC ( KHttpRequestAddPostParam ( m_req, "accept-proto=https" ) );
398     REQUIRE_RC ( KHttpRequestAddPostParam ( m_req, "version=1.2" ) );
399 
400     KHttpResult * rslt;
401     REQUIRE_RC ( KHttpRequestPOST ( m_req, & rslt ) );
402     uint32_t code = 0;
403     REQUIRE_RC ( KClientHttpResultStatus ( rslt, & code, NULL, 0, NULL ) );
404     REQUIRE_EQ ( code, 200u );
405 
406     KStream * response;
407     REQUIRE_RC ( KHttpResultGetInputStream ( rslt, & response ) );
408     char buffer [ 512 ] = "";
409     size_t num_read = 0;
410     REQUIRE_RC (KStreamRead( response, buffer, sizeof buffer - 1,  &num_read ));
411     REQUIRE_LT ( num_read, sizeof buffer );
412     buffer [ num_read ] = '\0';
413     REQUIRE_EQ ( string ( buffer + num_read - 7 ), string ( "200|ok\n" ) );
414     REQUIRE_RC ( KStreamRelease ( response ) );
415 
416     REQUIRE_RC ( KHttpResultRelease( rslt ) );
417 }
418 
FIXTURE_TEST_CASE(HttpReliableRequest_BadCgi,HttpFixture)419 FIXTURE_TEST_CASE(HttpReliableRequest_BadCgi, HttpFixture)
420 {
421     /* calling non-existing cgi returns 404 */
422     REQUIRE_RC ( KNSManagerMakeReliableClientRequest ( m_mgr, & m_req, 0x01000000,
423         NULL, "https://trace.ncbi.nlm.nih.gov/Traces/names/bad.cgi" ) );
424     REQUIRE_RC ( KHttpRequestAddPostParam ( m_req, "acc=AAAB01" ) );
425 
426     KHttpResult * rslt;
427     REQUIRE_RC ( KHttpRequestPOST ( m_req, & rslt ) );
428     uint32_t code = 0;
429     REQUIRE_RC ( KClientHttpResultStatus ( rslt, & code, NULL, 0, NULL ) );
430     REQUIRE_EQ ( code, 404u );
431     REQUIRE_RC ( KHttpResultRelease( rslt ) );
432 }
433 #endif
434 
TEST_CASE(Test_urlEncodePluses)435 TEST_CASE(Test_urlEncodePluses) {
436     REQUIRE_RC(KClientHttpRequestUrlEncodeBase64(NULL));
437 
438     const String * encoding = NULL;
439     REQUIRE_RC(KClientHttpRequestUrlEncodeBase64(&encoding));
440 
441     encoding = (String*) calloc(1, sizeof *encoding);
442     REQUIRE_RC(KClientHttpRequestUrlEncodeBase64(&encoding));
443     free((void*)encoding);
444 
445     String s, d;
446 
447     CONST_STRING(&s, "");
448     StringCopy(&encoding, &s);
449     REQUIRE_RC(KClientHttpRequestUrlEncodeBase64(&encoding));
450     REQUIRE_EQ(StringCompare(encoding, &s), 0);
451     StringWhack(encoding);
452 
453     CONST_STRING(&s, "a");
454     StringCopy(&encoding, &s);
455     REQUIRE_RC(KClientHttpRequestUrlEncodeBase64(&encoding));
456     REQUIRE_EQ(StringCompare(encoding, &s), 0);
457     StringWhack(encoding);
458 
459     CONST_STRING(&s, "+/");
460     StringCopy(&encoding, &s);
461     REQUIRE_RC(KClientHttpRequestUrlEncodeBase64(&encoding));
462     CONST_STRING(&d, "%2b%2f");
463     REQUIRE_EQ(StringCompare(encoding, &d), 0);
464     StringWhack(encoding);
465 }
466 
467 //////////////////////////////////////////// Main
468 
argsHandler(int argc,char * argv[])469 static rc_t argsHandler ( int argc, char * argv [] ) {
470     Args * args = NULL;
471     rc_t rc = ArgsMakeAndHandle ( & args, argc, argv, 0, NULL, 0 );
472     ArgsWhack ( args );
473     return rc;
474 }
475 
476 extern "C"
477 {
478 
479 #include <kapp/args.h>
480 #include <kfg/config.h>
481 #include <klib/debug.h>
482 
KAppVersion(void)483 ver_t CC KAppVersion ( void )
484 {
485     return 0x1000000;
486 }
UsageSummary(const char * progname)487 rc_t CC UsageSummary (const char * progname)
488 {
489     return 0;
490 }
491 
Usage(const Args * args)492 rc_t CC Usage ( const Args * args )
493 {
494     return 0;
495 }
496 const char UsageDefaultName[] = "test-http";
497 
KMain(int argc,char * argv[])498 rc_t CC KMain ( int argc, char *argv [] )
499 {
500     KConfig * kfg = NULL;
501     rc_t rc = KConfigMake(&kfg, NULL);
502 
503     if (rc == 0) // needed to use ceRequired on cloud
504         rc = KConfig_Set_Report_Cloud_Instance_Identity(kfg, true);
505 
506     if ( 0 ) assert ( ! KDbgSetString ( "KNS" ) );
507     if ( 0 ) assert ( ! KDbgSetString ( "VFS" ) );
508 
509     KConfigDisableUserSettings();
510 
511 	// this makes messages from the test code appear
512 	// (same as running the executable with "-l=message")
513 	// TestEnv::verbosity = LogLevel::e_message;
514 
515     if (rc == 0)
516         rc = HttpRequestVerifyURLSuite(argc, argv);
517 
518     rc_t r2 = KConfigRelease(kfg);
519     if (rc == 0 && r2 != 0)
520         rc = r2;
521 
522     return rc;
523 }
524 
525 }
526