1 /* 2 * Copyright (C) 2019 The Android Open Source Project 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17 package com.android.documentsui.archives; 18 19 import static android.os.ParcelFileDescriptor.MODE_READ_ONLY; 20 21 import android.os.ParcelFileDescriptor; 22 import android.util.Log; 23 24 import androidx.test.platform.app.InstrumentationRegistry; 25 26 import org.apache.commons.compress.utils.IOUtils; 27 import org.junit.rules.TestName; 28 import org.junit.runner.Description; 29 30 import java.io.FileInputStream; 31 import java.io.IOException; 32 import java.io.InputStream; 33 import java.io.InputStreamReader; 34 import java.nio.file.Files; 35 import java.nio.file.Path; 36 import java.nio.file.StandardCopyOption; 37 import java.nio.file.attribute.FileAttribute; 38 import java.nio.file.attribute.PosixFilePermission; 39 import java.nio.file.attribute.PosixFilePermissions; 40 import java.util.ArrayList; 41 import java.util.List; 42 import java.util.Locale; 43 import java.util.Set; 44 45 public class ArchiveFileTestRule extends TestName { 46 private static final String TAG = ArchiveFileTestRule.class.getSimpleName(); 47 48 private final List<Path> mTemporaries; 49 private final List<ParcelFileDescriptor> mParcelFileDescriptors; 50 51 private String mClassName; 52 private String mMethodName; 53 private Path mTemporaryPath; 54 ArchiveFileTestRule()55 public ArchiveFileTestRule() { 56 mTemporaries = new ArrayList<>(); 57 mParcelFileDescriptors = new ArrayList<>(); 58 } 59 60 @Override starting(Description description)61 protected void starting(Description description) { 62 super.starting(description); 63 mClassName = description.getClassName(); 64 mMethodName = description.getMethodName(); 65 66 try { 67 mTemporaryPath = Files.createTempDirectory( 68 InstrumentationRegistry.getInstrumentation() 69 .getTargetContext().getCacheDir().toPath(), 70 mClassName); 71 } catch (IOException e) { 72 Log.e(TAG, String.format(Locale.ENGLISH, 73 "It can't create temporary directory in the staring of %s.%s.", 74 mClassName, mMethodName)); 75 } 76 } 77 78 @Override finished(Description description)79 protected void finished(Description description) { 80 super.finished(description); 81 82 for (Path path : mTemporaries) { 83 if (path != null) { 84 path.toFile().delete(); 85 } 86 } 87 88 mTemporaryPath.toFile().delete(); 89 90 for (ParcelFileDescriptor parcelFileDescriptor : mParcelFileDescriptors) { 91 IOUtils.closeQuietly(parcelFileDescriptor); 92 } 93 } 94 95 /** 96 * To generate the temporary file and return the file path. 97 * 98 * @param suffix the suffix of the temporary file name 99 * @return the file path 100 * @throws IOException to create temporary file fail raises IOException 101 */ generateFile(String suffix)102 public Path generateFile(String suffix) throws IOException { 103 Set<PosixFilePermission> perm = PosixFilePermissions.fromString("rwx------"); 104 FileAttribute<Set<PosixFilePermission>> attr = PosixFilePermissions.asFileAttribute(perm); 105 Path filePath = Files.createTempFile(mTemporaryPath, mMethodName, suffix, attr); 106 mTemporaries.add(filePath); 107 return filePath; 108 } 109 110 /** 111 * To dump asset path file as temporary file. There are some problems to get the file 112 * descriptor from the asset files in instrumentation context. It's null pointer. It needs to 113 * dump to temporary file in the target context of the instrumentation. 114 * 115 * @param assetPath assetPath in test context 116 * @param suffix the suffix of the temporary file name 117 * @return the file path 118 */ dumpAssetFile(String assetPath, String suffix)119 public Path dumpAssetFile(String assetPath, String suffix) throws IOException { 120 Path destinationPath = generateFile(suffix); 121 122 try (InputStream inputStream = InstrumentationRegistry.getInstrumentation() 123 .getContext().getAssets().open(assetPath)) { 124 Files.copy(inputStream, destinationPath, StandardCopyOption.REPLACE_EXISTING); 125 } 126 127 return destinationPath; 128 } 129 130 /** 131 * To dump asset path file as temporary file. There are some problems to get the file 132 * descriptor from the asset files in instrumentation context. It's null pointer. It needs to 133 * dump to temporary file in the target context of the instrumentation. 134 * 135 * @param assetPath assetPath in test context 136 * @param suffix the suffix of the temporary file name 137 * @return the file path 138 */ openAssetFile(String assetPath, String suffix)139 public ParcelFileDescriptor openAssetFile(String assetPath, String suffix) throws IOException { 140 Path destinationPath = dumpAssetFile(assetPath, suffix); 141 142 ParcelFileDescriptor parcelFileDescriptor = ParcelFileDescriptor 143 .open(destinationPath.toFile(), MODE_READ_ONLY); 144 145 mParcelFileDescriptors.add(parcelFileDescriptor); 146 return parcelFileDescriptor; 147 } 148 149 /** 150 * To get asset content that is a type of text. 151 * 152 * @param assetPath assetPath in test context 153 * @return the text content 154 */ getAssetText(String assetPath)155 public String getAssetText(String assetPath) throws IOException { 156 ParcelFileDescriptor parcelFileDescriptor = openAssetFile(assetPath, ".text"); 157 158 try (FileInputStream fileInputStream = 159 new FileInputStream(parcelFileDescriptor.getFileDescriptor())) { 160 return getStringFromInputStream(fileInputStream); 161 } 162 } 163 getStringFromInputStream(InputStream inputStream)164 public static String getStringFromInputStream(InputStream inputStream) throws IOException { 165 InputStreamReader inputStreamReader = new InputStreamReader(inputStream); 166 167 int size = inputStream.available(); 168 char[] buffer = new char[size]; 169 170 inputStreamReader.read(buffer); 171 172 return new String(buffer); 173 } 174 } 175