content: package org.araymond.joal.core.config;
  
  import com.fasterxml.jackson.databind.ObjectMapper;
  import org.apache.commons.lang3.RandomStringUtils;
  import org.araymond.joal.core.SeedManager;
  import org.araymond.joal.core.events.config.ConfigHasBeenLoadedEvent;
  import org.junit.jupiter.api.Test;
  import org.mockito.ArgumentCaptor;
  import org.mockito.Mockito;
  import org.springframework.context.ApplicationEventPublisher;
  
  import javax.inject.Provider;
  import java.io.File;
  import java.io.FileNotFoundException;
  import java.io.IOException;
  import java.nio.file.Files;
  import java.nio.file.Paths;
  import java.util.Random;
  
  import static org.assertj.core.api.Assertions.assertThat;
  import static org.assertj.core.api.Assertions.assertThatThrownBy;
  
  /**
   * Created by raymo on 18/04/2017.
   */
  public class JoalConfigProviderTest {
  
      private static final SeedManager.JoalFoldersPath joalFoldersPath = new SeedManager.JoalFoldersPath(Paths.get("src/test/resources/configtest"));
      private static final SeedManager.JoalFoldersPath rewritableJoalFoldersPath = new SeedManager.JoalFoldersPath(Paths.get("src/test/resources/rewritable-config"));
      public static final AppConfiguration defaultConfig = new AppConfiguration(
              180L,
              190L,
              5,
              "azureus-5.7.5.0.client",
              false,
              1f
      );
  
      @Test
      public void shouldFailIfJsonFileIsNotPresent() {
          final SeedManager.JoalFoldersPath fakeFolders = new SeedManager.JoalFoldersPath(Paths.get("nop"));
          assertThatThrownBy(() -> new JoalConfigProvider(new ObjectMapper(), fakeFolders, Mockito.mock(ApplicationEventPublisher.class)))
                  .isInstanceOf(FileNotFoundException.class)
                  .hasMessageContaining("App configuration file [" + fakeFolders.getConfDirRootPath() + File.separator + "config.json] not found");
      }
  
      @Test
      public void shouldFailToGetConfIfNotInitialized() throws FileNotFoundException {
          final Provider<AppConfiguration> provider = new JoalConfigProvider(new ObjectMapper(), joalFoldersPath, Mockito.mock(ApplicationEventPublisher.class));
  
          assertThatThrownBy(provider::get)
                  .isInstanceOf(IllegalStateException.class)
                  .hasMessage("Attempted to get configuration before init");
      }
  
      @Test
      public void shouldLoadCong() throws FileNotFoundException {
          final JoalConfigProvider provider = new JoalConfigProvider(new ObjectMapper(), joalFoldersPath, Mockito.mock(ApplicationEventPublisher.class));
  
          assertThat(provider.loadConfiguration()).usingRecursiveComparison().isEqualTo(defaultConfig);
      }
  
      @Test
      public void shouldGetConf() throws FileNotFoundException {
          final JoalConfigProvider provider = new JoalConfigProvider(new ObjectMapper(), joalFoldersPath, Mockito.mock(ApplicationEventPublisher.class));
          AppConfiguration conf = provider.init();
          AppConfiguration confGet = provider.get();
  
          assertThat(confGet).isEqualTo(defaultConfig);
          assertThat(confGet).isEqualTo(conf);
      }
  
      @Test
      public void shouldAlwaysReturnSameConf() throws FileNotFoundException {
          final JoalConfigProvider provider = new JoalConfigProvider(new ObjectMapper(), joalFoldersPath, Mockito.mock(ApplicationEventPublisher.class));
          AppConfiguration confInit = provider.init();
  
          assertThat(provider.get()).usingComparator((o1, o2) -> {
              if (o1 == o2) return 0;
              return -1;
          })
                  .isEqualTo(provider.get())
                  .isEqualTo(provider.get())
                  .isEqualTo(confInit);
      }
  
      @Test
      public void shouldPublishConfigHasBeenLoadedEventOnConfigLoad() throws FileNotFoundException {
          final ApplicationEventPublisher publisher = Mockito.mock(ApplicationEventPublisher.class);
          final JoalConfigProvider provider = new JoalConfigProvider(new ObjectMapper(), joalFoldersPath, publisher);
  
          final AppConfiguration loadedConf = provider.loadConfiguration();
  
          final ArgumentCaptor<ConfigHasBeenLoadedEvent> captor = ArgumentCaptor.forClass(ConfigHasBeenLoadedEvent.class);
          Mockito.verify(publisher, Mockito.times(1)).publishEvent(captor.capture());
  
          final ConfigHasBeenLoadedEvent event = captor.getValue();
          assertThat(event.getConfiguration()).isEqualTo(loadedConf);
      }
  
      @Test
      public void shouldWriteConfigurationFile() throws IOException {
          new ObjectMapper().writeValue(rewritableJoalFoldersPath.getConfDirRootPath().resolve("config.json").toFile(), defaultConfig);
          try {
              final JoalConfigProvider provider = new JoalConfigProvider(new ObjectMapper(), rewritableJoalFoldersPath, Mockito.mock(ApplicationEventPublisher.class));
              final Random rand = new Random();
              final AppConfiguration newConf = new AppConfiguration(
                      rand.longs(1, 200).findFirst().getAsLong(),
                      rand.longs(201, 400).findFirst().getAsLong(),
                      rand.ints(1, 5).findFirst().getAsInt(),
                      RandomStringUtils.random(60),
                      false,
                      1f
              );
  
              provider.saveNewConf(newConf);
  
              assertThat(provider.loadConfiguration()).isEqualTo(newConf);
          } finally {
              Files.deleteIfExists(rewritableJoalFoldersPath.getConfDirRootPath().resolve("config.json"));
          }
      }
  
  }
  