comparison testharness/src/bin/testharness.rs @ 163:a75a66cb4181

Add end-to-end tests; fix issues found by tests. - Create tests and installer/remover shell script - Fix Pointer/pointee problems - Add Debug formatting - Misc cleanup
author Paul Fisher <paul@pfish.zone>
date Mon, 14 Jul 2025 17:40:11 -0400
parents a2676475e86b
children 2f5913131295
comparison
equal deleted inserted replaced
162:180237d0b498 163:a75a66cb4181
1 //! The actual program which runs the tests. 1 //! The actual program which runs the tests.
2 2
3 fn main() {} 3 use nonstick::conv::Exchange;
4 use nonstick::items::Items;
5 use nonstick::libpam::TransactionBuilder;
6 use nonstick::{Conversation, ErrorCode, Flags, LibPamTransaction, PamShared, Transaction};
7 use std::cell::Cell;
8 use std::ffi::OsString;
9 use std::os::unix::ffi::OsStrExt;
10
11 fn main() {
12 test_wrong_user();
13 test_wrong_password();
14 test_correct();
15 }
16
17 #[derive(Debug, Default)]
18 struct TestHarness {
19 username_requested: Cell<bool>,
20 wrong_username: bool,
21 wrong_password: bool,
22 changing_password: Cell<bool>,
23 change_prompt_count: Cell<u8>,
24 }
25
26 impl Conversation for &TestHarness {
27 fn communicate(&self, messages: &[Exchange]) {
28 if let [only_msg] = messages {
29 match only_msg {
30 Exchange::Prompt(p) => {
31 if self.username_requested.get() {
32 panic!("username already requested!")
33 }
34 if self.wrong_username {
35 p.set_answer(Ok(OsString::from("not-right")))
36 } else {
37 p.set_answer(Ok(OsString::from("initial")))
38 }
39 self.username_requested.set(true)
40 }
41 Exchange::MaskedPrompt(p) => {
42 let answer = if self.changing_password.get() {
43 let prompts = self.change_prompt_count.get();
44 self.change_prompt_count.set(prompts + 1);
45 match prompts {
46 0 => "mistake",
47 1 => "mismatch",
48 2 => "acceptable",
49 3 => "acceptable",
50 _ => panic!("unexpected number of prompts!"),
51 }
52 } else if self.wrong_password {
53 "bogus"
54 } else {
55 "valid"
56 };
57 p.set_answer(Ok(OsString::from(answer)));
58 }
59 Exchange::Error(e) if self.changing_password.get() => e.set_answer(Ok(())),
60 other => panic!("Unknown message {other:?}!"),
61 }
62 } else {
63 for msg in messages {
64 match msg {
65 Exchange::Info(i) => i.set_answer(Ok(())),
66 Exchange::Error(e) => e.set_answer(Ok(())),
67 Exchange::Prompt(p) => match p.question().as_bytes() {
68 b"How many?" => p.set_answer(Ok(OsString::from("123"))),
69 _ => p.set_answer(Err(ErrorCode::ConversationError)),
70 },
71 Exchange::MaskedPrompt(p) => match p.question().as_bytes() {
72 b"Where?" => p.set_answer(Ok(OsString::from("abc"))),
73 _ => p.set_answer(Err(ErrorCode::ConversationError)),
74 },
75 other => other.set_error(ErrorCode::Abort),
76 }
77 }
78 }
79 }
80 }
81
82 impl TestHarness {
83 fn start(&self) -> LibPamTransaction<&Self> {
84 TransactionBuilder::new_with_service("nonstick-testharness")
85 .build(self)
86 .expect("expected build success")
87 }
88 }
89
90 fn test_wrong_user() {
91 let harness = TestHarness {
92 wrong_username: true,
93 ..Default::default()
94 };
95 let mut tx = harness.start();
96 let auth = tx.authenticate(Flags::empty());
97 assert_eq!(auth, Err(ErrorCode::UserUnknown));
98 }
99
100 fn test_wrong_password() {
101 let harness = TestHarness {
102 wrong_password: true,
103 ..Default::default()
104 };
105 let mut tx = harness.start();
106 let auth = tx.authenticate(Flags::empty());
107 assert_eq!(auth, Err(ErrorCode::AuthenticationError));
108 }
109
110 fn test_correct() {
111 let harness = TestHarness::default();
112 let mut tx = harness.start();
113 tx.authenticate(Flags::empty()).unwrap();
114 assert_eq!(tx.items().user().unwrap().unwrap(), "updated-in-process");
115 let result = tx.account_management(Flags::empty());
116 assert_eq!(result, Err(ErrorCode::NewAuthTokRequired));
117 harness.changing_password.set(true);
118 let change = tx.change_authtok(Flags::CHANGE_EXPIRED_AUTHTOK);
119 assert_eq!(change, Err(ErrorCode::TryAgain));
120 tx.change_authtok(Flags::CHANGE_EXPIRED_AUTHTOK).unwrap();
121 }