blob: a563fb9955101821fe842d54ba23cf1f6c3ffe15 [file] [log] [blame]
// Copyright 2021 The Fuchsia Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
use fidl_fuchsia_io as fio;
/// Set of all rights that are valid to use with the conformance test harness.
const ALL_RIGHTS_FLAGS: fio::OpenFlags = fio::OpenFlags::empty()
.union(fio::OpenFlags::RIGHT_READABLE)
.union(fio::OpenFlags::RIGHT_WRITABLE)
.union(fio::OpenFlags::RIGHT_EXECUTABLE);
/// Helper struct that encapsulates generation of valid/invalid sets of flags based on
/// which rights are supported by a particular node type.
pub struct Rights {
rights: fio::OpenFlags,
}
impl Rights {
/// Creates a new Rights struct based on a bitset of OPEN_RIGHT_* flags OR'd together.
pub fn new(rights: fio::OpenFlags) -> Rights {
assert_eq!(rights & !ALL_RIGHTS_FLAGS, fio::OpenFlags::empty());
Rights { rights }
}
/// Returns the bitset of all supported OPEN_RIGHT_* flags.
pub fn all(&self) -> fio::OpenFlags {
self.rights
}
/// Returns a vector of all valid flag combinations.
pub fn valid_combos(&self) -> Vec<fio::OpenFlags> {
vfs::test_utils::build_flag_combinations(fio::OpenFlags::empty(), self.rights)
}
/// Returns a vector of all valid flag combinations that include the specified `with_flags`.
/// Will be empty if none of the requested rights are supported.
pub fn valid_combos_with(&self, with_flags: fio::OpenFlags) -> Vec<fio::OpenFlags> {
let mut flag_combos = self.valid_combos();
flag_combos.retain(|&flags| flags.contains(with_flags));
flag_combos
}
/// Returns a vector of all valid flag combinations that exclude the specified `without_flags`.
/// Will be empty if none are supported.
pub fn valid_combos_without(&self, without_flags: fio::OpenFlags) -> Vec<fio::OpenFlags> {
let mut flag_combos = self.valid_combos();
flag_combos.retain(|&flags| !flags.intersects(without_flags));
flag_combos
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_rights_combos() {
const TEST_RIGHTS: fio::OpenFlags = fio::OpenFlags::empty()
.union(fio::OpenFlags::RIGHT_READABLE)
.union(fio::OpenFlags::RIGHT_WRITABLE)
.union(fio::OpenFlags::RIGHT_EXECUTABLE);
// We should get 0, R, W, X, RW, RX, WX, RWX (8 in total).
const EXPECTED_COMBOS: [fio::OpenFlags; 8] = [
fio::OpenFlags::empty(),
fio::OpenFlags::RIGHT_READABLE,
fio::OpenFlags::RIGHT_WRITABLE,
fio::OpenFlags::RIGHT_EXECUTABLE,
fio::OpenFlags::empty()
.union(fio::OpenFlags::RIGHT_READABLE)
.union(fio::OpenFlags::RIGHT_WRITABLE),
fio::OpenFlags::empty()
.union(fio::OpenFlags::RIGHT_READABLE)
.union(fio::OpenFlags::RIGHT_EXECUTABLE),
fio::OpenFlags::empty()
.union(fio::OpenFlags::RIGHT_WRITABLE)
.union(fio::OpenFlags::RIGHT_EXECUTABLE),
fio::OpenFlags::empty()
.union(fio::OpenFlags::RIGHT_READABLE)
.union(fio::OpenFlags::RIGHT_WRITABLE)
.union(fio::OpenFlags::RIGHT_EXECUTABLE),
];
let rights = Rights::new(TEST_RIGHTS);
assert_eq!(rights.all(), TEST_RIGHTS);
// Test that all possible combinations are generated correctly.
let all_combos = rights.valid_combos();
assert_eq!(all_combos.len(), EXPECTED_COMBOS.len());
for expected_rights in EXPECTED_COMBOS {
assert!(all_combos.contains(&expected_rights));
}
// Test that combinations including READABLE are generated correctly.
// We should get R, RW, RX, and RWX (4 in total).
const EXPECTED_READABLE_COMBOS: [fio::OpenFlags; 4] = [
fio::OpenFlags::RIGHT_READABLE,
fio::OpenFlags::empty()
.union(fio::OpenFlags::RIGHT_READABLE)
.union(fio::OpenFlags::RIGHT_WRITABLE),
fio::OpenFlags::empty()
.union(fio::OpenFlags::RIGHT_READABLE)
.union(fio::OpenFlags::RIGHT_EXECUTABLE),
fio::OpenFlags::empty()
.union(fio::OpenFlags::RIGHT_READABLE)
.union(fio::OpenFlags::RIGHT_WRITABLE)
.union(fio::OpenFlags::RIGHT_EXECUTABLE),
];
let readable_combos = rights.valid_combos_with(fio::OpenFlags::RIGHT_READABLE);
assert_eq!(readable_combos.len(), EXPECTED_READABLE_COMBOS.len());
for expected_rights in EXPECTED_READABLE_COMBOS {
assert!(readable_combos.contains(&expected_rights));
}
// Test that combinations excluding READABLE are generated correctly.
// We should get 0, W, X, and WX (4 in total).
const EXPECTED_NONREADABLE_COMBOS: [fio::OpenFlags; 4] = [
fio::OpenFlags::empty(),
fio::OpenFlags::RIGHT_WRITABLE,
fio::OpenFlags::RIGHT_EXECUTABLE,
fio::OpenFlags::empty()
.union(fio::OpenFlags::RIGHT_WRITABLE)
.union(fio::OpenFlags::RIGHT_EXECUTABLE),
];
let nonreadable_combos = rights.valid_combos_without(fio::OpenFlags::RIGHT_READABLE);
assert_eq!(nonreadable_combos.len(), EXPECTED_NONREADABLE_COMBOS.len());
for expected_rights in EXPECTED_NONREADABLE_COMBOS {
assert!(nonreadable_combos.contains(&expected_rights));
}
}
#[test]
#[should_panic]
fn test_rights_unsupported() {
// Passing anything other than OPEN_RIGHT_* should fail.
Rights::new(fio::OpenFlags::CREATE);
}
}