rsanheim-fakefs 0.0.1

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.
data/README.markdown ADDED
@@ -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]
data/Rakefile ADDED
@@ -0,0 +1,19 @@
1
+ task :default do
2
+ Dir['test/*_test.rb'].each { |file| require file }
3
+ end
4
+
5
+ begin
6
+ require 'jeweler'
7
+ Jeweler::Tasks.new do |gemspec|
8
+ gemspec.name = "fakefs"
9
+ gemspec.summary = "A fake filesystem. Use it in your tests."
10
+ gemspec.email = "chris@ozmm.org"
11
+ gemspec.homepage = "http://github.com/defunkt/fakefs"
12
+ gemspec.description = "A fake filesystem. Use it in your tests."
13
+ gemspec.authors = ["Chris Wanstrath"]
14
+ gemspec.has_rdoc = false
15
+ end
16
+ rescue LoadError
17
+ puts "Jeweler not available."
18
+ puts "Install it with: gem install technicalpickles-jeweler"
19
+ end
@@ -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
+
data/lib/fakefs/dir.rb ADDED
@@ -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,126 @@
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
+ content.flatten.each do |obj|
108
+ write(obj.to_s + "\n")
109
+ end
110
+ end
111
+
112
+ def write(content)
113
+ raise IOError.new('closed stream') unless @open
114
+
115
+ if !File.exists?(@path)
116
+ @file = FileSystem.add(path, FakeFile.new)
117
+ end
118
+
119
+ @file.content += content
120
+ end
121
+ alias_method :print, :write
122
+ alias_method :<<, :write
123
+
124
+ def flush; self; end
125
+ end
126
+ 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,109 @@
1
+ module FakeFS
2
+ module FileUtils
3
+ extend self
4
+
5
+ def mkdir_p(path)
6
+ FileSystem.add(path, FakeDir.new)
7
+ end
8
+ alias_method :mkpath, :mkdir_p
9
+
10
+ def rm(path)
11
+ FileSystem.delete(path)
12
+ end
13
+ alias_method :rm_rf, :rm
14
+ alias_method :rm_r, :rm
15
+
16
+ def ln_s(target, path)
17
+ raise Errno::EEXIST, path if FileSystem.find(path)
18
+ FileSystem.add(path, FakeSymlink.new(target))
19
+ end
20
+
21
+ def cp(src, dest)
22
+ dst_file = FileSystem.find(dest)
23
+ src_file = FileSystem.find(src)
24
+
25
+ if !src_file
26
+ raise Errno::ENOENT, src
27
+ end
28
+
29
+ if File.directory? src_file
30
+ raise Errno::EISDIR, src
31
+ end
32
+
33
+ if dst_file && File.directory?(dst_file)
34
+ FileSystem.add(File.join(dest, src), src_file.entry.clone(dst_file))
35
+ else
36
+ FileSystem.delete(dest)
37
+ FileSystem.add(dest, src_file.entry.clone)
38
+ end
39
+ end
40
+
41
+ def cp_r(src, dest)
42
+ # This error sucks, but it conforms to the original Ruby
43
+ # method.
44
+ raise "unknown file type: #{src}" unless dir = FileSystem.find(src)
45
+
46
+ new_dir = FileSystem.find(dest)
47
+
48
+ if new_dir && !File.directory?(dest)
49
+ raise Errno::EEXIST, dest
50
+ end
51
+
52
+ if !new_dir && !FileSystem.find(dest+'/../')
53
+ raise Errno::ENOENT, dest
54
+ end
55
+
56
+ # This last bit is a total abuse and should be thought hard
57
+ # about and cleaned up.
58
+ if new_dir
59
+ if src[-2..-1] == '/.'
60
+ dir.values.each{|f| new_dir[f.name] = f.clone(new_dir) }
61
+ else
62
+ new_dir[dir.name] = dir.entry.clone(new_dir)
63
+ end
64
+ else
65
+ FileSystem.add(dest, dir.entry.clone)
66
+ end
67
+ end
68
+
69
+ def mv(src, dest)
70
+ if target = FileSystem.find(src)
71
+ FileSystem.add(dest, target.entry.clone)
72
+ FileSystem.delete(src)
73
+ else
74
+ raise Errno::ENOENT, src
75
+ end
76
+ end
77
+
78
+ def chown(user, group, list, options={})
79
+ list = Array(list)
80
+ list.each do |f|
81
+ unless File.exists?(f)
82
+ raise Errno::ENOENT, f
83
+ end
84
+ end
85
+ list
86
+ end
87
+
88
+ def chown_R(user, group, list, options={})
89
+ chown(user, group, list, options={})
90
+ end
91
+
92
+ def touch(list, options={})
93
+ Array(list).each do |f|
94
+ directory = File.dirname(f)
95
+ # FIXME this explicit check for '.' shouldn't need to happen
96
+ if File.exists?(directory) || directory == '.'
97
+ FileSystem.add(f, FakeFile.new)
98
+ else
99
+ raise Errno::ENOENT, f
100
+ end
101
+ end
102
+ end
103
+
104
+ def cd(dir)
105
+ FileSystem.chdir(dir)
106
+ end
107
+ alias_method :chdir, :cd
108
+ end
109
+ 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
data/lib/fakefs.rb ADDED
@@ -0,0 +1,3 @@
1
+ require 'fakefs/safe'
2
+
3
+ FakeFS.activate!
@@ -0,0 +1,543 @@
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_can_create_directories_with_mkpath
30
+ FileUtils.mkpath("/path/to/dir")
31
+ assert_kind_of FakeDir, FileSystem.fs['path']['to']['dir']
32
+ end
33
+
34
+ def test_knows_directories_exist
35
+ FileUtils.mkdir_p(path = "/path/to/dir")
36
+ assert File.exists?(path)
37
+ end
38
+
39
+ def test_knows_directories_are_directories
40
+ FileUtils.mkdir_p(path = "/path/to/dir")
41
+ assert File.directory?(path)
42
+ end
43
+
44
+ def test_knows_symlink_directories_are_directories
45
+ FileUtils.mkdir_p(path = "/path/to/dir")
46
+ FileUtils.ln_s path, sympath = '/sympath'
47
+ assert File.directory?(sympath)
48
+ end
49
+
50
+ def test_knows_non_existent_directories_arent_directories
51
+ path = 'does/not/exist/'
52
+ assert_equal RealFile.directory?(path), File.directory?(path)
53
+ end
54
+
55
+ def test_doesnt_overwrite_existing_directories
56
+ FileUtils.mkdir_p(path = "/path/to/dir")
57
+ assert File.exists?(path)
58
+ FileUtils.mkdir_p("/path/to")
59
+ assert File.exists?(path)
60
+ end
61
+
62
+ def test_can_create_symlinks
63
+ FileUtils.mkdir_p(target = "/path/to/target")
64
+ FileUtils.ln_s(target, "/path/to/link")
65
+ assert_kind_of FakeSymlink, FileSystem.fs['path']['to']['link']
66
+
67
+ assert_raises(Errno::EEXIST) {
68
+ FileUtils.ln_s(target, '/path/to/link')
69
+ }
70
+ end
71
+
72
+ def test_can_follow_symlinks
73
+ FileUtils.mkdir_p(target = "/path/to/target")
74
+ FileUtils.ln_s(target, link = "/path/to/symlink")
75
+ assert_equal target, File.readlink(link)
76
+ end
77
+
78
+ def test_knows_symlinks_are_symlinks
79
+ FileUtils.mkdir_p(target = "/path/to/target")
80
+ FileUtils.ln_s(target, link = "/path/to/symlink")
81
+ assert File.symlink?(link)
82
+ end
83
+
84
+ def test_can_create_files
85
+ path = '/path/to/file.txt'
86
+ File.open(path, 'w') do |f|
87
+ f.write "Yatta!"
88
+ end
89
+
90
+ assert File.exists?(path)
91
+ end
92
+
93
+ def test_can_read_files_once_written
94
+ path = '/path/to/file.txt'
95
+ File.open(path, 'w') do |f|
96
+ f.write "Yatta!"
97
+ end
98
+
99
+ assert_equal "Yatta!", File.read(path)
100
+ end
101
+
102
+ def test_can_write_to_files
103
+ path = '/path/to/file.txt'
104
+ File.open(path, 'w') do |f|
105
+ f << 'Yada Yada'
106
+ end
107
+ assert_equal 'Yada Yada', File.read(path)
108
+ end
109
+
110
+ def test_can_read_with_File_readlines
111
+ path = '/path/to/file.txt'
112
+ File.open(path, 'w') do |f|
113
+ f.puts "Yatta!", "Gatta!"
114
+ f.puts ["woot","toot"]
115
+ end
116
+
117
+ assert_equal %w(Yatta! Gatta! woot toot), File.readlines(path)
118
+ end
119
+
120
+ def test_File_close_disallows_further_access
121
+ path = '/path/to/file.txt'
122
+ file = File.open(path, 'w')
123
+ file.write 'Yada'
124
+ file.close
125
+ assert_raise IOError do
126
+ file.read
127
+ end
128
+ end
129
+
130
+ def test_can_read_from_file_objects
131
+ path = '/path/to/file.txt'
132
+ File.open(path, 'w') do |f|
133
+ f.write "Yatta!"
134
+ end
135
+
136
+ assert_equal "Yatta!", File.new(path).read
137
+ end
138
+
139
+ def test_file_read_errors_appropriately
140
+ assert_raise Errno::ENOENT do
141
+ File.read('anything')
142
+ end
143
+ end
144
+
145
+ def test_knows_files_are_files
146
+ path = '/path/to/file.txt'
147
+ File.open(path, 'w') do |f|
148
+ f.write "Yatta!"
149
+ end
150
+
151
+ assert File.file?(path)
152
+ end
153
+
154
+ def test_knows_symlink_files_are_files
155
+ path = '/path/to/file.txt'
156
+ File.open(path, 'w') do |f|
157
+ f.write "Yatta!"
158
+ end
159
+ FileUtils.ln_s path, sympath='/sympath'
160
+
161
+ assert File.file?(sympath)
162
+ end
163
+
164
+ def test_knows_non_existent_files_arent_files
165
+ assert_equal RealFile.file?('does/not/exist.txt'), File.file?('does/not/exist.txt')
166
+ end
167
+
168
+ def test_can_chown_files
169
+ good = 'file.txt'
170
+ bad = 'nofile.txt'
171
+ File.open(good,'w'){|f| f.write "foo" }
172
+
173
+ assert_equal [good], FileUtils.chown('noone', 'nogroup', good, :verbose => true)
174
+ assert_raises(Errno::ENOENT) do
175
+ FileUtils.chown('noone', 'nogroup', bad, :verbose => true)
176
+ end
177
+
178
+ assert_equal [good], FileUtils.chown('noone', 'nogroup', good)
179
+ assert_raises(Errno::ENOENT) do
180
+ FileUtils.chown('noone', 'nogroup', bad)
181
+ end
182
+
183
+ assert_equal [good], FileUtils.chown('noone', 'nogroup', [good])
184
+ assert_raises(Errno::ENOENT) do
185
+ FileUtils.chown('noone', 'nogroup', [good, bad])
186
+ end
187
+ end
188
+
189
+ def test_can_chown_R_files
190
+ FileUtils.mkdir_p '/path/'
191
+ File.open('/path/foo', 'w'){|f| f.write 'foo' }
192
+ File.open('/path/foobar', 'w'){|f| f.write 'foo' }
193
+ resp = FileUtils.chown_R('no', 'no', '/path')
194
+ assert_equal ['/path'], resp
195
+ end
196
+
197
+ def test_dir_globs_paths
198
+ FileUtils.mkdir_p '/path'
199
+ File.open('/path/foo', 'w'){|f| f.write 'foo' }
200
+ File.open('/path/foobar', 'w'){|f| f.write 'foo' }
201
+
202
+ FileUtils.mkdir_p '/path/bar'
203
+ File.open('/path/bar/baz', 'w'){|f| f.write 'foo' }
204
+
205
+ FileUtils.cp_r '/path/bar', '/path/bar2'
206
+
207
+ assert_equal ['/path'], Dir['/path']
208
+ assert_equal %w( /path/bar /path/bar2 /path/foo /path/foobar ), Dir['/path/*']
209
+
210
+ assert_equal ['/path/bar/baz'], Dir['/path/bar/*']
211
+ assert_equal ['/path/foo'], Dir['/path/foo']
212
+
213
+ assert_equal ['/path'], Dir['/path*']
214
+ assert_equal ['/path/foo', '/path/foobar'], Dir['/p*h/foo*']
215
+ assert_equal ['/path/foo', '/path/foobar'], Dir['/p??h/foo*']
216
+
217
+ FileUtils.cp_r '/path', '/otherpath'
218
+
219
+ assert_equal %w( /otherpath/foo /otherpath/foobar /path/foo /path/foobar ), Dir['/*/foo*']
220
+ end
221
+
222
+ def test_dir_glob_handles_root
223
+ FileUtils.mkdir_p '/path'
224
+
225
+ # this fails. the root dir should be named '/' but it is '.'
226
+ #assert_equal ['/'], Dir['/']
227
+ end
228
+
229
+ def test_chdir_changes_directories_like_a_boss
230
+ # I know memes!
231
+ FileUtils.mkdir_p '/path'
232
+ assert_equal '.', FileSystem.fs.name
233
+ assert_equal({}, FileSystem.fs['path'])
234
+ Dir.chdir '/path' do
235
+ File.open('foo', 'w'){|f| f.write 'foo'}
236
+ File.open('foobar', 'w'){|f| f.write 'foo'}
237
+ end
238
+
239
+ assert_equal '.', FileSystem.fs.name
240
+ assert_equal(['foo', 'foobar'], FileSystem.fs['path'].keys.sort)
241
+
242
+ c = nil
243
+ Dir.chdir '/path' do
244
+ c = File.open('foo', 'r'){|f| f.read }
245
+ end
246
+
247
+ assert_equal 'foo', c
248
+ end
249
+
250
+ def test_chdir_shouldnt_keep_us_from_absolute_paths
251
+ FileUtils.mkdir_p '/path'
252
+
253
+ Dir.chdir '/path' do
254
+ File.open('foo', 'w'){|f| f.write 'foo'}
255
+ File.open('/foobar', 'w'){|f| f.write 'foo'}
256
+ end
257
+ assert_equal ['foo'], FileSystem.fs['path'].keys.sort
258
+ assert_equal ['foobar', 'path'], FileSystem.fs.keys.sort
259
+
260
+ Dir.chdir '/path' do
261
+ FileUtils.rm('foo')
262
+ FileUtils.rm('/foobar')
263
+ end
264
+
265
+ assert_equal [], FileSystem.fs['path'].keys.sort
266
+ assert_equal ['path'], FileSystem.fs.keys.sort
267
+ end
268
+
269
+ def test_chdir_should_be_nestable
270
+ FileUtils.mkdir_p '/path/me'
271
+ Dir.chdir '/path' do
272
+ File.open('foo', 'w'){|f| f.write 'foo'}
273
+ Dir.chdir 'me' do
274
+ File.open('foobar', 'w'){|f| f.write 'foo'}
275
+ end
276
+ end
277
+
278
+ assert_equal ['foo','me'], FileSystem.fs['path'].keys.sort
279
+ assert_equal ['foobar'], FileSystem.fs['path']['me'].keys.sort
280
+ end
281
+
282
+ def test_chdir_should_flop_over_and_die_if_the_dir_doesnt_exist
283
+ assert_raise(Errno::ENOENT) do
284
+ Dir.chdir('/nope') do
285
+ 1
286
+ end
287
+ end
288
+ end
289
+
290
+ def test_chdir_shouldnt_lose_state_because_of_errors
291
+ FileUtils.mkdir_p '/path'
292
+
293
+ Dir.chdir '/path' do
294
+ File.open('foo', 'w'){|f| f.write 'foo'}
295
+ File.open('foobar', 'w'){|f| f.write 'foo'}
296
+ end
297
+
298
+ begin
299
+ Dir.chdir('/path') do
300
+ raise Exception
301
+ end
302
+ rescue Exception # hardcore
303
+ end
304
+
305
+ Dir.chdir('/path') do
306
+ begin
307
+ Dir.chdir('nope'){ }
308
+ rescue Errno::ENOENT
309
+ end
310
+
311
+ assert_equal ['/path'], FileSystem.dir_levels
312
+ end
313
+
314
+ assert_equal(['foo', 'foobar'], FileSystem.fs['path'].keys.sort)
315
+ end
316
+
317
+ def test_chdir_with_no_block_is_awesome
318
+ FileUtils.mkdir_p '/path'
319
+ Dir.chdir('/path')
320
+ FileUtils.mkdir_p 'subdir'
321
+ assert_equal ['subdir'], FileSystem.current_dir.keys
322
+ Dir.chdir('subdir')
323
+ File.open('foo', 'w'){|f| f.write 'foo'}
324
+ assert_equal ['foo'], FileSystem.current_dir.keys
325
+
326
+ assert_raises(Errno::ENOENT) do
327
+ Dir.chdir('subsubdir')
328
+ end
329
+
330
+ assert_equal ['foo'], FileSystem.current_dir.keys
331
+ end
332
+
333
+ def test_current_dir_reflected_by_pwd
334
+ FileUtils.mkdir_p '/path'
335
+ Dir.chdir('/path')
336
+
337
+ assert_equal '/path', Dir.pwd
338
+ assert_equal '/path', Dir.getwd
339
+
340
+ FileUtils.mkdir_p 'subdir'
341
+ Dir.chdir('subdir')
342
+
343
+ assert_equal '/path/subdir', Dir.pwd
344
+ assert_equal '/path/subdir', Dir.getwd
345
+ end
346
+
347
+ def test_file_open_defaults_to_read
348
+ File.open('foo','w'){|f| f.write 'bar' }
349
+ assert_equal 'bar', File.open('foo'){|f| f.read }
350
+ end
351
+
352
+ def test_flush_exists_on_file
353
+ r = File.open('foo','w'){|f| f.write 'bar'; f.flush }
354
+ assert_equal 'foo', r.path
355
+ end
356
+
357
+ def test_mv_should_raise_error_on_missing_file
358
+ assert_raise(Errno::ENOENT) do
359
+ FileUtils.mv 'blafgag', 'foo'
360
+ end
361
+ end
362
+
363
+ def test_mv_actually_works
364
+ File.open('foo', 'w') {|f| f.write 'bar' }
365
+ FileUtils.mv 'foo', 'baz'
366
+ assert_equal 'bar', File.open('baz'){|f| f.read }
367
+ end
368
+
369
+ def test_cp_actually_works
370
+ File.open('foo', 'w') {|f| f.write 'bar' }
371
+ FileUtils.cp('foo', 'baz')
372
+ assert_equal 'bar', File.read('baz')
373
+ end
374
+
375
+ def test_cp_file_into_dir
376
+ File.open('foo', 'w') {|f| f.write 'bar' }
377
+ FileUtils.mkdir_p 'baz'
378
+
379
+ FileUtils.cp('foo', 'baz')
380
+ assert_equal 'bar', File.read('baz/foo')
381
+ end
382
+
383
+ def test_cp_overwrites_dest_file
384
+ File.open('foo', 'w') {|f| f.write 'FOO' }
385
+ File.open('bar', 'w') {|f| f.write 'BAR' }
386
+
387
+ FileUtils.cp('foo', 'bar')
388
+ assert_equal 'FOO', File.read('bar')
389
+ end
390
+
391
+ def test_cp_fails_on_no_source
392
+ assert_raise Errno::ENOENT do
393
+ FileUtils.cp('foo', 'baz')
394
+ end
395
+ end
396
+
397
+ def test_cp_fails_on_directory_copy
398
+ FileUtils.mkdir_p 'baz'
399
+
400
+ assert_raise Errno::EISDIR do
401
+ FileUtils.cp('baz', 'bar')
402
+ end
403
+ end
404
+
405
+ def test_cp_r_doesnt_tangle_files_together
406
+ File.open('foo', 'w') {|f| f.write 'bar' }
407
+ FileUtils.cp_r('foo', 'baz')
408
+ File.open('baz', 'w') {|f| f.write 'quux' }
409
+ assert_equal 'bar', File.open('foo'){|f| f.read }
410
+ end
411
+
412
+ def test_cp_r_should_raise_error_on_missing_file
413
+ # Yes, this error sucks, but it conforms to the original Ruby
414
+ # method.
415
+ assert_raise(RuntimeError) do
416
+ FileUtils.cp_r 'blafgag', 'foo'
417
+ end
418
+ end
419
+
420
+ def test_cp_r_handles_copying_directories
421
+ FileUtils.mkdir_p 'subdir'
422
+ Dir.chdir('subdir'){ File.open('foo', 'w'){|f| f.write 'footext' } }
423
+
424
+ FileUtils.mkdir_p 'baz'
425
+
426
+ # To a previously uncreated directory
427
+ FileUtils.cp_r('subdir', 'quux')
428
+ assert_equal 'footext', File.open('quux/foo'){|f| f.read }
429
+
430
+ # To a directory that already exists
431
+ FileUtils.cp_r('subdir', 'baz')
432
+ assert_equal 'footext', File.open('baz/subdir/foo'){|f| f.read }
433
+
434
+ # To a subdirectory of a directory that does not exist
435
+ assert_raises(Errno::ENOENT) {
436
+ FileUtils.cp_r('subdir', 'nope/something')
437
+ }
438
+ end
439
+
440
+ def test_cp_r_only_copies_into_directories
441
+ FileUtils.mkdir_p 'subdir'
442
+ Dir.chdir('subdir'){ File.open('foo', 'w'){|f| f.write 'footext' } }
443
+
444
+ File.open('bar', 'w') {|f| f.write 'bartext' }
445
+
446
+ assert_raises(Errno::EEXIST) do
447
+ FileUtils.cp_r 'subdir', 'bar'
448
+ end
449
+
450
+ FileUtils.mkdir_p 'otherdir'
451
+ FileUtils.ln_s 'otherdir', 'symdir'
452
+
453
+ FileUtils.cp_r 'subdir', 'symdir'
454
+ assert_equal 'footext', File.open('symdir/subdir/foo'){|f| f.read }
455
+ end
456
+
457
+ def test_cp_r_sets_parent_correctly
458
+ FileUtils.mkdir_p '/path/foo'
459
+ File.open('/path/foo/bar', 'w'){|f| f.write 'foo' }
460
+ File.open('/path/foo/baz', 'w'){|f| f.write 'foo' }
461
+
462
+ FileUtils.cp_r '/path/foo', '/path/bar'
463
+
464
+ assert File.exists?('/path/bar/baz')
465
+ FileUtils.rm_rf '/path/bar/baz'
466
+ assert_equal %w( /path/bar/bar ), Dir['/path/bar/*']
467
+ end
468
+
469
+ def test_clone_clones_normal_files
470
+ RealFile.open(here('foo'), 'w'){|f| f.write 'bar' }
471
+ assert !File.exists?(here('foo'))
472
+ FileSystem.clone(here('foo'))
473
+ assert_equal 'bar', File.open(here('foo')){|f| f.read }
474
+ ensure
475
+ RealFile.unlink(here('foo')) if RealFile.exists?(here('foo'))
476
+ end
477
+
478
+ def test_clone_clones_directories
479
+ RealFileUtils.mkdir_p(here('subdir'))
480
+
481
+ FileSystem.clone(here('subdir'))
482
+
483
+ assert File.exists?(here('subdir')), 'subdir was cloned'
484
+ assert File.directory?(here('subdir')), 'subdir is a directory'
485
+ ensure
486
+ RealFileUtils.rm_rf(here('subdir')) if RealFile.exists?(here('subdir'))
487
+ end
488
+
489
+ def test_clone_clones_dot_files_even_hard_to_find_ones
490
+ RealFileUtils.mkdir_p(here('subdir/.bar/baz/.quux/foo'))
491
+ assert !File.exists?(here('subdir'))
492
+
493
+ FileSystem.clone(here('subdir'))
494
+ assert_equal ['.bar'], FileSystem.find(here('subdir')).keys
495
+ assert_equal ['foo'], FileSystem.find(here('subdir/.bar/baz/.quux')).keys
496
+ ensure
497
+ RealFileUtils.rm_rf(here('subdir')) if RealFile.exists?(here('subdir'))
498
+ end
499
+
500
+ def test_putting_a_dot_at_end_copies_the_contents
501
+ FileUtils.mkdir_p 'subdir'
502
+ Dir.chdir('subdir'){ File.open('foo', 'w'){|f| f.write 'footext' } }
503
+
504
+ FileUtils.mkdir_p 'newdir'
505
+ FileUtils.cp_r 'subdir/.', 'newdir'
506
+ assert_equal 'footext', File.open('newdir/foo'){|f| f.read }
507
+ end
508
+
509
+ def test_file_can_read_from_symlinks
510
+ File.open('first', 'w'){|f| f.write '1'}
511
+ FileUtils.ln_s 'first', 'one'
512
+ assert_equal '1', File.open('one'){|f| f.read }
513
+
514
+ FileUtils.mkdir_p 'subdir'
515
+ File.open('subdir/nother','w'){|f| f.write 'works' }
516
+ FileUtils.ln_s 'subdir', 'new'
517
+ assert_equal 'works', File.open('new/nother'){|f| f.read }
518
+ end
519
+
520
+ def test_files_can_be_touched
521
+ FileUtils.touch('touched_file')
522
+ assert File.exists?('touched_file')
523
+ list = ['newfile', 'another']
524
+ FileUtils.touch(list)
525
+ list.each { |fp| assert(File.exists?(fp)) }
526
+ end
527
+
528
+ def test_touch_does_not_work_if_the_dir_path_cannot_be_found
529
+ assert_raises(Errno::ENOENT) {
530
+ FileUtils.touch('this/path/should/not/be/here')
531
+ }
532
+ FileUtils.mkdir_p('subdir')
533
+ list = ['subdir/foo', 'nosubdir/bar']
534
+
535
+ assert_raises(Errno::ENOENT) {
536
+ FileUtils.touch(list)
537
+ }
538
+ end
539
+
540
+ def here(fname)
541
+ RealFile.expand_path(RealFile.dirname(__FILE__)+'/'+fname)
542
+ end
543
+ end
data/test/safe_test.rb ADDED
@@ -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
data/test/verify.rb ADDED
@@ -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
data/version.yml ADDED
@@ -0,0 +1,4 @@
1
+ ---
2
+ :major: 0
3
+ :minor: 0
4
+ :patch: 1
metadata ADDED
@@ -0,0 +1,74 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: rsanheim-fakefs
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.0.1
5
+ platform: ruby
6
+ authors:
7
+ - Chris Wanstrath
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+
12
+ date: 2009-09-12 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
+ - version.yml
44
+ has_rdoc: false
45
+ homepage: http://github.com/defunkt/fakefs
46
+ licenses:
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