blob: 393fae1ecf4ce60c0d3365d909a18e2c17afa3ae [file] [log] [blame]
Marcel Hlopko3f771a92022-05-09 06:09:59 -07001// Part of the Crubit project, under the Apache License v2.0 with LLVM
2// Exceptions. See /LICENSE for license information.
3// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
4
5#include "rs_bindings_from_cc/generate_bindings_and_metadata.h"
6
Marcel Hlopkoc31d95a2022-09-09 05:17:32 -07007#include <string>
8
Luca Versaric21d92f2022-05-25 00:56:30 -07009#include "gmock/gmock.h"
10#include "gtest/gtest.h"
Marcel Hlopkoc31d95a2022-09-09 05:17:32 -070011#include "absl/status/status.h"
12#include "absl/status/statusor.h"
13#include "absl/strings/string_view.h"
14#include "common/status_macros.h"
Marcel Hlopko2ee23912022-05-09 06:13:55 -070015#include "common/test_utils.h"
Marcel Hlopko3f771a92022-05-09 06:09:59 -070016#include "rs_bindings_from_cc/cmdline.h"
Rosica Dejanovskaabe406f2022-09-02 07:06:50 -070017#include "rs_bindings_from_cc/collect_namespaces.h"
Rosica Dejanovskaaf348cc2022-08-30 05:54:16 -070018#include "rs_bindings_from_cc/ir.h"
Marcel Hlopko3f771a92022-05-09 06:09:59 -070019
20namespace crubit {
21namespace {
22
Marcel Hlopkoc31d95a2022-09-09 05:17:32 -070023using ::testing::ElementsAre;
24using ::testing::IsEmpty;
25using ::testing::Pair;
Marcel Hlopko2ee23912022-05-09 06:13:55 -070026using ::testing::StrEq;
27
Lukasz Anforowiczd7d68f02022-05-26 07:41:02 -070028constexpr absl::string_view kDefaultRustfmtExePath =
Googler83b6d7f2023-02-14 05:18:49 -080029 "nowhere/llvm/rust/main_sysroot/bin/rustfmt";
Lukasz Anforowiczd7d68f02022-05-26 07:41:02 -070030
Lukasz Anforowicz5bf49432022-12-12 12:17:24 -080031constexpr absl::string_view kDefaultClangFormatExePath =
32 "third_party/crosstool/google3_users/clang-format";
33
Marcel Hlopko3f771a92022-05-09 06:09:59 -070034TEST(GenerateBindingsAndMetadataTest, GeneratingIR) {
35 constexpr absl::string_view kTargetsAndHeaders = R"([
36 {"t": "target1", "h": ["a.h"]}
37 ])";
38
Marcel Hlopko3f771a92022-05-09 06:09:59 -070039 ASSERT_OK_AND_ASSIGN(
40 Cmdline cmdline,
41 Cmdline::CreateForTesting(
Devin Jeanpierree87ae2a2023-01-20 12:15:36 -080042 "//:target", "cc_out", "rs_out", "ir_out", "namespaces_out",
43 "crubit_support_path", std::string(kDefaultClangFormatExePath),
Lukasz Anforowiczd7d68f02022-05-26 07:41:02 -070044 std::string(kDefaultRustfmtExePath), "nowhere/rustfmt.toml",
Marcel Hlopko3f771a92022-05-09 06:09:59 -070045 /* do_nothing= */ false,
46 /* public_headers= */ {"a.h"}, std::string(kTargetsAndHeaders),
Devin Jeanpierre96bf0bd2022-10-04 20:32:15 -070047 /* extra_rs_srcs= */ {},
48 /* srcs_to_scan_for_instantiations= */ {},
Michael VanBemmelf5cbdf42022-10-14 17:00:11 -070049 /* instantiations_out= */ "",
Googler69e09632023-03-03 12:18:35 -080050 /* error_report_out= */ "", SourceLocationDocComment::Enabled));
Marcel Hlopko3f771a92022-05-09 06:09:59 -070051
52 ASSERT_OK_AND_ASSIGN(
53 BindingsAndMetadata result,
Rosica Dejanovskaaf348cc2022-08-30 05:54:16 -070054 GenerateBindingsAndMetadata(cmdline, DefaultClangArgs(),
55 /* virtual_headers_contents= */
56 {{HeaderName("a.h"), "namespace ns{}"}}));
Marcel Hlopko3f771a92022-05-09 06:09:59 -070057
Lukasz Anforowicz121338a2022-11-01 14:28:32 -070058 ASSERT_EQ(result.ir.public_headers.size(), 1);
59 ASSERT_EQ(result.ir.public_headers.front().IncludePath(), "a.h");
Michael VanBemmelf5cbdf42022-10-14 17:00:11 -070060 ASSERT_EQ(result.error_report, "");
Rosica Dejanovskaaf348cc2022-08-30 05:54:16 -070061
62 // Check that IR items have the proper owning target set.
63 auto item = result.ir.get_items_if<Namespace>().front();
64 ASSERT_EQ(item->owning_target.value(), "target1");
Marcel Hlopko3f771a92022-05-09 06:09:59 -070065}
66
Marcel Hlopko2ee23912022-05-09 06:13:55 -070067TEST(GenerateBindingsAndMetadataTest, InstantiationsAreEmptyInNormalMode) {
68 constexpr absl::string_view kTargetsAndHeaders = R"([
69 {"t": "target1", "h": ["a.h"]}
70 ])";
Marcel Hlopko2ee23912022-05-09 06:13:55 -070071 ASSERT_OK_AND_ASSIGN(
72 Cmdline cmdline,
73 Cmdline::CreateForTesting(
Devin Jeanpierree87ae2a2023-01-20 12:15:36 -080074 "//:target", "cc_out", "rs_out", "ir_out", "namespaces_out",
75 "crubit_support_path", std::string(kDefaultClangFormatExePath),
Lukasz Anforowiczd7d68f02022-05-26 07:41:02 -070076 std::string(kDefaultRustfmtExePath), "nowhere/rustfmt.toml",
Marcel Hlopko2ee23912022-05-09 06:13:55 -070077 /* do_nothing= */ false,
78 /* public_headers= */ {"a.h"}, std::string(kTargetsAndHeaders),
Devin Jeanpierre96bf0bd2022-10-04 20:32:15 -070079 /* extra_rs_srcs= */ {},
80 /* srcs_to_scan_for_instantiations= */ {},
Michael VanBemmelf5cbdf42022-10-14 17:00:11 -070081 /* instantiations_out= */ "",
Googler69e09632023-03-03 12:18:35 -080082 /* error_report_out= */ "", SourceLocationDocComment::Enabled));
Marcel Hlopko2ee23912022-05-09 06:13:55 -070083
84 ASSERT_OK_AND_ASSIGN(
85 BindingsAndMetadata result,
Rosica Dejanovskaaf348cc2022-08-30 05:54:16 -070086 GenerateBindingsAndMetadata(cmdline, DefaultClangArgs(),
87 /* virtual_headers_contents= */
88 {{HeaderName("a.h"), "// empty header"}}));
Marcel Hlopko2ee23912022-05-09 06:13:55 -070089
Marcel Hlopkoc31d95a2022-09-09 05:17:32 -070090 ASSERT_THAT(result.instantiations, IsEmpty());
Marcel Hlopko2ee23912022-05-09 06:13:55 -070091}
92
Marcel Hlopkoc31d95a2022-09-09 05:17:32 -070093absl::StatusOr<absl::flat_hash_map<std::string, std::string>>
94GetInstantiationsFor(absl::string_view header_content,
95 absl::string_view rust_source) {
96 std::string a_rs_path = WriteFileForCurrentTest("a.rs", rust_source);
Marcel Hlopko2ee23912022-05-09 06:13:55 -070097 constexpr absl::string_view kTargetsAndHeaders = R"([
98 {"t": "target1", "h": ["a.h"]}
99 ])";
Marcel Hlopkoc31d95a2022-09-09 05:17:32 -0700100
101 CRUBIT_ASSIGN_OR_RETURN(
Marcel Hlopko2ee23912022-05-09 06:13:55 -0700102 Cmdline cmdline,
103 Cmdline::CreateForTesting(
Devin Jeanpierree87ae2a2023-01-20 12:15:36 -0800104 "//:target", "cc_out", "rs_out", "ir_out", "namespaces_out",
105 "crubit_support_path", std::string(kDefaultClangFormatExePath),
Lukasz Anforowiczd7d68f02022-05-26 07:41:02 -0700106 std::string(kDefaultRustfmtExePath), "nowhere/rustfmt.toml",
Marcel Hlopko2ee23912022-05-09 06:13:55 -0700107 /* do_nothing= */ false,
Marcel Hlopkoc31d95a2022-09-09 05:17:32 -0700108 /* public_headers= */
109 {"a.h"}, std::string(kTargetsAndHeaders),
Devin Jeanpierre96bf0bd2022-10-04 20:32:15 -0700110 /* extra_rs_srcs= */ {},
111 /* srcs_to_scan_for_instantiations= */ {a_rs_path},
Googler69e09632023-03-03 12:18:35 -0800112 "instantiations_out", /* error_report_out= */ "",
113 SourceLocationDocComment::Enabled));
Marcel Hlopko2ee23912022-05-09 06:13:55 -0700114
Marcel Hlopkoc31d95a2022-09-09 05:17:32 -0700115 CRUBIT_ASSIGN_OR_RETURN(
Marcel Hlopko2ee23912022-05-09 06:13:55 -0700116 BindingsAndMetadata result,
Marcel Hlopkoc31d95a2022-09-09 05:17:32 -0700117 GenerateBindingsAndMetadata(
118 cmdline, DefaultClangArgs(),
119 /* virtual_headers_contents= */
120 {{HeaderName("a.h"), std::string(header_content)}}));
Marcel Hlopko2ee23912022-05-09 06:13:55 -0700121
Marcel Hlopkoc31d95a2022-09-09 05:17:32 -0700122 return std::move(result.instantiations);
123}
124
125TEST(GenerateBindingsAndMetadataTest,
Marcel Hlopko20de6de2022-09-13 05:28:08 -0700126 RegularTypeAliasNotPresentInInstantiations) {
127 ASSERT_OK_AND_ASSIGN(auto instantiations,
128 GetInstantiationsFor(
129 R"cc(
130 template <typename T>
131 class MyTemplate {};
Marcel Hlopkoc31d95a2022-09-09 05:17:32 -0700132
Marcel Hlopko20de6de2022-09-13 05:28:08 -0700133 using MyFunnyTemplate = MyTemplate<bool>;
Marcel Hlopkoc31d95a2022-09-09 05:17:32 -0700134
Marcel Hlopko20de6de2022-09-13 05:28:08 -0700135 template <typename T>
136 class ExpectedTemplate {};
137 )cc",
138 "cc_template!{ExpectedTemplate<bool>}"));
139
140 ASSERT_THAT(instantiations,
141 ElementsAre(Pair("ExpectedTemplate<bool>",
142 "__CcTemplateInst16ExpectedTemplateIbE")));
Marcel Hlopkoc31d95a2022-09-09 05:17:32 -0700143}
144
145TEST(GenerateBindingsAndMetadataTest,
Marcel Hlopko20de6de2022-09-13 05:28:08 -0700146 ExplicitClassTemplateInstantiationDeclarationsNotPresentInInstantiations) {
147 ASSERT_OK_AND_ASSIGN(auto instantiations,
148 GetInstantiationsFor(
149 R"cc(
150 template <typename T>
151 class MyTemplate {};
Marcel Hlopkoc31d95a2022-09-09 05:17:32 -0700152
Marcel Hlopko20de6de2022-09-13 05:28:08 -0700153 extern template class MyTemplate<bool>;
Marcel Hlopkoc31d95a2022-09-09 05:17:32 -0700154
Marcel Hlopko20de6de2022-09-13 05:28:08 -0700155 template <typename T>
156 class ExpectedTemplate {};
157 )cc",
158 "cc_template!{ExpectedTemplate<bool>}"));
159
160 ASSERT_THAT(instantiations,
161 ElementsAre(Pair("ExpectedTemplate<bool>",
162 "__CcTemplateInst16ExpectedTemplateIbE")));
Marcel Hlopkoc31d95a2022-09-09 05:17:32 -0700163}
164
Marcel Hlopkoc31d95a2022-09-09 05:17:32 -0700165TEST(GenerateBindingsAndMetadataTest,
Marcel Hlopko20de6de2022-09-13 05:28:08 -0700166 ExplicitClassTemplateInstantiationDefinitionsNotPresentInInstantiations) {
167 ASSERT_OK_AND_ASSIGN(auto instantiations,
168 GetInstantiationsFor(
169 R"cc(
170 template <typename T>
171 class MyTemplate {};
Marcel Hlopkoc31d95a2022-09-09 05:17:32 -0700172
Marcel Hlopko20de6de2022-09-13 05:28:08 -0700173 template class MyTemplate<bool>;
Lukasz Anforowicz38310f32022-09-09 11:17:52 -0700174
Marcel Hlopko20de6de2022-09-13 05:28:08 -0700175 template <typename T>
176 class ExpectedTemplate {};
177 )cc",
178 "cc_template!{ExpectedTemplate<bool>}"));
Marcel Hlopkoc31d95a2022-09-09 05:17:32 -0700179
Marcel Hlopko20de6de2022-09-13 05:28:08 -0700180 ASSERT_THAT(instantiations,
181 ElementsAre(Pair("ExpectedTemplate<bool>",
182 "__CcTemplateInst16ExpectedTemplateIbE")));
183}
184
185TEST(GenerateBindingsAndMetadataTest,
186 RegularRecordsNotPresentInInstantiations) {
187 ASSERT_OK_AND_ASSIGN(auto instantiations,
188 GetInstantiationsFor(
189 R"cc(
190 struct MyStruct {};
191
192 template <typename T>
193 class ExpectedTemplate {};
194 )cc",
195 "cc_template!{ExpectedTemplate<bool>}"));
196
197 ASSERT_THAT(instantiations,
198 ElementsAre(Pair("ExpectedTemplate<bool>",
199 "__CcTemplateInst16ExpectedTemplateIbE")));
200}
201
202TEST(GenerateBindingsAndMetadataTest,
203 InstantiationsAreGeneratedForCcTemplateMacro) {
204 ASSERT_OK_AND_ASSIGN(auto instantiations,
205 GetInstantiationsFor(
206 R"cc(
207 template <typename T>
208 class ExpectedTemplate {};
209 )cc",
210 "cc_template!{ExpectedTemplate<bool>}"));
211
212 ASSERT_THAT(instantiations,
213 ElementsAre(Pair("ExpectedTemplate<bool>",
214 "__CcTemplateInst16ExpectedTemplateIbE")));
Marcel Hlopko2ee23912022-05-09 06:13:55 -0700215}
216
Rosica Dejanovskaabe406f2022-09-02 07:06:50 -0700217TEST(GenerateBindingsAndMetadataTest, NamespacesJsonGenerated) {
218 constexpr absl::string_view kTargetsAndHeaders = R"([
Devin Jeanpierree87ae2a2023-01-20 12:15:36 -0800219 {"t": "//:target1", "h": ["a.h"]}
Rosica Dejanovskaabe406f2022-09-02 07:06:50 -0700220 ])";
221 constexpr absl::string_view kHeaderContent = R"(
222 namespace top_level_1 {
223 namespace middle {
224 namespace inner_1 {}
225 }
226 namespace middle {
227 namespace inner_2 {}
228 }
229 }
230
231 namespace top_level_2 {
232 namespace inner_3 {}
233 }
234
235 namespace top_level_1 {}
236 )";
237 constexpr absl::string_view kExpected = R"({
Devin Jeanpierree87ae2a2023-01-20 12:15:36 -0800238 "label": "//:target1",
Rosica Dejanovskaabe406f2022-09-02 07:06:50 -0700239 "namespaces": [
240 {
Rosica Dejanovska5b2e8132022-09-20 02:11:51 -0700241 "children": [
242 {
243 "children": [
244 {
245 "children": [],
246 "name": "inner_1"
247 },
248 {
249 "children": [],
250 "name": "inner_2"
Rosica Dejanovskaabe406f2022-09-02 07:06:50 -0700251 }
Rosica Dejanovska5b2e8132022-09-20 02:11:51 -0700252 ],
253 "name": "middle"
254 }
255 ],
256 "name": "top_level_1"
Rosica Dejanovskaabe406f2022-09-02 07:06:50 -0700257 },
258 {
Rosica Dejanovska5b2e8132022-09-20 02:11:51 -0700259 "children": [
260 {
261 "children": [],
262 "name": "inner_3"
263 }
264 ],
265 "name": "top_level_2"
Rosica Dejanovskaabe406f2022-09-02 07:06:50 -0700266 }
267 ]
268})";
269
270 ASSERT_OK_AND_ASSIGN(
271 Cmdline cmdline,
272 Cmdline::CreateForTesting(
Devin Jeanpierree87ae2a2023-01-20 12:15:36 -0800273 "//:target1", "cc_out", "rs_out", "ir_out", "namespaces_json",
Lukasz Anforowicz5bf49432022-12-12 12:17:24 -0800274 "crubit_support_path", std::string(kDefaultClangFormatExePath),
275 std::string(kDefaultRustfmtExePath), "nowhere/rustfmt.toml",
Rosica Dejanovskaabe406f2022-09-02 07:06:50 -0700276 /* do_nothing= */ false,
277 /* public_headers= */ {"a.h"}, std::string(kTargetsAndHeaders),
Devin Jeanpierre96bf0bd2022-10-04 20:32:15 -0700278 /* extra_rs_srcs= */ {},
279 /* srcs_to_scan_for_instantiations= */ {},
Googler69e09632023-03-03 12:18:35 -0800280 /* instantiations_out= */ "", /* error_report_out= */ "",
281 SourceLocationDocComment::Enabled));
Rosica Dejanovskaabe406f2022-09-02 07:06:50 -0700282 ASSERT_OK_AND_ASSIGN(BindingsAndMetadata result,
283 GenerateBindingsAndMetadata(
284 cmdline, DefaultClangArgs(),
285 /* virtual_headers_contents= */
286 {{HeaderName("a.h"), std::string(kHeaderContent)}}));
287
288 ASSERT_THAT(NamespacesAsJson(result.namespaces), StrEq(kExpected));
289}
290
Marcel Hlopko3f771a92022-05-09 06:09:59 -0700291} // namespace
292} // namespace crubit