@cryptotaxi247 / netdata-1 / commits / 1528f3d72

Format workspace with `cargo fmt` (#21733)

vkalintiris committed Feb 11, 2026 at 12:07 UTC 1528f3d72032e42cc75ab20e6d62c3da60ee7a42
28 files changed +358 -201
src/crates/journal-core/src/file/cursor.rs
+2 -2
@@ -1,7 +1,7 @@
1 -use crate::file::{file::JournalFile, filter::FilterExpr, offset_array, offset_array::Direction};
1 +use super::mmap::MemoryMap;
2 use crate::error::{JournalError, Result};
3 +use crate::file::{file::JournalFile, filter::FilterExpr, offset_array, offset_array::Direction};
4 use std::num::NonZeroU64;
4 -use super::mmap::MemoryMap;
5
6 #[derive(Debug, Copy, Clone, PartialEq, Eq)]
7 pub enum Location {
src/crates/journal-core/src/file/filter.rs
+2 -2
@@ -1,7 +1,7 @@
1 -use crate::file::{file::JournalFile, offset_array::InlinedCursor};
1 +use super::mmap::MemoryMap;
2 use crate::error::{JournalError, Result};
3 +use crate::file::{file::JournalFile, offset_array::InlinedCursor};
4 use std::num::NonZeroU64;
4 -use super::mmap::MemoryMap;
5
6 #[derive(Clone, Debug)]
7 pub enum FilterExpr {
src/crates/journal-core/src/file/mod.rs
+1 -1
@@ -26,7 +26,7 @@ pub use cursor::JournalCursor;
26 pub use filter::{FilterExpr, JournalFilter, LogicalOp};
27
28 // For FFI compatibility and advanced object manipulation
29 -pub use object::{EntryItemsType, HashableObject, JournalState, HeaderIncompatibleFlags};
29 +pub use object::{EntryItemsType, HashableObject, HeaderIncompatibleFlags, JournalState};
30
31 // Re-export commonly needed external types
32 pub use mmap::{Mmap, MmapMut};
src/crates/journal-core/src/file/object.rs
+1 -2
@@ -998,8 +998,7 @@ impl<B: ByteSlice> DataObject<B> {
998 return Err(JournalError::DecompressorError);
999 }
1000
1001 - let uncompressed_size =
1002 - u64::from_le_bytes(payload[..8].try_into().unwrap()) as usize;
1001 + let uncompressed_size = u64::from_le_bytes(payload[..8].try_into().unwrap()) as usize;
1002 let compressed_data = &payload[8..];
1003
1004 buf.clear();
src/crates/journal-engine/src/histogram.rs
+7 -4
@@ -198,7 +198,7 @@ impl HistogramEngine {
198 pub fn with_capacity(capacity: usize) -> Self {
199 Self {
200 responses: RwLock::new(LruCache::new(
201 - NonZeroUsize::new(capacity).expect("capacity must be non-zero")
201 + NonZeroUsize::new(capacity).expect("capacity must be non-zero"),
202 )),
203 }
204 }
@@ -288,8 +288,7 @@ impl HistogramEngine {
288 };
289
290 // Count total entries in this file for this bucket's time range
291 - let all_entries =
292 - Bitmap::insert_range(0..file_index.total_entries() as u32);
291 + let all_entries = Bitmap::insert_range(0..file_index.total_entries() as u32);
292 let unfiltered_total = file_index
293 .count_entries_in_time_range(
294 &all_entries,
@@ -358,7 +357,11 @@ impl HistogramEngine {
357 // Cache only the responses that are safe to cache (no online file contributions)
358 let mut responses_guard = self.responses.write();
359 for (bucket_request, response) in &new_responses {
361 - if bucket_cacheable.get(bucket_request).copied().unwrap_or(false) {
360 + if bucket_cacheable
361 + .get(bucket_request)
362 + .copied()
363 + .unwrap_or(false)
364 + {
365 responses_guard.put(bucket_request.clone(), response.clone());
366 }
367 }
src/crates/journal-engine/src/indexing.rs
+1 -1
@@ -9,11 +9,11 @@ use crate::{
9 error::{EngineError, Result},
10 query_time_range::QueryTimeRange,
11 };
12 -use tokio_util::sync::CancellationToken;
12 use journal_index::{FileIndex, FileIndexer, IndexingLimits};
13 use journal_registry::Registry;
14 use std::sync::Arc;
15 use std::sync::atomic::AtomicUsize;
16 +use tokio_util::sync::CancellationToken;
17 use tracing::{error, trace};
18
19 // ============================================================================
src/crates/journal-engine/src/query_time_range.rs
+6 -6
@@ -1,7 +1,7 @@
1 //! Query time range with automatic alignment for histogram bucketing
2
3 -use crate::histogram::calculate_bucket_duration;
3 use crate::EngineError;
4 +use crate::histogram::calculate_bucket_duration;
5 use journal_index::Seconds;
6
7 /// A time range for querying journal entries with automatic alignment.
@@ -55,10 +55,7 @@ impl QueryTimeRange {
55 /// ```
56 pub fn new(start: u32, end: u32) -> Result<Self, EngineError> {
57 if start >= end {
58 - return Err(EngineError::InvalidTimeRange {
59 - start,
60 - end,
61 - });
58 + return Err(EngineError::InvalidTimeRange { start, end });
59 }
60
61 let duration = end - start;
@@ -181,7 +178,10 @@ mod tests {
178 assert_eq!(range.requested_end(), 500);
179 assert_eq!(range.requested_duration(), 400);
180 assert!(range.bucket_duration() > 0);
184 - assert_eq!(range.aligned_duration(), range.aligned_end() - range.aligned_start());
181 + assert_eq!(
182 + range.aligned_duration(),
183 + range.aligned_end() - range.aligned_start()
184 + );
185 }
186
187 #[test]
src/crates/journal-index/src/lib.rs
+2 -1
@@ -21,7 +21,8 @@ pub use file_index::{
21
22 pub mod file_indexer;
23 pub use file_indexer::{
24 - FileIndexer, IndexingLimits, DEFAULT_MAX_FIELD_PAYLOAD_SIZE, DEFAULT_MAX_UNIQUE_VALUES_PER_FIELD,
24 + DEFAULT_MAX_FIELD_PAYLOAD_SIZE, DEFAULT_MAX_UNIQUE_VALUES_PER_FIELD, FileIndexer,
25 + IndexingLimits,
26 };
27
28 pub mod bitmap;
src/crates/journal-index/tests/pagination.rs
+156 -116
@@ -130,13 +130,21 @@ fn test_pagination_forward_with_same_timestamps() {
130
131 let results = file_index.find_log_entries(&file, &params).unwrap();
132 println!("First page: {} entries", results.len());
133 - assert_eq!(results.len(), PAGE_SIZE, "First page should return PAGE_SIZE entries");
133 + assert_eq!(
134 + results.len(),
135 + PAGE_SIZE,
136 + "First page should return PAGE_SIZE entries"
137 + );
138
139 // Verify all have the same timestamp
140 for entry in &results {
141 assert_eq!(entry.timestamp, same_timestamp);
142 all_offsets.push(entry.offset);
139 - assert!(all_positions.insert(entry.position), "Position {} appeared twice", entry.position);
143 + assert!(
144 + all_positions.insert(entry.position),
145 + "Position {} appeared twice",
146 + entry.position
147 + );
148 }
149
150 if let Some(last_entry) = results.last() {
@@ -152,13 +160,21 @@ fn test_pagination_forward_with_same_timestamps() {
160
161 let results = file_index.find_log_entries(&file, &params).unwrap();
162 println!("Second page: {} entries", results.len());
155 - assert_eq!(results.len(), TOTAL_ENTRIES - PAGE_SIZE, "Second page should return remaining entries");
163 + assert_eq!(
164 + results.len(),
165 + TOTAL_ENTRIES - PAGE_SIZE,
166 + "Second page should return remaining entries"
167 + );
168
169 // Verify all have the same timestamp
170 for entry in &results {
171 assert_eq!(entry.timestamp, same_timestamp);
172 all_offsets.push(entry.offset);
161 - assert!(all_positions.insert(entry.position), "Position {} appeared twice", entry.position);
173 + assert!(
174 + all_positions.insert(entry.position),
175 + "Position {} appeared twice",
176 + entry.position
177 + );
178 }
179
180 if let Some(last_entry) = results.last() {
@@ -177,14 +193,26 @@ fn test_pagination_forward_with_same_timestamps() {
193 assert_eq!(results.len(), 0, "Third page should be empty");
194
195 // Verify we got all entries
180 - assert_eq!(all_offsets.len(), TOTAL_ENTRIES, "Should have retrieved all entries");
196 + assert_eq!(
197 + all_offsets.len(),
198 + TOTAL_ENTRIES,
199 + "Should have retrieved all entries"
200 + );
201
202 // Verify all offsets are unique (no duplicates)
203 let unique_offsets: HashSet<_> = all_offsets.iter().collect();
184 - assert_eq!(unique_offsets.len(), TOTAL_ENTRIES, "All offsets should be unique");
204 + assert_eq!(
205 + unique_offsets.len(),
206 + TOTAL_ENTRIES,
207 + "All offsets should be unique"
208 + );
209
210 // Verify all positions are unique and contiguous
187 - assert_eq!(all_positions.len(), TOTAL_ENTRIES, "Should have unique positions");
211 + assert_eq!(
212 + all_positions.len(),
213 + TOTAL_ENTRIES,
214 + "Should have unique positions"
215 + );
216 for i in 0..TOTAL_ENTRIES {
217 assert!(all_positions.contains(&i), "Position {} missing", i);
218 }
@@ -231,13 +259,21 @@ fn test_pagination_backward_with_same_timestamps() {
259
260 let results = file_index.find_log_entries(&file, &params).unwrap();
261 println!("First page: {} entries", results.len());
234 - assert_eq!(results.len(), PAGE_SIZE, "First page should return PAGE_SIZE entries");
262 + assert_eq!(
263 + results.len(),
264 + PAGE_SIZE,
265 + "First page should return PAGE_SIZE entries"
266 + );
267
268 // Verify all have the same timestamp
269 for entry in &results {
270 assert_eq!(entry.timestamp, same_timestamp);
271 all_offsets.push(entry.offset);
240 - assert!(all_positions.insert(entry.position), "Position {} appeared twice", entry.position);
272 + assert!(
273 + all_positions.insert(entry.position),
274 + "Position {} appeared twice",
275 + entry.position
276 + );
277 }
278
279 if let Some(last_entry) = results.last() {
@@ -253,13 +289,21 @@ fn test_pagination_backward_with_same_timestamps() {
289
290 let results = file_index.find_log_entries(&file, &params).unwrap();
291 println!("Second page: {} entries", results.len());
256 - assert_eq!(results.len(), TOTAL_ENTRIES - PAGE_SIZE, "Second page should return remaining entries");
292 + assert_eq!(
293 + results.len(),
294 + TOTAL_ENTRIES - PAGE_SIZE,
295 + "Second page should return remaining entries"
296 + );
297
298 // Verify all have the same timestamp
299 for entry in &results {
300 assert_eq!(entry.timestamp, same_timestamp);
301 all_offsets.push(entry.offset);
262 - assert!(all_positions.insert(entry.position), "Position {} appeared twice", entry.position);
302 + assert!(
303 + all_positions.insert(entry.position),
304 + "Position {} appeared twice",
305 + entry.position
306 + );
307 }
308
309 if let Some(last_entry) = results.last() {
@@ -278,14 +322,26 @@ fn test_pagination_backward_with_same_timestamps() {
322 assert_eq!(results.len(), 0, "Third page should be empty");
323
324 // Verify we got all entries
281 - assert_eq!(all_offsets.len(), TOTAL_ENTRIES, "Should have retrieved all entries");
325 + assert_eq!(
326 + all_offsets.len(),
327 + TOTAL_ENTRIES,
328 + "Should have retrieved all entries"
329 + );
330
331 // Verify all offsets are unique (no duplicates)
332 let unique_offsets: HashSet<_> = all_offsets.iter().collect();
285 - assert_eq!(unique_offsets.len(), TOTAL_ENTRIES, "All offsets should be unique");
333 + assert_eq!(
334 + unique_offsets.len(),
335 + TOTAL_ENTRIES,
336 + "All offsets should be unique"
337 + );
338
339 // Verify all positions are unique and contiguous
288 - assert_eq!(all_positions.len(), TOTAL_ENTRIES, "Should have unique positions");
340 + assert_eq!(
341 + all_positions.len(),
342 + TOTAL_ENTRIES,
343 + "Should have unique positions"
344 + );
345 for i in 0..TOTAL_ENTRIES {
346 assert!(all_positions.contains(&i), "Position {} missing", i);
347 }
@@ -305,7 +361,7 @@ fn test_pagination_forward_with_mixed_timestamps() {
361 entries.push(
362 TestEntry::new(timestamp1)
363 .with_field("MESSAGE", format!("Batch 1 Entry {}", i))
308 - .with_field("ENTRY_ID", format!("1-{}", i))
364 + .with_field("ENTRY_ID", format!("1-{}", i)),
365 );
366 }
367
@@ -315,7 +371,7 @@ fn test_pagination_forward_with_mixed_timestamps() {
371 entries.push(
372 TestEntry::new(timestamp2)
373 .with_field("MESSAGE", format!("Batch 2 Entry {}", i))
318 - .with_field("ENTRY_ID", format!("2-{}", i))
374 + .with_field("ENTRY_ID", format!("2-{}", i)),
375 );
376 }
377
@@ -394,16 +450,12 @@ fn test_pagination_empty_journal() {
450 #[test]
451 fn test_pagination_single_entry() {
452 let timestamp = JAN_1_2024_MIDNIGHT;
397 - let entries = vec![
398 - TestEntry::new(timestamp).with_field("MESSAGE", "Single entry"),
399 - ];
453 + let entries = vec![TestEntry::new(timestamp).with_field("MESSAGE", "Single entry")];
454
455 let (_temp_dir, file) = create_test_journal(entries).unwrap();
456
457 let mut indexer = FileIndexer::default();
404 - let file_index = indexer
405 - .index(&file, None, &[], Seconds(3600))
406 - .unwrap();
458 + let file_index = indexer.index(&file, None, &[], Seconds(3600)).unwrap();
459
460 // Query forward with large limit
461 let params = LogQueryParamsBuilder::new(Anchor::Head, Direction::Forward)
@@ -445,7 +497,11 @@ fn test_pagination_single_entry() {
497 .unwrap();
498
499 let results = file_index.find_log_entries(&file, &params).unwrap();
448 - assert_eq!(results.len(), 0, "Backward from position 0 should return empty");
500 + assert_eq!(
501 + results.len(),
502 + 0,
503 + "Backward from position 0 should return empty"
504 + );
505 }
506
507 #[test]
@@ -459,9 +515,7 @@ fn test_pagination_two_entries() {
515 let (_temp_dir, file) = create_test_journal(entries).unwrap();
516
517 let mut indexer = FileIndexer::default();
462 - let file_index = indexer
463 - .index(&file, None, &[], Seconds(3600))
464 - .unwrap();
518 + let file_index = indexer.index(&file, None, &[], Seconds(3600)).unwrap();
519
520 // Forward: Get both entries at once with limit 10
521 let params = LogQueryParamsBuilder::new(Anchor::Head, Direction::Forward)
@@ -550,9 +604,7 @@ fn test_pagination_limit_zero() {
604 let (_temp_dir, file) = create_test_journal(entries).unwrap();
605
606 let mut indexer = FileIndexer::default();
553 - let file_index = indexer
554 - .index(&file, None, &[], Seconds(3600))
555 - .unwrap();
607 + let file_index = indexer.index(&file, None, &[], Seconds(3600)).unwrap();
608
609 // Query with limit 0 should return empty results
610 let params = LogQueryParamsBuilder::new(Anchor::Head, Direction::Forward)
@@ -586,9 +638,7 @@ fn test_pagination_limit_exact_match() {
638 let (_temp_dir, file) = create_test_journal(entries).unwrap();
639
640 let mut indexer = FileIndexer::default();
589 - let file_index = indexer
590 - .index(&file, None, &[], Seconds(3600))
591 - .unwrap();
641 + let file_index = indexer.index(&file, None, &[], Seconds(3600)).unwrap();
642
643 // Query with limit exactly equal to total entries
644 let params = LogQueryParamsBuilder::new(Anchor::Head, Direction::Forward)
@@ -625,9 +675,7 @@ fn test_pagination_limit_exceeds_total() {
675 let (_temp_dir, file) = create_test_journal(entries).unwrap();
676
677 let mut indexer = FileIndexer::default();
628 - let file_index = indexer
629 - .index(&file, None, &[], Seconds(3600))
630 - .unwrap();
678 + let file_index = indexer.index(&file, None, &[], Seconds(3600)).unwrap();
679
680 // Query with limit much larger than total entries
681 let params = LogQueryParamsBuilder::new(Anchor::Head, Direction::Forward)
@@ -654,7 +702,11 @@ fn test_pagination_limit_exceeds_total() {
702 .unwrap();
703
704 let results = file_index.find_log_entries(&file, &params).unwrap();
657 - assert_eq!(results.len(), TOTAL_ENTRIES, "Should return all entries backward");
705 + assert_eq!(
706 + results.len(),
707 + TOTAL_ENTRIES,
708 + "Should return all entries backward"
709 + );
710 }
711
712 #[test]
@@ -670,9 +722,7 @@ fn test_pagination_resume_out_of_bounds() {
722 let (_temp_dir, file) = create_test_journal(entries).unwrap();
723
724 let mut indexer = FileIndexer::default();
673 - let file_index = indexer
674 - .index(&file, None, &[], Seconds(3600))
675 - .unwrap();
725 + let file_index = indexer.index(&file, None, &[], Seconds(3600)).unwrap();
726
727 // Forward: Resume from position equal to total entries (at boundary)
728 let params = LogQueryParamsBuilder::new(Anchor::Head, Direction::Forward)
@@ -682,7 +732,11 @@ fn test_pagination_resume_out_of_bounds() {
732 .unwrap();
733
734 let results = file_index.find_log_entries(&file, &params).unwrap();
685 - assert_eq!(results.len(), 0, "Resume from last position should return empty");
735 + assert_eq!(
736 + results.len(),
737 + 0,
738 + "Resume from last position should return empty"
739 + );
740
741 // Forward: Resume from position beyond total entries
742 let params = LogQueryParamsBuilder::new(Anchor::Head, Direction::Forward)
@@ -720,7 +774,11 @@ fn test_pagination_resume_out_of_bounds() {
774 .unwrap();
775
776 let results = file_index.find_log_entries(&file, &params).unwrap();
723 - assert_eq!(results.len(), 0, "Backward from position 0 should return empty");
777 + assert_eq!(
778 + results.len(),
779 + 0,
780 + "Backward from position 0 should return empty"
781 + );
782
783 // Backward: Resume from position equal to total entries
784 let params = LogQueryParamsBuilder::new(Anchor::Tail, Direction::Backward)
@@ -781,19 +839,15 @@ fn test_pagination_anchor_before_all_entries() {
839 let (_temp_dir, file) = create_test_journal(entries).unwrap();
840
841 let mut indexer = FileIndexer::default();
784 - let file_index = indexer
785 - .index(&file, None, &[], Seconds(3600))
786 - .unwrap();
842 + let file_index = indexer.index(&file, None, &[], Seconds(3600)).unwrap();
843
844 // Anchor at 09:00 (before all entries), going forward
845 let anchor_timestamp = Microseconds(base_timestamp.0 + 9 * 3600_000_000);
790 - let params = LogQueryParamsBuilder::new(
791 - Anchor::Timestamp(anchor_timestamp),
792 - Direction::Forward,
793 - )
794 - .with_limit(10)
795 - .build()
796 - .unwrap();
846 + let params =
847 + LogQueryParamsBuilder::new(Anchor::Timestamp(anchor_timestamp), Direction::Forward)
848 + .with_limit(10)
849 + .build()
850 + .unwrap();
851
852 let results = file_index.find_log_entries(&file, &params).unwrap();
853 assert_eq!(
@@ -803,13 +857,11 @@ fn test_pagination_anchor_before_all_entries() {
857 );
858
859 // Anchor at 09:00, going backward
806 - let params = LogQueryParamsBuilder::new(
807 - Anchor::Timestamp(anchor_timestamp),
808 - Direction::Backward,
809 - )
810 - .with_limit(10)
811 - .build()
812 - .unwrap();
860 + let params =
861 + LogQueryParamsBuilder::new(Anchor::Timestamp(anchor_timestamp), Direction::Backward)
862 + .with_limit(10)
863 + .build()
864 + .unwrap();
865
866 let results = file_index.find_log_entries(&file, &params).unwrap();
867 assert_eq!(
@@ -835,19 +887,15 @@ fn test_pagination_anchor_after_all_entries() {
887 let (_temp_dir, file) = create_test_journal(entries).unwrap();
888
889 let mut indexer = FileIndexer::default();
838 - let file_index = indexer
839 - .index(&file, None, &[], Seconds(3600))
840 - .unwrap();
890 + let file_index = indexer.index(&file, None, &[], Seconds(3600)).unwrap();
891
892 // Anchor at 13:00 (after all entries), going forward
893 let anchor_timestamp = Microseconds(base_timestamp.0 + 13 * 3600_000_000);
844 - let params = LogQueryParamsBuilder::new(
845 - Anchor::Timestamp(anchor_timestamp),
846 - Direction::Forward,
847 - )
848 - .with_limit(10)
849 - .build()
850 - .unwrap();
894 + let params =
895 + LogQueryParamsBuilder::new(Anchor::Timestamp(anchor_timestamp), Direction::Forward)
896 + .with_limit(10)
897 + .build()
898 + .unwrap();
899
900 let results = file_index.find_log_entries(&file, &params).unwrap();
901 assert_eq!(
@@ -857,13 +905,11 @@ fn test_pagination_anchor_after_all_entries() {
905 );
906
907 // Anchor at 13:00, going backward
860 - let params = LogQueryParamsBuilder::new(
861 - Anchor::Timestamp(anchor_timestamp),
862 - Direction::Backward,
863 - )
864 - .with_limit(10)
865 - .build()
866 - .unwrap();
908 + let params =
909 + LogQueryParamsBuilder::new(Anchor::Timestamp(anchor_timestamp), Direction::Backward)
910 + .with_limit(10)
911 + .build()
912 + .unwrap();
913
914 let results = file_index.find_log_entries(&file, &params).unwrap();
915 assert_eq!(
@@ -893,19 +939,15 @@ fn test_pagination_anchor_in_middle_with_pagination() {
939 let (_temp_dir, file) = create_test_journal(entries).unwrap();
940
941 let mut indexer = FileIndexer::default();
896 - let file_index = indexer
897 - .index(&file, None, &[], Seconds(3600))
898 - .unwrap();
942 + let file_index = indexer.index(&file, None, &[], Seconds(3600)).unwrap();
943
944 // Anchor at 12:00 (middle), going forward with limit 2
945 let anchor_timestamp = Microseconds(base_timestamp.0 + 12 * 3600_000_000);
902 - let params = LogQueryParamsBuilder::new(
903 - Anchor::Timestamp(anchor_timestamp),
904 - Direction::Forward,
905 - )
906 - .with_limit(2)
907 - .build()
908 - .unwrap();
946 + let params =
947 + LogQueryParamsBuilder::new(Anchor::Timestamp(anchor_timestamp), Direction::Forward)
948 + .with_limit(2)
949 + .build()
950 + .unwrap();
951
952 let results = file_index.find_log_entries(&file, &params).unwrap();
953 assert_eq!(
@@ -918,27 +960,23 @@ fn test_pagination_anchor_in_middle_with_pagination() {
960 assert_eq!(results[1].position, 3);
961
962 // Paginate forward to get the rest
921 - let params = LogQueryParamsBuilder::new(
922 - Anchor::Timestamp(anchor_timestamp),
923 - Direction::Forward,
924 - )
925 - .with_limit(2)
926 - .with_resume_position(results[1].position)
927 - .build()
928 - .unwrap();
963 + let params =
964 + LogQueryParamsBuilder::new(Anchor::Timestamp(anchor_timestamp), Direction::Forward)
965 + .with_limit(2)
966 + .with_resume_position(results[1].position)
967 + .build()
968 + .unwrap();
969
970 let results = file_index.find_log_entries(&file, &params).unwrap();
971 assert_eq!(results.len(), 1, "Should return remaining 1 entry");
972 assert_eq!(results[0].position, 4);
973
974 // Anchor at 12:00, going backward with limit 2
935 - let params = LogQueryParamsBuilder::new(
936 - Anchor::Timestamp(anchor_timestamp),
937 - Direction::Backward,
938 - )
939 - .with_limit(2)
940 - .build()
941 - .unwrap();
975 + let params =
976 + LogQueryParamsBuilder::new(Anchor::Timestamp(anchor_timestamp), Direction::Backward)
977 + .with_limit(2)
978 + .build()
979 + .unwrap();
980
981 let results = file_index.find_log_entries(&file, &params).unwrap();
982 assert_eq!(
@@ -951,14 +989,12 @@ fn test_pagination_anchor_in_middle_with_pagination() {
989 assert_eq!(results[1].position, 1);
990
991 // Paginate backward to get the rest
954 - let params = LogQueryParamsBuilder::new(
955 - Anchor::Timestamp(anchor_timestamp),
956 - Direction::Backward,
957 - )
958 - .with_limit(2)
959 - .with_resume_position(results[1].position)
960 - .build()
961 - .unwrap();
992 + let params =
993 + LogQueryParamsBuilder::new(Anchor::Timestamp(anchor_timestamp), Direction::Backward)
994 + .with_limit(2)
995 + .with_resume_position(results[1].position)
996 + .build()
997 + .unwrap();
998
999 let results = file_index.find_log_entries(&file, &params).unwrap();
1000 assert_eq!(results.len(), 1, "Should return remaining 1 entry");
@@ -980,9 +1016,7 @@ fn test_pagination_with_time_boundaries() {
1016 let (_temp_dir, file) = create_test_journal(entries).unwrap();
1017
1018 let mut indexer = FileIndexer::default();
983 - let file_index = indexer
984 - .index(&file, None, &[], Seconds(3600))
985 - .unwrap();
1019 + let file_index = indexer.index(&file, None, &[], Seconds(3600)).unwrap();
1020
1021 // Query with after and before boundaries: entries from hour 5 to hour 15 (exclusive)
1022 // That's entries 5, 6, 7, 8, 9, 10, 11, 12, 13, 14 (10 entries total)
@@ -1032,7 +1066,11 @@ fn test_pagination_with_time_boundaries() {
1066 .unwrap();
1067
1068 let results = file_index.find_log_entries(&file, &params).unwrap();
1035 - assert_eq!(results.len(), 2, "Third page should return remaining 2 entries");
1069 + assert_eq!(
1070 + results.len(),
1071 + 2,
1072 + "Third page should return remaining 2 entries"
1073 + );
1074 // Should get entries 13, 14
1075 assert_eq!(results[0].position, 13);
1076 assert_eq!(results[1].position, 14);
@@ -1081,9 +1119,7 @@ fn test_pagination_backward_with_time_boundaries() {
1119 let (_temp_dir, file) = create_test_journal(entries).unwrap();
1120
1121 let mut indexer = FileIndexer::default();
1084 - let file_index = indexer
1085 - .index(&file, None, &[], Seconds(3600))
1086 - .unwrap();
1122 + let file_index = indexer.index(&file, None, &[], Seconds(3600)).unwrap();
1123
1124 // Query backward with boundaries: entries from hour 5 to hour 15 (exclusive)
1125 // That's entries 5-14 (10 entries total), going backward from 14 to 5
@@ -1133,7 +1169,11 @@ fn test_pagination_backward_with_time_boundaries() {
1169 .unwrap();
1170
1171 let results = file_index.find_log_entries(&file, &params).unwrap();
1136 - assert_eq!(results.len(), 2, "Third page should return remaining 2 entries");
1172 + assert_eq!(
1173 + results.len(),
1174 + 2,
1175 + "Third page should return remaining 2 entries"
1176 + );
1177 // Should get 6, 5
1178 assert_eq!(results[0].position, 6);
1179 assert_eq!(results[1].position, 5);
src/crates/journal-log-writer/tests/log_writer.rs
+5 -1
@@ -245,7 +245,11 @@ fn test_boot_id_injection() {
245 })
246 .collect();
247
248 - assert_eq!(journal_files.len(), 1, "Should have created exactly one journal file");
248 + assert_eq!(
249 + journal_files.len(),
250 + 1,
251 + "Should have created exactly one journal file"
252 + );
253
254 let journal_path = journal_files[0].path();
255 let boot_id = load_boot_id().unwrap();
src/crates/netdata-log-viewer/journal-function/src/lib.rs
+3 -3
@@ -11,9 +11,9 @@ pub mod netdata;
11 // Re-export types from journal-engine for convenience
12 pub use journal_engine::{
13 BucketRequest, BucketResponse, CellValue, ColumnInfo, Facets, FileIndexCache,
14 - FileIndexCacheBuilder, FileIndexKey, Histogram, HistogramEngine, IndexingLimits,
15 - LogEntryData, LogQuery, QueryTimeRange, Result, Table, batch_compute_file_indexes,
16 - calculate_bucket_duration, entry_data_to_table,
14 + FileIndexCacheBuilder, FileIndexKey, Histogram, HistogramEngine, IndexingLimits, LogEntryData,
15 + LogQuery, QueryTimeRange, Result, Table, batch_compute_file_indexes, calculate_bucket_duration,
16 + entry_data_to_table,
17 };
18
19 // Re-export Netdata-specific charts/metrics
src/crates/netdata-log-viewer/journal-function/src/netdata/facets.rs
+2 -2
@@ -3,11 +3,11 @@
3 //! This module converts histogram responses into facet structures for the
4 //! Netdata dashboard filtering UI.
5
6 -use journal_engine::Histogram;
6 use super::transformations::TransformationRegistry;
7 use super::ui_types::{Facet, FacetOption};
9 -use journal_index::FieldValuePair;
8 use journal_core::collections::HashMap;
9 +use journal_engine::Histogram;
10 +use journal_index::FieldValuePair;
11
12 /// Creates a list of facets from a Histogram.
13 ///
src/crates/netdata-log-viewer/journal-function/src/netdata/histogram.rs
+2 -1
@@ -66,7 +66,8 @@ fn chart_from_histogram(
66 field: &FieldName,
67 transformations: &TransformationRegistry,
68 ) -> Chart {
69 - let (raw_values, result) = chart_result_from_histogram(histogram_response, field, transformations);
69 + let (raw_values, result) =
70 + chart_result_from_histogram(histogram_response, field, transformations);
71 let view = chart_view_from_histogram(histogram_response, field, &raw_values, &result.labels);
72
73 Chart { view, result }
src/crates/netdata-log-viewer/journal-function/src/netdata/transformations.rs
+4 -1
@@ -625,7 +625,10 @@ pub fn systemd_transformations() -> TransformationRegistry {
625 registry.register("MESSAGE_ID", Arc::new(MessageIdTransformation));
626
627 // OpenTelemetry log fields
628 - registry.register("log.severity_number", Arc::new(OtelSeverityNumberTransformation));
628 + registry.register(
629 + "log.severity_number",
630 + Arc::new(OtelSeverityNumberTransformation),
631 + );
632
633 // Also register variations that exist in the wild
634 registry.register("OBJECT_UID", Arc::new(UidTransformation));
src/crates/netdata-otel/flatten_otel/src/metrics.rs
+3 -3
@@ -1,10 +1,10 @@
1 -use serde_json::{json, Map as JsonMap, Value as JsonValue};
1 +use serde_json::{Map as JsonMap, Value as JsonValue, json};
2
3 use opentelemetry_proto::tonic::{
4 collector::metrics::v1::ExportMetricsServiceRequest,
5 metrics::v1::{
6 - metric::Data, AggregationTemporality, Gauge, Histogram, HistogramDataPoint, Metric,
7 - NumberDataPoint, ResourceMetrics, ScopeMetrics, Sum,
6 + AggregationTemporality, Gauge, Histogram, HistogramDataPoint, Metric, NumberDataPoint,
7 + ResourceMetrics, ScopeMetrics, Sum, metric::Data,
8 },
9 };
10
src/crates/netdata-otel/otel-plugin/src/flattened_point.rs
+4 -1
@@ -101,7 +101,10 @@ impl FlattenedPoint {
101 Some(JsonValue::Number(n)) => n.to_string(),
102 Some(JsonValue::Bool(b)) => b.to_string(),
103 Some(value) => {
104 - eprintln!("Only strings/number/bool values can be used for dimension name >>>{:#?}<<<", value);
104 + eprintln!(
105 + "Only strings/number/bool values can be used for dimension name >>>{:#?}<<<",
106 + value
107 + );
108 return None;
109 }
110 _ => {
src/crates/netdata-otel/otel-plugin/src/logs_service.rs
+6 -1
@@ -153,7 +153,12 @@ impl LogsService for NetdataLogsService {
153 }
154
155 let entry_refs: Vec<&[u8]> = entry_data.iter().map(|v| v.as_slice()).collect();
156 - if let Err(e) = self.log.lock().unwrap().write_entry(&entry_refs, source_timestamp_usec) {
156 + if let Err(e) = self
157 + .log
158 + .lock()
159 + .unwrap()
160 + .write_entry(&entry_refs, source_timestamp_usec)
161 + {
162 eprintln!("Failed to write log entry: {}", e);
163 return Err(Status::internal(format!(
164 "Failed to write log entry: {}",
src/crates/netdata-otel/otel-plugin/src/metrics_service.rs
+2 -2
@@ -1,8 +1,8 @@
1 use anyhow::{Context, Result};
2 use flatten_otel::flatten_metrics_request;
3 use opentelemetry_proto::tonic::collector::metrics::v1::{
4 - metrics_service_server::MetricsService, ExportMetricsServiceRequest,
5 - ExportMetricsServiceResponse,
4 + ExportMetricsServiceRequest, ExportMetricsServiceResponse,
5 + metrics_service_server::MetricsService,
6 };
7 use std::collections::HashMap;
8 use std::sync::Arc;
src/crates/netdata-otel/otel-plugin/src/netdata_chart.rs
+5 -1
@@ -282,7 +282,11 @@ impl NetdataChart {
282 }
283
284 fn emit_set(&self, buffer: &mut ChartOutputBuffer, dimension_name: &str, value: f64) {
285 - buffer.push_str(&format!("SET {} {}\n", dimension_name, value * self.divisor as f64));
285 + buffer.push_str(&format!(
286 + "SET {} {}\n",
287 + dimension_name,
288 + value * self.divisor as f64
289 + ));
290 }
291
292 fn emit_end(&self, buffer: &mut ChartOutputBuffer) {
src/crates/netdata-plugin/charts-derive/src/lib.rs
+1 -1
@@ -5,7 +5,7 @@
5
6 use proc_macro::TokenStream;
7 use quote::quote;
8 -use syn::{parse_macro_input, Data, DeriveInput, Fields};
8 +use syn::{Data, DeriveInput, Fields, parse_macro_input};
9
10 /// Derive macro for NetdataChart trait
11 ///
src/crates/netdata-plugin/error/src/lib.rs
+9 -9
@@ -9,32 +9,32 @@ pub enum NetdataPluginError {
9 /// Transport layer error (I/O, network)
10 #[error("transport error: {0}")]
11 Transport(#[from] std::io::Error),
12 -
12 +
13 /// Protocol parsing or communication error
14 #[error("protocol error: {message}")]
15 Protocol { message: String },
16 -
16 +
17 /// Runtime error during plugin execution
18 - #[error("runtime error: {message}")]
18 + #[error("runtime error: {message}")]
19 Runtime { message: String },
20 -
20 +
21 /// Configuration error
22 #[error("configuration error: {message}")]
23 Config { message: String },
24 -
24 +
25 /// Function handler error
26 #[error("function handler error: {message}")]
27 FunctionHandler { message: String },
28 -
28 +
29 /// Schema validation error
30 #[error("schema validation error: {message}")]
31 Schema { message: String },
32 -
32 +
33 /// Transport is closed
34 #[error("transport is closed")]
35 Closed,
36 -
36 +
37 /// Generic error with custom message
38 #[error("{message}")]
39 Other { message: String },
40 -}
\ No newline at end of file
40 +}
src/crates/netdata-plugin/rt/src/charts/chart_trait.rs
+6 -5
@@ -2,7 +2,7 @@
2
3 use super::metadata::{ChartMetadata, ChartType, DimensionAlgorithm, DimensionMetadata};
4 use super::writer::ChartWriter;
5 -use schemars::{schema_for, JsonSchema};
5 +use schemars::{JsonSchema, schema_for};
6 use serde_json::Value;
7
8 /// Trait for writing chart dimensions efficiently.
@@ -142,7 +142,10 @@ fn extract_chart_metadata<T: serde::Serialize>(schema: &T) -> ChartMetadata {
142 }
143
144 /// Extract dimension metadata from a field schema
145 -fn extract_dimension_metadata(field_name: &str, field_obj: &serde_json::Map<String, Value>) -> DimensionMetadata {
145 +fn extract_dimension_metadata(
146 + field_name: &str,
147 + field_obj: &serde_json::Map<String, Value>,
148 +) -> DimensionMetadata {
149 let mut dim = DimensionMetadata::new(field_name);
150
151 if let Some(name) = extract_string_from_json(field_obj, "x-dimension-name") {
@@ -176,9 +179,7 @@ fn extract_dimension_metadata(field_name: &str, field_obj: &serde_json::Map<Stri
179
180 /// Helper to extract string from JSON object
181 fn extract_string_from_json(obj: &serde_json::Map<String, Value>, key: &str) -> Option<String> {
179 - obj.get(key)
180 - .and_then(|v| v.as_str())
181 - .map(|s| s.to_string())
182 + obj.get(key).and_then(|v| v.as_str()).map(|s| s.to_string())
183 }
184
185 /// Helper to extract i64 from JSON object
src/crates/netdata-plugin/rt/src/charts/registry.rs
+10 -2
@@ -184,7 +184,11 @@ trait ChartSampler: Send + Sync {
184 /// # Parameters
185 /// - `buffer`: Buffer to write the chart data to
186 /// - `collection_time`: When the data was collected
187 - async fn sample_to_buffer(&mut self, buffer: &mut bytes::BytesMut, collection_time: std::time::SystemTime);
187 + async fn sample_to_buffer(
188 + &mut self,
189 + buffer: &mut bytes::BytesMut,
190 + collection_time: std::time::SystemTime,
191 + );
192 fn interval(&self) -> Duration;
193 }
194
@@ -200,7 +204,11 @@ impl<T> ChartSampler for SingletonChartSampler<T>
204 where
205 T: NetdataChart + Default + PartialEq + Clone + Send + Sync,
206 {
203 - async fn sample_to_buffer(&mut self, buffer: &mut BytesMut, collection_time: std::time::SystemTime) {
207 + async fn sample_to_buffer(
208 + &mut self,
209 + buffer: &mut BytesMut,
210 + collection_time: std::time::SystemTime,
211 + ) {
212 // Sample the current value
213 let current = {
214 let guard = self.data.read();
src/crates/netdata-plugin/rt/src/charts/tracker.rs
+17 -4
@@ -22,7 +22,11 @@ impl<T: NetdataChart + Default + PartialEq + Clone> TrackedChart<T> {
22 }
23
24 /// Create a new tracked chart with explicit metadata (used for instantiated templates)
25 - pub(crate) fn new_with_metadata(initial: T, interval: Duration, metadata: ChartMetadata) -> Self {
25 + pub(crate) fn new_with_metadata(
26 + initial: T,
27 + interval: Duration,
28 + metadata: ChartMetadata,
29 + ) -> Self {
30 Self {
31 previous: initial.clone(),
32 current: initial,
@@ -116,15 +120,24 @@ mod tests {
120
121 #[test]
122 fn test_change_detection() {
119 - let initial = TestMetrics { value1: 10, value2: 20 };
123 + let initial = TestMetrics {
124 + value1: 10,
125 + value2: 20,
126 + };
127 let mut tracker = TrackedChart::new(initial.clone(), Duration::from_secs(1));
128
129 assert!(!tracker.has_changed());
130
124 - tracker.update(TestMetrics { value1: 15, value2: 20 });
131 + tracker.update(TestMetrics {
132 + value1: 15,
133 + value2: 20,
134 + });
135 assert!(tracker.has_changed());
136
127 - tracker.update(TestMetrics { value1: 15, value2: 20 });
137 + tracker.update(TestMetrics {
138 + value1: 15,
139 + value2: 20,
140 + });
141 assert!(!tracker.has_changed());
142 }
143
src/crates/netdata-plugin/rt/src/charts/writer.rs
+6 -2
@@ -42,7 +42,8 @@ impl ChartWriter {
42 self.buffer.put_slice(b"' '");
43 self.buffer.put_slice(metadata.context.as_bytes());
44 self.buffer.put_slice(b"' ");
45 - self.buffer.put_slice(metadata.chart_type.as_str().as_bytes());
45 + self.buffer
46 + .put_slice(metadata.chart_type.as_str().as_bytes());
47 self.buffer.put_slice(b" ");
48 self.write_i64(metadata.priority);
49 self.buffer.put_slice(b" ");
@@ -201,7 +202,10 @@ mod tests {
202 writer.end_chart(UNIX_EPOCH + Duration::from_secs(1609459200)); // 2021-01-01 00:00:00 UTC
203
204 let output = String::from_utf8_lossy(&writer.buffer);
204 - assert_eq!(output, "BEGIN test.chart 1000000\nSET value1 = 42\nSET value2 = 13\nEND 1609459200\n");
205 + assert_eq!(
206 + output,
207 + "BEGIN test.chart 1000000\nSET value1 = 42\nSET value2 = 13\nEND 1609459200\n"
208 + );
209 }
210
211 #[test]
src/crates/netdata-plugin/rt/src/lib.rs
+1 -2
@@ -825,8 +825,7 @@ where
825 .expect("outbound_rx consumed only once");
826
827 let writer_task = tokio::spawn(async move {
828 - let mut keepalive =
829 - tokio::time::interval(tokio::time::Duration::from_secs(60));
828 + let mut keepalive = tokio::time::interval(tokio::time::Duration::from_secs(60));
829
830 loop {
831 tokio::select! {
src/crates/netdata-plugin/types/src/dyncfg_source_type.rs
+61 -16
@@ -78,21 +78,51 @@ mod tests {
78
79 #[test]
80 fn test_from_name() {
81 - assert_eq!(DynCfgSourceType::from_name("internal"), Some(DynCfgSourceType::Internal));
82 - assert_eq!(DynCfgSourceType::from_name("stock"), Some(DynCfgSourceType::Stock));
83 - assert_eq!(DynCfgSourceType::from_name("user"), Some(DynCfgSourceType::User));
84 - assert_eq!(DynCfgSourceType::from_name("dyncfg"), Some(DynCfgSourceType::Dyncfg));
85 - assert_eq!(DynCfgSourceType::from_name("discovered"), Some(DynCfgSourceType::Discovered));
81 + assert_eq!(
82 + DynCfgSourceType::from_name("internal"),
83 + Some(DynCfgSourceType::Internal)
84 + );
85 + assert_eq!(
86 + DynCfgSourceType::from_name("stock"),
87 + Some(DynCfgSourceType::Stock)
88 + );
89 + assert_eq!(
90 + DynCfgSourceType::from_name("user"),
91 + Some(DynCfgSourceType::User)
92 + );
93 + assert_eq!(
94 + DynCfgSourceType::from_name("dyncfg"),
95 + Some(DynCfgSourceType::Dyncfg)
96 + );
97 + assert_eq!(
98 + DynCfgSourceType::from_name("discovered"),
99 + Some(DynCfgSourceType::Discovered)
100 + );
101 assert_eq!(DynCfgSourceType::from_name("invalid"), None);
102 }
103
104 #[test]
105 fn test_from_slice() {
91 - assert_eq!(DynCfgSourceType::from_slice(b"internal"), Some(DynCfgSourceType::Internal));
92 - assert_eq!(DynCfgSourceType::from_slice(b" stock "), Some(DynCfgSourceType::Stock));
93 - assert_eq!(DynCfgSourceType::from_slice(b"user"), Some(DynCfgSourceType::User));
94 - assert_eq!(DynCfgSourceType::from_slice(b"dyncfg"), Some(DynCfgSourceType::Dyncfg));
95 - assert_eq!(DynCfgSourceType::from_slice(b"discovered"), Some(DynCfgSourceType::Discovered));
106 + assert_eq!(
107 + DynCfgSourceType::from_slice(b"internal"),
108 + Some(DynCfgSourceType::Internal)
109 + );
110 + assert_eq!(
111 + DynCfgSourceType::from_slice(b" stock "),
112 + Some(DynCfgSourceType::Stock)
113 + );
114 + assert_eq!(
115 + DynCfgSourceType::from_slice(b"user"),
116 + Some(DynCfgSourceType::User)
117 + );
118 + assert_eq!(
119 + DynCfgSourceType::from_slice(b"dyncfg"),
120 + Some(DynCfgSourceType::Dyncfg)
121 + );
122 + assert_eq!(
123 + DynCfgSourceType::from_slice(b"discovered"),
124 + Some(DynCfgSourceType::Discovered)
125 + );
126 assert_eq!(DynCfgSourceType::from_slice(b"invalid"), None);
127 assert_eq!(DynCfgSourceType::from_slice(&[0xFF, 0xFE]), None); // Invalid UTF-8
128 }
@@ -108,11 +138,26 @@ mod tests {
138
139 #[test]
140 fn test_from_str() {
111 - assert_eq!("internal".parse::<DynCfgSourceType>(), Ok(DynCfgSourceType::Internal));
112 - assert_eq!("stock".parse::<DynCfgSourceType>(), Ok(DynCfgSourceType::Stock));
113 - assert_eq!("user".parse::<DynCfgSourceType>(), Ok(DynCfgSourceType::User));
114 - assert_eq!("dyncfg".parse::<DynCfgSourceType>(), Ok(DynCfgSourceType::Dyncfg));
115 - assert_eq!("discovered".parse::<DynCfgSourceType>(), Ok(DynCfgSourceType::Discovered));
141 + assert_eq!(
142 + "internal".parse::<DynCfgSourceType>(),
143 + Ok(DynCfgSourceType::Internal)
144 + );
145 + assert_eq!(
146 + "stock".parse::<DynCfgSourceType>(),
147 + Ok(DynCfgSourceType::Stock)
148 + );
149 + assert_eq!(
150 + "user".parse::<DynCfgSourceType>(),
151 + Ok(DynCfgSourceType::User)
152 + );
153 + assert_eq!(
154 + "dyncfg".parse::<DynCfgSourceType>(),
155 + Ok(DynCfgSourceType::Dyncfg)
156 + );
157 + assert_eq!(
158 + "discovered".parse::<DynCfgSourceType>(),
159 + Ok(DynCfgSourceType::Discovered)
160 + );
161 assert_eq!("invalid".parse::<DynCfgSourceType>(), Err(()));
162 }
163
@@ -120,4 +165,4 @@ mod tests {
165 fn test_default() {
166 assert_eq!(DynCfgSourceType::default(), DynCfgSourceType::Internal);
167 }
123 -}
\ No newline at end of file
168 +}
src/crates/netdata-plugin/types/src/dyncfg_status.rs
+33 -9
@@ -87,19 +87,43 @@ mod tests {
87 #[test]
88 fn test_from_name() {
89 assert_eq!(DynCfgStatus::from_name("none"), Some(DynCfgStatus::None));
90 - assert_eq!(DynCfgStatus::from_name("accepted"), Some(DynCfgStatus::Accepted));
91 - assert_eq!(DynCfgStatus::from_name("running"), Some(DynCfgStatus::Running));
92 - assert_eq!(DynCfgStatus::from_name("failed"), Some(DynCfgStatus::Failed));
93 - assert_eq!(DynCfgStatus::from_name("disabled"), Some(DynCfgStatus::Disabled));
94 - assert_eq!(DynCfgStatus::from_name("orphan"), Some(DynCfgStatus::Orphan));
95 - assert_eq!(DynCfgStatus::from_name("incomplete"), Some(DynCfgStatus::Incomplete));
90 + assert_eq!(
91 + DynCfgStatus::from_name("accepted"),
92 + Some(DynCfgStatus::Accepted)
93 + );
94 + assert_eq!(
95 + DynCfgStatus::from_name("running"),
96 + Some(DynCfgStatus::Running)
97 + );
98 + assert_eq!(
99 + DynCfgStatus::from_name("failed"),
100 + Some(DynCfgStatus::Failed)
101 + );
102 + assert_eq!(
103 + DynCfgStatus::from_name("disabled"),
104 + Some(DynCfgStatus::Disabled)
105 + );
106 + assert_eq!(
107 + DynCfgStatus::from_name("orphan"),
108 + Some(DynCfgStatus::Orphan)
109 + );
110 + assert_eq!(
111 + DynCfgStatus::from_name("incomplete"),
112 + Some(DynCfgStatus::Incomplete)
113 + );
114 assert_eq!(DynCfgStatus::from_name("invalid"), None);
115 }
116
117 #[test]
118 fn test_from_slice() {
101 - assert_eq!(DynCfgStatus::from_slice(b"running"), Some(DynCfgStatus::Running));
102 - assert_eq!(DynCfgStatus::from_slice(b" failed "), Some(DynCfgStatus::Failed));
119 + assert_eq!(
120 + DynCfgStatus::from_slice(b"running"),
121 + Some(DynCfgStatus::Running)
122 + );
123 + assert_eq!(
124 + DynCfgStatus::from_slice(b" failed "),
125 + Some(DynCfgStatus::Failed)
126 + );
127 assert_eq!(DynCfgStatus::from_slice(b"invalid"), None);
128 assert_eq!(DynCfgStatus::from_slice(&[0xFF, 0xFE]), None); // Invalid UTF-8
129 }
@@ -122,4 +146,4 @@ mod tests {
146 fn test_default() {
147 assert_eq!(DynCfgStatus::default(), DynCfgStatus::None);
148 }
125 -}
\ No newline at end of file
149 +}