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 HTTP interfaces
26 */
27 
28 #include "HttpFixture.hpp"
29 
30 #include <ktst/unit_test.hpp>
31 #include <kfg/config.h>
32 #include <kns/manager.h>
33 #include <kns/http.h>
34 #include <kfs/directory.h>
35 #include <kfs/file.h>
36 
37 using namespace std;
38 using namespace ncbi::NK;
39 
40 rc_t CC
Whack(KSTREAM_IMPL * self)41 TestStream ::  Whack ( KSTREAM_IMPL *self )
42 {
43     if ( TestEnv::verbosity == LogLevel::e_message )
44         cout << "TestStream::Whack() called" << endl;
45     return 0;
46 }
47 
48 rc_t CC
Read(const KSTREAM_IMPL * self,void * buffer,size_t bsize,size_t * num_read)49 TestStream :: Read ( const KSTREAM_IMPL *self, void *buffer, size_t bsize, size_t *num_read )
50 {
51     if ( TestEnv::verbosity == LogLevel::e_message )
52         cout << "TestStream::Read() called" << endl;
53     * num_read = 0;
54     return 0;
55 }
56 
57 rc_t CC
Write(KSTREAM_IMPL * self,const void * buffer,size_t size,size_t * num_writ)58 TestStream :: Write ( KSTREAM_IMPL *self, const void *buffer, size_t size, size_t *num_writ )
59 {
60     if ( TestEnv::verbosity == LogLevel::e_message )
61         cout << "TestStream::Write() called" << endl;
62     * num_writ = size;
63     m_requests . push_back ( string ( (const char*)buffer, size) );
64     return 0;
65 }
66 
67 rc_t CC
TimedRead(const KSTREAM_IMPL * self,void * buffer,size_t bsize,size_t * num_read,struct timeout_t * tm)68 TestStream :: TimedRead ( const KSTREAM_IMPL *self, void *buffer, size_t bsize, size_t *num_read, struct timeout_t *tm )
69 {
70     if ( TestEnv::verbosity == LogLevel::e_message )
71         cout << "TestStream::TimedRead() called" << endl;
72 
73     string response;
74     if ( m_responses.size()> 0)
75     {
76         response = m_responses.front();
77         m_responses.pop_front();
78     }
79     else
80     {
81         throw logic_error ( "TestStream: TimedRead is out of responses" );
82     }
83 
84     if ( response.size() >= bsize )
85     {
86         memmove(buffer, response.c_str(), bsize);
87         * num_read = bsize;
88         response = response.substr(bsize);
89     }
90     else
91     {
92         memmove(buffer, response.c_str(), response.size());
93         * num_read = response.size();
94         response.clear();
95     }
96     if ( TestEnv::verbosity == LogLevel::e_message )
97         cout << "TestStream::TimedRead returned \"" << string((const char*)buffer, * num_read) << "\"" << endl;
98 
99     return 0;
100 }
101 
102 rc_t CC
TimedWrite(KSTREAM_IMPL * self,const void * buffer,size_t size,size_t * num_writ,struct timeout_t * tm)103 TestStream :: TimedWrite ( KSTREAM_IMPL *self, const void *buffer, size_t size, size_t *num_writ, struct timeout_t *tm )
104 {
105     if ( TestEnv::verbosity == LogLevel::e_message )
106         cout << "TestStream::TimedWrite(\"" << string((const char*)buffer, size) << "\") called" << endl;
107     * num_writ = size;
108     m_requests . push_back ( string ( (const char*)buffer, size) );
109     return 0;
110 }
111 
112 void
AddResponse(const string & p_str,bool end_binary)113 TestStream :: AddResponse ( const string& p_str, bool end_binary )
114 {
115     if (end_binary)
116         m_responses.push_back(p_str);
117     else
118         m_responses.push_back(std::string(p_str.c_str(), p_str.size() + 1));
119 }
120 
121 list<string> TestStream :: m_requests;
122 list<string> TestStream :: m_responses;
123 
124 KStream_vt_v1 TestStream::vt =
125 {
126     1, 1,
127     TestStream::Whack,
128     TestStream::Read,
129     TestStream::Write,
130     TestStream::TimedRead,
131     TestStream::TimedWrite
132 };
133 
HttpFixture()134 HttpFixture :: HttpFixture()
135 :   m_file ( nullptr ),
136     m_req ( nullptr )
137 {
138     if ( KStreamInit ( & m_stream, ( const KStream_vt* ) & TestStream::vt, "TestStream", "", true, true ) != 0 )
139         throw logic_error ( "HttpFixture: KStreamInit failed" );
140 
141     TestStream::m_requests.clear();
142     TestStream::m_responses.clear();
143 }
144 
~HttpFixture()145 HttpFixture :: ~HttpFixture()
146 {
147     if ( KFileRelease ( m_file ) != 0 )
148         cerr << "HttpFixture::~HttpFixture KFileRelease failed" << endl;
149 
150     if ( KClientHttpRequestRelease ( m_req ) != 0 )
151         cerr << "HttpFixture::~HttpFixture KClientHttpRequestRelease failed" << endl;
152 
153     if ( ! TestStream::m_responses.empty() )
154         cerr << "HttpFixture::~HttpFixture not all TestStream::m_responses have been consumed" << endl;
155 }
156 
157 KConfig*
MakeConfig(const char * name,const char * contents)158 HttpFixture :: MakeConfig( const char* name, const char* contents )
159 {
160     KDirectory* wd;
161     if ( KDirectoryNativeDir ( & wd ) != 0 )
162         throw logic_error("KfgFixture: KDirectoryNativeDir failed");
163 
164     {
165         KFile* file;
166         if (KDirectoryCreateFile(wd, &file, true, 0664, kcmInit, name) != 0)
167             throw logic_error("MakeConfig: KDirectoryCreateFile failed");
168 
169         size_t num_writ=0;
170         if (KFileWrite(file, 0, contents, strlen(contents), &num_writ) != 0)
171             throw logic_error("MakeConfig: KFileWrite failed");
172 
173         if (KFileRelease(file) != 0)
174             throw logic_error("MakeConfig: KFileRelease failed");
175     }
176 
177     KConfig* ret;
178     {
179         if (KConfigMake ( & ret, wd ) != 0)
180             throw logic_error("MakeConfig: KConfigMake failed");
181 
182         KFile* file;
183         if (KDirectoryOpenFileRead(wd, (const KFile**)&file, name) != 0)
184             throw logic_error("MakeConfig: KDirectoryOpenFileRead failed");
185 
186         if (KConfigLoadFile ( ret, name, file) != 0)
187             throw logic_error("MakeConfig: KConfigLoadFile failed");
188 
189         if (KFileRelease(file) != 0)
190             throw logic_error("MakeConfig: KFileRelease failed");
191     }
192 
193     if (KDirectoryRemove(wd, true, name) != 0)
194         throw logic_error("MakeConfig: KDirectoryRemove failed");
195     if (KDirectoryRelease(wd) != 0)
196         throw logic_error("MakeConfig: KDirectoryRelease failed");
197 
198     return ret;
199 }
200 
201 struct KStream *
Reconnect()202 HttpFixture :: Reconnect ()
203 {
204     return & m_stream;
205 }
206 
207 string
MakeURL(const string & base)208 HttpFixture :: MakeURL(const string & base)
209 {
210     return string("http://") + base + ".com/blah";
211 }
212 
213 KStream HttpFixture :: m_stream;
214 
215