From 89e6b193564075c89b1e0fc24b8184240ea6d324 Mon Sep 17 00:00:00 2001 From: wycats Date: Sun, 20 Feb 2011 01:10:34 -0800 Subject: [PATCH] Add tests for an FSSM backend for the file system watcher using the FSSM polling support. --- Gemfile | 1 + activesupport/test/file_watcher_test.rb | 153 ++++++++++++++++++++++++ 2 files changed, 154 insertions(+) diff --git a/Gemfile b/Gemfile index 08399c2d27..7d8949409c 100644 --- a/Gemfile +++ b/Gemfile @@ -22,6 +22,7 @@ end # AS gem "memcache-client", ">= 1.8.5" +gem "fssm", "~> 0.2.5" platforms :mri_18 do gem "system_timer" diff --git a/activesupport/test/file_watcher_test.rb b/activesupport/test/file_watcher_test.rb index 3e577df5af..1394c66d9f 100644 --- a/activesupport/test/file_watcher_test.rb +++ b/activesupport/test/file_watcher_test.rb @@ -1,4 +1,7 @@ require 'abstract_unit' +require 'fssm' +require "fileutils" + class FileWatcherTest < ActiveSupport::TestCase class DumbBackend < ActiveSupport::FileWatcher::Backend @@ -73,3 +76,153 @@ class FileWatcherTest < ActiveSupport::TestCase assert_equal [:changed => ["app/assets/main.scss", "app/assets/print.scss"]], @payload end end + +module FSSM::Backends + class Polling + def initialize(options={}) + @handlers = [] + @latency = options[:latency] || 0.1 + end + + def add_handler(handler, preload=true) + handler.refresh(nil, true) if preload + @handlers << handler + end + + def run + begin + loop do + start = Time.now.to_f + @handlers.each { |handler| handler.refresh } + nap_time = @latency - (Time.now.to_f - start) + sleep nap_time if nap_time > 0 + end + rescue Interrupt + end + end + end +end + +class FSSMFileWatcherTest < ActiveSupport::TestCase + class FSSMBackend < ActiveSupport::FileWatcher::Backend + def initialize(path, watcher) + super + + monitor = FSSM::Monitor.new + monitor.path(path, '**/*') do |monitor| + monitor.update { |base, relative| trigger relative => :changed } + monitor.delete { |base, relative| trigger relative => :deleted } + monitor.create { |base, relative| trigger relative => :created } + end + + @thread = Thread.new do + monitor.run + end + end + + def stop + @thread.kill + end + end + + def setup + Thread.abort_on_exception = true + + @watcher = ActiveSupport::FileWatcher.new + + @path = path = File.expand_path("../tmp", __FILE__) + FileUtils.rm_rf path + + create "app/assets/main.scss", true + create "app/assets/javascripts/foo.coffee", true + create "app/assets/print.scss", true + create "app/assets/videos.scss", true + + @backend = FSSMBackend.new(path, @watcher) + + @payload = [] + + @watcher.watch %r{^app/assets/.*\.scss$} do |pay| + pay.each do |status, files| + files.sort! + end + @payload << pay + end + end + + def teardown + @backend.stop + Thread.abort_on_exception = false + end + + def create(path, past = false) + path = File.join(@path, path) + FileUtils.mkdir_p(File.dirname(path)) + + FileUtils.touch(path) + File.utime(Time.now - 100, Time.now - 100, path) if past + sleep 0.1 unless past + end + + def change(path) + FileUtils.touch(File.join(@path, path)) + sleep 0.1 + end + + def delete(path) + FileUtils.rm(File.join(@path, path)) + sleep 0.1 + end + + def test_one_change + change "app/assets/main.scss" + assert_equal({:changed => ["app/assets/main.scss"]}, @payload.first) + end + + def test_multiple_changes + change "app/assets/main.scss" + change "app/assets/javascripts/foo.coffee" + assert_equal([{:changed => ["app/assets/main.scss"]}], @payload) + end + + def test_multiple_changes_match + change "app/assets/main.scss" + change "app/assets/print.scss" + change "app/assets/javascripts/foo.coffee" + assert_equal([{:changed => ["app/assets/main.scss"]}, {:changed => ["app/assets/print.scss"]}], @payload) + end + + def test_multiple_state_changes + create "app/assets/new.scss" + change "app/assets/print.scss" + delete "app/assets/videos.scss" + assert_equal([{:created => ["app/assets/new.scss"]}, {:changed => ["app/assets/print.scss"]}, {:deleted => ["app/assets/videos.scss"]}], @payload) + end + + def test_delete + + end + + def test_more_blocks + payload = [] + @watcher.watch %r{^config/routes\.rb$} do |pay| + payload << pay + end + + create "config/routes.rb" + assert_equal [{:created => ["config/routes.rb"]}], payload + assert_equal [], @payload + end + + def test_overlapping_watchers + payload = [] + @watcher.watch %r{^app/assets/main\.scss$} do |pay| + payload << pay + end + + change "app/assets/main.scss" + change "app/assets/print.scss" + assert_equal [{:changed => ["app/assets/main.scss"]}], payload + assert_equal [{:changed => ["app/assets/main.scss"]}, {:changed => ["app/assets/print.scss"]}], @payload + end +end