Instrument Neutral Distributed Interface INDI  2.0.2
TestClientQueries.cpp
Go to the documentation of this file.
1 /*******************************************************************************
2  Copyright(c) 2022 Ludovic Pollet. All rights reserved.
3 
4  This library is free software; you can redistribute it and/or
5  modify it under the terms of the GNU Library General Public
6  License version 2 as published by the Free Software Foundation.
7 
8  This library is distributed in the hope that it will be useful,
9  but WITHOUT ANY WARRANTY; without even the implied warranty of
10  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
11  Library General Public License for more details.
12 
13  You should have received a copy of the GNU Library General Public License
14  along with this library; see the file COPYING.LIB. If not, write to
15  the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
16  Boston, MA 02110-1301, USA.
17 *******************************************************************************/
18 
19 #include <stdexcept>
20 #include <stdio.h>
21 #include <unistd.h>
22 #include <sys/types.h>
23 #include <system_error>
24 
25 #include "gtest/gtest.h"
26 
27 #include "utils.h"
28 
29 #include "SharedBuffer.h"
30 #include "DriverMock.h"
31 #include "IndiServerController.h"
32 #include "IndiClientMock.h"
33 
34 #define PROP_COUNT 5
35 
36 static void driverSendsProps(DriverMock &fakeDriver)
37 {
38  fprintf(stderr, "Driver sends properties\n");
39  for(int i = 0; i < PROP_COUNT; ++i)
40  {
41  fakeDriver.cnx.send("<defNumberVector device='fakedev1' name='testnumber" + std::to_string(
42  i) + "' label='test label' group='test_group' state='Idle' perm='rw' timeout='100' timestamp='2018-01-01T00:00:00'>\n");
43  fakeDriver.cnx.send("<defNumber name='content' label='content' min='0' max='100' step='1'>50</defNumber>\n");
44  fakeDriver.cnx.send("</defNumberVector>\n");
45  }
46 }
47 
48 static void clientReceivesProps(IndiClientMock &indiClient)
49 {
50  fprintf(stderr, "Client reveives properties\n");
51  for(int i = 0; i < PROP_COUNT; ++i)
52  {
53  indiClient.cnx.expectXml("<defNumberVector device='fakedev1' name='testnumber" + std::to_string(
54  i) + "' label='test label' group='test_group' state='Idle' perm='rw' timeout='100' timestamp='2018-01-01T00:00:00'>");
55  indiClient.cnx.expectXml("<defNumber name='content' label='content' min='0' max='100' step='1'>");
56  indiClient.cnx.expect("\n50");
57  indiClient.cnx.expectXml("</defNumber>");
58  indiClient.cnx.expectXml("</defNumberVector>");
59  }
60 }
61 
62 
63 static void startFakeDev1(IndiServerController &indiServer, DriverMock &fakeDriver)
64 {
65  setupSigPipe();
66 
67  fakeDriver.setup();
68 
69  std::string fakeDriverPath = getTestExePath("fakedriver");
70 
71  // Start indiserver with one instance, repeat 0
72  indiServer.startDriver(fakeDriverPath);
73  fprintf(stderr, "indiserver started\n");
74 
75  fakeDriver.waitEstablish();
76  fprintf(stderr, "fake driver started\n");
77 
78  fakeDriver.cnx.expectXml("<getProperties version='1.7'/>");
79  fprintf(stderr, "getProperties received\n");
80 
81  driverSendsProps(fakeDriver);
82 }
83 
84 static void connectFakeDev1Client(IndiServerController &, DriverMock &fakeDriver, IndiClientMock &indiClient)
85 {
86  fprintf(stderr, "Client asks properties\n");
87  indiClient.cnx.send("<getProperties version='1.7'/>\n");
88  fakeDriver.cnx.expectXml("<getProperties version='1.7'/>");
89 
90  driverSendsProps(fakeDriver);
91  fprintf(stderr, "Driver sends properties\n");
92 
93  fprintf(stderr, "Client receive properties\n");
94  clientReceivesProps(indiClient);
95 }
96 
97 TEST(TestClientQueries, ServerForwardRequest)
98 {
99  DriverMock fakeDriver;
100  IndiServerController indiServer;
101 
102  startFakeDev1(indiServer, fakeDriver);
103 
104  IndiClientMock indiClient;
105 
106  indiClient.connect(indiServer);
107 
108  connectFakeDev1Client(indiServer, fakeDriver, indiClient);
109 
110  indiClient.cnx.send("<newNumberVector device='fakedev1' name='testnumber' timestamp='2018-01-01T00:00:00'>");
111  indiClient.cnx.send("<oneNumber name='content' > 51 </oneNumber>");
112  indiClient.cnx.send("</newNumberVector>");
113 
114  fakeDriver.cnx.expectXml("<newNumberVector device='fakedev1' name='testnumber' timestamp='2018-01-01T00:00:00'>");
115  fakeDriver.cnx.expectXml("<oneNumber name='content'>");
116  fakeDriver.cnx.expect("\n51");
117  fakeDriver.cnx.expectXml("</oneNumber>");
118  fakeDriver.cnx.expectXml("</newNumberVector>");
119 
120  fakeDriver.terminateDriver();
121  // Exit code 1 is expected when driver stopped
122  indiServer.waitProcessEnd(1);
123 
124 }
125 
126 TEST(TestClientQueries, ServerForwardRequestOfHalfDeadClient)
127 {
128  DriverMock fakeDriver;
129  IndiServerController indiServer;
130 
131  startFakeDev1(indiServer, fakeDriver);
132 
133  IndiClientMock indiClient;
134 
135  indiClient.connect(indiServer);
136 
137  connectFakeDev1Client(indiServer, fakeDriver, indiClient);
138 
139  indiClient.cnx.send("<getProperties version='1.7'/>\n");
140  fakeDriver.cnx.expectXml("<getProperties version='1.7'/>");
141 
142  driverSendsProps(fakeDriver);
143 
144  // Make sure the server is sync with the client before shutdown. Get a full interaction with it
145  fakeDriver.cnx.send("<pingRequest uid='1'/>\n");
146  fakeDriver.cnx.expectXml("<pingReply uid='1'/>");
147 
148  indiClient.cnx.send("<newNumberVector device='fakedev1' name='testnumber' timestamp='2018-01-01T00:00:00'>");
149  indiClient.cnx.send("<oneNumber name='content' > 51 </oneNumber>");
150  indiClient.cnx.send("</newNumberVector>");
151 
152  // Client is done writing.
153  indiClient.cnx.shutdown(false, true);
154 
155  fakeDriver.cnx.expectXml("<newNumberVector device='fakedev1' name='testnumber' timestamp='2018-01-01T00:00:00'>");
156  fakeDriver.cnx.expectXml("<oneNumber name='content'>");
157  fakeDriver.cnx.expect("\n51");
158  fakeDriver.cnx.expectXml("</oneNumber>");
159  fakeDriver.cnx.expectXml("</newNumberVector>");
160 
161  indiClient.close();
162 
163  fakeDriver.terminateDriver();
164  // Exit code 1 is expected when driver stopped
165  indiServer.waitProcessEnd(1);
166 }
TEST(TestClientQueries, ServerForwardRequest)
#define PROP_COUNT
void connectFakeDev1Client(IndiServerController &, DriverMock &fakeDriver, IndiClientMock &indiClient)
void shutdown(bool rd, bool wr)
void expect(const std::string &content)
void send(const std::string &content)
void expectXml(const std::string &xml)
void terminateDriver()
Definition: DriverMock.cpp:56
ConnectionMock cnx
Definition: DriverMock.h:50
void waitEstablish()
Definition: DriverMock.cpp:49
void setup()
Definition: DriverMock.cpp:44
ConnectionMock cnx
void connect(const IndiServerController &server)
void startDriver(const std::string &driver)
void waitProcessEnd(int expectedExitCode)
NLOHMANN_BASIC_JSON_TPL_DECLARATION std::string to_string(const NLOHMANN_BASIC_JSON_TPL &j)
user-defined to_string function for JSON values
Definition: json.h:23613
std::string getTestExePath(const std::string &str)
Definition: utils.cpp:340
void setupSigPipe()
Definition: utils.cpp:37