mnoble-fakefs 0.3.1

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,139 @@
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, File::WRITE_ONLY) 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 node = FileSystem.find(path)
70
+ node.delete
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 = case pattern
110
+ when '**'
111
+ case parts
112
+ when ['*']
113
+ parts = [] # end recursion
114
+ directories_under(dir).map do |d|
115
+ d.values.select{|f| f.is_a?(FakeFile) || f.is_a?(FakeDir) }
116
+ end.flatten.uniq
117
+ when []
118
+ parts = [] # end recursion
119
+ dir.values.flatten.uniq
120
+ else
121
+ directories_under(dir)
122
+ end
123
+ else
124
+ dir.reject {|k,v| /\A#{pattern.gsub('?','.').gsub('*', '.*')}\Z/ !~ k }.values
125
+ end
126
+
127
+ if parts.empty? # we're done recursing
128
+ matches
129
+ else
130
+ matches.map{|entry| find_recurser(entry, parts) }
131
+ end
132
+ end
133
+
134
+ def directories_under(dir)
135
+ children = dir.values.select{|f| f.is_a? FakeDir}
136
+ ([dir] + children + children.map{|c| directories_under(c)}).flatten.uniq
137
+ end
138
+ end
139
+ end
@@ -0,0 +1,7 @@
1
+ module FakeFS
2
+ class FileTest
3
+ def self.exist?(file_name)
4
+ File.exist?(file_name)
5
+ end
6
+ end
7
+ end
@@ -0,0 +1,140 @@
1
+ module FakeFS
2
+ module FileUtils
3
+ extend self
4
+
5
+ def mkdir_p(path, options = {})
6
+ FileSystem.add(path, FakeDir.new)
7
+ end
8
+ alias_method :mkpath, :mkdir_p
9
+
10
+ def mkdir(path)
11
+ parent = path.split('/')
12
+ parent.pop
13
+ raise Errno::ENOENT, "No such file or directory - #{path}" unless parent.join == "" || FileSystem.find(parent.join('/'))
14
+ raise Errno::EEXIST, "File exists - #{path}" if FileSystem.find(path)
15
+ FileSystem.add(path, FakeDir.new)
16
+ end
17
+
18
+ def rmdir(list, options = {})
19
+ list = [ list ] unless list.is_a?(Array)
20
+ list.each do |l|
21
+ parent = l.split('/')
22
+ parent.pop
23
+ raise Errno::ENOENT, "No such file or directory - #{l}" unless parent.join == "" || FileSystem.find(parent.join('/'))
24
+ raise Errno::ENOENT, l unless FileSystem.find(l)
25
+ raise Errno::ENOTEMPTY, l unless FileSystem.find(l).values.empty?
26
+ rm(l)
27
+ end
28
+ end
29
+
30
+ def rm(list, options = {})
31
+ Array(list).each do |path|
32
+ FileSystem.delete(path)
33
+ end
34
+ end
35
+
36
+ alias_method :rm_rf, :rm
37
+ alias_method :rm_r, :rm
38
+ alias_method :rm_f, :rm
39
+
40
+ def ln_s(target, path, options = {})
41
+ options = { :force => false }.merge(options)
42
+ (FileSystem.find(path) and !options[:force]) ? raise(Errno::EEXIST, path) : FileSystem.delete(path)
43
+ FileSystem.add(path, FakeSymlink.new(target))
44
+ end
45
+ def ln_sf(target, path)
46
+ ln_s(target, path, { :force => true })
47
+ end
48
+
49
+ def cp(src, dest)
50
+ dst_file = FileSystem.find(dest)
51
+ src_file = FileSystem.find(src)
52
+
53
+ if !src_file
54
+ raise Errno::ENOENT, src
55
+ end
56
+
57
+ if File.directory? src_file
58
+ raise Errno::EISDIR, src
59
+ end
60
+
61
+ if dst_file && File.directory?(dst_file)
62
+ FileSystem.add(File.join(dest, src), src_file.entry.clone(dst_file))
63
+ else
64
+ FileSystem.delete(dest)
65
+ FileSystem.add(dest, src_file.entry.clone)
66
+ end
67
+ end
68
+
69
+ def cp_r(src, dest)
70
+ # This error sucks, but it conforms to the original Ruby
71
+ # method.
72
+ raise "unknown file type: #{src}" unless dir = FileSystem.find(src)
73
+
74
+ new_dir = FileSystem.find(dest)
75
+
76
+ if new_dir && !File.directory?(dest)
77
+ raise Errno::EEXIST, dest
78
+ end
79
+
80
+ if !new_dir && !FileSystem.find(dest+'/../')
81
+ raise Errno::ENOENT, dest
82
+ end
83
+
84
+ # This last bit is a total abuse and should be thought hard
85
+ # about and cleaned up.
86
+ if new_dir
87
+ if src[-2..-1] == '/.'
88
+ dir.values.each{|f| new_dir[f.name] = f.clone(new_dir) }
89
+ else
90
+ new_dir[dir.name] = dir.entry.clone(new_dir)
91
+ end
92
+ else
93
+ FileSystem.add(dest, dir.entry.clone)
94
+ end
95
+ end
96
+
97
+ def mv(src, dest, options={})
98
+ Array(src).each do |path|
99
+ if target = FileSystem.find(path)
100
+ dest_path = File.directory?(dest) ? File.join(dest, File.basename(path)) : dest
101
+ FileSystem.add(dest_path, target.entry.clone)
102
+ FileSystem.delete(path)
103
+ else
104
+ raise Errno::ENOENT, src
105
+ end
106
+ end
107
+ end
108
+
109
+ def chown(user, group, list, options={})
110
+ list = Array(list)
111
+ list.each do |f|
112
+ unless File.exists?(f)
113
+ raise Errno::ENOENT, f
114
+ end
115
+ end
116
+ list
117
+ end
118
+
119
+ def chown_R(user, group, list, options={})
120
+ chown(user, group, list, options={})
121
+ end
122
+
123
+ def touch(list, options={})
124
+ Array(list).each do |f|
125
+ directory = File.dirname(f)
126
+ # FIXME this explicit check for '.' shouldn't need to happen
127
+ if File.exists?(directory) || directory == '.'
128
+ FileSystem.add(f, FakeFile.new)
129
+ else
130
+ raise Errno::ENOENT, f
131
+ end
132
+ end
133
+ end
134
+
135
+ def cd(dir)
136
+ FileSystem.chdir(dir)
137
+ end
138
+ alias_method :chdir, :cd
139
+ end
140
+ 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/file_test'
11
+ require 'fakefs/dir'
@@ -0,0 +1,46 @@
1
+ # FakeFS::SpecHelpers provides a simple macro for RSpec example groups to turn FakeFS on and off.
2
+ # To use it simply require 'fakefs/spec_helpers', then include FakeFS::SpecHelpers into any
3
+ # example groups that you wish to use FakeFS in. For example:
4
+ #
5
+ # require 'fakefs/spec_helpers'
6
+ #
7
+ # describe "Some specs that deal with files" do
8
+ # include FakeFS::SpecHelpers
9
+ # ...
10
+ # end
11
+ #
12
+ # Alternatively, you can include FakeFS::SpecHelpers in all your example groups using RSpec's
13
+ # configuration block in your spec helper:
14
+ #
15
+ # require 'fakefs/spec_helpers'
16
+ #
17
+ # Spec::Runner.configure do |config|
18
+ # config.include FakeFS::SpecHelpers
19
+ # end
20
+ #
21
+ # If you do the above then use_fakefs will be available in all of your example groups.
22
+ #
23
+ require 'fakefs/safe'
24
+
25
+ module FakeFS
26
+ module SpecHelpers
27
+ def self.extended(example_group)
28
+ example_group.use_fakefs(example_group)
29
+ end
30
+
31
+ def self.included(example_group)
32
+ example_group.extend self
33
+ end
34
+
35
+ def use_fakefs(describe_block)
36
+ describe_block.before :each do
37
+ FakeFS.activate!
38
+ end
39
+
40
+ describe_block.after :each do
41
+ FakeFS.deactivate!
42
+ FakeFS::FileSystem.clear
43
+ end
44
+ end
45
+ end
46
+ end
@@ -0,0 +1,9 @@
1
+ module FakeFS
2
+ module Version
3
+ VERSION = "0.3.1"
4
+
5
+ def self.to_s
6
+ VERSION
7
+ end
8
+ end
9
+ end
@@ -0,0 +1,57 @@
1
+ require 'spec_helper'
2
+
3
+ module FakeFS
4
+ describe SpecHelpers do
5
+ before do
6
+ @rspec_example_group = Class.new do
7
+ def self.before(sym = :each)
8
+ yield if block_given?
9
+ end
10
+
11
+ def self.after(sym = :each)
12
+ yield if block_given?
13
+ end
14
+ end
15
+ end
16
+
17
+ describe "when extending" do
18
+ context "before each" do
19
+ it "should call it" do
20
+ @rspec_example_group.should_receive(:before).with(:each)
21
+ @rspec_example_group.extend FakeFS::SpecHelpers
22
+ end
23
+
24
+ it "should call FakeFS.activate!" do
25
+ FakeFS.should_receive(:activate!)
26
+ @rspec_example_group.extend FakeFS::SpecHelpers
27
+ end
28
+ end
29
+
30
+ context "after each" do
31
+ it "should call it" do
32
+ @rspec_example_group.should_receive(:after).with(:each)
33
+ @rspec_example_group.extend FakeFS::SpecHelpers
34
+ end
35
+
36
+ it "should deactivate fakefs" do
37
+ FakeFS.should_receive(:deactivate!)
38
+ @rspec_example_group.extend FakeFS::SpecHelpers
39
+ end
40
+
41
+ it "should clear the fakefs filesystem for the next run" do
42
+ FakeFS::FileSystem.should_receive(:clear)
43
+ @rspec_example_group.extend FakeFS::SpecHelpers
44
+ end
45
+ end
46
+ end
47
+
48
+ describe "when including" do
49
+ it "should call before :each" do
50
+ @rspec_example_group.should_receive(:before)
51
+ @rspec_example_group.class_eval do
52
+ include FakeFS::SpecHelpers
53
+ end
54
+ end
55
+ end
56
+ end
57
+ end
@@ -0,0 +1 @@
1
+ --color
@@ -0,0 +1,3 @@
1
+ $LOAD_PATH.unshift File.join(File.dirname(__FILE__), '..', 'lib')
2
+
3
+ require 'fakefs/spec_helpers'
@@ -0,0 +1,59 @@
1
+ require "test_helper"
2
+
3
+ class FileStat < Test::Unit::TestCase
4
+ def setup
5
+ FakeFS.activate!
6
+ FakeFS::FileSystem.clear
7
+ end
8
+
9
+ def teardown
10
+ FakeFS.deactivate!
11
+ end
12
+
13
+ def test_calling_lstat_should_create_a_new_file_stat_object
14
+ File.open("foo", "w") do |f|
15
+ f << "bar"
16
+ end
17
+
18
+ File.open("foo") do |f|
19
+ assert_equal File::Stat, f.lstat.class
20
+ end
21
+ end
22
+
23
+ def test_lstat_should_use_correct_file
24
+ File.open("bar", "w") do |f|
25
+ f << "1"
26
+ end
27
+
28
+ File.open("bar") do |f|
29
+ assert_equal 1, f.lstat.size
30
+ end
31
+ end
32
+
33
+ def test_lstat_should_report_on_symlink_itself
34
+ File.open("foo", "w") { |f| f << "some content" }
35
+ File.symlink "foo", "my_symlink"
36
+
37
+ assert_not_equal File.lstat("my_symlink").size, File.lstat("foo").size
38
+ end
39
+
40
+ def test_should_report_on_symlink_itself_with_size_instance_method
41
+ File.open("foo", "w") { |f| f << "some content" }
42
+ File.symlink "foo", "my_symlink"
43
+
44
+ file = File.open("foo")
45
+ symlink = File.open("my_symlink")
46
+
47
+ assert_not_equal file.lstat.size, symlink.lstat.size
48
+ end
49
+
50
+ def test_symlink_size_is_size_of_path_pointed_to
51
+ File.open("a", "w") { |x| x << "foobarbazfoobarbaz" }
52
+ File.symlink "a", "one_char_symlink"
53
+ assert_equal 1, File.lstat("one_char_symlink").size
54
+
55
+ File.open("ab", "w") { |x| x << "foobarbazfoobarbaz" }
56
+ File.symlink "ab", "two_char_symlink"
57
+ assert_equal 2, File.lstat("two_char_symlink").size
58
+ end
59
+ end