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));
     }
 }
Пример #2
0
		public CopyFileSynchronizer(
			MusicMirrorConfiguration configuration,
			IAsyncDirectoryOperations directoryOperations)
		{
			_configuration = Guard.ForNull(configuration, nameof(configuration));
			_directoryOperations = Guard.ForNull(directoryOperations, nameof(directoryOperations));
		}
		public IFileSynchronizerVisitor CreateVisitor(MusicMirrorConfiguration configuration)
		{
			var fileSynchronizerRepository = new SynchronizedFilesRepository(
				_transcoder,
				configuration,
                new SystemUtcNow());
			var fileOperations = new AsyncOperations(new FileOperations());
			var transcodingMirroredFileOperations = new SynchronizeFileService(
					fileOperations,
					configuration,
					new FileSynchronizer(
						fileSynchronizerRepository,
						_transcoder),
					fileSynchronizerRepository);
			var nonTranscodingFileService = new SynchronizeFileService(
				GetFileOperations(configuration.NonTranscodingFilesBehavior, fileOperations),
				configuration,
				GetSynchronizer(configuration, fileOperations, new AsyncDirectoryOperations(new DirectoryOperations())),
				fileSynchronizerRepository);
			return new FileSynchronizeVisitor(
				new ChooseFolderOperation(
					new DefaultRequireTranscoding(),
					nonTranscodingFileService,
					transcodingMirroredFileOperations));
		}
Пример #4
0
		public static DirectoryInfo GetDirectoryFromSourceFile(this FileInfo sourceFile, MusicMirrorConfiguration configuration)
		{
			if (sourceFile == null) throw new ArgumentNullException(nameof(sourceFile));
			if (configuration == null) throw new ArgumentNullException(nameof(configuration));
			var relativePath = Path.GetDirectoryName(sourceFile.FullName.Replace(configuration.SourcePath.FullName, string.Empty)).TrimStart('\\');
			return new DirectoryInfo(Path.Combine(configuration.TargetPath.FullName, relativePath));
		}
Пример #5
0
		public async Task Synchronize_WhenLastSynchronizationTimeIsMoreRecentThanFileModificationDate_ShouldNotCallTranscode(
			double daysToAdd,
			[Frozen]Mock<ISynchronizedFilesRepository> synchronizedFileRepository,
			[Frozen]Mock<IFileTranscoder> fileTranscoder,
			MusicMirrorConfiguration config,
			FileSynchronizer sut,
			SourceFilePath sourceFile,
			TargetFilePath targetFile)
		{
			//arrange
			var lastWriteTime = new DateTimeOffset(2015, 04, 01, 0, 0, 0, TimeSpan.Zero);
			var lastSyncTime = lastWriteTime.AddDays(daysToAdd);
			sourceFile.LastWriteTime = lastWriteTime;
			synchronizedFileRepository.Setup(s => s.GetMirroredFilePath(It.IsAny<CancellationToken>(), sourceFile.File)).ReturnsTask(targetFile.File);
			synchronizedFileRepository.Setup(s => s.GetLastSynchronization(It.IsAny<CancellationToken>(), sourceFile.File)).ReturnsTask(lastSyncTime);
			//act
			await sut.Synchronize(CancellationToken.None, sourceFile);
			//assert
			fileTranscoder.Verify(f =>
				f.Transcode(
					It.IsAny<CancellationToken>(),
					sourceFile.File,
					AudioFormat.Flac,
					It.Is((DirectoryInfo d) => d.FullName.Equals(targetFile.File.DirectoryName))),
				Times.Never());
		}
Пример #6
0
		public SymbolicLinkFileSynchronizer(
			MusicMirrorConfiguration configuration,
			IAsyncFileOperations fileOperations,
			IAsyncDirectoryOperations directoryOperations)
		{
			_configuration = Guard.ForNull(configuration, nameof(configuration));
			_fileOperations = Guard.ForNull(fileOperations, nameof(fileOperations));
			_directoryOperations = Guard.ForNull(directoryOperations, nameof(directoryOperations));
		}
Пример #7
0
		public static TargetFilePath CreateFromPathWithoutExtension(
			MusicMirrorConfiguration config,
			string[] relativePathParts)
		{
			return new TargetFilePath(
				config.TargetPath.FullName,
				relativePathParts.Skip(1).ToArray(),
				relativePathParts[0] + ".mp3");
		}
Пример #8
0
		public static SourceFilePath CreateFromPathWithoutExtension(
			MusicMirrorConfiguration config, 
			string[] relativePathParts)
		{
			return new SourceFilePath(
				config.SourcePath.FullName,
				relativePathParts.Skip(1).ToArray(),
				relativePathParts[0] + ".flac");
		}
		public async Task Synchronize_ShouldCallInnerSynchronize(
			[Frozen]Mock<IFileTranscoder> innerFileTranscoder,
			CopyId3TagsPostProcessor sut,
			SourceFilePath sourceFile,
			MusicMirrorConfiguration configuration)
		{
			//arrange
			//act
			await sut.Transcode(CancellationToken.None, sourceFile.File, AudioFormat.Flac, configuration.TargetPath);
			//assert
			innerFileTranscoder.Verify(f => f.Transcode(It.IsAny<CancellationToken>(), sourceFile.File, AudioFormat.Flac, configuration.TargetPath));
		}
 public SynchronizedFilesRepository(
     IFileTranscoder fileTranscoder,
     MusicMirrorConfiguration configuration,
     INow now)
 {
     if (now == null) throw new ArgumentNullException(nameof(now), $"{nameof(now)} is null.");
     if (fileTranscoder == null) throw new ArgumentNullException(nameof(fileTranscoder));
     if (configuration == null) throw new ArgumentNullException(nameof(configuration));
     _fileTranscoder = fileTranscoder;
     _configuration = configuration;
     _now = now;
     _synchronizations = new ConcurrentDictionary<string, DateTimeOffset>();
 }
Пример #11
0
		public SynchronizeFileService(
			IAsyncFileOperations asyncFileOperations,
			MusicMirrorConfiguration configuration,
			IFileSynchronizer fileSynchronizer,
			ISynchronizedFilesRepository synchronizedFilesRepository)
		{
			if (asyncFileOperations == null) throw new ArgumentNullException(nameof(asyncFileOperations));
			if (configuration == null) throw new ArgumentNullException(nameof(configuration));
			if (fileSynchronizer == null) throw new ArgumentNullException(nameof(fileSynchronizer));
			if (synchronizedFilesRepository == null) throw new ArgumentNullException(nameof(synchronizedFilesRepository));
			_asyncFileOperations = asyncFileOperations;
			_configuration = configuration;
			_fileSynchronizer = fileSynchronizer;
			_synchronizedFilesRepository = synchronizedFilesRepository;
		}
		public void Sut_ShouldReturnCorrectValue(
			[Frozen]Mock<ISettingsService> settingsService,
			ConfigurationObservable sut,
			TestScheduler scheduler,
			MusicMirrorConfiguration expected)
		{
			//arrange
			settingsService.Setup(s => s.ObserveValue(ConfigurationObservable.SourcePathKey, It.IsAny<Func<string>>()))
						   .Returns(scheduler.CreateColdObservable(OnNext(0, expected.SourcePath.FullName)));
			settingsService.Setup(s => s.ObserveValue(ConfigurationObservable.TargetPathKey, It.IsAny<Func<string>>()))
						   .Returns(scheduler.CreateColdObservable(OnNext(0, expected.TargetPath.FullName)));
			//act
			var result = scheduler.Start(() => sut);
			//assert
			result.Values().First().Should().Be(expected);
		}
		public IFileSynchronizerVisitor CreateVisitor(MusicMirrorConfiguration configuration)
		{
			return new LoggingFileSynchronizerVisitor(_innerFactory.CreateVisitor(configuration), _log);
		}
		public IFileSynchronizerVisitor CreateVisitor(MusicMirrorConfiguration configuration)
		{
			return new EmptyFileSynchronizerVisitor();
		}
 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 IFileSynchronizer GetSynchronizer(MusicMirrorConfiguration configuration, IAsyncFileOperations fileOperations, IAsyncDirectoryOperations directoryOperations)
		{
			switch (configuration.NonTranscodingFilesBehavior)
			{
				case NonTranscodingFilesBehavior.Copy:
					return new CopyFileSynchronizer(configuration, directoryOperations);
				case NonTranscodingFilesBehavior.SymbolicLink:
					return new SymbolicLinkFileSynchronizer(configuration, fileOperations, directoryOperations);
				default:
					throw new NotSupportedException();
			}
		}
        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);
 }
Пример #19
0
		public async Task Synchronize_WhenFormatIsUknown_ShouldNotCallTranscode(
		[Frozen]Mock<ISynchronizedFilesRepository> synchronizedFileRepository,
		[Frozen]Mock<IFileTranscoder> fileTranscoder,
		MusicMirrorConfiguration config,
		FileSynchronizer sut,
		TargetFilePath targetFile)
		{
			//arrange
			var expectedExtension = ".uknownExtension";
			var sourceFile = new SourceFilePath(config.SourcePath.FullName, new[] { "test", "test" }, "test" + expectedExtension);
			var lastWriteTime = new DateTimeOffset(2015, 04, 01, 0, 0, 0, TimeSpan.Zero);
			var lastSyncTime = lastWriteTime.AddDays(-1);
			sourceFile.LastWriteTime = lastWriteTime;
			synchronizedFileRepository.Setup(s => s.GetMirroredFilePath(It.IsAny<CancellationToken>(), sourceFile.File)).ReturnsTask(targetFile.File);
			synchronizedFileRepository.Setup(s => s.GetLastSynchronization(It.IsAny<CancellationToken>(), sourceFile.File)).ReturnsTask(lastSyncTime);
			var expectedFormat = new AudioFormat("Uknown format", "Uknown format", expectedExtension, default(LossKind));
			//act
			await sut.Synchronize(CancellationToken.None, sourceFile);
			//assert
			fileTranscoder.Verify(f =>
				f.Transcode(
					It.IsAny<CancellationToken>(),
					sourceFile.File,
					expectedFormat,
					It.Is((DirectoryInfo d) => d.FullName.Equals(targetFile.File.DirectoryName))));
		}
		public void Sut_WhenUsingDefaultValue_ShouldReturnCorrectValue(
			[Frozen]Mock<ISettingsService> settingsService,
			ConfigurationObservable sut,
			TestScheduler scheduler
			)
		{
			//arrange
			settingsService.Setup(s => s.ObserveValue(ConfigurationObservable.SourcePathKey, It.IsAny<Func<string>>()))
						   .Returns<string, Func<string>>((key, defaultValue) => scheduler.CreateColdObservable(
							OnNext(0, defaultValue())
							));
			settingsService.Setup(s => s.ObserveValue(ConfigurationObservable.TargetPathKey, It.IsAny<Func<string>>()))
						   .Returns<string, Func<string>>((key, defaultValue) => scheduler.CreateColdObservable(
							OnNext(0, defaultValue())
							));
			var expected = new MusicMirrorConfiguration(null, null, NonTranscodingFilesBehavior.Copy);
			//act
			var result = scheduler.Start(() => sut);
			//assert
			result.Values().First().ShouldBeEquivalentTo(expected);
		}
 private IObservable<Unit> ObserveFiles(MusicMirrorConfiguration configuration)
 {
     var visitor = FileSynchronizerVisitorFactory.CreateVisitor(configuration);
     return FileObserverFactory.GetFileObserver(configuration.SourcePath)          
                               .ObserveOn(_notificationsScheduler)                                                       
                               .Do(files =>
                               {                                          
                                   _numberOfFilesAddedInTranscodingQueue.OnNext(files.Length);                                          
                                   _fileNotifications.OnNext(files);                                          
                               })
                               .SelectMany(files => files.Select(file => SynchronizeFile(file, visitor))
                                                          .Merge(4, _synchronizationScheduler)
                                                          .ToList()
                                                          .SelectUnit());
 }
 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);
 }