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