blob: f2008e5926cfc3dbd73096b0358355fe612f8052 [file] [log] [blame]
Inseob Kim900fbad2019-06-26 14:09:20 +09001/*
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 "ApiChecker.h"
18
19#include <string>
20#include <unordered_map>
21
22using android::base::Errorf;
23using android::base::Result;
24
25namespace {
26
27Result<void> CompareProps(const sysprop::Properties& latest,
28 const sysprop::Properties& current) {
29 std::unordered_map<std::string, sysprop::Property> props;
30
31 for (int i = 0; i < current.prop_size(); ++i) {
32 const auto& prop = current.prop(i);
33 props[prop.api_name()] = prop;
34 }
35
36 std::string err;
37
38 bool latest_empty = true;
39 for (int i = 0; i < latest.prop_size(); ++i) {
40 const auto& latest_prop = latest.prop(i);
Inseob Kim715a69e2019-12-03 16:50:50 +090041 if (latest_prop.deprecated() || latest_prop.scope() == sysprop::Internal) {
Inseob Kim900fbad2019-06-26 14:09:20 +090042 continue;
43 }
44
45 latest_empty = false;
46
47 auto itr = props.find(latest_prop.api_name());
48 if (itr == props.end()) {
49 err += "Prop " + latest_prop.api_name() + " has been removed\n";
50 continue;
51 }
52
53 const auto& current_prop = itr->second;
54
55 if (latest_prop.type() != current_prop.type()) {
56 err += "Type of prop " + latest_prop.api_name() + " has been changed\n";
57 }
58 // Readonly > Writeonce > ReadWrite
59 if (latest_prop.access() > current_prop.access()) {
60 err += "Accessibility of prop " + latest_prop.api_name() +
61 " has become more restrictive\n";
62 }
63 // Public < Internal
64 if (latest_prop.scope() < current_prop.scope()) {
65 err += "Scope of prop " + latest_prop.api_name() +
66 " has become more restrictive\n";
67 }
68 if (latest_prop.prop_name() != current_prop.prop_name()) {
69 err += "Underlying property of prop " + latest_prop.api_name() +
70 " has been changed\n";
71 }
72 if (latest_prop.enum_values() != current_prop.enum_values()) {
73 err += "Enum values of prop " + latest_prop.api_name() +
74 " has been changed\n";
75 }
76 if (latest_prop.integer_as_bool() != current_prop.integer_as_bool()) {
77 err += "Integer-as-bool of prop " + latest_prop.api_name() +
78 " has been changed\n";
79 }
80 }
81
82 if (!latest_empty) {
83 if (latest.owner() != current.owner()) {
84 err += "owner of module " + latest.module() + " has been changed\n";
85 }
86 }
87
88 if (err.empty())
89 return {};
90 else
91 return Errorf("{}", err);
92}
93
94} // namespace
95
96Result<void> CompareApis(const sysprop::SyspropLibraryApis& latest,
97 const sysprop::SyspropLibraryApis& current) {
98 std::unordered_map<std::string, sysprop::Properties> propsMap;
99
100 for (int i = 0; i < current.props_size(); ++i) {
101 propsMap[current.props(i).module()] = current.props(i);
102 }
103
104 for (int i = 0; i < latest.props_size(); ++i) {
105 // Checking whether propsMap contains latest.props(i)->module() or not
106 // is intentionally skipped to handle the case that latest.props(i) has
107 // only deprecated properties.
108 if (auto res =
109 CompareProps(latest.props(i), propsMap[latest.props(i).module()]);
110 !res) {
111 return res;
112 }
113 }
114
115 return {};
116}