From a00578ce5cdf4bab95990bca9e806c6322bb1384 Mon Sep 17 00:00:00 2001 From: Robert Speicher Date: Wed, 4 Jan 2017 13:43:06 -0500 Subject: Absorb gitlab_git --- spec/lib/gitlab/git/diff_collection_spec.rb | 460 ++++++++++++++++++++++++++++ 1 file changed, 460 insertions(+) create mode 100644 spec/lib/gitlab/git/diff_collection_spec.rb (limited to 'spec/lib/gitlab/git/diff_collection_spec.rb') diff --git a/spec/lib/gitlab/git/diff_collection_spec.rb b/spec/lib/gitlab/git/diff_collection_spec.rb new file mode 100644 index 00000000000..4fa72c565ae --- /dev/null +++ b/spec/lib/gitlab/git/diff_collection_spec.rb @@ -0,0 +1,460 @@ +require 'spec_helper' + +describe Gitlab::Git::DiffCollection, seed_helper: true do + subject do + Gitlab::Git::DiffCollection.new( + iterator, + max_files: max_files, + max_lines: max_lines, + all_diffs: all_diffs, + no_collapse: no_collapse + ) + end + let(:iterator) { Array.new(file_count, fake_diff(line_length, line_count)) } + let(:file_count) { 0 } + let(:line_length) { 1 } + let(:line_count) { 1 } + let(:max_files) { 10 } + let(:max_lines) { 100 } + let(:all_diffs) { false } + let(:no_collapse) { true } + + describe '#to_a' do + subject { super().to_a } + it { is_expected.to be_kind_of ::Array } + end + + describe :decorate! do + let(:file_count) { 3 } + + it 'modifies the array in place' do + count = 0 + subject.decorate! { |d| !d.nil? && count += 1 } + expect(subject.to_a).to eq([1, 2, 3]) + expect(count).to eq(3) + end + + it 'avoids future iterator iterations' do + subject.decorate! { |d| d unless d.nil? } + + expect(iterator).not_to receive(:each) + + subject.overflow? + end + end + + context 'overflow handling' do + context 'adding few enough files' do + let(:file_count) { 3 } + + context 'and few enough lines' do + let(:line_count) { 10 } + + describe '#overflow?' do + subject { super().overflow? } + it { is_expected.to be_falsey } + end + + describe '#empty?' do + subject { super().empty? } + it { is_expected.to be_falsey } + end + + describe '#real_size' do + subject { super().real_size } + it { is_expected.to eq('3') } + end + it { expect(subject.size).to eq(3) } + + context 'when limiting is disabled' do + let(:all_diffs) { true } + + describe '#overflow?' do + subject { super().overflow? } + it { is_expected.to be_falsey } + end + + describe '#empty?' do + subject { super().empty? } + it { is_expected.to be_falsey } + end + + describe '#real_size' do + subject { super().real_size } + it { is_expected.to eq('3') } + end + it { expect(subject.size).to eq(3) } + end + end + + context 'and too many lines' do + let(:line_count) { 1000 } + + describe '#overflow?' do + subject { super().overflow? } + it { is_expected.to be_truthy } + end + + describe '#empty?' do + subject { super().empty? } + it { is_expected.to be_falsey } + end + + describe '#real_size' do + subject { super().real_size } + it { is_expected.to eq('0+') } + end + it { expect(subject.size).to eq(0) } + + context 'when limiting is disabled' do + let(:all_diffs) { true } + + describe '#overflow?' do + subject { super().overflow? } + it { is_expected.to be_falsey } + end + + describe '#empty?' do + subject { super().empty? } + it { is_expected.to be_falsey } + end + + describe '#real_size' do + subject { super().real_size } + it { is_expected.to eq('3') } + end + it { expect(subject.size).to eq(3) } + end + end + end + + context 'adding too many files' do + let(:file_count) { 11 } + + context 'and few enough lines' do + let(:line_count) { 1 } + + describe '#overflow?' do + subject { super().overflow? } + it { is_expected.to be_truthy } + end + + describe '#empty?' do + subject { super().empty? } + it { is_expected.to be_falsey } + end + + describe '#real_size' do + subject { super().real_size } + it { is_expected.to eq('10+') } + end + it { expect(subject.size).to eq(10) } + + context 'when limiting is disabled' do + let(:all_diffs) { true } + + describe '#overflow?' do + subject { super().overflow? } + it { is_expected.to be_falsey } + end + + describe '#empty?' do + subject { super().empty? } + it { is_expected.to be_falsey } + end + + describe '#real_size' do + subject { super().real_size } + it { is_expected.to eq('11') } + end + it { expect(subject.size).to eq(11) } + end + end + + context 'and too many lines' do + let(:line_count) { 30 } + + describe '#overflow?' do + subject { super().overflow? } + it { is_expected.to be_truthy } + end + + describe '#empty?' do + subject { super().empty? } + it { is_expected.to be_falsey } + end + + describe '#real_size' do + subject { super().real_size } + it { is_expected.to eq('3+') } + end + it { expect(subject.size).to eq(3) } + + context 'when limiting is disabled' do + let(:all_diffs) { true } + + describe '#overflow?' do + subject { super().overflow? } + it { is_expected.to be_falsey } + end + + describe '#empty?' do + subject { super().empty? } + it { is_expected.to be_falsey } + end + + describe '#real_size' do + subject { super().real_size } + it { is_expected.to eq('11') } + end + it { expect(subject.size).to eq(11) } + end + end + end + + context 'adding exactly the maximum number of files' do + let(:file_count) { 10 } + + context 'and few enough lines' do + let(:line_count) { 1 } + + describe '#overflow?' do + subject { super().overflow? } + it { is_expected.to be_falsey } + end + + describe '#empty?' do + subject { super().empty? } + it { is_expected.to be_falsey } + end + + describe '#real_size' do + subject { super().real_size } + it { is_expected.to eq('10') } + end + it { expect(subject.size).to eq(10) } + end + end + + context 'adding too many bytes' do + let(:file_count) { 10 } + let(:line_length) { 5200 } + + describe '#overflow?' do + subject { super().overflow? } + it { is_expected.to be_truthy } + end + + describe '#empty?' do + subject { super().empty? } + it { is_expected.to be_falsey } + end + + describe '#real_size' do + subject { super().real_size } + it { is_expected.to eq('9+') } + end + it { expect(subject.size).to eq(9) } + + context 'when limiting is disabled' do + let(:all_diffs) { true } + + describe '#overflow?' do + subject { super().overflow? } + it { is_expected.to be_falsey } + end + + describe '#empty?' do + subject { super().empty? } + it { is_expected.to be_falsey } + end + + describe '#real_size' do + subject { super().real_size } + it { is_expected.to eq('10') } + end + it { expect(subject.size).to eq(10) } + end + end + end + + describe 'empty collection' do + subject { Gitlab::Git::DiffCollection.new([]) } + + describe '#overflow?' do + subject { super().overflow? } + it { is_expected.to be_falsey } + end + + describe '#empty?' do + subject { super().empty? } + it { is_expected.to be_truthy } + end + + describe '#size' do + subject { super().size } + it { is_expected.to eq(0) } + end + + describe '#real_size' do + subject { super().real_size } + it { is_expected.to eq('0')} + end + end + + describe :each do + context 'when diff are too large' do + let(:collection) do + Gitlab::Git::DiffCollection.new([{ diff: 'a' * 204800 }]) + end + + it 'yields Diff instances even when they are too large' do + expect { |b| collection.each(&b) }. + to yield_with_args(an_instance_of(Gitlab::Git::Diff)) + end + + it 'prunes diffs that are too large' do + diff = nil + + collection.each do |d| + diff = d + end + + expect(diff.diff).to eq('') + end + end + + context 'when diff is quite large will collapse by default' do + let(:iterator) { [{ diff: 'a' * 20480 }] } + + context 'when no collapse is set' do + let(:no_collapse) { true } + + it 'yields Diff instances even when they are quite big' do + expect { |b| subject.each(&b) }. + to yield_with_args(an_instance_of(Gitlab::Git::Diff)) + end + + it 'does not prune diffs' do + diff = nil + + subject.each do |d| + diff = d + end + + expect(diff.diff).not_to eq('') + end + end + + context 'when no collapse is unset' do + let(:no_collapse) { false } + + it 'yields Diff instances even when they are quite big' do + expect { |b| subject.each(&b) }. + to yield_with_args(an_instance_of(Gitlab::Git::Diff)) + end + + it 'prunes diffs that are quite big' do + diff = nil + + subject.each do |d| + diff = d + end + + expect(diff.diff).to eq('') + end + + context 'when go over safe limits on files' do + let(:iterator) { [ fake_diff(1, 1) ] * 4 } + + before(:each) do + stub_const('Gitlab::Git::DiffCollection::DEFAULT_LIMITS', { max_files: 2, max_lines: max_lines }) + end + + it 'prunes diffs by default even little ones' do + subject.each_with_index do |d, i| + if i < 2 + expect(d.diff).not_to eq('') + else # 90 lines + expect(d.diff).to eq('') + end + end + end + end + + context 'when go over safe limits on lines' do + let(:iterator) do + [ + fake_diff(1, 45), + fake_diff(1, 45), + fake_diff(1, 20480), + fake_diff(1, 1) + ] + end + + before(:each) do + stub_const('Gitlab::Git::DiffCollection::DEFAULT_LIMITS', { max_files: max_files, max_lines: 80 }) + end + + it 'prunes diffs by default even little ones' do + subject.each_with_index do |d, i| + if i < 2 + expect(d.diff).not_to eq('') + else # 90 lines + expect(d.diff).to eq('') + end + end + end + end + + context 'when go over safe limits on bytes' do + let(:iterator) do + [ + fake_diff(1, 45), + fake_diff(1, 45), + fake_diff(1, 20480), + fake_diff(1, 1) + ] + end + + before(:each) do + stub_const('Gitlab::Git::DiffCollection::DEFAULT_LIMITS', { max_files: max_files, max_lines: 80 }) + end + + it 'prunes diffs by default even little ones' do + subject.each_with_index do |d, i| + if i < 2 + expect(d.diff).not_to eq('') + else # > 80 bytes + expect(d.diff).to eq('') + end + end + end + end + end + + context 'when limiting is disabled' do + let(:all_diffs) { true } + + it 'yields Diff instances even when they are quite big' do + expect { |b| subject.each(&b) }. + to yield_with_args(an_instance_of(Gitlab::Git::Diff)) + end + + it 'does not prune diffs' do + diff = nil + + subject.each do |d| + diff = d + end + + expect(diff.diff).not_to eq('') + end + end + end + end + + def fake_diff(line_length, line_count) + { 'diff' => "#{'a' * line_length}\n" * line_count } + end +end -- cgit v1.2.1