Skip to content

Commit 1fb1154

Browse files
committed
check if err returned when password required but not set
1 parent c2e7fc3 commit 1fb1154

File tree

2 files changed

+127
-5
lines changed

2 files changed

+127
-5
lines changed

crates/advent-of-code-data/src/cache.rs

Lines changed: 24 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,10 @@ use crate::{
1515

1616
#[derive(Debug, Error)]
1717
pub enum CacheError {
18+
#[error("AOC encryption token expected but not provided (check your config)")]
19+
EncryptionTokenNotSet,
20+
#[error("Cached input file is not encrypted but encryption token was provided")]
21+
EncryptionTokenNotNeeded,
1822
#[error("base 64 decoding failed: {}", .0)]
1923
DecodeBase64(#[from] base64::DecodeError),
2024
#[error("decryption failed: {}", .0)]
@@ -116,15 +120,30 @@ impl PuzzleCache for PuzzleFsCache {
116120

117121
fn load_input(&self, day: Day, year: Year) -> Result<String, CacheError> {
118122
// Load the cached input file from disk.
119-
let input_path =
120-
Self::input_file_path(&self.cache_dir, day, year, self.encryption_token.is_some());
121-
tracing::debug!("loading input for day {day} year {year} from {input_path:?}");
123+
let using_encryption = self.encryption_token.is_some();
124+
let input_path = Self::input_file_path(&self.cache_dir, day, year, using_encryption);
125+
126+
// Check for the existence or non-existence of the input file, and hint
127+
// to the user if encryption seems to be incorrectly configured.
128+
if !std::fs::exists(&input_path)? {
129+
let alt_input_path =
130+
Self::input_file_path(&self.cache_dir, day, year, !using_encryption);
131+
132+
match (
133+
std::fs::exists(&alt_input_path).unwrap_or(false),
134+
using_encryption,
135+
) {
136+
(true, false) => return Err(CacheError::EncryptionTokenNotSet),
137+
(true, true) => return Err(CacheError::EncryptionTokenNotNeeded),
138+
_ => {}
139+
}
140+
}
122141

142+
// Read the input file.
143+
tracing::debug!("loading input for day {day} year {year} from {input_path:?}");
123144
let mut input_text = std::fs::read_to_string(input_path)?;
124145

125146
// Decrypt the input data.
126-
// TODO: Add error check to see if input file is encrypted and the password
127-
// token is `None` leading to encrypted input passed to puzzle.
128147
if let Some(encryption_token) = &self.encryption_token {
129148
let encrypted_bytes = BASE64_STANDARD
130149
.decode(input_text.as_bytes())

tests/test_cache_fs.rs

Lines changed: 103 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -36,6 +36,31 @@ fn persist_puzzle_input() {
3636
assert_eq!(&read_cached_input(Day(3), Year(2000)), "foobar");
3737
}
3838

39+
#[test]
40+
fn try_load_unencrypted_input() {
41+
let cache_dir = tempdir().unwrap();
42+
let encryption_token: Option<String> = None;
43+
44+
// Write input data with a temporary client.
45+
{
46+
let puzzle_cache = PuzzleFsCache::new(cache_dir.path(), encryption_token.clone());
47+
puzzle_cache
48+
.save_input("foobar", Day(19), Year(2000))
49+
.unwrap();
50+
}
51+
52+
// Read input data back with another temporary client.
53+
let read_cached_input = |day: Day, year: Year| {
54+
let puzzle_cache = PuzzleFsCache::new(cache_dir.path(), encryption_token.clone());
55+
puzzle_cache.try_load_input(day, year).unwrap()
56+
};
57+
58+
assert_eq!(
59+
read_cached_input(Day(19), Year(2000)),
60+
Some("foobar".to_string())
61+
);
62+
}
63+
3964
#[test]
4065
fn try_load_input_exists() {
4166
let cache_dir = tempdir().unwrap();
@@ -83,3 +108,81 @@ fn try_load_missing_puzzle_input() {
83108

84109
assert!(result.is_none())
85110
}
111+
112+
#[test]
113+
fn load_input_err_if_wrong_password() {
114+
let cache_dir = tempdir().unwrap();
115+
116+
// Write encrypted input data with a temporary client.
117+
{
118+
let encryption_token = Some("TEST".to_string());
119+
let puzzle_cache = PuzzleFsCache::new(cache_dir.path(), encryption_token);
120+
puzzle_cache
121+
.save_input("foobar", Day(19), Year(2000))
122+
.unwrap();
123+
}
124+
125+
// Read input data back with another temporary client.
126+
let read_cached_input = |day: Day, year: Year| {
127+
let encryption_token = Some("wrong password".to_string());
128+
let puzzle_cache = PuzzleFsCache::new(cache_dir.path(), encryption_token);
129+
puzzle_cache.load_input(day, year)
130+
};
131+
132+
assert!(matches!(
133+
read_cached_input(Day(19), Year(2000)),
134+
Err(CacheError::Decryption(_))
135+
));
136+
}
137+
138+
#[test]
139+
fn load_input_err_if_password_missing() {
140+
let cache_dir = tempdir().unwrap();
141+
142+
// Write encrypted input data with a temporary client.
143+
{
144+
let encryption_token = Some("TEST".to_string());
145+
let puzzle_cache = PuzzleFsCache::new(cache_dir.path(), encryption_token);
146+
puzzle_cache
147+
.save_input("foobar", Day(19), Year(2000))
148+
.unwrap();
149+
}
150+
151+
// Read input data back with another temporary client.
152+
let read_cached_input = |day: Day, year: Year| {
153+
let encryption_token: Option<String> = None;
154+
let puzzle_cache = PuzzleFsCache::new(cache_dir.path(), encryption_token);
155+
puzzle_cache.load_input(day, year)
156+
};
157+
158+
assert!(matches!(
159+
read_cached_input(Day(19), Year(2000)),
160+
Err(CacheError::EncryptionTokenNotSet)
161+
));
162+
}
163+
164+
#[test]
165+
fn load_input_err_uses_unencrypted_input_if_possible() {
166+
let cache_dir = tempdir().unwrap();
167+
168+
// Write encrypted input data with a temporary client.
169+
{
170+
let encryption_token: Option<String> = None;
171+
let puzzle_cache = PuzzleFsCache::new(cache_dir.path(), encryption_token);
172+
puzzle_cache
173+
.save_input("foobar", Day(19), Year(2000))
174+
.unwrap();
175+
}
176+
177+
// Read input data back with another temporary client.
178+
let read_cached_input = |day: Day, year: Year| {
179+
let encryption_token = Some("TEST".to_string());
180+
let puzzle_cache = PuzzleFsCache::new(cache_dir.path(), encryption_token);
181+
puzzle_cache.load_input(day, year)
182+
};
183+
184+
assert!(matches!(
185+
read_cached_input(Day(19), Year(2000)),
186+
Err(CacheError::EncryptionTokenNotNeeded)
187+
));
188+
}

0 commit comments

Comments
 (0)