fakefs 0.1.0

Sign up to get free protection for your applications and to get access to all the features.
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