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 "ipc/ipc_path_manager.h"
31
32 #if defined(OS_ANDROID) || defined(OS_NACL)
33 #error "This platform is not supported."
34 #endif // OS_ANDROID || OS_NACL
35
36 #include <string>
37 #include <vector>
38
39 #include "base/port.h"
40 #include "base/file_stream.h"
41 #include "base/file_util.h"
42 #include "base/process_mutex.h"
43 #include "base/system_util.h"
44 #include "base/thread.h"
45 #include "base/util.h"
46 #include "base/version.h"
47 #include "ipc/ipc.h"
48 #include "ipc/ipc.pb.h"
49 #include "testing/base/public/gunit.h"
50
51 DECLARE_string(test_tmpdir);
52
53 namespace mozc {
54 namespace {
55
56 class CreateThread : public Thread {
57 public:
Run()58 virtual void Run() {
59 IPCPathManager *manager =
60 IPCPathManager::GetIPCPathManager("test");
61 EXPECT_TRUE(manager->CreateNewPathName());
62 EXPECT_TRUE(manager->SavePathName());
63 EXPECT_TRUE(manager->GetPathName(&path_));
64 EXPECT_GT(manager->GetServerProtocolVersion(), 0);
65 EXPECT_FALSE(manager->GetServerProductVersion().empty());
66 EXPECT_GT(manager->GetServerProcessId(), 0);
67 }
68
path() const69 const string &path() const {
70 return path_;
71 }
72
73 private:
74 string path_;
75 };
76
77 class BatchGetPathNameThread : public Thread {
78 public:
Run()79 virtual void Run() {
80 for (int i = 0; i < 100; ++i) {
81 IPCPathManager *manager =
82 IPCPathManager::GetIPCPathManager("test2");
83 string path;
84 EXPECT_TRUE(manager->CreateNewPathName());
85 EXPECT_TRUE(manager->GetPathName(&path));
86 }
87 }
88 };
89 } // namespace
90
91 class IPCPathManagerTest : public ::testing::Test {
92 protected:
SetUp()93 virtual void SetUp() {
94 SystemUtil::SetUserProfileDirectory(FLAGS_test_tmpdir);
95 }
96 };
97
TEST_F(IPCPathManagerTest,IPCPathManagerTest)98 TEST_F(IPCPathManagerTest, IPCPathManagerTest) {
99 CreateThread t;
100 t.Start("IPCPathManagerTest");
101 Util::Sleep(1000);
102 IPCPathManager *manager =
103 IPCPathManager::GetIPCPathManager("test");
104 EXPECT_TRUE(manager->CreateNewPathName());
105 EXPECT_TRUE(manager->SavePathName());
106 string path;
107 EXPECT_TRUE(manager->GetPathName(&path));
108 EXPECT_GT(manager->GetServerProtocolVersion(), 0);
109 EXPECT_FALSE(manager->GetServerProductVersion().empty());
110 EXPECT_GT(manager->GetServerProcessId(), 0);
111 EXPECT_EQ(t.path(), path);
112 #ifdef OS_LINUX
113 // On Linux, |path| should be abstract (see man unix(7) for details.)
114 ASSERT_FALSE(path.empty());
115 EXPECT_EQ('\0', path[0]);
116 #endif
117 }
118
119 // Test the thread-safeness of GetPathName() and
120 // GetIPCPathManager
TEST_F(IPCPathManagerTest,IPCPathManagerBatchTest)121 TEST_F(IPCPathManagerTest, IPCPathManagerBatchTest) {
122 // mozc::Thread is not designed as value-semantics.
123 // So here we use pointers to maintain these instances.
124 std::vector<BatchGetPathNameThread *> threads(64);
125 for (size_t i = 0; i < threads.size(); ++i) {
126 threads[i] = new BatchGetPathNameThread;
127 threads[i]->Start("IPCPathManagerBatchTest");
128 }
129 for (size_t i = 0; i < threads.size(); ++i) {
130 threads[i]->Join();
131 delete threads[i];
132 threads[i] = NULL;
133 }
134 }
135
TEST_F(IPCPathManagerTest,ReloadTest)136 TEST_F(IPCPathManagerTest, ReloadTest) {
137 // We have only mock implementations for Windows, so no test should be run.
138 #ifndef OS_WIN
139 IPCPathManager *manager =
140 IPCPathManager::GetIPCPathManager("reload_test");
141
142 EXPECT_TRUE(manager->CreateNewPathName());
143 EXPECT_TRUE(manager->SavePathName());
144
145 // Just after the save, there are no need to reload.
146 EXPECT_FALSE(manager->ShouldReload());
147
148 // Modify the saved file explicitly.
149 EXPECT_TRUE(manager->path_mutex_->UnLock());
150 Util::Sleep(1000); // msec
151 string filename = FileUtil::JoinPath(
152 SystemUtil::GetUserProfileDirectory(), ".reload_test.ipc");
153 OutputFileStream outf(filename.c_str());
154 outf << "foobar";
155 outf.close();
156
157 EXPECT_TRUE(manager->ShouldReload());
158 #endif // OS_WIN
159 }
160
TEST_F(IPCPathManagerTest,PathNameTest)161 TEST_F(IPCPathManagerTest, PathNameTest) {
162 IPCPathManager *manager =
163 IPCPathManager::GetIPCPathManager("path_name_test");
164
165 EXPECT_TRUE(manager->CreateNewPathName());
166 EXPECT_TRUE(manager->SavePathName());
167 const ipc::IPCPathInfo original_path = *(manager->ipc_path_info_);
168 EXPECT_EQ(IPC_PROTOCOL_VERSION, original_path.protocol_version());
169 // Checks that versions are same.
170 EXPECT_EQ(Version::GetMozcVersion(), original_path.product_version());
171 EXPECT_TRUE(original_path.has_key());
172 EXPECT_TRUE(original_path.has_process_id());
173 EXPECT_TRUE(original_path.has_thread_id());
174
175 manager->ipc_path_info_->Clear();
176 EXPECT_TRUE(manager->LoadPathName());
177
178 const ipc::IPCPathInfo loaded_path = *(manager->ipc_path_info_);
179 EXPECT_EQ(original_path.protocol_version(), loaded_path.protocol_version());
180 EXPECT_EQ(original_path.product_version(), loaded_path.product_version());
181 EXPECT_EQ(original_path.key(), loaded_path.key());
182 EXPECT_EQ(original_path.process_id(), loaded_path.process_id());
183 EXPECT_EQ(original_path.thread_id(), loaded_path.thread_id());
184 }
185 } // namespace mozc
186