• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2019 The Android Open Source Project
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *      http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 
17 #include "linkerconfig/section.h"
18 
19 #include <android-base/result.h>
20 #include <gmock/gmock.h>
21 #include <gtest/gtest.h>
22 
23 #include "apex_testbase.h"
24 #include "linkerconfig/basecontext.h"
25 #include "linkerconfig/configwriter.h"
26 #include "modules_testbase.h"
27 
28 using namespace android::linkerconfig::modules;
29 
30 constexpr const char* kSectionWithNamespacesExpectedResult =
31     R"([test_section]
32 additional.namespaces = namespace1,namespace2
33 namespace.default.isolated = true
34 namespace.default.visible = true
35 namespace.default.search.paths = /search_path1
36 namespace.default.search.paths += /search_path2
37 namespace.default.search.paths += /search_path3
38 namespace.default.permitted.paths = /permitted_path1
39 namespace.default.permitted.paths += /permitted_path2
40 namespace.default.permitted.paths += /permitted_path3
41 namespace.default.asan.search.paths = /data/asan/search_path1
42 namespace.default.asan.search.paths += /search_path1
43 namespace.default.asan.search.paths += /search_path2
44 namespace.default.asan.permitted.paths = /data/asan/permitted_path1
45 namespace.default.asan.permitted.paths += /permitted_path1
46 namespace.default.asan.permitted.paths += /permitted_path2
47 namespace.default.links = namespace1,namespace2
48 namespace.default.link.namespace1.shared_libs = lib1.so
49 namespace.default.link.namespace1.shared_libs += lib2.so
50 namespace.default.link.namespace1.shared_libs += lib3.so
51 namespace.default.link.namespace2.allow_all_shared_libs = true
52 namespace.namespace1.isolated = false
53 namespace.namespace1.search.paths = /search_path1
54 namespace.namespace1.search.paths += /search_path2
55 namespace.namespace1.search.paths += /search_path3
56 namespace.namespace1.permitted.paths = /permitted_path1
57 namespace.namespace1.permitted.paths += /permitted_path2
58 namespace.namespace1.permitted.paths += /permitted_path3
59 namespace.namespace1.asan.search.paths = /data/asan/search_path1
60 namespace.namespace1.asan.search.paths += /search_path1
61 namespace.namespace1.asan.search.paths += /search_path2
62 namespace.namespace1.asan.permitted.paths = /data/asan/permitted_path1
63 namespace.namespace1.asan.permitted.paths += /permitted_path1
64 namespace.namespace1.asan.permitted.paths += /permitted_path2
65 namespace.namespace1.links = default,namespace2
66 namespace.namespace1.link.default.shared_libs = lib1.so
67 namespace.namespace1.link.default.shared_libs += lib2.so
68 namespace.namespace1.link.default.shared_libs += lib3.so
69 namespace.namespace1.link.namespace2.allow_all_shared_libs = true
70 namespace.namespace2.isolated = false
71 namespace.namespace2.search.paths = /search_path1
72 namespace.namespace2.search.paths += /search_path2
73 namespace.namespace2.search.paths += /search_path3
74 namespace.namespace2.permitted.paths = /permitted_path1
75 namespace.namespace2.permitted.paths += /permitted_path2
76 namespace.namespace2.permitted.paths += /permitted_path3
77 namespace.namespace2.asan.search.paths = /data/asan/search_path1
78 namespace.namespace2.asan.search.paths += /search_path1
79 namespace.namespace2.asan.search.paths += /search_path2
80 namespace.namespace2.asan.permitted.paths = /data/asan/permitted_path1
81 namespace.namespace2.asan.permitted.paths += /permitted_path1
82 namespace.namespace2.asan.permitted.paths += /permitted_path2
83 )";
84 
85 constexpr const char* kSectionWithOneNamespaceExpectedResult =
86     R"([test_section]
87 namespace.default.isolated = false
88 namespace.default.search.paths = /search_path1
89 namespace.default.search.paths += /search_path2
90 namespace.default.search.paths += /search_path3
91 namespace.default.permitted.paths = /permitted_path1
92 namespace.default.permitted.paths += /permitted_path2
93 namespace.default.permitted.paths += /permitted_path3
94 namespace.default.asan.search.paths = /data/asan/search_path1
95 namespace.default.asan.search.paths += /search_path1
96 namespace.default.asan.search.paths += /search_path2
97 namespace.default.asan.permitted.paths = /data/asan/permitted_path1
98 namespace.default.asan.permitted.paths += /permitted_path1
99 namespace.default.asan.permitted.paths += /permitted_path2
100 )";
101 
TEST(linkerconfig_section,section_with_namespaces)102 TEST(linkerconfig_section, section_with_namespaces) {
103   ConfigWriter writer;
104 
105   std::vector<Namespace> namespaces;
106 
107   namespaces.emplace_back(CreateNamespaceWithLinks(
108       "default", true, true, "namespace1", "namespace2"));
109   namespaces.emplace_back(CreateNamespaceWithLinks(
110       "namespace1", false, false, "default", "namespace2"));
111   namespaces.emplace_back(CreateNamespaceWithPaths("namespace2", false, false));
112 
113   Section section("test_section", std::move(namespaces));
114 
115   section.WriteConfig(writer);
116   auto config = writer.ToString();
117   ASSERT_EQ(kSectionWithNamespacesExpectedResult, config);
118 }
119 
TEST(linkerconfig_section,section_with_one_namespace)120 TEST(linkerconfig_section, section_with_one_namespace) {
121   android::linkerconfig::modules::ConfigWriter writer;
122 
123   std::vector<Namespace> namespaces;
124   namespaces.emplace_back(CreateNamespaceWithPaths("default", false, false));
125 
126   Section section("test_section", std::move(namespaces));
127   section.WriteConfig(writer);
128   auto config = writer.ToString();
129   ASSERT_EQ(kSectionWithOneNamespaceExpectedResult, config);
130 }
131 
TEST(linkerconfig_section,resolve_contraints)132 TEST(linkerconfig_section, resolve_contraints) {
133   BaseContext ctx;
134   std::vector<Namespace> namespaces;
135   Namespace& foo = namespaces.emplace_back("foo");
136   foo.AddProvides(std::vector{"libfoo.so"});
137   foo.AddRequires(std::vector{"libbar.so"});
138   Namespace& bar = namespaces.emplace_back("bar");
139   bar.AddProvides(std::vector{"libbar.so"});
140   Namespace& baz = namespaces.emplace_back("baz");
141   baz.AddRequires(std::vector{"libfoo.so"});
142 
143   Section section("section", std::move(namespaces));
144   section.Resolve(ctx);
145 
146   ConfigWriter writer;
147   section.WriteConfig(writer);
148 
149   ASSERT_EQ(
150       "[section]\n"
151       "additional.namespaces = bar,baz,foo\n"
152       "namespace.bar.isolated = false\n"
153       "namespace.baz.isolated = false\n"
154       "namespace.baz.links = foo\n"
155       "namespace.baz.link.foo.shared_libs = libfoo.so\n"
156       "namespace.foo.isolated = false\n"
157       "namespace.foo.links = bar\n"
158       "namespace.foo.link.bar.shared_libs = libbar.so\n",
159       writer.ToString());
160 }
161 
TEST(linkerconfig_section,error_if_duplicate_providing)162 TEST(linkerconfig_section, error_if_duplicate_providing) {
163   BaseContext ctx;
164   std::vector<Namespace> namespaces;
165   Namespace& foo1 = namespaces.emplace_back("foo1");
166   foo1.AddProvides(std::vector{"libfoo.so"});
167   Namespace& foo2 = namespaces.emplace_back("foo2");
168   foo2.AddProvides(std::vector{"libfoo.so"});
169   Namespace& bar = namespaces.emplace_back("bar");
170   bar.AddRequires(std::vector{"libfoo.so"});
171 
172   Section section("section", std::move(namespaces));
173   auto result = section.Resolve(ctx);
174   ASSERT_EQ("duplicate: libfoo.so is provided by foo1 and foo2 in [section]",
175             result.error().message());
176 }
177 
TEST(linkerconfig_section,error_if_no_providers_in_strict_mode)178 TEST(linkerconfig_section, error_if_no_providers_in_strict_mode) {
179   BaseContext ctx;
180   ctx.SetStrictMode(true);
181 
182   std::vector<Namespace> namespaces;
183   Namespace& foo = namespaces.emplace_back("foo");
184   foo.AddRequires(std::vector{"libfoo.so"});
185 
186   Section section("section", std::move(namespaces));
187   auto result = section.Resolve(ctx);
188   ASSERT_EQ("not found: libfoo.so is required by foo in [section]",
189             result.error().message());
190 }
191 
TEST(linkerconfig_section,ignore_unmet_requirements)192 TEST(linkerconfig_section, ignore_unmet_requirements) {
193   BaseContext ctx;
194   ctx.SetStrictMode(false);  // default
195 
196   std::vector<Namespace> namespaces;
197   Namespace& foo = namespaces.emplace_back("foo");
198   foo.AddRequires(std::vector{"libfoo.so"});
199 
200   Section section("section", std::move(namespaces));
201   auto result = section.Resolve(ctx);
202   ASSERT_RESULT_OK(result);
203 
204   ConfigWriter writer;
205   section.WriteConfig(writer);
206 
207   ASSERT_EQ(
208       "[section]\n"
209       "namespace.foo.isolated = false\n",
210       writer.ToString());
211 }
212 
TEST_F(ApexTest,resolve_section_with_apex)213 TEST_F(ApexTest, resolve_section_with_apex) {
214   BaseContext ctx;
215   ctx.AddApexModule(PrepareApex("foo", {"a.so"}, {"b.so"}));
216   ctx.AddApexModule(PrepareApex("bar", {"b.so"}, {}));
217   ctx.AddApexModule(PrepareApex("baz", {"c.so"}, {"a.so"}));
218 
219   std::vector<Namespace> namespaces;
220   Namespace& default_ns = namespaces.emplace_back("default");
221   default_ns.AddRequires(std::vector{"a.so", "b.so"});
222 
223   Section section("section", std::move(namespaces));
224   auto result = section.Resolve(ctx);
225 
226   EXPECT_RESULT_OK(result);
227   EXPECT_THAT(
228       std::vector<std::string>{"a.so"},
229       ::testing::ContainerEq(
230           section.GetNamespace("default")->GetLink("foo").GetSharedLibs()));
231   EXPECT_THAT(
232       std::vector<std::string>{"b.so"},
233       ::testing::ContainerEq(
234           section.GetNamespace("default")->GetLink("bar").GetSharedLibs()));
235   EXPECT_THAT(std::vector<std::string>{"b.so"},
236               ::testing::ContainerEq(
237                   section.GetNamespace("foo")->GetLink("bar").GetSharedLibs()));
238   EXPECT_EQ(nullptr, section.GetNamespace("baz"));
239 }
240