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 <cstring>
31 #include <iostream>  // NOLINT
32 #include <string>
33 #include <vector>
34 
35 #include "base/flags.h"
36 #include "base/init_mozc.h"
37 #include "base/logging.h"
38 #include "base/port.h"
39 #include "base/thread.h"
40 #include "ipc/ipc.h"
41 
42 DEFINE_string(server_address, "ipc_test", "");
43 DEFINE_bool(test, false, "automatic test mode");
44 DEFINE_bool(server, false, "invoke as server mode");
45 DEFINE_bool(client, false, "invoke as client mode");
46 DEFINE_string(server_path, "", "server path");
47 DEFINE_int32(num_threads, 10, "number of threads");
48 DEFINE_int32(num_requests, 100, "number of requests");
49 
50 namespace mozc {
51 
52 class MultiConnections: public Thread {
53  public:
Run()54   void Run() {
55     char buf[8192];
56     for (int i = 0; i < FLAGS_num_requests; ++i) {
57       mozc::IPCClient con(FLAGS_server_address, FLAGS_server_path);
58       CHECK(con.Connected());
59       string input = "testtesttesttest";
60       size_t length = sizeof(buf);
61       ::memset(buf, 0, length);
62       CHECK(con.Call(input.data(), input.size(), buf, &length, 1000));
63       string output(buf, length);
64       CHECK_EQ(input.size(), output.size());
65       CHECK_EQ(input, output);
66     }
67   }
68 };
69 
70 class EchoServer: public IPCServer {
71  public:
EchoServer(const string & path,int32 num_connections,int32 timeout)72   EchoServer(const string &path,
73              int32 num_connections,
74              int32 timeout) :
75       IPCServer(path, num_connections, timeout) {}
Process(const char * input_buffer,size_t input_length,char * output_buffer,size_t * output_length)76   virtual bool Process(const char *input_buffer,
77                        size_t input_length,
78                        char *output_buffer,
79                        size_t *output_length) {
80     ::memcpy(output_buffer, input_buffer, input_length);
81     *output_length = input_length;
82     return ::memcmp("kill", input_buffer, 4) != 0;
83   }
84 };
85 
86 class EchoServerThread: public Thread {
87  public:
EchoServerThread(EchoServer * con)88   explicit EchoServerThread(EchoServer *con): con_(con) {}
Run()89   virtual void Run() {
90     con_->Loop();
91   }
92  private:
93   EchoServer *con_;
94 };
95 
96 }  // namespace mozc
97 
main(int argc,char ** argv)98 int main(int argc, char **argv) {
99   mozc::InitMozc(argv[0], &argc, &argv, false);
100 
101   if (FLAGS_test) {
102     mozc::EchoServer con(FLAGS_server_address, 10, 1000);
103     mozc::EchoServerThread server_thread_main(&con);
104     server_thread_main.SetJoinable(true);
105     server_thread_main.Start("IpcMain");
106 
107     std::vector<mozc::MultiConnections> cons(FLAGS_num_threads);
108     for (size_t i = 0; i < cons.size(); ++i) {
109       cons[i].SetJoinable(true);
110       cons[i].Start("MultiConnections");
111     }
112     for (size_t i = 0; i < cons.size(); ++i) {
113       cons[i].Join();
114     }
115 
116     mozc::IPCClient kill(FLAGS_server_address, FLAGS_server_path);
117     const char kill_cmd[32] = "kill";
118     char output[32];
119     size_t output_size = sizeof(output);
120     kill.Call(kill_cmd, strlen(kill_cmd),
121               output, &output_size, 1000);
122               server_thread_main.Join();
123 
124     LOG(INFO) << "Done";
125 
126   } else if (FLAGS_server) {
127     mozc::EchoServer con(FLAGS_server_address,
128                          10, -1);
129     CHECK(con.Connected());
130     LOG(INFO) << "Start Server at " << FLAGS_server_address;
131     con.Loop();
132   } else if (FLAGS_client) {
133     string line;
134     char response[8192];
135     while (getline(cin, line)) {
136       mozc::IPCClient con(FLAGS_server_address, FLAGS_server_path);
137       CHECK(con.Connected());
138       size_t response_size = sizeof(response);
139       CHECK(con.Call(line.data(), line.size(),
140                      response, &response_size, 1000));
141       cout << "Request: " << line << endl;
142       cout << "Response: " << string(response, response_size) << endl;
143     }
144   } else {
145     LOG(INFO) << "either --server or --client or --test must be set true";
146   }
147 
148   return 0;
149 }
150