use super::*;
use kcode_k1_access_profile_values::ProfileOwner;
fn tx(byte: u8) -> TxId {
TxId::from_bytes([byte; 12])
}
fn profile() -> AuthorizationProfile {
AuthorizationProfile::new(vec![ProfileOwner::RequestUser], Vec::new()).unwrap()
}
fn root() -> PathBuf {
std::env::temp_dir().join(format!("profile-sqlite-test-{}", std::process::id()))
}
#[test]
fn color_actions_privacy_and_rebuildable_state() {
let root = root();
fs::remove_dir_all(&root).ok();
let owner = UserId::from_tx_id(tx(1));
let stranger = UserId::from_tx_id(tx(9));
let (database, _) = ProfileDatabase::open(&root).unwrap();
database
.apply(
tx(2),
ProfileAction::Create {
owner,
profile: profile(),
},
)
.unwrap();
let name = ProfileName::new("Named".to_owned()).unwrap();
database
.apply(
tx(3),
ProfileAction::CreateNamed {
owner,
name: name.clone(),
profile: profile(),
},
)
.unwrap();
assert!(
database
.list_for_user(owner)
.unwrap()
.iter()
.all(|saved| saved.color().is_none())
);
let cyan = ProfileColor::new("cyan".to_owned()).unwrap();
database
.apply(
tx(4),
ProfileAction::CreateNamedColored {
owner,
name,
color: Some(cyan.clone()),
profile: profile(),
},
)
.unwrap();
let id = ProfileId::new(tx(4));
assert_eq!(database.get_for_user(stranger, id).unwrap(), None);
assert!(database.list_for_user(stranger).unwrap().is_empty());
let equal = ProfileAction::SetColor {
profile_id: id,
actor: owner,
color: Some(cyan),
};
assert_eq!(
database.apply(tx(5), equal).unwrap(),
ApplyOutcome::Unchanged(ProfileRevision::new(id, tx(4)))
);
let rose = ProfileColor::new("rose".to_owned()).unwrap();
let denied = ProfileAction::SetColor {
profile_id: id,
actor: stranger,
color: Some(rose.clone()),
};
assert_eq!(database.apply(tx(6), denied).unwrap(), unavailable());
database
.apply(
tx(7),
ProfileAction::SetColor {
profile_id: id,
actor: owner,
color: Some(rose),
},
)
.unwrap();
let saved = database.get_for_user(owner, id).unwrap().unwrap();
assert_eq!(
(saved.color().unwrap().as_str(), saved.revision()),
("rose", ProfileRevision::new(id, tx(7)))
);
drop(database);
let raw = Connection::open(root.join(DATABASE_FILE)).unwrap();
raw.execute("UPDATE profiles SET color='purple'", [])
.unwrap();
drop(raw);
assert!(matches!(
ProfileDatabase::open(&root),
Err(OpenError::Rebuildable)
));
fs::remove_dir_all(&root).unwrap();
fs::create_dir_all(&root).unwrap();
let raw = Connection::open(root.join(DATABASE_FILE)).unwrap();
raw.execute_batch("CREATE TABLE metadata(schema_version INTEGER NOT NULL CHECK(schema_version=1), last_applied_txid BLOB CHECK(last_applied_txid IS NULL OR (typeof(last_applied_txid)='blob' AND length(last_applied_txid)=12)));
CREATE TABLE profiles(profile_id BLOB PRIMARY KEY NOT NULL CHECK(typeof(profile_id)='blob' AND length(profile_id)=12), owner BLOB NOT NULL CHECK(typeof(owner)='blob' AND length(owner)=12), revision BLOB NOT NULL CHECK(typeof(revision)='blob' AND length(revision)=12), name TEXT NOT NULL, profile BLOB NOT NULL CHECK(typeof(profile)='blob')) WITHOUT ROWID;
CREATE INDEX profiles_owner ON profiles(owner);
INSERT INTO metadata(schema_version, last_applied_txid) VALUES(1, NULL);").unwrap();
drop(raw);
assert!(matches!(
ProfileDatabase::open(&root),
Err(OpenError::Rebuildable)
));
fs::remove_dir_all(root).unwrap();
}