123456789_123456789_123456789_123456789_123456789_

Module: RBS::UnitTest::TypeAssertions

Relationships & Source Files
Namespace Children
Modules:
Defined in: lib/rbs/unit_test/type_assertions.rb

Class Method Summary

Instance Method Summary

Class Method Details

.included(base)

[ GitHub ]

  
# File 'lib/rbs/unit_test/type_assertions.rb', line 57

def self.included(base)
  base.extend ClassMethods
end

Instance Method Details

#allow_non_simple_method_type

[ GitHub ]

  
# File 'lib/rbs/unit_test/type_assertions.rb', line 314

def allow_non_simple_method_type()
  begin
    @allows_non_simple_method_type = true
    yield
  rescue
    @allows_non_simple_method_type = false
  end
end

#allows_error(*errors)

[ GitHub ]

  
# File 'lib/rbs/unit_test/type_assertions.rb', line 246

def allows_error(*errors)
  yield
rescue *errors => exn
  notify "Error allowed: #{exn.inspect}"
end

#assert_const_type(type, constant_name)

[ GitHub ]

  
# File 'lib/rbs/unit_test/type_assertions.rb', line 252

def assert_const_type(type, constant_name)
  constant = Object.const_get(constant_name)

  typecheck = RBS::Test::TypeCheck.new(
    self_class: constant.class,
    instance_class: instance_class,
    class_class: class_class,
    builder: builder,
    sample_size: 100,
    unchecked_classes: []
  )

  value_type =
    case type
    when String
      RBS::Parser.parse_type(type, variables: []) || raise
    else
      type
    end

  assert typecheck.value(constant, value_type), "`#{constant_name}` (#{constant.inspect}) must be compatible with given type `#{value_type}`"

  type_name = TypeName(constant_name).absolute!
  definition = env.constant_entry(type_name)
  assert definition, "Cannot find RBS type definition of `#{constant_name}`"

  case definition
  when RBS::Environment::ClassEntry, RBS::Environment::ModuleEntry
    definition_type = RBS::Types::ClassSingleton.new(name: type_name, location: nil)
  when RBS::Environment::ClassAliasEntry, RBS::Environment::ModuleAliasEntry
    type_name = env.normalize_type_name!(type_name)
    definition_type = RBS::Types::ClassSingleton.new(name: type_name, location: nil)
  when RBS::Environment::ConstantEntry
    definition_type = definition.decl.type
  end

  assert definition_type, "Cannot find RBS entry for `#{constant_name}`"
  definition_type or raise
  assert typecheck.value(constant, definition_type), "`#{constant_name}` (#{constant.inspect}) must be compatible with RBS type definition `#{definition_type}`"
end

#assert_type(type, value)

[ GitHub ]

  
# File 'lib/rbs/unit_test/type_assertions.rb', line 293

def assert_type(type, value)
  typecheck = RBS::Test::TypeCheck.new(
    self_class: value.class,
    instance_class: _ = "No `instance` class allowed",
    class_class: _ = "No `class` class allowed",
    builder: builder,
    sample_size: 100,
    unchecked_classes: []
  )

  type =
    case type
    when String
      RBS::Parser.parse_type(type, variables: []) or raise
    else
      type
    end

  assert typecheck.value(value, type), "`#{value.inspect}` must be compatible with given type `#{type}`"
end

#break_from_block(value = nil)

[ GitHub ]

  
# File 'lib/rbs/unit_test/type_assertions.rb', line 331

def break_from_block(value = nil)
  raise "Cannot break without `@break_tag`" unless @break_tag
  throw @break_tag, value
end

#builder

[ GitHub ]

  
# File 'lib/rbs/unit_test/type_assertions.rb', line 65

def builder
  (_ = self.class).builder
end

#class_class

[ GitHub ]

  
# File 'lib/rbs/unit_test/type_assertions.rb', line 121

def class_class
  type, _ = target

  case type
  when RBS::Types::ClassSingleton, RBS::Types::ClassInstance
    Object.const_get(type.name.to_s).singleton_class
  end
end

#env

[ GitHub ]

  
# File 'lib/rbs/unit_test/type_assertions.rb', line 61

def env
  (_ = self.class).env
end

#instance_class

[ GitHub ]

  
# File 'lib/rbs/unit_test/type_assertions.rb', line 112

def instance_class
  type, _ = target

  case type
  when RBS::Types::ClassSingleton, RBS::Types::ClassInstance
    Object.const_get(type.name.to_s)
  end
end

#method_types(method)

[ GitHub ]

  
# File 'lib/rbs/unit_test/type_assertions.rb', line 230

def method_types(method)
  type, definition = target

  case type
  when Types::ClassInstance
    subst = RBS::Substitution.build(definition.type_params, type.args)
    definition.methods[method].method_types.map do |method_type|
      method_type.sub(subst)
    end
  when Types::ClassSingleton
    definition.methods[method].method_types
  else
    raise
  end
end

#pass(message = nil)

[ GitHub ]

  
# File 'lib/rbs/unit_test/type_assertions.rb', line 336

def pass(message = nil)
  assert true, message
end

#send_setup(method_type, receiver, method, args, proc) {|mt, last_trace, result, exception| ... }

Yields:

  • (mt, last_trace, result, exception)
[ GitHub ]

  
# File 'lib/rbs/unit_test/type_assertions.rb', line 130

def send_setup(method_type, receiver, method, args, proc)
  mt =
    case method_type
    when String
      RBS::Parser.parse_method_type(method_type, variables: []) || raise
    when RBS::MethodType
      method_type
    end

  validate_simple_method_type(mt)

  trace = [] #: Array[Test::CallTrace]
  spy = Spy.wrap(receiver, method)
  spy.callback = -> (result) { trace << result }

  result = nil #: untyped
  exception = nil #: Exception?
  non_jump_exit = true

  begin
    result = catch do |tag|
      @break_tag = tag
      spy.wrapped_object.__send__(method, *args, &proc)
    ensure
      @break_tag = nil
    end

    non_jump_exit = false
  rescue Exception => exn
    exception = exn
  ensure
    if non_jump_exit && !exception
      raise "`break` nor `return` from blocks given to `assert_send_type` are prohibited. Use `#break_from_block` instead."
    end
  end

  last_trace = trace.last or raise

  yield(mt, last_trace, result, exception)
end

#target

[ GitHub ]

  
# File 'lib/rbs/unit_test/type_assertions.rb', line 73

def target
  targets.last || (_ = self.class).target
end

#targets

[ GitHub ]

  
# File 'lib/rbs/unit_test/type_assertions.rb', line 69

def targets
  @targets ||= []
end

#testing(type_or_string)

[ GitHub ]

  
# File 'lib/rbs/unit_test/type_assertions.rb', line 77

def testing(type_or_string)
  type = case type_or_string
         when String
           RBS::Parser.parse_type(type_or_string, variables: [])
         else
           type_or_string
         end

  definition = case type
               when RBS::Types::ClassInstance
                 builder.build_instance(type.name)
               when RBS::Types::ClassSingleton
                 builder.build_singleton(type.name)
               else
                 raise "Test target should be class instance or class singleton: #{type}"
               end

  targets.push(
    [
      type,  #: target_type
      definition
    ]
  )

  if block_given?
    begin
      yield
    ensure
      targets.pop
    end
  else
    [type, definition]
  end
end

#validate_simple_method_type(type)

[ GitHub ]

  
# File 'lib/rbs/unit_test/type_assertions.rb', line 323

def validate_simple_method_type(type)
  return if @allows_non_simple_method_type

  refute_predicate type, :has_self_type?, "`self` types is prohibited in method type: `#{type}`"
  refute_predicate type, :has_classish_type?, "`instance` and `class` types is prohibited in method type: `#{type}`"
  refute_predicate type, :with_nonreturn_void?, "`void` is only allowed at return type or generics parameters: `#{type}`"
end