instantcache 0.1.0a1

Sign up to get free protection for your applications and to get access to all the features.
data/script/console ADDED
@@ -0,0 +1,10 @@
1
+ #!/usr/bin/env ruby
2
+ # File: script/console
3
+ irb = RUBY_PLATFORM =~ /(:?mswin|mingw)/ ? 'irb.bat' : 'irb'
4
+
5
+ libs = " -r irb/completion"
6
+ # Perhaps use a console_lib to store any extra methods I may want available in the cosole
7
+ # libs << " -r #{File.dirname(__FILE__) + '/../lib/console_lib/console_logger.rb'}"
8
+ libs << " -r #{File.dirname(__FILE__) + '/../lib/instantcache.rb'}"
9
+ puts "Loading instantcache gem"
10
+ exec "#{irb} #{libs} --simple-prompt"
data/script/destroy ADDED
@@ -0,0 +1,14 @@
1
+ #!/usr/bin/env ruby
2
+ APP_ROOT = File.expand_path(File.join(File.dirname(__FILE__), '..'))
3
+
4
+ begin
5
+ require 'rubigen'
6
+ rescue LoadError
7
+ require 'rubygems'
8
+ require 'rubigen'
9
+ end
10
+ require 'rubigen/scripts/destroy'
11
+
12
+ ARGV.shift if ['--help', '-h'].include?(ARGV[0])
13
+ RubiGen::Base.use_component_sources! [:rubygems, :newgem, :newgem_theme, :test_unit]
14
+ RubiGen::Scripts::Destroy.new.run(ARGV)
data/script/generate ADDED
@@ -0,0 +1,14 @@
1
+ #!/usr/bin/env ruby
2
+ APP_ROOT = File.expand_path(File.join(File.dirname(__FILE__), '..'))
3
+
4
+ begin
5
+ require 'rubigen'
6
+ rescue LoadError
7
+ require 'rubygems'
8
+ require 'rubigen'
9
+ end
10
+ require 'rubigen/scripts/generate'
11
+
12
+ ARGV.shift if ['--help', '-h'].include?(ARGV[0])
13
+ RubiGen::Base.use_component_sources! [:rubygems, :newgem, :newgem_theme, :test_unit]
14
+ RubiGen::Scripts::Generate.new.run(ARGV)
@@ -0,0 +1,8 @@
1
+ Proc.new {
2
+ libdir = File.expand_path(File.join(File.dirname(__FILE__), '..', 'lib'))
3
+ $:.unshift(libdir) unless ($:.include?(libdir))
4
+ }.call
5
+ require 'rubygems'
6
+ require 'stringio'
7
+ require 'test/unit'
8
+ require 'instantcache'
@@ -0,0 +1,62 @@
1
+ require File.dirname(__FILE__) + '/test_helper.rb'
2
+
3
+ class TestInstantCache_01 < Test::Unit::TestCase
4
+
5
+ TestClass_def = <<-'EOT'
6
+ class TestClass
7
+ include InstantCache
8
+ memcached_accessor(:mca)
9
+ memcached_reader(:mcr)
10
+ memcached_counter(:mcc)
11
+ end
12
+ EOT
13
+
14
+ VARS = %w( mca mcr mcc )
15
+
16
+ def setup
17
+ if (InstantCache.cache_object.nil?)
18
+ InstantCache.cache_object = MemCache.new('127.0.0.1:11211')
19
+ end
20
+ if (self.class.const_defined?(:TestClass))
21
+ self.class.class_eval('remove_const(:TestClass)')
22
+ end
23
+ self.class.class_eval(TestClass_def)
24
+ @test_objects = []
25
+ end
26
+
27
+ def teardown
28
+ @test_objects.each do |o|
29
+ VARS.each do |ivar_s|
30
+ cell = o.instance_variable_get("@#{ivar_s}".to_sym)
31
+ cellname = cell.name
32
+ InstantCache.cache_object.delete(cellname)
33
+ cell.destroy! unless (cell.destroyed?)
34
+ end
35
+ end
36
+ end
37
+
38
+ def get_object
39
+ @test_objects << (test_obj = TestClass.new)
40
+ return test_obj
41
+ end
42
+
43
+ def test_01_new_and_empty
44
+ test_obj = get_object
45
+ assert_nil(test_obj.mca)
46
+ assert_nil(test_obj.mcr)
47
+ assert_equal(0, test_obj.mcc)
48
+ end
49
+
50
+ def test_02_test_default_names
51
+ test_obj = get_object
52
+ assert_nil(test_obj.mca)
53
+ assert_nil(test_obj.mcr)
54
+ assert_equal(0, test_obj.mcc)
55
+ VARS.each do |ivar|
56
+ expected = '%s:%d:@%s' % [ test_obj.class.name, test_obj.object_id, ivar ]
57
+ test_val = test_obj.instance_variable_get("@#{ivar}".to_sym).name
58
+ assert_equal(expected, test_val)
59
+ end
60
+ end
61
+
62
+ end
@@ -0,0 +1,187 @@
1
+ require File.dirname(__FILE__) + '/test_helper.rb'
2
+ require 'thread'
3
+
4
+ class TestInstantCacheComplexSharing < Test::Unit::TestCase
5
+
6
+ TestClass_def = <<-'EOT'
7
+ class TestClass
8
+ include InstantCache
9
+ memcached_accessor(:umca) { |ivar| "#{TestName.call}-#{ivar.to_s}" }
10
+ memcached_reader(:umcr) { |ivar| "#{TestName.call}-#{ivar.to_s}" }
11
+ memcached_counter(:umcc) { |ivar| "#{TestName.call}-#{ivar.to_s}" }
12
+ memcached_accessor(InstantCache::PRIVATE, :pmca)
13
+ memcached_reader(InstantCache::PRIVATE, :pmcr)
14
+ memcached_counter(InstantCache::PRIVATE, :pmcc)
15
+ memcached_accessor(InstantCache::SHARED, :smca) \
16
+ { |ivar| "#{TestName.call}-#{ivar.to_s}" }
17
+ memcached_reader(InstantCache::SHARED, :smcr) \
18
+ { |ivar| "#{TestName.call}-#{ivar.to_s}" }
19
+ memcached_counter(InstantCache::SHARED, :smcc) \
20
+ { |ivar| "#{TestName.call}-#{ivar.to_s}" }
21
+ end
22
+ EOT
23
+
24
+ VARS = %w( umca umcr umcc pmca pmcr pmcc smca smcr smcc )
25
+
26
+ def setup
27
+ unless (self.class.constants.include?('TestName'))
28
+ #
29
+ # Create a closure to make the test class instance available to
30
+ # the custom-name blocks.
31
+ #
32
+ self.class.const_set('TestName',
33
+ Proc.new {
34
+ self.class.name
35
+ })
36
+ end
37
+ #
38
+ # Make the connexion to the memcache cluster.
39
+ #
40
+ if (InstantCache.cache_object.nil?)
41
+ InstantCache.cache_object = MemCache.new('127.0.0.1:11211')
42
+ end
43
+ if (self.class.const_defined?(:TestClass))
44
+ self.class.class_eval('remove_const(:TestClass)')
45
+ end
46
+ self.class.class_eval(TestClass_def)
47
+ @test_objects = []
48
+ end
49
+
50
+ def teardown
51
+ @test_objects.each do |o|
52
+ VARS.each do |ivar_s|
53
+ cell = o.instance_variable_get("@#{ivar_s}".to_sym)
54
+ cellname = cell.name
55
+ InstantCache.cache_object.delete(cellname)
56
+ cell.destroy! unless (cell.destroyed?)
57
+ end
58
+ end
59
+ if (self.class.const_defined?(:TestClass))
60
+ self.class.class_eval('remove_const(:TestClass)')
61
+ end
62
+ end
63
+
64
+ def get_object
65
+ @test_objects << (test_obj = TestClass.new)
66
+ VARS.each do |ivar_s|
67
+ ivar_sym = ivar_s.to_sym
68
+ if (ivar_s =~ %r!cc$!)
69
+ assert_equal(0, test_obj.send(ivar_sym),
70
+ "@#{ivar_s} should be 0")
71
+ else
72
+ assert_nil(test_obj.send(ivar_sym),
73
+ "@#{ivar_s} should be nil")
74
+ end
75
+ end
76
+ return test_obj
77
+ end
78
+
79
+ def test_01_test_custom_names
80
+ test_obj = get_object
81
+ test_obj2 = get_object
82
+ VARS.each do |ivar_s|
83
+ #
84
+ # Skip over the private ones for now, since we're not sure of their
85
+ # names.
86
+ #
87
+ next if (ivar_s[0,1] == 'p')
88
+ ivar_sym = ivar_s.to_sym
89
+ expected = '%s-%s' % [ TestName.call, ivar_s ]
90
+ test_var = test_obj.instance_variable_get("@#{ivar_s}".to_sym)
91
+ test_val = test_var.name
92
+ assert_equal(expected, test_val,
93
+ "test_obj:@#{ivar_s}'s name should be '#{expected}'")
94
+ test_var2 = test_obj2.instance_variable_get("@#{ivar_s}".to_sym)
95
+ test_val2 = test_var2.name
96
+ assert_equal(expected, test_val2,
97
+ "test_obj2:@#{ivar_s}'s name should be '#{expected}'")
98
+ assert_equal(test_val, test_val2,
99
+ "@#{ivar_s} should have the same name for both variables")
100
+ #
101
+ # Lock the cell for the next test.
102
+ #
103
+ assert(test_var.lock,
104
+ "test_var:@#{ivar_s} should be locked")
105
+ test_var.destroy!
106
+ assert_raises(InstantCache::Destroyed,
107
+ "test_var:@#{ivar_s} should be destroyed and not let us " +
108
+ '.destroy! it again') do
109
+ test_var.destroy!
110
+ end
111
+ assert_raises(InstantCache::Destroyed,
112
+ "test_var:@#{ivar_s} should be destroyed and not let us " +
113
+ 'fetch it') do
114
+ test_var.get
115
+ end
116
+ assert_raises(InstantCache::Destroyed,
117
+ "test_var:@#{ivar_s} should be destroyed and not let us " +
118
+ '_destroy! it again') do
119
+ test_obj.send("#{ivar_s}_destroy!".to_sym)
120
+ end
121
+ end
122
+ end
123
+
124
+ def test_02_test_that_destroy_unlocks
125
+ test_obj = get_object
126
+ VARS.each do |ivar_s|
127
+ ivar_sym = ivar_s.to_sym
128
+ test_var = test_obj.instance_variable_get("@#{ivar_s}".to_sym)
129
+ assert(test_var.lock,
130
+ "Should be able to lock test_obj:@#{ivar_s} (#{test_var.name}) " +
131
+ 'after destruction in previous test')
132
+ test_var.destroy!
133
+ end
134
+ end
135
+
136
+ def test_03_test_locking
137
+ main_obj = get_object
138
+ test_obj = get_object
139
+ VARS.each do |ivar_s|
140
+ ivar_sym = ivar_s.to_sym
141
+ main_var = main_obj.instance_variable_get("@#{ivar_s}".to_sym)
142
+ test_var = test_obj.instance_variable_get("@#{ivar_s}".to_sym)
143
+ main_lock = main_var.lock
144
+ test_lock = test_var.lock
145
+ assert(main_lock,
146
+ "main_var:@#{ivar_s}.lock should return true")
147
+ if (main_var.shared? && test_var.shared?)
148
+ assert(! test_lock,
149
+ "shared test_var:@#{ivar_s}.lock should return false or nil")
150
+ else
151
+ assert(test_lock,
152
+ "private test_var:@#{ivar_s}.lock should return true")
153
+ end
154
+ end
155
+ end
156
+
157
+ def test_04_test_multilocking
158
+ test_obj = get_object
159
+ VARS.each do |ivar_s|
160
+ ivar_sym = ivar_s.to_sym
161
+ main_var = test_obj.instance_variable_get("@#{ivar_s}".to_sym)
162
+ main_var.lock
163
+ threads = []
164
+ 100.times do
165
+ alt_obj = get_object
166
+ alt_var = alt_obj.instance_variable_get("@#{ivar_s}".to_sym)
167
+ assert_not_equal(main_var, alt_var,
168
+ "alt_var.#{ivar_s} should not match main_var's")
169
+ if (ivar_s[0,1] == 'p')
170
+ assert_not_equal(main_var.name, alt_var.name,
171
+ "alt_var.#{ivar_s}'s name should not match main_var's")
172
+ else
173
+ assert_equal(main_var.name, alt_var.name,
174
+ "alt_var.#{ivar_s}'s name should match main_var's")
175
+ end
176
+ attempt_lock = Proc.new { Thread.current[:locked] = alt_var.lock }
177
+ threads << Thread.new { attempt_lock }
178
+ end
179
+ threads.each do |thred|
180
+ thred.join
181
+ assert(! thred[:locked],
182
+ "#{thred.inspect}[:locked] should be false for @#{ivar_s}")
183
+ end
184
+ end
185
+ end
186
+
187
+ end
@@ -0,0 +1,164 @@
1
+ require File.dirname(__FILE__) + '/test_helper.rb'
2
+ require 'thread'
3
+
4
+ class TestInstantCacheSimpleSharing < Test::Unit::TestCase
5
+
6
+ TestClass_def = <<-'EOT'
7
+ class TestClass
8
+ include InstantCache
9
+ memcached_accessor(:umca) { |ivar| "#{TestName.call}-#{ivar.to_s}" }
10
+ memcached_reader(:umcr) { |ivar| "#{TestName.call}-#{ivar.to_s}" }
11
+ memcached_counter(:umcc) { |ivar| "#{TestName.call}-#{ivar.to_s}" }
12
+ memcached_accessor(InstantCache::PRIVATE, :pmca)
13
+ memcached_reader(InstantCache::PRIVATE, :pmcr)
14
+ memcached_counter(InstantCache::PRIVATE, :pmcc)
15
+ memcached_accessor(InstantCache::SHARED, :smca) \
16
+ { |ivar| "#{TestName.call}-#{ivar.to_s}" }
17
+ memcached_reader(InstantCache::SHARED, :smcr) \
18
+ { |ivar| "#{TestName.call}-#{ivar.to_s}" }
19
+ memcached_counter(InstantCache::SHARED, :smcc) \
20
+ { |ivar| "#{TestName.call}-#{ivar.to_s}" }
21
+ end
22
+ EOT
23
+
24
+ VARS = %w( umca umcr umcc pmca pmcr pmcc smca smcr smcc )
25
+
26
+ def setup
27
+ unless (self.class.constants.include?('TestName'))
28
+ #
29
+ # Create a closure to make the test class instance available to
30
+ # the custom-name blocks.
31
+ #
32
+ self.class.const_set('TestName',
33
+ Proc.new {
34
+ self.class.name +
35
+ '::' +
36
+ self.instance_variable_get(:@method_name)
37
+ })
38
+ end
39
+ #
40
+ # Make the connexion to the memcache cluster.
41
+ #
42
+ if (InstantCache.cache_object.nil?)
43
+ InstantCache.cache_object = MemCache.new('127.0.0.1:11211')
44
+ end
45
+ if (self.class.const_defined?(:TestClass))
46
+ self.class.class_eval('remove_const(:TestClass)')
47
+ end
48
+ self.class.class_eval(TestClass_def)
49
+ @test_objects = []
50
+ end
51
+
52
+ def teardown
53
+ @test_objects.each do |o|
54
+ VARS.each do |ivar_s|
55
+ cell = o.instance_variable_get("@#{ivar_s}".to_sym)
56
+ cellname = cell.name
57
+ InstantCache.cache_object.delete(cellname)
58
+ cell.destroy! unless (cell.destroyed?)
59
+ end
60
+ end
61
+ unless (self.class.const_defined?(:TestClass))
62
+ self.class.class_eval(TestClass_def)
63
+ end
64
+ cleanup = TestClass.new
65
+ VARS.each { |ivar_s| cleanup.send("#{ivar_s}_destroy!".to_sym) }
66
+ self.class.class_eval('remove_const(:TestClass)')
67
+ end
68
+
69
+ def get_object
70
+ @test_objects << (test_obj = TestClass.new)
71
+ VARS.each do |ivar_s|
72
+ ivar_sym = ivar_s.to_sym
73
+ if (ivar_s =~ %r!cc$!)
74
+ assert_equal(0, test_obj.send(ivar_sym),
75
+ "@#{ivar_s} should be 0")
76
+ else
77
+ assert_nil(test_obj.send(ivar_sym),
78
+ "@#{ivar_s} should be nil")
79
+ end
80
+ end
81
+ return test_obj
82
+ end
83
+
84
+ def test_01_test_custom_names
85
+ test_obj = get_object
86
+ VARS.each do |ivar_s|
87
+ #
88
+ # Skip over the private ones for now, since we're not sure of their
89
+ # names.
90
+ #
91
+ next if (ivar_s[0,1] == 'p')
92
+ ivar_sym = ivar_s.to_sym
93
+ expected = '%s-%s' % [ TestName.call, ivar_s ]
94
+ test_val = test_obj.instance_variable_get("@#{ivar_s}".to_sym).name
95
+ assert_equal(expected, test_val,
96
+ "@#{ivar_s}'s name should be '#{expected}'")
97
+ end
98
+ end
99
+
100
+ def test_02_test_sharedness
101
+ test_obj = get_object
102
+ VARS.each do |ivar_s|
103
+ ivar_sym = ivar_s.to_sym
104
+ test_var = test_obj.instance_variable_get("@#{ivar_s}".to_sym)
105
+ expect_shared = (ivar_s =~ %r!^p!) ? false : true
106
+ assert_equal(expect_shared, test_var.shared?,
107
+ "@#{ivar_s}.shared? should be #{expect_shared.inspect}")
108
+ assert_not_equal(expect_shared, test_var.private?,
109
+ "@#{ivar_s}.private? should not be #{expect_shared.inspect}")
110
+ end
111
+ end
112
+
113
+ def test_03_test_locking
114
+ main_obj = get_object
115
+ test_obj = get_object
116
+ VARS.each do |ivar_s|
117
+ ivar_sym = ivar_s.to_sym
118
+ main_var = main_obj.instance_variable_get("@#{ivar_s}".to_sym)
119
+ test_var = test_obj.instance_variable_get("@#{ivar_s}".to_sym)
120
+ main_lock = main_var.lock
121
+ test_lock = test_var.lock
122
+ assert(main_lock,
123
+ "main_var:@#{ivar_s}.lock should return true")
124
+ if (main_var.shared? && test_var.shared?)
125
+ assert(! test_lock,
126
+ "shared test_var:@#{ivar_s}.lock should return false or nil")
127
+ else
128
+ assert(test_lock,
129
+ "private test_var:@#{ivar_s}.lock should return true")
130
+ end
131
+ end
132
+ end
133
+
134
+ def test_04_test_multilocking
135
+ test_obj = get_object
136
+ VARS.each do |ivar_s|
137
+ ivar_sym = ivar_s.to_sym
138
+ main_var = test_obj.instance_variable_get("@#{ivar_s}".to_sym)
139
+ main_var.lock
140
+ threads = []
141
+ 100.times do
142
+ alt_obj = get_object
143
+ alt_var = alt_obj.instance_variable_get("@#{ivar_s}".to_sym)
144
+ assert_not_equal(main_var, alt_var,
145
+ "alt_var.#{ivar_s} should not match main_var's")
146
+ if (ivar_s[0,1] == 'p')
147
+ assert_not_equal(main_var.name, alt_var.name,
148
+ "alt_var.#{ivar_s}'s name should not match main_var's")
149
+ else
150
+ assert_equal(main_var.name, alt_var.name,
151
+ "alt_var.#{ivar_s}'s name should match main_var's")
152
+ end
153
+ attempt_lock = Proc.new { Thread.current[:locked] = alt_var.lock }
154
+ threads << Thread.new { attempt_lock }
155
+ end
156
+ threads.each do |thred|
157
+ thred.join
158
+ assert(! thred[:locked],
159
+ "#{thred.inspect}[:locked] should be false for @#{ivar_s}")
160
+ end
161
+ end
162
+ end
163
+
164
+ end
metadata ADDED
@@ -0,0 +1,142 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: instantcache
3
+ version: !ruby/object:Gem::Version
4
+ hash: 415506520
5
+ prerelease: true
6
+ segments:
7
+ - 0
8
+ - 1
9
+ - 0a1
10
+ version: 0.1.0a1
11
+ platform: ruby
12
+ authors:
13
+ - Ken Coar
14
+ autorequire:
15
+ bindir: bin
16
+ cert_chain: []
17
+
18
+ date: 2011-09-08 00:00:00 -04:00
19
+ default_executable:
20
+ dependencies:
21
+ - !ruby/object:Gem::Dependency
22
+ name: versionomy
23
+ prerelease: false
24
+ requirement: &id001 !ruby/object:Gem::Requirement
25
+ none: false
26
+ requirements:
27
+ - - ">="
28
+ - !ruby/object:Gem::Version
29
+ hash: 15
30
+ segments:
31
+ - 0
32
+ - 4
33
+ - 0
34
+ version: 0.4.0
35
+ type: :runtime
36
+ version_requirements: *id001
37
+ - !ruby/object:Gem::Dependency
38
+ name: memcache-client
39
+ prerelease: false
40
+ requirement: &id002 !ruby/object:Gem::Requirement
41
+ none: false
42
+ requirements:
43
+ - - ">="
44
+ - !ruby/object:Gem::Version
45
+ hash: 61
46
+ segments:
47
+ - 1
48
+ - 8
49
+ - 5
50
+ version: 1.8.5
51
+ type: :runtime
52
+ version_requirements: *id002
53
+ - !ruby/object:Gem::Dependency
54
+ name: hoe
55
+ prerelease: false
56
+ requirement: &id003 !ruby/object:Gem::Requirement
57
+ none: false
58
+ requirements:
59
+ - - ~>
60
+ - !ruby/object:Gem::Version
61
+ hash: 27
62
+ segments:
63
+ - 2
64
+ - 12
65
+ version: "2.12"
66
+ type: :development
67
+ version_requirements: *id003
68
+ description: |-
69
+ rubygem-instantcache provides the InstantCache module, a mixin
70
+ which has accessors that allow you to declare 'instance variables'
71
+ that are actually stored in a memcached cluster rather than
72
+ local memory.
73
+ email:
74
+ - coar@rubyforge.org
75
+ executables: []
76
+
77
+ extensions: []
78
+
79
+ extra_rdoc_files:
80
+ - History.txt
81
+ - LICENCE.txt
82
+ - Manifest.txt
83
+ - README.txt
84
+ files:
85
+ - History.txt
86
+ - LICENCE.txt
87
+ - Manifest.txt
88
+ - README.txt
89
+ - Rakefile
90
+ - instantcache.gemspec
91
+ - lib/instantcache.rb
92
+ - lib/instantcache/exceptions.rb
93
+ - script/console
94
+ - script/destroy
95
+ - script/generate
96
+ - test/test_helper.rb
97
+ - test/test_instantcache.rb
98
+ - test/test_sharing_complex.rb
99
+ - test/test_sharing_simple.rb
100
+ - .gemtest
101
+ has_rdoc: true
102
+ homepage: http://github.com/RoUS/rubygem-instantcache
103
+ licenses: []
104
+
105
+ post_install_message:
106
+ rdoc_options:
107
+ - --main
108
+ - README.txt
109
+ require_paths:
110
+ - lib
111
+ required_ruby_version: !ruby/object:Gem::Requirement
112
+ none: false
113
+ requirements:
114
+ - - ">="
115
+ - !ruby/object:Gem::Version
116
+ hash: 3
117
+ segments:
118
+ - 0
119
+ version: "0"
120
+ required_rubygems_version: !ruby/object:Gem::Requirement
121
+ none: false
122
+ requirements:
123
+ - - ">"
124
+ - !ruby/object:Gem::Version
125
+ hash: 25
126
+ segments:
127
+ - 1
128
+ - 3
129
+ - 1
130
+ version: 1.3.1
131
+ requirements: []
132
+
133
+ rubyforge_project: instantcache
134
+ rubygems_version: 1.3.7
135
+ signing_key:
136
+ specification_version: 3
137
+ summary: rubygem-instantcache provides the InstantCache module, a mixin which has accessors that allow you to declare 'instance variables' that are actually stored in a memcached cluster rather than local memory.
138
+ test_files:
139
+ - test/test_instantcache.rb
140
+ - test/test_helper.rb
141
+ - test/test_sharing_simple.rb
142
+ - test/test_sharing_complex.rb