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