madpilot-fakefs 0.1.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
data/LICENSE ADDED
@@ -0,0 +1,20 @@
1
+ Copyright (c) 2009 Chris Wanstrath
2
+
3
+ Permission is hereby granted, free of charge, to any person obtaining
4
+ a copy of this software and associated documentation files (the
5
+ "Software"), to deal in the Software without restriction, including
6
+ without limitation the rights to use, copy, modify, merge, publish,
7
+ distribute, sublicense, and/or sell copies of the Software, and to
8
+ permit persons to whom the Software is furnished to do so, subject to
9
+ the following conditions:
10
+
11
+ The above copyright notice and this permission notice shall be
12
+ included in all copies or substantial portions of the Software.
13
+
14
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
15
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
16
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
17
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
18
+ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
19
+ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
20
+ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
data/README.markdown ADDED
@@ -0,0 +1,68 @@
1
+ FakeFS
2
+ ======
3
+
4
+ Mocha is great. But when your library is all about manipulating the
5
+ filesystem, you really want to test the behavior and not the implementation.
6
+
7
+ If you're mocking and stubbing every call to FileUtils or File, you're
8
+ tightly coupling your tests with the implementation.
9
+
10
+ def test_creates_directory
11
+ FileUtils.expects(:mkdir).with("directory").once
12
+ Library.add "directory"
13
+ end
14
+
15
+ The above test will break if we decide to use `mkdir_p` in our code. Refactoring
16
+ code shouldn't necessitate refactoring tests.
17
+
18
+ With FakeFS:
19
+
20
+ def test_creates_directory
21
+ Library.add "directory"
22
+ assert File.directory?("directory")
23
+ end
24
+
25
+ Woot.
26
+
27
+
28
+ Usage
29
+ -----
30
+
31
+ require 'fakefs'
32
+
33
+ # That's it.
34
+
35
+
36
+ Don't Fake the FS Immediately
37
+ -----------------------------
38
+
39
+ require 'fakefs/safe'
40
+
41
+ FakeFS.activate!
42
+ # your code
43
+ FakeFS.deactivate!
44
+
45
+ # or
46
+ FakeFS do
47
+ # your code
48
+ end
49
+
50
+
51
+ How is this different than MockFS?
52
+ ----------------------------------
53
+
54
+ FakeFS provides a test suite and works with symlinks. It's also strictly a
55
+ test-time dependency: your actual library does not need to use or know about
56
+ FakeFS.
57
+
58
+
59
+ Speed?
60
+ ------
61
+ http://gist.github.com/156091
62
+
63
+
64
+ Authors
65
+ -------
66
+
67
+ * Chris Wanstrath [chris@ozmm.org]
68
+ * Pat Nakajima [http://github.com/nakajima]
data/Rakefile ADDED
@@ -0,0 +1,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,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,114 @@
1
+ module FakeFS
2
+ class Dir
3
+ include Enumerable
4
+
5
+ def initialize(string)
6
+ raise Errno::ENOENT, string unless FileSystem.find(string)
7
+ @path = string
8
+ @open = true
9
+ @pointer = 0
10
+ @contents = [ '.', '..', ] + FileSystem.find(@path).values
11
+ end
12
+
13
+ def close
14
+ @open = false
15
+ @pointer = nil
16
+ @contents = nil
17
+ nil
18
+ end
19
+
20
+ def each(&block)
21
+ while f = read
22
+ yield f
23
+ end
24
+ end
25
+
26
+ def path
27
+ @path
28
+ end
29
+
30
+ def pos
31
+ @pointer
32
+ end
33
+
34
+ def pos=(integer)
35
+ @pointer = integer
36
+ end
37
+
38
+ def read
39
+ raise IOError, "closed directory" if @pointer == nil
40
+ n = @contents[@pointer]
41
+ @pointer += 1
42
+ n.to_s if n
43
+ end
44
+
45
+ def rewind
46
+ @pointer = 0
47
+ end
48
+
49
+ def seek(integer)
50
+ raise IOError, "closed directory" if @pointer == nil
51
+ @pointer = integer
52
+ @contents[integer]
53
+ end
54
+
55
+ def self.[](pattern)
56
+ glob(pattern)
57
+ end
58
+
59
+ def self.chdir(dir, &blk)
60
+ FileSystem.chdir(dir, &blk)
61
+ end
62
+
63
+ def self.chroot(string)
64
+ # Not implemented yet
65
+ end
66
+
67
+ def self.delete(string)
68
+ raise SystemCallError, "No such file or directory - #{string}" unless FileSystem.find(string).values.empty?
69
+ FileSystem.delete(string)
70
+ end
71
+
72
+ def self.entries(dirname)
73
+ raise SystemCallError, dirname unless FileSystem.find(dirname)
74
+ Dir.new(dirname).map { |file| file }
75
+ end
76
+
77
+ def self.foreach(dirname, &block)
78
+ Dir.open(dirname) { |file| yield file }
79
+ end
80
+
81
+ def self.glob(pattern)
82
+ [FileSystem.find(pattern) || []].flatten.map{|e| e.to_s}.sort
83
+ end
84
+
85
+ def self.mkdir(string, integer = 0)
86
+ parent = string.split('/')
87
+ parent.pop
88
+ raise Errno::ENOENT, "No such file or directory - #{string}" unless parent.join == "" || FileSystem.find(parent.join('/'))
89
+ FileUtils.mkdir_p(string)
90
+ end
91
+
92
+ def self.open(string, &block)
93
+ if block_given?
94
+ Dir.new(string).each { |file| yield(file) }
95
+ else
96
+ Dir.new(string)
97
+ end
98
+ end
99
+
100
+ def tmpdir
101
+ '/tmp'
102
+ end
103
+
104
+ def self.pwd
105
+ FileSystem.current_dir.to_s
106
+ end
107
+
108
+ class << self
109
+ alias_method :getwd, :pwd
110
+ alias_method :rmdir, :delete
111
+ alias_method :unline, :delete
112
+ end
113
+ end
114
+ end
@@ -0,0 +1,37 @@
1
+ module FakeFS
2
+ class FakeDir < Hash
3
+ attr_accessor :name, :parent
4
+
5
+ def initialize(name = nil, parent = nil)
6
+ @name = name
7
+ @parent = parent
8
+ end
9
+
10
+ def entry
11
+ self
12
+ end
13
+
14
+ def inspect
15
+ "(FakeDir name:#{name.inspect} parent:#{parent.to_s.inspect} size:#{size})"
16
+ end
17
+
18
+ def clone(parent = nil)
19
+ clone = Marshal.load(Marshal.dump(self))
20
+ clone.each do |key, value|
21
+ value.parent = clone
22
+ end
23
+ clone.parent = parent if parent
24
+ clone
25
+ end
26
+
27
+ def to_s
28
+ if parent && parent.to_s != '.'
29
+ File.join(parent.to_s, name)
30
+ elsif parent && parent.to_s == '.'
31
+ "#{File::PATH_SEPARATOR}#{name}"
32
+ else
33
+ name
34
+ end
35
+ end
36
+ end
37
+ end
@@ -0,0 +1,29 @@
1
+ module FakeFS
2
+ class FakeFile
3
+ attr_accessor :name, :parent, :content
4
+
5
+ def initialize(name = nil, parent = nil)
6
+ @name = name
7
+ @parent = parent
8
+ @content = ''
9
+ end
10
+
11
+ def clone(parent = nil)
12
+ clone = super()
13
+ clone.parent = parent if parent
14
+ clone
15
+ end
16
+
17
+ def entry
18
+ self
19
+ end
20
+
21
+ def inspect
22
+ "(FakeFile name:#{name.inspect} parent:#{parent.to_s.inspect} size:#{content.size})"
23
+ end
24
+
25
+ def to_s
26
+ File.join(parent.to_s, name)
27
+ end
28
+ end
29
+ end
@@ -0,0 +1,26 @@
1
+ module FakeFS
2
+ class FakeSymlink
3
+ attr_accessor :name, :target
4
+ alias_method :to_s, :name
5
+
6
+ def initialize(target)
7
+ @target = target
8
+ end
9
+
10
+ def inspect
11
+ "symlink(#{target.split('/').last})"
12
+ end
13
+
14
+ def entry
15
+ FileSystem.find(target)
16
+ end
17
+
18
+ def method_missing(*args, &block)
19
+ entry.send(*args, &block)
20
+ end
21
+
22
+ def respond_to?(method)
23
+ entry.respond_to?(method)
24
+ end
25
+ end
26
+ end
@@ -0,0 +1,126 @@
1
+ module FakeFS
2
+ class File
3
+ PATH_SEPARATOR = '/'
4
+
5
+ def self.join(*parts)
6
+ parts * PATH_SEPARATOR
7
+ end
8
+
9
+ def self.exist?(path)
10
+ !!FileSystem.find(path)
11
+ end
12
+
13
+ class << self
14
+ alias_method :exists?, :exist?
15
+ end
16
+
17
+ def self.const_missing(name)
18
+ RealFile.const_get(name)
19
+ end
20
+
21
+ def self.directory?(path)
22
+ if path.respond_to? :entry
23
+ path.entry.is_a? FakeDir
24
+ else
25
+ result = FileSystem.find(path)
26
+ result ? result.entry.is_a?(FakeDir) : false
27
+ end
28
+ end
29
+
30
+ def self.symlink?(path)
31
+ if path.respond_to? :entry
32
+ path.is_a? FakeSymlink
33
+ else
34
+ FileSystem.find(path).is_a? FakeSymlink
35
+ end
36
+ end
37
+
38
+ def self.file?(path)
39
+ if path.respond_to? :entry
40
+ path.entry.is_a? FakeFile
41
+ else
42
+ result = FileSystem.find(path)
43
+ result ? result.entry.is_a?(FakeFile) : false
44
+ end
45
+ end
46
+
47
+ def self.expand_path(*args)
48
+ RealFile.expand_path(*args)
49
+ end
50
+
51
+ def self.basename(*args)
52
+ RealFile.basename(*args)
53
+ end
54
+
55
+ def self.dirname(path)
56
+ RealFile.dirname(path)
57
+ end
58
+
59
+ def self.readlink(path)
60
+ symlink = FileSystem.find(path)
61
+ FileSystem.find(symlink.target).to_s
62
+ end
63
+
64
+ def self.open(path, mode='r')
65
+ if block_given?
66
+ yield new(path, mode)
67
+ else
68
+ new(path, mode)
69
+ end
70
+ end
71
+
72
+ def self.read(path)
73
+ file = new(path)
74
+ if file.exists?
75
+ file.read
76
+ else
77
+ raise Errno::ENOENT
78
+ end
79
+ end
80
+
81
+ def self.readlines(path)
82
+ read(path).split("\n")
83
+ end
84
+
85
+ attr_reader :path
86
+ def initialize(path, mode = nil)
87
+ @path = path
88
+ @mode = mode
89
+ @file = FileSystem.find(path)
90
+ @open = true
91
+ end
92
+
93
+ def close
94
+ @open = false
95
+ end
96
+
97
+ def read
98
+ raise IOError.new('closed stream') unless @open
99
+ @file.content
100
+ end
101
+
102
+ def exists?
103
+ @file
104
+ end
105
+
106
+ def puts(*content)
107
+ content.flatten.each do |obj|
108
+ write(obj.to_s + "\n")
109
+ end
110
+ end
111
+
112
+ def write(content)
113
+ raise IOError.new('closed stream') unless @open
114
+
115
+ if !File.exists?(@path)
116
+ @file = FileSystem.add(path, FakeFile.new)
117
+ end
118
+
119
+ @file.content += content
120
+ end
121
+ alias_method :print, :write
122
+ alias_method :<<, :write
123
+
124
+ def flush; self; end
125
+ end
126
+ end
@@ -0,0 +1,118 @@
1
+ module FakeFS
2
+ module FileSystem
3
+ extend self
4
+
5
+ def dir_levels
6
+ @dir_levels ||= []
7
+ end
8
+
9
+ def fs
10
+ @fs ||= FakeDir.new('.')
11
+ end
12
+
13
+ def clear
14
+ @dir_levels = nil
15
+ @fs = nil
16
+ end
17
+
18
+ def files
19
+ fs.values
20
+ end
21
+
22
+ def find(path)
23
+ parts = path_parts(normalize_path(path))
24
+ return fs if parts.empty? # '/'
25
+
26
+ entries = find_recurser(fs, parts).flatten
27
+
28
+ case entries.length
29
+ when 0 then nil
30
+ when 1 then entries.first
31
+ else entries
32
+ end
33
+ end
34
+
35
+ def add(path, object=FakeDir.new)
36
+ parts = path_parts(normalize_path(path))
37
+
38
+ d = parts[0...-1].inject(fs) do |dir, part|
39
+ dir[part] ||= FakeDir.new(part, dir)
40
+ end
41
+
42
+ object.name = parts.last
43
+ object.parent = d
44
+ d[parts.last] ||= object
45
+ end
46
+
47
+ # copies directories and files from the real filesystem
48
+ # into our fake one
49
+ def clone(path)
50
+ path = File.expand_path(path)
51
+ pattern = File.join(path, '**', '*')
52
+ files = RealFile.file?(path) ? [path] : [path] + RealDir.glob(pattern, RealFile::FNM_DOTMATCH)
53
+
54
+ files.each do |f|
55
+ if RealFile.file?(f)
56
+ FileUtils.mkdir_p(File.dirname(f))
57
+ File.open(f, 'w') do |g|
58
+ g.print RealFile.open(f){|h| h.read }
59
+ end
60
+ elsif RealFile.directory?(f)
61
+ FileUtils.mkdir_p(f)
62
+ elsif RealFile.symlink?(f)
63
+ FileUtils.ln_s()
64
+ end
65
+ end
66
+ end
67
+
68
+ def delete(path)
69
+ if dir = FileSystem.find(path)
70
+ dir.parent.delete(dir.name)
71
+ end
72
+ end
73
+
74
+ def chdir(dir, &blk)
75
+ new_dir = find(dir)
76
+ dir_levels.push dir if blk
77
+
78
+ raise Errno::ENOENT, dir unless new_dir
79
+
80
+ dir_levels.push dir if !blk
81
+ blk.call if blk
82
+ ensure
83
+ dir_levels.pop if blk
84
+ end
85
+
86
+ def path_parts(path)
87
+ path.split(File::PATH_SEPARATOR).reject { |part| part.empty? }
88
+ end
89
+
90
+ def normalize_path(path)
91
+ if Pathname.new(path).absolute?
92
+ File.expand_path(path)
93
+ else
94
+ parts = dir_levels + [path]
95
+ File.expand_path(File.join(*parts))
96
+ end
97
+ end
98
+
99
+ def current_dir
100
+ find(normalize_path('.'))
101
+ end
102
+
103
+ private
104
+
105
+ def find_recurser(dir, parts)
106
+ return [] unless dir.respond_to? :[]
107
+
108
+ pattern , *parts = parts
109
+ matches = dir.reject {|k,v| /\A#{pattern.gsub('?','.').gsub('*', '.*')}\Z/ !~ k }.values
110
+
111
+ if parts.empty? # we're done recursing
112
+ matches
113
+ else
114
+ matches.map{|entry| find_recurser(entry, parts) }
115
+ end
116
+ end
117
+ end
118
+ end