• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /* Copyright (C) 2023 The Android Open Source Project
2  *
3  * Licensed under the Apache License, Version 2.0 (the "License");
4  * you may not use this file except in compliance with the License.
5  * You may obtain a copy of the License at
6  *
7  *      http://www.apache.org/licenses/LICENSE-2.0
8  *
9  * Unless required by applicable law or agreed to in writing, software
10  * distributed under the License is distributed on an "AS IS" BASIS,
11  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12  * See the License for the specific language governing permissions and
13  * limitations under the License.
14  */
15 #include <android-base/file.h>
16 #include <android-base/test_utils.h>
17 #include <gtest/gtest.h>
18 #include <unistd.h>
19 
20 #include <string>
21 
22 #include "RustGen.h"
23 
24 using namespace std::string_literals;
25 
26 namespace {
27 
28 constexpr const char* kTestSyspropFile =
29     R"(owner: Platform
30 module: "android.sysprop.PlatformProperties"
31 prop {
32     api_name: "test_double"
33     type: Double
34     prop_name: "android.test_double"
35     scope: Internal
36     access: ReadWrite
37 }
38 prop {
39     api_name: "test_int"
40     type: Integer
41     prop_name: "android.test_int"
42     scope: Public
43     access: ReadWrite
44 }
45 prop {
46     api_name: "test_string"
47     type: String
48     prop_name: "android.test.string"
49     scope: Public
50     access: Readonly
51     legacy_prop_name: "legacy.android.test.string"
52 }
53 prop {
54     api_name: "test_enum"
55     type: Enum
56     prop_name: "android.test.enum"
57     enum_values: "a|b|c|D|e|f|G"
58     scope: Internal
59     access: ReadWrite
60 }
61 prop {
62     api_name: "test_BOOLeaN"
63     type: Boolean
64     prop_name: "ro.android.test.b"
65     scope: Public
66     access: Writeonce
67 }
68 prop {
69     api_name: "android_os_test-long"
70     type: Long
71     scope: Public
72     access: ReadWrite
73 }
74 prop {
75     api_name: "test_double_list"
76     type: DoubleList
77     scope: Internal
78     access: ReadWrite
79 }
80 prop {
81     api_name: "test_list_int"
82     type: IntegerList
83     scope: Public
84     access: ReadWrite
85 }
86 prop {
87     api_name: "test_strlist"
88     type: StringList
89     scope: Public
90     access: ReadWrite
91     deprecated: true
92 }
93 prop {
94     api_name: "el"
95     type: EnumList
96     enum_values: "enu|mva|lue"
97     scope: Internal
98     access: ReadWrite
99     deprecated: true
100 }
101 )";
102 
103 constexpr const char* kExpectedPublicOutput =
104     R"(//! Autogenerated system property accessors.
105 //!
106 //! This is an autogenerated module. The module contains methods for typed access to
107 //! Android system properties.
108 
109 // Generated by the sysprop generator. DO NOT EDIT!
110 
111 use std::fmt;
112 use rustutils::system_properties::{self, parsers_formatters};
113 pub use rustutils::system_properties::error::SysPropError;
114 
115 /// The property name of the "test_int" API.
116 pub const TEST_INT_PROP: &str = "android.test_int";
117 
118 /// Returns the value of the property 'android.test_int' if set.
119 pub fn test_int() -> std::result::Result<Option<i32>, SysPropError> {
120     let result = match system_properties::read(TEST_INT_PROP) {
121         Err(e) => Err(SysPropError::FetchError(e)),
122         Ok(Some(val)) => parsers_formatters::parse(val.as_str()).map_err(SysPropError::ParseError).map(Some),
123         Ok(None) => Ok(None),
124     };
125     result
126 }
127 
128 /// Sets the value of the property 'android.test_int', returns 'Ok' if successful.
129 pub fn set_test_int(v: i32) -> std::result::Result<(), SysPropError> {
130     let value = parsers_formatters::format(&v);
131     system_properties::write(TEST_INT_PROP, value.as_str()).map_err(SysPropError::SetError)
132 }
133 
134 /// The property name of the "test_string" API.
135 pub const TEST_STRING_PROP: &str = "android.test.string";
136 
137 /// Returns the value of the property 'android.test.string' if set.
138 pub fn test_string() -> std::result::Result<Option<String>, SysPropError> {
139     let result = match system_properties::read(TEST_STRING_PROP) {
140         Err(e) => Err(SysPropError::FetchError(e)),
141         Ok(Some(val)) => parsers_formatters::parse(val.as_str()).map_err(SysPropError::ParseError).map(Some),
142         Ok(None) => Ok(None),
143     };
144     if result.is_ok() { return result; }
145     log::debug!("Failed to fetch the original property 'android.test.string' ('{}'), falling back to the legacy one 'legacy.android.test.string'.", result.unwrap_err());
146     match system_properties::read("legacy.android.test.string") {
147         Err(e) => Err(SysPropError::FetchError(e)),
148         Ok(Some(val)) => parsers_formatters::parse(val.as_str()).map_err(SysPropError::ParseError).map(Some),
149         Ok(None) => Ok(None),
150     }
151 }
152 
153 /// The property name of the "test_boo_lea_n" API.
154 pub const TEST_BOO_LEA_N_PROP: &str = "ro.android.test.b";
155 
156 /// Returns the value of the property 'ro.android.test.b' if set.
157 pub fn test_boo_lea_n() -> std::result::Result<Option<bool>, SysPropError> {
158     let result = match system_properties::read(TEST_BOO_LEA_N_PROP) {
159         Err(e) => Err(SysPropError::FetchError(e)),
160         Ok(Some(val)) => parsers_formatters::parse_bool(val.as_str()).map_err(SysPropError::ParseError).map(Some),
161         Ok(None) => Ok(None),
162     };
163     result
164 }
165 
166 /// Sets the value of the property 'ro.android.test.b', returns 'Ok' if successful.
167 pub fn set_test_boo_lea_n(v: bool) -> std::result::Result<(), SysPropError> {
168     let value = parsers_formatters::format_bool(&v);
169     system_properties::write(TEST_BOO_LEA_N_PROP, value.as_str()).map_err(SysPropError::SetError)
170 }
171 
172 /// The property name of the "android_os_test_long" API.
173 pub const ANDROID_OS_TEST_LONG_PROP: &str = "android_os_test-long";
174 
175 /// Returns the value of the property 'android_os_test-long' if set.
176 pub fn android_os_test_long() -> std::result::Result<Option<i64>, SysPropError> {
177     let result = match system_properties::read(ANDROID_OS_TEST_LONG_PROP) {
178         Err(e) => Err(SysPropError::FetchError(e)),
179         Ok(Some(val)) => parsers_formatters::parse(val.as_str()).map_err(SysPropError::ParseError).map(Some),
180         Ok(None) => Ok(None),
181     };
182     result
183 }
184 
185 /// Sets the value of the property 'android_os_test-long', returns 'Ok' if successful.
186 pub fn set_android_os_test_long(v: i64) -> std::result::Result<(), SysPropError> {
187     let value = parsers_formatters::format(&v);
188     system_properties::write(ANDROID_OS_TEST_LONG_PROP, value.as_str()).map_err(SysPropError::SetError)
189 }
190 
191 /// The property name of the "test_list_int" API.
192 pub const TEST_LIST_INT_PROP: &str = "test_list_int";
193 
194 /// Returns the value of the property 'test_list_int' if set.
195 pub fn test_list_int() -> std::result::Result<Option<Vec<i32>>, SysPropError> {
196     let result = match system_properties::read(TEST_LIST_INT_PROP) {
197         Err(e) => Err(SysPropError::FetchError(e)),
198         Ok(Some(val)) => parsers_formatters::parse_list(val.as_str()).map_err(SysPropError::ParseError).map(Some),
199         Ok(None) => Ok(None),
200     };
201     result
202 }
203 
204 /// Sets the value of the property 'test_list_int', returns 'Ok' if successful.
205 pub fn set_test_list_int(v: &[i32]) -> std::result::Result<(), SysPropError> {
206     let value = parsers_formatters::format_list(v);
207     system_properties::write(TEST_LIST_INT_PROP, value.as_str()).map_err(SysPropError::SetError)
208 }
209 
210 /// The property name of the "test_strlist" API.
211 pub const TEST_STRLIST_PROP: &str = "test_strlist";
212 
213 /// Returns the value of the property 'test_strlist' if set.
214 #[deprecated]
215 pub fn test_strlist() -> std::result::Result<Option<Vec<String>>, SysPropError> {
216     let result = match system_properties::read(TEST_STRLIST_PROP) {
217         Err(e) => Err(SysPropError::FetchError(e)),
218         Ok(Some(val)) => parsers_formatters::parse_list(val.as_str()).map_err(SysPropError::ParseError).map(Some),
219         Ok(None) => Ok(None),
220     };
221     result
222 }
223 
224 /// Sets the value of the property 'test_strlist', returns 'Ok' if successful.
225 #[deprecated]
226 pub fn set_test_strlist(v: &[String]) -> std::result::Result<(), SysPropError> {
227     let value = parsers_formatters::format_list(v);
228     system_properties::write(TEST_STRLIST_PROP, value.as_str()).map_err(SysPropError::SetError)
229 }
230 
231 )";
232 
233 constexpr const char* kExpectedInternalOutput =
234     R"(//! Autogenerated system property accessors.
235 //!
236 //! This is an autogenerated module. The module contains methods for typed access to
237 //! Android system properties.
238 
239 // Generated by the sysprop generator. DO NOT EDIT!
240 
241 use std::fmt;
242 use rustutils::system_properties::{self, parsers_formatters};
243 pub use rustutils::system_properties::error::SysPropError;
244 
245 /// The property name of the "test_double" API.
246 pub const TEST_DOUBLE_PROP: &str = "android.test_double";
247 
248 /// Returns the value of the property 'android.test_double' if set.
249 pub fn test_double() -> std::result::Result<Option<f64>, SysPropError> {
250     let result = match system_properties::read(TEST_DOUBLE_PROP) {
251         Err(e) => Err(SysPropError::FetchError(e)),
252         Ok(Some(val)) => parsers_formatters::parse(val.as_str()).map_err(SysPropError::ParseError).map(Some),
253         Ok(None) => Ok(None),
254     };
255     result
256 }
257 
258 /// Sets the value of the property 'android.test_double', returns 'Ok' if successful.
259 pub fn set_test_double(v: f64) -> std::result::Result<(), SysPropError> {
260     let value = parsers_formatters::format(&v);
261     system_properties::write(TEST_DOUBLE_PROP, value.as_str()).map_err(SysPropError::SetError)
262 }
263 
264 /// The property name of the "test_int" API.
265 pub const TEST_INT_PROP: &str = "android.test_int";
266 
267 /// Returns the value of the property 'android.test_int' if set.
268 pub fn test_int() -> std::result::Result<Option<i32>, SysPropError> {
269     let result = match system_properties::read(TEST_INT_PROP) {
270         Err(e) => Err(SysPropError::FetchError(e)),
271         Ok(Some(val)) => parsers_formatters::parse(val.as_str()).map_err(SysPropError::ParseError).map(Some),
272         Ok(None) => Ok(None),
273     };
274     result
275 }
276 
277 /// Sets the value of the property 'android.test_int', returns 'Ok' if successful.
278 pub fn set_test_int(v: i32) -> std::result::Result<(), SysPropError> {
279     let value = parsers_formatters::format(&v);
280     system_properties::write(TEST_INT_PROP, value.as_str()).map_err(SysPropError::SetError)
281 }
282 
283 /// The property name of the "test_string" API.
284 pub const TEST_STRING_PROP: &str = "android.test.string";
285 
286 /// Returns the value of the property 'android.test.string' if set.
287 pub fn test_string() -> std::result::Result<Option<String>, SysPropError> {
288     let result = match system_properties::read(TEST_STRING_PROP) {
289         Err(e) => Err(SysPropError::FetchError(e)),
290         Ok(Some(val)) => parsers_formatters::parse(val.as_str()).map_err(SysPropError::ParseError).map(Some),
291         Ok(None) => Ok(None),
292     };
293     if result.is_ok() { return result; }
294     log::debug!("Failed to fetch the original property 'android.test.string' ('{}'), falling back to the legacy one 'legacy.android.test.string'.", result.unwrap_err());
295     match system_properties::read("legacy.android.test.string") {
296         Err(e) => Err(SysPropError::FetchError(e)),
297         Ok(Some(val)) => parsers_formatters::parse(val.as_str()).map_err(SysPropError::ParseError).map(Some),
298         Ok(None) => Ok(None),
299     }
300 }
301 
302 /// The property name of the "test_enum" API.
303 pub const TEST_ENUM_PROP: &str = "android.test.enum";
304 
305 #[allow(missing_docs)]
306 #[derive(Copy, Clone, Debug, Eq, PartialEq, PartialOrd, Hash, Ord)]
307 pub enum TestEnumValues {
308     A,
309     B,
310     C,
311     D,
312     E,
313     F,
314     G,
315 }
316 
317 impl std::str::FromStr for TestEnumValues {
318     type Err = String;
319 
320     fn from_str(s: &str) -> std::result::Result<Self, Self::Err> {
321         match s {
322             "a" => Ok(TestEnumValues::A),
323             "b" => Ok(TestEnumValues::B),
324             "c" => Ok(TestEnumValues::C),
325             "D" => Ok(TestEnumValues::D),
326             "e" => Ok(TestEnumValues::E),
327             "f" => Ok(TestEnumValues::F),
328             "G" => Ok(TestEnumValues::G),
329             _ => Err(format!("'{}' cannot be parsed for TestEnumValues", s)),
330         }
331     }
332 }
333 
334 impl fmt::Display for TestEnumValues {
335     fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
336         match self {
337             TestEnumValues::A => write!(f, "a"),
338             TestEnumValues::B => write!(f, "b"),
339             TestEnumValues::C => write!(f, "c"),
340             TestEnumValues::D => write!(f, "D"),
341             TestEnumValues::E => write!(f, "e"),
342             TestEnumValues::F => write!(f, "f"),
343             TestEnumValues::G => write!(f, "G"),
344         }
345     }
346 }
347 
348 /// Returns the value of the property 'android.test.enum' if set.
349 pub fn test_enum() -> std::result::Result<Option<TestEnumValues>, SysPropError> {
350     let result = match system_properties::read(TEST_ENUM_PROP) {
351         Err(e) => Err(SysPropError::FetchError(e)),
352         Ok(Some(val)) => parsers_formatters::parse(val.as_str()).map_err(SysPropError::ParseError).map(Some),
353         Ok(None) => Ok(None),
354     };
355     result
356 }
357 
358 /// Sets the value of the property 'android.test.enum', returns 'Ok' if successful.
359 pub fn set_test_enum(v: TestEnumValues) -> std::result::Result<(), SysPropError> {
360     let value = parsers_formatters::format(&v);
361     system_properties::write(TEST_ENUM_PROP, value.as_str()).map_err(SysPropError::SetError)
362 }
363 
364 /// The property name of the "test_boo_lea_n" API.
365 pub const TEST_BOO_LEA_N_PROP: &str = "ro.android.test.b";
366 
367 /// Returns the value of the property 'ro.android.test.b' if set.
368 pub fn test_boo_lea_n() -> std::result::Result<Option<bool>, SysPropError> {
369     let result = match system_properties::read(TEST_BOO_LEA_N_PROP) {
370         Err(e) => Err(SysPropError::FetchError(e)),
371         Ok(Some(val)) => parsers_formatters::parse_bool(val.as_str()).map_err(SysPropError::ParseError).map(Some),
372         Ok(None) => Ok(None),
373     };
374     result
375 }
376 
377 /// Sets the value of the property 'ro.android.test.b', returns 'Ok' if successful.
378 pub fn set_test_boo_lea_n(v: bool) -> std::result::Result<(), SysPropError> {
379     let value = parsers_formatters::format_bool(&v);
380     system_properties::write(TEST_BOO_LEA_N_PROP, value.as_str()).map_err(SysPropError::SetError)
381 }
382 
383 /// The property name of the "android_os_test_long" API.
384 pub const ANDROID_OS_TEST_LONG_PROP: &str = "android_os_test-long";
385 
386 /// Returns the value of the property 'android_os_test-long' if set.
387 pub fn android_os_test_long() -> std::result::Result<Option<i64>, SysPropError> {
388     let result = match system_properties::read(ANDROID_OS_TEST_LONG_PROP) {
389         Err(e) => Err(SysPropError::FetchError(e)),
390         Ok(Some(val)) => parsers_formatters::parse(val.as_str()).map_err(SysPropError::ParseError).map(Some),
391         Ok(None) => Ok(None),
392     };
393     result
394 }
395 
396 /// Sets the value of the property 'android_os_test-long', returns 'Ok' if successful.
397 pub fn set_android_os_test_long(v: i64) -> std::result::Result<(), SysPropError> {
398     let value = parsers_formatters::format(&v);
399     system_properties::write(ANDROID_OS_TEST_LONG_PROP, value.as_str()).map_err(SysPropError::SetError)
400 }
401 
402 /// The property name of the "test_double_list" API.
403 pub const TEST_DOUBLE_LIST_PROP: &str = "test_double_list";
404 
405 /// Returns the value of the property 'test_double_list' if set.
406 pub fn test_double_list() -> std::result::Result<Option<Vec<f64>>, SysPropError> {
407     let result = match system_properties::read(TEST_DOUBLE_LIST_PROP) {
408         Err(e) => Err(SysPropError::FetchError(e)),
409         Ok(Some(val)) => parsers_formatters::parse_list(val.as_str()).map_err(SysPropError::ParseError).map(Some),
410         Ok(None) => Ok(None),
411     };
412     result
413 }
414 
415 /// Sets the value of the property 'test_double_list', returns 'Ok' if successful.
416 pub fn set_test_double_list(v: &[f64]) -> std::result::Result<(), SysPropError> {
417     let value = parsers_formatters::format_list(v);
418     system_properties::write(TEST_DOUBLE_LIST_PROP, value.as_str()).map_err(SysPropError::SetError)
419 }
420 
421 /// The property name of the "test_list_int" API.
422 pub const TEST_LIST_INT_PROP: &str = "test_list_int";
423 
424 /// Returns the value of the property 'test_list_int' if set.
425 pub fn test_list_int() -> std::result::Result<Option<Vec<i32>>, SysPropError> {
426     let result = match system_properties::read(TEST_LIST_INT_PROP) {
427         Err(e) => Err(SysPropError::FetchError(e)),
428         Ok(Some(val)) => parsers_formatters::parse_list(val.as_str()).map_err(SysPropError::ParseError).map(Some),
429         Ok(None) => Ok(None),
430     };
431     result
432 }
433 
434 /// Sets the value of the property 'test_list_int', returns 'Ok' if successful.
435 pub fn set_test_list_int(v: &[i32]) -> std::result::Result<(), SysPropError> {
436     let value = parsers_formatters::format_list(v);
437     system_properties::write(TEST_LIST_INT_PROP, value.as_str()).map_err(SysPropError::SetError)
438 }
439 
440 /// The property name of the "test_strlist" API.
441 pub const TEST_STRLIST_PROP: &str = "test_strlist";
442 
443 /// Returns the value of the property 'test_strlist' if set.
444 #[deprecated]
445 pub fn test_strlist() -> std::result::Result<Option<Vec<String>>, SysPropError> {
446     let result = match system_properties::read(TEST_STRLIST_PROP) {
447         Err(e) => Err(SysPropError::FetchError(e)),
448         Ok(Some(val)) => parsers_formatters::parse_list(val.as_str()).map_err(SysPropError::ParseError).map(Some),
449         Ok(None) => Ok(None),
450     };
451     result
452 }
453 
454 /// Sets the value of the property 'test_strlist', returns 'Ok' if successful.
455 #[deprecated]
456 pub fn set_test_strlist(v: &[String]) -> std::result::Result<(), SysPropError> {
457     let value = parsers_formatters::format_list(v);
458     system_properties::write(TEST_STRLIST_PROP, value.as_str()).map_err(SysPropError::SetError)
459 }
460 
461 /// The property name of the "el" API.
462 pub const EL_PROP: &str = "el";
463 
464 #[allow(missing_docs)]
465 #[derive(Copy, Clone, Debug, Eq, PartialEq, PartialOrd, Hash, Ord)]
466 pub enum ElValues {
467     Enu,
468     Mva,
469     Lue,
470 }
471 
472 impl std::str::FromStr for ElValues {
473     type Err = String;
474 
475     fn from_str(s: &str) -> std::result::Result<Self, Self::Err> {
476         match s {
477             "enu" => Ok(ElValues::Enu),
478             "mva" => Ok(ElValues::Mva),
479             "lue" => Ok(ElValues::Lue),
480             _ => Err(format!("'{}' cannot be parsed for ElValues", s)),
481         }
482     }
483 }
484 
485 impl fmt::Display for ElValues {
486     fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
487         match self {
488             ElValues::Enu => write!(f, "enu"),
489             ElValues::Mva => write!(f, "mva"),
490             ElValues::Lue => write!(f, "lue"),
491         }
492     }
493 }
494 
495 /// Returns the value of the property 'el' if set.
496 #[deprecated]
497 pub fn el() -> std::result::Result<Option<Vec<ElValues>>, SysPropError> {
498     let result = match system_properties::read(EL_PROP) {
499         Err(e) => Err(SysPropError::FetchError(e)),
500         Ok(Some(val)) => parsers_formatters::parse_list(val.as_str()).map_err(SysPropError::ParseError).map(Some),
501         Ok(None) => Ok(None),
502     };
503     result
504 }
505 
506 /// Sets the value of the property 'el', returns 'Ok' if successful.
507 #[deprecated]
508 pub fn set_el(v: &[ElValues]) -> std::result::Result<(), SysPropError> {
509     let value = parsers_formatters::format_list(v);
510     system_properties::write(EL_PROP, value.as_str()).map_err(SysPropError::SetError)
511 }
512 
513 )";
514 
RustGenTest(sysprop::Scope scope,const char * expected_output)515 void RustGenTest(sysprop::Scope scope, const char* expected_output) {
516   TemporaryFile temp_file;
517 
518   // strlen is optimized for constants, so don't worry about it.
519   ASSERT_EQ(write(temp_file.fd, kTestSyspropFile, strlen(kTestSyspropFile)),
520             strlen(kTestSyspropFile));
521   close(temp_file.fd);
522   temp_file.fd = -1;
523 
524   TemporaryDir temp_dir;
525   std::string rust_output_path = temp_dir.path + "/mod.rs"s;
526 
527   ASSERT_RESULT_OK(GenerateRustLibrary(temp_file.path, scope, temp_dir.path));
528 
529   std::string rust_output;
530   ASSERT_TRUE(
531       android::base::ReadFileToString(rust_output_path, &rust_output, true));
532   EXPECT_EQ(rust_output, expected_output);
533 
534   unlink(rust_output.c_str());
535   rmdir((temp_dir.path + "/com/somecompany"s).c_str());
536   rmdir((temp_dir.path + "/com"s).c_str());
537 }
538 
539 }  // namespace
540 
TEST(SyspropTest,RustGenTestInternal)541 TEST(SyspropTest, RustGenTestInternal) {
542   RustGenTest(sysprop::Scope::Internal, kExpectedInternalOutput);
543 }
544 
TEST(SyspropTest,RustGenTestPublic)545 TEST(SyspropTest, RustGenTestPublic) {
546   RustGenTest(sysprop::Scope::Public, kExpectedPublicOutput);
547 }
548