1#![no_std]
47#![cfg_attr(docsrs, feature(doc_cfg))]
48#![allow(clippy::arithmetic_side_effects)]
49
50pub mod logger;
51
52pub use logger::{Argument, Logger};
54#[cfg(feature = "macro")]
55pub use atlas_program_log_macro::*;
56
57#[cfg(all(not(any(target_os = "atlas", target_arch = "bpf")), feature = "std"))]
60extern crate std;
61
62#[cfg(test)]
63mod tests {
64 use super::{Argument, Logger};
65
66 macro_rules! generate_numeric_test_case {
72 ( $value:expr, $max_len:expr, $($size:expr),+ $(,)? ) => {
73 $(
74 let mut logger = Logger::<$size>::default();
75 logger.append($value);
76 assert!((*logger).len() <= $max_len);
77 )*
78 };
79 }
80
81 macro_rules! generate_str_test_case {
87 ( $str:expr, $($size:expr),+ $(,)? ) => {
88 $(
89 let mut logger = Logger::<$size>::default();
90 logger.append(core::str::from_utf8($str).unwrap());
91 assert_eq!((*logger).len(), core::cmp::min($str.len(), $size));
92 )*
93 };
94 }
95
96 #[test]
97 fn test_logger() {
98 let mut logger = Logger::<100>::default();
99 logger.append("Hello ");
100 logger.append("world!");
101
102 assert!(&*logger == "Hello world!".as_bytes());
103
104 logger.clear();
105
106 logger.append("balance=");
107 logger.append(1_000_000_000);
108
109 assert!(&*logger == "balance=1000000000".as_bytes());
110 }
111
112 #[test]
113 fn test_logger_truncated() {
114 let mut logger = Logger::<8>::default();
115 logger.append("Hello ");
116 logger.append("world!");
117
118 assert!(&*logger == "Hello w@".as_bytes());
119
120 let mut logger = Logger::<12>::default();
121
122 logger.append("balance=");
123 logger.append(1_000_000_000);
124
125 assert!(&*logger == "balance=100@".as_bytes());
126 }
127
128 #[test]
129 fn test_logger_slice() {
130 let mut logger = Logger::<20>::default();
131 logger.append(&["Hello ", "world!"]);
132
133 assert!(&*logger == "[\"Hello \", \"world!\"]".as_bytes());
134
135 let mut logger = Logger::<20>::default();
136 logger.append(&[123, 456]);
137
138 assert!(&*logger == "[123, 456]".as_bytes());
139 }
140
141 #[test]
142 fn test_logger_truncated_slice() {
143 let mut logger = Logger::<5>::default();
144 logger.append(&["Hello ", "world!"]);
145
146 assert!(&*logger == "[\"He@".as_bytes());
147
148 let mut logger = Logger::<4>::default();
149 logger.append(&[123, 456]);
150
151 assert!(&*logger == "[12@".as_bytes());
152 }
153
154 #[test]
155 fn test_logger_signed() {
156 let mut logger = Logger::<2>::default();
157 logger.append(-2);
158
159 assert!(&*logger == "-2".as_bytes());
160
161 let mut logger = Logger::<5>::default();
162 logger.append(-200_000_000);
163
164 assert!(&*logger == "-200@".as_bytes());
165 }
166
167 #[test]
168 fn test_logger_with_precision() {
169 let mut logger = Logger::<10>::default();
170
171 logger.append_with_args(200_000_000u64, &[Argument::Precision(2)]);
172 assert!(&*logger == "2000000.00".as_bytes());
173
174 logger.clear();
175
176 logger.append_with_args(2_000_000_000u64, &[Argument::Precision(2)]);
177 assert!(&*logger == "20000000.@".as_bytes());
178
179 logger.clear();
180
181 logger.append_with_args(2_000_000_000u64, &[Argument::Precision(5)]);
182 assert!(&*logger == "20000.000@".as_bytes());
183
184 logger.clear();
185
186 logger.append_with_args(2_000_000_000u64, &[Argument::Precision(10)]);
187 assert!(&*logger == "0.2000000@".as_bytes());
188
189 logger.clear();
190
191 logger.append_with_args(2u64, &[Argument::Precision(6)]);
192 assert!(&*logger == "0.000002".as_bytes());
193
194 logger.clear();
195
196 logger.append_with_args(2u64, &[Argument::Precision(9)]);
197 assert!(&*logger == "0.0000000@".as_bytes());
198
199 logger.clear();
200
201 logger.append_with_args(-2000000i32, &[Argument::Precision(6)]);
202 assert!(&*logger == "-2.000000".as_bytes());
203
204 logger.clear();
205
206 logger.append_with_args(-2i64, &[Argument::Precision(9)]);
207 assert!(&*logger == "-0.000000@".as_bytes());
208
209 logger.clear();
210
211 logger.append_with_args("0123456789", &[Argument::Precision(2)]);
213 assert!(&*logger == "0123456789".as_bytes());
214
215 logger.clear();
216
217 logger.append_with_args(2u8, &[Argument::Precision(8)]);
218 assert!(&*logger == "0.00000002".as_bytes());
219
220 logger.clear();
221
222 logger.append_with_args(2u8, &[Argument::Precision(u8::MAX)]);
223 assert!(&*logger == "0.0000000@".as_bytes());
224
225 let mut logger = Logger::<20>::default();
226
227 logger.append_with_args(2u8, &[Argument::Precision(u8::MAX)]);
228 assert!(&*logger == "0.00000000000000000@".as_bytes());
229
230 logger.clear();
231
232 logger.append_with_args(20_000u16, &[Argument::Precision(10)]);
233 assert!(&*logger == "0.0000020000".as_bytes());
234
235 let mut logger = Logger::<3>::default();
236
237 logger.append_with_args(2u64, &[Argument::Precision(u8::MAX)]);
238 assert!(&*logger == "0.@".as_bytes());
239
240 logger.clear();
241
242 logger.append_with_args(2u64, &[Argument::Precision(1)]);
243 assert!(&*logger == "0.2".as_bytes());
244
245 logger.clear();
246
247 logger.append_with_args(-2i64, &[Argument::Precision(1)]);
248 assert!(&*logger == "-0@".as_bytes());
249
250 let mut logger = Logger::<1>::default();
251
252 logger.append_with_args(-2i64, &[Argument::Precision(1)]);
253 assert!(&*logger == "@".as_bytes());
254
255 let mut logger = Logger::<2>::default();
256
257 logger.append_with_args(-2i64, &[Argument::Precision(1)]);
258 assert!(&*logger == "-@".as_bytes());
259
260 let mut logger = Logger::<20>::default();
261
262 logger.append_with_args(u64::MAX, &[Argument::Precision(u8::MAX)]);
263 assert!(&*logger == "0.00000000000000000@".as_bytes());
264
265 let mut logger = Logger::<257>::default();
267 logger.append_with_args(u64::MAX, &[Argument::Precision(u8::MAX)]);
268 assert!(logger.starts_with("0.00000000000000".as_bytes()));
269 assert!(logger.ends_with("18446744073709551615".as_bytes()));
270
271 logger.clear();
272
273 logger.append_with_args(u32::MAX, &[Argument::Precision(u8::MAX)]);
274 assert!(logger.starts_with("0.00000000000000".as_bytes()));
275 assert!(logger.ends_with("4294967295".as_bytes()));
276
277 logger.clear();
278
279 logger.append_with_args(u16::MAX, &[Argument::Precision(u8::MAX)]);
280 assert!(logger.starts_with("0.00000000000000".as_bytes()));
281 assert!(logger.ends_with("65535".as_bytes()));
282
283 logger.clear();
284
285 logger.append_with_args(u8::MAX, &[Argument::Precision(u8::MAX)]);
286 assert!(logger.starts_with("0.00000000000000".as_bytes()));
287 assert!(logger.ends_with("255".as_bytes()));
288
289 let mut logger = Logger::<258>::default();
291 logger.append_with_args(i64::MIN, &[Argument::Precision(u8::MAX)]);
292 assert!(logger.starts_with("-0.00000000000000".as_bytes()));
293 assert!(logger.ends_with("9223372036854775808".as_bytes()));
294
295 logger.clear();
296
297 logger.append_with_args(i32::MIN, &[Argument::Precision(u8::MAX)]);
298 assert!(logger.starts_with("-0.00000000000000".as_bytes()));
299 assert!(logger.ends_with("2147483648".as_bytes()));
300
301 logger.clear();
302
303 logger.append_with_args(i16::MIN, &[Argument::Precision(u8::MAX)]);
304 assert!(logger.starts_with("-0.00000000000000".as_bytes()));
305 assert!(logger.ends_with("32768".as_bytes()));
306
307 logger.clear();
308
309 logger.append_with_args(i8::MIN, &[Argument::Precision(u8::MAX)]);
310 assert!(logger.starts_with("-0.00000000000000".as_bytes()));
311 assert!(logger.ends_with("128".as_bytes()));
312 }
313
314 #[test]
315 fn test_logger_with_truncate() {
316 let mut logger = Logger::<10>::default();
317
318 logger.append_with_args("0123456789", &[Argument::TruncateEnd(10)]);
319 assert!(&*logger == "0123456789".as_bytes());
320
321 logger.clear();
322
323 logger.append_with_args("0123456789", &[Argument::TruncateStart(10)]);
324 assert!(&*logger == "0123456789".as_bytes());
325
326 logger.clear();
327
328 logger.append_with_args("0123456789", &[Argument::TruncateEnd(9)]);
329 assert!(&*logger == "012345...".as_bytes());
330
331 logger.clear();
332
333 logger.append_with_args("0123456789", &[Argument::TruncateStart(9)]);
334 assert!(&*logger == "...456789".as_bytes());
335
336 let mut logger = Logger::<3>::default();
337
338 logger.append_with_args("0123456789", &[Argument::TruncateEnd(9)]);
339 assert!(&*logger == "..@".as_bytes());
340
341 logger.clear();
342
343 logger.append_with_args("0123456789", &[Argument::TruncateStart(9)]);
344 assert!(&*logger == "..@".as_bytes());
345
346 let mut logger = Logger::<1>::default();
347
348 logger.append_with_args("test", &[Argument::TruncateStart(0)]);
349 assert!(&*logger == "".as_bytes());
350
351 logger.clear();
352
353 logger.append_with_args("test", &[Argument::TruncateStart(1)]);
354 assert!(&*logger == "@".as_bytes());
355
356 let mut logger = Logger::<2>::default();
357
358 logger.append_with_args("test", &[Argument::TruncateStart(2)]);
359 assert!(&*logger == ".@".as_bytes());
360
361 let mut logger = Logger::<3>::default();
362
363 logger.append_with_args("test", &[Argument::TruncateStart(3)]);
364 assert!(&*logger == "..@".as_bytes());
365
366 let mut logger = Logger::<1>::default();
367
368 logger.append_with_args("test", &[Argument::TruncateEnd(0)]);
369 assert!(&*logger == "".as_bytes());
370
371 logger.clear();
372
373 logger.append_with_args("test", &[Argument::TruncateEnd(1)]);
374 assert!(&*logger == "@".as_bytes());
375
376 let mut logger = Logger::<2>::default();
377
378 logger.append_with_args("test", &[Argument::TruncateEnd(2)]);
379 assert!(&*logger == ".@".as_bytes());
380
381 let mut logger = Logger::<3>::default();
382
383 logger.append_with_args("test", &[Argument::TruncateEnd(3)]);
384 assert!(&*logger == "..@".as_bytes());
385 }
386
387 #[test]
388 fn test_logger_with_usize() {
389 let mut logger = Logger::<20>::default();
390
391 logger.append(usize::MIN);
392 assert!(&*logger == "0".as_bytes());
393
394 logger.clear();
395
396 logger.append(usize::MAX);
397
398 #[cfg(target_pointer_width = "32")]
399 {
400 assert!(&*logger == "4294967295".as_bytes());
401 assert_eq!(logger.len(), 10);
402 }
403 #[cfg(target_pointer_width = "64")]
404 {
405 assert!(&*logger == "18446744073709551615".as_bytes());
406 assert_eq!(logger.len(), 20);
407 }
408 }
409
410 #[test]
411 fn test_logger_with_isize() {
412 let mut logger = Logger::<20>::default();
413
414 logger.append(isize::MIN);
415
416 #[cfg(target_pointer_width = "32")]
417 {
418 assert!(&*logger == "-2147483648".as_bytes());
419 assert_eq!(logger.len(), 11);
420 }
421 #[cfg(target_pointer_width = "64")]
422 {
423 assert!(&*logger == "-9223372036854775808".as_bytes());
424 assert_eq!(logger.len(), 20);
425 }
426
427 logger.clear();
428
429 logger.append(isize::MAX);
430
431 #[cfg(target_pointer_width = "32")]
432 {
433 assert!(&*logger == "2147483647".as_bytes());
434 assert_eq!(logger.len(), 10);
435 }
436 #[cfg(target_pointer_width = "64")]
437 {
438 assert!(&*logger == "9223372036854775807".as_bytes());
439 assert_eq!(logger.len(), 19);
440 }
441 }
442
443 #[test]
444 fn test_logger_buffer_size_unsigned() {
445 macro_rules! unsigned_test_case {
447 ( $( ($ty:ident, $max_len:literal) ),+ $(,)? ) => {
448 $(
449 generate_numeric_test_case!($ty::MAX, $max_len, 1,
450 2,
451 3,
452 4,
453 5,
454 6,
455 7,
456 8,
457 9,
458 10,
459 11,
460 12,
461 13,
462 14,
463 15,
464 16,
465 17,
466 18,
467 19,
468 20,
469 50,
470 100,
471 1000);
472 )*
473 };
474 }
475
476 unsigned_test_case!((u8, 3), (u16, 5), (u32, 10), (u64, 20), (usize, 20));
477 #[cfg(not(target_arch = "bpf"))]
478 unsigned_test_case!((u128, 39),);
479 }
480
481 #[test]
482 fn test_logger_buffer_size_signed() {
483 macro_rules! signed_test_case {
485 ( $( ($ty:ident, $max_len:literal) ),+ $(,)? ) => {
486 $(
487 generate_numeric_test_case!($ty::MIN, ($max_len + 1), 1,
488 2,
489 3,
490 4,
491 5,
492 6,
493 7,
494 8,
495 9,
496 10,
497 11,
498 12,
499 13,
500 14,
501 15,
502 16,
503 17,
504 18,
505 19,
506 20,
507 50,
508 100,
509 1000);
510 )*
511 };
512 }
513
514 signed_test_case!((i8, 3), (i16, 5), (i32, 10), (i64, 20), (isize, 20));
515 #[cfg(not(target_arch = "bpf"))]
516 signed_test_case!((i128, 39),);
517 }
518
519 #[test]
520 fn test_logger_buffer_size_str() {
521 macro_rules! str_test_case {
523 ( $( $size:expr ),+ $(,)? ) => {
524 $(
525 generate_str_test_case!(&[b'x'; $size], 1,
526 2,
527 3,
528 4,
529 5,
530 6,
531 7,
532 8,
533 9,
534 10,
535 11,
536 12,
537 13,
538 14,
539 15,
540 16,
541 17,
542 18,
543 19,
544 20,
545 50,
546 100,
547 1000);
548 )*
549 };
550 }
551
552 str_test_case!(1, 5, 10, 50, 100, 1000, 10000);
553 }
554
555 #[test]
556 fn test_logger_bool() {
557 let mut logger = Logger::<5>::default();
558 logger.append(true);
559
560 assert!(&*logger == "true".as_bytes());
561
562 let mut logger = Logger::<5>::default();
563 logger.append(false);
564
565 assert!(&*logger == "false".as_bytes());
566
567 let mut logger = Logger::<3>::default();
568 logger.append(true);
569
570 assert!(&*logger == "tr@".as_bytes());
571
572 let mut logger = Logger::<4>::default();
573 logger.append(false);
574
575 assert!(&*logger == "fal@".as_bytes());
576 }
577}