1 /* 2 * Copyright (C) 2016 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.tools.build.apkzlib.utils; 18 19 import static org.junit.Assert.assertTrue; 20 21 import com.android.testutils.TestResources; 22 import com.android.tools.build.apkzlib.zip.ZFile; 23 import com.google.common.base.Preconditions; 24 import com.google.common.io.ByteSource; 25 import com.google.common.io.Resources; 26 import java.io.ByteArrayInputStream; 27 import java.io.EOFException; 28 import java.io.File; 29 import java.io.IOException; 30 import java.io.RandomAccessFile; 31 import javax.annotation.Nonnull; 32 33 /** 34 * Utility functions for tests. 35 */ 36 public final class ApkZFileTestUtils { 37 38 /** 39 * Reads a portion of a file to memory. 40 * 41 * @param file the file to read data from 42 * @param start the offset in the file to start reading 43 * @param length the number of bytes to read 44 * @return the bytes read 45 * @throws Exception failed to read the file 46 */ 47 @Nonnull readSegment(@onnull File file, long start, int length)48 public static byte[] readSegment(@Nonnull File file, long start, int length) throws Exception { 49 Preconditions.checkArgument(start >= 0, "start < 0"); 50 Preconditions.checkArgument(length >= 0, "length < 0"); 51 52 byte data[]; 53 try (RandomAccessFile raf = new RandomAccessFile(file, "r")) { 54 raf.seek(start); 55 56 data = new byte[length]; 57 int tot = 0; 58 while (tot < length) { 59 int r = raf.read(data, tot, length - tot); 60 if (r < 0) { 61 throw new EOFException(); 62 } 63 64 tot += r; 65 } 66 } 67 68 return data; 69 } 70 71 /** 72 * Obtains the test resource with the given path. 73 * 74 * @param path the path 75 * @return the test resource 76 */ 77 @Nonnull getResource(@onnull String path)78 public static File getResource(@Nonnull String path) { 79 File resource = TestResources.getFile(ApkZFileTestUtils.class, path); 80 assertTrue(resource.exists()); 81 return resource; 82 } 83 84 /** 85 * Obtains the test resource with the given path. 86 * 87 * @param path the path 88 * @return the test resource 89 */ 90 @Nonnull getResourceBytes(@onnull String path)91 public static ByteSource getResourceBytes(@Nonnull String path) { 92 return Resources.asByteSource(Resources.getResource(ApkZFileTestUtils.class, path)); 93 } 94 95 /** 96 * Sleeps the current thread for enough time to ensure that the local file system had enough 97 * time to notice a "tick". This method is usually called in tests when it is necessary to 98 * ensure filesystem writes are detected through timestamp modification. 99 * 100 * @param currentTimestamp last timestamp read from disk 101 * @throws InterruptedException waiting interrupted 102 * @throws IOException issues creating a temporary file 103 */ waitForFileSystemTick(long currentTimestamp)104 public static void waitForFileSystemTick(long currentTimestamp) 105 throws InterruptedException, IOException { 106 while (getFreshTimestamp() <= currentTimestamp) { 107 Thread.sleep(100); 108 } 109 } 110 111 /* 112 * Adds a basic compiled AndroidManifest to the given ZFile containing minSdkVersion equal 15 113 * and targetSdkVersion equal 25. 114 */ addAndroidManifest(ZFile zf)115 public static void addAndroidManifest(ZFile zf) throws IOException { 116 zf.add("AndroidManifest.xml", new ByteArrayInputStream(getAndroidManifest())); 117 } 118 119 /* 120 * Provides a basic compiled AndroidManifest containing minSdkVersion equal 15 and 121 * targetSdkVersion equal 25. 122 */ getAndroidManifest()123 public static byte[] getAndroidManifest() throws IOException { 124 return ApkZFileTestUtils.getResourceBytes("/testData/packaging/AndroidManifest.xml").read(); 125 } 126 127 /** 128 * Obtains the timestamp of a newly-created file. 129 * 130 * @return the timestamp 131 * @throws IOException the I/O Exception 132 */ getFreshTimestamp()133 private static long getFreshTimestamp() throws IOException { 134 File notUsed = File.createTempFile(ApkZFileTestUtils.class.getName(), "waitForFSTick"); 135 long freshTimestamp = notUsed.lastModified(); 136 assertTrue(notUsed.delete()); 137 return freshTimestamp; 138 } 139 } 140