From d0c1fc2d57ec490082ac424b65428b5d693cfb18 Mon Sep 17 00:00:00 2001 From: Jeremie Boulic Date: Wed, 19 Mar 2025 04:20:15 +0000 Subject: [DocsUI Peek] Initial Peek overlay and view manager Define the initial Peek fragment, with its associated layout. If Peek is enabled, the PeekViewManager, instantiated when DocsUI is launched, loads the PeekFragment (with its inflated view) in its hidden container. Flag: com.android.documentsui.flags.use_material3 Flag: com.android.documentsui.flags.use_peek_preview_ro Test: DocumentsUIGoogleTests:com.android.documentsui.peek.PeekUiTest Test: DocumentsUIGoogleTests:c.a.d.files.ActionHandlerTest#testShowPeek Bug: 382163291 Bug: 382163274 Change-Id: I7fdd1afd856803091425b8257b69206746530989 --- .../layout/drawer_layout.xml | 8 +++ .../layout/fixed_layout.xml | 7 ++ .../layout/nav_rail_layout.xml | 8 +++ .../layout/peek_layout.xml | 22 ++++++ .../values/colors.xml | 4 ++ src/com/android/documentsui/BaseActivity.java | 8 +++ .../android/documentsui/files/ActionHandler.java | 14 ++-- .../android/documentsui/files/FilesActivity.java | 1 + src/com/android/documentsui/peek/PeekFragment.kt | 32 +++++++++ .../android/documentsui/peek/PeekViewManager.kt | 83 ++++++++++++++++++++++ src/com/android/documentsui/util/FlagUtils.kt | 2 +- tests/Android.bp | 3 + .../common/com/android/documentsui/bots/Bots.java | 4 +- .../common/com/android/documentsui/bots/PeekBot.kt | 50 +++++++++++++ .../documentsui/testing/TestPeekViewManager.kt | 34 +++++++++ .../com/android/documentsui/peek/PeekUiTest.kt | 68 ++++++++++++++++++ .../documentsui/files/ActionHandlerTest.java | 7 ++ 17 files changed, 349 insertions(+), 6 deletions(-) create mode 100644 res/flag(com.android.documentsui.flags.use_material3)/layout/peek_layout.xml create mode 100644 src/com/android/documentsui/peek/PeekFragment.kt create mode 100644 src/com/android/documentsui/peek/PeekViewManager.kt create mode 100644 tests/common/com/android/documentsui/bots/PeekBot.kt create mode 100644 tests/common/com/android/documentsui/testing/TestPeekViewManager.kt create mode 100644 tests/functional/com/android/documentsui/peek/PeekUiTest.kt diff --git a/res/flag(com.android.documentsui.flags.use_material3)/layout/drawer_layout.xml b/res/flag(com.android.documentsui.flags.use_material3)/layout/drawer_layout.xml index de6b3d8a9..c13f68132 100644 --- a/res/flag(com.android.documentsui.flags.use_material3)/layout/drawer_layout.xml +++ b/res/flag(com.android.documentsui.flags.use_material3)/layout/drawer_layout.xml @@ -104,4 +104,12 @@ + + + + diff --git a/res/flag(com.android.documentsui.flags.use_material3)/layout/fixed_layout.xml b/res/flag(com.android.documentsui.flags.use_material3)/layout/fixed_layout.xml index feaa34e6d..d3b66494f 100644 --- a/res/flag(com.android.documentsui.flags.use_material3)/layout/fixed_layout.xml +++ b/res/flag(com.android.documentsui.flags.use_material3)/layout/fixed_layout.xml @@ -131,4 +131,11 @@ + + + diff --git a/res/flag(com.android.documentsui.flags.use_material3)/layout/nav_rail_layout.xml b/res/flag(com.android.documentsui.flags.use_material3)/layout/nav_rail_layout.xml index a014d8866..9c382c193 100644 --- a/res/flag(com.android.documentsui.flags.use_material3)/layout/nav_rail_layout.xml +++ b/res/flag(com.android.documentsui.flags.use_material3)/layout/nav_rail_layout.xml @@ -178,4 +178,12 @@ + + + + diff --git a/res/flag(com.android.documentsui.flags.use_material3)/layout/peek_layout.xml b/res/flag(com.android.documentsui.flags.use_material3)/layout/peek_layout.xml new file mode 100644 index 000000000..50102d622 --- /dev/null +++ b/res/flag(com.android.documentsui.flags.use_material3)/layout/peek_layout.xml @@ -0,0 +1,22 @@ + + + + diff --git a/res/flag(com.android.documentsui.flags.use_material3)/values/colors.xml b/res/flag(com.android.documentsui.flags.use_material3)/values/colors.xml index 77a41868f..05cbb6c81 100644 --- a/res/flag(com.android.documentsui.flags.use_material3)/values/colors.xml +++ b/res/flag(com.android.documentsui.flags.use_material3)/values/colors.xml @@ -76,4 +76,8 @@ --> #14000000 + + + #CC000000 diff --git a/src/com/android/documentsui/BaseActivity.java b/src/com/android/documentsui/BaseActivity.java index 0b5d96da9..ab40eca3f 100644 --- a/src/com/android/documentsui/BaseActivity.java +++ b/src/com/android/documentsui/BaseActivity.java @@ -20,6 +20,7 @@ import static com.android.documentsui.base.Shared.EXTRA_BENCHMARK; import static com.android.documentsui.base.SharedMinimal.DEBUG; import static com.android.documentsui.base.State.MODE_GRID; import static com.android.documentsui.util.FlagUtils.isUseMaterial3FlagEnabled; +import static com.android.documentsui.util.FlagUtils.isUsePeekPreviewFlagEnabled; import android.content.Context; import android.content.Intent; @@ -65,6 +66,7 @@ import com.android.documentsui.base.UserId; import com.android.documentsui.dirlist.AnimationView; import com.android.documentsui.dirlist.AppsRowManager; import com.android.documentsui.dirlist.DirectoryFragment; +import com.android.documentsui.peek.PeekViewManager; import com.android.documentsui.prefs.LocalPreferences; import com.android.documentsui.prefs.PreferencesMonitor; import com.android.documentsui.queries.CommandInterceptor; @@ -96,6 +98,7 @@ public abstract class BaseActivity protected SearchViewManager mSearchManager; protected AppsRowManager mAppsRowManager; + protected @Nullable PeekViewManager mPeekViewManager; protected UserIdManager mUserIdManager; protected UserManagerState mUserManagerState; protected State mState; @@ -414,6 +417,11 @@ public abstract class BaseActivity // Base classes must update result in their onCreate. setResult(AppCompatActivity.RESULT_CANCELED); updateRecentsSetting(); + + if (isUsePeekPreviewFlagEnabled()) { + mPeekViewManager = new PeekViewManager(this); + mPeekViewManager.initFragment(getSupportFragmentManager()); + } } private NavigationViewManager getNavigationViewManager(Breadcrumb breadcrumb, diff --git a/src/com/android/documentsui/files/ActionHandler.java b/src/com/android/documentsui/files/ActionHandler.java index 86f7a1a14..cbe02dc25 100644 --- a/src/com/android/documentsui/files/ActionHandler.java +++ b/src/com/android/documentsui/files/ActionHandler.java @@ -71,6 +71,7 @@ import com.android.documentsui.clipping.DocumentClipper; import com.android.documentsui.clipping.UrisSupplier; import com.android.documentsui.dirlist.AnimationView; import com.android.documentsui.inspector.InspectorActivity; +import com.android.documentsui.peek.PeekViewManager; import com.android.documentsui.queries.SearchViewManager; import com.android.documentsui.roots.ProvidersAccess; import com.android.documentsui.services.FileOperation; @@ -101,6 +102,7 @@ public class ActionHandler() + + override fun initFragment(fm: FragmentManager) { + throw UnsupportedOperationException() + } + + override fun peekDocument(doc: DocumentInfo) { + peekDocument.accept(doc) + } +} \ No newline at end of file diff --git a/tests/functional/com/android/documentsui/peek/PeekUiTest.kt b/tests/functional/com/android/documentsui/peek/PeekUiTest.kt new file mode 100644 index 000000000..a7624df2f --- /dev/null +++ b/tests/functional/com/android/documentsui/peek/PeekUiTest.kt @@ -0,0 +1,68 @@ +/* + * 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.peek + +import android.os.RemoteException +import android.platform.test.annotations.RequiresFlagsEnabled +import android.platform.test.flag.junit.CheckFlagsRule +import android.platform.test.flag.junit.DeviceFlagsValueProvider +import androidx.test.ext.junit.runners.AndroidJUnit4 +import androidx.test.filters.LargeTest +import com.android.documentsui.ActivityTestJunit4 +import com.android.documentsui.files.FilesActivity +import com.android.documentsui.flags.Flags +import org.junit.After +import org.junit.Before +import org.junit.Rule +import org.junit.Test +import org.junit.runner.RunWith + +@LargeTest +@RunWith(AndroidJUnit4::class) +@RequiresFlagsEnabled(Flags.FLAG_USE_MATERIAL3, Flags.FLAG_USE_PEEK_PREVIEW_RO) +class PeekUiTest : ActivityTestJunit4() { + @get:Rule + val mCheckFlagsRule: CheckFlagsRule = DeviceFlagsValueProvider.createCheckFlagsRule() + + @Before + @Throws(Exception::class) + override fun setUp() { + super.setUp() + initTestFiles() + } + + @After + @Throws(Exception::class) + override fun tearDown() { + super.tearDown() + } + + @Throws(RemoteException::class) + override fun initTestFiles() { + mDocsHelper!!.createDocument(rootDir0, "image/png", "image.png") + } + + @Test + @Throws( + Exception::class + ) + fun testShowPeek() { + bots!!.peek.assertPeekHidden() + bots!!.directory.selectDocument("image.png") + bots!!.main.clickActionItem("Get info") + bots!!.peek.assertPeekActive() + } +} diff --git a/tests/unit/com/android/documentsui/files/ActionHandlerTest.java b/tests/unit/com/android/documentsui/files/ActionHandlerTest.java index 1d6ef1fd6..5b19fcdc2 100644 --- a/tests/unit/com/android/documentsui/files/ActionHandlerTest.java +++ b/tests/unit/com/android/documentsui/files/ActionHandlerTest.java @@ -76,6 +76,7 @@ import com.android.documentsui.testing.TestDocumentClipper; import com.android.documentsui.testing.TestDragAndDropManager; import com.android.documentsui.testing.TestEnv; import com.android.documentsui.testing.TestFeatures; +import com.android.documentsui.testing.TestPeekViewManager; import com.android.documentsui.testing.TestProvidersAccess; import com.android.documentsui.testing.UserManagers; import com.android.documentsui.ui.TestDialogController; @@ -110,6 +111,7 @@ public class ActionHandlerTest { private ActionHandler mHandler; private TestDocumentClipper mClipper; private TestDragAndDropManager mDragAndDropManager; + private TestPeekViewManager mPeekViewManager; private TestFeatures mFeatures; private TestConfigStore mTestConfigStore; private boolean refreshAnswer = false; @@ -141,6 +143,7 @@ public class ActionHandlerTest { mDialogs = new TestDialogController(); mClipper = new TestDocumentClipper(); mDragAndDropManager = new TestDragAndDropManager(); + mPeekViewManager = new TestPeekViewManager(mActivity); mTestConfigStore = new TestConfigStore(); mEnv.state.configStore = mTestConfigStore; @@ -744,6 +747,8 @@ public class ActionHandlerTest { mHandler.showPreview(TestEnv.FILE_GIF); // The inspector activity is not called. mActivity.startActivity.assertNotCalled(); + mPeekViewManager.getPeekDocument().assertCalled(); + mPeekViewManager.getPeekDocument().assertLastArgument(TestEnv.FILE_GIF); } @Test @@ -751,6 +756,7 @@ public class ActionHandlerTest { public void testShowInspector() throws Exception { mHandler.showPreview(TestEnv.FILE_GIF); + mPeekViewManager.getPeekDocument().assertNotCalled(); mActivity.startActivity.assertCalled(); Intent intent = mActivity.startActivity.getLastValue(); assertTargetsComponent(intent, InspectorActivity.class); @@ -864,6 +870,7 @@ public class ActionHandlerTest { mClipper, null, // clip storage, not utilized unless we venture into *jumbo* clip territory. mDragAndDropManager, + mPeekViewManager, mEnv.injector); } } -- cgit v1.2.3-59-g8ed1b From 8c5c3c4046b546e7655e5877ee3f574058a2f028 Mon Sep 17 00:00:00 2001 From: François Degros Date: Fri, 14 Mar 2025 15:56:28 +1100 Subject: Modernize ArchiveHandleTest Use try-with-resources statements where the linter suggests them. Avoid calling methods having a @NonNull-annotated parameter with a null argument, because this causes the linter to complain. Bug: 404658729 Flag: EXEMPT only changed test code Test: atest DocumentsUIGoogleTests:com.android.documentsui.archives Change-Id: I8d2d98c295ee2e90765c19a8e6b11645b62382e0 --- .../documentsui/archives/ArchiveHandleTest.java | 475 +++++++++------------ 1 file changed, 194 insertions(+), 281 deletions(-) diff --git a/tests/functional/com/android/documentsui/archives/ArchiveHandleTest.java b/tests/functional/com/android/documentsui/archives/ArchiveHandleTest.java index d8a1f4225..46b2698df 100644 --- a/tests/functional/com/android/documentsui/archives/ArchiveHandleTest.java +++ b/tests/functional/com/android/documentsui/archives/ArchiveHandleTest.java @@ -22,6 +22,8 @@ import static org.junit.Assert.fail; import static org.mockito.Mockito.mock; import static org.mockito.Mockito.when; +import static java.util.Objects.requireNonNull; + import android.os.ParcelFileDescriptor; import androidx.annotation.NonNull; @@ -49,27 +51,24 @@ public class ArchiveHandleTest { @Rule public ArchiveFileTestRule mArchiveFileTestRule = new ArchiveFileTestRule(); - - private ArchiveHandle prepareArchiveHandle(String archivePath, String suffix, - String mimeType) throws IOException, CompressorException, ArchiveException { - ParcelFileDescriptor parcelFileDescriptor = mArchiveFileTestRule - .openAssetFile(archivePath, suffix); + private ArchiveHandle prepareArchiveHandle(String archivePath, String suffix, String mimeType) + throws IOException, CompressorException, ArchiveException { + ParcelFileDescriptor parcelFileDescriptor = mArchiveFileTestRule.openAssetFile(archivePath, + suffix); return ArchiveHandle.create(parcelFileDescriptor, mimeType); } - private static ArchiveEntry getFileInArchive(Enumeration enumeration, - String pathInArchive) { + private static ArchiveEntry getFileInArchive(Enumeration enumeration) { while (enumeration.hasMoreElements()) { ArchiveEntry entry = enumeration.nextElement(); - if (entry.getName().equals(pathInArchive)) { + if (entry.getName().equals("hello/inside_folder/hello_insside.txt")) { return entry; } } return null; } - private static class ArchiveEntryRecord implements ArchiveEntry { private final String mName; private final long mSize; @@ -91,11 +90,9 @@ public class ArchiveHandleTest { return false; } - if (obj instanceof ArchiveEntryRecord) { - ArchiveEntryRecord recordB = (ArchiveEntryRecord) obj; - return mName.equals(recordB.mName) - && mSize == recordB.mSize - && mIsDirectory == recordB.mIsDirectory; + if (obj instanceof ArchiveEntryRecord record) { + return mName.equals(record.mName) && mSize == record.mSize + && mIsDirectory == record.mIsDirectory; } return false; @@ -124,13 +121,13 @@ public class ArchiveHandleTest { @NonNull @Override public String toString() { - return String.format(Locale.ENGLISH, "name: %s, size: %d, isDirectory: %b", - mName, mSize, mIsDirectory); + return String.format(Locale.ENGLISH, "name: %s, size: %d, isDirectory: %b", mName, + mSize, mIsDirectory); } } private static List transformToIterable(Enumeration enumeration) { - List list = new ArrayList(); + List list = new ArrayList<>(); while (enumeration.hasMoreElements()) { list.add(new ArchiveEntryRecord(enumeration.nextElement())); } @@ -182,312 +179,260 @@ public class ArchiveHandleTest { assertThat(getNormalizedPath("//./../a//b///../c.ext/", false)).isEqualTo("/a/c.ext/?"); } - @Test - public void buildArchiveHandle_withoutFileDescriptor_shouldBeIllegal() throws Exception { - try { - ArchiveHandle.create(null, - "application/x-7z-compressed"); - fail("It should not be here!"); - } catch (NullPointerException e) { - /* do nothing */ - } - } - - @Test - public void buildArchiveHandle_withWrongMimeType_shouldBeIllegal() throws Exception { - ParcelFileDescriptor parcelFileDescriptor = mArchiveFileTestRule - .openAssetFile("archives/7z/hello.7z", ".7z"); - - try { - ArchiveHandle.create(parcelFileDescriptor, null); - fail("It should not be here!"); - } catch (IllegalArgumentException e) { - /* do nothing */ - } - } - @Test public void buildArchiveHandle_sevenZFile_shouldNotNull() throws Exception { - ArchiveHandle archiveHandle = prepareArchiveHandle("archives/7z/hello.7z", - ".7z", "application/x-7z-compressed"); - - assertThat(archiveHandle).isNotNull(); + try (ArchiveHandle archiveHandle = prepareArchiveHandle("archives/7z/hello.7z", ".7z", + "application/x-7z-compressed")) { + assertThat(archiveHandle).isNotNull(); + } } @Test public void buildArchiveHandle_zipFile_shouldNotNull() throws Exception { - ArchiveHandle archiveHandle = prepareArchiveHandle("archives/zip/hello.zip", - ".zip", "application/zip"); - - assertThat(archiveHandle).isNotNull(); - } - - @Test - public void buildArchiveHandle_zipWithWrongMimeType_shouldBeNull() throws Exception { - try { - prepareArchiveHandle("archives/zip/hello.zip", - ".zip", "application/xxxzip"); - fail("It should not be here!"); - } catch (UnsupportedOperationException e) { - /* do nothing */ + try (ArchiveHandle archiveHandle = prepareArchiveHandle("archives/zip/hello.zip", ".zip", + "application/zip")) { + assertThat(archiveHandle).isNotNull(); } } @Test public void buildArchiveHandle_tarFile_shouldNotNull() throws Exception { - ArchiveHandle archiveHandle = prepareArchiveHandle("archives/tar/hello.tar", - ".tar", "application/x-gtar"); - - assertThat(archiveHandle).isNotNull(); + try (ArchiveHandle archiveHandle = prepareArchiveHandle("archives/tar/hello.tar", ".tar", + "application/x-gtar")) { + assertThat(archiveHandle).isNotNull(); + } } @Test public void buildArchiveHandle_tgzFile_shouldNotNull() throws Exception { - ArchiveHandle archiveHandle = prepareArchiveHandle("archives/tar_gz/hello.tgz", - ".tgz", "application/x-compressed-tar"); - - assertThat(archiveHandle).isNotNull(); + try (ArchiveHandle archiveHandle = prepareArchiveHandle("archives/tar_gz/hello.tgz", ".tgz", + "application/x-compressed-tar")) { + assertThat(archiveHandle).isNotNull(); + } } @Test public void buildArchiveHandle_tarGzFile_shouldNotNull() throws Exception { - ArchiveHandle archiveHandle = - prepareArchiveHandle("archives/tar_gz/hello_tar_gz", ".tar.gz", - "application/x-compressed-tar"); - - assertThat(archiveHandle).isNotNull(); + try (ArchiveHandle archiveHandle = prepareArchiveHandle("archives/tar_gz/hello_tar_gz", + ".tar.gz", "application/x-compressed-tar")) { + assertThat(archiveHandle).isNotNull(); + } } @Test public void buildArchiveHandle_tarBzipFile_shouldNotNull() throws Exception { - ArchiveHandle archiveHandle = - prepareArchiveHandle("archives/tar_bz2/hello.tar.bz2", - ".tar.bz2", "application/x-bzip-compressed-tar"); - - assertThat(archiveHandle).isNotNull(); + try (ArchiveHandle archiveHandle = prepareArchiveHandle("archives/tar_bz2/hello.tar.bz2", + ".tar.bz2", "application/x-bzip-compressed-tar")) { + assertThat(archiveHandle).isNotNull(); + } } @Test public void buildArchiveHandle_tarXzFile_shouldNotNull() throws Exception { - ArchiveHandle archiveHandle = - prepareArchiveHandle("archives/xz/hello.tar.xz", ".tar.xz", - "application/x-xz-compressed-tar"); - - assertThat(archiveHandle).isNotNull(); + try (ArchiveHandle archiveHandle = prepareArchiveHandle("archives/xz/hello.tar.xz", + ".tar.xz", "application/x-xz-compressed-tar")) { + assertThat(archiveHandle).isNotNull(); + } } @Test public void buildArchiveHandle_tarBrFile_shouldNotNull() throws Exception { - ArchiveHandle archiveHandle = - prepareArchiveHandle("archives/brotli/hello.tar.br", ".tar.br", - "application/x-brotli-compressed-tar"); - - assertThat(archiveHandle).isNotNull(); + try (ArchiveHandle archiveHandle = prepareArchiveHandle("archives/brotli/hello.tar.br", + ".tar.br", "application/x-brotli-compressed-tar")) { + assertThat(archiveHandle).isNotNull(); + } } @Test public void getMimeType_sevenZFile_shouldBeSevenZ() throws CompressorException, ArchiveException, IOException { - ArchiveHandle archiveHandle = prepareArchiveHandle("archives/7z/hello.7z", - ".7z", "application/x-7z-compressed"); - - assertThat(archiveHandle.getMimeType()).isEqualTo("application/x-7z-compressed"); + try (ArchiveHandle archiveHandle = prepareArchiveHandle("archives/7z/hello.7z", ".7z", + "application/x-7z-compressed")) { + assertThat(archiveHandle.getMimeType()).isEqualTo("application/x-7z-compressed"); + } } @Test public void getMimeType_tarBrotli_shouldBeBrotliCompressedTar() throws CompressorException, ArchiveException, IOException { - ArchiveHandle archiveHandle = - prepareArchiveHandle("archives/brotli/hello.tar.br", ".tar.br", - "application/x-brotli-compressed-tar"); - - assertThat(archiveHandle.getMimeType()) - .isEqualTo("application/x-brotli-compressed-tar"); + try (ArchiveHandle archiveHandle = prepareArchiveHandle("archives/brotli/hello.tar.br", + ".tar.br", "application/x-brotli-compressed-tar")) { + assertThat(archiveHandle.getMimeType()).isEqualTo( + "application/x-brotli-compressed-tar"); + } } @Test public void getMimeType_tarXz_shouldBeXzCompressedTar() throws CompressorException, ArchiveException, IOException { - ArchiveHandle archiveHandle = - prepareArchiveHandle("archives/xz/hello.tar.xz", ".tar.xz", - "application/x-xz-compressed-tar"); - - assertThat(archiveHandle.getMimeType()) - .isEqualTo("application/x-xz-compressed-tar"); + try (ArchiveHandle archiveHandle = prepareArchiveHandle("archives/xz/hello.tar.xz", + ".tar.xz", "application/x-xz-compressed-tar")) { + assertThat(archiveHandle.getMimeType()).isEqualTo("application/x-xz-compressed-tar"); + } } @Test public void getMimeType_tarGz_shouldBeCompressedTar() throws CompressorException, ArchiveException, IOException { - ArchiveHandle archiveHandle = - prepareArchiveHandle("archives/tar_gz/hello_tar_gz", ".tar.gz", - "application/x-compressed-tar"); - - assertThat(archiveHandle.getMimeType()) - .isEqualTo("application/x-compressed-tar"); + try (ArchiveHandle archiveHandle = prepareArchiveHandle("archives/tar_gz/hello_tar_gz", + ".tar.gz", "application/x-compressed-tar")) { + assertThat(archiveHandle.getMimeType()).isEqualTo("application/x-compressed-tar"); + } } @Test public void getCommonArchive_tarBrFile_shouldBeCommonArchiveInputHandle() throws Exception { - ArchiveHandle archiveHandle = - prepareArchiveHandle("archives/brotli/hello.tar.br", ".tar.br", - "application/x-brotli-compressed-tar"); - - assertThat(archiveHandle.toString()).contains("CommonArchiveInputHandle"); + try (ArchiveHandle archiveHandle = prepareArchiveHandle("archives/brotli/hello.tar.br", + ".tar.br", "application/x-brotli-compressed-tar")) { + assertThat(archiveHandle.toString()).contains("CommonArchiveInputHandle"); + } } @Test public void getCommonArchive_sevenZFile_shouldBeSevenZFileHandle() throws Exception { - ArchiveHandle archiveHandle = prepareArchiveHandle("archives/7z/hello.7z", - ".7z", "application/x-7z-compressed"); - - assertThat(archiveHandle.toString()).contains("SevenZFileHandle"); + try (ArchiveHandle archiveHandle = prepareArchiveHandle("archives/7z/hello.7z", ".7z", + "application/x-7z-compressed")) { + assertThat(archiveHandle.toString()).contains("SevenZFileHandle"); + } } - @Test public void getCommonArchive_zipFile_shouldBeZipFileHandle() throws Exception { - ArchiveHandle archiveHandle = prepareArchiveHandle("archives/zip/hello.zip", - ".zip", "application/zip"); - - assertThat(archiveHandle.toString()).contains("ZipFileHandle"); + try (ArchiveHandle archiveHandle = prepareArchiveHandle("archives/zip/hello.zip", ".zip", + "application/zip")) { + assertThat(archiveHandle.toString()).contains("ZipFileHandle"); + } } @Test public void close_zipFile_shouldBeSuccess() throws Exception { - ArchiveHandle archiveHandle = prepareArchiveHandle("archives/zip/hello.zip", - ".zip", "application/zip"); - - archiveHandle.close(); + try (ArchiveHandle archiveHandle = prepareArchiveHandle("archives/zip/hello.zip", ".zip", + "application/zip")) { + assertThat(archiveHandle).isNotNull(); + } } @Test public void close_sevenZFile_shouldBeSuccess() throws Exception { - ArchiveHandle archiveHandle = prepareArchiveHandle("archives/7z/hello.7z", - ".7z", "application/x-7z-compressed"); - - archiveHandle.close(); + try (ArchiveHandle archiveHandle = prepareArchiveHandle("archives/7z/hello.7z", ".7z", + "application/x-7z-compressed")) { + assertThat(archiveHandle).isNotNull(); + } } @Test public void closeInputStream_zipFile_shouldBeSuccess() throws Exception { - ArchiveHandle archiveHandle = prepareArchiveHandle("archives/zip/hello.zip", - ".zip", "application/zip"); - - InputStream inputStream = archiveHandle.getInputStream( - getFileInArchive(archiveHandle.getEntries(), - "hello/inside_folder/hello_insside.txt")); - - assertThat(inputStream).isNotNull(); - - inputStream.close(); + try (ArchiveHandle archiveHandle = prepareArchiveHandle("archives/zip/hello.zip", ".zip", + "application/zip")) { + try (InputStream inputStream = archiveHandle.getInputStream( + requireNonNull(getFileInArchive(archiveHandle.getEntries())))) { + assertThat(inputStream).isNotNull(); + } + } } @Test public void close_zipFile_shouldNotOpen() throws Exception { - ParcelFileDescriptor parcelFileDescriptor = mArchiveFileTestRule - .openAssetFile("archives/zip/hello.zip", ".zip"); + ParcelFileDescriptor parcelFileDescriptor = mArchiveFileTestRule.openAssetFile( + "archives/zip/hello.zip", ".zip"); - ArchiveHandle archiveHandle = ArchiveHandle.create(parcelFileDescriptor, - "application/zip"); + ArchiveHandle archiveHandle = ArchiveHandle.create(parcelFileDescriptor, "application/zip"); archiveHandle.close(); - FileInputStream fileInputStream = - new FileInputStream(parcelFileDescriptor.getFileDescriptor()); + FileInputStream fileInputStream = new FileInputStream( + parcelFileDescriptor.getFileDescriptor()); assertThat(fileInputStream).isNotNull(); } @Test public void getInputStream_zipFile_shouldHaveTheSameContent() throws Exception { - ParcelFileDescriptor parcelFileDescriptor = mArchiveFileTestRule - .openAssetFile("archives/zip/hello.zip", ".zip"); + ParcelFileDescriptor parcelFileDescriptor = mArchiveFileTestRule.openAssetFile( + "archives/zip/hello.zip", ".zip"); String expectedContent = mArchiveFileTestRule.getAssetText( "archives/original/hello/inside_folder/hello_insside.txt"); - ArchiveHandle archiveHandle = ArchiveHandle.create(parcelFileDescriptor, - "application/zip"); + ArchiveHandle archiveHandle = ArchiveHandle.create(parcelFileDescriptor, "application/zip"); InputStream inputStream = archiveHandle.getInputStream( - getFileInArchive(archiveHandle.getEntries(), - "hello/inside_folder/hello_insside.txt")); + requireNonNull(getFileInArchive(archiveHandle.getEntries()))); - assertThat(ArchiveFileTestRule.getStringFromInputStream(inputStream)) - .isEqualTo(expectedContent); + assertThat(ArchiveFileTestRule.getStringFromInputStream(inputStream)).isEqualTo( + expectedContent); } @Test public void getInputStream_zipFileNotExistEntry_shouldFail() throws Exception { - ArchiveHandle archiveHandle = prepareArchiveHandle("archives/zip/hello.zip", - ".zip", "application/zip"); - - ArchiveEntry archiveEntry = mock(ArchiveEntry.class); - when(archiveEntry.getName()).thenReturn("/not_exist_entry"); - - try { - archiveHandle.getInputStream(archiveEntry); - fail("It should not be here."); - } catch (ClassCastException e) { - /* do nothing */ + try (ArchiveHandle archiveHandle = prepareArchiveHandle("archives/zip/hello.zip", ".zip", + "application/zip")) { + ArchiveEntry archiveEntry = mock(ArchiveEntry.class); + when(archiveEntry.getName()).thenReturn("/not_exist_entry"); + + try { + archiveHandle.getInputStream(archiveEntry); + fail("It should not be here."); + } catch (ClassCastException e) { + /* do nothing */ + } } } @Test public void getInputStream_directoryEntry_shouldFail() throws Exception { - ArchiveHandle archiveHandle = prepareArchiveHandle("archives/zip/hello.zip", - ".zip", "application/zip"); - - ArchiveEntry archiveEntry = mock(ArchiveEntry.class); - when(archiveEntry.isDirectory()).thenReturn(true); - - try { - archiveHandle.getInputStream(archiveEntry); - fail("It should not be here."); - } catch (IllegalArgumentException e) { - /* expected, do nothing */ + try (ArchiveHandle archiveHandle = prepareArchiveHandle("archives/zip/hello.zip", ".zip", + "application/zip")) { + ArchiveEntry archiveEntry = mock(ArchiveEntry.class); + when(archiveEntry.isDirectory()).thenReturn(true); + + try { + archiveHandle.getInputStream(archiveEntry); + fail("It should not be here."); + } catch (IllegalArgumentException e) { + /* expected, do nothing */ + } } } @Test public void getInputStream_negativeSizeEntry_shouldFail() throws Exception { - ArchiveHandle archiveHandle = prepareArchiveHandle("archives/zip/hello.zip", - ".zip", "application/zip"); - - ArchiveEntry archiveEntry = mock(ArchiveEntry.class); - when(archiveEntry.isDirectory()).thenReturn(false); - when(archiveEntry.getSize()).thenReturn(-1L); - - try { - archiveHandle.getInputStream(archiveEntry); - fail("It should not be here."); - } catch (IllegalArgumentException e) { - /* expected, do nothing */ + try (ArchiveHandle archiveHandle = prepareArchiveHandle("archives/zip/hello.zip", ".zip", + "application/zip")) { + ArchiveEntry archiveEntry = mock(ArchiveEntry.class); + when(archiveEntry.isDirectory()).thenReturn(false); + when(archiveEntry.getSize()).thenReturn(-1L); + + try { + archiveHandle.getInputStream(archiveEntry); + fail("It should not be here."); + } catch (IllegalArgumentException e) { + /* expected, do nothing */ + } } } @Test public void getInputStream_emptyStringEntry_shouldFail() throws Exception { - ArchiveHandle archiveHandle = prepareArchiveHandle("archives/zip/hello.zip", - ".zip", "application/zip"); - - ArchiveEntry archiveEntry = mock(ArchiveEntry.class); - when(archiveEntry.isDirectory()).thenReturn(false); - when(archiveEntry.getSize()).thenReturn(14L); - when(archiveEntry.getName()).thenReturn(""); - - try { - archiveHandle.getInputStream(archiveEntry); - fail("It should not be here."); - } catch (IllegalArgumentException e) { - /* expected, do nothing */ + try (ArchiveHandle archiveHandle = prepareArchiveHandle("archives/zip/hello.zip", ".zip", + "application/zip")) { + ArchiveEntry archiveEntry = mock(ArchiveEntry.class); + when(archiveEntry.isDirectory()).thenReturn(false); + when(archiveEntry.getSize()).thenReturn(14L); + when(archiveEntry.getName()).thenReturn(""); + + try { + archiveHandle.getInputStream(archiveEntry); + fail("It should not be here."); + } catch (IllegalArgumentException e) { + /* expected, do nothing */ + } } } @Test public void getInputStream_sevenZFile_shouldHaveTheSameContent() throws Exception { - ParcelFileDescriptor parcelFileDescriptor = mArchiveFileTestRule - .openAssetFile("archives/7z/hello.7z", ".7z"); + ParcelFileDescriptor parcelFileDescriptor = mArchiveFileTestRule.openAssetFile( + "archives/7z/hello.7z", ".7z"); String expectedContent = mArchiveFileTestRule.getAssetText( "archives/original/hello/inside_folder/hello_insside.txt"); @@ -496,17 +441,16 @@ public class ArchiveHandleTest { "application/x-7z-compressed"); InputStream inputStream = archiveHandle.getInputStream( - getFileInArchive(archiveHandle.getEntries(), - "hello/inside_folder/hello_insside.txt")); + requireNonNull(getFileInArchive(archiveHandle.getEntries()))); - assertThat(ArchiveFileTestRule.getStringFromInputStream(inputStream)) - .isEqualTo(expectedContent); + assertThat(ArchiveFileTestRule.getStringFromInputStream(inputStream)).isEqualTo( + expectedContent); } @Test public void getInputStream_tarGzFile_shouldHaveTheSameContent() throws Exception { - ParcelFileDescriptor parcelFileDescriptor = mArchiveFileTestRule - .openAssetFile("archives/tar_gz/hello.tgz", ".tar.gz"); + ParcelFileDescriptor parcelFileDescriptor = mArchiveFileTestRule.openAssetFile( + "archives/tar_gz/hello.tgz", ".tar.gz"); String expectedContent = mArchiveFileTestRule.getAssetText( "archives/original/hello/inside_folder/hello_insside.txt"); @@ -515,40 +459,16 @@ public class ArchiveHandleTest { "application/x-compressed-tar"); InputStream inputStream = archiveHandle.getInputStream( - getFileInArchive(archiveHandle.getEntries(), - "hello/inside_folder/hello_insside.txt")); - - assertThat(ArchiveFileTestRule.getStringFromInputStream(inputStream)) - .isEqualTo(expectedContent); - } - - @Test - public void getInputStream_tarGzFileNullEntry_getNullInputStream() throws Exception { - ParcelFileDescriptor parcelFileDescriptor = mArchiveFileTestRule - .openAssetFile("archives/tar_gz/hello.tgz", ".tar.gz"); - - String expectedContent = mArchiveFileTestRule.getAssetText( - "archives/original/hello/inside_folder/hello_insside.txt"); + requireNonNull(getFileInArchive(archiveHandle.getEntries()))); - ArchiveHandle archiveHandle = ArchiveHandle.create(parcelFileDescriptor, - "application/x-compressed-tar"); - - try { - archiveHandle.getInputStream(null); - fail("It should not here"); - } catch (IllegalArgumentException | ArchiveException | CompressorException e) { - /* expected, do nothing */ - } + assertThat(ArchiveFileTestRule.getStringFromInputStream(inputStream)).isEqualTo( + expectedContent); } - @Test public void getInputStream_tarGzFileInvalidEntry_getNullInputStream() throws Exception { - ParcelFileDescriptor parcelFileDescriptor = mArchiveFileTestRule - .openAssetFile("archives/tar_gz/hello.tgz", ".tar.gz"); - - String expectedContent = mArchiveFileTestRule.getAssetText( - "archives/original/hello/inside_folder/hello_insside.txt"); + ParcelFileDescriptor parcelFileDescriptor = mArchiveFileTestRule.openAssetFile( + "archives/tar_gz/hello.tgz", ".tar.gz"); ArchiveHandle archiveHandle = ArchiveHandle.create(parcelFileDescriptor, "application/x-compressed-tar"); @@ -565,8 +485,8 @@ public class ArchiveHandleTest { @Test public void getInputStream_tarBrotliFile_shouldHaveTheSameContent() throws Exception { - ParcelFileDescriptor parcelFileDescriptor = mArchiveFileTestRule - .openAssetFile("archives/brotli/hello.tar.br", ".tar.br"); + ParcelFileDescriptor parcelFileDescriptor = mArchiveFileTestRule.openAssetFile( + "archives/brotli/hello.tar.br", ".tar.br"); String expectedContent = mArchiveFileTestRule.getAssetText( "archives/original/hello/inside_folder/hello_insside.txt"); @@ -575,70 +495,63 @@ public class ArchiveHandleTest { "application/x-brotli-compressed-tar"); InputStream inputStream = archiveHandle.getInputStream( - getFileInArchive(archiveHandle.getEntries(), - "hello/inside_folder/hello_insside.txt")); + requireNonNull(getFileInArchive(archiveHandle.getEntries()))); - assertThat(ArchiveFileTestRule.getStringFromInputStream(inputStream)) - .isEqualTo(expectedContent); + assertThat(ArchiveFileTestRule.getStringFromInputStream(inputStream)).isEqualTo( + expectedContent); } @Test public void getEntries_zipFile_shouldTheSameWithList() throws Exception { - ArchiveHandle archiveHandle = - prepareArchiveHandle("archives/zip/hello.zip", ".zip", - "application/zip"); - - assertThat(transformToIterable(archiveHandle.getEntries())) - .containsAtLeastElementsIn(sExpectEntries); + try (ArchiveHandle archiveHandle = prepareArchiveHandle("archives/zip/hello.zip", ".zip", + "application/zip")) { + assertThat(transformToIterable(archiveHandle.getEntries())).containsAtLeastElementsIn( + sExpectEntries); + } } @Test public void getEntries_tarFile_shouldTheSameWithList() throws Exception { - ArchiveHandle archiveHandle = - prepareArchiveHandle("archives/tar/hello.tar", ".tar", - "application/x-gtar"); - - assertThat(transformToIterable(archiveHandle.getEntries())) - .containsAtLeastElementsIn(sExpectEntries); + try (ArchiveHandle archiveHandle = prepareArchiveHandle("archives/tar/hello.tar", ".tar", + "application/x-gtar")) { + assertThat(transformToIterable(archiveHandle.getEntries())).containsAtLeastElementsIn( + sExpectEntries); + } } @Test public void getEntries_tgzFile_shouldTheSameWithList() throws Exception { - ArchiveHandle archiveHandle = - prepareArchiveHandle("archives/tar_gz/hello.tgz", ".tgz", - "application/x-compressed-tar"); - - assertThat(transformToIterable(archiveHandle.getEntries())) - .containsAtLeastElementsIn(sExpectEntries); + try (ArchiveHandle archiveHandle = prepareArchiveHandle("archives/tar_gz/hello.tgz", ".tgz", + "application/x-compressed-tar")) { + assertThat(transformToIterable(archiveHandle.getEntries())).containsAtLeastElementsIn( + sExpectEntries); + } } @Test public void getEntries_tarBzFile_shouldTheSameWithList() throws Exception { - ArchiveHandle archiveHandle = - prepareArchiveHandle("archives/tar_bz2/hello.tar.bz2", ".tar.bz2", - "application/x-bzip-compressed-tar"); - - assertThat(transformToIterable(archiveHandle.getEntries())) - .containsAtLeastElementsIn(sExpectEntries); + try (ArchiveHandle archiveHandle = prepareArchiveHandle("archives/tar_bz2/hello.tar.bz2", + ".tar.bz2", "application/x-bzip-compressed-tar")) { + assertThat(transformToIterable(archiveHandle.getEntries())).containsAtLeastElementsIn( + sExpectEntries); + } } @Test public void getEntries_tarBrotliFile_shouldTheSameWithList() throws Exception { - ArchiveHandle archiveHandle = - prepareArchiveHandle("archives/brotli/hello.tar.br", ".tar.br", - "application/x-brotli-compressed-tar"); - - assertThat(transformToIterable(archiveHandle.getEntries())) - .containsAtLeastElementsIn(sExpectEntries); + try (ArchiveHandle archiveHandle = prepareArchiveHandle("archives/brotli/hello.tar.br", + ".tar.br", "application/x-brotli-compressed-tar")) { + assertThat(transformToIterable(archiveHandle.getEntries())).containsAtLeastElementsIn( + sExpectEntries); + } } @Test public void getEntries_tarXzFile_shouldTheSameWithList() throws Exception { - ArchiveHandle archiveHandle = - prepareArchiveHandle("archives/xz/hello.tar.xz", ".tar.xz", - "application/x-xz-compressed-tar"); - - assertThat(transformToIterable(archiveHandle.getEntries())) - .containsAtLeastElementsIn(sExpectEntries); + try (ArchiveHandle archiveHandle = prepareArchiveHandle("archives/xz/hello.tar.xz", + ".tar.xz", "application/x-xz-compressed-tar")) { + assertThat(transformToIterable(archiveHandle.getEntries())).containsAtLeastElementsIn( + sExpectEntries); + } } } -- cgit v1.2.3-59-g8ed1b From 4332f355c63fbfc4bc7c859ce8969b1960dc39dd Mon Sep 17 00:00:00 2001 From: Austin Tankiang Date: Fri, 14 Mar 2025 16:11:39 +0000 Subject: Add the job progress panel This panel is displayed on click of the job toolbar icon. This also changes the context passed into files.MenuManager to be the activity context as the application context doesn't have the theme information required for JobPanelController to inflate layouts. Bug: 385841754 Test: atest -c 'DocumentsUIGoogleTests:com.android.documentsui.JobPanelUiTest' Flag: com.android.documentsui.flags.visual_signals_ro Change-Id: Idd95bd97863892407ed740b3ff8a013408e37b6a --- proguard.flags | 1 + .../layout/job_progress_panel.xml | 43 ++++++++++ .../values/dimens.xml | 4 + .../values/styles.xml | 7 ++ .../values/styles_text.xml | 4 + res/values/strings.xml | 1 + src/com/android/documentsui/JobPanelController.kt | 26 +++++- .../android/documentsui/files/FilesActivity.java | 3 +- tests/Android.bp | 2 + .../documentsui/testing/MutableJobProgress.kt | 32 ++++++++ .../com/android/documentsui/JobPanelUiTest.kt | 93 ++++++++++++++++++++++ .../android/documentsui/JobPanelControllerTest.kt | 14 +--- 12 files changed, 215 insertions(+), 15 deletions(-) create mode 100644 res/flag(com.android.documentsui.flags.use_material3)/layout/job_progress_panel.xml create mode 100644 tests/common/com/android/documentsui/testing/MutableJobProgress.kt create mode 100644 tests/functional/com/android/documentsui/JobPanelUiTest.kt diff --git a/proguard.flags b/proguard.flags index 76449d4e9..34071fa6d 100644 --- a/proguard.flags +++ b/proguard.flags @@ -106,6 +106,7 @@ int dir_menu_view_in_owner; int drawer_layout; int inspector_details_view; + int job_progress_panel_title; int option_menu_create_dir; int option_menu_debug; int option_menu_extract_all; diff --git a/res/flag(com.android.documentsui.flags.use_material3)/layout/job_progress_panel.xml b/res/flag(com.android.documentsui.flags.use_material3)/layout/job_progress_panel.xml new file mode 100644 index 000000000..17f6aa6fc --- /dev/null +++ b/res/flag(com.android.documentsui.flags.use_material3)/layout/job_progress_panel.xml @@ -0,0 +1,43 @@ + + + + + + + + + + + diff --git a/res/flag(com.android.documentsui.flags.use_material3)/values/dimens.xml b/res/flag(com.android.documentsui.flags.use_material3)/values/dimens.xml index ed94fd16f..c679e64a3 100644 --- a/res/flag(com.android.documentsui.flags.use_material3)/values/dimens.xml +++ b/res/flag(com.android.documentsui.flags.use_material3)/values/dimens.xml @@ -240,4 +240,8 @@ 5dp 0.08 0.10 + + 360dp + @dimen/space_small_1 + @dimen/space_small_1 diff --git a/res/flag(com.android.documentsui.flags.use_material3)/values/styles.xml b/res/flag(com.android.documentsui.flags.use_material3)/values/styles.xml index 6819c12a3..481cd0be8 100644 --- a/res/flag(com.android.documentsui.flags.use_material3)/values/styles.xml +++ b/res/flag(com.android.documentsui.flags.use_material3)/values/styles.xml @@ -190,4 +190,11 @@ @color/nav_rail_item_text_color @style/NavRailItemTextAppearance + + diff --git a/res/flag(com.android.documentsui.flags.use_material3)/values/styles_text.xml b/res/flag(com.android.documentsui.flags.use_material3)/values/styles_text.xml index 37dd8a135..92ec6b8ae 100644 --- a/res/flag(com.android.documentsui.flags.use_material3)/values/styles_text.xml +++ b/res/flag(com.android.documentsui.flags.use_material3)/values/styles_text.xml @@ -160,4 +160,8 @@ @string/config_fontFamily + + diff --git a/res/values/strings.xml b/res/values/strings.xml index f8ade4c47..c3f11bab4 100644 --- a/res/values/strings.xml +++ b/res/values/strings.xml @@ -429,6 +429,7 @@ =1 {Zipping {filename}} other {Zipping # files} } + File Progress Grant ^1 diff --git a/src/com/android/documentsui/JobPanelController.kt b/src/com/android/documentsui/JobPanelController.kt index b3b5f1cfd..a8ab8b0a4 100644 --- a/src/com/android/documentsui/JobPanelController.kt +++ b/src/com/android/documentsui/JobPanelController.kt @@ -20,7 +20,10 @@ import android.content.Context import android.content.Intent import android.content.IntentFilter import android.util.Log +import android.view.LayoutInflater import android.view.MenuItem +import android.view.ViewGroup +import android.widget.PopupWindow import android.widget.ProgressBar import com.android.documentsui.base.Menus import com.android.documentsui.services.FileOperationService @@ -77,8 +80,29 @@ class JobPanelController(private val mContext: Context) : BroadcastReceiver() { /** * Sets the menu item controlled by this class. The item's actionView must be a [ProgressBar]. */ + @Suppress("ktlint:standard:comment-wrapping") fun setMenuItem(menuItem: MenuItem) { - (menuItem.actionView as ProgressBar).max = MAX_PROGRESS + val progressIcon = menuItem.actionView as ProgressBar + progressIcon.max = MAX_PROGRESS + progressIcon.setOnClickListener { view -> + val panel = LayoutInflater.from(mContext).inflate( + R.layout.job_progress_panel, + /* root= */ null + ) + val popupWidth = mContext.resources.getDimension(R.dimen.job_progress_panel_width) + + mContext.resources.getDimension(R.dimen.job_progress_panel_margin) + val popup = PopupWindow( + /* contentView= */ panel, + /* width= */ popupWidth.toInt(), + /* height= */ ViewGroup.LayoutParams.WRAP_CONTENT, + /* focusable= */ true + ) + popup.showAsDropDown( + /* anchor= */ view, + /* xoff= */ view.width - popupWidth.toInt(), + /* yoff= */ 0 + ) + } mMenuItem = menuItem updateMenuItem(animate = false) } diff --git a/src/com/android/documentsui/files/FilesActivity.java b/src/com/android/documentsui/files/FilesActivity.java index 50e266d38..5d2c37b55 100644 --- a/src/com/android/documentsui/files/FilesActivity.java +++ b/src/com/android/documentsui/files/FilesActivity.java @@ -19,6 +19,7 @@ package com.android.documentsui.files; import static com.android.documentsui.OperationDialogFragment.DIALOG_TYPE_UNKNOWN; import static com.android.documentsui.base.SharedMinimal.DEBUG; import static com.android.documentsui.util.FlagUtils.isUseMaterial3FlagEnabled; +import static com.android.documentsui.util.FlagUtils.isVisualSignalsFlagEnabled; import static com.android.documentsui.util.FlagUtils.isZipNgFlagEnabled; import android.app.ActivityManager.TaskDescription; @@ -134,7 +135,7 @@ public class FilesActivity extends BaseActivity implements AbstractActionHandler return clipper.hasItemsToPaste(); } }, - getApplicationContext(), + isVisualSignalsFlagEnabled() ? this : getApplicationContext(), mInjector.selectionMgr, mProviders::getApplicationName, mInjector.getModel()::getItemUri, diff --git a/tests/Android.bp b/tests/Android.bp index 41ccc1ab1..95418bdde 100644 --- a/tests/Android.bp +++ b/tests/Android.bp @@ -70,6 +70,7 @@ android_library { srcs: [ "common/**/*.java", + "common/**/*.kt", "unit/**/*.java", "unit/**/*.kt", ], @@ -94,6 +95,7 @@ android_library { srcs: [ "common/**/*.java", + "common/**/*.kt", "functional/**/*.java", "functional/**/*.kt", "unit/**/*.java", diff --git a/tests/common/com/android/documentsui/testing/MutableJobProgress.kt b/tests/common/com/android/documentsui/testing/MutableJobProgress.kt new file mode 100644 index 000000000..b2dd595f9 --- /dev/null +++ b/tests/common/com/android/documentsui/testing/MutableJobProgress.kt @@ -0,0 +1,32 @@ +/* + * 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.testing + +import com.android.documentsui.services.Job +import com.android.documentsui.services.JobProgress + +data class MutableJobProgress( + var id: String, + @Job.State var state: Int, + var msg: String?, + var hasFailures: Boolean, + var currentBytes: Long = -1, + var requiredBytes: Long = -1, + var msRemaining: Long = -1, +) { + fun toJobProgress() = + JobProgress(id, state, msg, hasFailures, currentBytes, requiredBytes, msRemaining) +} diff --git a/tests/functional/com/android/documentsui/JobPanelUiTest.kt b/tests/functional/com/android/documentsui/JobPanelUiTest.kt new file mode 100644 index 000000000..5b28b1f5d --- /dev/null +++ b/tests/functional/com/android/documentsui/JobPanelUiTest.kt @@ -0,0 +1,93 @@ +/* + * 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.content.Intent +import android.platform.test.annotations.RequiresFlagsEnabled +import android.platform.test.flag.junit.CheckFlagsRule +import android.platform.test.flag.junit.DeviceFlagsValueProvider +import androidx.test.espresso.Espresso.onView +import androidx.test.espresso.action.ViewActions.click +import androidx.test.espresso.assertion.ViewAssertions.doesNotExist +import androidx.test.espresso.assertion.ViewAssertions.matches +import androidx.test.espresso.matcher.ViewMatchers.isDisplayed +import androidx.test.espresso.matcher.ViewMatchers.withId +import androidx.test.ext.junit.runners.AndroidJUnit4 +import androidx.test.platform.app.InstrumentationRegistry +import com.android.documentsui.files.FilesActivity +import com.android.documentsui.flags.Flags.FLAG_USE_MATERIAL3 +import com.android.documentsui.flags.Flags.FLAG_VISUAL_SIGNALS_RO +import com.android.documentsui.services.FileOperationService.ACTION_PROGRESS +import com.android.documentsui.services.FileOperationService.EXTRA_PROGRESS +import com.android.documentsui.services.Job +import com.android.documentsui.services.JobProgress +import com.android.documentsui.testing.MutableJobProgress +import org.junit.After +import org.junit.Before +import org.junit.Rule +import org.junit.Test +import org.junit.runner.RunWith + +@RequiresFlagsEnabled(FLAG_USE_MATERIAL3, FLAG_VISUAL_SIGNALS_RO) +@RunWith(AndroidJUnit4::class) +class JobPanelUiTest : ActivityTestJunit4() { + @get:Rule + val mCheckFlagsRule: CheckFlagsRule = DeviceFlagsValueProvider.createCheckFlagsRule() + + private var mLastId = 0L + + private fun sendProgress(progresses: ArrayList, id: Long = mLastId++) { + val context = InstrumentationRegistry.getInstrumentation().targetContext + var intent = Intent(ACTION_PROGRESS).apply { + `package` = context.packageName + putExtra("id", id) + putParcelableArrayListExtra(EXTRA_PROGRESS, progresses) + } + context.sendBroadcast(intent) + } + + @Before + override fun setUp() { + super.setUp() + } + + @After + override fun tearDown() { + super.tearDown() + } + + @Test + fun testJobPanelAppearsOnClick() { + onView(withId(R.id.option_menu_job_progress)).check(doesNotExist()) + onView(withId(R.id.job_progress_panel_title)).check(doesNotExist()) + + val progress = MutableJobProgress( + id = "jobId1", + state = Job.STATE_SET_UP, + msg = "Job started", + hasFailures = false, + currentBytes = 4, + requiredBytes = 10, + msRemaining = -1 + ) + sendProgress(arrayListOf(progress.toJobProgress())) + + onView(withId(R.id.option_menu_job_progress)) + .check(matches(isDisplayed())) + .perform(click()) + onView(withId(R.id.job_progress_panel_title)).check(matches(isDisplayed())) + } +} diff --git a/tests/unit/com/android/documentsui/JobPanelControllerTest.kt b/tests/unit/com/android/documentsui/JobPanelControllerTest.kt index be0c9adbd..3e510edd9 100644 --- a/tests/unit/com/android/documentsui/JobPanelControllerTest.kt +++ b/tests/unit/com/android/documentsui/JobPanelControllerTest.kt @@ -30,6 +30,7 @@ import com.android.documentsui.services.FileOperationService.ACTION_PROGRESS import com.android.documentsui.services.FileOperationService.EXTRA_PROGRESS import com.android.documentsui.services.Job import com.android.documentsui.services.JobProgress +import com.android.documentsui.testing.MutableJobProgress import junit.framework.Assert.assertEquals import junit.framework.Assert.assertFalse import junit.framework.Assert.assertTrue @@ -38,19 +39,6 @@ import org.junit.Rule import org.junit.Test import org.junit.runner.RunWith -private data class MutableJobProgress( - var id: String, - @Job.State var state: Int, - var msg: String?, - var hasFailures: Boolean, - var currentBytes: Long = -1, - var requiredBytes: Long = -1, - var msRemaining: Long = -1, -) { - fun toJobProgress() = - JobProgress(id, state, msg, hasFailures, currentBytes, requiredBytes, msRemaining) -} - @SmallTest @RequiresFlagsEnabled(FLAG_USE_MATERIAL3, FLAG_VISUAL_SIGNALS_RO) @RunWith(AndroidJUnit4::class) -- cgit v1.2.3-59-g8ed1b From f9ecf70950aebdee209df17d3b20c3821f448e86 Mon Sep 17 00:00:00 2001 From: Cassy Chun-Crogan Date: Wed, 19 Mar 2025 01:26:23 +0000 Subject: [DocsUI M3] Re-layout file list on window size change Previously only a directory load or an app bar layout change would re-layout the file list. A lot of small, incremental window size changes would not trigger a re-layout leading to a strange UI or overcrowded items or excessive space. Update the layout whenever the AnimationView (the directory fragment) observes a size change. Introduce an OnSizeChangedListener to trigger the re-layout. Also use the dimens grid_width, grid_height and grid_item_margin on the grid item (item_doc_grid.xml) as these are also used by the DirectoryFragment.java to get the correct spacing for the layout. See bug for demo video. Bug: 404625076 Test: m DocumentsUIGoogle && manual inspection Flag: com.android.documentsui.flags.use_material3 Change-Id: I5e2a94757b8effc2462f818bc2fa286fefcd4740 --- .../layout/item_doc_grid.xml | 6 +-- .../values/dimens.xml | 8 ++-- .../android/documentsui/dirlist/AnimationView.java | 43 +++++++++++++++++++++- .../documentsui/dirlist/DirectoryFragment.java | 24 ++++++++++-- 4 files changed, 68 insertions(+), 13 deletions(-) diff --git a/res/flag(com.android.documentsui.flags.use_material3)/layout/item_doc_grid.xml b/res/flag(com.android.documentsui.flags.use_material3)/layout/item_doc_grid.xml index f854cf5f8..7d40f794b 100644 --- a/res/flag(com.android.documentsui.flags.use_material3)/layout/item_doc_grid.xml +++ b/res/flag(com.android.documentsui.flags.use_material3)/layout/item_doc_grid.xml @@ -17,9 +17,9 @@ 4dp 85% 200% - 152dp + 150dp + 132dp 0dp - 6dp + @dimen/space_small_1 4dp 4dp 56dp @@ -71,8 +72,6 @@ 16dp 8dp 120dp - 150dp - 132dp @dimen/space_extra_small_2 @dimen/space_extra_small_2 @dimen/space_extra_small_2 @@ -81,7 +80,6 @@ 12dp 64dp 64dp - @dimen/space_small_1 142dp 44dp 4dp diff --git a/src/com/android/documentsui/dirlist/AnimationView.java b/src/com/android/documentsui/dirlist/AnimationView.java index d17bddf98..5813085b3 100644 --- a/src/com/android/documentsui/dirlist/AnimationView.java +++ b/src/com/android/documentsui/dirlist/AnimationView.java @@ -16,19 +16,22 @@ package com.android.documentsui.dirlist; -import androidx.annotation.IntDef; -import androidx.fragment.app.FragmentTransaction; +import static com.android.documentsui.util.FlagUtils.isUseMaterial3FlagEnabled; import android.content.Context; import android.os.Bundle; import android.util.AttributeSet; import android.widget.LinearLayout; +import androidx.annotation.IntDef; +import androidx.fragment.app.FragmentTransaction; + import com.android.documentsui.R; import com.android.documentsui.base.Shared; import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; +import java.util.ArrayList; /** * This class exists solely to support animated transition of our directory fragment. @@ -51,6 +54,8 @@ public class AnimationView extends LinearLayout { public static final int ANIM_LEAVE = 3; public static final int ANIM_ENTER = 4; + private final ArrayList mOnSizeChangedListeners = new ArrayList<>(); + private float mPosition = 0f; // The distance the animation will cover...currently matches the height of the @@ -65,11 +70,45 @@ public class AnimationView extends LinearLayout { super(context, attrs); } + /** + * A listener of the onSizeChanged method. + */ + public interface OnSizeChangedListener { + /** + * Called on the View's onSizeChanged. + */ + void onSizeChanged(); + } + + /** + * Adds a listener of the onSizeChanged method. + */ + public void addOnSizeChangedListener(OnSizeChangedListener listener) { + if (isUseMaterial3FlagEnabled()) { + mOnSizeChangedListeners.add(listener); + } + } + + /** + * Removes a listener of the onSizeChanged method. + */ + public void removeOnSizeChangedListener(OnSizeChangedListener listener) { + if (isUseMaterial3FlagEnabled()) { + mOnSizeChangedListeners.remove(listener); + } + } + + @Override protected void onSizeChanged(int w, int h, int oldw, int oldh) { super.onSizeChanged(w, h, oldw, oldh); mSpan = h; setPosition(mPosition); + if (isUseMaterial3FlagEnabled()) { + for (int i = mOnSizeChangedListeners.size() - 1; i >= 0; --i) { + mOnSizeChangedListeners.get(i).onSizeChanged(); + } + } } public float getPosition() { diff --git a/src/com/android/documentsui/dirlist/DirectoryFragment.java b/src/com/android/documentsui/dirlist/DirectoryFragment.java index 2ea906a60..2911d04e9 100644 --- a/src/com/android/documentsui/dirlist/DirectoryFragment.java +++ b/src/com/android/documentsui/dirlist/DirectoryFragment.java @@ -108,6 +108,7 @@ import com.android.documentsui.clipping.ClipStore; import com.android.documentsui.clipping.DocumentClipper; import com.android.documentsui.clipping.UrisSupplier; import com.android.documentsui.dirlist.AnimationView.AnimationType; +import com.android.documentsui.dirlist.AnimationView.OnSizeChangedListener; import com.android.documentsui.picker.PickActivity; import com.android.documentsui.services.FileOperation; import com.android.documentsui.services.FileOperationService; @@ -188,7 +189,7 @@ public class DirectoryFragment extends Fragment implements SwipeRefreshLayout.On private SelectionMetadata mSelectionMetadata; private KeyInputHandler mKeyListener; private @Nullable DragHoverListener mDragHoverListener; - private View mRootView; + private AnimationView mRootView; private IconHelper mIconHelper; private SwipeRefreshLayout mRefreshLayout; private RecyclerView mRecView; @@ -416,13 +417,27 @@ public class DirectoryFragment extends Fragment implements SwipeRefreshLayout.On || Intent.ACTION_MANAGED_PROFILE_UNAVAILABLE.equals(action); } + private OnSizeChangedListener mOnSizeChangedListener = + new AnimationView.OnSizeChangedListener() { + @Override + public void onSizeChanged() { + if (isUseMaterial3FlagEnabled() && mState.derivedMode != MODE_LIST) { + // Update the grid layout when the window size changes. + updateLayout(mState.derivedMode); + } + } + }; + @Override public View onCreateView( LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) { mHandler = new Handler(Looper.getMainLooper()); mActivity = (BaseActivity) getActivity(); - mRootView = inflater.inflate(R.layout.fragment_directory, container, false); + mRootView = (AnimationView) inflater.inflate(R.layout.fragment_directory, container, false); + if (isUseMaterial3FlagEnabled()) { + mRootView.addOnSizeChangedListener(mOnSizeChangedListener); + } mProgressBar = mRootView.findViewById(R.id.progressbar); assert mProgressBar != null; @@ -497,6 +512,10 @@ public class DirectoryFragment extends Fragment implements SwipeRefreshLayout.On mModel.removeUpdateListener(mAdapter.getModelUpdateListener()); setPreDrawListenerEnabled(false); + if (isUseMaterial3FlagEnabled()) { + mRootView.removeOnSizeChangedListener(mOnSizeChangedListener); + } + super.onDestroyView(); } @@ -809,7 +828,6 @@ public class DirectoryFragment extends Fragment implements SwipeRefreshLayout.On if (mLayout != null) { mLayout.setSpanCount(mColumnCount); } - int pad = getDirectoryPadding(mode); mAppBarHeight = getAppBarLayoutHeight(); mSaveLayoutHeight = getSaveLayoutHeight(); -- cgit v1.2.3-59-g8ed1b From b00d0c7f4762f5babb84da63afc4eaa0639c8370 Mon Sep 17 00:00:00 2001 From: Cassy Chun-Crogan Date: Thu, 20 Mar 2025 03:41:05 +0000 Subject: [DocsUI M3] Centre items in grid layout Previously items (columns) were not centred leading to any extra spacing going to the righthand side. Add an outer FrameLayout layer where width is match_parent which will evenly distribute the space between items. Within the FrameLayout centre the actual grid item with center_horizontal. See bug for demo. Bug: 404978773 Test: m DocumentsUIGoogle && manual inspection Flag: com.android.documentsui.flags.use_material3 Change-Id: I379a9a97c0e6c3b8656a9c730e862cdc903de370 --- .../layout/item_doc_grid.xml | 295 +++++++++++---------- 1 file changed, 151 insertions(+), 144 deletions(-) diff --git a/res/flag(com.android.documentsui.flags.use_material3)/layout/item_doc_grid.xml b/res/flag(com.android.documentsui.flags.use_material3)/layout/item_doc_grid.xml index 7d40f794b..a8e3148b4 100644 --- a/res/flag(com.android.documentsui.flags.use_material3)/layout/item_doc_grid.xml +++ b/res/flag(com.android.documentsui.flags.use_material3)/layout/item_doc_grid.xml @@ -13,163 +13,170 @@ See the License for the specific language governing permissions and limitations under the License. --> - - - - - - - - - - - - - + + + + + + + + + - - - - - - - - - - - - - - - - - + app:cardBackgroundColor="?attr/colorSurfaceContainerLowest" + app:cardElevation="0dp" + app:strokeColor="?attr/colorSecondaryContainer" + app:strokeWidth="0dp"> + + + + + + + + + + - - + android:layout_width="@dimen/zoom_icon_size" + android:layout_height="@dimen/zoom_icon_size" + android:layout_gravity="center" + android:background="@drawable/circle_button_background" + android:padding="2dp" + android:scaleType="fitCenter" + android:src="@drawable/ic_zoom_out" /> - + + + - - - - - + + + - - + + + + + + + + + + android:gravity="center" + android:orientation="horizontal"> + + + + + + + + - + - \ No newline at end of file + \ No newline at end of file -- cgit v1.2.3-59-g8ed1b From b7e3e6e63350447a71053435b6c1ed82d07ca0b3 Mon Sep 17 00:00:00 2001 From: Cassy Chun-Crogan Date: Thu, 20 Mar 2025 04:18:27 +0000 Subject: [DocsUI M3] Uplift ripple for grid items See bug for attached demo. Bug: 404992153 Test: m DocumentsUIGoogle && manual inspection Flag: com.android.documentsui.flags.use_material3 Change-Id: Id7dbf1186b6828824c44f36b77f39e703ca8a15a --- .../color/grid_item_ripple_color.xml | 28 +++ .../drawable/grid_item_mask.xml | 21 ++ .../drawable/grid_nameplate_background.xml | 214 +++++++++++---------- 3 files changed, 161 insertions(+), 102 deletions(-) create mode 100644 res/flag(com.android.documentsui.flags.use_material3)/color/grid_item_ripple_color.xml create mode 100644 res/flag(com.android.documentsui.flags.use_material3)/drawable/grid_item_mask.xml diff --git a/res/flag(com.android.documentsui.flags.use_material3)/color/grid_item_ripple_color.xml b/res/flag(com.android.documentsui.flags.use_material3)/color/grid_item_ripple_color.xml new file mode 100644 index 000000000..85e5b46ce --- /dev/null +++ b/res/flag(com.android.documentsui.flags.use_material3)/color/grid_item_ripple_color.xml @@ -0,0 +1,28 @@ + + + + + + + + + + diff --git a/res/flag(com.android.documentsui.flags.use_material3)/drawable/grid_item_mask.xml b/res/flag(com.android.documentsui.flags.use_material3)/drawable/grid_item_mask.xml new file mode 100644 index 000000000..98473059c --- /dev/null +++ b/res/flag(com.android.documentsui.flags.use_material3)/drawable/grid_item_mask.xml @@ -0,0 +1,21 @@ + + + + + + + + \ No newline at end of file diff --git a/res/flag(com.android.documentsui.flags.use_material3)/drawable/grid_nameplate_background.xml b/res/flag(com.android.documentsui.flags.use_material3)/drawable/grid_nameplate_background.xml index 502efaede..087fc1c15 100644 --- a/res/flag(com.android.documentsui.flags.use_material3)/drawable/grid_nameplate_background.xml +++ b/res/flag(com.android.documentsui.flags.use_material3)/drawable/grid_nameplate_background.xml @@ -14,56 +14,124 @@ limitations under the License. --> - - - - + + + + + + + + - - - - + android:state_focused="true" + android:state_hovered="true" + android:state_selected="true"> + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - - - - + android:state_hovered="true" + android:state_selected="true"> + + + + + + + + + + + + + + - + - + - - - - + + - - - - + android:state_focused="true" + android:state_hovered="true"> + + + + + + + + + + + + + + - + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + - - - - - - - + - - - - - - - - - - - - - + - \ No newline at end of file + \ No newline at end of file -- cgit v1.2.3-59-g8ed1b From 90df5c40efe25b96d19abae58fc2c6eb55d0dc17 Mon Sep 17 00:00:00 2001 From: Ben Reich Date: Thu, 20 Mar 2025 18:57:56 -0700 Subject: Revert "Modernize ArchiveHandleTest" This reverts commit 8c5c3c4046b546e7655e5877ee3f574058a2f028. Reason for revert: As mentioned we don't know if this works on Android 11-13 which DocumentsUI requires to support. Change-Id: If85391a87532b782d77435034eb7ea5d506fc77e --- .../documentsui/archives/ArchiveHandleTest.java | 475 ++++++++++++--------- 1 file changed, 281 insertions(+), 194 deletions(-) diff --git a/tests/functional/com/android/documentsui/archives/ArchiveHandleTest.java b/tests/functional/com/android/documentsui/archives/ArchiveHandleTest.java index 46b2698df..d8a1f4225 100644 --- a/tests/functional/com/android/documentsui/archives/ArchiveHandleTest.java +++ b/tests/functional/com/android/documentsui/archives/ArchiveHandleTest.java @@ -22,8 +22,6 @@ import static org.junit.Assert.fail; import static org.mockito.Mockito.mock; import static org.mockito.Mockito.when; -import static java.util.Objects.requireNonNull; - import android.os.ParcelFileDescriptor; import androidx.annotation.NonNull; @@ -51,24 +49,27 @@ public class ArchiveHandleTest { @Rule public ArchiveFileTestRule mArchiveFileTestRule = new ArchiveFileTestRule(); - private ArchiveHandle prepareArchiveHandle(String archivePath, String suffix, String mimeType) - throws IOException, CompressorException, ArchiveException { - ParcelFileDescriptor parcelFileDescriptor = mArchiveFileTestRule.openAssetFile(archivePath, - suffix); + + private ArchiveHandle prepareArchiveHandle(String archivePath, String suffix, + String mimeType) throws IOException, CompressorException, ArchiveException { + ParcelFileDescriptor parcelFileDescriptor = mArchiveFileTestRule + .openAssetFile(archivePath, suffix); return ArchiveHandle.create(parcelFileDescriptor, mimeType); } - private static ArchiveEntry getFileInArchive(Enumeration enumeration) { + private static ArchiveEntry getFileInArchive(Enumeration enumeration, + String pathInArchive) { while (enumeration.hasMoreElements()) { ArchiveEntry entry = enumeration.nextElement(); - if (entry.getName().equals("hello/inside_folder/hello_insside.txt")) { + if (entry.getName().equals(pathInArchive)) { return entry; } } return null; } + private static class ArchiveEntryRecord implements ArchiveEntry { private final String mName; private final long mSize; @@ -90,9 +91,11 @@ public class ArchiveHandleTest { return false; } - if (obj instanceof ArchiveEntryRecord record) { - return mName.equals(record.mName) && mSize == record.mSize - && mIsDirectory == record.mIsDirectory; + if (obj instanceof ArchiveEntryRecord) { + ArchiveEntryRecord recordB = (ArchiveEntryRecord) obj; + return mName.equals(recordB.mName) + && mSize == recordB.mSize + && mIsDirectory == recordB.mIsDirectory; } return false; @@ -121,13 +124,13 @@ public class ArchiveHandleTest { @NonNull @Override public String toString() { - return String.format(Locale.ENGLISH, "name: %s, size: %d, isDirectory: %b", mName, - mSize, mIsDirectory); + return String.format(Locale.ENGLISH, "name: %s, size: %d, isDirectory: %b", + mName, mSize, mIsDirectory); } } private static List transformToIterable(Enumeration enumeration) { - List list = new ArrayList<>(); + List list = new ArrayList(); while (enumeration.hasMoreElements()) { list.add(new ArchiveEntryRecord(enumeration.nextElement())); } @@ -180,259 +183,311 @@ public class ArchiveHandleTest { } @Test - public void buildArchiveHandle_sevenZFile_shouldNotNull() throws Exception { - try (ArchiveHandle archiveHandle = prepareArchiveHandle("archives/7z/hello.7z", ".7z", - "application/x-7z-compressed")) { - assertThat(archiveHandle).isNotNull(); + public void buildArchiveHandle_withoutFileDescriptor_shouldBeIllegal() throws Exception { + try { + ArchiveHandle.create(null, + "application/x-7z-compressed"); + fail("It should not be here!"); + } catch (NullPointerException e) { + /* do nothing */ + } + } + + @Test + public void buildArchiveHandle_withWrongMimeType_shouldBeIllegal() throws Exception { + ParcelFileDescriptor parcelFileDescriptor = mArchiveFileTestRule + .openAssetFile("archives/7z/hello.7z", ".7z"); + + try { + ArchiveHandle.create(parcelFileDescriptor, null); + fail("It should not be here!"); + } catch (IllegalArgumentException e) { + /* do nothing */ } } + @Test + public void buildArchiveHandle_sevenZFile_shouldNotNull() throws Exception { + ArchiveHandle archiveHandle = prepareArchiveHandle("archives/7z/hello.7z", + ".7z", "application/x-7z-compressed"); + + assertThat(archiveHandle).isNotNull(); + } + @Test public void buildArchiveHandle_zipFile_shouldNotNull() throws Exception { - try (ArchiveHandle archiveHandle = prepareArchiveHandle("archives/zip/hello.zip", ".zip", - "application/zip")) { - assertThat(archiveHandle).isNotNull(); + ArchiveHandle archiveHandle = prepareArchiveHandle("archives/zip/hello.zip", + ".zip", "application/zip"); + + assertThat(archiveHandle).isNotNull(); + } + + @Test + public void buildArchiveHandle_zipWithWrongMimeType_shouldBeNull() throws Exception { + try { + prepareArchiveHandle("archives/zip/hello.zip", + ".zip", "application/xxxzip"); + fail("It should not be here!"); + } catch (UnsupportedOperationException e) { + /* do nothing */ } } @Test public void buildArchiveHandle_tarFile_shouldNotNull() throws Exception { - try (ArchiveHandle archiveHandle = prepareArchiveHandle("archives/tar/hello.tar", ".tar", - "application/x-gtar")) { - assertThat(archiveHandle).isNotNull(); - } + ArchiveHandle archiveHandle = prepareArchiveHandle("archives/tar/hello.tar", + ".tar", "application/x-gtar"); + + assertThat(archiveHandle).isNotNull(); } @Test public void buildArchiveHandle_tgzFile_shouldNotNull() throws Exception { - try (ArchiveHandle archiveHandle = prepareArchiveHandle("archives/tar_gz/hello.tgz", ".tgz", - "application/x-compressed-tar")) { - assertThat(archiveHandle).isNotNull(); - } + ArchiveHandle archiveHandle = prepareArchiveHandle("archives/tar_gz/hello.tgz", + ".tgz", "application/x-compressed-tar"); + + assertThat(archiveHandle).isNotNull(); } @Test public void buildArchiveHandle_tarGzFile_shouldNotNull() throws Exception { - try (ArchiveHandle archiveHandle = prepareArchiveHandle("archives/tar_gz/hello_tar_gz", - ".tar.gz", "application/x-compressed-tar")) { - assertThat(archiveHandle).isNotNull(); - } + ArchiveHandle archiveHandle = + prepareArchiveHandle("archives/tar_gz/hello_tar_gz", ".tar.gz", + "application/x-compressed-tar"); + + assertThat(archiveHandle).isNotNull(); } @Test public void buildArchiveHandle_tarBzipFile_shouldNotNull() throws Exception { - try (ArchiveHandle archiveHandle = prepareArchiveHandle("archives/tar_bz2/hello.tar.bz2", - ".tar.bz2", "application/x-bzip-compressed-tar")) { - assertThat(archiveHandle).isNotNull(); - } + ArchiveHandle archiveHandle = + prepareArchiveHandle("archives/tar_bz2/hello.tar.bz2", + ".tar.bz2", "application/x-bzip-compressed-tar"); + + assertThat(archiveHandle).isNotNull(); } @Test public void buildArchiveHandle_tarXzFile_shouldNotNull() throws Exception { - try (ArchiveHandle archiveHandle = prepareArchiveHandle("archives/xz/hello.tar.xz", - ".tar.xz", "application/x-xz-compressed-tar")) { - assertThat(archiveHandle).isNotNull(); - } + ArchiveHandle archiveHandle = + prepareArchiveHandle("archives/xz/hello.tar.xz", ".tar.xz", + "application/x-xz-compressed-tar"); + + assertThat(archiveHandle).isNotNull(); } @Test public void buildArchiveHandle_tarBrFile_shouldNotNull() throws Exception { - try (ArchiveHandle archiveHandle = prepareArchiveHandle("archives/brotli/hello.tar.br", - ".tar.br", "application/x-brotli-compressed-tar")) { - assertThat(archiveHandle).isNotNull(); - } + ArchiveHandle archiveHandle = + prepareArchiveHandle("archives/brotli/hello.tar.br", ".tar.br", + "application/x-brotli-compressed-tar"); + + assertThat(archiveHandle).isNotNull(); } @Test public void getMimeType_sevenZFile_shouldBeSevenZ() throws CompressorException, ArchiveException, IOException { - try (ArchiveHandle archiveHandle = prepareArchiveHandle("archives/7z/hello.7z", ".7z", - "application/x-7z-compressed")) { - assertThat(archiveHandle.getMimeType()).isEqualTo("application/x-7z-compressed"); - } + ArchiveHandle archiveHandle = prepareArchiveHandle("archives/7z/hello.7z", + ".7z", "application/x-7z-compressed"); + + assertThat(archiveHandle.getMimeType()).isEqualTo("application/x-7z-compressed"); } @Test public void getMimeType_tarBrotli_shouldBeBrotliCompressedTar() throws CompressorException, ArchiveException, IOException { - try (ArchiveHandle archiveHandle = prepareArchiveHandle("archives/brotli/hello.tar.br", - ".tar.br", "application/x-brotli-compressed-tar")) { - assertThat(archiveHandle.getMimeType()).isEqualTo( - "application/x-brotli-compressed-tar"); - } + ArchiveHandle archiveHandle = + prepareArchiveHandle("archives/brotli/hello.tar.br", ".tar.br", + "application/x-brotli-compressed-tar"); + + assertThat(archiveHandle.getMimeType()) + .isEqualTo("application/x-brotli-compressed-tar"); } @Test public void getMimeType_tarXz_shouldBeXzCompressedTar() throws CompressorException, ArchiveException, IOException { - try (ArchiveHandle archiveHandle = prepareArchiveHandle("archives/xz/hello.tar.xz", - ".tar.xz", "application/x-xz-compressed-tar")) { - assertThat(archiveHandle.getMimeType()).isEqualTo("application/x-xz-compressed-tar"); - } + ArchiveHandle archiveHandle = + prepareArchiveHandle("archives/xz/hello.tar.xz", ".tar.xz", + "application/x-xz-compressed-tar"); + + assertThat(archiveHandle.getMimeType()) + .isEqualTo("application/x-xz-compressed-tar"); } @Test public void getMimeType_tarGz_shouldBeCompressedTar() throws CompressorException, ArchiveException, IOException { - try (ArchiveHandle archiveHandle = prepareArchiveHandle("archives/tar_gz/hello_tar_gz", - ".tar.gz", "application/x-compressed-tar")) { - assertThat(archiveHandle.getMimeType()).isEqualTo("application/x-compressed-tar"); - } + ArchiveHandle archiveHandle = + prepareArchiveHandle("archives/tar_gz/hello_tar_gz", ".tar.gz", + "application/x-compressed-tar"); + + assertThat(archiveHandle.getMimeType()) + .isEqualTo("application/x-compressed-tar"); } @Test public void getCommonArchive_tarBrFile_shouldBeCommonArchiveInputHandle() throws Exception { - try (ArchiveHandle archiveHandle = prepareArchiveHandle("archives/brotli/hello.tar.br", - ".tar.br", "application/x-brotli-compressed-tar")) { - assertThat(archiveHandle.toString()).contains("CommonArchiveInputHandle"); - } + ArchiveHandle archiveHandle = + prepareArchiveHandle("archives/brotli/hello.tar.br", ".tar.br", + "application/x-brotli-compressed-tar"); + + assertThat(archiveHandle.toString()).contains("CommonArchiveInputHandle"); } @Test public void getCommonArchive_sevenZFile_shouldBeSevenZFileHandle() throws Exception { - try (ArchiveHandle archiveHandle = prepareArchiveHandle("archives/7z/hello.7z", ".7z", - "application/x-7z-compressed")) { - assertThat(archiveHandle.toString()).contains("SevenZFileHandle"); - } + ArchiveHandle archiveHandle = prepareArchiveHandle("archives/7z/hello.7z", + ".7z", "application/x-7z-compressed"); + + assertThat(archiveHandle.toString()).contains("SevenZFileHandle"); } + @Test public void getCommonArchive_zipFile_shouldBeZipFileHandle() throws Exception { - try (ArchiveHandle archiveHandle = prepareArchiveHandle("archives/zip/hello.zip", ".zip", - "application/zip")) { - assertThat(archiveHandle.toString()).contains("ZipFileHandle"); - } + ArchiveHandle archiveHandle = prepareArchiveHandle("archives/zip/hello.zip", + ".zip", "application/zip"); + + assertThat(archiveHandle.toString()).contains("ZipFileHandle"); } @Test public void close_zipFile_shouldBeSuccess() throws Exception { - try (ArchiveHandle archiveHandle = prepareArchiveHandle("archives/zip/hello.zip", ".zip", - "application/zip")) { - assertThat(archiveHandle).isNotNull(); - } + ArchiveHandle archiveHandle = prepareArchiveHandle("archives/zip/hello.zip", + ".zip", "application/zip"); + + archiveHandle.close(); } @Test public void close_sevenZFile_shouldBeSuccess() throws Exception { - try (ArchiveHandle archiveHandle = prepareArchiveHandle("archives/7z/hello.7z", ".7z", - "application/x-7z-compressed")) { - assertThat(archiveHandle).isNotNull(); - } + ArchiveHandle archiveHandle = prepareArchiveHandle("archives/7z/hello.7z", + ".7z", "application/x-7z-compressed"); + + archiveHandle.close(); } @Test public void closeInputStream_zipFile_shouldBeSuccess() throws Exception { - try (ArchiveHandle archiveHandle = prepareArchiveHandle("archives/zip/hello.zip", ".zip", - "application/zip")) { - try (InputStream inputStream = archiveHandle.getInputStream( - requireNonNull(getFileInArchive(archiveHandle.getEntries())))) { - assertThat(inputStream).isNotNull(); - } - } + ArchiveHandle archiveHandle = prepareArchiveHandle("archives/zip/hello.zip", + ".zip", "application/zip"); + + InputStream inputStream = archiveHandle.getInputStream( + getFileInArchive(archiveHandle.getEntries(), + "hello/inside_folder/hello_insside.txt")); + + assertThat(inputStream).isNotNull(); + + inputStream.close(); } @Test public void close_zipFile_shouldNotOpen() throws Exception { - ParcelFileDescriptor parcelFileDescriptor = mArchiveFileTestRule.openAssetFile( - "archives/zip/hello.zip", ".zip"); + ParcelFileDescriptor parcelFileDescriptor = mArchiveFileTestRule + .openAssetFile("archives/zip/hello.zip", ".zip"); - ArchiveHandle archiveHandle = ArchiveHandle.create(parcelFileDescriptor, "application/zip"); + ArchiveHandle archiveHandle = ArchiveHandle.create(parcelFileDescriptor, + "application/zip"); archiveHandle.close(); - FileInputStream fileInputStream = new FileInputStream( - parcelFileDescriptor.getFileDescriptor()); + FileInputStream fileInputStream = + new FileInputStream(parcelFileDescriptor.getFileDescriptor()); assertThat(fileInputStream).isNotNull(); } @Test public void getInputStream_zipFile_shouldHaveTheSameContent() throws Exception { - ParcelFileDescriptor parcelFileDescriptor = mArchiveFileTestRule.openAssetFile( - "archives/zip/hello.zip", ".zip"); + ParcelFileDescriptor parcelFileDescriptor = mArchiveFileTestRule + .openAssetFile("archives/zip/hello.zip", ".zip"); String expectedContent = mArchiveFileTestRule.getAssetText( "archives/original/hello/inside_folder/hello_insside.txt"); - ArchiveHandle archiveHandle = ArchiveHandle.create(parcelFileDescriptor, "application/zip"); + ArchiveHandle archiveHandle = ArchiveHandle.create(parcelFileDescriptor, + "application/zip"); InputStream inputStream = archiveHandle.getInputStream( - requireNonNull(getFileInArchive(archiveHandle.getEntries()))); + getFileInArchive(archiveHandle.getEntries(), + "hello/inside_folder/hello_insside.txt")); - assertThat(ArchiveFileTestRule.getStringFromInputStream(inputStream)).isEqualTo( - expectedContent); + assertThat(ArchiveFileTestRule.getStringFromInputStream(inputStream)) + .isEqualTo(expectedContent); } @Test public void getInputStream_zipFileNotExistEntry_shouldFail() throws Exception { - try (ArchiveHandle archiveHandle = prepareArchiveHandle("archives/zip/hello.zip", ".zip", - "application/zip")) { - ArchiveEntry archiveEntry = mock(ArchiveEntry.class); - when(archiveEntry.getName()).thenReturn("/not_exist_entry"); - - try { - archiveHandle.getInputStream(archiveEntry); - fail("It should not be here."); - } catch (ClassCastException e) { - /* do nothing */ - } + ArchiveHandle archiveHandle = prepareArchiveHandle("archives/zip/hello.zip", + ".zip", "application/zip"); + + ArchiveEntry archiveEntry = mock(ArchiveEntry.class); + when(archiveEntry.getName()).thenReturn("/not_exist_entry"); + + try { + archiveHandle.getInputStream(archiveEntry); + fail("It should not be here."); + } catch (ClassCastException e) { + /* do nothing */ } } @Test public void getInputStream_directoryEntry_shouldFail() throws Exception { - try (ArchiveHandle archiveHandle = prepareArchiveHandle("archives/zip/hello.zip", ".zip", - "application/zip")) { - ArchiveEntry archiveEntry = mock(ArchiveEntry.class); - when(archiveEntry.isDirectory()).thenReturn(true); - - try { - archiveHandle.getInputStream(archiveEntry); - fail("It should not be here."); - } catch (IllegalArgumentException e) { - /* expected, do nothing */ - } + ArchiveHandle archiveHandle = prepareArchiveHandle("archives/zip/hello.zip", + ".zip", "application/zip"); + + ArchiveEntry archiveEntry = mock(ArchiveEntry.class); + when(archiveEntry.isDirectory()).thenReturn(true); + + try { + archiveHandle.getInputStream(archiveEntry); + fail("It should not be here."); + } catch (IllegalArgumentException e) { + /* expected, do nothing */ } } @Test public void getInputStream_negativeSizeEntry_shouldFail() throws Exception { - try (ArchiveHandle archiveHandle = prepareArchiveHandle("archives/zip/hello.zip", ".zip", - "application/zip")) { - ArchiveEntry archiveEntry = mock(ArchiveEntry.class); - when(archiveEntry.isDirectory()).thenReturn(false); - when(archiveEntry.getSize()).thenReturn(-1L); - - try { - archiveHandle.getInputStream(archiveEntry); - fail("It should not be here."); - } catch (IllegalArgumentException e) { - /* expected, do nothing */ - } + ArchiveHandle archiveHandle = prepareArchiveHandle("archives/zip/hello.zip", + ".zip", "application/zip"); + + ArchiveEntry archiveEntry = mock(ArchiveEntry.class); + when(archiveEntry.isDirectory()).thenReturn(false); + when(archiveEntry.getSize()).thenReturn(-1L); + + try { + archiveHandle.getInputStream(archiveEntry); + fail("It should not be here."); + } catch (IllegalArgumentException e) { + /* expected, do nothing */ } } @Test public void getInputStream_emptyStringEntry_shouldFail() throws Exception { - try (ArchiveHandle archiveHandle = prepareArchiveHandle("archives/zip/hello.zip", ".zip", - "application/zip")) { - ArchiveEntry archiveEntry = mock(ArchiveEntry.class); - when(archiveEntry.isDirectory()).thenReturn(false); - when(archiveEntry.getSize()).thenReturn(14L); - when(archiveEntry.getName()).thenReturn(""); - - try { - archiveHandle.getInputStream(archiveEntry); - fail("It should not be here."); - } catch (IllegalArgumentException e) { - /* expected, do nothing */ - } + ArchiveHandle archiveHandle = prepareArchiveHandle("archives/zip/hello.zip", + ".zip", "application/zip"); + + ArchiveEntry archiveEntry = mock(ArchiveEntry.class); + when(archiveEntry.isDirectory()).thenReturn(false); + when(archiveEntry.getSize()).thenReturn(14L); + when(archiveEntry.getName()).thenReturn(""); + + try { + archiveHandle.getInputStream(archiveEntry); + fail("It should not be here."); + } catch (IllegalArgumentException e) { + /* expected, do nothing */ } } @Test public void getInputStream_sevenZFile_shouldHaveTheSameContent() throws Exception { - ParcelFileDescriptor parcelFileDescriptor = mArchiveFileTestRule.openAssetFile( - "archives/7z/hello.7z", ".7z"); + ParcelFileDescriptor parcelFileDescriptor = mArchiveFileTestRule + .openAssetFile("archives/7z/hello.7z", ".7z"); String expectedContent = mArchiveFileTestRule.getAssetText( "archives/original/hello/inside_folder/hello_insside.txt"); @@ -441,16 +496,17 @@ public class ArchiveHandleTest { "application/x-7z-compressed"); InputStream inputStream = archiveHandle.getInputStream( - requireNonNull(getFileInArchive(archiveHandle.getEntries()))); + getFileInArchive(archiveHandle.getEntries(), + "hello/inside_folder/hello_insside.txt")); - assertThat(ArchiveFileTestRule.getStringFromInputStream(inputStream)).isEqualTo( - expectedContent); + assertThat(ArchiveFileTestRule.getStringFromInputStream(inputStream)) + .isEqualTo(expectedContent); } @Test public void getInputStream_tarGzFile_shouldHaveTheSameContent() throws Exception { - ParcelFileDescriptor parcelFileDescriptor = mArchiveFileTestRule.openAssetFile( - "archives/tar_gz/hello.tgz", ".tar.gz"); + ParcelFileDescriptor parcelFileDescriptor = mArchiveFileTestRule + .openAssetFile("archives/tar_gz/hello.tgz", ".tar.gz"); String expectedContent = mArchiveFileTestRule.getAssetText( "archives/original/hello/inside_folder/hello_insside.txt"); @@ -459,16 +515,40 @@ public class ArchiveHandleTest { "application/x-compressed-tar"); InputStream inputStream = archiveHandle.getInputStream( - requireNonNull(getFileInArchive(archiveHandle.getEntries()))); + getFileInArchive(archiveHandle.getEntries(), + "hello/inside_folder/hello_insside.txt")); + + assertThat(ArchiveFileTestRule.getStringFromInputStream(inputStream)) + .isEqualTo(expectedContent); + } + + @Test + public void getInputStream_tarGzFileNullEntry_getNullInputStream() throws Exception { + ParcelFileDescriptor parcelFileDescriptor = mArchiveFileTestRule + .openAssetFile("archives/tar_gz/hello.tgz", ".tar.gz"); + + String expectedContent = mArchiveFileTestRule.getAssetText( + "archives/original/hello/inside_folder/hello_insside.txt"); - assertThat(ArchiveFileTestRule.getStringFromInputStream(inputStream)).isEqualTo( - expectedContent); + ArchiveHandle archiveHandle = ArchiveHandle.create(parcelFileDescriptor, + "application/x-compressed-tar"); + + try { + archiveHandle.getInputStream(null); + fail("It should not here"); + } catch (IllegalArgumentException | ArchiveException | CompressorException e) { + /* expected, do nothing */ + } } + @Test public void getInputStream_tarGzFileInvalidEntry_getNullInputStream() throws Exception { - ParcelFileDescriptor parcelFileDescriptor = mArchiveFileTestRule.openAssetFile( - "archives/tar_gz/hello.tgz", ".tar.gz"); + ParcelFileDescriptor parcelFileDescriptor = mArchiveFileTestRule + .openAssetFile("archives/tar_gz/hello.tgz", ".tar.gz"); + + String expectedContent = mArchiveFileTestRule.getAssetText( + "archives/original/hello/inside_folder/hello_insside.txt"); ArchiveHandle archiveHandle = ArchiveHandle.create(parcelFileDescriptor, "application/x-compressed-tar"); @@ -485,8 +565,8 @@ public class ArchiveHandleTest { @Test public void getInputStream_tarBrotliFile_shouldHaveTheSameContent() throws Exception { - ParcelFileDescriptor parcelFileDescriptor = mArchiveFileTestRule.openAssetFile( - "archives/brotli/hello.tar.br", ".tar.br"); + ParcelFileDescriptor parcelFileDescriptor = mArchiveFileTestRule + .openAssetFile("archives/brotli/hello.tar.br", ".tar.br"); String expectedContent = mArchiveFileTestRule.getAssetText( "archives/original/hello/inside_folder/hello_insside.txt"); @@ -495,63 +575,70 @@ public class ArchiveHandleTest { "application/x-brotli-compressed-tar"); InputStream inputStream = archiveHandle.getInputStream( - requireNonNull(getFileInArchive(archiveHandle.getEntries()))); + getFileInArchive(archiveHandle.getEntries(), + "hello/inside_folder/hello_insside.txt")); - assertThat(ArchiveFileTestRule.getStringFromInputStream(inputStream)).isEqualTo( - expectedContent); + assertThat(ArchiveFileTestRule.getStringFromInputStream(inputStream)) + .isEqualTo(expectedContent); } @Test public void getEntries_zipFile_shouldTheSameWithList() throws Exception { - try (ArchiveHandle archiveHandle = prepareArchiveHandle("archives/zip/hello.zip", ".zip", - "application/zip")) { - assertThat(transformToIterable(archiveHandle.getEntries())).containsAtLeastElementsIn( - sExpectEntries); - } + ArchiveHandle archiveHandle = + prepareArchiveHandle("archives/zip/hello.zip", ".zip", + "application/zip"); + + assertThat(transformToIterable(archiveHandle.getEntries())) + .containsAtLeastElementsIn(sExpectEntries); } @Test public void getEntries_tarFile_shouldTheSameWithList() throws Exception { - try (ArchiveHandle archiveHandle = prepareArchiveHandle("archives/tar/hello.tar", ".tar", - "application/x-gtar")) { - assertThat(transformToIterable(archiveHandle.getEntries())).containsAtLeastElementsIn( - sExpectEntries); - } + ArchiveHandle archiveHandle = + prepareArchiveHandle("archives/tar/hello.tar", ".tar", + "application/x-gtar"); + + assertThat(transformToIterable(archiveHandle.getEntries())) + .containsAtLeastElementsIn(sExpectEntries); } @Test public void getEntries_tgzFile_shouldTheSameWithList() throws Exception { - try (ArchiveHandle archiveHandle = prepareArchiveHandle("archives/tar_gz/hello.tgz", ".tgz", - "application/x-compressed-tar")) { - assertThat(transformToIterable(archiveHandle.getEntries())).containsAtLeastElementsIn( - sExpectEntries); - } + ArchiveHandle archiveHandle = + prepareArchiveHandle("archives/tar_gz/hello.tgz", ".tgz", + "application/x-compressed-tar"); + + assertThat(transformToIterable(archiveHandle.getEntries())) + .containsAtLeastElementsIn(sExpectEntries); } @Test public void getEntries_tarBzFile_shouldTheSameWithList() throws Exception { - try (ArchiveHandle archiveHandle = prepareArchiveHandle("archives/tar_bz2/hello.tar.bz2", - ".tar.bz2", "application/x-bzip-compressed-tar")) { - assertThat(transformToIterable(archiveHandle.getEntries())).containsAtLeastElementsIn( - sExpectEntries); - } + ArchiveHandle archiveHandle = + prepareArchiveHandle("archives/tar_bz2/hello.tar.bz2", ".tar.bz2", + "application/x-bzip-compressed-tar"); + + assertThat(transformToIterable(archiveHandle.getEntries())) + .containsAtLeastElementsIn(sExpectEntries); } @Test public void getEntries_tarBrotliFile_shouldTheSameWithList() throws Exception { - try (ArchiveHandle archiveHandle = prepareArchiveHandle("archives/brotli/hello.tar.br", - ".tar.br", "application/x-brotli-compressed-tar")) { - assertThat(transformToIterable(archiveHandle.getEntries())).containsAtLeastElementsIn( - sExpectEntries); - } + ArchiveHandle archiveHandle = + prepareArchiveHandle("archives/brotli/hello.tar.br", ".tar.br", + "application/x-brotli-compressed-tar"); + + assertThat(transformToIterable(archiveHandle.getEntries())) + .containsAtLeastElementsIn(sExpectEntries); } @Test public void getEntries_tarXzFile_shouldTheSameWithList() throws Exception { - try (ArchiveHandle archiveHandle = prepareArchiveHandle("archives/xz/hello.tar.xz", - ".tar.xz", "application/x-xz-compressed-tar")) { - assertThat(transformToIterable(archiveHandle.getEntries())).containsAtLeastElementsIn( - sExpectEntries); - } + ArchiveHandle archiveHandle = + prepareArchiveHandle("archives/xz/hello.tar.xz", ".tar.xz", + "application/x-xz-compressed-tar"); + + assertThat(transformToIterable(archiveHandle.getEntries())) + .containsAtLeastElementsIn(sExpectEntries); } } -- cgit v1.2.3-59-g8ed1b