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


xmlrpcpp
Author(s): Chris Morley, Konstantin Pilipchuk, Morgan Quigley, Austin Hendrix, Dirk Thomas
autogenerated on Mon Feb 28 2022 23:33:22