content: package org.araymond.joal.core.ttorrent.client;
  
  import com.turn.ttorrent.client.announce.AnnounceException;
  import com.turn.ttorrent.common.protocol.TrackerMessage.AnnounceRequestMessage.RequestEvent;
  import org.araymond.joal.core.bandwith.BandwidthDispatcher;
  import org.araymond.joal.core.config.AppConfiguration;
  import org.araymond.joal.core.config.AppConfigurationTest;
  import org.araymond.joal.core.exception.NoMoreTorrentsFileAvailableException;
  import org.araymond.joal.core.torrent.torrent.InfoHash;
  import org.araymond.joal.core.torrent.torrent.InfoHashTest;
  import org.araymond.joal.core.torrent.torrent.MockedTorrent;
  import org.araymond.joal.core.torrent.torrent.MockedTorrentTest;
  import org.araymond.joal.core.torrent.watcher.TorrentFileProvider;
  import org.araymond.joal.core.ttorrent.client.announcer.Announcer;
  import org.araymond.joal.core.ttorrent.client.announcer.AnnouncerFactory;
  import org.araymond.joal.core.ttorrent.client.announcer.exceptions.TooManyAnnouncesFailedInARowException;
  import org.araymond.joal.core.ttorrent.client.announcer.request.AnnounceRequest;
  import org.araymond.joal.core.ttorrent.client.announcer.request.AnnouncerExecutor;
  import org.junit.jupiter.api.Test;
  import org.mockito.ArgumentCaptor;
  import org.mockito.Mockito;
  import org.mockito.stubbing.Stubber;
  import org.springframework.context.ApplicationEventPublisher;
  
  import java.time.temporal.TemporalUnit;
  import java.util.ArrayList;
  import java.util.Collections;
  import java.util.List;
  
  import static org.assertj.core.api.Assertions.assertThat;
  import static org.assertj.core.api.Assertions.fail;
  import static org.mockito.ArgumentMatchers.any;
  import static org.mockito.ArgumentMatchers.anyInt;
  import static org.mockito.ArgumentMatchers.argThat;
  import static org.mockito.ArgumentMatchers.eq;
  import static org.mockito.Mockito.*;
  
  public class ClientTest {
  
      private AppConfiguration createMockedConf() {
          // wrap into spy to allow mocking
          return spy(AppConfigurationTest.createOne());
      }
  
      private AnnouncerFactory createMockedAnnouncerFactory() {
          final AnnouncerFactory announcerFactory = mock(AnnouncerFactory.class);
          doAnswer(invocation -> {
              final Announcer announcer = mock(Announcer.class);
              final InfoHash infoHash = ((MockedTorrent) invocation.getArguments()[0]).getTorrentInfoHash();
              doReturn(infoHash).when(announcer).getTorrentInfoHash();
              return announcer;
          }).when(announcerFactory).create(any(MockedTorrent.class));
  
          return announcerFactory;
      }
  
      private TorrentFileProvider createMockedTorrentFileProviderWithTorrent(final Iterable<MockedTorrent> mockedTorrents) {
          final TorrentFileProvider torrentFileProvider = mock(TorrentFileProvider.class);
          Stubber stubber = null;
          for (final MockedTorrent torrent : mockedTorrents) {
              if (stubber == null) {
                  stubber = doReturn(torrent);
              } else {
                  stubber = stubber.doReturn(torrent);
              }
          }
          try {
              if (stubber == null) {
                  Mockito.doThrow(new NoMoreTorrentsFileAvailableException("no more"))
                          .when(torrentFileProvider).getTorrentNotIn(anyCollection());
              } else {
                  stubber
                          .doThrow(new NoMoreTorrentsFileAvailableException("no more"))
                          .when(torrentFileProvider).getTorrentNotIn(anyCollection());
              }
          } catch (final NoMoreTorrentsFileAvailableException ignore) {
          }
  
          return torrentFileProvider;
      }
  
      @SuppressWarnings("unchecked")
      @Test
      public void shouldDeleteTorrentIfNoMorePeersOnlyIfConfigValueShouldKeepInactiveTorrentIsFalse() {
          final AppConfiguration appConfiguration = this.createMockedConf();
          doReturn(false).when(appConfiguration).isKeepTorrentWithZeroLeechers();
  
          final TorrentFileProvider torrentFileProvider = mock(TorrentFileProvider.class);
  
          final Client client = (Client) ClientBuilder.builder()
                  .withAnnouncerFactory(mock(AnnouncerFactory.class))
                  .withBandwidthDispatcher(mock(BandwidthDispatcher.class))
                  .withAppConfiguration(appConfiguration)
                  .withTorrentFileProvider(torrentFileProvider)
                  .withEventPublisher(mock(ApplicationEventPublisher.class))
                  .withDelayQueue(mock(DelayQueue.class))
                  .build();
  
          final InfoHash infoHash = InfoHashTest.createOne("abcd");
          client.onNoMorePeers(infoHash);
  
          verify(torrentFileProvider, times(1)).moveToArchiveFolder(eq(infoHash));
  
          final InfoHash infoHash2 = InfoHashTest.createOne("abcd");
          doReturn(true).when(appConfiguration).isKeepTorrentWithZeroLeechers();
          client.onNoMorePeers(infoHash);
  
          verify(torrentFileProvider, times(1)).moveToArchiveFolder(eq(infoHash2));
      }
  
      @SuppressWarnings({"unchecked", "TypeMayBeWeakened", "ResultOfMethodCallIgnored", "ConstantConditions"})
      @Test
      public void shouldStartAnnouncerWhenStart() {
          // given
          final AppConfiguration appConfiguration = this.createMockedConf();
          doReturn(5).when(appConfiguration).getSimultaneousSeed();
  
          final TorrentFileProvider torrentFileProvider = createMockedTorrentFileProviderWithTorrent(List.of(
                  MockedTorrentTest.createOneMock("abc"),
                  MockedTorrentTest.createOneMock("def"),
                  MockedTorrentTest.createOneMock("ghi"),
                  MockedTorrentTest.createOneMock("jkl"),
                  MockedTorrentTest.createOneMock("mno")
          ));
  
          final DelayQueue<AnnounceRequest> delayQueue = mock(DelayQueue.class);
          final AnnouncerFactory mockedAnnouncerFactory = createMockedAnnouncerFactory();
  
          final Client client = (Client) ClientBuilder.builder()
                  .withAnnouncerFactory(mockedAnnouncerFactory)
                  .withBandwidthDispatcher(mock(BandwidthDispatcher.class))
                  .withAppConfiguration(appConfiguration)
                  .withTorrentFileProvider(torrentFileProvider)
                  .withEventPublisher(mock(ApplicationEventPublisher.class))
                  .withDelayQueue(delayQueue)
                  .build();
  
          // when
          client.start();
  
          // then
          Mockito.verify(delayQueue, times(appConfiguration.getSimultaneousSeed()))
                  .addOrReplace(any(AnnounceRequest.class), anyInt(), any(TemporalUnit.class));
          assertThat(client.getCurrentlySeedingAnnouncers().stream()
                  .map(announcer -> announcer.getTorrentInfoHash().value())
                  .reduce((o, t) -> o + t).get()
          ).isEqualTo("abcdefghijklmno");
      }
  
      @SuppressWarnings({"unchecked", "ResultOfMethodCallIgnored"})
      @Test
      public void shouldNotFailToAddTorrentIfThereIsNoMoreTorrentFileAvailable() {
          final AppConfiguration appConfiguration = this.createMockedConf();
          doReturn(5).when(appConfiguration).getSimultaneousSeed();
  
          final TorrentFileProvider torrentFileProvider = createMockedTorrentFileProviderWithTorrent(Collections.emptyList());
  
          final AnnouncerFactory mockedAnnouncerFactory = createMockedAnnouncerFactory();
  
          final Client client = (Client) ClientBuilder.builder()
                  .withAnnouncerFactory(mockedAnnouncerFactory)
                  .withBandwidthDispatcher(mock(BandwidthDispatcher.class))
                  .withAppConfiguration(appConfiguration)
                  .withTorrentFileProvider(torrentFileProvider)
                  .withEventPublisher(mock(ApplicationEventPublisher.class))
                  .withDelayQueue(mock(DelayQueue.class))
                  .build();
  
          try {
              client.start();
          } catch (final Throwable t) {
              fail("should not fail if no torrents are available");
          }
      }
  
      @SuppressWarnings({"ResultOfMethodCallIgnored", "unchecked"})
      @Test
      public void shouldClearDelayQueueOnStopAndSendStopAnnounceToExecutor() throws AnnounceException, TooManyAnnouncesFailedInARowException {
          final AppConfiguration appConfiguration = this.createMockedConf();
          doReturn(1).when(appConfiguration).getSimultaneousSeed();
  
          final TorrentFileProvider torrentFileProvider = createMockedTorrentFileProviderWithTorrent(List.of(
                  MockedTorrentTest.createOneMock("abc")
          ));
  
          final DelayQueue<AnnounceRequest> delayQueue = mock(DelayQueue.class);
          doReturn(List.of(AnnounceRequest.createRegular(null))).when(delayQueue).drainAll();
          final AnnouncerFactory mockedAnnouncerFactory = mock(AnnouncerFactory.class);
  
          final Client client = (Client) ClientBuilder.builder()
                  .withAnnouncerFactory(mockedAnnouncerFactory)
                  .withBandwidthDispatcher(mock(BandwidthDispatcher.class))
                  .withAppConfiguration(appConfiguration)
                  .withTorrentFileProvider(torrentFileProvider)
                  .withEventPublisher(mock(ApplicationEventPublisher.class))
                  .withDelayQueue(delayQueue)
                  .build();
  
          final AnnouncerExecutor announcerExecutor = mock(AnnouncerExecutor.class);
          client.setAnnouncerExecutor(announcerExecutor);
  
          client.start();
          verify(delayQueue, times(1)).addOrReplace(any(AnnounceRequest.class), anyInt(), any(TemporalUnit.class));
          Thread.yield();
  
          client.stop();
          verify(delayQueue, times(1)).drainAll();
          verify(announcerExecutor, times(1)).execute(argThat(argument -> argument.getEvent() == RequestEvent.STOPPED));
      }
  
      @Test
      public void shouldNotExecuteAnnounceStopForAnnouncerInDelayQueueThatAreAwaitingStartedWhenClientStop() {
          final AppConfiguration appConfiguration = this.createMockedConf();
          doReturn(1).when(appConfiguration).getSimultaneousSeed();
  
          final TorrentFileProvider torrentFileProvider = createMockedTorrentFileProviderWithTorrent(List.of(
                  MockedTorrentTest.createOneMock("abc")
          ));
  
          final DelayQueue<AnnounceRequest> delayQueue = mock(DelayQueue.class);
          final AnnouncerFactory mockedAnnouncerFactory = mock(AnnouncerFactory.class);
  
          final Client client = (Client) ClientBuilder.builder()
                  .withAnnouncerFactory(mockedAnnouncerFactory)
                  .withBandwidthDispatcher(mock(BandwidthDispatcher.class))
                  .withAppConfiguration(appConfiguration)
                  .withTorrentFileProvider(torrentFileProvider)
                  .withEventPublisher(mock(ApplicationEventPublisher.class))
                  .withDelayQueue(delayQueue)
                  .build();
  
          final AnnouncerExecutor announcerExecutor = mock(AnnouncerExecutor.class);
          client.setAnnouncerExecutor(announcerExecutor);
  
          client.start();
          verify(delayQueue, times(1)).addOrReplace(any(AnnounceRequest.class), anyInt(), any(TemporalUnit.class));
          Thread.yield();
  
          client.stop();
          verify(delayQueue, times(1)).drainAll();
          verify(announcerExecutor, never()).execute(argThat(argument -> argument.getEvent() == RequestEvent.STOPPED));
      }
  
      @SuppressWarnings({"unchecked", "ResultOfMethodCallIgnored"})
      @Test
      public void shouldAwaitAnnounceExecutorOnStop() {
          final AppConfiguration appConfiguration = this.createMockedConf();
          doReturn(0).when(appConfiguration).getSimultaneousSeed();
  
          final TorrentFileProvider torrentFileProvider = createMockedTorrentFileProviderWithTorrent(List.of(
                  MockedTorrentTest.createOneMock("abc")
          ));
  
          final DelayQueue<AnnounceRequest> delayQueue = mock(DelayQueue.class);
          final AnnouncerFactory mockedAnnouncerFactory = mock(AnnouncerFactory.class);
  
          final Client client = (Client) ClientBuilder.builder()
                  .withAnnouncerFactory(mockedAnnouncerFactory)
                  .withBandwidthDispatcher(mock(BandwidthDispatcher.class))
                  .withAppConfiguration(appConfiguration)
                  .withTorrentFileProvider(torrentFileProvider)
                  .withEventPublisher(mock(ApplicationEventPublisher.class))
                  .withDelayQueue(delayQueue)
                  .build();
  
          final AnnouncerExecutor announcerExecutor = mock(AnnouncerExecutor.class);
          client.setAnnouncerExecutor(announcerExecutor);
  
          client.start();
  
          client.stop();
          verify(announcerExecutor, times(1)).awaitForRunningTasks();
      }
  
      @SuppressWarnings({"unchecked", "ResultOfMethodCallIgnored"})
      @Test
      public void shouldRemoveAnnouncerFromRunningListOnTooManyFailsAndEnqueueAnother() {
          final AppConfiguration appConfiguration = this.createMockedConf();
          doReturn(1).when(appConfiguration).getSimultaneousSeed();
  
          final TorrentFileProvider torrentFileProvider = createMockedTorrentFileProviderWithTorrent(List.of(
                  MockedTorrentTest.createOneMock("abc"),
                  MockedTorrentTest.createOneMock("def")
          ));
  
          final DelayQueue<AnnounceRequest> delayQueue = mock(DelayQueue.class);
          final AnnouncerFactory mockedAnnouncerFactory = createMockedAnnouncerFactory();
  
          final Client client = (Client) ClientBuilder.builder()
                  .withAnnouncerFactory(mockedAnnouncerFactory)
                  .withBandwidthDispatcher(mock(BandwidthDispatcher.class))
                  .withAppConfiguration(appConfiguration)
                  .withTorrentFileProvider(torrentFileProvider)
                  .withEventPublisher(mock(ApplicationEventPublisher.class))
                  .withDelayQueue(delayQueue)
                  .build();
  
          final AnnouncerExecutor announcerExecutor = mock(AnnouncerExecutor.class);
          client.setAnnouncerExecutor(announcerExecutor);
          final ArgumentCaptor<AnnounceRequest> argumentCaptor = ArgumentCaptor.forClass(AnnounceRequest.class);
  
          client.start();
          verify(delayQueue, times(1)).addOrReplace(argumentCaptor.capture(), anyInt(), any(TemporalUnit.class));
          assertThat(client.getCurrentlySeedingAnnouncers()).hasSize(1);
  
          final Announcer firstAnnouncer = argumentCaptor.getValue().getAnnouncer();
  
          client.onTooManyFailedInARow(firstAnnouncer);
          verify(torrentFileProvider, times(1)).moveToArchiveFolder(eq(firstAnnouncer.getTorrentInfoHash()));
          verify(delayQueue, times(2)).addOrReplace(argumentCaptor.capture(), anyInt(), any(TemporalUnit.class));
          assertThat(argumentCaptor.getValue().getInfoHash()).isNotEqualTo(firstAnnouncer.getTorrentInfoHash());
          assertThat(argumentCaptor.getValue().getInfoHash().value()).isEqualTo("def");
          assertThat(client.getCurrentlySeedingAnnouncers()).hasSize(1);
      }
  
      @SuppressWarnings({"unchecked", "ResultOfMethodCallIgnored"})
      @Test
      public void shouldTryToAddAnotherTorrentAfterAnAnnouncerHasStopped() {
          final AppConfiguration appConfiguration = this.createMockedConf();
          doReturn(1).when(appConfiguration).getSimultaneousSeed();
  
          final MockedTorrent torrent = MockedTorrentTest.createOneMock("abc");
          final MockedTorrent torrent2 = MockedTorrentTest.createOneMock("abc");
          final TorrentFileProvider torrentFileProvider = createMockedTorrentFileProviderWithTorrent(List.of(
                  torrent,
                  torrent2
          ));
  
          final DelayQueue<AnnounceRequest> delayQueue = mock(DelayQueue.class);
          final AnnouncerFactory mockedAnnouncerFactory = createMockedAnnouncerFactory();
  
          final Client client = (Client) ClientBuilder.builder()
                  .withAnnouncerFactory(mockedAnnouncerFactory)
                  .withBandwidthDispatcher(mock(BandwidthDispatcher.class))
                  .withAppConfiguration(appConfiguration)
                  .withTorrentFileProvider(torrentFileProvider)
                  .withEventPublisher(mock(ApplicationEventPublisher.class))
                  .withDelayQueue(delayQueue)
                  .build();
  
          final AnnouncerExecutor announcerExecutor = mock(AnnouncerExecutor.class);
          client.setAnnouncerExecutor(announcerExecutor);
  
          client.start();
          assertThat(client.getCurrentlySeedingAnnouncers()).hasSize(1);
          final ArgumentCaptor<AnnounceRequest> argumentCaptor = ArgumentCaptor.forClass(AnnounceRequest.class);
          verify(delayQueue, times(1)).addOrReplace(argumentCaptor.capture(), anyInt(), any(TemporalUnit.class));
  
          Mockito.reset(delayQueue);
          client.onTorrentHasStopped(argumentCaptor.getValue().getAnnouncer());
          verify(delayQueue, times(1)).addOrReplace(argumentCaptor.capture(), anyInt(), any(TemporalUnit.class));
  
          final AnnounceRequest announceRequest = argumentCaptor.getValue();
          assertThat(announceRequest.getInfoHash()).isEqualTo(torrent2.getTorrentInfoHash());
          assertThat(announceRequest.getEvent()).isEqualTo(RequestEvent.STARTED);
      }
  
      @SuppressWarnings({"unchecked", "ResultOfMethodCallIgnored"})
      @Test
      public void shouldAddTorrentWhenATorrentFileIsCreatedAnClientNotAlreadySeedingOnMaxSimultaneousSeed() {
          final AppConfiguration appConfiguration = this.createMockedConf();
          doReturn(2).when(appConfiguration).getSimultaneousSeed();
  
          final MockedTorrent torrent2 = MockedTorrentTest.createOneMock("def");
          final TorrentFileProvider torrentFileProvider = createMockedTorrentFileProviderWithTorrent(List.of(
                  MockedTorrentTest.createOneMock("abc")
          ));
  
          final DelayQueue<AnnounceRequest> delayQueue = mock(DelayQueue.class);
          final AnnouncerFactory mockedAnnouncerFactory = createMockedAnnouncerFactory();
  
          final Client client = (Client) ClientBuilder.builder()
                  .withAnnouncerFactory(mockedAnnouncerFactory)
                  .withBandwidthDispatcher(mock(BandwidthDispatcher.class))
                  .withAppConfiguration(appConfiguration)
                  .withTorrentFileProvider(torrentFileProvider)
                  .withEventPublisher(mock(ApplicationEventPublisher.class))
                  .withDelayQueue(delayQueue)
                  .build();
  
          final AnnouncerExecutor announcerExecutor = mock(AnnouncerExecutor.class);
          client.setAnnouncerExecutor(announcerExecutor);
  
          client.start();
          assertThat(client.getCurrentlySeedingAnnouncers()).hasSize(1);
  
  
          final ArgumentCaptor<AnnounceRequest> argumentCaptor = ArgumentCaptor.forClass(AnnounceRequest.class);
  
          Mockito.reset(delayQueue);
          client.onTorrentFileAdded(torrent2);
          verify(delayQueue, times(1)).addOrReplace(argumentCaptor.capture(), anyInt(), any(TemporalUnit.class));
  
          final AnnounceRequest announceRequest = argumentCaptor.getValue();
          assertThat(announceRequest.getInfoHash()).isEqualTo(torrent2.getTorrentInfoHash());
          assertThat(announceRequest.getEvent()).isEqualTo(RequestEvent.STARTED);
  
          assertThat(client.getCurrentlySeedingAnnouncers()).hasSize(2);
      }
  
      @SuppressWarnings({"unchecked", "ResultOfMethodCallIgnored"})
      @Test
      public void shouldNotAddTorrentWhenATorrentFileIsCreatedAnClientAlreadySeedingOnMaxSimultaneousSeed() {
          final AppConfiguration appConfiguration = this.createMockedConf();
          doReturn(1).when(appConfiguration).getSimultaneousSeed();
  
          final MockedTorrent torrent3 = MockedTorrentTest.createOneMock("ghi");
          final TorrentFileProvider torrentFileProvider = createMockedTorrentFileProviderWithTorrent(List.of(
                  MockedTorrentTest.createOneMock("abc"),
                  MockedTorrentTest.createOneMock("def")
          ));
  
          final DelayQueue<AnnounceRequest> delayQueue = mock(DelayQueue.class);
          final AnnouncerFactory mockedAnnouncerFactory = createMockedAnnouncerFactory();
  
          final Client client = (Client) ClientBuilder.builder()
                  .withAnnouncerFactory(mockedAnnouncerFactory)
                  .withBandwidthDispatcher(mock(BandwidthDispatcher.class))
                  .withAppConfiguration(appConfiguration)
                  .withTorrentFileProvider(torrentFileProvider)
                  .withEventPublisher(mock(ApplicationEventPublisher.class))
                  .withDelayQueue(delayQueue)
                  .build();
  
          final AnnouncerExecutor announcerExecutor = mock(AnnouncerExecutor.class);
          client.setAnnouncerExecutor(announcerExecutor);
  
          client.start();
          assertThat(client.getCurrentlySeedingAnnouncers()).hasSize(1);
  
          Mockito.reset(delayQueue);
          client.onTorrentFileAdded(torrent3);
          verify(delayQueue, never()).addOrReplace(any(AnnounceRequest.class), anyInt(), any(TemporalUnit.class));
  
          assertThat(client.getCurrentlySeedingAnnouncers()).hasSize(1);
      }
  
  
      @SuppressWarnings({"unchecked", "ResultOfMethodCallIgnored"})
      @Test
      public void shouldTryToStopAnnouncerWhenTorrentFileIsDeleted() {
          final AppConfiguration appConfiguration = this.createMockedConf();
          doReturn(1).when(appConfiguration).getSimultaneousSeed();
  
          final MockedTorrent torrent = MockedTorrentTest.createOneMock("abc");
          final TorrentFileProvider torrentFileProvider = createMockedTorrentFileProviderWithTorrent(List.of(
                  torrent
          ));
  
          final DelayQueue<AnnounceRequest> delayQueue = mock(DelayQueue.class);
          final AnnouncerFactory mockedAnnouncerFactory = createMockedAnnouncerFactory();
  
          final Client client = (Client) ClientBuilder.builder()
                  .withAnnouncerFactory(mockedAnnouncerFactory)
                  .withBandwidthDispatcher(mock(BandwidthDispatcher.class))
                  .withAppConfiguration(appConfiguration)
                  .withTorrentFileProvider(torrentFileProvider)
                  .withEventPublisher(mock(ApplicationEventPublisher.class))
                  .withDelayQueue(delayQueue)
                  .build();
  
          final AnnouncerExecutor announcerExecutor = mock(AnnouncerExecutor.class);
          client.setAnnouncerExecutor(announcerExecutor);
  
          client.start();
          assertThat(client.getCurrentlySeedingAnnouncers()).hasSize(1);
  
  
          final ArgumentCaptor<AnnounceRequest> argumentCaptor = ArgumentCaptor.forClass(AnnounceRequest.class);
  
          Mockito.reset(delayQueue);
          client.onTorrentFileRemoved(torrent);
          verify(delayQueue, times(1)).addOrReplace(argumentCaptor.capture(), anyInt(), any(TemporalUnit.class));
  
          final AnnounceRequest announceRequest = argumentCaptor.getValue();
          assertThat(announceRequest.getInfoHash()).isEqualTo(torrent.getTorrentInfoHash());
          assertThat(announceRequest.getEvent()).isEqualTo(RequestEvent.STOPPED);
      }
  
      @SuppressWarnings({"unchecked", "ResultOfMethodCallIgnored"})
      @Test
      public void shouldNotFailWhenATorrentFileIsRemovedButNoAnnouncerIsStartedForThisFile() {
          final AppConfiguration appConfiguration = this.createMockedConf();
          doReturn(1).when(appConfiguration).getSimultaneousSeed();
  
          final TorrentFileProvider torrentFileProvider = createMockedTorrentFileProviderWithTorrent(List.of(
                  MockedTorrentTest.createOneMock("abc")
          ));
  
          final DelayQueue<AnnounceRequest> delayQueue = mock(DelayQueue.class);
          final AnnouncerFactory mockedAnnouncerFactory = createMockedAnnouncerFactory();
  
          final Client client = (Client) ClientBuilder.builder()
                  .withAnnouncerFactory(mockedAnnouncerFactory)
                  .withBandwidthDispatcher(mock(BandwidthDispatcher.class))
                  .withAppConfiguration(appConfiguration)
                  .withTorrentFileProvider(torrentFileProvider)
                  .withEventPublisher(mock(ApplicationEventPublisher.class))
                  .withDelayQueue(delayQueue)
                  .build();
  
          final AnnouncerExecutor announcerExecutor = mock(AnnouncerExecutor.class);
          client.setAnnouncerExecutor(announcerExecutor);
  
          client.start();
          assertThat(client.getCurrentlySeedingAnnouncers()).hasSize(1);
  
          try {
              client.onTorrentFileRemoved(MockedTorrentTest.createOneMock("def"));
          } catch (final Throwable t) {
              fail("Should not have thrown");
          }
          assertThat(client.getCurrentlySeedingAnnouncers()).hasSize(1);
      }
  
  
      @SuppressWarnings({"unchecked", "TypeMayBeWeakened", "ResultOfMethodCallIgnored", "ConstantConditions"})
      @Test
      public void shouldRegisterToTorrentFileProviderOnStartAndUnregisterOnStop() {
          final AppConfiguration appConfiguration = this.createMockedConf();
  
          final TorrentFileProvider torrentFileProvider = createMockedTorrentFileProviderWithTorrent(new ArrayList<>());
  
          final DelayQueue<AnnounceRequest> delayQueue = mock(DelayQueue.class);
          final AnnouncerFactory mockedAnnouncerFactory = createMockedAnnouncerFactory();
          final BandwidthDispatcher bandwidthDispatcher = mock(BandwidthDispatcher.class);
  
          final Client client = (Client) ClientBuilder.builder()
                  .withAnnouncerFactory(mockedAnnouncerFactory)
                  .withBandwidthDispatcher(bandwidthDispatcher)
                  .withAppConfiguration(appConfiguration)
                  .withTorrentFileProvider(torrentFileProvider)
                  .withEventPublisher(mock(ApplicationEventPublisher.class))
                  .withDelayQueue(delayQueue)
                  .build();
  
          client.start();
          Mockito.verify(torrentFileProvider, times(1))
                  .registerListener(eq(client));
  
          client.stop();
          Mockito.verify(torrentFileProvider, times(1))
                  .unRegisterListener(eq(client));
      }
  
  }
  