package com.faforever.client.map;
import com.faforever.client.i18n.I18n;
import com.faforever.client.preferences.ForgedAlliancePrefs;
import com.faforever.client.preferences.Preferences;
import com.faforever.client.preferences.PreferencesService;
import com.faforever.client.task.CompletableTask;
import com.faforever.client.task.TaskService;
import com.faforever.client.test.AbstractPlainJavaFxTest;
import javafx.beans.property.ObjectProperty;
import javafx.collections.ObservableList;
import org.apache.lucene.analysis.core.SimpleAnalyzer;
import org.apache.lucene.store.RAMDirectory;
import org.junit.Before;
import org.junit.Rule;
import org.junit.Test;
import org.junit.rules.ExpectedException;
import org.junit.rules.TemporaryFolder;
import org.luaj.vm2.LuaError;
import org.mockito.Mock;
import org.testfx.util.WaitForAsyncUtils;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.util.concurrent.ThreadPoolExecutor;
import static java.nio.charset.StandardCharsets.UTF_8;
import static org.hamcrest.Matchers.equalTo;
import static org.hamcrest.Matchers.hasSize;
import static org.hamcrest.Matchers.instanceOf;
import static org.hamcrest.Matchers.isEmptyOrNullString;
import static org.hamcrest.Matchers.notNullValue;
import static org.hamcrest.Matchers.startsWith;
import static org.hamcrest.core.Is.is;
import static org.junit.Assert.assertThat;
import static org.junit.Assert.assertTrue;
import static org.mockito.Matchers.any;
import static org.mockito.Mockito.doAnswer;
import static org.mockito.Mockito.when;
public class MapServiceImplTest extends AbstractPlainJavaFxTest {
@Rule
public TemporaryFolder customMapsDirectory = new TemporaryFolder();
@Rule
public TemporaryFolder gameDirectory = new TemporaryFolder();
@Rule
public ExpectedException expectedException = ExpectedException.none();
private MapServiceImpl instance;
@Mock
private PreferencesService preferencesService;
@Mock
private Preferences preferences;
@Mock
private ForgedAlliancePrefs forgedAlliancePrefs;
@Mock
private ObjectProperty<Path> customMapsDirectoryProperty;
@Mock
private ThreadPoolExecutor threadPoolExecutor;
@Mock
private TaskService taskService;
@Mock
private I18n i18n;
private Path mapsDirectory;
@Before
public void setUp() throws Exception {
instance = new MapServiceImpl();
instance.preferencesService = preferencesService;
instance.threadPoolExecutor = threadPoolExecutor;
instance.taskService = taskService;
instance.directory = new RAMDirectory();
instance.analyzer = new SimpleAnalyzer();
instance.i18n = i18n;
mapsDirectory = gameDirectory.newFolder("maps").toPath();
when(preferencesService.getPreferences()).thenReturn(preferences);
when(preferences.getForgedAlliance()).thenReturn(forgedAlliancePrefs);
when(forgedAlliancePrefs.getCustomMapsDirectory()).thenReturn(customMapsDirectory.getRoot().toPath());
when(forgedAlliancePrefs.customMapsDirectoryProperty()).thenReturn(customMapsDirectoryProperty);
when(forgedAlliancePrefs.getPath()).thenReturn(gameDirectory.getRoot().toPath());
doAnswer(invocation -> {
@SuppressWarnings("unchecked")
CompletableTask<Void> task = invocation.getArgumentAt(0, CompletableTask.class);
WaitForAsyncUtils.asyncFx(task);
task.getFuture().get();
return task;
}).when(taskService).submitTask(any());
instance.postConstruct();
}
@Test
public void testGetLocalMapsNoMaps() throws Exception {
assertThat(instance.getInstalledMaps(), hasSize(0));
}
@Test
public void testGetLocalMapsOfficialMap() throws Exception {
Path scmp001 = Files.createDirectory(mapsDirectory.resolve("SCMP_001"));
Files.copy(getClass().getResourceAsStream("/maps/SCMP_001/SCMP_001_scenario.lua"), scmp001.resolve("SCMP_001_scenario.lua"));
instance.postConstruct();
ObservableList<MapBean> localMapBeans = instance.getInstalledMaps();
assertThat(localMapBeans, hasSize(1));
MapBean mapBean = localMapBeans.get(0);
assertThat(mapBean, notNullValue());
assertThat(mapBean.getFolderName(), is("SCMP_001"));
assertThat(mapBean.getDisplayName(), is("Burial Mounds"));
assertThat(mapBean.getSize(), equalTo(new MapSize(20, 20)));
}
@Test
public void testReadMapOfNonFolderThrowsException() throws Exception {
expectedException.expect(MapLoadException.class);
expectedException.expectMessage(startsWith("Not a folder"));
instance.readMap(mapsDirectory.resolve("something"));
}
@Test
public void testReadMapInvalidMap() throws Exception {
Path corruptMap = Files.createDirectory(mapsDirectory.resolve("corruptMap"));
Files.write(corruptMap.resolve("corruptMap_scenario.lua"), "{\"This is invalid\", \"}".getBytes(UTF_8));
expectedException.expect(MapLoadException.class);
expectedException.expectCause(instanceOf(LuaError.class));
instance.readMap(corruptMap);
}
@Test
public void testReadMap() throws Exception {
MapBean mapBean = instance.readMap(Paths.get(getClass().getResource("/maps/SCMP_001").toURI()));
assertThat(mapBean, notNullValue());
assertThat(mapBean.getId(), isEmptyOrNullString());
assertThat(mapBean.getDescription(), startsWith("Initial scans of the planet"));
assertThat(mapBean.getSize(), is(new MapSize(20, 20)));
assertThat(mapBean.getVersion(), is(1));
assertThat(mapBean.getFolderName(), is("SCMP_001"));
}
@Test
public void testInstalledOfficialMapIgnoreCase() throws Exception {
Path scmp001 = Files.createDirectory(mapsDirectory.resolve("SCMP_001"));
Files.copy(getClass().getResourceAsStream("/maps/SCMP_001/SCMP_001_scenario.lua"), scmp001.resolve("SCMP_001_scenario.lua"));
instance.postConstruct();
assertTrue(instance.isInstalled("ScMp_001"));
}
}