use chrono::Duration;
use sd_id128::*;
use sd_journal::*;
use std::{ffi::CString,
path::{Path, PathBuf}};
fn open_testdata() -> sd_journal::Journal {
let mut test_data = PathBuf::from(env!("CARGO_MANIFEST_DIR"));
test_data.push("test-data/");
println!("looking for test data in folder {}", test_data.display());
Journal::open_directory(&test_data, PathFlags::FullPath, UserFlags::AllUsers).unwrap()
}
#[test]
fn log_message() {
Journal::log_message(Level::Info, "Hello World!").unwrap();
Journal::log_message(Level::Info, String::from("Hello World!").as_str()).unwrap();
Journal::log_message(Level::Info, String::from("Hello World!")).unwrap();
Journal::log_message(Level::Info, CString::new("Hello World!").unwrap()).unwrap();
}
#[test]
fn log_raw_record() {
Journal::log_message(Level::Info, "Hello World!").unwrap();
Journal::log_raw_record(&["PRIORITY=6", "MESSAGE=Hello World!"]).unwrap();
Journal::log_raw_record(&vec![format!("PRIORITY={}", Level::Info),
"MESSAGE=Hello World!".to_string(),
format!("CODE_LINE={}", line!()),
format!("CODE_FILE={}", file!()),
"CUSTOM_FIELD=42".to_string()]).unwrap();
Journal::log_raw_record(&["MESSAGE=Hello World!",
&format!("PRIORITY={}", Level::Info),
&format!("CODE_FILE={}", file!()),
&format!("CODE_LINE={}", line!()),
"CUSTOM_FIELD=42"]).unwrap();
}
#[test]
fn get_catalog_for_message_id() {
let journal = Journal::open(FileFlags::AllFiles, UserFlags::AllUsers).unwrap();
loop {
match journal.next() {
Ok(CursorMovement::EoF) => break,
Ok(_) => (),
Err(_) => break
}
let id = match journal.get_data("MESSAGE_ID") {
Err(_) => continue,
Ok(value) => value
};
println!("Message ID: {}", id);
let id128 = sd_id128::ID128::from_str(&id).unwrap();
let catalog = match Journal::get_catalog_for_message_id(id128) {
Err(_) => continue,
Ok(v) => v
};
println!("{}", catalog);
break;
}
}
#[test]
fn open() {
Journal::open(FileFlags::AllFiles, UserFlags::AllUsers).unwrap();
Journal::open(FileFlags::LocalOnly, UserFlags::CurrentUserOnly).unwrap();
Journal::open(FileFlags::RuntimeOnly, UserFlags::CurrentUserAndSystemOnly).unwrap();
Journal::open(FileFlags::LocalOnly, UserFlags::SystemOnly).unwrap();
Journal::open(FileFlags::LocalRuntimeOnly,
UserFlags::CurrentUserAndSystemOnly).unwrap();
}
#[test]
fn open_namespace() {
Journal::open_namespace("namespace",
NamespaceFlags::DefaultNamespaceIncluded,
FileFlags::LocalOnly,
UserFlags::AllUsers).unwrap();
let journal = Journal::open_namespace("akjghöowighjökvndsövlljsk",
NamespaceFlags::SelectedNamespaceOnly,
FileFlags::AllFiles,
UserFlags::AllUsers).unwrap();
assert_eq!(journal.next().unwrap(), CursorMovement::EoF);
}
#[test]
fn open_all_namespaces() {
let journal = Journal::open_all_namespaces(FileFlags::AllFiles, UserFlags::AllUsers).unwrap();
assert_eq!(journal.next().unwrap(), CursorMovement::Done);
}
#[test]
fn open_directory() {
Journal::open_directory("/", PathFlags::PathToOSRoot, UserFlags::AllUsers).unwrap();
Journal::open_directory(Path::new("/"), PathFlags::PathToOSRoot, UserFlags::AllUsers).unwrap();
Journal::open_directory(PathBuf::from("/"),
PathFlags::PathToOSRoot,
UserFlags::AllUsers).unwrap();
let mut test_data = PathBuf::from(env!("CARGO_MANIFEST_DIR"));
test_data.push("test-data/");
println!("looking for test data in folder {}", test_data.display());
Journal::open_directory(test_data, PathFlags::FullPath, UserFlags::AllUsers).unwrap();
Journal::open_directory("/...", PathFlags::FullPath, UserFlags::AllUsers).unwrap_err();
}
#[test]
fn open_files() {
let machine_id = sd_id128::ID128::machine_id().unwrap()
.to_string_sd()
.unwrap();
let mut sdjournal_path = PathBuf::from("/var/log/journal/");
sdjournal_path.push(&machine_id);
sdjournal_path.push("system.journal");
println!("looking for sd-journal in {}", sdjournal_path.display());
Journal::open_files([sdjournal_path]).unwrap();
let mut test_data = PathBuf::from(env!("CARGO_MANIFEST_DIR"));
test_data.push("test-data/test.journal");
println!("looking for test data in {}", test_data.display());
Journal::open_files([test_data]).unwrap();
Journal::open_files(vec!["/abcdefghijk.xyz"]).unwrap_err();
}
#[test]
fn next() {
let mut test_data = PathBuf::from(env!("CARGO_MANIFEST_DIR"));
test_data.push("test-data/");
println!("looking for test data in folder {}", test_data.display());
let journal =
Journal::open_directory(&test_data, PathFlags::FullPath, UserFlags::AllUsers).unwrap();
while let Ok(CursorMovement::Done) = journal.next() {
println!("{}", journal.get_data("MESSAGE").unwrap());
}
journal.seek_tail().unwrap();
journal.previous().unwrap();
assert_eq!(journal.next().unwrap(), CursorMovement::EoF);
}
#[test]
fn iter() {
let mut test_data = PathBuf::from(env!("CARGO_MANIFEST_DIR"));
test_data.push("test-data/");
println!("looking for test data in folder {}", test_data.display());
let journal =
Journal::open_directory(&test_data, PathFlags::FullPath, UserFlags::AllUsers).unwrap();
for cursor in journal.iter() {
match cursor {
Err(_) => break,
Ok(cursor) => println!("{}", cursor.get_data("MESSAGE").unwrap())
}
}
journal.seek_head().unwrap();
let cursor = journal.iter_reverse().next().unwrap().unwrap();
let m1 = cursor.get_data("MESSAGE").unwrap();
let m2 = journal.get_data("MESSAGE").unwrap();
assert_eq!(m1, m2);
}
#[test]
fn previous() {
let mut test_data = PathBuf::from(env!("CARGO_MANIFEST_DIR"));
test_data.push("test-data/");
println!("looking for test data in folder {}", test_data.display());
let journal =
Journal::open_directory(&test_data, PathFlags::FullPath, UserFlags::AllUsers).unwrap();
journal.seek_tail().unwrap();
while let Ok(CursorMovement::Done) = journal.previous() {
println!("{}", journal.get_data("MESSAGE").unwrap());
}
journal.seek_head().unwrap();
journal.next().unwrap();
assert_eq!(journal.previous().unwrap(), CursorMovement::EoF);
}
#[test]
fn iter_reverse() {
let mut test_data = PathBuf::from(env!("CARGO_MANIFEST_DIR"));
test_data.push("test-data/");
println!("looking for test data in folder {}", test_data.display());
let journal =
Journal::open_directory(&test_data, PathFlags::FullPath, UserFlags::AllUsers).unwrap();
journal.seek_tail().unwrap();
for cursor in journal.iter_reverse() {
match cursor {
Err(_) => break,
Ok(cursor) => println!("{}", cursor.get_data("MESSAGE").unwrap())
}
}
journal.seek_tail().unwrap();
let cursor = journal.iter_reverse().next().unwrap().unwrap();
let m1 = cursor.get_data("MESSAGE").unwrap();
let m2 = journal.get_data("MESSAGE").unwrap();
assert_eq!(m1, m2);
}
#[test]
fn next_skip() {
let journal = Journal::open(FileFlags::AllFiles, UserFlags::AllUsers).unwrap();
journal.seek_tail().unwrap();
journal.previous().unwrap();
journal.previous_skip(5).unwrap();
assert_eq!(journal.next_skip(10).unwrap(), CursorMovement::Limited(5));
}
#[test]
fn previous_skip() {
let journal = Journal::open(FileFlags::AllFiles, UserFlags::AllUsers).unwrap();
journal.seek_head().unwrap();
journal.next().unwrap();
journal.next_skip(5).unwrap();
assert_eq!(journal.previous_skip(10).unwrap(),
CursorMovement::Limited(5));
}
#[test]
fn seek_head() {
let journal = Journal::open(FileFlags::AllFiles, UserFlags::AllUsers).unwrap();
journal.seek_head().unwrap();
journal.next().unwrap();
assert_eq!(journal.previous(), Ok(CursorMovement::EoF));
}
#[test]
fn seek_tail() {
let journal = Journal::open(FileFlags::AllFiles, UserFlags::AllUsers).unwrap();
journal.seek_tail().unwrap();
journal.previous().unwrap();
assert_eq!(journal.next(), Ok(CursorMovement::EoF));
}
#[test]
fn seek_monotonic() {
let journal = Journal::open(FileFlags::AllFiles, UserFlags::AllUsers).unwrap();
let boot_id = ID128::boot_id().unwrap();
let (from, _) = journal.get_monotonic_cutoff(boot_id.clone()).unwrap();
journal.seek_monotonic(boot_id.clone(), from).unwrap();
journal.previous().unwrap();
let (mono_journal, bid_journal) = journal.get_monotonic().unwrap();
assert_eq!(mono_journal, from);
assert_eq!(bid_journal, boot_id);
}
#[test]
fn seek_realtime() {
let journal = Journal::open(FileFlags::AllFiles, UserFlags::AllUsers).unwrap();
let now = chrono::offset::Local::now().naive_local();
journal.seek_realtime(now).unwrap();
journal.previous().unwrap();
let clock_last_entry = journal.get_realtime().unwrap();
assert!(clock_last_entry <= now);
journal.seek_tail().unwrap();
journal.previous().unwrap();
let clock_tail = journal.get_realtime().unwrap();
assert_eq!(clock_last_entry, clock_tail);
let (start, end) = journal.get_realtime_cutoff().unwrap();
assert_eq!(clock_last_entry, end);
let bstart = start.checked_sub_signed(chrono::Duration::seconds(6))
.unwrap();
journal.seek_realtime(bstart).unwrap();
journal.next().unwrap();
assert_eq!(start, journal.get_realtime().unwrap());
let aend = end.checked_add_signed(Duration::seconds(10)).unwrap();
journal.seek_realtime(aend).unwrap();
journal.previous().unwrap();
assert_eq!(end, journal.get_realtime().unwrap());
}
#[test]
fn seek_cursor_id() {
let journal = Journal::open(FileFlags::AllFiles, UserFlags::AllUsers).unwrap();
journal.seek_tail().unwrap();
journal.previous_skip(10).unwrap();
let cursor = journal.get_cursor_id().unwrap();
println!("initial cursor: {:?}", cursor);
journal.seek_head().unwrap();
journal.next().unwrap();
journal.seek_cursor_id(cursor.clone()).unwrap();
journal.previous().unwrap();
let same_cursor = journal.get_cursor_id().unwrap();
println!("same cursor: {:?}", same_cursor);
assert_eq!(cursor, same_cursor);
journal.next().unwrap();
let other_cursor = journal.get_cursor_id().unwrap();
println!("other cursor: {:?}", other_cursor);
assert_ne!(cursor, other_cursor);
}
#[test]
fn add_match() {
let journal = Journal::open(FileFlags::AllFiles, UserFlags::AllUsers).unwrap();
journal.add_match("MESSAGE=Hello World!").unwrap();
assert_eq!(journal.next().unwrap(), CursorMovement::Done);
while let Ok(CursorMovement::Done) = journal.next() {
}
journal.flush_matches();
journal.add_match("MESSAGE=Hello Woooooorld!").unwrap();
assert_eq!(journal.next().unwrap(), CursorMovement::EoF);
journal.add_match("MESSAGE=Hello Woooooorld!").unwrap();
journal.add_match(&"MESSAGE=Hello Woooooorld!").unwrap();
journal.add_match("MESSAGE=Hello Woooooorld!".to_string())
.unwrap();
}
#[test]
fn add_disjunction() {
let journal = open_testdata();
journal.add_match(b"MESSAGE=Hello Woooooorld!").unwrap();
journal.add_disjunction().unwrap();
journal.add_match(b"_TRANSPORT=journal").unwrap();
assert_eq!(journal.next().unwrap(), CursorMovement::Done);
}
#[test]
fn add_conjunction() {
let journal = open_testdata();
journal.add_match(b"MESSAGE=Hello Woooooorld!").unwrap();
journal.add_conjunction().unwrap();
journal.add_match(b"_TRANSPORT=journal").unwrap();
assert_eq!(journal.next().unwrap(), CursorMovement::EoF);
}
#[test]
fn flush_matches() {
let journal = open_testdata();
journal.add_match(b"MESSAGE=Hello Woooooorld!").unwrap();
assert_eq!(journal.next().unwrap(), CursorMovement::EoF);
journal.flush_matches();
assert_eq!(journal.next().unwrap(), CursorMovement::Done);
}
#[test]
fn get_realtime_cutoff() {
let journal = open_testdata();
let (from, to) = journal.get_realtime_cutoff().unwrap();
println!("{} - {}", from, to);
assert!(from < to);
}
#[test]
fn get_monotonic_cutoff() {
let journal = Journal::open(FileFlags::AllFiles, UserFlags::AllUsers).unwrap();
let (from, to) = journal.get_monotonic_cutoff(sd_id128::ID128::boot_id().unwrap())
.unwrap();
println!("{} - {}", from, to);
assert!(from < to);
}
#[test]
fn set_treshold() {
let journal = Journal::open(FileFlags::AllFiles, UserFlags::AllUsers).unwrap();
journal.set_data_treshold(5).unwrap();
}
#[test]
fn get_treshold() {
let journal = Journal::open(FileFlags::AllFiles, UserFlags::AllUsers).unwrap();
let old = journal.get_data_treshold().unwrap();
println!("old value: {}", old);
journal.set_data_treshold(5).unwrap();
let new = journal.get_data_treshold().unwrap();
println!("new value: {}", new);
assert!(old != new);
assert_eq!(new, 5);
journal.set_data_treshold(0).unwrap();
let ulimited = journal.get_data_treshold().unwrap();
println!("ulimited value: {}", ulimited);
assert_eq!(ulimited, 0);
}
#[test]
fn enumerate_field_names() {
let journal = Journal::open(FileFlags::AllFiles, UserFlags::AllUsers).unwrap();
loop {
match journal.enumerate_field_names().unwrap() {
Enumeration::EoF => break,
Enumeration::Value(string) => println!("{}", string)
}
}
}
#[test]
fn restart_fields() {
let journal = Journal::open(FileFlags::AllFiles, UserFlags::AllUsers).unwrap();
loop {
match journal.enumerate_field_names().unwrap() {
Enumeration::EoF => break,
Enumeration::Value(string) => {
if string == "MESSAGE" {
println!("Field 'MESSAGE' found for the first time. Let's restart \
enumeration.");
journal.restart_field_name_enumeration();
break;
}
},
}
}
loop {
match journal.enumerate_field_names().unwrap() {
Enumeration::EoF => break,
Enumeration::Value(string) => {
if string == "MESSAGE" {
println!("Field 'MESSAGE' found for the second time. Restart seems to work \
fine.");
return;
}
},
}
}
panic!("Test failed: Field Message was either not existing at all or restart did not work.");
}
#[test]
fn iter_field_names() {
let journal = Journal::open(FileFlags::AllFiles, UserFlags::AllUsers).unwrap();
for fieldname in journal.iter_field_names() {
println!("{}", fieldname.unwrap());
}
}
#[test]
fn get_fd() {
let journal = Journal::open(FileFlags::AllFiles, UserFlags::AllUsers).unwrap();
journal.get_fd().unwrap();
}
#[test]
fn get_events() {
let journal = Journal::open(FileFlags::AllFiles, UserFlags::AllUsers).unwrap();
journal.get_events().unwrap();
}
#[test]
fn get_timeout() {
let journal = Journal::open(FileFlags::AllFiles, UserFlags::AllUsers).unwrap();
journal.get_timeout().unwrap();
}
#[test]
fn process() {
let journal = Journal::open(FileFlags::AllFiles, UserFlags::AllUsers).unwrap();
journal.process().unwrap();
}
#[test]
fn wait() {
let journal = Journal::open(FileFlags::AllFiles, UserFlags::AllUsers).unwrap();
journal.seek_tail().unwrap();
journal.wait(10).unwrap();
}
#[test]
fn has_runtime_files() {
let journal = Journal::open(FileFlags::AllFiles, UserFlags::AllUsers).unwrap();
journal.has_runtime_files().unwrap();
}
#[test]
fn has_persistent_files() {
let journal = Journal::open(FileFlags::AllFiles, UserFlags::AllUsers).unwrap();
journal.has_persistent_files().unwrap();
}
#[test]
fn get_usage() {
let journal = Journal::open(FileFlags::AllFiles, UserFlags::AllUsers).unwrap();
println!("usage in bytes: {}", journal.get_usage().unwrap());
assert!(journal.get_usage().unwrap() > 0);
}
#[test]
fn get_realtime() {
let journal = open_testdata();
journal.next().unwrap();
println!("realtime at journal head: {}",
journal.get_realtime().unwrap());
journal.seek_tail().unwrap();
journal.previous().unwrap();
println!("realtime at journal tail: {}",
journal.get_realtime().unwrap());
}
#[test]
fn get_monotonic() {
let journal = open_testdata();
journal.next().unwrap();
println!("monotonic at journal head: ({}, {})",
journal.get_monotonic().unwrap().0,
journal.get_monotonic().unwrap().1);
journal.seek_tail().unwrap();
journal.previous().unwrap();
println!("monotonic at journal tail: ({}, {})",
journal.get_monotonic().unwrap().0,
journal.get_monotonic().unwrap().1);
}
#[test]
fn get_cursor_id() {
let journal = Journal::open(FileFlags::AllFiles, UserFlags::AllUsers).unwrap();
journal.next().unwrap();
println!("{:?}", journal.get_cursor_id().unwrap());
}
#[test]
fn cursor_id_matches() {
let journal = Journal::open(FileFlags::AllFiles, UserFlags::AllUsers).unwrap();
journal.next().unwrap();
let cursor = journal.get_cursor_id().unwrap();
assert_eq!(journal.cursor_id_matches(cursor.clone()).unwrap(), true);
journal.next().unwrap();
assert_eq!(journal.cursor_id_matches(cursor.clone()).unwrap(), false);
}
#[test]
fn get_catalog() {
let journal = Journal::open(FileFlags::AllFiles, UserFlags::AllUsers).unwrap();
journal.next().unwrap();
while journal.get_data("MESSAGE_ID").is_err() {
match journal.next().unwrap() {
CursorMovement::EoF => return,
_ => ()
}
}
let c = journal.get_catalog().unwrap();
println!("{}", c);
while journal.get_data("MESSAGE_ID").is_ok() {
match journal.next().unwrap() {
CursorMovement::EoF => return,
_ => ()
}
}
journal.get_catalog().unwrap_err();
}
#[test]
fn get_data() {
let mut test_data = PathBuf::from(env!("CARGO_MANIFEST_DIR"));
test_data.push("test-data/");
println!("looking for test data in folder {}", test_data.display());
let journal =
Journal::open_directory(&test_data, PathFlags::FullPath, UserFlags::AllUsers).unwrap();
for cursor in &journal {
let cursor = cursor.unwrap();
let message = cursor.get_data("MESSAGE")
.unwrap_or("[no message available]".to_string());
let datetime = cursor.get_realtime().unwrap();
println!("{} - {}", datetime, message);
}
}
#[test]
fn enumerate_fields() {
let journal = Journal::open(FileFlags::AllFiles, UserFlags::AllUsers).unwrap();
journal.next().unwrap();
while let Ok(Enumeration::Value((field, value))) = journal.enumerate_fields() {
println!("{}: {}", field, value)
}
}
#[test]
fn enumerate_available_fields() {
let journal = Journal::open(FileFlags::AllFiles, UserFlags::AllUsers).unwrap();
journal.next().unwrap();
while let Ok(Enumeration::Value((field, value))) = journal.enumerate_available_fields() {
println!("{}: {}", field, value)
}
}
#[test]
fn restart_fields_enumeration() {
let journal = open_testdata();
journal.next().unwrap();
while let Ok(Enumeration::Value((field, value))) = journal.enumerate_fields() {
println!("{}: {}", field, value);
if field == "MESSAGE" {
journal.restart_fields_enumeration();
break;
}
}
while let Ok(Enumeration::Value((field, value))) = journal.enumerate_fields() {
println!("{}: {}", field, value);
if field == "MESSAGE" {
return;
}
}
panic!("Test failed: Field MESSAGE either does not exist or restart_data() did not succeed.");
}
#[test]
fn iter_fields() {
let journal = open_testdata();
journal.next().unwrap();
while let Ok(Enumeration::Value((field, value))) = journal.enumerate_fields() {
println!("{}: {}", field, value);
}
for field in journal.iter_fields() {
let (field, value) = field.unwrap();
println!("{}: {}", field, value);
}
}
#[test]
fn query_unique_values() {
let journal = open_testdata();
journal.query_unique_values("MESSAGE").unwrap();
}
#[test]
fn enumerate_unique_values() {
let journal = open_testdata();
journal.query_unique_values("MESSAGE").unwrap();
let first = journal.enumerate_unique_values().unwrap();
println!("first: {:?}", first);
let second = journal.enumerate_unique_values().unwrap();
println!("second: {:?}", second);
assert_eq!(first, Enumeration::Value("Hello World!".to_string()));
assert_eq!(second, Enumeration::EoF);
}
#[test]
fn enumerate_available_unique_values() {
let journal = open_testdata();
journal.query_unique_values("MESSAGE").unwrap();
let first = journal.enumerate_unique_values().unwrap();
println!("first: {:?}", first);
let second = journal.enumerate_unique_values().unwrap();
println!("second: {:?}", second);
assert_eq!(first, Enumeration::Value("Hello World!".to_string()));
assert_eq!(second, Enumeration::EoF);
}
#[test]
fn restart_unique_value_enumeration() {
let journal = open_testdata();
journal.query_unique_values("_PID").unwrap();
let first = journal.enumerate_unique_values().unwrap();
println!("first: {:?}", first);
let second = journal.enumerate_unique_values().unwrap();
println!("second: {:?}", second);
journal.restart_unique_value_enumeration();
let third = journal.enumerate_unique_values().unwrap();
println!("third: {:?}", third);
assert_ne!(first, second);
assert_eq!(first, third);
}
#[test]
fn iter_unique_values() {
let journal = open_testdata();
for value in journal.iter_unique_values("MESSAGE").unwrap() {
let value = value.unwrap();
println!("{}", value);
}
}