package com.faforever.client.patch;
import com.faforever.client.game.GameType;
import com.faforever.client.i18n.I18n;
import com.faforever.client.notification.NotificationService;
import com.faforever.client.notification.PersistentNotification;
import com.faforever.client.notification.Severity;
import com.faforever.client.preferences.ForgedAlliancePrefs;
import com.faforever.client.preferences.Preferences;
import com.faforever.client.preferences.PreferencesService;
import com.faforever.client.task.TaskService;
import com.faforever.client.test.AbstractPlainJavaFxTest;
import org.junit.Before;
import org.junit.Rule;
import org.junit.Test;
import org.junit.rules.TemporaryFolder;
import org.mockito.ArgumentCaptor;
import org.mockito.Mock;
import org.springframework.context.ApplicationContext;
import org.springframework.core.env.Environment;
import java.nio.file.Files;
import java.nio.file.Path;
import java.util.concurrent.CompletableFuture;
import java.util.concurrent.TimeUnit;
import static com.faforever.client.patch.GitRepositoryGameUpdateService.STEAM_API_DLL;
import static org.hamcrest.CoreMatchers.is;
import static org.hamcrest.CoreMatchers.nullValue;
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.mock;
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.verifyZeroInteractions;
import static org.mockito.Mockito.when;
import static org.mockito.Mockito.withSettings;
public class GitRepositoryGameUpdateServiceTest extends AbstractPlainJavaFxTest {
private static final long TIMEOUT = 5000;
private static final TimeUnit TIMEOUT_UNIT = TimeUnit.MILLISECONDS;
@Rule
public final TemporaryFolder reposDirectory = new TemporaryFolder();
@Rule
public TemporaryFolder faDirectory = new TemporaryFolder();
@Mock
private ForgedAlliancePrefs forgedAlliancePrefs;
@Mock
private ApplicationContext applicationContext;
@Mock
private Environment environment;
@Mock
private PreferencesService preferencesService;
@Mock
private TaskService taskService;
@Mock
private I18n i18n;
@Mock
private GitWrapper gitWrapper;
@Mock
private NotificationService notificationService;
@Mock
private Preferences preferences;
private Path faBinDirectory;
private GitRepositoryGameUpdateService instance;
@Before
public void setUp() throws Exception {
instance = new GitRepositoryGameUpdateService();
instance.preferencesService = preferencesService;
instance.taskService = taskService;
instance.i18n = i18n;
instance.gitWrapper = gitWrapper;
instance.notificationService = notificationService;
instance.applicationContext = applicationContext;
GitCheckGameUpdateTask gameUpdateTask = mock(GitCheckGameUpdateTask.class, withSettings().useConstructor());
when(preferencesService.getPreferences()).thenReturn(preferences);
when(preferencesService.getFafReposDirectory()).thenReturn(reposDirectory.getRoot().toPath());
when(preferences.getForgedAlliance()).thenReturn(forgedAlliancePrefs);
when(forgedAlliancePrefs.getPath()).thenReturn(faDirectory.getRoot().toPath());
when(applicationContext.getBean(GitCheckGameUpdateTask.class)).thenReturn(gameUpdateTask);
doAnswer(invocation -> invocation.getArgumentAt(0, Object.class)).when(taskService).submitTask(any());
faBinDirectory = faDirectory.getRoot().toPath().resolve("bin");
Files.createDirectories(faBinDirectory);
instance.postConstruct();
}
@Test
public void testUpdateInBackgroundFaDirectoryUnspecified() throws Exception {
when(forgedAlliancePrefs.getPath()).thenReturn(null);
instance.updateInBackground(GameType.FAF.getString(), null, null, null);
verifyZeroInteractions(instance.taskService);
}
@Test
public void testUpdateInBackgroundThrowsException() throws Exception {
GitGameUpdateTask task = mock(GitGameUpdateTask.class, withSettings().useConstructor());
when(applicationContext.getBean(GitGameUpdateTask.class)).thenReturn(task);
CompletableFuture<Void> future = new CompletableFuture<>();
future.completeExceptionally(new Exception("This exception mimicks that something went wrong"));
when(task.getFuture()).thenReturn(future);
instance.updateInBackground(GameType.FAF.getString(), null, null, null).toCompletableFuture().get(TIMEOUT, TIMEOUT_UNIT);
ArgumentCaptor<PersistentNotification> captor = ArgumentCaptor.forClass(PersistentNotification.class);
verify(notificationService).addNotification(captor.capture());
assertThat(captor.getValue().getSeverity(), is(Severity.WARN));
}
@Test
@SuppressWarnings("unchecked")
public void testCheckForUpdatesInBackgroundPatchingIsNeeded() throws Exception {
GitCheckGameUpdateTask task = mock(GitCheckGameUpdateTask.class);
when(task.getFuture()).thenReturn(CompletableFuture.completedFuture(null));
when(applicationContext.getBean(GitCheckGameUpdateTask.class)).thenReturn(task);
CompletableFuture<Void> future = instance.checkForUpdateInBackground().toCompletableFuture();
assertThat(future.get(TIMEOUT, TIMEOUT_UNIT), is(nullValue()));
assertThat(future.isCompletedExceptionally(), is(false));
}
@Test
public void testCheckForUpdatesInBackgroundThrowsException() throws Exception {
GitCheckGameUpdateTask task = mock(GitCheckGameUpdateTask.class, withSettings().useConstructor());
when(applicationContext.getBean(GitCheckGameUpdateTask.class)).thenReturn(task);
CompletableFuture<Boolean> exceptionFuture = new CompletableFuture<>();
exceptionFuture.completeExceptionally(new Exception("This exception mimicks that something went wrong"));
when(task.getFuture()).thenReturn(exceptionFuture);
CompletableFuture<Void> future = instance.checkForUpdateInBackground().toCompletableFuture();
future.get(TIMEOUT, TIMEOUT_UNIT);
ArgumentCaptor<PersistentNotification> captor = ArgumentCaptor.forClass(PersistentNotification.class);
verify(notificationService).addNotification(captor.capture());
assertThat(captor.getValue().getSeverity(), is(Severity.WARN));
}
@Test
public void testGuessInstallTypeRetail() throws Exception {
assertTrue(Files.notExists(faBinDirectory.resolve(STEAM_API_DLL)));
GitRepositoryGameUpdateService.InstallType installType = instance.guessInstallType();
assertThat(installType, is(GitRepositoryGameUpdateService.InstallType.RETAIL));
}
@Test
public void testGuessInstallTypeSteam() throws Exception {
Files.createDirectories(faBinDirectory);
Files.createFile(faBinDirectory.resolve(STEAM_API_DLL));
GitRepositoryGameUpdateService.InstallType installType = instance.guessInstallType();
assertThat(installType, is(GitRepositoryGameUpdateService.InstallType.STEAM));
}
}