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 #pragma once
17
18 #include <unordered_set>
19
20 #include "gtest/gtest.h"
21 #include "linkerconfigparser.h"
22 #include "modules.h"
23
24 namespace {
TraverseLink(const Namespace & ns,std::unordered_set<std::string> & visible_ns)25 inline void TraverseLink(const Namespace& ns, std::unordered_set<std::string>& visible_ns) {
26 if (visible_ns.count(ns.name) != 0) {
27 return;
28 }
29
30 visible_ns.insert(ns.name);
31
32 for (auto& [_, link] : ns.links) {
33 TraverseLink(*link.to, visible_ns);
34 }
35 }
36
ValidateAllNamespacesAreVisible(const Section & section)37 inline void ValidateAllNamespacesAreVisible(const Section& section) {
38 std::unordered_set<std::string> visible_ns;
39 for (auto& [_, ns] : section.namespaces) {
40 if (ns.name == "default" || ns.is_visible) {
41 TraverseLink(ns, visible_ns);
42 }
43 }
44
45 for (auto& [_, ns] : section.namespaces) {
46 EXPECT_EQ(1u, visible_ns.count(ns.name))
47 << "Namespace " << ns.name << " is not visible from section " << section.name;
48 }
49 }
50
ValidateNamespace(const Namespace & target_namespace,const Section & parent_section)51 inline void ValidateNamespace(const Namespace& target_namespace, const Section& parent_section) {
52 EXPECT_FALSE(target_namespace.name.empty()) << "Namespace name should not be empty";
53 EXPECT_FALSE(target_namespace.name != "default" && target_namespace.search_path.empty() &&
54 target_namespace.permitted_path.empty())
55 << "Search path or permitted path should be defined in namespace " << target_namespace.name
56 << " from section " << parent_section.name;
57 }
58
ValidateSection(const Section & section)59 inline void ValidateSection(const Section& section) {
60 EXPECT_FALSE(section.name.empty()) << "Section name should not be empty";
61 EXPECT_NE(0u, section.namespaces.size())
62 << "Section " << section.name << " should contain at least one namespace";
63 EXPECT_NE(0u, section.dirs.size())
64 << "Section " << section.name << "does not contain any directory as executable path";
65 EXPECT_TRUE(MapContainsKey(section.namespaces, std::string("default")))
66 << "Section " << section.name << " should contain namespace named 'default'";
67
68 for (auto& [_, target_namespace] : section.namespaces) {
69 ValidateNamespace(target_namespace, section);
70 }
71
72 ValidateAllNamespacesAreVisible(section);
73 }
74
ValidateConfiguration(const Configuration & conf)75 inline void ValidateConfiguration(const Configuration& conf) {
76 EXPECT_NE(0u, conf.sections.size());
77 for (auto& [_, section] : conf.sections) {
78 ValidateSection(section);
79 }
80 }
81 } // namespace
82
VerifyConfiguration(const std::string & configuration_str)83 inline void VerifyConfiguration(const std::string& configuration_str) {
84 Configuration conf;
85 ParseConfiguration(configuration_str, conf);
86 ValidateConfiguration(conf);
87 }
88