ようへいの日々精進XP

よかろうもん

2018 年 02 月 13 日(火)

ジョギング

  • お休み
  • 朝、起きた後の体調が悪すぎる

日課

  • お休み

夕飯

  • 片栗粉をまぶして焼いた手羽中とベビーホタテで出汁を取ったらとても美味しかった

今日のるびぃ ~ awspec の issue に挑む (1) ~

issue

github.com

Elasticache for Redis のキャッシュパラメータグループ timeout というパラメータを its メソッドでテストしようとした場合に, Object#timeout が呼ばれてしまうというもの. ちなみに Object#timeoutRuby 2.3.0 以降は deprecated 扱いになっている.

method_missing

キャッシュパラメータのそれぞれのパラメータを awspec はどのように解釈しているのかというと, 以下のように Object#method_missing を使って解釈しているはず.

...
    def method_missing(name)
      param_name = name.to_s.tr('_', '-')
      if resource_via_client.include?(param_name)
        resource_via_client[param_name].to_s
      else
        super
      end
    end
...

ところが, 手元で試してみると, この method_missing に捕捉された直後に timeout は Object#timeout として呼ばれてしまっているような挙動.

動作確認

lib/awspec/stub/elasticache_cache_parameter_group.rb を以下のように記述する.

Aws.config[:elasticache] = {
  stub_responses: {
    describe_cache_parameters: {
      parameters: [
        {
          parameter_name: 'timeout',
          parameter_value: '0'
        }
      ]
    }
  }
}

spec/type/elasticache_cache_parameter_group_spec.rb を以下のように記述する.

require 'spec_helper'
Awspec::Stub.load 'elasticache_cache_parameter_group'

describe elasticache_cache_parameter_group('my-cache-parameter-group') do
  its(:timeout) { should eq '0' }
end

実行すると, 以下のように Fail となる.

...
../bundle/ruby/2.3.0/gems/rspec-its-1.2.0/lib/rspec/its.rb:115:in `block (3 levels) in its': Object#timeout is deprecated, use Timeout.timeout instead.
F

Failures:

  1) elasticache_cache_parameter_group 'my-cache-parameter-group' timeout 
     Failure/Error: its(:timeout) { should eq '0' }
     
     ArgumentError:
       wrong number of arguments (given 0, expected 1..2)
     # ./spec/type/elasticache_cache_parameter_group_spec.rb:8:in `block (2 levels) in <top (required)>'

Finished in 0.01082 seconds (files took 1.33 seconds to load)
4 examples, 1 failure

Failed examples:

rspec ./spec/type/elasticache_cache_parameter_group_spec.rb:8 # elasticache_cache_parameter_group 'my-cache-parameter-group' timeout 
...

ふむふむ.

で, どうしようか...

先述の method_missing を呼ばれた直後に, Object#timeout メソッドとして呼ばれている状況からすると, この Object#timeout を無効にすれば良いのでは...

class Object
  undef timeout
end

Object クラスをオープンクラスして timeout メソッドを undef してみた. この方法はメタプログラミング Ruby の「3.5 ブランクスレート」に書かれている方法を参考にしてみた.

$ bundle exec rake spec:elasticache_cache_parameter_group
.........

Finished in 0.01789 seconds (files took 1.47 seconds to load)
9 examples, 0 failures

一応, LGTM. ただ, Object#timeout を無効にすることによる影響範囲ってどんなもんなんだろうと思ったり.

ふむふむ.