Compare commits
5 Commits
c34ad15ba1
...
be632d3da3
| Author | SHA1 | Date |
|---|---|---|
|
|
be632d3da3 | |
|
|
90de4a0cfd | |
|
|
3c64bb27de | |
|
|
bcbcd6fbb7 | |
|
|
b5b794817c |
|
|
@ -104,18 +104,19 @@ mod test_flags {
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn test_flags_files_unhidden_only() {
|
fn test_flags_files_unhidden_only() {
|
||||||
let d = tempdir::TempDir::new("").unwrap();
|
tests::with_dir(|d| {
|
||||||
std::fs::File::create(d.path().join("plain")).unwrap();
|
std::fs::File::create(d.path().join("plain")).unwrap();
|
||||||
std::fs::File::create(d.path().join(".hidden")).unwrap();
|
std::fs::File::create(d.path().join(".hidden")).unwrap();
|
||||||
|
|
||||||
let flags = Flags {
|
let flags = Flags {
|
||||||
path: d.path().to_str().unwrap().to_string(),
|
path: d.path().to_str().unwrap().to_string(),
|
||||||
add: None,
|
add: None,
|
||||||
edit: false,
|
edit: false,
|
||||||
dry_run: true,
|
dry_run: true,
|
||||||
};
|
};
|
||||||
let files = flags.files().expect("failed to files from dir");
|
let files = flags.files().expect("failed to files from dir");
|
||||||
assert_eq!(1, files.files.len());
|
assert_eq!(1, files.files.len());
|
||||||
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -158,15 +159,15 @@ impl File {
|
||||||
|
|
||||||
pub fn persist_stage(&self) -> Result<(), String> {
|
pub fn persist_stage(&self) -> Result<(), String> {
|
||||||
let persisted = self.events()?.snapshot()?;
|
let persisted = self.events()?.snapshot()?;
|
||||||
let snapshot = serde_json::to_string(&persisted).unwrap();
|
let persisted = serde_json::to_string(&persisted).unwrap();
|
||||||
let snapshot = snapshot.as_str();
|
let persisted = persisted.as_str();
|
||||||
let snapshot: serde_json::Value = serde_json::from_str(&snapshot).unwrap();
|
let persisted: serde_json::Value = serde_json::from_str(&persisted).unwrap();
|
||||||
|
|
||||||
let stage = self.stage()?;
|
let stage = self.stage()?;
|
||||||
let stage = serde_json::to_string(&stage).unwrap();
|
let stage = serde_json::to_string(&stage).unwrap();
|
||||||
let stage: serde_json::Value = serde_json::from_str(stage.as_str()).unwrap();
|
let stage: serde_json::Value = serde_json::from_str(stage.as_str()).unwrap();
|
||||||
|
|
||||||
let patches = json_patch::diff(&snapshot, &stage);
|
let patches = json_patch::diff(&persisted, &stage);
|
||||||
let deltas: Vec<Delta> = patches
|
let deltas: Vec<Delta> = patches
|
||||||
.iter()
|
.iter()
|
||||||
.map(|patch| patch.clone())
|
.map(|patch| patch.clone())
|
||||||
|
|
@ -233,12 +234,125 @@ mod test_file {
|
||||||
use super::*;
|
use super::*;
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn test_file() {
|
fn test_file_empty_empty() {
|
||||||
let d = tempdir::TempDir::new("").unwrap();
|
tests::with_dir(|d| {
|
||||||
let mut f = std::fs::File::create(d.path().join("plain")).unwrap();
|
tests::write_file(&d, "plain", "[]");
|
||||||
writeln!(f, "hello world").unwrap();
|
|
||||||
|
|
||||||
assert!(false, "not impl");
|
let f = File::new(&d.path().join("plain").to_str().unwrap().to_string());
|
||||||
|
|
||||||
|
assert_eq!(0, f.events().unwrap().0.len());
|
||||||
|
assert_eq!(0, f.stage().unwrap().len());
|
||||||
|
tests::file_contains(&d, "plain", "[]");
|
||||||
|
|
||||||
|
f.persist_stage().unwrap();
|
||||||
|
assert_eq!(0, f.events().unwrap().0.len());
|
||||||
|
assert_eq!(0, f.stage().unwrap().len());
|
||||||
|
tests::file_contains(&d, "plain", "[]");
|
||||||
|
|
||||||
|
f.stage_persisted().unwrap();
|
||||||
|
assert_eq!(0, f.events().unwrap().0.len());
|
||||||
|
assert_eq!(0, f.stage().unwrap().len());
|
||||||
|
tests::file_contains(&d, "plain", "[]");
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn test_file_empty_stage_fills_events() {
|
||||||
|
tests::with_dir(|d| {
|
||||||
|
tests::write_file(&d, "plain", "[hello, world]");
|
||||||
|
|
||||||
|
let f = File::new(&d.path().join("plain").to_str().unwrap().to_string());
|
||||||
|
|
||||||
|
assert_eq!(0, f.events().unwrap().0.len());
|
||||||
|
assert_eq!(2, f.stage().unwrap().len());
|
||||||
|
tests::file_contains(&d, "plain", "[hello, world]");
|
||||||
|
|
||||||
|
f.persist_stage().unwrap();
|
||||||
|
assert_eq!(2, f.events().unwrap().0.len());
|
||||||
|
assert_eq!(2, f.stage().unwrap().len());
|
||||||
|
tests::file_contains(&d, "plain", "[hello, world]");
|
||||||
|
|
||||||
|
f.stage_persisted().unwrap();
|
||||||
|
assert_eq!(2, f.events().unwrap().0.len());
|
||||||
|
assert_eq!(2, f.stage().unwrap().len());
|
||||||
|
tests::file_contains(&d, "plain", "- hello\n- world");
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn test_file_persist_empty_drains_events() {
|
||||||
|
tests::with_dir(|d| {
|
||||||
|
tests::write_file(&d, "plain", "[]");
|
||||||
|
tests::write_file(
|
||||||
|
&d,
|
||||||
|
".plain.host_a",
|
||||||
|
r#"
|
||||||
|
{"ts":1, "patch":{"op":"replace", "path":"", "value": ["initial"]}}
|
||||||
|
{"ts":3, "patch":{"op":"add", "path":"/-", "value": {"k":"v"}}}
|
||||||
|
"#,
|
||||||
|
);
|
||||||
|
tests::write_file(
|
||||||
|
&d,
|
||||||
|
".plain.host_b",
|
||||||
|
r#"
|
||||||
|
{"ts":2, "patch":{"op":"add", "path":"/-", "value": 1}}
|
||||||
|
"#,
|
||||||
|
);
|
||||||
|
|
||||||
|
let f = File::new(&d.path().join("plain").to_str().unwrap().to_string());
|
||||||
|
|
||||||
|
assert_eq!(3, f.events().unwrap().0.len());
|
||||||
|
assert_eq!(0, f.stage().unwrap().len());
|
||||||
|
tests::file_contains(&d, "plain", "[]");
|
||||||
|
|
||||||
|
f.persist_stage().unwrap();
|
||||||
|
assert_eq!(6, f.events().unwrap().0.len());
|
||||||
|
assert_eq!(0, f.stage().unwrap().len());
|
||||||
|
tests::file_contains(&d, "plain", "[]");
|
||||||
|
|
||||||
|
f.stage_persisted().unwrap();
|
||||||
|
assert_eq!(6, f.events().unwrap().0.len());
|
||||||
|
assert_eq!(0, f.stage().unwrap().len());
|
||||||
|
tests::file_contains(&d, "plain", "[]");
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn test_file_deletion_to_persist() {
|
||||||
|
tests::with_dir(|d| {
|
||||||
|
tests::write_file(&d, "plain", "- initial\n- 1");
|
||||||
|
tests::write_file(
|
||||||
|
&d,
|
||||||
|
".plain.host_a",
|
||||||
|
r#"
|
||||||
|
{"ts":1, "patch":{"op":"replace", "path":"", "value": ["initial"]}}
|
||||||
|
{"ts":3, "patch":{"op":"add", "path":"/-", "value": {"k":"v"}}}
|
||||||
|
"#,
|
||||||
|
);
|
||||||
|
tests::write_file(
|
||||||
|
&d,
|
||||||
|
".plain.host_b",
|
||||||
|
r#"
|
||||||
|
{"ts":2, "patch":{"op":"add", "path":"/-", "value": 1}}
|
||||||
|
"#,
|
||||||
|
);
|
||||||
|
|
||||||
|
let f = File::new(&d.path().join("plain").to_str().unwrap().to_string());
|
||||||
|
|
||||||
|
assert_eq!(3, f.events().unwrap().0.len());
|
||||||
|
assert_eq!(2, f.stage().unwrap().len());
|
||||||
|
tests::file_contains(&d, "plain", "- initial\n- 1");
|
||||||
|
|
||||||
|
f.persist_stage().unwrap();
|
||||||
|
assert_eq!(4, f.events().unwrap().0.len());
|
||||||
|
assert_eq!(2, f.stage().unwrap().len());
|
||||||
|
tests::file_contains(&d, "plain", "- initial\n- 1");
|
||||||
|
|
||||||
|
f.stage_persisted().unwrap();
|
||||||
|
assert_eq!(4, f.events().unwrap().0.len());
|
||||||
|
assert_eq!(2, f.stage().unwrap().len());
|
||||||
|
tests::file_contains(&d, "plain", "- initial\n- 1");
|
||||||
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -294,6 +408,7 @@ impl Events {
|
||||||
Ok(f) => {
|
Ok(f) => {
|
||||||
for line in std::io::BufReader::new(f).lines() {
|
for line in std::io::BufReader::new(f).lines() {
|
||||||
let line = line.unwrap();
|
let line = line.unwrap();
|
||||||
|
let line = line.trim();
|
||||||
if line.len() > 0 {
|
if line.len() > 0 {
|
||||||
let delta = match serde_json::from_str(&line) {
|
let delta = match serde_json::from_str(&line) {
|
||||||
Ok(v) => Ok(v),
|
Ok(v) => Ok(v),
|
||||||
|
|
@ -307,7 +422,9 @@ impl Events {
|
||||||
Err(msg) => Err(format!("failed to read {}: {}", &log, msg)),
|
Err(msg) => Err(format!("failed to read {}: {}", &log, msg)),
|
||||||
}?;
|
}?;
|
||||||
}
|
}
|
||||||
|
|
||||||
result.sort_by(|a, b| a.ts.cmp(&b.ts));
|
result.sort_by(|a, b| a.ts.cmp(&b.ts));
|
||||||
|
|
||||||
Ok(Events(result))
|
Ok(Events(result))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -356,26 +473,95 @@ mod test_events {
|
||||||
use super::*;
|
use super::*;
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn test_events() {
|
fn test_events_oplog_to_snapshot_one() {
|
||||||
let d = tempdir::TempDir::new("").unwrap();
|
tests::with_dir(|d| {
|
||||||
test_file(&d, "plain", "- persisted\n- stage only");
|
tests::write_file(&d, "plain", "- persisted\n- stage only");
|
||||||
test_file(
|
tests::write_file(
|
||||||
&d,
|
&d,
|
||||||
".plain.log",
|
".plain.some_host",
|
||||||
r#"
|
r#"
|
||||||
{"ts":1, "patch":{"op":"replace", "path":"", "value":["persisted"]}}
|
{"ts":1, "patch":{"op":"replace", "path":"", "value":["persisted"]}}
|
||||||
"#,
|
"#,
|
||||||
);
|
);
|
||||||
|
|
||||||
let events = Events::new(&d.path().join("plain").to_str().unwrap().to_string()).unwrap();
|
let events =
|
||||||
assert_eq!(1, events.0.len(), "events: {:?}", events);
|
Events::new(&d.path().join("plain").to_str().unwrap().to_string()).unwrap();
|
||||||
|
assert_eq!(1, events.0.len(), "events: {:?}", events);
|
||||||
|
|
||||||
assert!(false, "not impl");
|
let snapshot = events.snapshot().unwrap();
|
||||||
|
assert_eq!(1, snapshot.len());
|
||||||
|
assert_eq!(
|
||||||
|
serde_yaml::Value::String("persisted".to_string()),
|
||||||
|
snapshot[0].0
|
||||||
|
);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn test_events_oplog_to_snapshot_complex() {
|
||||||
|
tests::with_dir(|d| {
|
||||||
|
tests::write_file(&d, "plain", "- ignored");
|
||||||
|
tests::write_file(
|
||||||
|
&d,
|
||||||
|
".plain.host_a",
|
||||||
|
r#"
|
||||||
|
{"ts":1, "patch":{"op":"replace", "path":"", "value":["persisted"]}}
|
||||||
|
{"ts":3, "patch":{"op":"add", "path":"/-", "value":"persisted 3"}}
|
||||||
|
{"ts":2, "patch":{"op":"add", "path":"/-", "value":"persisted 2"}}
|
||||||
|
{"ts":6, "patch":{"op":"replace", "path":"/4", "value":"persisted 5'"}}
|
||||||
|
{"ts":7, "patch":{"op":"remove", "path":"/3"}}
|
||||||
|
"#,
|
||||||
|
);
|
||||||
|
tests::write_file(
|
||||||
|
&d,
|
||||||
|
".plain.host_b",
|
||||||
|
r#"
|
||||||
|
{"ts":4, "patch":{"op":"add", "path":"/-", "value":"persisted 4"}}
|
||||||
|
{"ts":5, "patch":{"op":"add", "path":"/-", "value":"persisted 5"}}
|
||||||
|
"#,
|
||||||
|
);
|
||||||
|
|
||||||
|
let events =
|
||||||
|
Events::new(&d.path().join("plain").to_str().unwrap().to_string()).unwrap();
|
||||||
|
|
||||||
|
let snapshot = events.snapshot().unwrap();
|
||||||
|
assert_eq!(4, snapshot.len());
|
||||||
|
assert_eq!(
|
||||||
|
serde_yaml::Value::String("persisted".to_string()),
|
||||||
|
snapshot[0].0
|
||||||
|
);
|
||||||
|
assert_eq!(
|
||||||
|
serde_yaml::Value::String("persisted 2".to_string()),
|
||||||
|
snapshot[1].0
|
||||||
|
);
|
||||||
|
assert_eq!(
|
||||||
|
serde_yaml::Value::String("persisted 3".to_string()),
|
||||||
|
snapshot[2].0
|
||||||
|
);
|
||||||
|
assert_eq!(
|
||||||
|
serde_yaml::Value::String("persisted 5'".to_string()),
|
||||||
|
snapshot[3].0
|
||||||
|
);
|
||||||
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn test_file(d: &tempdir::TempDir, fname: &str, content: &str) {
|
mod tests {
|
||||||
let mut f = std::fs::File::create(d.path().join("plain")).unwrap();
|
use super::*;
|
||||||
writeln!(f, "- persisted\n- stage only").unwrap();
|
|
||||||
f.sync_all().unwrap();
|
pub fn with_dir(mut foo: impl FnMut(tempdir::TempDir)) {
|
||||||
|
foo(tempdir::TempDir::new("").unwrap());
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn write_file(d: &tempdir::TempDir, fname: &str, content: &str) {
|
||||||
|
let mut f = std::fs::File::create(d.path().join(&fname)).unwrap();
|
||||||
|
writeln!(f, "{}", &content).unwrap();
|
||||||
|
f.sync_all().unwrap();
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn file_contains(d: &tempdir::TempDir, fname: &str, content: &str) {
|
||||||
|
let p = d.path().join(&fname);
|
||||||
|
let file_content = std::fs::read_to_string(p).unwrap();
|
||||||
|
assert!(file_content.contains(content));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue