Skip to content

Commit

Permalink
Fixup TypeCheck drivers
Browse files Browse the repository at this point in the history
  • Loading branch information
soutaro committed Jul 8, 2020
1 parent 0ea443a commit 612b3bc
Show file tree
Hide file tree
Showing 3 changed files with 11 additions and 25 deletions.
22 changes: 3 additions & 19 deletions lib/rbs/test/setup.rb
Original file line number Diff line number Diff line change
Expand Up @@ -10,18 +10,15 @@
opts = Shellwords.shellsplit(ENV["RBS_TEST_OPT"] || "-I sig")
filter = ENV.fetch("RBS_TEST_TARGET").split(",")
skips = (ENV["RBS_TEST_SKIP"] || "").split(",")
sampling = !ENV.key?("RBS_TEST_NO_SAMPLE")
RBS.logger_level = (ENV["RBS_TEST_LOGLEVEL"] || "info")
rescue
STDERR.puts "rbs/test/setup handles the following environment variables:"
STDERR.puts " [REQUIRED] RBS_TEST_TARGET: test target class name, `Foo::Bar,Foo::Baz` for each class or `Foo::*` for all classes under `Foo`"
STDERR.puts " [OPTIONAL] RBS_TEST_SKIP: skip testing classes"
STDERR.puts " [OPTIONAL] RBS_TEST_OPT: options for signatures (`-r` for libraries or `-I` for signatures)"
STDERR.puts " [OPTIONAL] RBS_TEST_LOGLEVEL: one of debug|info|warn|error|fatal (defaults to info)"
STDERR.puts " [OPTIONAL] RBS_TEST_ARRAY_NO_SAMPLE: if set, all the values of an Array object would be type-checked"
STDERR.puts " [OPTIONAL] RBS_TEST_ENUMERATOR_NO_SAMPLE: if set, all the values of an Enumerator object would be type-checked"
STDERR.puts " [OPTIONAL] RBS_TEST_HASH_NO_SAMPLE: if set, all the values of a Hash object would be type-checked"
STDERR.puts " [OPTIONAL] RBS_TEST_NO_SAMPLING: if set, all the values of any type of collection would be type-checked"
STDERR.puts " [OPTIONAL] RBS_TEST_SAMPLE_SIZE: sets the amount of values in a collection to be type-checked"
STDERR.puts " [OPTIONAL] RBS_TEST_NO_SAMPLE: if set, the type checker tests all the values of a collection"
exit 1
end

Expand All @@ -41,21 +38,9 @@ def match(filter, name)
end
end

def true? obj
!!obj || obj == "false"
end

factory = RBS::Factory.new()
tester = RBS::Test::Tester.new(env: env)

def get_sampling_options
{
Array: true?(ENV['RBS_TEST_ARRAY_NO_SAMPLE']) || true?(ENV['RBS_TEST_NO_SAMPLING']),
Enumerator: true?(ENV['RBS_TEST_ENUMERATOR_NO_SAMPLE']) || true?(ENV['RBS_TEST_NO_SAMPLING']),
Hash: true?(ENV['RBS_TEST_HASH_NO_SAMPLE']) || true?(ENV['RBS_TEST_NO_SAMPLING']),
}
end

TracePoint.trace :end do |tp|
class_name = tp.self.name&.yield_self {|name| factory.type_name(name).absolute! }

Expand All @@ -64,8 +49,7 @@ def get_sampling_options
if tester.checkers.none? {|hook| hook.klass == tp.self }
if env.class_decls.key?(class_name)
logger.info "Setting up hooks for #{class_name}"
tester.install!(tp.self)
hooks << RBS::Test::Hook.install(env, tp.self, logger: logger, sampling_options: get_sampling_options ).verify_all.raise_on_error!(raise_on_error)
tester.install!(tp.self, sampling: sampling)
end
end
end
Expand Down
12 changes: 7 additions & 5 deletions lib/rbs/test/tester.rb
Original file line number Diff line number Diff line change
Expand Up @@ -17,14 +17,14 @@ def builder
@builder ||= DefinitionBuilder.new(env: env)
end

def install!(klass)
def install!(klass, sampling:)
RBS.logger.info { "Installing runtime type checker in #{klass}..." }

type_name = factory.type_name(klass.name).absolute!

builder.build_instance(type_name).tap do |definition|
instance_key = new_key(type_name, "InstanceChecker")
Observer.register(instance_key, MethodCallTester.new(klass, builder, definition, kind: :instance))
Observer.register(instance_key, MethodCallTester.new(klass, builder, definition, kind: :instance, sampling: sampling))

definition.methods.each do |name, method|
if method.implemented_in == type_name
Expand All @@ -36,7 +36,7 @@ def install!(klass)

builder.build_singleton(type_name).tap do |definition|
singleton_key = new_key(type_name, "SingletonChecker")
Observer.register(singleton_key, MethodCallTester.new(klass.singleton_class, builder, definition, kind: :singleton))
Observer.register(singleton_key, MethodCallTester.new(klass.singleton_class, builder, definition, kind: :singleton, sampling: sampling))

definition.methods.each do |name, method|
if method.implemented_in == type_name || name == :new
Expand Down Expand Up @@ -66,20 +66,22 @@ class MethodCallTester
attr_reader :definition
attr_reader :builder
attr_reader :kind
attr_reader :sampling

def initialize(self_class, builder, definition, kind:)
def initialize(self_class, builder, definition, kind:, sampling:)
@self_class = self_class
@definition = definition
@builder = builder
@kind = kind
@sampling = sampling
end

def env
builder.env
end

def check
@check ||= TypeCheck.new(self_class: self_class, builder: builder)
@check ||= TypeCheck.new(self_class: self_class, builder: builder, sampling: sampling)
end

def format_method_name(name)
Expand Down
2 changes: 1 addition & 1 deletion test/rbs/test/tester_test.rb
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@ def move: (?x: Integer, ?y: Integer) -> void
builder = RBS::DefinitionBuilder.new(env: env)
definition = builder.build_instance(type_name("::Hello"))

checker = RBS::Test::Tester::MethodCallTester.new(Object, builder, definition, kind: :instance)
checker = RBS::Test::Tester::MethodCallTester.new(Object, builder, definition, kind: :instance, sampling: true)

# No type error detected
checker.call(
Expand Down

0 comments on commit 612b3bc

Please sign in to comment.