virtfs 0.0.1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (91) hide show
  1. checksums.yaml +7 -0
  2. data/.gitignore +18 -0
  3. data/.rspec +2 -0
  4. data/.travis.yml +8 -0
  5. data/Gemfile +4 -0
  6. data/LICENSE.txt +22 -0
  7. data/README.md +154 -0
  8. data/Rakefile +5 -0
  9. data/lib/virtfs-nativefs-thick.rb +1 -0
  10. data/lib/virtfs-nativefs-thin.rb +1 -0
  11. data/lib/virtfs.rb +38 -0
  12. data/lib/virtfs/activation.rb +97 -0
  13. data/lib/virtfs/block_io.rb +140 -0
  14. data/lib/virtfs/byte_range.rb +71 -0
  15. data/lib/virtfs/context.rb +300 -0
  16. data/lib/virtfs/context_manager.rb +175 -0
  17. data/lib/virtfs/context_switch_class_methods.rb +96 -0
  18. data/lib/virtfs/delegate_module.rb +40 -0
  19. data/lib/virtfs/dir_instance_delegate.rb +3 -0
  20. data/lib/virtfs/exception.rb +13 -0
  21. data/lib/virtfs/file_instance_delegate.rb +3 -0
  22. data/lib/virtfs/file_modes_and_options.rb +293 -0
  23. data/lib/virtfs/find_class_methods.rb +106 -0
  24. data/lib/virtfs/io_buffer.rb +133 -0
  25. data/lib/virtfs/io_instance_delegate.rb +3 -0
  26. data/lib/virtfs/kernel.rb +146 -0
  27. data/lib/virtfs/nativefs/thick.rb +30 -0
  28. data/lib/virtfs/nativefs/thick/dir_class_methods.rb +38 -0
  29. data/lib/virtfs/nativefs/thick/file_class_methods.rb +178 -0
  30. data/lib/virtfs/nativefs/thin.rb +32 -0
  31. data/lib/virtfs/nativefs/thin/dir.rb +30 -0
  32. data/lib/virtfs/nativefs/thin/dir_class_methods.rb +41 -0
  33. data/lib/virtfs/nativefs/thin/file.rb +112 -0
  34. data/lib/virtfs/nativefs/thin/file_class_methods.rb +181 -0
  35. data/lib/virtfs/protofs/protofs.rb +7 -0
  36. data/lib/virtfs/protofs/protofs_base.rb +12 -0
  37. data/lib/virtfs/protofs/protofs_dir.rb +13 -0
  38. data/lib/virtfs/protofs/protofs_dir_class.rb +31 -0
  39. data/lib/virtfs/protofs/protofs_file.rb +27 -0
  40. data/lib/virtfs/protofs/protofs_file_class.rb +136 -0
  41. data/lib/virtfs/stat.rb +100 -0
  42. data/lib/virtfs/thin_dir_delegator.rb +79 -0
  43. data/lib/virtfs/thin_file_delegator.rb +77 -0
  44. data/lib/virtfs/thin_io_delegator_methods.rb +301 -0
  45. data/lib/virtfs/thin_io_delegator_methods_bufferio.rb +337 -0
  46. data/lib/virtfs/v_dir.rb +238 -0
  47. data/lib/virtfs/v_file.rb +480 -0
  48. data/lib/virtfs/v_io.rb +243 -0
  49. data/lib/virtfs/v_pathname.rb +128 -0
  50. data/lib/virtfs/version.rb +3 -0
  51. data/spec/activate_spec.rb +202 -0
  52. data/spec/chroot_spec.rb +120 -0
  53. data/spec/context_manager_class_spec.rb +246 -0
  54. data/spec/context_manager_instance_spec.rb +255 -0
  55. data/spec/context_spec.rb +335 -0
  56. data/spec/data/UTF-16LE-data.txt +0 -0
  57. data/spec/data/UTF-8-data.txt +212 -0
  58. data/spec/dir_class_spec.rb +506 -0
  59. data/spec/dir_instance_spec.rb +208 -0
  60. data/spec/file_class_spec.rb +2106 -0
  61. data/spec/file_instance_spec.rb +154 -0
  62. data/spec/file_modes_and_options_spec.rb +1556 -0
  63. data/spec/find_spec.rb +142 -0
  64. data/spec/io_bufferio_size_shared_examples.rb +371 -0
  65. data/spec/io_bufferio_size_spec.rb +861 -0
  66. data/spec/io_bufferio_spec.rb +801 -0
  67. data/spec/io_class_spec.rb +145 -0
  68. data/spec/io_instance_spec.rb +516 -0
  69. data/spec/kernel_spec.rb +285 -0
  70. data/spec/mount_spec.rb +186 -0
  71. data/spec/nativefs_local_root_spec.rb +132 -0
  72. data/spec/path_spec.rb +39 -0
  73. data/spec/spec_helper.rb +126 -0
  74. data/tasks/rspec.rake +3 -0
  75. data/tasks/yard.rake +7 -0
  76. data/test/UTF-8-demo.txt +212 -0
  77. data/test/bench.rb +18 -0
  78. data/test/bio_internal_test.rb +45 -0
  79. data/test/delegate_io.rb +31 -0
  80. data/test/delegate_module.rb +62 -0
  81. data/test/encode_test.rb +42 -0
  82. data/test/enoent_test.rb +30 -0
  83. data/test/namespace_test.rb +42 -0
  84. data/test/read_block_valid_encoding.rb +44 -0
  85. data/test/read_test.rb +78 -0
  86. data/test/stream_readers.rb +46 -0
  87. data/test/utf-16-demo.txt +0 -0
  88. data/test/utf8_to_utf16.rb +77 -0
  89. data/test/wrapper_test.rb +34 -0
  90. data/virtfs.gemspec +29 -0
  91. metadata +230 -0
@@ -0,0 +1,120 @@
1
+ require 'spec_helper'
2
+
3
+ describe "VirtFS.dir_chroot (#{$fs_interface} interface)" do
4
+ before(:all) do
5
+ @full_path = VfsRealFile.expand_path(__FILE__)
6
+ @this_dir = VfsRealFile.expand_path(__dir__)
7
+ @root = File::SEPARATOR
8
+
9
+ @new_root = VfsRealFile.expand_path(VfsRealFile.join(__dir__, ".."))
10
+ @new_this_dir = VfsRealFile.expand_path(VfsRealFile.join("/", VfsRealFile.basename(__dir__)))
11
+ @new_full_path = VfsRealFile.expand_path(VfsRealFile.join(@new_this_dir, VfsRealFile.basename(__FILE__)))
12
+ end
13
+
14
+ before(:each) do
15
+ reset_context
16
+ @native_fs = nativefs_class.new
17
+ VirtFS.mount(@native_fs, @root)
18
+ end
19
+
20
+ describe "Dir.chroot" do
21
+ it "should raise Errno::ENOENT when directory does exist" do
22
+ expect do
23
+ VirtFS::VDir.chroot("/not_a_dir/foo.d")
24
+ end.to raise_error(
25
+ Errno::ENOENT, /No such file or directory/
26
+ )
27
+ end
28
+
29
+ it "should return 0 on success" do
30
+ expect(VirtFS::VDir.chroot(@this_dir)).to eq(0)
31
+ end
32
+
33
+ it "should set the value of root accordingly" do
34
+ VirtFS::VDir.chroot(@new_root)
35
+ expect(VirtFS.root).to eq(@new_root)
36
+ end
37
+
38
+ it "should set the current directory to '/'" do
39
+ VirtFS::VDir.chroot(@new_root)
40
+ expect(VirtFS::VDir.getwd).to eq(File::SEPARATOR)
41
+ end
42
+
43
+ it "should find directory through new full path" do
44
+ VirtFS::VDir.chroot(@new_root)
45
+ expect(VirtFS::VDir.exist?(@new_this_dir)).to be true
46
+ end
47
+
48
+ it "should find file through new full path" do
49
+ VirtFS::VDir.chroot(@new_root)
50
+ expect(VirtFS::VFile.exist?(@new_full_path)).to be true
51
+ end
52
+ end
53
+
54
+ describe "Dir.chdir" do
55
+ before(:all) do
56
+ @parent_dir = @new_root
57
+ @child_dir = @this_dir
58
+ @rel_child_dir_name = VfsRealFile.basename(@child_dir)
59
+ @abs_child_dir_name = VfsRealFile.join("/", @rel_child_dir_name)
60
+ end
61
+
62
+ it "should raise Errno::ENOENT when directory does exist under current root" do
63
+ VirtFS::VDir.chroot(@child_dir)
64
+ expect do
65
+ VirtFS::VDir.chdir(@parent_dir)
66
+ end.to raise_error(
67
+ Errno::ENOENT, /No such file or directory/
68
+ )
69
+ end
70
+
71
+ it "should cd to absolute path based on new root" do
72
+ VirtFS::VDir.chroot(@parent_dir)
73
+ VirtFS::VDir.chdir(@abs_child_dir_name)
74
+ expect(VirtFS::VDir.getwd).to eq(@abs_child_dir_name)
75
+ end
76
+
77
+ it "should cd to relative path based on new root" do
78
+ VirtFS::VDir.chroot(@parent_dir)
79
+ VirtFS::VDir.chdir(@rel_child_dir_name)
80
+ expect(VirtFS::VDir.getwd).to eq(@abs_child_dir_name)
81
+ end
82
+
83
+ it "should not permit traversal above root" do
84
+ VirtFS::VDir.chroot(@parent_dir)
85
+ VirtFS::VDir.chdir("..")
86
+ expect(VirtFS::VDir.getwd).to eq("/")
87
+ VirtFS::VDir.chdir(VfsRealFile.join("..", ".."))
88
+ expect(VirtFS::VDir.getwd).to eq("/")
89
+ VirtFS::VDir.chdir(VfsRealFile.join("..", "..", ".."))
90
+ expect(VirtFS::VDir.getwd).to eq("/")
91
+ end
92
+
93
+ it "should traverse up to root, then back down" do
94
+ VirtFS::VDir.chroot(@parent_dir)
95
+ VirtFS::VDir.chdir(VfsRealFile.join("..", "..", "..", @rel_child_dir_name))
96
+ expect(VirtFS::VDir.getwd).to eq(@abs_child_dir_name)
97
+ end
98
+ end
99
+
100
+ describe "Dir.glob" do
101
+ it "should enumerate the same file names as the standard Dir.glob - simple glob" do
102
+ VirtFS::VDir.chroot(@new_root)
103
+ VfsRealDir.chdir(@new_root) do # for VfsRealDir.glob
104
+ expect(VirtFS::VDir.glob("*")).to match_array(VfsRealDir.glob("*"))
105
+ expect(VirtFS::VDir.glob("*/*.rb")).to match_array(VfsRealDir.glob("*/*.rb"))
106
+ end
107
+ end
108
+
109
+ it "should enumerate the same file names as the standard Dir.glob - relative glob" do
110
+ VirtFS::VDir.chroot(@new_root)
111
+ VfsRealDir.chdir(@new_root) do # for VfsRealDir.glob
112
+ # We're at root, so the ".." will keep us at root.
113
+ v_results = VirtFS::VDir.glob("../**/*.rb").collect { |f| VfsRealFile.basename(f) }.sort
114
+ # We're not at root in the real FS, so omitting the ".." should result in the same files.
115
+ r_results = VfsRealDir.glob("**/*.rb").collect { |f| VfsRealFile.basename(f) }.sort
116
+ expect(v_results).to eq(r_results)
117
+ end
118
+ end
119
+ end
120
+ end
@@ -0,0 +1,246 @@
1
+ require 'spec_helper'
2
+
3
+ describe VirtFS, " - context manager class operations (#{$fs_interface} interface)" do
4
+ before(:all) do
5
+ @root = File::SEPARATOR
6
+ end
7
+
8
+ before(:each) do
9
+ reset_context
10
+ end
11
+
12
+ context "Before any FS operations" do
13
+ describe "context_manager.managers" do
14
+ it "should return a Hash" do
15
+ cm_hash = VirtFS.context_manager.managers
16
+ expect(cm_hash).to be_kind_of(Hash)
17
+ end
18
+
19
+ it "should return an empty hash before any operations" do
20
+ cm_hash = VirtFS.context_manager.managers
21
+ expect(cm_hash.empty?).to be true
22
+ end
23
+ end
24
+
25
+ describe "context_manager.current!" do
26
+ it "should raise VirtFS::NoContextError when there's no context for the ThreadGroup" do
27
+ expect do
28
+ VirtFS.context_manager.current!
29
+ end.to raise_exception(VirtFS::NoContextError, /No filesystem context defined for thread group:/)
30
+ end
31
+ end
32
+
33
+ describe "context!" do
34
+ it "should raise VirtFS::NoContextError when there's no context for the ThreadGroup" do
35
+ expect do
36
+ VirtFS.context!
37
+ end.to raise_exception(VirtFS::NoContextError, /No filesystem context defined for thread group:/)
38
+ end
39
+ end
40
+
41
+ describe "context_manager.current" do
42
+ it "should return a ContextManager bound to our ThreadGroup" do
43
+ cmanager = VirtFS.context_manager.current
44
+ expect(cmanager.thread_group).to eq(Thread.current.group)
45
+ end
46
+ end
47
+
48
+ describe "context" do
49
+ it "should return a Context bound to our ThreadGroup" do
50
+ context = VirtFS.context
51
+ expect(context).to be_kind_of(VirtFS::Context)
52
+ end
53
+ end
54
+
55
+ describe "context_manager.manager_for" do
56
+ it "should raise ArgumentError when not passed a ThreadGroup object" do
57
+ expect do
58
+ VirtFS.context_manager.manager_for(nil)
59
+ end.to raise_exception(ArgumentError, "value must be a ThreadGroup object")
60
+ end
61
+
62
+ it "should return nil when given an unused ThreadGroup" do
63
+ expect(VirtFS.context_manager.manager_for(ThreadGroup.new)).to be nil
64
+ end
65
+
66
+ it "should return nil when given our ThreadGroup" do
67
+ expect(VirtFS.context_manager.manager_for(Thread.current.group)).to be nil
68
+ end
69
+ end
70
+
71
+ describe "context_manager.new_manager_for" do
72
+ it "should raise ArgumentError when not passed a ThreadGroup object" do
73
+ expect do
74
+ VirtFS.context_manager.new_manager_for(nil)
75
+ end.to raise_exception(ArgumentError, "value must be a ThreadGroup object")
76
+ end
77
+
78
+ it "should return a ContextManager when given an unused ThreadGroup" do
79
+ expect(VirtFS.context_manager.new_manager_for(ThreadGroup.new)).to be_kind_of(VirtFS::ContextManager)
80
+ end
81
+
82
+ it "should return a ContextManager when given our ThreadGroup" do
83
+ expect(VirtFS.context_manager.new_manager_for(Thread.current.group)).to be_kind_of(VirtFS::ContextManager)
84
+ end
85
+
86
+ it "should return a ContextManager bound to a new ThreadGroup" do
87
+ tgroup = ThreadGroup.new
88
+ cmanager = VirtFS.context_manager.new_manager_for(tgroup)
89
+ expect(cmanager.thread_group).to eq(tgroup)
90
+ end
91
+
92
+ it "should return a ContextManager bound to our ThreadGroup" do
93
+ tgroup = Thread.current.group
94
+ cmanager = VirtFS.context_manager.new_manager_for(tgroup)
95
+ expect(cmanager.thread_group).to eq(tgroup)
96
+ end
97
+
98
+ it "new ContextManager should be retrievable by ThreadGroup" do
99
+ tgroup = Thread.current.group
100
+ cmanager = VirtFS.context_manager.new_manager_for(tgroup)
101
+ expect(VirtFS.context_manager.manager_for(tgroup)).to eq(cmanager)
102
+ end
103
+ end
104
+
105
+ describe "context_manager.remove_manager_for" do
106
+ it "should raise ArgumentError when not passed a ThreadGroup object" do
107
+ expect do
108
+ VirtFS.context_manager.remove_manager_for(nil)
109
+ end.to raise_exception(ArgumentError, "value must be a ThreadGroup object")
110
+ end
111
+
112
+ it "should return nil when given an unused ThreadGroup" do
113
+ expect(VirtFS.context_manager.remove_manager_for(ThreadGroup.new)).to be nil
114
+ end
115
+
116
+ it "should return nil when given our ThreadGroup" do
117
+ expect(VirtFS.context_manager.remove_manager_for(Thread.current.group)).to be nil
118
+ end
119
+ end
120
+ end
121
+
122
+ context "With root mounted by main thread/thread_group" do
123
+ before(:each) do
124
+ @native_fs = nativefs_class.new
125
+ VirtFS.mount(@native_fs, @root)
126
+ end
127
+
128
+ describe "context_manager.managers" do
129
+ it "should return a Hash" do
130
+ cm_hash = VirtFS.context_manager.managers
131
+ expect(cm_hash).to be_kind_of(Hash)
132
+ end
133
+
134
+ it "should return a Hash with one entry" do
135
+ cm_hash = VirtFS.context_manager.managers
136
+ expect(cm_hash.length).to eq(1)
137
+ end
138
+
139
+ it "should contain a ContextManager" do
140
+ cm = VirtFS.context_manager.managers.values.first
141
+ expect(cm).to be_kind_of(VirtFS::ContextManager)
142
+ end
143
+
144
+ it "should contain a ContextManager bound to the current ThreadGroup" do
145
+ cm = VirtFS.context_manager.managers.values.first
146
+ expect(cm.thread_group).to eq(Thread.current.group)
147
+ end
148
+ end
149
+
150
+ describe "context_manager_for" do
151
+ it "should raise ArgumentError when not passed a ThreadGroup object" do
152
+ expect do
153
+ VirtFS.context_manager.manager_for(nil)
154
+ end.to raise_exception(ArgumentError, "value must be a ThreadGroup object")
155
+ end
156
+
157
+ it "should return nil when given an unused ThreadGroup" do
158
+ expect(VirtFS.context_manager.manager_for(ThreadGroup.new)).to be nil
159
+ end
160
+
161
+ it "should return a ContextManager when given our ThreadGroup" do
162
+ cm = VirtFS.context_manager.manager_for(Thread.current.group)
163
+ expect(cm).to be_kind_of(VirtFS::ContextManager)
164
+ expect(cm.thread_group).to eq(Thread.current.group)
165
+ end
166
+ end
167
+ end
168
+
169
+ context "With root mounted by different thread groups" do
170
+ before(:each) do
171
+ @thread_groups = [ThreadGroup.new, ThreadGroup.new, ThreadGroup.new]
172
+ @thread_groups.each_with_index do |tg, i|
173
+ tg.add(Thread.current)
174
+ native_fs = nativefs_class.new
175
+ native_fs.name = "FS-#{i}"
176
+ VirtFS.mount(native_fs, @root)
177
+ end
178
+ end
179
+
180
+ after(:each) do
181
+ ThreadGroup::Default.add(Thread.current)
182
+ end
183
+
184
+ describe "context_manager.managers" do
185
+ it "should return a Hash" do
186
+ cm_hash = VirtFS.context_manager.managers
187
+ expect(cm_hash).to be_kind_of(Hash)
188
+ end
189
+
190
+ it "should return a hash of the expected length" do
191
+ cm_hash = VirtFS.context_manager.managers
192
+ expect(cm_hash.length).to eq(@thread_groups.length)
193
+ end
194
+
195
+ it "hash should contain one entry per thread group" do
196
+ cm_hash = VirtFS.context_manager.managers
197
+ @thread_groups.each do |tg|
198
+ cm = cm_hash[tg]
199
+ expect(cm).to be_kind_of(VirtFS::ContextManager)
200
+ expect(cm.thread_group).to eq(tg)
201
+ end
202
+ end
203
+ end
204
+
205
+ describe "context_manager.manager_for" do
206
+ it "should raise ArgumentError when not passed a ThreadGroup object" do
207
+ expect do
208
+ VirtFS.context_manager.manager_for(nil)
209
+ end.to raise_exception(ArgumentError, "value must be a ThreadGroup object")
210
+ end
211
+
212
+ it "should return nil when given an unused ThreadGroup" do
213
+ expect(VirtFS.context_manager.manager_for(ThreadGroup.new)).to be nil
214
+ end
215
+
216
+ it "should return a ContextManager when given each ThreadGroup" do
217
+ @thread_groups.each do |tg|
218
+ cm = VirtFS.context_manager.manager_for(tg)
219
+ expect(cm).to be_kind_of(VirtFS::ContextManager)
220
+ expect(cm.thread_group).to eq(tg)
221
+ end
222
+ end
223
+ end
224
+
225
+ describe "context_manager.remove_manager_for" do
226
+ it "should raise ArgumentError when not passed a ThreadGroup object" do
227
+ expect do
228
+ VirtFS.context_manager.remove_manager_for(nil)
229
+ end.to raise_exception(ArgumentError, "value must be a ThreadGroup object")
230
+ end
231
+
232
+ it "should return nil when given an unused ThreadGroup" do
233
+ expect(VirtFS.context_manager.remove_manager_for(ThreadGroup.new)).to be nil
234
+ end
235
+
236
+ it "should return nil when given our ThreadGroup" do
237
+ @thread_groups.each do |tg|
238
+ cm = VirtFS.context_manager.manager_for(tg)
239
+ expect(cm).to be_kind_of(VirtFS::ContextManager)
240
+ expect(VirtFS.context_manager.remove_manager_for(tg)).to eq(cm)
241
+ expect(VirtFS.context_manager.manager_for(tg)).to be nil
242
+ end
243
+ end
244
+ end
245
+ end
246
+ end
@@ -0,0 +1,255 @@
1
+ require 'spec_helper'
2
+
3
+ describe VirtFS, " - context manager instance operations (#{$fs_interface} interface)" do
4
+ before(:all) do
5
+ @root = File::SEPARATOR
6
+ end
7
+
8
+ before(:each) do
9
+ reset_context
10
+ @my_context_manager = VirtFS.context_manager.current
11
+ end
12
+
13
+ describe "#[]" do
14
+ it "should return nil given an non-existent key" do
15
+ expect(@my_context_manager[:not_a_key]).to be nil
16
+ end
17
+
18
+ it "should have a default context" do
19
+ expect(@my_context_manager[:default]).to be_kind_of(VirtFS::Context)
20
+ end
21
+ end
22
+
23
+ describe "#[]=" do
24
+ it "should raise an ArgumentError when not passed a VirtFS::Context object" do
25
+ expect do
26
+ @my_context_manager[:new_key] = "not a context object"
27
+ end.to raise_exception(ArgumentError, "Context must be a VirtFS::Context object")
28
+ end
29
+
30
+ it "should raise an ArgumentError when attempting to change the default context" do
31
+ expect do
32
+ @my_context_manager[:default] = VirtFS::Context.new
33
+ end.to raise_exception(ArgumentError, "Cannot change the default context")
34
+ end
35
+
36
+ it "should return the assigned context on success" do
37
+ new_context = VirtFS::Context.new
38
+ expect(@my_context_manager[:new_key] = new_context).to eq(new_context)
39
+ end
40
+
41
+ it "should raise an RuntimeError when attempting to change existing value" do
42
+ new_context = VirtFS::Context.new
43
+ expect(@my_context_manager[:new_key] = new_context).to eq(new_context)
44
+ expect do
45
+ @my_context_manager[:new_key] = VirtFS::Context.new
46
+ end.to raise_exception(RuntimeError, "Context for given key already exists")
47
+ end
48
+
49
+ it "should raise an RuntimeError when attempting assign context to more than one key" do
50
+ new_context = VirtFS::Context.new
51
+ expect(@my_context_manager[:new_key1] = new_context).to eq(new_context)
52
+ expect do
53
+ @my_context_manager[:new_key2] = new_context
54
+ end.to raise_exception(RuntimeError, /Context already assigned to key:/)
55
+ end
56
+
57
+ it "should delete a context by assigning nil" do
58
+ new_context = VirtFS::Context.new
59
+ expect(@my_context_manager[:new_key] = new_context).to eq(new_context)
60
+ expect(@my_context_manager[:new_key] = nil).to be nil
61
+ expect(@my_context_manager[:new_key]).to be nil
62
+ end
63
+
64
+ it "should permit re-assignment of deleted entry" do
65
+ new_context = VirtFS::Context.new
66
+ expect(@my_context_manager[:new_key] = new_context).to eq(new_context)
67
+ expect do
68
+ @my_context_manager[:new_key] = VirtFS::Context.new
69
+ end.to raise_exception(RuntimeError, "Context for given key already exists")
70
+ expect(@my_context_manager[:new_key] = nil).to be nil
71
+ expect(@my_context_manager[:new_key] = new_context).to eq(new_context)
72
+ end
73
+
74
+ it "should permit assignment to new key after deletion from old key" do
75
+ new_context = VirtFS::Context.new
76
+ expect(@my_context_manager[:new_key1] = new_context).to eq(new_context)
77
+ expect do
78
+ @my_context_manager[:new_key2] = new_context
79
+ end.to raise_exception(RuntimeError, /Context already assigned to key:/)
80
+ expect(@my_context_manager[:new_key1] = nil).to be nil
81
+ expect(@my_context_manager[:new_key2] = new_context).to eq(new_context)
82
+ end
83
+ end
84
+
85
+ describe "#current_context and #current_context=" do
86
+ it "should return the default context by default" do
87
+ expect(@my_context_manager.current_context).to eq(@my_context_manager[:default])
88
+ end
89
+
90
+ it "should raise RuntimeError when key doesn't exist" do
91
+ expect do
92
+ @my_context_manager.current_context = :new_key
93
+ end.to raise_exception(RuntimeError, "Context for given key doesn't exist")
94
+ end
95
+
96
+ it "should set the current_context to a new value" do
97
+ new_context = VirtFS::Context.new
98
+ expect(@my_context_manager[:new_key] = new_context).to eq(new_context)
99
+ expect(@my_context_manager.current_context).to eq(@my_context_manager[:default])
100
+ @my_context_manager.current_context = :new_key
101
+ expect(@my_context_manager.current_context).to eq(@my_context_manager[:new_key])
102
+ end
103
+ end
104
+
105
+ describe "#activated?" do
106
+ after(:each) do
107
+ @my_context_manager.deactivate! if @my_context_manager.activated?
108
+ end
109
+
110
+ it "should return false by default" do
111
+ expect(@my_context_manager.activated?).to be false
112
+ end
113
+
114
+ it "should return true when activated" do
115
+ @my_context_manager.activate!(:default)
116
+ expect(@my_context_manager.activated?).to be true
117
+ end
118
+ end
119
+
120
+ describe "#activate!" do
121
+ after(:each) do
122
+ @my_context_manager.deactivate! if @my_context_manager.activated?
123
+ end
124
+
125
+ it "should raise RuntimeError when key doesn't exist" do
126
+ expect do
127
+ @my_context_manager.activate!(:new_key)
128
+ end.to raise_exception(RuntimeError, "Context for given key doesn't exist")
129
+ end
130
+
131
+ it "should raise RuntimeError when already activated" do
132
+ @my_context_manager.activate!(:default)
133
+ expect do
134
+ @my_context_manager.activate!(:default)
135
+ end.to raise_exception(RuntimeError, "Context already activated")
136
+ end
137
+
138
+ it "should cause activated? to return true" do
139
+ expect(@my_context_manager.activated?).to be false
140
+ @my_context_manager.activate!(:default)
141
+ expect(@my_context_manager.activated?).to be true
142
+ end
143
+
144
+ it "should return the pre-activation context" do
145
+ new_context = VirtFS::Context.new
146
+ @my_context_manager[:new_key] = new_context
147
+ prev_context = @my_context_manager.current_context
148
+ expect(new_context).not_to eq(prev_context)
149
+ expect(@my_context_manager.activate!(:new_key)).to eq(prev_context)
150
+ end
151
+
152
+ it "should change the current context" do
153
+ new_context = VirtFS::Context.new
154
+ @my_context_manager[:new_key] = new_context
155
+ expect(@my_context_manager[:default]).not_to eq(new_context)
156
+ expect(@my_context_manager.current_context).to eq(@my_context_manager[:default])
157
+ @my_context_manager.activate!(:new_key)
158
+ expect(@my_context_manager.current_context).to eq(new_context)
159
+ end
160
+ end
161
+
162
+ describe "#deactivate!" do
163
+ it "should raise RuntimeError when not activated" do
164
+ expect do
165
+ @my_context_manager.deactivate!
166
+ end.to raise_exception(RuntimeError, "Context not activated")
167
+ end
168
+
169
+ it "should cause activated? to return false" do
170
+ expect(@my_context_manager.activated?).to be false
171
+ @my_context_manager.activate!(:default)
172
+ expect(@my_context_manager.activated?).to be true
173
+ @my_context_manager.deactivate!
174
+ expect(@my_context_manager.activated?).to be false
175
+ end
176
+
177
+ it "should return the pre-deactivated context" do
178
+ new_context = VirtFS::Context.new
179
+ @my_context_manager[:new_key] = new_context
180
+ @my_context_manager.activate!(:new_key)
181
+ expect(@my_context_manager.deactivate!).to eq(new_context)
182
+ end
183
+
184
+ it "should restore original context" do
185
+ context0 = @my_context_manager.current_context
186
+ new_context = VirtFS::Context.new
187
+ @my_context_manager[:new_key] = new_context
188
+ @my_context_manager.activate!(:new_key)
189
+ expect(@my_context_manager.current_context).not_to eq(context0)
190
+ @my_context_manager.deactivate!
191
+ expect(@my_context_manager.current_context).to eq(context0)
192
+ end
193
+ end
194
+
195
+ describe "#with" do
196
+ it "should raise RuntimeError when key doesn't exist" do
197
+ expect do
198
+ @my_context_manager.with(:new_key) {}
199
+ end.to raise_exception(RuntimeError, "Context for given key doesn't exist")
200
+ end
201
+
202
+ it "should raise RuntimeError when already activated" do
203
+ @my_context_manager.activate!(:default)
204
+ expect do
205
+ @my_context_manager.with(:default) {}
206
+ end.to raise_exception(RuntimeError, "Context already activated")
207
+ end
208
+
209
+ it "should cause activated? to return true within the block" do
210
+ expect(@my_context_manager.activated?).to be false
211
+ @my_context_manager.with(:default) do
212
+ expect(@my_context_manager.activated?).to be true
213
+ end
214
+ expect(@my_context_manager.activated?).to be false
215
+ end
216
+
217
+ it "should save and restore original context" do
218
+ context0 = @my_context_manager.current_context
219
+ new_context = VirtFS::Context.new
220
+ @my_context_manager[:new_key] = new_context
221
+ @my_context_manager.with(:new_key) do
222
+ expect(@my_context_manager.current_context).not_to eq(context0)
223
+ expect(@my_context_manager.current_context).to eq(new_context)
224
+ end
225
+ expect(@my_context_manager.current_context).to eq(context0)
226
+ end
227
+ end
228
+
229
+ describe "#without" do
230
+ it "should not change the current context when not activated" do
231
+ context0 = @my_context_manager.current_context
232
+ @my_context_manager.without do
233
+ expect(@my_context_manager.current_context).to eq(context0)
234
+ end
235
+ expect(@my_context_manager.current_context).to eq(context0)
236
+ end
237
+
238
+ it "should deactivate the context for the duration of the block" do
239
+ context0 = @my_context_manager.current_context
240
+ new_context = VirtFS::Context.new
241
+ @my_context_manager[:new_key] = new_context
242
+ @my_context_manager.with(:new_key) do
243
+ expect(@my_context_manager.current_context).not_to eq(context0)
244
+ expect(@my_context_manager.current_context).to eq(new_context)
245
+
246
+ @my_context_manager.without do
247
+ expect(@my_context_manager.current_context).to eq(context0)
248
+ end
249
+
250
+ expect(@my_context_manager.current_context).to eq(new_context)
251
+ end
252
+ expect(@my_context_manager.current_context).to eq(context0)
253
+ end
254
+ end
255
+ end