blob: d22e64d21cea2cdec4448cdef77356b08a08f58c [file] [log] [blame]
/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.apache.beam.sdk.io;
import static org.hamcrest.Matchers.containsInAnyOrder;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertThat;
import static org.junit.Assert.assertTrue;
import java.io.Writer;
import java.nio.channels.Channels;
import java.nio.charset.StandardCharsets;
import java.nio.file.NoSuchFileException;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.util.List;
import org.apache.beam.sdk.io.fs.CreateOptions;
import org.apache.beam.sdk.io.fs.MoveOptions;
import org.apache.beam.sdk.io.fs.ResourceId;
import org.apache.beam.sdk.options.PipelineOptionsFactory;
import org.apache.beam.sdk.util.MimeTypes;
import org.apache.beam.vendor.guava.v26_0_jre.com.google.common.collect.FluentIterable;
import org.apache.beam.vendor.guava.v26_0_jre.com.google.common.collect.ImmutableList;
import org.apache.beam.vendor.guava.v26_0_jre.com.google.common.collect.Sets;
import org.apache.beam.vendor.guava.v26_0_jre.com.google.common.io.Files;
import org.apache.commons.lang3.SystemUtils;
import org.junit.Rule;
import org.junit.Test;
import org.junit.rules.ExpectedException;
import org.junit.rules.TemporaryFolder;
import org.junit.runner.RunWith;
import org.junit.runners.JUnit4;
/** Tests for {@link FileSystems}. */
@RunWith(JUnit4.class)
public class FileSystemsTest {
@Rule public TemporaryFolder temporaryFolder = new TemporaryFolder();
@Rule public ExpectedException thrown = ExpectedException.none();
private LocalFileSystem localFileSystem = new LocalFileSystem();
@Test
public void testGetLocalFileSystem() throws Exception {
assertTrue(
FileSystems.getFileSystemInternal(toLocalResourceId("~/home/").getScheme())
instanceof LocalFileSystem);
assertTrue(
FileSystems.getFileSystemInternal(toLocalResourceId("file://home").getScheme())
instanceof LocalFileSystem);
assertTrue(
FileSystems.getFileSystemInternal(toLocalResourceId("FILE://home").getScheme())
instanceof LocalFileSystem);
assertTrue(
FileSystems.getFileSystemInternal(toLocalResourceId("File://home").getScheme())
instanceof LocalFileSystem);
if (SystemUtils.IS_OS_WINDOWS) {
assertTrue(
FileSystems.getFileSystemInternal(toLocalResourceId("c:\\home\\").getScheme())
instanceof LocalFileSystem);
}
}
@Test
public void testVerifySchemesAreUnique() throws Exception {
thrown.expect(RuntimeException.class);
thrown.expectMessage("Scheme: [file] has conflicting filesystems");
FileSystems.verifySchemesAreUnique(
PipelineOptionsFactory.create(),
Sets.newHashSet(new LocalFileSystemRegistrar(), new LocalFileSystemRegistrar()));
}
@Test
public void testDeleteIgnoreMissingFiles() throws Exception {
Path existingPath = temporaryFolder.newFile().toPath();
Path nonExistentPath = existingPath.resolveSibling("non-existent");
createFileWithContent(existingPath, "content1");
FileSystems.delete(
toResourceIds(ImmutableList.of(existingPath, nonExistentPath), false /* isDirectory */));
}
@Test
public void testCopyThrowsNoSuchFileException() throws Exception {
Path existingPath = temporaryFolder.newFile().toPath();
Path nonExistentPath = existingPath.resolveSibling("non-existent");
Path destPath1 = existingPath.resolveSibling("dest1");
Path destPath2 = nonExistentPath.resolveSibling("dest2");
createFileWithContent(existingPath, "content1");
thrown.expect(NoSuchFileException.class);
FileSystems.copy(
toResourceIds(ImmutableList.of(existingPath, nonExistentPath), false /* isDirectory */),
toResourceIds(ImmutableList.of(destPath1, destPath2), false /* isDirectory */));
}
@Test
public void testCopyIgnoreMissingFiles() throws Exception {
Path srcPath1 = temporaryFolder.newFile().toPath();
Path nonExistentPath = srcPath1.resolveSibling("non-existent");
Path srcPath3 = temporaryFolder.newFile().toPath();
Path destPath1 = srcPath1.resolveSibling("dest1");
Path destPath2 = nonExistentPath.resolveSibling("dest2");
Path destPath3 = srcPath1.resolveSibling("dest3");
createFileWithContent(srcPath1, "content1");
createFileWithContent(srcPath3, "content3");
FileSystems.copy(
toResourceIds(
ImmutableList.of(srcPath1, nonExistentPath, srcPath3), false /* isDirectory */),
toResourceIds(ImmutableList.of(destPath1, destPath2, destPath3), false /* isDirectory */),
MoveOptions.StandardMoveOptions.IGNORE_MISSING_FILES);
assertTrue(srcPath1.toFile().exists());
assertTrue(srcPath3.toFile().exists());
assertThat(
Files.readLines(srcPath1.toFile(), StandardCharsets.UTF_8), containsInAnyOrder("content1"));
assertFalse(destPath2.toFile().exists());
assertThat(
Files.readLines(srcPath3.toFile(), StandardCharsets.UTF_8), containsInAnyOrder("content3"));
}
@Test
public void testRenameThrowsNoSuchFileException() throws Exception {
Path existingPath = temporaryFolder.newFile().toPath();
Path nonExistentPath = existingPath.resolveSibling("non-existent");
Path destPath1 = existingPath.resolveSibling("dest1");
Path destPath2 = nonExistentPath.resolveSibling("dest2");
createFileWithContent(existingPath, "content1");
thrown.expect(NoSuchFileException.class);
FileSystems.rename(
toResourceIds(ImmutableList.of(existingPath, nonExistentPath), false /* isDirectory */),
toResourceIds(ImmutableList.of(destPath1, destPath2), false /* isDirectory */));
}
@Test
public void testRenameIgnoreMissingFiles() throws Exception {
Path srcPath1 = temporaryFolder.newFile().toPath();
Path nonExistentPath = srcPath1.resolveSibling("non-existent");
Path srcPath3 = temporaryFolder.newFile().toPath();
Path destPath1 = srcPath1.resolveSibling("dest1");
Path destPath2 = nonExistentPath.resolveSibling("dest2");
Path destPath3 = srcPath1.resolveSibling("dest3");
createFileWithContent(srcPath1, "content1");
createFileWithContent(srcPath3, "content3");
FileSystems.rename(
toResourceIds(
ImmutableList.of(srcPath1, nonExistentPath, srcPath3), false /* isDirectory */),
toResourceIds(ImmutableList.of(destPath1, destPath2, destPath3), false /* isDirectory */),
MoveOptions.StandardMoveOptions.IGNORE_MISSING_FILES);
assertFalse(srcPath1.toFile().exists());
assertFalse(srcPath3.toFile().exists());
assertThat(
Files.readLines(destPath1.toFile(), StandardCharsets.UTF_8),
containsInAnyOrder("content1"));
assertFalse(destPath2.toFile().exists());
assertThat(
Files.readLines(destPath3.toFile(), StandardCharsets.UTF_8),
containsInAnyOrder("content3"));
}
@Test
public void testValidMatchNewResourceForLocalFileSystem() {
assertEquals("file", FileSystems.matchNewResource("/tmp/f1", false).getScheme());
assertEquals("file", FileSystems.matchNewResource("tmp/f1", false).getScheme());
assertEquals("file", FileSystems.matchNewResource("c:\\tmp\\f1", false).getScheme());
}
@Test(expected = IllegalArgumentException.class)
public void testInvalidSchemaMatchNewResource() {
assertEquals("file", FileSystems.matchNewResource("invalidschema://tmp/f1", false));
assertEquals("file", FileSystems.matchNewResource("c:/tmp/f1", false));
}
private List<ResourceId> toResourceIds(List<Path> paths, final boolean isDirectory) {
return FluentIterable.from(paths)
.transform(path -> (ResourceId) LocalResourceId.fromPath(path, isDirectory))
.toList();
}
private void createFileWithContent(Path path, String content) throws Exception {
try (Writer writer =
Channels.newWriter(
localFileSystem.create(
LocalResourceId.fromPath(path, false /* isDirectory */),
CreateOptions.StandardCreateOptions.builder().setMimeType(MimeTypes.TEXT).build()),
StandardCharsets.UTF_8.name())) {
writer.write(content);
}
}
private LocalResourceId toLocalResourceId(String str) throws Exception {
boolean isDirectory;
if (SystemUtils.IS_OS_WINDOWS) {
isDirectory = str.endsWith("\\");
} else {
isDirectory = str.endsWith("/");
}
return LocalResourceId.fromPath(Paths.get(str), isDirectory);
}
}