mnoble-fakefs 0.3.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.
@@ -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