15eb774884266e72b9e6f0caf79f4dc6b698d121cLeif Wilden/* 25eb774884266e72b9e6f0caf79f4dc6b698d121cLeif Wilden * Copyright (C) 2016 The Android Open Source Project 35eb774884266e72b9e6f0caf79f4dc6b698d121cLeif Wilden * 45eb774884266e72b9e6f0caf79f4dc6b698d121cLeif Wilden * Licensed under the Apache License, Version 2.0 (the "License"); 55eb774884266e72b9e6f0caf79f4dc6b698d121cLeif Wilden * you may not use this file except in compliance with the License. 65eb774884266e72b9e6f0caf79f4dc6b698d121cLeif Wilden * You may obtain a copy of the License at 75eb774884266e72b9e6f0caf79f4dc6b698d121cLeif Wilden * 85eb774884266e72b9e6f0caf79f4dc6b698d121cLeif Wilden * http://www.apache.org/licenses/LICENSE-2.0 95eb774884266e72b9e6f0caf79f4dc6b698d121cLeif Wilden * 105eb774884266e72b9e6f0caf79f4dc6b698d121cLeif Wilden * Unless required by applicable law or agreed to in writing, software 115eb774884266e72b9e6f0caf79f4dc6b698d121cLeif Wilden * distributed under the License is distributed on an "AS IS" BASIS, 125eb774884266e72b9e6f0caf79f4dc6b698d121cLeif Wilden * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 135eb774884266e72b9e6f0caf79f4dc6b698d121cLeif Wilden * See the License for the specific language governing permissions and 145eb774884266e72b9e6f0caf79f4dc6b698d121cLeif Wilden * limitations under the License. 155eb774884266e72b9e6f0caf79f4dc6b698d121cLeif Wilden */ 165eb774884266e72b9e6f0caf79f4dc6b698d121cLeif Wildenpackage com.android.settingslib.core.instrumentation; 175eb774884266e72b9e6f0caf79f4dc6b698d121cLeif Wilden 185eb774884266e72b9e6f0caf79f4dc6b698d121cLeif Wildenimport static com.android.internal.logging.nano.MetricsProto.MetricsEvent.ACTION_SETTINGS_PREFERENCE_CHANGE; 195eb774884266e72b9e6f0caf79f4dc6b698d121cLeif Wildenimport static com.android.internal.logging.nano.MetricsProto.MetricsEvent.FIELD_SETTINGS_PREFERENCE_CHANGE_FLOAT_VALUE; 205eb774884266e72b9e6f0caf79f4dc6b698d121cLeif Wildenimport static com.android.internal.logging.nano.MetricsProto.MetricsEvent.FIELD_SETTINGS_PREFERENCE_CHANGE_INT_VALUE; 215eb774884266e72b9e6f0caf79f4dc6b698d121cLeif Wildenimport static com.android.internal.logging.nano.MetricsProto.MetricsEvent.FIELD_SETTINGS_PREFERENCE_CHANGE_NAME; 225eb774884266e72b9e6f0caf79f4dc6b698d121cLeif Wildenimport static org.mockito.Matchers.any; 235eb774884266e72b9e6f0caf79f4dc6b698d121cLeif Wildenimport static org.mockito.Matchers.anyInt; 245eb774884266e72b9e6f0caf79f4dc6b698d121cLeif Wildenimport static org.mockito.Matchers.argThat; 255eb774884266e72b9e6f0caf79f4dc6b698d121cLeif Wildenimport static org.mockito.Matchers.eq; 265eb774884266e72b9e6f0caf79f4dc6b698d121cLeif Wildenimport static org.mockito.Mockito.times; 275eb774884266e72b9e6f0caf79f4dc6b698d121cLeif Wildenimport static org.mockito.Mockito.verify; 285eb774884266e72b9e6f0caf79f4dc6b698d121cLeif Wilden 295eb774884266e72b9e6f0caf79f4dc6b698d121cLeif Wildenimport android.content.Context; 305eb774884266e72b9e6f0caf79f4dc6b698d121cLeif Wildenimport android.content.SharedPreferences; 315eb774884266e72b9e6f0caf79f4dc6b698d121cLeif Wildenimport android.util.Pair; 325eb774884266e72b9e6f0caf79f4dc6b698d121cLeif Wilden 335eb774884266e72b9e6f0caf79f4dc6b698d121cLeif Wildenimport com.android.settingslib.SettingsLibRobolectricTestRunner; 345eb774884266e72b9e6f0caf79f4dc6b698d121cLeif Wilden 355eb774884266e72b9e6f0caf79f4dc6b698d121cLeif Wildenimport org.junit.Before; 365eb774884266e72b9e6f0caf79f4dc6b698d121cLeif Wildenimport org.junit.Test; 375eb774884266e72b9e6f0caf79f4dc6b698d121cLeif Wildenimport org.junit.runner.RunWith; 385eb774884266e72b9e6f0caf79f4dc6b698d121cLeif Wildenimport org.mockito.Answers; 395eb774884266e72b9e6f0caf79f4dc6b698d121cLeif Wildenimport org.mockito.ArgumentMatcher; 405eb774884266e72b9e6f0caf79f4dc6b698d121cLeif Wildenimport org.mockito.Mock; 415eb774884266e72b9e6f0caf79f4dc6b698d121cLeif Wildenimport org.mockito.MockitoAnnotations; 425eb774884266e72b9e6f0caf79f4dc6b698d121cLeif Wilden 435eb774884266e72b9e6f0caf79f4dc6b698d121cLeif Wilden@RunWith(SettingsLibRobolectricTestRunner.class) 445eb774884266e72b9e6f0caf79f4dc6b698d121cLeif Wildenpublic class SharedPreferenceLoggerTest { 455eb774884266e72b9e6f0caf79f4dc6b698d121cLeif Wilden 465eb774884266e72b9e6f0caf79f4dc6b698d121cLeif Wilden private static final String TEST_TAG = "tag"; 475eb774884266e72b9e6f0caf79f4dc6b698d121cLeif Wilden private static final String TEST_KEY = "key"; 485eb774884266e72b9e6f0caf79f4dc6b698d121cLeif Wilden 495eb774884266e72b9e6f0caf79f4dc6b698d121cLeif Wilden @Mock(answer = Answers.RETURNS_DEEP_STUBS) 505eb774884266e72b9e6f0caf79f4dc6b698d121cLeif Wilden private Context mContext; 515eb774884266e72b9e6f0caf79f4dc6b698d121cLeif Wilden 525eb774884266e72b9e6f0caf79f4dc6b698d121cLeif Wilden private ArgumentMatcher<Pair<Integer, Object>> mNamePairMatcher; 535eb774884266e72b9e6f0caf79f4dc6b698d121cLeif Wilden @Mock 545eb774884266e72b9e6f0caf79f4dc6b698d121cLeif Wilden private MetricsFeatureProvider mMetricsFeature; 555eb774884266e72b9e6f0caf79f4dc6b698d121cLeif Wilden private SharedPreferencesLogger mSharedPrefLogger; 565eb774884266e72b9e6f0caf79f4dc6b698d121cLeif Wilden 575eb774884266e72b9e6f0caf79f4dc6b698d121cLeif Wilden @Before 585eb774884266e72b9e6f0caf79f4dc6b698d121cLeif Wilden public void init() { 595eb774884266e72b9e6f0caf79f4dc6b698d121cLeif Wilden MockitoAnnotations.initMocks(this); 605eb774884266e72b9e6f0caf79f4dc6b698d121cLeif Wilden mSharedPrefLogger = new SharedPreferencesLogger(mContext, TEST_TAG, mMetricsFeature); 615eb774884266e72b9e6f0caf79f4dc6b698d121cLeif Wilden mNamePairMatcher = pairMatches(FIELD_SETTINGS_PREFERENCE_CHANGE_NAME, String.class); 625eb774884266e72b9e6f0caf79f4dc6b698d121cLeif Wilden } 635eb774884266e72b9e6f0caf79f4dc6b698d121cLeif Wilden 645eb774884266e72b9e6f0caf79f4dc6b698d121cLeif Wilden @Test 655eb774884266e72b9e6f0caf79f4dc6b698d121cLeif Wilden public void putInt_shouldNotLogInitialPut() { 665eb774884266e72b9e6f0caf79f4dc6b698d121cLeif Wilden final SharedPreferences.Editor editor = mSharedPrefLogger.edit(); 675eb774884266e72b9e6f0caf79f4dc6b698d121cLeif Wilden editor.putInt(TEST_KEY, 1); 685eb774884266e72b9e6f0caf79f4dc6b698d121cLeif Wilden editor.putInt(TEST_KEY, 1); 695eb774884266e72b9e6f0caf79f4dc6b698d121cLeif Wilden editor.putInt(TEST_KEY, 1); 705eb774884266e72b9e6f0caf79f4dc6b698d121cLeif Wilden editor.putInt(TEST_KEY, 2); 715eb774884266e72b9e6f0caf79f4dc6b698d121cLeif Wilden editor.putInt(TEST_KEY, 2); 725eb774884266e72b9e6f0caf79f4dc6b698d121cLeif Wilden editor.putInt(TEST_KEY, 2); 735eb774884266e72b9e6f0caf79f4dc6b698d121cLeif Wilden editor.putInt(TEST_KEY, 2); 745eb774884266e72b9e6f0caf79f4dc6b698d121cLeif Wilden 755eb774884266e72b9e6f0caf79f4dc6b698d121cLeif Wilden verify(mMetricsFeature, times(6)).action(any(Context.class), anyInt(), 765eb774884266e72b9e6f0caf79f4dc6b698d121cLeif Wilden argThat(mNamePairMatcher), 775eb774884266e72b9e6f0caf79f4dc6b698d121cLeif Wilden argThat(pairMatches(FIELD_SETTINGS_PREFERENCE_CHANGE_INT_VALUE, Integer.class))); 785eb774884266e72b9e6f0caf79f4dc6b698d121cLeif Wilden } 795eb774884266e72b9e6f0caf79f4dc6b698d121cLeif Wilden 805eb774884266e72b9e6f0caf79f4dc6b698d121cLeif Wilden @Test 815eb774884266e72b9e6f0caf79f4dc6b698d121cLeif Wilden public void putBoolean_shouldNotLogInitialPut() { 825eb774884266e72b9e6f0caf79f4dc6b698d121cLeif Wilden final SharedPreferences.Editor editor = mSharedPrefLogger.edit(); 835eb774884266e72b9e6f0caf79f4dc6b698d121cLeif Wilden editor.putBoolean(TEST_KEY, true); 845eb774884266e72b9e6f0caf79f4dc6b698d121cLeif Wilden editor.putBoolean(TEST_KEY, true); 855eb774884266e72b9e6f0caf79f4dc6b698d121cLeif Wilden editor.putBoolean(TEST_KEY, false); 865eb774884266e72b9e6f0caf79f4dc6b698d121cLeif Wilden editor.putBoolean(TEST_KEY, false); 875eb774884266e72b9e6f0caf79f4dc6b698d121cLeif Wilden editor.putBoolean(TEST_KEY, false); 885eb774884266e72b9e6f0caf79f4dc6b698d121cLeif Wilden 895eb774884266e72b9e6f0caf79f4dc6b698d121cLeif Wilden 905eb774884266e72b9e6f0caf79f4dc6b698d121cLeif Wilden verify(mMetricsFeature).action(any(Context.class), anyInt(), 915eb774884266e72b9e6f0caf79f4dc6b698d121cLeif Wilden argThat(mNamePairMatcher), 925eb774884266e72b9e6f0caf79f4dc6b698d121cLeif Wilden argThat(pairMatches(FIELD_SETTINGS_PREFERENCE_CHANGE_INT_VALUE, true))); 935eb774884266e72b9e6f0caf79f4dc6b698d121cLeif Wilden verify(mMetricsFeature, times(3)).action(any(Context.class), anyInt(), 945eb774884266e72b9e6f0caf79f4dc6b698d121cLeif Wilden argThat(mNamePairMatcher), 955eb774884266e72b9e6f0caf79f4dc6b698d121cLeif Wilden argThat(pairMatches(FIELD_SETTINGS_PREFERENCE_CHANGE_INT_VALUE, false))); 965eb774884266e72b9e6f0caf79f4dc6b698d121cLeif Wilden } 975eb774884266e72b9e6f0caf79f4dc6b698d121cLeif Wilden 985eb774884266e72b9e6f0caf79f4dc6b698d121cLeif Wilden @Test 995eb774884266e72b9e6f0caf79f4dc6b698d121cLeif Wilden public void putLong_shouldNotLogInitialPut() { 1005eb774884266e72b9e6f0caf79f4dc6b698d121cLeif Wilden final SharedPreferences.Editor editor = mSharedPrefLogger.edit(); 1015eb774884266e72b9e6f0caf79f4dc6b698d121cLeif Wilden editor.putLong(TEST_KEY, 1); 1025eb774884266e72b9e6f0caf79f4dc6b698d121cLeif Wilden editor.putLong(TEST_KEY, 1); 1035eb774884266e72b9e6f0caf79f4dc6b698d121cLeif Wilden editor.putLong(TEST_KEY, 1); 1045eb774884266e72b9e6f0caf79f4dc6b698d121cLeif Wilden editor.putLong(TEST_KEY, 1); 1055eb774884266e72b9e6f0caf79f4dc6b698d121cLeif Wilden editor.putLong(TEST_KEY, 2); 1065eb774884266e72b9e6f0caf79f4dc6b698d121cLeif Wilden 1075eb774884266e72b9e6f0caf79f4dc6b698d121cLeif Wilden verify(mMetricsFeature, times(4)).action(any(Context.class), anyInt(), 1085eb774884266e72b9e6f0caf79f4dc6b698d121cLeif Wilden argThat(mNamePairMatcher), 1095eb774884266e72b9e6f0caf79f4dc6b698d121cLeif Wilden argThat(pairMatches(FIELD_SETTINGS_PREFERENCE_CHANGE_INT_VALUE, Integer.class))); 1105eb774884266e72b9e6f0caf79f4dc6b698d121cLeif Wilden } 1115eb774884266e72b9e6f0caf79f4dc6b698d121cLeif Wilden 1125eb774884266e72b9e6f0caf79f4dc6b698d121cLeif Wilden @Test 1135eb774884266e72b9e6f0caf79f4dc6b698d121cLeif Wilden public void putLong_biggerThanIntMax_shouldLogIntMax() { 1145eb774884266e72b9e6f0caf79f4dc6b698d121cLeif Wilden final SharedPreferences.Editor editor = mSharedPrefLogger.edit(); 1155eb774884266e72b9e6f0caf79f4dc6b698d121cLeif Wilden final long veryBigNumber = 500L + Integer.MAX_VALUE; 1165eb774884266e72b9e6f0caf79f4dc6b698d121cLeif Wilden editor.putLong(TEST_KEY, 1); 1175eb774884266e72b9e6f0caf79f4dc6b698d121cLeif Wilden editor.putLong(TEST_KEY, veryBigNumber); 1185eb774884266e72b9e6f0caf79f4dc6b698d121cLeif Wilden 1195eb774884266e72b9e6f0caf79f4dc6b698d121cLeif Wilden verify(mMetricsFeature).action(any(Context.class), anyInt(), 1205eb774884266e72b9e6f0caf79f4dc6b698d121cLeif Wilden argThat(mNamePairMatcher), 1215eb774884266e72b9e6f0caf79f4dc6b698d121cLeif Wilden argThat(pairMatches( 1225eb774884266e72b9e6f0caf79f4dc6b698d121cLeif Wilden FIELD_SETTINGS_PREFERENCE_CHANGE_INT_VALUE, Integer.MAX_VALUE))); 1235eb774884266e72b9e6f0caf79f4dc6b698d121cLeif Wilden } 1245eb774884266e72b9e6f0caf79f4dc6b698d121cLeif Wilden 1255eb774884266e72b9e6f0caf79f4dc6b698d121cLeif Wilden @Test 1265eb774884266e72b9e6f0caf79f4dc6b698d121cLeif Wilden public void putLong_smallerThanIntMin_shouldLogIntMin() { 1275eb774884266e72b9e6f0caf79f4dc6b698d121cLeif Wilden final SharedPreferences.Editor editor = mSharedPrefLogger.edit(); 1285eb774884266e72b9e6f0caf79f4dc6b698d121cLeif Wilden final long veryNegativeNumber = -500L + Integer.MIN_VALUE; 1295eb774884266e72b9e6f0caf79f4dc6b698d121cLeif Wilden editor.putLong(TEST_KEY, 1); 1305eb774884266e72b9e6f0caf79f4dc6b698d121cLeif Wilden editor.putLong(TEST_KEY, veryNegativeNumber); 1315eb774884266e72b9e6f0caf79f4dc6b698d121cLeif Wilden 1325eb774884266e72b9e6f0caf79f4dc6b698d121cLeif Wilden verify(mMetricsFeature).action(any(Context.class), anyInt(), 1335eb774884266e72b9e6f0caf79f4dc6b698d121cLeif Wilden argThat(mNamePairMatcher), 1345eb774884266e72b9e6f0caf79f4dc6b698d121cLeif Wilden argThat(pairMatches( 1355eb774884266e72b9e6f0caf79f4dc6b698d121cLeif Wilden FIELD_SETTINGS_PREFERENCE_CHANGE_INT_VALUE, Integer.MIN_VALUE))); 1365eb774884266e72b9e6f0caf79f4dc6b698d121cLeif Wilden } 1375eb774884266e72b9e6f0caf79f4dc6b698d121cLeif Wilden 1385eb774884266e72b9e6f0caf79f4dc6b698d121cLeif Wilden @Test 1395eb774884266e72b9e6f0caf79f4dc6b698d121cLeif Wilden public void putFloat_shouldNotLogInitialPut() { 1405eb774884266e72b9e6f0caf79f4dc6b698d121cLeif Wilden final SharedPreferences.Editor editor = mSharedPrefLogger.edit(); 1415eb774884266e72b9e6f0caf79f4dc6b698d121cLeif Wilden editor.putFloat(TEST_KEY, 1); 1425eb774884266e72b9e6f0caf79f4dc6b698d121cLeif Wilden editor.putFloat(TEST_KEY, 1); 1435eb774884266e72b9e6f0caf79f4dc6b698d121cLeif Wilden editor.putFloat(TEST_KEY, 1); 1445eb774884266e72b9e6f0caf79f4dc6b698d121cLeif Wilden editor.putFloat(TEST_KEY, 1); 1455eb774884266e72b9e6f0caf79f4dc6b698d121cLeif Wilden editor.putFloat(TEST_KEY, 2); 1465eb774884266e72b9e6f0caf79f4dc6b698d121cLeif Wilden 1475eb774884266e72b9e6f0caf79f4dc6b698d121cLeif Wilden verify(mMetricsFeature, times(4)).action(any(Context.class), anyInt(), 1485eb774884266e72b9e6f0caf79f4dc6b698d121cLeif Wilden argThat(mNamePairMatcher), 1495eb774884266e72b9e6f0caf79f4dc6b698d121cLeif Wilden argThat(pairMatches(FIELD_SETTINGS_PREFERENCE_CHANGE_FLOAT_VALUE, Float.class))); 1505eb774884266e72b9e6f0caf79f4dc6b698d121cLeif Wilden } 1515eb774884266e72b9e6f0caf79f4dc6b698d121cLeif Wilden 1525eb774884266e72b9e6f0caf79f4dc6b698d121cLeif Wilden @Test 1535eb774884266e72b9e6f0caf79f4dc6b698d121cLeif Wilden public void logPackage_shouldUseLogPackageApi() { 1545eb774884266e72b9e6f0caf79f4dc6b698d121cLeif Wilden mSharedPrefLogger.logPackageName("key", "com.android.settings"); 1555eb774884266e72b9e6f0caf79f4dc6b698d121cLeif Wilden verify(mMetricsFeature).action(any(Context.class), 1565eb774884266e72b9e6f0caf79f4dc6b698d121cLeif Wilden eq(ACTION_SETTINGS_PREFERENCE_CHANGE), 1575eb774884266e72b9e6f0caf79f4dc6b698d121cLeif Wilden eq("com.android.settings"), 1585eb774884266e72b9e6f0caf79f4dc6b698d121cLeif Wilden any(Pair.class)); 1595eb774884266e72b9e6f0caf79f4dc6b698d121cLeif Wilden } 1605eb774884266e72b9e6f0caf79f4dc6b698d121cLeif Wilden 1615eb774884266e72b9e6f0caf79f4dc6b698d121cLeif Wilden private ArgumentMatcher<Pair<Integer, Object>> pairMatches(int tag, Class clazz) { 16222c3585c54f4bcaaf5ffe250ed99a2befc8e3e4fAurimas Liutikas return pair -> pair.first == tag && isInstanceOfType(pair.second, clazz); 1635eb774884266e72b9e6f0caf79f4dc6b698d121cLeif Wilden } 1645eb774884266e72b9e6f0caf79f4dc6b698d121cLeif Wilden 1655eb774884266e72b9e6f0caf79f4dc6b698d121cLeif Wilden private ArgumentMatcher<Pair<Integer, Object>> pairMatches(int tag, boolean bool) { 1665eb774884266e72b9e6f0caf79f4dc6b698d121cLeif Wilden return pair -> pair.first == tag 16722c3585c54f4bcaaf5ffe250ed99a2befc8e3e4fAurimas Liutikas && isInstanceOfType(pair.second, Integer.class) 1685eb774884266e72b9e6f0caf79f4dc6b698d121cLeif Wilden && pair.second.equals((bool ? 1 : 0)); 1695eb774884266e72b9e6f0caf79f4dc6b698d121cLeif Wilden } 1705eb774884266e72b9e6f0caf79f4dc6b698d121cLeif Wilden 1715eb774884266e72b9e6f0caf79f4dc6b698d121cLeif Wilden private ArgumentMatcher<Pair<Integer, Object>> pairMatches(int tag, int val) { 1725eb774884266e72b9e6f0caf79f4dc6b698d121cLeif Wilden return pair -> pair.first == tag 17322c3585c54f4bcaaf5ffe250ed99a2befc8e3e4fAurimas Liutikas && isInstanceOfType(pair.second, Integer.class) 1745eb774884266e72b9e6f0caf79f4dc6b698d121cLeif Wilden && pair.second.equals(val); 1755eb774884266e72b9e6f0caf79f4dc6b698d121cLeif Wilden } 17622c3585c54f4bcaaf5ffe250ed99a2befc8e3e4fAurimas Liutikas 17722c3585c54f4bcaaf5ffe250ed99a2befc8e3e4fAurimas Liutikas /** Returns true if the instance is assignable to the type Clazz. */ 17822c3585c54f4bcaaf5ffe250ed99a2befc8e3e4fAurimas Liutikas private static boolean isInstanceOfType(Object instance, Class<?> clazz) { 17922c3585c54f4bcaaf5ffe250ed99a2befc8e3e4fAurimas Liutikas return clazz.isInstance(instance); 18022c3585c54f4bcaaf5ffe250ed99a2befc8e3e4fAurimas Liutikas } 1815eb774884266e72b9e6f0caf79f4dc6b698d121cLeif Wilden} 182