1 /* 2 * Copyright 2022 Google LLC 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 package com.google.android.libraries.mobiledatadownload.file.common.testing; 17 18 import static com.google.android.libraries.mobiledatadownload.file.common.internal.Charsets.ISO_8859_1; 19 import static com.google.android.libraries.mobiledatadownload.file.common.internal.Charsets.UTF_8; 20 import static com.google.common.truth.Truth.assertThat; 21 22 import android.net.Uri; 23 import com.google.android.libraries.mobiledatadownload.file.SynchronousFileStorage; 24 import com.google.android.libraries.mobiledatadownload.file.common.ReleasableResource; 25 import com.google.android.libraries.mobiledatadownload.file.openers.AppendStreamOpener; 26 import com.google.android.libraries.mobiledatadownload.file.openers.ReadStreamOpener; 27 import com.google.android.libraries.mobiledatadownload.file.openers.WriteStreamOpener; 28 import com.google.common.io.ByteStreams; 29 import com.google.common.io.CharStreams; 30 import java.io.Closeable; 31 import java.io.IOException; 32 import java.io.InputStream; 33 import java.io.InputStreamReader; 34 import java.io.OutputStream; 35 import java.io.OutputStreamWriter; 36 import java.io.Reader; 37 import java.io.Writer; 38 39 /** Helpers for using Streams in tests. */ 40 public final class StreamUtils { 41 StreamUtils()42 private StreamUtils() {} 43 44 @Deprecated createFile(SynchronousFileStorage storage, Uri uri, String contents)45 public static void createFile(SynchronousFileStorage storage, Uri uri, String contents) 46 throws IOException { 47 writeFileToSink(storage.open(uri, WriteStreamOpener.create()), contents); 48 } 49 createFile(SynchronousFileStorage storage, Uri uri, byte[] contents)50 public static void createFile(SynchronousFileStorage storage, Uri uri, byte[] contents) 51 throws IOException { 52 try (OutputStream out = storage.open(uri, WriteStreamOpener.create())) { 53 out.write(contents); 54 } 55 } 56 57 /** 58 * Write contents to sink stream and then close it. 59 * 60 * @deprecated Use the equivalent byte-based method. 61 */ 62 @Deprecated writeFileToSink(OutputStream sink, String contents)63 public static void writeFileToSink(OutputStream sink, String contents) throws IOException { 64 try (Writer writer = new OutputStreamWriter(sink, ISO_8859_1)) { 65 writer.write(contents); 66 } 67 } 68 writeFileToSink(OutputStream sink, byte[] contents)69 public static void writeFileToSink(OutputStream sink, byte[] contents) throws IOException { 70 try (ReleasableResource<Closeable> out = ReleasableResource.create(sink)) { 71 sink.write(contents); 72 } 73 } 74 75 /** Appends or Creates a file at {@code uri} containing the byte stream {@code contents}. */ appendFile(SynchronousFileStorage storage, Uri uri, byte[] contents)76 public static void appendFile(SynchronousFileStorage storage, Uri uri, byte[] contents) 77 throws IOException { 78 try (OutputStream out = storage.open(uri, AppendStreamOpener.create())) { 79 out.write(contents); 80 } 81 } 82 83 @Deprecated readFile(SynchronousFileStorage storage, Uri uri)84 public static String readFile(SynchronousFileStorage storage, Uri uri) throws IOException { 85 return readFileFromSource(storage.open(uri, ReadStreamOpener.create())); 86 } 87 readFileInBytes(SynchronousFileStorage storage, Uri uri)88 public static byte[] readFileInBytes(SynchronousFileStorage storage, Uri uri) throws IOException { 89 try (InputStream in = storage.open(uri, ReadStreamOpener.create())) { 90 return ByteStreams.toByteArray(in); 91 } 92 } 93 /** 94 * Read all bytes from source stream and then close it. 95 * 96 * @deprecated Use the equivalent byte-based method. 97 */ 98 @Deprecated readFileFromSource(InputStream source)99 public static String readFileFromSource(InputStream source) throws IOException { 100 try (Reader reader = new InputStreamReader(source, ISO_8859_1)) { 101 return CharStreams.toString(reader); 102 } 103 } 104 readFileInBytesFromSource(InputStream source)105 public static byte[] readFileInBytesFromSource(InputStream source) throws IOException { 106 byte[] read = null; 107 try (ReleasableResource<Closeable> in = ReleasableResource.create(source)) { 108 read = ByteStreams.toByteArray(source); 109 } 110 return read; 111 } 112 /** 113 * Create an amount of content that exceeds what the OS is expected to buffer. This is sufficient 114 * for convincing ourselves that streams behave as expected. 115 * 116 * <p>TODO: This could also be testdata - should it be? 117 * 118 * @deprecated Use the equivalent byte-based method. 119 */ 120 @Deprecated makeContentThatExceedsOsBufferSize()121 public static String makeContentThatExceedsOsBufferSize() { 122 StringBuilder buf = new StringBuilder(); 123 for (int i = 0; i < 2000; i++) { 124 buf.append("all work and no play makes jack a dull boy\n"); 125 } 126 assertThat(buf.length()).isGreaterThan(65536 /* linux pipe capacity*/); 127 return buf.toString(); 128 } 129 makeByteContentThatExceedsOsBufferSize()130 public static byte[] makeByteContentThatExceedsOsBufferSize() { 131 return makeArrayOfBytesContent(65540); // linux pipe capacity is 65536 132 } 133 134 /** Create an arbitrary array of bytes */ makeArrayOfBytesContent()135 public static byte[] makeArrayOfBytesContent() { 136 return "all work and no play makes jack a dull boy\n".getBytes(UTF_8); 137 } 138 139 /** Create an arbitrary array of bytes of a given length */ makeArrayOfBytesContent(int length)140 public static byte[] makeArrayOfBytesContent(int length) { 141 byte[] array = new byte[length]; 142 for (int i = 0; i < length; i++) { 143 array[i] = (byte) i; 144 } 145 return array; 146 } 147 } 148