diff --git a/lib/etcdv3/lock.rb b/lib/etcdv3/lock.rb index a439d61..ce9b36c 100644 --- a/lib/etcdv3/lock.rb +++ b/lib/etcdv3/lock.rb @@ -10,12 +10,12 @@ def initialize(hostname, credentials, timeout, metadata = {}) def lock(name, lease_id, timeout: nil) request = V3lockpb::LockRequest.new(name: name, lease: lease_id) - @stub.lock(request, deadline: deadline(timeout)) + @stub.lock(request, metadata: @metadata, deadline: deadline(timeout)) end def unlock(key, timeout: nil) request = V3lockpb::UnlockRequest.new(key: key) - @stub.unlock(request, deadline: deadline(timeout)) + @stub.unlock(request, metadata: @metadata, deadline: deadline(timeout)) end private diff --git a/lib/etcdv3/namespace/lock.rb b/lib/etcdv3/namespace/lock.rb index d31cd2a..76b60f6 100644 --- a/lib/etcdv3/namespace/lock.rb +++ b/lib/etcdv3/namespace/lock.rb @@ -13,14 +13,14 @@ def initialize(hostname, credentials, timeout, namespace, metadata = {}) def lock(name, lease_id, timeout: nil) name = prepend_prefix(@namespace, name) request = V3lockpb::LockRequest.new(name: name, lease: lease_id) - resp = @stub.lock(request, deadline: deadline(timeout)) + resp = @stub.lock(request, metadata: @metadata, deadline: deadline(timeout)) strip_prefix_from_lock(@namespace, resp) end def unlock(key, timeout: nil) key = prepend_prefix(@namespace, key) request = V3lockpb::UnlockRequest.new(key: key) - @stub.unlock(request, deadline: deadline(timeout)) + @stub.unlock(request, metadata: @metadata, deadline: deadline(timeout)) end private diff --git a/spec/etcdv3/lock_spec.rb b/spec/etcdv3/lock_spec.rb index 39ac574..7917545 100644 --- a/spec/etcdv3/lock_spec.rb +++ b/spec/etcdv3/lock_spec.rb @@ -10,14 +10,28 @@ #it_should_behave_like "a method with a GRPC timeout", described_class, :lock, :lock, 'foo' describe '#lock' do - let(:lease_id) { lease_stub.lease_grant(10)['ID'] } - subject { stub.lock('foo', lease_id) } - it { is_expected.to be_an_instance_of(V3lockpb::LockResponse) } + it 'returns a response' do + lease_id = lease_stub.lease_grant(10)['ID'] + + expect(stub.lock('example1', lease_id)).to be_an_instance_of(V3lockpb::LockResponse) + end + + it 'passes metadata correctly' do + lease_id = lease_stub.lease_grant(10)['ID'] + stub = expect_metadata_passthrough(described_class, :lock, :lock) + stub.lock('example2', lease_id) + end end describe '#unlock' do - subject { stub.unlock('foo') } - it { is_expected.to be_an_instance_of(V3lockpb::UnlockResponse) } + it 'returns a response' do + expect(stub.unlock('example3')).to be_an_instance_of(V3lockpb::UnlockResponse) + end + + it 'passes metadata correctly' do + stub = expect_metadata_passthrough(described_class, :unlock, :unlock) + stub.unlock('example4') + end end end end diff --git a/spec/etcdv3/namespace/lock_spec.rb b/spec/etcdv3/namespace/lock_spec.rb index 784ce2f..e976181 100644 --- a/spec/etcdv3/namespace/lock_spec.rb +++ b/spec/etcdv3/namespace/lock_spec.rb @@ -2,22 +2,41 @@ # Locking is not implemented in etcd v3.1.X unless $instance.version < Gem::Version.new("3.2.0") - describe Etcdv3::Lock do + describe Etcdv3::Namespace::Lock do let(:stub) { local_namespace_stub(Etcdv3::Namespace::Lock, 1, '/namespace/') } let(:lease_stub) { local_stub(Etcdv3::Lease, 1) } - it_should_behave_like "a method with a GRPC timeout", described_class, :unlock, :unlock, 'foo' + # NOTE: this was running duplicate tests against Etcdv3::Lock before, but it + # doesn't work with Etcdv3::Namespace::Lock + # + # it_should_behave_like "a method with a GRPC timeout", described_class, :unlock, :unlock, 'foo' + # it_should_behave_like "a method with a GRPC timeout", described_class, :lock, :lock, 'foo' describe '#lock' do - let(:lease_id) { lease_stub.lease_grant(10)['ID'] } - subject { stub.lock('foo', lease_id) } - it { is_expected.to be_an_instance_of(V3lockpb::LockResponse) } + it 'returns a response' do + lease_id = lease_stub.lease_grant(10)['ID'] + expect(stub.lock('example1', lease_id)).to( + be_an_instance_of(V3lockpb::LockResponse) + ) + end + + it 'passes metadata correctly' do + lease_id = lease_stub.lease_grant(10)['ID'] + stub = expect_metadata_passthrough_namespace(described_class, :lock, :lock, '/namespace/') + stub.lock('example2', lease_id) + end end describe '#unlock' do - subject { stub.unlock('foo') } - it { is_expected.to be_an_instance_of(V3lockpb::UnlockResponse) } + it 'returns a response' do + expect(stub.unlock('example3')).to be_an_instance_of(V3lockpb::UnlockResponse) + end + + it 'passes metadata correctly' do + stub = expect_metadata_passthrough_namespace(described_class, :unlock, :unlock, '/namespace/') + stub.unlock('example4') + end end end end diff --git a/spec/helpers/connections.rb b/spec/helpers/connections.rb index 00081b5..ce626ed 100644 --- a/spec/helpers/connections.rb +++ b/spec/helpers/connections.rb @@ -21,10 +21,18 @@ def local_stub(interface, timeout=nil) interface.new(local_url, :this_channel_is_insecure, timeout, {}) end + def local_stub_with_metadata(interface, timeout: nil, metadata: {}) + interface.new(local_url, :this_channel_is_insecure, timeout, metadata) + end + def local_namespace_stub(interface, timeout=nil, namespace) interface.new(local_url, :this_channel_is_insecure, timeout, namespace, {}) end + def local_namespace_stub_with_metadata(interface, timeout: nil, namespace:, metadata: {}) + interface.new(local_url, :this_channel_is_insecure, timeout, namespace, metadata) + end + def local_url "127.0.0.1:#{port}" end diff --git a/spec/helpers/metadata_passthrough.rb b/spec/helpers/metadata_passthrough.rb new file mode 100644 index 0000000..57f2d84 --- /dev/null +++ b/spec/helpers/metadata_passthrough.rb @@ -0,0 +1,21 @@ +module Helpers + module MetadataPassthrough + include Connections + + def expect_metadata_passthrough(stub_class, method_name, expectation_target) + metadata = { user: "foo", password: "bar" } + handler = local_stub_with_metadata(stub_class, metadata: metadata, timeout: 1) + inner_stub = handler.instance_variable_get("@stub") + expect(inner_stub).to receive(expectation_target).with(anything, hash_including(metadata: metadata)).and_call_original + return handler + end + + def expect_metadata_passthrough_namespace(stub_class, method_name, expectation_target, namespace) + metadata = { user: "foo", password: "bar" } + handler = local_namespace_stub_with_metadata(stub_class, metadata: metadata, timeout: 1, namespace: namespace) + inner_stub = handler.instance_variable_get("@stub") + expect(inner_stub).to receive(expectation_target).with(anything, hash_including(metadata: metadata)).and_call_original + return handler + end + end +end diff --git a/spec/helpers/test_instance.rb b/spec/helpers/test_instance.rb index b6bf525..d4fde29 100644 --- a/spec/helpers/test_instance.rb +++ b/spec/helpers/test_instance.rb @@ -3,10 +3,12 @@ require 'socket' require 'timeout' require 'helpers/connections' +require 'helpers/metadata_passthrough' module Helpers class TestInstance include Helpers::Connections + include Helpers::MetadataPassthrough class InvalidVersionException < StandardError; end class PortInUseException < StandardError; end diff --git a/spec/spec_helper.rb b/spec/spec_helper.rb index 125b885..885f54e 100644 --- a/spec/spec_helper.rb +++ b/spec/spec_helper.rb @@ -11,12 +11,14 @@ require 'etcdv3' require 'helpers/test_instance' require 'helpers/connections' +require 'helpers/metadata_passthrough' require 'helpers/shared_examples_for_timeout' $instance = Helpers::TestInstance.new RSpec.configure do |config| config.include(Helpers::Connections) + config.include(Helpers::MetadataPassthrough) config.expect_with :rspec do |expectations| expectations.include_chain_clauses_in_custom_matcher_descriptions = true