Skip to content

Commit 8db410c

Browse files
committed
tests: add a few unit tests
1 parent 13e1aea commit 8db410c

4 files changed

Lines changed: 150 additions & 1 deletion

File tree

Cargo.lock

Lines changed: 1 addition & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

Cargo.toml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@ elasticsearch = "9.0.0-alpha.1"
99
redis = "0.32.4"
1010
rmp-serde = "1.3.0"
1111
serde = "1.0.219"
12+
serde_derive = "1.0.219"
1213
serde_json = "1.0.142"
1314
tokio = "1.47.0"
1415
toml = "0.9.5"

src/config.rs

Lines changed: 55 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -65,6 +65,7 @@ impl IngestorConfig {
6565
}
6666
}
6767

68+
#[cfg(test)]
6869
mod tests {
6970
use super::*;
7071

@@ -108,4 +109,58 @@ port = 9876
108109
assert_eq!(config.elastic.url.full_url(), "http://127.0.0.1:9876");
109110
assert_eq!(config.elastic.api_key, "abcdefgh==");
110111
}
112+
113+
#[test]
114+
fn test_redis_defaults() {
115+
let test_str = "
116+
[url]
117+
url = \"http://localhost\"
118+
port = 6379
119+
";
120+
let redis: RedisConfig = toml::from_str(&test_str).unwrap();
121+
assert_eq!(redis.chunk_size, 100);
122+
assert_eq!(redis.blocktime_millis, 1000);
123+
assert_eq!(redis.consumer_group, "log-ingestor");
124+
assert_eq!(redis.consumer_id, "log-ingestor");
125+
}
126+
127+
#[test]
128+
fn test_elastic_defaults() {
129+
let test_str = "
130+
url = { url = \"http://localhost\", port = 9200 }
131+
api_key = \"testkey\"
132+
";
133+
let elastic: ElasticConfig = toml::from_str(&test_str).unwrap();
134+
assert_eq!(elastic.chunk_size, 100);
135+
assert_eq!(elastic.api_key, "testkey");
136+
assert_eq!(elastic.url.full_url(), "http://localhost:9200");
137+
}
138+
139+
#[test]
140+
fn test_invalid_urlport_missing_field() {
141+
let test_str = "
142+
url = \"http://localhost\"
143+
";
144+
let result: Result<UrlPort, _> = toml::from_str(&test_str);
145+
assert!(result.is_err());
146+
}
147+
148+
#[test]
149+
fn test_invalid_toml() {
150+
let test_str = "
151+
this is not toml
152+
";
153+
let result: Result<RedisConfig, _> = toml::from_str(&test_str);
154+
assert!(result.is_err());
155+
}
156+
157+
#[test]
158+
fn test_from_file_error() {
159+
use std::path::PathBuf;
160+
let path = PathBuf::from("/nonexistent/config.toml");
161+
let result = std::panic::catch_unwind(|| {
162+
IngestorConfig::from_file(path);
163+
});
164+
assert!(result.is_err());
165+
}
111166
}

src/elastic_push.rs

Lines changed: 93 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -60,4 +60,96 @@ pub async fn consumer_loop(rx: &mut mpsc::UnboundedReceiver<LogRecord>, config:
6060
println!("Producer dropped, consumer exiting");
6161
}
6262

63-
mod tests {}
63+
#[cfg(test)]
64+
mod tests {
65+
use super::*;
66+
use serde::{Deserialize, Serialize};
67+
68+
#[derive(Debug, Clone, Serialize, Deserialize, PartialEq)]
69+
struct DummyLog {
70+
msg: String,
71+
level: String,
72+
}
73+
74+
// Implement LogRecord for test if not already present
75+
impl From<DummyLog> for LogRecord {
76+
fn from(d: DummyLog) -> Self {
77+
// Adjust this conversion as per your actual LogRecord struct
78+
LogRecord {
79+
elapsed: crate::redis_logs::Elapsed {
80+
repr: "".into(),
81+
seconds: 0.0,
82+
},
83+
exception: None,
84+
extra: {}.into(),
85+
file: crate::redis_logs::File {
86+
name: "".into(),
87+
path: "".into(),
88+
},
89+
function: "".into(),
90+
level: crate::redis_logs::LogLevel {
91+
icon: "".into(),
92+
name: d.level,
93+
no: 100,
94+
},
95+
line: 0,
96+
message: d.msg,
97+
module: "".into(),
98+
name: "".into(),
99+
process: crate::redis_logs::NameId {
100+
name: "".into(),
101+
id: 0,
102+
},
103+
thread: crate::redis_logs::NameId {
104+
name: "".into(),
105+
id: 0,
106+
},
107+
time: crate::redis_logs::Timestamp {
108+
repr: "".into(),
109+
timestamp: 0.0,
110+
},
111+
}
112+
}
113+
}
114+
115+
#[test]
116+
fn test_make_docs_values_empty() {
117+
let records: Vec<LogRecord> = vec![];
118+
let docs = make_docs_values(&records).unwrap();
119+
assert!(docs.is_empty());
120+
}
121+
122+
#[test]
123+
fn test_make_docs_values_single() {
124+
let record: LogRecord = DummyLog {
125+
msg: "hello".to_string(),
126+
level: "info".to_string(),
127+
}
128+
.into();
129+
let docs = make_docs_values(&vec![record.clone()]).unwrap();
130+
// Each record should produce two JSON bodies (action + doc)
131+
assert_eq!(docs.len(), 2);
132+
}
133+
134+
#[test]
135+
fn test_make_docs_values_multiple() {
136+
let record1: LogRecord = DummyLog {
137+
msg: "a".to_string(),
138+
level: "info".to_string(),
139+
}
140+
.into();
141+
let record2: LogRecord = DummyLog {
142+
msg: "b".to_string(),
143+
level: "warn".to_string(),
144+
}
145+
.into();
146+
let docs = make_docs_values(&vec![record1, record2]).unwrap();
147+
assert_eq!(docs.len(), 4);
148+
}
149+
150+
#[test]
151+
fn test_elastic_client_invalid_url() {
152+
let result = elastic_client("not a url", "apikey");
153+
assert!(result.is_err());
154+
}
155+
}

0 commit comments

Comments
 (0)