blob: 58e0235a0a7477dcffd809da2c3bd18059b1fdd9 [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 =
29 "third_party/unsupported_toolchains/rust/toolchains/nightly/bin/rustfmt";
30
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(
Rosica Dejanovskaabe406f2022-09-02 07:06:50 -070042 "cc_out", "rs_out", "ir_out", "namespaces_out", "crubit_support_path",
Lukasz Anforowicz5bf49432022-12-12 12:17:24 -080043 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= */ "",
50 /* error_report_out= */ ""));
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(
Rosica Dejanovskaabe406f2022-09-02 07:06:50 -070074 "cc_out", "rs_out", "ir_out", "namespaces_out", "crubit_support_path",
Lukasz Anforowicz5bf49432022-12-12 12:17:24 -080075 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= */ "",
82 /* error_report_out= */ ""));
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(
Rosica Dejanovskaabe406f2022-09-02 07:06:50 -0700104 "cc_out", "rs_out", "ir_out", "namespaces_out", "crubit_support_path",
Lukasz Anforowicz5bf49432022-12-12 12:17:24 -0800105 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},
Michael VanBemmelf5cbdf42022-10-14 17:00:11 -0700112 "instantiations_out", /* error_report_out= */ ""));
Marcel Hlopko2ee23912022-05-09 06:13:55 -0700113
Marcel Hlopkoc31d95a2022-09-09 05:17:32 -0700114 CRUBIT_ASSIGN_OR_RETURN(
Marcel Hlopko2ee23912022-05-09 06:13:55 -0700115 BindingsAndMetadata result,
Marcel Hlopkoc31d95a2022-09-09 05:17:32 -0700116 GenerateBindingsAndMetadata(
117 cmdline, DefaultClangArgs(),
118 /* virtual_headers_contents= */
119 {{HeaderName("a.h"), std::string(header_content)}}));
Marcel Hlopko2ee23912022-05-09 06:13:55 -0700120
Marcel Hlopkoc31d95a2022-09-09 05:17:32 -0700121 return std::move(result.instantiations);
122}
123
124TEST(GenerateBindingsAndMetadataTest,
Marcel Hlopko20de6de2022-09-13 05:28:08 -0700125 RegularTypeAliasNotPresentInInstantiations) {
126 ASSERT_OK_AND_ASSIGN(auto instantiations,
127 GetInstantiationsFor(
128 R"cc(
129 template <typename T>
130 class MyTemplate {};
Marcel Hlopkoc31d95a2022-09-09 05:17:32 -0700131
Marcel Hlopko20de6de2022-09-13 05:28:08 -0700132 using MyFunnyTemplate = MyTemplate<bool>;
Marcel Hlopkoc31d95a2022-09-09 05:17:32 -0700133
Marcel Hlopko20de6de2022-09-13 05:28:08 -0700134 template <typename T>
135 class ExpectedTemplate {};
136 )cc",
137 "cc_template!{ExpectedTemplate<bool>}"));
138
139 ASSERT_THAT(instantiations,
140 ElementsAre(Pair("ExpectedTemplate<bool>",
141 "__CcTemplateInst16ExpectedTemplateIbE")));
Marcel Hlopkoc31d95a2022-09-09 05:17:32 -0700142}
143
144TEST(GenerateBindingsAndMetadataTest,
Marcel Hlopko20de6de2022-09-13 05:28:08 -0700145 ExplicitClassTemplateInstantiationDeclarationsNotPresentInInstantiations) {
146 ASSERT_OK_AND_ASSIGN(auto instantiations,
147 GetInstantiationsFor(
148 R"cc(
149 template <typename T>
150 class MyTemplate {};
Marcel Hlopkoc31d95a2022-09-09 05:17:32 -0700151
Marcel Hlopko20de6de2022-09-13 05:28:08 -0700152 extern template class MyTemplate<bool>;
Marcel Hlopkoc31d95a2022-09-09 05:17:32 -0700153
Marcel Hlopko20de6de2022-09-13 05:28:08 -0700154 template <typename T>
155 class ExpectedTemplate {};
156 )cc",
157 "cc_template!{ExpectedTemplate<bool>}"));
158
159 ASSERT_THAT(instantiations,
160 ElementsAre(Pair("ExpectedTemplate<bool>",
161 "__CcTemplateInst16ExpectedTemplateIbE")));
Marcel Hlopkoc31d95a2022-09-09 05:17:32 -0700162}
163
Marcel Hlopkoc31d95a2022-09-09 05:17:32 -0700164TEST(GenerateBindingsAndMetadataTest,
Marcel Hlopko20de6de2022-09-13 05:28:08 -0700165 ExplicitClassTemplateInstantiationDefinitionsNotPresentInInstantiations) {
166 ASSERT_OK_AND_ASSIGN(auto instantiations,
167 GetInstantiationsFor(
168 R"cc(
169 template <typename T>
170 class MyTemplate {};
Marcel Hlopkoc31d95a2022-09-09 05:17:32 -0700171
Marcel Hlopko20de6de2022-09-13 05:28:08 -0700172 template class MyTemplate<bool>;
Lukasz Anforowicz38310f32022-09-09 11:17:52 -0700173
Marcel Hlopko20de6de2022-09-13 05:28:08 -0700174 template <typename T>
175 class ExpectedTemplate {};
176 )cc",
177 "cc_template!{ExpectedTemplate<bool>}"));
Marcel Hlopkoc31d95a2022-09-09 05:17:32 -0700178
Marcel Hlopko20de6de2022-09-13 05:28:08 -0700179 ASSERT_THAT(instantiations,
180 ElementsAre(Pair("ExpectedTemplate<bool>",
181 "__CcTemplateInst16ExpectedTemplateIbE")));
182}
183
184TEST(GenerateBindingsAndMetadataTest,
185 RegularRecordsNotPresentInInstantiations) {
186 ASSERT_OK_AND_ASSIGN(auto instantiations,
187 GetInstantiationsFor(
188 R"cc(
189 struct MyStruct {};
190
191 template <typename T>
192 class ExpectedTemplate {};
193 )cc",
194 "cc_template!{ExpectedTemplate<bool>}"));
195
196 ASSERT_THAT(instantiations,
197 ElementsAre(Pair("ExpectedTemplate<bool>",
198 "__CcTemplateInst16ExpectedTemplateIbE")));
199}
200
201TEST(GenerateBindingsAndMetadataTest,
202 InstantiationsAreGeneratedForCcTemplateMacro) {
203 ASSERT_OK_AND_ASSIGN(auto instantiations,
204 GetInstantiationsFor(
205 R"cc(
206 template <typename T>
207 class ExpectedTemplate {};
208 )cc",
209 "cc_template!{ExpectedTemplate<bool>}"));
210
211 ASSERT_THAT(instantiations,
212 ElementsAre(Pair("ExpectedTemplate<bool>",
213 "__CcTemplateInst16ExpectedTemplateIbE")));
Marcel Hlopko2ee23912022-05-09 06:13:55 -0700214}
215
Rosica Dejanovskaabe406f2022-09-02 07:06:50 -0700216TEST(GenerateBindingsAndMetadataTest, NamespacesJsonGenerated) {
217 constexpr absl::string_view kTargetsAndHeaders = R"([
218 {"t": "target1", "h": ["a.h"]}
219 ])";
220 constexpr absl::string_view kHeaderContent = R"(
221 namespace top_level_1 {
222 namespace middle {
223 namespace inner_1 {}
224 }
225 namespace middle {
226 namespace inner_2 {}
227 }
228 }
229
230 namespace top_level_2 {
231 namespace inner_3 {}
232 }
233
234 namespace top_level_1 {}
235 )";
236 constexpr absl::string_view kExpected = R"({
Rosica Dejanovska5b2e8132022-09-20 02:11:51 -0700237 "label": "target1",
Rosica Dejanovskaabe406f2022-09-02 07:06:50 -0700238 "namespaces": [
239 {
Rosica Dejanovska5b2e8132022-09-20 02:11:51 -0700240 "children": [
241 {
242 "children": [
243 {
244 "children": [],
245 "name": "inner_1"
246 },
247 {
248 "children": [],
249 "name": "inner_2"
Rosica Dejanovskaabe406f2022-09-02 07:06:50 -0700250 }
Rosica Dejanovska5b2e8132022-09-20 02:11:51 -0700251 ],
252 "name": "middle"
253 }
254 ],
255 "name": "top_level_1"
Rosica Dejanovskaabe406f2022-09-02 07:06:50 -0700256 },
257 {
Rosica Dejanovska5b2e8132022-09-20 02:11:51 -0700258 "children": [
259 {
260 "children": [],
261 "name": "inner_3"
262 }
263 ],
264 "name": "top_level_2"
Rosica Dejanovskaabe406f2022-09-02 07:06:50 -0700265 }
266 ]
267})";
268
269 ASSERT_OK_AND_ASSIGN(
270 Cmdline cmdline,
271 Cmdline::CreateForTesting(
272 "cc_out", "rs_out", "ir_out", "namespaces_json",
Lukasz Anforowicz5bf49432022-12-12 12:17:24 -0800273 "crubit_support_path", std::string(kDefaultClangFormatExePath),
274 std::string(kDefaultRustfmtExePath), "nowhere/rustfmt.toml",
Rosica Dejanovskaabe406f2022-09-02 07:06:50 -0700275 /* do_nothing= */ false,
276 /* public_headers= */ {"a.h"}, std::string(kTargetsAndHeaders),
Devin Jeanpierre96bf0bd2022-10-04 20:32:15 -0700277 /* extra_rs_srcs= */ {},
278 /* srcs_to_scan_for_instantiations= */ {},
Michael VanBemmelf5cbdf42022-10-14 17:00:11 -0700279 /* instantiations_out= */ "", /* error_report_out= */ ""));
Rosica Dejanovskaabe406f2022-09-02 07:06:50 -0700280 ASSERT_OK_AND_ASSIGN(BindingsAndMetadata result,
281 GenerateBindingsAndMetadata(
282 cmdline, DefaultClangArgs(),
283 /* virtual_headers_contents= */
284 {{HeaderName("a.h"), std::string(kHeaderContent)}}));
285
286 ASSERT_THAT(NamespacesAsJson(result.namespaces), StrEq(kExpected));
287}
288
Marcel Hlopko3f771a92022-05-09 06:09:59 -0700289} // namespace
290} // namespace crubit