public void Start_WhenFileNotificationIsYield_ShouldCallSynchronize(
            [Frozen]TestScheduler scheduler,
            [Frozen(As = typeof(IObservable<MusicMirrorConfiguration>))]TestObservableWrapper<MusicMirrorConfiguration> configurationObservable,
            [Frozen]Mock<IFileObserverFactory> fileObserverFactory,
            [Frozen]Mock<IFileSynchronizerVisitorFactory> fileSynchronizerFactory,
            SynchronizeFilesWhenFileChanged sut,
            MusicMirrorConfiguration configuration,
            IFileNotification[][] fileNotification,
            Mock<IFileSynchronizerVisitor> fileSynchronizerVisitor)
 {
     //arrange
     configurationObservable.SetObservable(scheduler.CreateHotObservable(OnNext(Subscribed + 1, configuration)));
     const long NotificationsStart = Subscribed + 2;
     var fileObserver = scheduler.CreateHotObservable(
         fileNotification.Select((f, i) => OnNext(NotificationsStart + i, f)).ToArray());
     fileObserverFactory.Setup(f => f.GetFileObserver(configuration.SourcePath)).Returns(fileObserver);
     fileSynchronizerFactory.Setup(f => f.CreateVisitor(configuration)).Returns(fileSynchronizerVisitor.Object);          
     //act            
     sut.Start();
     scheduler.Start();
     //assert                        
     foreach (var m in fileNotification.SelectMany(f => f).Select(f => Mock.Get(f)))
     {
         m.Verify(ff => ff.Accept(It.IsAny<CancellationToken>(), fileSynchronizerVisitor.Object));
     }
 }
		private async Task Log(Task task, string message, IFileNotification notification)
		{
			_log.Info(message);
			try
			{
				await task;
			}
			catch (Exception ex)
			{
				_log.Error(ex, "Error while visiting " + notification.Kind);
				throw;
			}
		}
 void OnSourceFileNotification(IFileNotification notification)
 {
     Log(notification);
     _sourceFileIndices.AddOrUpdate(notification.File, SourceSymbolsFor, (file, oldValue) => SourceSymbolsFor(file));
 }
 private IObservable<Unit> SynchronizeFile(IFileNotification file, IFileSynchronizerVisitor visitor)
 {
     return Observable.FromAsync(async ct => await file.Accept(ct, visitor), _notificationsScheduler)                             
                      .Do(_ =>
                      {
                          _transcodingResultNotifications.OnNext(FileTranscodingResultNotification.CreateSuccess(file));
                          _numberOfFilesAddedInTranscodingQueue.OnNext(-1);
                      })
                      .Catch((Exception ex) =>
                      {
                          _transcodingResultNotifications.OnNext(FileTranscodingResultNotification.CreateFailure(file, ex));
                          _numberOfFilesAddedInTranscodingQueue.OnNext(-1);
                          return Observable.Return(Unit.Default, ImmediateScheduler.Instance);
                      });
 }
        public void SynchronizedFileCount_WhenTranscodingIsNotRunning_AndFileNotificationsArePushed_ShouldReturnCorrectValue(
            [Frozen]TestSchedulers schedulers,
            [Frozen]Mock<ITranscodingNotifications> notifications,
            ConfigurationPageViewModel sut,
            IFileNotification[] fileNotifications)
        {
            //arrange
            var fileNotificationsObservable = schedulers.CreateHotObservable(
                OnNext(202, fileNotifications));
            var notificationsObservable = schedulers.CreateHotObservable(
                OnNext(201, false));
            notifications.Setup(n => n.ObserveIsTranscodingRunning()).Returns(notificationsObservable);
            notifications.Setup(n => n.ObserveNotifications()).Returns(fileNotificationsObservable);

            //act
            var actual = schedulers.Start(() => sut.SynchronizedFileCount);
            //assert
            var expected = new[]
            {
                OnNext(200, SynchronizedFilesCountViewModel.Empty)
            };
            actual.Messages.ShouldAllBeEquivalentTo(expected);
        }
 public void SynchronizedFileCount_WhenTranscodingIsRunning_AndTranscodingResultsArePushedWithFailures_ShouldReturnCorrectValue(
  [Frozen]TestSchedulers schedulers,
  [Frozen]Mock<ITranscodingNotifications> notifications,
  IFileNotification[] fileNotifications,
  IFileNotification[] failuresNotifications,
  Fixture fixture)
 {
     //arrange          
     var notificationsObservable = schedulers.CreateHotObservable(
         OnNext(201, true));
     var transcodingResultsObservable = schedulers.CreateHotObservable(
         fileNotifications.Select((f, i) => OnNext(203 + i, FileTranscodingResultNotification.CreateSuccess(f)))
                          .Concat(failuresNotifications.Select((f, i) => OnNext(203 + fileNotifications.Length + i, FileTranscodingResultNotification.CreateFailure(f, new Exception()))))
                          .ToArray());
     notifications.Setup(n => n.ObserveIsTranscodingRunning()).Returns(notificationsObservable);
     notifications.Setup(n => n.ObserveTranscodingResult()).Returns(transcodingResultsObservable);
     var sut = fixture.Create<ConfigurationPageViewModel>();
     //act
     var actual = schedulers.Start(() => sut.SynchronizedFileCount);
     //assert
     var expected = new[]
     {
         OnNext(Subscribed, SynchronizedFilesCountViewModel.Empty),
     }
     .Concat(fileNotifications.Select((f, i) => OnNext(203 + i, new SynchronizedFilesCountViewModel(i + 1, 0))).ToArray());
     actual.Messages.ShouldAllBeEquivalentTo(expected);
 }
 public void SynchronizedFileCount_WhenTranscodingIsRunningChangesSeveralTimes_AndTranscodingResultsArePushed_ShouldReturnCorrectValue(
  [Frozen]TestSchedulers schedulers,
  [Frozen]Mock<ITranscodingNotifications> notifications,
  IFileNotification[] fileNotifications,
  Fixture fixture)
 {
     //arrange          
     var notificationsObservable = schedulers.CreateHotObservable(
         OnNext(Subscribed + 1, false),
         OnNext(Subscribed + 100, true),
         OnNext(Subscribed + 199, false),
         OnNext(Subscribed + 200, true),
         OnNext(Subscribed + 299, false),
         OnNext(Subscribed + 300, true),
         OnNext(Subscribed + 399, false));
     Func<long, IEnumerable<Recorded<Notification<IFileTranscodingResultNotification>>>> createFileNotifications =
         offset => fileNotifications.Select((f, i) => OnNext(offset + i, FileTranscodingResultNotification.CreateSuccess(f)));
     var transcodingResultsObservable = schedulers.CreateHotObservable(
             createFileNotifications(Subscribed + 101)
                          .Concat(createFileNotifications(Subscribed + 201))
                          .Concat(createFileNotifications(Subscribed + 301))
                          .ToArray()
                          );
     notifications.Setup(n => n.ObserveIsTranscodingRunning()).Returns(notificationsObservable);
     notifications.Setup(n => n.ObserveTranscodingResult()).Returns(transcodingResultsObservable);
     var sut = fixture.Create<ConfigurationPageViewModel>();
     //act
     var actual = schedulers.Start(() => sut.SynchronizedFileCount.Do(_ => { }));
     //assert
     Func<long, IEnumerable<Recorded<Notification<SynchronizedFilesCountViewModel>>>> createExpectedFileNotifications =
         offset => fileNotifications.Select((f, i) => OnNext(offset + i, new SynchronizedFilesCountViewModel(i + 1, 0)));      
     var expected = new[]
         {
             OnNext(Subscribed, SynchronizedFilesCountViewModel.Empty),
         }
         .Concat(createExpectedFileNotifications(Subscribed + 101))                
         .Concat(createExpectedFileNotifications(Subscribed + 201))                
         .Concat(createExpectedFileNotifications(Subscribed + 301))                
         .ToArray();
     actual.Messages.ShouldAllBeEquivalentTo(expected);
 }
 private static IEnumerable<Recorded<System.Reactive.Notification<SynchronizedFilesCountViewModel>>> CreateExpectedFileNotifications(
     IFileNotification[][] fileNotifications,
     int offset)
 {
     return fileNotifications.Aggregate(new List<int>(), (list, files) =>
                             {
                                 list.Add(list.LastOrDefault() + files.Length);
                                 return list;
                             })
                             .Select((f, i) => OnNext(Subscribed + i + offset, new SynchronizedFilesCountViewModel(0, f)));
 }
        public void SynchronizedFileCount_WhenTranscodingIsRunningChangesSeveralTimes_AndFileNotificationsArePushedSeveralTimes_ShouldReturnCorrectValue(
            [Frozen]TestSchedulers schedulers,
            [Frozen]Mock<ITranscodingNotifications> notifications,
            IFileNotification[][] fileNotifications,
            Fixture fixture)
        {
            //arrange            
            const int TranscodingStoppedRelativeTime = 50;
            var fileNotificationsObservable = schedulers.CreateHotObservable(
                fileNotifications.Select((f, i) => OnNext(Subscribed + i + 101, f))
                                 .Concat(fileNotifications.Select((f, i) => OnNext(Subscribed + i + 201, f)))
                                 .Concat(fileNotifications.Select((f, i) => OnNext(Subscribed + i + 301, f)))
                                 .ToArray()
                                 );
            var notificationsObservable = schedulers.CreateHotObservable(
                OnNext(Subscribed + 1, false),
                OnNext(Subscribed + 100, true),
                OnNext(Subscribed + 100 + TranscodingStoppedRelativeTime, false),
                OnNext(Subscribed + 200, true),
                OnNext(Subscribed + 200 + TranscodingStoppedRelativeTime, false),
                OnNext(Subscribed + 300, true),
                OnNext(Subscribed + 300 + TranscodingStoppedRelativeTime, false));
            notifications.Setup(n => n.ObserveIsTranscodingRunning()).Returns(notificationsObservable);
            notifications.Setup(n => n.ObserveNotifications()).Returns(fileNotificationsObservable);
            var sut = fixture.Create<ConfigurationPageViewModel>();
            
            //act
            var actual = schedulers.Start(() => sut.SynchronizedFileCount);
            //assert                                    
            var expected = OnNext(Subscribed, SynchronizedFilesCountViewModel.Empty).Yield()
                        .Concat(CreateExpectedFileNotifications(fileNotifications, 101))                        
                        .Concat(CreateExpectedFileNotifications(fileNotifications, 201))                        
                        .Concat(CreateExpectedFileNotifications(fileNotifications, 301))                        
                        .ToArray();

            actual.Messages.ShouldAllBeEquivalentTo(expected);
        }
 public void ObserveTranscodingResult_WhenFileNotificationIsYield_ShouldReturnCorrectValue(
     [Frozen]TestScheduler scheduler,
     [Frozen(As = typeof(IObservable<MusicMirrorConfiguration>))]TestObservableWrapper<MusicMirrorConfiguration> configurationObservable,
     [Frozen]Mock<IFileObserverFactory> fileObserverFactory,
     [Frozen]Mock<IFileSynchronizerVisitorFactory> fileSynchronizerFactory,
     SynchronizeFilesWhenFileChanged sut,
     MusicMirrorConfiguration configuration,
     IFileNotification[][] fileNotification,
     Mock<IFileSynchronizerVisitor> fileSynchronizerVisitor)
 {
     //arrange
     sut.SynchronizationScheduler = ImmediateScheduler.Instance;
     configurationObservable.SetObservable(scheduler.CreateHotObservable(OnNext(Subscribed + 1, configuration)));
     const long NotificationsStart = Subscribed + 2;
     var fileObserver = scheduler.CreateHotObservable(
         fileNotification.Select((f, i) => OnNext(NotificationsStart + i, f)).ToArray());
     fileObserverFactory.Setup(f => f.GetFileObserver(configuration.SourcePath)).Returns(fileObserver);
     fileSynchronizerFactory.Setup(f => f.CreateVisitor(configuration)).Returns(fileSynchronizerVisitor.Object);
     scheduler.Schedule(200.Ticks(), () => sut.Start());
     //act         
     var actual = scheduler.Start(() => sut.ObserveTranscodingResult());
     //assert            
     var expected = fileNotification.SelectMany(
         (notifications, i) => notifications.Select(
             f => new FileTranscodingResultNotification.SuccessTranscodingResultNotification(f))
             ).ToArray();
     actual.Values().ShouldAllBeEquivalentTo(expected, o => o.RespectingRuntimeTypes());
 }
 private static void SetupTranscodingWorkWithIncrementalDuration(TestScheduler scheduler, IFileNotification[] fileNotification)
 {
     var i = 0;
     foreach (var f in fileNotification)
     {
         i++;
         var j = i;
         Mock.Get(f).Setup(ff => ff.Accept(It.IsAny<CancellationToken>(), It.IsAny<IFileSynchronizerVisitor>()))
                    .Returns(() =>
                    {
                        var completionSource = new TaskCompletionSource<bool>();
                        scheduler.ScheduleAbsolute(scheduler.Now.AddTicks(j).Ticks, () => completionSource.SetResult(true));
                        return completionSource.Task;
                    });
     }
 }
        public void ObserveIsTranscodingRunning_WhenFilesAreTranscodingAndSubscribeOccursLaterOn_ShouldReturnCorrectValue(
           [Frozen]TestScheduler scheduler,
           [Frozen(As = typeof(IObservable<MusicMirrorConfiguration>))]TestObservableWrapper<MusicMirrorConfiguration> configurationObservable,
           [Frozen]Mock<IFileObserverFactory> fileObserverFactory,
           SynchronizeFilesWhenFileChanged sut,
           MusicMirrorConfiguration configuration,
           IFileNotification[] fileNotification
           )
        {
            sut.SynchronizationScheduler = ImmediateScheduler.Instance;
            const long NotificationsStart = Subscribed + 1;
            const long Subscription = Subscribed + 3;
            configurationObservable.SetObservable(scheduler.CreateHotObservable(OnNext(NotificationsStart, configuration)));
            var fileObserver = scheduler.CreateHotObservable(OnNext(NotificationsStart, fileNotification));
            fileObserverFactory.Setup(f => f.GetFileObserver(configuration.SourcePath)).Returns(fileObserver);
            SetupTranscodingWorkWithIncrementalDuration(scheduler, fileNotification);
            scheduler.Schedule(200.Ticks(), () => sut.Start());

            //act            
            var actual = scheduler.Start(() => sut.ObserveIsTranscodingRunning(), Created, Subscription, Disposed);
            //assert
            var expected = new[] { true, false };
            //+1 because we expect that the tasks results of file.Accept will be scheduled on the TestScheduler            
            actual.Values().ShouldAllBeEquivalentTo(expected);
        }
 public void ObserveIsTranscodingRunning_WhenFilesAreTranscoding_ShouldReturnCorrectValue(
     [Frozen]TestScheduler scheduler,
     [Frozen(As = typeof(IObservable<MusicMirrorConfiguration>))]TestObservableWrapper<MusicMirrorConfiguration> configurationObservable,
     [Frozen]Mock<IFileObserverFactory> fileObserverFactory,
     SynchronizeFilesWhenFileChanged sut,
     MusicMirrorConfiguration configuration,
     IFileNotification[] fileNotification
     )
 {
     //arrange
     sut.SynchronizationScheduler = ImmediateScheduler.Instance;
     configurationObservable.SetObservable(scheduler.CreateHotObservable(OnNext(Subscribed + 1, configuration)));
     const long NotificationsStart = Subscribed + 2;
     var fileObserver = scheduler.CreateHotObservable(OnNext(NotificationsStart, fileNotification));
     fileObserverFactory.Setup(f => f.GetFileObserver(configuration.SourcePath)).Returns(fileObserver);
     SetupTranscodingWorkWithIncrementalDuration(scheduler, fileNotification);
     scheduler.Schedule(200.Ticks(), () => sut.Start());
     //act            
     var actual = scheduler.Start(() => sut.ObserveIsTranscodingRunning());
     //assert
     var expected = new[] { false, true, false };
     actual.Values().ShouldAllBeEquivalentTo(expected);
 }
 public void ObserveFileNotifications_Start_WhenFileNotificationIsYield_ShouldCallSynchronize(
 [Frozen]TestScheduler scheduler,
 [Frozen(As = typeof(IObservable<MusicMirrorConfiguration>))]TestObservableWrapper<MusicMirrorConfiguration> configurationObservable,
 [Frozen]Mock<IFileObserverFactory> fileObserverFactory,
 SynchronizeFilesWhenFileChanged sut,
 MusicMirrorConfiguration configuration,
 IFileNotification[][] fileNotification)
 {
     //arrange
     configurationObservable.SetObservable(scheduler.CreateHotObservable(OnNext(Subscribed + 1, configuration)));
     var expectedNotifications = fileNotification.Select((f, i) => OnNext(Subscribed + i + 2, f)).ToArray();
     var fileObserver = scheduler.CreateHotObservable(expectedNotifications);
     fileObserverFactory.Setup(f => f.GetFileObserver(configuration.SourcePath)).Returns(fileObserver);
     scheduler.Schedule(200.Ticks(), () => sut.Start());
     //act            
     var actual = scheduler.Start(() => sut.ObserveNotifications());
     //assert            
     var expected = expectedNotifications.Select(n => n.Value.Value);
     actual.Values().ShouldAllBeEquivalentTo(expected);
 }
 public FileHandlerLogic(IRepository repository, IFileClassesCommunication fileClassesCommunication, IFileNotification fileNotification)
     : base(repository)
 {
     _fileClassesCommunication = fileClassesCommunication;
     _fileNotification         = fileNotification;
 }
		void OnSourceFileNotification(IFileNotification notification)
		{
			Log(notification);
			_sourceFileIndices.AddOrUpdate(notification.File, SourceSymbolsFor, (file, oldValue) => SourceSymbolsFor(file));
		}