Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit ef382414 authored by Austin Tankiang's avatar Austin Tankiang Committed by Android (Google) Code Review
Browse files

Merge "Remove stale pending/in progress items on update" into main

parents 415b5463 1d513634
Loading
Loading
Loading
Loading
+6 −1
Original line number Diff line number Diff line
@@ -78,11 +78,15 @@ class JobPanelViewModel : ViewModel() {
    }

    /**
     * Updates the list of progresses managed by this class.
     * Updates the list of progresses managed by this class. This function will add and update all
     * given items, while removing any queued/in progress items not in [progresses]. Completed items
     * are kept.
     */
    fun updateProgress(progresses: List<JobProgress>) {
        val seen = hashSetOf<String>()
        for (jobProgress in progresses) {
            if (DEBUG) Log.d(TAG, "Received $jobProgress")
            seen.add(jobProgress.id)
            if (jobProgress.state == Job.STATE_CANCELED) {
                _currentJobs.remove(jobProgress.id)
            } else {
@@ -91,6 +95,7 @@ class JobPanelViewModel : ViewModel() {
                }
            }
        }
        _currentJobs.entries.removeAll { (id, model) -> !model.jobProgress.isFinal && id !in seen }
    }

    /**
+181 −0
Original line number Diff line number Diff line
/*
 * Copyright (C) 2025 The Android Open Source Project
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
package com.android.documentsui

import android.platform.test.annotations.RequiresFlagsEnabled
import androidx.test.ext.junit.runners.AndroidJUnit4
import androidx.test.filters.SmallTest
import com.android.documentsui.JobPanelViewModel.ProgressViewModel
import com.android.documentsui.flags.Flags.FLAG_USE_MATERIAL3
import com.android.documentsui.flags.Flags.FLAG_VISUAL_SIGNALS_RO
import com.android.documentsui.rules.CheckAndForceMaterial3Flag
import com.android.documentsui.services.FileOperationService
import com.android.documentsui.services.Job
import com.android.documentsui.testing.MutableJobProgress
import junit.framework.Assert.assertEquals
import junit.framework.Assert.assertTrue
import kotlin.collections.emptyList
import org.junit.Rule
import org.junit.Test
import org.junit.runner.RunWith

private fun List<MutableJobProgress>.toJobProgressList() = map { item -> item.toJobProgress() }

private fun List<MutableJobProgress>.withExpandStates(vararg expandStates: Boolean):
        List<ProgressViewModel> =
    toJobProgressList().zip(expandStates.asList(), ::ProgressViewModel)

@SmallTest
@RequiresFlagsEnabled(FLAG_USE_MATERIAL3, FLAG_VISUAL_SIGNALS_RO)
@RunWith(AndroidJUnit4::class)
class JobPanelViewModelTest {
    @get:Rule
    val checkFlags = CheckAndForceMaterial3Flag()

    @Test
    fun testListModifications() {
        val viewModel = JobPanelViewModel()

        val progress1 = MutableJobProgress(
            id = "Job1",
            operationType = FileOperationService.OPERATION_COPY,
            state = Job.STATE_CREATED,
            msg = "Job1",
            hasFailures = false,
        )
        val progress2 = MutableJobProgress(
            id = "Job2",
            operationType = FileOperationService.OPERATION_COPY,
            state = Job.STATE_CREATED,
            msg = "Job2",
            hasFailures = false,
        )

        viewModel.updateProgress(listOf(progress1, progress2).toJobProgressList())
        assertEquals(
            listOf(progress1, progress2)
                .withExpandStates(false, false),
            ArrayList(viewModel.currentJobs.values)
        )

        val progress3 = MutableJobProgress(
            id = "Job3",
            operationType = FileOperationService.OPERATION_COPY,
            state = Job.STATE_STARTED,
            msg = "Job3",
            hasFailures = false,
        )

        val progress4 = MutableJobProgress(
            id = "Job4",
            operationType = FileOperationService.OPERATION_COPY,
            state = Job.STATE_SET_UP,
            msg = "Job4",
            hasFailures = false,
            currentBytes = 50,
            requiredBytes = 100,
            msRemaining = 4000
        )

        viewModel.toggleExpanded("Job2")
        viewModel
            .updateProgress(listOf(progress1, progress2, progress3, progress4).toJobProgressList())
        assertEquals(
            listOf(progress1, progress2, progress3, progress4)
                .withExpandStates(false, true, false, false),
            ArrayList(viewModel.currentJobs.values)
        )

        progress1.state = Job.STATE_COMPLETED
        progress2.state = Job.STATE_COMPLETED
        progress2.hasFailures = true

        viewModel.updateProgress(listOf(progress1, progress2, progress4).toJobProgressList())
        assertEquals(
            listOf(progress1, progress2, progress4)
                .withExpandStates(false, true, false),
            ArrayList(viewModel.currentJobs.values)
        )

        progress4.state = Job.STATE_CANCELED
        viewModel.updateProgress(listOf(progress4).toJobProgressList())
        // Progresses 1 and 2 should be kept as they are in the completed state.
        assertEquals(
            listOf(progress1, progress2)
                .withExpandStates(false, true),
            ArrayList(viewModel.currentJobs.values)
        )

        viewModel.updateProgress(emptyList())
        assertEquals(
            listOf(progress1, progress2)
                .withExpandStates(false, true),
            ArrayList(viewModel.currentJobs.values)
        )

        viewModel.dismissProgress("Job1")
        assertEquals(
            listOf(progress2).withExpandStates(true),
            ArrayList(viewModel.currentJobs.values)
        )
    }

    @Test
    fun testDismissNonExistentItem() {
        val viewModel = JobPanelViewModel()

        viewModel.dismissProgress("Job1")
        assertTrue(viewModel.currentJobs.isEmpty())

        val progress1 = MutableJobProgress(
            id = "Job1",
            operationType = FileOperationService.OPERATION_COPY,
            state = Job.STATE_CREATED,
            msg = "Job1",
            hasFailures = false,
        )

        viewModel.updateProgress(listOf(progress1).toJobProgressList())
        viewModel.dismissProgress("Job2")
        assertEquals(
            listOf(progress1).withExpandStates(false),
            ArrayList(viewModel.currentJobs.values)
        )
    }

    @Test
    fun testExpandNonExistentItem() {
        val viewModel = JobPanelViewModel()

        viewModel.toggleExpanded("Job1")
        assertTrue(viewModel.currentJobs.isEmpty())

        val progress1 = MutableJobProgress(
            id = "Job1",
            operationType = FileOperationService.OPERATION_COPY,
            state = Job.STATE_CREATED,
            msg = "Job1",
            hasFailures = false,
        )

        viewModel.updateProgress(listOf(progress1).toJobProgressList())
        viewModel.toggleExpanded("Job2")
        assertEquals(
            listOf(progress1).withExpandStates(false),
            ArrayList(viewModel.currentJobs.values)
        )
    }
}