1# Copyright (c) Facebook, Inc. and its affiliates.
2#
3# Licensed under the Apache License, Version 2.0 (the "License");
4# you may not use this file except in compliance with the License.
5# You may obtain a copy of the License at
6#
7#     http://www.apache.org/licenses/LICENSE-2.0
8#
9# Unless required by applicable law or agreed to in writing, software
10# distributed under the License is distributed on an "AS IS" BASIS,
11# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12# See the License for the specific language governing permissions and
13# limitations under the License.
14
15import os
16import shutil
17import tempfile
18import textwrap
19import unittest
20
21from thrift.compiler.codemod.test_utils import write_file, run_binary, read_file
22
23
24# TODO(urielrivas): We can use clangr's unit-test formatting in the future.
25class CppRefToUnstructured(unittest.TestCase):
26    def setUp(self):
27        tmp = tempfile.mkdtemp()
28        self.addCleanup(shutil.rmtree, tmp, True)
29        self.tmp = tmp
30        self.addCleanup(os.chdir, os.getcwd())
31        os.chdir(self.tmp)
32        self.maxDiff = None
33
34    def test_basic_replace(self):
35        write_file(
36            "foo.thrift",
37            textwrap.dedent(
38                """\
39                struct Faa {
40                    1: i32 faa1;
41                    2: optional Faa faa2 (cpp.ref);
42                    3: i32 faa3;
43                }
44                """
45            ),
46        )
47
48        run_binary("cppref_to_structured", "foo.thrift")
49
50        # NOTE: For current tests, user should rely on automated formatting.
51        self.assertEqual(
52            read_file("foo.thrift"),
53            textwrap.dedent(
54                """\
55                include "thrift/annotation/cpp.thrift"
56                struct Faa {
57                    1: i32 faa1;
58                    @cpp.Ref{type = cpp.RefType.Unique}
59                2: optional Faa faa2 ;
60                    3: i32 faa3;
61                }
62                """
63            ),
64        )
65
66    def test_existing_includes(self):
67        write_file("a.thrift", "")
68        write_file("b.thrift", "")
69        write_file("c.thrift", "")
70
71        write_file(
72            "foo.thrift",
73            textwrap.dedent(
74                """\
75                include "a.thrift"
76                include "b.thrift"
77                include "c.thrift"
78
79                struct Faa {
80                    1: i32 faa1;
81                    2: optional Faa faa2 (cpp.ref);
82                    3: i32 faa3;
83                }
84                """
85            ),
86        )
87
88        run_binary("cppref_to_structured", "foo.thrift")
89
90        self.assertEqual(
91            read_file("foo.thrift"),
92            textwrap.dedent(
93                """\
94                include "a.thrift"
95                include "b.thrift"
96                include "c.thrift"
97                include "thrift/annotation/cpp.thrift"
98
99                struct Faa {
100                    1: i32 faa1;
101                    @cpp.Ref{type = cpp.RefType.Unique}
102                2: optional Faa faa2 ;
103                    3: i32 faa3;
104                }
105                """
106            ),
107        )
108
109    def test_namespaces(self):
110        write_file(
111            "foo.thrift",
112            textwrap.dedent(
113                """\
114                namespace cpp2 apache.thrift
115                namespace py3 thrift.lib.thrift
116                struct Faa {
117                    1: i32 faa1;
118                    2: optional Faa faa2 (cpp.ref);
119                    3: i32 faa3;
120                }
121                """
122            ),
123        )
124
125        run_binary("cppref_to_structured", "foo.thrift")
126
127        self.assertEqual(
128            read_file("foo.thrift"),
129            textwrap.dedent(
130                """\
131                namespace cpp2 apache.thrift
132                namespace py3 thrift.lib.thrift
133                struct Faa {
134                    1: i32 faa1;
135                    2: optional Faa faa2 (cpp.ref);
136                    3: i32 faa3;
137                }
138                """
139            ),
140        )
141
142    def test_cpp_and_cpp2(self):
143        write_file(
144            "foo.thrift",
145            textwrap.dedent(
146                """\
147                struct Faa {
148                    1: i32 faa1;
149                    2: optional Faa faa2 (cpp.ref = "true", cpp2.ref = "true");
150                    3: i32 faa3;
151                }
152                """
153            ),
154        )
155
156        run_binary("cppref_to_structured", "foo.thrift")
157
158        self.assertEqual(
159            read_file("foo.thrift"),
160            textwrap.dedent(
161                """\
162                include "thrift/annotation/cpp.thrift"
163                struct Faa {
164                    1: i32 faa1;
165                    @cpp.Ref{type = cpp.RefType.Unique}
166                2: optional Faa faa2 ;
167                    3: i32 faa3;
168                }
169                """
170            ),
171        )
172