police-vminfo 0.0.1

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/.document ADDED
@@ -0,0 +1,5 @@
1
+ lib/**/*.rb
2
+ bin/*
3
+ -
4
+ features/**/*.feature
5
+ LICENSE.txt
data/Gemfile ADDED
@@ -0,0 +1,10 @@
1
+ source :rubygems
2
+
3
+ group :development do
4
+ gem 'bundler', '>= 1.1.0'
5
+ gem 'jeweler', '>= 1.8.3'
6
+ gem 'minitest', '>= 2.11.2'
7
+ gem 'rdoc', '>= 3.12'
8
+ gem 'simplecov', '>= 0.6.1'
9
+ gem 'yard', '>= 0.7'
10
+ end
data/Gemfile.lock ADDED
@@ -0,0 +1,31 @@
1
+ GEM
2
+ remote: http://rubygems.org/
3
+ specs:
4
+ git (1.2.5)
5
+ jeweler (1.8.3)
6
+ bundler (~> 1.0)
7
+ git (>= 1.2.5)
8
+ rake
9
+ rdoc
10
+ json (1.6.6)
11
+ minitest (2.11.4)
12
+ multi_json (1.2.0)
13
+ rake (0.9.2.2)
14
+ rdoc (3.12)
15
+ json (~> 1.4)
16
+ simplecov (0.6.1)
17
+ multi_json (~> 1.0)
18
+ simplecov-html (~> 0.5.3)
19
+ simplecov-html (0.5.3)
20
+ yard (0.7.5)
21
+
22
+ PLATFORMS
23
+ ruby
24
+
25
+ DEPENDENCIES
26
+ bundler (>= 1.1.0)
27
+ jeweler (>= 1.8.3)
28
+ minitest (>= 2.11.2)
29
+ rdoc (>= 3.12)
30
+ simplecov (>= 0.6.1)
31
+ yard (>= 0.7)
data/LICENSE.txt ADDED
@@ -0,0 +1,20 @@
1
+ Copyright (c) 2012 Victor Costan
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,17 @@
1
+ # police-vminfo
2
+
3
+ Collects information about the internals of the running Ruby VM.
4
+
5
+ This is useful for applications that want to re-implement standard library
6
+ objects such as String, or track their usage, e.g. for data flow taint tracking.
7
+ The code here can be used to ensure that an implementation fully covers an
8
+ object's methods.
9
+
10
+ Right now, this gem collects the Ruby exploration code used to build
11
+ police-dataflow.
12
+
13
+
14
+ ## Copyright
15
+
16
+ Copyright (c) 2012 Massachusetts Institute of Technology. See LICENSE.txt for
17
+ further details.
data/Rakefile ADDED
@@ -0,0 +1,38 @@
1
+ # encoding: utf-8
2
+
3
+ require 'rubygems'
4
+ require 'bundler'
5
+ begin
6
+ Bundler.setup(:default, :development)
7
+ rescue Bundler::BundlerError => e
8
+ $stderr.puts e.message
9
+ $stderr.puts "Run `bundle install` to install missing gems"
10
+ exit e.status_code
11
+ end
12
+ require 'rake'
13
+
14
+ require 'jeweler'
15
+ Jeweler::Tasks.new do |gem|
16
+ # gem is a Gem::Specification... see http://docs.rubygems.org/read/chapter/20 for more options
17
+ gem.name = "police-vminfo"
18
+ gem.homepage = "http://github.com/pwnall/police-vminfo"
19
+ gem.license = "MIT"
20
+ gem.summary = %Q{Information about the Ruby VM internals.}
21
+ gem.description = %Q{Collects information about the Ruby VM implementation details.}
22
+ gem.email = "victor@costan.us"
23
+ gem.authors = ["Victor Costan"]
24
+ # dependencies defined in Gemfile
25
+ end
26
+ Jeweler::RubygemsDotOrgTasks.new
27
+
28
+ require 'rake/testtask'
29
+ Rake::TestTask.new(:test) do |test|
30
+ test.libs << 'lib' << 'test'
31
+ test.pattern = 'test/**/*_test.rb'
32
+ test.verbose = true
33
+ end
34
+
35
+ task :default => :test
36
+
37
+ require 'yard'
38
+ YARD::Rake::YardocTask.new
data/VERSION ADDED
@@ -0,0 +1 @@
1
+ 0.0.1
@@ -0,0 +1,2 @@
1
+ # Allow require 'police-vminfo' instead of 'police/vminfo'
2
+ require 'police/vminfo'
@@ -0,0 +1,3 @@
1
+ require 'police/vminfo/objects.rb'
2
+ require 'police/vminfo/paths.rb'
3
+ require 'police/vminfo/signature.rb'
@@ -0,0 +1,164 @@
1
+ module Police
2
+
3
+ module VmInfo
4
+ # All loaded Ruby modules, obtained by walking the constants graph.
5
+ #
6
+ # @return [Array<Module>] the Ruby modules that could be discovered by
7
+ # searching the constants graph; this should include everything except for
8
+ # anonymous (not assigned to constants) classes
9
+ def self.named_modules
10
+ # NOTE: this is a Set, but we don't want to load the module.
11
+ explored = { Object => true }
12
+ left = [Object]
13
+ until left.empty?
14
+ namespace = left.pop
15
+ namespace.constants.each do |const_name|
16
+ begin
17
+ const = if namespace.const_defined? const_name
18
+ namespace.const_get const_name
19
+ else
20
+ namespace.const_missing const_name
21
+ end
22
+ rescue LoadError, NameError
23
+ # Delayed loading failure.
24
+ next
25
+ end
26
+ next if explored[const] || !const.kind_of?(Module)
27
+ explored[const] = true
28
+ left.push const
29
+ end
30
+ end
31
+ explored.keys.sort_by!(&:name).freeze
32
+ end
33
+
34
+ # All loaded Ruby classes, obtained by walking the constants graph.
35
+ #
36
+ # Note that all classes are modules, so this is a subset of named_modules.
37
+ #
38
+ # @return [Array<Module>] the Ruby classes that could be discovered by
39
+ # searching the constants graph; this should include everything except for
40
+ # anonymous (not assigned to constants) classes
41
+ def self.named_classes
42
+ named_modules.select { |m| m.kind_of? Class }
43
+ end
44
+
45
+ # All loaded Ruby modules, obtained by querying ObjectSpace.
46
+ #
47
+ # Querying ObjectSpace can be painfully slow, especially on non-MRI VMs.
48
+ #
49
+ # @return [Array<Module>] all the Ruby modules
50
+ def self.all_modules
51
+ ObjectSpace.each_object(Module).to_a
52
+ end
53
+
54
+ # All loaded Ruby classes, obtained by querying ObjectSpace.
55
+ #
56
+ # Querying ObjectSpace can be painfully slow, especially on non-MRI VMs. Note
57
+ # that all classes are modules, so this is a subset of all_modules.
58
+ #
59
+ # @return [Array<Classes>] all the Ruby classes
60
+ def self.all_classes
61
+ ObjectSpace.each_object(Class).to_a
62
+ end
63
+
64
+ # The modules making up the Ruby VM implementation.
65
+ #
66
+ # @return [Array<Module>] the modules that are present in a vanilla Ruby
67
+ # environment
68
+ def self.core_modules
69
+ return @core_modules if @core_modules
70
+
71
+ output =
72
+ `#{Gem.ruby} -e 'puts ObjectSpace.each_object(Module).to_a.join("\n")'`
73
+ modules = []
74
+ output.split("\n").each do |name|
75
+ next if name[0] == ?#
76
+ begin
77
+ mod = constantize name
78
+ next unless mod.kind_of? Module
79
+ modules << mod
80
+ rescue NameError, LoadError
81
+ # Delayed loading failure.
82
+ next
83
+ end
84
+ end
85
+
86
+ @core_modules = modules.freeze
87
+ end
88
+ @core_modules = nil
89
+
90
+ # The classes making up the Ruby VM implementation.
91
+ #
92
+ # Note that all classes are modules, so this is a subset of core_modules.
93
+ #
94
+ # @return [Array<Class>] the classes that are present in a vanilla Ruby
95
+ # environment
96
+ def self.core_classes
97
+ return @core_classes if @core_classes
98
+ @core_classes = core_modules.select { |m| m.kind_of? Class }
99
+ @core_classes.freeze
100
+ end
101
+ @core_classes = nil
102
+
103
+ # All methods defined in a class or module.
104
+ #
105
+ # @param [Module] module_or_class a Class or Module instance
106
+ # @return [Array<Method, UnboundMethod>] all the class and instance methods
107
+ # defined by the given Class or Module
108
+ def self.all_methods(module_or_class)
109
+ class_methods(module_or_class) + instance_methods(module_or_class)
110
+ end
111
+
112
+ # All instance methods defined in a class or module.
113
+ #
114
+ # @param [Module] module_or_class a Class or Module instance
115
+ # @return [Array<Method, UnboundMethod>] all the instance methods defined by
116
+ # the given Class or Module
117
+ def self.instance_methods(module_or_class)
118
+ module_or_class.instance_methods.tap do |array|
119
+ array.map! { |name| module_or_class.instance_method name }
120
+ array.select! { |method| method.owner == module_or_class }
121
+ end
122
+ end
123
+
124
+ # All class methods defined in a class or module.
125
+ #
126
+ # Note: the class methods of a class or module are the instance methods of the
127
+ # class or module's meta-class.
128
+ #
129
+ # @param [Module] module_or_class a Class or Module instance
130
+ # @return [Array<Method, UnboundMethod>] all the instance methods defined by
131
+ # the given Class or Module
132
+ def self.class_methods(module_or_class)
133
+ # NOTE: this long-winded approach avoids creating new singleton classes
134
+ method_names = module_or_class.singleton_methods
135
+ return [] if method_names.empty?
136
+ singleton_class = module_or_class.singleton_class
137
+ method_names.tap do |array|
138
+ array.map! { |name| module_or_class.method name }
139
+ array.select! { |method| method.owner == singleton_class }
140
+ end
141
+ end
142
+
143
+ # Resolves the name of a constant into its value.
144
+ #
145
+ # @param [String] name a constant name, potentially including the scope
146
+ # operator ::
147
+ # @return [Object] the value of the constant with the given name
148
+ # @raise [NameError] no constant with the given name is defined
149
+ def self.constantize(name)
150
+ segments = name.split '::'
151
+ value = Object
152
+ segments.each do |segment|
153
+ next if segment.empty?
154
+ value = if value.const_defined? segment
155
+ value.const_get segment
156
+ else
157
+ value.const_missing segment
158
+ end
159
+ end
160
+ value
161
+ end
162
+ end # namespace VmInfo
163
+
164
+ end # namespace Police
@@ -0,0 +1,67 @@
1
+ module Police
2
+
3
+ module VmInfo
4
+ # Classifies the path to a Ruby file based on its provenance.
5
+ #
6
+ # @param [Method, UnboundMethod] method VM information about a method; usually
7
+ # obtained by calling Object#method or Module#instance_method
8
+ # @return [Symbol] :native for methods defined in a low-level language (C/C++
9
+ # for MRI and Rubinius, Java for JRuby), :kernel for methods belonging to
10
+ # the core VM code (Rubinius and JRuby), :stdlib for methods in Ruby's
11
+ # standard library, :gem for methods that are implemented in a loaded Ruby
12
+ # gem, and :app for all other methods (presumably defined in the current
13
+ # application)
14
+ def self.method_source(method)
15
+ location = method.source_location
16
+ return :native if location.nil?
17
+ code_path = location.first
18
+ return :stdlib if stdlib_path?(code_path)
19
+ return :gem if gem_path?(code_path)
20
+ return :kernel if kernel_path?(code_path)
21
+ :app
22
+ end
23
+
24
+ # True if the given source code path belongs to a gem.
25
+ def self.gem_path?(path)
26
+ Gem.default_path.any? { |gem_path| Paths.descendant? path, gem_path }
27
+ end
28
+
29
+ # True if the given source code path belongs to the Ruby standard library.
30
+ def self.stdlib_path?(path)
31
+ # NOTE: assuming the convention that all directories are prepended to the
32
+ # load path throughout a program's execution
33
+ load_paths = $LOAD_PATH
34
+ last_gem_index = -1
35
+ (load_paths.length - 1).downto(0) do |index|
36
+ if gem_path? load_paths[index]
37
+ last_gem_index = index
38
+ break
39
+ end
40
+ end
41
+ stdlib_paths = load_paths[(last_gem_index + 1)..-1]
42
+ stdlib_paths.any? { |stdlib_path| Paths.descendant? path, stdlib_path }
43
+ end
44
+
45
+ # True if the given source code path belongs to the Ruby VM kernel.
46
+ def self.kernel_path?(path)
47
+ !$LOAD_PATH.any? { |load_path| Paths.descendant? path, load_path }
48
+ end
49
+
50
+ # Implementation details.
51
+ # @private
52
+ module Paths
53
+ class <<self
54
+ # True if a path points to a descendant of the directory in anothe
55
+ def descendant?(descendant, dir)
56
+ if descendant.length > dir.length
57
+ descendant[0, dir.length] == dir &&
58
+ descendant[dir.length] == File::SEPARATOR
59
+ else
60
+ descendant == dir
61
+ end
62
+ end
63
+ end
64
+ end
65
+ end # module VmInfo
66
+
67
+ end # namespace Police
@@ -0,0 +1,13 @@
1
+ module Police
2
+
3
+ module VmInfo
4
+ # Fingerprint for the Ruby VM's core and stdlib API.
5
+ #
6
+ # @return [String] a string that contains the Ruby VM's engine name and
7
+ # core version; this should be representative of the
8
+ def self.signature
9
+ Gem.ruby_engine + Gem.ruby_version.segments[0, 3].join('.')
10
+ end
11
+ end # module VmInfo
12
+
13
+ end # namespace Police
@@ -0,0 +1,53 @@
1
+ # Generated by jeweler
2
+ # DO NOT EDIT THIS FILE DIRECTLY
3
+ # Instead, edit Jeweler::Tasks in Rakefile, and run 'rake gemspec'
4
+ # -*- encoding: utf-8 -*-
5
+
6
+ Gem::Specification.new do |s|
7
+ s.name = "police-vminfo"
8
+ s.version = "0.0.1"
9
+
10
+ s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version=
11
+ s.authors = ["Victor Costan"]
12
+ s.date = "2012-03-28"
13
+ s.description = "Collects information about the Ruby VM implementation details."
14
+ s.email = "victor@costan.us"
15
+ s.extra_rdoc_files = [
16
+ "LICENSE.txt",
17
+ "README.markdown"
18
+ ]
19
+ s.files = [
20
+ ".document",
21
+ "Gemfile",
22
+ "Gemfile.lock",
23
+ "LICENSE.txt",
24
+ "README.markdown",
25
+ "Rakefile",
26
+ "VERSION",
27
+ "lib/police-vminfo.rb",
28
+ "lib/police/vminfo.rb",
29
+ "lib/police/vminfo/objects.rb",
30
+ "lib/police/vminfo/paths.rb",
31
+ "lib/police/vminfo/signature.rb",
32
+ "police-vminfo.gemspec",
33
+ "test/helper.rb",
34
+ "test/vminfo/objects_test.rb",
35
+ "test/vminfo/paths_test.rb",
36
+ "test/vminfo/signature_test.rb"
37
+ ]
38
+ s.homepage = "http://github.com/pwnall/police-vminfo"
39
+ s.licenses = ["MIT"]
40
+ s.require_paths = ["lib"]
41
+ s.rubygems_version = "1.8.21"
42
+ s.summary = "Information about the Ruby VM internals."
43
+
44
+ if s.respond_to? :specification_version then
45
+ s.specification_version = 3
46
+
47
+ if Gem::Version.new(Gem::VERSION) >= Gem::Version.new('1.2.0') then
48
+ else
49
+ end
50
+ else
51
+ end
52
+ end
53
+
data/test/helper.rb ADDED
@@ -0,0 +1,20 @@
1
+ require 'rubygems'
2
+ require 'bundler'
3
+ begin
4
+ Bundler.setup(:default, :development)
5
+ rescue Bundler::BundlerError => e
6
+ $stderr.puts e.message
7
+ $stderr.puts "Run `bundle install` to install missing gems"
8
+ exit e.status_code
9
+ end
10
+ require 'minitest/unit'
11
+ require 'minitest/spec'
12
+
13
+ $LOAD_PATH.unshift(File.dirname(__FILE__))
14
+ $LOAD_PATH.unshift(File.join(File.dirname(__FILE__), '..', 'lib'))
15
+ require 'police-vminfo'
16
+
17
+ class MiniTest::Unit::TestCase
18
+ end
19
+
20
+ MiniTest::Unit.autorun
@@ -0,0 +1,302 @@
1
+ require File.expand_path('../helper.rb', File.dirname(__FILE__))
2
+
3
+ describe Police::VmInfo do
4
+ CORE_MODULES = [Kernel, Process::Sys]
5
+ GEM_MODULES = [MiniTest]
6
+ MODULES = CORE_MODULES + GEM_MODULES
7
+ CORE_CLASSES = [Object, Encoding::Converter]
8
+ GEM_CLASSES = [MiniTest::Unit]
9
+ CLASSES = CORE_CLASSES + GEM_CLASSES
10
+
11
+ describe '#named_modules' do
12
+ let(:result) { Police::VmInfo.named_modules }
13
+ (MODULES + CLASSES).each do |const|
14
+ it "contains #{const}" do
15
+ result.must_include const
16
+ end
17
+ end
18
+ end
19
+
20
+ describe '#named_classes' do
21
+ let(:result) { Police::VmInfo.named_classes }
22
+
23
+ CLASSES.each do |const|
24
+ it "contains #{const}" do
25
+ result.must_include const
26
+ end
27
+ end
28
+
29
+ MODULES.each do |const|
30
+ it "does not contain #{const}" do
31
+ result.wont_include const
32
+ end
33
+ end
34
+ end
35
+
36
+ describe '#all_modules' do
37
+ let(:result) { Police::VmInfo.all_modules }
38
+ (MODULES + CLASSES).each do |const|
39
+ it "contains #{const}" do
40
+ result.must_include const
41
+ end
42
+ end
43
+
44
+ it 'contains anonymous module' do
45
+ anonymous_module = Module.new
46
+ Police::VmInfo.all_modules.must_include anonymous_module
47
+ end
48
+
49
+ it 'contains anonymous class' do
50
+ anonymous_class = Class.new
51
+ Police::VmInfo.all_modules.must_include anonymous_class
52
+ end
53
+ end
54
+
55
+ describe '#all_classes' do
56
+ let(:result) { Police::VmInfo.all_classes }
57
+
58
+ CLASSES.each do |const|
59
+ it "contains #{const}" do
60
+ result.must_include const
61
+ end
62
+ end
63
+
64
+ MODULES.each do |const|
65
+ it "does not contain #{const}" do
66
+ result.wont_include const
67
+ end
68
+ end
69
+
70
+ it 'does not contain anonymous module' do
71
+ anonymous_module = Module.new
72
+ Police::VmInfo.all_classes.wont_include anonymous_module
73
+ end
74
+
75
+ it 'contains anonymous class' do
76
+ anonymous_class = Class.new
77
+ Police::VmInfo.all_classes.must_include anonymous_class
78
+ end
79
+ end
80
+
81
+ describe '#core_modules' do
82
+ let(:result) { Police::VmInfo.core_modules }
83
+
84
+ (CORE_MODULES + CORE_CLASSES).each do |const|
85
+ it "contains #{const}" do
86
+ result.must_include const
87
+ end
88
+ end
89
+
90
+ (GEM_MODULES + GEM_CLASSES).each do |const|
91
+ it "does not contain #{const}" do
92
+ result.wont_include const
93
+ end
94
+ end
95
+ end
96
+
97
+ describe '#code_classes' do
98
+ let(:result) { Police::VmInfo.core_classes }
99
+
100
+ (CORE_CLASSES).each do |const|
101
+ it "contains #{const}" do
102
+ result.must_include const
103
+ end
104
+ end
105
+
106
+ (CORE_MODULES + GEM_MODULES + GEM_CLASSES).each do |const|
107
+ it "does not contain #{const}" do
108
+ result.wont_include const
109
+ end
110
+ end
111
+ end
112
+
113
+ def fixture_module
114
+ Module.new do
115
+ include Enumerable
116
+
117
+ def police_new_module_method; end
118
+ def map; end
119
+
120
+ def self.dup; end
121
+ def self.police_new_module_class_method; end
122
+ end
123
+ end
124
+
125
+ def fixture_class
126
+ Class.new String do
127
+ def police_new_method; end
128
+ def length; end
129
+
130
+ def self.new; end
131
+ def self.police_new_class_method; end
132
+ end
133
+ end
134
+
135
+ describe "#all_methods" do
136
+ describe 'on the fixture module' do
137
+ let :method_names do
138
+ Police::VmInfo.all_methods(fixture_module).map(&:name)
139
+ end
140
+
141
+ it 'contains overridden class methods' do
142
+ method_names.must_include :dup
143
+ end
144
+
145
+ it 'contains new class methods' do
146
+ method_names.must_include :police_new_module_class_method
147
+ end
148
+
149
+ it 'does not contain inherited class methods' do
150
+ method_names.wont_include :clone
151
+ end
152
+
153
+ it 'contains overridden instance methods' do
154
+ method_names.must_include :map
155
+ end
156
+
157
+ it 'contains new instance methods' do
158
+ method_names.must_include :police_new_module_method
159
+ end
160
+
161
+ it 'does not contain inherited instance methods' do
162
+ method_names.wont_include :select
163
+ end
164
+ end
165
+
166
+ describe 'on the fixture class' do
167
+ let :method_names do
168
+ Police::VmInfo.all_methods(fixture_class).map(&:name)
169
+ end
170
+
171
+ it 'contains overridden class methods' do
172
+ method_names.must_include :new
173
+ end
174
+
175
+ it 'contains new class methods' do
176
+ method_names.must_include :police_new_class_method
177
+ end
178
+
179
+ it 'does not contain inherited class methods' do
180
+ method_names.wont_include :superclass
181
+ end
182
+
183
+ it 'contains overridden instance methods' do
184
+ method_names.must_include :length
185
+ end
186
+
187
+ it 'contains new instance methods' do
188
+ method_names.must_include :police_new_method
189
+ end
190
+
191
+ it 'does not contain inherited instance methods' do
192
+ method_names.wont_include :to_s
193
+ end
194
+ end
195
+ end
196
+
197
+ describe "#class_methods" do
198
+ describe 'on the fixture module' do
199
+ let :method_names do
200
+ Police::VmInfo.class_methods(fixture_module).map(&:name)
201
+ end
202
+
203
+ it 'contains overridden methods' do
204
+ method_names.must_include :dup
205
+ end
206
+
207
+ it 'contains new methods' do
208
+ method_names.must_include :police_new_module_class_method
209
+ end
210
+
211
+ it 'does not contain inherited class methods' do
212
+ method_names.wont_include :clone
213
+ end
214
+
215
+ it 'does not contain instance methods' do
216
+ method_names.wont_include :police_new_module_method
217
+ end
218
+ end
219
+
220
+ describe 'on the fixture class' do
221
+ let :method_names do
222
+ Police::VmInfo.class_methods(fixture_class).map(&:name)
223
+ end
224
+
225
+ it 'contains overridden methods' do
226
+ method_names.must_include :new
227
+ end
228
+
229
+ it 'contains new methods' do
230
+ method_names.must_include :police_new_class_method
231
+ end
232
+
233
+ it 'does not contain inherited class methods' do
234
+ method_names.wont_include :superclass
235
+ end
236
+
237
+ it 'does not contain instance methods' do
238
+ method_names.wont_include :police_new_method
239
+ end
240
+ end
241
+ end
242
+
243
+ describe "#instance_methods" do
244
+ describe 'on the fixture module' do
245
+ let :method_names do
246
+ Police::VmInfo.instance_methods(fixture_module).map(&:name)
247
+ end
248
+
249
+ it 'contains overridden methods' do
250
+ method_names.must_include :map
251
+ end
252
+
253
+ it 'contains new methods' do
254
+ method_names.must_include :police_new_module_method
255
+ end
256
+
257
+ it 'does not contain inherited methods' do
258
+ method_names.wont_include :select
259
+ end
260
+
261
+ it 'does not contain class methods' do
262
+ method_names.wont_include :police_new_module_class_method
263
+ end
264
+ end
265
+
266
+ describe 'on the fixture class' do
267
+ let :method_names do
268
+ Police::VmInfo.instance_methods(fixture_class).map(&:name)
269
+ end
270
+
271
+ it 'contains overridden methods' do
272
+ method_names.must_include :length
273
+ end
274
+
275
+ it 'contains new methods' do
276
+ method_names.must_include :police_new_method
277
+ end
278
+
279
+ it 'does not contain inherited methods' do
280
+ method_names.wont_include :to_s
281
+ end
282
+
283
+ it 'does not contain class methods' do
284
+ method_names.wont_include :police_new_class_method
285
+ end
286
+ end
287
+ end
288
+
289
+ describe "#constantize" do
290
+ it 'works on simple names' do
291
+ Police::VmInfo.constantize('Object').must_equal Object
292
+ end
293
+
294
+ it 'works on scoped names' do
295
+ Police::VmInfo.constantize('Process::Sys').must_equal Process::Sys
296
+ end
297
+
298
+ it 'works on global scoped names' do
299
+ Police::VmInfo.constantize('::Process::Sys').must_equal Process::Sys
300
+ end
301
+ end
302
+ end
@@ -0,0 +1,84 @@
1
+ require File.expand_path('../helper.rb', File.dirname(__FILE__))
2
+ require 'net/http'
3
+
4
+ describe Police::VmInfo do
5
+ def some_method; end
6
+
7
+ APP_PATH = Police::VmInfo.method(:gem_path?).source_location.first
8
+ TEST_PATH = self.instance_method(:some_method).source_location.first
9
+ HTTP_PATH = Net::HTTP.method(:new).source_location.first
10
+ BUNDLER_PATH = Bundler.method(:setup).source_location.first
11
+
12
+ describe '#method_source' do
13
+ it 'recognizes stdlib methods' do
14
+ Police::VmInfo.method_source(Net::HTTP.method(:new)).must_equal :stdlib
15
+ end
16
+
17
+ it 'recognizes gem methods' do
18
+ Police::VmInfo.method_source(Bundler.method(:setup)).must_equal :gem
19
+ end
20
+
21
+ it 'recognizes app methods' do
22
+ Police::VmInfo.method_source(Police::VmInfo.method(:gem_path?)).
23
+ must_equal :app
24
+ end
25
+ end
26
+
27
+ describe '#gem_path?' do
28
+ it 'accepts Bundler path' do
29
+ Police::VmInfo.gem_path?(BUNDLER_PATH).must_equal true
30
+ end
31
+
32
+ it 'rejects Net::HTTP path' do
33
+ Police::VmInfo.gem_path?(HTTP_PATH).must_equal false
34
+ end
35
+
36
+ it 'rejects test path' do
37
+ Police::VmInfo.gem_path?(TEST_PATH).must_equal false
38
+ end
39
+
40
+ it 'rejects app path' do
41
+ Police::VmInfo.gem_path?(APP_PATH).must_equal false
42
+ end
43
+ end
44
+
45
+ describe '#stdlib_path?' do
46
+ it 'rejects Bundler path' do
47
+ Police::VmInfo.stdlib_path?(BUNDLER_PATH).must_equal false
48
+ end
49
+
50
+ it 'accepts Net::HTTP path' do
51
+ Police::VmInfo.stdlib_path?(HTTP_PATH).must_equal true
52
+ end
53
+
54
+ it 'rejects test path' do
55
+ Police::VmInfo.stdlib_path?(TEST_PATH).must_equal false
56
+ end
57
+
58
+ it 'rejects app path' do
59
+ Police::VmInfo.stdlib_path?(APP_PATH).must_equal false
60
+ end
61
+ end
62
+
63
+ describe '#kernel_path?' do
64
+ it 'rejects Bundler path' do
65
+ Police::VmInfo.kernel_path?(BUNDLER_PATH).must_equal false
66
+ end
67
+
68
+ it 'rejects Net::HTTP path' do
69
+ Police::VmInfo.kernel_path?(HTTP_PATH).must_equal false
70
+ end
71
+
72
+ it 'rejects test path' do
73
+ Police::VmInfo.kernel_path?(TEST_PATH).must_equal false
74
+ end
75
+
76
+ it 'rejects app path' do
77
+ Police::VmInfo.kernel_path?(APP_PATH).must_equal false
78
+ end
79
+
80
+ it 'accepts a Rubinius kernel path' do
81
+ Police::VmInfo.kernel_path?('kernel/bootstrap/string.rb').must_equal true
82
+ end
83
+ end
84
+ end
@@ -0,0 +1,15 @@
1
+ require File.expand_path('../helper.rb', File.dirname(__FILE__))
2
+
3
+ describe Police::VmInfo do
4
+ describe '#signature' do
5
+ let(:result) { Police::VmInfo.signature }
6
+
7
+ it "should not be empty" do
8
+ result.length.wont_equal 0
9
+ end
10
+
11
+ it "should have a bunch of letters, numbers and .s" do
12
+ result.must_match(/\A\w+[0-9.]+\Z/)
13
+ end
14
+ end
15
+ end
metadata ADDED
@@ -0,0 +1,67 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: police-vminfo
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.0.1
5
+ prerelease:
6
+ platform: ruby
7
+ authors:
8
+ - Victor Costan
9
+ autorequire:
10
+ bindir: bin
11
+ cert_chain: []
12
+ date: 2012-03-28 00:00:00.000000000 Z
13
+ dependencies: []
14
+ description: Collects information about the Ruby VM implementation details.
15
+ email: victor@costan.us
16
+ executables: []
17
+ extensions: []
18
+ extra_rdoc_files:
19
+ - LICENSE.txt
20
+ - README.markdown
21
+ files:
22
+ - .document
23
+ - Gemfile
24
+ - Gemfile.lock
25
+ - LICENSE.txt
26
+ - README.markdown
27
+ - Rakefile
28
+ - VERSION
29
+ - lib/police-vminfo.rb
30
+ - lib/police/vminfo.rb
31
+ - lib/police/vminfo/objects.rb
32
+ - lib/police/vminfo/paths.rb
33
+ - lib/police/vminfo/signature.rb
34
+ - police-vminfo.gemspec
35
+ - test/helper.rb
36
+ - test/vminfo/objects_test.rb
37
+ - test/vminfo/paths_test.rb
38
+ - test/vminfo/signature_test.rb
39
+ homepage: http://github.com/pwnall/police-vminfo
40
+ licenses:
41
+ - MIT
42
+ post_install_message:
43
+ rdoc_options: []
44
+ require_paths:
45
+ - lib
46
+ required_ruby_version: !ruby/object:Gem::Requirement
47
+ none: false
48
+ requirements:
49
+ - - ! '>='
50
+ - !ruby/object:Gem::Version
51
+ version: '0'
52
+ segments:
53
+ - 0
54
+ hash: -2040166733346347996
55
+ required_rubygems_version: !ruby/object:Gem::Requirement
56
+ none: false
57
+ requirements:
58
+ - - ! '>='
59
+ - !ruby/object:Gem::Version
60
+ version: '0'
61
+ requirements: []
62
+ rubyforge_project:
63
+ rubygems_version: 1.8.21
64
+ signing_key:
65
+ specification_version: 3
66
+ summary: Information about the Ruby VM internals.
67
+ test_files: []