madpilot-fakefs 0.1.2

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.
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