diff options
Diffstat (limited to 'mobile/android/geckoview/src/androidTest/java/org/mozilla/geckoview/GeckoInputStreamTest.java')
-rw-r--r-- | mobile/android/geckoview/src/androidTest/java/org/mozilla/geckoview/GeckoInputStreamTest.java | 167 |
1 files changed, 167 insertions, 0 deletions
diff --git a/mobile/android/geckoview/src/androidTest/java/org/mozilla/geckoview/GeckoInputStreamTest.java b/mobile/android/geckoview/src/androidTest/java/org/mozilla/geckoview/GeckoInputStreamTest.java new file mode 100644 index 0000000000..98d43238a7 --- /dev/null +++ b/mobile/android/geckoview/src/androidTest/java/org/mozilla/geckoview/GeckoInputStreamTest.java @@ -0,0 +1,167 @@ +package org.mozilla.geckoview; + +import androidx.test.ext.junit.runners.AndroidJUnit4; +import androidx.test.filters.MediumTest; +import java.io.BufferedReader; +import java.io.File; +import java.io.FileInputStream; +import java.io.FileOutputStream; +import java.io.IOException; +import java.io.InputStreamReader; +import java.io.OutputStream; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.HashMap; +import java.util.List; +import java.util.concurrent.CompletableFuture; +import java.util.concurrent.ExecutionException; +import org.junit.Assert; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.mozilla.geckoview.test.BaseSessionTest; + +@RunWith(AndroidJUnit4.class) +@MediumTest +public class GeckoInputStreamTest extends BaseSessionTest { + + @Test + public void readAndWriteFile() throws IOException, ExecutionException, InterruptedException { + final byte[] originalBytes = getTestBytes(TEST_GIF_PATH); + final File createdFile = File.createTempFile("temp", ".gif"); + final GeckoInputStream geckoInputStream = new GeckoInputStream(null); + + // Reads from the GeckoInputStream and rewrites to a new file + final Thread readAndRewrite = + new Thread() { + public void run() { + try (OutputStream output = new FileOutputStream(createdFile)) { + byte[] buffer = new byte[4 * 1024]; + int read; + while ((read = geckoInputStream.read(buffer)) != -1) { + output.write(buffer, 0, read); + } + output.flush(); + geckoInputStream.close(); + } catch (IOException e) { + throw new RuntimeException(e.getMessage()); + } + } + }; + + // Writes the bytes from the original file to the GeckoInputStream + final Thread write = + new Thread() { + public void run() { + try { + geckoInputStream.appendBuffer(originalBytes); + } catch (IOException e) { + throw new RuntimeException(e.getMessage()); + } + geckoInputStream.sendEof(); + } + }; + + final CompletableFuture<Void> testReadWrite = + CompletableFuture.allOf( + CompletableFuture.runAsync(readAndRewrite), CompletableFuture.runAsync(write)); + testReadWrite.get(); + + final byte[] fileContent = new byte[(int) createdFile.length()]; + final FileInputStream fis = new FileInputStream(createdFile); + fis.read(fileContent); + fis.close(); + + Assert.assertTrue("File was recreated correctly.", Arrays.equals(originalBytes, fileContent)); + } + + class Writer implements Runnable { + final char threadName; + final int timesToRun; + final GeckoInputStream stream; + + public Writer(char threadName, int timesToRun, GeckoInputStream stream) { + this.threadName = threadName; + this.timesToRun = timesToRun; + this.stream = stream; + } + + public void run() { + for (int i = 0; i <= timesToRun; i++) { + final byte[] data = String.format("%s %d %n", threadName, i).getBytes(); + try { + stream.appendBuffer(data); + } catch (IOException e) { + throw new RuntimeException(e.getMessage()); + } + } + } + } + + private boolean isSequenceInOrder( + List<String> lines, List<Character> threadNames, int dataLength) { + HashMap<Character, Integer> lastValue = new HashMap<>(); + for (Character thread : threadNames) { + lastValue.put(thread, -1); + } + for (String line : lines) { + final char thread = line.charAt(0); + final int number = Integer.parseInt(line.replaceAll("[\\D]", "")); + + // Number should always be in sequence for a given thread + if (lastValue.get(thread) + 1 == number) { + lastValue.replace(thread, number); + } else { + return false; + } + } + for (Character thread : threadNames) { + if (lastValue.get(thread) != dataLength) { + return false; + } + } + return true; + } + + @Test + public void multipleWriters() throws ExecutionException, InterruptedException, IOException { + final GeckoInputStream geckoInputStream = new GeckoInputStream(null); + final List<Character> threadNames = Arrays.asList('A', 'B'); + final int writeCount = 1000; + final CompletableFuture<Void> writers = + CompletableFuture.allOf( + CompletableFuture.runAsync( + new Writer(threadNames.get(0), writeCount, geckoInputStream)), + CompletableFuture.runAsync( + new Writer(threadNames.get(1), writeCount, geckoInputStream))); + writers.get(); + geckoInputStream.sendEof(); + + final List<String> lines = new ArrayList<>(); + final BufferedReader reader = new BufferedReader(new InputStreamReader(geckoInputStream)); + while (reader.ready()) { + lines.add(reader.readLine()); + } + reader.close(); + + Assert.assertTrue( + "Writers wrote as expected.", isSequenceInOrder(lines, threadNames, writeCount)); + } + + @Test + public void writeError() throws IOException { + boolean didThrowIoException = false; + final GeckoInputStream inputStream = new GeckoInputStream(null); + final BufferedReader reader = new BufferedReader(new InputStreamReader(inputStream)); + final byte[] data = "Hello, World.".getBytes(); + inputStream.appendBuffer(data); + inputStream.writeError(); + inputStream.sendEof(); + try { + reader.readLine(); + } catch (IOException e) { + didThrowIoException = true; + } + reader.close(); + Assert.assertTrue("Correctly caused an IOException from writer.", didThrowIoException); + } +} |