google-protobuf 3.7.1 → 3.17.3

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.

Potentially problematic release.


This version of google-protobuf might be problematic. Click here for more details.

Files changed (37) hide show
  1. checksums.yaml +4 -4
  2. data/ext/google/protobuf_c/convert.c +349 -0
  3. data/ext/google/protobuf_c/convert.h +72 -0
  4. data/ext/google/protobuf_c/defs.c +1555 -1228
  5. data/ext/google/protobuf_c/defs.h +107 -0
  6. data/ext/google/protobuf_c/extconf.rb +5 -7
  7. data/ext/google/protobuf_c/map.c +312 -470
  8. data/ext/google/protobuf_c/map.h +67 -0
  9. data/ext/google/protobuf_c/message.c +942 -348
  10. data/ext/google/protobuf_c/message.h +101 -0
  11. data/ext/google/protobuf_c/protobuf.c +400 -51
  12. data/ext/google/protobuf_c/protobuf.h +47 -545
  13. data/ext/google/protobuf_c/repeated_field.c +313 -308
  14. data/ext/google/protobuf_c/repeated_field.h +63 -0
  15. data/ext/google/protobuf_c/ruby-upb.c +8858 -0
  16. data/ext/google/protobuf_c/ruby-upb.h +4411 -0
  17. data/ext/google/protobuf_c/third_party/wyhash/wyhash.h +145 -0
  18. data/lib/google/protobuf.rb +70 -0
  19. data/lib/google/protobuf/any_pb.rb +1 -1
  20. data/lib/google/protobuf/api_pb.rb +3 -3
  21. data/lib/google/protobuf/duration_pb.rb +1 -1
  22. data/lib/google/protobuf/empty_pb.rb +1 -1
  23. data/lib/google/protobuf/field_mask_pb.rb +1 -1
  24. data/lib/google/protobuf/source_context_pb.rb +1 -1
  25. data/lib/google/protobuf/struct_pb.rb +4 -4
  26. data/lib/google/protobuf/timestamp_pb.rb +1 -1
  27. data/lib/google/protobuf/type_pb.rb +8 -8
  28. data/lib/google/protobuf/well_known_types.rb +8 -2
  29. data/lib/google/protobuf/wrappers_pb.rb +9 -9
  30. data/tests/basic.rb +320 -70
  31. data/tests/generated_code_test.rb +0 -0
  32. data/tests/stress.rb +0 -0
  33. metadata +27 -15
  34. data/ext/google/protobuf_c/encode_decode.c +0 -1614
  35. data/ext/google/protobuf_c/storage.c +0 -1032
  36. data/ext/google/protobuf_c/upb.c +0 -17480
  37. data/ext/google/protobuf_c/upb.h +0 -10642
@@ -0,0 +1,145 @@
1
+ /* Copyright 2020 王一 Wang Yi <godspeed_china@yeah.net>
2
+ This is free and unencumbered software released into the public domain. http://unlicense.org/
3
+ See github.com/wangyi-fudan/wyhash/ LICENSE
4
+ */
5
+ #ifndef wyhash_final_version
6
+ #define wyhash_final_version
7
+ //defines that change behavior
8
+ #ifndef WYHASH_CONDOM
9
+ #define WYHASH_CONDOM 1 //0: read 8 bytes before and after boundaries, dangerous but fastest. 1: normal valid behavior 2: extra protection against entropy loss (probability=2^-63), aka. "blind multiplication"
10
+ #endif
11
+ #define WYHASH_32BIT_MUM 0 //faster on 32 bit system
12
+ //includes
13
+ #include <stdint.h>
14
+ #include <string.h>
15
+ #if defined(_MSC_VER) && defined(_M_X64)
16
+ #include <intrin.h>
17
+ #pragma intrinsic(_umul128)
18
+ #endif
19
+ #if defined(__GNUC__) || defined(__INTEL_COMPILER) || defined(__clang__)
20
+ #define _likely_(x) __builtin_expect(x,1)
21
+ #define _unlikely_(x) __builtin_expect(x,0)
22
+ #else
23
+ #define _likely_(x) (x)
24
+ #define _unlikely_(x) (x)
25
+ #endif
26
+ //mum function
27
+ static inline uint64_t _wyrot(uint64_t x) { return (x>>32)|(x<<32); }
28
+ static inline void _wymum(uint64_t *A, uint64_t *B){
29
+ #if(WYHASH_32BIT_MUM)
30
+ uint64_t hh=(*A>>32)*(*B>>32), hl=(*A>>32)*(unsigned)*B, lh=(unsigned)*A*(*B>>32), ll=(uint64_t)(unsigned)*A*(unsigned)*B;
31
+ #if(WYHASH_CONDOM>1)
32
+ *A^=_wyrot(hl)^hh; *B^=_wyrot(lh)^ll;
33
+ #else
34
+ *A=_wyrot(hl)^hh; *B=_wyrot(lh)^ll;
35
+ #endif
36
+ #elif defined(__SIZEOF_INT128__)
37
+ __uint128_t r=*A; r*=*B;
38
+ #if(WYHASH_CONDOM>1)
39
+ *A^=(uint64_t)r; *B^=(uint64_t)(r>>64);
40
+ #else
41
+ *A=(uint64_t)r; *B=(uint64_t)(r>>64);
42
+ #endif
43
+ #elif defined(_MSC_VER) && defined(_M_X64)
44
+ #if(WYHASH_CONDOM>1)
45
+ uint64_t a, b;
46
+ a=_umul128(*A,*B,&b);
47
+ *A^=a; *B^=b;
48
+ #else
49
+ *A=_umul128(*A,*B,B);
50
+ #endif
51
+ #else
52
+ uint64_t ha=*A>>32, hb=*B>>32, la=(uint32_t)*A, lb=(uint32_t)*B, hi, lo;
53
+ uint64_t rh=ha*hb, rm0=ha*lb, rm1=hb*la, rl=la*lb, t=rl+(rm0<<32), c=t<rl;
54
+ lo=t+(rm1<<32); c+=lo<t; hi=rh+(rm0>>32)+(rm1>>32)+c;
55
+ #if(WYHASH_CONDOM>1)
56
+ *A^=lo; *B^=hi;
57
+ #else
58
+ *A=lo; *B=hi;
59
+ #endif
60
+ #endif
61
+ }
62
+ static inline uint64_t _wymix(uint64_t A, uint64_t B){ _wymum(&A,&B); return A^B; }
63
+ //read functions
64
+ #ifndef WYHASH_LITTLE_ENDIAN
65
+ #if defined(_WIN32) || defined(__LITTLE_ENDIAN__) || (defined(__BYTE_ORDER__) && __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__)
66
+ #define WYHASH_LITTLE_ENDIAN 1
67
+ #elif defined(__BIG_ENDIAN__) || (defined(__BYTE_ORDER__) && __BYTE_ORDER__ == __ORDER_BIG_ENDIAN__)
68
+ #define WYHASH_LITTLE_ENDIAN 0
69
+ #endif
70
+ #endif
71
+ #if (WYHASH_LITTLE_ENDIAN)
72
+ static inline uint64_t _wyr8(const uint8_t *p) { uint64_t v; memcpy(&v, p, 8); return v;}
73
+ static inline uint64_t _wyr4(const uint8_t *p) { unsigned v; memcpy(&v, p, 4); return v;}
74
+ #elif defined(__GNUC__) || defined(__INTEL_COMPILER) || defined(__clang__)
75
+ static inline uint64_t _wyr8(const uint8_t *p) { uint64_t v; memcpy(&v, p, 8); return __builtin_bswap64(v);}
76
+ static inline uint64_t _wyr4(const uint8_t *p) { unsigned v; memcpy(&v, p, 4); return __builtin_bswap32(v);}
77
+ #elif defined(_MSC_VER)
78
+ static inline uint64_t _wyr8(const uint8_t *p) { uint64_t v; memcpy(&v, p, 8); return _byteswap_uint64(v);}
79
+ static inline uint64_t _wyr4(const uint8_t *p) { unsigned v; memcpy(&v, p, 4); return _byteswap_ulong(v);}
80
+ #endif
81
+ static inline uint64_t _wyr3(const uint8_t *p, unsigned k) { return (((uint64_t)p[0])<<16)|(((uint64_t)p[k>>1])<<8)|p[k-1];}
82
+ //wyhash function
83
+ static inline uint64_t _wyfinish16(const uint8_t *p, uint64_t len, uint64_t seed, const uint64_t *secret, uint64_t i){
84
+ #if(WYHASH_CONDOM>0)
85
+ uint64_t a, b;
86
+ if(_likely_(i<=8)){
87
+ if(_likely_(i>=4)){ a=_wyr4(p); b=_wyr4(p+i-4); }
88
+ else if (_likely_(i)){ a=_wyr3(p,i); b=0; }
89
+ else a=b=0;
90
+ }
91
+ else{ a=_wyr8(p); b=_wyr8(p+i-8); }
92
+ return _wymix(secret[1]^len,_wymix(a^secret[1], b^seed));
93
+ #else
94
+ #define oneshot_shift ((i<8)*((8-i)<<3))
95
+ return _wymix(secret[1]^len,_wymix((_wyr8(p)<<oneshot_shift)^secret[1],(_wyr8(p+i-8)>>oneshot_shift)^seed));
96
+ #endif
97
+ }
98
+
99
+ static inline uint64_t _wyfinish(const uint8_t *p, uint64_t len, uint64_t seed, const uint64_t *secret, uint64_t i){
100
+ if(_likely_(i<=16)) return _wyfinish16(p,len,seed,secret,i);
101
+ return _wyfinish(p+16,len,_wymix(_wyr8(p)^secret[1],_wyr8(p+8)^seed),secret,i-16);
102
+ }
103
+
104
+ static inline uint64_t wyhash(const void *key, uint64_t len, uint64_t seed, const uint64_t *secret){
105
+ const uint8_t *p=(const uint8_t *)key;
106
+ uint64_t i=len; seed^=*secret;
107
+ if(_unlikely_(i>64)){
108
+ uint64_t see1=seed;
109
+ do{
110
+ seed=_wymix(_wyr8(p)^secret[1],_wyr8(p+8)^seed)^_wymix(_wyr8(p+16)^secret[2],_wyr8(p+24)^seed);
111
+ see1=_wymix(_wyr8(p+32)^secret[3],_wyr8(p+40)^see1)^_wymix(_wyr8(p+48)^secret[4],_wyr8(p+56)^see1);
112
+ p+=64; i-=64;
113
+ }while(i>64);
114
+ seed^=see1;
115
+ }
116
+ return _wyfinish(p,len,seed,secret,i);
117
+ }
118
+ //utility functions
119
+ static const uint64_t _wyp[5] = {0xa0761d6478bd642full, 0xe7037ed1a0b428dbull, 0x8ebc6af09c88c6e3ull, 0x589965cc75374cc3ull, 0x1d8e4e27c47d124full};
120
+ static inline uint64_t wyhash64(uint64_t A, uint64_t B){ A^=_wyp[0]; B^=_wyp[1]; _wymum(&A,&B); return _wymix(A^_wyp[0],B^_wyp[1]);}
121
+ static inline uint64_t wyrand(uint64_t *seed){ *seed+=_wyp[0]; return _wymix(*seed,*seed^_wyp[1]);}
122
+ static inline double wy2u01(uint64_t r){ const double _wynorm=1.0/(1ull<<52); return (r>>12)*_wynorm;}
123
+ static inline double wy2gau(uint64_t r){ const double _wynorm=1.0/(1ull<<20); return ((r&0x1fffff)+((r>>21)&0x1fffff)+((r>>42)&0x1fffff))*_wynorm-3.0;}
124
+ static inline uint64_t wy2u0k(uint64_t r, uint64_t k){ _wymum(&r,&k); return k; }
125
+
126
+ static inline void make_secret(uint64_t seed, uint64_t *secret){
127
+ uint8_t c[] = {15, 23, 27, 29, 30, 39, 43, 45, 46, 51, 53, 54, 57, 58, 60, 71, 75, 77, 78, 83, 85, 86, 89, 90, 92, 99, 101, 102, 105, 106, 108, 113, 114, 116, 120, 135, 139, 141, 142, 147, 149, 150, 153, 154, 156, 163, 165, 166, 169, 170, 172, 177, 178, 180, 184, 195, 197, 198, 201, 202, 204, 209, 210, 212, 216, 225, 226, 228, 232, 240 };
128
+ for(size_t i=0;i<5;i++){
129
+ uint8_t ok;
130
+ do{
131
+ ok=1; secret[i]=0;
132
+ for(size_t j=0;j<64;j+=8) secret[i]|=((uint64_t)c[wyrand(&seed)%sizeof(c)])<<j;
133
+ if(secret[i]%2==0){ ok=0; continue; }
134
+ for(size_t j=0;j<i;j++)
135
+ #if defined(__GNUC__) || defined(__INTEL_COMPILER) || defined(__clang__)
136
+ if(__builtin_popcountll(secret[j]^secret[i])!=32){ ok=0; break; }
137
+ #elif defined(_MSC_VER) && defined(_M_X64)
138
+ if(_mm_popcnt_u64(secret[j]^secret[i])!=32){ ok=0; break; }
139
+ #endif
140
+ if(!ok)continue;
141
+ for(uint64_t j=3;j<0x100000000ull;j+=2) if(secret[i]%j==0){ ok=0; break; }
142
+ }while(!ok);
143
+ }
144
+ }
145
+ #endif
@@ -50,6 +50,76 @@ else
50
50
  rescue LoadError
51
51
  require 'google/protobuf_c'
52
52
  end
53
+
54
+ module Google
55
+ module Protobuf
56
+ module Internal
57
+ def self.infer_package(names)
58
+ # Package is longest common prefix ending in '.', if any.
59
+ if not names.empty?
60
+ min, max = names.minmax
61
+ last_common_dot = nil
62
+ min.size.times { |i|
63
+ if min[i] != max[i] then break end
64
+ if min[i] == ?. then last_common_dot = i end
65
+ }
66
+ if last_common_dot
67
+ return min.slice(0, last_common_dot)
68
+ end
69
+ end
70
+
71
+ nil
72
+ end
73
+
74
+ class NestingBuilder
75
+ def initialize(msg_names, enum_names)
76
+ @to_pos = {nil=>nil}
77
+ @msg_children = Hash.new { |hash, key| hash[key] = [] }
78
+ @enum_children = Hash.new { |hash, key| hash[key] = [] }
79
+
80
+ msg_names.each_with_index { |name, idx| @to_pos[name] = idx }
81
+ enum_names.each_with_index { |name, idx| @to_pos[name] = idx }
82
+
83
+ msg_names.each { |name| @msg_children[parent(name)] << name }
84
+ enum_names.each { |name| @enum_children[parent(name)] << name }
85
+ end
86
+
87
+ def build(package)
88
+ return build_msg(package)
89
+ end
90
+
91
+ private
92
+ def build_msg(msg)
93
+ return {
94
+ :pos => @to_pos[msg],
95
+ :msgs => @msg_children[msg].map { |child| build_msg(child) },
96
+ :enums => @enum_children[msg].map { |child| @to_pos[child] },
97
+ }
98
+ end
99
+
100
+ private
101
+ def parent(name)
102
+ idx = name.rindex(?.)
103
+ if idx
104
+ return name.slice(0, idx)
105
+ else
106
+ return nil
107
+ end
108
+ end
109
+ end
110
+
111
+ def self.fixup_descriptor(package, msg_names, enum_names)
112
+ if package.nil?
113
+ package = self.infer_package(msg_names + enum_names)
114
+ end
115
+
116
+ nesting = NestingBuilder.new(msg_names, enum_names).build(package)
117
+
118
+ return package, nesting
119
+ end
120
+ end
121
+ end
122
+ end
53
123
  end
54
124
 
55
125
  require 'google/protobuf/repeated_field'
@@ -14,6 +14,6 @@ end
14
14
 
15
15
  module Google
16
16
  module Protobuf
17
- Any = Google::Protobuf::DescriptorPool.generated_pool.lookup("google.protobuf.Any").msgclass
17
+ Any = ::Google::Protobuf::DescriptorPool.generated_pool.lookup("google.protobuf.Any").msgclass
18
18
  end
19
19
  end
@@ -34,8 +34,8 @@ end
34
34
 
35
35
  module Google
36
36
  module Protobuf
37
- Api = Google::Protobuf::DescriptorPool.generated_pool.lookup("google.protobuf.Api").msgclass
38
- Method = Google::Protobuf::DescriptorPool.generated_pool.lookup("google.protobuf.Method").msgclass
39
- Mixin = Google::Protobuf::DescriptorPool.generated_pool.lookup("google.protobuf.Mixin").msgclass
37
+ Api = ::Google::Protobuf::DescriptorPool.generated_pool.lookup("google.protobuf.Api").msgclass
38
+ Method = ::Google::Protobuf::DescriptorPool.generated_pool.lookup("google.protobuf.Method").msgclass
39
+ Mixin = ::Google::Protobuf::DescriptorPool.generated_pool.lookup("google.protobuf.Mixin").msgclass
40
40
  end
41
41
  end
@@ -14,6 +14,6 @@ end
14
14
 
15
15
  module Google
16
16
  module Protobuf
17
- Duration = Google::Protobuf::DescriptorPool.generated_pool.lookup("google.protobuf.Duration").msgclass
17
+ Duration = ::Google::Protobuf::DescriptorPool.generated_pool.lookup("google.protobuf.Duration").msgclass
18
18
  end
19
19
  end
@@ -12,6 +12,6 @@ end
12
12
 
13
13
  module Google
14
14
  module Protobuf
15
- Empty = Google::Protobuf::DescriptorPool.generated_pool.lookup("google.protobuf.Empty").msgclass
15
+ Empty = ::Google::Protobuf::DescriptorPool.generated_pool.lookup("google.protobuf.Empty").msgclass
16
16
  end
17
17
  end
@@ -13,6 +13,6 @@ end
13
13
 
14
14
  module Google
15
15
  module Protobuf
16
- FieldMask = Google::Protobuf::DescriptorPool.generated_pool.lookup("google.protobuf.FieldMask").msgclass
16
+ FieldMask = ::Google::Protobuf::DescriptorPool.generated_pool.lookup("google.protobuf.FieldMask").msgclass
17
17
  end
18
18
  end
@@ -13,6 +13,6 @@ end
13
13
 
14
14
  module Google
15
15
  module Protobuf
16
- SourceContext = Google::Protobuf::DescriptorPool.generated_pool.lookup("google.protobuf.SourceContext").msgclass
16
+ SourceContext = ::Google::Protobuf::DescriptorPool.generated_pool.lookup("google.protobuf.SourceContext").msgclass
17
17
  end
18
18
  end
@@ -29,9 +29,9 @@ end
29
29
 
30
30
  module Google
31
31
  module Protobuf
32
- Struct = Google::Protobuf::DescriptorPool.generated_pool.lookup("google.protobuf.Struct").msgclass
33
- Value = Google::Protobuf::DescriptorPool.generated_pool.lookup("google.protobuf.Value").msgclass
34
- ListValue = Google::Protobuf::DescriptorPool.generated_pool.lookup("google.protobuf.ListValue").msgclass
35
- NullValue = Google::Protobuf::DescriptorPool.generated_pool.lookup("google.protobuf.NullValue").enummodule
32
+ Struct = ::Google::Protobuf::DescriptorPool.generated_pool.lookup("google.protobuf.Struct").msgclass
33
+ Value = ::Google::Protobuf::DescriptorPool.generated_pool.lookup("google.protobuf.Value").msgclass
34
+ ListValue = ::Google::Protobuf::DescriptorPool.generated_pool.lookup("google.protobuf.ListValue").msgclass
35
+ NullValue = ::Google::Protobuf::DescriptorPool.generated_pool.lookup("google.protobuf.NullValue").enummodule
36
36
  end
37
37
  end
@@ -14,6 +14,6 @@ end
14
14
 
15
15
  module Google
16
16
  module Protobuf
17
- Timestamp = Google::Protobuf::DescriptorPool.generated_pool.lookup("google.protobuf.Timestamp").msgclass
17
+ Timestamp = ::Google::Protobuf::DescriptorPool.generated_pool.lookup("google.protobuf.Timestamp").msgclass
18
18
  end
19
19
  end
@@ -79,13 +79,13 @@ end
79
79
 
80
80
  module Google
81
81
  module Protobuf
82
- Type = Google::Protobuf::DescriptorPool.generated_pool.lookup("google.protobuf.Type").msgclass
83
- Field = Google::Protobuf::DescriptorPool.generated_pool.lookup("google.protobuf.Field").msgclass
84
- Field::Kind = Google::Protobuf::DescriptorPool.generated_pool.lookup("google.protobuf.Field.Kind").enummodule
85
- Field::Cardinality = Google::Protobuf::DescriptorPool.generated_pool.lookup("google.protobuf.Field.Cardinality").enummodule
86
- Enum = Google::Protobuf::DescriptorPool.generated_pool.lookup("google.protobuf.Enum").msgclass
87
- EnumValue = Google::Protobuf::DescriptorPool.generated_pool.lookup("google.protobuf.EnumValue").msgclass
88
- Option = Google::Protobuf::DescriptorPool.generated_pool.lookup("google.protobuf.Option").msgclass
89
- Syntax = Google::Protobuf::DescriptorPool.generated_pool.lookup("google.protobuf.Syntax").enummodule
82
+ Type = ::Google::Protobuf::DescriptorPool.generated_pool.lookup("google.protobuf.Type").msgclass
83
+ Field = ::Google::Protobuf::DescriptorPool.generated_pool.lookup("google.protobuf.Field").msgclass
84
+ Field::Kind = ::Google::Protobuf::DescriptorPool.generated_pool.lookup("google.protobuf.Field.Kind").enummodule
85
+ Field::Cardinality = ::Google::Protobuf::DescriptorPool.generated_pool.lookup("google.protobuf.Field.Cardinality").enummodule
86
+ Enum = ::Google::Protobuf::DescriptorPool.generated_pool.lookup("google.protobuf.Enum").msgclass
87
+ EnumValue = ::Google::Protobuf::DescriptorPool.generated_pool.lookup("google.protobuf.EnumValue").msgclass
88
+ Option = ::Google::Protobuf::DescriptorPool.generated_pool.lookup("google.protobuf.Option").msgclass
89
+ Syntax = ::Google::Protobuf::DescriptorPool.generated_pool.lookup("google.protobuf.Syntax").enummodule
90
90
  end
91
91
  end
@@ -72,8 +72,14 @@ module Google
72
72
  end
73
73
 
74
74
  Timestamp.class_eval do
75
- def to_time
76
- Time.at(self.to_f)
75
+ if RUBY_VERSION < "2.5"
76
+ def to_time
77
+ Time.at(self.to_f)
78
+ end
79
+ else
80
+ def to_time
81
+ Time.at(seconds, nanos, :nanosecond)
82
+ end
77
83
  end
78
84
 
79
85
  def from_time(time)
@@ -37,14 +37,14 @@ end
37
37
 
38
38
  module Google
39
39
  module Protobuf
40
- DoubleValue = Google::Protobuf::DescriptorPool.generated_pool.lookup("google.protobuf.DoubleValue").msgclass
41
- FloatValue = Google::Protobuf::DescriptorPool.generated_pool.lookup("google.protobuf.FloatValue").msgclass
42
- Int64Value = Google::Protobuf::DescriptorPool.generated_pool.lookup("google.protobuf.Int64Value").msgclass
43
- UInt64Value = Google::Protobuf::DescriptorPool.generated_pool.lookup("google.protobuf.UInt64Value").msgclass
44
- Int32Value = Google::Protobuf::DescriptorPool.generated_pool.lookup("google.protobuf.Int32Value").msgclass
45
- UInt32Value = Google::Protobuf::DescriptorPool.generated_pool.lookup("google.protobuf.UInt32Value").msgclass
46
- BoolValue = Google::Protobuf::DescriptorPool.generated_pool.lookup("google.protobuf.BoolValue").msgclass
47
- StringValue = Google::Protobuf::DescriptorPool.generated_pool.lookup("google.protobuf.StringValue").msgclass
48
- BytesValue = Google::Protobuf::DescriptorPool.generated_pool.lookup("google.protobuf.BytesValue").msgclass
40
+ DoubleValue = ::Google::Protobuf::DescriptorPool.generated_pool.lookup("google.protobuf.DoubleValue").msgclass
41
+ FloatValue = ::Google::Protobuf::DescriptorPool.generated_pool.lookup("google.protobuf.FloatValue").msgclass
42
+ Int64Value = ::Google::Protobuf::DescriptorPool.generated_pool.lookup("google.protobuf.Int64Value").msgclass
43
+ UInt64Value = ::Google::Protobuf::DescriptorPool.generated_pool.lookup("google.protobuf.UInt64Value").msgclass
44
+ Int32Value = ::Google::Protobuf::DescriptorPool.generated_pool.lookup("google.protobuf.Int32Value").msgclass
45
+ UInt32Value = ::Google::Protobuf::DescriptorPool.generated_pool.lookup("google.protobuf.UInt32Value").msgclass
46
+ BoolValue = ::Google::Protobuf::DescriptorPool.generated_pool.lookup("google.protobuf.BoolValue").msgclass
47
+ StringValue = ::Google::Protobuf::DescriptorPool.generated_pool.lookup("google.protobuf.StringValue").msgclass
48
+ BytesValue = ::Google::Protobuf::DescriptorPool.generated_pool.lookup("google.protobuf.BytesValue").msgclass
49
49
  end
50
50
  end
data/tests/basic.rb CHANGED
@@ -17,7 +17,6 @@ module BasicTest
17
17
  add_message "BadFieldNames" do
18
18
  optional :dup, :int32, 1
19
19
  optional :class, :int32, 2
20
- optional :"a.b", :int32, 3
21
20
  end
22
21
  end
23
22
 
@@ -32,12 +31,51 @@ module BasicTest
32
31
  end
33
32
  include CommonTests
34
33
 
34
+ def test_issue_8311_crash
35
+ Google::Protobuf::DescriptorPool.generated_pool.build do
36
+ add_file("inner.proto", :syntax => :proto3) do
37
+ add_message "Inner" do
38
+ # Removing either of these fixes the segfault.
39
+ optional :foo, :string, 1
40
+ optional :bar, :string, 2
41
+ end
42
+ end
43
+ end
44
+
45
+ Google::Protobuf::DescriptorPool.generated_pool.build do
46
+ add_file("outer.proto", :syntax => :proto3) do
47
+ add_message "Outer" do
48
+ repeated :inners, :message, 1, "Inner"
49
+ end
50
+ end
51
+ end
52
+
53
+ outer = ::Google::Protobuf::DescriptorPool.generated_pool.lookup("Outer").msgclass
54
+
55
+ outer.new(
56
+ inners: []
57
+ )['inners'].to_s
58
+
59
+ assert_raise Google::Protobuf::TypeError do
60
+ outer.new(
61
+ inners: [nil]
62
+ ).to_s
63
+ end
64
+ end
65
+
66
+ def test_issue_8559_crash
67
+ msg = TestMessage.new
68
+ msg.repeated_int32 = ::Google::Protobuf::RepeatedField.new(:int32, [1, 2, 3])
69
+ GC.start(full_mark: true, immediate_sweep: true)
70
+ TestMessage.encode(msg)
71
+ end
72
+
35
73
  def test_has_field
36
- m = TestMessage.new
37
- assert !m.has_optional_msg?
38
- m.optional_msg = TestMessage2.new
39
- assert m.has_optional_msg?
40
- assert TestMessage.descriptor.lookup('optional_msg').has?(m)
74
+ m = TestSingularFields.new
75
+ assert !m.has_singular_msg?
76
+ m.singular_msg = TestMessage2.new
77
+ assert m.has_singular_msg?
78
+ assert TestSingularFields.descriptor.lookup('singular_msg').has?(m)
41
79
 
42
80
  m = OneofMessage.new
43
81
  assert !m.has_my_oneof?
@@ -46,32 +84,31 @@ module BasicTest
46
84
  assert_raise NoMethodError do
47
85
  m.has_a?
48
86
  end
49
- assert_raise ArgumentError do
50
- OneofMessage.descriptor.lookup('a').has?(m)
51
- end
87
+ assert_true OneofMessage.descriptor.lookup('a').has?(m)
52
88
 
53
- m = TestMessage.new
89
+ m = TestSingularFields.new
54
90
  assert_raise NoMethodError do
55
- m.has_optional_int32?
91
+ m.has_singular_int32?
56
92
  end
57
93
  assert_raise ArgumentError do
58
- TestMessage.descriptor.lookup('optional_int32').has?(m)
94
+ TestSingularFields.descriptor.lookup('singular_int32').has?(m)
59
95
  end
60
96
 
61
97
  assert_raise NoMethodError do
62
- m.has_optional_string?
98
+ m.has_singular_string?
63
99
  end
64
100
  assert_raise ArgumentError do
65
- TestMessage.descriptor.lookup('optional_string').has?(m)
101
+ TestSingularFields.descriptor.lookup('singular_string').has?(m)
66
102
  end
67
103
 
68
104
  assert_raise NoMethodError do
69
- m.has_optional_bool?
105
+ m.has_singular_bool?
70
106
  end
71
107
  assert_raise ArgumentError do
72
- TestMessage.descriptor.lookup('optional_bool').has?(m)
108
+ TestSingularFields.descriptor.lookup('singular_bool').has?(m)
73
109
  end
74
110
 
111
+ m = TestMessage.new
75
112
  assert_raise NoMethodError do
76
113
  m.has_repeated_msg?
77
114
  end
@@ -80,40 +117,59 @@ module BasicTest
80
117
  end
81
118
  end
82
119
 
120
+ def test_no_presence
121
+ m = TestSingularFields.new
122
+
123
+ # Explicitly setting to zero does not cause anything to be serialized.
124
+ m.singular_int32 = 0
125
+ assert_equal "", TestSingularFields.encode(m)
126
+
127
+ # Explicitly setting to a non-zero value *does* cause serialization.
128
+ m.singular_int32 = 1
129
+ assert_not_equal "", TestSingularFields.encode(m)
130
+
131
+ m.singular_int32 = 0
132
+ assert_equal "", TestSingularFields.encode(m)
133
+ end
134
+
83
135
  def test_set_clear_defaults
84
- m = TestMessage.new
136
+ m = TestSingularFields.new
137
+
138
+ m.singular_int32 = -42
139
+ assert_equal -42, m.singular_int32
140
+ m.clear_singular_int32
141
+ assert_equal 0, m.singular_int32
142
+
143
+ m.singular_int32 = 50
144
+ assert_equal 50, m.singular_int32
145
+ TestSingularFields.descriptor.lookup('singular_int32').clear(m)
146
+ assert_equal 0, m.singular_int32
147
+
148
+ m.singular_string = "foo bar"
149
+ assert_equal "foo bar", m.singular_string
150
+ m.clear_singular_string
151
+ assert_equal "", m.singular_string
152
+
153
+ m.singular_string = "foo"
154
+ assert_equal "foo", m.singular_string
155
+ TestSingularFields.descriptor.lookup('singular_string').clear(m)
156
+ assert_equal "", m.singular_string
157
+
158
+ m.singular_msg = TestMessage2.new(:foo => 42)
159
+ assert_equal TestMessage2.new(:foo => 42), m.singular_msg
160
+ assert m.has_singular_msg?
161
+ m.clear_singular_msg
162
+ assert_equal nil, m.singular_msg
163
+ assert !m.has_singular_msg?
164
+
165
+ m.singular_msg = TestMessage2.new(:foo => 42)
166
+ assert_equal TestMessage2.new(:foo => 42), m.singular_msg
167
+ TestSingularFields.descriptor.lookup('singular_msg').clear(m)
168
+ assert_equal nil, m.singular_msg
169
+ end
85
170
 
86
- m.optional_int32 = -42
87
- assert_equal -42, m.optional_int32
88
- m.clear_optional_int32
89
- assert_equal 0, m.optional_int32
90
-
91
- m.optional_int32 = 50
92
- assert_equal 50, m.optional_int32
93
- TestMessage.descriptor.lookup('optional_int32').clear(m)
94
- assert_equal 0, m.optional_int32
95
-
96
- m.optional_string = "foo bar"
97
- assert_equal "foo bar", m.optional_string
98
- m.clear_optional_string
99
- assert_equal "", m.optional_string
100
-
101
- m.optional_string = "foo"
102
- assert_equal "foo", m.optional_string
103
- TestMessage.descriptor.lookup('optional_string').clear(m)
104
- assert_equal "", m.optional_string
105
-
106
- m.optional_msg = TestMessage2.new(:foo => 42)
107
- assert_equal TestMessage2.new(:foo => 42), m.optional_msg
108
- assert m.has_optional_msg?
109
- m.clear_optional_msg
110
- assert_equal nil, m.optional_msg
111
- assert !m.has_optional_msg?
112
-
113
- m.optional_msg = TestMessage2.new(:foo => 42)
114
- assert_equal TestMessage2.new(:foo => 42), m.optional_msg
115
- TestMessage.descriptor.lookup('optional_msg').clear(m)
116
- assert_equal nil, m.optional_msg
171
+ def test_clear_repeated_fields
172
+ m = TestMessage.new
117
173
 
118
174
  m.repeated_int32.push(1)
119
175
  assert_equal [1], m.repeated_int32
@@ -129,6 +185,7 @@ module BasicTest
129
185
  m.a = "foo"
130
186
  assert_equal "foo", m.a
131
187
  assert m.has_my_oneof?
188
+ assert_equal :a, m.my_oneof
132
189
  m.clear_a
133
190
  assert !m.has_my_oneof?
134
191
 
@@ -144,7 +201,6 @@ module BasicTest
144
201
  assert !m.has_my_oneof?
145
202
  end
146
203
 
147
-
148
204
  def test_initialization_map_errors
149
205
  e = assert_raise ArgumentError do
150
206
  TestMessage.new(:hello => "world")
@@ -170,10 +226,12 @@ module BasicTest
170
226
  m = MapMessage.new(
171
227
  :map_string_int32 => {"a" => 1, "b" => 2},
172
228
  :map_string_msg => {"a" => TestMessage2.new(:foo => 1),
173
- "b" => TestMessage2.new(:foo => 2)})
229
+ "b" => TestMessage2.new(:foo => 2)},
230
+ :map_string_enum => {"a" => :A, "b" => :B})
174
231
  assert m.map_string_int32.keys.sort == ["a", "b"]
175
232
  assert m.map_string_int32["a"] == 1
176
233
  assert m.map_string_msg["b"].foo == 2
234
+ assert m.map_string_enum["a"] == :A
177
235
 
178
236
  m.map_string_int32["c"] = 3
179
237
  assert m.map_string_int32["c"] == 3
@@ -197,18 +255,37 @@ module BasicTest
197
255
  m.map_string_int32 = {}
198
256
  end
199
257
 
200
- assert_raise TypeError do
258
+ assert_raise Google::Protobuf::TypeError do
201
259
  m = MapMessage.new(:map_string_int32 => { 1 => "I am not a number" })
202
260
  end
203
261
  end
204
262
 
263
+ def test_map_field_with_symbol
264
+ m = MapMessage.new
265
+ assert m.map_string_int32 == {}
266
+ assert m.map_string_msg == {}
267
+
268
+ m = MapMessage.new(
269
+ :map_string_int32 => {a: 1, "b" => 2},
270
+ :map_string_msg => {a: TestMessage2.new(:foo => 1),
271
+ b: TestMessage2.new(:foo => 10)})
272
+ assert_equal 1, m.map_string_int32[:a]
273
+ assert_equal 2, m.map_string_int32[:b]
274
+ assert_equal 10, m.map_string_msg[:b].foo
275
+ end
276
+
205
277
  def test_map_inspect
206
278
  m = MapMessage.new(
207
279
  :map_string_int32 => {"a" => 1, "b" => 2},
208
280
  :map_string_msg => {"a" => TestMessage2.new(:foo => 1),
209
- "b" => TestMessage2.new(:foo => 2)})
210
- expected = "<BasicTest::MapMessage: map_string_int32: {\"b\"=>2, \"a\"=>1}, map_string_msg: {\"b\"=><BasicTest::TestMessage2: foo: 2>, \"a\"=><BasicTest::TestMessage2: foo: 1>}>"
211
- assert_equal expected, m.inspect
281
+ "b" => TestMessage2.new(:foo => 2)},
282
+ :map_string_enum => {"a" => :A, "b" => :B})
283
+
284
+ # JRuby doesn't keep consistent ordering so check for either version
285
+ expected_a = "<BasicTest::MapMessage: map_string_int32: {\"b\"=>2, \"a\"=>1}, map_string_msg: {\"b\"=><BasicTest::TestMessage2: foo: 2>, \"a\"=><BasicTest::TestMessage2: foo: 1>}, map_string_enum: {\"b\"=>:B, \"a\"=>:A}>"
286
+ expected_b = "<BasicTest::MapMessage: map_string_int32: {\"a\"=>1, \"b\"=>2}, map_string_msg: {\"a\"=><BasicTest::TestMessage2: foo: 1>, \"b\"=><BasicTest::TestMessage2: foo: 2>}, map_string_enum: {\"a\"=>:A, \"b\"=>:B}>"
287
+ inspect_result = m.inspect
288
+ assert expected_a == inspect_result || expected_b == inspect_result, "Incorrect inspect result: #{inspect_result}"
212
289
  end
213
290
 
214
291
  def test_map_corruption
@@ -218,6 +295,128 @@ module BasicTest
218
295
  m.map_string_int32['aaa'] = 3
219
296
  end
220
297
 
298
+ def test_map_wrappers
299
+ run_asserts = ->(m) {
300
+ assert_equal 2.0, m.map_double[0].value
301
+ assert_equal 4.0, m.map_float[0].value
302
+ assert_equal 3, m.map_int32[0].value
303
+ assert_equal 4, m.map_int64[0].value
304
+ assert_equal 5, m.map_uint32[0].value
305
+ assert_equal 6, m.map_uint64[0].value
306
+ assert_equal true, m.map_bool[0].value
307
+ assert_equal 'str', m.map_string[0].value
308
+ assert_equal 'fun', m.map_bytes[0].value
309
+ }
310
+
311
+ m = proto_module::Wrapper.new(
312
+ map_double: {0 => Google::Protobuf::DoubleValue.new(value: 2.0)},
313
+ map_float: {0 => Google::Protobuf::FloatValue.new(value: 4.0)},
314
+ map_int32: {0 => Google::Protobuf::Int32Value.new(value: 3)},
315
+ map_int64: {0 => Google::Protobuf::Int64Value.new(value: 4)},
316
+ map_uint32: {0 => Google::Protobuf::UInt32Value.new(value: 5)},
317
+ map_uint64: {0 => Google::Protobuf::UInt64Value.new(value: 6)},
318
+ map_bool: {0 => Google::Protobuf::BoolValue.new(value: true)},
319
+ map_string: {0 => Google::Protobuf::StringValue.new(value: 'str')},
320
+ map_bytes: {0 => Google::Protobuf::BytesValue.new(value: 'fun')},
321
+ )
322
+
323
+ run_asserts.call(m)
324
+ serialized = proto_module::Wrapper::encode(m)
325
+ m2 = proto_module::Wrapper::decode(serialized)
326
+ run_asserts.call(m2)
327
+
328
+ # Test the case where we are serializing directly from the parsed form
329
+ # (before anything lazy is materialized).
330
+ m3 = proto_module::Wrapper::decode(serialized)
331
+ serialized2 = proto_module::Wrapper::encode(m3)
332
+ m4 = proto_module::Wrapper::decode(serialized2)
333
+ run_asserts.call(m4)
334
+
335
+ # Test that the lazy form compares equal to the expanded form.
336
+ m5 = proto_module::Wrapper::decode(serialized2)
337
+ assert_equal m5, m
338
+ end
339
+
340
+ def test_map_wrappers_with_default_values
341
+ run_asserts = ->(m) {
342
+ assert_equal 0.0, m.map_double[0].value
343
+ assert_equal 0.0, m.map_float[0].value
344
+ assert_equal 0, m.map_int32[0].value
345
+ assert_equal 0, m.map_int64[0].value
346
+ assert_equal 0, m.map_uint32[0].value
347
+ assert_equal 0, m.map_uint64[0].value
348
+ assert_equal false, m.map_bool[0].value
349
+ assert_equal '', m.map_string[0].value
350
+ assert_equal '', m.map_bytes[0].value
351
+ }
352
+
353
+ m = proto_module::Wrapper.new(
354
+ map_double: {0 => Google::Protobuf::DoubleValue.new(value: 0.0)},
355
+ map_float: {0 => Google::Protobuf::FloatValue.new(value: 0.0)},
356
+ map_int32: {0 => Google::Protobuf::Int32Value.new(value: 0)},
357
+ map_int64: {0 => Google::Protobuf::Int64Value.new(value: 0)},
358
+ map_uint32: {0 => Google::Protobuf::UInt32Value.new(value: 0)},
359
+ map_uint64: {0 => Google::Protobuf::UInt64Value.new(value: 0)},
360
+ map_bool: {0 => Google::Protobuf::BoolValue.new(value: false)},
361
+ map_string: {0 => Google::Protobuf::StringValue.new(value: '')},
362
+ map_bytes: {0 => Google::Protobuf::BytesValue.new(value: '')},
363
+ )
364
+
365
+ run_asserts.call(m)
366
+ serialized = proto_module::Wrapper::encode(m)
367
+ m2 = proto_module::Wrapper::decode(serialized)
368
+ run_asserts.call(m2)
369
+
370
+ # Test the case where we are serializing directly from the parsed form
371
+ # (before anything lazy is materialized).
372
+ m3 = proto_module::Wrapper::decode(serialized)
373
+ serialized2 = proto_module::Wrapper::encode(m3)
374
+ m4 = proto_module::Wrapper::decode(serialized2)
375
+ run_asserts.call(m4)
376
+
377
+ # Test that the lazy form compares equal to the expanded form.
378
+ m5 = proto_module::Wrapper::decode(serialized2)
379
+ assert_equal m5, m
380
+ end
381
+
382
+ def test_map_wrappers_with_no_value
383
+ run_asserts = ->(m) {
384
+ assert_equal 0.0, m.map_double[0].value
385
+ assert_equal 0.0, m.map_float[0].value
386
+ assert_equal 0, m.map_int32[0].value
387
+ assert_equal 0, m.map_int64[0].value
388
+ assert_equal 0, m.map_uint32[0].value
389
+ assert_equal 0, m.map_uint64[0].value
390
+ assert_equal false, m.map_bool[0].value
391
+ assert_equal '', m.map_string[0].value
392
+ assert_equal '', m.map_bytes[0].value
393
+ }
394
+
395
+ m = proto_module::Wrapper.new(
396
+ map_double: {0 => Google::Protobuf::DoubleValue.new()},
397
+ map_float: {0 => Google::Protobuf::FloatValue.new()},
398
+ map_int32: {0 => Google::Protobuf::Int32Value.new()},
399
+ map_int64: {0 => Google::Protobuf::Int64Value.new()},
400
+ map_uint32: {0 => Google::Protobuf::UInt32Value.new()},
401
+ map_uint64: {0 => Google::Protobuf::UInt64Value.new()},
402
+ map_bool: {0 => Google::Protobuf::BoolValue.new()},
403
+ map_string: {0 => Google::Protobuf::StringValue.new()},
404
+ map_bytes: {0 => Google::Protobuf::BytesValue.new()},
405
+ )
406
+ run_asserts.call(m)
407
+
408
+ serialized = proto_module::Wrapper::encode(m)
409
+ m2 = proto_module::Wrapper::decode(serialized)
410
+ run_asserts.call(m2)
411
+
412
+ # Test the case where we are serializing directly from the parsed form
413
+ # (before anything lazy is materialized).
414
+ m3 = proto_module::Wrapper::decode(serialized)
415
+ serialized2 = proto_module::Wrapper::encode(m3)
416
+ m4 = proto_module::Wrapper::decode(serialized2)
417
+ run_asserts.call(m4)
418
+ end
419
+
221
420
  def test_concurrent_decoding
222
421
  o = Outer.new
223
422
  o.items[0] = Inner.new
@@ -237,7 +436,8 @@ module BasicTest
237
436
  m = MapMessage.new(
238
437
  :map_string_int32 => {"a" => 1, "b" => 2},
239
438
  :map_string_msg => {"a" => TestMessage2.new(:foo => 1),
240
- "b" => TestMessage2.new(:foo => 2)})
439
+ "b" => TestMessage2.new(:foo => 2)},
440
+ :map_string_enum => {"a" => :A, "b" => :B})
241
441
  m2 = MapMessage.decode(MapMessage.encode(m))
242
442
  assert m == m2
243
443
 
@@ -267,6 +467,14 @@ module BasicTest
267
467
  assert_match(/No such field: not_in_message/, e.message)
268
468
  end
269
469
 
470
+ #def test_json_quoted_string
471
+ # m = TestMessage.decode_json(%q(
472
+ # "optionalInt64": "1",,
473
+ # }))
474
+ # puts(m)
475
+ # assert_equal 1, m.optional_int32
476
+ #end
477
+
270
478
  def test_to_h
271
479
  m = TestMessage.new(:optional_bool => true, :optional_double => -10.100001, :optional_string => 'foo', :repeated_string => ['bar1', 'bar2'], :repeated_msg => [TestMessage2.new(:foo => 100)])
272
480
  expected_result = {
@@ -278,6 +486,7 @@ module BasicTest
278
486
  :optional_int32=>0,
279
487
  :optional_int64=>0,
280
488
  :optional_msg=>nil,
489
+ :optional_msg2=>nil,
281
490
  :optional_string=>"foo",
282
491
  :optional_uint32=>0,
283
492
  :optional_uint64=>0,
@@ -298,10 +507,12 @@ module BasicTest
298
507
  m = MapMessage.new(
299
508
  :map_string_int32 => {"a" => 1, "b" => 2},
300
509
  :map_string_msg => {"a" => TestMessage2.new(:foo => 1),
301
- "b" => TestMessage2.new(:foo => 2)})
510
+ "b" => TestMessage2.new(:foo => 2)},
511
+ :map_string_enum => {"a" => :A, "b" => :B})
302
512
  expected_result = {
303
513
  :map_string_int32 => {"a" => 1, "b" => 2},
304
- :map_string_msg => {"a" => {:foo => 1}, "b" => {:foo => 2}}
514
+ :map_string_msg => {"a" => {:foo => 1}, "b" => {:foo => 2}},
515
+ :map_string_enum => {"a" => :A, "b" => :B}
305
516
  }
306
517
  assert_equal expected_result, m.to_h
307
518
  end
@@ -311,26 +522,50 @@ module BasicTest
311
522
  # TODO: Fix JSON in JRuby version.
312
523
  return if RUBY_PLATFORM == "java"
313
524
  m = MapMessage.new(:map_string_int32 => {"a" => 1})
314
- expected = {mapStringInt32: {a: 1}, mapStringMsg: {}}
315
- expected_preserve = {map_string_int32: {a: 1}, map_string_msg: {}}
316
- assert JSON.parse(MapMessage.encode_json(m), :symbolize_names => true) == expected
525
+ expected = {mapStringInt32: {a: 1}, mapStringMsg: {}, mapStringEnum: {}}
526
+ expected_preserve = {map_string_int32: {a: 1}, map_string_msg: {}, map_string_enum: {}}
527
+ assert_equal JSON.parse(MapMessage.encode_json(m, :emit_defaults=>true), :symbolize_names => true), expected
317
528
 
318
- json = MapMessage.encode_json(m, :preserve_proto_fieldnames => true)
319
- assert JSON.parse(json, :symbolize_names => true) == expected_preserve
529
+ json = MapMessage.encode_json(m, :preserve_proto_fieldnames => true, :emit_defaults=>true)
530
+ assert_equal JSON.parse(json, :symbolize_names => true), expected_preserve
320
531
 
321
532
  m2 = MapMessage.decode_json(MapMessage.encode_json(m))
322
- assert m == m2
533
+ assert_equal m, m2
323
534
  end
324
535
 
325
536
  def test_json_maps_emit_defaults_submsg
326
537
  # TODO: Fix JSON in JRuby version.
327
538
  return if RUBY_PLATFORM == "java"
328
- m = MapMessage.new(:map_string_msg => {"a" => TestMessage2.new})
329
- expected = {mapStringInt32: {}, mapStringMsg: {a: {foo: 0}}}
539
+ m = MapMessage.new(:map_string_msg => {"a" => TestMessage2.new(foo: 0)})
540
+ expected = {mapStringInt32: {}, mapStringMsg: {a: {foo: 0}}, mapStringEnum: {}}
330
541
 
331
542
  actual = MapMessage.encode_json(m, :emit_defaults => true)
332
543
 
333
- assert JSON.parse(actual, :symbolize_names => true) == expected
544
+ assert_equal JSON.parse(actual, :symbolize_names => true), expected
545
+ end
546
+
547
+ def test_json_emit_defaults_submsg
548
+ # TODO: Fix JSON in JRuby version.
549
+ return if RUBY_PLATFORM == "java"
550
+ m = TestSingularFields.new(singular_msg: proto_module::TestMessage2.new)
551
+
552
+ expected = {
553
+ singularInt32: 0,
554
+ singularInt64: "0",
555
+ singularUint32: 0,
556
+ singularUint64: "0",
557
+ singularBool: false,
558
+ singularFloat: 0,
559
+ singularDouble: 0,
560
+ singularString: "",
561
+ singularBytes: "",
562
+ singularMsg: {},
563
+ singularEnum: "Default",
564
+ }
565
+
566
+ actual = proto_module::TestMessage.encode_json(m, :emit_defaults => true)
567
+
568
+ assert_equal expected, JSON.parse(actual, :symbolize_names => true)
334
569
  end
335
570
 
336
571
  def test_respond_to
@@ -351,11 +586,26 @@ module BasicTest
351
586
  assert nil != file_descriptor
352
587
  assert_equal "tests/basic_test.proto", file_descriptor.name
353
588
  assert_equal :proto3, file_descriptor.syntax
589
+ end
354
590
 
355
- file_descriptor = BadFieldNames.descriptor.file_descriptor
356
- assert nil != file_descriptor
357
- assert_equal nil, file_descriptor.name
358
- assert_equal :proto3, file_descriptor.syntax
591
+ # Ruby 2.5 changed to raise FrozenError instead of RuntimeError
592
+ FrozenErrorType = Gem::Version.new(RUBY_VERSION) < Gem::Version.new('2.5') ? RuntimeError : FrozenError
593
+
594
+ def test_map_freeze
595
+ m = proto_module::MapMessage.new
596
+ m.map_string_int32['a'] = 5
597
+ m.map_string_msg['b'] = proto_module::TestMessage2.new
598
+
599
+ m.map_string_int32.freeze
600
+ m.map_string_msg.freeze
601
+
602
+ assert m.map_string_int32.frozen?
603
+ assert m.map_string_msg.frozen?
604
+
605
+ assert_raise(FrozenErrorType) { m.map_string_int32['foo'] = 1 }
606
+ assert_raise(FrozenErrorType) { m.map_string_msg['bar'] = proto_module::TestMessage2.new }
607
+ assert_raise(FrozenErrorType) { m.map_string_int32.delete('a') }
608
+ assert_raise(FrozenErrorType) { m.map_string_int32.clear }
359
609
  end
360
610
  end
361
611
  end