diff --git a/.gitignore b/.gitignore index 144394f..57a1d0d 100644 --- a/.gitignore +++ b/.gitignore @@ -1,3 +1,3 @@ *.sw? pkg - +Gemfile.lock diff --git a/.rspec b/.rspec new file mode 100644 index 0000000..5052887 --- /dev/null +++ b/.rspec @@ -0,0 +1 @@ +--color \ No newline at end of file diff --git a/CONTRIBUTORS b/CONTRIBUTORS index 17ea9bc..3a342a2 100644 --- a/CONTRIBUTORS +++ b/CONTRIBUTORS @@ -4,24 +4,32 @@ Chris Wanstrath Myles Eftos Jeff Hodges Matt Freels +Eero Saynatkari Víctor Martínez Nick Quaranto Aaron Suggs Victor Costan +Eric MSP Veith Jon Yurek +Jared Luxenberg +Lars Gierth Greg Campbell Ben Mabey Mark Sam Goldstein +Ryan McGeary +Noah Paessel dmathieu <42@dmathieu.com> -Lars Gierth +Mariusz Pietrzyk marano jameswilding -Scott Barron Tymon Tobolski -Mariusz Pietrzyk +Scott Barron +Andrius Chamentauskas Keita Urashima David Reese msassak +Andrius Chamentauskas +timo3377 Mislav Marohnić Rob Sanheim diff --git a/Gemfile b/Gemfile new file mode 100644 index 0000000..35f6baa --- /dev/null +++ b/Gemfile @@ -0,0 +1,8 @@ +source :rubygems + +group :development do + gem 'rspec' + gem 'jeweler' + gem 'sdoc-helpers' + gem 'rdiscount' +end \ No newline at end of file diff --git a/README.markdown b/README.markdown index 33708af..938130f 100644 --- a/README.markdown +++ b/README.markdown @@ -47,6 +47,13 @@ Don't Fake the FS Immediately # your code end +Rails +----- + +If you are using fakefs in a rails project with bundler, you'll probably want to specify the following in your Gemfile: + + gem "fakefs", :require => "fakefs/safe" + RSpec ----- @@ -121,3 +128,10 @@ Meta [0]: http://help.github.com/forking/ [1]: http://github.com/defunkt/fakefs/issues + +Releasing +--------- + +1. Update version in lib/fakefs/version.rb +2. Commit it +3. rake publish \ No newline at end of file diff --git a/Rakefile b/Rakefile index 253d4af..353ebce 100644 --- a/Rakefile +++ b/Rakefile @@ -8,16 +8,9 @@ end task :default => [:test, :spec] -begin - require 'spec/rake/spectask' - - desc "Run specs" - Spec::Rake::SpecTask.new(:spec) do |t| - t.spec_files = FileList["spec/**/*.rb"] - end -rescue LoadError - puts "Spec task can't be loaded. `gem install rspec`" -end +require 'rspec/core/rake_task' +desc "Run specs" +RSpec::Core::RakeTask.new begin require 'jeweler' diff --git a/fakefs.gemspec b/fakefs.gemspec index 9573c5a..f2ab64a 100644 --- a/fakefs.gemspec +++ b/fakefs.gemspec @@ -1,86 +1,83 @@ # Generated by jeweler # DO NOT EDIT THIS FILE DIRECTLY -# Instead, edit Jeweler::Tasks in Rakefile, and run the gemspec command +# Instead, edit Jeweler::Tasks in Rakefile, and run 'rake gemspec' # -*- encoding: utf-8 -*- Gem::Specification.new do |s| s.name = %q{fakefs} - s.version = "0.3.1" + s.version = "0.4.0" s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version= s.authors = ["Chris Wanstrath", "Scott Taylor", "Jeff Hodges", "Pat Nakajima"] - s.date = %q{2010-12-18} + s.date = %q{2011-09-05} s.description = %q{A fake filesystem. Use it in your tests.} s.email = %q{chris@ozmm.org} s.extra_rdoc_files = [ "LICENSE", - "README.markdown" + "README.markdown" ] s.files = [ ".autotest", - ".gitignore", - "CONTRIBUTORS", - "LICENSE", - "README.markdown", - "Rakefile", - "fakefs.gemspec", - "lib/fakefs.rb", - "lib/fakefs/base.rb", - "lib/fakefs/dir.rb", - "lib/fakefs/fake/dir.rb", - "lib/fakefs/fake/file.rb", - "lib/fakefs/fake/symlink.rb", - "lib/fakefs/file.rb", - "lib/fakefs/file_system.rb", - "lib/fakefs/file_test.rb", - "lib/fakefs/fileutils.rb", - "lib/fakefs/safe.rb", - "lib/fakefs/spec_helpers.rb", - "lib/fakefs/version.rb", - "spec/fakefs/spec_helpers_spec.rb", - "spec/spec.opts", - "spec/spec_helper.rb", - "test/fake/file/lstat_test.rb", - "test/fake/file/stat_test.rb", - "test/fake/file/sysseek_test.rb", - "test/fake/file/syswrite_test.rb", - "test/fake/file_test.rb", - "test/fake/symlink_test.rb", - "test/fakefs_test.rb", - "test/file/stat_test.rb", - "test/safe_test.rb", - "test/test_helper.rb", - "test/verify.rb" + ".rspec", + "CONTRIBUTORS", + "Gemfile", + "LICENSE", + "README.markdown", + "Rakefile", + "fakefs.gemspec", + "lib/fakefs.rb", + "lib/fakefs/base.rb", + "lib/fakefs/dir.rb", + "lib/fakefs/fake/dir.rb", + "lib/fakefs/fake/file.rb", + "lib/fakefs/fake/symlink.rb", + "lib/fakefs/file.rb", + "lib/fakefs/file_system.rb", + "lib/fakefs/file_test.rb", + "lib/fakefs/fileutils.rb", + "lib/fakefs/safe.rb", + "lib/fakefs/spec_helpers.rb", + "lib/fakefs/version.rb", + "spec/fakefs/spec_helpers_spec.rb", + "spec/spec.opts", + "spec/spec_helper.rb", + "test/fake/file/join_test.rb", + "test/fake/file/lstat_test.rb", + "test/fake/file/stat_test.rb", + "test/fake/file/sysseek_test.rb", + "test/fake/file/syswrite_test.rb", + "test/fake/file_test.rb", + "test/fake/symlink_test.rb", + "test/fakefs_test.rb", + "test/file/stat_test.rb", + "test/safe_test.rb", + "test/test_helper.rb", + "test/verify.rb" ] s.homepage = %q{http://github.com/defunkt/fakefs} - s.rdoc_options = ["--charset=UTF-8"] s.require_paths = ["lib"] - s.rubygems_version = %q{1.3.7} + s.rubygems_version = %q{1.6.2} s.summary = %q{A fake filesystem. Use it in your tests.} - s.test_files = [ - "spec/fakefs/spec_helpers_spec.rb", - "spec/spec_helper.rb", - "test/fake/file/lstat_test.rb", - "test/fake/file/stat_test.rb", - "test/fake/file/sysseek_test.rb", - "test/fake/file/syswrite_test.rb", - "test/fake/file_test.rb", - "test/fake/symlink_test.rb", - "test/fakefs_test.rb", - "test/file/stat_test.rb", - "test/safe_test.rb", - "test/test_helper.rb", - "test/verify.rb" - ] if s.respond_to? :specification_version then - current_version = Gem::Specification::CURRENT_SPECIFICATION_VERSION s.specification_version = 3 if Gem::Version.new(Gem::VERSION) >= Gem::Version.new('1.2.0') then + s.add_development_dependency(%q, [">= 0"]) + s.add_development_dependency(%q, [">= 0"]) + s.add_development_dependency(%q, [">= 0"]) + s.add_development_dependency(%q, [">= 0"]) else + s.add_dependency(%q, [">= 0"]) + s.add_dependency(%q, [">= 0"]) + s.add_dependency(%q, [">= 0"]) + s.add_dependency(%q, [">= 0"]) end else + s.add_dependency(%q, [">= 0"]) + s.add_dependency(%q, [">= 0"]) + s.add_dependency(%q, [">= 0"]) + s.add_dependency(%q, [">= 0"]) end end diff --git a/lib/fakefs/dir.rb b/lib/fakefs/dir.rb index 32c5234..fbfea32 100644 --- a/lib/fakefs/dir.rb +++ b/lib/fakefs/dir.rb @@ -2,8 +2,13 @@ module FakeFS class Dir include Enumerable + def self._check_for_valid_file(path) + raise Errno::ENOENT, "No such file or directory - #{path}" unless FileSystem.find(path) + end + def initialize(string) - raise Errno::ENOENT, string unless FileSystem.find(string) + self.class._check_for_valid_file(string) + @path = string @open = true @pointer = 0 @@ -52,8 +57,12 @@ module FakeFS @contents[integer] end - def self.[](pattern) - glob(pattern) + def self.[](*pattern) + glob pattern + end + + def self.exists?(path) + File.exists?(path) && File.directory?(path) end def self.chdir(dir, &blk) @@ -61,16 +70,19 @@ module FakeFS end def self.chroot(string) - # Not implemented yet + raise NotImplementedError end def self.delete(string) - raise SystemCallError, "No such file or directory - #{string}" unless FileSystem.find(string).values.empty? + _check_for_valid_file(string) + raise Errno::ENOTEMPTY, "Directory not empty - #{string}" unless FileSystem.find(string).values.empty? + FileSystem.delete(string) end def self.entries(dirname) - raise SystemCallError, dirname unless FileSystem.find(dirname) + _check_for_valid_file(dirname) + Dir.new(dirname).map { |file| File.basename(file) } end @@ -79,15 +91,25 @@ module FakeFS end def self.glob(pattern, &block) - files = [FileSystem.find(pattern) || []].flatten.map(&:to_s).sort - block_given? ? files.each { |file| block.call(file) } : files + matches_for_pattern = lambda { |matcher| [FileSystem.find(matcher) || []].flatten.map{|e| e.to_s}.sort } + + if pattern.is_a? Array + files = pattern.collect { |matcher| matches_for_pattern.call matcher }.flatten + else + files = matches_for_pattern.call pattern + end + return block_given? ? files.each { |file| block.call(file) } : files end def self.mkdir(string, integer = 0) parent = string.split('/') parent.pop - raise Errno::ENOENT, "No such file or directory - #{string}" unless parent.join == "" || FileSystem.find(parent.join('/')) + + joined_parent_path = parent.join + + _check_for_valid_file(joined_parent_path) unless joined_parent_path == "" raise Errno::EEXIST, "File exists - #{string}" if File.exists?(string) + FileUtils.mkdir_p(string) end @@ -107,6 +129,52 @@ module FakeFS FileSystem.current_dir.to_s end + # This code has been borrowed from Rubinius + def self.mktmpdir(prefix_suffix = nil, tmpdir = nil) + case prefix_suffix + when nil + prefix = "d" + suffix = "" + when String + prefix = prefix_suffix + suffix = "" + when Array + prefix = prefix_suffix[0] + suffix = prefix_suffix[1] + else + raise ArgumentError, "unexpected prefix_suffix: #{prefix_suffix.inspect}" + end + + t = Time.now.strftime("%Y%m%d") + n = nil + + begin + path = "#{tmpdir}/#{prefix}#{t}-#{$$}-#{rand(0x100000000).to_s(36)}" + path << "-#{n}" if n + path << suffix + mkdir(path, 0700) + rescue Errno::EEXIST + n ||= 0 + n += 1 + retry + end + + if block_given? + begin + yield path + ensure + require 'fileutils' + # This here was using FileUtils.remove_entry_secure instead of just + # .rm_r. However, the security concerns that apply to + # .rm_r/.remove_entry_secure shouldn't apply to a test fake + # filesystem. :^) + FileUtils.rm_r path + end + else + path + end + end + class << self alias_method :getwd, :pwd alias_method :rmdir, :delete diff --git a/lib/fakefs/fake/dir.rb b/lib/fakefs/fake/dir.rb index f72ea4f..068a427 100644 --- a/lib/fakefs/fake/dir.rb +++ b/lib/fakefs/fake/dir.rb @@ -1,13 +1,14 @@ module FakeFS class FakeDir < Hash attr_accessor :name, :parent - attr_reader :ctime, :mtime + attr_reader :ctime, :mtime, :atime def initialize(name = nil, parent = nil) @name = name @parent = parent @ctime = Time.now @mtime = @ctime + @atime = @ctime end def entry diff --git a/lib/fakefs/fake/file.rb b/lib/fakefs/fake/file.rb index ec5086f..10bdf7f 100644 --- a/lib/fakefs/fake/file.rb +++ b/lib/fakefs/fake/file.rb @@ -1,6 +1,6 @@ module FakeFS class FakeFile - attr_accessor :name, :parent, :content, :mtime + attr_accessor :name, :parent, :content, :mtime, :atime attr_reader :ctime class Inode @@ -34,6 +34,7 @@ module FakeFS @inode = Inode.new(self) @ctime = Time.now @mtime = @ctime + @atime = @ctime end attr_accessor :inode diff --git a/lib/fakefs/fake/symlink.rb b/lib/fakefs/fake/symlink.rb index 5132542..132eead 100644 --- a/lib/fakefs/fake/symlink.rb +++ b/lib/fakefs/fake/symlink.rb @@ -1,7 +1,6 @@ module FakeFS class FakeSymlink - attr_accessor :name, :target - alias_method :to_s, :name + attr_accessor :name, :target, :parent def initialize(target) @target = target @@ -19,6 +18,10 @@ module FakeFS parent.delete(self) end + def to_s + File.join(parent.to_s, name) + end + def respond_to?(method) entry.respond_to?(method) end diff --git a/lib/fakefs/file.rb b/lib/fakefs/file.rb index 0fe0c8c..b6289fc 100644 --- a/lib/fakefs/file.rb +++ b/lib/fakefs/file.rb @@ -37,7 +37,12 @@ module FakeFS end def self.exist?(path) - !!FileSystem.find(path) + if(File.symlink?(path)) then + referent = File.expand_path(File.readlink(path), File.dirname(path)) + exist?(referent) + else + !!FileSystem.find(path) + end end class << self @@ -64,9 +69,18 @@ module FakeFS end end + def self.atime(path) + if exists?(path) + FileSystem.find(path).atime + else + raise Errno::ENOENT + end + end + def self.utime(atime, mtime, *paths) paths.each do |path| if exists?(path) + FileSystem.find(path).atime = atime FileSystem.find(path).mtime = mtime else raise Errno::ENOENT @@ -132,12 +146,13 @@ module FakeFS def self.readlink(path) symlink = FileSystem.find(path) - FileSystem.find(symlink.target).to_s + symlink.target end def self.read(path) file = new(path) if file.exists? + FileSystem.find(path).atime = Time.now file.read else raise Errno::ENOENT @@ -220,7 +235,7 @@ module FakeFS end class Stat - attr_reader :ctime, :mtime + attr_reader :ctime, :mtime, :atime def initialize(file, __lstat = false) if !File.exists?(file) @@ -232,6 +247,7 @@ module FakeFS @__lstat = __lstat @ctime = @fake_file.ctime @mtime = @fake_file.mtime + @atime = @fake_file.atime end def symlink? @@ -321,7 +337,7 @@ module FakeFS end def atime - raise NotImplementedError + self.class.atime(@path) end def chmod(mode_int) @@ -358,7 +374,7 @@ module FakeFS end def to_path - raise NotImplementedError + @path end end @@ -398,8 +414,22 @@ module FakeFS (@mode & mask) != 0 if @mode.is_a?(Integer) end + # Create a missing file if the path is valid. + # def create_missing_file - if !File.exists?(@path) + raise Errno::EISDIR, "Is a directory - #{path}" if File.directory?(@path) + + if !File.exists?(@path) # Unnecessary check, probably. + dirname = RealFile.dirname @path + + unless dirname == "." + dir = FileSystem.find dirname + + unless dir.kind_of? FakeDir + raise Errno::ENOENT, "No such file or directory - #{path}" + end + end + @file = FileSystem.add(path, FakeFile.new) end end diff --git a/lib/fakefs/file_system.rb b/lib/fakefs/file_system.rb index 402b584..a5c8087 100644 --- a/lib/fakefs/file_system.rb +++ b/lib/fakefs/file_system.rb @@ -7,7 +7,7 @@ module FakeFS end def fs - @fs ||= FakeDir.new('.') + @fs ||= FakeDir.new('/') end def clear @@ -68,6 +68,7 @@ module FakeFS def delete(path) if node = FileSystem.find(path) node.delete + true end end @@ -121,10 +122,8 @@ module FakeFS directories_under(dir) end else - pattern = pattern.gsub('?','.').gsub('*', '.*') - pattern = pattern.gsub(%r{\{([^\}]+)\}}) { |all| "(#{$1.gsub(',', '|')})" } - - dir.reject {|k,v| /\A#{pattern}\Z/ !~ k }.values + regexp_pattern = /\A#{pattern.gsub('?','.').gsub('*', '.*').gsub(/\{(.*?)\}/) { "(#{$1.gsub(',', '|')})" }}\Z/ + dir.reject {|k,v| regexp_pattern !~ k }.values end if parts.empty? # we're done recursing diff --git a/lib/fakefs/file_test.rb b/lib/fakefs/file_test.rb index 6c9cee7..2f6a61d 100644 --- a/lib/fakefs/file_test.rb +++ b/lib/fakefs/file_test.rb @@ -3,5 +3,13 @@ module FakeFS def self.exist?(file_name) File.exist?(file_name) end + + def self.directory?(file_name) + File.directory?(file_name) + end + + def self.file?(file_name) + File.file?(file_name) + end end end diff --git a/lib/fakefs/fileutils.rb b/lib/fakefs/fileutils.rb index 4315feb..81ff2d7 100644 --- a/lib/fakefs/fileutils.rb +++ b/lib/fakefs/fileutils.rb @@ -6,6 +6,7 @@ module FakeFS FileSystem.add(path, FakeDir.new) end alias_method :mkpath, :mkdir_p + alias_method :makedirs, :mkdir_p def mkdir(path) parent = path.split('/') @@ -29,7 +30,7 @@ module FakeFS def rm(list, options = {}) Array(list).each do |path| - FileSystem.delete(path) + FileSystem.delete(path) or raise Errno::ENOENT.new(path) end end @@ -39,9 +40,17 @@ module FakeFS def ln_s(target, path, options = {}) options = { :force => false }.merge(options) - (FileSystem.find(path) and !options[:force]) ? raise(Errno::EEXIST, path) : FileSystem.delete(path) + (FileSystem.find(path) && !options[:force]) ? + raise(Errno::EEXIST, path) : + FileSystem.delete(path) + + if !options[:force] && !Dir.exists?(File.dirname(path)) + raise Errno::ENOENT, path + end + FileSystem.add(path, FakeSymlink.new(target)) end + def ln_sf(target, path) ln_s(target, path, { :force => true }) end @@ -101,7 +110,7 @@ module FakeFS FileSystem.add(dest_path, target.entry.clone) FileSystem.delete(path) else - raise Errno::ENOENT, src + raise Errno::ENOENT, path end end end diff --git a/lib/fakefs/version.rb b/lib/fakefs/version.rb index 61e9d52..aa0ad20 100644 --- a/lib/fakefs/version.rb +++ b/lib/fakefs/version.rb @@ -1,6 +1,6 @@ module FakeFS module Version - VERSION = "0.3.1" + VERSION = "0.4.0" def self.to_s VERSION diff --git a/test/fakefs_test.rb b/test/fakefs_test.rb index c6028df..67f111d 100644 --- a/test/fakefs_test.rb +++ b/test/fakefs_test.rb @@ -63,6 +63,22 @@ class FakeFSTest < Test::Unit::TestCase assert_kind_of FakeDir, FileSystem.fs['path']['to']['dir'] end + def test_can_create_directories_with_mkpath + FileUtils.makedirs("/path/to/dir") + assert_kind_of FakeDir, FileSystem.fs['path']['to']['dir'] + end + + def test_can_create_directories_with_mkpath_and_options + FileUtils.makedirs("/path/to/dir", :mode => 0755) + assert_kind_of FakeDir, FileSystem.fs['path']['to']['dir'] + end + + def test_unlink_errors_on_file_not_found + assert_raise Errno::ENOENT do + FileUtils.rm("/foo") + end + end + def test_can_delete_directories FileUtils.mkdir_p("/path/to/dir") FileUtils.rmdir("/path/to/dir") @@ -109,6 +125,11 @@ class FakeFSTest < Test::Unit::TestCase assert File.exists?(path) end + def test_symlink_with_missing_refferent_does_not_exist + File.symlink('/foo', '/bar') + assert !File.exists?('/bar') + end + def test_can_create_symlinks FileUtils.mkdir_p(target = "/path/to/target") FileUtils.ln_s(target, "/path/to/link") @@ -139,14 +160,63 @@ class FakeFSTest < Test::Unit::TestCase assert_equal target, File.readlink(link) end + def test_symlinks_in_different_directories + FileUtils.mkdir_p("/path/to/bar") + FileUtils.mkdir_p(target = "/path/to/foo/target") + + FileUtils.ln_s(target, link = "/path/to/bar/symlink") + assert_equal target, File.readlink(link) + end + + def test_symlink_with_relative_path_exists + FileUtils.touch("/file") + FileUtils.mkdir_p("/a/b") + FileUtils.ln_s("../../file", link = "/a/b/symlink") + assert File.exist?('/a/b/symlink') + end + + def test_symlink_with_relative_path_and_nonexistant_file_does_not_exist + FileUtils.touch("/file") + FileUtils.mkdir_p("/a/b") + FileUtils.ln_s("../../file_foo", link = "/a/b/symlink") + assert !File.exist?('/a/b/symlink') + end + + def test_symlink_with_relative_path_has_correct_target + FileUtils.touch("/file") + FileUtils.mkdir_p("/a/b") + FileUtils.ln_s("../../file", link = "/a/b/symlink") + assert_equal "../../file", File.readlink(link) + end + + def test_symlinks_to_symlinks + FileUtils.mkdir_p(target = "/path/to/foo/target") + FileUtils.mkdir_p("/path/to/bar") + FileUtils.mkdir_p("/path/to/bar2") + + FileUtils.ln_s(target, link1 = "/path/to/bar/symlink") + FileUtils.ln_s(link1, link2 = "/path/to/bar2/symlink") + assert_equal link1, File.readlink(link2) + end + + def test_symlink_to_symlinks_should_raise_error_if_dir_doesnt_exist + FileUtils.mkdir_p(target = "/path/to/foo/target") + + assert !Dir.exists?("/path/to/bar") + + assert_raise Errno::ENOENT do + FileUtils.ln_s(target, "/path/to/bar/symlink") + end + end + def test_knows_symlinks_are_symlinks FileUtils.mkdir_p(target = "/path/to/target") FileUtils.ln_s(target, link = "/path/to/symlink") assert File.symlink?(link) end - def test_can_create_files - path = '/path/to/file.txt' + def test_can_create_files_in_current_dir + path = 'file.txt' File.open(path, 'w') do |f| f.write "Yatta!" end @@ -156,7 +226,74 @@ class FakeFSTest < Test::Unit::TestCase assert File.writable?(path) end + def test_can_create_files_in_existing_dir + FileUtils.mkdir_p "/path/to" + path = "/path/to/file.txt" + + File.open(path, 'w') do |f| + f.write "Yatta!" + end + + assert File.exists?(path) + assert File.readable?(path) + assert File.writable?(path) + end + + def test_raises_ENOENT_trying_to_create_files_in_nonexistent_dir + path = "/path/to/file.txt" + + assert_raises(Errno::ENOENT) { + File.open(path, 'w') do |f| + f.write "Yatta!" + end + } + end + + def test_raises_ENOENT_trying_to_create_files_in_relative_nonexistent_dir + FileUtils.mkdir_p "/some/path" + + Dir.chdir("/some/path") { + assert_raises(Errno::ENOENT) { + File.open("../foo") {|f| f.write "moo" } + } + } + end + + def test_raises_ENOENT_trying_to_create_files_in_obscured_nonexistent_dir + FileUtils.mkdir_p "/some/path" + + assert_raises(Errno::ENOENT) { + File.open("/some/path/../foo") {|f| f.write "moo" } + } + end + + def test_raises_ENOENT_trying_to_create_tilde_referenced_nonexistent_dir + path = "~/fakefs_test_#{$$}_0000" + + while File.exist? path + path = path.succ + end + + assert_raises(Errno::ENOENT) { + File.open("#{path}/foo") {|f| f.write "moo" } + } + end + + def test_raises_EISDIR_if_trying_to_open_existing_directory_name + path = "/path/to" + + FileUtils.mkdir_p path + + assert_raises(Errno::EISDIR) { + File.open(path, 'w') do |f| + f.write "Yatta!" + end + } + end + def test_can_create_files_with_bitmasks + FileUtils.mkdir_p("/path/to") + path = '/path/to/file.txt' File.open(path, File::RDWR | File::CREAT) do |f| f.write "Yatta!" @@ -275,7 +412,7 @@ class FakeFSTest < Test::Unit::TestCase end def test_can_read_files_once_written - path = '/path/to/file.txt' + path = 'file.txt' File.open(path, 'w') do |f| f.write "Yatta!" end @@ -284,7 +421,7 @@ class FakeFSTest < Test::Unit::TestCase end def test_can_write_to_files - path = '/path/to/file.txt' + path = 'file.txt' File.open(path, 'w') do |f| f << 'Yada Yada' end @@ -298,11 +435,12 @@ class FakeFSTest < Test::Unit::TestCase end def test_can_open_file_in_binary_mode - File.open("/foo", "wb") { |x| x << "a" } - assert_equal "a", File.read("/foo") + File.open("foo", "wb") { |x| x << "a" } + assert_equal "a", File.read("foo") end def test_can_chunk_io_when_reading + FileUtils.mkdir_p "/path/to" path = '/path/to/file.txt' File.open(path, 'w') do |f| f << 'Yada Yada' @@ -316,7 +454,7 @@ class FakeFSTest < Test::Unit::TestCase end def test_can_get_size_of_files - path = '/path/to/file.txt' + path = 'file.txt' File.open(path, 'w') do |f| f << 'Yada Yada' end @@ -324,20 +462,20 @@ class FakeFSTest < Test::Unit::TestCase end def test_can_check_if_file_has_size? - path = '/path/to/file.txt' + path = 'file.txt' File.open(path, 'w') do |f| f << 'Yada Yada' end assert File.size?(path) - assert_nil File.size?("/path/to/other.txt") + assert_nil File.size?("other.txt") end def test_can_check_size_of_empty_file - path = '/path/to/file.txt' + path = 'file.txt' File.open(path, 'w') do |f| f << '' end - assert_nil File.size?("/path/to/file.txt") + assert_nil File.size?("file.txt") end def test_raises_error_on_mtime_if_file_does_not_exist @@ -347,16 +485,16 @@ class FakeFSTest < Test::Unit::TestCase end def test_can_return_mtime_on_existing_file - path = '/path/to/file.txt' + path = 'file.txt' File.open(path, 'w') do |f| f << '' end - assert File.mtime('/path/to/file.txt').is_a?(Time) + assert File.mtime('file.txt').is_a?(Time) end def test_raises_error_on_ctime_if_file_does_not_exist assert_raise Errno::ENOENT do - File.ctime('/path/to/file.txt') + File.ctime('file.txt') end end @@ -365,27 +503,45 @@ class FakeFSTest < Test::Unit::TestCase assert File.ctime('foo').is_a?(Time) end - def test_ctime_and_mtime_are_equal_for_new_files + def test_raises_error_on_atime_if_file_does_not_exist + assert_raise Errno::ENOENT do + File.atime('file.txt') + end + end + + def test_can_return_atime_on_existing_file + File.open("foo", "w") { |f| f << "some content" } + assert File.atime('foo').is_a?(Time) + end + + def test_ctime_mtime_and_atime_are_equal_for_new_files File.open("foo", "w") { |f| f << "some content" } ctime = File.ctime("foo") mtime = File.mtime("foo") + atime = File.atime("foo") assert ctime.is_a?(Time) assert mtime.is_a?(Time) + assert atime.is_a?(Time) assert_equal ctime, mtime + assert_equal ctime, atime File.open("foo", "r") do |f| assert_equal ctime, f.ctime assert_equal mtime, f.mtime + assert_equal atime, f.atime end end - def test_ctime_and_mtime_are_equal_for_new_directories + def test_ctime_mtime_and_atime_are_equal_for_new_directories FileUtils.mkdir_p("foo") ctime = File.ctime("foo") mtime = File.mtime("foo") + atime = File.atime("foo") assert ctime.is_a?(Time) assert mtime.is_a?(Time) + assert atime.is_a?(Time) assert_equal ctime, mtime + assert_equal ctime, atime end def test_file_ctime_is_equal_to_file_stat_ctime @@ -408,6 +564,16 @@ class FakeFSTest < Test::Unit::TestCase assert_equal File.stat("foo").mtime, File.mtime("foo") end + def test_file_atime_is_equal_to_file_stat_atime + File.open("foo", "w") { |f| f << "some content" } + assert_equal File.stat("foo").atime, File.atime("foo") + end + + def test_directory_atime_is_equal_to_directory_stat_atime + FileUtils.mkdir_p("foo") + assert_equal File.stat("foo").atime, File.atime("foo") + end + def test_utime_raises_error_if_path_does_not_exist assert_raise Errno::ENOENT do File.utime(Time.now, Time.now, '/path/to/file.txt') @@ -416,16 +582,17 @@ class FakeFSTest < Test::Unit::TestCase def test_can_call_utime_on_an_existing_file time = Time.now - 300 # Not now - path = '/path/to/file.txt' + path = 'file.txt' File.open(path, 'w') do |f| f << '' end File.utime(time, time, path) - assert_equal time, File.mtime('/path/to/file.txt') + assert_equal time, File.mtime('file.txt') + assert_equal time, File.atime('file.txt') end def test_utime_returns_number_of_paths - path1, path2 = '/path/to/file.txt', '/path/to/another_file.txt' + path1, path2 = 'file.txt', 'another_file.txt' [path1, path2].each do |path| File.open(path, 'w') do |f| f << '' @@ -434,8 +601,23 @@ class FakeFSTest < Test::Unit::TestCase assert_equal 2, File.utime(Time.now, Time.now, path1, path2) end + def test_file_a_time_updated_when_file_is_read + old_atime = Time.now - 300 + + path = "file.txt" + File.open(path, "w") do |f| + f << "Hello" + end + + File.utime(old_atime, File.mtime(path), path) + + assert_equal File.atime(path), old_atime + File.read(path) + assert File.atime(path) != old_atime + end + def test_can_read_with_File_readlines - path = '/path/to/file.txt' + path = 'file.txt' File.open(path, 'w') do |f| f.puts "Yatta!", "Gatta!" f.puts ["woot","toot"] @@ -445,7 +627,7 @@ class FakeFSTest < Test::Unit::TestCase end def test_File_close_disallows_further_access - path = '/path/to/file.txt' + path = 'file.txt' file = File.open(path, 'w') file.write 'Yada' file.close @@ -455,7 +637,7 @@ class FakeFSTest < Test::Unit::TestCase end def test_File_close_disallows_further_writes - path = '/path/to/file.txt' + path = 'file.txt' file = File.open(path, 'w') file.write 'Yada' file.close @@ -465,7 +647,7 @@ class FakeFSTest < Test::Unit::TestCase end def test_can_read_from_file_objects - path = '/path/to/file.txt' + path = 'file.txt' File.open(path, 'w') do |f| f.write "Yatta!" end @@ -480,7 +662,7 @@ class FakeFSTest < Test::Unit::TestCase end def test_knows_files_are_files - path = '/path/to/file.txt' + path = 'file.txt' File.open(path, 'w') do |f| f.write "Yatta!" end @@ -489,17 +671,17 @@ class FakeFSTest < Test::Unit::TestCase end def test_File_io_returns_self - f = File.open("/foo", "w") + f = File.open("foo", "w") assert_equal f, f.to_io end def test_File_to_i_is_alias_for_filno - f = File.open("/foo", "w") + f = File.open("foo", "w") assert_equal f.method(:to_i), f.method(:fileno) end def test_knows_symlink_files_are_files - path = '/path/to/file.txt' + path = 'file.txt' File.open(path, 'w') do |f| f.write "Yatta!" end @@ -566,24 +748,29 @@ class FakeFSTest < Test::Unit::TestCase assert_equal ['/path', '/path/bar', '/path/bar/baz', '/path/bar2', '/path/bar2/baz', '/path/foo', '/path/foobar'], Dir['/**/*'] assert_equal ['/path/bar', '/path/bar/baz', '/path/bar2', '/path/bar2/baz', '/path/foo', '/path/foobar'], Dir['/path/**/*'] - assert_equal ['/path/bar/baz'], Dir['/path/bar/**/*'] - assert_equal ['/path/bar', '/path/foo'], Dir['/path/{foo,bar}'].sort + assert_equal ['/path/bar/baz', '/path/bar2/baz'], Dir['/path/bar/**/*', '/path/bar2/**/*'] + assert_equal ['/path/bar/baz', '/path/bar2/baz', '/path/bar/baz'], Dir['/path/ba*/**/*', '/path/bar/**/*'] FileUtils.cp_r '/path', '/otherpath' assert_equal %w( /otherpath/foo /otherpath/foobar /path/foo /path/foobar ), Dir['/*/foo*'] + + assert_equal ['/path/bar', '/path/foo'], Dir['/path/{foo,bar}'] + + assert_equal ['/path/bar', '/path/bar2'], Dir['/path/bar{2,}'] end def test_dir_glob_handles_root FileUtils.mkdir_p '/path' # this fails. the root dir should be named '/' but it is '.' - #assert_equal ['/'], Dir['/'] + assert_equal ['/'], Dir['/'] end def test_dir_glob_handles_recursive_globs + FileUtils.mkdir_p "/one/two/three" File.open('/one/two/three/four.rb', 'w') File.open('/one/five.rb', 'w') assert_equal ['/one/five.rb', '/one/two/three/four.rb'], Dir['/one/**/*.rb'] @@ -592,6 +779,7 @@ class FakeFSTest < Test::Unit::TestCase end def test_dir_recursive_glob_ending_in_wildcards_returns_both_files_and_dirs + FileUtils.mkdir_p "/one/two/three" File.open('/one/two/three/four.rb', 'w') File.open('/one/five.rb', 'w') assert_equal ['/one/five.rb', '/one/two', '/one/two/three', '/one/two/three/four.rb'], Dir['/one/**/*'] @@ -609,7 +797,7 @@ class FakeFSTest < Test::Unit::TestCase end def test_should_report_pos_as_0_when_opening - File.open("/foo", "w") do |f| + File.open("foo", "w") do |f| f << "foobar" f.rewind @@ -618,7 +806,7 @@ class FakeFSTest < Test::Unit::TestCase end def test_should_report_pos_as_1_when_seeking_one_char - File.open("/foo", "w") do |f| + File.open("foo", "w") do |f| f << "foobar" f.rewind @@ -629,22 +817,22 @@ class FakeFSTest < Test::Unit::TestCase end def test_should_set_pos - File.open("/foo", "w") do |f| + File.open("foo", "w") do |f| f << "foo" end - fp = File.open("/foo", "r") + fp = File.open("foo", "r") fp.pos = 1 assert_equal 1, fp.pos end def test_should_set_pos_with_tell_method - File.open("/foo", "w") do |f| + File.open("foo", "w") do |f| f << "foo" end - fp = File.open("/foo", "r") + fp = File.open("foo", "r") fp.tell = 1 assert_equal 1, fp.pos @@ -674,14 +862,14 @@ class FakeFSTest < Test::Unit::TestCase def test_chdir_changes_directories_like_a_boss # I know memes! FileUtils.mkdir_p '/path' - assert_equal '.', FileSystem.fs.name + assert_equal '/', FileSystem.fs.name assert_equal({}, FileSystem.fs['path']) Dir.chdir '/path' do File.open('foo', 'w') { |f| f.write 'foo'} File.open('foobar', 'w') { |f| f.write 'foo'} end - assert_equal '.', FileSystem.fs.name + assert_equal '/', FileSystem.fs.name assert_equal(['foo', 'foobar'], FileSystem.fs['path'].keys.sort) c = nil @@ -803,6 +991,10 @@ class FakeFSTest < Test::Unit::TestCase assert_raise(Errno::ENOENT) do FileUtils.mv 'blafgag', 'foo' end + exception = assert_raise(Errno::ENOENT) do + FileUtils.mv ['foo', 'bar'], 'destdir' + end + assert_equal "No such file or directory - foo", exception.message end def test_mv_actually_works @@ -1208,11 +1400,17 @@ class FakeFSTest < Test::Unit::TestCase FileUtils.touch("/this/path/should/be/here/#{f}") end - assert_raises(SystemCallError) do + assert_raises(Errno::ENOTEMPTY) do Dir.delete('/this/path/should/be/here') end end + def test_directory_class_delete_does_not_work_if_dir_path_cannot_be_found + assert_raises(Errno::ENOENT) do + Dir.delete('/this/path/should/not/be/here') + end + end + def test_directory_entries test = ['.', '..', 'file_1', 'file_2', 'file_3', 'file_4', 'file_5' ] @@ -1241,6 +1439,12 @@ class FakeFSTest < Test::Unit::TestCase test.each { |t| assert yielded.include?(t) } end + def test_directory_entries_does_not_work_if_dir_path_cannot_be_found + assert_raises(Errno::ENOENT) do + Dir.delete('/this/path/should/not/be/here') + end + end + def test_directory_foreach test = ['.', '..', 'file_1', 'file_2', 'file_3', 'file_4', 'file_5' ] @@ -1465,14 +1669,6 @@ class FakeFSTest < Test::Unit::TestCase end end - def test_delete_does_not_raise_error_when_second_file_does_not_exist - FileUtils.touch("/foo") - - assert_nothing_raised do - File.delete("/foo", "/bar") - end - end - def test_unlink_is_alias_for_delete assert_equal File.method(:unlink), File.method(:delete) end @@ -1573,6 +1769,28 @@ class FakeFSTest < Test::Unit::TestCase assert !FileTest.exist?("/path/to/dir") end + def test_filetest_directory_returns_correct_values + FileUtils.mkdir_p '/path/to/somedir' + assert FileTest.directory?('/path/to/somedir') + + FileUtils.rm_r '/path/to/somedir' + assert !FileTest.directory?('/path/to/somedir') + end + + def test_filetest_file_returns_correct_values + FileUtils.mkdir_p("/path/to") + + path = '/path/to/file.txt' + File.open(path, 'w') { |f| f.write "Yatta!" } + assert FileTest.file?(path) + + FileUtils.rm path + assert !FileTest.file?(path) + + FileUtils.mkdir_p '/path/to/somedir' + assert !FileTest.file?('/path/to/somedir') + end + def test_pathname_exists_returns_correct_value FileUtils.touch "foo" assert Pathname.new("foo").exist? @@ -1580,6 +1798,20 @@ class FakeFSTest < Test::Unit::TestCase assert !Pathname.new("bar").exist? end + def test_dir_mktmpdir + FileUtils.mkdir '/tmp' + + tmpdir = Dir.mktmpdir + assert File.directory?(tmpdir) + FileUtils.rm_r tmpdir + + Dir.mktmpdir do |t| + tmpdir = t + assert File.directory?(t) + end + assert !File.directory?(tmpdir) + end + def test_activating_returns_true FakeFS.deactivate! assert_equal true, FakeFS.activate! @@ -1589,6 +1821,15 @@ class FakeFSTest < Test::Unit::TestCase assert_equal true, FakeFS.deactivate! end + def test_split + assert File.respond_to? :split + filename = "/this/is/what/we/expect.txt" + path,filename = File.split(filename) + assert_equal path, "/this/is/what/we" + assert_equal filename, "expect.txt" + end + + def here(fname) RealFile.expand_path(File.join(RealFile.dirname(__FILE__), fname)) end @@ -1617,5 +1858,11 @@ class FakeFSTest < Test::Unit::TestCase assert_equal false, f.autoclose? end end + + def test_to_path + File.new("foo", 'w') do |f| + assert_equal "foo", f.to_path + end + end end end diff --git a/test/safe_test.rb b/test/safe_test.rb index f16dc4e..3404e59 100644 --- a/test/safe_test.rb +++ b/test/safe_test.rb @@ -10,7 +10,7 @@ class FakeFSSafeTest < Test::Unit::TestCase end def test_FakeFS_method_does_not_intrude_on_global_namespace - path = '/path/to/file.txt' + path = 'file.txt' FakeFS do File.open(path, 'w') { |f| f.write "Yatta!" } diff --git a/test/verify.rb b/test/verify.rb index 52a4c10..4df051d 100644 --- a/test/verify.rb +++ b/test/verify.rb @@ -24,7 +24,7 @@ class FakeFSVerifierTest < Test::Unit::TestCase real_class.instance_methods.each do |method| define_method("test #{method} instance method") do - assert fake_class.instance_methods.include?(method), "#{fake_class}##{name} not implemented" + assert fake_class.instance_methods.include?(method), "#{fake_class}##{method} not implemented" end end end