begin require 'spec' require 'appengine-sdk' rescue LoadError require 'rubygems' require 'spec' require 'appengine-sdk' end $:.unshift(File.dirname(__FILE__) + '/../lib') AppEngine::SDK.load_apiproxy require 'appengine-apis/testing' AppEngine::Testing.install_test_env class ProtoMatcher def compare(hash, proto, prefix='') hash.each do |key, value| name = "#{prefix}#{key}" case value when Array if value[0].kind_of? Hash count = proto.send("#{key}_size") compare_value("#{name}.size", value.size, count) value.each_with_index do |item, index| break if index == count compare(item, proto.send(key, index), "#{name}[#{index}].") end else actual = proto.send("#{key}s").to_a compare_value(name, value, actual) end when Hash compare(value, proto.send(key), "#{name}.") else compare_value(name, value, proto.send(key)) end end end def compare_value(label, expected, actual) if expected != actual @failures << "%s differs. expected: %s actual: %s" % [label, expected.inspect, actual.inspect] end end def initialize(klass, expected) @klass = klass @expected = expected end def matches(bytes) @failures = [] @proto = @klass.new @proto.parse_from(bytes) compare(@expected, @proto) @failures.empty? end def ==(bytes) Spec::Expectations.fail_with(failure_message) unless matches(bytes) true end def failure_message @failures.join("\n") end end module ProtoMethods def proto(klass, hash) ProtoMatcher.new(klass, hash) end alias be_proto proto def mock_delegate delegate = mock("apiproxy") delegate.instance_eval do class << self include AppEngine::ApiProxy::Delegate end end end end Spec::Runner.configure do |config| config.include(ProtoMethods) end