1d6b29fd71beba98f01ece4b28b1826ed2b636b72Jan Clarin/*
2b1605287bf0093b6437545a326257b8814f654ebXyan Bhatnagar * Copyright 2017 The Android Open Source Project
3d6b29fd71beba98f01ece4b28b1826ed2b636b72Jan Clarin *
4d6b29fd71beba98f01ece4b28b1826ed2b636b72Jan Clarin * Licensed under the Apache License, Version 2.0 (the "License");
5d6b29fd71beba98f01ece4b28b1826ed2b636b72Jan Clarin * you may not use this file except in compliance with the License.
6d6b29fd71beba98f01ece4b28b1826ed2b636b72Jan Clarin * You may obtain a copy of the License at
7d6b29fd71beba98f01ece4b28b1826ed2b636b72Jan Clarin *
8d6b29fd71beba98f01ece4b28b1826ed2b636b72Jan Clarin *      http://www.apache.org/licenses/LICENSE-2.0
9d6b29fd71beba98f01ece4b28b1826ed2b636b72Jan Clarin *
10d6b29fd71beba98f01ece4b28b1826ed2b636b72Jan Clarin * Unless required by applicable law or agreed to in writing, software
11d6b29fd71beba98f01ece4b28b1826ed2b636b72Jan Clarin * distributed under the License is distributed on an "AS IS" BASIS,
12d6b29fd71beba98f01ece4b28b1826ed2b636b72Jan Clarin * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13d6b29fd71beba98f01ece4b28b1826ed2b636b72Jan Clarin * See the License for the specific language governing permissions and
14d6b29fd71beba98f01ece4b28b1826ed2b636b72Jan Clarin * limitations under the License.
15d6b29fd71beba98f01ece4b28b1826ed2b636b72Jan Clarin */
16d6b29fd71beba98f01ece4b28b1826ed2b636b72Jan Clarin
17564e43098c323d1a90be53c190b8fdbdde973505Sumir Katariapackage androidx.work.impl.utils;
18d6b29fd71beba98f01ece4b28b1826ed2b636b72Jan Clarin
1922a8129c2b3313100f851460f7da9e56ca98bd8fRahul Ravikumarimport static androidx.work.impl.utils.IdGenerator.INITIAL_ID;
2022a8129c2b3313100f851460f7da9e56ca98bd8fRahul Ravikumar
219e3c28e0e843b84a93cc6912ada4be871c10562dJan Clarinimport static org.hamcrest.CoreMatchers.is;
229e3c28e0e843b84a93cc6912ada4be871c10562dJan Clarinimport static org.hamcrest.MatcherAssert.assertThat;
23d6b29fd71beba98f01ece4b28b1826ed2b636b72Jan Clarinimport static org.mockito.ArgumentMatchers.anyInt;
24d6b29fd71beba98f01ece4b28b1826ed2b636b72Jan Clarinimport static org.mockito.ArgumentMatchers.eq;
25d6b29fd71beba98f01ece4b28b1826ed2b636b72Jan Clarinimport static org.mockito.Mockito.mock;
26d6b29fd71beba98f01ece4b28b1826ed2b636b72Jan Clarinimport static org.mockito.Mockito.when;
27d6b29fd71beba98f01ece4b28b1826ed2b636b72Jan Clarin
2822a8129c2b3313100f851460f7da9e56ca98bd8fRahul Ravikumarimport static java.lang.Integer.MAX_VALUE;
2922a8129c2b3313100f851460f7da9e56ca98bd8fRahul Ravikumar
30d6b29fd71beba98f01ece4b28b1826ed2b636b72Jan Clarinimport android.content.Context;
31d6b29fd71beba98f01ece4b28b1826ed2b636b72Jan Clarinimport android.content.SharedPreferences;
32a4353373922f5b8a9f853b6e95703d9a91111c72Sumir Katariaimport android.support.test.filters.SdkSuppress;
33d6b29fd71beba98f01ece4b28b1826ed2b636b72Jan Clarinimport android.support.test.filters.SmallTest;
34d6b29fd71beba98f01ece4b28b1826ed2b636b72Jan Clarinimport android.support.test.runner.AndroidJUnit4;
35d6b29fd71beba98f01ece4b28b1826ed2b636b72Jan Clarin
36b5728f4e1a4b3f4f1fabf033b1363ca6b1cffdefSumir Katariaimport androidx.work.impl.WorkManagerImpl;
37b5728f4e1a4b3f4f1fabf033b1363ca6b1cffdefSumir Kataria
38d6b29fd71beba98f01ece4b28b1826ed2b636b72Jan Clarinimport org.junit.Before;
39d6b29fd71beba98f01ece4b28b1826ed2b636b72Jan Clarinimport org.junit.Test;
40d6b29fd71beba98f01ece4b28b1826ed2b636b72Jan Clarinimport org.junit.runner.RunWith;
41d6b29fd71beba98f01ece4b28b1826ed2b636b72Jan Clarinimport org.mockito.invocation.InvocationOnMock;
42d6b29fd71beba98f01ece4b28b1826ed2b636b72Jan Clarinimport org.mockito.stubbing.Answer;
43d6b29fd71beba98f01ece4b28b1826ed2b636b72Jan Clarin
44d6b29fd71beba98f01ece4b28b1826ed2b636b72Jan Clarin@SmallTest
45d6b29fd71beba98f01ece4b28b1826ed2b636b72Jan Clarin@RunWith(AndroidJUnit4.class)
4690c024663706960aa738040824160d6d8f6df449Sumir Kataria@SdkSuppress(minSdkVersion = WorkManagerImpl.MIN_JOB_SCHEDULER_API_LEVEL)
47b1605287bf0093b6437545a326257b8814f654ebXyan Bhatnagarpublic class IdGeneratorTest {
48d6b29fd71beba98f01ece4b28b1826ed2b636b72Jan Clarin    private Integer mMockSharedPrefsNextId;
49b1605287bf0093b6437545a326257b8814f654ebXyan Bhatnagar    private IdGenerator mIdGenerator;
50d6b29fd71beba98f01ece4b28b1826ed2b636b72Jan Clarin
51d6b29fd71beba98f01ece4b28b1826ed2b636b72Jan Clarin    @Before
52d6b29fd71beba98f01ece4b28b1826ed2b636b72Jan Clarin    public void setUp() {
53d6b29fd71beba98f01ece4b28b1826ed2b636b72Jan Clarin        Context mMockContext = mock(Context.class);
54d6b29fd71beba98f01ece4b28b1826ed2b636b72Jan Clarin        SharedPreferences.Editor mockEditor = createMockSharedPreferencesEditor();
55d6b29fd71beba98f01ece4b28b1826ed2b636b72Jan Clarin        SharedPreferences mockSharedPrefs = createMockSharedPreferences(mockEditor);
56d6b29fd71beba98f01ece4b28b1826ed2b636b72Jan Clarin        when(mMockContext.getSharedPreferences(
57b1605287bf0093b6437545a326257b8814f654ebXyan Bhatnagar                eq(IdGenerator.PREFERENCE_FILE_KEY), anyInt()))
58d6b29fd71beba98f01ece4b28b1826ed2b636b72Jan Clarin                .thenReturn(mockSharedPrefs);
59b1605287bf0093b6437545a326257b8814f654ebXyan Bhatnagar        mIdGenerator = new IdGenerator(mMockContext);
60d6b29fd71beba98f01ece4b28b1826ed2b636b72Jan Clarin    }
61d6b29fd71beba98f01ece4b28b1826ed2b636b72Jan Clarin
62d6b29fd71beba98f01ece4b28b1826ed2b636b72Jan Clarin    @Test
63d6b29fd71beba98f01ece4b28b1826ed2b636b72Jan Clarin    public void testNextId_returnsInitialIdWhenNoStoredNextId() {
6422a8129c2b3313100f851460f7da9e56ca98bd8fRahul Ravikumar        int nextId = mIdGenerator.nextJobSchedulerIdWithRange(INITIAL_ID, MAX_VALUE);
6522a8129c2b3313100f851460f7da9e56ca98bd8fRahul Ravikumar        assertThat(nextId, is(INITIAL_ID));
66d6b29fd71beba98f01ece4b28b1826ed2b636b72Jan Clarin    }
67d6b29fd71beba98f01ece4b28b1826ed2b636b72Jan Clarin
68d6b29fd71beba98f01ece4b28b1826ed2b636b72Jan Clarin    @Test
69d6b29fd71beba98f01ece4b28b1826ed2b636b72Jan Clarin    public void testNextId_returnsStoredNextId() {
70d6b29fd71beba98f01ece4b28b1826ed2b636b72Jan Clarin        int expectedId = 100;
71d6b29fd71beba98f01ece4b28b1826ed2b636b72Jan Clarin        storeNextIdInSharedPrefs(expectedId);
7222a8129c2b3313100f851460f7da9e56ca98bd8fRahul Ravikumar        int nextId = mIdGenerator.nextJobSchedulerIdWithRange(INITIAL_ID, MAX_VALUE);
7322a8129c2b3313100f851460f7da9e56ca98bd8fRahul Ravikumar        assertThat(nextId, is(expectedId));
74d6b29fd71beba98f01ece4b28b1826ed2b636b72Jan Clarin    }
75d6b29fd71beba98f01ece4b28b1826ed2b636b72Jan Clarin
76d6b29fd71beba98f01ece4b28b1826ed2b636b72Jan Clarin    @Test
77d6b29fd71beba98f01ece4b28b1826ed2b636b72Jan Clarin    public void testNextId_returnsInitialIdAfterReturningMaxInteger() {
7822a8129c2b3313100f851460f7da9e56ca98bd8fRahul Ravikumar        int expectedId = MAX_VALUE;
79d6b29fd71beba98f01ece4b28b1826ed2b636b72Jan Clarin        storeNextIdInSharedPrefs(expectedId);
8022a8129c2b3313100f851460f7da9e56ca98bd8fRahul Ravikumar        int nextId = mIdGenerator.nextJobSchedulerIdWithRange(INITIAL_ID, MAX_VALUE);
8122a8129c2b3313100f851460f7da9e56ca98bd8fRahul Ravikumar        assertThat(nextId, is(MAX_VALUE));
8222a8129c2b3313100f851460f7da9e56ca98bd8fRahul Ravikumar        nextId = mIdGenerator.nextJobSchedulerIdWithRange(INITIAL_ID, MAX_VALUE);
8322a8129c2b3313100f851460f7da9e56ca98bd8fRahul Ravikumar        assertThat(nextId, is(INITIAL_ID));
8422a8129c2b3313100f851460f7da9e56ca98bd8fRahul Ravikumar    }
8522a8129c2b3313100f851460f7da9e56ca98bd8fRahul Ravikumar
8622a8129c2b3313100f851460f7da9e56ca98bd8fRahul Ravikumar    @Test
8722a8129c2b3313100f851460f7da9e56ca98bd8fRahul Ravikumar    public void testNextId_belowMinRange() {
8822a8129c2b3313100f851460f7da9e56ca98bd8fRahul Ravikumar        storeNextIdInSharedPrefs(2);
8922a8129c2b3313100f851460f7da9e56ca98bd8fRahul Ravikumar        assertThat(mIdGenerator.nextJobSchedulerIdWithRange(10, 100), is(10));
9022a8129c2b3313100f851460f7da9e56ca98bd8fRahul Ravikumar    }
9122a8129c2b3313100f851460f7da9e56ca98bd8fRahul Ravikumar
9222a8129c2b3313100f851460f7da9e56ca98bd8fRahul Ravikumar    @Test
9322a8129c2b3313100f851460f7da9e56ca98bd8fRahul Ravikumar    public void testNextId_aboveMaxRange() {
9422a8129c2b3313100f851460f7da9e56ca98bd8fRahul Ravikumar        storeNextIdInSharedPrefs(100);
9522a8129c2b3313100f851460f7da9e56ca98bd8fRahul Ravikumar        assertThat(mIdGenerator.nextJobSchedulerIdWithRange(10, 100), is(100));
9622a8129c2b3313100f851460f7da9e56ca98bd8fRahul Ravikumar    }
9722a8129c2b3313100f851460f7da9e56ca98bd8fRahul Ravikumar
9822a8129c2b3313100f851460f7da9e56ca98bd8fRahul Ravikumar    @Test
9922a8129c2b3313100f851460f7da9e56ca98bd8fRahul Ravikumar    public void testNextId_aboveMaxRange2() {
10022a8129c2b3313100f851460f7da9e56ca98bd8fRahul Ravikumar        storeNextIdInSharedPrefs(110);
10122a8129c2b3313100f851460f7da9e56ca98bd8fRahul Ravikumar        assertThat(mIdGenerator.nextJobSchedulerIdWithRange(10, 100), is(10));
10222a8129c2b3313100f851460f7da9e56ca98bd8fRahul Ravikumar    }
10322a8129c2b3313100f851460f7da9e56ca98bd8fRahul Ravikumar
10422a8129c2b3313100f851460f7da9e56ca98bd8fRahul Ravikumar    @Test
10522a8129c2b3313100f851460f7da9e56ca98bd8fRahul Ravikumar    public void testNextId_withinRange() {
10622a8129c2b3313100f851460f7da9e56ca98bd8fRahul Ravikumar        storeNextIdInSharedPrefs(20);
10722a8129c2b3313100f851460f7da9e56ca98bd8fRahul Ravikumar        assertThat(mIdGenerator.nextJobSchedulerIdWithRange(10, 100), is(20));
108d6b29fd71beba98f01ece4b28b1826ed2b636b72Jan Clarin    }
109d6b29fd71beba98f01ece4b28b1826ed2b636b72Jan Clarin
110d6b29fd71beba98f01ece4b28b1826ed2b636b72Jan Clarin    /**
111d6b29fd71beba98f01ece4b28b1826ed2b636b72Jan Clarin     * Mocks setting a stored value in {@link SharedPreferences} for the next ID.
112d6b29fd71beba98f01ece4b28b1826ed2b636b72Jan Clarin     *
113d6b29fd71beba98f01ece4b28b1826ed2b636b72Jan Clarin     * @param nextId The next ID to store in {@link SharedPreferences}.
114d6b29fd71beba98f01ece4b28b1826ed2b636b72Jan Clarin     */
115d6b29fd71beba98f01ece4b28b1826ed2b636b72Jan Clarin    private void storeNextIdInSharedPrefs(int nextId) {
116d6b29fd71beba98f01ece4b28b1826ed2b636b72Jan Clarin        mMockSharedPrefsNextId = nextId;
117d6b29fd71beba98f01ece4b28b1826ed2b636b72Jan Clarin    }
118d6b29fd71beba98f01ece4b28b1826ed2b636b72Jan Clarin
119d6b29fd71beba98f01ece4b28b1826ed2b636b72Jan Clarin    private SharedPreferences createMockSharedPreferences(SharedPreferences.Editor mockEditor) {
120d6b29fd71beba98f01ece4b28b1826ed2b636b72Jan Clarin        final SharedPreferences mockSharedPreferences = mock(SharedPreferences.class);
121d6b29fd71beba98f01ece4b28b1826ed2b636b72Jan Clarin        when(mockSharedPreferences.edit()).thenReturn(mockEditor);
122b1605287bf0093b6437545a326257b8814f654ebXyan Bhatnagar        when(mockSharedPreferences.getInt(eq(IdGenerator.NEXT_JOB_SCHEDULER_ID_KEY), anyInt()))
123d6b29fd71beba98f01ece4b28b1826ed2b636b72Jan Clarin                .thenAnswer(new Answer<Integer>() {
124d6b29fd71beba98f01ece4b28b1826ed2b636b72Jan Clarin                    @Override
125d6b29fd71beba98f01ece4b28b1826ed2b636b72Jan Clarin                    public Integer answer(InvocationOnMock invocation) throws Throwable {
126d6b29fd71beba98f01ece4b28b1826ed2b636b72Jan Clarin                        int defValue = invocation.getArgument(1);
127d6b29fd71beba98f01ece4b28b1826ed2b636b72Jan Clarin                        return (mMockSharedPrefsNextId == null) ? defValue : mMockSharedPrefsNextId;
128d6b29fd71beba98f01ece4b28b1826ed2b636b72Jan Clarin                    }
129d6b29fd71beba98f01ece4b28b1826ed2b636b72Jan Clarin                });
130d6b29fd71beba98f01ece4b28b1826ed2b636b72Jan Clarin        return mockSharedPreferences;
131d6b29fd71beba98f01ece4b28b1826ed2b636b72Jan Clarin    }
132d6b29fd71beba98f01ece4b28b1826ed2b636b72Jan Clarin
133d6b29fd71beba98f01ece4b28b1826ed2b636b72Jan Clarin    private SharedPreferences.Editor createMockSharedPreferencesEditor() {
134d6b29fd71beba98f01ece4b28b1826ed2b636b72Jan Clarin        final SharedPreferences.Editor mockEditor = mock(SharedPreferences.Editor.class);
135b1605287bf0093b6437545a326257b8814f654ebXyan Bhatnagar        when(mockEditor.putInt(eq(IdGenerator.NEXT_JOB_SCHEDULER_ID_KEY), anyInt())).thenAnswer(
136d6b29fd71beba98f01ece4b28b1826ed2b636b72Jan Clarin                new Answer<SharedPreferences.Editor>() {
137d6b29fd71beba98f01ece4b28b1826ed2b636b72Jan Clarin                    @Override
138d6b29fd71beba98f01ece4b28b1826ed2b636b72Jan Clarin                    public SharedPreferences.Editor answer(InvocationOnMock invocation)
139d6b29fd71beba98f01ece4b28b1826ed2b636b72Jan Clarin                            throws Throwable {
140d6b29fd71beba98f01ece4b28b1826ed2b636b72Jan Clarin                        mMockSharedPrefsNextId = invocation.getArgument(1);
141d6b29fd71beba98f01ece4b28b1826ed2b636b72Jan Clarin                        return mockEditor;
142d6b29fd71beba98f01ece4b28b1826ed2b636b72Jan Clarin                    }
143d6b29fd71beba98f01ece4b28b1826ed2b636b72Jan Clarin                });
144d6b29fd71beba98f01ece4b28b1826ed2b636b72Jan Clarin        return mockEditor;
145d6b29fd71beba98f01ece4b28b1826ed2b636b72Jan Clarin    }
146d6b29fd71beba98f01ece4b28b1826ed2b636b72Jan Clarin}
147