diff --git a/src/libstd/rt/logging.rs b/src/libstd/rt/logging.rs index a9fd43c23afbe..8a4aba3eb8792 100644 --- a/src/libstd/rt/logging.rs +++ b/src/libstd/rt/logging.rs @@ -15,13 +15,12 @@ use rt::util::dumb_println; use str::StrSlice; use str::raw::from_c_str; use u32; -use u32::{min}; use unstable::raw::Closure; use vec::ImmutableVector; struct LogDirective { - name: ~str, + name: Option<~str>, level: u32 } @@ -74,7 +73,7 @@ static log_level_names : &'static[&'static str] = &'static["error", "warn", "inf fn parse_log_level(level: &str) -> Option { let num = u32::from_str(level); let mut log_level; - match (num) { + match num { Some(num) => { if num < MAX_LOG_LEVEL { log_level = Some(num); @@ -84,9 +83,9 @@ fn parse_log_level(level: &str) -> Option { } _ => { let position = log_level_names.iter().position(|&name| name == level); - match (position) { + match position { Some(position) => { - log_level = Some(min(MAX_LOG_LEVEL, (position + 1) as u32)) + log_level = Some(u32::min(MAX_LOG_LEVEL, (position + 1) as u32)) }, _ => { log_level = None; @@ -108,8 +107,22 @@ fn parse_logging_spec(spec: ~str) -> ~[LogDirective]{ for s in spec.split_iter(',') { let parts: ~[&str] = s.split_iter('=').collect(); let mut log_level; + let mut name = Some(parts[0].to_owned()); match parts.len() { - 1 => log_level = MAX_LOG_LEVEL, + 1 => { + //if the single argument is a log-level string or number, + //treat that as a global fallback + let possible_log_level = parse_log_level(parts[0]); + match possible_log_level { + Some(num) => { + name = None; + log_level = num; + }, + _ => { + log_level = MAX_LOG_LEVEL + } + } + } 2 => { let possible_log_level = parse_log_level(parts[1]); match possible_log_level { @@ -129,7 +142,7 @@ fn parse_logging_spec(spec: ~str) -> ~[LogDirective]{ loop; } } - let dir = LogDirective {name: parts[0].to_owned(), level: log_level}; + let dir = LogDirective {name: name, level: log_level}; dirs.push(dir); } return dirs; @@ -139,18 +152,30 @@ fn parse_logging_spec(spec: ~str) -> ~[LogDirective]{ /// of log directives fn update_entry(dirs: &[LogDirective], entry: *mut ModEntry) -> u32 { let mut new_lvl: u32 = DEFAULT_LOG_LEVEL; - let mut longest_match = 0; + let mut longest_match = -1i; unsafe { for dir in dirs.iter() { - let name = from_c_str((*entry).name); - if name.starts_with(dir.name) && dir.name.len() > longest_match { - longest_match = dir.name.len(); - new_lvl = dir.level; - } + match dir.name { + None => { + if longest_match == -1 { + longest_match = 0; + new_lvl = dir.level; + } + } + Some(ref dir_name) => { + let name = from_c_str((*entry).name); + let len = dir_name.len() as int; + if name.starts_with(*dir_name) && + len >= longest_match { + longest_match = len; + new_lvl = dir.level; + } + } + }; } *(*entry).log_level = new_lvl; } - if longest_match > 0 { return 1; } else { return 0; } + if longest_match >= 0 { return 1; } else { return 0; } } #[fixed_stack_segment] #[inline(never)] @@ -264,54 +289,66 @@ extern { // Tests for parse_logging_spec() #[test] fn parse_logging_spec_valid() { - let dirs: ~[LogDirective] = parse_logging_spec(~"crate1::mod1=1,crate1::mod2,crate2=4"); + let dirs = parse_logging_spec(~"crate1::mod1=1,crate1::mod2,crate2=4"); assert_eq!(dirs.len(), 3); - assert!(dirs[0].name == ~"crate1::mod1"); + assert!(dirs[0].name == Some(~"crate1::mod1")); assert_eq!(dirs[0].level, 1); - assert!(dirs[1].name == ~"crate1::mod2"); + assert!(dirs[1].name == Some(~"crate1::mod2")); assert_eq!(dirs[1].level, MAX_LOG_LEVEL); - assert!(dirs[2].name == ~"crate2"); + assert!(dirs[2].name == Some(~"crate2")); assert_eq!(dirs[2].level, 4); } #[test] fn parse_logging_spec_invalid_crate() { // test parse_logging_spec with multiple = in specification - let dirs: ~[LogDirective] = parse_logging_spec(~"crate1::mod1=1=2,crate2=4"); + let dirs = parse_logging_spec(~"crate1::mod1=1=2,crate2=4"); assert_eq!(dirs.len(), 1); - assert!(dirs[0].name == ~"crate2"); + assert!(dirs[0].name == Some(~"crate2")); assert_eq!(dirs[0].level, 4); } #[test] fn parse_logging_spec_invalid_log_level() { // test parse_logging_spec with 'noNumber' as log level - let dirs: ~[LogDirective] = parse_logging_spec(~"crate1::mod1=noNumber,crate2=4"); + let dirs = parse_logging_spec(~"crate1::mod1=noNumber,crate2=4"); assert_eq!(dirs.len(), 1); - assert!(dirs[0].name == ~"crate2"); + assert!(dirs[0].name == Some(~"crate2")); assert_eq!(dirs[0].level, 4); } #[test] fn parse_logging_spec_string_log_level() { // test parse_logging_spec with 'warn' as log level - let dirs: ~[LogDirective] = parse_logging_spec(~"crate1::mod1=wrong,crate2=warn"); + let dirs = parse_logging_spec(~"crate1::mod1=wrong,crate2=warn"); assert_eq!(dirs.len(), 1); - assert!(dirs[0].name == ~"crate2"); + assert!(dirs[0].name == Some(~"crate2")); assert_eq!(dirs[0].level, 2); } +#[test] +fn parse_logging_spec_global() { + // test parse_logging_spec with no crate + let dirs = parse_logging_spec(~"warn,crate2=4"); + assert_eq!(dirs.len(), 2); + assert!(dirs[0].name == None); + assert_eq!(dirs[0].level, 2); + assert!(dirs[1].name == Some(~"crate2")); + assert_eq!(dirs[1].level, 4); +} + // Tests for update_entry #[test] fn update_entry_match_full_path() { use c_str::ToCStr; - let dirs = ~[LogDirective {name: ~"crate1::mod1", level: 2 }, - LogDirective {name: ~"crate2", level: 3}]; + let dirs = ~[LogDirective {name: Some(~"crate1::mod1"), level: 2 }, + LogDirective {name: Some(~"crate2"), level: 3}]; + let level = &mut 0; unsafe { do "crate1::mod1".to_c_str().with_ref |ptr| { - let entry= &ModEntry {name: ptr, log_level: &mut 0}; + let entry= &ModEntry {name: ptr, log_level: level}; let m = update_entry(dirs, transmute(entry)); assert!(*entry.log_level == 2); assert!(m == 1); @@ -322,11 +359,12 @@ fn update_entry_match_full_path() { #[test] fn update_entry_no_match() { use c_str::ToCStr; - let dirs = ~[LogDirective {name: ~"crate1::mod1", level: 2 }, - LogDirective {name: ~"crate2", level: 3}]; + let dirs = ~[LogDirective {name: Some(~"crate1::mod1"), level: 2 }, + LogDirective {name: Some(~"crate2"), level: 3}]; + let level = &mut 0; unsafe { do "crate3::mod1".to_c_str().with_ref |ptr| { - let entry= &ModEntry {name: ptr, log_level: &mut 0}; + let entry= &ModEntry {name: ptr, log_level: level}; let m = update_entry(dirs, transmute(entry)); assert!(*entry.log_level == DEFAULT_LOG_LEVEL); assert!(m == 0); @@ -337,11 +375,12 @@ fn update_entry_no_match() { #[test] fn update_entry_match_beginning() { use c_str::ToCStr; - let dirs = ~[LogDirective {name: ~"crate1::mod1", level: 2 }, - LogDirective {name: ~"crate2", level: 3}]; + let dirs = ~[LogDirective {name: Some(~"crate1::mod1"), level: 2 }, + LogDirective {name: Some(~"crate2"), level: 3}]; + let level = &mut 0; unsafe { do "crate2::mod1".to_c_str().with_ref |ptr| { - let entry= &ModEntry {name: ptr, log_level: &mut 0}; + let entry= &ModEntry {name: ptr, log_level: level}; let m = update_entry(dirs, transmute(entry)); assert!(*entry.log_level == 3); assert!(m == 1); @@ -352,14 +391,39 @@ fn update_entry_match_beginning() { #[test] fn update_entry_match_beginning_longest_match() { use c_str::ToCStr; - let dirs = ~[LogDirective {name: ~"crate1::mod1", level: 2 }, - LogDirective {name: ~"crate2", level: 3}, LogDirective {name: ~"crate2::mod", level: 4}]; + let dirs = ~[LogDirective {name: Some(~"crate1::mod1"), level: 2 }, + LogDirective {name: Some(~"crate2"), level: 3}, + LogDirective {name: Some(~"crate2::mod"), level: 4}]; + let level = &mut 0; unsafe { do "crate2::mod1".to_c_str().with_ref |ptr| { - let entry = &ModEntry {name: ptr, log_level: &mut 0}; + let entry = &ModEntry {name: ptr, log_level: level}; let m = update_entry(dirs, transmute(entry)); assert!(*entry.log_level == 4); assert!(m == 1); } } } + +#[test] +fn update_entry_match_default() { + use c_str::ToCStr; + let dirs = ~[LogDirective {name: Some(~"crate1::mod1"), level: 2 }, + LogDirective {name: None, level: 3} + ]; + let level = &mut 0; + unsafe { + do "crate1::mod1".to_c_str().with_ref |ptr| { + let entry= &ModEntry {name: ptr, log_level: level}; + let m = update_entry(dirs, transmute(entry)); + assert!(*entry.log_level == 2); + assert!(m == 1); + } + do "crate2::mod2".to_c_str().with_ref |ptr| { + let entry= &ModEntry {name: ptr, log_level: level}; + let m = update_entry(dirs, transmute(entry)); + assert!(*entry.log_level == 3); + assert!(m == 1); + } + } +}