diff --git a/native/jni/src/suggest/policyimpl/dictionary/structure/v4/ver4_patricia_trie_policy.cpp b/native/jni/src/suggest/policyimpl/dictionary/structure/v4/ver4_patricia_trie_policy.cpp index 82cd95e6b..3447dce93 100644 --- a/native/jni/src/suggest/policyimpl/dictionary/structure/v4/ver4_patricia_trie_policy.cpp +++ b/native/jni/src/suggest/policyimpl/dictionary/structure/v4/ver4_patricia_trie_policy.cpp @@ -36,6 +36,11 @@ const char *const Ver4PatriciaTriePolicy::MAX_UNIGRAM_COUNT_QUERY = "MAX_UNIGRAM const char *const Ver4PatriciaTriePolicy::MAX_BIGRAM_COUNT_QUERY = "MAX_BIGRAM_COUNT"; const char *const Ver4PatriciaTriePolicy::SET_NEEDS_TO_DECAY_FOR_TESTING_QUERY = "SET_NEEDS_TO_DECAY_FOR_TESTING"; +const char *const Ver4PatriciaTriePolicy::SET_CURRENT_TIME_FOR_TESTING_QUERY_FORMAT = + "SET_CURRENT_TIME_FOR_TESTING:%d"; +const char *const Ver4PatriciaTriePolicy::GET_CURRENT_TIME_QUERY = "GET_CURRENT_TIME"; +const char *const Ver4PatriciaTriePolicy::QUIT_TIMEKEEPER_TEST_MODE_QUERY = + "QUIT_TIMEKEEPER_TEST_MODE"; const int Ver4PatriciaTriePolicy::MARGIN_TO_REFUSE_DYNAMIC_OPERATIONS = 1024; const int Ver4PatriciaTriePolicy::MIN_DICT_SIZE_TO_REFUSE_DYNAMIC_OPERATIONS = Ver4DictConstants::MAX_DICTIONARY_SIZE - MARGIN_TO_REFUSE_DYNAMIC_OPERATIONS; @@ -290,6 +295,7 @@ bool Ver4PatriciaTriePolicy::needsToRunGC(const bool mindsBlockByGC) const { void Ver4PatriciaTriePolicy::getProperty(const char *const query, const int queryLength, char *const outResult, const int maxResultLength) { const int compareLength = queryLength + 1 /* terminator */; + int timestamp = NOT_A_TIMESTAMP; if (strncmp(query, UNIGRAM_COUNT_QUERY, compareLength) == 0) { snprintf(outResult, maxResultLength, "%d", mUnigramCount); } else if (strncmp(query, BIGRAM_COUNT_QUERY, compareLength) == 0) { @@ -304,6 +310,12 @@ void Ver4PatriciaTriePolicy::getProperty(const char *const query, const int quer static_cast(Ver4DictConstants::MAX_DICTIONARY_SIZE)); } else if (strncmp(query, SET_NEEDS_TO_DECAY_FOR_TESTING_QUERY, compareLength) == 0) { mNeedsToDecayForTesting = true; + } else if (sscanf(query, SET_CURRENT_TIME_FOR_TESTING_QUERY_FORMAT, ×tamp) == 1) { + TimeKeeper::startTestModeWithForceCurrentTime(timestamp); + } else if (strncmp(query, GET_CURRENT_TIME_QUERY, compareLength) == 0) { + snprintf(outResult, maxResultLength, "%d", TimeKeeper::peekCurrentTime()); + } else if (strncmp(query, QUIT_TIMEKEEPER_TEST_MODE_QUERY, compareLength) == 0) { + TimeKeeper::stopTestMode(); } } diff --git a/native/jni/src/suggest/policyimpl/dictionary/structure/v4/ver4_patricia_trie_policy.h b/native/jni/src/suggest/policyimpl/dictionary/structure/v4/ver4_patricia_trie_policy.h index db4e8d21c..d2d2ead50 100644 --- a/native/jni/src/suggest/policyimpl/dictionary/structure/v4/ver4_patricia_trie_policy.h +++ b/native/jni/src/suggest/policyimpl/dictionary/structure/v4/ver4_patricia_trie_policy.h @@ -118,6 +118,9 @@ class Ver4PatriciaTriePolicy : public DictionaryStructureWithBufferPolicy { static const char *const MAX_UNIGRAM_COUNT_QUERY; static const char *const MAX_BIGRAM_COUNT_QUERY; static const char *const SET_NEEDS_TO_DECAY_FOR_TESTING_QUERY; + static const char *const SET_CURRENT_TIME_FOR_TESTING_QUERY_FORMAT; + static const char *const GET_CURRENT_TIME_QUERY; + static const char *const QUIT_TIMEKEEPER_TEST_MODE_QUERY; // When the dictionary size is near the maximum size, we have to refuse dynamic operations to // prevent the dictionary from overflowing. static const int MARGIN_TO_REFUSE_DYNAMIC_OPERATIONS; diff --git a/tests/src/com/android/inputmethod/latin/BinaryDictionaryDecayingTests.java b/tests/src/com/android/inputmethod/latin/BinaryDictionaryDecayingTests.java index 000b5016c..1ea54eae5 100644 --- a/tests/src/com/android/inputmethod/latin/BinaryDictionaryDecayingTests.java +++ b/tests/src/com/android/inputmethod/latin/BinaryDictionaryDecayingTests.java @@ -37,9 +37,13 @@ public class BinaryDictionaryDecayingTests extends AndroidTestCase { private static final String TEST_LOCALE = "test"; // Note that these are corresponding definitions in native code in - // latinime::DynamicPatriciaTriePolicy. + // latinime::Ver4PatriciaTriePolicy. private static final String SET_NEEDS_TO_DECAY_FOR_TESTING_KEY = "SET_NEEDS_TO_DECAY_FOR_TESTING"; + private static final String SET_CURRENT_TIME_FOR_TESTING_QUERY = + "SET_CURRENT_TIME_FOR_TESTING"; + private static final String GET_CURRENT_TIME_QUERY = "GET_CURRENT_TIME"; + private static final String QUIT_TIMEKEEPER_TEST_MODE_QUERY = "QUIT_TIMEKEEPER_TEST_MODE"; private static final int DUMMY_PROBABILITY = 0; @@ -116,6 +120,45 @@ public class BinaryDictionaryDecayingTests extends AndroidTestCase { } } + private static int getCurrentTime(final BinaryDictionary binaryDictionary) { + return Integer.parseInt(binaryDictionary.getPropertyForTests(GET_CURRENT_TIME_QUERY)); + } + + private static void setCurrentTime(final BinaryDictionary binaryDictionary, + final int currentTime) { + final String query = SET_CURRENT_TIME_FOR_TESTING_QUERY + ":" + currentTime; + binaryDictionary.getPropertyForTests(query); + } + + public void testControllCurrentTime() { + testControllCurrentTime(FormatSpec.VERSION4); + } + + private void testControllCurrentTime(final int formatVersion) { + final int TEST_COUNT = 1000; + final long seed = System.currentTimeMillis(); + final Random random = new Random(seed); + File dictFile = null; + try { + dictFile = createEmptyDictionaryAndGetFile("TestBinaryDictionary", formatVersion); + } catch (IOException e) { + fail("IOException while writing an initial dictionary : " + e); + } + BinaryDictionary binaryDictionary = new BinaryDictionary(dictFile.getAbsolutePath(), + 0 /* offset */, dictFile.length(), true /* useFullEditDistance */, + Locale.getDefault(), TEST_LOCALE, true /* isUpdatable */); + final int startTime = getCurrentTime(binaryDictionary); + for (int i = 0; i < TEST_COUNT; i++) { + final int currentTime = random.nextInt(Integer.MAX_VALUE); + setCurrentTime(binaryDictionary, currentTime); + assertEquals(currentTime, getCurrentTime(binaryDictionary)); + } + binaryDictionary.getPropertyForTests(QUIT_TIMEKEEPER_TEST_MODE_QUERY); + final int endTime = getCurrentTime(binaryDictionary); + final int MAX_ALLOWED_ELAPSED_TIME = 10; + assertTrue(startTime <= endTime && endTime <= startTime + MAX_ALLOWED_ELAPSED_TIME); + } + public void testAddValidAndInvalidWords() { testAddValidAndInvalidWords(FormatSpec.VERSION4); }