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 // Header for testing a custom Content-length value
651 const std::string header3 = "HTTP/1.1 200 OK\r\n"
652  "Server: XMLRPC++ 0.7\r\n"
653  "Content-Type: text/xml\r\n"
654  "Content-length: ";
655 // Generic response XML
656 const std::string response = "<?xml version=\"1.0\"?>\r\n"
657  "<methodResponse><params><param>\r\n"
658  "<value>Hello</value>\r\n"
659  "</param></params></methodResponse>\r\n";
660 
661 // Test readHeader()
662 // Test that a full read with just a header works correctly.
663 // Test that various partial reads of the header work.
664 // Test that stacked partial reads of the header eventually result in success.
665 // Test that a read that returns both header and response data correctly
666 // removes the header and leaves the response.
667 // TODO(future work): Test the header parser in readHeader.
668 // TODO(future work): Test cases where the Content-length header is absent,
669 // zero, negative or garbage.
670 //
671 // Test that readHeader works correctly with the header from XmlRpcpp
673  XmlRpcClientForTest a("localhost", 42);
674 
675  // Hack us into the correct initial state.
676  a.setfd(7);
678 
679  // Self-test that response length matches encoded values above.
680  ASSERT_EQ(114u, response.length());
681 
682  // Expect a read and have it return the header and the response.
683  Expect_nbRead(7, header + response, false, true);
684 
685  EXPECT_TRUE(a.readHeader());
686 
687  // Check that state machine is in the correct state after getting the header.
689  // Check that the remaining response is stored in _response
690  EXPECT_EQ(response, a._response);
691  EXPECT_EQ(114, a._contentLength); // Check decoded content length
692 
693  // Check that all expected function calls were made before destruction.
694  CheckCalls();
695 
696  // Expect close on destruction.
697  Expect_close(7);
698 }
699 
700 // Test that readHeader works correctly with the header from roscore.
701 TEST_F(MockSocketTest, readHeader2) {
702  XmlRpcClientForTest a("localhost", 42);
703 
704  // Hack us into the correct initial state.
705  a.setfd(7);
707 
708  // Expect a read and have it return the header and the response.
709  Expect_nbRead(7, header2 + response, false, true);
710 
711  EXPECT_TRUE(a.readHeader());
712 
713  // Check that state machine is in the correct state after getting the header.
715  // Check that the remaining response is stored in _response
716  EXPECT_EQ(response, a._response);
717  EXPECT_EQ(114, a._contentLength); // Check decoded content length
718 
719  // Check that all expected function calls were made before destruction.
720  CheckCalls();
721 
722  // Expect close on destruction.
723  Expect_close(7);
724 }
725 
726 // Test that readHeader decodes the content-length when read only returns the
727 // header.
728 // TODO(future work): there appears to be a bug in the header parsing where it
729 // doesn't pass the header parsing state until it gets the first byte of the
730 // response body.
731 TEST_F(MockSocketTest, readHeader_only) {
732  XmlRpcClientForTest a("localhost", 42);
733 
734  // Hack us into the correct initial state.
735  a.setfd(7);
737 
738  // Expect a read and have it return only the header.
739  // NOTE(austin): the header parser doesn't terminate until it gets the first
740  // byte of the response; so give it one additional byte.
741  Expect_nbRead(7, header + " ", false, true);
742 
743  EXPECT_TRUE(a.readHeader());
744 
745  // Check that state machine is in the correct state after getting the header.
747  // Check that the remaining response is stored in _response
748  EXPECT_EQ(" ", a._response);
749  EXPECT_EQ(114, a._contentLength); // Check decoded content length
750 
751  // Check that all expected function calls were made before destruction.
752  CheckCalls();
753 
754  // Expect close on destruction.
755  Expect_close(7);
756 }
757 
758 // Test that readHeader correctly resumes after getting a partial header read.
759 TEST_F(MockSocketTest, readHeader_partial) {
760  XmlRpcClientForTest a("localhost", 42);
761 
762  // Hack us into the correct initial state.
763  a.setfd(7);
765 
766  std::string header_part1 = header.substr(0, 32);
767  std::string header_part2 = header.substr(32);
768 
769  // Expect a read and have it return only part of the header.
770  Expect_nbRead(7, header_part1, false, true);
771  EXPECT_TRUE(a.readHeader());
772  // Check that state machine is in the correct state after getting the header.
774  // Check that the partial header is stored in _header.
775  EXPECT_EQ(header_part1, a._header);
776 
777  // Check that all expected function calls were made before we proceed.
778  CheckCalls();
779 
780  // Expect a read and have it return the remainder of the header.
781  Expect_nbRead(7, header_part2 + " ", false, true);
782  EXPECT_TRUE(a.readHeader());
783  // Check that state machine is in the correct state after getting the header.
785  // Check that the remaining response is stored in _response
786  EXPECT_EQ(" ", a._response);
787  EXPECT_EQ(114, a._contentLength); // Check decoded content length
788 
789  // Check that all expected function calls were made before destruction.
790  CheckCalls();
791 
792  // Expect close on destruction.
793  Expect_close(7);
794 }
795 
796 // Test that readHeader reports an error if the read fails.
797 TEST_F(MockSocketTest, readHeader_err) {
798  XmlRpcClientForTest a("localhost", 42);
799 
800  // Hack us into the correct initial state.
801  a.setfd(7);
803 
804  // Expect a read and have it fail.
805  Expect_nbRead(7, "", false, false);
806  // Expect the client to close the socket.
807  Expect_close(7);
808  // Expect a reconnect attempt
809  Expect_socket(8);
810  Expect_setNonBlocking(8, true);
811  Expect_connect(8, "localhost", 42, true);
812 
813  EXPECT_TRUE(a.readHeader());
814 
815  // Check that state machine is in the correct state after getting the header.
817  EXPECT_EQ(1, a._sendAttempts);
818 
819  // Check that all expected function calls were made before destruction.
820  CheckCalls();
821 
822  // Skip the state machine forward to READ_HEADER state again.
824 
825  // Do it again, but this time don't expect a reconnect attempt
826  // Expect a read and have it return eof and success.
827  Expect_nbRead(8, "", true, true);
828  Expect_getError(ENOTCONN);
829  // Expect the client to close the socket.
830  Expect_close(8);
831 
832  EXPECT_FALSE(a.readHeader());
833 
834  // Check that state machine is in the correct state after getting the header.
836 
837  // Check that all expected function calls were made before destruction.
838  CheckCalls();
839 }
840 
841 // Test that readHeader reports an error if it gets EOF before it gets the
842 // content length.
843 TEST_F(MockSocketTest, readHeader_eof) {
844  XmlRpcClientForTest a("localhost", 42);
845 
846  // Hack us into the correct initial state.
847  a.setfd(7);
849 
850  // Expect a read and have it return eof and success.
851  Expect_nbRead(7, "", true, true);
852  // Expect the client to close the socket.
853  Expect_close(7);
854  // Expect a reconnect attempt
855  Expect_socket(8);
856  Expect_setNonBlocking(8, true);
857  Expect_connect(8, "localhost", 42, true);
858 
859  EXPECT_TRUE(a.readHeader());
860 
861  // Check that state machine is in the correct state after getting the header.
863  EXPECT_EQ(1, a._sendAttempts);
864 
865  // Check that all expected function calls were made before destruction.
866  CheckCalls();
867 
868  // Skip the state machine forward to READ_HEADER state again.
870 
871  // Do it again, but this time don't expect a reconnect attempt
872  // Expect a read and have it return eof and success.
873  Expect_nbRead(8, "", true, true);
874  Expect_getError(ENOTCONN);
875  // Expect the client to close the socket.
876  Expect_close(8);
877 
878  EXPECT_FALSE(a.readHeader());
879 
880  // Check that state machine is in the correct state after getting the header.
882 
883  // Check that all expected function calls were made before destruction.
884  CheckCalls();
885 }
886 
887 // Test that readHeader reports an error and closes the socket if the second
888 // part of a partial read returns an error.
889 TEST_F(MockSocketTest, readHeader_partial_err) {
890  XmlRpcClientForTest a("localhost", 42);
891 
892  // Hack us into the correct initial state.
893  a.setfd(7);
895 
896  std::string header_part1 = header.substr(0, 32);
897 
898  // Expect a read and have it return only part of the header.
899  Expect_nbRead(7, header_part1, false, true);
900  EXPECT_TRUE(a.readHeader());
901  // Check that state machine is in the correct state after getting the header.
903  // Check that the partial header is stored in _header.
904  EXPECT_EQ(header_part1, a._header);
905 
906  // Check that all expected function calls were made before we proceed.
907  CheckCalls();
908 
909  // Expect a read and have it return an error.
910  Expect_nbRead(7, "", false, false);
911  Expect_close(7);
912  // Expect a reconnect attempt
913  Expect_socket(8);
914  Expect_setNonBlocking(8, true);
915  Expect_connect(8, "localhost", 42, true);
916 
917  EXPECT_TRUE(a.readHeader());
918  // Check that state machine is in the correct state after getting the header.
920 
921  // Check that all expected function calls were made before destruction.
922  CheckCalls();
923 
924  // Expect socket close on destruction.
925  Expect_close(8);
926 }
927 
928 // Test that the read will fail when content-length is too large
929 TEST_F(MockSocketTest, readHeader_oversize) {
930  XmlRpcClientForTest a("localhost", 42);
931 
932  // Hack us into the correct initial state.
933  a.setfd(7);
935 
936  // Add a large content-length to the standard header
937  std::string header_cl = header3;
938  header_cl += std::to_string(size_t(__INT_MAX__) + 1);
939  header_cl += "\r\n\r\n ";
940 
941  Expect_nbRead(7, header_cl, false, true);
942  Expect_close(7);
943 
944  EXPECT_FALSE(a.readHeader());
945  EXPECT_EQ(0, a._contentLength); // Content length should be reset
946 
947  // Check that all expected function calls were made before destruction.
948  CheckCalls();
949 }
950 
951 // Test readResponse()
952 // Test read of response in a single read call
953 // Test response spread across several read calls
954 // Test empty response
955 // Test read errors on first or subsequent reads
956 // Test for correct state after each of these events.
957 
958 // Test that readResponse does nothing if _response is already populated by
959 // readHeader.
960 TEST_F(MockSocketTest, readResponse_noop) {
961  XmlRpcClientForTest a("localhost", 42);
962 
963  // Hack us into the correct initial state.
964  a.setfd(7);
966  // Response was already read by readHeader
967  // (verified by previous tests).
968  a._response = response;
969  a._contentLength = 114;
970  ASSERT_EQ(114u, a._response.length());
971 
972  // Don't expect any calls. Expect readResponse to return false since we don't
973  // need to keep monitoring this client.
974  EXPECT_FALSE(a.readResponse());
975 
976  // Check that state machine is in the correct state after getting the header.
978  // Check that the remaining response is stored in _response
979  EXPECT_EQ(response, a._response);
980  EXPECT_EQ(114, a._contentLength); // Check decoded content length
981 
982  // Check that all expected function calls were made before destruction.
983  CheckCalls();
984 
985  // Expect close on destruction.
986  Expect_close(7);
987 }
988 
989 // Test that readResponse works if the initial buffer is empty.
991  XmlRpcClientForTest a("localhost", 42);
992 
993  // Hack us into the correct initial state.
994  a.setfd(7);
996  // Start with empty response and pre-populated content length.
997  a._response = "";
998  a._contentLength = 114;
999  ASSERT_EQ(114u, response.length());
1000 
1001  // Expect a read, have it return the full response and success.
1002  Expect_nbRead(7, response, false, true);
1003  // Expect readResponse to return false since we're done monitoring this
1004  // socket.
1005  EXPECT_FALSE(a.readResponse());
1006 
1007  // Check that state machine is in the correct state after getting the header.
1009  // Check that the remaining response is stored in _response
1010  EXPECT_EQ(response, a._response);
1011 
1012  // Check that all expected function calls were made before destruction.
1013  CheckCalls();
1014 
1015  // Expect close on destruction.
1016  Expect_close(7);
1017 }
1018 
1019 // Test that readResponse works if the initial buffer is empty.
1020 TEST_F(MockSocketTest, readResponse_partial) {
1021  XmlRpcClientForTest a("localhost", 42);
1022 
1023  // Hack us into the correct initial state.
1024  a.setfd(7);
1026  // Start with empty response and pre-populated content length.
1027  a._response = "";
1028  a._contentLength = 114;
1029  ASSERT_EQ(114u, response.length());
1030 
1031  const std::string response_part1 = response.substr(0, 60);
1032  const std::string response_part2 = response.substr(60);
1033 
1034  // Expect a read, have it return the first part of the response.
1035  Expect_nbRead(7, response_part1, false, true);
1036  EXPECT_TRUE(a.readResponse());
1037 
1038  // Check that the first part of the response is stored in _response
1039  EXPECT_EQ(response_part1, a._response);
1040  // Check that state machine is in the correct state after getting the header.
1042 
1043  // Check that all expected function calls were made before destruction.
1044  CheckCalls();
1045 
1046  // Expect a read, have it return the remainder of the response and success.
1047  Expect_nbRead(7, response_part2, false, true);
1048 
1049  // Expect readResponse to return false now since we're done monitoring this
1050  // socket.
1051  EXPECT_FALSE(a.readResponse());
1052 
1053  // Check that state machine is in the correct state after getting the header.
1055  // Check that the remaining response is stored in _response
1056  EXPECT_EQ(response, a._response);
1057 
1058  // Check that all expected function calls were made before destruction.
1059  CheckCalls();
1060 
1061  // Expect close on destruction.
1062  Expect_close(7);
1063 }
1064 
1065 // Test that readResponse closes the socket and returns an error if the read
1066 // fails.
1067 TEST_F(MockSocketTest, readResponse_err) {
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 an error.
1079  Expect_nbRead(7, "", false, false);
1080  // Expect getError and close()
1081  Expect_getError(ENOTCONN);
1082  Expect_close(7);
1083  // Expect readResponse to return false since we're done monitoring this
1084  // socket.
1085  EXPECT_FALSE(a.readResponse());
1086 
1087  // Check that state machine is in the correct state after getting the header.
1089 
1090  // Check that all expected function calls were made before destruction.
1091  CheckCalls();
1092 }
1093 
1094 // Test that readResponse works if the initial buffer is empty.
1095 TEST_F(MockSocketTest, readResponse_eof) {
1096  XmlRpcClientForTest a("localhost", 42);
1097 
1098  // Hack us into the correct initial state.
1099  a.setfd(7);
1101  // Start with empty response and pre-populated content length.
1102  a._response = "";
1103  a._contentLength = 114;
1104  ASSERT_EQ(114u, response.length());
1105 
1106  // Expect a read, have it return nothing and EOF.
1107  Expect_nbRead(7, "", true, true);
1108  // Expect that we close the socket.
1109  Expect_close(7);
1110  // Expect readResponse to return false since we're done monitoring this
1111  // socket.
1112  EXPECT_FALSE(a.readResponse());
1113 
1114  // Check that state machine is in the correct state after getting the header.
1116 
1117  // Check that all expected function calls were made before destruction.
1118  CheckCalls();
1119 }
1120 
1121 // Test parseResponse
1122 // Test correct parsing of various response types: empty, int, double,
1123 // string, bool, list, struct, date, base64, etc
1124 // Test for correct handling of empty response body
1125 // Test for correct parsing/handling of partial response
1126 // Test for correct handling of garbage data
1127 // Test for correct handling of mismatched XML tags at top level
1128 // Test for correct handling of ALL UPPERCASE, lowercase and CamelCase tags
1129 
1130 int main(int argc, char **argv)
1131 {
1132  ::testing::InitGoogleTest(&argc, argv);
1133  return RUN_ALL_TESTS();
1134 }
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: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
const std::string header3
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, Dirk Thomas
autogenerated on Mon Oct 19 2020 03:23:56