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