summaryrefslogtreecommitdiff
path: root/spec/lib/gitlab/gitaly_client
diff options
context:
space:
mode:
authorGitLab Bot <gitlab-bot@gitlab.com>2022-11-17 11:33:21 +0000
committerGitLab Bot <gitlab-bot@gitlab.com>2022-11-17 11:33:21 +0000
commit7021455bd1ed7b125c55eb1b33c5a01f2bc55ee0 (patch)
tree5bdc2229f5198d516781f8d24eace62fc7e589e9 /spec/lib/gitlab/gitaly_client
parent185b095e93520f96e9cfc31d9c3e69b498cdab7c (diff)
downloadgitlab-ce-7021455bd1ed7b125c55eb1b33c5a01f2bc55ee0.tar.gz
Add latest changes from gitlab-org/gitlab@15-6-stable-eev15.6.0-rc42
Diffstat (limited to 'spec/lib/gitlab/gitaly_client')
-rw-r--r--spec/lib/gitlab/gitaly_client/object_pool_service_spec.rb33
-rw-r--r--spec/lib/gitlab/gitaly_client/operation_service_spec.rb227
-rw-r--r--spec/lib/gitlab/gitaly_client/ref_service_spec.rb20
-rw-r--r--spec/lib/gitlab/gitaly_client/with_feature_flag_actors_spec.rb275
4 files changed, 525 insertions, 30 deletions
diff --git a/spec/lib/gitlab/gitaly_client/object_pool_service_spec.rb b/spec/lib/gitlab/gitaly_client/object_pool_service_spec.rb
index 9c3bc935acc..baf7076c718 100644
--- a/spec/lib/gitlab/gitaly_client/object_pool_service_spec.rb
+++ b/spec/lib/gitlab/gitaly_client/object_pool_service_spec.rb
@@ -4,7 +4,7 @@ require 'spec_helper'
RSpec.describe Gitlab::GitalyClient::ObjectPoolService do
let(:pool_repository) { create(:pool_repository) }
- let(:project) { create(:project, :repository) }
+ let(:project) { pool_repository.source_project }
let(:raw_repository) { project.repository.raw }
let(:object_pool) { pool_repository.object_pool }
@@ -45,21 +45,32 @@ RSpec.describe Gitlab::GitalyClient::ObjectPoolService do
end
describe '#fetch' do
- before do
- subject.delete
+ context 'without changes' do
+ it 'fetches changes' do
+ expect(subject.fetch(project.repository)).to eq(Gitaly::FetchIntoObjectPoolResponse.new)
+ end
end
- it 'restores the pool repository objects' do
- subject.fetch(project.repository)
+ context 'with new reference in source repository' do
+ let(:branch) { 'ref-to-be-fetched' }
+ let(:source_ref) { "refs/heads/#{branch}" }
+ let(:pool_ref) { "refs/remotes/origin/heads/#{branch}" }
- expect(object_pool.repository.exists?).to be(true)
- end
+ before do
+ # Create a new reference in the source repository that we can fetch.
+ project.repository.write_ref(source_ref, 'refs/heads/master')
+ end
- context 'when called twice' do
- it "doesn't raise an error" do
- subject.delete
+ it 'fetches changes' do
+ # Sanity-check to verify that the reference only exists in the source repository now, but not in the
+ # object pool.
+ expect(project.repository.ref_exists?(source_ref)).to be(true)
+ expect(object_pool.repository.ref_exists?(pool_ref)).to be(false)
+
+ subject.fetch(project.repository)
- expect { subject.fetch(project.repository) }.not_to raise_error
+ # The fetch should've created the reference in the object pool.
+ expect(object_pool.repository.ref_exists?(pool_ref)).to be(true)
end
end
end
diff --git a/spec/lib/gitlab/gitaly_client/operation_service_spec.rb b/spec/lib/gitlab/gitaly_client/operation_service_spec.rb
index 7e8aaa3cdf4..604feeea325 100644
--- a/spec/lib/gitlab/gitaly_client/operation_service_spec.rb
+++ b/spec/lib/gitlab/gitaly_client/operation_service_spec.rb
@@ -830,32 +830,225 @@ RSpec.describe Gitlab::GitalyClient::OperationService do
'master', repository)
end
- before do
- expect_any_instance_of(Gitaly::OperationService::Stub)
- .to receive(:user_commit_files).with(kind_of(Enumerator), kind_of(Hash))
- .and_return(response)
- end
+ context 'with unstructured errors' do
+ before do
+ expect_any_instance_of(Gitaly::OperationService::Stub)
+ .to receive(:user_commit_files).with(kind_of(Enumerator), kind_of(Hash))
+ .and_return(response)
+ end
- context 'when a pre_receive_error is present' do
- let(:response) { Gitaly::UserCommitFilesResponse.new(pre_receive_error: "GitLab: something failed") }
+ context 'when a pre_receive_error is present' do
+ let(:response) { Gitaly::UserCommitFilesResponse.new(pre_receive_error: "GitLab: something failed") }
- it 'raises a PreReceiveError' do
- expect { subject }.to raise_error(Gitlab::Git::PreReceiveError, "something failed")
+ it 'raises a PreReceiveError' do
+ expect { subject }.to raise_error(Gitlab::Git::PreReceiveError, "something failed")
+ end
end
- end
- context 'when an index_error is present' do
- let(:response) { Gitaly::UserCommitFilesResponse.new(index_error: "something failed") }
+ context 'when an index_error is present' do
+ let(:response) { Gitaly::UserCommitFilesResponse.new(index_error: "something failed") }
- it 'raises a PreReceiveError' do
- expect { subject }.to raise_error(Gitlab::Git::Index::IndexError, "something failed")
+ it 'raises an IndexError' do
+ expect { subject }.to raise_error(Gitlab::Git::Index::IndexError, "something failed")
+ end
+ end
+
+ context 'when branch_update is nil' do
+ let(:response) { Gitaly::UserCommitFilesResponse.new }
+
+ it { expect(subject).to be_nil }
end
end
- context 'when branch_update is nil' do
- let(:response) { Gitaly::UserCommitFilesResponse.new }
+ context 'with structured errors' do
+ context 'with AccessCheckError' do
+ before do
+ expect_any_instance_of(Gitaly::OperationService::Stub)
+ .to receive(:user_commit_files).with(kind_of(Enumerator), kind_of(Hash))
+ .and_raise(raised_error)
+ end
- it { expect(subject).to be_nil }
+ let(:raised_error) do
+ new_detailed_error(
+ GRPC::Core::StatusCodes::PERMISSION_DENIED,
+ "error updating file",
+ Gitaly::UserCommitFilesError.new(
+ access_check: Gitaly::AccessCheckError.new(
+ error_message: "something went wrong"
+ )))
+ end
+
+ it 'raises a PreReceiveError' do
+ expect { subject }.to raise_error do |error|
+ expect(error).to be_a(Gitlab::Git::PreReceiveError)
+ expect(error.message).to eq("something went wrong")
+ end
+ end
+ end
+
+ context 'with IndexError' do
+ let(:status_code) { nil }
+ let(:expected_error) { nil }
+
+ let(:structured_error) do
+ new_detailed_error(
+ status_code,
+ "unused error message",
+ expected_error)
+ end
+
+ shared_examples '#user_commit_files failure' do
+ it 'raises a PreReceiveError' do
+ expect_any_instance_of(Gitaly::OperationService::Stub)
+ .to receive(:user_commit_files).with(kind_of(Enumerator), kind_of(Hash))
+ .and_raise(structured_error)
+
+ expect { subject }.to raise_error do |error|
+ expect(error).to be_a(Gitlab::Git::Index::IndexError)
+ expect(error.message).to eq(expected_message)
+ end
+ end
+ end
+
+ context 'with missing file' do
+ let(:status_code) { GRPC::Core::StatusCodes::NOT_FOUND }
+ let(:expected_message) { "File not found: README.md" }
+ let(:expected_error) do
+ Gitaly::UserCommitFilesError.new(
+ index_update: Gitaly::IndexError.new(
+ path: "README.md",
+ error_type: Gitaly::IndexError::ErrorType::ERROR_TYPE_FILE_NOT_FOUND
+ ))
+ end
+
+ it_behaves_like '#user_commit_files failure'
+ end
+
+ context 'with existing directory' do
+ let(:status_code) { GRPC::Core::StatusCodes::ALREADY_EXISTS }
+ let(:expected_message) { "Directory already exists: dir1" }
+ let(:expected_error) do
+ Gitaly::UserCommitFilesError.new(
+ index_update: Gitaly::IndexError.new(
+ path: "dir1",
+ error_type: Gitaly::IndexError::ErrorType::ERROR_TYPE_DIRECTORY_EXISTS
+ ))
+ end
+
+ it_behaves_like '#user_commit_files failure'
+ end
+
+ context 'with existing file' do
+ let(:status_code) { GRPC::Core::StatusCodes::ALREADY_EXISTS }
+ let(:expected_message) { "File already exists: README.md" }
+ let(:expected_error) do
+ Gitaly::UserCommitFilesError.new(
+ index_update: Gitaly::IndexError.new(
+ path: "README.md",
+ error_type: Gitaly::IndexError::ErrorType::ERROR_TYPE_FILE_EXISTS
+ ))
+ end
+
+ it_behaves_like '#user_commit_files failure'
+ end
+
+ context 'with invalid path' do
+ let(:status_code) { GRPC::Core::StatusCodes::INVALID_ARGUMENT }
+ let(:expected_message) { "Invalid path: invalid://file/name" }
+ let(:expected_error) do
+ Gitaly::UserCommitFilesError.new(
+ index_update: Gitaly::IndexError.new(
+ path: "invalid://file/name",
+ error_type: Gitaly::IndexError::ErrorType::ERROR_TYPE_INVALID_PATH
+ ))
+ end
+
+ it_behaves_like '#user_commit_files failure'
+ end
+
+ context 'with directory traversal' do
+ let(:status_code) { GRPC::Core::StatusCodes::INVALID_ARGUMENT }
+ let(:expected_message) { "Directory traversal in path escapes repository: ../../../../etc/shadow" }
+ let(:expected_error) do
+ Gitaly::UserCommitFilesError.new(
+ index_update: Gitaly::IndexError.new(
+ path: "../../../../etc/shadow",
+ error_type: Gitaly::IndexError::ErrorType::ERROR_TYPE_DIRECTORY_TRAVERSAL
+ ))
+ end
+
+ it_behaves_like '#user_commit_files failure'
+ end
+
+ context 'with empty path' do
+ let(:status_code) { GRPC::Core::StatusCodes::INVALID_ARGUMENT }
+ let(:expected_message) { "Received empty path" }
+ let(:expected_error) do
+ Gitaly::UserCommitFilesError.new(
+ index_update: Gitaly::IndexError.new(
+ path: "",
+ error_type: Gitaly::IndexError::ErrorType::ERROR_TYPE_EMPTY_PATH
+ ))
+ end
+
+ it_behaves_like '#user_commit_files failure'
+ end
+
+ context 'with unspecified error' do
+ let(:status_code) { GRPC::Core::StatusCodes::INVALID_ARGUMENT }
+ let(:expected_message) { "Unknown error performing git operation" }
+ let(:expected_error) do
+ Gitaly::UserCommitFilesError.new(
+ index_update: Gitaly::IndexError.new(
+ path: "",
+ error_type: Gitaly::IndexError::ErrorType::ERROR_TYPE_UNSPECIFIED
+ ))
+ end
+
+ it_behaves_like '#user_commit_files failure'
+ end
+
+ context 'with an exception without the detailed error' do
+ let(:permission_error) do
+ GRPC::PermissionDenied.new
+ end
+
+ it 'raises PermissionDenied' do
+ expect_any_instance_of(Gitaly::OperationService::Stub)
+ .to receive(:user_commit_files).with(kind_of(Enumerator), kind_of(Hash))
+ .and_raise(permission_error)
+
+ expect { subject }.to raise_error(GRPC::PermissionDenied)
+ end
+ end
+ end
+
+ context 'with CustomHookError' do
+ before do
+ expect_any_instance_of(Gitaly::OperationService::Stub)
+ .to receive(:user_commit_files).with(kind_of(Enumerator), kind_of(Hash))
+ .and_raise(raised_error)
+ end
+
+ let(:raised_error) do
+ new_detailed_error(
+ GRPC::Core::StatusCodes::PERMISSION_DENIED,
+ "error updating file",
+ Gitaly::UserCommitFilesError.new(
+ custom_hook: Gitaly::CustomHookError.new(
+ stdout: "some stdout",
+ stderr: "GitLab: some custom hook error message",
+ hook_type: Gitaly::CustomHookError::HookType::HOOK_TYPE_PRERECEIVE
+ )))
+ end
+
+ it 'raises a PreReceiveError' do
+ expect { subject }.to raise_error do |error|
+ expect(error).to be_a(Gitlab::Git::PreReceiveError)
+ expect(error.message).to eq("some custom hook error message")
+ end
+ end
+ end
end
end
diff --git a/spec/lib/gitlab/gitaly_client/ref_service_spec.rb b/spec/lib/gitlab/gitaly_client/ref_service_spec.rb
index 5ce88b06241..bd96e9baf1d 100644
--- a/spec/lib/gitlab/gitaly_client/ref_service_spec.rb
+++ b/spec/lib/gitlab/gitaly_client/ref_service_spec.rb
@@ -3,7 +3,7 @@
require 'spec_helper'
RSpec.describe Gitlab::GitalyClient::RefService do
- let_it_be(:project) { create(:project, :repository) }
+ let_it_be(:project) { create(:project, :repository, create_tag: 'test') }
let(:storage_name) { project.repository_storage }
let(:relative_path) { project.disk_path + '.git' }
@@ -438,12 +438,28 @@ RSpec.describe Gitlab::GitalyClient::RefService do
it 'sends a find_refs_by_oid message' do
expect_any_instance_of(Gitaly::RefService::Stub)
.to receive(:find_refs_by_oid)
- .with(gitaly_request_with_params(sort_field: 'refname', oid: oid, limit: 1), kind_of(Hash))
+ .with(gitaly_request_with_params(sort_field: 'refname',
+ oid: oid,
+ limit: 1), kind_of(Hash))
.and_call_original
refs = client.find_refs_by_oid(oid: oid, limit: 1)
expect(refs.to_a).to eq([Gitlab::Git::BRANCH_REF_PREFIX + project.repository.root_ref])
end
+
+ it 'filters by ref_patterns' do
+ expect_any_instance_of(Gitaly::RefService::Stub)
+ .to receive(:find_refs_by_oid)
+ .with(gitaly_request_with_params(sort_field: 'refname',
+ oid: oid,
+ limit: 1,
+ ref_patterns: [Gitlab::Git::TAG_REF_PREFIX]), kind_of(Hash))
+ .and_call_original
+
+ refs = client.find_refs_by_oid(oid: oid, limit: 1, ref_patterns: [Gitlab::Git::TAG_REF_PREFIX])
+
+ expect(refs.to_a).to eq([Gitlab::Git::TAG_REF_PREFIX + 'test'])
+ end
end
end
diff --git a/spec/lib/gitlab/gitaly_client/with_feature_flag_actors_spec.rb b/spec/lib/gitlab/gitaly_client/with_feature_flag_actors_spec.rb
new file mode 100644
index 00000000000..41dce5d76dd
--- /dev/null
+++ b/spec/lib/gitlab/gitaly_client/with_feature_flag_actors_spec.rb
@@ -0,0 +1,275 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+RSpec.describe Gitlab::GitalyClient::WithFeatureFlagActors do
+ let(:user) { create(:user) }
+ let(:service) do
+ Class.new do
+ include Gitlab::GitalyClient::WithFeatureFlagActors
+ end.new
+ end
+
+ describe '#user_actor' do
+ context 'when user is not available in ApplicationContext' do
+ it 'returns nil' do
+ expect(service.user_actor).to be(nil)
+ end
+ end
+
+ context 'when user is available in ApplicationContext' do
+ around do |example|
+ ::Gitlab::ApplicationContext.with_context(user: user) { example.run }
+ end
+
+ it 'returns corresponding user record' do
+ expect(service.user_actor.flipper_id).to eql(user.flipper_id)
+ end
+ end
+
+ context 'when user does not exist' do
+ around do |example|
+ ::Gitlab::ApplicationContext.with_context(user: SecureRandom.uuid) { example.run }
+ end
+
+ it 'returns corresponding user record' do
+ expect(service.user_actor).to be(nil)
+ end
+ end
+ end
+
+ describe '#repository, #project_actor, #group_actor' do
+ context 'when normal project repository' do
+ let_it_be(:project) { create(:project, group: create(:group)) }
+ let(:expected_project) { project }
+ let(:expected_group) { Feature::Gitaly::ActorWrapper.new(::Group, project.group.id) }
+
+ it_behaves_like 'Gitaly feature flag actors are inferred from repository' do
+ let(:repository) { project.repository }
+ end
+
+ it_behaves_like 'Gitaly feature flag actors are inferred from repository' do
+ let(:repository) { project.repository.raw }
+ end
+
+ it_behaves_like 'Gitaly feature flag actors are inferred from repository' do
+ let(:repository) { raw_repo_without_container(project.repository) }
+ end
+ end
+
+ context 'when project wiki repository' do
+ let_it_be(:project) { create(:project, :wiki_repo, group: create(:group)) }
+ let(:expected_project) { nil }
+ let(:expected_group) { nil }
+
+ it_behaves_like 'Gitaly feature flag actors are inferred from repository' do
+ let(:repository) { project.wiki.repository }
+ end
+
+ it_behaves_like 'Gitaly feature flag actors are inferred from repository' do
+ let(:repository) { project.wiki.repository.raw }
+ end
+
+ it_behaves_like 'Gitaly feature flag actors are inferred from repository' do
+ let(:repository) { raw_repo_without_container(project.wiki.repository) }
+ end
+ end
+
+ context 'when repository of project in user namespace' do
+ let_it_be(:project) { create(:project, namespace: create(:user).namespace) }
+ let(:expected_project) { project }
+ let(:expected_group) { Feature::Gitaly::ActorWrapper.new(::Group, project.namespace_id) }
+
+ it_behaves_like 'Gitaly feature flag actors are inferred from repository' do
+ let(:repository) { project.repository }
+ end
+
+ it_behaves_like 'Gitaly feature flag actors are inferred from repository' do
+ let(:repository) { project.repository.raw }
+ end
+
+ it_behaves_like 'Gitaly feature flag actors are inferred from repository' do
+ let(:repository) { raw_repo_without_container(project.repository) }
+ end
+ end
+
+ context 'when personal snippet' do
+ let(:snippet) { create(:personal_snippet) }
+ let(:expected_project) { nil }
+ let(:expected_group) { nil }
+
+ it_behaves_like 'Gitaly feature flag actors are inferred from repository' do
+ let(:repository) { snippet.repository }
+ end
+
+ it_behaves_like 'Gitaly feature flag actors are inferred from repository' do
+ let(:repository) { snippet.repository.raw }
+ end
+
+ it_behaves_like 'Gitaly feature flag actors are inferred from repository' do
+ let(:repository) { raw_repo_without_container(snippet.repository) }
+ end
+ end
+
+ context 'when project snippet' do
+ let_it_be(:project) { create(:project, group: create(:group)) }
+ let(:snippet) { create(:project_snippet, project: project) }
+ let(:expected_project) { nil }
+ let(:expected_group) { nil }
+
+ it_behaves_like 'Gitaly feature flag actors are inferred from repository' do
+ let(:repository) { snippet.repository }
+ end
+
+ it_behaves_like 'Gitaly feature flag actors are inferred from repository' do
+ let(:repository) { snippet.repository.raw }
+ end
+
+ it_behaves_like 'Gitaly feature flag actors are inferred from repository' do
+ let(:repository) { raw_repo_without_container(snippet.repository) }
+ end
+ end
+
+ context 'when project design' do
+ let_it_be(:project) { create(:project, group: create(:group)) }
+ let(:issue) { create(:issue, project: project) }
+ let(:design) { create(:design, issue: issue) }
+
+ let(:expected_project) { project }
+ let(:expected_group) { project.group }
+
+ it_behaves_like 'Gitaly feature flag actors are inferred from repository' do
+ let(:repository) { design.repository }
+ end
+
+ it_behaves_like 'Gitaly feature flag actors are inferred from repository' do
+ let(:repository) { design.repository.raw }
+ end
+
+ it_behaves_like 'Gitaly feature flag actors are inferred from repository' do
+ let(:repository) { raw_repo_without_container(design.repository) }
+ end
+ end
+ end
+
+ describe '#gitaly_client_call' do
+ let(:call_arg_1) { double }
+ let(:call_arg_2) { double }
+ let(:call_arg_3) { double }
+ let(:call_result) { double }
+
+ before do
+ allow(Gitlab::GitalyClient).to receive(:call).and_return(call_result)
+ end
+
+ context 'when actors_aware_gitaly_calls flag is enabled' do
+ let(:repository_actor) { instance_double(::Repository) }
+ let(:user_actor) { instance_double(::User) }
+ let(:project_actor) { instance_double(Project) }
+ let(:group_actor) { instance_double(Group) }
+
+ before do
+ stub_feature_flags(actors_aware_gitaly_calls: true)
+
+ allow(service).to receive(:user_actor).and_return(user_actor)
+ allow(service).to receive(:repository_actor).and_return(repository_actor)
+ allow(service).to receive(:project_actor).and_return(project_actor)
+ allow(service).to receive(:group_actor).and_return(group_actor)
+ allow(Gitlab::GitalyClient).to receive(:with_feature_flag_actors).and_call_original
+ end
+
+ it 'triggers client call with feature flag actors' do
+ result = service.gitaly_client_call(call_arg_1, call_arg_2, karg: call_arg_3)
+
+ expect(Gitlab::GitalyClient).to have_received(:call).with(call_arg_1, call_arg_2, karg: call_arg_3)
+ expect(Gitlab::GitalyClient).to have_received(:with_feature_flag_actors).with(
+ repository: repository_actor,
+ user: user_actor,
+ project: project_actor,
+ group: group_actor
+ )
+ expect(result).to be(call_result)
+ end
+
+ context 'when call without repository_actor' do
+ before do
+ allow(service).to receive(:repository_actor).and_return(nil)
+ allow(Gitlab::ErrorTracking).to receive(:track_and_raise_for_dev_exception).and_call_original
+ end
+
+ it 'calls error tracking track_and_raise_for_dev_exception' do
+ expect do
+ service.gitaly_client_call(call_arg_1, call_arg_2, karg: call_arg_3)
+ end.to raise_error /gitaly_client_call called without setting repository_actor/
+
+ expect(Gitlab::ErrorTracking).to have_received(:track_and_raise_for_dev_exception).with(
+ be_a(Feature::InvalidFeatureFlagError)
+ )
+ end
+ end
+ end
+
+ context 'when actors_aware_gitaly_calls not enabled' do
+ before do
+ stub_feature_flags(actors_aware_gitaly_calls: false)
+ end
+
+ it 'triggers client call without feature flag actors' do
+ expect(Gitlab::GitalyClient).not_to receive(:with_feature_flag_actors)
+
+ result = service.gitaly_client_call(call_arg_1, call_arg_2, karg: call_arg_3)
+
+ expect(Gitlab::GitalyClient).to have_received(:call).with(call_arg_1, call_arg_2, karg: call_arg_3)
+ expect(result).to be(call_result)
+ end
+ end
+
+ describe '#gitaly_feature_flag_actors' do
+ let_it_be(:project) { create(:project) }
+ let(:repository_actor) { project.repository }
+
+ context 'when actors_aware_gitaly_calls flag is enabled' do
+ let(:user_actor) { instance_double(::User) }
+ let(:project_actor) { instance_double(Project) }
+ let(:group_actor) { instance_double(Group) }
+
+ before do
+ stub_feature_flags(actors_aware_gitaly_calls: true)
+
+ allow(Feature::Gitaly).to receive(:user_actor).and_return(user_actor)
+ allow(Feature::Gitaly).to receive(:project_actor).with(project).and_return(project_actor)
+ allow(Feature::Gitaly).to receive(:group_actor).with(project).and_return(group_actor)
+ end
+
+ it 'returns a hash with collected feature flag actors' do
+ result = service.gitaly_feature_flag_actors(repository_actor)
+ expect(result).to eql(
+ repository: repository_actor,
+ user: user_actor,
+ project: project_actor,
+ group: group_actor
+ )
+
+ expect(Feature::Gitaly).to have_received(:user_actor).with(no_args)
+ expect(Feature::Gitaly).to have_received(:project_actor).with(project)
+ expect(Feature::Gitaly).to have_received(:group_actor).with(project)
+ end
+ end
+
+ context 'when actors_aware_gitaly_calls not enabled' do
+ before do
+ stub_feature_flags(actors_aware_gitaly_calls: false)
+ end
+
+ it 'returns an empty hash' do
+ expect(Feature::Gitaly).not_to receive(:user_actor)
+ expect(Feature::Gitaly).not_to receive(:project_actor)
+ expect(Feature::Gitaly).not_to receive(:group_actor)
+
+ result = service.gitaly_feature_flag_actors(repository_actor)
+ expect(result).to eql({})
+ end
+ end
+ end
+ end
+end