hprevalence 0.1.0
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/README +18 -0
- data/lib/hprevalence.rb +243 -0
- data/lib/internal/command_logger.rb +98 -0
- data/lib/internal/iomanager.rb +83 -0
- data/lib/internal/object_graph.rb +68 -0
- data/lib/internal/serializer.rb +83 -0
- data/lib/internal/store_manager.rb +74 -0
- data/lib/transparent.rb +218 -0
- data/rake.rb +4 -0
- data/rakefile.rb +62 -0
- data/test/abstract_hprevalence_testcase.rb +26 -0
- data/test/command_logger_test.rb +39 -0
- data/test/default_model_serializer_test.rb +65 -0
- data/test/dvd_store_model.rb +57 -0
- data/test/file_io_manager_test.rb +129 -0
- data/test/natural_object_model_test.rb +119 -0
- data/test/simple_engine_test.rb +79 -0
- data/test/task_model.rb +74 -0
- data/test/transparent_module_test.rb +95 -0
- metadata +54 -0
data/lib/transparent.rb
ADDED
@@ -0,0 +1,218 @@
|
|
1
|
+
|
2
|
+
module HPrevalence
|
3
|
+
|
4
|
+
module Transparent
|
5
|
+
|
6
|
+
module CustomBehavior
|
7
|
+
|
8
|
+
def self.included(type)
|
9
|
+
class << type
|
10
|
+
def attr_proxy( *symbols )
|
11
|
+
@proxied_attributes ||= []
|
12
|
+
symbols.each do |symbol|
|
13
|
+
@proxied_attributes << symbol
|
14
|
+
end
|
15
|
+
end
|
16
|
+
|
17
|
+
def attr_read_only( *symbols )
|
18
|
+
symbols.each do |symbol|
|
19
|
+
self.instance_eval {
|
20
|
+
@readonly_attributes ||= []
|
21
|
+
@readonly_attributes << symbol
|
22
|
+
}
|
23
|
+
end
|
24
|
+
end
|
25
|
+
end
|
26
|
+
end
|
27
|
+
|
28
|
+
def _read_only_attributes()
|
29
|
+
self.class.instance_eval { @readonly_attributes ||= [] }
|
30
|
+
end
|
31
|
+
|
32
|
+
def _proxied_attributes()
|
33
|
+
self.class.instance_eval { @proxied_attributes ||= [] }
|
34
|
+
end
|
35
|
+
|
36
|
+
def _should_proxy( symbol )
|
37
|
+
if _proxied_attributes().include?( symbol )
|
38
|
+
return true if _symbol2proxy(symbol).nil?
|
39
|
+
end
|
40
|
+
false
|
41
|
+
end
|
42
|
+
|
43
|
+
def _symbol2proxy( symbol )
|
44
|
+
self.instance_eval {
|
45
|
+
@symbol2proxy ||= {}
|
46
|
+
@symbol2proxy[symbol]
|
47
|
+
}
|
48
|
+
end
|
49
|
+
|
50
|
+
def _set_proxy( symbol, proxy )
|
51
|
+
self.instance_eval {
|
52
|
+
@symbol2proxy ||= {}
|
53
|
+
@symbol2proxy[symbol] = proxy
|
54
|
+
}
|
55
|
+
end
|
56
|
+
|
57
|
+
end
|
58
|
+
|
59
|
+
class AutomaticCommand
|
60
|
+
|
61
|
+
def initialize( proxy_id, symbol, *args )
|
62
|
+
@proxy_id, @symbol, @args = proxy_id, symbol, *args
|
63
|
+
end
|
64
|
+
|
65
|
+
def execute(system)
|
66
|
+
TransparentEngine.current() { |engine|
|
67
|
+
proxy = engine.proxy_by_id(@proxy_id)
|
68
|
+
raise 'Could not obtain proxy' if proxy.nil?
|
69
|
+
return proxy.send(@symbol, *arguments)
|
70
|
+
}
|
71
|
+
end
|
72
|
+
|
73
|
+
protected
|
74
|
+
|
75
|
+
def arguments()
|
76
|
+
@args ||= []
|
77
|
+
end
|
78
|
+
|
79
|
+
end
|
80
|
+
|
81
|
+
class NestedAutomaticCommand < AutomaticCommand
|
82
|
+
|
83
|
+
attr_reader :related_symbol, :parent_proxy_id
|
84
|
+
|
85
|
+
def initialize( related_symbol, parent_proxy_id, proxy_id, symbol, *args )
|
86
|
+
super( proxy_id, symbol, *args )
|
87
|
+
raise 'Missing related_symbol' if related_symbol.nil?
|
88
|
+
raise 'Missing parent_proxy_id' if parent_proxy_id.nil?
|
89
|
+
@related_symbol, @parent_proxy_id = related_symbol, parent_proxy_id
|
90
|
+
end
|
91
|
+
|
92
|
+
def execute(system)
|
93
|
+
TransparentEngine.current() { |engine|
|
94
|
+
proxy = engine.proxy_by_id(@proxy_id, @related_symbol, @parent_proxy_id)
|
95
|
+
raise 'Could not obtain proxy' if proxy.nil?
|
96
|
+
return proxy.send(@symbol, *arguments)
|
97
|
+
}
|
98
|
+
end
|
99
|
+
end
|
100
|
+
|
101
|
+
class TransparentProxy
|
102
|
+
attr_accessor :target, :proxy_id, :engine_id
|
103
|
+
|
104
|
+
def initialize(target)
|
105
|
+
raise 'A proxy must have a target' if target.nil?
|
106
|
+
raise 'Strange. A proxy is supposed to exist within an engine' unless Thread.current[:engine]
|
107
|
+
@engine_id = Thread.current[:engine].engine_id
|
108
|
+
@proxy_id = Thread.current[:engine].register_proxy(self)
|
109
|
+
# puts "New proxy with id #{@proxy_id.to_s} for #{target.class.to_s}"
|
110
|
+
@target = target
|
111
|
+
@is_custom = target.kind_of?(CustomBehavior)
|
112
|
+
end
|
113
|
+
|
114
|
+
def method_missing(symbol, *args, &block)
|
115
|
+
# puts "Sending #{symbol} to #{@target.to_s} args #{args.to_s}"
|
116
|
+
raise NoMethodError, "Undefined method" unless @target.respond_to?(symbol)
|
117
|
+
|
118
|
+
if (@is_custom)
|
119
|
+
if (@target._read_only_attributes.include?(symbol) )
|
120
|
+
return @target.send(symbol, *args)
|
121
|
+
elsif (@target._should_proxy(symbol) )
|
122
|
+
return TransparentEngine.create_nested_proxy( @proxy_id, symbol, @engine_id )
|
123
|
+
# nested_target = @target.send(symbol, *args)
|
124
|
+
# return nil if nested_target.nil?
|
125
|
+
# TransparentEngine.within_engine( @engine_id ) { |engine|
|
126
|
+
# new_proxy = TransparentProxy.new( nested_target )
|
127
|
+
# @target._set_proxy( symbol, new_proxy )
|
128
|
+
# return new_proxy
|
129
|
+
# }
|
130
|
+
else
|
131
|
+
nested_proxy = @target._symbol2proxy(symbol)
|
132
|
+
# Returns the nested proxy associated with this symbol
|
133
|
+
# puts "Returning nested proxy for #{symbol} if #{nested_proxy.class.to_s}"
|
134
|
+
return nested_proxy unless nested_proxy.nil?
|
135
|
+
end
|
136
|
+
end
|
137
|
+
|
138
|
+
proceed(symbol, *args, &block)
|
139
|
+
end
|
140
|
+
|
141
|
+
# Custom marshalling - this adds the internal id (myid) and the system id to a marshall
|
142
|
+
# of the object we are the proxy for.
|
143
|
+
# We take care to not marshal the same object twice, so circular references will work.
|
144
|
+
|
145
|
+
def _dump(depth)
|
146
|
+
references = Thread.current[:references]
|
147
|
+
if (references)
|
148
|
+
if (references[self])
|
149
|
+
[@proxy_id.to_s, @engine_id.to_s].pack("A8A40")
|
150
|
+
else
|
151
|
+
references[self] = true
|
152
|
+
[@proxy_id.to_s, @engine_id.to_s].pack("A8A40") + Marshal.dump(@target, depth)
|
153
|
+
end
|
154
|
+
else
|
155
|
+
[@proxy_id.to_s, @engine_id.to_s].pack("A8A40")
|
156
|
+
end
|
157
|
+
end
|
158
|
+
|
159
|
+
# Custom marshalling - restore a Prox object.
|
160
|
+
|
161
|
+
def TransparentProxy._load(buffer)
|
162
|
+
proxy = TransparentProxy.allocate
|
163
|
+
list = buffer.unpack("A8A40a*")
|
164
|
+
proxy.proxy_id = list[0].to_i
|
165
|
+
proxy.engine_id = Guid.from_s( list[1] )
|
166
|
+
TransparentEngine.current() { |engine|
|
167
|
+
proxy = engine.restore(proxy)
|
168
|
+
proxy.target = Marshal.load(list[2]) if (list[2] > "")
|
169
|
+
}
|
170
|
+
proxy
|
171
|
+
end
|
172
|
+
|
173
|
+
protected
|
174
|
+
|
175
|
+
def build_command( symbol, *args )
|
176
|
+
AutomaticCommand.new( @proxy_id, symbol, *args )
|
177
|
+
end
|
178
|
+
|
179
|
+
def proceed(symbol, *args, &block)
|
180
|
+
engine = TransparentEngine.current
|
181
|
+
result = nil
|
182
|
+
|
183
|
+
if (engine.nil?)
|
184
|
+
# In this case the invocation happens on the object by user code
|
185
|
+
raise "Blocks are not supported... yet" if block_given?
|
186
|
+
|
187
|
+
TransparentEngine.within_engine( @engine_id ) { |engine|
|
188
|
+
result = engine.execute_command( build_command(symbol, *args) )
|
189
|
+
}
|
190
|
+
else
|
191
|
+
# In this case the invocation is happening within an execute_command
|
192
|
+
result = @target.send(symbol, *args)
|
193
|
+
end
|
194
|
+
result
|
195
|
+
end
|
196
|
+
|
197
|
+
end
|
198
|
+
|
199
|
+
class NestedTransparentProxy < TransparentProxy
|
200
|
+
attr_reader :related_symbol, :parent_proxy_id
|
201
|
+
|
202
|
+
def initialize(target, symbol, parent_proxy_id)
|
203
|
+
raise 'A nested-proxy must have a symbol' if symbol.nil?
|
204
|
+
super(target)
|
205
|
+
@related_symbol, @parent_proxy_id = symbol, parent_proxy_id
|
206
|
+
end
|
207
|
+
|
208
|
+
protected
|
209
|
+
|
210
|
+
def build_command( symbol, *args )
|
211
|
+
NestedAutomaticCommand.new( @related_symbol, @parent_proxy_id, @proxy_id, symbol, *args )
|
212
|
+
end
|
213
|
+
|
214
|
+
end
|
215
|
+
|
216
|
+
end
|
217
|
+
|
218
|
+
end
|
data/rake.rb
ADDED
data/rakefile.rb
ADDED
@@ -0,0 +1,62 @@
|
|
1
|
+
|
2
|
+
require 'rake'
|
3
|
+
require 'rubygems'
|
4
|
+
require 'rake/gempackagetask'
|
5
|
+
require 'rake/testtask'
|
6
|
+
require 'rake/rdoctask'
|
7
|
+
|
8
|
+
#$VERBOSE = nil
|
9
|
+
#require 'code_statistics'
|
10
|
+
|
11
|
+
#task :default => [ :test_units, :test_functional, :appdoc, :stats ]
|
12
|
+
desc "Run all the tests"
|
13
|
+
task :default => [ :test_units, :package ]
|
14
|
+
|
15
|
+
desc "Run the unit tests in test/unit"
|
16
|
+
Rake::TestTask.new("test_units") { |t|
|
17
|
+
t.libs << "test"
|
18
|
+
t.pattern = 'test/*_test.rb'
|
19
|
+
t.verbose = true
|
20
|
+
}
|
21
|
+
|
22
|
+
PKG_VERSION = '0.1.0'
|
23
|
+
PKG_FILES = FileList['README', './**/*.rb']
|
24
|
+
|
25
|
+
spec = Gem::Specification.new do |s|
|
26
|
+
s.name = 'hprevalence'
|
27
|
+
s.version = PKG_VERSION
|
28
|
+
s.summary = "Ruby based prevalence engine."
|
29
|
+
s.description = <<-EOF
|
30
|
+
HPrevalence is an prevalence engine for Ruby
|
31
|
+
which aims to provide non-intrusive capabilities to
|
32
|
+
prevalent object models.
|
33
|
+
EOF
|
34
|
+
#
|
35
|
+
s.files = PKG_FILES.to_a
|
36
|
+
#
|
37
|
+
s.require_path = 'lib'
|
38
|
+
s.autorequire = 'hprevalence'
|
39
|
+
#
|
40
|
+
s.has_rdoc = false
|
41
|
+
#
|
42
|
+
s.author = "Hamilton Verissimo"
|
43
|
+
s.email = "hammett@apache.org"
|
44
|
+
s.homepage = "http://www.digitalcraftsmen.com.br/~hammett"
|
45
|
+
s.rubyforge_project = "hprevalence"
|
46
|
+
end
|
47
|
+
|
48
|
+
desc "Creates the gem package for hprevalence"
|
49
|
+
Rake::GemPackageTask.new(spec) do |pkg|
|
50
|
+
pkg.need_zip = true
|
51
|
+
pkg.need_tar = true
|
52
|
+
end
|
53
|
+
|
54
|
+
desc "Generate documentation for the application"
|
55
|
+
Rake::RDocTask.new("appdoc") { |rdoc|
|
56
|
+
rdoc.rdoc_dir = 'doc/app'
|
57
|
+
rdoc.title = ""
|
58
|
+
rdoc.options << '--line-numbers --inline-source'
|
59
|
+
rdoc.rdoc_files.include('doc/README_FOR_APP')
|
60
|
+
rdoc.rdoc_files.include('**/*.rb')
|
61
|
+
}
|
62
|
+
|
@@ -0,0 +1,26 @@
|
|
1
|
+
|
2
|
+
module AbstractHPrevalenceTestHelper
|
3
|
+
|
4
|
+
def reset_dir( dir )
|
5
|
+
begin
|
6
|
+
current_dir = File.dirname(__FILE__)
|
7
|
+
@target_dir = File.join( current_dir, dir )
|
8
|
+
if File.exist?( @target_dir )
|
9
|
+
Dir.entries( @target_dir ).each do |file|
|
10
|
+
File.delete( File.join(@target_dir,file) ) unless File.directory?( file )
|
11
|
+
end
|
12
|
+
end
|
13
|
+
Dir.rmdir( @target_dir )
|
14
|
+
rescue
|
15
|
+
# puts 'could not reset dir ' + $!
|
16
|
+
end
|
17
|
+
end
|
18
|
+
|
19
|
+
def ensure_dir( dir = @target_dir )
|
20
|
+
begin
|
21
|
+
Dir.mkdir( dir )
|
22
|
+
rescue
|
23
|
+
end
|
24
|
+
end
|
25
|
+
|
26
|
+
end
|
@@ -0,0 +1,39 @@
|
|
1
|
+
$:.unshift(File.dirname(__FILE__) + "/../lib/")
|
2
|
+
|
3
|
+
require 'internal/command_logger'
|
4
|
+
require 'internal/iomanager'
|
5
|
+
require 'abstract_hprevalence_testcase'
|
6
|
+
require 'test/unit'
|
7
|
+
|
8
|
+
class CommandLoggerTest < Test::Unit::TestCase
|
9
|
+
include AbstractHPrevalenceTestHelper
|
10
|
+
|
11
|
+
def setup
|
12
|
+
reset_dir 'store/file_command_test'
|
13
|
+
|
14
|
+
@fc = CommandLogger.new( FileIOManager.new( @target_dir ) )
|
15
|
+
end
|
16
|
+
|
17
|
+
def test_available_logs
|
18
|
+
assert_equal 0, @fc.log_files.length
|
19
|
+
|
20
|
+
ensure_dir
|
21
|
+
|
22
|
+
assert_equal 0, @fc.log_files.length
|
23
|
+
end
|
24
|
+
|
25
|
+
def test_new_log
|
26
|
+
ensure_dir
|
27
|
+
assert_equal 0, @fc.log_files.length
|
28
|
+
|
29
|
+
command_store = @fc.create_command_store
|
30
|
+
assert_equal 1, @fc.log_files.length
|
31
|
+
assert_equal File.join(@target_dir, '000000000001.commandlog'), @fc.current_file_name
|
32
|
+
|
33
|
+
command_store = @fc.create_command_store
|
34
|
+
assert_equal 2, @fc.log_files.length
|
35
|
+
assert_equal File.join(@target_dir, '000000000002.commandlog'), @fc.current_file_name
|
36
|
+
end
|
37
|
+
|
38
|
+
end
|
39
|
+
|
@@ -0,0 +1,65 @@
|
|
1
|
+
$:.unshift(File.dirname(__FILE__) + "/../lib/")
|
2
|
+
|
3
|
+
require 'internal/iomanager'
|
4
|
+
require 'internal/serializer'
|
5
|
+
require 'abstract_hprevalence_testcase'
|
6
|
+
require 'test/unit'
|
7
|
+
require 'task_model'
|
8
|
+
|
9
|
+
class DefaultModelSerializerTest < Test::Unit::TestCase
|
10
|
+
include AbstractHPrevalenceTestHelper
|
11
|
+
|
12
|
+
def setup
|
13
|
+
reset_dir 'store/default_model_serializer'
|
14
|
+
ensure_dir
|
15
|
+
|
16
|
+
@serializer = DefaultModelSerializer.new( FileIOManager.new( @target_dir ) )
|
17
|
+
end
|
18
|
+
|
19
|
+
def test_dump_and_load
|
20
|
+
|
21
|
+
db = TaskDatabase.new()
|
22
|
+
db.add_task( Task.new( 'one', 'yada yada yada' ) )
|
23
|
+
db.add_task( Task.new( 'two', 'yada yada yada' ) )
|
24
|
+
db.add_task( Task.new( 'three', 'yada yada yada' ) )
|
25
|
+
db.priority_task = db.tasks[0]
|
26
|
+
|
27
|
+
@serializer.dump( db )
|
28
|
+
db = @serializer.load
|
29
|
+
|
30
|
+
assert_equal 3, db.tasks.length
|
31
|
+
assert_equal db.priority_task.id, db.tasks[0].id
|
32
|
+
|
33
|
+
db.priority_task.contents = 'new content'
|
34
|
+
|
35
|
+
@serializer.dump( db )
|
36
|
+
db = @serializer.load
|
37
|
+
|
38
|
+
assert_equal db.priority_task.id, db.tasks[0].id
|
39
|
+
assert_equal db.priority_task.contents, db.tasks[0].contents
|
40
|
+
|
41
|
+
end
|
42
|
+
|
43
|
+
def test_multiple_snapshots
|
44
|
+
|
45
|
+
db = TaskDatabase.new()
|
46
|
+
db.add_task( Task.new( 'one', 'yada yada yada' ) )
|
47
|
+
|
48
|
+
@serializer.dump( db )
|
49
|
+
|
50
|
+
db.add_task( Task.new( 'two', 'yada yada yada' ) )
|
51
|
+
|
52
|
+
@serializer.dump( db )
|
53
|
+
|
54
|
+
db.add_task( Task.new( 'three', 'yada yada yada' ) )
|
55
|
+
|
56
|
+
@serializer.dump( db )
|
57
|
+
|
58
|
+
db = @serializer.load
|
59
|
+
|
60
|
+
assert_equal 3, db.tasks.length
|
61
|
+
|
62
|
+
end
|
63
|
+
|
64
|
+
end
|
65
|
+
|
@@ -0,0 +1,57 @@
|
|
1
|
+
$:.unshift(File.dirname(__FILE__) + "/../lib/")
|
2
|
+
|
3
|
+
require 'transparent'
|
4
|
+
|
5
|
+
class DvdStore
|
6
|
+
include HPrevalence::Transparent::CustomBehavior
|
7
|
+
|
8
|
+
attr_reader :available_items
|
9
|
+
attr_reader :available_categories
|
10
|
+
attr_reader :customers
|
11
|
+
|
12
|
+
attr_proxy :available_items, :available_categories, :customers
|
13
|
+
attr_read_only :total_customers
|
14
|
+
|
15
|
+
def initialize()
|
16
|
+
@available_items = []
|
17
|
+
@available_categories = []
|
18
|
+
@customers = []
|
19
|
+
end
|
20
|
+
|
21
|
+
def total_customers
|
22
|
+
@customers.length
|
23
|
+
end
|
24
|
+
|
25
|
+
end
|
26
|
+
|
27
|
+
class Category
|
28
|
+
attr_reader :name
|
29
|
+
|
30
|
+
def initialize( name )
|
31
|
+
@name = name
|
32
|
+
end
|
33
|
+
|
34
|
+
end
|
35
|
+
|
36
|
+
class Dvd
|
37
|
+
attr_accessor :name, :price, :categories
|
38
|
+
|
39
|
+
def initialize( name, price, *categories )
|
40
|
+
@name, @price = name, price
|
41
|
+
@categories = *categories.dup()
|
42
|
+
end
|
43
|
+
|
44
|
+
end
|
45
|
+
|
46
|
+
class Customer
|
47
|
+
attr_accessor :name, :items_bought, :prefered_categories
|
48
|
+
|
49
|
+
def initialize( name )
|
50
|
+
@name = name
|
51
|
+
@items_bought = []
|
52
|
+
@prefered_categories = []
|
53
|
+
end
|
54
|
+
|
55
|
+
end
|
56
|
+
|
57
|
+
|
@@ -0,0 +1,129 @@
|
|
1
|
+
$:.unshift(File.dirname(__FILE__) + "/../lib/")
|
2
|
+
|
3
|
+
require 'internal/iomanager'
|
4
|
+
require 'abstract_hprevalence_testcase'
|
5
|
+
require 'test/unit'
|
6
|
+
|
7
|
+
class FileIOManagerTest < Test::Unit::TestCase
|
8
|
+
include AbstractHPrevalenceTestHelper
|
9
|
+
|
10
|
+
def setup
|
11
|
+
reset_dir 'store/file_io_manager_test'
|
12
|
+
ensure_dir
|
13
|
+
|
14
|
+
@filemanager = FileIOManager.new( @target_dir )
|
15
|
+
end
|
16
|
+
|
17
|
+
def test_create_new_stream
|
18
|
+
|
19
|
+
output = @filemanager.create_new_stream( 'test_extension' )
|
20
|
+
assert_not_nil output
|
21
|
+
assert_equal '000000000001.test_extension', output.basename
|
22
|
+
|
23
|
+
output.puts 'Testing'
|
24
|
+
output.close
|
25
|
+
|
26
|
+
end
|
27
|
+
|
28
|
+
def test_create_new_stream_twice
|
29
|
+
|
30
|
+
output1 = @filemanager.create_new_stream( 'test_extension' )
|
31
|
+
assert_not_nil output1
|
32
|
+
output2 = @filemanager.create_new_stream( 'test_extension' )
|
33
|
+
assert_not_nil output2
|
34
|
+
|
35
|
+
assert_equal '000000000001.test_extension', output1.basename
|
36
|
+
assert_equal '000000000002.test_extension', output2.basename
|
37
|
+
|
38
|
+
output1.close
|
39
|
+
output2.close
|
40
|
+
|
41
|
+
end
|
42
|
+
|
43
|
+
def test_list_simple_situation
|
44
|
+
|
45
|
+
@filemanager.create_new_stream( 'test' ).close
|
46
|
+
@filemanager.create_new_stream( 'test' ).close
|
47
|
+
@filemanager.create_new_stream( 'test' ).close
|
48
|
+
|
49
|
+
files = @filemanager.list( 'test' )
|
50
|
+
|
51
|
+
assert_not_nil files
|
52
|
+
assert_equal 3, files.length
|
53
|
+
|
54
|
+
assert_equal '000000000001.test', files[0]
|
55
|
+
assert_equal '000000000002.test', files[1]
|
56
|
+
assert_equal '000000000003.test', files[2]
|
57
|
+
|
58
|
+
end
|
59
|
+
|
60
|
+
def test_list_not_so_simple_situation
|
61
|
+
|
62
|
+
@filemanager.create_new_stream( 'test' ).close
|
63
|
+
@filemanager.create_new_stream( 'test' ).close
|
64
|
+
@filemanager.create_new_stream( 'test' ).close
|
65
|
+
@filemanager.create_new_stream( 'other' ).close
|
66
|
+
@filemanager.create_new_stream( 'other' ).close
|
67
|
+
|
68
|
+
files = @filemanager.list( 'test' )
|
69
|
+
|
70
|
+
assert_not_nil files
|
71
|
+
assert_equal 3, files.length
|
72
|
+
|
73
|
+
assert_equal '000000000001.test', files[0]
|
74
|
+
assert_equal '000000000002.test', files[1]
|
75
|
+
assert_equal '000000000003.test', files[2]
|
76
|
+
|
77
|
+
files = @filemanager.list( 'other' )
|
78
|
+
|
79
|
+
assert_not_nil files
|
80
|
+
assert_equal 2, files.length
|
81
|
+
|
82
|
+
assert_equal '000000000001.other', files[0]
|
83
|
+
assert_equal '000000000002.other', files[1]
|
84
|
+
|
85
|
+
end
|
86
|
+
|
87
|
+
def test_obtain_ordered_read_streams
|
88
|
+
|
89
|
+
output = @filemanager.create_new_stream( 'test' )
|
90
|
+
output.puts 'Testing 1'
|
91
|
+
output.close
|
92
|
+
|
93
|
+
output = @filemanager.create_new_stream( 'test' )
|
94
|
+
output.puts 'Testing 2'
|
95
|
+
output.close
|
96
|
+
|
97
|
+
streams = @filemanager.obtain_ordered_read_streams( 'test' )
|
98
|
+
assert_not_nil streams
|
99
|
+
assert_equal 2, streams.length
|
100
|
+
|
101
|
+
stream = streams[0]
|
102
|
+
assert_equal "Testing 1\n", stream.readline
|
103
|
+
stream.close
|
104
|
+
|
105
|
+
stream = streams[1]
|
106
|
+
assert_equal "Testing 2\n", stream.readline
|
107
|
+
stream.close
|
108
|
+
|
109
|
+
end
|
110
|
+
|
111
|
+
def test_obtain_latest_read_stream
|
112
|
+
|
113
|
+
output = @filemanager.create_new_stream( 'test' )
|
114
|
+
output.puts 'Testing 1'
|
115
|
+
output.close
|
116
|
+
|
117
|
+
output = @filemanager.create_new_stream( 'test' )
|
118
|
+
output.puts 'Testing 2'
|
119
|
+
output.close
|
120
|
+
|
121
|
+
stream = @filemanager.obtain_latest_read_stream( 'test' )
|
122
|
+
assert_not_nil stream
|
123
|
+
assert_equal "Testing 2\n", stream.readline
|
124
|
+
stream.close
|
125
|
+
|
126
|
+
end
|
127
|
+
|
128
|
+
end
|
129
|
+
|