Add `encode_module_info` unit tests
Bug: 369375199
Test: atest keystore2_test
Change-Id: Ia1cda76e1c65724113708bd1177ccefd8d268b08
diff --git a/keystore2/src/maintenance.rs b/keystore2/src/maintenance.rs
index 7b44ad7..54b5b44 100644
--- a/keystore2/src/maintenance.rs
+++ b/keystore2/src/maintenance.rs
@@ -50,6 +50,9 @@
/// Reexport Domain for the benefit of DeleteListener
pub use android_system_keystore2::aidl::android::system::keystore2::Domain::Domain;
+#[cfg(test)]
+mod tests;
+
/// Version number of KeyMint V4.
pub const KEYMINT_V4: i32 = 400;
diff --git a/keystore2/src/maintenance/tests.rs b/keystore2/src/maintenance/tests.rs
new file mode 100644
index 0000000..fbafa73
--- /dev/null
+++ b/keystore2/src/maintenance/tests.rs
@@ -0,0 +1,182 @@
+// Copyright 2024, The Android Open Source Project
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+//! Maintenance tests.
+use super::*;
+use der::ErrorKind;
+
+#[test]
+fn test_encode_module_info_empty() {
+ let expected = vec![0x31, 0x00];
+ assert_eq!(expected, Maintenance::encode_module_info(Vec::new()).unwrap());
+}
+
+#[test]
+fn test_encode_module_info_same_name() {
+ // Same versions
+ let module_info: Vec<ModuleInfo> = vec![
+ ModuleInfo {
+ name: OctetString::new("com.android.os.statsd".to_string()).unwrap(),
+ version: 25,
+ },
+ ModuleInfo {
+ name: OctetString::new("com.android.os.statsd".to_string()).unwrap(),
+ version: 25,
+ },
+ ];
+ let actual = Maintenance::encode_module_info(module_info);
+ assert!(actual.is_err());
+ assert_eq!(ErrorKind::SetDuplicate, actual.unwrap_err().kind());
+
+ // Different versions
+ let module_info: Vec<ModuleInfo> = vec![
+ ModuleInfo {
+ name: OctetString::new("com.android.os.statsd".to_string()).unwrap(),
+ version: 3,
+ },
+ ModuleInfo {
+ name: OctetString::new("com.android.os.statsd".to_string()).unwrap(),
+ version: 789,
+ },
+ ];
+ let actual = Maintenance::encode_module_info(module_info);
+ assert!(actual.is_err());
+ assert_eq!(ErrorKind::SetDuplicate, actual.unwrap_err().kind());
+}
+
+#[test]
+fn test_encode_module_info_same_name_length() {
+ let module_info: Vec<ModuleInfo> = vec![
+ ModuleInfo { name: OctetString::new("com.android.wifi".to_string()).unwrap(), version: 2 },
+ ModuleInfo { name: OctetString::new("com.android.virt".to_string()).unwrap(), version: 1 },
+ ];
+ let actual = Maintenance::encode_module_info(module_info).unwrap();
+ let expected = hex::decode(concat!(
+ "312e", // SET OF, len 46
+ "3015", // SEQUENCE, len 21
+ "0410", // OCTET STRING, len 16
+ "636f6d2e616e64726f69642e76697274", // "com.android.virt"
+ "020101", // INTEGER len 1 value 1
+ "3015", // SEQUENCE, len 21
+ "0410", // OCTET STRING, len 16
+ "636f6d2e616e64726f69642e77696669", // "com.android.wifi"
+ "020102", // INTEGER len 1 value 2
+ ))
+ .unwrap();
+ assert_eq!(expected, actual);
+}
+
+#[test]
+fn test_encode_module_info_version_irrelevant() {
+ // Versions of the modules are irrelevant for determining encoding order since differing names
+ // guarantee a unique ascending order. See Maintenance::ModuleInfo::der_cmp for more detail.
+ let module_info: Vec<ModuleInfo> = vec![
+ ModuleInfo {
+ name: OctetString::new("com.android.extservices".to_string()).unwrap(),
+ version: 1,
+ },
+ ModuleInfo { name: OctetString::new("com.android.adbd".to_string()).unwrap(), version: 14 },
+ ];
+ let actual = Maintenance::encode_module_info(module_info).unwrap();
+ let expected = hex::decode(concat!(
+ "3135", // SET OF, len 53
+ "3015", // SEQUENCE, len 21
+ "0410", // OCTET STRING, len 16
+ "636f6d2e616e64726f69642e61646264", // "com.android.abdb"
+ "02010e", // INTEGER len 2 value 14
+ "301c", // SEQUENCE, len 28
+ "0417", // OCTET STRING, len 23
+ "636f6d2e616e64726f69642e6578747365727669636573", // "com.android.extservices"
+ "020101", // INTEGER len 1 value 1
+ ))
+ .unwrap();
+ assert_eq!(expected, actual);
+}
+
+#[test]
+fn test_encode_module_info_alphaordering_irrelevant() {
+ // Character ordering of the names of modules is irrelevant for determining encoding order since
+ // differing name lengths guarantee a unique ascending order. See
+ // Maintenance::ModuleInfo::der_cmp for more detail.
+ let module_info: Vec<ModuleInfo> = vec![
+ ModuleInfo {
+ name: OctetString::new("com.android.crashrecovery".to_string()).unwrap(),
+ version: 3,
+ },
+ ModuleInfo { name: OctetString::new("com.android.rkpd".to_string()).unwrap(), version: 8 },
+ ];
+ let actual = Maintenance::encode_module_info(module_info).unwrap();
+ let expected = hex::decode(concat!(
+ "3137", // SET OF, len 55
+ "3015", // SEQUENCE, len 21
+ "0410", // OCTET STRING, len 16
+ "636f6d2e616e64726f69642e726b7064", // "com.android.rkpd"
+ "020108", // INTEGER len 1 value 8
+ "301e", // SEQUENCE, len 30
+ "0419", // OCTET STRING, len 25
+ "636f6d2e616e64726f69642e63726173687265636f76657279", // "com.android.crashrecovery"
+ "020103", // INTEGER len 1 value 3
+ ))
+ .unwrap();
+ assert_eq!(expected, actual);
+}
+
+#[test]
+fn test_encode_module_info() {
+ // Collection of `ModuleInfo`s from a few of the other test_encode_module_info_* tests
+ let module_info: Vec<ModuleInfo> = vec![
+ ModuleInfo { name: OctetString::new("com.android.rkpd".to_string()).unwrap(), version: 8 },
+ ModuleInfo {
+ name: OctetString::new("com.android.extservices".to_string()).unwrap(),
+ version: 1,
+ },
+ ModuleInfo {
+ name: OctetString::new("com.android.crashrecovery".to_string()).unwrap(),
+ version: 3,
+ },
+ ModuleInfo { name: OctetString::new("com.android.wifi".to_string()).unwrap(), version: 2 },
+ ModuleInfo { name: OctetString::new("com.android.virt".to_string()).unwrap(), version: 1 },
+ ModuleInfo { name: OctetString::new("com.android.adbd".to_string()).unwrap(), version: 14 },
+ ];
+ let actual = Maintenance::encode_module_info(module_info).unwrap();
+ let expected = hex::decode(concat!(
+ "31819a", // SET OF, len 154
+ "3015", // SEQUENCE, len 21
+ "0410", // OCTET STRING, len 16
+ "636f6d2e616e64726f69642e61646264", // "com.android.abdb"
+ "02010e", // INTEGER len 2 value 14
+ "3015", // SEQUENCE, len 21
+ "0410", // OCTET STRING, len 16
+ "636f6d2e616e64726f69642e726b7064", // "com.android.rkpd"
+ "020108", // INTEGER len 1 value 8
+ "3015", // SEQUENCE, len 21
+ "0410", // OCTET STRING, len 16
+ "636f6d2e616e64726f69642e76697274", // "com.android.virt"
+ "020101", // INTEGER len 1 value 1
+ "3015", // SEQUENCE, len 21
+ "0410", // OCTET STRING, len 16
+ "636f6d2e616e64726f69642e77696669", // "com.android.wifi"
+ "020102", // INTEGER len 1 value 2
+ "301c", // SEQUENCE, len 28
+ "0417", // OCTET STRING, len 23
+ "636f6d2e616e64726f69642e6578747365727669636573", // "com.android.extservices"
+ "020101", // INTEGER len 1 value 1
+ "301e", // SEQUENCE, len 30
+ "0419", // OCTET STRING, len 25
+ "636f6d2e616e64726f69642e63726173687265636f76657279", // "com.android.crashrecovery"
+ "020103", // INTEGER len 1 value 3
+ ))
+ .unwrap();
+ assert_eq!(expected, actual);
+}