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.
- checksums.yaml +4 -4
- data/ext/google/protobuf_c/convert.c +349 -0
- data/ext/google/protobuf_c/convert.h +72 -0
- data/ext/google/protobuf_c/defs.c +1555 -1228
- data/ext/google/protobuf_c/defs.h +107 -0
- data/ext/google/protobuf_c/extconf.rb +5 -7
- data/ext/google/protobuf_c/map.c +312 -470
- data/ext/google/protobuf_c/map.h +67 -0
- data/ext/google/protobuf_c/message.c +942 -348
- data/ext/google/protobuf_c/message.h +101 -0
- data/ext/google/protobuf_c/protobuf.c +400 -51
- data/ext/google/protobuf_c/protobuf.h +47 -545
- data/ext/google/protobuf_c/repeated_field.c +313 -308
- data/ext/google/protobuf_c/repeated_field.h +63 -0
- data/ext/google/protobuf_c/ruby-upb.c +8858 -0
- data/ext/google/protobuf_c/ruby-upb.h +4411 -0
- data/ext/google/protobuf_c/third_party/wyhash/wyhash.h +145 -0
- data/lib/google/protobuf.rb +70 -0
- data/lib/google/protobuf/any_pb.rb +1 -1
- data/lib/google/protobuf/api_pb.rb +3 -3
- data/lib/google/protobuf/duration_pb.rb +1 -1
- data/lib/google/protobuf/empty_pb.rb +1 -1
- data/lib/google/protobuf/field_mask_pb.rb +1 -1
- data/lib/google/protobuf/source_context_pb.rb +1 -1
- data/lib/google/protobuf/struct_pb.rb +4 -4
- data/lib/google/protobuf/timestamp_pb.rb +1 -1
- data/lib/google/protobuf/type_pb.rb +8 -8
- data/lib/google/protobuf/well_known_types.rb +8 -2
- data/lib/google/protobuf/wrappers_pb.rb +9 -9
- data/tests/basic.rb +320 -70
- data/tests/generated_code_test.rb +0 -0
- data/tests/stress.rb +0 -0
- metadata +27 -15
- data/ext/google/protobuf_c/encode_decode.c +0 -1614
- data/ext/google/protobuf_c/storage.c +0 -1032
- data/ext/google/protobuf_c/upb.c +0 -17480
- 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
|
data/lib/google/protobuf.rb
CHANGED
@@ -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'
|
@@ -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
|
@@ -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
|
-
|
76
|
-
|
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 =
|
37
|
-
assert !m.
|
38
|
-
m.
|
39
|
-
assert m.
|
40
|
-
assert
|
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
|
-
|
50
|
-
OneofMessage.descriptor.lookup('a').has?(m)
|
51
|
-
end
|
87
|
+
assert_true OneofMessage.descriptor.lookup('a').has?(m)
|
52
88
|
|
53
|
-
m =
|
89
|
+
m = TestSingularFields.new
|
54
90
|
assert_raise NoMethodError do
|
55
|
-
m.
|
91
|
+
m.has_singular_int32?
|
56
92
|
end
|
57
93
|
assert_raise ArgumentError do
|
58
|
-
|
94
|
+
TestSingularFields.descriptor.lookup('singular_int32').has?(m)
|
59
95
|
end
|
60
96
|
|
61
97
|
assert_raise NoMethodError do
|
62
|
-
m.
|
98
|
+
m.has_singular_string?
|
63
99
|
end
|
64
100
|
assert_raise ArgumentError do
|
65
|
-
|
101
|
+
TestSingularFields.descriptor.lookup('singular_string').has?(m)
|
66
102
|
end
|
67
103
|
|
68
104
|
assert_raise NoMethodError do
|
69
|
-
m.
|
105
|
+
m.has_singular_bool?
|
70
106
|
end
|
71
107
|
assert_raise ArgumentError do
|
72
|
-
|
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 =
|
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
|
-
|
87
|
-
|
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
|
-
|
211
|
-
|
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
|
-
|
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
|
-
|
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
|
-
|
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
|
-
|
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
|
-
|
356
|
-
|
357
|
-
|
358
|
-
|
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
|