fakefs 0.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
data/LICENSE ADDED
@@ -0,0 +1,20 @@
1
+ Copyright (c) 2009 Chris Wanstrath
2
+
3
+ Permission is hereby granted, free of charge, to any person obtaining
4
+ a copy of this software and associated documentation files (the
5
+ "Software"), to deal in the Software without restriction, including
6
+ without limitation the rights to use, copy, modify, merge, publish,
7
+ distribute, sublicense, and/or sell copies of the Software, and to
8
+ permit persons to whom the Software is furnished to do so, subject to
9
+ the following conditions:
10
+
11
+ The above copyright notice and this permission notice shall be
12
+ included in all copies or substantial portions of the Software.
13
+
14
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
15
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
16
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
17
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
18
+ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
19
+ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
20
+ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
@@ -0,0 +1,68 @@
1
+ FakeFS
2
+ ======
3
+
4
+ Mocha is great. But when your library is all about manipulating the
5
+ filesystem, you really want to test the behavior and not the implementation.
6
+
7
+ If you're mocking and stubbing every call to FileUtils or File, you're
8
+ tightly coupling your tests with the implementation.
9
+
10
+ def test_creates_directory
11
+ FileUtils.expects(:mkdir).with("directory").once
12
+ Library.add "directory"
13
+ end
14
+
15
+ The above test will break if we decide to use `mkdir_p` in our code. Refactoring
16
+ code shouldn't necessitate refactoring tests.
17
+
18
+ With FakeFS:
19
+
20
+ def test_creates_directory
21
+ Library.add "directory"
22
+ assert File.directory?("directory")
23
+ end
24
+
25
+ Woot.
26
+
27
+
28
+ Usage
29
+ -----
30
+
31
+ require 'fakefs'
32
+
33
+ # That's it.
34
+
35
+
36
+ Don't Fake the FS Immediately
37
+ -----------------------------
38
+
39
+ require 'fakefs/safe'
40
+
41
+ FakeFS.activate!
42
+ # your code
43
+ FakeFS.deactivate!
44
+
45
+ # or
46
+ FakeFS do
47
+ # your code
48
+ end
49
+
50
+
51
+ How is this different than MockFS?
52
+ ----------------------------------
53
+
54
+ FakeFS provides a test suite and works with symlinks. It's also strictly a
55
+ test-time dependency: your actual library does not need to use or know about
56
+ FakeFS.
57
+
58
+
59
+ Speed?
60
+ ------
61
+ http://gist.github.com/156091
62
+
63
+
64
+ Authors
65
+ -------
66
+
67
+ * Chris Wanstrath [chris@ozmm.org]
68
+ * Pat Nakajima [http://github.com/nakajima]
@@ -0,0 +1,40 @@
1
+ task :default do
2
+ Dir['test/*_test.rb'].each { |file| require file }
3
+ end
4
+
5
+ begin
6
+ require 'jeweler'
7
+
8
+ # We're not putting VERSION or VERSION.yml in the root,
9
+ # so we have to help Jeweler find our version.
10
+ $LOAD_PATH.unshift File.dirname(__FILE__) + '/lib'
11
+ require 'fakefs/version'
12
+
13
+ FakeFS::Version.instance_eval do
14
+ def refresh
15
+ end
16
+ end
17
+
18
+ class Jeweler
19
+ def version_helper
20
+ FakeFS::Version
21
+ end
22
+
23
+ def version_exists?
24
+ true
25
+ end
26
+ end
27
+
28
+ Jeweler::Tasks.new do |gemspec|
29
+ gemspec.name = "fakefs"
30
+ gemspec.summary = "A fake filesystem. Use it in your tests."
31
+ gemspec.email = "chris@ozmm.org"
32
+ gemspec.homepage = "http://github.com/defunkt/fakefs"
33
+ gemspec.description = "A fake filesystem. Use it in your tests."
34
+ gemspec.authors = ["Chris Wanstrath"]
35
+ gemspec.has_rdoc = false
36
+ end
37
+ rescue LoadError
38
+ puts "Jeweler not available."
39
+ puts "Install it with: gem install technicalpickles-jeweler"
40
+ end
@@ -0,0 +1,3 @@
1
+ require 'fakefs/safe'
2
+
3
+ FakeFS.activate!
@@ -0,0 +1,37 @@
1
+ RealFile = File
2
+ RealFileUtils = FileUtils
3
+ RealDir = Dir
4
+ RealFileUtils::Dir = RealDir
5
+ RealFileUtils::File = RealFile
6
+
7
+ module FakeFS
8
+ def self.activate!
9
+ Object.class_eval do
10
+ remove_const(:Dir)
11
+ remove_const(:File)
12
+ remove_const(:FileUtils)
13
+ const_set(:Dir, FakeFS::Dir)
14
+ const_set(:File, FakeFS::File)
15
+ const_set(:FileUtils, FakeFS::FileUtils)
16
+ end
17
+ end
18
+
19
+ def self.deactivate!
20
+ Object.class_eval do
21
+ remove_const(:Dir)
22
+ remove_const(:File)
23
+ remove_const(:FileUtils)
24
+ const_set(:Dir, RealDir)
25
+ const_set(:File, RealFile)
26
+ const_set(:FileUtils, RealFileUtils)
27
+ end
28
+ end
29
+ end
30
+
31
+ def FakeFS
32
+ return ::FakeFS unless block_given?
33
+ ::FakeFS.activate!
34
+ yield
35
+ ::FakeFS.deactivate!
36
+ end
37
+
@@ -0,0 +1,23 @@
1
+ module FakeFS
2
+ class Dir
3
+ def self.glob(pattern)
4
+ [FileSystem.find(pattern) || []].flatten.map{|e| e.to_s}.sort
5
+ end
6
+
7
+ def self.[](pattern)
8
+ glob(pattern)
9
+ end
10
+
11
+ def self.chdir(dir, &blk)
12
+ FileSystem.chdir(dir, &blk)
13
+ end
14
+
15
+ def self.pwd
16
+ FileSystem.current_dir.to_s
17
+ end
18
+
19
+ class << self
20
+ alias_method :getwd, :pwd
21
+ end
22
+ end
23
+ end
@@ -0,0 +1,37 @@
1
+ module FakeFS
2
+ class FakeDir < Hash
3
+ attr_accessor :name, :parent
4
+
5
+ def initialize(name = nil, parent = nil)
6
+ @name = name
7
+ @parent = parent
8
+ end
9
+
10
+ def entry
11
+ self
12
+ end
13
+
14
+ def inspect
15
+ "(FakeDir name:#{name.inspect} parent:#{parent.to_s.inspect} size:#{size})"
16
+ end
17
+
18
+ def clone(parent = nil)
19
+ clone = Marshal.load(Marshal.dump(self))
20
+ clone.each do |key, value|
21
+ value.parent = clone
22
+ end
23
+ clone.parent = parent if parent
24
+ clone
25
+ end
26
+
27
+ def to_s
28
+ if parent && parent.to_s != '.'
29
+ File.join(parent.to_s, name)
30
+ elsif parent && parent.to_s == '.'
31
+ "#{File::PATH_SEPARATOR}#{name}"
32
+ else
33
+ name
34
+ end
35
+ end
36
+ end
37
+ end
@@ -0,0 +1,29 @@
1
+ module FakeFS
2
+ class FakeFile
3
+ attr_accessor :name, :parent, :content
4
+
5
+ def initialize(name = nil, parent = nil)
6
+ @name = name
7
+ @parent = parent
8
+ @content = ''
9
+ end
10
+
11
+ def clone(parent = nil)
12
+ clone = super()
13
+ clone.parent = parent if parent
14
+ clone
15
+ end
16
+
17
+ def entry
18
+ self
19
+ end
20
+
21
+ def inspect
22
+ "(FakeFile name:#{name.inspect} parent:#{parent.to_s.inspect} size:#{content.size})"
23
+ end
24
+
25
+ def to_s
26
+ File.join(parent.to_s, name)
27
+ end
28
+ end
29
+ end
@@ -0,0 +1,26 @@
1
+ module FakeFS
2
+ class FakeSymlink
3
+ attr_accessor :name, :target
4
+ alias_method :to_s, :name
5
+
6
+ def initialize(target)
7
+ @target = target
8
+ end
9
+
10
+ def inspect
11
+ "symlink(#{target.split('/').last})"
12
+ end
13
+
14
+ def entry
15
+ FileSystem.find(target)
16
+ end
17
+
18
+ def method_missing(*args, &block)
19
+ entry.send(*args, &block)
20
+ end
21
+
22
+ def respond_to?(method)
23
+ entry.respond_to?(method)
24
+ end
25
+ end
26
+ end
@@ -0,0 +1,124 @@
1
+ module FakeFS
2
+ class File
3
+ PATH_SEPARATOR = '/'
4
+
5
+ def self.join(*parts)
6
+ parts * PATH_SEPARATOR
7
+ end
8
+
9
+ def self.exist?(path)
10
+ !!FileSystem.find(path)
11
+ end
12
+
13
+ class << self
14
+ alias_method :exists?, :exist?
15
+ end
16
+
17
+ def self.const_missing(name)
18
+ RealFile.const_get(name)
19
+ end
20
+
21
+ def self.directory?(path)
22
+ if path.respond_to? :entry
23
+ path.entry.is_a? FakeDir
24
+ else
25
+ result = FileSystem.find(path)
26
+ result ? result.entry.is_a?(FakeDir) : false
27
+ end
28
+ end
29
+
30
+ def self.symlink?(path)
31
+ if path.respond_to? :entry
32
+ path.is_a? FakeSymlink
33
+ else
34
+ FileSystem.find(path).is_a? FakeSymlink
35
+ end
36
+ end
37
+
38
+ def self.file?(path)
39
+ if path.respond_to? :entry
40
+ path.entry.is_a? FakeFile
41
+ else
42
+ result = FileSystem.find(path)
43
+ result ? result.entry.is_a?(FakeFile) : false
44
+ end
45
+ end
46
+
47
+ def self.expand_path(*args)
48
+ RealFile.expand_path(*args)
49
+ end
50
+
51
+ def self.basename(*args)
52
+ RealFile.basename(*args)
53
+ end
54
+
55
+ def self.dirname(path)
56
+ RealFile.dirname(path)
57
+ end
58
+
59
+ def self.readlink(path)
60
+ symlink = FileSystem.find(path)
61
+ FileSystem.find(symlink.target).to_s
62
+ end
63
+
64
+ def self.open(path, mode='r')
65
+ if block_given?
66
+ yield new(path, mode)
67
+ else
68
+ new(path, mode)
69
+ end
70
+ end
71
+
72
+ def self.read(path)
73
+ file = new(path)
74
+ if file.exists?
75
+ file.read
76
+ else
77
+ raise Errno::ENOENT
78
+ end
79
+ end
80
+
81
+ def self.readlines(path)
82
+ read(path).split("\n")
83
+ end
84
+
85
+ attr_reader :path
86
+ def initialize(path, mode = nil)
87
+ @path = path
88
+ @mode = mode
89
+ @file = FileSystem.find(path)
90
+ @open = true
91
+ end
92
+
93
+ def close
94
+ @open = false
95
+ end
96
+
97
+ def read
98
+ raise IOError.new('closed stream') unless @open
99
+ @file.content
100
+ end
101
+
102
+ def exists?
103
+ @file
104
+ end
105
+
106
+ def puts(content)
107
+ write(content + "\n")
108
+ end
109
+
110
+ def write(content)
111
+ raise IOError.new('closed stream') unless @open
112
+
113
+ if !File.exists?(@path)
114
+ @file = FileSystem.add(path, FakeFile.new)
115
+ end
116
+
117
+ @file.content += content
118
+ end
119
+ alias_method :print, :write
120
+ alias_method :<<, :write
121
+
122
+ def flush; self; end
123
+ end
124
+ end
@@ -0,0 +1,118 @@
1
+ module FakeFS
2
+ module FileSystem
3
+ extend self
4
+
5
+ def dir_levels
6
+ @dir_levels ||= []
7
+ end
8
+
9
+ def fs
10
+ @fs ||= FakeDir.new('.')
11
+ end
12
+
13
+ def clear
14
+ @dir_levels = nil
15
+ @fs = nil
16
+ end
17
+
18
+ def files
19
+ fs.values
20
+ end
21
+
22
+ def find(path)
23
+ parts = path_parts(normalize_path(path))
24
+ return fs if parts.empty? # '/'
25
+
26
+ entries = find_recurser(fs, parts).flatten
27
+
28
+ case entries.length
29
+ when 0 then nil
30
+ when 1 then entries.first
31
+ else entries
32
+ end
33
+ end
34
+
35
+ def add(path, object=FakeDir.new)
36
+ parts = path_parts(normalize_path(path))
37
+
38
+ d = parts[0...-1].inject(fs) do |dir, part|
39
+ dir[part] ||= FakeDir.new(part, dir)
40
+ end
41
+
42
+ object.name = parts.last
43
+ object.parent = d
44
+ d[parts.last] ||= object
45
+ end
46
+
47
+ # copies directories and files from the real filesystem
48
+ # into our fake one
49
+ def clone(path)
50
+ path = File.expand_path(path)
51
+ pattern = File.join(path, '**', '*')
52
+ files = RealFile.file?(path) ? [path] : [path] + RealDir.glob(pattern, RealFile::FNM_DOTMATCH)
53
+
54
+ files.each do |f|
55
+ if RealFile.file?(f)
56
+ FileUtils.mkdir_p(File.dirname(f))
57
+ File.open(f, 'w') do |g|
58
+ g.print RealFile.open(f){|h| h.read }
59
+ end
60
+ elsif RealFile.directory?(f)
61
+ FileUtils.mkdir_p(f)
62
+ elsif RealFile.symlink?(f)
63
+ FileUtils.ln_s()
64
+ end
65
+ end
66
+ end
67
+
68
+ def delete(path)
69
+ if dir = FileSystem.find(path)
70
+ dir.parent.delete(dir.name)
71
+ end
72
+ end
73
+
74
+ def chdir(dir, &blk)
75
+ new_dir = find(dir)
76
+ dir_levels.push dir if blk
77
+
78
+ raise Errno::ENOENT, dir unless new_dir
79
+
80
+ dir_levels.push dir if !blk
81
+ blk.call if blk
82
+ ensure
83
+ dir_levels.pop if blk
84
+ end
85
+
86
+ def path_parts(path)
87
+ path.split(File::PATH_SEPARATOR).reject { |part| part.empty? }
88
+ end
89
+
90
+ def normalize_path(path)
91
+ if Pathname.new(path).absolute?
92
+ File.expand_path(path)
93
+ else
94
+ parts = dir_levels + [path]
95
+ File.expand_path(File.join(*parts))
96
+ end
97
+ end
98
+
99
+ def current_dir
100
+ find(normalize_path('.'))
101
+ end
102
+
103
+ private
104
+
105
+ def find_recurser(dir, parts)
106
+ return [] unless dir.respond_to? :[]
107
+
108
+ pattern , *parts = parts
109
+ matches = dir.reject {|k,v| /\A#{pattern.gsub('?','.').gsub('*', '.*')}\Z/ !~ k }.values
110
+
111
+ if parts.empty? # we're done recursing
112
+ matches
113
+ else
114
+ matches.map{|entry| find_recurser(entry, parts) }
115
+ end
116
+ end
117
+ end
118
+ end
@@ -0,0 +1,108 @@
1
+ module FakeFS
2
+ module FileUtils
3
+ extend self
4
+
5
+ def mkdir_p(path)
6
+ FileSystem.add(path, FakeDir.new)
7
+ end
8
+
9
+ def rm(path)
10
+ FileSystem.delete(path)
11
+ end
12
+ alias_method :rm_rf, :rm
13
+ alias_method :rm_r, :rm
14
+
15
+ def ln_s(target, path)
16
+ raise Errno::EEXIST, path if FileSystem.find(path)
17
+ FileSystem.add(path, FakeSymlink.new(target))
18
+ end
19
+
20
+ def cp(src, dest)
21
+ dst_file = FileSystem.find(dest)
22
+ src_file = FileSystem.find(src)
23
+
24
+ if !src_file
25
+ raise Errno::ENOENT, src
26
+ end
27
+
28
+ if File.directory? src_file
29
+ raise Errno::EISDIR, src
30
+ end
31
+
32
+ if dst_file && File.directory?(dst_file)
33
+ FileSystem.add(File.join(dest, src), src_file.entry.clone(dst_file))
34
+ else
35
+ FileSystem.delete(dest)
36
+ FileSystem.add(dest, src_file.entry.clone)
37
+ end
38
+ end
39
+
40
+ def cp_r(src, dest)
41
+ # This error sucks, but it conforms to the original Ruby
42
+ # method.
43
+ raise "unknown file type: #{src}" unless dir = FileSystem.find(src)
44
+
45
+ new_dir = FileSystem.find(dest)
46
+
47
+ if new_dir && !File.directory?(dest)
48
+ raise Errno::EEXIST, dest
49
+ end
50
+
51
+ if !new_dir && !FileSystem.find(dest+'/../')
52
+ raise Errno::ENOENT, dest
53
+ end
54
+
55
+ # This last bit is a total abuse and should be thought hard
56
+ # about and cleaned up.
57
+ if new_dir
58
+ if src[-2..-1] == '/.'
59
+ dir.values.each{|f| new_dir[f.name] = f.clone(new_dir) }
60
+ else
61
+ new_dir[dir.name] = dir.entry.clone(new_dir)
62
+ end
63
+ else
64
+ FileSystem.add(dest, dir.entry.clone)
65
+ end
66
+ end
67
+
68
+ def mv(src, dest)
69
+ if target = FileSystem.find(src)
70
+ FileSystem.add(dest, target.entry.clone)
71
+ FileSystem.delete(src)
72
+ else
73
+ raise Errno::ENOENT, src
74
+ end
75
+ end
76
+
77
+ def chown(user, group, list, options={})
78
+ list = Array(list)
79
+ list.each do |f|
80
+ unless File.exists?(f)
81
+ raise Errno::ENOENT, f
82
+ end
83
+ end
84
+ list
85
+ end
86
+
87
+ def chown_R(user, group, list, options={})
88
+ chown(user, group, list, options={})
89
+ end
90
+
91
+ def touch(list, options={})
92
+ Array(list).each do |f|
93
+ directory = File.dirname(f)
94
+ # FIXME this explicit check for '.' shouldn't need to happen
95
+ if File.exists?(directory) || directory == '.'
96
+ FileSystem.add(f, FakeFile.new)
97
+ else
98
+ raise Errno::ENOENT, f
99
+ end
100
+ end
101
+ end
102
+
103
+ def cd(dir)
104
+ FileSystem.chdir(dir)
105
+ end
106
+ alias_method :chdir, :cd
107
+ end
108
+ end
@@ -0,0 +1,11 @@
1
+ require 'fileutils'
2
+ require 'pathname'
3
+ require 'fakefs/base'
4
+ require 'fakefs/fake/file'
5
+ require 'fakefs/fake/dir'
6
+ require 'fakefs/fake/symlink'
7
+ require 'fakefs/file_system'
8
+ require 'fakefs/fileutils'
9
+ require 'fakefs/file'
10
+ require 'fakefs/dir'
11
+
@@ -0,0 +1,9 @@
1
+ module FakeFS
2
+ module Version
3
+ VERSION = "0.1.0"
4
+
5
+ def self.to_s
6
+ VERSION
7
+ end
8
+ end
9
+ end
@@ -0,0 +1,538 @@
1
+ $LOAD_PATH.unshift File.join(File.dirname(__FILE__), '..', 'lib')
2
+ require 'fakefs'
3
+ require 'test/unit'
4
+
5
+ class FakeFSTest < Test::Unit::TestCase
6
+ include FakeFS
7
+
8
+ def setup
9
+ FileSystem.clear
10
+ end
11
+
12
+ def test_can_be_initialized_empty
13
+ fs = FileSystem
14
+ assert_equal 0, fs.files.size
15
+ end
16
+
17
+ def xtest_can_be_initialized_with_an_existing_directory
18
+ fs = FileSystem
19
+ fs.clone(File.expand_path(File.dirname(__FILE__))).inspect
20
+ puts fs.files.inspect
21
+ assert_equal 1, fs.files.size
22
+ end
23
+
24
+ def test_can_create_directories
25
+ FileUtils.mkdir_p("/path/to/dir")
26
+ assert_kind_of FakeDir, FileSystem.fs['path']['to']['dir']
27
+ end
28
+
29
+ def test_knows_directories_exist
30
+ FileUtils.mkdir_p(path = "/path/to/dir")
31
+ assert File.exists?(path)
32
+ end
33
+
34
+ def test_knows_directories_are_directories
35
+ FileUtils.mkdir_p(path = "/path/to/dir")
36
+ assert File.directory?(path)
37
+ end
38
+
39
+ def test_knows_symlink_directories_are_directories
40
+ FileUtils.mkdir_p(path = "/path/to/dir")
41
+ FileUtils.ln_s path, sympath = '/sympath'
42
+ assert File.directory?(sympath)
43
+ end
44
+
45
+ def test_knows_non_existent_directories_arent_directories
46
+ path = 'does/not/exist/'
47
+ assert_equal RealFile.directory?(path), File.directory?(path)
48
+ end
49
+
50
+ def test_doesnt_overwrite_existing_directories
51
+ FileUtils.mkdir_p(path = "/path/to/dir")
52
+ assert File.exists?(path)
53
+ FileUtils.mkdir_p("/path/to")
54
+ assert File.exists?(path)
55
+ end
56
+
57
+ def test_can_create_symlinks
58
+ FileUtils.mkdir_p(target = "/path/to/target")
59
+ FileUtils.ln_s(target, "/path/to/link")
60
+ assert_kind_of FakeSymlink, FileSystem.fs['path']['to']['link']
61
+
62
+ assert_raises(Errno::EEXIST) {
63
+ FileUtils.ln_s(target, '/path/to/link')
64
+ }
65
+ end
66
+
67
+ def test_can_follow_symlinks
68
+ FileUtils.mkdir_p(target = "/path/to/target")
69
+ FileUtils.ln_s(target, link = "/path/to/symlink")
70
+ assert_equal target, File.readlink(link)
71
+ end
72
+
73
+ def test_knows_symlinks_are_symlinks
74
+ FileUtils.mkdir_p(target = "/path/to/target")
75
+ FileUtils.ln_s(target, link = "/path/to/symlink")
76
+ assert File.symlink?(link)
77
+ end
78
+
79
+ def test_can_create_files
80
+ path = '/path/to/file.txt'
81
+ File.open(path, 'w') do |f|
82
+ f.write "Yatta!"
83
+ end
84
+
85
+ assert File.exists?(path)
86
+ end
87
+
88
+ def test_can_read_files_once_written
89
+ path = '/path/to/file.txt'
90
+ File.open(path, 'w') do |f|
91
+ f.write "Yatta!"
92
+ end
93
+
94
+ assert_equal "Yatta!", File.read(path)
95
+ end
96
+
97
+ def test_can_write_to_files
98
+ path = '/path/to/file.txt'
99
+ File.open(path, 'w') do |f|
100
+ f << 'Yada Yada'
101
+ end
102
+ assert_equal 'Yada Yada', File.read(path)
103
+ end
104
+
105
+ def test_can_read_with_File_readlines
106
+ path = '/path/to/file.txt'
107
+ File.open(path, 'w') do |f|
108
+ f.puts "Yatta!"
109
+ f.puts "woot"
110
+ end
111
+
112
+ assert_equal ["Yatta!", "woot"], File.readlines(path)
113
+ end
114
+
115
+ def test_File_close_disallows_further_access
116
+ path = '/path/to/file.txt'
117
+ file = File.open(path, 'w')
118
+ file.write 'Yada'
119
+ file.close
120
+ assert_raise IOError do
121
+ file.read
122
+ end
123
+ end
124
+
125
+ def test_can_read_from_file_objects
126
+ path = '/path/to/file.txt'
127
+ File.open(path, 'w') do |f|
128
+ f.write "Yatta!"
129
+ end
130
+
131
+ assert_equal "Yatta!", File.new(path).read
132
+ end
133
+
134
+ def test_file_read_errors_appropriately
135
+ assert_raise Errno::ENOENT do
136
+ File.read('anything')
137
+ end
138
+ end
139
+
140
+ def test_knows_files_are_files
141
+ path = '/path/to/file.txt'
142
+ File.open(path, 'w') do |f|
143
+ f.write "Yatta!"
144
+ end
145
+
146
+ assert File.file?(path)
147
+ end
148
+
149
+ def test_knows_symlink_files_are_files
150
+ path = '/path/to/file.txt'
151
+ File.open(path, 'w') do |f|
152
+ f.write "Yatta!"
153
+ end
154
+ FileUtils.ln_s path, sympath='/sympath'
155
+
156
+ assert File.file?(sympath)
157
+ end
158
+
159
+ def test_knows_non_existent_files_arent_files
160
+ assert_equal RealFile.file?('does/not/exist.txt'), File.file?('does/not/exist.txt')
161
+ end
162
+
163
+ def test_can_chown_files
164
+ good = 'file.txt'
165
+ bad = 'nofile.txt'
166
+ File.open(good,'w'){|f| f.write "foo" }
167
+
168
+ assert_equal [good], FileUtils.chown('noone', 'nogroup', good, :verbose => true)
169
+ assert_raises(Errno::ENOENT) do
170
+ FileUtils.chown('noone', 'nogroup', bad, :verbose => true)
171
+ end
172
+
173
+ assert_equal [good], FileUtils.chown('noone', 'nogroup', good)
174
+ assert_raises(Errno::ENOENT) do
175
+ FileUtils.chown('noone', 'nogroup', bad)
176
+ end
177
+
178
+ assert_equal [good], FileUtils.chown('noone', 'nogroup', [good])
179
+ assert_raises(Errno::ENOENT) do
180
+ FileUtils.chown('noone', 'nogroup', [good, bad])
181
+ end
182
+ end
183
+
184
+ def test_can_chown_R_files
185
+ FileUtils.mkdir_p '/path/'
186
+ File.open('/path/foo', 'w'){|f| f.write 'foo' }
187
+ File.open('/path/foobar', 'w'){|f| f.write 'foo' }
188
+ resp = FileUtils.chown_R('no', 'no', '/path')
189
+ assert_equal ['/path'], resp
190
+ end
191
+
192
+ def test_dir_globs_paths
193
+ FileUtils.mkdir_p '/path'
194
+ File.open('/path/foo', 'w'){|f| f.write 'foo' }
195
+ File.open('/path/foobar', 'w'){|f| f.write 'foo' }
196
+
197
+ FileUtils.mkdir_p '/path/bar'
198
+ File.open('/path/bar/baz', 'w'){|f| f.write 'foo' }
199
+
200
+ FileUtils.cp_r '/path/bar', '/path/bar2'
201
+
202
+ assert_equal ['/path'], Dir['/path']
203
+ assert_equal %w( /path/bar /path/bar2 /path/foo /path/foobar ), Dir['/path/*']
204
+
205
+ assert_equal ['/path/bar/baz'], Dir['/path/bar/*']
206
+ assert_equal ['/path/foo'], Dir['/path/foo']
207
+
208
+ assert_equal ['/path'], Dir['/path*']
209
+ assert_equal ['/path/foo', '/path/foobar'], Dir['/p*h/foo*']
210
+ assert_equal ['/path/foo', '/path/foobar'], Dir['/p??h/foo*']
211
+
212
+ FileUtils.cp_r '/path', '/otherpath'
213
+
214
+ assert_equal %w( /otherpath/foo /otherpath/foobar /path/foo /path/foobar ), Dir['/*/foo*']
215
+ end
216
+
217
+ def test_dir_glob_handles_root
218
+ FileUtils.mkdir_p '/path'
219
+
220
+ # this fails. the root dir should be named '/' but it is '.'
221
+ #assert_equal ['/'], Dir['/']
222
+ end
223
+
224
+ def test_chdir_changes_directories_like_a_boss
225
+ # I know memes!
226
+ FileUtils.mkdir_p '/path'
227
+ assert_equal '.', FileSystem.fs.name
228
+ assert_equal({}, FileSystem.fs['path'])
229
+ Dir.chdir '/path' do
230
+ File.open('foo', 'w'){|f| f.write 'foo'}
231
+ File.open('foobar', 'w'){|f| f.write 'foo'}
232
+ end
233
+
234
+ assert_equal '.', FileSystem.fs.name
235
+ assert_equal(['foo', 'foobar'], FileSystem.fs['path'].keys.sort)
236
+
237
+ c = nil
238
+ Dir.chdir '/path' do
239
+ c = File.open('foo', 'r'){|f| f.read }
240
+ end
241
+
242
+ assert_equal 'foo', c
243
+ end
244
+
245
+ def test_chdir_shouldnt_keep_us_from_absolute_paths
246
+ FileUtils.mkdir_p '/path'
247
+
248
+ Dir.chdir '/path' do
249
+ File.open('foo', 'w'){|f| f.write 'foo'}
250
+ File.open('/foobar', 'w'){|f| f.write 'foo'}
251
+ end
252
+ assert_equal ['foo'], FileSystem.fs['path'].keys.sort
253
+ assert_equal ['foobar', 'path'], FileSystem.fs.keys.sort
254
+
255
+ Dir.chdir '/path' do
256
+ FileUtils.rm('foo')
257
+ FileUtils.rm('/foobar')
258
+ end
259
+
260
+ assert_equal [], FileSystem.fs['path'].keys.sort
261
+ assert_equal ['path'], FileSystem.fs.keys.sort
262
+ end
263
+
264
+ def test_chdir_should_be_nestable
265
+ FileUtils.mkdir_p '/path/me'
266
+ Dir.chdir '/path' do
267
+ File.open('foo', 'w'){|f| f.write 'foo'}
268
+ Dir.chdir 'me' do
269
+ File.open('foobar', 'w'){|f| f.write 'foo'}
270
+ end
271
+ end
272
+
273
+ assert_equal ['foo','me'], FileSystem.fs['path'].keys.sort
274
+ assert_equal ['foobar'], FileSystem.fs['path']['me'].keys.sort
275
+ end
276
+
277
+ def test_chdir_should_flop_over_and_die_if_the_dir_doesnt_exist
278
+ assert_raise(Errno::ENOENT) do
279
+ Dir.chdir('/nope') do
280
+ 1
281
+ end
282
+ end
283
+ end
284
+
285
+ def test_chdir_shouldnt_lose_state_because_of_errors
286
+ FileUtils.mkdir_p '/path'
287
+
288
+ Dir.chdir '/path' do
289
+ File.open('foo', 'w'){|f| f.write 'foo'}
290
+ File.open('foobar', 'w'){|f| f.write 'foo'}
291
+ end
292
+
293
+ begin
294
+ Dir.chdir('/path') do
295
+ raise Exception
296
+ end
297
+ rescue Exception # hardcore
298
+ end
299
+
300
+ Dir.chdir('/path') do
301
+ begin
302
+ Dir.chdir('nope'){ }
303
+ rescue Errno::ENOENT
304
+ end
305
+
306
+ assert_equal ['/path'], FileSystem.dir_levels
307
+ end
308
+
309
+ assert_equal(['foo', 'foobar'], FileSystem.fs['path'].keys.sort)
310
+ end
311
+
312
+ def test_chdir_with_no_block_is_awesome
313
+ FileUtils.mkdir_p '/path'
314
+ Dir.chdir('/path')
315
+ FileUtils.mkdir_p 'subdir'
316
+ assert_equal ['subdir'], FileSystem.current_dir.keys
317
+ Dir.chdir('subdir')
318
+ File.open('foo', 'w'){|f| f.write 'foo'}
319
+ assert_equal ['foo'], FileSystem.current_dir.keys
320
+
321
+ assert_raises(Errno::ENOENT) do
322
+ Dir.chdir('subsubdir')
323
+ end
324
+
325
+ assert_equal ['foo'], FileSystem.current_dir.keys
326
+ end
327
+
328
+ def test_current_dir_reflected_by_pwd
329
+ FileUtils.mkdir_p '/path'
330
+ Dir.chdir('/path')
331
+
332
+ assert_equal '/path', Dir.pwd
333
+ assert_equal '/path', Dir.getwd
334
+
335
+ FileUtils.mkdir_p 'subdir'
336
+ Dir.chdir('subdir')
337
+
338
+ assert_equal '/path/subdir', Dir.pwd
339
+ assert_equal '/path/subdir', Dir.getwd
340
+ end
341
+
342
+ def test_file_open_defaults_to_read
343
+ File.open('foo','w'){|f| f.write 'bar' }
344
+ assert_equal 'bar', File.open('foo'){|f| f.read }
345
+ end
346
+
347
+ def test_flush_exists_on_file
348
+ r = File.open('foo','w'){|f| f.write 'bar'; f.flush }
349
+ assert_equal 'foo', r.path
350
+ end
351
+
352
+ def test_mv_should_raise_error_on_missing_file
353
+ assert_raise(Errno::ENOENT) do
354
+ FileUtils.mv 'blafgag', 'foo'
355
+ end
356
+ end
357
+
358
+ def test_mv_actually_works
359
+ File.open('foo', 'w') {|f| f.write 'bar' }
360
+ FileUtils.mv 'foo', 'baz'
361
+ assert_equal 'bar', File.open('baz'){|f| f.read }
362
+ end
363
+
364
+ def test_cp_actually_works
365
+ File.open('foo', 'w') {|f| f.write 'bar' }
366
+ FileUtils.cp('foo', 'baz')
367
+ assert_equal 'bar', File.read('baz')
368
+ end
369
+
370
+ def test_cp_file_into_dir
371
+ File.open('foo', 'w') {|f| f.write 'bar' }
372
+ FileUtils.mkdir_p 'baz'
373
+
374
+ FileUtils.cp('foo', 'baz')
375
+ assert_equal 'bar', File.read('baz/foo')
376
+ end
377
+
378
+ def test_cp_overwrites_dest_file
379
+ File.open('foo', 'w') {|f| f.write 'FOO' }
380
+ File.open('bar', 'w') {|f| f.write 'BAR' }
381
+
382
+ FileUtils.cp('foo', 'bar')
383
+ assert_equal 'FOO', File.read('bar')
384
+ end
385
+
386
+ def test_cp_fails_on_no_source
387
+ assert_raise Errno::ENOENT do
388
+ FileUtils.cp('foo', 'baz')
389
+ end
390
+ end
391
+
392
+ def test_cp_fails_on_directory_copy
393
+ FileUtils.mkdir_p 'baz'
394
+
395
+ assert_raise Errno::EISDIR do
396
+ FileUtils.cp('baz', 'bar')
397
+ end
398
+ end
399
+
400
+ def test_cp_r_doesnt_tangle_files_together
401
+ File.open('foo', 'w') {|f| f.write 'bar' }
402
+ FileUtils.cp_r('foo', 'baz')
403
+ File.open('baz', 'w') {|f| f.write 'quux' }
404
+ assert_equal 'bar', File.open('foo'){|f| f.read }
405
+ end
406
+
407
+ def test_cp_r_should_raise_error_on_missing_file
408
+ # Yes, this error sucks, but it conforms to the original Ruby
409
+ # method.
410
+ assert_raise(RuntimeError) do
411
+ FileUtils.cp_r 'blafgag', 'foo'
412
+ end
413
+ end
414
+
415
+ def test_cp_r_handles_copying_directories
416
+ FileUtils.mkdir_p 'subdir'
417
+ Dir.chdir('subdir'){ File.open('foo', 'w'){|f| f.write 'footext' } }
418
+
419
+ FileUtils.mkdir_p 'baz'
420
+
421
+ # To a previously uncreated directory
422
+ FileUtils.cp_r('subdir', 'quux')
423
+ assert_equal 'footext', File.open('quux/foo'){|f| f.read }
424
+
425
+ # To a directory that already exists
426
+ FileUtils.cp_r('subdir', 'baz')
427
+ assert_equal 'footext', File.open('baz/subdir/foo'){|f| f.read }
428
+
429
+ # To a subdirectory of a directory that does not exist
430
+ assert_raises(Errno::ENOENT) {
431
+ FileUtils.cp_r('subdir', 'nope/something')
432
+ }
433
+ end
434
+
435
+ def test_cp_r_only_copies_into_directories
436
+ FileUtils.mkdir_p 'subdir'
437
+ Dir.chdir('subdir'){ File.open('foo', 'w'){|f| f.write 'footext' } }
438
+
439
+ File.open('bar', 'w') {|f| f.write 'bartext' }
440
+
441
+ assert_raises(Errno::EEXIST) do
442
+ FileUtils.cp_r 'subdir', 'bar'
443
+ end
444
+
445
+ FileUtils.mkdir_p 'otherdir'
446
+ FileUtils.ln_s 'otherdir', 'symdir'
447
+
448
+ FileUtils.cp_r 'subdir', 'symdir'
449
+ assert_equal 'footext', File.open('symdir/subdir/foo'){|f| f.read }
450
+ end
451
+
452
+ def test_cp_r_sets_parent_correctly
453
+ FileUtils.mkdir_p '/path/foo'
454
+ File.open('/path/foo/bar', 'w'){|f| f.write 'foo' }
455
+ File.open('/path/foo/baz', 'w'){|f| f.write 'foo' }
456
+
457
+ FileUtils.cp_r '/path/foo', '/path/bar'
458
+
459
+ assert File.exists?('/path/bar/baz')
460
+ FileUtils.rm_rf '/path/bar/baz'
461
+ assert_equal %w( /path/bar/bar ), Dir['/path/bar/*']
462
+ end
463
+
464
+ def test_clone_clones_normal_files
465
+ RealFile.open(here('foo'), 'w'){|f| f.write 'bar' }
466
+ assert !File.exists?(here('foo'))
467
+ FileSystem.clone(here('foo'))
468
+ assert_equal 'bar', File.open(here('foo')){|f| f.read }
469
+ ensure
470
+ RealFile.unlink(here('foo')) if RealFile.exists?(here('foo'))
471
+ end
472
+
473
+ def test_clone_clones_directories
474
+ RealFileUtils.mkdir_p(here('subdir'))
475
+
476
+ FileSystem.clone(here('subdir'))
477
+
478
+ assert File.exists?(here('subdir')), 'subdir was cloned'
479
+ assert File.directory?(here('subdir')), 'subdir is a directory'
480
+ ensure
481
+ RealFileUtils.rm_rf(here('subdir')) if RealFile.exists?(here('subdir'))
482
+ end
483
+
484
+ def test_clone_clones_dot_files_even_hard_to_find_ones
485
+ RealFileUtils.mkdir_p(here('subdir/.bar/baz/.quux/foo'))
486
+ assert !File.exists?(here('subdir'))
487
+
488
+ FileSystem.clone(here('subdir'))
489
+ assert_equal ['.bar'], FileSystem.find(here('subdir')).keys
490
+ assert_equal ['foo'], FileSystem.find(here('subdir/.bar/baz/.quux')).keys
491
+ ensure
492
+ RealFileUtils.rm_rf(here('subdir')) if RealFile.exists?(here('subdir'))
493
+ end
494
+
495
+ def test_putting_a_dot_at_end_copies_the_contents
496
+ FileUtils.mkdir_p 'subdir'
497
+ Dir.chdir('subdir'){ File.open('foo', 'w'){|f| f.write 'footext' } }
498
+
499
+ FileUtils.mkdir_p 'newdir'
500
+ FileUtils.cp_r 'subdir/.', 'newdir'
501
+ assert_equal 'footext', File.open('newdir/foo'){|f| f.read }
502
+ end
503
+
504
+ def test_file_can_read_from_symlinks
505
+ File.open('first', 'w'){|f| f.write '1'}
506
+ FileUtils.ln_s 'first', 'one'
507
+ assert_equal '1', File.open('one'){|f| f.read }
508
+
509
+ FileUtils.mkdir_p 'subdir'
510
+ File.open('subdir/nother','w'){|f| f.write 'works' }
511
+ FileUtils.ln_s 'subdir', 'new'
512
+ assert_equal 'works', File.open('new/nother'){|f| f.read }
513
+ end
514
+
515
+ def test_files_can_be_touched
516
+ FileUtils.touch('touched_file')
517
+ assert File.exists?('touched_file')
518
+ list = ['newfile', 'another']
519
+ FileUtils.touch(list)
520
+ list.each { |fp| assert(File.exists?(fp)) }
521
+ end
522
+
523
+ def test_touch_does_not_work_if_the_dir_path_cannot_be_found
524
+ assert_raises(Errno::ENOENT) {
525
+ FileUtils.touch('this/path/should/not/be/here')
526
+ }
527
+ FileUtils.mkdir_p('subdir')
528
+ list = ['subdir/foo', 'nosubdir/bar']
529
+
530
+ assert_raises(Errno::ENOENT) {
531
+ FileUtils.touch(list)
532
+ }
533
+ end
534
+
535
+ def here(fname)
536
+ RealFile.expand_path(RealFile.dirname(__FILE__)+'/'+fname)
537
+ end
538
+ end
@@ -0,0 +1,20 @@
1
+ $LOAD_PATH.unshift File.join(File.dirname(__FILE__), '..', 'lib')
2
+ require 'fakefs/safe'
3
+ require 'test/unit'
4
+
5
+ class FakeFSSafeTest < Test::Unit::TestCase
6
+ def setup
7
+ FakeFS.deactivate!
8
+ end
9
+
10
+ def test_FakeFS_method_does_not_intrude_on_global_namespace
11
+ path = '/path/to/file.txt'
12
+
13
+ FakeFS do
14
+ File.open(path, 'w') { |f| f.write "Yatta!" }
15
+ assert File.exists?(path)
16
+ end
17
+
18
+ assert ! File.exists?(path)
19
+ end
20
+ end
@@ -0,0 +1,27 @@
1
+ # Figure out what's missing from fakefs
2
+ #
3
+ # USAGE
4
+ #
5
+ # $ ruby test/verify.rb | grep "not implemented"
6
+ require 'fakefs'
7
+ require 'test/unit'
8
+
9
+ class FakeFSVerifierTest < Test::Unit::TestCase
10
+ (RealFile.methods - Class.new.methods).each do |name|
11
+ define_method("test #{name} class method") do
12
+ assert File.respond_to?(name), "File.#{name} not implemented"
13
+ end
14
+ end
15
+
16
+ (RealFile.instance_methods - Enumerable.instance_methods).each do |name|
17
+ define_method("test #{name} instance method") do
18
+ assert File.instance_methods.include?(name), "File##{name} not implemented"
19
+ end
20
+ end
21
+
22
+ (RealFileUtils.methods - Class.new.methods).each do |name|
23
+ define_method("test #{name} module method") do
24
+ assert FileUtils.respond_to?(name), "FileUtils.#{name} not implemented"
25
+ end
26
+ end
27
+ end
metadata ADDED
@@ -0,0 +1,74 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: fakefs
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.1.0
5
+ platform: ruby
6
+ authors:
7
+ - Chris Wanstrath
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+
12
+ date: 2009-09-10 00:00:00 -07:00
13
+ default_executable:
14
+ dependencies: []
15
+
16
+ description: A fake filesystem. Use it in your tests.
17
+ email: chris@ozmm.org
18
+ executables: []
19
+
20
+ extensions: []
21
+
22
+ extra_rdoc_files:
23
+ - LICENSE
24
+ - README.markdown
25
+ files:
26
+ - LICENSE
27
+ - README.markdown
28
+ - Rakefile
29
+ - lib/fakefs.rb
30
+ - lib/fakefs/base.rb
31
+ - lib/fakefs/dir.rb
32
+ - lib/fakefs/fake/dir.rb
33
+ - lib/fakefs/fake/file.rb
34
+ - lib/fakefs/fake/symlink.rb
35
+ - lib/fakefs/file.rb
36
+ - lib/fakefs/file_system.rb
37
+ - lib/fakefs/fileutils.rb
38
+ - lib/fakefs/safe.rb
39
+ - lib/fakefs/version.rb
40
+ - test/fakefs_test.rb
41
+ - test/safe_test.rb
42
+ - test/verify.rb
43
+ has_rdoc: true
44
+ homepage: http://github.com/defunkt/fakefs
45
+ licenses: []
46
+
47
+ post_install_message:
48
+ rdoc_options:
49
+ - --charset=UTF-8
50
+ require_paths:
51
+ - lib
52
+ required_ruby_version: !ruby/object:Gem::Requirement
53
+ requirements:
54
+ - - ">="
55
+ - !ruby/object:Gem::Version
56
+ version: "0"
57
+ version:
58
+ required_rubygems_version: !ruby/object:Gem::Requirement
59
+ requirements:
60
+ - - ">="
61
+ - !ruby/object:Gem::Version
62
+ version: "0"
63
+ version:
64
+ requirements: []
65
+
66
+ rubyforge_project:
67
+ rubygems_version: 1.3.5
68
+ signing_key:
69
+ specification_version: 3
70
+ summary: A fake filesystem. Use it in your tests.
71
+ test_files:
72
+ - test/fakefs_test.rb
73
+ - test/safe_test.rb
74
+ - test/verify.rb