/*
* Copyright 2013-2015 the original author or authors.
*
* Licensed 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.springframework.integration.file.filters;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertTrue;
import java.io.Closeable;
import java.io.File;
import java.io.Flushable;
import java.io.IOException;
import java.util.Arrays;
import java.util.List;
import java.util.concurrent.Callable;
import java.util.concurrent.CountDownLatch;
import java.util.concurrent.Executors;
import java.util.concurrent.Future;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.atomic.AtomicBoolean;
import java.util.concurrent.atomic.AtomicInteger;
import org.junit.Test;
import org.springframework.integration.metadata.ConcurrentMetadataStore;
import org.springframework.integration.metadata.SimpleMetadataStore;
/**
* @author Gary Russell
* @since 3.0
*
*/
public class PersistentAcceptOnceFileListFilterTests extends AcceptOnceFileListFilterTests {
@Test
public void testFileSystem() throws Exception {
final AtomicBoolean suspend = new AtomicBoolean();
final CountDownLatch latch1 = new CountDownLatch(1);
final CountDownLatch latch2 = new CountDownLatch(1);
ConcurrentMetadataStore store = new SimpleMetadataStore() {
@Override
public boolean replace(String key, String oldValue, String newValue) {
if (suspend.get()) {
latch2.countDown();
try {
latch1.await(10, TimeUnit.SECONDS);
}
catch (InterruptedException e) {
Thread.currentThread().interrupt();
}
}
return super.replace(key, oldValue, newValue);
}
};
final FileSystemPersistentAcceptOnceFileListFilter filter =
new FileSystemPersistentAcceptOnceFileListFilter(store, "foo:");
final File file = File.createTempFile("foo", ".txt");
assertEquals(1, filter.filterFiles(new File[] {file}).size());
String ts = store.get("foo:" + file.getAbsolutePath());
assertEquals(String.valueOf(file.lastModified()), ts);
assertEquals(0, filter.filterFiles(new File[] {file}).size());
file.setLastModified(file.lastModified() + 5000L);
assertEquals(1, filter.filterFiles(new File[] {file}).size());
ts = store.get("foo:" + file.getAbsolutePath());
assertEquals(String.valueOf(file.lastModified()), ts);
assertEquals(0, filter.filterFiles(new File[] {file}).size());
suspend.set(true);
file.setLastModified(file.lastModified() + 5000L);
Future<Integer> result = Executors.newSingleThreadExecutor().submit(new Callable<Integer>() {
@Override
public Integer call() throws Exception {
return filter.filterFiles(new File[] {file}).size();
}
});
assertTrue(latch2.await(10, TimeUnit.SECONDS));
store.put("foo:" + file.getAbsolutePath(), "43");
latch1.countDown();
Integer theResult = result.get(10, TimeUnit.SECONDS);
assertEquals(Integer.valueOf(0), theResult); // lost the race, key changed
file.delete();
filter.close();
}
@Override
@Test
public void testRollback() {
AbstractPersistentAcceptOnceFileListFilter<String> filter = new AbstractPersistentAcceptOnceFileListFilter<String>(
new SimpleMetadataStore(), "rollback:") {
@Override
protected long modified(String file) {
return 0;
}
@Override
protected String fileName(String file) {
return file;
}
};
doTestRollback(filter);
}
@Test
public void testRollbackFileSystem() throws Exception {
FileSystemPersistentAcceptOnceFileListFilter filter = new FileSystemPersistentAcceptOnceFileListFilter(
new SimpleMetadataStore(), "rollback:");
File[] files = new File[] {new File("foo"), new File("bar"), new File("baz")};
List<File> passed = filter.filterFiles(files);
assertTrue(Arrays.equals(files, passed.toArray()));
List<File> now = filter.filterFiles(files);
assertEquals(0, now.size());
filter.rollback(passed.get(1), passed);
now = filter.filterFiles(files);
assertEquals(2, now.size());
assertEquals("bar", now.get(0).getName());
assertEquals("baz", now.get(1).getName());
now = filter.filterFiles(files);
assertEquals(0, now.size());
filter.close();
}
@Test
/*
* INT-3721: Test all operations that can cause the metadata to be flushed.
*/
public void testFlush() throws Exception {
final AtomicInteger flushes = new AtomicInteger();
final AtomicBoolean replaced = new AtomicBoolean();
class MS extends SimpleMetadataStore implements Flushable, Closeable {
@Override
public void flush() throws IOException {
flushes.incrementAndGet();
}
@Override
public void close() throws IOException {
flush();
}
@Override
public boolean replace(String key, String oldValue, String newValue) {
replaced.set(true);
return super.replace(key, oldValue, newValue);
}
}
MS store = new MS();
String prefix = "flush:";
FileSystemPersistentAcceptOnceFileListFilter filter = new FileSystemPersistentAcceptOnceFileListFilter(
store, prefix);
final File file = File.createTempFile("foo", ".txt");
File[] files = new File[] { file };
List<File> passed = filter.filterFiles(files);
assertTrue(Arrays.equals(files, passed.toArray()));
filter.rollback(passed.get(0), passed);
assertEquals(0, flushes.get());
filter.setFlushOnUpdate(true);
passed = filter.filterFiles(files);
assertTrue(Arrays.equals(files, passed.toArray()));
assertEquals(1, flushes.get());
filter.rollback(passed.get(0), passed);
assertEquals(2, flushes.get());
passed = filter.filterFiles(files);
assertTrue(Arrays.equals(files, passed.toArray()));
assertEquals(3, flushes.get());
passed = filter.filterFiles(files);
assertEquals(0, passed.size());
assertEquals(3, flushes.get());
assertFalse(replaced.get());
store.put(prefix + file.getAbsolutePath(), "1");
passed = filter.filterFiles(files);
assertTrue(Arrays.equals(files, passed.toArray()));
assertEquals(4, flushes.get());
assertTrue(replaced.get());
file.delete();
filter.close();
assertEquals(5, flushes.get());
}
}