コード例 #1
0
        public async Task Foo()
        {
            var fs   = new Shell();
            var path = DirectoryPath.GetCurrentDirectory() / new FileName(Guid.NewGuid().ToString());
            var doc  = new FileWatchingDocument(fs, path);

            var externalChanges = doc.ExternalChanges.FirstAsync().ToTask();

            await doc.Save(new byte[] { 13, 37 });

            await doc.Contents.FirstAsync();

            Assert.ThrowsAsync <TimeoutException>(async() =>
                                                  await externalChanges.ToObservable().Timeout(TimeSpan.FromSeconds(1)).FirstAsync());

            fs.ForceWriteText(path, "trettentretisju");

            await externalChanges;
        }
コード例 #2
0
        public async Task Retries_reading_of_file_when_getting_exception_until_successful()
        {
            var testScheduler = new HistoricalScheduler(DateTimeOffset.Now);

            var    path = AbsoluteFilePath.Parse(Platform.OperatingSystem == OS.Windows ? @"c:\trololol\foobar.ux" : @"/trololol/foobar.ux");
            var    fileNotifications = new Subject <Unit>();
            var    fs                         = Substitute.For <IFileSystem>();
            bool   fileLocked                 = false;
            string fileContent                = "abcd";
            string readContent                = null;
            int    readErrorCounter           = 0;
            int    errorsDuringLoadingCounter = 0;
            var    errorDuringLoading         = Optional.None <Exception>();

            fs.Watch(path).Returns(fileNotifications);
            fs.OpenRead(path).Returns(_ =>
            {
                if (fileLocked)
                {
                    readErrorCounter++;
                    throw new IOException(string.Format("The process cannot access the file '{0}' because it is being used by another process.", path.NativePath));
                }
                return(new MemoryStream(Encoding.UTF8.GetBytes(fileContent)));
            });

            // Start by opening FileWatchingDocument, reading unlocked file.
            var doc = new FileWatchingDocument(fs, path, testScheduler);

            doc.Contents.Subscribe(bytes => readContent = Encoding.UTF8.GetString(bytes));
            doc.ErrorsDuringLoading.Subscribe(err =>
            {
                if (err.HasValue)
                {
                    errorsDuringLoadingCounter++;
                }
                errorDuringLoading = err;
            });

            fileNotifications.OnNext(Unit.Default);
            testScheduler.AdvanceBy(FileWatchingDocument.PreLogRetryInterval);

            Assert.That(readContent, Is.EqualTo(fileContent));

            // Now change and lock the file
            fileContent = "1337";
            fileLocked  = true;
            fileNotifications.OnNext(Unit.Default);

            var slightlyBeforeErrorMessage = FileWatchingDocument.RetryErrorMessageDelay - FileWatchingDocument.PreLogRetryInterval;

            testScheduler.AdvanceBy(slightlyBeforeErrorMessage);
            Assert.That(readContent, Is.EqualTo("abcd"));
            Assert.That(readErrorCounter, Is.EqualTo(slightlyBeforeErrorMessage.TotalSeconds / FileWatchingDocument.PreLogRetryInterval.TotalSeconds).Within(1.0));

            // Wait another long interval
            readErrorCounter = 0;
            testScheduler.AdvanceBy(FileWatchingDocument.PostLogRetryInterval);

            // Check that we have the exception message ready now
            Assert.That(errorDuringLoading.HasValue, Is.True);
            Assert.That(errorDuringLoading.Value.Message, Is.EqualTo(string.Format(@"The process cannot access the file '{0}' because it is being used by another process. Retrying in background until problem is resolved.", path.NativePath)));
            Assert.That(errorsDuringLoadingCounter, Is.EqualTo(1));
            Assert.That(readErrorCounter, Is.GreaterThanOrEqualTo(1));

            // Check that error message is only output once
            readErrorCounter = 0;
            testScheduler.AdvanceBy(FileWatchingDocument.PostLogRetryInterval);
            Assert.That(readErrorCounter, Is.GreaterThanOrEqualTo(1));
            Assert.That(errorsDuringLoadingCounter, Is.EqualTo(1));

            fileLocked = false;
            testScheduler.AdvanceBy(TimeSpan.FromSeconds(FileWatchingDocument.PostLogRetryInterval.TotalSeconds * 1.1));
            Assert.That(errorDuringLoading.HasValue, Is.False);

            // HACK: I'm not completely sure why this is necesarry, I suspect it could be due to the use of Observable.DeferAsync?
            // Fix to work around HistoricalScheduler not playing nice with DeferAsync(?)
            await Task.Delay(10);

            Assert.That(readContent, Is.EqualTo(fileContent));
        }