Codebase list mozc / ba7cbec
Update from the upstream. (BUILD=4219) * Fixed some incompatibility issues of Bazel build. * Fixed potential issues of the thread handling. * Removed no longer used code around GenericStorageManager. * Code refactoring. Hiroyuki Komatsu 3 years ago
34 changed file(s) with 167 addition(s) and 873 deletion(s). Raw diff Collapse all Expand all
99 build --objccopt "-fsigned-char"
1010
1111 # Linux
12 build:linux --define TARGET=oss_linux
13 build:oss_linux --define TARGET=oss_linux
12 build:linux --define TARGET=oss_linux --copt "-fPIC"
13 build:oss_linux --define TARGET=oss_linux --copt "-fPIC"
1414
1515 # Android
1616 build:android --define TARGET=oss_android \
11081108 "version_def_template.h",
11091109 ],
11101110 outs = ["version_def.h"],
1111 cmd = "$(location //build_tools:replace_version) --version_file=$(location mozc_version.txt) --input=$(location version_def_template.h) --output=$(OUTS) --branding=GoogleJapaneseInput",
1111 cmd = ("$(location //build_tools:replace_version)" +
1112 " --version_file=$(location mozc_version.txt) " +
1113 " --input=$(location version_def_template.h) --output=$(OUTS)" +
1114 " --branding=Mozc"),
11121115 exec_tools = ["//build_tools:replace_version"],
11131116 visibility = ["//visibility:private"],
11141117 )
169169 return build_override
170170
171171 if not build_changelist_file:
172 return '0'
172 return None
173173
174174 with open(build_changelist_file, 'r') as cl_file:
175175 for line in cl_file:
176176 if line.startswith('BUILD_CHANGELIST'):
177177 return line.rstrip().split(' ')[1]
178178
179 return '0'
179 return None
180180
181181
182182 def GenerateVersionFileFromTemplate(template_path,
109109 ":client_interface",
110110 "//base",
111111 "//base:logging",
112 "//base:mutex",
112113 "//protocol:commands_proto",
113114 ],
114115 )
3737 // boilerplates for those methods.
3838 #define MockConstBoolImplementation(method_name, argument) \
3939 bool ClientMock::method_name(argument) const { \
40 scoped_lock l(&mutex_); \
4041 function_counter_[#method_name]++; \
4142 std::map<std::string, bool>::const_iterator it = \
4243 return_bool_values_.find(#method_name); \
4748 }
4849 #define MockBoolImplementation(method_name, argument) \
4950 bool ClientMock::method_name(argument) { \
51 scoped_lock l(&mutex_); \
5052 function_counter_[#method_name]++; \
5153 std::map<std::string, bool>::const_iterator it = \
5254 return_bool_values_.find(#method_name); \
5759 }
5860 #define MockVoidImplementation(method_name, argument) \
5961 void ClientMock::method_name(argument) { \
62 scoped_lock l(&mutex_); \
6063 function_counter_[#method_name]++; \
6164 return; \
6265 }
99102 bool ClientMock::method_name(argtype argument, \
100103 const commands::Context &context, \
101104 commands::Output *output) { \
105 scoped_lock l(&mutex_); \
102106 function_counter_[#method_name]++; \
103107 called_##method_name##_.CopyFrom(argument); \
104108 std::map<std::string, commands::Output>::const_iterator it = \
126130 // Exceptional methods.
127131 // GetConfig needs to obtain the "called_config_".
128132 bool ClientMock::GetConfig(config::Config *config) {
133 scoped_lock l(&mutex_);
129134 function_counter_["GetConfig"]++;
130135 config->CopyFrom(called_config_);
131136 std::map<std::string, bool>::const_iterator it =
138143
139144 // SetConfig needs to set the "called_config_".
140145 bool ClientMock::SetConfig(const config::Config &config) {
146 scoped_lock l(&mutex_);
141147 function_counter_["SetConfig"]++;
142148 called_config_.CopyFrom(config);
143149 std::map<std::string, bool>::const_iterator it =
151157 // LaunchTool arguments are quite different from other methods.
152158 bool ClientMock::LaunchTool(const std::string &mode,
153159 const std::string &extra_arg) {
160 scoped_lock l(&mutex_);
154161 function_counter_["LaunchTool"]++;
155162 return return_bool_values_["LaunchTool"];
156163 }
158165 // Other methods to deal with internal data such like operations over
159166 // function counters or setting the expected return values.
160167 void ClientMock::ClearFunctionCounter() {
168 scoped_lock l(&mutex_);
161169 for (std::map<std::string, int>::iterator it = function_counter_.begin();
162170 it != function_counter_.end(); it++) {
163171 it->second = 0;
165173 }
166174
167175 void ClientMock::SetBoolFunctionReturn(std::string func_name, bool value) {
176 scoped_lock l(&mutex_);
168177 return_bool_values_[func_name] = value;
169178 }
170179
171180 int ClientMock::GetFunctionCallCount(std::string key) {
181 scoped_lock l(&mutex_);
172182 return function_counter_[key];
173183 }
174184
3131
3232 #include <map>
3333 #include <string>
34 #include "base/mutex.h"
3435 #include "client/client_interface.h"
3536 #include "protocol/commands.pb.h"
3637
106107 std::map<std::string, commands::Output> outputs_;
107108
108109 config::Config called_config_;
110
111 // ClientMock is called from a thread in SessionWatchDog, and
112 // SessionWatchDogTest. So a mutex lock is required.
113 mutable Mutex mutex_;
109114 };
110115 } // namespace client
111116 } // namespace mozc
317317 SendCommand_UndoOrRewind
318318 SendCommand_StopKeyToggling
319319 SendCommand_ExpandSuggestion
320 SendCommand_ObsoleteSendCaretLocation
321 SendCommand_ObsoleteSendLanguageBarCommand
322 SendCommand_ObsoleteGetAsyncResult
323320 SendCommand_CommitRawText
324321 SendCommand_ConvertPrevPage
325322 SendCommand_ConvertNextPage
3232 MINOR = 26
3333
3434 # Number to be increased. This value may be replaced by other tools.
35 BUILD = 4213
35 BUILD = 4219
3636
3737 # Represent the platform and release channel.
3838 REVISION = 100
9696 '<(PRODUCT_DIR)/libengine_builder.a',
9797 '<(PRODUCT_DIR)/libengine_builder_proto.a',
9898 '<(PRODUCT_DIR)/libflags.a',
99 '<(PRODUCT_DIR)/libgeneric_storage_manager.a',
10099 '<(PRODUCT_DIR)/libgoogle_data_manager.a',
101100 '<(PRODUCT_DIR)/libhash.a',
102101 '<(PRODUCT_DIR)/libimmutable_converter.a',
256256 )
257257
258258 ## Commented out on 2011-03-09, because no other rule depends on it.
259 ## cc_binary_mozc(name = "process_watch_dog_main",
260 ## srcs = ["process_watch_dog_main.cc",],
261 ## deps = [":process_watch_dog",
262 ## "//base:base",])
259 # cc_binary_mozc(
260 # name = "process_watch_dog_main",
261 # srcs = ["process_watch_dog_main.cc"],
262 # deps = [
263 # ":process_watch_dog",
264 # "//base",
265 # "//base:flags",
266 # "//base:init_mozc",
267 # "//base:logging",
268 # "//base:number_util",
269 # "//base:port",
270 # "//base:util",
271 # ],
272 # )
263273
264274 cc_test_mozc(
265275 name = "process_watch_dog_test",
5555 LOG(ERROR) << "::CreateEvent() failed.";
5656 return;
5757 }
58 Thread::Start("WatchDog"); // start
5958 }
6059
6160 ProcessWatchDog::~ProcessWatchDog() {
62 is_finished_ = true; // set the flag to terminate the thread
61 StopWatchDog();
62 }
63
64 void ProcessWatchDog::StartWatchDog() {
65 Thread::Start("WatchDog");
66 }
67
68 void ProcessWatchDog::StopWatchDog() {
69 {
70 scoped_lock l(mutex_.get());
71 is_finished_ = true; // set the flag to terminate the thread
72 }
6373
6474 if (event_.get() != nullptr) {
6575 ::SetEvent(event_.get()); // wake up WaitForMultipleObjects
6676 }
6777
68 Join(); // wait for the thread
78 Join();
6979 }
7080
7181 bool ProcessWatchDog::SetID(ProcessID process_id, ThreadID thread_id,
8191 return true;
8292 }
8393
84 // rewrite the valeus
94 // rewrite the values
8595 {
8696 scoped_lock l(mutex_.get());
8797 process_id_ = process_id;
96106 }
97107
98108 void ProcessWatchDog::Run() {
99 while (!is_finished_) {
109 while (true) {
110 {
111 scoped_lock l(mutex_.get());
112 if (is_finished_) {
113 break;
114 }
115 }
116
100117 ScopedHandle process_handle;
101118 ScopedHandle thread_handle;
102119 int timeout = -1;
218235 : process_id_(UnknownProcessID),
219236 thread_id_(UnknownProcessID),
220237 is_finished_(false),
221 mutex_(new Mutex) {
238 mutex_(new Mutex) {}
239
240 ProcessWatchDog::~ProcessWatchDog() {
241 // StopWatchDog() should be called before the deconstructor.
242 // This call is a fallback.
243 StopWatchDog();
244 }
245
246 void ProcessWatchDog::StartWatchDog() {
222247 Thread::Start("WatchDog");
223248 }
224249
225 ProcessWatchDog::~ProcessWatchDog() {
226 is_finished_ = true;
250 void ProcessWatchDog::StopWatchDog() {
251 {
252 scoped_lock l(mutex_.get());
253 is_finished_ = true; // set the flag to terminate the thread
254 }
227255 Join();
228256 }
229257
266294 // reuse same process id in 250ms or write to is_finished_ stays
267295 // forever in another CPU's local cache.
268296 // TODO(team): use kqueue with EVFILT_PROC/NOTE_EXIT for Mac.
269 while (!is_finished_) {
297 while (true) {
298 {
299 scoped_lock l(mutex_.get());
300 if (is_finished_) {
301 break;
302 }
303 }
304
270305 Util::Sleep(250);
271 if (process_id_ == UnknownProcessID) {
272 continue;
306 {
307 scoped_lock l(mutex_.get());
308 if (process_id_ == UnknownProcessID) {
309 continue;
310 }
273311 }
274312 if (::kill(process_id_, 0) != 0) {
275313 if (errno == EPERM) {
6161 PROCESS_SIGNALED = 1, // process is signaled,
6262 PROCESS_NOT_FOUND_SIGNALED = 3, // process id was not found
6363 PROCESS_ACCESS_DENIED_SIGNALED = 4, // operation was not allowed
64 PROCESS_ERROR_SIGNALED = 5, // unkown error in getting process info
64 PROCESS_ERROR_SIGNALED = 5, // unknown error in getting process info
6565 THREAD_SIGNALED = 6, // thread is signaled
6666 THREAD_NOT_FOUND_SIGNALED = 7, // thread id was not found
6767 THREAD_ACCESS_DENIED_SIGNALED = 8, // operation was not allowed
68 THREAD_ERROR_SIGNALED = 9, // unkown error in getting thread info
68 THREAD_ERROR_SIGNALED = 9, // unknown error in getting thread info
6969 TIMEOUT_SIGNALED = 10, // timeout is signaled
7070 };
7171
102102
103103 ProcessWatchDog();
104104 virtual ~ProcessWatchDog();
105 void StartWatchDog();
106 void StopWatchDog();
105107
106108 private:
107109 #ifdef OS_WIN
3333 #include "base/flags.h"
3434 #include "base/init_mozc.h"
3535 #include "base/logging.h"
36 #include "base/number_util.h"
3637 #include "base/port.h"
3738 #include "base/util.h"
3839 #include "ipc/process_watch_dog.h"
5253 mozc::InitMozc(argv[0], &argc, &argv);
5354
5455 mozc::TestProcessWatchDog dog;
56 dog.StartWatchDog();
5557
5658 string line;
5759 std::vector<string> fields;
5860
59 while (getline(cin, line)) {
61 while (std::getline(std::cin, line)) {
6062 fields.clear();
6163 mozc::Util::SplitStringUsing(line, "\t ", &fields);
6264 if (line == "exit") {
6769 continue;
6870 }
6971
70 const int32 process_id = atoi32(fields[0].c_str());
71 const int32 thread_id = atoi32(fields[1].c_str());
72 const int32 process_id = mozc::NumberUtil::SimpleAtoi(fields[0]);
73 const int32 thread_id = mozc::NumberUtil::SimpleAtoi(fields[1]);
7274
7375 if (!dog.SetID(static_cast<mozc::ProcessWatchDog::ProcessID>(process_id),
7476 static_cast<mozc::ProcessWatchDog::ThreadID>(thread_id),
6060 exit(0);
6161 } else if (pid > 0) {
6262 TestProcessWatchDog dog;
63 dog.StartWatchDog();
6364 dog.SetID(static_cast<ProcessWatchDog::ProcessID>(pid),
6465 ProcessWatchDog::UnknownThreadID, -1);
6566 Util::Sleep(4000);
67 dog.StopWatchDog();
6668 } else {
6769 LOG(ERROR) << "cannot execute fork";
6870 }
211211 }
212212 optional Direction direction = 14 [default = VERTICAL];
213213
214 reserved 15; // Deprecated composition_rectangle
215 reserved 16; // Deprecated caret_rectangle
216 reserved 17; // Deprecated window_location
214 reserved 15;
215 reserved "composition_rectangle";
216 reserved 16;
217 reserved "caret_rectangle";
218 reserved 17;
219 reserved "window_location";
217220
218221 // The number of candidates per page.
219222 optional uint32 page_size = 18 [default = 9];
409409 EXPAND_SUGGESTION = 15;
410410
411411 // Obsolete command. Used only in old IBus client.
412 OBSOLETE_SEND_CARET_LOCATION = 16;
412 reserved 16;
413 reserved "SEND_CARET_LOCATION";
413414
414415 // Obsolete command. Don't simply remove this command for NUM_OF_COMMANDS.
415416 // TODO(team): Replace this command by useful one.
416 OBSOLETE_SEND_LANGUAGE_BAR_COMMAND = 17;
417 reserved 17;
418 reserved "SEND_LANGUAGE_BAR_COMMAND";
417419
418420 // Obsolete command. Don't simply remove this command for NUM_OF_COMMANDS.
419421 // TODO(team): Replace this command by useful one.
420 OBSOLETE_GET_ASYNC_RESULT = 18;
422 reserved 18;
423 reserved "GET_ASYNC_RESULT";
421424
422425 // Commit the raw text of the composed string.
423426 COMMIT_RAW_TEXT = 19;
657660 NOTOUCH_TO_HALFWIDTHASCII = 41;
658661
659662 // Obsolete items.
660 OBSOLETE_TWELVE_KEYS_TO_NUMBER = 12;
661 OBSOLETE_FLICK_TO_NUMBER = 15;
662 OBSOLETE_GODAN_TO_NUMBER = 32;
663 OBSOLETE_QWERTY_MOBILE_TO_HIRAGANA_NUMBER = 21;
664 OBSOLETE_TOGGLE_FLICK_TO_NUMBER = 18;
663 reserved 12, 15, 32, 21, 18;
664 reserved "TWELVE_KEYS_TO_NUMBER";
665 reserved "GODAN_TO_NUMBER";
666 reserved "QWERTY_MOBILE_TO_HIRAGANA_NUMBER";
665667 }
666668
667669 // Use special Romanji table.
897899 NO_OPERATION = 14;
898900
899901 // Sync feature is deprecated since 1.13 dev.
900 // TODO(mozc-team): Remove following variables.
901 OBSOLETE_START_CLOUD_SYNC = 18;
902 OBSOLETE_GET_CLOUD_SYNC_STATUS = 23;
903 OBSOLETE_ADD_AUTH_CODE = 24;
904
905 INSERT_TO_STORAGE = 20;
906 READ_ALL_FROM_STORAGE = 21;
907 CLEAR_STORAGE = 25;
902 reserved 18, 23, 24;
903 reserved "START_CLOUD_SYNC";
904 reserved "GET_CLOUD_SYNC_STATUS";
905 reserved "ADD_AUTH_CODE";
906
907 reserved 20, 21, 25;
908 reserved "INSERT_TO_STORAGE";
909 reserved "READ_ALL_FROM_STORAGE";
910 reserved "CLEAR_STORAGE";
908911
909912 // Send a command for user dictionary session.
910913 SEND_USER_DICTIONARY_COMMAND = 26;
7676 // set verbose level of logging library (FLAGS_v)
7777 optional int32 verbose_level = 10 [default = 0];
7878
79 reserved 11; // Deprecated log_all_commands
79 reserved 11;
80 reserved "log_all_commands";
8081
8182 //////////////////////////////////////////////////////////////
8283 //
8788 // Disable all mutable operation if incognito_mode is true
8889 optional bool incognito_mode = 20 [default = false];
8990
90 reserved 21; // Deprecated upload_usage_stats
91 reserved 21;
92 reserved "upload_usage_stats";
9193
9294 // whether to show the set default dialog on startup
9395 optional bool check_default = 22 [default = true];
300302
301303 message InformationListConfig {
302304 optional bool use_local_usage_dictionary = 1 [default = true];
303 reserved 2; // Deprecated use_web_usage_dictionary
304 reserved 10; // Deprecated web_service_entries
305 reserved 2;
306 reserved "use_web_usage_dictionary";
307 reserved 10;
308 reserved "web_service_entries";
305309 }
306310 optional InformationListConfig information_list_config = 90;
307311
333337 // Cloud (300-319)
334338 //
335339 // Configuration for cloud sync feature. This field is obsolete.
336 reserved 300; // Deprecated sync_config
337 reserved 301; // Deprecated allow_cloud_handwriting
338 reserved 996; // Deprecated pinyin_config
339 reserved 998; // Deprecated hangul_config
340 reserved 999; // Deprecated chewing_config
340 reserved 300;
341 reserved "sync_config";
342 reserved 301;
343 reserved "allow_cloud_handwriting";
344 reserved 996;
345 reserved "pinyin_config";
346 reserved 998;
347 reserved "hangul_config";
348 reserved 999;
349 reserved "chewing_config";
341350 }
8989 // An equivalent to COMPOSITIONFORM in IMM32. (For Windows only)
9090 // TODO(yukawa): make a common composition form format for all platforms.
9191 message CompositionForm {
92 reserved 1; // Deprecated style
92 reserved 1;
93 reserved "style";
9394 optional Point current_position = 2;
9495 optional Rectangle area = 3;
9596 // Used as bit flags in |style_bits|.
106107 // An equivalent to CANDIDATEFORM in IMM32. (For Windows only)
107108 // TODO(yukawa): make a common candidate form format for all platforms.
108109 message CandidateForm {
109 reserved 1; // Deprecated style
110 reserved 1;
111 reserved "style";
110112 optional Point current_position = 2;
111113 optional Rectangle area = 3;
112114 // Used as bit flags in |style_bits|.
202204 // Represents caret information.
203205 optional CaretInfo caret_info = 11;
204206
205 reserved 12; // Deprecated message_sender_type
207 reserved 12;
208 reserved "message_sender_type";
206209
207210 // A string representation of PangoFontDescription
208211 // http://developer.gnome.org/pango/stable/pango-Fonts.html#pango-font-description-from-string
4343 // whether session is just after commitment
4444 optional bool committed = 3 [default = false];
4545
46 reserved 4; // Deprecated selected_indices
47
48 reserved 5; // Deprecated mode
46 reserved 4;
47 reserved "selected_indices";
48 reserved 5;
49 reserved "mode";
4950
5051 optional uint64 start_preedit_time = 10 [jstype = JS_STRING];
5152 optional uint64 start_conversion_window_time = 11 [jstype = JS_STRING];
5960 // last candidates state
6061 optional mozc.commands.Candidates candidates = 21;
6162
62 reserved 22; // Deprecated all_candidate_words
63 reserved 22;
64 reserved "all_candidate_words";
6365
6466 // last candidates result
6567 optional mozc.commands.Result result = 23;
203203 GET_ENTRY_SIZE = 10;
204204
205205 // Use GET_ENTRIES instead.
206 OBSOLETE_GET_ENTRY = 11;
206 reserved 11;
207 reserved "OBSOLETE_GET_ENTRY";
207208
208209 // Returns if it is possible to add new dictionary or not.
209210 // The result is returned by using status code.
107107 "//ipc:process_watch_dog",
108108 "//protocol:config_proto",
109109 "//protocol:renderer_proto",
110 "@com_google_absl//absl/memory",
110111 ],
111112 )
112113
4848 #include "protocol/config.pb.h"
4949 #include "protocol/renderer_command.pb.h"
5050 #include "renderer/renderer_interface.h"
51 #include "absl/memory/memory.h"
5152
5253 // By default, mozc_renderer quits when user-input continues to be
5354 // idle for 10min.
168169 : IPCServer(GetServiceName(), kNumConnections, kIPCServerTimeOut),
169170 timeout_(0),
170171 renderer_interface_(nullptr),
171 ALLOW_THIS_IN_INITIALIZER_LIST(
172 watch_dog_(new ParentApplicationWatchDog(this))),
173172 send_command_(new RendererServerSendCommand) {
173 watch_dog_ = absl::make_unique<ParentApplicationWatchDog>(this);
174 watch_dog_->StartWatchDog();
174175 if (FLAGS_restricted) {
175176 FLAGS_timeout =
176177 std::min(FLAGS_timeout, 60); // set 60sec with restricted mode
186187 #endif // MOZC_NO_LOGGING
187188 }
188189
189 RendererServer::~RendererServer() {}
190 RendererServer::~RendererServer() {
191 watch_dog_->StopWatchDog();
192 }
190193
191194 void RendererServer::SetRendererInterface(
192195 RendererInterface *renderer_interface) {
223226 // different threads, we have to use heap to share the serialized message.
224227 // If we use stack, this program will be crashed.
225228 //
226 // The reciver of command_str takes the ownership of this string.
229 // The receiver of command_str takes the ownership of this string.
227230 std::string *command_str = new std::string(request, request_size);
228231
229232 // no need to set the result code.
5050 test_suite(
5151 name = "android_test",
5252 tests = [
53 ":generic_storage_manager_test_android",
5453 ":ime_switch_util_test_android",
5554 ":key_info_util_test_android",
5655 ":output_util_test_android",
316315 "//base:process",
317316 ],
318317 ) + [
319 ":generic_storage_manager",
320318 ":session",
321319 ":session_handler_interface",
322320 ":session_observer_handler",
394392 ],
395393 requires_full_emulation = False,
396394 deps = [
397 ":generic_storage_manager",
398395 ":session_handler",
399396 ":session_handler_test_util",
400397 "//base",
771768 )
772769
773770 cc_library_mozc(
774 name = "generic_storage_manager",
775 srcs = ["generic_storage_manager.cc"],
776 hdrs = ["generic_storage_manager.h"],
777 deps = [
778 "//base",
779 "//base:config_file_stream",
780 "//base:logging",
781 "//base:mutex",
782 "//base:port",
783 "//base:singleton",
784 "//protocol:commands_proto",
785 "//storage:lru_storage",
786 ],
787 )
788
789 cc_library_mozc(
790771 name = "session_handler_interface",
791772 hdrs = ["session_handler_interface.h"],
792773 visibility = [
817798 visibility = ["//visibility:private"],
818799 deps = ["//base:port"],
819800 )
820
821 cc_test_mozc(
822 name = "generic_storage_manager_test",
823 size = "small",
824 srcs = ["generic_storage_manager_test.cc"],
825 requires_full_emulation = False,
826 deps = [
827 ":generic_storage_manager",
828 "//base:file_util",
829 "//base:util",
830 "//testing:gunit_main",
831 ],
832 )
+0
-212
src/session/generic_storage_manager.cc less more
0 // Copyright 2010-2020, Google Inc.
1 // All rights reserved.
2 //
3 // Redistribution and use in source and binary forms, with or without
4 // modification, are permitted provided that the following conditions are
5 // met:
6 //
7 // * Redistributions of source code must retain the above copyright
8 // notice, this list of conditions and the following disclaimer.
9 // * Redistributions in binary form must reproduce the above
10 // copyright notice, this list of conditions and the following disclaimer
11 // in the documentation and/or other materials provided with the
12 // distribution.
13 // * Neither the name of Google Inc. nor the names of its
14 // contributors may be used to endorse or promote products derived from
15 // this software without specific prior written permission.
16 //
17 // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
18 // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
19 // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
20 // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
21 // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
22 // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
23 // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
24 // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
25 // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
26 // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
27 // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
28
29 #include "session/generic_storage_manager.h"
30
31 #include <cstring>
32 #include <memory>
33 #include <string>
34 #include <vector>
35
36 #include "base/config_file_stream.h"
37 #include "base/logging.h"
38 #include "base/mutex.h"
39 #include "base/port.h"
40 #include "base/singleton.h"
41 #include "storage/lru_storage.h"
42
43 namespace {
44
45 mozc::Mutex g_storage_ensure_mutex;
46
47 mozc::GenericStorageManagerInterface *g_storage_manager = nullptr;
48
49 const char kSymbolStorageFileName[] = "user://symbol_history.db";
50 // 32 characters * 3 bytes(typical byte size per character)
51 const size_t kSymbolValueSize = 32 * 3;
52 const size_t kSymbolSize = 100;
53 const uint32 kSymbolSeed = 336843897;
54
55 const char kEmoticonStorageFileName[] = "user://emoticon_history.db";
56 // 64 characters * 3 bytes(typical byte size per character)
57 const size_t kEmoticonValueSize = 64 * 3;
58 const size_t kEmoticonSize = 100;
59 const uint32 kEmoticonSeed = 236843897;
60
61 const char kEmojiStorageFileName[] = "user://emoji_history.db";
62 // 32 characters * 3 bytes(typical byte size per character)
63 const size_t kEmojiValueSize = 32 * 3;
64 const size_t kEmojiSize = 100;
65 const uint32 kEmojiSeed = 136843897;
66
67 } // namespace
68
69 namespace mozc {
70
71 using mozc::storage::LRUStorage;
72
73 class GenericStorageManagerImpl : public GenericStorageManagerInterface {
74 public:
75 GenericStorageManagerImpl()
76 : symbol_history_storage_(kSymbolStorageFileName, kSymbolValueSize,
77 kSymbolSize, kSymbolSeed),
78 emoticon_history_storage_(kEmoticonStorageFileName, kEmoticonValueSize,
79 kEmoticonSize, kEmoticonSeed),
80 emoji_history_storage_(kEmojiStorageFileName, kEmojiValueSize,
81 kEmojiSize, kEmojiSeed) {}
82
83 ~GenericStorageManagerImpl() override = default;
84
85 GenericStorageInterface *GetStorage(
86 commands::GenericStorageEntry::StorageType storage_type) override;
87
88 bool SyncAll() override;
89
90 private:
91 GenericLruStorage symbol_history_storage_;
92 GenericLruStorage emoticon_history_storage_;
93 GenericLruStorage emoji_history_storage_;
94 };
95
96 GenericStorageInterface *GenericStorageManagerImpl::GetStorage(
97 commands::GenericStorageEntry::StorageType storage_type) {
98 switch (storage_type) {
99 case commands::GenericStorageEntry::SYMBOL_HISTORY:
100 return &symbol_history_storage_;
101 case commands::GenericStorageEntry::EMOTICON_HISTORY:
102 return &emoticon_history_storage_;
103 case commands::GenericStorageEntry::EMOJI_HISTORY:
104 return &emoji_history_storage_;
105 default:
106 LOG(WARNING) << "Invalid storage type";
107 }
108 return nullptr;
109 }
110
111 bool GenericStorageManagerImpl::SyncAll() {
112 const bool symbol_ok = symbol_history_storage_.Sync();
113 const bool emoticon_ok = emoticon_history_storage_.Sync();
114 const bool emoji_ok = emoji_history_storage_.Sync();
115 return symbol_ok && emoticon_ok && emoji_ok;
116 }
117
118 // static
119 void GenericStorageManagerFactory::SetGenericStorageManager(
120 GenericStorageManagerInterface *manager) {
121 g_storage_manager = manager;
122 }
123
124 // static
125 GenericStorageInterface *GenericStorageManagerFactory::GetStorage(
126 commands::GenericStorageEntry::StorageType storage_type) {
127 GenericStorageManagerInterface *manager =
128 g_storage_manager ? g_storage_manager
129 : Singleton<GenericStorageManagerImpl>::get();
130 return manager->GetStorage(storage_type);
131 }
132
133 bool GenericStorageManagerFactory::SyncAll() {
134 GenericStorageManagerInterface *manager =
135 g_storage_manager ? g_storage_manager
136 : Singleton<GenericStorageManagerImpl>::get();
137 return manager->SyncAll();
138 }
139
140 GenericLruStorage::GenericLruStorage(const char *file_name, size_t value_size,
141 size_t size, uint32 seed)
142 : file_name_(file_name),
143 value_size_(value_size),
144 size_(size),
145 seed_(seed),
146 value_buffer_(new char[value_size + 1]) {}
147
148 GenericLruStorage::~GenericLruStorage() {}
149
150 bool GenericLruStorage::EnsureStorage() {
151 scoped_lock lock(&g_storage_ensure_mutex);
152 if (lru_storage_.get()) {
153 // We already have prepared storage.
154 return true;
155 }
156 std::unique_ptr<LRUStorage> new_storage;
157 new_storage.reset(new LRUStorage());
158 const std::string &filename = ConfigFileStream::GetFileName(file_name_);
159 if (!new_storage->OpenOrCreate(filename.data(), value_size_, size_, seed_)) {
160 return false;
161 }
162 lru_storage_.swap(new_storage);
163 return true;
164 }
165
166 bool GenericLruStorage::Insert(const std::string &key, const char *value) {
167 if (!EnsureStorage()) {
168 return false;
169 }
170 const size_t value_size = strnlen(value, value_size_ + 1);
171 if (value_size > value_size_) {
172 LOG(DFATAL) << "Too long value: [" << value << "] size: " << value_size;
173 return false;
174 }
175 // LRUStorage only accepts fixed-length value, so we should allocate enough
176 // memory to avoid illegal access.
177 memcpy(value_buffer_.get(), value, value_size + 1);
178 return lru_storage_->Insert(key, value_buffer_.get());
179 }
180
181 const char *GenericLruStorage::Lookup(const std::string &key) {
182 if (!EnsureStorage()) {
183 return nullptr;
184 }
185 return lru_storage_->Lookup(key);
186 }
187
188 bool GenericLruStorage::GetAllValues(std::vector<std::string> *values) {
189 if (!EnsureStorage()) {
190 return false;
191 }
192 lru_storage_->GetAllValues(values);
193 return true;
194 }
195
196 bool GenericLruStorage::Clear() {
197 if (!EnsureStorage()) {
198 return false;
199 }
200 return lru_storage_->Clear();
201 }
202
203 bool GenericLruStorage::Sync() {
204 if (!EnsureStorage()) {
205 return false;
206 }
207 lru_storage_->DeleteElementsUntouchedFor62Days();
208 return true;
209 }
210
211 } // namespace mozc
+0
-153
src/session/generic_storage_manager.h less more
0 // Copyright 2010-2020, Google Inc.
1 // All rights reserved.
2 //
3 // Redistribution and use in source and binary forms, with or without
4 // modification, are permitted provided that the following conditions are
5 // met:
6 //
7 // * Redistributions of source code must retain the above copyright
8 // notice, this list of conditions and the following disclaimer.
9 // * Redistributions in binary form must reproduce the above
10 // copyright notice, this list of conditions and the following disclaimer
11 // in the documentation and/or other materials provided with the
12 // distribution.
13 // * Neither the name of Google Inc. nor the names of its
14 // contributors may be used to endorse or promote products derived from
15 // this software without specific prior written permission.
16 //
17 // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
18 // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
19 // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
20 // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
21 // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
22 // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
23 // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
24 // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
25 // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
26 // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
27 // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
28
29 #ifndef MOZC_SESSION_GENERIC_STORAGE_MANAGER_H_
30 #define MOZC_SESSION_GENERIC_STORAGE_MANAGER_H_
31
32 #include <memory>
33
34 #include "base/port.h"
35 #include "protocol/commands.pb.h"
36
37 namespace mozc {
38
39 class GenericStorageInterface;
40
41 // For unit test.
42 class GenericLruStorageProxy;
43
44 namespace storage {
45 class LRUStorage;
46 } // namespace storage
47
48 // Override and set the subclass's instance to
49 // GenericStorageManager for unit test.
50 class GenericStorageManagerInterface {
51 public:
52 virtual ~GenericStorageManagerInterface() = default;
53
54 virtual GenericStorageInterface *GetStorage(
55 commands::GenericStorageEntry::StorageType storage_type) = 0;
56
57 // Synchronizes all the managed storages. Returns true iff all the storages
58 // are synchronized successfully (Note: even if one failed, it's guaranteed
59 // that Sync() to all the storages are called.).
60 virtual bool SyncAll() = 0;
61 };
62
63 // Manages generic storages.
64 class GenericStorageManagerFactory {
65 public:
66 // Returns corresponding storage's instance.
67 // If no instance is available, NULL is returned.
68 static GenericStorageInterface *GetStorage(
69 commands::GenericStorageEntry::StorageType storage_type);
70
71 // Synchronizes all the storages managed by this factory. Returns true iff
72 // all the storages are synchronized successfully (Note: even if one failed,
73 // it's guaranteed that Sync() to all the storages are called.).
74 static bool SyncAll();
75
76 // For unit test.
77 static void SetGenericStorageManager(GenericStorageManagerInterface *manager);
78
79 GenericStorageManagerFactory() = delete;
80 GenericStorageManagerFactory(const GenericStorageManagerFactory &) = delete;
81 GenericStorageManagerFactory &operator=(
82 const GenericStorageManagerFactory &) = delete;
83 };
84
85 // Generic interface for storages.
86 // This class defines only the interfaces.
87 // Detailed behaviors depend on the subclass's
88 // backend.
89 class GenericStorageInterface {
90 public:
91 virtual ~GenericStorageInterface() = default;
92
93 // Inserts new entry.
94 // If something goes wrong, returns false.
95 // value should be terminated by '\0'.
96 virtual bool Insert(const std::string &key, const char *value) = 0;
97 // Looks up the value.
98 // If something goes wrong, returns NULL.
99 virtual const char *Lookup(const std::string &key) = 0;
100 // Lists all the values.
101 // If something goes wrong, returns false.
102 virtual bool GetAllValues(std::vector<std::string> *values) = 0;
103 // Clears all the entries.
104 virtual bool Clear() = 0;
105 // Writes the data to file(s).
106 virtual bool Sync() = 0;
107 };
108
109 // Storage class of which backend is LRUStorage.
110 class GenericLruStorage : public GenericStorageInterface {
111 public:
112 GenericLruStorage(const char *file_name, size_t value_size, size_t size,
113 uint32 seed);
114
115 GenericLruStorage(const GenericLruStorage &) = delete;
116 GenericLruStorage &operator=(const GenericLruStorage &) = delete;
117
118 ~GenericLruStorage() override;
119
120 // If the storage has |key|, this method overwrites
121 // the old value.
122 // If the entiry's size is over GetSize(),
123 // the oldest value is disposed.
124 bool Insert(const std::string &key, const char *value) override;
125
126 const char *Lookup(const std::string &key) override;
127
128 // The order is new to old.
129 bool GetAllValues(std::vector<std::string> *values) override;
130
131 bool Clear() override;
132 bool Sync() override;
133
134 protected:
135 // Opens the storage if not opened yet.
136 // If something goes wrong, returns false.
137 bool EnsureStorage();
138
139 private:
140 friend class GenericLruStorageProxy;
141 std::unique_ptr<mozc::storage::LRUStorage> lru_storage_;
142 const std::string file_name_;
143 const size_t value_size_;
144 const size_t size_;
145 const uint32 seed_;
146 // Temporary buffer to insert a value into this storage.
147 std::unique_ptr<char[]> value_buffer_;
148 };
149
150 } // namespace mozc
151
152 #endif // MOZC_SESSION_GENERIC_STORAGE_MANAGER_H_
+0
-101
src/session/generic_storage_manager_test.cc less more
0 // Copyright 2010-2020, Google Inc.
1 // All rights reserved.
2 //
3 // Redistribution and use in source and binary forms, with or without
4 // modification, are permitted provided that the following conditions are
5 // met:
6 //
7 // * Redistributions of source code must retain the above copyright
8 // notice, this list of conditions and the following disclaimer.
9 // * Redistributions in binary form must reproduce the above
10 // copyright notice, this list of conditions and the following disclaimer
11 // in the documentation and/or other materials provided with the
12 // distribution.
13 // * Neither the name of Google Inc. nor the names of its
14 // contributors may be used to endorse or promote products derived from
15 // this software without specific prior written permission.
16 //
17 // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
18 // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
19 // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
20 // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
21 // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
22 // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
23 // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
24 // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
25 // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
26 // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
27 // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
28
29 #include "session/generic_storage_manager.h"
30
31 #include "base/file_util.h"
32 #include "base/util.h"
33 #include "testing/base/public/googletest.h"
34 #include "testing/base/public/gunit.h"
35
36 namespace {
37
38 static const std::string GetTemporaryFilePath() {
39 return mozc::FileUtil::JoinPath(FLAGS_test_tmpdir, "generic_storage_test.db");
40 }
41
42 } // namespace
43
44 namespace mozc {
45
46 TEST(GenericStorageManagerFactoryTest, GetStorage) {
47 GenericStorageInterface *symbol = GenericStorageManagerFactory::GetStorage(
48 commands::GenericStorageEntry::SYMBOL_HISTORY);
49 GenericStorageInterface *emoticon = GenericStorageManagerFactory::GetStorage(
50 commands::GenericStorageEntry::EMOTICON_HISTORY);
51 GenericStorageInterface *invalid = GenericStorageManagerFactory::GetStorage(
52 static_cast<commands::GenericStorageEntry::StorageType>(100));
53
54 EXPECT_NE(nullptr, symbol);
55 EXPECT_NE(nullptr, emoticon);
56 EXPECT_EQ(nullptr, invalid);
57 EXPECT_NE(symbol, emoticon);
58 }
59
60 // Checks the basic operations of LRU.
61 // Detailed test is omitted because storage/lru_storage_test.cc does.
62 TEST(GenericLruStorageTest, BasicOperations) {
63 const int kValueSize = 12;
64 const int kSize = 10;
65 constexpr const char *kPrintFormat = "%12zu"; // 12 = kValueSize
66
67 GenericLruStorage storage(GetTemporaryFilePath().data(), kValueSize, kSize,
68 123);
69 // Inserts (kSize + 1) entries.
70 for (size_t i = 0; i < kSize + 1; ++i) {
71 const std::string value = Util::StringPrintf(kPrintFormat, i);
72 const std::string key = std::string("key") + value;
73 storage.Insert(key, value.data());
74 // Check the existence.
75 EXPECT_EQ(value, std::string(storage.Lookup(key), kValueSize));
76 }
77
78 // First inserted entry is already pushed out.
79 EXPECT_EQ(nullptr, storage.Lookup("0"));
80 for (size_t i = 1; i < kSize + 1; ++i) {
81 const std::string value = Util::StringPrintf(kPrintFormat, i);
82 const std::string key = std::string("key") + value;
83 EXPECT_EQ(value, std::string(storage.Lookup(key), kValueSize));
84 }
85
86 // Check the list.
87 std::vector<std::string> values;
88 storage.GetAllValues(&values);
89 EXPECT_EQ(kSize, values.size());
90 for (size_t i = 1; i < kSize + 1; ++i) {
91 EXPECT_EQ(Util::StringPrintf(kPrintFormat, i), values.at(kSize - i));
92 }
93
94 // Clean
95 storage.Clear();
96 storage.GetAllValues(&values);
97 EXPECT_TRUE(values.empty());
98 }
99
100 } // namespace mozc
104104 '../protocol/protocol.gyp:engine_builder_proto',
105105 '../protocol/protocol.gyp:user_dictionary_storage_proto',
106106 '../usage_stats/usage_stats_base.gyp:usage_stats',
107 'session_base.gyp:generic_storage_manager',
108107 ':session_watch_dog',
109108 ],
110109 'conditions': [
129129 '../usage_stats/usage_stats_base.gyp:usage_stats',
130130 ],
131131 },
132 {
133 'target_name': 'generic_storage_manager',
134 'type': 'static_library',
135 'sources': [
136 'generic_storage_manager.cc',
137 ],
138 'dependencies': [
139 '../base/base.gyp:base',
140 '../base/base.gyp:config_file_stream',
141 '../protocol/protocol.gyp:commands_proto',
142 '../storage/storage.gyp:storage',
143 ]
144 },
145132 ],
146133 }
5555 #include "protocol/commands.pb.h"
5656 #include "protocol/config.pb.h"
5757 #include "protocol/user_dictionary_storage.pb.h"
58 #include "session/generic_storage_manager.h"
5958 #include "session/session.h"
6059 #include "session/session_observer_handler.h"
6160 #ifndef MOZC_DISABLE_SESSION_WATCHDOG
123122 // android version supports base/process.cc
124123 #endif // MOZC_DISABLE_SESSION_WATCHDOG
125124 return true;
126 }
127
128 bool IsCarrierEmoji(const std::string &utf8_str) {
129 if (Util::CharsLen(utf8_str) != 1) {
130 return false;
131 }
132 const char *utf8_begin = utf8_str.c_str();
133 size_t mblen = 0;
134 const uint32 ucs4_val = static_cast<uint32>(
135 Util::UTF8ToUCS4(utf8_begin, utf8_begin + utf8_str.size(), &mblen));
136 const uint32 kMinEmojiPuaCodePoint = 0xFE000;
137 const uint32 kMaxEmojiPuaCodePoint = 0xFEEA0;
138 return kMinEmojiPuaCodePoint <= ucs4_val && ucs4_val <= kMaxEmojiPuaCodePoint;
139125 }
140126 } // namespace
141127
262248 bool SessionHandler::SyncData(commands::Command *command) {
263249 VLOG(1) << "Syncing user data";
264250 engine_->GetUserDataManager()->Sync();
265 GenericStorageManagerFactory::SyncAll();
266251 return true;
267252 }
268253
367352 return true;
368353 }
369354
370 bool SessionHandler::InsertToStorage(commands::Command *command) {
371 VLOG(1) << "Insert to generic storage";
372 if (!command->input().has_storage_entry()) {
373 LOG(WARNING) << "No storage_entry";
374 return false;
375 }
376 const commands::GenericStorageEntry &storage_entry =
377 command->input().storage_entry();
378 if (!storage_entry.has_type() || !storage_entry.has_key() ||
379 storage_entry.value().empty()) {
380 LOG(WARNING) << "storage_entry lacks some fields.";
381 return false;
382 }
383
384 GenericStorageInterface *storage =
385 GenericStorageManagerFactory::GetStorage(storage_entry.type());
386 if (!storage) {
387 LOG(WARNING) << "No storage found";
388 return false;
389 }
390
391 for (int i = 0; i < storage_entry.value_size(); ++i) {
392 const std::string &value = storage_entry.value(i);
393 storage->Insert(value, value.c_str());
394 }
395
396 if (storage_entry.type() == commands::GenericStorageEntry::EMOJI_HISTORY) {
397 for (int i = 0; i < storage_entry.value_size(); ++i) {
398 if (IsCarrierEmoji(storage_entry.value(i))) {
399 UsageStats::IncrementCount("CommitCarrierEmoji");
400 } else {
401 UsageStats::IncrementCount("CommitUnicodeEmoji");
402 }
403 }
404 }
405
406 return true;
407 }
408
409 bool SessionHandler::ReadAllFromStorage(commands::Command *command) {
410 VLOG(1) << "Read all from storage";
411 commands::Output *output = command->mutable_output();
412 if (!command->input().has_storage_entry()) {
413 LOG(WARNING) << "No storage_entry";
414 return false;
415 }
416 if (!command->input().storage_entry().has_type()) {
417 LOG(WARNING) << "storage_entry lacks type fields.";
418 return false;
419 }
420
421 commands::GenericStorageEntry::StorageType storage_type =
422 command->input().storage_entry().type();
423 GenericStorageInterface *storage =
424 GenericStorageManagerFactory::GetStorage(storage_type);
425 if (!storage) {
426 LOG(WARNING) << "No storage found";
427 return false;
428 }
429
430 std::vector<std::string> result;
431 storage->GetAllValues(&result);
432 output->mutable_storage_entry()->set_type(storage_type);
433 for (size_t i = 0; i < result.size(); ++i) {
434 output->mutable_storage_entry()->add_value(result[i]);
435 }
436 return true;
437 }
438
439 bool SessionHandler::ClearStorage(commands::Command *command) {
440 VLOG(1) << "Clear storage";
441 commands::Output *output = command->mutable_output();
442 if (!command->input().has_storage_entry()) {
443 LOG(WARNING) << "No storage_entry";
444 return false;
445 }
446 if (!command->input().storage_entry().has_type()) {
447 LOG(WARNING) << "storage_entry lacks type fields.";
448 return false;
449 }
450
451 commands::GenericStorageEntry::StorageType storage_type =
452 command->input().storage_entry().type();
453 GenericStorageInterface *storage =
454 GenericStorageManagerFactory::GetStorage(storage_type);
455 if (!storage) {
456 LOG(WARNING) << "No storage found";
457 return false;
458 }
459 output->mutable_storage_entry()->set_type(storage_type);
460 return storage->Clear();
461 }
462
463355 bool SessionHandler::EvalCommand(commands::Command *command) {
464356 if (!is_available_) {
465357 LOG(ERROR) << "SessionHandler is not available.";
518410 break;
519411 case commands::Input::CLEANUP:
520412 eval_succeeded = Cleanup(command);
521 break;
522 case commands::Input::INSERT_TO_STORAGE:
523 eval_succeeded = InsertToStorage(command);
524 break;
525 case commands::Input::READ_ALL_FROM_STORAGE:
526 eval_succeeded = ReadAllFromStorage(command);
527 break;
528 case commands::Input::CLEAR_STORAGE:
529 eval_succeeded = ClearStorage(command);
530413 break;
531414 case commands::Input::SEND_USER_DICTIONARY_COMMAND:
532415 eval_succeeded = SendUserDictionaryCommand(command);
712595 if (engine_->GetUserDataManager()) {
713596 engine_->GetUserDataManager()->Sync();
714597 }
715 GenericStorageManagerFactory::SyncAll();
716598 return true;
717599 }
718600
781663
782664 // Sync all data. This is a regression bug fix http://b/3033708
783665 engine_->GetUserDataManager()->Sync();
784 GenericStorageManagerFactory::SyncAll();
785666
786667 // timeout is enabled.
787668 if (FLAGS_timeout > 0 && last_session_empty_time_ != 0 &&
129129 bool SetImposedConfig(commands::Command *command);
130130 bool SetRequest(commands::Command *command);
131131
132 bool InsertToStorage(commands::Command *command);
133 bool ReadAllFromStorage(commands::Command *command);
134 bool ClearStorage(commands::Command *command);
135132 bool Cleanup(commands::Command *command);
136133 bool SendUserDictionaryCommand(commands::Command *command);
137134 bool SendEngineReloadRequest(commands::Command *command);
4646 #include "engine/user_data_manager_mock.h"
4747 #include "protocol/commands.pb.h"
4848 #include "protocol/config.pb.h"
49 #include "session/generic_storage_manager.h"
5049 #include "session/session_handler_test_util.h"
5150 #include "testing/base/public/googletest.h"
5251 #include "testing/base/public/gunit.h"
148147 void SetUp() override {
149148 SessionHandlerTestBase::SetUp();
150149 Clock::SetClockForUnitTest(nullptr);
151 GenericStorageManagerFactory::SetGenericStorageManager(nullptr);
152150 }
153151
154152 void TearDown() override {
155 GenericStorageManagerFactory::SetGenericStorageManager(nullptr);
156153 Clock::SetClockForUnitTest(nullptr);
157154 SessionHandlerTestBase::TearDown();
158155 }
438435 }
439436 }
440437
441 const char *kStorageTestData[] = {
442 "angel",
443 "bishop",
444 "chariot",
445 "dragon",
446 };
447
448 class MockStorage : public GenericStorageInterface {
449 public:
450 int insert_count;
451 int clear_count;
452 const char **insert_expect;
453
454 MockStorage() : insert_count(0), clear_count(0) {}
455 ~MockStorage() override = default;
456
457 bool Insert(const std::string &key, const char *value) override {
458 EXPECT_EQ(std::string(insert_expect[insert_count]), key);
459 EXPECT_EQ(std::string(insert_expect[insert_count]), std::string(value));
460 ++insert_count;
461 return true;
462 }
463
464 const char *Lookup(const std::string &key) override { return nullptr; }
465
466 bool GetAllValues(std::vector<std::string> *values) override {
467 values->clear();
468 for (size_t i = 0; i < arraysize(kStorageTestData); ++i) {
469 values->push_back(kStorageTestData[i]);
470 }
471 return true;
472 }
473
474 bool Clear() override {
475 ++clear_count;
476 return true;
477 }
478
479 bool Sync() override { return true; }
480
481 void SetInsertExpect(const char **expect) { insert_expect = expect; }
482 };
483
484 class MockStorageManager : public GenericStorageManagerInterface {
485 public:
486 GenericStorageInterface *GetStorage(
487 commands::GenericStorageEntry::StorageType storage_type) override {
488 return storage;
489 }
490
491 void SetStorage(MockStorage *newStorage) { storage = newStorage; }
492
493 bool SyncAll() override {
494 if (storage == nullptr) {
495 return true;
496 }
497 return storage->Sync();
498 }
499
500 private:
501 MockStorage *storage;
502 };
503
504 // Tests basic behavior of InsertToStorage and ReadAllFromStorage methods.
505 TEST_F(SessionHandlerTest, StorageTest) {
506 // Inject mock objects.
507 MockStorageManager storageManager;
508 GenericStorageManagerFactory::SetGenericStorageManager(&storageManager);
509 SessionHandler handler(CreateMockDataEngine());
510 {
511 // InsertToStorage
512 MockStorage mock_storage;
513 mock_storage.SetInsertExpect(kStorageTestData);
514 storageManager.SetStorage(&mock_storage);
515 commands::Command command;
516 command.mutable_input()->set_type(commands::Input::INSERT_TO_STORAGE);
517 commands::GenericStorageEntry *storage_entry =
518 command.mutable_input()->mutable_storage_entry();
519 storage_entry->set_type(commands::GenericStorageEntry::SYMBOL_HISTORY);
520 storage_entry->mutable_key()->assign("dummy key");
521 for (size_t i = 0; i < arraysize(kStorageTestData); ++i) {
522 storage_entry->mutable_value()->Add()->assign(kStorageTestData[i]);
523 }
524 EXPECT_TRUE(handler.InsertToStorage(&command));
525 EXPECT_EQ(arraysize(kStorageTestData), mock_storage.insert_count);
526 }
527 {
528 // ReadAllFromStorage
529 MockStorage mock_storage;
530 storageManager.SetStorage(&mock_storage);
531 commands::Command command;
532 command.mutable_input()->set_type(commands::Input::READ_ALL_FROM_STORAGE);
533 commands::GenericStorageEntry *storage_entry =
534 command.mutable_input()->mutable_storage_entry();
535 storage_entry->set_type(commands::GenericStorageEntry::EMOTICON_HISTORY);
536 EXPECT_TRUE(handler.ReadAllFromStorage(&command));
537 EXPECT_EQ(commands::GenericStorageEntry::EMOTICON_HISTORY,
538 command.output().storage_entry().type());
539 EXPECT_EQ(arraysize(kStorageTestData),
540 command.output().storage_entry().value().size());
541 }
542 {
543 // Clear
544 MockStorage mock_storage;
545 storageManager.SetStorage(&mock_storage);
546 commands::Command command;
547 command.mutable_input()->set_type(commands::Input::CLEAR_STORAGE);
548 commands::GenericStorageEntry *storage_entry =
549 command.mutable_input()->mutable_storage_entry();
550 storage_entry->set_type(commands::GenericStorageEntry::EMOTICON_HISTORY);
551 EXPECT_TRUE(handler.ClearStorage(&command));
552 EXPECT_EQ(commands::GenericStorageEntry::EMOTICON_HISTORY,
553 command.output().storage_entry().type());
554 EXPECT_EQ(1, mock_storage.clear_count);
555 }
556 }
557
558 TEST_F(SessionHandlerTest, EmojiUsageStatsTest) {
559 SessionHandler handler(CreateMockDataEngine());
560
561 commands::Command command;
562 command.mutable_input()->set_type(commands::Input::INSERT_TO_STORAGE);
563 commands::GenericStorageEntry *storage_entry =
564 command.mutable_input()->mutable_storage_entry();
565 storage_entry->set_type(commands::GenericStorageEntry::EMOJI_HISTORY);
566 storage_entry->mutable_key()->assign("dummy key");
567
568 // Carrier emoji "BLACK SUN WITH RAYS"
569 storage_entry->mutable_value()->Clear();
570 storage_entry->mutable_value()->Add()->assign("\xF3\xBE\x80\x80");
571 EXPECT_TRUE(handler.EvalCommand(&command));
572 EXPECT_COUNT_STATS("CommitCarrierEmoji", 1);
573 EXPECT_COUNT_STATS("CommitUnicodeEmoji", 0);
574
575 storage_entry->mutable_value()->Clear();
576 // Carrier emoji "BLACK SUN WITH RAYS"
577 storage_entry->mutable_value()->Add()->assign("\xF3\xBE\x80\x80");
578 // Carrier emoji "GOOGLE"
579 storage_entry->mutable_value()->Add()->assign("\xF3\xBE\xBA\xA0");
580 // Unicode emoji "BLACK SUN WITH RAYS"
581 storage_entry->mutable_value()->Add()->assign("☀");
582 // Unicode emoji "RABBIT FACE"
583 storage_entry->mutable_value()->Add()->assign("🐰");
584 EXPECT_TRUE(handler.EvalCommand(&command));
585 EXPECT_COUNT_STATS("CommitCarrierEmoji", 3);
586 EXPECT_COUNT_STATS("CommitUnicodeEmoji", 2);
587 }
588
589438 // Tests the interaction with EngineBuilderInterface for successful Engine
590439 // reload event.
591440 TEST_F(SessionHandlerTest, EngineReload_SuccessfulScenario) {
282282 },
283283 },
284284 {
285 'target_name': 'generic_storage_manager_test',
286 'type': 'executable',
287 'sources': [
288 'generic_storage_manager_test.cc'
289 ],
290 'dependencies': [
291 '../base/base.gyp:base',
292 '../testing/testing.gyp:gtest_main',
293 'session_base.gyp:generic_storage_manager',
294 ],
295 'variables': {
296 'test_size': 'small',
297 },
298 },
299 {
300285 'target_name': 'request_test_util_test',
301286 'type': 'executable',
302287 'sources': [
340325 'target_name': 'session_all_test',
341326 'type': 'none',
342327 'dependencies': [
343 'generic_storage_manager_test',
344328 'random_keyevents_generator_test',
345329 'request_test_util_test',
346330 'session_converter_stress_test',
9090 case commands::Input::CLEAR_USER_HISTORY:
9191 case commands::Input::CLEAR_USER_PREDICTION:
9292 case commands::Input::CLEAR_UNUSED_USER_PREDICTION:
93 case commands::Input::CLEAR_STORAGE:
94 case commands::Input::READ_ALL_FROM_STORAGE:
9593 case commands::Input::RELOAD:
9694 case commands::Input::SEND_USER_DICTIONARY_COMMAND:
9795 return true;
163163
164164 // Smoke test to make sure it works without crash.
165165 for (int i = 0; i < SessionCommand::CommandType_ARRAYSIZE; ++i) {
166 if (!SessionCommand::CommandType_IsValid(i)) {
167 continue;
168 }
166169 input.Clear();
167170 input.set_type(Input::SEND_COMMAND);
168171 input.mutable_command()->set_type(