/*
* Copyright 2012-2017 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.boot.devtools.classpath;
import java.io.File;
import java.net.URL;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import org.junit.Rule;
import org.junit.Test;
import org.junit.rules.ExpectedException;
import org.junit.rules.TemporaryFolder;
import org.springframework.boot.devtools.filewatch.ChangedFile;
import org.springframework.boot.devtools.filewatch.FileSystemWatcher;
import org.springframework.boot.devtools.filewatch.FileSystemWatcherFactory;
import org.springframework.context.ApplicationListener;
import org.springframework.context.annotation.AnnotationConfigApplicationContext;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.core.env.Environment;
import org.springframework.core.env.MapPropertySource;
import org.springframework.util.FileCopyUtils;
import static org.assertj.core.api.Assertions.assertThat;
import static org.mockito.Mockito.mock;
/**
* Tests for {@link ClassPathFileSystemWatcher}.
*
* @author Phillip Webb
*/
public class ClassPathFileSystemWatcherTests {
@Rule
public ExpectedException thrown = ExpectedException.none();
@Rule
public TemporaryFolder temp = new TemporaryFolder();
@Test
public void urlsMustNotBeNull() throws Exception {
this.thrown.expect(IllegalArgumentException.class);
this.thrown.expectMessage("Urls must not be null");
URL[] urls = null;
new ClassPathFileSystemWatcher(mock(FileSystemWatcherFactory.class),
mock(ClassPathRestartStrategy.class), urls);
}
@Test
public void configuredWithRestartStrategy() throws Exception {
AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext();
Map<String, Object> properties = new HashMap<>();
File folder = this.temp.newFolder();
List<URL> urls = new ArrayList<>();
urls.add(new URL("http://spring.io"));
urls.add(folder.toURI().toURL());
properties.put("urls", urls);
MapPropertySource propertySource = new MapPropertySource("test", properties);
context.getEnvironment().getPropertySources().addLast(propertySource);
context.register(Config.class);
context.refresh();
Thread.sleep(200);
File classFile = new File(folder, "Example.class");
FileCopyUtils.copy("file".getBytes(), classFile);
Thread.sleep(1000);
List<ClassPathChangedEvent> events = context.getBean(Listener.class).getEvents();
for (int i = 0; i < 20; i++) {
if (!events.isEmpty()) {
break;
}
Thread.sleep(500);
}
assertThat(events.size()).isEqualTo(1);
assertThat(events.get(0).getChangeSet().iterator().next().getFiles().iterator()
.next().getFile()).isEqualTo(classFile);
context.close();
}
@Configuration
public static class Config {
public final Environment environment;
public Config(Environment environment) {
this.environment = environment;
}
@Bean
public ClassPathFileSystemWatcher watcher() {
FileSystemWatcher watcher = new FileSystemWatcher(false, 100, 10);
URL[] urls = this.environment.getProperty("urls", URL[].class);
return new ClassPathFileSystemWatcher(
new MockFileSystemWatcherFactory(watcher), restartStrategy(), urls);
}
@Bean
public ClassPathRestartStrategy restartStrategy() {
return new ClassPathRestartStrategy() {
@Override
public boolean isRestartRequired(ChangedFile file) {
return false;
}
};
}
@Bean
public Listener listener() {
return new Listener();
}
}
public static class Listener implements ApplicationListener<ClassPathChangedEvent> {
private List<ClassPathChangedEvent> events = new ArrayList<>();
@Override
public void onApplicationEvent(ClassPathChangedEvent event) {
this.events.add(event);
}
public List<ClassPathChangedEvent> getEvents() {
return this.events;
}
}
private static class MockFileSystemWatcherFactory
implements FileSystemWatcherFactory {
private final FileSystemWatcher watcher;
MockFileSystemWatcherFactory(FileSystemWatcher watcher) {
this.watcher = watcher;
}
@Override
public FileSystemWatcher getFileSystemWatcher() {
return this.watcher;
}
}
}