1 // Protocol Buffers - Google's data interchange format
2 // Copyright 2023 Google LLC. All rights reserved.
3 //
4 // Use of this source code is governed by a BSD-style
5 // license that can be found in the LICENSE file or at
6 // https://developers.google.com/open-source/licenses/bsd
7
8 #include "upb/json/encode.h"
9
10 #include <cstddef>
11 #include <string>
12
13 #include "google/protobuf/struct.upb.h"
14 #include <gtest/gtest.h>
15 #include "upb/base/status.hpp"
16 #include "upb/base/upcast.h"
17 #include "upb/json/test.upb.h"
18 #include "upb/json/test.upbdefs.h"
19 #include "upb/mem/arena.h"
20 #include "upb/mem/arena.hpp"
21 #include "upb/reflection/def.hpp"
22
JsonEncode(const upb_test_Box * msg,int options)23 static std::string JsonEncode(const upb_test_Box* msg, int options) {
24 upb::Arena a;
25 upb::Status status;
26 upb::DefPool defpool;
27 upb::MessageDefPtr m(upb_test_Box_getmsgdef(defpool.ptr()));
28 EXPECT_TRUE(m.ptr() != nullptr);
29
30 size_t json_size = upb_JsonEncode(UPB_UPCAST(msg), m.ptr(), defpool.ptr(),
31 options, nullptr, 0, status.ptr());
32 char* json_buf = (char*)upb_Arena_Malloc(a.ptr(), json_size + 1);
33
34 size_t size = upb_JsonEncode(UPB_UPCAST(msg), m.ptr(), defpool.ptr(), options,
35 json_buf, json_size + 1, status.ptr());
36 EXPECT_EQ(size, json_size);
37 return std::string(json_buf, json_size);
38 }
39
40 // Encode a single optional enum.
TEST(JsonTest,EncodeEnum)41 TEST(JsonTest, EncodeEnum) {
42 upb::Arena a;
43
44 upb_test_Box* foo = upb_test_Box_new(a.ptr());
45 upb_test_Box_set_first_tag(foo, upb_test_Z_BAR);
46
47 EXPECT_EQ(R"({"firstTag":"Z_BAR"})", JsonEncode(foo, 0));
48 EXPECT_EQ(R"({"firstTag":1})",
49 JsonEncode(foo, upb_JsonEncode_FormatEnumsAsIntegers));
50 }
51
52 // Encode a single optional negative enum.
TEST(JsonTest,EncodeNegativeEnum)53 TEST(JsonTest, EncodeNegativeEnum) {
54 upb::Arena a;
55
56 upb_test_Box* foo = upb_test_Box_new(a.ptr());
57 upb_test_Box_set_last_tag(foo, upb_test_Z_BAZ);
58
59 EXPECT_EQ(R"({"lastTag":"Z_BAZ"})", JsonEncode(foo, 0));
60 EXPECT_EQ(R"({"lastTag":-2})",
61 JsonEncode(foo, upb_JsonEncode_FormatEnumsAsIntegers));
62 }
63
64 // Encode a single repeated enum.
TEST(JsonTest,EncodeRepeatedEnum)65 TEST(JsonTest, EncodeRepeatedEnum) {
66 upb::Arena a;
67
68 upb_test_Box* foo = upb_test_Box_new(a.ptr());
69 upb_test_Box_add_more_tags(foo, upb_test_Z_BAT, a.ptr());
70
71 EXPECT_EQ(R"({"moreTags":["Z_BAT"]})", JsonEncode(foo, 0));
72 EXPECT_EQ(R"({"moreTags":[13]})",
73 JsonEncode(foo, upb_JsonEncode_FormatEnumsAsIntegers));
74 }
75
76 // Special case: encode null enum.
TEST(JsonTest,EncodeNullEnum)77 TEST(JsonTest, EncodeNullEnum) {
78 upb::Arena a;
79
80 upb_test_Box* foo = upb_test_Box_new(a.ptr());
81 google_protobuf_Value_set_null_value(upb_test_Box_mutable_val(foo, a.ptr()),
82 google_protobuf_NULL_VALUE);
83
84 EXPECT_EQ(R"({"val":null})", JsonEncode(foo, 0));
85 EXPECT_EQ(R"({"val":null})",
86 JsonEncode(foo, upb_JsonEncode_FormatEnumsAsIntegers));
87 }
88
TEST(JsonTest,EncodeConflictJsonName)89 TEST(JsonTest, EncodeConflictJsonName) {
90 upb::Arena a;
91 upb_test_Box* box = upb_test_Box_new(a.ptr());
92 upb_test_Box_set_value(box, 2);
93 EXPECT_EQ(R"({"old_value":2})", JsonEncode(box, 0));
94
95 upb_test_Box* new_box = upb_test_Box_new(a.ptr());
96 upb_test_Box_set_new_value(new_box, 2);
97 EXPECT_EQ(R"({"value":2})", JsonEncode(new_box, 0));
98 }
99