<commit_before># encoding: utf-8
require "spec_helper"

# Note that hash specific specs are based off the rubyspec library, and
# converted manually to RSpec syntax.
#
# @see https://github.com/rubyspec/rubyspec/tree/master/core/hash
describe BSON::Document do

  pending "#=="
  pending "#[]"
  pending "#[]"
  pending "#[]="

  describe "#allocate" do

    let(:doc) do
      described_class.allocate
    end

    it "returns an instance of a Document" do
      expect(doc).to be_a(described_class)
    end

    it "returns a fully-formed instance of a Document" do
      expect(doc.size).to eq(0)
    end
  end

  describe "#assoc" do

    let(:doc) do
      { :apple => :green, :orange => :orange, :grape => :green, :banana => :yellow }
    end

    it "returns an Array if the argument is == to a key of the Hash" do
      expect(doc.assoc(:apple)).to be_a(Array)
    end

    it "returns a 2-element Array if the argument is == to a key of the Hash" do
      expect(doc.assoc(:grape).size).to eq(2)
    end

    it "sets the first element of the Array to the located key" do
      expect(doc.assoc(:banana).first).to eq(:banana)
    end

    it "sets the last element of the Array to the value of the located key" do
      expect(doc.assoc(:banana).last).to eq(:yellow)
    end

    it "uses #== to compare the argument to the keys" do
      doc[1.0] = :value
      expect(doc.assoc(1)).to eq([ 1.0, :value ])
    end

    it "returns nil if the argument is not a key of the Hash" do
      expect(doc.assoc(:green)).to be_nil
    end

    context "when the document compares by identity" do

      before do
        doc.compare_by_identity
        doc["pear"] = :red
        doc["pear"] = :green
      end

      it "duplicates keys" do
        expect(doc.keys.grep(/pear/).size).to eq(2)
      end

      it "only returns the first matching key-value pair" do
        expect(doc.assoc("pear")).to eq([ "pear", :red ])
      end
    end

    context "when there is a default value" do

      context "when specified in the constructor" do

        let(:doc) do
          described_class.new(42).merge!(:foo => :bar)
        end

        context "when the argument is not a key" do

          it "returns nil" do
            expect(doc.assoc(42)).to be_nil
          end
        end
      end

      context "when specified by a block" do

        let(:doc) do
          described_class.new{|h, k| h[k] = 42}.merge!(:foo => :bar)
        end

        context "when the argument is not a key" do

          it "returns nil" do
            expect(doc.assoc(42)).to be_nil
          end
        end
      end
    end
  end

  describe "#clear" do

    let(:doc) do
      described_class[1 => 2, 3 => 4]
    end

    it "removes all key, value pairs" do
      expect(doc.clear).to be_empty
    end

    it "returns the same instance" do
      expect(doc.clear).to eql(doc)
    end

    context "when the document has a default" do

      context "when the default is a value" do

        let(:doc) do
          described_class.new(5)
        end

        before do
          doc.clear
        end

        it "keeps the default value" do
          expect(doc.default).to eq(5)
        end

        it "returns the default for empty keys" do
          expect(doc["z"]).to eq(5)
        end
      end

      context "when the default is a proc" do

        let(:doc) do
          described_class.new { 5 }
        end

        before do
          doc.clear
        end

        it "keeps the default proc" do
          expect(doc.default_proc).to_not be_nil
        end

        it "returns the default for empty keys" do
          expect(doc["z"]).to eq(5)
        end
      end
    end

    context "when the document is frozen" do

      before do
        doc.freeze
      end

      it "raises an error" do
        expect {
          doc.clear
        }.to raise_error(RuntimeError)
      end
    end
  end

  pending "#compare_by_identity"
  pending "#compare_by_identity?"
  pending "#default"
  pending "#default="
  pending "#default_proc"
  pending "#default_proc="
  pending "#delete"
  pending "#delete_if"
  pending "#each"
  pending "#each_key"
  pending "#each_pair"
  pending "#each_value"
  pending "#empty?"
  pending "#eql?"
  pending "#fetch"<commit_msg>Adding in specs for compare_by_identity<commit_after># encoding: utf-8
require "spec_helper"

# Note that hash specific specs are based off the rubyspec library, and
# converted manually to RSpec syntax.
#
# @see https://github.com/rubyspec/rubyspec/tree/master/core/hash
describe BSON::Document do

  pending "#=="
  pending "#[]"
  pending "#[]"
  pending "#[]="

  describe "#allocate" do

    let(:doc) do
      described_class.allocate
    end

    it "returns an instance of a Document" do
      expect(doc).to be_a(described_class)
    end

    it "returns a fully-formed instance of a Document" do
      expect(doc.size).to eq(0)
    end
  end

  describe "#assoc" do

    let(:doc) do
      { :apple => :green, :orange => :orange, :grape => :green, :banana => :yellow }
    end

    it "returns an Array if the argument is == to a key of the Hash" do
      expect(doc.assoc(:apple)).to be_a(Array)
    end

    it "returns a 2-element Array if the argument is == to a key of the Hash" do
      expect(doc.assoc(:grape).size).to eq(2)
    end

    it "sets the first element of the Array to the located key" do
      expect(doc.assoc(:banana).first).to eq(:banana)
    end

    it "sets the last element of the Array to the value of the located key" do
      expect(doc.assoc(:banana).last).to eq(:yellow)
    end

    it "uses #== to compare the argument to the keys" do
      doc[1.0] = :value
      expect(doc.assoc(1)).to eq([ 1.0, :value ])
    end

    it "returns nil if the argument is not a key of the Hash" do
      expect(doc.assoc(:green)).to be_nil
    end

    context "when the document compares by identity" do

      before do
        doc.compare_by_identity
        doc["pear"] = :red
        doc["pear"] = :green
      end

      it "duplicates keys" do
        expect(doc.keys.grep(/pear/).size).to eq(2)
      end

      it "only returns the first matching key-value pair" do
        expect(doc.assoc("pear")).to eq([ "pear", :red ])
      end
    end

    context "when there is a default value" do

      context "when specified in the constructor" do

        let(:doc) do
          described_class.new(42).merge!(:foo => :bar)
        end

        context "when the argument is not a key" do

          it "returns nil" do
            expect(doc.assoc(42)).to be_nil
          end
        end
      end

      context "when specified by a block" do

        let(:doc) do
          described_class.new{|h, k| h[k] = 42}.merge!(:foo => :bar)
        end

        context "when the argument is not a key" do

          it "returns nil" do
            expect(doc.assoc(42)).to be_nil
          end
        end
      end
    end
  end

  describe "#clear" do

    let(:doc) do
      described_class[1 => 2, 3 => 4]
    end

    it "removes all key, value pairs" do
      expect(doc.clear).to be_empty
    end

    it "returns the same instance" do
      expect(doc.clear).to eql(doc)
    end

    context "when the document has a default" do

      context "when the default is a value" do

        let(:doc) do
          described_class.new(5)
        end

        before do
          doc.clear
        end

        it "keeps the default value" do
          expect(doc.default).to eq(5)
        end

        it "returns the default for empty keys" do
          expect(doc["z"]).to eq(5)
        end
      end

      context "when the default is a proc" do

        let(:doc) do
          described_class.new { 5 }
        end

        before do
          doc.clear
        end

        it "keeps the default proc" do
          expect(doc.default_proc).to_not be_nil
        end

        it "returns the default for empty keys" do
          expect(doc["z"]).to eq(5)
        end
      end
    end

    context "when the document is frozen" do

      before do
        doc.freeze
      end

      it "raises an error" do
        expect {
          doc.clear
        }.to raise_error(RuntimeError)
      end
    end
  end

  describe "#compare_by_identity" do

    let(:doc) do
      described_class.new
    end

    let!(:identity) do
      doc.compare_by_identity
    end

    it "causes future comparisons on the receiver to be made by identity" do
      doc["a"] = :a
      expect(doc["a"]).to be_nil
    end

    it "causes #compare_by_identity? to return true" do
      expect(doc.compare_by_identity?).to be_true
    end

    it "returns self" do
      expect(identity).to eql(doc)
    end

    it "uses the semantics of BasicObject#equal? to determine key identity" do
      doc[-0.0] = :a
      doc[-0.0] = :b
      doc[[ 1 ]] = :c
      doc[[ 1 ]] = :d
      doc[:bar] = :e
      doc[:bar] = :f
      doc["bar"] = :g
      doc["bar"] = :h
      expect(doc.values).to eq([ :a, :b, :c, :d, :f, :g, :h ])
    end

    it "uses #equal? semantics, but doesn't actually call #equal? to determine identity" do
      obj = mock("equal")
      obj.should_not_receive(:equal?)
      doc[:foo] = :glark
      doc[obj] = :a
      expect(doc[obj]).to eq(:a)
    end

    it "regards #dup'd objects as having different identities" do
      str = "foo"
      doc[str.dup] = :str
      expect(doc[str]).to be_nil
    end

    it "regards #clone'd objects as having different identities" do
      str = 'foo'
      doc[str.clone] = :str
      expect(doc[str]).to be_nil
    end

    it "regards references to the same object as having the same identity" do
      o = Object.new
      doc[o] = :o
      doc[:a] = :a
      expect(doc[o]).to eq(:o)
    end

    it "perists over #dups" do
      doc["foo"] = :bar
      doc["foo"] = :glark
      expect(doc.dup).to eq(doc)
      expect(doc.dup.size).to eq(doc.size)
    end

    it "persists over #clones" do
      doc["foo"] = :bar
      doc["foo"] = :glark
      expect(doc.clone).to eq(doc)
      expect(doc.clone.size).to eq(doc.size)
    end

    context "when the document is frozen" do

      before do
        doc.freeze
      end

      it "raises a RuntimeError on frozen hashes" do
        expect {
          doc.compare_by_identity
        }.to raise_error(RuntimeError)
      end
    end
  end

  pending "#compare_by_identity?"
  pending "#default"
  pending "#default="
  pending "#default_proc"
  pending "#default_proc="
  pending "#delete"
  pending "#delete_if"
  pending "#each"
  pending "#each_key"
  pending "#each_pair"
  pending "#each_value"
  pending "#empty?"
  pending "#eql?"
  pending "#fetch"
{'fraction_non_alphanumeric': 0.10730700684738767, 'fraction_numerical': 0.005627989869618235, 'mean_word_length': 2.0367416690401594, 'pattern_counts': {'":': 0, '<': 3, '<?xml version=': 0, '>': 19, 'https://': 2, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 1, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '4800307', 'n_tokens_mistral': 3495, 'n_tokens_neox': 3325, 'n_words': 1135}