test_client.cpp
Go to the documentation of this file.
1 /*
2  * Unit tests for XmlRpc++
3  *
4  * Copyright (C) 2017, Zoox Inc
5  *
6  * This library is free software; you can redistribute it and/or
7  * modify it under the terms of the GNU Lesser General Public
8  * License as published by the Free Software Foundation; either
9  * version 2.1 of the License, or (at your option) any later version.
10  *
11  * This library is distributed in the hope that it will be useful,
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14  * Lesser General Public License for more details.
15  *
16  * You should have received a copy of the GNU Lesser General Public
17  * License along with this library; if not, write to the Free Software
18  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
19  *
20  * Author: Austin Hendrix <austin@zoox.com>
21  *
22  */
23 
24 #include "xmlrpcpp/XmlRpcClient.h"
25 #include "xmlrpcpp/XmlRpcValue.h"
26 
27 #include "mock_socket.h"
28 #include <errno.h>
29 
30 #include <gtest/gtest.h>
31 
34 
35 // Helper class to change the accessibility of protected members of the class under test so we can test them
37 {
38 public:
39  XmlRpcClientForTest(const char* host, int port, const char* uri=0) : XmlRpcClient(host, port, uri)
40  {
41  }
42 
43  using XmlRpcClient::doConnect;
44  using XmlRpcClient::setupConnection;
45  using XmlRpcClient::generateRequest;
46  using XmlRpcClient::generateHeader;
47  using XmlRpcClient::writeRequest;
48  using XmlRpcClient::readHeader;
49  using XmlRpcClient::readResponse;
50  using XmlRpcClient::parseResponse;
51 
52  using XmlRpcClient::ClientConnectionState;
53  using XmlRpcClient::NO_CONNECTION;
54  using XmlRpcClient::CONNECTING;
55  using XmlRpcClient::WRITE_REQUEST;
56  using XmlRpcClient::READ_HEADER;
57  using XmlRpcClient::READ_RESPONSE;
58  using XmlRpcClient::IDLE;
59 
60  using XmlRpcClient::_connectionState;
61  using XmlRpcClient::connectionStateStr;
62 };
63 namespace XmlRpc {
65  ::std::ostream* os) {
67 }
68 }; // namespace XmlRpc
69 
70 // Helper function to check if our source is in the dispatch source list or not.
73  XmlRpc::XmlRpcDispatch::SourceList::const_iterator itr;
74  for (itr = list.begin(); itr != list.end(); itr++) {
75  if (itr->getSource() == source) {
76  return true;
77  }
78  }
79  return false;
80 }
81 
82 // Tests for XmlRpcClient
83 //
84 // Test connectionStateStr macro
86 #define TEST_STATE(state) \
87  EXPECT_STREQ(#state, XmlRpcClientForTest::connectionStateStr(XmlRpcClientForTest::state))
94 }
95 
96 // Test state of client once constructor is done, including optional URL arg.
97 TEST_F(MockSocketTest, constructor) {
98  XmlRpcClientForTest a("localhost", 42);
99  EXPECT_EQ("localhost", a.getHost());
100  EXPECT_EQ(42, a.getPort());
101  EXPECT_EQ("/RPC2", a.getUri());
102 
104  EXPECT_EQ(false, a._executing);
105  EXPECT_EQ(false, a._eof);
106  EXPECT_EQ(true, a.getKeepOpen());
107  EXPECT_EQ(-1, a.getfd());
108  EXPECT_EQ(0, a._sendAttempts);
109  EXPECT_EQ(0, a._bytesWritten);
110  EXPECT_EQ(0, a._contentLength);
111  EXPECT_FALSE(a._isFault);
112  EXPECT_FALSE(sourceInList(&a, a._disp._sources));
113 
114  XmlRpcClientForTest b("nowhere.com", 404, "/where");
115  EXPECT_EQ("nowhere.com", b.getHost());
116  EXPECT_EQ(404, b.getPort());
117  EXPECT_EQ("/where", b.getUri());
118  // Don't really need to repeat the tests for the other variables.
119 }
120 
121 // Test close() function:
122 // * Does not call close when socket is already closed.
123 TEST_F(MockSocketTest, close_invalid_fd) {
124  XmlRpcClientForTest a("localhost", 42);
125 
126  ASSERT_EQ(-1, a.getfd());
127 
128  // Close when no file descriptor is set
129  a.close();
130  EXPECT_EQ(-1, a.getfd());
131 }
132 
133 // Test close() function:
134 // * Correctly calls close when socket is not closed.
135 TEST_F(MockSocketTest, close_valid_fd) {
136  XmlRpcClientForTest a("localhost", 42);
137 
138  // Set file descriptor and then expect that close is called once.
139  a.setfd(5);
140  Expect_close(5);
141  a.close();
142  EXPECT_EQ(-1, a.getfd());
143 
144  // Intermediate check that all expected calls have been executed.
145  CheckCalls();
146 
147  // Calling close again should have no effect.
148  a.close();
149  EXPECT_EQ(-1, a.getfd());
150 }
151 
152 TEST_F(MockSocketTest, close_destructor) {
153  // Test that the XmlRpcClient destructor closes the file descriptor.
154  {
155  XmlRpcClientForTest a("localhost", 42);
156 
157  // Set file descriptor and then expect that close is called once.
158  a.setfd(5);
159  Expect_close(5);
160  // XmlRpcClient destructor called at the end of this scope.
161  }
162 }
163 
164 // Test execute() function? TODO(future work)
165 // This is a bit complicated; maybe test the underlying functions and then
166 // mock them out for this test.
167 // Test exectuteNonBlock() function? TODO(future work)
168 // Again, complicated. Maybe test underlying functions.
169 // Test executeCheckDone() ? TODO(future work)
170 // Complicated. There are known bugs here where the client never reports done
171 // if the connection is lost; we should try to test that logic.
172 // Test handleEvent() TODO(future work)
173 // For each ConnectionState
174 // The correct sequence of socket functions is called.
175 // The correct action is taken if the socket operations fail.
176 
177 // Test setupConnection()
178 // Correct handling of initial states.
179 // Correct handling of errors.
181  XmlRpcClientForTest a("localhost", 42);
182 
183  // Default initial state; expect socket, setNonBlocking and connect.
184  // NOTE(austin): This does not currently expect these calls in order; it just
185  // checks that all of them have been made.
186  Expect_socket(7);
187  Expect_setNonBlocking(7, true);
188  Expect_connect(7, "localhost", 42, true);
189 
190  EXPECT_TRUE(a.setupConnection());
191 
192  // Check that correct FD was set.
193  EXPECT_EQ(7, a.getfd());
194 
195  // Check that source is in the dispatch source list now.
196  EXPECT_TRUE(sourceInList(&a, a._disp._sources));
197 
198  // Check internal state is reset.
200  EXPECT_EQ(0, a._bytesWritten);
201  CheckCalls();
202 
203  Expect_close(7);
204 }
205 
206 TEST_F(MockSocketTest, setupConnection_eof) {
207  XmlRpcClientForTest a("localhost", 42);
208 
209  // Initial state: file descriptor set, but _eof. Expect close and socket,
210  // setNonBlocking, connect.
211  a.setfd(5);
212  a._eof = true;
213  Expect_close(5);
214 
215  Expect_socket(7);
216  Expect_setNonBlocking(7, true);
217  Expect_connect(7, "localhost", 42, true);
218 
219  EXPECT_TRUE(a.setupConnection());
220 
221  // Check that correct FD was set.
222  EXPECT_EQ(7, a.getfd());
223 
224  // Check that source is in the dispatch source list now.
225  EXPECT_TRUE(sourceInList(&a, a._disp._sources));
226 
227  // Check internal state is reset.
229  EXPECT_EQ(0, a._bytesWritten);
230  CheckCalls();
231 
232  Expect_close(7);
233 }
234 
235 TEST_F(MockSocketTest, setupConnection_close) {
236  XmlRpcClientForTest a("localhost", 42);
237 
238  // Initial state: file descriptor set, but _eof
239  // NOTE(austin): Having multiple variables that imply that the fd is valid
240  // smells funny.
241  a.setfd(5);
243  Expect_close(5);
244 
245  Expect_socket(7);
246  Expect_setNonBlocking(7, true);
247  Expect_connect(7, "localhost", 42, true);
248 
249  EXPECT_TRUE(a.setupConnection());
250 
251  // Check that correct FD was set.
252  EXPECT_EQ(7, a.getfd());
253 
254  // Check that source is in the dispatch source list now.
255  EXPECT_TRUE(sourceInList(&a, a._disp._sources));
256 
257  // Check internal state is reset.
259  EXPECT_EQ(0, a._bytesWritten);
260  CheckCalls();
261 
262  Expect_close(7);
263 }
264 
265 TEST_F(MockSocketTest, setupConnection_err) {
266  XmlRpcClientForTest a("localhost", 42);
267 
268  // Connect failure. Any failure that causes doConnect here will do; we choose
269  // an arbitrary failure mode here and then separately test that doConnect
270  // reports failure correctly in a separate set of tests.
271  Expect_socket(7);
272  Expect_setNonBlocking(7, true);
273  Expect_connect(7, "localhost", 42, false);
274  Expect_getError(ECONNREFUSED);
275  Expect_close(7);
276 
277  EXPECT_FALSE(a.setupConnection());
278 
279  // Check that FD is not set.
280  EXPECT_EQ(-1, a.getfd());
281 
282  // Check that source is not in the dispatch source list now.
283  EXPECT_FALSE(sourceInList(&a, a._disp._sources));
284 
285  // Check internal state is NO_CONNECTION
287 }
288 
289 // Check that _disp is left in the correct state after closing and then failing
290 // to reopen the socket.
291 TEST_F(MockSocketTest, setupConnection_eor_reopen) {
292  XmlRpcClientForTest a("localhost", 42);
293 
294  // Default initial state; expect socket, setNonBlocking and connect.
295  // NOTE(austin): This does not currently expect these calls in order; it just
296  // checks that all of them have been made.
297  Expect_socket(7);
298  Expect_setNonBlocking(7, true);
299  Expect_connect(7, "localhost", 42, true);
300 
301  EXPECT_TRUE(a.setupConnection());
302 
303  // Check that correct FD was set.
304  EXPECT_EQ(7, a.getfd());
305 
306  // Check that source is in the dispatch source list now.
307  EXPECT_TRUE(sourceInList(&a, a._disp._sources));
308 
309  // Check internal state is reset.
311  EXPECT_EQ(0, a._bytesWritten);
312  CheckCalls();
313 
314  // Simulate socket encountering EOF
315  a._eof = true;
316 
317  // Expect close, socket, setNonBlocking and connect. Make connect fail.
318  Expect_close(7);
319  Expect_socket(8);
320  Expect_setNonBlocking(8, true);
321  Expect_connect(8, "localhost", 42, false);
322  Expect_getError(ECONNREFUSED);
323  Expect_close(8);
324 
325  EXPECT_FALSE(a.setupConnection());
326 
327  // Check that correct FD was set.
328  EXPECT_EQ(-1, a.getfd());
329 
330  // Check that source is no longer in the dispatch source list now.
331  EXPECT_FALSE(sourceInList(&a, a._disp._sources));
332 
333  // Check internal state is reset.
335  CheckCalls();
336 }
337 
338 // Test doConnect()
339 // Correct sequence of calls to XmlRpcSocket
340 // Correct handling of socket errors.
342  XmlRpcClientForTest a("localhost", 42);
343 
344  // Expect that socket, setNonBlocking and connect are called.
345  // NOTE(austin): this doesn't enforce ordering.
346  Expect_socket(7);
347  Expect_setNonBlocking(7, true);
348  Expect_connect(7, "localhost", 42, true);
349 
350  EXPECT_TRUE(a.doConnect());
351 
352  // Check that correct FD was set.
353  EXPECT_EQ(7, a.getfd());
354 
355  // Check that the expected calls have happened.
356  CheckCalls();
357 
358  // Expect close on destruction.
359  Expect_close(7);
360 }
361 
362 TEST_F(MockSocketTest, doConnect_socketerr) {
363  XmlRpcClientForTest a("localhost", 42);
364 
365  Expect_socket(-1);
366  Expect_getError(ENFILE);
367 
368  EXPECT_FALSE(a.doConnect());
369 
370  // Check that correct FD was set.
371  EXPECT_EQ(-1, a.getfd());
372 }
373 
374 TEST_F(MockSocketTest, doConnect_nonBlockErr) {
375  XmlRpcClientForTest a("localhost", 42);
376 
377  // Expect that setNonBlocking causes the socket to be closed and getError to
378  // be called.
379  Expect_socket(7);
380  Expect_setNonBlocking(7, false);
381  Expect_getError(EBADF);
382  Expect_close(7);
383 
384  EXPECT_FALSE(a.doConnect());
385 
386  // Check that correct FD was set.
387  EXPECT_EQ(-1, a.getfd());
388 }
389 
390 TEST_F(MockSocketTest, doConnect_connectErr) {
391  XmlRpcClientForTest a("localhost", 42);
392 
393  // Expect that a connection failure causes the socket to be closed.
394  Expect_socket(7);
395  Expect_setNonBlocking(7, true);
396  Expect_connect(7, "localhost", 42, false);
397  Expect_getError(ECONNREFUSED);
398  Expect_close(7);
399 
400  EXPECT_FALSE(a.doConnect());
401 
402  // Check that correct FD was set.
403  EXPECT_EQ(-1, a.getfd());
404 }
405 
406 // Test generateRequest()
407 // Correct XML is generated for a variety of request types.
408 // Correct XML is generated for empty request
410  XmlRpcClientForTest a("localhost", 42);
411  // generateRequest takes a method name and params and puts the result in the
412  // _request member variable.
413  std::string header = "POST /RPC2 HTTP/1.1\r\n"
414  "User-Agent: XMLRPC++ 0.7\r\n"
415  "Host: localhost:42\r\n"
416  "Content-Type: text/xml\r\n";
417 
418  // Various tests for the nominal case of a normal XmlRpcValue
419  XmlRpcValue s("Hello");
420  EXPECT_TRUE(a.generateRequest("DoFoo", s));
421  EXPECT_EQ(header + "Content-length: 134\r\n\r\n"
422  "<?xml version=\"1.0\"?>\r\n"
423  "<methodCall><methodName>DoFoo</methodName>\r\n"
424  "<params><param><value>Hello</value></param></params></"
425  "methodCall>\r\n",
426  a._request);
427 
428  XmlRpcValue b(true);
429  EXPECT_TRUE(a.generateRequest("DoFoo", b));
430  EXPECT_EQ(header + "Content-length: 149\r\n\r\n"
431  "<?xml version=\"1.0\"?>\r\n"
432  "<methodCall><methodName>DoFoo</methodName>\r\n"
433  "<params><param><value><boolean>1</boolean></value></"
434  "param></params></methodCall>\r\n",
435  a._request);
436 
437  XmlRpcValue i(42);
438  EXPECT_TRUE(a.generateRequest("DoFoo", i));
439  EXPECT_EQ(header + "Content-length: 140\r\n\r\n"
440  "<?xml version=\"1.0\"?>\r\n"
441  "<methodCall><methodName>DoFoo</methodName>\r\n"
442  "<params><param><value><i4>42</i4></value></param></"
443  "params></methodCall>\r\n",
444  a._request);
445 
446  // Array case is a bit special because it results in emitting multiple
447  // <param> tags.
448  XmlRpcValue arr;
449  arr[0] = 2;
450  arr[1] = 3;
451  arr[2] = 5;
452  arr[3] = 7;
453  arr[4] = 11;
454  arr[5] = 13;
455  arr[6] = 17;
456  EXPECT_TRUE(a.generateRequest("DoFoo", arr));
457  EXPECT_EQ(header + "Content-length: 382\r\n\r\n"
458  "<?xml version=\"1.0\"?>\r\n"
459  "<methodCall><methodName>DoFoo</methodName>\r\n"
460  "<params>"
461  "<param><value><i4>2</i4></value></param>"
462  "<param><value><i4>3</i4></value></param>"
463  "<param><value><i4>5</i4></value></param>"
464  "<param><value><i4>7</i4></value></param>"
465  "<param><value><i4>11</i4></value></param>"
466  "<param><value><i4>13</i4></value></param>"
467  "<param><value><i4>17</i4></value></param>"
468  "</params></methodCall>\r\n",
469  a._request);
470 
471  // Tests for errors in arguments.
472  // Method name null
473  // TODO(austin): this causes a segfault.
474  /*
475  EXPECT_TRUE(a.generateRequest(NULL, s));
476  EXPECT_EQ(header + "Content-length: 134\r\n\r\n" \
477  "<?xml version=\"1.0\"?>\r\n" \
478  "<methodCall><methodName></methodName>\r\n" \
479  "<params><param><value>Hello</value></param></params></methodCall>\r\n"
480  , a._request);
481  */
482 
483  // Empty(invalid) param(s)
484  // NOTE(austin): this matches the existing implementation but seems unusual.
485  // I don't have a specification to check this against so I'm just going to
486  // assume it's OK.
487  XmlRpcValue empty;
488  EXPECT_FALSE(empty.valid());
489  EXPECT_TRUE(a.generateRequest("DoEmpty", empty));
490  EXPECT_EQ(header + "Content-length: 84\r\n\r\n"
491  "<?xml version=\"1.0\"?>\r\n"
492  "<methodCall><methodName>DoEmpty</methodName>\r\n"
493  "</methodCall>\r\n",
494  a._request);
495 }
496 
497 // Test generateHeader()
498 // Correct header is generated for various sizes and content of request body.
500  XmlRpcClientForTest a("localhost", 42);
501  // generateRequest takes a method name and params and puts the result in the
502  // _request member variable.
503  std::string header = "POST /RPC2 HTTP/1.1\r\n"
504  "User-Agent: XMLRPC++ 0.7\r\n"
505  "Host: localhost:42\r\n"
506  "Content-Type: text/xml\r\n";
507 
508  // Nonzero length message body.
509  EXPECT_EQ(header + "Content-length: 30\r\n\r\n", a.generateHeader(30));
510 
511  // Zero-length body as degenerate case.
512  EXPECT_EQ(header + "Content-length: 0\r\n\r\n", a.generateHeader(0));
513 }
514 
515 // Test writeRequest()
516 // Test that everything in a single write works; Client is left in the correct
517 // state.
518 // Test that partial write works, client is left in the correct state.
519 // Test that socket errors result in the correct state and that the socket
520 // is closed (or not) correctly.
522  XmlRpcClientForTest a("localhost", 42);
523 
524  // Hack us into the correct initial state.
525  a.setfd(7);
527  a._request = "FAKE_REQUEST";
528 
529  // Check that request length is the correct size.
530  ASSERT_EQ(12u, a._request.size());
531 
532  // Expect a write; write all bytes and return success.
533  Expect_nbWrite(7, "FAKE_REQUEST", 12, true);
534 
535  // Expect that writeRequest is successful.
536  EXPECT_TRUE(a.writeRequest());
537 
538  // Check that resulting state is READ_HEADER
540 
541  // Check that all expected function calls were made before destruction.
542  CheckCalls();
543 
544  // Expect a close on destruction.
545  Expect_close(7);
546 }
547 
548 TEST_F(MockSocketTest, writeRequest_partial) {
549  XmlRpcClientForTest a("localhost", 42);
550 
551  // Hack us into the correct initial state.
552  a.setfd(7);
554  a._request = "FAKE_REQUEST";
555 
556  // Check that request length is the correct size.
557  ASSERT_EQ(12u, a._request.size());
558 
559  // Expect a write; only write 5 bytes and return success.
560  Expect_nbWrite(7, "FAKE_REQUEST", 5, true);
561  // Expect that writeRequest is successful.
562  EXPECT_TRUE(a.writeRequest());
563  // Check that resulting state is READ_HEADER
565  // Check that all expected function calls were made.
566  CheckCalls();
567 
568  // Expect a write; write remaining bytes and return success.
569  Expect_nbWrite(7, "REQUEST", 7, true);
570  // Expect that writeRequest is successful.
571  EXPECT_TRUE(a.writeRequest());
572  // Check that resulting state is READ_HEADER
574  // Check that all expected function calls were made before destruction.
575  CheckCalls();
576 
577  // Expect a close on destruction.
578  Expect_close(7);
579 }
580 
581 TEST_F(MockSocketTest, writeRequest_partial_error) {
582  XmlRpcClientForTest a("localhost", 42);
583 
584  // Hack us into the correct initial state.
585  a.setfd(7);
587  a._request = "FAKE_REQUEST";
588 
589  // Check that request length is the correct size.
590  ASSERT_EQ(12u, a._request.size());
591 
592  // Expect a write; only write 5 bytes and return success.
593  Expect_nbWrite(7, "FAKE_REQUEST", 5, true);
594  // Expect that writeRequest is successful.
595  EXPECT_TRUE(a.writeRequest());
596  // Check that resulting state is READ_HEADER
598  // Check that all expected function calls were made.
599  CheckCalls();
600 
601  // Expect a write; write no bytes and return failure.
602  Expect_nbWrite(7, "REQUEST", 0, false);
603  // Expect close, since the write failed.
604  Expect_close(7);
605  Expect_getError(ECONNREFUSED);
606  // Expect that writeRequest fails.
607  EXPECT_FALSE(a.writeRequest());
608  // Check that resulting state is not connected.
610 
611  // Check that all expected function calls were made before destruction.
612  CheckCalls();
613 }
614 
615 TEST_F(MockSocketTest, writeRequest_error) {
616  XmlRpcClientForTest a("localhost", 42);
617 
618  // Hack us into the correct initial state.
619  a.setfd(7);
621  a._request = "FAKE_REQUEST";
622 
623  // Check that request length is the correct size.
624  ASSERT_EQ(12u, a._request.size());
625 
626  // Expect a write; write no bytes and return error.
627  Expect_nbWrite(7, "FAKE_REQUEST", 0, false);
628  Expect_close(7);
629  Expect_getError(ECONNREFUSED);
630  // Expect that writeRequest fails.
631  EXPECT_FALSE(a.writeRequest());
632  // Check that resulting state is not connected.
634 
635  // Check that all expected function calls were made before destruction.
636  CheckCalls();
637 }
638 
639 // Header as it would be generated by XmlRpcpp and body.
640 const std::string header = "HTTP/1.1 200 OK\r\n"
641  "Server: XMLRPC++ 0.7\r\n"
642  "Content-Type: text/xml\r\n"
643  "Content-length: 114\r\n\r\n";
644 // Alternate header as returned by roscore
645 const std::string header2 = "HTTP/1.0 200 OK\r\n"
646  "Server: BaseHTTP/0.3 Python/2.7.6\r\n"
647  "Date: Mon, 30 Oct 2017 22:28:12 GMT\r\n"
648  "Content-type: text/xml\r\n"
649  "Content-length: 114\r\n\r\n";
650 // Generic response XML
651 const std::string response = "<?xml version=\"1.0\"?>\r\n"
652  "<methodResponse><params><param>\r\n"
653  "<value>Hello</value>\r\n"
654  "</param></params></methodResponse>\r\n";
655 
656 // Test readHeader()
657 // Test that a full read with just a header works correctly.
658 // Test that various partial reads of the header work.
659 // Test that stacked partial reads of the header eventually result in success.
660 // Test that a read that returns both header and response data correctly
661 // removes the header and leaves the response.
662 // TODO(future work): Test the header parser in readHeader.
663 // TODO(future work): Test cases where the Content-length header is absent,
664 // zero, negative or garbage.
665 //
666 // Test that readHeader works correctly with the header from XmlRpcpp
668  XmlRpcClientForTest a("localhost", 42);
669 
670  // Hack us into the correct initial state.
671  a.setfd(7);
673 
674  // Self-test that response length matches encoded values above.
675  ASSERT_EQ(114u, response.length());
676 
677  // Expect a read and have it return the header and the response.
678  Expect_nbRead(7, header + response, false, true);
679 
680  EXPECT_TRUE(a.readHeader());
681 
682  // Check that state machine is in the correct state after getting the header.
684  // Check that the remaining response is stored in _response
685  EXPECT_EQ(response, a._response);
686  EXPECT_EQ(114, a._contentLength); // Check decoded content length
687 
688  // Check that all expected function calls were made before destruction.
689  CheckCalls();
690 
691  // Expect close on destruction.
692  Expect_close(7);
693 }
694 
695 // Test that readHeader works correctly with the header from roscore.
696 TEST_F(MockSocketTest, readHeader2) {
697  XmlRpcClientForTest a("localhost", 42);
698 
699  // Hack us into the correct initial state.
700  a.setfd(7);
702 
703  // Expect a read and have it return the header and the response.
704  Expect_nbRead(7, header2 + response, false, true);
705 
706  EXPECT_TRUE(a.readHeader());
707 
708  // Check that state machine is in the correct state after getting the header.
710  // Check that the remaining response is stored in _response
711  EXPECT_EQ(response, a._response);
712  EXPECT_EQ(114, a._contentLength); // Check decoded content length
713 
714  // Check that all expected function calls were made before destruction.
715  CheckCalls();
716 
717  // Expect close on destruction.
718  Expect_close(7);
719 }
720 
721 // Test that readHeader decodes the content-length when read only returns the
722 // header.
723 // TODO(future work): there appears to be a bug in the header parsing where it
724 // doesn't pass the header parsing state until it gets the first byte of the
725 // response body.
726 TEST_F(MockSocketTest, readHeader_only) {
727  XmlRpcClientForTest a("localhost", 42);
728 
729  // Hack us into the correct initial state.
730  a.setfd(7);
732 
733  // Expect a read and have it return only the header.
734  // NOTE(austin): the header parser doesn't terminate until it gets the first
735  // byte of the response; so give it one additional byte.
736  Expect_nbRead(7, header + " ", false, true);
737 
738  EXPECT_TRUE(a.readHeader());
739 
740  // Check that state machine is in the correct state after getting the header.
742  // Check that the remaining response is stored in _response
743  EXPECT_EQ(" ", a._response);
744  EXPECT_EQ(114, a._contentLength); // Check decoded content length
745 
746  // Check that all expected function calls were made before destruction.
747  CheckCalls();
748 
749  // Expect close on destruction.
750  Expect_close(7);
751 }
752 
753 // Test that readHeader correctly resumes after getting a partial header read.
754 TEST_F(MockSocketTest, readHeader_partial) {
755  XmlRpcClientForTest a("localhost", 42);
756 
757  // Hack us into the correct initial state.
758  a.setfd(7);
760 
761  std::string header_part1 = header.substr(0, 32);
762  std::string header_part2 = header.substr(32);
763 
764  // Expect a read and have it return only part of the header.
765  Expect_nbRead(7, header_part1, false, true);
766  EXPECT_TRUE(a.readHeader());
767  // Check that state machine is in the correct state after getting the header.
769  // Check that the partial header is stored in _header.
770  EXPECT_EQ(header_part1, a._header);
771 
772  // Check that all expected function calls were made before we proceed.
773  CheckCalls();
774 
775  // Expect a read and have it return the remainder of the header.
776  Expect_nbRead(7, header_part2 + " ", false, true);
777  EXPECT_TRUE(a.readHeader());
778  // Check that state machine is in the correct state after getting the header.
780  // Check that the remaining response is stored in _response
781  EXPECT_EQ(" ", a._response);
782  EXPECT_EQ(114, a._contentLength); // Check decoded content length
783 
784  // Check that all expected function calls were made before destruction.
785  CheckCalls();
786 
787  // Expect close on destruction.
788  Expect_close(7);
789 }
790 
791 // Test that readHeader reports an error if the read fails.
792 TEST_F(MockSocketTest, readHeader_err) {
793  XmlRpcClientForTest a("localhost", 42);
794 
795  // Hack us into the correct initial state.
796  a.setfd(7);
798 
799  // Expect a read and have it fail.
800  Expect_nbRead(7, "", false, false);
801  // Expect the client to close the socket.
802  Expect_close(7);
803  // Expect a reconnect attempt
804  Expect_socket(8);
805  Expect_setNonBlocking(8, true);
806  Expect_connect(8, "localhost", 42, true);
807 
808  EXPECT_TRUE(a.readHeader());
809 
810  // Check that state machine is in the correct state after getting the header.
812  EXPECT_EQ(1, a._sendAttempts);
813 
814  // Check that all expected function calls were made before destruction.
815  CheckCalls();
816 
817  // Skip the state machine forward to READ_HEADER state again.
819 
820  // Do it again, but this time don't expect a reconnect attempt
821  // Expect a read and have it return eof and success.
822  Expect_nbRead(8, "", true, true);
823  Expect_getError(ENOTCONN);
824  // Expect the client to close the socket.
825  Expect_close(8);
826 
827  EXPECT_FALSE(a.readHeader());
828 
829  // Check that state machine is in the correct state after getting the header.
831 
832  // Check that all expected function calls were made before destruction.
833  CheckCalls();
834 }
835 
836 // Test that readHeader reports an error if it gets EOF before it gets the
837 // content length.
838 TEST_F(MockSocketTest, readHeader_eof) {
839  XmlRpcClientForTest a("localhost", 42);
840 
841  // Hack us into the correct initial state.
842  a.setfd(7);
844 
845  // Expect a read and have it return eof and success.
846  Expect_nbRead(7, "", true, true);
847  // Expect the client to close the socket.
848  Expect_close(7);
849  // Expect a reconnect attempt
850  Expect_socket(8);
851  Expect_setNonBlocking(8, true);
852  Expect_connect(8, "localhost", 42, true);
853 
854  EXPECT_TRUE(a.readHeader());
855 
856  // Check that state machine is in the correct state after getting the header.
858  EXPECT_EQ(1, a._sendAttempts);
859 
860  // Check that all expected function calls were made before destruction.
861  CheckCalls();
862 
863  // Skip the state machine forward to READ_HEADER state again.
865 
866  // Do it again, but this time don't expect a reconnect attempt
867  // Expect a read and have it return eof and success.
868  Expect_nbRead(8, "", true, true);
869  Expect_getError(ENOTCONN);
870  // Expect the client to close the socket.
871  Expect_close(8);
872 
873  EXPECT_FALSE(a.readHeader());
874 
875  // Check that state machine is in the correct state after getting the header.
877 
878  // Check that all expected function calls were made before destruction.
879  CheckCalls();
880 }
881 
882 // Test that readHeader reports an error and closes the socket if the second
883 // part of a partial read returns an error.
884 TEST_F(MockSocketTest, readHeader_partial_err) {
885  XmlRpcClientForTest a("localhost", 42);
886 
887  // Hack us into the correct initial state.
888  a.setfd(7);
890 
891  std::string header_part1 = header.substr(0, 32);
892 
893  // Expect a read and have it return only part of the header.
894  Expect_nbRead(7, header_part1, false, true);
895  EXPECT_TRUE(a.readHeader());
896  // Check that state machine is in the correct state after getting the header.
898  // Check that the partial header is stored in _header.
899  EXPECT_EQ(header_part1, a._header);
900 
901  // Check that all expected function calls were made before we proceed.
902  CheckCalls();
903 
904  // Expect a read and have it return an error.
905  Expect_nbRead(7, "", false, false);
906  Expect_close(7);
907  // Expect a reconnect attempt
908  Expect_socket(8);
909  Expect_setNonBlocking(8, true);
910  Expect_connect(8, "localhost", 42, true);
911 
912  EXPECT_TRUE(a.readHeader());
913  // Check that state machine is in the correct state after getting the header.
915 
916  // Check that all expected function calls were made before destruction.
917  CheckCalls();
918 
919  // Expect socket close on destruction.
920  Expect_close(8);
921 }
922 
923 // Test readResponse()
924 // Test read of response in a single read call
925 // Test response spread across several read calls
926 // Test empty response
927 // Test read errors on first or subsequent reads
928 // Test for correct state after each of these events.
929 
930 // Test that readResponse does nothing if _response is already populated by
931 // readHeader.
932 TEST_F(MockSocketTest, readResponse_noop) {
933  XmlRpcClientForTest a("localhost", 42);
934 
935  // Hack us into the correct initial state.
936  a.setfd(7);
938  // Response was already read by readHeader
939  // (verified by previous tests).
940  a._response = response;
941  a._contentLength = 114;
942  ASSERT_EQ(114u, a._response.length());
943 
944  // Don't expect any calls. Expect readResponse to return false since we don't
945  // need to keep monitoring this client.
946  EXPECT_FALSE(a.readResponse());
947 
948  // Check that state machine is in the correct state after getting the header.
950  // Check that the remaining response is stored in _response
951  EXPECT_EQ(response, a._response);
952  EXPECT_EQ(114, a._contentLength); // Check decoded content length
953 
954  // Check that all expected function calls were made before destruction.
955  CheckCalls();
956 
957  // Expect close on destruction.
958  Expect_close(7);
959 }
960 
961 // Test that readResponse works if the initial buffer is empty.
963  XmlRpcClientForTest a("localhost", 42);
964 
965  // Hack us into the correct initial state.
966  a.setfd(7);
968  // Start with empty response and pre-populated content length.
969  a._response = "";
970  a._contentLength = 114;
971  ASSERT_EQ(114u, response.length());
972 
973  // Expect a read, have it return the full response and success.
974  Expect_nbRead(7, response, false, true);
975  // Expect readResponse to return false since we're done monitoring this
976  // socket.
977  EXPECT_FALSE(a.readResponse());
978 
979  // Check that state machine is in the correct state after getting the header.
981  // Check that the remaining response is stored in _response
982  EXPECT_EQ(response, a._response);
983 
984  // Check that all expected function calls were made before destruction.
985  CheckCalls();
986 
987  // Expect close on destruction.
988  Expect_close(7);
989 }
990 
991 // Test that readResponse works if the initial buffer is empty.
992 TEST_F(MockSocketTest, readResponse_partial) {
993  XmlRpcClientForTest a("localhost", 42);
994 
995  // Hack us into the correct initial state.
996  a.setfd(7);
998  // Start with empty response and pre-populated content length.
999  a._response = "";
1000  a._contentLength = 114;
1001  ASSERT_EQ(114u, response.length());
1002 
1003  const std::string response_part1 = response.substr(0, 60);
1004  const std::string response_part2 = response.substr(60);
1005 
1006  // Expect a read, have it return the first part of the response.
1007  Expect_nbRead(7, response_part1, false, true);
1008  EXPECT_TRUE(a.readResponse());
1009 
1010  // Check that the first part of the response is stored in _response
1011  EXPECT_EQ(response_part1, a._response);
1012  // Check that state machine is in the correct state after getting the header.
1014 
1015  // Check that all expected function calls were made before destruction.
1016  CheckCalls();
1017 
1018  // Expect a read, have it return the remainder of the response and success.
1019  Expect_nbRead(7, response_part2, false, true);
1020 
1021  // Expect readResponse to return false now since we're done monitoring this
1022  // socket.
1023  EXPECT_FALSE(a.readResponse());
1024 
1025  // Check that state machine is in the correct state after getting the header.
1027  // Check that the remaining response is stored in _response
1028  EXPECT_EQ(response, a._response);
1029 
1030  // Check that all expected function calls were made before destruction.
1031  CheckCalls();
1032 
1033  // Expect close on destruction.
1034  Expect_close(7);
1035 }
1036 
1037 // Test that readResponse closes the socket and returns an error if the read
1038 // fails.
1039 TEST_F(MockSocketTest, readResponse_err) {
1040  XmlRpcClientForTest a("localhost", 42);
1041 
1042  // Hack us into the correct initial state.
1043  a.setfd(7);
1045  // Start with empty response and pre-populated content length.
1046  a._response = "";
1047  a._contentLength = 114;
1048  ASSERT_EQ(114u, response.length());
1049 
1050  // Expect a read, have it return an error.
1051  Expect_nbRead(7, "", false, false);
1052  // Expect getError and close()
1053  Expect_getError(ENOTCONN);
1054  Expect_close(7);
1055  // Expect readResponse to return false since we're done monitoring this
1056  // socket.
1057  EXPECT_FALSE(a.readResponse());
1058 
1059  // Check that state machine is in the correct state after getting the header.
1061 
1062  // Check that all expected function calls were made before destruction.
1063  CheckCalls();
1064 }
1065 
1066 // Test that readResponse works if the initial buffer is empty.
1067 TEST_F(MockSocketTest, readResponse_eof) {
1068  XmlRpcClientForTest a("localhost", 42);
1069 
1070  // Hack us into the correct initial state.
1071  a.setfd(7);
1073  // Start with empty response and pre-populated content length.
1074  a._response = "";
1075  a._contentLength = 114;
1076  ASSERT_EQ(114u, response.length());
1077 
1078  // Expect a read, have it return nothing and EOF.
1079  Expect_nbRead(7, "", true, true);
1080  // Expect that we close the socket.
1081  Expect_close(7);
1082  // Expect readResponse to return false since we're done monitoring this
1083  // socket.
1084  EXPECT_FALSE(a.readResponse());
1085 
1086  // Check that state machine is in the correct state after getting the header.
1088 
1089  // Check that all expected function calls were made before destruction.
1090  CheckCalls();
1091 }
1092 
1093 // Test parseResponse
1094 // Test correct parsing of various response types: empty, int, double,
1095 // string, bool, list, struct, date, base64, etc
1096 // Test for correct handling of empty response body
1097 // Test for correct parsing/handling of partial response
1098 // Test for correct handling of garbage data
1099 // Test for correct handling of mismatched XML tags at top level
1100 // Test for correct handling of ALL UPPERCASE, lowercase and CamelCase tags
1101 
1102 int main(int argc, char **argv)
1103 {
1104  ::testing::InitGoogleTest(&argc, argv);
1105  return RUN_ALL_TESTS();
1106 }
virtual bool generateRequest(const char *method, XmlRpcValue const &params)
int getfd() const
Return the file descriptor being monitored.
Definition: XmlRpcSource.h:27
RPC method arguments and results are represented by Values.
Definition: XmlRpcValue.h:24
virtual bool readHeader()
XmlRpcServer s
Definition: HelloServer.cpp:11
bool valid() const
Return true if the value has been set to something.
Definition: XmlRpcValue.h:114
const std::string & getHost()
Definition: XmlRpcClient.h:100
std::string _request
Definition: XmlRpcClient.h:105
TEST(XmlRpcClient, connectionStateStr)
Definition: test_client.cpp:85
int main(int argc, char **argv)
virtual void close()
Close the connection.
XmlRpcDispatch _disp
Definition: XmlRpcClient.h:131
ClientConnectionState _connectionState
Definition: XmlRpcClient.h:91
TEST_F(MockSocketTest, constructor)
Definition: test_client.cpp:97
void setfd(int fd)
Specify the file descriptor to monitor.
Definition: XmlRpcSource.h:29
bool sourceInList(XmlRpc::XmlRpcSource *source, const XmlRpc::XmlRpcDispatch::SourceList &list)
Definition: test_client.cpp:71
An RPC source represents a file descriptor to monitor.
Definition: XmlRpcSource.h:16
static const char * connectionStateStr(ClientConnectionState state)
virtual bool doConnect()
const std::string & getUri()
Definition: XmlRpcClient.h:101
void PrintTo(const XmlRpcClientForTest::ClientConnectionState &state, ::std::ostream *os)
Definition: test_client.cpp:64
const std::string header2
A class to send XML RPC requests to a server and return the results.
Definition: XmlRpcClient.h:26
virtual std::string generateHeader(size_t length) const
bool getKeepOpen() const
Return whether the file descriptor should be kept open if it is no longer monitored.
Definition: XmlRpcSource.h:32
std::string _response
Definition: XmlRpcClient.h:107
const std::string header
std::list< MonitoredSource > SourceList
#define TEST_STATE(state)
virtual bool setupConnection()
virtual bool readResponse()
const std::string response
virtual bool writeRequest()
XmlRpcClientForTest(const char *host, int port, const char *uri=0)
Definition: test_client.cpp:39


xmlrpcpp
Author(s): Chris Morley, Konstantin Pilipchuk, Morgan Quigley, Austin Hendrix
autogenerated on Wed Oct 16 2019 03:27:40