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