1 // Copyright 2010-2018, Google Inc.
2 // All rights reserved.
3 //
4 // Redistribution and use in source and binary forms, with or without
5 // modification, are permitted provided that the following conditions are
6 // met:
7 //
8 //     * Redistributions of source code must retain the above copyright
9 // notice, this list of conditions and the following disclaimer.
10 //     * Redistributions in binary form must reproduce the above
11 // copyright notice, this list of conditions and the following disclaimer
12 // in the documentation and/or other materials provided with the
13 // distribution.
14 //     * Neither the name of Google Inc. nor the names of its
15 // contributors may be used to endorse or promote products derived from
16 // this software without specific prior written permission.
17 //
18 // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
19 // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
20 // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
21 // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
22 // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
23 // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
24 // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
25 // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
26 // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
27 // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
28 // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
29 
30 #include "renderer/renderer_client.h"
31 
32 #include <string>
33 
34 #include "base/logging.h"
35 #include "base/number_util.h"
36 #include "base/port.h"
37 #include "base/util.h"
38 #include "base/version.h"
39 #include "ipc/ipc.h"
40 #include "protocol/renderer_command.pb.h"
41 #include "renderer/renderer_interface.h"
42 #include "testing/base/public/gunit.h"
43 
44 namespace mozc {
45 
46 namespace renderer {
47 
48 namespace {
UpdateVersion(int diff)49 const string UpdateVersion(int diff) {
50   std::vector<string> tokens;
51   Util::SplitStringUsing(Version::GetMozcVersion(), ".", &tokens);
52   EXPECT_EQ(tokens.size(), 4);
53   char buf[64];
54   snprintf(buf, sizeof(buf), "%d", NumberUtil::SimpleAtoi(tokens[3]) + diff);
55   tokens[3] = buf;
56   string output;
57   Util::JoinStrings(tokens, ".", &output);
58   return output;
59 }
60 
61 int g_counter = 0;
62 bool g_connected = false;
63 uint32 g_server_protocol_version = IPC_PROTOCOL_VERSION;
64 string g_server_product_version;
65 
66 class TestIPCClient : public IPCClientInterface {
67  public:
TestIPCClient()68   TestIPCClient() {
69     g_server_product_version = Version::GetMozcVersion();
70   }
~TestIPCClient()71   ~TestIPCClient() {}
72 
Connected() const73   bool Connected() const {
74     return g_connected;
75   }
76 
GetServerProtocolVersion() const77   uint32 GetServerProtocolVersion() const {
78     return g_server_protocol_version;
79   }
80 
GetServerProductVersion() const81   const string &GetServerProductVersion() const {
82     return g_server_product_version;
83   }
84 
85 
GetServerProcessId() const86   uint32 GetServerProcessId() const {
87     return 0;
88   }
89 
90   // just count up how many times Call is called.
Call(const char * request,size_t request_size,char * response,size_t * response_size,int32 timeout)91   virtual bool Call(const char *request,
92                     size_t request_size,
93                     char *response,
94                     size_t *response_size,
95                     int32 timeout) {
96     g_counter++;
97     return true;
98   }
99 
set_connected(bool connected)100   static void set_connected(bool connected) {
101     g_connected = connected;
102   }
103 
Reset()104   static void Reset() {
105     g_counter = 0;
106   }
107 
counter()108   static int counter() {
109     return g_counter;
110   }
111 
set_server_protocol_version(uint32 version)112   static void set_server_protocol_version(uint32 version) {
113     g_server_protocol_version = version;
114   }
115 
GetLastIPCError() const116   virtual IPCErrorType GetLastIPCError() const {
117     return IPC_NO_ERROR;
118   }
119 };
120 
121 class TestIPCClientFactory : public IPCClientFactoryInterface {
122  public:
TestIPCClientFactory()123   TestIPCClientFactory() {}
~TestIPCClientFactory()124   ~TestIPCClientFactory() {}
125 
NewClient(const string & name,const string & path_name)126   virtual IPCClientInterface *NewClient(const string &name,
127                                         const string &path_name) {
128     return new TestIPCClient;
129   }
130 
NewClient(const string & name)131   virtual IPCClientInterface *NewClient(const string &name) {
132     return new TestIPCClient;
133   }
134 };
135 
136 class TestRendererLauncher : public RendererLauncherInterface {
137  public:
TestRendererLauncher()138   TestRendererLauncher()
139       : start_renderer_called_(false),
140         force_terminate_renderer_called_(false),
141         available_(false), can_connect_(false) {}
~TestRendererLauncher()142   ~TestRendererLauncher() {}
143 
144   // implement StartServer.
145   // return true if server can launched successfully.
StartRenderer(const string & name,const string & renderer_path,bool disable_renderer_path_check,IPCClientFactoryInterface * ipc_client_factory_interface)146   void StartRenderer(const string &name,
147                      const string &renderer_path,
148                      bool disable_renderer_path_check,
149                      IPCClientFactoryInterface *ipc_client_factory_interface) {
150     start_renderer_called_ = true;
151     LOG(INFO) << name << " " << renderer_path;
152   }
153 
ForceTerminateRenderer(const string & name)154   bool ForceTerminateRenderer(const string &name) {
155     force_terminate_renderer_called_ = true;
156     return true;
157   }
158 
OnFatal(RendererErrorType type)159   void OnFatal(RendererErrorType type) {
160     LOG(ERROR) << static_cast<int>(type);
161   }
162 
163   // return true if the renderer is running
IsAvailable() const164   virtual bool IsAvailable() const {
165     return available_;
166   }
167 
168   // return true if client can make a IPC connection.
CanConnect() const169   virtual bool CanConnect() const {
170     return can_connect_;
171   }
172 
SetPendingCommand(const commands::RendererCommand & command)173   virtual void SetPendingCommand(
174       const commands::RendererCommand &command) {
175     set_pending_command_called_ = true;
176   }
177 
set_suppress_error_dialog(bool suppress)178   virtual void set_suppress_error_dialog(bool suppress) {
179   }
180 
Reset()181   void Reset() {
182     start_renderer_called_ = false;
183     force_terminate_renderer_called_ = false;
184     available_ = false;
185     can_connect_ = false;
186     set_pending_command_called_ = false;
187   }
188 
set_available(bool available)189   void set_available(bool available) {
190     available_ = available;
191   }
192 
set_can_connect(bool can_connect)193   void set_can_connect(bool can_connect) {
194     can_connect_ = can_connect;
195   }
196 
is_start_renderer_called() const197   bool is_start_renderer_called() const {
198     return start_renderer_called_;
199   }
200 
is_force_terminate_renderer_called() const201   bool is_force_terminate_renderer_called() const {
202     return force_terminate_renderer_called_;
203   }
204 
is_set_pending_command_called() const205   bool is_set_pending_command_called() const {
206     return set_pending_command_called_;
207   }
208 
209  private:
210   bool start_renderer_called_;
211   bool force_terminate_renderer_called_;
212   bool available_;
213   bool can_connect_;
214   bool set_pending_command_called_;
215 };
216 }  // namespace
217 
TEST(RendererClient,InvalidTest)218 TEST(RendererClient, InvalidTest) {
219   RendererClient client;
220 
221   client.SetIPCClientFactory(NULL);
222   client.SetRendererLauncherInterface(NULL);
223   commands::RendererCommand command;
224 
225   // IPCClientFactory and Launcher must be set.
226   EXPECT_FALSE(client.ExecCommand(command));
227   EXPECT_FALSE(client.IsAvailable());
228   EXPECT_FALSE(client.Activate());
229 }
230 
TEST(RendererClient,ActivateTest)231 TEST(RendererClient, ActivateTest) {
232   TestIPCClientFactory factory;
233   TestRendererLauncher launcher;
234 
235   RendererClient client;
236 
237   client.SetIPCClientFactory(&factory);
238   client.SetRendererLauncherInterface(&launcher);
239 
240   {
241     launcher.set_available(true);
242     EXPECT_TRUE(client.IsAvailable());
243     launcher.set_available(false);
244     EXPECT_FALSE(client.IsAvailable());
245   }
246 
247   {
248     // No connection may happen if can_connect is false
249     launcher.set_available(false);
250     launcher.set_can_connect(false);
251     TestIPCClient::Reset();
252     EXPECT_TRUE(client.Activate());
253     EXPECT_EQ(0, TestIPCClient::counter());
254   }
255 
256   {
257     // No connection may happen if connected return false
258     launcher.set_available(false);
259     launcher.set_can_connect(true);
260     TestIPCClient::set_connected(false);
261     TestIPCClient::Reset();
262     EXPECT_TRUE(client.Activate());
263     EXPECT_EQ(0, TestIPCClient::counter());
264   }
265 
266   {
267     // one IPC call happens
268     launcher.set_available(false);
269     launcher.set_can_connect(true);
270     TestIPCClient::set_connected(true);
271     TestIPCClient::Reset();
272     EXPECT_TRUE(client.Activate());
273     EXPECT_EQ(1, TestIPCClient::counter());
274   }
275 
276   {
277     // once launcher is available, no IPC call happens
278     // with Activate()
279     launcher.set_available(true);
280     TestIPCClient::Reset();
281     EXPECT_TRUE(client.Activate());
282     EXPECT_TRUE(client.Activate());
283     EXPECT_TRUE(client.Activate());
284     EXPECT_EQ(0, TestIPCClient::counter());
285   }
286 }
287 
TEST(RendererClient,LaunchTest)288 TEST(RendererClient, LaunchTest) {
289   TestIPCClientFactory factory;
290   TestRendererLauncher launcher;
291 
292   RendererClient client;
293 
294   client.SetIPCClientFactory(&factory);
295   client.SetRendererLauncherInterface(&launcher);
296 
297   commands::RendererCommand command;
298   command.mutable_output()->set_id(0);
299   command.set_type(commands::RendererCommand::NOOP);
300 
301   {
302     // if can connect is false,
303     // renderer is not launched
304     launcher.Reset();
305     launcher.set_can_connect(false);
306     TestIPCClient::set_connected(false);
307     EXPECT_TRUE(client.ExecCommand(command));
308     EXPECT_FALSE(launcher.is_start_renderer_called());
309   }
310 
311   {
312     // if connection is not available, start renderer process
313     launcher.Reset();
314     launcher.set_can_connect(true);
315     TestIPCClient::set_connected(false);
316     command.set_visible(true);
317     EXPECT_TRUE(client.ExecCommand(command));
318     EXPECT_TRUE(launcher.is_start_renderer_called());
319   }
320 
321   {
322     // if connection is not available,
323     // but the command type is HIDE, renderer is not launched
324     launcher.Reset();
325     launcher.set_can_connect(true);
326     TestIPCClient::set_connected(false);
327     command.set_visible(false);
328     command.set_type(commands::RendererCommand::UPDATE);
329     EXPECT_TRUE(client.ExecCommand(command));
330     EXPECT_FALSE(launcher.is_start_renderer_called());
331   }
332 
333   {
334     command.set_type(commands::RendererCommand::NOOP);
335     // if every state is OK, renderer is not launched
336     launcher.Reset();
337     launcher.set_can_connect(true);
338     TestIPCClient::set_connected(true);
339     command.set_visible(true);
340     EXPECT_TRUE(client.ExecCommand(command));
341     EXPECT_TRUE(client.ExecCommand(command));
342     EXPECT_TRUE(client.ExecCommand(command));
343     EXPECT_FALSE(launcher.is_start_renderer_called());
344   }
345 }
346 
TEST(RendererClient,ConnectionTest)347 TEST(RendererClient, ConnectionTest) {
348   TestIPCClientFactory factory;
349   TestRendererLauncher launcher;
350 
351   RendererClient client;
352 
353   client.SetIPCClientFactory(&factory);
354   client.SetRendererLauncherInterface(&launcher);
355 
356   commands::RendererCommand command;
357   command.set_type(commands::RendererCommand::NOOP);
358 
359   {
360     launcher.Reset();
361     launcher.set_can_connect(true);
362     TestIPCClient::set_connected(true);
363     TestIPCClient::Reset();
364     EXPECT_TRUE(client.ExecCommand(command));
365     EXPECT_TRUE(client.ExecCommand(command));
366     EXPECT_TRUE(client.ExecCommand(command));
367 
368     // IPC should be called three times
369     EXPECT_EQ(3, TestIPCClient::counter());
370   }
371 
372   {
373     // launcher denies connection
374     launcher.Reset();
375     launcher.set_can_connect(false);
376     TestIPCClient::set_connected(true);
377     TestIPCClient::Reset();
378     EXPECT_TRUE(client.ExecCommand(command));
379     EXPECT_TRUE(client.ExecCommand(command));
380     EXPECT_TRUE(client.ExecCommand(command));
381     EXPECT_EQ(0, TestIPCClient::counter());
382   }
383 
384   {
385     // IPC connection is lost.
386     launcher.Reset();
387     launcher.set_can_connect(true);
388     TestIPCClient::set_connected(false);
389     TestIPCClient::Reset();
390     EXPECT_TRUE(client.ExecCommand(command));
391     EXPECT_TRUE(client.ExecCommand(command));
392     EXPECT_TRUE(client.ExecCommand(command));
393     EXPECT_EQ(0, TestIPCClient::counter());
394   }
395 }
396 
TEST(RendererClient,ShutdownTest)397 TEST(RendererClient, ShutdownTest) {
398   TestIPCClientFactory factory;
399   TestRendererLauncher launcher;
400 
401   RendererClient client;
402 
403   client.SetIPCClientFactory(&factory);
404   client.SetRendererLauncherInterface(&launcher);
405 
406   {
407     launcher.Reset();
408     launcher.set_can_connect(true);
409     TestIPCClient::set_connected(true);
410     TestIPCClient::Reset();
411 
412     // Shutdown with commands::RendererCommand::SHUTDOWN command
413     EXPECT_TRUE(client.Shutdown(false));
414     EXPECT_FALSE(launcher.is_force_terminate_renderer_called());
415     EXPECT_EQ(1, TestIPCClient::counter());
416   }
417 
418   {
419     launcher.Reset();
420     launcher.set_can_connect(true);
421     TestIPCClient::set_connected(true);
422     TestIPCClient::Reset();
423 
424     // Shutdown with ForceTerminateRenderer
425     EXPECT_TRUE(client.Shutdown(true));
426     EXPECT_TRUE(launcher.is_force_terminate_renderer_called());
427     EXPECT_EQ(0, TestIPCClient::counter());
428   }
429 
430   {
431     launcher.Reset();
432     launcher.set_can_connect(false);
433     TestIPCClient::set_connected(false);
434     TestIPCClient::Reset();
435 
436     EXPECT_TRUE(client.Shutdown(false));
437     EXPECT_FALSE(launcher.is_force_terminate_renderer_called());
438     EXPECT_EQ(0, TestIPCClient::counter());
439   }
440 
441   {
442     launcher.Reset();
443     launcher.set_can_connect(false);
444     TestIPCClient::set_connected(false);
445     TestIPCClient::Reset();
446 
447     EXPECT_TRUE(client.Shutdown(true));
448     EXPECT_FALSE(launcher.is_force_terminate_renderer_called());
449     EXPECT_EQ(0, TestIPCClient::counter());
450   }
451 }
452 
TEST(RendererClient,ProtocolVersionMismatchNewer)453 TEST(RendererClient, ProtocolVersionMismatchNewer) {
454   TestIPCClientFactory factory;
455   TestRendererLauncher launcher;
456 
457   RendererClient client;
458 
459   client.SetIPCClientFactory(&factory);
460   client.SetRendererLauncherInterface(&launcher);
461 
462   commands::RendererCommand command;
463   command.set_type(commands::RendererCommand::NOOP);
464 
465   {
466     launcher.Reset();
467     launcher.set_can_connect(true);
468     TestIPCClient::set_connected(true);
469     TestIPCClient::Reset();
470     TestIPCClient::set_server_protocol_version(IPC_PROTOCOL_VERSION - 1);
471     EXPECT_TRUE(client.ExecCommand(command));
472     EXPECT_TRUE(launcher.is_force_terminate_renderer_called());
473     EXPECT_EQ(0, TestIPCClient::counter());
474   }
475 }
476 
TEST(RendererClient,ProtocolVersionMismatchOlder)477 TEST(RendererClient, ProtocolVersionMismatchOlder) {
478   TestIPCClientFactory factory;
479   TestRendererLauncher launcher;
480 
481   RendererClient client;
482 
483   client.SetIPCClientFactory(&factory);
484   client.SetRendererLauncherInterface(&launcher);
485 
486   commands::RendererCommand command;
487   command.set_type(commands::RendererCommand::NOOP);
488 
489   {
490     launcher.Reset();
491     launcher.set_can_connect(true);
492     TestIPCClient::set_connected(true);
493     TestIPCClient::Reset();
494     TestIPCClient::set_server_protocol_version(IPC_PROTOCOL_VERSION + 1);
495     EXPECT_TRUE(client.ExecCommand(command));
496     EXPECT_FALSE(launcher.is_force_terminate_renderer_called());
497     EXPECT_EQ(0, TestIPCClient::counter());
498   }
499 }
500 
TEST(RendererClient,MozcVersionMismatchNewer)501 TEST(RendererClient, MozcVersionMismatchNewer) {
502   TestIPCClientFactory factory;
503   TestRendererLauncher launcher;
504 
505   RendererClient client;
506 
507   client.SetIPCClientFactory(&factory);
508   client.SetRendererLauncherInterface(&launcher);
509 
510   commands::RendererCommand command;
511   command.set_type(commands::RendererCommand::NOOP);
512   g_server_product_version = UpdateVersion(-1);
513 
514   {
515     launcher.Reset();
516     launcher.set_can_connect(true);
517     TestIPCClient::set_connected(true);
518     TestIPCClient::Reset();
519     TestIPCClient::set_server_protocol_version(IPC_PROTOCOL_VERSION);
520     EXPECT_TRUE(client.ExecCommand(command));
521     EXPECT_FALSE(launcher.is_force_terminate_renderer_called());
522     EXPECT_EQ(1, TestIPCClient::counter());
523   }
524 }
525 
TEST(RendererClient,MozcVersionMismatchOlder)526 TEST(RendererClient, MozcVersionMismatchOlder) {
527   TestIPCClientFactory factory;
528   TestRendererLauncher launcher;
529 
530   RendererClient client;
531 
532   client.SetIPCClientFactory(&factory);
533   client.SetRendererLauncherInterface(&launcher);
534 
535   commands::RendererCommand command;
536   command.set_type(commands::RendererCommand::NOOP);
537   g_server_product_version = UpdateVersion(1);
538 
539   {
540     launcher.Reset();
541     launcher.set_can_connect(true);
542     TestIPCClient::set_connected(true);
543     TestIPCClient::Reset();
544     TestIPCClient::set_server_protocol_version(IPC_PROTOCOL_VERSION);
545     EXPECT_TRUE(client.ExecCommand(command));
546     EXPECT_FALSE(launcher.is_force_terminate_renderer_called());
547     EXPECT_EQ(1, TestIPCClient::counter());
548   }
549 }
550 
TEST(RendererClient,SetPendingCommandTest)551 TEST(RendererClient, SetPendingCommandTest) {
552   TestIPCClientFactory factory;
553   TestRendererLauncher launcher;
554 
555   RendererClient client;
556 
557   client.SetIPCClientFactory(&factory);
558   client.SetRendererLauncherInterface(&launcher);
559 
560   commands::RendererCommand command;
561   command.set_type(commands::RendererCommand::NOOP);
562 
563   {
564     launcher.Reset();
565     launcher.set_can_connect(true);
566     TestIPCClient::set_connected(false);
567     command.set_visible(true);
568     EXPECT_TRUE(client.ExecCommand(command));
569     EXPECT_TRUE(launcher.is_start_renderer_called());
570     EXPECT_TRUE(launcher.is_set_pending_command_called());
571   }
572 
573   {
574     launcher.Reset();
575     launcher.set_can_connect(false);
576     TestIPCClient::set_connected(false);
577     command.set_visible(true);
578     EXPECT_TRUE(client.ExecCommand(command));
579     EXPECT_TRUE(launcher.is_set_pending_command_called());
580   }
581 
582   {
583     launcher.Reset();
584     launcher.set_can_connect(true);
585     TestIPCClient::set_connected(true);
586     command.set_visible(true);
587     EXPECT_TRUE(client.ExecCommand(command));
588     EXPECT_FALSE(launcher.is_set_pending_command_called());
589   }
590 }
591 }  // namespace renderer
592 }  // namespace mozc
593