1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194
|
require "tmpdir"
require "fileutils"
require "timeout"
require "active_support/core_ext/numeric/time"
module Spring
module Test
class WatcherTest < ActiveSupport::TestCase
runnables.delete self # prevent Minitest running this class
LATENCY = 0.001
TIMEOUT = 1
attr_accessor :dir
def watcher_class
raise NotImplementedError
end
def watcher
@watcher ||= watcher_class.new(dir, LATENCY)
end
def setup
@dir = File.realpath(Dir.mktmpdir)
end
def teardown
FileUtils.remove_entry_secure @dir
watcher.stop
end
def touch(file, mtime = nil)
options = {}
options[:mtime] = mtime if mtime
FileUtils.touch(file, **options)
end
def assert_stale
timeout = Time.now + TIMEOUT
sleep LATENCY until watcher.stale? || Time.now > timeout
assert watcher.stale?
end
def assert_not_stale
sleep LATENCY * 10
assert !watcher.stale?
end
test "starting with no file" do
file = "#{@dir}/omg"
touch file, Time.now - 2.seconds
watcher.start
watcher.add file
assert_not_stale
touch file, Time.now
assert_stale
end
test "is stale when a watched file is updated" do
file = "#{@dir}/omg"
touch file, Time.now - 2.seconds
watcher.add file
watcher.start
assert_not_stale
touch file, Time.now
assert_stale
end
test "is stale when removing files" do
file = "#{@dir}/omg"
touch file, Time.now
watcher.add file
watcher.start
assert_not_stale
FileUtils.rm(file)
assert_stale
end
test "is stale when files are added to a watched directory" do
subdir = "#{@dir}/subdir"
FileUtils.mkdir(subdir)
watcher.add subdir
watcher.start
assert_not_stale
touch "#{subdir}/foo", Time.now - 1.minute
assert_stale
end
test "is stale when a file is changed in a watched directory" do
subdir = "#{@dir}/subdir"
FileUtils.mkdir(subdir)
touch "#{subdir}/foo", Time.now - 1.minute
watcher.add subdir
watcher.start
assert_not_stale
touch "#{subdir}/foo", Time.now
assert_stale
end
test "adding doesn't wipe stale state" do
file = "#{@dir}/omg"
file2 = "#{@dir}/foo"
touch file, Time.now - 2.seconds
touch file2, Time.now - 2.seconds
watcher.add file
watcher.start
assert_not_stale
touch file, Time.now
watcher.add file2
assert_stale
end
test "on stale" do
file = "#{@dir}/omg"
touch file, Time.now - 2.seconds
stale = false
watcher.on_stale { stale = true }
watcher.add file
watcher.start
touch file, Time.now
Timeout.timeout(1) { sleep 0.01 until stale }
assert stale
# Check that we only get notified once
stale = false
sleep LATENCY * 3
assert !stale
end
test "add relative path" do
File.write("#{dir}/foo", "foo")
watcher.add "foo"
assert_equal ["#{dir}/foo"], watcher.files.to_a
end
test "add dot relative path" do
File.write("#{dir}/foo", "foo")
watcher.add "./foo"
assert_equal ["#{dir}/foo"], watcher.files.to_a
end
test "add non existent file" do
watcher.add './foobar'
assert watcher.files.empty?
end
test "add symlink" do
File.write("#{dir}/bar", "bar")
File.symlink("#{dir}/bar", "#{dir}/foo")
watcher.add './foo'
assert_equal ["#{dir}/bar"], watcher.files.to_a
end
test "add dangling symlink" do
File.symlink("#{dir}/bar", "#{dir}/foo")
watcher.add './foo'
assert watcher.files.empty?
end
test "add directory with dangling symlink" do
subdir = "#{@dir}/subdir"
FileUtils.mkdir(subdir)
File.symlink("dangling", "#{subdir}/foo")
watcher.add subdir
assert_not_stale
# Adding a new file should mark as stale despite the dangling symlink.
File.write("#{subdir}/new-file", "new")
watcher.check_stale
assert_stale
end
end
end
end
|