144235b3ed93a4783f6bb1f3979779ee039289bfcRahul Ravikumar/*
244235b3ed93a4783f6bb1f3979779ee039289bfcRahul Ravikumar * Copyright 2018 The Android Open Source Project
344235b3ed93a4783f6bb1f3979779ee039289bfcRahul Ravikumar *
444235b3ed93a4783f6bb1f3979779ee039289bfcRahul Ravikumar * Licensed under the Apache License, Version 2.0 (the "License");
544235b3ed93a4783f6bb1f3979779ee039289bfcRahul Ravikumar * you may not use this file except in compliance with the License.
644235b3ed93a4783f6bb1f3979779ee039289bfcRahul Ravikumar * You may obtain a copy of the License at
744235b3ed93a4783f6bb1f3979779ee039289bfcRahul Ravikumar *
844235b3ed93a4783f6bb1f3979779ee039289bfcRahul Ravikumar *      http://www.apache.org/licenses/LICENSE-2.0
944235b3ed93a4783f6bb1f3979779ee039289bfcRahul Ravikumar *
1044235b3ed93a4783f6bb1f3979779ee039289bfcRahul Ravikumar * Unless required by applicable law or agreed to in writing, software
1144235b3ed93a4783f6bb1f3979779ee039289bfcRahul Ravikumar * distributed under the License is distributed on an "AS IS" BASIS,
1244235b3ed93a4783f6bb1f3979779ee039289bfcRahul Ravikumar * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
1344235b3ed93a4783f6bb1f3979779ee039289bfcRahul Ravikumar * See the License for the specific language governing permissions and
1444235b3ed93a4783f6bb1f3979779ee039289bfcRahul Ravikumar * limitations under the License.
1544235b3ed93a4783f6bb1f3979779ee039289bfcRahul Ravikumar */
1644235b3ed93a4783f6bb1f3979779ee039289bfcRahul Ravikumar
17564e43098c323d1a90be53c190b8fdbdde973505Sumir Katariapackage androidx.work.impl;
1844235b3ed93a4783f6bb1f3979779ee039289bfcRahul Ravikumar
1987d37e5587b277ba523d69df71e17a4039274cdaRahul Ravikumarimport static org.hamcrest.CoreMatchers.is;
2087e8dc0458781cd41a5ee990be811790ac7f4e88Sumir Katariaimport static org.hamcrest.CoreMatchers.not;
2187d37e5587b277ba523d69df71e17a4039274cdaRahul Ravikumarimport static org.hamcrest.CoreMatchers.notNullValue;
2287d37e5587b277ba523d69df71e17a4039274cdaRahul Ravikumarimport static org.hamcrest.CoreMatchers.nullValue;
2387d37e5587b277ba523d69df71e17a4039274cdaRahul Ravikumarimport static org.hamcrest.MatcherAssert.assertThat;
2487e8dc0458781cd41a5ee990be811790ac7f4e88Sumir Katariaimport static org.hamcrest.Matchers.contains;
2587d37e5587b277ba523d69df71e17a4039274cdaRahul Ravikumarimport static org.hamcrest.Matchers.containsInAnyOrder;
260c252a21d65ac58c2a19540bd6af9ffdd77b1e94Rahul Ravikumarimport static org.mockito.Mockito.mock;
2787d37e5587b277ba523d69df71e17a4039274cdaRahul Ravikumarimport static org.mockito.Mockito.spy;
2844235b3ed93a4783f6bb1f3979779ee039289bfcRahul Ravikumarimport static org.mockito.Mockito.times;
2944235b3ed93a4783f6bb1f3979779ee039289bfcRahul Ravikumarimport static org.mockito.Mockito.verify;
300c252a21d65ac58c2a19540bd6af9ffdd77b1e94Rahul Ravikumarimport static org.mockito.Mockito.when;
3144235b3ed93a4783f6bb1f3979779ee039289bfcRahul Ravikumar
3287d37e5587b277ba523d69df71e17a4039274cdaRahul Ravikumarimport android.arch.core.executor.ArchTaskExecutor;
3387d37e5587b277ba523d69df71e17a4039274cdaRahul Ravikumarimport android.arch.lifecycle.Lifecycle;
3487d37e5587b277ba523d69df71e17a4039274cdaRahul Ravikumarimport android.content.Context;
3587d37e5587b277ba523d69df71e17a4039274cdaRahul Ravikumarimport android.support.annotation.NonNull;
3687d37e5587b277ba523d69df71e17a4039274cdaRahul Ravikumarimport android.support.test.InstrumentationRegistry;
372574ac4ac18d2bb4ceeae795a213d86c3a70fc68Rahul Ravikumarimport android.support.test.filters.LargeTest;
3844235b3ed93a4783f6bb1f3979779ee039289bfcRahul Ravikumarimport android.support.test.filters.SmallTest;
3944235b3ed93a4783f6bb1f3979779ee039289bfcRahul Ravikumarimport android.support.test.runner.AndroidJUnit4;
4044235b3ed93a4783f6bb1f3979779ee039289bfcRahul Ravikumar
417f44b37e7640e4b91656e024d1754fa7a062a833Sumir Katariaimport androidx.work.Configuration;
4264e6bd86c786f1cb1b0c3dbc2b5307cca5c0d1f6Sumir Katariaimport androidx.work.Data;
437031a0fbe12b8159ab2dc6d9c50be5b3f38477faRahul Ravikumarimport androidx.work.OneTimeWorkRequest;
4487e8dc0458781cd41a5ee990be811790ac7f4e88Sumir Katariaimport androidx.work.State;
4587e8dc0458781cd41a5ee990be811790ac7f4e88Sumir Katariaimport androidx.work.TestLifecycleOwner;
4687e8dc0458781cd41a5ee990be811790ac7f4e88Sumir Katariaimport androidx.work.WorkContinuation;
4787e8dc0458781cd41a5ee990be811790ac7f4e88Sumir Katariaimport androidx.work.WorkManagerTest;
485a4ced8020d8a3ee4b9100b97559db3d1fb5132bRahul Ravikumarimport androidx.work.WorkStatus;
4987e8dc0458781cd41a5ee990be811790ac7f4e88Sumir Katariaimport androidx.work.impl.model.WorkSpec;
5087e8dc0458781cd41a5ee990be811790ac7f4e88Sumir Katariaimport androidx.work.impl.model.WorkSpecDao;
5187e8dc0458781cd41a5ee990be811790ac7f4e88Sumir Katariaimport androidx.work.impl.utils.taskexecutor.InstantTaskExecutorRule;
5287e8dc0458781cd41a5ee990be811790ac7f4e88Sumir Katariaimport androidx.work.worker.TestWorker;
5387e8dc0458781cd41a5ee990be811790ac7f4e88Sumir Kataria
5487d37e5587b277ba523d69df71e17a4039274cdaRahul Ravikumarimport org.junit.After;
5544235b3ed93a4783f6bb1f3979779ee039289bfcRahul Ravikumarimport org.junit.Before;
5687d37e5587b277ba523d69df71e17a4039274cdaRahul Ravikumarimport org.junit.Rule;
5744235b3ed93a4783f6bb1f3979779ee039289bfcRahul Ravikumarimport org.junit.Test;
5844235b3ed93a4783f6bb1f3979779ee039289bfcRahul Ravikumarimport org.junit.runner.RunWith;
590c252a21d65ac58c2a19540bd6af9ffdd77b1e94Rahul Ravikumarimport org.mockito.ArgumentCaptor;
6044235b3ed93a4783f6bb1f3979779ee039289bfcRahul Ravikumar
615a4ced8020d8a3ee4b9100b97559db3d1fb5132bRahul Ravikumarimport java.util.ArrayList;
6287e8dc0458781cd41a5ee990be811790ac7f4e88Sumir Katariaimport java.util.Arrays;
6351b5cd2bc8a7fb7979e2bcd731fc8fd0d195f860Sumir Katariaimport java.util.Collections;
640c252a21d65ac58c2a19540bd6af9ffdd77b1e94Rahul Ravikumarimport java.util.HashSet;
6587d37e5587b277ba523d69df71e17a4039274cdaRahul Ravikumarimport java.util.List;
660c252a21d65ac58c2a19540bd6af9ffdd77b1e94Rahul Ravikumarimport java.util.Set;
67fa284c943bd003ff03f1934370d70bd4a5e034c3Sumir Katariaimport java.util.UUID;
68137c84c9c8212a44ee81c238a1a2271637ffa24bSumir Katariaimport java.util.concurrent.Executors;
6987d37e5587b277ba523d69df71e17a4039274cdaRahul Ravikumar
7044235b3ed93a4783f6bb1f3979779ee039289bfcRahul Ravikumar
7144235b3ed93a4783f6bb1f3979779ee039289bfcRahul Ravikumar@RunWith(AndroidJUnit4.class)
7244235b3ed93a4783f6bb1f3979779ee039289bfcRahul Ravikumar@SmallTest
7387e8dc0458781cd41a5ee990be811790ac7f4e88Sumir Katariapublic class WorkContinuationImplTest extends WorkManagerTest {
7444235b3ed93a4783f6bb1f3979779ee039289bfcRahul Ravikumar
75e326592ec414dfe4c002e2840d9fc4aef0ee8747Rahul Ravikumar    private Configuration mConfiguration;
7687d37e5587b277ba523d69df71e17a4039274cdaRahul Ravikumar    private WorkDatabase mDatabase;
7744235b3ed93a4783f6bb1f3979779ee039289bfcRahul Ravikumar    private WorkManagerImpl mWorkManagerImpl;
780c252a21d65ac58c2a19540bd6af9ffdd77b1e94Rahul Ravikumar    private Scheduler mScheduler;
7987d37e5587b277ba523d69df71e17a4039274cdaRahul Ravikumar
8087d37e5587b277ba523d69df71e17a4039274cdaRahul Ravikumar    @Rule
8187d37e5587b277ba523d69df71e17a4039274cdaRahul Ravikumar    public InstantTaskExecutorRule mRule = new InstantTaskExecutorRule();
8244235b3ed93a4783f6bb1f3979779ee039289bfcRahul Ravikumar
8344235b3ed93a4783f6bb1f3979779ee039289bfcRahul Ravikumar    @Before
8487d37e5587b277ba523d69df71e17a4039274cdaRahul Ravikumar    public void setUp() {
8587d37e5587b277ba523d69df71e17a4039274cdaRahul Ravikumar        ArchTaskExecutor.getInstance().setDelegate(new android.arch.core.executor.TaskExecutor() {
8687d37e5587b277ba523d69df71e17a4039274cdaRahul Ravikumar            @Override
8787d37e5587b277ba523d69df71e17a4039274cdaRahul Ravikumar            public void executeOnDiskIO(@NonNull Runnable runnable) {
8887d37e5587b277ba523d69df71e17a4039274cdaRahul Ravikumar                runnable.run();
8987d37e5587b277ba523d69df71e17a4039274cdaRahul Ravikumar            }
9087d37e5587b277ba523d69df71e17a4039274cdaRahul Ravikumar
9187d37e5587b277ba523d69df71e17a4039274cdaRahul Ravikumar            @Override
9287d37e5587b277ba523d69df71e17a4039274cdaRahul Ravikumar            public void postToMainThread(@NonNull Runnable runnable) {
9387d37e5587b277ba523d69df71e17a4039274cdaRahul Ravikumar                runnable.run();
9487d37e5587b277ba523d69df71e17a4039274cdaRahul Ravikumar            }
9587d37e5587b277ba523d69df71e17a4039274cdaRahul Ravikumar
9687d37e5587b277ba523d69df71e17a4039274cdaRahul Ravikumar            @Override
9787d37e5587b277ba523d69df71e17a4039274cdaRahul Ravikumar            public boolean isMainThread() {
9887d37e5587b277ba523d69df71e17a4039274cdaRahul Ravikumar                return true;
9987d37e5587b277ba523d69df71e17a4039274cdaRahul Ravikumar            }
10087d37e5587b277ba523d69df71e17a4039274cdaRahul Ravikumar        });
10187d37e5587b277ba523d69df71e17a4039274cdaRahul Ravikumar
10287d37e5587b277ba523d69df71e17a4039274cdaRahul Ravikumar        TestLifecycleOwner lifecycleOwner = new TestLifecycleOwner();
10387d37e5587b277ba523d69df71e17a4039274cdaRahul Ravikumar        lifecycleOwner.mLifecycleRegistry.markState(Lifecycle.State.CREATED);
10487d37e5587b277ba523d69df71e17a4039274cdaRahul Ravikumar
1050c252a21d65ac58c2a19540bd6af9ffdd77b1e94Rahul Ravikumar        mScheduler = mock(Scheduler.class);
10687d37e5587b277ba523d69df71e17a4039274cdaRahul Ravikumar        Context context = InstrumentationRegistry.getTargetContext();
107e326592ec414dfe4c002e2840d9fc4aef0ee8747Rahul Ravikumar        mConfiguration = new Configuration.Builder()
108b9490b789c8cba57b58cb8404463c0b83fb89074Rahul Ravikumar                .setExecutor(Executors.newSingleThreadExecutor())
1097f44b37e7640e4b91656e024d1754fa7a062a833Sumir Kataria                .build();
1100c252a21d65ac58c2a19540bd6af9ffdd77b1e94Rahul Ravikumar
111e326592ec414dfe4c002e2840d9fc4aef0ee8747Rahul Ravikumar        mWorkManagerImpl = spy(new WorkManagerImpl(context, mConfiguration));
1120c252a21d65ac58c2a19540bd6af9ffdd77b1e94Rahul Ravikumar        when(mWorkManagerImpl.getSchedulers()).thenReturn(Collections.singletonList(mScheduler));
113cc86a28f45a8393bb14b1945dfe5b35ec44a190bSumir Kataria        WorkManagerImpl.setDelegate(mWorkManagerImpl);
11487d37e5587b277ba523d69df71e17a4039274cdaRahul Ravikumar        mDatabase = mWorkManagerImpl.getWorkDatabase();
11587d37e5587b277ba523d69df71e17a4039274cdaRahul Ravikumar    }
11687d37e5587b277ba523d69df71e17a4039274cdaRahul Ravikumar
11787d37e5587b277ba523d69df71e17a4039274cdaRahul Ravikumar    @After
11887d37e5587b277ba523d69df71e17a4039274cdaRahul Ravikumar    public void tearDown() {
11987d37e5587b277ba523d69df71e17a4039274cdaRahul Ravikumar        List<String> ids = mDatabase.workSpecDao().getAllWorkSpecIds();
12087d37e5587b277ba523d69df71e17a4039274cdaRahul Ravikumar        for (String id : ids) {
121fa284c943bd003ff03f1934370d70bd4a5e034c3Sumir Kataria            mWorkManagerImpl.cancelWorkByIdSync(UUID.fromString(id));
12287d37e5587b277ba523d69df71e17a4039274cdaRahul Ravikumar        }
123cc86a28f45a8393bb14b1945dfe5b35ec44a190bSumir Kataria        WorkManagerImpl.setDelegate(null);
12487d37e5587b277ba523d69df71e17a4039274cdaRahul Ravikumar        ArchTaskExecutor.getInstance().setDelegate(null);
12544235b3ed93a4783f6bb1f3979779ee039289bfcRahul Ravikumar    }
12644235b3ed93a4783f6bb1f3979779ee039289bfcRahul Ravikumar
12744235b3ed93a4783f6bb1f3979779ee039289bfcRahul Ravikumar    @Test
12887d37e5587b277ba523d69df71e17a4039274cdaRahul Ravikumar    public void testContinuation_noParent() {
1297031a0fbe12b8159ab2dc6d9c50be5b3f38477faRahul Ravikumar        OneTimeWorkRequest testWork = createTestWorker();
13087d37e5587b277ba523d69df71e17a4039274cdaRahul Ravikumar        WorkContinuationImpl continuation =
13151b5cd2bc8a7fb7979e2bcd731fc8fd0d195f860Sumir Kataria                new WorkContinuationImpl(mWorkManagerImpl, Collections.singletonList(testWork));
13244235b3ed93a4783f6bb1f3979779ee039289bfcRahul Ravikumar
13359cbb5756e54d32fb51e72fe1ed94934c93f7303Rahul Ravikumar        assertThat(continuation.getParents(), is(nullValue()));
13459cbb5756e54d32fb51e72fe1ed94934c93f7303Rahul Ravikumar        assertThat(continuation.getIds().size(), is(1));
135fa284c943bd003ff03f1934370d70bd4a5e034c3Sumir Kataria        assertThat(continuation.getIds().get(0), is(testWork.getStringId()));
13687d37e5587b277ba523d69df71e17a4039274cdaRahul Ravikumar        assertThat(continuation.getAllIds().size(), is(1));
13744235b3ed93a4783f6bb1f3979779ee039289bfcRahul Ravikumar    }
13844235b3ed93a4783f6bb1f3979779ee039289bfcRahul Ravikumar
13944235b3ed93a4783f6bb1f3979779ee039289bfcRahul Ravikumar    @Test
14087d37e5587b277ba523d69df71e17a4039274cdaRahul Ravikumar    public void testContinuation_singleChain() {
1417031a0fbe12b8159ab2dc6d9c50be5b3f38477faRahul Ravikumar        OneTimeWorkRequest testWork = createTestWorker();
1427031a0fbe12b8159ab2dc6d9c50be5b3f38477faRahul Ravikumar        OneTimeWorkRequest dependentWork = createTestWorker();
143b776ef68aac1def7eeda4a1f14b7364009302982Sumir Kataria        WorkContinuationImpl continuation =
14451b5cd2bc8a7fb7979e2bcd731fc8fd0d195f860Sumir Kataria                new WorkContinuationImpl(mWorkManagerImpl, Collections.singletonList(testWork));
145b776ef68aac1def7eeda4a1f14b7364009302982Sumir Kataria        WorkContinuationImpl dependent = (WorkContinuationImpl) (continuation.then(
14644235b3ed93a4783f6bb1f3979779ee039289bfcRahul Ravikumar                dependentWork));
14744235b3ed93a4783f6bb1f3979779ee039289bfcRahul Ravikumar
14859cbb5756e54d32fb51e72fe1ed94934c93f7303Rahul Ravikumar        assertThat(dependent.getParents(), containsInAnyOrder(continuation));
14959cbb5756e54d32fb51e72fe1ed94934c93f7303Rahul Ravikumar        assertThat(dependent.getIds().size(), is(1));
150fa284c943bd003ff03f1934370d70bd4a5e034c3Sumir Kataria        assertThat(dependent.getIds().get(0), is(dependentWork.getStringId()));
15187d37e5587b277ba523d69df71e17a4039274cdaRahul Ravikumar        assertThat(dependent.getAllIds().size(), is(2));
15287d37e5587b277ba523d69df71e17a4039274cdaRahul Ravikumar        assertThat(
15387d37e5587b277ba523d69df71e17a4039274cdaRahul Ravikumar                dependent.getAllIds(),
154fa284c943bd003ff03f1934370d70bd4a5e034c3Sumir Kataria                containsInAnyOrder(dependentWork.getStringId(), testWork.getStringId()));
15544235b3ed93a4783f6bb1f3979779ee039289bfcRahul Ravikumar    }
15644235b3ed93a4783f6bb1f3979779ee039289bfcRahul Ravikumar
15744235b3ed93a4783f6bb1f3979779ee039289bfcRahul Ravikumar    @Test
15887d37e5587b277ba523d69df71e17a4039274cdaRahul Ravikumar    public void testContinuation_enqueue() {
159b776ef68aac1def7eeda4a1f14b7364009302982Sumir Kataria        WorkContinuationImpl continuation = new WorkContinuationImpl(mWorkManagerImpl,
16051b5cd2bc8a7fb7979e2bcd731fc8fd0d195f860Sumir Kataria                createTestWorkerList());
16187d37e5587b277ba523d69df71e17a4039274cdaRahul Ravikumar        assertThat(continuation.isEnqueued(), is(false));
16262e0be94ea7e54ca9227564b14c1c6736ae770f7Sumir Kataria        continuation.enqueueSync();
16344235b3ed93a4783f6bb1f3979779ee039289bfcRahul Ravikumar        verifyEnqueued(continuation);
1640c252a21d65ac58c2a19540bd6af9ffdd77b1e94Rahul Ravikumar        verifyScheduled(mScheduler, continuation);
16544235b3ed93a4783f6bb1f3979779ee039289bfcRahul Ravikumar    }
16644235b3ed93a4783f6bb1f3979779ee039289bfcRahul Ravikumar
16744235b3ed93a4783f6bb1f3979779ee039289bfcRahul Ravikumar    @Test
16887d37e5587b277ba523d69df71e17a4039274cdaRahul Ravikumar    public void testContinuation_chainEnqueue() {
169b776ef68aac1def7eeda4a1f14b7364009302982Sumir Kataria        WorkContinuationImpl continuation =
17051b5cd2bc8a7fb7979e2bcd731fc8fd0d195f860Sumir Kataria                new WorkContinuationImpl(mWorkManagerImpl, createTestWorkerList());
171b776ef68aac1def7eeda4a1f14b7364009302982Sumir Kataria        WorkContinuationImpl chain = (WorkContinuationImpl) (
17244235b3ed93a4783f6bb1f3979779ee039289bfcRahul Ravikumar                continuation.then(createTestWorker()).then(createTestWorker(), createTestWorker()));
17362e0be94ea7e54ca9227564b14c1c6736ae770f7Sumir Kataria        chain.enqueueSync();
17444235b3ed93a4783f6bb1f3979779ee039289bfcRahul Ravikumar        verifyEnqueued(continuation);
1750c252a21d65ac58c2a19540bd6af9ffdd77b1e94Rahul Ravikumar        verifyScheduled(mScheduler, continuation);
17644235b3ed93a4783f6bb1f3979779ee039289bfcRahul Ravikumar    }
17744235b3ed93a4783f6bb1f3979779ee039289bfcRahul Ravikumar
17844235b3ed93a4783f6bb1f3979779ee039289bfcRahul Ravikumar    @Test
17987d37e5587b277ba523d69df71e17a4039274cdaRahul Ravikumar    public void testContinuation_chainEnqueueNoOpOnRetry() {
180b776ef68aac1def7eeda4a1f14b7364009302982Sumir Kataria        WorkContinuationImpl continuation =
18151b5cd2bc8a7fb7979e2bcd731fc8fd0d195f860Sumir Kataria                new WorkContinuationImpl(mWorkManagerImpl, createTestWorkerList());
182b776ef68aac1def7eeda4a1f14b7364009302982Sumir Kataria        WorkContinuationImpl chain = (WorkContinuationImpl) (
18344235b3ed93a4783f6bb1f3979779ee039289bfcRahul Ravikumar                continuation.then(createTestWorker()).then(createTestWorker(), createTestWorker()));
18462e0be94ea7e54ca9227564b14c1c6736ae770f7Sumir Kataria        chain.enqueueSync();
18544235b3ed93a4783f6bb1f3979779ee039289bfcRahul Ravikumar        verifyEnqueued(continuation);
1860c252a21d65ac58c2a19540bd6af9ffdd77b1e94Rahul Ravikumar        verifyScheduled(mScheduler, continuation);
18787d37e5587b277ba523d69df71e17a4039274cdaRahul Ravikumar        WorkContinuationImpl spy = spy(chain);
18862e0be94ea7e54ca9227564b14c1c6736ae770f7Sumir Kataria        spy.enqueueSync();
18987d37e5587b277ba523d69df71e17a4039274cdaRahul Ravikumar        // Verify no more calls to markEnqueued().
19087d37e5587b277ba523d69df71e17a4039274cdaRahul Ravikumar        verify(spy, times(0)).markEnqueued();
19144235b3ed93a4783f6bb1f3979779ee039289bfcRahul Ravikumar    }
19244235b3ed93a4783f6bb1f3979779ee039289bfcRahul Ravikumar
19359cbb5756e54d32fb51e72fe1ed94934c93f7303Rahul Ravikumar    @Test
19459cbb5756e54d32fb51e72fe1ed94934c93f7303Rahul Ravikumar    public void testContinuation_join() {
19559cbb5756e54d32fb51e72fe1ed94934c93f7303Rahul Ravikumar        WorkContinuationImpl first = new WorkContinuationImpl(mWorkManagerImpl,
19651b5cd2bc8a7fb7979e2bcd731fc8fd0d195f860Sumir Kataria                createTestWorkerList());
19759cbb5756e54d32fb51e72fe1ed94934c93f7303Rahul Ravikumar        WorkContinuationImpl second = new WorkContinuationImpl(mWorkManagerImpl,
19851b5cd2bc8a7fb7979e2bcd731fc8fd0d195f860Sumir Kataria                createTestWorkerList());
199930c8fb091c540642a0002e89eebb35c9eb88205Rahul Ravikumar
20055a030183e5b974f3ebf04ef5cd9ab83f3557dadSumir Kataria        WorkContinuationImpl dependent = (WorkContinuationImpl) WorkContinuation.combine(first,
20159cbb5756e54d32fb51e72fe1ed94934c93f7303Rahul Ravikumar                second);
20259cbb5756e54d32fb51e72fe1ed94934c93f7303Rahul Ravikumar        assertThat(dependent.getParents(), is(notNullValue()));
20359cbb5756e54d32fb51e72fe1ed94934c93f7303Rahul Ravikumar        assertThat(dependent.getParents(), containsInAnyOrder(first, second));
20459cbb5756e54d32fb51e72fe1ed94934c93f7303Rahul Ravikumar    }
20559cbb5756e54d32fb51e72fe1ed94934c93f7303Rahul Ravikumar
206930c8fb091c540642a0002e89eebb35c9eb88205Rahul Ravikumar    public void testContinuation_withWorkJoin() {
207930c8fb091c540642a0002e89eebb35c9eb88205Rahul Ravikumar        WorkContinuationImpl first = new WorkContinuationImpl(mWorkManagerImpl,
20851b5cd2bc8a7fb7979e2bcd731fc8fd0d195f860Sumir Kataria                createTestWorkerList());
209930c8fb091c540642a0002e89eebb35c9eb88205Rahul Ravikumar        WorkContinuationImpl second = new WorkContinuationImpl(mWorkManagerImpl,
21051b5cd2bc8a7fb7979e2bcd731fc8fd0d195f860Sumir Kataria                createTestWorkerList());
211930c8fb091c540642a0002e89eebb35c9eb88205Rahul Ravikumar
2127031a0fbe12b8159ab2dc6d9c50be5b3f38477faRahul Ravikumar        OneTimeWorkRequest work = createTestWorker();
213930c8fb091c540642a0002e89eebb35c9eb88205Rahul Ravikumar
21455a030183e5b974f3ebf04ef5cd9ab83f3557dadSumir Kataria        WorkContinuationImpl dependent = (WorkContinuationImpl) WorkContinuation.combine(
21555a030183e5b974f3ebf04ef5cd9ab83f3557dadSumir Kataria                work, first, second);
216930c8fb091c540642a0002e89eebb35c9eb88205Rahul Ravikumar
217fa284c943bd003ff03f1934370d70bd4a5e034c3Sumir Kataria        assertThat(dependent.getIds(), containsInAnyOrder(work.getStringId()));
218930c8fb091c540642a0002e89eebb35c9eb88205Rahul Ravikumar        assertThat(dependent.getParents(), is(notNullValue()));
219930c8fb091c540642a0002e89eebb35c9eb88205Rahul Ravikumar        assertThat(dependent.getParents(), containsInAnyOrder(first, second));
220930c8fb091c540642a0002e89eebb35c9eb88205Rahul Ravikumar    }
221930c8fb091c540642a0002e89eebb35c9eb88205Rahul Ravikumar
22259cbb5756e54d32fb51e72fe1ed94934c93f7303Rahul Ravikumar    @Test
22359cbb5756e54d32fb51e72fe1ed94934c93f7303Rahul Ravikumar    public void testContinuation_joinAndEnqueue() {
22459cbb5756e54d32fb51e72fe1ed94934c93f7303Rahul Ravikumar        WorkContinuationImpl first = new WorkContinuationImpl(mWorkManagerImpl,
22551b5cd2bc8a7fb7979e2bcd731fc8fd0d195f860Sumir Kataria                createTestWorkerList());
22659cbb5756e54d32fb51e72fe1ed94934c93f7303Rahul Ravikumar        WorkContinuationImpl second = new WorkContinuationImpl(mWorkManagerImpl,
22751b5cd2bc8a7fb7979e2bcd731fc8fd0d195f860Sumir Kataria                createTestWorkerList());
22859cbb5756e54d32fb51e72fe1ed94934c93f7303Rahul Ravikumar
22959cbb5756e54d32fb51e72fe1ed94934c93f7303Rahul Ravikumar        WorkContinuationImpl third = new WorkContinuationImpl(mWorkManagerImpl,
23051b5cd2bc8a7fb7979e2bcd731fc8fd0d195f860Sumir Kataria                createTestWorkerList());
23159cbb5756e54d32fb51e72fe1ed94934c93f7303Rahul Ravikumar        WorkContinuationImpl fourth = new WorkContinuationImpl(mWorkManagerImpl,
23251b5cd2bc8a7fb7979e2bcd731fc8fd0d195f860Sumir Kataria                createTestWorkerList());
23359cbb5756e54d32fb51e72fe1ed94934c93f7303Rahul Ravikumar
23455a030183e5b974f3ebf04ef5cd9ab83f3557dadSumir Kataria        WorkContinuationImpl firstDependent = (WorkContinuationImpl) WorkContinuation.combine(
23555a030183e5b974f3ebf04ef5cd9ab83f3557dadSumir Kataria                first, second);
23655a030183e5b974f3ebf04ef5cd9ab83f3557dadSumir Kataria        WorkContinuationImpl secondDependent = (WorkContinuationImpl) WorkContinuation.combine(
23755a030183e5b974f3ebf04ef5cd9ab83f3557dadSumir Kataria                third, fourth);
23855a030183e5b974f3ebf04ef5cd9ab83f3557dadSumir Kataria        WorkContinuationImpl dependent = (WorkContinuationImpl) WorkContinuation.combine(
23959cbb5756e54d32fb51e72fe1ed94934c93f7303Rahul Ravikumar                firstDependent, secondDependent);
24062e0be94ea7e54ca9227564b14c1c6736ae770f7Sumir Kataria        dependent.enqueueSync();
24159cbb5756e54d32fb51e72fe1ed94934c93f7303Rahul Ravikumar        verifyEnqueued(dependent);
2420c252a21d65ac58c2a19540bd6af9ffdd77b1e94Rahul Ravikumar        verifyScheduled(mScheduler, dependent);
24359cbb5756e54d32fb51e72fe1ed94934c93f7303Rahul Ravikumar    }
24459cbb5756e54d32fb51e72fe1ed94934c93f7303Rahul Ravikumar
24559cbb5756e54d32fb51e72fe1ed94934c93f7303Rahul Ravikumar    @Test
24659cbb5756e54d32fb51e72fe1ed94934c93f7303Rahul Ravikumar    public void testContinuation_joinAndEnqueueWithOverlaps() {
24759cbb5756e54d32fb51e72fe1ed94934c93f7303Rahul Ravikumar        WorkContinuationImpl first = new WorkContinuationImpl(mWorkManagerImpl,
24851b5cd2bc8a7fb7979e2bcd731fc8fd0d195f860Sumir Kataria                createTestWorkerList());
24959cbb5756e54d32fb51e72fe1ed94934c93f7303Rahul Ravikumar        WorkContinuationImpl second = new WorkContinuationImpl(mWorkManagerImpl,
25051b5cd2bc8a7fb7979e2bcd731fc8fd0d195f860Sumir Kataria                createTestWorkerList());
25159cbb5756e54d32fb51e72fe1ed94934c93f7303Rahul Ravikumar        WorkContinuationImpl third = new WorkContinuationImpl(mWorkManagerImpl,
25251b5cd2bc8a7fb7979e2bcd731fc8fd0d195f860Sumir Kataria                createTestWorkerList());
25355a030183e5b974f3ebf04ef5cd9ab83f3557dadSumir Kataria        WorkContinuationImpl firstDependent = (WorkContinuationImpl) WorkContinuation.combine(
25455a030183e5b974f3ebf04ef5cd9ab83f3557dadSumir Kataria                first, second);
25555a030183e5b974f3ebf04ef5cd9ab83f3557dadSumir Kataria        WorkContinuationImpl secondDependent = (WorkContinuationImpl) WorkContinuation.combine(
25655a030183e5b974f3ebf04ef5cd9ab83f3557dadSumir Kataria                first, third);
25755a030183e5b974f3ebf04ef5cd9ab83f3557dadSumir Kataria        WorkContinuationImpl dependent = (WorkContinuationImpl) WorkContinuation.combine(
25859cbb5756e54d32fb51e72fe1ed94934c93f7303Rahul Ravikumar                firstDependent, secondDependent);
25962e0be94ea7e54ca9227564b14c1c6736ae770f7Sumir Kataria        dependent.enqueueSync();
26059cbb5756e54d32fb51e72fe1ed94934c93f7303Rahul Ravikumar        verifyEnqueued(dependent);
2610c252a21d65ac58c2a19540bd6af9ffdd77b1e94Rahul Ravikumar        verifyScheduled(mScheduler, dependent);
26259cbb5756e54d32fb51e72fe1ed94934c93f7303Rahul Ravikumar    }
26359cbb5756e54d32fb51e72fe1ed94934c93f7303Rahul Ravikumar
26487e8dc0458781cd41a5ee990be811790ac7f4e88Sumir Kataria    @Test
2652574ac4ac18d2bb4ceeae795a213d86c3a70fc68Rahul Ravikumar    @LargeTest
26687e8dc0458781cd41a5ee990be811790ac7f4e88Sumir Kataria    @SuppressWarnings("unchecked")
26787e8dc0458781cd41a5ee990be811790ac7f4e88Sumir Kataria    public void testContinuation_joinPassesAllOutput() throws InterruptedException {
26887e8dc0458781cd41a5ee990be811790ac7f4e88Sumir Kataria        final String intTag = "myint";
26987e8dc0458781cd41a5ee990be811790ac7f4e88Sumir Kataria        final String stringTag = "mystring";
27087e8dc0458781cd41a5ee990be811790ac7f4e88Sumir Kataria
2717031a0fbe12b8159ab2dc6d9c50be5b3f38477faRahul Ravikumar        OneTimeWorkRequest firstWork = new OneTimeWorkRequest.Builder(TestWorker.class)
27262a7e773945d980084dfc5d00c724de2e27dc22dSumir Kataria                .setInitialState(State.SUCCEEDED)
27387e8dc0458781cd41a5ee990be811790ac7f4e88Sumir Kataria                .build();
2747031a0fbe12b8159ab2dc6d9c50be5b3f38477faRahul Ravikumar        OneTimeWorkRequest secondWork = new OneTimeWorkRequest.Builder(TestWorker.class)
27562a7e773945d980084dfc5d00c724de2e27dc22dSumir Kataria                .setInitialState(State.SUCCEEDED)
27687e8dc0458781cd41a5ee990be811790ac7f4e88Sumir Kataria                .build();
27787e8dc0458781cd41a5ee990be811790ac7f4e88Sumir Kataria
27887e8dc0458781cd41a5ee990be811790ac7f4e88Sumir Kataria        WorkSpecDao workSpecDao = mDatabase.workSpecDao();
27987e8dc0458781cd41a5ee990be811790ac7f4e88Sumir Kataria        workSpecDao.insertWorkSpec(getWorkSpec(firstWork));
28087e8dc0458781cd41a5ee990be811790ac7f4e88Sumir Kataria        workSpecDao.insertWorkSpec(getWorkSpec(secondWork));
28187e8dc0458781cd41a5ee990be811790ac7f4e88Sumir Kataria
28287e8dc0458781cd41a5ee990be811790ac7f4e88Sumir Kataria        workSpecDao.setOutput(
283fa284c943bd003ff03f1934370d70bd4a5e034c3Sumir Kataria                firstWork.getStringId(),
28464e6bd86c786f1cb1b0c3dbc2b5307cca5c0d1f6Sumir Kataria                new Data.Builder().putInt(intTag, 0).build());
28587e8dc0458781cd41a5ee990be811790ac7f4e88Sumir Kataria        workSpecDao.setOutput(
286fa284c943bd003ff03f1934370d70bd4a5e034c3Sumir Kataria                secondWork.getStringId(),
28764e6bd86c786f1cb1b0c3dbc2b5307cca5c0d1f6Sumir Kataria                new Data.Builder().putInt(intTag, 1).putString(stringTag, "hello").build());
28887e8dc0458781cd41a5ee990be811790ac7f4e88Sumir Kataria
28987e8dc0458781cd41a5ee990be811790ac7f4e88Sumir Kataria        WorkContinuationImpl firstContinuation =
29087e8dc0458781cd41a5ee990be811790ac7f4e88Sumir Kataria                new WorkContinuationImpl(mWorkManagerImpl, Collections.singletonList(firstWork));
29187e8dc0458781cd41a5ee990be811790ac7f4e88Sumir Kataria        WorkContinuationImpl secondContinuation =
29287e8dc0458781cd41a5ee990be811790ac7f4e88Sumir Kataria                new WorkContinuationImpl(mWorkManagerImpl, Collections.singletonList(secondWork));
29387e8dc0458781cd41a5ee990be811790ac7f4e88Sumir Kataria        WorkContinuationImpl dependentContinuation =
29455a030183e5b974f3ebf04ef5cd9ab83f3557dadSumir Kataria                (WorkContinuationImpl) WorkContinuation.combine(
29555a030183e5b974f3ebf04ef5cd9ab83f3557dadSumir Kataria                        firstContinuation, secondContinuation);
29662e0be94ea7e54ca9227564b14c1c6736ae770f7Sumir Kataria        dependentContinuation.enqueueSync();
29787e8dc0458781cd41a5ee990be811790ac7f4e88Sumir Kataria
29887e8dc0458781cd41a5ee990be811790ac7f4e88Sumir Kataria        String joinId = null;
29987e8dc0458781cd41a5ee990be811790ac7f4e88Sumir Kataria        for (String id : dependentContinuation.getAllIds()) {
300fa284c943bd003ff03f1934370d70bd4a5e034c3Sumir Kataria            if (!firstWork.getStringId().equals(id) && !secondWork.getStringId().equals(id)) {
30187e8dc0458781cd41a5ee990be811790ac7f4e88Sumir Kataria                joinId = id;
30287e8dc0458781cd41a5ee990be811790ac7f4e88Sumir Kataria                break;
30387e8dc0458781cd41a5ee990be811790ac7f4e88Sumir Kataria            }
30487e8dc0458781cd41a5ee990be811790ac7f4e88Sumir Kataria        }
30587e8dc0458781cd41a5ee990be811790ac7f4e88Sumir Kataria
3065f5e7072d763d88253de1f3f092957b67f4cd8e4Sumir Kataria        Thread.sleep(5000L);
3075f5e7072d763d88253de1f3f092957b67f4cd8e4Sumir Kataria
3085f5e7072d763d88253de1f3f092957b67f4cd8e4Sumir Kataria        // TODO(sumir): I can't seem to get this kicked off automatically, so I'm running it myself.
3095f5e7072d763d88253de1f3f092957b67f4cd8e4Sumir Kataria        // Figure out what's going on here.
310e326592ec414dfe4c002e2840d9fc4aef0ee8747Rahul Ravikumar        Context context = InstrumentationRegistry.getTargetContext();
311e326592ec414dfe4c002e2840d9fc4aef0ee8747Rahul Ravikumar        new WorkerWrapper.Builder(context, mConfiguration, mDatabase, joinId)
3125f5e7072d763d88253de1f3f092957b67f4cd8e4Sumir Kataria                .build()
3135f5e7072d763d88253de1f3f092957b67f4cd8e4Sumir Kataria                .run();
3145f5e7072d763d88253de1f3f092957b67f4cd8e4Sumir Kataria
31587e8dc0458781cd41a5ee990be811790ac7f4e88Sumir Kataria        assertThat(joinId, is(not(nullValue())));
3165f5e7072d763d88253de1f3f092957b67f4cd8e4Sumir Kataria        WorkSpec joinWorkSpec = mDatabase.workSpecDao().getWorkSpec(joinId);
31787e8dc0458781cd41a5ee990be811790ac7f4e88Sumir Kataria        assertThat(joinWorkSpec, is(not(nullValue())));
3185f5e7072d763d88253de1f3f092957b67f4cd8e4Sumir Kataria        assertThat(joinWorkSpec.state, is(State.SUCCEEDED));
31987e8dc0458781cd41a5ee990be811790ac7f4e88Sumir Kataria
32064e6bd86c786f1cb1b0c3dbc2b5307cca5c0d1f6Sumir Kataria        Data output = joinWorkSpec.output;
3215f5e7072d763d88253de1f3f092957b67f4cd8e4Sumir Kataria        int[] intArray = output.getIntArray(intTag);
3225f5e7072d763d88253de1f3f092957b67f4cd8e4Sumir Kataria
3235f5e7072d763d88253de1f3f092957b67f4cd8e4Sumir Kataria        assertThat(intArray, is(not(nullValue())));
3245f5e7072d763d88253de1f3f092957b67f4cd8e4Sumir Kataria        Arrays.sort(intArray);
3255f5e7072d763d88253de1f3f092957b67f4cd8e4Sumir Kataria        assertThat(Arrays.binarySearch(intArray, 0), is(not(-1)));
3265f5e7072d763d88253de1f3f092957b67f4cd8e4Sumir Kataria        assertThat(Arrays.binarySearch(intArray, 1), is(not(-1)));
32787e8dc0458781cd41a5ee990be811790ac7f4e88Sumir Kataria        assertThat(output.getStringArray(stringTag), is(not(nullValue())));
32887e8dc0458781cd41a5ee990be811790ac7f4e88Sumir Kataria        assertThat(Arrays.asList(output.getStringArray(stringTag)), contains("hello"));
3295f5e7072d763d88253de1f3f092957b67f4cd8e4Sumir Kataria
33087e8dc0458781cd41a5ee990be811790ac7f4e88Sumir Kataria    }
33187e8dc0458781cd41a5ee990be811790ac7f4e88Sumir Kataria
3322ca6b2dec030049de439acaa719e321252af4413Rahul Ravikumar    @Test
3332ca6b2dec030049de439acaa719e321252af4413Rahul Ravikumar    @SmallTest
33455a030183e5b974f3ebf04ef5cd9ab83f3557dadSumir Kataria    public void testContinuation_hasCycles() {
3357031a0fbe12b8159ab2dc6d9c50be5b3f38477faRahul Ravikumar        OneTimeWorkRequest aWork = createTestWorker(); // A
3367031a0fbe12b8159ab2dc6d9c50be5b3f38477faRahul Ravikumar        OneTimeWorkRequest bWork = createTestWorker(); // B
3377031a0fbe12b8159ab2dc6d9c50be5b3f38477faRahul Ravikumar        OneTimeWorkRequest cWork = createTestWorker(); // C
3382ca6b2dec030049de439acaa719e321252af4413Rahul Ravikumar
3392ca6b2dec030049de439acaa719e321252af4413Rahul Ravikumar        WorkContinuation continuationA = new WorkContinuationImpl(
3402ca6b2dec030049de439acaa719e321252af4413Rahul Ravikumar                mWorkManagerImpl, Collections.singletonList(aWork));
3412ca6b2dec030049de439acaa719e321252af4413Rahul Ravikumar
3422ca6b2dec030049de439acaa719e321252af4413Rahul Ravikumar        WorkContinuation continuationB = new WorkContinuationImpl(
3432ca6b2dec030049de439acaa719e321252af4413Rahul Ravikumar                mWorkManagerImpl, Collections.singletonList(bWork));
3442ca6b2dec030049de439acaa719e321252af4413Rahul Ravikumar
3452ca6b2dec030049de439acaa719e321252af4413Rahul Ravikumar        // B -> C
3462ca6b2dec030049de439acaa719e321252af4413Rahul Ravikumar        WorkContinuation continuationBC = continuationB.then(cWork);
3472ca6b2dec030049de439acaa719e321252af4413Rahul Ravikumar
34855a030183e5b974f3ebf04ef5cd9ab83f3557dadSumir Kataria        // combine -> A, C
34955a030183e5b974f3ebf04ef5cd9ab83f3557dadSumir Kataria        WorkContinuation join = WorkContinuation.combine(continuationA, continuationBC);
3502ca6b2dec030049de439acaa719e321252af4413Rahul Ravikumar
3512ca6b2dec030049de439acaa719e321252af4413Rahul Ravikumar        // withCycles -> B
3522ca6b2dec030049de439acaa719e321252af4413Rahul Ravikumar        WorkContinuationImpl withCycles = (WorkContinuationImpl) join.then(bWork);
3532ca6b2dec030049de439acaa719e321252af4413Rahul Ravikumar        assertThat(withCycles.hasCycles(), is(true));
3542ca6b2dec030049de439acaa719e321252af4413Rahul Ravikumar    }
3552ca6b2dec030049de439acaa719e321252af4413Rahul Ravikumar
3562ca6b2dec030049de439acaa719e321252af4413Rahul Ravikumar    @Test
3572ca6b2dec030049de439acaa719e321252af4413Rahul Ravikumar    @SmallTest
35855a030183e5b974f3ebf04ef5cd9ab83f3557dadSumir Kataria    public void testContinuation_hasCycles2() {
3597031a0fbe12b8159ab2dc6d9c50be5b3f38477faRahul Ravikumar        OneTimeWorkRequest aWork = createTestWorker(); // A
3602ca6b2dec030049de439acaa719e321252af4413Rahul Ravikumar        WorkContinuation continuationA = new WorkContinuationImpl(
3612ca6b2dec030049de439acaa719e321252af4413Rahul Ravikumar                mWorkManagerImpl, Collections.singletonList(aWork));
3622ca6b2dec030049de439acaa719e321252af4413Rahul Ravikumar
3632ca6b2dec030049de439acaa719e321252af4413Rahul Ravikumar        // A -> A
3642ca6b2dec030049de439acaa719e321252af4413Rahul Ravikumar        WorkContinuationImpl withCycles = (WorkContinuationImpl) continuationA.then(aWork);
3652ca6b2dec030049de439acaa719e321252af4413Rahul Ravikumar        assertThat(withCycles.hasCycles(), is(true));
3662ca6b2dec030049de439acaa719e321252af4413Rahul Ravikumar    }
3672ca6b2dec030049de439acaa719e321252af4413Rahul Ravikumar
3682ca6b2dec030049de439acaa719e321252af4413Rahul Ravikumar    @Test
3692ca6b2dec030049de439acaa719e321252af4413Rahul Ravikumar    @SmallTest
37055a030183e5b974f3ebf04ef5cd9ab83f3557dadSumir Kataria    public void testContinuation_hasCycles3() {
3717031a0fbe12b8159ab2dc6d9c50be5b3f38477faRahul Ravikumar        OneTimeWorkRequest aWork = createTestWorker(); // A
3722ca6b2dec030049de439acaa719e321252af4413Rahul Ravikumar        WorkContinuation continuationA = new WorkContinuationImpl(
3732ca6b2dec030049de439acaa719e321252af4413Rahul Ravikumar                mWorkManagerImpl, Collections.singletonList(aWork));
3742ca6b2dec030049de439acaa719e321252af4413Rahul Ravikumar
3752ca6b2dec030049de439acaa719e321252af4413Rahul Ravikumar        // A -> A
3762ca6b2dec030049de439acaa719e321252af4413Rahul Ravikumar        WorkContinuation first = continuationA.then(aWork);
3772ca6b2dec030049de439acaa719e321252af4413Rahul Ravikumar        // A -> A
3782ca6b2dec030049de439acaa719e321252af4413Rahul Ravikumar        WorkContinuation second = continuationA.then(aWork);
3792ca6b2dec030049de439acaa719e321252af4413Rahul Ravikumar        //   A
3802ca6b2dec030049de439acaa719e321252af4413Rahul Ravikumar        //  A A
3812ca6b2dec030049de439acaa719e321252af4413Rahul Ravikumar        //   A
38255a030183e5b974f3ebf04ef5cd9ab83f3557dadSumir Kataria        WorkContinuationImpl joined = (WorkContinuationImpl) WorkContinuation.combine(
38355a030183e5b974f3ebf04ef5cd9ab83f3557dadSumir Kataria                first, second);
3842ca6b2dec030049de439acaa719e321252af4413Rahul Ravikumar        assertThat(joined.hasCycles(), is(true));
3852ca6b2dec030049de439acaa719e321252af4413Rahul Ravikumar    }
3862ca6b2dec030049de439acaa719e321252af4413Rahul Ravikumar
3872ca6b2dec030049de439acaa719e321252af4413Rahul Ravikumar    @Test
3882ca6b2dec030049de439acaa719e321252af4413Rahul Ravikumar    @SmallTest
38955a030183e5b974f3ebf04ef5cd9ab83f3557dadSumir Kataria    public void testContinuation_hasCycles4() {
3907031a0fbe12b8159ab2dc6d9c50be5b3f38477faRahul Ravikumar        OneTimeWorkRequest aWork = createTestWorker(); // A
3917031a0fbe12b8159ab2dc6d9c50be5b3f38477faRahul Ravikumar        OneTimeWorkRequest cWork = createTestWorker(); // C
3922ca6b2dec030049de439acaa719e321252af4413Rahul Ravikumar
3932ca6b2dec030049de439acaa719e321252af4413Rahul Ravikumar        WorkContinuation continuationA = new WorkContinuationImpl(
3942ca6b2dec030049de439acaa719e321252af4413Rahul Ravikumar                mWorkManagerImpl, Collections.singletonList(aWork));
3952ca6b2dec030049de439acaa719e321252af4413Rahul Ravikumar
3962ca6b2dec030049de439acaa719e321252af4413Rahul Ravikumar        // A   A
3972ca6b2dec030049de439acaa719e321252af4413Rahul Ravikumar        //   B
39855a030183e5b974f3ebf04ef5cd9ab83f3557dadSumir Kataria        WorkContinuation continuationB = WorkContinuation.combine(continuationA, continuationA);
3992ca6b2dec030049de439acaa719e321252af4413Rahul Ravikumar        // A   A
4002ca6b2dec030049de439acaa719e321252af4413Rahul Ravikumar        //   B
4012ca6b2dec030049de439acaa719e321252af4413Rahul Ravikumar        //   C
4022ca6b2dec030049de439acaa719e321252af4413Rahul Ravikumar        WorkContinuation continuationC = continuationB.then(cWork);
4032ca6b2dec030049de439acaa719e321252af4413Rahul Ravikumar        // A   A
4042ca6b2dec030049de439acaa719e321252af4413Rahul Ravikumar        //   B
4052ca6b2dec030049de439acaa719e321252af4413Rahul Ravikumar        //   C
4062ca6b2dec030049de439acaa719e321252af4413Rahul Ravikumar        //   A
4072ca6b2dec030049de439acaa719e321252af4413Rahul Ravikumar        WorkContinuationImpl withCycles = (WorkContinuationImpl) continuationC.then(aWork);
4082ca6b2dec030049de439acaa719e321252af4413Rahul Ravikumar        assertThat(withCycles.hasCycles(), is(true));
4092ca6b2dec030049de439acaa719e321252af4413Rahul Ravikumar    }
4102ca6b2dec030049de439acaa719e321252af4413Rahul Ravikumar
4112ca6b2dec030049de439acaa719e321252af4413Rahul Ravikumar    @Test
4122ca6b2dec030049de439acaa719e321252af4413Rahul Ravikumar    @SmallTest
41355a030183e5b974f3ebf04ef5cd9ab83f3557dadSumir Kataria    public void testContinuation_hasNoCycles() {
4147031a0fbe12b8159ab2dc6d9c50be5b3f38477faRahul Ravikumar        OneTimeWorkRequest aWork = createTestWorker(); // A
4157031a0fbe12b8159ab2dc6d9c50be5b3f38477faRahul Ravikumar        OneTimeWorkRequest bWork = createTestWorker(); // B
4167031a0fbe12b8159ab2dc6d9c50be5b3f38477faRahul Ravikumar        OneTimeWorkRequest cWork = createTestWorker(); // C
4172ca6b2dec030049de439acaa719e321252af4413Rahul Ravikumar
4182ca6b2dec030049de439acaa719e321252af4413Rahul Ravikumar        WorkContinuation continuationAB = new WorkContinuationImpl(
4192ca6b2dec030049de439acaa719e321252af4413Rahul Ravikumar                mWorkManagerImpl, Arrays.asList(aWork, bWork));
4202ca6b2dec030049de439acaa719e321252af4413Rahul Ravikumar
4212ca6b2dec030049de439acaa719e321252af4413Rahul Ravikumar        WorkContinuation continuationBC = new WorkContinuationImpl(
4222ca6b2dec030049de439acaa719e321252af4413Rahul Ravikumar                mWorkManagerImpl, Arrays.asList(bWork, cWork));
4232ca6b2dec030049de439acaa719e321252af4413Rahul Ravikumar
4242ca6b2dec030049de439acaa719e321252af4413Rahul Ravikumar        WorkContinuationImpl joined =
42555a030183e5b974f3ebf04ef5cd9ab83f3557dadSumir Kataria                (WorkContinuationImpl) WorkContinuation.combine(continuationAB, continuationBC);
4262ca6b2dec030049de439acaa719e321252af4413Rahul Ravikumar
4272ca6b2dec030049de439acaa719e321252af4413Rahul Ravikumar        assertThat(joined.hasCycles(), is(false));
4282ca6b2dec030049de439acaa719e321252af4413Rahul Ravikumar    }
4292ca6b2dec030049de439acaa719e321252af4413Rahul Ravikumar
4302ca6b2dec030049de439acaa719e321252af4413Rahul Ravikumar    @Test
4312ca6b2dec030049de439acaa719e321252af4413Rahul Ravikumar    @SmallTest
43255a030183e5b974f3ebf04ef5cd9ab83f3557dadSumir Kataria    public void testContinuation_hasNoCycles2() {
4337031a0fbe12b8159ab2dc6d9c50be5b3f38477faRahul Ravikumar        OneTimeWorkRequest aWork = createTestWorker(); // A
4347031a0fbe12b8159ab2dc6d9c50be5b3f38477faRahul Ravikumar        OneTimeWorkRequest bWork = createTestWorker(); // B
4357031a0fbe12b8159ab2dc6d9c50be5b3f38477faRahul Ravikumar        OneTimeWorkRequest cWork = createTestWorker(); // C
4362ca6b2dec030049de439acaa719e321252af4413Rahul Ravikumar
4372ca6b2dec030049de439acaa719e321252af4413Rahul Ravikumar        WorkContinuation continuationA = new WorkContinuationImpl(
4382ca6b2dec030049de439acaa719e321252af4413Rahul Ravikumar                mWorkManagerImpl, Collections.singletonList(aWork));
4392ca6b2dec030049de439acaa719e321252af4413Rahul Ravikumar
4402ca6b2dec030049de439acaa719e321252af4413Rahul Ravikumar        // A -> B
4412ca6b2dec030049de439acaa719e321252af4413Rahul Ravikumar        WorkContinuation continuationB = continuationA.then(bWork);
4422ca6b2dec030049de439acaa719e321252af4413Rahul Ravikumar        // A -> C
4432ca6b2dec030049de439acaa719e321252af4413Rahul Ravikumar        WorkContinuation continuationC = continuationA.then(cWork);
4442ca6b2dec030049de439acaa719e321252af4413Rahul Ravikumar
4452ca6b2dec030049de439acaa719e321252af4413Rahul Ravikumar        WorkContinuation continuationA2 = new WorkContinuationImpl(
4462ca6b2dec030049de439acaa719e321252af4413Rahul Ravikumar                mWorkManagerImpl, Collections.singletonList(aWork));
4472ca6b2dec030049de439acaa719e321252af4413Rahul Ravikumar        // A -> B
4482ca6b2dec030049de439acaa719e321252af4413Rahul Ravikumar        WorkContinuation continuationB2 = continuationA2.then(bWork);
4492ca6b2dec030049de439acaa719e321252af4413Rahul Ravikumar        // A -> C
4502ca6b2dec030049de439acaa719e321252af4413Rahul Ravikumar        WorkContinuation continuationC2 = continuationA2.then(cWork);
4512ca6b2dec030049de439acaa719e321252af4413Rahul Ravikumar
4522ca6b2dec030049de439acaa719e321252af4413Rahul Ravikumar        //    A      A
4532ca6b2dec030049de439acaa719e321252af4413Rahul Ravikumar        //  B   C  B   C
4542ca6b2dec030049de439acaa719e321252af4413Rahul Ravikumar        //       D
45555a030183e5b974f3ebf04ef5cd9ab83f3557dadSumir Kataria        WorkContinuationImpl joined = (WorkContinuationImpl) WorkContinuation.combine(
45655a030183e5b974f3ebf04ef5cd9ab83f3557dadSumir Kataria                continuationB, continuationC, continuationB2, continuationC2);
4572ca6b2dec030049de439acaa719e321252af4413Rahul Ravikumar
4582ca6b2dec030049de439acaa719e321252af4413Rahul Ravikumar        assertThat(joined.hasCycles(), is(false));
4592ca6b2dec030049de439acaa719e321252af4413Rahul Ravikumar    }
4602ca6b2dec030049de439acaa719e321252af4413Rahul Ravikumar
4612ca6b2dec030049de439acaa719e321252af4413Rahul Ravikumar    @Test
4622ca6b2dec030049de439acaa719e321252af4413Rahul Ravikumar    @SmallTest
46355a030183e5b974f3ebf04ef5cd9ab83f3557dadSumir Kataria    public void testContinuation_hasNoCycles3() {
4647031a0fbe12b8159ab2dc6d9c50be5b3f38477faRahul Ravikumar        OneTimeWorkRequest aWork = createTestWorker(); // A
4657031a0fbe12b8159ab2dc6d9c50be5b3f38477faRahul Ravikumar        OneTimeWorkRequest bWork = createTestWorker(); // B
4667031a0fbe12b8159ab2dc6d9c50be5b3f38477faRahul Ravikumar        OneTimeWorkRequest cWork = createTestWorker(); // C
4672ca6b2dec030049de439acaa719e321252af4413Rahul Ravikumar
4682ca6b2dec030049de439acaa719e321252af4413Rahul Ravikumar        WorkContinuation continuationA = new WorkContinuationImpl(
4692ca6b2dec030049de439acaa719e321252af4413Rahul Ravikumar                mWorkManagerImpl, Collections.singletonList(aWork));
4702ca6b2dec030049de439acaa719e321252af4413Rahul Ravikumar
4712ca6b2dec030049de439acaa719e321252af4413Rahul Ravikumar        WorkContinuation continuationB = new WorkContinuationImpl(
4722ca6b2dec030049de439acaa719e321252af4413Rahul Ravikumar                mWorkManagerImpl, Collections.singletonList(bWork));
4732ca6b2dec030049de439acaa719e321252af4413Rahul Ravikumar
4742ca6b2dec030049de439acaa719e321252af4413Rahul Ravikumar        WorkContinuation continuationC = new WorkContinuationImpl(
4752ca6b2dec030049de439acaa719e321252af4413Rahul Ravikumar                mWorkManagerImpl, Collections.singletonList(cWork));
4762ca6b2dec030049de439acaa719e321252af4413Rahul Ravikumar
47755a030183e5b974f3ebf04ef5cd9ab83f3557dadSumir Kataria        WorkContinuation first = WorkContinuation.combine(continuationA, continuationB);
47855a030183e5b974f3ebf04ef5cd9ab83f3557dadSumir Kataria        WorkContinuation second = WorkContinuation.combine(continuationA, continuationC);
4792ca6b2dec030049de439acaa719e321252af4413Rahul Ravikumar
48055a030183e5b974f3ebf04ef5cd9ab83f3557dadSumir Kataria        WorkContinuationImpl joined = (WorkContinuationImpl) WorkContinuation.combine(
48155a030183e5b974f3ebf04ef5cd9ab83f3557dadSumir Kataria                first, second);
4822ca6b2dec030049de439acaa719e321252af4413Rahul Ravikumar        assertThat(joined.hasCycles(), is(false));
4832ca6b2dec030049de439acaa719e321252af4413Rahul Ravikumar    }
4842ca6b2dec030049de439acaa719e321252af4413Rahul Ravikumar
4855a4ced8020d8a3ee4b9100b97559db3d1fb5132bRahul Ravikumar    @Test
4865a4ced8020d8a3ee4b9100b97559db3d1fb5132bRahul Ravikumar    @SmallTest
4875a4ced8020d8a3ee4b9100b97559db3d1fb5132bRahul Ravikumar    public void testGetStatusesSync() {
4885a4ced8020d8a3ee4b9100b97559db3d1fb5132bRahul Ravikumar        OneTimeWorkRequest aWork = createTestWorker(); // A
4895a4ced8020d8a3ee4b9100b97559db3d1fb5132bRahul Ravikumar        OneTimeWorkRequest bWork = createTestWorker(); // B
4905a4ced8020d8a3ee4b9100b97559db3d1fb5132bRahul Ravikumar        OneTimeWorkRequest cWork = createTestWorker(); // C
4915a4ced8020d8a3ee4b9100b97559db3d1fb5132bRahul Ravikumar        OneTimeWorkRequest dWork = createTestWorker(); // D
4925a4ced8020d8a3ee4b9100b97559db3d1fb5132bRahul Ravikumar
4935a4ced8020d8a3ee4b9100b97559db3d1fb5132bRahul Ravikumar        WorkContinuation firstChain = mWorkManagerImpl.beginWith(aWork).then(bWork);
4945a4ced8020d8a3ee4b9100b97559db3d1fb5132bRahul Ravikumar        WorkContinuation secondChain = mWorkManagerImpl.beginWith(cWork);
4955a4ced8020d8a3ee4b9100b97559db3d1fb5132bRahul Ravikumar        WorkContinuation combined = WorkContinuation.combine(dWork, firstChain, secondChain);
4965a4ced8020d8a3ee4b9100b97559db3d1fb5132bRahul Ravikumar
4975a4ced8020d8a3ee4b9100b97559db3d1fb5132bRahul Ravikumar        combined.synchronous().enqueueSync();
4985a4ced8020d8a3ee4b9100b97559db3d1fb5132bRahul Ravikumar        List<WorkStatus> statuses = combined.synchronous().getStatusesSync();
4995a4ced8020d8a3ee4b9100b97559db3d1fb5132bRahul Ravikumar        assertThat(statuses, is(notNullValue()));
5005a4ced8020d8a3ee4b9100b97559db3d1fb5132bRahul Ravikumar        List<UUID> ids = new ArrayList<>(statuses.size());
5015a4ced8020d8a3ee4b9100b97559db3d1fb5132bRahul Ravikumar        for (WorkStatus status : statuses) {
5025a4ced8020d8a3ee4b9100b97559db3d1fb5132bRahul Ravikumar            ids.add(status.getId());
5035a4ced8020d8a3ee4b9100b97559db3d1fb5132bRahul Ravikumar        }
5045a4ced8020d8a3ee4b9100b97559db3d1fb5132bRahul Ravikumar        assertThat(ids, containsInAnyOrder(
5055a4ced8020d8a3ee4b9100b97559db3d1fb5132bRahul Ravikumar                aWork.getId(), bWork.getId(), cWork.getId(), dWork.getId()));
5065a4ced8020d8a3ee4b9100b97559db3d1fb5132bRahul Ravikumar    }
5075a4ced8020d8a3ee4b9100b97559db3d1fb5132bRahul Ravikumar
5080c252a21d65ac58c2a19540bd6af9ffdd77b1e94Rahul Ravikumar    private static void verifyEnqueued(WorkContinuationImpl continuation) {
50987d37e5587b277ba523d69df71e17a4039274cdaRahul Ravikumar        assertThat(continuation.isEnqueued(), is(true));
51059cbb5756e54d32fb51e72fe1ed94934c93f7303Rahul Ravikumar        List<WorkContinuationImpl> parents = continuation.getParents();
51159cbb5756e54d32fb51e72fe1ed94934c93f7303Rahul Ravikumar        if (parents != null) {
51259cbb5756e54d32fb51e72fe1ed94934c93f7303Rahul Ravikumar            for (WorkContinuationImpl parent : parents) {
51359cbb5756e54d32fb51e72fe1ed94934c93f7303Rahul Ravikumar                verifyEnqueued(parent);
51459cbb5756e54d32fb51e72fe1ed94934c93f7303Rahul Ravikumar            }
51544235b3ed93a4783f6bb1f3979779ee039289bfcRahul Ravikumar        }
51644235b3ed93a4783f6bb1f3979779ee039289bfcRahul Ravikumar    }
51744235b3ed93a4783f6bb1f3979779ee039289bfcRahul Ravikumar
5180c252a21d65ac58c2a19540bd6af9ffdd77b1e94Rahul Ravikumar    private static void verifyScheduled(Scheduler scheduler, WorkContinuationImpl continuation) {
519e326592ec414dfe4c002e2840d9fc4aef0ee8747Rahul Ravikumar        Configuration configuration = continuation.getWorkManagerImpl().getConfiguration();
5200c252a21d65ac58c2a19540bd6af9ffdd77b1e94Rahul Ravikumar        ArgumentCaptor<WorkSpec> captor = ArgumentCaptor.forClass(WorkSpec.class);
5210c252a21d65ac58c2a19540bd6af9ffdd77b1e94Rahul Ravikumar        verify(scheduler, times(1)).schedule(captor.capture());
5220c252a21d65ac58c2a19540bd6af9ffdd77b1e94Rahul Ravikumar        List<WorkSpec> workSpecs = captor.getAllValues();
5230c252a21d65ac58c2a19540bd6af9ffdd77b1e94Rahul Ravikumar        assertThat(workSpecs, notNullValue());
5240c252a21d65ac58c2a19540bd6af9ffdd77b1e94Rahul Ravikumar
5250c252a21d65ac58c2a19540bd6af9ffdd77b1e94Rahul Ravikumar        WorkDatabase workDatabase = continuation.getWorkManagerImpl().getWorkDatabase();
5260c252a21d65ac58c2a19540bd6af9ffdd77b1e94Rahul Ravikumar        List<WorkSpec> eligibleWorkSpecs =
527e326592ec414dfe4c002e2840d9fc4aef0ee8747Rahul Ravikumar                workDatabase
528e326592ec414dfe4c002e2840d9fc4aef0ee8747Rahul Ravikumar                        .workSpecDao()
529e326592ec414dfe4c002e2840d9fc4aef0ee8747Rahul Ravikumar                        .getEligibleWorkForScheduling(
530e326592ec414dfe4c002e2840d9fc4aef0ee8747Rahul Ravikumar                                configuration.getMaxSchedulerLimit());
5310c252a21d65ac58c2a19540bd6af9ffdd77b1e94Rahul Ravikumar
5320c252a21d65ac58c2a19540bd6af9ffdd77b1e94Rahul Ravikumar        Set<String> capturedIds = new HashSet<>();
5330c252a21d65ac58c2a19540bd6af9ffdd77b1e94Rahul Ravikumar        for (WorkSpec workSpec : workSpecs) {
5340c252a21d65ac58c2a19540bd6af9ffdd77b1e94Rahul Ravikumar            capturedIds.add(workSpec.id);
5350c252a21d65ac58c2a19540bd6af9ffdd77b1e94Rahul Ravikumar        }
5360c252a21d65ac58c2a19540bd6af9ffdd77b1e94Rahul Ravikumar
5370c252a21d65ac58c2a19540bd6af9ffdd77b1e94Rahul Ravikumar        for (WorkSpec eligibleWorkSpec : eligibleWorkSpecs) {
5380c252a21d65ac58c2a19540bd6af9ffdd77b1e94Rahul Ravikumar            assertThat(capturedIds.contains(eligibleWorkSpec.id), is(true));
5390c252a21d65ac58c2a19540bd6af9ffdd77b1e94Rahul Ravikumar        }
5400c252a21d65ac58c2a19540bd6af9ffdd77b1e94Rahul Ravikumar    }
5410c252a21d65ac58c2a19540bd6af9ffdd77b1e94Rahul Ravikumar
5427031a0fbe12b8159ab2dc6d9c50be5b3f38477faRahul Ravikumar    private static OneTimeWorkRequest createTestWorker() {
5437031a0fbe12b8159ab2dc6d9c50be5b3f38477faRahul Ravikumar        return new OneTimeWorkRequest.Builder(TestWorker.class).build();
54444235b3ed93a4783f6bb1f3979779ee039289bfcRahul Ravikumar    }
54551b5cd2bc8a7fb7979e2bcd731fc8fd0d195f860Sumir Kataria
5467031a0fbe12b8159ab2dc6d9c50be5b3f38477faRahul Ravikumar    private static List<OneTimeWorkRequest> createTestWorkerList() {
54751b5cd2bc8a7fb7979e2bcd731fc8fd0d195f860Sumir Kataria        return Collections.singletonList(createTestWorker());
54851b5cd2bc8a7fb7979e2bcd731fc8fd0d195f860Sumir Kataria    }
54944235b3ed93a4783f6bb1f3979779ee039289bfcRahul Ravikumar}
550