Skip to content

Commit fa7dd2a

Browse files
committed
Fix some tests
These tests would fail on Windows, because Windows paths contain \s, which are interpreted by TOML as Unicode escapes. This commit fixes that issue, as well as removes the dependence on the specific text of the error. These strings are platform dependent, and so these tests will be very fragile. Because the errors are only Strings anyway, I changed the tests to verify an Err was returned, but not which one. A more robust test would require a more robust error type, and I wasn't sure that was worth actually doing yet.
1 parent 09abf77 commit fa7dd2a

File tree

10 files changed

+179
-98
lines changed

10 files changed

+179
-98
lines changed

Cargo.lock

Lines changed: 4 additions & 2 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

Cargo.toml

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,9 @@ tokio = { version = "0.2", features = [ "full" ] }
1919
toml = "0.5.6"
2020
uuid = { version = "0.8", features = [ "serde", "v4" ] }
2121

22+
[dev-dependencies]
23+
libc = "0.2.71"
24+
2225
[dependencies.slog]
2326
version = "2.5"
2427
features = [ "max_level_trace", "release_max_level_debug" ]

dropshot/Cargo.toml

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -30,3 +30,6 @@ uuid = { version = "0.8", features = [ "serde", "v4" ] }
3030
[dependencies.slog]
3131
version = "2.5"
3232
features = [ "max_level_trace", "release_max_level_debug" ]
33+
34+
[dev-dependencies]
35+
libc = "0.2.71"

dropshot/src/lib.rs

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -63,7 +63,8 @@
6363
* ConfigLogging::StderrTerminal {
6464
* level: ConfigLoggingLevel::Info,
6565
* }
66-
* .to_logger("minimal-example")?;
66+
* .to_logger("minimal-example")
67+
* .map_err(|e| e.to_string())?;
6768
*
6869
* // Describe the API.
6970
* let mut api = ApiDescription::new();

dropshot/src/logging.rs

Lines changed: 75 additions & 66 deletions
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@ use slog::Drain;
1010
use slog::Level;
1111
use slog::Logger;
1212
use std::fs::OpenOptions;
13-
use std::path::Path;
13+
use std::{io, path::Path};
1414

1515
/**
1616
* Represents the logging configuration for a server. This is expected to be a
@@ -77,7 +77,7 @@ impl ConfigLogging {
7777
pub fn to_logger<S: AsRef<str>>(
7878
&self,
7979
log_name: S,
80-
) -> Result<Logger, String> {
80+
) -> Result<Logger, io::Error> {
8181
match self {
8282
ConfigLogging::StderrTerminal {
8383
level,
@@ -141,18 +141,12 @@ fn log_drain_for_file(
141141
open_options: &OpenOptions,
142142
path: &Path,
143143
log_name: String,
144-
) -> Result<slog::Fuse<slog_json::Json<std::fs::File>>, String> {
144+
) -> Result<slog::Fuse<slog_json::Json<std::fs::File>>, io::Error> {
145145
if let Some(parent) = path.parent() {
146-
std::fs::create_dir_all(parent).map_err(|e| {
147-
let p = path.display();
148-
format!("open log file \"{}\": {}", p, e)
149-
})?;
146+
std::fs::create_dir_all(parent)?;
150147
}
151148

152-
let file = open_options.open(path).map_err(|e| {
153-
let p = path.display();
154-
format!("open log file \"{}\": {}", p, e)
155-
})?;
149+
let file = open_options.open(path)?;
156150

157151
/*
158152
* Record a message to the stderr so that a reader who doesn't already know
@@ -180,10 +174,11 @@ mod test {
180174
use crate::test_util::verify_bunyan_records_sequential;
181175
use crate::test_util::BunyanLogRecordSpec;
182176
use crate::ConfigLogging;
177+
use libc;
183178
use slog::Logger;
184179
use std::fs;
185180
use std::path::Path;
186-
use std::path::PathBuf;
181+
use std::{io, path::PathBuf};
187182

188183
/**
189184
* Generates a temporary filesystem path unique for the given label.
@@ -207,7 +202,7 @@ mod test {
207202
fn read_config_and_create_logger(
208203
label: &str,
209204
contents: &str,
210-
) -> Result<Logger, String> {
205+
) -> Result<Logger, io::Error> {
211206
let config = read_config::<ConfigLogging>(label, contents).unwrap();
212207
let result = config.to_logger("test-logger");
213208
if let Err(ref error) = result {
@@ -224,7 +219,8 @@ mod test {
224219
fn test_config_bad_log_mode() {
225220
let bad_config = r##" mode = "bonkers" "##;
226221
let error = read_config::<ConfigLogging>("bad_log_mode", bad_config)
227-
.unwrap_err();
222+
.unwrap_err()
223+
.to_string();
228224
assert!(error.starts_with(
229225
"unknown variant `bonkers`, expected `stderr-terminal` or `file` \
230226
for key `mode`"
@@ -243,7 +239,8 @@ mod test {
243239
let bad_config = r##" mode = "stderr-terminal" "##;
244240
assert_eq!(
245241
read_config::<ConfigLogging>("bad_terminal_no_level", bad_config)
246-
.unwrap_err(),
242+
.unwrap_err()
243+
.to_string(),
247244
"missing field `level`"
248245
);
249246
}
@@ -256,7 +253,8 @@ mod test {
256253
"##;
257254
assert_eq!(
258255
read_config::<ConfigLogging>("bad_terminal_bad_level", bad_config)
259-
.unwrap_err(),
256+
.unwrap_err()
257+
.to_string(),
260258
"unknown variant `everything`, expected one of `trace`, `debug`, \
261259
`info`, `warn`, `error`, `critical`"
262260
);
@@ -296,7 +294,8 @@ mod test {
296294
"##;
297295
let error =
298296
read_config::<ConfigLogging>("bad_file_no_file", bad_config)
299-
.unwrap_err();
297+
.unwrap_err()
298+
.to_string();
300299
assert_eq!(error, "missing field `path`");
301300
}
302301

@@ -308,7 +307,8 @@ mod test {
308307
"##;
309308
let error =
310309
read_config::<ConfigLogging>("bad_file_no_level", bad_config)
311-
.unwrap_err();
310+
.unwrap_err()
311+
.to_string();
312312
assert_eq!(error, "missing field `level`");
313313
}
314314

@@ -357,34 +357,32 @@ mod test {
357357

358358
/**
359359
* Records that the caller intends to create a directory with relative
360-
* path "path" underneath the root directory for this log test. Returns
361-
* a String representing the path to this directory. This directory
362-
* will be removed during teardown. Directories and files must be
363-
* recorded in the order they would be created so that the order can be
364-
* reversed at teardown (without needing any kind of recursive removal).
360+
* path "path" underneath the root directory for this log test. Returns
361+
* the path to this directory. This directory will be removed during
362+
* teardown. Directories and files must be recorded in the order they
363+
* would be created so that the order can be reversed at teardown
364+
* (without needing any kind of recursive removal).
365365
*/
366-
fn will_create_dir(&mut self, path: &str) -> String {
366+
fn will_create_dir(&mut self, path: &str) -> PathBuf {
367367
let mut pathbuf = self.directory.clone();
368368
pathbuf.push(path);
369-
let rv = pathbuf.as_path().display().to_string();
370-
self.cleanup_list.push(LogTestCleanup::Directory(pathbuf));
371-
rv
369+
self.cleanup_list.push(LogTestCleanup::Directory(pathbuf.clone()));
370+
pathbuf
372371
}
373372

374373
/**
375374
* Records that the caller intends to create a file with relative path
376-
* "path" underneath the root directory for this log test. Returns a
377-
* String representing the path to this file. This file will be removed
378-
* during teardown. Directories and files must be recorded in the order
379-
* they would be created so that the order can be reversed at teardown
380-
* (without needing any kind of recursive removal).
375+
* "path" underneath the root directory for this log test. Returns a
376+
* the path to this file. This file will be removed during teardown.
377+
* Directories and files must be recorded in the order they would be
378+
* created so that the order can be reversed at teardown (without
379+
* needing any kind of recursive removal).
381380
*/
382-
fn will_create_file(&mut self, path: &str) -> String {
381+
fn will_create_file(&mut self, path: &str) -> PathBuf {
383382
let mut pathbuf = self.directory.clone();
384383
pathbuf.push(path);
385-
let rv = pathbuf.as_path().display().to_string();
386-
self.cleanup_list.push(LogTestCleanup::File(pathbuf));
387-
rv
384+
self.cleanup_list.push(LogTestCleanup::File(pathbuf.clone()));
385+
pathbuf
388386
}
389387
}
390388

@@ -413,26 +411,32 @@ mod test {
413411
let path = logtest.will_create_dir("log_file_as_dir");
414412
fs::create_dir(&path).unwrap();
415413

414+
// Windows paths need to have \ turned into \\
415+
let escaped_path =
416+
path.display().to_string().escape_default().to_string();
417+
416418
let bad_config = format!(
417-
"{}\"{}\"\n",
418-
r##"
419+
r#"
419420
mode = "file"
420421
level = "warn"
421422
if_exists = "append"
422-
path = "##,
423-
&path
423+
path = "{}"
424+
"#,
425+
escaped_path
424426
);
425427

426428
let error = read_config_and_create_logger(
427429
"bad_file_bad_path_type",
428430
&bad_config,
429431
)
430432
.unwrap_err();
431-
let message = format!("{}", error);
432-
assert!(message.starts_with(&format!(
433-
"open log file \"{}\": Is a directory",
434-
&path
435-
)));
433+
434+
if cfg!(windows) {
435+
assert_eq!(error.kind(), std::io::ErrorKind::PermissionDenied);
436+
} else {
437+
assert_eq!(error.kind(), std::io::ErrorKind::Other);
438+
assert_eq!(error.raw_os_error(), Some(libc::EISDIR));
439+
}
436440
}
437441

438442
#[test]
@@ -441,26 +445,27 @@ mod test {
441445
let logpath = logtest.will_create_file("log.out");
442446
fs::write(&logpath, "").expect("writing empty file");
443447

448+
// Windows paths need to have \ turned into \\
449+
let escaped_path =
450+
logpath.display().to_string().escape_default().to_string();
451+
444452
let bad_config = format!(
445-
"{}\"{}\"\n",
446-
r##"
453+
r#"
447454
mode = "file"
448455
level = "warn"
449456
if_exists = "fail"
450-
path = "##,
451-
&logpath
457+
path = "{}"
458+
"#,
459+
escaped_path
452460
);
453461

454462
let error = read_config_and_create_logger(
455463
"bad_file_bad_path_exists_fail",
456464
&bad_config,
457465
)
458466
.unwrap_err();
459-
let message = format!("{}", error);
460-
assert!(message.starts_with(&format!(
461-
"open log file \"{}\": File exists",
462-
&logpath
463-
)));
467+
468+
assert_eq!(error.kind(), std::io::ErrorKind::AlreadyExists);
464469
}
465470

466471
/*
@@ -475,15 +480,19 @@ mod test {
475480
let logpath = logtest.will_create_file("log.out");
476481
let time_before = chrono::offset::Utc::now();
477482

483+
// Windows paths need to have \ turned into \\
484+
let escaped_path =
485+
logpath.display().to_string().escape_default().to_string();
486+
478487
/* The first attempt should succeed. The log file doesn't exist yet. */
479488
let config = format!(
480-
"{}\"{}\"\n",
481-
r##"
489+
r#"
482490
mode = "file"
483491
level = "warn"
484492
if_exists = "fail"
485-
path = "##,
486-
&logpath
493+
path = "{}"
494+
"#,
495+
escaped_path
487496
);
488497

489498
{
@@ -499,13 +508,13 @@ mod test {
499508

500509
/* Try again with if_exists = "append". This should also work. */
501510
let config = format!(
502-
"{}\"{}\"\n",
503-
r##"
511+
r#"
504512
mode = "file"
505513
level = "warn"
506514
if_exists = "append"
507-
path = "##,
508-
&logpath
515+
path = "{}"
516+
"#,
517+
escaped_path
509518
);
510519

511520
{
@@ -541,13 +550,13 @@ mod test {
541550
let time_before = time_after;
542551
let time_after = chrono::offset::Utc::now();
543552
let config = format!(
544-
"{}\"{}\"\n",
545-
r##"
553+
r#"
546554
mode = "file"
547555
level = "trace"
548556
if_exists = "truncate"
549-
path = "##,
550-
&logpath
557+
path = "{}"
558+
"#,
559+
escaped_path
551560
);
552561

553562
{

dropshot/src/test_util.rs

Lines changed: 3 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -625,9 +625,8 @@ pub fn log_file_for_test(test_name: &str) -> PathBuf {
625625
pub fn read_config<T: DeserializeOwned + Debug>(
626626
label: &str,
627627
contents: &str,
628-
) -> Result<T, String> {
629-
let result: Result<T, String> =
630-
toml::from_str(contents).map_err(|error| format!("{}", error));
628+
) -> Result<T, toml::de::Error> {
629+
let result = toml::from_str(contents);
631630
eprintln!("config \"{}\": {:?}", label, result);
632631
result
633632
}
@@ -653,7 +652,7 @@ pub struct BunyanLogRecord {
653652
/**
654653
* Read a file containing a Bunyan-format log, returning an array of records.
655654
*/
656-
pub fn read_bunyan_log(logpath: &str) -> Vec<BunyanLogRecord> {
655+
pub fn read_bunyan_log(logpath: &Path) -> Vec<BunyanLogRecord> {
657656
let log_contents = fs::read_to_string(logpath).unwrap();
658657
let log_records = log_contents
659658
.split("\n")

0 commit comments

Comments
 (0)