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 +20 -0
- data/README.markdown +68 -0
- data/Rakefile +40 -0
- data/lib/fakefs.rb +3 -0
- data/lib/fakefs/base.rb +37 -0
- data/lib/fakefs/dir.rb +23 -0
- data/lib/fakefs/fake/dir.rb +37 -0
- data/lib/fakefs/fake/file.rb +29 -0
- data/lib/fakefs/fake/symlink.rb +26 -0
- data/lib/fakefs/file.rb +124 -0
- data/lib/fakefs/file_system.rb +118 -0
- data/lib/fakefs/fileutils.rb +108 -0
- data/lib/fakefs/safe.rb +11 -0
- data/lib/fakefs/version.rb +9 -0
- data/test/fakefs_test.rb +538 -0
- data/test/safe_test.rb +20 -0
- data/test/verify.rb +27 -0
- metadata +74 -0
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,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
|
data/lib/fakefs.rb
ADDED
data/lib/fakefs/base.rb
ADDED
@@ -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
|
data/lib/fakefs/file.rb
ADDED
@@ -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
|
data/lib/fakefs/safe.rb
ADDED
@@ -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
|
+
|
data/test/fakefs_test.rb
ADDED
@@ -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
|
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
|
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
|