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 +5 -0
- data/Gemfile +10 -0
- data/Gemfile.lock +31 -0
- data/LICENSE.txt +20 -0
- data/README.markdown +17 -0
- data/Rakefile +38 -0
- data/VERSION +1 -0
- data/lib/police-vminfo.rb +2 -0
- data/lib/police/vminfo.rb +3 -0
- data/lib/police/vminfo/objects.rb +164 -0
- data/lib/police/vminfo/paths.rb +67 -0
- data/lib/police/vminfo/signature.rb +13 -0
- data/police-vminfo.gemspec +53 -0
- data/test/helper.rb +20 -0
- data/test/vminfo/objects_test.rb +302 -0
- data/test/vminfo/paths_test.rb +84 -0
- data/test/vminfo/signature_test.rb +15 -0
- metadata +67 -0
data/.document
ADDED
data/Gemfile
ADDED
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,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: []
|