blob: 5327d5742247a98e56168e3a35907f23e78677d6 [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.lucene.mockfile;
import java.io.IOException;
import java.net.URI;
import java.nio.file.DirectoryStream;
import java.nio.file.FileSystem;
import java.nio.file.Files;
import java.nio.file.Path;
import java.util.ArrayList;
import java.util.HashSet;
import java.util.List;
/** Basic tests for ShuffleFS */
public class TestShuffleFS extends MockFileSystemTestCase {
@Override
protected Path wrap(Path path) {
return wrap(path, random().nextLong());
}
Path wrap(Path path, long seed) {
FileSystem fs = new ShuffleFS(path.getFileSystem(), seed).getFileSystem(URI.create("file:///"));
return new FilterPath(path, fs);
}
/** test that we return directory listings correctly */
public void testShuffleWorks() throws IOException {
Path dir = wrap(createTempDir());
Files.createFile(dir.resolve("file1"));
Files.createFile(dir.resolve("file2"));
Files.createFile(dir.resolve("file3"));
List<Path> seen = new ArrayList<>();
try (DirectoryStream<Path> stream = Files.newDirectoryStream(dir)) {
for (Path path : stream) {
seen.add(path);
}
}
assertEquals(3, seen.size());
assertTrue(seen.contains(dir.resolve("file1")));
assertTrue(seen.contains(dir.resolve("file2")));
assertTrue(seen.contains(dir.resolve("file3")));
}
/** test that we change order of directory listings */
public void testActuallyShuffles() throws IOException {
Path dir = createTempDir();
for (int i = 0; i < 100; i++) {
Files.createFile(dir.resolve("file" + i));
}
List<String> expected = new ArrayList<>();
// get the raw listing from the actual filesystem
try (DirectoryStream<Path> stream = Files.newDirectoryStream(dir)) {
for (Path path : stream) {
expected.add(path.getFileName().toString());
}
}
// shuffle until the order changes.
for (int i = 0; i < 10000; i++) {
Path wrapped = wrap(dir, random().nextLong());
List<String> seen = new ArrayList<>();
try (DirectoryStream<Path> stream = Files.newDirectoryStream(wrapped)) {
for (Path path : stream) {
seen.add(path.getFileName().toString());
}
}
// we should always see the same files.
assertEquals(new HashSet<>(expected), new HashSet<>(seen));
if (!expected.equals(seen)) {
return;
}
}
fail("ordering never changed");
}
/**
* shuffle underlying contents randomly with different seeds,
* and ensure shuffling that again with the same seed is consistent.
*/
public void testConsistentOrder() throws IOException {
Path raw = createTempDir();
for (int i = 0; i < 100; i++) {
Files.createFile(raw.resolve("file" + i));
}
long seed = random().nextLong();
Path dirExpected = wrap(raw, seed);
// get the shuffled listing for the seed.
List<String> expected = new ArrayList<>();
try (DirectoryStream<Path> stream = Files.newDirectoryStream(dirExpected)) {
for (Path path : stream) {
expected.add(path.getFileName().toString());
}
}
// shuffle wrapping a different scrambled ordering each time, it should always be the same.
for (int i = 0; i < 100; i++) {
Path scrambled = wrap(raw, random().nextLong());
Path ordered = wrap(scrambled, seed);
List<String> seen = new ArrayList<>();
try (DirectoryStream<Path> stream = Files.newDirectoryStream(ordered)) {
for (Path path : stream) {
seen.add(path.getFileName().toString());
}
}
// we should always see the same files in the same order
assertEquals(expected, seen);
}
}
/**
* test that we give a consistent order
* for the same file names within different directories
*/
public void testFileNameOnly() throws IOException {
Path dir = wrap(createTempDir());
Files.createFile(dir.resolve("file1"));
Files.createFile(dir.resolve("file2"));
Files.createFile(dir.resolve("file3"));
List<String> expected = new ArrayList<>();
try (DirectoryStream<Path> stream = Files.newDirectoryStream(dir)) {
for (Path path : stream) {
expected.add(path.getFileName().toString());
}
}
Path subdir = dir.resolve("subdir");
Files.createDirectory(subdir);
Files.createFile(subdir.resolve("file3"));
Files.createFile(subdir.resolve("file2"));
Files.createFile(subdir.resolve("file1"));
List<String> actual = new ArrayList<>();
try (DirectoryStream<Path> stream = Files.newDirectoryStream(subdir)) {
for (Path path : stream) {
actual.add(path.getFileName().toString());
}
}
assertEquals(expected, actual);
}
}