コード例 #1
1
        public async Task Token_Callbacks_Are_Async_And_TokenNotAffected_By_Exceptions()
        {
            var fileName = Guid.NewGuid().ToString();
            var fileLocation = Path.Combine(Path.GetTempPath(), fileName);
            File.WriteAllText(fileLocation, "Content");
            var provider = new PhysicalFileProvider(Path.GetTempPath());

            var changeToken = provider.Watch(fileName);
            changeToken.RegisterChangeCallback(async _ =>
            {
                await Task.Delay(10 * 1000);
                throw new Exception("Callback throwing exception");
            }, null);

            File.AppendAllText(fileLocation, "UpdatedContent");
            // Wait for callback to be fired.
            await Task.Delay(WaitTimeForTokenToFire);
            Assert.True(changeToken.HasChanged);

            // Verify file system watcher is stable.
            int callbackCount = 0;
            var changeTokenAfterCallbackException = provider.Watch(fileName);
            changeTokenAfterCallbackException.RegisterChangeCallback(_ => { callbackCount++; }, null);
            File.AppendAllText(fileLocation, "UpdatedContent");

            // Wait for callback to be fired.
            await Task.Delay(WaitTimeForTokenToFire);
            Assert.True(changeToken.HasChanged);
            Assert.Equal(1, callbackCount);

            File.Delete(fileLocation);
        }
コード例 #2
0
        public async Task Trigger_Fired_On_Directory_Name_Change()
        {
            var provider = new PhysicalFileProvider(Path.GetTempPath());
            var oldDirectoryName = Guid.NewGuid().ToString();
            var newDirectoryName = Guid.NewGuid().ToString();
            var oldDirectoryFullPath = Path.Combine(Path.GetTempPath(), oldDirectoryName);
            var newDirectoryFullPath = Path.Combine(Path.GetTempPath(), newDirectoryName);

            Directory.CreateDirectory(oldDirectoryFullPath);
            var oldDirectoryTrigger = provider.Watch("**/" + oldDirectoryName);
            var newDirectoryTrigger = provider.Watch("**/" + newDirectoryName);
            var oldTriggers = new List<IExpirationTrigger>();
            var newTriggers = new List<IExpirationTrigger>();

            oldTriggers.Add(provider.Watch(Path.Combine("**", oldDirectoryName, "*.txt")));
            newTriggers.Add(provider.Watch(Path.Combine("**", newDirectoryName, "*.txt")));

            for (int i = 0; i < 5; i++)
            {
                var fileName = string.Format("test{0}.txt", i);
                File.WriteAllText(Path.Combine(oldDirectoryFullPath, fileName), "test content");
                oldTriggers.Add(provider.Watch(Path.Combine("**", oldDirectoryName, fileName)));
                newTriggers.Add(provider.Watch(Path.Combine("**", newDirectoryName, fileName)));
            }

            await Task.Delay(2 * 100); // Give it a while before trying rename.
            Directory.Move(oldDirectoryFullPath, newDirectoryFullPath);

            // Wait for triggers to fire.
            await Task.Delay(WAIT_TIME_FOR_TRIGGER_TO_FIRE);
            oldDirectoryTrigger.IsExpired.ShouldBe(true);
            newDirectoryTrigger.IsExpired.ShouldBe(true);
            oldTriggers.All(t => t.IsExpired).ShouldBe(true);
            newTriggers.All(t => t.IsExpired).ShouldBe(true);

            newDirectoryTrigger = provider.Watch(newDirectoryName);
            newTriggers = new List<IExpirationTrigger>();

            newTriggers.Add(provider.Watch(Path.Combine("**", newDirectoryName, "*.txt")));
            for (int i = 0; i < 5; i++)
            {
                var fileName = string.Format("test{0}.txt", i);
                newTriggers.Add(provider.Watch(Path.Combine("**", newDirectoryName, fileName)));
            }

            Directory.Delete(newDirectoryFullPath, true);

            // Wait for triggers to fire.
            await Task.Delay(WAIT_TIME_FOR_TRIGGER_TO_FIRE);
            newDirectoryTrigger.IsExpired.ShouldBe(true);
            newTriggers.All(t => t.IsExpired).ShouldBe(true);
        }
コード例 #3
0
        public async Task Triggers_With_Regular_Expression_Pointing_To_SubFolder()
        {
            var subFolderName = Guid.NewGuid().ToString();
            var pattern1 = "**/*";
            var pattern2 = string.Format("{0}/**/*.cshtml", subFolderName);
            var root = Path.GetTempPath();
            var fileName = Guid.NewGuid().ToString();
            var subFolder = Path.Combine(root, subFolderName);
            Directory.CreateDirectory(subFolder);

            int pattern1TriggerCount = 0, pattern2TriggerCount = 0;
            var provider = new PhysicalFileProvider(root);
            var trigger1 = provider.Watch(pattern1);
            trigger1.RegisterExpirationCallback(_ => { pattern1TriggerCount++; }, null);
            var trigger2 = provider.Watch(pattern2);
            trigger2.RegisterExpirationCallback(_ => { pattern2TriggerCount++; }, null);

            File.WriteAllText(Path.Combine(root, fileName + ".cshtml"), "Content");

            await Task.Delay(WAIT_TIME_FOR_TRIGGER_TO_FIRE);
            pattern1TriggerCount.ShouldBe(1);
            pattern2TriggerCount.ShouldBe(0);

            trigger1 = provider.Watch(pattern1);
            trigger1.RegisterExpirationCallback(_ => { pattern1TriggerCount++; }, null);
            // Register this trigger again.
            var trigger3 = provider.Watch(pattern2);
            trigger3.RegisterExpirationCallback(_ => { pattern2TriggerCount++; }, null);
            trigger3.ShouldBe(trigger2);
            File.WriteAllText(Path.Combine(subFolder, fileName + ".cshtml"), "Content");

            await Task.Delay(WAIT_TIME_FOR_TRIGGER_TO_FIRE);
            pattern1TriggerCount.ShouldBe(2);
            pattern2TriggerCount.ShouldBe(2);

            Directory.Delete(subFolder, true);
            File.Delete(Path.Combine(root, fileName + ".cshtml"));
        }
コード例 #4
0
        public async Task Triggers_With_Path_Not_Ending_With_Slash()
        {
            var provider = new PhysicalFileProvider(Path.GetTempPath());
            string directoryName = Guid.NewGuid().ToString();
            string fileName = Guid.NewGuid().ToString();

            int triggerCount = 0;
            // Matches file/directory with this name.
            var fileTrigger = provider.Watch("/" + directoryName);
            fileTrigger.RegisterExpirationCallback(_ => { triggerCount++; }, null);

            Directory.CreateDirectory(Path.Combine(Path.GetTempPath(), directoryName));
            await Task.Delay(WAIT_TIME_FOR_TRIGGER_TO_FIRE);
            triggerCount.ShouldBe(1);

            // Matches file/directory with this name.
            fileTrigger = provider.Watch("/" + fileName);
            fileTrigger.RegisterExpirationCallback(_ => { triggerCount++; }, null);

            File.WriteAllText(Path.Combine(Path.GetTempPath(), fileName), "Content");
            await Task.Delay(WAIT_TIME_FOR_TRIGGER_TO_FIRE);
            triggerCount.ShouldBe(2);
        }
コード例 #5
0
        public async Task Trigger_Fired_For_File_Or_Directory_Create_And_Delete()
        {
            var root = Path.GetTempPath();
            var provider = new PhysicalFileProvider(root);
            string fileName = Guid.NewGuid().ToString();
            string directoryName = Guid.NewGuid().ToString();

            int triggerCount = 0;
            var fileTrigger = provider.Watch(fileName);
            fileTrigger.RegisterExpirationCallback(_ => { triggerCount++; }, null);
            var directoryTrigger = provider.Watch(directoryName);
            directoryTrigger.RegisterExpirationCallback(_ => { triggerCount++; }, null);

            fileTrigger.ShouldNotBe(directoryTrigger);

            File.WriteAllText(Path.Combine(root, fileName), "Content");
            Directory.CreateDirectory(Path.Combine(Path.GetTempPath(), directoryName));

            // Wait for triggers to fire.
            await Task.Delay(WAIT_TIME_FOR_TRIGGER_TO_FIRE);

            triggerCount.ShouldBe(2);

            fileTrigger.IsExpired.ShouldBe(true);
            directoryTrigger.IsExpired.ShouldBe(true);

            fileTrigger = provider.Watch(fileName);
            fileTrigger.RegisterExpirationCallback(_ => { triggerCount++; }, null);
            directoryTrigger = provider.Watch(directoryName);
            directoryTrigger.RegisterExpirationCallback(_ => { triggerCount++; }, null);

            File.Delete(Path.Combine(root, fileName));
            Directory.Delete(Path.Combine(Path.GetTempPath(), directoryName));

            // Wait for triggers to fire.
            await Task.Delay(WAIT_TIME_FOR_TRIGGER_TO_FIRE);
            triggerCount.ShouldBe(4);
        }
コード例 #6
0
        public async Task ModifyContent_And_Delete_File_Succeeds_And_Callsback_Registered_Triggers()
        {
            var fileName = Guid.NewGuid().ToString();
            var fileLocation = Path.Combine(Path.GetTempPath(), fileName);
            File.WriteAllText(fileLocation, "OldContent");
            var provider = new PhysicalFileProvider(Path.GetTempPath());
            var fileInfo = provider.GetFileInfo(fileName);
            fileInfo.Length.ShouldBe(new FileInfo(fileInfo.PhysicalPath).Length);
            fileInfo.Exists.ShouldBe(true);

            IExpirationTrigger trigger3 = null, trigger4 = null;
            var trigger1 = provider.Watch(fileName);
            var trigger2 = provider.Watch(fileName);

            // Valid trigger1 created.
            trigger1.ShouldNotBe(null);
            trigger1.IsExpired.ShouldBe(false);
            trigger1.ActiveExpirationCallbacks.ShouldBe(true);

            // Valid trigger2 created.
            trigger2.ShouldNotBe(null);
            trigger2.IsExpired.ShouldBe(false);
            trigger2.ActiveExpirationCallbacks.ShouldBe(true);

            // Trigger is the same for a specific file.
            trigger1.ShouldBe(trigger2);

            trigger1.RegisterExpirationCallback(state =>
            {
                var infoFromState = state as IFileInfo;
                trigger3 = provider.Watch(infoFromState.Name);
                trigger3.ShouldNotBe(null);
                trigger3.RegisterExpirationCallback(_ => { }, null);
                trigger3.IsExpired.ShouldBe(false);
            }, state: fileInfo);

            trigger2.RegisterExpirationCallback(state =>
            {
                var infoFromState = state as IFileInfo;
                trigger4 = provider.Watch(infoFromState.Name);
                trigger4.ShouldNotBe(null);
                trigger4.RegisterExpirationCallback(_ => { }, null);
                trigger4.IsExpired.ShouldBe(false);
            }, state: fileInfo);

            // Write new content.
            File.WriteAllText(fileLocation, "OldContent + NewContent");
            fileInfo.Exists.ShouldBe(true);
            // Wait for callbacks to be fired.
            await Task.Delay(WAIT_TIME_FOR_TRIGGER_TO_FIRE);
            trigger1.IsExpired.ShouldBe(true);
            trigger2.IsExpired.ShouldBe(true);

            // Trigger is the same for a specific file.
            trigger3.ShouldBe(trigger4);
            // A new trigger is created.
            trigger3.ShouldNotBe(trigger1);

            // Delete the file and verify file info is updated.
            File.Delete(fileLocation);
            fileInfo = provider.GetFileInfo(fileName);
            fileInfo.Exists.ShouldBe(false);
            new FileInfo(fileLocation).Exists.ShouldBe(false);

            // Wait for callbacks to be fired.
            await Task.Delay(WAIT_TIME_FOR_TRIGGER_TO_FIRE);
            trigger3.IsExpired.ShouldBe(true);
            trigger4.IsExpired.ShouldBe(true);
        }
コード例 #7
0
        public async Task Trigger_With_MultipleFiles()
        {
            var fileName1 = Guid.NewGuid().ToString();
            var fileName2 = Guid.NewGuid().ToString();
            var fileLocation1 = Path.Combine(Path.GetTempPath(), fileName1);
            var fileLocation2 = Path.Combine(Path.GetTempPath(), fileName2);
            File.WriteAllText(fileLocation1, "Content1");
            File.WriteAllText(fileLocation2, "Content2");
            var provider = new PhysicalFileProvider(Path.GetTempPath());

            int invocationCount1 = 0, invocationCount2 = 0;
            var trigger1 = provider.Watch(fileName1);
            trigger1.RegisterExpirationCallback(_ => { invocationCount1++; }, null);
            var trigger2 = provider.Watch(fileName2);
            trigger2.RegisterExpirationCallback(_ => { invocationCount2++; }, null);

            trigger1.ShouldNotBe(null);
            trigger1.IsExpired.ShouldNotBe(true);
            trigger1.ActiveExpirationCallbacks.ShouldBe(true);

            trigger2.ShouldNotBe(null);
            trigger2.IsExpired.ShouldNotBe(true);
            trigger2.ActiveExpirationCallbacks.ShouldBe(true);

            trigger1.ShouldNotBe(trigger2);

            File.AppendAllText(fileLocation1, "Update1");
            File.AppendAllText(fileLocation2, "Update2");

            // Wait for callbacks to be fired.
            await Task.Delay(WAIT_TIME_FOR_TRIGGER_TO_FIRE);

            invocationCount1.ShouldBe(1);
            invocationCount2.ShouldBe(1);
            trigger1.IsExpired.ShouldBe(true);
            trigger2.IsExpired.ShouldBe(true);

            File.Delete(fileLocation1);
            File.Delete(fileLocation2);

            // Callbacks not invoked on expired triggers.
            invocationCount1.ShouldBe(1);
            invocationCount2.ShouldBe(1);
        }
コード例 #8
0
        public async Task FileTrigger_NotTriggered_After_Expiry()
        {
            var fileName = Guid.NewGuid().ToString();
            var fileLocation = Path.Combine(Path.GetTempPath(), fileName);
            File.WriteAllText(fileLocation, "Content");
            var provider = new PhysicalFileProvider(Path.GetTempPath());

            var expirationTrigger = provider.Watch(fileName);
            int invocationCount = 0;
            expirationTrigger.RegisterExpirationCallback(_ => { invocationCount++; }, null);

            // Callback expected for this change.
            File.AppendAllText(fileLocation, "UpdatedContent1");

            // Callback not expected for this change.
            File.AppendAllText(fileLocation, "UpdatedContent2");

            // Wait for callbacks to be fired.
            await Task.Delay(WAIT_TIME_FOR_TRIGGER_TO_FIRE);

            invocationCount.ShouldBe(1);

            File.Delete(fileLocation);
        }
コード例 #9
0
        public async Task Tokens_With_Path_Ending_With_Slash()
        {
            var provider = new PhysicalFileProvider(Path.GetTempPath());
            string fileName = Guid.NewGuid().ToString();
            string folderName = Guid.NewGuid().ToString();

            int tokenCount = 0;
            var filetoken = provider.Watch("/" + folderName + "/");
            filetoken.RegisterChangeCallback(_ => { tokenCount++; }, null);

            var folderPath = Path.Combine(Path.GetTempPath(), folderName);
            Directory.CreateDirectory(folderPath);
            File.WriteAllText(Path.Combine(folderPath, fileName), "Content");

            await Task.Delay(WaitTimeForTokenToFire);
            Assert.Equal(1, tokenCount);

            filetoken = provider.Watch("/" + folderName + "/");
            filetoken.RegisterChangeCallback(_ => { tokenCount++; }, null);

            File.AppendAllText(Path.Combine(folderPath, fileName), "UpdatedContent");
            await Task.Delay(WaitTimeForTokenToFire);
            Assert.Equal(2, tokenCount);

            filetoken = provider.Watch("/" + folderName + "/");
            filetoken.RegisterChangeCallback(_ => { tokenCount++; }, null);

            File.Delete(Path.Combine(folderPath, fileName));
            await Task.Delay(WaitTimeForTokenToFire);
            Assert.Equal(3, tokenCount);
        }
コード例 #10
0
        public async Task Token_Fired_For_File_Or_Directory_Create_And_Delete()
        {
            var root = Path.GetTempPath();
            var provider = new PhysicalFileProvider(root);
            string fileName = Guid.NewGuid().ToString();
            string directoryName = Guid.NewGuid().ToString();

            int tokenCount = 0;
            var filetoken = provider.Watch(fileName);
            filetoken.RegisterChangeCallback(_ => { tokenCount++; }, null);
            var directorytoken = provider.Watch(directoryName);
            directorytoken.RegisterChangeCallback(_ => { tokenCount++; }, null);

            Assert.NotEqual(directorytoken, filetoken);

            File.WriteAllText(Path.Combine(root, fileName), "Content");
            Directory.CreateDirectory(Path.Combine(Path.GetTempPath(), directoryName));

            // Wait for tokens to fire.
            await Task.Delay(WaitTimeForTokenToFire);

            Assert.Equal(2, tokenCount);

            Assert.True(filetoken.HasChanged);
            Assert.True(directorytoken.HasChanged);

            filetoken = provider.Watch(fileName);
            filetoken.RegisterChangeCallback(_ => { tokenCount++; }, null);
            directorytoken = provider.Watch(directoryName);
            directorytoken.RegisterChangeCallback(_ => { tokenCount++; }, null);

            File.Delete(Path.Combine(root, fileName));
            Directory.Delete(Path.Combine(Path.GetTempPath(), directoryName));

            // Wait for tokens to fire.
            await Task.Delay(WaitTimeForTokenToFire);
            Assert.Equal(4, tokenCount);
        }
コード例 #11
0
        public void Token_For_AbsolutePath_Filters()
        {
            var provider = new PhysicalFileProvider(Path.GetTempPath());
            var path = Path.Combine(Path.GetTempPath(), "filename");
            var token = provider.Watch(path);

            Assert.Same(NoopChangeToken.Singleton, token);
        }
コード例 #12
0
        public void Token_For_Whitespace_Filters()
        {
            var provider = new PhysicalFileProvider(Path.GetTempPath());
            var token = provider.Watch("  ");

            Assert.False(token.HasChanged);
            Assert.True(token.ActiveChangeCallbacks);
        }
コード例 #13
0
        public void Token_For_Empty_Filter()
        {
            var provider = new PhysicalFileProvider(Path.GetTempPath());
            var token = provider.Watch(string.Empty);

            Assert.False(token.HasChanged);
            Assert.True(token.ActiveChangeCallbacks);
        }
コード例 #14
0
        public void Token_For_Null_Filter()
        {
            var provider = new PhysicalFileProvider(Path.GetTempPath());
            var token = provider.Watch(null);

            Assert.Same(NoopChangeToken.Singleton, token);
        }
コード例 #15
0
        public async Task ModifyContent_And_Delete_File_Succeeds_And_Callsback_RegisteredTokens()
        {
            var fileName = Guid.NewGuid().ToString();
            var fileLocation = Path.Combine(Path.GetTempPath(), fileName);
            File.WriteAllText(fileLocation, "OldContent");
            var provider = new PhysicalFileProvider(Path.GetTempPath());
            var fileInfo = provider.GetFileInfo(fileName);
            Assert.Equal(new FileInfo(fileInfo.PhysicalPath).Length, fileInfo.Length);
            Assert.True(fileInfo.Exists);

            var token1 = provider.Watch(fileName);
            var token2 = provider.Watch(fileName);

            // Valid token1 created.
            Assert.NotNull(token1);
            Assert.False(token1.HasChanged);
            Assert.True(token1.ActiveChangeCallbacks);

            // Valid token2 created.
            Assert.NotNull(token2);
            Assert.False(token2.HasChanged);
            Assert.True(token2.ActiveChangeCallbacks);

            // token is the same for a specific file.
            Assert.Equal(token2, token1);

            IChangeToken token3 = null;
            IChangeToken token4 = null;
            token1.RegisterChangeCallback(state =>
            {
                var infoFromState = state as IFileInfo;
                token3 = provider.Watch(infoFromState.Name);
                Assert.NotNull(token3);
                token3.RegisterChangeCallback(_ => { }, null);
                Assert.False(token3.HasChanged);
            }, state: fileInfo);

            token2.RegisterChangeCallback(state =>
            {
                var infoFromState = state as IFileInfo;
                token4 = provider.Watch(infoFromState.Name);
                Assert.NotNull(token4);
                token4.RegisterChangeCallback(_ => { }, null);
                Assert.False(token4.HasChanged);
            }, state: fileInfo);

            // Write new content.
            File.WriteAllText(fileLocation, "OldContent + NewContent");
            Assert.True(fileInfo.Exists);
            // Wait for callbacks to be fired.
            await Task.Delay(WaitTimeForTokenToFire);
            Assert.True(token1.HasChanged);
            Assert.True(token2.HasChanged);

            // token is the same for a specific file.
            Assert.Same(token4, token3);
            // A new token is created.
            Assert.NotEqual(token1, token3);

            // Delete the file and verify file info is updated.
            File.Delete(fileLocation);
            fileInfo = provider.GetFileInfo(fileName);
            Assert.False(fileInfo.Exists);
            Assert.False(new FileInfo(fileLocation).Exists);

            // Wait for callbacks to be fired.
            await Task.Delay(WaitTimeForTokenToFire);
            Assert.True(token3.HasChanged);
            Assert.True(token4.HasChanged);
        }
コード例 #16
0
        public async Task Tokens_With_Path_Not_Ending_With_Slash()
        {
            var provider = new PhysicalFileProvider(Path.GetTempPath());
            string directoryName = Guid.NewGuid().ToString();
            string fileName = Guid.NewGuid().ToString();

            int tokenCount = 0;
            // Matches file/directory with this name.
            var filetoken = provider.Watch("/" + directoryName);
            filetoken.RegisterChangeCallback(_ => { tokenCount++; }, null);

            Directory.CreateDirectory(Path.Combine(Path.GetTempPath(), directoryName));
            await Task.Delay(WaitTimeForTokenToFire);
            Assert.Equal(1, tokenCount);

            // Matches file/directory with this name.
            filetoken = provider.Watch("/" + fileName);
            filetoken.RegisterChangeCallback(_ => { tokenCount++; }, null);

            File.WriteAllText(Path.Combine(Path.GetTempPath(), fileName), "Content");
            await Task.Delay(WaitTimeForTokenToFire);
            Assert.Equal(2, tokenCount);
        }
コード例 #17
0
        public async Task Createdtrigger_Same_For_A_File_And_Callsback_AllRegisteredTriggers_OnChange()
        {
            var fileName = Guid.NewGuid().ToString();
            var fileLocation = Path.Combine(Path.GetTempPath(), fileName);
            File.WriteAllText(fileLocation, "Content");
            var provider = new PhysicalFileProvider(Path.GetTempPath());

            var count = 10;
            var tasks = new List<Task>(count);
            var triggers = new IExpirationTrigger[count];
            var callbackResults = new bool[count];

            for (int i = 0; i < count; i++)
            {
                tasks.Add(new Task(index =>
                {
                    var expirationTrigger = provider.Watch(fileName);
                    triggers[(int)index] = expirationTrigger;
                    expirationTrigger.ShouldNotBe(null);
                    expirationTrigger.IsExpired.ShouldNotBe(true);
                    expirationTrigger.RegisterExpirationCallback(_ => { callbackResults[(int)index] = true; }, index);
                }, state: i));
            }

            // Simulating multiple concurrent requests to the same file.
            Parallel.ForEach(tasks, task => task.Start());
            await Task.WhenAll(tasks);
            File.AppendAllText(fileLocation, "UpdatedContent");

            // Some warm up time for the callbacks to be fired.
            await Task.Delay(WAIT_TIME_FOR_TRIGGER_TO_FIRE);

            for (int index = 1; index < count; index++)
            {
                triggers[index].ShouldBe(triggers[index - 1]);
            }

            callbackResults.All(c => c == true).ShouldBe(true);

            File.Delete(fileLocation);
        }
コード例 #18
0
        public async Task Tokens_With_Regular_Expression_Filters()
        {
            var pattern1 = "**/*";
            var pattern2 = "*.cshtml";
            var root = Path.GetTempPath();
            var fileName = Guid.NewGuid().ToString();
            var subFolder = Path.Combine(root, Guid.NewGuid().ToString());
            Directory.CreateDirectory(subFolder);

            int pattern1tokenCount = 0, pattern2tokenCount = 0;
            Action<object> callback1 = _ => { pattern1tokenCount++; };
            Action<object> callback2 = _ => { pattern2tokenCount++; };

            var provider = new PhysicalFileProvider(root);
            var token1 = provider.Watch(pattern1);
            token1.RegisterChangeCallback(callback1, null);
            var token2 = provider.Watch(pattern2);
            token2.RegisterChangeCallback(callback2, null);

            File.WriteAllText(Path.Combine(root, fileName + ".cshtml"), "Content");

            await Task.Delay(WaitTimeForTokenToFire);
            Assert.Equal(1, pattern1tokenCount);
            Assert.Equal(1, pattern2tokenCount);

            token1 = provider.Watch(pattern1);
            token1.RegisterChangeCallback(callback1, null);
            token2 = provider.Watch(pattern2);
            token2.RegisterChangeCallback(callback2, null);
            File.WriteAllText(Path.Combine(subFolder, fileName + ".txt"), "Content");

            await Task.Delay(WaitTimeForTokenToFire);
            Assert.Equal(2, pattern1tokenCount);
            Assert.Equal(1, pattern2tokenCount);

            Directory.Delete(subFolder, true);
            File.Delete(Path.Combine(root, fileName + ".cshtml"));
        }
コード例 #19
0
        public void Trigger_Is_FileName_Case_Insensitive()
        {
            var fileName = Guid.NewGuid().ToString() + 'A';
            var fileLocation = Path.Combine(Path.GetTempPath(), fileName);
            File.WriteAllText(fileLocation, "Content");
            var provider = new PhysicalFileProvider(Path.GetTempPath());

            var expirationTrigger = provider.Watch(fileName);
            var lowerCaseExpirationTrigger = provider.Watch(fileName.ToLowerInvariant());
            expirationTrigger.ShouldBe(lowerCaseExpirationTrigger);

            File.Delete(fileLocation);
        }
コード例 #20
0
        public async Task Tokens_With_Regular_Expression_Pointing_To_SubFolder()
        {
            var subFolderName = Guid.NewGuid().ToString();
            var pattern1 = "**/*";
            var pattern2 = string.Format("{0}/**/*.cshtml", subFolderName);
            var root = Path.GetTempPath();
            var fileName = Guid.NewGuid().ToString();
            var subFolder = Path.Combine(root, subFolderName);
            Directory.CreateDirectory(subFolder);

            int pattern1tokenCount = 0, pattern2tokenCount = 0;
            var provider = new PhysicalFileProvider(root);
            var token1 = provider.Watch(pattern1);
            token1.RegisterChangeCallback(_ => { pattern1tokenCount++; }, null);
            var token2 = provider.Watch(pattern2);
            token2.RegisterChangeCallback(_ => { pattern2tokenCount++; }, null);

            File.WriteAllText(Path.Combine(root, fileName + ".cshtml"), "Content");

            await Task.Delay(WaitTimeForTokenToFire);
            Assert.Equal(1, pattern1tokenCount);
            Assert.Equal(0, pattern2tokenCount);

            token1 = provider.Watch(pattern1);
            token1.RegisterChangeCallback(_ => { pattern1tokenCount++; }, null);
            // Register this token again.
            var token3 = provider.Watch(pattern2);
            token3.RegisterChangeCallback(_ => { pattern2tokenCount++; }, null);
            Assert.Equal(token2, token3);
            File.WriteAllText(Path.Combine(subFolder, fileName + ".cshtml"), "Content");

            await Task.Delay(WaitTimeForTokenToFire);
            Assert.Equal(2, pattern1tokenCount);
            Assert.Equal(2, pattern2tokenCount);

            Directory.Delete(subFolder, true);
            File.Delete(Path.Combine(root, fileName + ".cshtml"));
        }
コード例 #21
0
        public async Task Trigger_Callbacks_Are_Async_And_TriggerNotAffected_By_Exceptions()
        {
            var fileName = Guid.NewGuid().ToString();
            var fileLocation = Path.Combine(Path.GetTempPath(), fileName);
            File.WriteAllText(fileLocation, "Content");
            var provider = new PhysicalFileProvider(Path.GetTempPath());

            var expirationTrigger = provider.Watch(fileName);
            expirationTrigger.RegisterExpirationCallback(async _ =>
            {
                await Task.Delay(10 * 1000);
                throw new Exception("Callback throwing exception");
            }, null);

            File.AppendAllText(fileLocation, "UpdatedContent");
            // Wait for callback to be fired.
            await Task.Delay(WAIT_TIME_FOR_TRIGGER_TO_FIRE);
            expirationTrigger.IsExpired.ShouldBe(true);

            // Verify file system watcher is stable.
            int callbackCount = 0;
            var expirationTriggerAfterCallbackException = provider.Watch(fileName);
            expirationTriggerAfterCallbackException.RegisterExpirationCallback(_ => { callbackCount++; }, null);
            File.AppendAllText(fileLocation, "UpdatedContent");

            // Wait for callback to be fired.
            await Task.Delay(WAIT_TIME_FOR_TRIGGER_TO_FIRE);
            expirationTrigger.IsExpired.ShouldBe(true);
            callbackCount.ShouldBe(1);

            File.Delete(fileLocation);
        }
コード例 #22
0
        public void Tokens_With_Forward_And_Backward_Slash()
        {
            var provider = new PhysicalFileProvider(Path.GetTempPath());
            var token1 = provider.Watch("/a/b");
            var token2 = provider.Watch("a/b");
            var token3 = provider.Watch(@"a\b");

            Assert.Equal(token2, token1);
            Assert.Equal(token3, token2);

            Assert.True(token1.ActiveChangeCallbacks);
            Assert.True(token2.ActiveChangeCallbacks);
            Assert.True(token3.ActiveChangeCallbacks);

            Assert.False(token1.HasChanged);
            Assert.False(token2.HasChanged);
            Assert.False(token3.HasChanged);
        }
コード例 #23
0
        public void Trigger_For_Null_Empty_Whitespace_Filters()
        {
            var provider = new PhysicalFileProvider(Path.GetTempPath());

            var trigger = provider.Watch(null);
            trigger.IsExpired.ShouldBe(false);
            trigger.ActiveExpirationCallbacks.ShouldBe(false);

            trigger = provider.Watch(string.Empty);
            trigger.IsExpired.ShouldBe(false);
            trigger.ActiveExpirationCallbacks.ShouldBe(true);

            // White space.
            trigger = provider.Watch("  ");
            trigger.IsExpired.ShouldBe(false);
            trigger.ActiveExpirationCallbacks.ShouldBe(true);

            // Absolute path.
            trigger = provider.Watch(Path.Combine(Path.GetTempPath() + "filename"));
            trigger.IsExpired.ShouldBe(false);
            trigger.ActiveExpirationCallbacks.ShouldBe(false);
        }
コード例 #24
0
        public async Task Token_Fired_On_Directory_Name_Change()
        {
            var provider = new PhysicalFileProvider(Path.GetTempPath());
            var oldDirectoryName = Guid.NewGuid().ToString();
            var newDirectoryName = Guid.NewGuid().ToString();
            var oldDirectoryFullPath = Path.Combine(Path.GetTempPath(), oldDirectoryName);
            var newDirectoryFullPath = Path.Combine(Path.GetTempPath(), newDirectoryName);

            Directory.CreateDirectory(oldDirectoryFullPath);
            var oldDirectorytoken = provider.Watch("**/" + oldDirectoryName);
            var newDirectorytoken = provider.Watch("**/" + newDirectoryName);
            var oldtokens = new List<IChangeToken>();
            var newtokens = new List<IChangeToken>();

            oldtokens.Add(provider.Watch(Path.Combine("**", oldDirectoryName, "*.txt")));
            newtokens.Add(provider.Watch(Path.Combine("**", newDirectoryName, "*.txt")));

            for (int i = 0; i < 5; i++)
            {
                var fileName = string.Format("test{0}.txt", i);
                File.WriteAllText(Path.Combine(oldDirectoryFullPath, fileName), "test content");
                oldtokens.Add(provider.Watch(Path.Combine("**", oldDirectoryName, fileName)));
                newtokens.Add(provider.Watch(Path.Combine("**", newDirectoryName, fileName)));
            }

            await Task.Delay(2 * 100); // Give it a while before trying rename.
            Directory.Move(oldDirectoryFullPath, newDirectoryFullPath);

            // Wait for tokens to fire.
            await Task.Delay(WaitTimeForTokenToFire);
            Assert.True(oldDirectorytoken.HasChanged);
            Assert.True(newDirectorytoken.HasChanged);
            oldtokens.ForEach(t => Assert.True(t.HasChanged));
            newtokens.ForEach(t => Assert.True(t.HasChanged));

            newDirectorytoken = provider.Watch(newDirectoryName);
            newtokens = new List<IChangeToken>();

            newtokens.Add(provider.Watch(Path.Combine("**", newDirectoryName, "*.txt")));
            for (int i = 0; i < 5; i++)
            {
                var fileName = string.Format("test{0}.txt", i);
                newtokens.Add(provider.Watch(Path.Combine("**", newDirectoryName, fileName)));
            }

            Directory.Delete(newDirectoryFullPath, true);

            // Wait for tokens to fire.
            await Task.Delay(WaitTimeForTokenToFire);
            Assert.True(newDirectorytoken.HasChanged);
            newtokens.ForEach(t => Assert.True(t.HasChanged));
        }
コード例 #25
0
        public async Task Triggers_With_Path_Ending_With_Slash()
        {
            var provider = new PhysicalFileProvider(Path.GetTempPath());
            string fileName = Guid.NewGuid().ToString();
            string folderName = Guid.NewGuid().ToString();

            int triggerCount = 0;
            var fileTrigger = provider.Watch("/" + folderName + "/");
            fileTrigger.RegisterExpirationCallback(_ => { triggerCount++; }, null);

            var folderPath = Path.Combine(Path.GetTempPath(), folderName);
            Directory.CreateDirectory(folderPath);
            File.WriteAllText(Path.Combine(folderPath, fileName), "Content");

            await Task.Delay(WAIT_TIME_FOR_TRIGGER_TO_FIRE);
            triggerCount.ShouldBe(1);

            fileTrigger = provider.Watch("/" + folderName + "/");
            fileTrigger.RegisterExpirationCallback(_ => { triggerCount++; }, null);

            File.AppendAllText(Path.Combine(folderPath, fileName), "UpdatedContent");
            await Task.Delay(WAIT_TIME_FOR_TRIGGER_TO_FIRE);
            triggerCount.ShouldBe(2);

            fileTrigger = provider.Watch("/" + folderName + "/");
            fileTrigger.RegisterExpirationCallback(_ => { triggerCount++; }, null);

            File.Delete(Path.Combine(folderPath, fileName));
            await Task.Delay(WAIT_TIME_FOR_TRIGGER_TO_FIRE);
            triggerCount.ShouldBe(3);
        }
コード例 #26
0
        public async Task Tokens_NotFired_For_FileNames_Starting_With_Period()
        {
            var root = Path.GetTempPath();
            var fileNameStartingWithPeriod = Path.Combine(root, "." + Guid.NewGuid().ToString());
            File.WriteAllText(fileNameStartingWithPeriod, "Content");

            var provider = new PhysicalFileProvider(Path.GetTempPath());
            var tokenFileNameStartingPeriod = provider.Watch(Path.GetFileName(fileNameStartingWithPeriod));

            Assert.False(tokenFileNameStartingPeriod.HasChanged);

            File.WriteAllText(fileNameStartingWithPeriod, "Updated Contents");

            // Wait for tokens to fire.
            await Task.Delay(WaitTimeForTokenToFire);

            Assert.False(tokenFileNameStartingPeriod.HasChanged);
        }
コード例 #27
0
        public async Task Triggers_With_Regular_Expression_Filters()
        {
            var pattern1 = "**/*";
            var pattern2 = "*.cshtml";
            var root = Path.GetTempPath();
            var fileName = Guid.NewGuid().ToString();
            var subFolder = Path.Combine(root, Guid.NewGuid().ToString());
            Directory.CreateDirectory(subFolder);

            int pattern1TriggerCount = 0, pattern2TriggerCount = 0;
            Action<object> callback1 = _ => { pattern1TriggerCount++; };
            Action<object> callback2 = _ => { pattern2TriggerCount++; };

            var provider = new PhysicalFileProvider(root);
            var trigger1 = provider.Watch(pattern1);
            trigger1.RegisterExpirationCallback(callback1, null);
            var trigger2 = provider.Watch(pattern2);
            trigger2.RegisterExpirationCallback(callback2, null);

            File.WriteAllText(Path.Combine(root, fileName + ".cshtml"), "Content");

            await Task.Delay(WAIT_TIME_FOR_TRIGGER_TO_FIRE);
            pattern1TriggerCount.ShouldBe(1);
            pattern2TriggerCount.ShouldBe(1);

            trigger1 = provider.Watch(pattern1);
            trigger1.RegisterExpirationCallback(callback1, null);
            trigger2 = provider.Watch(pattern2);
            trigger2.RegisterExpirationCallback(callback2, null);
            File.WriteAllText(Path.Combine(subFolder, fileName + ".txt"), "Content");

            await Task.Delay(WAIT_TIME_FOR_TRIGGER_TO_FIRE);
            pattern1TriggerCount.ShouldBe(2);
            pattern2TriggerCount.ShouldBe(1);

            Directory.Delete(subFolder, true);
            File.Delete(Path.Combine(root, fileName + ".cshtml"));
        }
コード例 #28
0
        public async Task Tokens_NotFired_For_Hidden_And_System_Files()
        {
            var root = Path.GetTempPath();
            var hiddenFileName = Path.Combine(root, Guid.NewGuid().ToString());
            File.WriteAllText(hiddenFileName, "Content");
            var systemFileName = Path.Combine(root, Guid.NewGuid().ToString());
            File.WriteAllText(systemFileName, "Content");
            var fileInfo = new FileInfo(hiddenFileName);
            File.SetAttributes(hiddenFileName, fileInfo.Attributes | FileAttributes.Hidden);
            fileInfo = new FileInfo(systemFileName);
            File.SetAttributes(systemFileName, fileInfo.Attributes | FileAttributes.System);

            var provider = new PhysicalFileProvider(Path.GetTempPath());
            var hiddenFiletoken = provider.Watch(Path.GetFileName(hiddenFileName));
            var systemFiletoken = provider.Watch(Path.GetFileName(systemFileName));

            Assert.False(hiddenFiletoken.HasChanged);
            Assert.False(systemFiletoken.HasChanged);

            File.AppendAllText(hiddenFileName, "Appending text");
            File.AppendAllText(systemFileName, "Appending text");

            // Wait for tokens to fire.
            await Task.Delay(WaitTimeForTokenToFire);

            Assert.False(hiddenFiletoken.HasChanged);
            Assert.False(systemFiletoken.HasChanged);
        }
コード例 #29
0
        public void Triggers_With_Forward_And_Backward_Slash()
        {
            var provider = new PhysicalFileProvider(Path.GetTempPath());
            var trigger1 = provider.Watch("/a/b");
            var trigger2 = provider.Watch("a/b");
            var trigger3 = provider.Watch(@"a\b");

            trigger1.ShouldBe(trigger2);
            trigger2.ShouldBe(trigger3);

            trigger1.ActiveExpirationCallbacks.ShouldBe(true);
            trigger2.ActiveExpirationCallbacks.ShouldBe(true);
            trigger3.ActiveExpirationCallbacks.ShouldBe(true);

            trigger1.IsExpired.ShouldBe(false);
            trigger2.IsExpired.ShouldBe(false);
            trigger3.IsExpired.ShouldBe(false);
        }
コード例 #30
0
        public async Task ModifyContent_And_Delete_File_Succeeds_And_Callsback_RegisteredTokens()
        {
            var fileName     = Guid.NewGuid().ToString();
            var fileLocation = Path.Combine(Path.GetTempPath(), fileName);

            File.WriteAllText(fileLocation, "OldContent");
            var provider = new PhysicalFileProvider(Path.GetTempPath());
            var fileInfo = provider.GetFileInfo(fileName);

            Assert.Equal(new FileInfo(fileInfo.PhysicalPath).Length, fileInfo.Length);
            Assert.True(fileInfo.Exists);

            var token1 = provider.Watch(fileName);
            var token2 = provider.Watch(fileName);

            // Valid token1 created.
            Assert.NotNull(token1);
            Assert.False(token1.HasChanged);
            Assert.True(token1.ActiveChangeCallbacks);

            // Valid token2 created.
            Assert.NotNull(token2);
            Assert.False(token2.HasChanged);
            Assert.True(token2.ActiveChangeCallbacks);

            // token is the same for a specific file.
            Assert.Equal(token2, token1);

            IChangeToken token3 = null;
            IChangeToken token4 = null;

            token1.RegisterChangeCallback(state =>
            {
                var infoFromState = state as IFileInfo;
                token3            = provider.Watch(infoFromState.Name);
                Assert.NotNull(token3);
                token3.RegisterChangeCallback(_ => { }, null);
                Assert.False(token3.HasChanged);
            }, state: fileInfo);

            token2.RegisterChangeCallback(state =>
            {
                var infoFromState = state as IFileInfo;
                token4            = provider.Watch(infoFromState.Name);
                Assert.NotNull(token4);
                token4.RegisterChangeCallback(_ => { }, null);
                Assert.False(token4.HasChanged);
            }, state: fileInfo);

            // Write new content.
            File.WriteAllText(fileLocation, "OldContent + NewContent");
            Assert.True(fileInfo.Exists);
            // Wait for callbacks to be fired.
            await Task.Delay(WaitTimeForTokenToFire);

            Assert.True(token1.HasChanged);
            Assert.True(token2.HasChanged);

            // token is the same for a specific file.
            Assert.Same(token4, token3);
            // A new token is created.
            Assert.NotEqual(token1, token3);

            // Delete the file and verify file info is updated.
            File.Delete(fileLocation);
            fileInfo = provider.GetFileInfo(fileName);
            Assert.False(fileInfo.Exists);
            Assert.False(new FileInfo(fileLocation).Exists);

            // Wait for callbacks to be fired.
            await Task.Delay(WaitTimeForTokenToFire);

            Assert.True(token3.HasChanged);
            Assert.True(token4.HasChanged);
        }
コード例 #31
0
        public async Task Triggers_NotFired_For_FileNames_Starting_With_Period_And_Hidden_Files()
        {
            var root = Path.GetTempPath();
            var hiddenFileName = Path.Combine(root, Guid.NewGuid().ToString());
            File.WriteAllText(hiddenFileName, "Content");
            var systemFileName = Path.Combine(root, Guid.NewGuid().ToString());
            File.WriteAllText(systemFileName, "Content");
            var fileNameStartingWithPeriod = Path.Combine(root, "." + Guid.NewGuid().ToString());
            File.WriteAllText(fileNameStartingWithPeriod, "Content");
            var fileInfo = new FileInfo(hiddenFileName);
            File.SetAttributes(hiddenFileName, fileInfo.Attributes | FileAttributes.Hidden);
            fileInfo = new FileInfo(systemFileName);
            File.SetAttributes(systemFileName, fileInfo.Attributes | FileAttributes.System);

            var provider = new PhysicalFileProvider(Path.GetTempPath());
            var hiddenFileTrigger = provider.Watch(Path.GetFileName(hiddenFileName));
            var triggerFileNameStartingPeriod = provider.Watch(Path.GetFileName(fileNameStartingWithPeriod));
            var systemFileTrigger = provider.Watch(Path.GetFileName(systemFileName));

            hiddenFileTrigger.IsExpired.ShouldBe(false);
            triggerFileNameStartingPeriod.IsExpired.ShouldBe(false);
            systemFileTrigger.IsExpired.ShouldBe(false);

            File.AppendAllText(hiddenFileName, "Appending text");
            File.WriteAllText(fileNameStartingWithPeriod, "Updated Contents");
            File.AppendAllText(systemFileName, "Appending text");

            // Wait for triggers to fire.
            await Task.Delay(WAIT_TIME_FOR_TRIGGER_TO_FIRE);

            hiddenFileTrigger.IsExpired.ShouldBe(false);
            triggerFileNameStartingPeriod.IsExpired.ShouldBe(false);
            systemFileTrigger.IsExpired.ShouldBe(false);
        }
コード例 #32
0
        public async Task ModifyContent_And_Delete_File_Succeeds_And_Callsback_Registered_Triggers()
        {
            var fileName     = Guid.NewGuid().ToString();
            var fileLocation = Path.Combine(Path.GetTempPath(), fileName);

            File.WriteAllText(fileLocation, "OldContent");
            var provider = new PhysicalFileProvider(Path.GetTempPath());
            var fileInfo = provider.GetFileInfo(fileName);

            Assert.Equal(new FileInfo(fileInfo.PhysicalPath).Length, fileInfo.Length);
            Assert.True(fileInfo.Exists);

            IExpirationTrigger trigger3 = null, trigger4 = null;
            var trigger1 = provider.Watch(fileName);
            var trigger2 = provider.Watch(fileName);

            // Valid trigger1 created.
            Assert.NotNull(trigger1);
            Assert.False(trigger1.IsExpired);
            Assert.True(trigger1.ActiveExpirationCallbacks);

            // Valid trigger2 created.
            Assert.NotNull(trigger2);
            Assert.False(trigger2.IsExpired);
            Assert.True(trigger2.ActiveExpirationCallbacks);

            // Trigger is the same for a specific file.
            Assert.Equal(trigger2, trigger1);

            trigger1.RegisterExpirationCallback(state =>
            {
                var infoFromState = state as IFileInfo;
                trigger3          = provider.Watch(infoFromState.Name);
                Assert.NotNull(trigger3);
                trigger3.RegisterExpirationCallback(_ => { }, null);
                Assert.False(trigger3.IsExpired);
            }, state: fileInfo);

            trigger2.RegisterExpirationCallback(state =>
            {
                var infoFromState = state as IFileInfo;
                trigger4          = provider.Watch(infoFromState.Name);
                Assert.NotNull(trigger4);
                trigger4.RegisterExpirationCallback(_ => { }, null);
                Assert.False(trigger4.IsExpired);
            }, state: fileInfo);

            // Write new content.
            File.WriteAllText(fileLocation, "OldContent + NewContent");
            Assert.True(fileInfo.Exists);
            // Wait for callbacks to be fired.
            await Task.Delay(WAIT_TIME_FOR_TRIGGER_TO_FIRE);

            Assert.True(trigger1.IsExpired);
            Assert.True(trigger2.IsExpired);

            // Trigger is the same for a specific file.
            Assert.Equal(trigger4, trigger3);
            // A new trigger is created.
            Assert.NotEqual(trigger1, trigger3);

            // Delete the file and verify file info is updated.
            File.Delete(fileLocation);
            fileInfo = provider.GetFileInfo(fileName);
            Assert.False(fileInfo.Exists);
            Assert.False(new FileInfo(fileLocation).Exists);

            // Wait for callbacks to be fired.
            await Task.Delay(WAIT_TIME_FOR_TRIGGER_TO_FIRE);

            Assert.True(trigger3.IsExpired);
            Assert.True(trigger4.IsExpired);
        }