<commit_before>require 'spec_helper'

module LazyTNetstring
  describe Parser do

    describe '#new' do
      subject { LazyTNetstring::Parser.new(data) }

      context 'for anything but a hash' do
        let(:data) { TNetstring.dump(1) }

        it 'rejects initialization' do
          expect { subject }.to raise_error
        end
      end

      context 'for an empty hash' do
        let(:data) { TNetstring.dump({}) }

        it { should be_an LazyTNetstring::Parser }
        its(:data)   { should == data }
        its(:offset) { should == 0 }
        its(:length) { should == data.length }
      end

      context 'for a hash' do
        let(:data) { TNetstring.dump({'key' => 'value', 'another' => 'value'}) }

        it { should be_an LazyTNetstring::Parser }
        its(:data)   { should == data }
        its(:offset) { should == 0 }
        its(:length) { should == data.length }
      end
    end

    describe '#find_key' do
      subject { LazyTNetstring::Parser.new(data).find_key(key) }
      let(:data) {
        TNetstring.dump({'key1' => 'value1',
                         'key2' => 'key3',
                         'key3' => {'subkey1' => 1, 'subkey2' => 2},
                         'key4' => 'value4'
                        })
      }
=begin
85:4:key1,6:value1,4:key2,4:key3,4:key3,28:7:subkey1,1:1#7:subkey2,1:2#}4:key4,6:value4,}
=end

      context 'for unknown key' do
        let(:key) { 'unknown' }
        it 'raises KeyNotFoundError' do
          expect { subject }.to raise_error(LazyTNetstring::KeyNotFoundError)
        end
      end

      context 'for known key' do
        let(:key) { 'key2' }
        its(:offset) { should == 21 }
      end

      context 'where value equals key name' do
        let(:key) { 'key3' }
        its(:offset) { should == 35 }
      end

      context 'for key in nested hash' do
        let(:key) { 'subkey1' }
        it 'rejects key access' do
          expect { s }.to raise_error
        end
      end

      context 'for key after nested hash' do
        let(:key) { 'key4' }
        its(:offset) { should == 74 }
      end
    end

    describe '#next_term' do
      subject { LazyTNetstring::Parser.new(data).next_term(offset) }
      let(:data) { TNetstring.dump({'key_longer_than_10_chars' => 'value1',
                                    'key2' => {'subkey1' => 1, 'subkey2' => 2},
                                    'key3' => 'foobar'}) }
=begin
92:24:key_longer_than_10_chars,6:value1,4:key2,28:7:subkey1,1:1#7:subkey2,1:2#}4:key3,6:foobar,}
=end

      context 'for first term' do
        let(:offset) { 3 }
        it { should be_a LazyTNetstring::Term }
        its(:offset) { should == 6 }
        its(:length) { should == 24 }
      end

      context 'for second term' do
        let(:offset) { 31 }
        its(:offset) { should == 33 }
        its(:length) { should == 6 }
      end

      context 'for third term' do
        let(:offset) { 40 }
        its(:offset) { 42 }
        its(:length) { 4 }
      end

      context 'for term after nested hash' do
        let(:offset) { 79 }
        its(:offset) { 81 }
        its(:length) { 4 }
      end
    end

    describe '#[]' do
      subject { LazyTNetstring::Parser.new(data)[key]}
      let(:key) { 'foo' }

      context 'for empty hash' do
        let(:data) { TNetstring.dump({}) }
        it { should be_nil }
      end

      context 'for unknown keys' do
        let(:data) { TNetstring.dump({'baz' => 'bar'}) }
        it { should be_nil }
      end

      context 'for String' do
        let(:data) { TNetstring.dump({'foo' => 'bar'}) }
        it { should == 'bar' }
        it { should be_a String}
      end

      context 'for nested hash' do
        let(:data) { TNetstring.dump({'outer' => { 'inner' => 'value'} }) }
        let(:key) { 'outer' }

        it { should be_an LazyTNetstring::Parser }
        its(:hash_data) { should == TNetstring.dump({ 'inner' => 'value'}) }
      end

      # TODO provides correct data type of leaf elements
    end

  end
end<commit_msg>reorder spec, add comments and clarify expectations<commit_after>require 'spec_helper'

module LazyTNetstring
  describe Parser do

    describe '#new' do
      subject { LazyTNetstring::Parser.new(data) }

      context 'for anything but a hash' do
        let(:data) { TNetstring.dump(1) }

        it 'rejects initialization' do
          expect { subject }.to raise_error
        end
      end

      context 'for an empty hash' do
        let(:data) { TNetstring.dump({}) }

        it { should be_an LazyTNetstring::Parser }
        its(:data)   { should == data }
        its(:offset) { should == 0 }
        its(:length) { should == data.length }
      end

      context 'for a hash' do
        let(:data) { TNetstring.dump({'key' => 'value', 'another' => 'value'}) }

        it { should be_an LazyTNetstring::Parser }
        its(:data)   { should == data }
        its(:offset) { should == 0 }
        its(:length) { should == data.length }
      end
    end

    describe '#[]' do
      subject { LazyTNetstring::Parser.new(data)[key]}
      let(:key) { 'foo' }

      context 'for empty hash' do
        let(:data) { TNetstring.dump({}) }
        it { should be_nil }
      end

      context 'for unknown keys' do
        let(:data) { TNetstring.dump({'baz' => 'bar'}) }
        it { should be_nil }
      end

      context 'for String' do
        let(:data) { TNetstring.dump({'foo' => 'bar'}) }
        it { should == 'bar' }
        it { should be_a String}
      end

      context 'for nested hash' do
        let(:data) { TNetstring.dump({'outer' => { 'inner' => 'value'} }) }
        let(:key) { 'outer' }

        it { should be_an LazyTNetstring::Parser }
        its(:hash_data) { should == TNetstring.dump({ 'inner' => 'value'}) }
      end

      # TODO provides correct data type of leaf elements
    end

    describe '#find_key' do
      subject { LazyTNetstring::Parser.new(data).find_key(key) }
      let(:data) {
        TNetstring.dump({'key1' => 'value1',
                         'key2' => 'key3',
                         'key3' => {'subkey1' => 1, 'subkey2' => 2},
                         'key4' => 'value4'
                        })
      }
      # data will hold the following tnetstring (WARNING: this relies on
      # Ruby 1.9 ordered hash semantics):
=begin
85:4:key1,6:value1,4:key2,4:key3,4:key3,28:7:subkey1,1:1#7:subkey2,1:2#}4:key4,6:value4,}
=end

      context 'for unknown key' do
        let(:key) { 'unknown' }
        it 'raises KeyNotFoundError' do
          expect { subject }.to raise_error(LazyTNetstring::KeyNotFoundError)
        end
      end

      context 'for known key' do
        let(:key) { 'key2' }
        its(:offset) { should == 21 }
      end

      context 'where value equals key name' do
        let(:key) { 'key3' }
        its(:offset) { should == 35 }
      end

      context 'for a key that is only known in a nested hash' do
        let(:key) { 'subkey1' }
        it 'raises KeyNotFoundError' do
          expect { subject }.to raise_error(LazyTNetstring::KeyNotFoundError)
        end
      end

      context 'for key after nested hash' do
        let(:key) { 'key4' }
        its(:offset) { should == 74 }
      end
    end

    describe '#next_term' do
      subject { LazyTNetstring::Parser.new(data).next_term(offset) }
      let(:data) { TNetstring.dump({'key_longer_than_10_chars' => 'value1',
                                    'key2' => {'subkey1' => 1, 'subkey2' => 2},
                                    'key3' => 'foobar'}) }
      # data will hold the following tnetstring (WARNING: this relies on
      # Ruby 1.9 ordered hash semantics):
=begin
92:24:key_longer_than_10_chars,6:value1,4:key2,28:7:subkey1,1:1#7:subkey2,1:2#}4:key3,6:foobar,}
=end

      context 'for first term' do
        let(:offset) { 3 }
        it { should be_a LazyTNetstring::Term }
        its(:offset) { should == 6 }
        its(:length) { should == 24 }
      end

      context 'for second term' do
        let(:offset) { 31 }
        its(:offset) { should == 33 }
        its(:length) { should == 6 }
      end

      context 'for third term' do
        let(:offset) { 40 }
        its(:offset) { 42 }
        its(:length) { 4 }
      end

      context 'for term after nested hash' do
        let(:offset) { 79 }
        its(:offset) { 81 }
        its(:length) { 4 }
      end
    end

  end
end
{'fraction_non_alphanumeric': 0.1392119629717541, 'fraction_numerical': 0.024448136719677188, 'mean_word_length': 1.9362369337979095, 'pattern_counts': {'":': 0, '<': 3, '<?xml version=': 0, '>': 39, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 4, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '3380666', 'n_tokens_mistral': 2856, 'n_tokens_neox': 2694, 'n_words': 692}