#![allow(deprecated)] use gpgme; use std::io::prelude::*; use gpgme::{ edit::{self, EditInteractionStatus, Editor}, Error, Result, }; use self::common::passphrase_cb; #[macro_use] mod common; #[derive(Debug, Copy, Clone, Eq, PartialEq)] enum TestEditorState { Start, Fingerprint, Expire, Valid, Uid, Primary, Quit, Save, } impl Default for TestEditorState { fn default() -> Self { TestEditorState::Start } } struct TestEditor; impl Editor for TestEditor { type State = TestEditorState; fn next_state( state: Result, status: EditInteractionStatus<'_>, need_response: bool, ) -> Result { use self::TestEditorState as State; println!("[-- Code: {:?}, {:?} --]", status.code, status.args()); if !need_response { return state; } if status.args() == Ok(edit::PROMPT) { match state { Ok(State::Start) => Ok(State::Fingerprint), Ok(State::Fingerprint) => Ok(State::Expire), Ok(State::Valid) => Ok(State::Uid), Ok(State::Uid) => Ok(State::Primary), Ok(State::Quit) => state, Ok(State::Primary) | Err(_) => Ok(State::Quit), _ => Err(Error::GENERAL), } } else if (status.args() == Ok(edit::KEY_VALID)) && (state == Ok(State::Expire)) { Ok(State::Valid) } else if (status.args() == Ok(edit::CONFIRM_SAVE)) && (state == Ok(State::Quit)) { Ok(State::Save) } else { state.and(Err(Error::GENERAL)) } } fn action(&self, state: Self::State, out: &mut dyn Write) -> Result<()> { use self::TestEditorState as State; match state { State::Fingerprint => out.write_all(b"fpr")?, State::Expire => out.write_all(b"expire")?, State::Valid => out.write_all(b"0")?, State::Uid => out.write_all(b"1")?, State::Primary => out.write_all(b"primary")?, State::Quit => write!(out, "{}", edit::QUIT)?, State::Save => write!(out, "{}", edit::YES)?, _ => return Err(Error::GENERAL), } Ok(()) } } test_case! { test_edit(test) { test.create_context().with_passphrase_provider(passphrase_cb, |ctx| { let key = ctx.find_keys(Some("Alpha")).unwrap().next().unwrap().unwrap(); ctx.edit_key_with(&key, TestEditor, &mut Vec::new()).unwrap(); }); } }