instantcache 0.1.0a1

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