| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640 | #!/usr/bin/rubyrequire 'google/protobuf'require 'test/unit'class RepeatedFieldTest < Test::Unit::TestCase  def test_acts_like_enumerator    m = TestMessage.new    (Enumerable.instance_methods - TestMessage.new.repeated_string.methods).each do |method_name|      assert m.repeated_string.respond_to?(method_name) == true, "does not respond to #{method_name}"    end  end  def test_acts_like_an_array    m = TestMessage.new    arr_methods = ([].methods - TestMessage.new.repeated_string.methods)    # jRuby additions to the Array class that we can ignore    arr_methods -= [ :indices, :iter_for_each, :iter_for_each_index,      :iter_for_each_with_index, :dimensions, :copy_data, :copy_data_simple,      :nitems, :iter_for_reverse_each, :indexes]    arr_methods.each do |method_name|      assert m.repeated_string.respond_to?(method_name) == true, "does not respond to #{method_name}"    end  end  def test_first    m = TestMessage.new    repeated_field_names(TestMessage).each do |field_name|      assert_nil m.send(field_name).first    end    fill_test_msg(m)    assert_equal -10, m.repeated_int32.first    assert_equal -1_000_000, m.repeated_int64.first    assert_equal 10, m.repeated_uint32.first    assert_equal 1_000_000, m.repeated_uint64.first    assert_equal true, m.repeated_bool.first    assert_equal -1.01,  m.repeated_float.first.round(2)    assert_equal -1.0000000000001, m.repeated_double.first    assert_equal 'foo', m.repeated_string.first    assert_equal "bar".encode!('ASCII-8BIT'), m.repeated_bytes.first    assert_equal TestMessage2.new(:foo => 1), m.repeated_msg.first    assert_equal :A, m.repeated_enum.first  end  def test_last    m = TestMessage.new    repeated_field_names(TestMessage).each do |field_name|      assert_nil m.send(field_name).first    end    fill_test_msg(m)    assert_equal -11, m.repeated_int32.last    assert_equal -1_000_001, m.repeated_int64.last    assert_equal 11, m.repeated_uint32.last    assert_equal 1_000_001, m.repeated_uint64.last    assert_equal false, m.repeated_bool.last    assert_equal -1.02, m.repeated_float.last.round(2)    assert_equal -1.0000000000002, m.repeated_double.last    assert_equal 'bar', m.repeated_string.last    assert_equal "foo".encode!('ASCII-8BIT'), m.repeated_bytes.last    assert_equal TestMessage2.new(:foo => 2), m.repeated_msg.last    assert_equal :B, m.repeated_enum.last  end  def test_pop    m = TestMessage.new    repeated_field_names(TestMessage).each do |field_name|      assert_nil m.send(field_name).pop    end    fill_test_msg(m)    assert_equal -11, m.repeated_int32.pop    assert_equal -10, m.repeated_int32.pop    assert_equal -1_000_001, m.repeated_int64.pop    assert_equal -1_000_000, m.repeated_int64.pop    assert_equal 11, m.repeated_uint32.pop    assert_equal 10, m.repeated_uint32.pop    assert_equal 1_000_001, m.repeated_uint64.pop    assert_equal 1_000_000, m.repeated_uint64.pop    assert_equal false, m.repeated_bool.pop    assert_equal true, m.repeated_bool.pop    assert_equal -1.02,  m.repeated_float.pop.round(2)    assert_equal -1.01,  m.repeated_float.pop.round(2)    assert_equal -1.0000000000002, m.repeated_double.pop    assert_equal -1.0000000000001, m.repeated_double.pop    assert_equal 'bar', m.repeated_string.pop    assert_equal 'foo', m.repeated_string.pop    assert_equal "foo".encode!('ASCII-8BIT'), m.repeated_bytes.pop    assert_equal "bar".encode!('ASCII-8BIT'), m.repeated_bytes.pop    assert_equal TestMessage2.new(:foo => 2), m.repeated_msg.pop    assert_equal TestMessage2.new(:foo => 1), m.repeated_msg.pop    assert_equal :B, m.repeated_enum.pop    assert_equal :A, m.repeated_enum.pop    repeated_field_names(TestMessage).each do |field_name|      assert_nil m.send(field_name).pop    end    fill_test_msg(m)    assert_equal ['bar', 'foo'], m.repeated_string.pop(2)    assert_nil m.repeated_string.pop  end  def test_each    m = TestMessage.new    5.times{|i| m.repeated_string << 'string' }    count = 0    m.repeated_string.each do |val|      assert_equal 'string', val      count += 1    end    assert_equal 5, count    result = m.repeated_string.each{|val| val + '_junk'}    assert_equal ['string'] * 5, result  end  def test_empty?    m = TestMessage.new    assert_equal true, m.repeated_string.empty?    m.repeated_string << 'foo'    assert_equal false, m.repeated_string.empty?    m.repeated_string << 'bar'    assert_equal false, m.repeated_string.empty?  end  def test_array_accessor    m = TestMessage.new    reference_arr = %w(foo bar baz)    m.repeated_string += reference_arr.clone    check_self_modifying_method(m.repeated_string, reference_arr) do |arr|      arr[1]    end    check_self_modifying_method(m.repeated_string, reference_arr) do |arr|      arr[-2]    end    check_self_modifying_method(m.repeated_string, reference_arr) do |arr|      arr[20]    end    check_self_modifying_method(m.repeated_string, reference_arr) do |arr|      arr[1, 2]    end    check_self_modifying_method(m.repeated_string, reference_arr) do |arr|      arr[0..2]    end    check_self_modifying_method(m.repeated_string, reference_arr) do |arr|      arr[-1, 1]    end    check_self_modifying_method(m.repeated_string, reference_arr) do |arr|      arr[10, 12]    end  end  def test_array_settor    m = TestMessage.new    reference_arr = %w(foo bar baz)    m.repeated_string += reference_arr.clone    check_self_modifying_method(m.repeated_string, reference_arr) do |arr|      arr[1] = 'junk'    end    check_self_modifying_method(m.repeated_string, reference_arr) do |arr|      arr[-2] = 'snappy'    end    check_self_modifying_method(m.repeated_string, reference_arr) do |arr|      arr[3] = ''    end    # slight deviation; we are strongly typed, and nil is not allowed    # for string types;    m.repeated_string[5] = 'spacious'    assert_equal ["foo", "snappy", "baz", "", "", "spacious"], m.repeated_string    #make sure it sests the default types for other fields besides strings    %w(repeated_int32 repeated_int64 repeated_uint32 repeated_uint64).each do |field_name|      m.send(field_name)[3] = 10      assert_equal [0,0,0,10], m.send(field_name)    end    m.repeated_float[3] = 10.1    #wonky mri float handling    assert_equal [0,0,0], m.repeated_float.to_a[0..2]    assert_equal 10.1, m.repeated_float[3].round(1)    m.repeated_double[3] = 10.1    assert_equal [0,0,0,10.1], m.repeated_double    m.repeated_bool[3] = true    assert_equal [false, false, false, true], m.repeated_bool    m.repeated_bytes[3] = "bar".encode!('ASCII-8BIT')    assert_equal ['', '', '', "bar".encode!('ASCII-8BIT')], m.repeated_bytes    m.repeated_msg[3] = TestMessage2.new(:foo => 1)    assert_equal [nil, nil, nil, TestMessage2.new(:foo => 1)], m.repeated_msg    m.repeated_enum[3] = :A    assert_equal [:Default, :Default, :Default, :A], m.repeated_enum    # check_self_modifying_method(m.repeated_string, reference_arr) do |arr|    #   arr[20] = 'spacious'    # end    # TODO: accessor doesn't allow other ruby-like methods    # check_self_modifying_method(m.repeated_string, reference_arr) do |arr|    #   arr[1, 2] = 'fizz'    # end    # check_self_modifying_method(m.repeated_string, reference_arr) do |arr|    #   arr[0..2] = 'buzz'    # end  end  def test_push    m = TestMessage.new    reference_arr = %w(foo bar baz)    m.repeated_string += reference_arr.clone    check_self_modifying_method(m.repeated_string, reference_arr) do |arr|      arr.push('fizz')    end    check_self_modifying_method(m.repeated_string, reference_arr) do |arr|      arr << 'fizz'    end    #TODO: push should support multiple    # check_self_modifying_method(m.repeated_string, reference_arr) do |arr|    #   arr.push('fizz', 'buzz')    # end  end  def test_clear    m = TestMessage.new    reference_arr = %w(foo bar baz)    m.repeated_string += reference_arr.clone    check_self_modifying_method(m.repeated_string, reference_arr) do |arr|      arr.clear    end  end  def test_concat    m = TestMessage.new    reference_arr = %w(foo bar baz)    m.repeated_string += reference_arr.clone    m.repeated_string.concat(['fizz', 'buzz'])    assert_equal %w(foo bar baz fizz buzz), m.repeated_string    #TODO: concat should return the orig array    # check_self_modifying_method(m.repeated_string, reference_arr) do |arr|    #   arr.concat(['fizz', 'buzz'])    # end  end  def test_equal    m = TestMessage.new    reference_arr = %w(foo bar baz)    m.repeated_string += reference_arr.clone    assert_equal reference_arr, m.repeated_string    reference_arr << 'fizz'    assert_not_equal reference_arr, m.repeated_string    m.repeated_string << 'fizz'    assert_equal reference_arr, m.repeated_string  end  def test_hash    # just a sanity check    m = TestMessage.new    reference_arr = %w(foo bar baz)    m.repeated_string += reference_arr.clone    assert m.repeated_string.hash.is_a?(Integer)    hash = m.repeated_string.hash    assert_equal hash, m.repeated_string.hash    m.repeated_string << 'j'    assert_not_equal hash, m.repeated_string.hash  end  def test_plus    m = TestMessage.new    reference_arr = %w(foo bar baz)    m.repeated_string += reference_arr.clone    check_self_modifying_method(m.repeated_string, reference_arr) do |arr|      arr + ['fizz', 'buzz']    end    check_self_modifying_method(m.repeated_string, reference_arr) do |arr|      arr += ['fizz', 'buzz']    end  end  def test_replace    m = TestMessage.new    reference_arr = %w(foo bar baz)    m.repeated_string += reference_arr.clone    check_self_modifying_method(m.repeated_string, reference_arr) do |arr|      arr.replace(['fizz', 'buzz'])    end  end  def test_to_a    m = TestMessage.new    reference_arr = %w(foo bar baz)    m.repeated_string += reference_arr.clone    check_self_modifying_method(m.repeated_string, reference_arr) do |arr|      arr.to_a    end  end  def test_to_ary    m = TestMessage.new    reference_arr = %w(foo bar baz)    m.repeated_string += reference_arr.clone    check_self_modifying_method(m.repeated_string, reference_arr) do |arr|      arr.to_ary    end  end  # emulate Array behavior  ##########################  def test_collect!    m = TestMessage.new    reference_arr = %w(foo bar baz)    m.repeated_string += reference_arr.clone    check_self_modifying_method(m.repeated_string, reference_arr) do |arr|      arr.collect!{|x| x + "!" }    end    check_self_modifying_method(m.repeated_string, reference_arr) do |arr|      arr.collect!.with_index{|x, i| x[0...i] }    end  end  def test_compact!    m = TestMessage.new    m.repeated_msg << TestMessage2.new(:foo => 1)    m.repeated_msg << nil    m.repeated_msg << TestMessage2.new(:foo => 2)    reference_arr = m.repeated_string.to_a    check_self_modifying_method(m.repeated_string, reference_arr) do |arr|      arr.compact!    end  end  def test_delete    m = TestMessage.new    reference_arr = %w(foo bar baz)    m.repeated_string += reference_arr.clone    check_self_modifying_method(m.repeated_string, reference_arr) do |arr|      arr.delete('bar')    end    check_self_modifying_method(m.repeated_string, reference_arr) do |arr|      arr.delete('nope')    end    check_self_modifying_method(m.repeated_string, reference_arr) do |arr|      arr.delete('nope'){'within'}    end  end  def test_delete_at    m = TestMessage.new    reference_arr = %w(foo bar baz)    m.repeated_string += reference_arr.clone    check_self_modifying_method(m.repeated_string, reference_arr) do |arr|      arr.delete_at(2)    end    check_self_modifying_method(m.repeated_string, reference_arr) do |arr|      arr.delete_at(10)    end  end  def test_fill    m = TestMessage.new    reference_arr = %w(foo bar baz)    m.repeated_string += reference_arr.clone    check_self_modifying_method(m.repeated_string, reference_arr) do |arr|      arr.fill("x")    end    check_self_modifying_method(m.repeated_string, reference_arr) do |arr|      arr.fill("z", 2, 2)    end    check_self_modifying_method(m.repeated_string, reference_arr) do |arr|      arr.fill("y", 0..1)    end    check_self_modifying_method(m.repeated_string, reference_arr) do |arr|      arr.fill { |i| (i*i).to_s }    end    check_self_modifying_method(m.repeated_string, reference_arr) do |arr|      arr.fill(-2) { |i| (i*i*i).to_s }    end  end  def test_flatten!    m = TestMessage.new    reference_arr = %w(foo bar baz)    m.repeated_string += reference_arr.clone    check_self_modifying_method(m.repeated_string, reference_arr) do |arr|      arr.flatten!    end    check_self_modifying_method(m.repeated_string, reference_arr) do |arr|      arr.flatten!(1)    end  end  def test_insert    m = TestMessage.new    reference_arr = %w(foo bar baz)    m.repeated_string += reference_arr.clone    check_self_modifying_method(m.repeated_string, reference_arr) do |arr|      arr.insert(2, 'fizz')    end    check_self_modifying_method(m.repeated_string, reference_arr) do |arr|      arr.insert(3, 'fizz', 'buzz', 'bazz')    end  end  def test_inspect    m = TestMessage.new    assert_equal '[]', m.repeated_string.inspect    m.repeated_string << 'foo'    assert_equal m.repeated_string.to_a.inspect, m.repeated_string.inspect    m.repeated_string << 'bar'    assert_equal m.repeated_string.to_a.inspect, m.repeated_string.inspect  end  def test_reverse!    m = TestMessage.new    reference_arr = %w(foo bar baz)    m.repeated_string += reference_arr.clone    check_self_modifying_method(m.repeated_string, reference_arr) do |arr|      arr.reverse!    end  end  def test_rotate!    m = TestMessage.new    reference_arr = %w(foo bar baz)    m.repeated_string += reference_arr.clone    check_self_modifying_method(m.repeated_string, reference_arr) do |arr|      arr.rotate!    end    check_self_modifying_method(m.repeated_string, reference_arr) do |arr|      arr.rotate!(2)    end  end  def test_select!    m = TestMessage.new    reference_arr = %w(foo bar baz)    m.repeated_string += reference_arr.clone    check_self_modifying_method(m.repeated_string, reference_arr) do |arr|      arr.select! { |v| v =~ /[aeiou]/ }    end  end  def test_shift    m = TestMessage.new    reference_arr = %w(foo bar baz)    m.repeated_string += reference_arr.clone    # should return an element    check_self_modifying_method(m.repeated_string, reference_arr) do |arr|      arr.shift    end    # should return an array    check_self_modifying_method(m.repeated_string, reference_arr) do |arr|      arr.shift(2)    end    # should return nil    check_self_modifying_method(m.repeated_string, reference_arr) do |arr|      arr.shift    end  end  def test_shuffle!    m = TestMessage.new    m.repeated_string += %w(foo bar baz)    orig_repeated_string = m.repeated_string.clone    result = m.repeated_string.shuffle!    assert_equal m.repeated_string, result    # NOTE: sometimes it doesn't change the order...    # assert_not_equal m.repeated_string.to_a, orig_repeated_string.to_a  end  def test_slice!    m = TestMessage.new    reference_arr = %w(foo bar baz bar fizz buzz)    m.repeated_string += reference_arr.clone    check_self_modifying_method(m.repeated_string, reference_arr) do |arr|      arr.slice!(2)    end    check_self_modifying_method(m.repeated_string, reference_arr) do |arr|      arr.slice!(1,2)    end    check_self_modifying_method(m.repeated_string, reference_arr) do |arr|      arr.slice!(0..1)    end    check_self_modifying_method(m.repeated_string, reference_arr) do |arr|      arr.slice!(10)    end  end  def test_sort!    m = TestMessage.new    reference_arr = %w(foo bar baz)    m.repeated_string += reference_arr.clone    check_self_modifying_method(m.repeated_string, reference_arr) do |arr|      arr.sort!    end    check_self_modifying_method(m.repeated_string, reference_arr) do |arr|      arr.sort! { |x,y| y <=> x }    end  end  def test_sort_by!    m = TestMessage.new    reference_arr = %w(foo bar baz)    m.repeated_string += reference_arr.clone    check_self_modifying_method(m.repeated_string, reference_arr) do |arr|      arr.sort_by!    end    check_self_modifying_method(m.repeated_string, reference_arr) do |arr|      arr.sort_by!(&:hash)    end  end  def test_uniq!    m = TestMessage.new    reference_arr = %w(foo bar baz)    m.repeated_string += reference_arr.clone    check_self_modifying_method(m.repeated_string, reference_arr) do |arr|      arr.uniq!    end    check_self_modifying_method(m.repeated_string, reference_arr) do |arr|      arr.uniq!{|s| s[0] }    end  end  def test_unshift    m = TestMessage.new    reference_arr = %w(foo bar baz)    m.repeated_string += reference_arr.clone    check_self_modifying_method(m.repeated_string, reference_arr) do |arr|      arr.unshift('1')    end    check_self_modifying_method(m.repeated_string, reference_arr) do |arr|      arr.unshift('a', 'b')    end    check_self_modifying_method(m.repeated_string, reference_arr) do |arr|      arr.unshift('')    end  end  ##### HELPER METHODS  def check_self_modifying_method(repeated_field, ref_array)    expected_result = yield(ref_array)    actual_result = yield(repeated_field)    if expected_result.is_a?(Enumerator)      assert_equal expected_result.to_a, actual_result.to_a    else      assert_equal expected_result, actual_result    end    assert_equal ref_array, repeated_field  end  def repeated_field_names(klass)    klass.descriptor.find_all{|f| f.label == :repeated}.map(&:name)  end  def fill_test_msg(test_msg)    test_msg.repeated_int32  += [-10, -11]    test_msg.repeated_int64  += [-1_000_000, -1_000_001]    test_msg.repeated_uint32 += [10, 11]    test_msg.repeated_uint64 += [1_000_000, 1_000_001]    test_msg.repeated_bool   += [true, false]    test_msg.repeated_float  += [-1.01, -1.02]    test_msg.repeated_double += [-1.0000000000001, -1.0000000000002]    test_msg.repeated_string += %w(foo bar)    test_msg.repeated_bytes  += ["bar".encode!('ASCII-8BIT'), "foo".encode!('ASCII-8BIT')]    test_msg.repeated_msg    << TestMessage2.new(:foo => 1)    test_msg.repeated_msg    << TestMessage2.new(:foo => 2)    test_msg.repeated_enum   << :A    test_msg.repeated_enum   << :B  end  pool = Google::Protobuf::DescriptorPool.new  pool.build do    add_message "TestMessage" do      optional :optional_int32,  :int32,        1      optional :optional_int64,  :int64,        2      optional :optional_uint32, :uint32,       3      optional :optional_uint64, :uint64,       4      optional :optional_bool,   :bool,         5      optional :optional_float,  :float,        6      optional :optional_double, :double,       7      optional :optional_string, :string,       8      optional :optional_bytes,  :bytes,        9      optional :optional_msg,    :message,      10, "TestMessage2"      optional :optional_enum,   :enum,         11, "TestEnum"      repeated :repeated_int32,  :int32,        12      repeated :repeated_int64,  :int64,        13      repeated :repeated_uint32, :uint32,       14      repeated :repeated_uint64, :uint64,       15      repeated :repeated_bool,   :bool,         16      repeated :repeated_float,  :float,        17      repeated :repeated_double, :double,       18      repeated :repeated_string, :string,       19      repeated :repeated_bytes,  :bytes,        20      repeated :repeated_msg,    :message,      21, "TestMessage2"      repeated :repeated_enum,   :enum,         22, "TestEnum"    end    add_message "TestMessage2" do      optional :foo, :int32, 1    end    add_enum "TestEnum" do      value :Default, 0      value :A, 1      value :B, 2      value :C, 3    end  end  TestMessage = pool.lookup("TestMessage").msgclass  TestMessage2 = pool.lookup("TestMessage2").msgclass  TestEnum = pool.lookup("TestEnum").enummoduleend
 |