1 /*
2  * Copyright (C) 2020 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 <string>
18 
19 #include <android-base/test_utils.h>
20 #include <gtest/gtest.h>
21 
22 #include "Common.h"
23 #include "TypeChecker.h"
24 
25 using android::properties::ParsePropertyInfoFile;
26 using android::properties::PropertyInfoEntry;
27 
28 namespace {
29 
30 constexpr const char* kApi =
31     R"(
32 props {
33     owner: Platform
34     module: "android.platprop"
35     prop {
36         api_name: "prop1"
37         type: Long
38         scope: Public
39         access: ReadWrite
40         prop_name: "prop1"
41     }
42     prop {
43         api_name: "prop2"
44         type: Enum
45         scope: Public
46         access: Writeonce
47         enum_values: "a|b|c"
48         prop_name: "ro.public.prop2"
49     }
50     prop {
51         api_name: "prop3"
52         type: Boolean
53         scope: Public
54         access: ReadWrite
55         prop_name: "ctl.start$prop3"
56     }
57     prop {
58         api_name: "prop4"
59         type: String
60         scope: Public
61         access: Readonly
62         prop_name: "ro.prop4"
63         legacy_prop_name: "ro.legacy.prop4"
64         deprecated: true
65     }
66 
67 }
68 )";
69 
70 constexpr const char* kContexts =
71     R"(
72 prop1           u:object_r:default_prop:s0 exact int
73 ro.public.prop2 u:object_r:foo_prop:s0 exact enum c b a
74 ctl.start$prop3 u:object_r:ctl_prop:s0 exact bool
75 ro.prop4        u:object_r:bar_prop:s0 exact string
76 ro.legacy.prop4 u:object_r:baz_prop:s0 exact string
77 )";
78 
79 constexpr const char* kBadContexts =
80     R"(
81 prop1           u:object_r:default_prop:s0 exact double
82 ro.public.prop2 u:object_r:foo_prop:s0 exact enum a c
83 ctl.start$prop3 u:object_r:ctl_prop:s0 exact string
84 ro.prop4        u:object_r:bar_prop:s0 exact int
85 ro.legacy.prop4 u:object_r:baz_prop:s0 exact bool
86 )";
87 
88 }  // namespace
89 
TEST(SyspropTest,TypeCheckerTest)90 TEST(SyspropTest, TypeCheckerTest) {
91   TemporaryFile api_file;
92   close(api_file.fd);
93   api_file.fd = -1;
94   ASSERT_TRUE(android::base::WriteStringToFile(kApi, api_file.path));
95 
96   std::string err;
97   auto api = ParseApiFile(api_file.path);
98   ASSERT_RESULT_OK(api);
99 
100   // Good property_contexts tests
101   std::vector<PropertyInfoEntry> entries;
102   std::vector<std::string> errors;
103   ParsePropertyInfoFile(kContexts, true, &entries, &errors);
104   ASSERT_TRUE(errors.empty());
105 
106   auto res = CheckPropertyTypes(*api, entries);
107   EXPECT_TRUE(res.ok());
108 
109   // Bad property_contexts tests
110   std::vector<PropertyInfoEntry> bad_entries;
111   ParsePropertyInfoFile(kBadContexts, true, &bad_entries, &errors);
112   ASSERT_TRUE(errors.empty());
113 
114   auto bad_res = CheckPropertyTypes(*api, bad_entries);
115   EXPECT_FALSE(bad_res.ok());
116 
117   EXPECT_EQ(
118       bad_res.error().message(),
119       "Type of prop 'prop1' is incompatible with property_contexts\n"
120       "In sysprop_library: Long\n"
121       "In property_contexts: double (should be 'int')\n"
122       "\n"
123       "Type of prop 'ro.public.prop2' is incompatible with property_contexts\n"
124       "In sysprop_library: Enum a|b|c\n"
125       "In property_contexts: enum a c (should be 'enum a b c')\n"
126       "\n"
127       "Type of prop 'ctl.start$prop3' is incompatible with property_contexts\n"
128       "In sysprop_library: Boolean\n"
129       "In property_contexts: string (should be 'bool')\n"
130       "\n"
131       "Type of prop 'ro.prop4' is incompatible with property_contexts\n"
132       "In sysprop_library: String\n"
133       "In property_contexts: int (should be 'string')\n"
134       "\n"
135       "Type of prop 'ro.legacy.prop4' is incompatible with property_contexts\n"
136       "In sysprop_library: String\n"
137       "In property_contexts: bool (should be 'string')\n");
138 }
139