decode_test.go 64 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440144114421443144414451446144714481449145014511452145314541455145614571458145914601461146214631464146514661467146814691470147114721473147414751476147714781479148014811482148314841485148614871488148914901491149214931494149514961497149814991500150115021503150415051506150715081509151015111512151315141515151615171518151915201521152215231524152515261527152815291530153115321533153415351536153715381539154015411542154315441545154615471548154915501551155215531554155515561557155815591560156115621563156415651566156715681569157015711572157315741575157615771578157915801581158215831584158515861587158815891590159115921593159415951596159715981599160016011602160316041605160616071608160916101611161216131614161516161617161816191620162116221623162416251626162716281629163016311632163316341635163616371638163916401641164216431644164516461647164816491650165116521653165416551656165716581659166016611662166316641665166616671668166916701671167216731674167516761677167816791680168116821683168416851686168716881689169016911692169316941695169616971698169917001701170217031704170517061707170817091710171117121713171417151716171717181719172017211722172317241725172617271728172917301731173217331734173517361737173817391740174117421743174417451746174717481749175017511752175317541755175617571758175917601761176217631764176517661767176817691770177117721773177417751776177717781779178017811782178317841785178617871788178917901791179217931794179517961797179817991800180118021803180418051806180718081809181018111812181318141815181618171818181918201821182218231824182518261827182818291830183118321833183418351836183718381839184018411842184318441845184618471848184918501851185218531854185518561857185818591860186118621863186418651866186718681869187018711872187318741875187618771878187918801881188218831884188518861887188818891890189118921893189418951896189718981899190019011902190319041905190619071908190919101911191219131914191519161917191819191920192119221923192419251926192719281929193019311932193319341935193619371938193919401941194219431944194519461947194819491950195119521953195419551956195719581959196019611962196319641965196619671968196919701971197219731974197519761977197819791980198119821983198419851986198719881989199019911992199319941995199619971998199920002001200220032004200520062007200820092010201120122013201420152016201720182019202020212022202320242025202620272028202920302031203220332034203520362037203820392040204120422043204420452046204720482049205020512052205320542055205620572058205920602061206220632064206520662067206820692070207120722073207420752076207720782079208020812082208320842085208620872088208920902091209220932094209520962097209820992100210121022103210421052106210721082109211021112112211321142115211621172118211921202121212221232124212521262127212821292130213121322133213421352136213721382139214021412142214321442145214621472148214921502151215221532154215521562157215821592160216121622163216421652166216721682169217021712172217321742175217621772178217921802181218221832184218521862187218821892190219121922193219421952196219721982199220022012202220322042205220622072208220922102211221222132214221522162217221822192220222122222223222422252226222722282229223022312232223322342235223622372238223922402241224222432244224522462247224822492250225122522253225422552256225722582259226022612262226322642265226622672268226922702271227222732274227522762277227822792280228122822283228422852286228722882289229022912292229322942295229622972298229923002301230223032304230523062307230823092310231123122313231423152316231723182319232023212322232323242325232623272328232923302331233223332334233523362337233823392340234123422343234423452346234723482349235023512352235323542355235623572358235923602361236223632364236523662367236823692370237123722373237423752376237723782379238023812382238323842385238623872388238923902391239223932394239523962397239823992400240124022403240424052406240724082409241024112412241324142415241624172418241924202421242224232424242524262427242824292430243124322433243424352436243724382439244024412442244324442445244624472448244924502451245224532454245524562457245824592460246124622463246424652466246724682469247024712472247324742475247624772478247924802481248224832484248524862487248824892490
  1. // Copyright 2019 The Go Authors. All rights reserved.
  2. // Use of this source code is governed by a BSD-style
  3. // license that can be found in the LICENSE file.
  4. package protojson_test
  5. import (
  6. "math"
  7. "testing"
  8. "google.golang.org/protobuf/encoding/protojson"
  9. "google.golang.org/protobuf/encoding/testprotos/pb2"
  10. "google.golang.org/protobuf/encoding/testprotos/pb3"
  11. pimpl "google.golang.org/protobuf/internal/impl"
  12. "google.golang.org/protobuf/internal/scalar"
  13. "google.golang.org/protobuf/proto"
  14. preg "google.golang.org/protobuf/reflect/protoregistry"
  15. "google.golang.org/protobuf/runtime/protoiface"
  16. "google.golang.org/protobuf/types/known/anypb"
  17. "google.golang.org/protobuf/types/known/durationpb"
  18. "google.golang.org/protobuf/types/known/emptypb"
  19. "google.golang.org/protobuf/types/known/fieldmaskpb"
  20. "google.golang.org/protobuf/types/known/structpb"
  21. "google.golang.org/protobuf/types/known/timestamppb"
  22. "google.golang.org/protobuf/types/known/wrapperspb"
  23. )
  24. func init() {
  25. // TODO: remove these registerExtension calls when generated code registers
  26. // to V2 global registry.
  27. registerExtension(pb2.E_OptExtBool)
  28. registerExtension(pb2.E_OptExtString)
  29. registerExtension(pb2.E_OptExtEnum)
  30. registerExtension(pb2.E_OptExtNested)
  31. registerExtension(pb2.E_RptExtFixed32)
  32. registerExtension(pb2.E_RptExtEnum)
  33. registerExtension(pb2.E_RptExtNested)
  34. registerExtension(pb2.E_ExtensionsContainer_OptExtBool)
  35. registerExtension(pb2.E_ExtensionsContainer_OptExtString)
  36. registerExtension(pb2.E_ExtensionsContainer_OptExtEnum)
  37. registerExtension(pb2.E_ExtensionsContainer_OptExtNested)
  38. registerExtension(pb2.E_ExtensionsContainer_RptExtString)
  39. registerExtension(pb2.E_ExtensionsContainer_RptExtEnum)
  40. registerExtension(pb2.E_ExtensionsContainer_RptExtNested)
  41. registerExtension(pb2.E_MessageSetExtension)
  42. registerExtension(pb2.E_MessageSetExtension_MessageSetExtension)
  43. registerExtension(pb2.E_MessageSetExtension_NotMessageSetExtension)
  44. registerExtension(pb2.E_MessageSetExtension_ExtNested)
  45. registerExtension(pb2.E_FakeMessageSetExtension_MessageSetExtension)
  46. }
  47. func registerExtension(xd *protoiface.ExtensionDescV1) {
  48. preg.GlobalTypes.Register(xd.Type)
  49. }
  50. func TestUnmarshal(t *testing.T) {
  51. tests := []struct {
  52. desc string
  53. umo protojson.UnmarshalOptions
  54. inputMessage proto.Message
  55. inputText string
  56. wantMessage proto.Message
  57. // TODO: verify expected error message substring.
  58. wantErr bool
  59. }{{
  60. desc: "proto2 empty message",
  61. inputMessage: &pb2.Scalars{},
  62. inputText: "{}",
  63. wantMessage: &pb2.Scalars{},
  64. }, {
  65. desc: "unexpected value instead of EOF",
  66. inputMessage: &pb2.Scalars{},
  67. inputText: "{} {}",
  68. wantErr: true,
  69. }, {
  70. desc: "proto2 optional scalars set to zero values",
  71. inputMessage: &pb2.Scalars{},
  72. inputText: `{
  73. "optBool": false,
  74. "optInt32": 0,
  75. "optInt64": 0,
  76. "optUint32": 0,
  77. "optUint64": 0,
  78. "optSint32": 0,
  79. "optSint64": 0,
  80. "optFixed32": 0,
  81. "optFixed64": 0,
  82. "optSfixed32": 0,
  83. "optSfixed64": 0,
  84. "optFloat": 0,
  85. "optDouble": 0,
  86. "optBytes": "",
  87. "optString": ""
  88. }`,
  89. wantMessage: &pb2.Scalars{
  90. OptBool: scalar.Bool(false),
  91. OptInt32: scalar.Int32(0),
  92. OptInt64: scalar.Int64(0),
  93. OptUint32: scalar.Uint32(0),
  94. OptUint64: scalar.Uint64(0),
  95. OptSint32: scalar.Int32(0),
  96. OptSint64: scalar.Int64(0),
  97. OptFixed32: scalar.Uint32(0),
  98. OptFixed64: scalar.Uint64(0),
  99. OptSfixed32: scalar.Int32(0),
  100. OptSfixed64: scalar.Int64(0),
  101. OptFloat: scalar.Float32(0),
  102. OptDouble: scalar.Float64(0),
  103. OptBytes: []byte{},
  104. OptString: scalar.String(""),
  105. },
  106. }, {
  107. desc: "proto3 scalars set to zero values",
  108. inputMessage: &pb3.Scalars{},
  109. inputText: `{
  110. "sBool": false,
  111. "sInt32": 0,
  112. "sInt64": 0,
  113. "sUint32": 0,
  114. "sUint64": 0,
  115. "sSint32": 0,
  116. "sSint64": 0,
  117. "sFixed32": 0,
  118. "sFixed64": 0,
  119. "sSfixed32": 0,
  120. "sSfixed64": 0,
  121. "sFloat": 0,
  122. "sDouble": 0,
  123. "sBytes": "",
  124. "sString": ""
  125. }`,
  126. wantMessage: &pb3.Scalars{},
  127. }, {
  128. desc: "proto2 optional scalars set to null",
  129. inputMessage: &pb2.Scalars{},
  130. inputText: `{
  131. "optBool": null,
  132. "optInt32": null,
  133. "optInt64": null,
  134. "optUint32": null,
  135. "optUint64": null,
  136. "optSint32": null,
  137. "optSint64": null,
  138. "optFixed32": null,
  139. "optFixed64": null,
  140. "optSfixed32": null,
  141. "optSfixed64": null,
  142. "optFloat": null,
  143. "optDouble": null,
  144. "optBytes": null,
  145. "optString": null
  146. }`,
  147. wantMessage: &pb2.Scalars{},
  148. }, {
  149. desc: "proto3 scalars set to null",
  150. inputMessage: &pb3.Scalars{},
  151. inputText: `{
  152. "sBool": null,
  153. "sInt32": null,
  154. "sInt64": null,
  155. "sUint32": null,
  156. "sUint64": null,
  157. "sSint32": null,
  158. "sSint64": null,
  159. "sFixed32": null,
  160. "sFixed64": null,
  161. "sSfixed32": null,
  162. "sSfixed64": null,
  163. "sFloat": null,
  164. "sDouble": null,
  165. "sBytes": null,
  166. "sString": null
  167. }`,
  168. wantMessage: &pb3.Scalars{},
  169. }, {
  170. desc: "boolean",
  171. inputMessage: &pb3.Scalars{},
  172. inputText: `{"sBool": true}`,
  173. wantMessage: &pb3.Scalars{
  174. SBool: true,
  175. },
  176. }, {
  177. desc: "not boolean",
  178. inputMessage: &pb3.Scalars{},
  179. inputText: `{"sBool": "true"}`,
  180. wantErr: true,
  181. }, {
  182. desc: "float and double",
  183. inputMessage: &pb3.Scalars{},
  184. inputText: `{
  185. "sFloat": 1.234,
  186. "sDouble": 5.678
  187. }`,
  188. wantMessage: &pb3.Scalars{
  189. SFloat: 1.234,
  190. SDouble: 5.678,
  191. },
  192. }, {
  193. desc: "float and double in string",
  194. inputMessage: &pb3.Scalars{},
  195. inputText: `{
  196. "sFloat": "1.234",
  197. "sDouble": "5.678"
  198. }`,
  199. wantMessage: &pb3.Scalars{
  200. SFloat: 1.234,
  201. SDouble: 5.678,
  202. },
  203. }, {
  204. desc: "float and double in E notation",
  205. inputMessage: &pb3.Scalars{},
  206. inputText: `{
  207. "sFloat": 12.34E-1,
  208. "sDouble": 5.678e4
  209. }`,
  210. wantMessage: &pb3.Scalars{
  211. SFloat: 1.234,
  212. SDouble: 56780,
  213. },
  214. }, {
  215. desc: "float and double in string E notation",
  216. inputMessage: &pb3.Scalars{},
  217. inputText: `{
  218. "sFloat": "12.34E-1",
  219. "sDouble": "5.678e4"
  220. }`,
  221. wantMessage: &pb3.Scalars{
  222. SFloat: 1.234,
  223. SDouble: 56780,
  224. },
  225. }, {
  226. desc: "float exceeds limit",
  227. inputMessage: &pb3.Scalars{},
  228. inputText: `{"sFloat": 3.4e39}`,
  229. wantErr: true,
  230. }, {
  231. desc: "float in string exceeds limit",
  232. inputMessage: &pb3.Scalars{},
  233. inputText: `{"sFloat": "-3.4e39"}`,
  234. wantErr: true,
  235. }, {
  236. desc: "double exceeds limit",
  237. inputMessage: &pb3.Scalars{},
  238. inputText: `{"sFloat": -1.79e+309}`,
  239. wantErr: true,
  240. }, {
  241. desc: "double in string exceeds limit",
  242. inputMessage: &pb3.Scalars{},
  243. inputText: `{"sFloat": "1.79e+309"}`,
  244. wantErr: true,
  245. }, {
  246. desc: "infinites",
  247. inputMessage: &pb3.Scalars{},
  248. inputText: `{"sFloat": "Infinity", "sDouble": "-Infinity"}`,
  249. wantMessage: &pb3.Scalars{
  250. SFloat: float32(math.Inf(+1)),
  251. SDouble: math.Inf(-1),
  252. },
  253. }, {
  254. desc: "float string with leading space",
  255. inputMessage: &pb3.Scalars{},
  256. inputText: `{"sFloat": " 1.234"}`,
  257. wantErr: true,
  258. }, {
  259. desc: "double string with trailing space",
  260. inputMessage: &pb3.Scalars{},
  261. inputText: `{"sDouble": "5.678 "}`,
  262. wantErr: true,
  263. }, {
  264. desc: "not float",
  265. inputMessage: &pb3.Scalars{},
  266. inputText: `{"sFloat": true}`,
  267. wantErr: true,
  268. }, {
  269. desc: "not double",
  270. inputMessage: &pb3.Scalars{},
  271. inputText: `{"sDouble": "not a number"}`,
  272. wantErr: true,
  273. }, {
  274. desc: "integers",
  275. inputMessage: &pb3.Scalars{},
  276. inputText: `{
  277. "sInt32": 1234,
  278. "sInt64": -1234,
  279. "sUint32": 1e2,
  280. "sUint64": 100E-2,
  281. "sSint32": 1.0,
  282. "sSint64": -1.0,
  283. "sFixed32": 1.234e+5,
  284. "sFixed64": 1200E-2,
  285. "sSfixed32": -1.234e05,
  286. "sSfixed64": -1200e-02
  287. }`,
  288. wantMessage: &pb3.Scalars{
  289. SInt32: 1234,
  290. SInt64: -1234,
  291. SUint32: 100,
  292. SUint64: 1,
  293. SSint32: 1,
  294. SSint64: -1,
  295. SFixed32: 123400,
  296. SFixed64: 12,
  297. SSfixed32: -123400,
  298. SSfixed64: -12,
  299. },
  300. }, {
  301. desc: "integers in string",
  302. inputMessage: &pb3.Scalars{},
  303. inputText: `{
  304. "sInt32": "1234",
  305. "sInt64": "-1234",
  306. "sUint32": "1e2",
  307. "sUint64": "100E-2",
  308. "sSint32": "1.0",
  309. "sSint64": "-1.0",
  310. "sFixed32": "1.234e+5",
  311. "sFixed64": "1200E-2",
  312. "sSfixed32": "-1.234e05",
  313. "sSfixed64": "-1200e-02"
  314. }`,
  315. wantMessage: &pb3.Scalars{
  316. SInt32: 1234,
  317. SInt64: -1234,
  318. SUint32: 100,
  319. SUint64: 1,
  320. SSint32: 1,
  321. SSint64: -1,
  322. SFixed32: 123400,
  323. SFixed64: 12,
  324. SSfixed32: -123400,
  325. SSfixed64: -12,
  326. },
  327. }, {
  328. desc: "integers in escaped string",
  329. inputMessage: &pb3.Scalars{},
  330. inputText: `{"sInt32": "\u0031\u0032"}`,
  331. wantMessage: &pb3.Scalars{
  332. SInt32: 12,
  333. },
  334. }, {
  335. desc: "integer string with leading space",
  336. inputMessage: &pb3.Scalars{},
  337. inputText: `{"sInt32": " 1234"}`,
  338. wantErr: true,
  339. }, {
  340. desc: "integer string with trailing space",
  341. inputMessage: &pb3.Scalars{},
  342. inputText: `{"sUint32": "1e2 "}`,
  343. wantErr: true,
  344. }, {
  345. desc: "number is not an integer",
  346. inputMessage: &pb3.Scalars{},
  347. inputText: `{"sInt32": 1.001}`,
  348. wantErr: true,
  349. }, {
  350. desc: "32-bit int exceeds limit",
  351. inputMessage: &pb3.Scalars{},
  352. inputText: `{"sInt32": 2e10}`,
  353. wantErr: true,
  354. }, {
  355. desc: "64-bit int exceeds limit",
  356. inputMessage: &pb3.Scalars{},
  357. inputText: `{"sSfixed64": -9e19}`,
  358. wantErr: true,
  359. }, {
  360. desc: "not integer",
  361. inputMessage: &pb3.Scalars{},
  362. inputText: `{"sInt32": "not a number"}`,
  363. wantErr: true,
  364. }, {
  365. desc: "not unsigned integer",
  366. inputMessage: &pb3.Scalars{},
  367. inputText: `{"sUint32": "not a number"}`,
  368. wantErr: true,
  369. }, {
  370. desc: "number is not an unsigned integer",
  371. inputMessage: &pb3.Scalars{},
  372. inputText: `{"sUint32": -1}`,
  373. wantErr: true,
  374. }, {
  375. desc: "string",
  376. inputMessage: &pb2.Scalars{},
  377. inputText: `{"optString": "谷歌"}`,
  378. wantMessage: &pb2.Scalars{
  379. OptString: scalar.String("谷歌"),
  380. },
  381. }, {
  382. desc: "string with invalid UTF-8",
  383. inputMessage: &pb3.Scalars{},
  384. inputText: "{\"sString\": \"\xff\"}",
  385. wantErr: true,
  386. }, {
  387. desc: "not string",
  388. inputMessage: &pb2.Scalars{},
  389. inputText: `{"optString": 42}`,
  390. wantErr: true,
  391. }, {
  392. desc: "bytes",
  393. inputMessage: &pb3.Scalars{},
  394. inputText: `{"sBytes": "aGVsbG8gd29ybGQ"}`,
  395. wantMessage: &pb3.Scalars{
  396. SBytes: []byte("hello world"),
  397. },
  398. }, {
  399. desc: "bytes padded",
  400. inputMessage: &pb3.Scalars{},
  401. inputText: `{"sBytes": "aGVsbG8gd29ybGQ="}`,
  402. wantMessage: &pb3.Scalars{
  403. SBytes: []byte("hello world"),
  404. },
  405. }, {
  406. desc: "not bytes",
  407. inputMessage: &pb3.Scalars{},
  408. inputText: `{"sBytes": true}`,
  409. wantErr: true,
  410. }, {
  411. desc: "proto2 enum",
  412. inputMessage: &pb2.Enums{},
  413. inputText: `{
  414. "optEnum": "ONE",
  415. "optNestedEnum": "UNO"
  416. }`,
  417. wantMessage: &pb2.Enums{
  418. OptEnum: pb2.Enum_ONE.Enum(),
  419. OptNestedEnum: pb2.Enums_UNO.Enum(),
  420. },
  421. }, {
  422. desc: "proto3 enum",
  423. inputMessage: &pb3.Enums{},
  424. inputText: `{
  425. "sEnum": "ONE",
  426. "sNestedEnum": "DIEZ"
  427. }`,
  428. wantMessage: &pb3.Enums{
  429. SEnum: pb3.Enum_ONE,
  430. SNestedEnum: pb3.Enums_DIEZ,
  431. },
  432. }, {
  433. desc: "enum numeric value",
  434. inputMessage: &pb3.Enums{},
  435. inputText: `{
  436. "sEnum": 2,
  437. "sNestedEnum": 2
  438. }`,
  439. wantMessage: &pb3.Enums{
  440. SEnum: pb3.Enum_TWO,
  441. SNestedEnum: pb3.Enums_DOS,
  442. },
  443. }, {
  444. desc: "enum unnamed numeric value",
  445. inputMessage: &pb3.Enums{},
  446. inputText: `{
  447. "sEnum": 101,
  448. "sNestedEnum": -101
  449. }`,
  450. wantMessage: &pb3.Enums{
  451. SEnum: 101,
  452. SNestedEnum: -101,
  453. },
  454. }, {
  455. desc: "enum set to number string",
  456. inputMessage: &pb3.Enums{},
  457. inputText: `{
  458. "sEnum": "1"
  459. }`,
  460. wantErr: true,
  461. }, {
  462. desc: "enum set to invalid named",
  463. inputMessage: &pb3.Enums{},
  464. inputText: `{
  465. "sEnum": "UNNAMED"
  466. }`,
  467. wantErr: true,
  468. }, {
  469. desc: "enum set to not enum",
  470. inputMessage: &pb3.Enums{},
  471. inputText: `{
  472. "sEnum": true
  473. }`,
  474. wantErr: true,
  475. }, {
  476. desc: "enum set to JSON null",
  477. inputMessage: &pb3.Enums{},
  478. inputText: `{
  479. "sEnum": null
  480. }`,
  481. wantMessage: &pb3.Enums{},
  482. }, {
  483. desc: "proto name",
  484. inputMessage: &pb3.JSONNames{},
  485. inputText: `{
  486. "s_string": "proto name used"
  487. }`,
  488. wantMessage: &pb3.JSONNames{
  489. SString: "proto name used",
  490. },
  491. }, {
  492. desc: "json_name",
  493. inputMessage: &pb3.JSONNames{},
  494. inputText: `{
  495. "foo_bar": "json_name used"
  496. }`,
  497. wantMessage: &pb3.JSONNames{
  498. SString: "json_name used",
  499. },
  500. }, {
  501. desc: "camelCase name",
  502. inputMessage: &pb3.JSONNames{},
  503. inputText: `{
  504. "sString": "camelcase used"
  505. }`,
  506. wantErr: true,
  507. }, {
  508. desc: "proto name and json_name",
  509. inputMessage: &pb3.JSONNames{},
  510. inputText: `{
  511. "foo_bar": "json_name used",
  512. "s_string": "proto name used"
  513. }`,
  514. wantErr: true,
  515. }, {
  516. desc: "duplicate field names",
  517. inputMessage: &pb3.JSONNames{},
  518. inputText: `{
  519. "foo_bar": "one",
  520. "foo_bar": "two",
  521. }`,
  522. wantErr: true,
  523. }, {
  524. desc: "null message",
  525. inputMessage: &pb2.Nests{},
  526. inputText: "null",
  527. wantErr: true,
  528. }, {
  529. desc: "proto2 nested message not set",
  530. inputMessage: &pb2.Nests{},
  531. inputText: "{}",
  532. wantMessage: &pb2.Nests{},
  533. }, {
  534. desc: "proto2 nested message set to null",
  535. inputMessage: &pb2.Nests{},
  536. inputText: `{
  537. "optNested": null,
  538. "optgroup": null
  539. }`,
  540. wantMessage: &pb2.Nests{},
  541. }, {
  542. desc: "proto2 nested message set to empty",
  543. inputMessage: &pb2.Nests{},
  544. inputText: `{
  545. "optNested": {},
  546. "optgroup": {}
  547. }`,
  548. wantMessage: &pb2.Nests{
  549. OptNested: &pb2.Nested{},
  550. Optgroup: &pb2.Nests_OptGroup{},
  551. },
  552. }, {
  553. desc: "proto2 nested messages",
  554. inputMessage: &pb2.Nests{},
  555. inputText: `{
  556. "optNested": {
  557. "optString": "nested message",
  558. "optNested": {
  559. "optString": "another nested message"
  560. }
  561. }
  562. }`,
  563. wantMessage: &pb2.Nests{
  564. OptNested: &pb2.Nested{
  565. OptString: scalar.String("nested message"),
  566. OptNested: &pb2.Nested{
  567. OptString: scalar.String("another nested message"),
  568. },
  569. },
  570. },
  571. }, {
  572. desc: "proto2 groups",
  573. inputMessage: &pb2.Nests{},
  574. inputText: `{
  575. "optgroup": {
  576. "optString": "inside a group",
  577. "optNested": {
  578. "optString": "nested message inside a group"
  579. },
  580. "optnestedgroup": {
  581. "optFixed32": 47
  582. }
  583. }
  584. }`,
  585. wantMessage: &pb2.Nests{
  586. Optgroup: &pb2.Nests_OptGroup{
  587. OptString: scalar.String("inside a group"),
  588. OptNested: &pb2.Nested{
  589. OptString: scalar.String("nested message inside a group"),
  590. },
  591. Optnestedgroup: &pb2.Nests_OptGroup_OptNestedGroup{
  592. OptFixed32: scalar.Uint32(47),
  593. },
  594. },
  595. },
  596. }, {
  597. desc: "proto3 nested message not set",
  598. inputMessage: &pb3.Nests{},
  599. inputText: "{}",
  600. wantMessage: &pb3.Nests{},
  601. }, {
  602. desc: "proto3 nested message set to null",
  603. inputMessage: &pb3.Nests{},
  604. inputText: `{"sNested": null}`,
  605. wantMessage: &pb3.Nests{},
  606. }, {
  607. desc: "proto3 nested message set to empty",
  608. inputMessage: &pb3.Nests{},
  609. inputText: `{"sNested": {}}`,
  610. wantMessage: &pb3.Nests{
  611. SNested: &pb3.Nested{},
  612. },
  613. }, {
  614. desc: "proto3 nested message",
  615. inputMessage: &pb3.Nests{},
  616. inputText: `{
  617. "sNested": {
  618. "sString": "nested message",
  619. "sNested": {
  620. "sString": "another nested message"
  621. }
  622. }
  623. }`,
  624. wantMessage: &pb3.Nests{
  625. SNested: &pb3.Nested{
  626. SString: "nested message",
  627. SNested: &pb3.Nested{
  628. SString: "another nested message",
  629. },
  630. },
  631. },
  632. }, {
  633. desc: "message set to non-message",
  634. inputMessage: &pb3.Nests{},
  635. inputText: `"not valid"`,
  636. wantErr: true,
  637. }, {
  638. desc: "nested message set to non-message",
  639. inputMessage: &pb3.Nests{},
  640. inputText: `{"sNested": true}`,
  641. wantErr: true,
  642. }, {
  643. desc: "oneof not set",
  644. inputMessage: &pb3.Oneofs{},
  645. inputText: "{}",
  646. wantMessage: &pb3.Oneofs{},
  647. }, {
  648. desc: "oneof set to empty string",
  649. inputMessage: &pb3.Oneofs{},
  650. inputText: `{"oneofString": ""}`,
  651. wantMessage: &pb3.Oneofs{
  652. Union: &pb3.Oneofs_OneofString{},
  653. },
  654. }, {
  655. desc: "oneof set to string",
  656. inputMessage: &pb3.Oneofs{},
  657. inputText: `{"oneofString": "hello"}`,
  658. wantMessage: &pb3.Oneofs{
  659. Union: &pb3.Oneofs_OneofString{
  660. OneofString: "hello",
  661. },
  662. },
  663. }, {
  664. desc: "oneof set to enum",
  665. inputMessage: &pb3.Oneofs{},
  666. inputText: `{"oneofEnum": "ZERO"}`,
  667. wantMessage: &pb3.Oneofs{
  668. Union: &pb3.Oneofs_OneofEnum{
  669. OneofEnum: pb3.Enum_ZERO,
  670. },
  671. },
  672. }, {
  673. desc: "oneof set to empty message",
  674. inputMessage: &pb3.Oneofs{},
  675. inputText: `{"oneofNested": {}}`,
  676. wantMessage: &pb3.Oneofs{
  677. Union: &pb3.Oneofs_OneofNested{
  678. OneofNested: &pb3.Nested{},
  679. },
  680. },
  681. }, {
  682. desc: "oneof set to message",
  683. inputMessage: &pb3.Oneofs{},
  684. inputText: `{
  685. "oneofNested": {
  686. "sString": "nested message"
  687. }
  688. }`,
  689. wantMessage: &pb3.Oneofs{
  690. Union: &pb3.Oneofs_OneofNested{
  691. OneofNested: &pb3.Nested{
  692. SString: "nested message",
  693. },
  694. },
  695. },
  696. }, {
  697. desc: "oneof set to more than one field",
  698. inputMessage: &pb3.Oneofs{},
  699. inputText: `{
  700. "oneofEnum": "ZERO",
  701. "oneofString": "hello"
  702. }`,
  703. wantErr: true,
  704. }, {
  705. desc: "oneof set to null and value",
  706. inputMessage: &pb3.Oneofs{},
  707. inputText: `{
  708. "oneofEnum": "ZERO",
  709. "oneofString": null
  710. }`,
  711. wantMessage: &pb3.Oneofs{
  712. Union: &pb3.Oneofs_OneofEnum{
  713. OneofEnum: pb3.Enum_ZERO,
  714. },
  715. },
  716. }, {
  717. desc: "repeated null fields",
  718. inputMessage: &pb2.Repeats{},
  719. inputText: `{
  720. "rptString": null,
  721. "rptInt32" : null,
  722. "rptFloat" : null,
  723. "rptBytes" : null
  724. }`,
  725. wantMessage: &pb2.Repeats{},
  726. }, {
  727. desc: "repeated scalars",
  728. inputMessage: &pb2.Repeats{},
  729. inputText: `{
  730. "rptString": ["hello", "world"],
  731. "rptInt32" : [-1, 0, 1],
  732. "rptBool" : [false, true]
  733. }`,
  734. wantMessage: &pb2.Repeats{
  735. RptString: []string{"hello", "world"},
  736. RptInt32: []int32{-1, 0, 1},
  737. RptBool: []bool{false, true},
  738. },
  739. }, {
  740. desc: "repeated enums",
  741. inputMessage: &pb2.Enums{},
  742. inputText: `{
  743. "rptEnum" : ["TEN", 1, 42],
  744. "rptNestedEnum": ["DOS", 2, -47]
  745. }`,
  746. wantMessage: &pb2.Enums{
  747. RptEnum: []pb2.Enum{pb2.Enum_TEN, pb2.Enum_ONE, 42},
  748. RptNestedEnum: []pb2.Enums_NestedEnum{pb2.Enums_DOS, pb2.Enums_DOS, -47},
  749. },
  750. }, {
  751. desc: "repeated messages",
  752. inputMessage: &pb2.Nests{},
  753. inputText: `{
  754. "rptNested": [
  755. {
  756. "optString": "repeat nested one"
  757. },
  758. {
  759. "optString": "repeat nested two",
  760. "optNested": {
  761. "optString": "inside repeat nested two"
  762. }
  763. },
  764. {}
  765. ]
  766. }`,
  767. wantMessage: &pb2.Nests{
  768. RptNested: []*pb2.Nested{
  769. {
  770. OptString: scalar.String("repeat nested one"),
  771. },
  772. {
  773. OptString: scalar.String("repeat nested two"),
  774. OptNested: &pb2.Nested{
  775. OptString: scalar.String("inside repeat nested two"),
  776. },
  777. },
  778. {},
  779. },
  780. },
  781. }, {
  782. desc: "repeated groups",
  783. inputMessage: &pb2.Nests{},
  784. inputText: `{
  785. "rptgroup": [
  786. {
  787. "rptString": ["hello", "world"]
  788. },
  789. {}
  790. ]
  791. }
  792. `,
  793. wantMessage: &pb2.Nests{
  794. Rptgroup: []*pb2.Nests_RptGroup{
  795. {
  796. RptString: []string{"hello", "world"},
  797. },
  798. {},
  799. },
  800. },
  801. }, {
  802. desc: "repeated string contains invalid UTF8",
  803. inputMessage: &pb2.Repeats{},
  804. inputText: `{"rptString": ["` + "abc\xff" + `"]}`,
  805. wantErr: true,
  806. }, {
  807. desc: "repeated messages contain invalid UTF8",
  808. inputMessage: &pb2.Nests{},
  809. inputText: `{"rptNested": [{"optString": "` + "abc\xff" + `"}]}`,
  810. wantErr: true,
  811. }, {
  812. desc: "repeated scalars contain invalid type",
  813. inputMessage: &pb2.Repeats{},
  814. inputText: `{"rptString": ["hello", null, "world"]}`,
  815. wantErr: true,
  816. }, {
  817. desc: "repeated messages contain invalid type",
  818. inputMessage: &pb2.Nests{},
  819. inputText: `{"rptNested": [{}, null]}`,
  820. wantErr: true,
  821. }, {
  822. desc: "map fields 1",
  823. inputMessage: &pb3.Maps{},
  824. inputText: `{
  825. "int32ToStr": {
  826. "-101": "-101",
  827. "0" : "zero",
  828. "255" : "0xff"
  829. },
  830. "boolToUint32": {
  831. "false": 101,
  832. "true" : "42"
  833. }
  834. }`,
  835. wantMessage: &pb3.Maps{
  836. Int32ToStr: map[int32]string{
  837. -101: "-101",
  838. 0xff: "0xff",
  839. 0: "zero",
  840. },
  841. BoolToUint32: map[bool]uint32{
  842. true: 42,
  843. false: 101,
  844. },
  845. },
  846. }, {
  847. desc: "map fields 2",
  848. inputMessage: &pb3.Maps{},
  849. inputText: `{
  850. "uint64ToEnum": {
  851. "1" : "ONE",
  852. "2" : 2,
  853. "10": 101
  854. }
  855. }`,
  856. wantMessage: &pb3.Maps{
  857. Uint64ToEnum: map[uint64]pb3.Enum{
  858. 1: pb3.Enum_ONE,
  859. 2: pb3.Enum_TWO,
  860. 10: 101,
  861. },
  862. },
  863. }, {
  864. desc: "map fields 3",
  865. inputMessage: &pb3.Maps{},
  866. inputText: `{
  867. "strToNested": {
  868. "nested_one": {
  869. "sString": "nested in a map"
  870. },
  871. "nested_two": {}
  872. }
  873. }`,
  874. wantMessage: &pb3.Maps{
  875. StrToNested: map[string]*pb3.Nested{
  876. "nested_one": {
  877. SString: "nested in a map",
  878. },
  879. "nested_two": {},
  880. },
  881. },
  882. }, {
  883. desc: "map fields 4",
  884. inputMessage: &pb3.Maps{},
  885. inputText: `{
  886. "strToOneofs": {
  887. "nested": {
  888. "oneofNested": {
  889. "sString": "nested oneof in map field value"
  890. }
  891. },
  892. "string": {
  893. "oneofString": "hello"
  894. }
  895. }
  896. }`,
  897. wantMessage: &pb3.Maps{
  898. StrToOneofs: map[string]*pb3.Oneofs{
  899. "string": {
  900. Union: &pb3.Oneofs_OneofString{
  901. OneofString: "hello",
  902. },
  903. },
  904. "nested": {
  905. Union: &pb3.Oneofs_OneofNested{
  906. OneofNested: &pb3.Nested{
  907. SString: "nested oneof in map field value",
  908. },
  909. },
  910. },
  911. },
  912. },
  913. }, {
  914. desc: "map contains duplicate keys",
  915. inputMessage: &pb3.Maps{},
  916. inputText: `{
  917. "int32ToStr": {
  918. "0": "cero",
  919. "0": "zero"
  920. }
  921. }
  922. `,
  923. wantErr: true,
  924. }, {
  925. desc: "map key empty string",
  926. inputMessage: &pb3.Maps{},
  927. inputText: `{
  928. "strToNested": {
  929. "": {}
  930. }
  931. }`,
  932. wantMessage: &pb3.Maps{
  933. StrToNested: map[string]*pb3.Nested{
  934. "": {},
  935. },
  936. },
  937. }, {
  938. desc: "map contains invalid key 1",
  939. inputMessage: &pb3.Maps{},
  940. inputText: `{
  941. "int32ToStr": {
  942. "invalid": "cero"
  943. }`,
  944. wantErr: true,
  945. }, {
  946. desc: "map contains invalid key 2",
  947. inputMessage: &pb3.Maps{},
  948. inputText: `{
  949. "int32ToStr": {
  950. "1.02": "float"
  951. }`,
  952. wantErr: true,
  953. }, {
  954. desc: "map contains invalid key 3",
  955. inputMessage: &pb3.Maps{},
  956. inputText: `{
  957. "int32ToStr": {
  958. "2147483648": "exceeds 32-bit integer max limit"
  959. }`,
  960. wantErr: true,
  961. }, {
  962. desc: "map contains invalid key 4",
  963. inputMessage: &pb3.Maps{},
  964. inputText: `{
  965. "uint64ToEnum": {
  966. "-1": 0
  967. }
  968. }`,
  969. wantErr: true,
  970. }, {
  971. desc: "map contains invalid value",
  972. inputMessage: &pb3.Maps{},
  973. inputText: `{
  974. "int32ToStr": {
  975. "101": true
  976. }`,
  977. wantErr: true,
  978. }, {
  979. desc: "map contains null for scalar value",
  980. inputMessage: &pb3.Maps{},
  981. inputText: `{
  982. "int32ToStr": {
  983. "101": null
  984. }`,
  985. wantErr: true,
  986. }, {
  987. desc: "map contains null for message value",
  988. inputMessage: &pb3.Maps{},
  989. inputText: `{
  990. "strToNested": {
  991. "hello": null
  992. }
  993. }`,
  994. wantErr: true,
  995. }, {
  996. desc: "map contains contains message value with invalid UTF8",
  997. inputMessage: &pb3.Maps{},
  998. inputText: `{
  999. "strToNested": {
  1000. "hello": {
  1001. "sString": "` + "abc\xff" + `"
  1002. }
  1003. }
  1004. }`,
  1005. wantErr: true,
  1006. }, {
  1007. desc: "map key contains invalid UTF8",
  1008. inputMessage: &pb3.Maps{},
  1009. inputText: `{
  1010. "strToNested": {
  1011. "` + "abc\xff" + `": {}
  1012. }
  1013. }`,
  1014. wantErr: true,
  1015. }, {
  1016. desc: "required fields not set",
  1017. inputMessage: &pb2.Requireds{},
  1018. wantErr: true,
  1019. }, {
  1020. desc: "required field set",
  1021. inputMessage: &pb2.PartialRequired{},
  1022. inputText: `{
  1023. "reqString": "this is required"
  1024. }`,
  1025. wantMessage: &pb2.PartialRequired{
  1026. ReqString: scalar.String("this is required"),
  1027. },
  1028. }, {
  1029. desc: "required fields partially set",
  1030. inputMessage: &pb2.Requireds{},
  1031. inputText: `{
  1032. "reqBool": false,
  1033. "reqSfixed64": 42,
  1034. "reqString": "hello",
  1035. "reqEnum": "ONE"
  1036. }`,
  1037. wantMessage: &pb2.Requireds{
  1038. ReqBool: scalar.Bool(false),
  1039. ReqSfixed64: scalar.Int64(42),
  1040. ReqString: scalar.String("hello"),
  1041. ReqEnum: pb2.Enum_ONE.Enum(),
  1042. },
  1043. wantErr: true,
  1044. }, {
  1045. desc: "required fields partially set with AllowPartial",
  1046. umo: protojson.UnmarshalOptions{AllowPartial: true},
  1047. inputMessage: &pb2.Requireds{},
  1048. inputText: `{
  1049. "reqBool": false,
  1050. "reqSfixed64": 42,
  1051. "reqString": "hello",
  1052. "reqEnum": "ONE"
  1053. }`,
  1054. wantMessage: &pb2.Requireds{
  1055. ReqBool: scalar.Bool(false),
  1056. ReqSfixed64: scalar.Int64(42),
  1057. ReqString: scalar.String("hello"),
  1058. ReqEnum: pb2.Enum_ONE.Enum(),
  1059. },
  1060. }, {
  1061. desc: "required fields all set",
  1062. inputMessage: &pb2.Requireds{},
  1063. inputText: `{
  1064. "reqBool": false,
  1065. "reqSfixed64": 42,
  1066. "reqDouble": 1.23,
  1067. "reqString": "hello",
  1068. "reqEnum": "ONE",
  1069. "reqNested": {}
  1070. }`,
  1071. wantMessage: &pb2.Requireds{
  1072. ReqBool: scalar.Bool(false),
  1073. ReqSfixed64: scalar.Int64(42),
  1074. ReqDouble: scalar.Float64(1.23),
  1075. ReqString: scalar.String("hello"),
  1076. ReqEnum: pb2.Enum_ONE.Enum(),
  1077. ReqNested: &pb2.Nested{},
  1078. },
  1079. }, {
  1080. desc: "indirect required field",
  1081. inputMessage: &pb2.IndirectRequired{},
  1082. inputText: `{
  1083. "optNested": {}
  1084. }`,
  1085. wantMessage: &pb2.IndirectRequired{
  1086. OptNested: &pb2.NestedWithRequired{},
  1087. },
  1088. wantErr: true,
  1089. }, {
  1090. desc: "indirect required field with AllowPartial",
  1091. umo: protojson.UnmarshalOptions{AllowPartial: true},
  1092. inputMessage: &pb2.IndirectRequired{},
  1093. inputText: `{
  1094. "optNested": {}
  1095. }`,
  1096. wantMessage: &pb2.IndirectRequired{
  1097. OptNested: &pb2.NestedWithRequired{},
  1098. },
  1099. }, {
  1100. desc: "indirect required field in repeated",
  1101. inputMessage: &pb2.IndirectRequired{},
  1102. inputText: `{
  1103. "rptNested": [
  1104. {"reqString": "one"},
  1105. {}
  1106. ]
  1107. }`,
  1108. wantMessage: &pb2.IndirectRequired{
  1109. RptNested: []*pb2.NestedWithRequired{
  1110. {
  1111. ReqString: scalar.String("one"),
  1112. },
  1113. {},
  1114. },
  1115. },
  1116. wantErr: true,
  1117. }, {
  1118. desc: "indirect required field in repeated with AllowPartial",
  1119. umo: protojson.UnmarshalOptions{AllowPartial: true},
  1120. inputMessage: &pb2.IndirectRequired{},
  1121. inputText: `{
  1122. "rptNested": [
  1123. {"reqString": "one"},
  1124. {}
  1125. ]
  1126. }`,
  1127. wantMessage: &pb2.IndirectRequired{
  1128. RptNested: []*pb2.NestedWithRequired{
  1129. {
  1130. ReqString: scalar.String("one"),
  1131. },
  1132. {},
  1133. },
  1134. },
  1135. }, {
  1136. desc: "indirect required field in map",
  1137. inputMessage: &pb2.IndirectRequired{},
  1138. inputText: `{
  1139. "strToNested": {
  1140. "missing": {},
  1141. "contains": {
  1142. "reqString": "here"
  1143. }
  1144. }
  1145. }`,
  1146. wantMessage: &pb2.IndirectRequired{
  1147. StrToNested: map[string]*pb2.NestedWithRequired{
  1148. "missing": &pb2.NestedWithRequired{},
  1149. "contains": &pb2.NestedWithRequired{
  1150. ReqString: scalar.String("here"),
  1151. },
  1152. },
  1153. },
  1154. wantErr: true,
  1155. }, {
  1156. desc: "indirect required field in map with AllowPartial",
  1157. umo: protojson.UnmarshalOptions{AllowPartial: true},
  1158. inputMessage: &pb2.IndirectRequired{},
  1159. inputText: `{
  1160. "strToNested": {
  1161. "missing": {},
  1162. "contains": {
  1163. "reqString": "here"
  1164. }
  1165. }
  1166. }`,
  1167. wantMessage: &pb2.IndirectRequired{
  1168. StrToNested: map[string]*pb2.NestedWithRequired{
  1169. "missing": &pb2.NestedWithRequired{},
  1170. "contains": &pb2.NestedWithRequired{
  1171. ReqString: scalar.String("here"),
  1172. },
  1173. },
  1174. },
  1175. }, {
  1176. desc: "indirect required field in oneof",
  1177. inputMessage: &pb2.IndirectRequired{},
  1178. inputText: `{
  1179. "oneofNested": {}
  1180. }`,
  1181. wantMessage: &pb2.IndirectRequired{
  1182. Union: &pb2.IndirectRequired_OneofNested{
  1183. OneofNested: &pb2.NestedWithRequired{},
  1184. },
  1185. },
  1186. wantErr: true,
  1187. }, {
  1188. desc: "indirect required field in oneof with AllowPartial",
  1189. umo: protojson.UnmarshalOptions{AllowPartial: true},
  1190. inputMessage: &pb2.IndirectRequired{},
  1191. inputText: `{
  1192. "oneofNested": {}
  1193. }`,
  1194. wantMessage: &pb2.IndirectRequired{
  1195. Union: &pb2.IndirectRequired_OneofNested{
  1196. OneofNested: &pb2.NestedWithRequired{},
  1197. },
  1198. },
  1199. }, {
  1200. desc: "extensions of non-repeated fields",
  1201. inputMessage: &pb2.Extensions{},
  1202. inputText: `{
  1203. "optString": "non-extension field",
  1204. "optBool": true,
  1205. "optInt32": 42,
  1206. "[pb2.opt_ext_bool]": true,
  1207. "[pb2.opt_ext_nested]": {
  1208. "optString": "nested in an extension",
  1209. "optNested": {
  1210. "optString": "another nested in an extension"
  1211. }
  1212. },
  1213. "[pb2.opt_ext_string]": "extension field",
  1214. "[pb2.opt_ext_enum]": "TEN"
  1215. }`,
  1216. wantMessage: func() proto.Message {
  1217. m := &pb2.Extensions{
  1218. OptString: scalar.String("non-extension field"),
  1219. OptBool: scalar.Bool(true),
  1220. OptInt32: scalar.Int32(42),
  1221. }
  1222. setExtension(m, pb2.E_OptExtBool, true)
  1223. setExtension(m, pb2.E_OptExtString, "extension field")
  1224. setExtension(m, pb2.E_OptExtEnum, pb2.Enum_TEN)
  1225. setExtension(m, pb2.E_OptExtNested, &pb2.Nested{
  1226. OptString: scalar.String("nested in an extension"),
  1227. OptNested: &pb2.Nested{
  1228. OptString: scalar.String("another nested in an extension"),
  1229. },
  1230. })
  1231. return m
  1232. }(),
  1233. }, {
  1234. desc: "extensions of repeated fields",
  1235. inputMessage: &pb2.Extensions{},
  1236. inputText: `{
  1237. "[pb2.rpt_ext_enum]": ["TEN", 101, "ONE"],
  1238. "[pb2.rpt_ext_fixed32]": [42, 47],
  1239. "[pb2.rpt_ext_nested]": [
  1240. {"optString": "one"},
  1241. {"optString": "two"},
  1242. {"optString": "three"}
  1243. ]
  1244. }`,
  1245. wantMessage: func() proto.Message {
  1246. m := &pb2.Extensions{}
  1247. setExtension(m, pb2.E_RptExtEnum, &[]pb2.Enum{pb2.Enum_TEN, 101, pb2.Enum_ONE})
  1248. setExtension(m, pb2.E_RptExtFixed32, &[]uint32{42, 47})
  1249. setExtension(m, pb2.E_RptExtNested, &[]*pb2.Nested{
  1250. &pb2.Nested{OptString: scalar.String("one")},
  1251. &pb2.Nested{OptString: scalar.String("two")},
  1252. &pb2.Nested{OptString: scalar.String("three")},
  1253. })
  1254. return m
  1255. }(),
  1256. }, {
  1257. desc: "extensions of non-repeated fields in another message",
  1258. inputMessage: &pb2.Extensions{},
  1259. inputText: `{
  1260. "[pb2.ExtensionsContainer.opt_ext_bool]": true,
  1261. "[pb2.ExtensionsContainer.opt_ext_enum]": "TEN",
  1262. "[pb2.ExtensionsContainer.opt_ext_nested]": {
  1263. "optString": "nested in an extension",
  1264. "optNested": {
  1265. "optString": "another nested in an extension"
  1266. }
  1267. },
  1268. "[pb2.ExtensionsContainer.opt_ext_string]": "extension field"
  1269. }`,
  1270. wantMessage: func() proto.Message {
  1271. m := &pb2.Extensions{}
  1272. setExtension(m, pb2.E_ExtensionsContainer_OptExtBool, true)
  1273. setExtension(m, pb2.E_ExtensionsContainer_OptExtString, "extension field")
  1274. setExtension(m, pb2.E_ExtensionsContainer_OptExtEnum, pb2.Enum_TEN)
  1275. setExtension(m, pb2.E_ExtensionsContainer_OptExtNested, &pb2.Nested{
  1276. OptString: scalar.String("nested in an extension"),
  1277. OptNested: &pb2.Nested{
  1278. OptString: scalar.String("another nested in an extension"),
  1279. },
  1280. })
  1281. return m
  1282. }(),
  1283. }, {
  1284. desc: "extensions of repeated fields in another message",
  1285. inputMessage: &pb2.Extensions{},
  1286. inputText: `{
  1287. "optString": "non-extension field",
  1288. "optBool": true,
  1289. "optInt32": 42,
  1290. "[pb2.ExtensionsContainer.rpt_ext_nested]": [
  1291. {"optString": "one"},
  1292. {"optString": "two"},
  1293. {"optString": "three"}
  1294. ],
  1295. "[pb2.ExtensionsContainer.rpt_ext_enum]": ["TEN", 101, "ONE"],
  1296. "[pb2.ExtensionsContainer.rpt_ext_string]": ["hello", "world"]
  1297. }`,
  1298. wantMessage: func() proto.Message {
  1299. m := &pb2.Extensions{
  1300. OptString: scalar.String("non-extension field"),
  1301. OptBool: scalar.Bool(true),
  1302. OptInt32: scalar.Int32(42),
  1303. }
  1304. setExtension(m, pb2.E_ExtensionsContainer_RptExtEnum, &[]pb2.Enum{pb2.Enum_TEN, 101, pb2.Enum_ONE})
  1305. setExtension(m, pb2.E_ExtensionsContainer_RptExtString, &[]string{"hello", "world"})
  1306. setExtension(m, pb2.E_ExtensionsContainer_RptExtNested, &[]*pb2.Nested{
  1307. &pb2.Nested{OptString: scalar.String("one")},
  1308. &pb2.Nested{OptString: scalar.String("two")},
  1309. &pb2.Nested{OptString: scalar.String("three")},
  1310. })
  1311. return m
  1312. }(),
  1313. }, {
  1314. desc: "invalid extension field name",
  1315. inputMessage: &pb2.Extensions{},
  1316. inputText: `{ "[pb2.invalid_message_field]": true }`,
  1317. wantErr: true,
  1318. }, {
  1319. desc: "MessageSet",
  1320. inputMessage: &pb2.MessageSet{},
  1321. inputText: `{
  1322. "[pb2.MessageSetExtension]": {
  1323. "optString": "a messageset extension"
  1324. },
  1325. "[pb2.MessageSetExtension.ext_nested]": {
  1326. "optString": "just a regular extension"
  1327. },
  1328. "[pb2.MessageSetExtension.not_message_set_extension]": {
  1329. "optString": "not a messageset extension"
  1330. }
  1331. }`,
  1332. wantMessage: func() proto.Message {
  1333. m := &pb2.MessageSet{}
  1334. setExtension(m, pb2.E_MessageSetExtension_MessageSetExtension, &pb2.MessageSetExtension{
  1335. OptString: scalar.String("a messageset extension"),
  1336. })
  1337. setExtension(m, pb2.E_MessageSetExtension_NotMessageSetExtension, &pb2.MessageSetExtension{
  1338. OptString: scalar.String("not a messageset extension"),
  1339. })
  1340. setExtension(m, pb2.E_MessageSetExtension_ExtNested, &pb2.Nested{
  1341. OptString: scalar.String("just a regular extension"),
  1342. })
  1343. return m
  1344. }(),
  1345. }, {
  1346. desc: "extensions of repeated field contains null",
  1347. inputMessage: &pb2.Extensions{},
  1348. inputText: `{
  1349. "[pb2.ExtensionsContainer.rpt_ext_nested]": [
  1350. {"optString": "one"},
  1351. null,
  1352. {"optString": "three"}
  1353. ],
  1354. }`,
  1355. wantErr: true,
  1356. }, {
  1357. desc: "not real MessageSet 1",
  1358. inputMessage: &pb2.FakeMessageSet{},
  1359. inputText: `{
  1360. "[pb2.FakeMessageSetExtension.message_set_extension]": {
  1361. "optString": "not a messageset extension"
  1362. }
  1363. }`,
  1364. wantMessage: func() proto.Message {
  1365. m := &pb2.FakeMessageSet{}
  1366. setExtension(m, pb2.E_FakeMessageSetExtension_MessageSetExtension, &pb2.FakeMessageSetExtension{
  1367. OptString: scalar.String("not a messageset extension"),
  1368. })
  1369. return m
  1370. }(),
  1371. }, {
  1372. desc: "not real MessageSet 2",
  1373. inputMessage: &pb2.FakeMessageSet{},
  1374. inputText: `{
  1375. "[pb2.FakeMessageSetExtension]": {
  1376. "optString": "not a messageset extension"
  1377. }
  1378. }`,
  1379. wantErr: true,
  1380. }, {
  1381. desc: "not real MessageSet 3",
  1382. inputMessage: &pb2.MessageSet{},
  1383. inputText: `{
  1384. "[pb2.message_set_extension]": {
  1385. "optString": "another not a messageset extension"
  1386. }
  1387. }`,
  1388. wantMessage: func() proto.Message {
  1389. m := &pb2.MessageSet{}
  1390. setExtension(m, pb2.E_MessageSetExtension, &pb2.FakeMessageSetExtension{
  1391. OptString: scalar.String("another not a messageset extension"),
  1392. })
  1393. return m
  1394. }(),
  1395. }, {
  1396. desc: "Empty",
  1397. inputMessage: &emptypb.Empty{},
  1398. inputText: `{}`,
  1399. wantMessage: &emptypb.Empty{},
  1400. }, {
  1401. desc: "Empty contains unknown",
  1402. inputMessage: &emptypb.Empty{},
  1403. inputText: `{"unknown": null}`,
  1404. wantErr: true,
  1405. }, {
  1406. desc: "BoolValue false",
  1407. inputMessage: &wrapperspb.BoolValue{},
  1408. inputText: `false`,
  1409. wantMessage: &wrapperspb.BoolValue{},
  1410. }, {
  1411. desc: "BoolValue true",
  1412. inputMessage: &wrapperspb.BoolValue{},
  1413. inputText: `true`,
  1414. wantMessage: &wrapperspb.BoolValue{Value: true},
  1415. }, {
  1416. desc: "BoolValue invalid value",
  1417. inputMessage: &wrapperspb.BoolValue{},
  1418. inputText: `{}`,
  1419. wantErr: true,
  1420. }, {
  1421. desc: "Int32Value",
  1422. inputMessage: &wrapperspb.Int32Value{},
  1423. inputText: `42`,
  1424. wantMessage: &wrapperspb.Int32Value{Value: 42},
  1425. }, {
  1426. desc: "Int32Value in JSON string",
  1427. inputMessage: &wrapperspb.Int32Value{},
  1428. inputText: `"1.23e3"`,
  1429. wantMessage: &wrapperspb.Int32Value{Value: 1230},
  1430. }, {
  1431. desc: "Int64Value",
  1432. inputMessage: &wrapperspb.Int64Value{},
  1433. inputText: `"42"`,
  1434. wantMessage: &wrapperspb.Int64Value{Value: 42},
  1435. }, {
  1436. desc: "UInt32Value",
  1437. inputMessage: &wrapperspb.UInt32Value{},
  1438. inputText: `42`,
  1439. wantMessage: &wrapperspb.UInt32Value{Value: 42},
  1440. }, {
  1441. desc: "UInt64Value",
  1442. inputMessage: &wrapperspb.UInt64Value{},
  1443. inputText: `"42"`,
  1444. wantMessage: &wrapperspb.UInt64Value{Value: 42},
  1445. }, {
  1446. desc: "FloatValue",
  1447. inputMessage: &wrapperspb.FloatValue{},
  1448. inputText: `1.02`,
  1449. wantMessage: &wrapperspb.FloatValue{Value: 1.02},
  1450. }, {
  1451. desc: "FloatValue exceeds max limit",
  1452. inputMessage: &wrapperspb.FloatValue{},
  1453. inputText: `1.23+40`,
  1454. wantErr: true,
  1455. }, {
  1456. desc: "FloatValue Infinity",
  1457. inputMessage: &wrapperspb.FloatValue{},
  1458. inputText: `"-Infinity"`,
  1459. wantMessage: &wrapperspb.FloatValue{Value: float32(math.Inf(-1))},
  1460. }, {
  1461. desc: "DoubleValue",
  1462. inputMessage: &wrapperspb.DoubleValue{},
  1463. inputText: `1.02`,
  1464. wantMessage: &wrapperspb.DoubleValue{Value: 1.02},
  1465. }, {
  1466. desc: "DoubleValue Infinity",
  1467. inputMessage: &wrapperspb.DoubleValue{},
  1468. inputText: `"Infinity"`,
  1469. wantMessage: &wrapperspb.DoubleValue{Value: math.Inf(+1)},
  1470. }, {
  1471. desc: "StringValue empty",
  1472. inputMessage: &wrapperspb.StringValue{},
  1473. inputText: `""`,
  1474. wantMessage: &wrapperspb.StringValue{},
  1475. }, {
  1476. desc: "StringValue",
  1477. inputMessage: &wrapperspb.StringValue{},
  1478. inputText: `"谷歌"`,
  1479. wantMessage: &wrapperspb.StringValue{Value: "谷歌"},
  1480. }, {
  1481. desc: "StringValue with invalid UTF8 error",
  1482. inputMessage: &wrapperspb.StringValue{},
  1483. inputText: "\"abc\xff\"",
  1484. wantErr: true,
  1485. }, {
  1486. desc: "StringValue field with invalid UTF8 error",
  1487. inputMessage: &pb2.KnownTypes{},
  1488. inputText: "{\n \"optString\": \"abc\xff\"\n}",
  1489. wantErr: true,
  1490. }, {
  1491. desc: "NullValue field with JSON null",
  1492. inputMessage: &pb2.KnownTypes{},
  1493. inputText: `{
  1494. "optNull": null
  1495. }`,
  1496. wantMessage: &pb2.KnownTypes{OptNull: new(structpb.NullValue)},
  1497. }, {
  1498. desc: "NullValue field with string",
  1499. inputMessage: &pb2.KnownTypes{},
  1500. inputText: `{
  1501. "optNull": "NULL_VALUE"
  1502. }`,
  1503. wantMessage: &pb2.KnownTypes{OptNull: new(structpb.NullValue)},
  1504. }, {
  1505. desc: "BytesValue",
  1506. inputMessage: &wrapperspb.BytesValue{},
  1507. inputText: `"aGVsbG8="`,
  1508. wantMessage: &wrapperspb.BytesValue{Value: []byte("hello")},
  1509. }, {
  1510. desc: "Value null",
  1511. inputMessage: &structpb.Value{},
  1512. inputText: `null`,
  1513. wantMessage: &structpb.Value{Kind: &structpb.Value_NullValue{}},
  1514. }, {
  1515. desc: "Value field null",
  1516. inputMessage: &pb2.KnownTypes{},
  1517. inputText: `{
  1518. "optValue": null
  1519. }`,
  1520. wantMessage: &pb2.KnownTypes{
  1521. OptValue: &structpb.Value{Kind: &structpb.Value_NullValue{}},
  1522. },
  1523. }, {
  1524. desc: "Value bool",
  1525. inputMessage: &structpb.Value{},
  1526. inputText: `false`,
  1527. wantMessage: &structpb.Value{Kind: &structpb.Value_BoolValue{}},
  1528. }, {
  1529. desc: "Value field bool",
  1530. inputMessage: &pb2.KnownTypes{},
  1531. inputText: `{
  1532. "optValue": true
  1533. }`,
  1534. wantMessage: &pb2.KnownTypes{
  1535. OptValue: &structpb.Value{Kind: &structpb.Value_BoolValue{true}},
  1536. },
  1537. }, {
  1538. desc: "Value number",
  1539. inputMessage: &structpb.Value{},
  1540. inputText: `1.02`,
  1541. wantMessage: &structpb.Value{Kind: &structpb.Value_NumberValue{1.02}},
  1542. }, {
  1543. desc: "Value field number",
  1544. inputMessage: &pb2.KnownTypes{},
  1545. inputText: `{
  1546. "optValue": 1.02
  1547. }`,
  1548. wantMessage: &pb2.KnownTypes{
  1549. OptValue: &structpb.Value{Kind: &structpb.Value_NumberValue{1.02}},
  1550. },
  1551. }, {
  1552. desc: "Value string",
  1553. inputMessage: &structpb.Value{},
  1554. inputText: `"hello"`,
  1555. wantMessage: &structpb.Value{Kind: &structpb.Value_StringValue{"hello"}},
  1556. }, {
  1557. desc: "Value string with invalid UTF8",
  1558. inputMessage: &structpb.Value{},
  1559. inputText: "\"\xff\"",
  1560. wantErr: true,
  1561. }, {
  1562. desc: "Value field string",
  1563. inputMessage: &pb2.KnownTypes{},
  1564. inputText: `{
  1565. "optValue": "NaN"
  1566. }`,
  1567. wantMessage: &pb2.KnownTypes{
  1568. OptValue: &structpb.Value{Kind: &structpb.Value_StringValue{"NaN"}},
  1569. },
  1570. }, {
  1571. desc: "Value field string with invalid UTF8",
  1572. inputMessage: &pb2.KnownTypes{},
  1573. inputText: `{
  1574. "optValue": "` + "\xff" + `"
  1575. }`,
  1576. wantErr: true,
  1577. }, {
  1578. desc: "Value empty struct",
  1579. inputMessage: &structpb.Value{},
  1580. inputText: `{}`,
  1581. wantMessage: &structpb.Value{
  1582. Kind: &structpb.Value_StructValue{
  1583. &structpb.Struct{Fields: map[string]*structpb.Value{}},
  1584. },
  1585. },
  1586. }, {
  1587. desc: "Value struct",
  1588. inputMessage: &structpb.Value{},
  1589. inputText: `{
  1590. "string": "hello",
  1591. "number": 123,
  1592. "null": null,
  1593. "bool": false,
  1594. "struct": {
  1595. "string": "world"
  1596. },
  1597. "list": []
  1598. }`,
  1599. wantMessage: &structpb.Value{
  1600. Kind: &structpb.Value_StructValue{
  1601. &structpb.Struct{
  1602. Fields: map[string]*structpb.Value{
  1603. "string": {Kind: &structpb.Value_StringValue{"hello"}},
  1604. "number": {Kind: &structpb.Value_NumberValue{123}},
  1605. "null": {Kind: &structpb.Value_NullValue{}},
  1606. "bool": {Kind: &structpb.Value_BoolValue{false}},
  1607. "struct": {
  1608. Kind: &structpb.Value_StructValue{
  1609. &structpb.Struct{
  1610. Fields: map[string]*structpb.Value{
  1611. "string": {Kind: &structpb.Value_StringValue{"world"}},
  1612. },
  1613. },
  1614. },
  1615. },
  1616. "list": {
  1617. Kind: &structpb.Value_ListValue{&structpb.ListValue{}},
  1618. },
  1619. },
  1620. },
  1621. },
  1622. },
  1623. }, {
  1624. desc: "Value struct with invalid UTF8 string",
  1625. inputMessage: &structpb.Value{},
  1626. inputText: "{\"string\": \"abc\xff\"}",
  1627. wantErr: true,
  1628. }, {
  1629. desc: "Value field struct",
  1630. inputMessage: &pb2.KnownTypes{},
  1631. inputText: `{
  1632. "optValue": {
  1633. "string": "hello"
  1634. }
  1635. }`,
  1636. wantMessage: &pb2.KnownTypes{
  1637. OptValue: &structpb.Value{
  1638. Kind: &structpb.Value_StructValue{
  1639. &structpb.Struct{
  1640. Fields: map[string]*structpb.Value{
  1641. "string": {Kind: &structpb.Value_StringValue{"hello"}},
  1642. },
  1643. },
  1644. },
  1645. },
  1646. },
  1647. }, {
  1648. desc: "Value empty list",
  1649. inputMessage: &structpb.Value{},
  1650. inputText: `[]`,
  1651. wantMessage: &structpb.Value{
  1652. Kind: &structpb.Value_ListValue{
  1653. &structpb.ListValue{Values: []*structpb.Value{}},
  1654. },
  1655. },
  1656. }, {
  1657. desc: "Value list",
  1658. inputMessage: &structpb.Value{},
  1659. inputText: `[
  1660. "string",
  1661. 123,
  1662. null,
  1663. true,
  1664. {},
  1665. [
  1666. "string",
  1667. 1.23,
  1668. null,
  1669. false
  1670. ]
  1671. ]`,
  1672. wantMessage: &structpb.Value{
  1673. Kind: &structpb.Value_ListValue{
  1674. &structpb.ListValue{
  1675. Values: []*structpb.Value{
  1676. {Kind: &structpb.Value_StringValue{"string"}},
  1677. {Kind: &structpb.Value_NumberValue{123}},
  1678. {Kind: &structpb.Value_NullValue{}},
  1679. {Kind: &structpb.Value_BoolValue{true}},
  1680. {Kind: &structpb.Value_StructValue{&structpb.Struct{}}},
  1681. {
  1682. Kind: &structpb.Value_ListValue{
  1683. &structpb.ListValue{
  1684. Values: []*structpb.Value{
  1685. {Kind: &structpb.Value_StringValue{"string"}},
  1686. {Kind: &structpb.Value_NumberValue{1.23}},
  1687. {Kind: &structpb.Value_NullValue{}},
  1688. {Kind: &structpb.Value_BoolValue{false}},
  1689. },
  1690. },
  1691. },
  1692. },
  1693. },
  1694. },
  1695. },
  1696. },
  1697. }, {
  1698. desc: "Value list with invalid UTF8 string",
  1699. inputMessage: &structpb.Value{},
  1700. inputText: "[\"abc\xff\"]",
  1701. wantErr: true,
  1702. }, {
  1703. desc: "Value field list with invalid UTF8 string",
  1704. inputMessage: &pb2.KnownTypes{},
  1705. inputText: `{
  1706. "optValue": [ "` + "abc\xff" + `"]
  1707. }`,
  1708. wantErr: true,
  1709. }, {
  1710. desc: "Duration empty string",
  1711. inputMessage: &durationpb.Duration{},
  1712. inputText: `""`,
  1713. wantErr: true,
  1714. }, {
  1715. desc: "Duration with secs",
  1716. inputMessage: &durationpb.Duration{},
  1717. inputText: `"3s"`,
  1718. wantMessage: &durationpb.Duration{Seconds: 3},
  1719. }, {
  1720. desc: "Duration with escaped unicode",
  1721. inputMessage: &durationpb.Duration{},
  1722. inputText: `"\u0033s"`,
  1723. wantMessage: &durationpb.Duration{Seconds: 3},
  1724. }, {
  1725. desc: "Duration with -secs",
  1726. inputMessage: &durationpb.Duration{},
  1727. inputText: `"-3s"`,
  1728. wantMessage: &durationpb.Duration{Seconds: -3},
  1729. }, {
  1730. desc: "Duration with plus sign",
  1731. inputMessage: &durationpb.Duration{},
  1732. inputText: `"+3s"`,
  1733. wantMessage: &durationpb.Duration{Seconds: 3},
  1734. }, {
  1735. desc: "Duration with nanos",
  1736. inputMessage: &durationpb.Duration{},
  1737. inputText: `"0.001s"`,
  1738. wantMessage: &durationpb.Duration{Nanos: 1e6},
  1739. }, {
  1740. desc: "Duration with -nanos",
  1741. inputMessage: &durationpb.Duration{},
  1742. inputText: `"-0.001s"`,
  1743. wantMessage: &durationpb.Duration{Nanos: -1e6},
  1744. }, {
  1745. desc: "Duration with -nanos",
  1746. inputMessage: &durationpb.Duration{},
  1747. inputText: `"-.001s"`,
  1748. wantMessage: &durationpb.Duration{Nanos: -1e6},
  1749. }, {
  1750. desc: "Duration with +nanos",
  1751. inputMessage: &durationpb.Duration{},
  1752. inputText: `"+.001s"`,
  1753. wantMessage: &durationpb.Duration{Nanos: 1e6},
  1754. }, {
  1755. desc: "Duration with -secs -nanos",
  1756. inputMessage: &durationpb.Duration{},
  1757. inputText: `"-123.000000450s"`,
  1758. wantMessage: &durationpb.Duration{Seconds: -123, Nanos: -450},
  1759. }, {
  1760. desc: "Duration with large secs",
  1761. inputMessage: &durationpb.Duration{},
  1762. inputText: `"10000000000.000000001s"`,
  1763. wantMessage: &durationpb.Duration{Seconds: 1e10, Nanos: 1},
  1764. }, {
  1765. desc: "Duration with decimal without fractional",
  1766. inputMessage: &durationpb.Duration{},
  1767. inputText: `"3.s"`,
  1768. wantMessage: &durationpb.Duration{Seconds: 3},
  1769. }, {
  1770. desc: "Duration with decimal without integer",
  1771. inputMessage: &durationpb.Duration{},
  1772. inputText: `"0.5s"`,
  1773. wantMessage: &durationpb.Duration{Nanos: 5e8},
  1774. }, {
  1775. desc: "Duration max value",
  1776. inputMessage: &durationpb.Duration{},
  1777. inputText: `"315576000000.999999999s"`,
  1778. wantMessage: &durationpb.Duration{Seconds: 315576000000, Nanos: 999999999},
  1779. }, {
  1780. desc: "Duration min value",
  1781. inputMessage: &durationpb.Duration{},
  1782. inputText: `"-315576000000.999999999s"`,
  1783. wantMessage: &durationpb.Duration{Seconds: -315576000000, Nanos: -999999999},
  1784. }, {
  1785. desc: "Duration with +secs out of range",
  1786. inputMessage: &durationpb.Duration{},
  1787. inputText: `"315576000001s"`,
  1788. wantErr: true,
  1789. }, {
  1790. desc: "Duration with -secs out of range",
  1791. inputMessage: &durationpb.Duration{},
  1792. inputText: `"-315576000001s"`,
  1793. wantErr: true,
  1794. }, {
  1795. desc: "Duration with nanos beyond 9 digits",
  1796. inputMessage: &durationpb.Duration{},
  1797. inputText: `"0.1000000000s"`,
  1798. wantErr: true,
  1799. }, {
  1800. desc: "Duration without suffix s",
  1801. inputMessage: &durationpb.Duration{},
  1802. inputText: `"123"`,
  1803. wantErr: true,
  1804. }, {
  1805. desc: "Duration invalid signed fraction",
  1806. inputMessage: &durationpb.Duration{},
  1807. inputText: `"123.+123s"`,
  1808. wantErr: true,
  1809. }, {
  1810. desc: "Duration invalid multiple .",
  1811. inputMessage: &durationpb.Duration{},
  1812. inputText: `"123.123.s"`,
  1813. wantErr: true,
  1814. }, {
  1815. desc: "Duration invalid integer",
  1816. inputMessage: &durationpb.Duration{},
  1817. inputText: `"01s"`,
  1818. wantErr: true,
  1819. }, {
  1820. desc: "Timestamp zero",
  1821. inputMessage: &timestamppb.Timestamp{},
  1822. inputText: `"1970-01-01T00:00:00Z"`,
  1823. wantMessage: &timestamppb.Timestamp{},
  1824. }, {
  1825. desc: "Timestamp with tz adjustment",
  1826. inputMessage: &timestamppb.Timestamp{},
  1827. inputText: `"1970-01-01T00:00:00+01:00"`,
  1828. wantMessage: &timestamppb.Timestamp{Seconds: -3600},
  1829. }, {
  1830. desc: "Timestamp UTC",
  1831. inputMessage: &timestamppb.Timestamp{},
  1832. inputText: `"2019-03-19T23:03:21Z"`,
  1833. wantMessage: &timestamppb.Timestamp{Seconds: 1553036601},
  1834. }, {
  1835. desc: "Timestamp with escaped unicode",
  1836. inputMessage: &timestamppb.Timestamp{},
  1837. inputText: `"2019-0\u0033-19T23:03:21Z"`,
  1838. wantMessage: &timestamppb.Timestamp{Seconds: 1553036601},
  1839. }, {
  1840. desc: "Timestamp with nanos",
  1841. inputMessage: &timestamppb.Timestamp{},
  1842. inputText: `"2019-03-19T23:03:21.000000001Z"`,
  1843. wantMessage: &timestamppb.Timestamp{Seconds: 1553036601, Nanos: 1},
  1844. }, {
  1845. desc: "Timestamp max value",
  1846. inputMessage: &timestamppb.Timestamp{},
  1847. inputText: `"9999-12-31T23:59:59.999999999Z"`,
  1848. wantMessage: &timestamppb.Timestamp{Seconds: 253402300799, Nanos: 999999999},
  1849. }, {
  1850. desc: "Timestamp above max value",
  1851. inputMessage: &timestamppb.Timestamp{},
  1852. inputText: `"9999-12-31T23:59:59-01:00"`,
  1853. wantErr: true,
  1854. }, {
  1855. desc: "Timestamp min value",
  1856. inputMessage: &timestamppb.Timestamp{},
  1857. inputText: `"0001-01-01T00:00:00Z"`,
  1858. wantMessage: &timestamppb.Timestamp{Seconds: -62135596800},
  1859. }, {
  1860. desc: "Timestamp below min value",
  1861. inputMessage: &timestamppb.Timestamp{},
  1862. inputText: `"0001-01-01T00:00:00+01:00"`,
  1863. wantErr: true,
  1864. }, {
  1865. desc: "Timestamp with nanos beyond 9 digits",
  1866. inputMessage: &timestamppb.Timestamp{},
  1867. inputText: `"1970-01-01T00:00:00.0000000001Z"`,
  1868. wantErr: true,
  1869. }, {
  1870. desc: "FieldMask empty",
  1871. inputMessage: &fieldmaskpb.FieldMask{},
  1872. inputText: `""`,
  1873. wantMessage: &fieldmaskpb.FieldMask{Paths: []string{}},
  1874. }, {
  1875. desc: "FieldMask",
  1876. inputMessage: &fieldmaskpb.FieldMask{},
  1877. inputText: `"foo,fooBar , foo.barQux ,Foo"`,
  1878. wantMessage: &fieldmaskpb.FieldMask{
  1879. Paths: []string{
  1880. "foo",
  1881. "foo_bar",
  1882. "foo.bar_qux",
  1883. "_foo",
  1884. },
  1885. },
  1886. }, {
  1887. desc: "FieldMask field",
  1888. inputMessage: &pb2.KnownTypes{},
  1889. inputText: `{
  1890. "optFieldmask": "foo, qux.fooBar"
  1891. }`,
  1892. wantMessage: &pb2.KnownTypes{
  1893. OptFieldmask: &fieldmaskpb.FieldMask{
  1894. Paths: []string{
  1895. "foo",
  1896. "qux.foo_bar",
  1897. },
  1898. },
  1899. },
  1900. }, {
  1901. desc: "Any empty",
  1902. inputMessage: &anypb.Any{},
  1903. inputText: `{}`,
  1904. wantMessage: &anypb.Any{},
  1905. }, {
  1906. desc: "Any with non-custom message",
  1907. umo: protojson.UnmarshalOptions{
  1908. Resolver: preg.NewTypes(pimpl.Export{}.MessageTypeOf(&pb2.Nested{})),
  1909. },
  1910. inputMessage: &anypb.Any{},
  1911. inputText: `{
  1912. "@type": "foo/pb2.Nested",
  1913. "optString": "embedded inside Any",
  1914. "optNested": {
  1915. "optString": "inception"
  1916. }
  1917. }`,
  1918. wantMessage: func() proto.Message {
  1919. m := &pb2.Nested{
  1920. OptString: scalar.String("embedded inside Any"),
  1921. OptNested: &pb2.Nested{
  1922. OptString: scalar.String("inception"),
  1923. },
  1924. }
  1925. b, err := proto.MarshalOptions{Deterministic: true}.Marshal(m)
  1926. if err != nil {
  1927. t.Fatalf("error in binary marshaling message for Any.value: %v", err)
  1928. }
  1929. return &anypb.Any{
  1930. TypeUrl: "foo/pb2.Nested",
  1931. Value: b,
  1932. }
  1933. }(),
  1934. }, {
  1935. desc: "Any with empty embedded message",
  1936. umo: protojson.UnmarshalOptions{
  1937. Resolver: preg.NewTypes(pimpl.Export{}.MessageTypeOf(&pb2.Nested{})),
  1938. },
  1939. inputMessage: &anypb.Any{},
  1940. inputText: `{"@type": "foo/pb2.Nested"}`,
  1941. wantMessage: &anypb.Any{TypeUrl: "foo/pb2.Nested"},
  1942. }, {
  1943. desc: "Any without registered type",
  1944. umo: protojson.UnmarshalOptions{Resolver: preg.NewTypes()},
  1945. inputMessage: &anypb.Any{},
  1946. inputText: `{"@type": "foo/pb2.Nested"}`,
  1947. wantErr: true,
  1948. }, {
  1949. desc: "Any with missing required",
  1950. umo: protojson.UnmarshalOptions{
  1951. Resolver: preg.NewTypes(pimpl.Export{}.MessageTypeOf(&pb2.PartialRequired{})),
  1952. },
  1953. inputMessage: &anypb.Any{},
  1954. inputText: `{
  1955. "@type": "pb2.PartialRequired",
  1956. "optString": "embedded inside Any"
  1957. }`,
  1958. wantMessage: func() proto.Message {
  1959. m := &pb2.PartialRequired{
  1960. OptString: scalar.String("embedded inside Any"),
  1961. }
  1962. b, err := proto.MarshalOptions{
  1963. Deterministic: true,
  1964. AllowPartial: true,
  1965. }.Marshal(m)
  1966. if err != nil {
  1967. t.Fatalf("error in binary marshaling message for Any.value: %v", err)
  1968. }
  1969. return &anypb.Any{
  1970. TypeUrl: string(m.ProtoReflect().Descriptor().FullName()),
  1971. Value: b,
  1972. }
  1973. }(),
  1974. }, {
  1975. desc: "Any with partial required and AllowPartial",
  1976. umo: protojson.UnmarshalOptions{
  1977. AllowPartial: true,
  1978. Resolver: preg.NewTypes(pimpl.Export{}.MessageTypeOf(&pb2.PartialRequired{})),
  1979. },
  1980. inputMessage: &anypb.Any{},
  1981. inputText: `{
  1982. "@type": "pb2.PartialRequired",
  1983. "optString": "embedded inside Any"
  1984. }`,
  1985. wantMessage: func() proto.Message {
  1986. m := &pb2.PartialRequired{
  1987. OptString: scalar.String("embedded inside Any"),
  1988. }
  1989. b, err := proto.MarshalOptions{
  1990. Deterministic: true,
  1991. AllowPartial: true,
  1992. }.Marshal(m)
  1993. if err != nil {
  1994. t.Fatalf("error in binary marshaling message for Any.value: %v", err)
  1995. }
  1996. return &anypb.Any{
  1997. TypeUrl: string(m.ProtoReflect().Descriptor().FullName()),
  1998. Value: b,
  1999. }
  2000. }(),
  2001. }, {
  2002. desc: "Any with invalid UTF8",
  2003. umo: protojson.UnmarshalOptions{
  2004. Resolver: preg.NewTypes(pimpl.Export{}.MessageTypeOf(&pb2.Nested{})),
  2005. },
  2006. inputMessage: &anypb.Any{},
  2007. inputText: `{
  2008. "optString": "` + "abc\xff" + `",
  2009. "@type": "foo/pb2.Nested"
  2010. }`,
  2011. wantErr: true,
  2012. }, {
  2013. desc: "Any with BoolValue",
  2014. umo: protojson.UnmarshalOptions{
  2015. Resolver: preg.NewTypes(pimpl.Export{}.MessageTypeOf(&wrapperspb.BoolValue{})),
  2016. },
  2017. inputMessage: &anypb.Any{},
  2018. inputText: `{
  2019. "@type": "type.googleapis.com/google.protobuf.BoolValue",
  2020. "value": true
  2021. }`,
  2022. wantMessage: func() proto.Message {
  2023. m := &wrapperspb.BoolValue{Value: true}
  2024. b, err := proto.MarshalOptions{Deterministic: true}.Marshal(m)
  2025. if err != nil {
  2026. t.Fatalf("error in binary marshaling message for Any.value: %v", err)
  2027. }
  2028. return &anypb.Any{
  2029. TypeUrl: "type.googleapis.com/google.protobuf.BoolValue",
  2030. Value: b,
  2031. }
  2032. }(),
  2033. }, {
  2034. desc: "Any with Empty",
  2035. umo: protojson.UnmarshalOptions{
  2036. Resolver: preg.NewTypes(pimpl.Export{}.MessageTypeOf(&emptypb.Empty{})),
  2037. },
  2038. inputMessage: &anypb.Any{},
  2039. inputText: `{
  2040. "value": {},
  2041. "@type": "type.googleapis.com/google.protobuf.Empty"
  2042. }`,
  2043. wantMessage: &anypb.Any{
  2044. TypeUrl: "type.googleapis.com/google.protobuf.Empty",
  2045. },
  2046. }, {
  2047. desc: "Any with missing Empty",
  2048. umo: protojson.UnmarshalOptions{
  2049. Resolver: preg.NewTypes(pimpl.Export{}.MessageTypeOf(&emptypb.Empty{})),
  2050. },
  2051. inputMessage: &anypb.Any{},
  2052. inputText: `{
  2053. "@type": "type.googleapis.com/google.protobuf.Empty"
  2054. }`,
  2055. wantErr: true,
  2056. }, {
  2057. desc: "Any with StringValue containing invalid UTF8",
  2058. umo: protojson.UnmarshalOptions{
  2059. Resolver: preg.NewTypes(pimpl.Export{}.MessageTypeOf(&wrapperspb.StringValue{})),
  2060. },
  2061. inputMessage: &anypb.Any{},
  2062. inputText: `{
  2063. "@type": "google.protobuf.StringValue",
  2064. "value": "` + "abc\xff" + `"
  2065. }`,
  2066. wantErr: true,
  2067. }, {
  2068. desc: "Any with Int64Value",
  2069. umo: protojson.UnmarshalOptions{
  2070. Resolver: preg.NewTypes(pimpl.Export{}.MessageTypeOf(&wrapperspb.Int64Value{})),
  2071. },
  2072. inputMessage: &anypb.Any{},
  2073. inputText: `{
  2074. "@type": "google.protobuf.Int64Value",
  2075. "value": "42"
  2076. }`,
  2077. wantMessage: func() proto.Message {
  2078. m := &wrapperspb.Int64Value{Value: 42}
  2079. b, err := proto.MarshalOptions{Deterministic: true}.Marshal(m)
  2080. if err != nil {
  2081. t.Fatalf("error in binary marshaling message for Any.value: %v", err)
  2082. }
  2083. return &anypb.Any{
  2084. TypeUrl: "google.protobuf.Int64Value",
  2085. Value: b,
  2086. }
  2087. }(),
  2088. }, {
  2089. desc: "Any with invalid Int64Value",
  2090. umo: protojson.UnmarshalOptions{
  2091. Resolver: preg.NewTypes(pimpl.Export{}.MessageTypeOf(&wrapperspb.Int64Value{})),
  2092. },
  2093. inputMessage: &anypb.Any{},
  2094. inputText: `{
  2095. "@type": "google.protobuf.Int64Value",
  2096. "value": "forty-two"
  2097. }`,
  2098. wantErr: true,
  2099. }, {
  2100. desc: "Any with invalid UInt64Value",
  2101. umo: protojson.UnmarshalOptions{
  2102. Resolver: preg.NewTypes(pimpl.Export{}.MessageTypeOf(&wrapperspb.UInt64Value{})),
  2103. },
  2104. inputMessage: &anypb.Any{},
  2105. inputText: `{
  2106. "@type": "google.protobuf.UInt64Value",
  2107. "value": -42
  2108. }`,
  2109. wantErr: true,
  2110. }, {
  2111. desc: "Any with Duration",
  2112. umo: protojson.UnmarshalOptions{
  2113. Resolver: preg.NewTypes(pimpl.Export{}.MessageTypeOf(&durationpb.Duration{})),
  2114. },
  2115. inputMessage: &anypb.Any{},
  2116. inputText: `{
  2117. "@type": "type.googleapis.com/google.protobuf.Duration",
  2118. "value": "0s"
  2119. }`,
  2120. wantMessage: func() proto.Message {
  2121. m := &durationpb.Duration{}
  2122. b, err := proto.MarshalOptions{Deterministic: true}.Marshal(m)
  2123. if err != nil {
  2124. t.Fatalf("error in binary marshaling message for Any.value: %v", err)
  2125. }
  2126. return &anypb.Any{
  2127. TypeUrl: "type.googleapis.com/google.protobuf.Duration",
  2128. Value: b,
  2129. }
  2130. }(),
  2131. }, {
  2132. desc: "Any with Value of StringValue",
  2133. umo: protojson.UnmarshalOptions{
  2134. Resolver: preg.NewTypes(pimpl.Export{}.MessageTypeOf(&structpb.Value{})),
  2135. },
  2136. inputMessage: &anypb.Any{},
  2137. inputText: `{
  2138. "@type": "google.protobuf.Value",
  2139. "value": "` + "abc\xff" + `"
  2140. }`,
  2141. wantErr: true,
  2142. }, {
  2143. desc: "Any with Value of NullValue",
  2144. umo: protojson.UnmarshalOptions{
  2145. Resolver: preg.NewTypes(pimpl.Export{}.MessageTypeOf(&structpb.Value{})),
  2146. },
  2147. inputMessage: &anypb.Any{},
  2148. inputText: `{
  2149. "@type": "google.protobuf.Value",
  2150. "value": null
  2151. }`,
  2152. wantMessage: func() proto.Message {
  2153. m := &structpb.Value{Kind: &structpb.Value_NullValue{}}
  2154. b, err := proto.MarshalOptions{Deterministic: true}.Marshal(m)
  2155. if err != nil {
  2156. t.Fatalf("error in binary marshaling message for Any.value: %v", err)
  2157. }
  2158. return &anypb.Any{
  2159. TypeUrl: "google.protobuf.Value",
  2160. Value: b,
  2161. }
  2162. }(),
  2163. }, {
  2164. desc: "Any with Struct",
  2165. umo: protojson.UnmarshalOptions{
  2166. Resolver: preg.NewTypes(
  2167. pimpl.Export{}.MessageTypeOf(&structpb.Struct{}),
  2168. pimpl.Export{}.MessageTypeOf(&structpb.Value{}),
  2169. pimpl.Export{}.MessageTypeOf(&wrapperspb.BoolValue{}),
  2170. pimpl.Export{}.EnumTypeOf(structpb.NullValue_NULL_VALUE),
  2171. pimpl.Export{}.MessageTypeOf(&wrapperspb.StringValue{}),
  2172. ),
  2173. },
  2174. inputMessage: &anypb.Any{},
  2175. inputText: `{
  2176. "@type": "google.protobuf.Struct",
  2177. "value": {
  2178. "bool": true,
  2179. "null": null,
  2180. "string": "hello",
  2181. "struct": {
  2182. "string": "world"
  2183. }
  2184. }
  2185. }`,
  2186. wantMessage: func() proto.Message {
  2187. m := &structpb.Struct{
  2188. Fields: map[string]*structpb.Value{
  2189. "bool": {Kind: &structpb.Value_BoolValue{true}},
  2190. "null": {Kind: &structpb.Value_NullValue{}},
  2191. "string": {Kind: &structpb.Value_StringValue{"hello"}},
  2192. "struct": {
  2193. Kind: &structpb.Value_StructValue{
  2194. &structpb.Struct{
  2195. Fields: map[string]*structpb.Value{
  2196. "string": {Kind: &structpb.Value_StringValue{"world"}},
  2197. },
  2198. },
  2199. },
  2200. },
  2201. },
  2202. }
  2203. b, err := proto.MarshalOptions{Deterministic: true}.Marshal(m)
  2204. if err != nil {
  2205. t.Fatalf("error in binary marshaling message for Any.value: %v", err)
  2206. }
  2207. return &anypb.Any{
  2208. TypeUrl: "google.protobuf.Struct",
  2209. Value: b,
  2210. }
  2211. }(),
  2212. }, {
  2213. desc: "Any with missing @type",
  2214. umo: protojson.UnmarshalOptions{},
  2215. inputMessage: &anypb.Any{},
  2216. inputText: `{
  2217. "value": {}
  2218. }`,
  2219. wantErr: true,
  2220. }, {
  2221. desc: "Any with empty @type",
  2222. inputMessage: &anypb.Any{},
  2223. inputText: `{
  2224. "@type": ""
  2225. }`,
  2226. wantErr: true,
  2227. }, {
  2228. desc: "Any with duplicate @type",
  2229. umo: protojson.UnmarshalOptions{
  2230. Resolver: preg.NewTypes(
  2231. pimpl.Export{}.MessageTypeOf(&pb2.Nested{}),
  2232. pimpl.Export{}.MessageTypeOf(&wrapperspb.StringValue{}),
  2233. ),
  2234. },
  2235. inputMessage: &anypb.Any{},
  2236. inputText: `{
  2237. "@type": "google.protobuf.StringValue",
  2238. "value": "hello",
  2239. "@type": "pb2.Nested"
  2240. }`,
  2241. wantErr: true,
  2242. }, {
  2243. desc: "Any with duplicate value",
  2244. umo: protojson.UnmarshalOptions{
  2245. Resolver: preg.NewTypes(pimpl.Export{}.MessageTypeOf(&wrapperspb.StringValue{})),
  2246. },
  2247. inputMessage: &anypb.Any{},
  2248. inputText: `{
  2249. "@type": "google.protobuf.StringValue",
  2250. "value": "hello",
  2251. "value": "world"
  2252. }`,
  2253. wantErr: true,
  2254. }, {
  2255. desc: "Any with unknown field",
  2256. umo: protojson.UnmarshalOptions{
  2257. Resolver: preg.NewTypes(pimpl.Export{}.MessageTypeOf(&pb2.Nested{})),
  2258. },
  2259. inputMessage: &anypb.Any{},
  2260. inputText: `{
  2261. "@type": "pb2.Nested",
  2262. "optString": "hello",
  2263. "unknown": "world"
  2264. }`,
  2265. wantErr: true,
  2266. }, {
  2267. desc: "Any with embedded type containing Any",
  2268. umo: protojson.UnmarshalOptions{
  2269. Resolver: preg.NewTypes(
  2270. pimpl.Export{}.MessageTypeOf(&pb2.KnownTypes{}),
  2271. pimpl.Export{}.MessageTypeOf(&anypb.Any{}),
  2272. pimpl.Export{}.MessageTypeOf(&wrapperspb.StringValue{}),
  2273. ),
  2274. },
  2275. inputMessage: &anypb.Any{},
  2276. inputText: `{
  2277. "@type": "pb2.KnownTypes",
  2278. "optAny": {
  2279. "@type": "google.protobuf.StringValue",
  2280. "value": "` + "abc\xff" + `"
  2281. }
  2282. }`,
  2283. wantErr: true,
  2284. }, {
  2285. desc: "well known types as field values",
  2286. umo: protojson.UnmarshalOptions{
  2287. Resolver: preg.NewTypes(pimpl.Export{}.MessageTypeOf(&emptypb.Empty{})),
  2288. },
  2289. inputMessage: &pb2.KnownTypes{},
  2290. inputText: `{
  2291. "optBool": false,
  2292. "optInt32": 42,
  2293. "optInt64": "42",
  2294. "optUint32": 42,
  2295. "optUint64": "42",
  2296. "optFloat": 1.23,
  2297. "optDouble": 3.1415,
  2298. "optString": "hello",
  2299. "optBytes": "aGVsbG8=",
  2300. "optDuration": "123s",
  2301. "optTimestamp": "2019-03-19T23:03:21Z",
  2302. "optStruct": {
  2303. "string": "hello"
  2304. },
  2305. "optList": [
  2306. null,
  2307. "",
  2308. {},
  2309. []
  2310. ],
  2311. "optValue": "world",
  2312. "optEmpty": {},
  2313. "optAny": {
  2314. "@type": "google.protobuf.Empty",
  2315. "value": {}
  2316. },
  2317. "optFieldmask": "fooBar,barFoo"
  2318. }`,
  2319. wantMessage: &pb2.KnownTypes{
  2320. OptBool: &wrapperspb.BoolValue{Value: false},
  2321. OptInt32: &wrapperspb.Int32Value{Value: 42},
  2322. OptInt64: &wrapperspb.Int64Value{Value: 42},
  2323. OptUint32: &wrapperspb.UInt32Value{Value: 42},
  2324. OptUint64: &wrapperspb.UInt64Value{Value: 42},
  2325. OptFloat: &wrapperspb.FloatValue{Value: 1.23},
  2326. OptDouble: &wrapperspb.DoubleValue{Value: 3.1415},
  2327. OptString: &wrapperspb.StringValue{Value: "hello"},
  2328. OptBytes: &wrapperspb.BytesValue{Value: []byte("hello")},
  2329. OptDuration: &durationpb.Duration{Seconds: 123},
  2330. OptTimestamp: &timestamppb.Timestamp{Seconds: 1553036601},
  2331. OptStruct: &structpb.Struct{
  2332. Fields: map[string]*structpb.Value{
  2333. "string": {Kind: &structpb.Value_StringValue{"hello"}},
  2334. },
  2335. },
  2336. OptList: &structpb.ListValue{
  2337. Values: []*structpb.Value{
  2338. {Kind: &structpb.Value_NullValue{}},
  2339. {Kind: &structpb.Value_StringValue{}},
  2340. {
  2341. Kind: &structpb.Value_StructValue{
  2342. &structpb.Struct{Fields: map[string]*structpb.Value{}},
  2343. },
  2344. },
  2345. {
  2346. Kind: &structpb.Value_ListValue{
  2347. &structpb.ListValue{Values: []*structpb.Value{}},
  2348. },
  2349. },
  2350. },
  2351. },
  2352. OptValue: &structpb.Value{
  2353. Kind: &structpb.Value_StringValue{"world"},
  2354. },
  2355. OptEmpty: &emptypb.Empty{},
  2356. OptAny: &anypb.Any{
  2357. TypeUrl: "google.protobuf.Empty",
  2358. },
  2359. OptFieldmask: &fieldmaskpb.FieldMask{
  2360. Paths: []string{"foo_bar", "bar_foo"},
  2361. },
  2362. },
  2363. }, {
  2364. desc: "DiscardUnknown: regular messages",
  2365. umo: protojson.UnmarshalOptions{DiscardUnknown: true},
  2366. inputMessage: &pb3.Nests{},
  2367. inputText: `{
  2368. "sNested": {
  2369. "unknown": {
  2370. "foo": 1,
  2371. "bar": [1, 2, 3]
  2372. }
  2373. },
  2374. "unknown": "not known"
  2375. }`,
  2376. wantMessage: &pb3.Nests{SNested: &pb3.Nested{}},
  2377. }, {
  2378. desc: "DiscardUnknown: repeated",
  2379. umo: protojson.UnmarshalOptions{DiscardUnknown: true},
  2380. inputMessage: &pb2.Nests{},
  2381. inputText: `{
  2382. "rptNested": [
  2383. {"unknown": "blah"},
  2384. {"optString": "hello"}
  2385. ]
  2386. }`,
  2387. wantMessage: &pb2.Nests{
  2388. RptNested: []*pb2.Nested{
  2389. {},
  2390. {OptString: scalar.String("hello")},
  2391. },
  2392. },
  2393. }, {
  2394. desc: "DiscardUnknown: map",
  2395. umo: protojson.UnmarshalOptions{DiscardUnknown: true},
  2396. inputMessage: &pb3.Maps{},
  2397. inputText: `{
  2398. "strToNested": {
  2399. "nested_one": {
  2400. "unknown": "what you see is not"
  2401. }
  2402. }
  2403. }`,
  2404. wantMessage: &pb3.Maps{
  2405. StrToNested: map[string]*pb3.Nested{
  2406. "nested_one": {},
  2407. },
  2408. },
  2409. }, {
  2410. desc: "DiscardUnknown: extension",
  2411. umo: protojson.UnmarshalOptions{DiscardUnknown: true},
  2412. inputMessage: &pb2.Extensions{},
  2413. inputText: `{
  2414. "[pb2.opt_ext_nested]": {
  2415. "unknown": []
  2416. }
  2417. }`,
  2418. wantMessage: func() proto.Message {
  2419. m := &pb2.Extensions{}
  2420. setExtension(m, pb2.E_OptExtNested, &pb2.Nested{})
  2421. return m
  2422. }(),
  2423. }, {
  2424. desc: "DiscardUnknown: Empty",
  2425. umo: protojson.UnmarshalOptions{DiscardUnknown: true},
  2426. inputMessage: &emptypb.Empty{},
  2427. inputText: `{"unknown": "something"}`,
  2428. wantMessage: &emptypb.Empty{},
  2429. }, {
  2430. desc: "DiscardUnknown: Any without type",
  2431. umo: protojson.UnmarshalOptions{DiscardUnknown: true},
  2432. inputMessage: &anypb.Any{},
  2433. inputText: `{
  2434. "value": {"foo": "bar"},
  2435. "unknown": true
  2436. }`,
  2437. wantMessage: &anypb.Any{},
  2438. }, {
  2439. desc: "DiscardUnknown: Any",
  2440. umo: protojson.UnmarshalOptions{
  2441. DiscardUnknown: true,
  2442. Resolver: preg.NewTypes(pimpl.Export{}.MessageTypeOf(&pb2.Nested{})),
  2443. },
  2444. inputMessage: &anypb.Any{},
  2445. inputText: `{
  2446. "@type": "foo/pb2.Nested",
  2447. "unknown": "none"
  2448. }`,
  2449. wantMessage: &anypb.Any{
  2450. TypeUrl: "foo/pb2.Nested",
  2451. },
  2452. }, {
  2453. desc: "DiscardUnknown: Any with Empty",
  2454. umo: protojson.UnmarshalOptions{
  2455. DiscardUnknown: true,
  2456. Resolver: preg.NewTypes(pimpl.Export{}.MessageTypeOf(&emptypb.Empty{})),
  2457. },
  2458. inputMessage: &anypb.Any{},
  2459. inputText: `{
  2460. "@type": "type.googleapis.com/google.protobuf.Empty",
  2461. "value": {"unknown": 47}
  2462. }`,
  2463. wantMessage: &anypb.Any{
  2464. TypeUrl: "type.googleapis.com/google.protobuf.Empty",
  2465. },
  2466. }}
  2467. for _, tt := range tests {
  2468. tt := tt
  2469. t.Run(tt.desc, func(t *testing.T) {
  2470. err := tt.umo.Unmarshal([]byte(tt.inputText), tt.inputMessage)
  2471. if err != nil && !tt.wantErr {
  2472. t.Errorf("Unmarshal() returned error: %v\n\n", err)
  2473. }
  2474. if err == nil && tt.wantErr {
  2475. t.Error("Unmarshal() got nil error, want error\n\n")
  2476. }
  2477. if tt.wantMessage != nil && !proto.Equal(tt.inputMessage, tt.wantMessage) {
  2478. t.Errorf("Unmarshal()\n<got>\n%v\n<want>\n%v\n", tt.inputMessage, tt.wantMessage)
  2479. }
  2480. })
  2481. }
  2482. }