8233451: (fs) Files.newInputStream() cannot be used with character special files
Reviewed-by: alanb
This commit is contained in:
parent
002de86081
commit
de92fe3757
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2001, 2023, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 2001, 2024, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
@ -38,6 +38,7 @@ import java.nio.channels.WritableByteChannel;
|
||||
import java.util.Arrays;
|
||||
import java.util.Objects;
|
||||
import jdk.internal.util.ArraysSupport;
|
||||
import jdk.internal.vm.annotation.Stable;
|
||||
|
||||
/**
|
||||
* An InputStream that reads bytes from a channel.
|
||||
@ -53,6 +54,10 @@ class ChannelInputStream extends InputStream {
|
||||
private byte[] bs; // Invoker's previous array
|
||||
private byte[] b1;
|
||||
|
||||
// if isOther is true, then the file being read is not a regular file,
|
||||
// nor a directory, nor a symbolic link, hence possibly not seekable
|
||||
private @Stable Boolean isOther;
|
||||
|
||||
/**
|
||||
* Initialize a ChannelInputStream that reads from the given channel.
|
||||
*/
|
||||
@ -60,6 +65,17 @@ class ChannelInputStream extends InputStream {
|
||||
this.ch = ch;
|
||||
}
|
||||
|
||||
private boolean isOther() throws IOException {
|
||||
Boolean isOther = this.isOther;
|
||||
if (isOther == null) {
|
||||
if (ch instanceof FileChannelImpl fci)
|
||||
this.isOther = isOther = fci.isOther();
|
||||
else
|
||||
this.isOther = isOther = Boolean.FALSE;
|
||||
}
|
||||
return isOther;
|
||||
}
|
||||
|
||||
/**
|
||||
* Reads a sequence of bytes from the channel into the given buffer.
|
||||
*/
|
||||
@ -105,7 +121,8 @@ class ChannelInputStream extends InputStream {
|
||||
|
||||
@Override
|
||||
public byte[] readAllBytes() throws IOException {
|
||||
if (!(ch instanceof SeekableByteChannel sbc))
|
||||
if (!(ch instanceof SeekableByteChannel sbc) ||
|
||||
(ch instanceof FileChannelImpl fci && isOther()))
|
||||
return super.readAllBytes();
|
||||
|
||||
long length = sbc.size();
|
||||
@ -156,7 +173,8 @@ class ChannelInputStream extends InputStream {
|
||||
if (len == 0)
|
||||
return new byte[0];
|
||||
|
||||
if (!(ch instanceof SeekableByteChannel sbc))
|
||||
if (!(ch instanceof SeekableByteChannel sbc) ||
|
||||
(ch instanceof FileChannelImpl fci && isOther()))
|
||||
return super.readNBytes(len);
|
||||
|
||||
long length = sbc.size();
|
||||
@ -192,7 +210,9 @@ class ChannelInputStream extends InputStream {
|
||||
@Override
|
||||
public int available() throws IOException {
|
||||
// special case where the channel is to a file
|
||||
if (ch instanceof SeekableByteChannel sbc) {
|
||||
if (ch instanceof FileChannelImpl fci) {
|
||||
return fci.available();
|
||||
} else if (ch instanceof SeekableByteChannel sbc) {
|
||||
long rem = Math.max(0, sbc.size() - sbc.position());
|
||||
return (rem > Integer.MAX_VALUE) ? Integer.MAX_VALUE : (int)rem;
|
||||
}
|
||||
@ -202,7 +222,8 @@ class ChannelInputStream extends InputStream {
|
||||
@Override
|
||||
public synchronized long skip(long n) throws IOException {
|
||||
// special case where the channel is to a file
|
||||
if (ch instanceof SeekableByteChannel sbc) {
|
||||
if (ch instanceof SeekableByteChannel sbc &&
|
||||
!(ch instanceof FileChannelImpl fci && isOther())) {
|
||||
long pos = sbc.position();
|
||||
long newPos;
|
||||
if (n > 0) {
|
||||
@ -224,7 +245,8 @@ class ChannelInputStream extends InputStream {
|
||||
public long transferTo(OutputStream out) throws IOException {
|
||||
Objects.requireNonNull(out, "out");
|
||||
|
||||
if (ch instanceof FileChannel fc) {
|
||||
if (ch instanceof FileChannel fc &&
|
||||
!(fc instanceof FileChannelImpl fci && isOther())) {
|
||||
// FileChannel -> SocketChannel
|
||||
if (out instanceof SocketOutputStream sos) {
|
||||
SocketChannelImpl sc = sos.channel();
|
||||
|
@ -454,6 +454,7 @@ public class FileChannelImpl
|
||||
}
|
||||
return bytesWritten;
|
||||
}
|
||||
|
||||
// -- Other operations --
|
||||
|
||||
@Override
|
||||
@ -529,6 +530,49 @@ public class FileChannelImpl
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns an estimate of the number of remaining bytes that can be read
|
||||
* from this channel without blocking.
|
||||
*/
|
||||
int available() throws IOException {
|
||||
ensureOpen();
|
||||
synchronized (positionLock) {
|
||||
int a = -1;
|
||||
int ti = -1;
|
||||
try {
|
||||
beginBlocking();
|
||||
ti = threads.add();
|
||||
if (!isOpen())
|
||||
return -1;
|
||||
a = nd.available(fd);
|
||||
} finally {
|
||||
threads.remove(ti);
|
||||
endBlocking(a > -1);
|
||||
}
|
||||
return a;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Tells whether the channel represents something other than a regular
|
||||
* file, directory, or symbolic link.
|
||||
*/
|
||||
boolean isOther() throws IOException {
|
||||
ensureOpen();
|
||||
int ti = -1;
|
||||
Boolean isOther = null;
|
||||
try {
|
||||
beginBlocking();
|
||||
ti = threads.add();
|
||||
if (!isOpen())
|
||||
return false;
|
||||
return isOther = nd.isOther(fd);
|
||||
} finally {
|
||||
threads.remove(ti);
|
||||
endBlocking(isOther != null);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public FileChannel truncate(long newSize) throws IOException {
|
||||
ensureOpen();
|
||||
|
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2007, 2022, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 2007, 2024, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
@ -49,6 +49,10 @@ abstract class FileDispatcher extends NativeDispatcher {
|
||||
|
||||
abstract long size(FileDescriptor fd) throws IOException;
|
||||
|
||||
abstract int available(FileDescriptor fd) throws IOException;
|
||||
|
||||
abstract boolean isOther(FileDescriptor fd) throws IOException;
|
||||
|
||||
abstract int lock(FileDescriptor fd, boolean blocking, long pos, long size,
|
||||
boolean shared) throws IOException;
|
||||
|
||||
|
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2000, 2022, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 2000, 2024, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
@ -93,6 +93,14 @@ class UnixFileDispatcherImpl extends FileDispatcher {
|
||||
return size0(fd);
|
||||
}
|
||||
|
||||
int available(FileDescriptor fd) throws IOException {
|
||||
return available0(fd);
|
||||
}
|
||||
|
||||
boolean isOther(FileDescriptor fd) throws IOException {
|
||||
return isOther0(fd);
|
||||
}
|
||||
|
||||
int lock(FileDescriptor fd, boolean blocking, long pos, long size,
|
||||
boolean shared) throws IOException
|
||||
{
|
||||
@ -196,6 +204,10 @@ class UnixFileDispatcherImpl extends FileDispatcher {
|
||||
|
||||
static native long size0(FileDescriptor fd) throws IOException;
|
||||
|
||||
static native int available0(FileDescriptor fd) throws IOException;
|
||||
|
||||
static native boolean isOther0(FileDescriptor fd) throws IOException;
|
||||
|
||||
static native int lock0(FileDescriptor fd, boolean blocking, long pos,
|
||||
long size, boolean shared) throws IOException;
|
||||
|
||||
|
@ -23,6 +23,7 @@
|
||||
* questions.
|
||||
*/
|
||||
|
||||
#include <sys/ioctl.h>
|
||||
#include <sys/mman.h>
|
||||
#include <sys/uio.h>
|
||||
#include <sys/stat.h>
|
||||
@ -41,8 +42,10 @@
|
||||
#include "nio.h"
|
||||
#include "nio_util.h"
|
||||
#include "sun_nio_ch_UnixFileDispatcherImpl.h"
|
||||
#include "java_lang_Integer.h"
|
||||
#include "java_lang_Long.h"
|
||||
#include <assert.h>
|
||||
#include "io_util_md.h"
|
||||
|
||||
#if defined(_AIX)
|
||||
#define statvfs statvfs64
|
||||
@ -178,6 +181,57 @@ Java_sun_nio_ch_UnixFileDispatcherImpl_size0(JNIEnv *env, jobject this, jobject
|
||||
return fbuf.st_size;
|
||||
}
|
||||
|
||||
JNIEXPORT jint JNICALL
|
||||
Java_sun_nio_ch_UnixFileDispatcherImpl_available0(JNIEnv *env, jobject this, jobject fdo)
|
||||
{
|
||||
jint fd = fdval(env, fdo);
|
||||
struct stat fbuf;
|
||||
jlong size = -1;
|
||||
|
||||
if (fstat(fd, &fbuf) != -1) {
|
||||
int mode = fbuf.st_mode;
|
||||
if (S_ISCHR(mode) || S_ISFIFO(mode) || S_ISSOCK(mode)) {
|
||||
int n = ioctl(fd, FIONREAD, &n);
|
||||
if (n >= 0) {
|
||||
return n;
|
||||
}
|
||||
} else if (S_ISREG(mode)) {
|
||||
size = fbuf.st_size;
|
||||
}
|
||||
}
|
||||
|
||||
jlong position;
|
||||
if ((position = lseek(fd, 0, SEEK_CUR)) == -1) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (size < position) {
|
||||
if ((size = lseek(fd, 0, SEEK_END)) == -1)
|
||||
return 0;
|
||||
else if (lseek(fd, position, SEEK_SET) == -1)
|
||||
return 0;
|
||||
}
|
||||
|
||||
jlong available = size - position;
|
||||
return available > java_lang_Integer_MAX_VALUE ?
|
||||
java_lang_Integer_MAX_VALUE : (jint)available;
|
||||
}
|
||||
|
||||
JNIEXPORT jboolean JNICALL
|
||||
Java_sun_nio_ch_UnixFileDispatcherImpl_isOther0(JNIEnv *env, jobject this, jobject fdo)
|
||||
{
|
||||
jint fd = fdval(env, fdo);
|
||||
struct stat fbuf;
|
||||
|
||||
if (fstat(fd, &fbuf) == -1)
|
||||
handle(env, -1, "isOther failed");
|
||||
|
||||
if (S_ISREG(fbuf.st_mode) || S_ISDIR(fbuf.st_mode) || S_ISLNK(fbuf.st_mode))
|
||||
return JNI_FALSE;
|
||||
|
||||
return JNI_TRUE;
|
||||
}
|
||||
|
||||
JNIEXPORT jint JNICALL
|
||||
Java_sun_nio_ch_UnixFileDispatcherImpl_lock0(JNIEnv *env, jobject this, jobject fdo,
|
||||
jboolean block, jlong pos, jlong size,
|
||||
|
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2000, 2022, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 2000, 2024, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
@ -101,6 +101,14 @@ class FileDispatcherImpl extends FileDispatcher {
|
||||
return size0(fd);
|
||||
}
|
||||
|
||||
int available(FileDescriptor fd) throws IOException {
|
||||
return available0(fd);
|
||||
}
|
||||
|
||||
boolean isOther(FileDescriptor fd) throws IOException {
|
||||
return isOther0(fd);
|
||||
}
|
||||
|
||||
int lock(FileDescriptor fd, boolean blocking, long pos, long size,
|
||||
boolean shared) throws IOException
|
||||
{
|
||||
@ -223,6 +231,10 @@ class FileDispatcherImpl extends FileDispatcher {
|
||||
|
||||
static native long size0(FileDescriptor fd) throws IOException;
|
||||
|
||||
static native int available0(FileDescriptor fd) throws IOException;
|
||||
|
||||
static native boolean isOther0(FileDescriptor fd) throws IOException;
|
||||
|
||||
static native int lock0(FileDescriptor fd, boolean blocking, long pos,
|
||||
long size, boolean shared) throws IOException;
|
||||
|
||||
|
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2000, 2023, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 2000, 2024, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
@ -24,6 +24,7 @@
|
||||
*/
|
||||
|
||||
#include <windows.h>
|
||||
#include <winioctl.h>
|
||||
#include "jni.h"
|
||||
#include "jni_util.h"
|
||||
#include "jvm.h"
|
||||
@ -33,6 +34,7 @@
|
||||
#include "nio_util.h"
|
||||
#include "java_lang_Integer.h"
|
||||
#include "sun_nio_ch_FileDispatcherImpl.h"
|
||||
#include "io_util_md.h"
|
||||
|
||||
#include <Mswsock.h> // Requires Mswsock.lib
|
||||
|
||||
@ -392,6 +394,75 @@ Java_sun_nio_ch_FileDispatcherImpl_size0(JNIEnv *env, jobject this, jobject fdo)
|
||||
return (jlong)size.QuadPart;
|
||||
}
|
||||
|
||||
JNIEXPORT jint JNICALL
|
||||
Java_sun_nio_ch_FileDispatcherImpl_available0(JNIEnv *env, jobject this, jobject fdo)
|
||||
{
|
||||
HANDLE handle = (HANDLE)(handleval(env, fdo));
|
||||
DWORD type = GetFileType(handle);
|
||||
jlong available = 0;
|
||||
|
||||
// Calculate the number of bytes available for a regular file,
|
||||
// and return the default (zero) for other types.
|
||||
if (type == FILE_TYPE_DISK) {
|
||||
jlong current, end;
|
||||
LARGE_INTEGER distance, pos, filesize;
|
||||
distance.QuadPart = 0;
|
||||
if (SetFilePointerEx(handle, distance, &pos, FILE_CURRENT) == 0) {
|
||||
JNU_ThrowIOExceptionWithLastError(env, "Available failed");
|
||||
return IOS_THROWN;
|
||||
}
|
||||
current = (jlong)pos.QuadPart;
|
||||
if (GetFileSizeEx(handle, &filesize) == 0) {
|
||||
JNU_ThrowIOExceptionWithLastError(env, "Available failed");
|
||||
return IOS_THROWN;
|
||||
}
|
||||
end = (jlong)filesize.QuadPart;
|
||||
available = end - current;
|
||||
if (available > java_lang_Integer_MAX_VALUE) {
|
||||
available = java_lang_Integer_MAX_VALUE;
|
||||
} else if (available < 0) {
|
||||
available = 0;
|
||||
}
|
||||
}
|
||||
|
||||
return (jint)available;
|
||||
}
|
||||
|
||||
|
||||
JNIEXPORT jboolean JNICALL
|
||||
Java_sun_nio_ch_FileDispatcherImpl_isOther0(JNIEnv *env, jobject this, jobject fdo)
|
||||
{
|
||||
HANDLE handle = (HANDLE)(handleval(env, fdo));
|
||||
|
||||
BY_HANDLE_FILE_INFORMATION finfo;
|
||||
if (!GetFileInformationByHandle(handle, &finfo))
|
||||
JNU_ThrowIOExceptionWithLastError(env, "isOther failed");
|
||||
DWORD fattr = finfo.dwFileAttributes;
|
||||
|
||||
if ((fattr & FILE_ATTRIBUTE_DEVICE) != 0)
|
||||
return (jboolean)JNI_TRUE;
|
||||
|
||||
if ((fattr & FILE_ATTRIBUTE_REPARSE_POINT) != 0) {
|
||||
int size = MAXIMUM_REPARSE_DATA_BUFFER_SIZE;
|
||||
void* lpOutBuffer = (void*)malloc(size*sizeof(char));
|
||||
if (lpOutBuffer == NULL)
|
||||
JNU_ThrowOutOfMemoryError(env, "isOther failed");
|
||||
|
||||
DWORD bytesReturned;
|
||||
if (!DeviceIoControl(handle, FSCTL_GET_REPARSE_POINT, NULL, 0,
|
||||
lpOutBuffer, (DWORD)size, &bytesReturned, NULL)) {
|
||||
free(lpOutBuffer);
|
||||
JNU_ThrowIOExceptionWithLastError(env, "isOther failed");
|
||||
}
|
||||
ULONG reparseTag = (*((PULONG)lpOutBuffer));
|
||||
free(lpOutBuffer);
|
||||
return reparseTag == IO_REPARSE_TAG_SYMLINK ?
|
||||
(jboolean)JNI_FALSE : (jboolean)JNI_TRUE;
|
||||
}
|
||||
|
||||
return (jboolean)JNI_FALSE;
|
||||
}
|
||||
|
||||
JNIEXPORT jint JNICALL
|
||||
Java_sun_nio_ch_FileDispatcherImpl_lock0(JNIEnv *env, jobject this, jobject fdo,
|
||||
jboolean block, jlong pos, jlong size,
|
||||
|
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2019, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 2019, 2024, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
@ -22,37 +22,123 @@
|
||||
*/
|
||||
|
||||
/* @test
|
||||
* @bug 8227609
|
||||
* @bug 8227609 8233451
|
||||
* @summary Test of InputStream and OutputStream created by java.nio.file.Files
|
||||
* @library ..
|
||||
* @library .. /test/lib
|
||||
* @build jdk.test.lib.Platform
|
||||
* @run junit/othervm --enable-native-access=ALL-UNNAMED InputStreamTest
|
||||
*/
|
||||
|
||||
import java.io.FileInputStream;
|
||||
import java.io.FileOutputStream;
|
||||
import java.io.InputStream;
|
||||
import java.io.OutputStream;
|
||||
import java.nio.channels.ClosedChannelException;
|
||||
import java.nio.file.*;
|
||||
import static java.nio.file.Files.*;
|
||||
import static java.nio.file.LinkOption.*;
|
||||
import java.nio.file.attribute.*;
|
||||
import java.io.IOException;
|
||||
import java.util.*;
|
||||
import java.io.OutputStream;
|
||||
import java.lang.foreign.Arena;
|
||||
import java.lang.foreign.FunctionDescriptor;
|
||||
import java.lang.foreign.Linker;
|
||||
import java.lang.foreign.MemorySegment;
|
||||
import java.lang.foreign.SymbolLookup;
|
||||
import java.lang.foreign.ValueLayout;
|
||||
import java.lang.invoke.MethodHandle;
|
||||
import java.nio.channels.ClosedChannelException;
|
||||
import java.nio.file.Files;
|
||||
import java.nio.file.Path;
|
||||
import java.util.Arrays;
|
||||
import jdk.test.lib.Platform;
|
||||
|
||||
import org.junit.jupiter.api.AfterAll;
|
||||
import org.junit.jupiter.api.BeforeAll;
|
||||
import org.junit.jupiter.api.Test;
|
||||
import org.junit.jupiter.api.condition.DisabledOnOs;
|
||||
import org.junit.jupiter.api.condition.OS;
|
||||
import static org.junit.jupiter.api.Assertions.*;
|
||||
|
||||
public class InputStreamTest {
|
||||
|
||||
public static void main(String[] args) throws IOException {
|
||||
Path dir = TestUtil.createTemporaryDirectory();
|
||||
try {
|
||||
testSkip(dir);
|
||||
} finally {
|
||||
TestUtil.removeAll(dir);
|
||||
private static final String PIPE = "pipe";
|
||||
private static final Path PIPE_PATH = Path.of(PIPE);
|
||||
private static final String SENTENCE =
|
||||
"Tout est permis mais rien n’est possible";
|
||||
|
||||
private static Path TMPDIR;
|
||||
|
||||
private static class mkfifo {
|
||||
public static final FunctionDescriptor DESC = FunctionDescriptor.of(
|
||||
ValueLayout.JAVA_INT,
|
||||
ValueLayout.ADDRESS,
|
||||
ValueLayout.JAVA_SHORT
|
||||
);
|
||||
|
||||
public static final MemorySegment ADDR;
|
||||
static {
|
||||
Linker linker = Linker.nativeLinker();
|
||||
SymbolLookup stdlib = linker.defaultLookup();
|
||||
ADDR = stdlib.find("mkfifo").orElseThrow();
|
||||
}
|
||||
|
||||
public static final MethodHandle HANDLE =
|
||||
Linker.nativeLinker().downcallHandle(ADDR, DESC);
|
||||
}
|
||||
|
||||
public static int mkfifo(MemorySegment x0, short x1) {
|
||||
var mh$ = mkfifo.HANDLE;
|
||||
try {
|
||||
return (int)mh$.invokeExact(x0, x1);
|
||||
} catch (Throwable ex$) {
|
||||
throw new AssertionError("should not reach here", ex$);
|
||||
}
|
||||
}
|
||||
|
||||
private static Thread createWriteThread() {
|
||||
Thread t = new Thread(
|
||||
new Runnable() {
|
||||
public void run() {
|
||||
try (FileOutputStream fos = new FileOutputStream(PIPE);) {
|
||||
fos.write(SENTENCE.getBytes());
|
||||
} catch (IOException e) {
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
}
|
||||
}
|
||||
);
|
||||
t.start();
|
||||
return t;
|
||||
}
|
||||
|
||||
@BeforeAll
|
||||
static void before() throws InterruptedException, IOException {
|
||||
TMPDIR = TestUtil.createTemporaryDirectory();
|
||||
|
||||
if (Platform.isWindows())
|
||||
return;
|
||||
|
||||
Files.deleteIfExists(PIPE_PATH);
|
||||
try (var newArena = Arena.ofConfined()) {
|
||||
var addr = newArena.allocateFrom(PIPE);
|
||||
short mode = 0666;
|
||||
assertEquals(0, mkfifo(addr, mode));
|
||||
}
|
||||
if (Files.notExists(PIPE_PATH))
|
||||
throw new RuntimeException("Failed to create " + PIPE);
|
||||
}
|
||||
|
||||
@AfterAll
|
||||
static void after() throws IOException {
|
||||
TestUtil.removeAll(TMPDIR);
|
||||
|
||||
if (Platform.isWindows())
|
||||
return;
|
||||
|
||||
Files.deleteIfExists(PIPE_PATH);
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests Files.newInputStream(Path).skip().
|
||||
*/
|
||||
static void testSkip(Path tmpdir) throws IOException {
|
||||
Path file = createFile(tmpdir.resolve("foo"));
|
||||
@Test
|
||||
void skip() throws IOException {
|
||||
Path file = Files.createFile(TMPDIR.resolve("foo"));
|
||||
try (OutputStream out = Files.newOutputStream(file)) {
|
||||
final int size = 512;
|
||||
byte[] blah = new byte[size];
|
||||
@ -123,8 +209,87 @@ public class InputStreamTest {
|
||||
}
|
||||
}
|
||||
|
||||
static void assertTrue(boolean okay) {
|
||||
if (!okay)
|
||||
throw new RuntimeException("Assertion Failed");
|
||||
/**
|
||||
* Tests that Files.newInputStream(Path).available() does not throw
|
||||
*/
|
||||
@Test
|
||||
@DisabledOnOs(OS.WINDOWS)
|
||||
void availableStdin() throws IOException {
|
||||
Path stdin = Path.of("/dev", "stdin");
|
||||
if (Files.exists(stdin)) {
|
||||
try (InputStream s = Files.newInputStream(stdin);) {
|
||||
s.available();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests that Files.newInputStream(Path).skip(0) does not throw
|
||||
*/
|
||||
@Test
|
||||
@DisabledOnOs(OS.WINDOWS)
|
||||
void skipStdin() throws IOException {
|
||||
Path stdin = Path.of("/dev", "stdin");
|
||||
if (Files.exists(stdin)) {
|
||||
try (InputStream s = Files.newInputStream(stdin);) {
|
||||
s.skip(0);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests Files.newInputStream(Path).readAllBytes().
|
||||
*/
|
||||
@Test
|
||||
@DisabledOnOs(OS.WINDOWS)
|
||||
void readAllBytes() throws InterruptedException, IOException {
|
||||
Thread t = createWriteThread();
|
||||
try (InputStream in = Files.newInputStream(Path.of(PIPE))) {
|
||||
String s = new String(in.readAllBytes());
|
||||
System.out.println(s);
|
||||
assertEquals(SENTENCE, s);
|
||||
} finally {
|
||||
t.join();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests Files.newInputStream(Path).readNBytes(byte[],int,int).
|
||||
*/
|
||||
@Test
|
||||
@DisabledOnOs(OS.WINDOWS)
|
||||
void readNBytesNoOverride() throws InterruptedException, IOException {
|
||||
Thread t = createWriteThread();
|
||||
try (InputStream in = Files.newInputStream(Path.of(PIPE))) {
|
||||
final int offset = 11;
|
||||
final int length = 17;
|
||||
assert length <= SENTENCE.length();
|
||||
byte[] b = new byte[offset + length];
|
||||
int n = in.readNBytes(b, offset, length);
|
||||
String s = new String(b, offset, length);
|
||||
System.out.println(s);
|
||||
assertEquals(SENTENCE.substring(0, length), s);
|
||||
} finally {
|
||||
t.join();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests Files.newInputStream(Path).readNBytes(int).
|
||||
*/
|
||||
@Test
|
||||
@DisabledOnOs(OS.WINDOWS)
|
||||
void readNBytesOverride() throws InterruptedException, IOException {
|
||||
Thread t = createWriteThread();
|
||||
try (InputStream in = Files.newInputStream(Path.of(PIPE))) {
|
||||
final int length = 17;
|
||||
assert length <= SENTENCE.length();
|
||||
byte[] b = in.readNBytes(length);
|
||||
String s = new String(b);
|
||||
System.out.println(s);
|
||||
assertEquals(SENTENCE.substring(0, length), s);
|
||||
} finally {
|
||||
t.join();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user