tests.rs 9.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267
  1. #![feature(c_variadic)]
  2. use core::{ffi::*, ptr::null_mut};
  3. extern "C" {
  4. fn asprintf(s: *mut *mut c_char, format: *const c_char, ...) -> c_int;
  5. fn free(p: *mut c_void);
  6. }
  7. unsafe extern "C" fn rust_fmt(str: *const c_char, mut args: ...) -> Box<(c_int, String)> {
  8. let mut s = String::new();
  9. let bytes_written = printf_compat::format(
  10. str,
  11. args.clone().as_va_list(),
  12. printf_compat::output::fmt_write(&mut s),
  13. );
  14. assert!(bytes_written >= 0);
  15. let mut s2 = std::io::Cursor::new(vec![]);
  16. assert_eq!(
  17. bytes_written,
  18. printf_compat::format(
  19. str,
  20. args.as_va_list(),
  21. printf_compat::output::io_write(&mut s2),
  22. )
  23. );
  24. assert_eq!(s.as_bytes(), s2.get_ref());
  25. Box::new((bytes_written, s))
  26. }
  27. macro_rules! c_fmt {
  28. ($format:literal $(, $p:expr)*) => {{
  29. let mut ptr = null_mut();
  30. let bytes_written = asprintf(&mut ptr, $format.as_ptr() $(, $p)*);
  31. assert!(bytes_written >= 0);
  32. let s: String = CStr::from_ptr(ptr).to_string_lossy().into();
  33. free(ptr.cast());
  34. (bytes_written, s)
  35. }};
  36. }
  37. /// Assert that `rust_fmt` produces the same output as C's `asprintf`,
  38. /// and that both match the `expected` literal.
  39. ///
  40. /// This takes a format literal, followed by optional printf arguments,
  41. /// followed by `=>` and then the `expected` output.
  42. ///
  43. /// Example usage:
  44. ///
  45. /// ```
  46. /// assert_eq_fmt!(c"%d %d", 1, 2 => "1 2");
  47. /// ```
  48. macro_rules! assert_eq_fmt {
  49. ($format:literal $(, $p:expr)* => $expected:literal) => {
  50. let (bytes_written, s) = c_fmt!($format $(, $p)*);
  51. assert_eq!(s, $expected);
  52. assert_eq!((bytes_written, s), *rust_fmt($format.as_ptr().cast(), $($p),*));
  53. assert_eq!(usize::try_from(bytes_written).unwrap(), $expected.len());
  54. };
  55. }
  56. /// Assert that a format string fails to parse. This checks that both
  57. /// C's `asprintf` and `printf_compat::format` return -1.
  58. fn assert_fmt_err(fmt: &CStr) {
  59. let mut ptr = null_mut();
  60. let bytes_written = unsafe { asprintf(&mut ptr, fmt.as_ptr()) };
  61. assert_eq!(bytes_written, -1, "asprintf parse unexpectedly succeeded");
  62. unsafe extern "C" fn format(str: *const c_char, args: ...) -> c_int {
  63. let mut s = String::new();
  64. let bytes_written = printf_compat::format(
  65. str,
  66. args.clone().as_va_list(),
  67. printf_compat::output::fmt_write(&mut s),
  68. );
  69. bytes_written
  70. }
  71. let bytes_written = unsafe { format(fmt.as_ptr()) };
  72. assert_eq!(
  73. bytes_written, -1,
  74. "printf_compat::output parse unexpectedly succeeded"
  75. );
  76. }
  77. #[test]
  78. fn test_plain() {
  79. unsafe {
  80. assert_eq_fmt!(c"abc" => "abc");
  81. assert_eq_fmt!(c"" => "");
  82. assert_eq_fmt!(c"%%" => "%");
  83. assert_eq_fmt!(c"%% def" => "% def");
  84. assert_eq_fmt!(c"abc %%" => "abc %");
  85. assert_eq_fmt!(c"abc %% def" => "abc % def");
  86. assert_eq_fmt!(c"abc %%%% def" => "abc %% def");
  87. assert_eq_fmt!(c"%%%%%%" => "%%%");
  88. }
  89. }
  90. #[test]
  91. fn test_str() {
  92. unsafe {
  93. assert_eq_fmt!(c"hello %s", c"world" => "hello world");
  94. assert_eq_fmt!(c"hello %%%s", c"world" => "hello %world");
  95. assert_eq_fmt!(c"%10s", c"world" => " world");
  96. assert_eq_fmt!(c"%.4s", c"world" => "worl");
  97. assert_eq_fmt!(c"%10.4s", c"world" => " worl");
  98. assert_eq_fmt!(c"%-10.4s", c"world" => "worl ");
  99. assert_eq_fmt!(c"%-10s", c"world" => "world ");
  100. assert_eq_fmt!(c"%s", null_mut::<c_char>() => "(null)");
  101. }
  102. }
  103. #[test]
  104. fn test_int() {
  105. unsafe {
  106. assert_eq_fmt!(c"% 0*i", 17, 23125 => " 0000000000023125");
  107. assert_eq_fmt!(c"% 010i", 23125 => " 000023125");
  108. assert_eq_fmt!(c"% 10i", 23125 => " 23125");
  109. assert_eq_fmt!(c"% 5i", 23125 => " 23125");
  110. assert_eq_fmt!(c"% 4i", 23125 => " 23125");
  111. assert_eq_fmt!(c"%- 010i", 23125 => " 23125 ");
  112. assert_eq_fmt!(c"%- 10i", 23125 => " 23125 ");
  113. assert_eq_fmt!(c"%- 5i", 23125 => " 23125");
  114. assert_eq_fmt!(c"%- 4i", 23125 => " 23125");
  115. assert_eq_fmt!(c"%+ 010i", 23125 => "+000023125");
  116. assert_eq_fmt!(c"%+ 10i", 23125 => " +23125");
  117. assert_eq_fmt!(c"%+ 5i", 23125 => "+23125");
  118. assert_eq_fmt!(c"%+ 4i", 23125 => "+23125");
  119. assert_eq_fmt!(c"%-010i", 23125 => "23125 ");
  120. assert_eq_fmt!(c"%-10i", 23125 => "23125 ");
  121. assert_eq_fmt!(c"%-5i", 23125 => "23125");
  122. assert_eq_fmt!(c"%-4i", 23125 => "23125");
  123. }
  124. }
  125. #[test]
  126. fn test_int_length_signed() {
  127. unsafe {
  128. assert_eq_fmt!(c"%hhi", -125 => "-125");
  129. assert_eq_fmt!(c"%hi", -23125 => "-23125");
  130. assert_eq_fmt!(c"%li", -211_126_823_125i64 => "-211126823125");
  131. assert_eq_fmt!(c"%lli", -211_126_823_125i64 => "-211126823125");
  132. assert_eq_fmt!(c"%ti", -211_126_823_125isize => "-211126823125");
  133. assert_eq_fmt!(c"%zi", 211_126_823_125usize => "211126823125");
  134. assert_eq_fmt!(c"% 5hhi", -125 => " -125");
  135. assert_eq_fmt!(c"% 7hi", -23125 => " -23125");
  136. assert_eq_fmt!(c"% 14li", -211_126_823_125i64 => " -211126823125");
  137. assert_eq_fmt!(c"% 14lli", -211_126_823_125i64 => " -211126823125");
  138. assert_eq_fmt!(c"% 14ti", -211_126_823_125isize => " -211126823125");
  139. assert_eq_fmt!(c"% 13zi", 211_126_823_125usize => " 211126823125");
  140. }
  141. }
  142. #[test]
  143. fn test_int_length_unsigned() {
  144. unsafe {
  145. assert_eq_fmt!(c"%hhu", 125 => "125");
  146. assert_eq_fmt!(c"%hu", 23125 => "23125");
  147. assert_eq_fmt!(c"%lu", 211_126_823_125u64 => "211126823125");
  148. assert_eq_fmt!(c"%llu", 211_126_823_125u64 => "211126823125");
  149. assert_eq_fmt!(c"%tu", 211_126_823_125isize => "211126823125");
  150. assert_eq_fmt!(c"%zu", 211_126_823_125usize => "211126823125");
  151. }
  152. }
  153. #[test]
  154. fn test_octal() {
  155. unsafe {
  156. assert_eq_fmt!(c"% 010o", 23125 => "0000055125");
  157. assert_eq_fmt!(c"% 10o", 23125 => " 55125");
  158. assert_eq_fmt!(c"% 5o", 23125 => "55125");
  159. assert_eq_fmt!(c"% 4o", 23125 => "55125");
  160. assert_eq_fmt!(c"%- 010o", 23125 => "55125 ");
  161. assert_eq_fmt!(c"%- 10o", 23125 => "55125 ");
  162. assert_eq_fmt!(c"%- 5o", 23125 => "55125");
  163. assert_eq_fmt!(c"%- 4o", 23125 => "55125");
  164. assert_eq_fmt!(c"%+ 010o", 23125 => "0000055125");
  165. assert_eq_fmt!(c"%+ 10o", 23125 => " 55125");
  166. assert_eq_fmt!(c"%+ 5o", 23125 => "55125");
  167. assert_eq_fmt!(c"%+ 4o", 23125 => "55125");
  168. assert_eq_fmt!(c"%-010o", 23125 => "55125 ");
  169. assert_eq_fmt!(c"%-10o", 23125 => "55125 ");
  170. assert_eq_fmt!(c"%-5o", 23125 => "55125");
  171. assert_eq_fmt!(c"%-4o", 23125 => "55125");
  172. }
  173. }
  174. #[test]
  175. fn test_hex() {
  176. unsafe {
  177. assert_eq_fmt!(c"% 010x", 23125 => "0000005a55");
  178. assert_eq_fmt!(c"% 10x", 23125 => " 5a55");
  179. assert_eq_fmt!(c"% 5x", 23125 => " 5a55");
  180. assert_eq_fmt!(c"% 4x", 23125 => "5a55");
  181. assert_eq_fmt!(c"%- 010x", 23125 => "5a55 ");
  182. assert_eq_fmt!(c"%- 10x", 23125 => "5a55 ");
  183. assert_eq_fmt!(c"%- 5x", 23125 => "5a55 ");
  184. assert_eq_fmt!(c"%- 4x", 23125 => "5a55");
  185. assert_eq_fmt!(c"%+ 010x", 23125 => "0000005a55");
  186. assert_eq_fmt!(c"%+ 10x", 23125 => " 5a55");
  187. assert_eq_fmt!(c"%+ 5x", 23125 => " 5a55");
  188. assert_eq_fmt!(c"%+ 4x", 23125 => "5a55");
  189. assert_eq_fmt!(c"%-010x", 23125 => "5a55 ");
  190. assert_eq_fmt!(c"%-10x", 23125 => "5a55 ");
  191. assert_eq_fmt!(c"%-5x", 23125 => "5a55 ");
  192. assert_eq_fmt!(c"%-4x", 23125 => "5a55");
  193. assert_eq_fmt!(c"%# 010x", 23125 => "0x00005a55");
  194. assert_eq_fmt!(c"%# 10x", 23125 => " 0x5a55");
  195. assert_eq_fmt!(c"%# 5x", 23125 => "0x5a55");
  196. assert_eq_fmt!(c"%# 4x", 23125 => "0x5a55");
  197. assert_eq_fmt!(c"%#- 010x", 23125 => "0x5a55 ");
  198. assert_eq_fmt!(c"%#- 10x", 23125 => "0x5a55 ");
  199. assert_eq_fmt!(c"%#- 5x", 23125 => "0x5a55");
  200. assert_eq_fmt!(c"%#- 4x", 23125 => "0x5a55");
  201. assert_eq_fmt!(c"%#+ 010x", 23125 => "0x00005a55");
  202. assert_eq_fmt!(c"%#+ 10x", 23125 => " 0x5a55");
  203. assert_eq_fmt!(c"%#+ 5x", 23125 => "0x5a55");
  204. assert_eq_fmt!(c"%#+ 4x", 23125 => "0x5a55");
  205. assert_eq_fmt!(c"%#-010x", 23125 => "0x5a55 ");
  206. assert_eq_fmt!(c"%#-10x", 23125 => "0x5a55 ");
  207. assert_eq_fmt!(c"%#-5x", 23125 => "0x5a55");
  208. assert_eq_fmt!(c"%#-4x", 23125 => "0x5a55");
  209. assert_eq_fmt!(c"% 010X", 23125 => "0000005A55");
  210. assert_eq_fmt!(c"% 10X", 23125 => " 5A55");
  211. assert_eq_fmt!(c"% 5X", 23125 => " 5A55");
  212. assert_eq_fmt!(c"% 4X", 23125 => "5A55");
  213. assert_eq_fmt!(c"%- 010X", 23125 => "5A55 ");
  214. assert_eq_fmt!(c"%- 10X", 23125 => "5A55 ");
  215. assert_eq_fmt!(c"%- 5X", 23125 => "5A55 ");
  216. assert_eq_fmt!(c"%- 4X", 23125 => "5A55");
  217. assert_eq_fmt!(c"%+ 010X", 23125 => "0000005A55");
  218. assert_eq_fmt!(c"%+ 10X", 23125 => " 5A55");
  219. assert_eq_fmt!(c"%+ 5X", 23125 => " 5A55");
  220. assert_eq_fmt!(c"%+ 4X", 23125 => "5A55");
  221. assert_eq_fmt!(c"%-010X", 23125 => "5A55 ");
  222. assert_eq_fmt!(c"%-10X", 23125 => "5A55 ");
  223. assert_eq_fmt!(c"%-5X", 23125 => "5A55 ");
  224. assert_eq_fmt!(c"%-4X", 23125 => "5A55");
  225. }
  226. }
  227. #[test]
  228. fn test_float() {
  229. unsafe {
  230. assert_eq_fmt!(c"%f", 1234f64 => "1234.000000");
  231. assert_eq_fmt!(c"%.5f", 1234f64 => "1234.00000");
  232. assert_eq_fmt!(c"%.*f", 1234f64, 3 => "1234.000");
  233. }
  234. }
  235. #[test]
  236. fn test_char() {
  237. unsafe {
  238. assert_eq_fmt!(c"%c", b'a' as c_int => "a");
  239. assert_eq_fmt!(c"%10c", b'a' as c_int => " a");
  240. assert_eq_fmt!(c"%-10c", b'a' as c_int => "a ");
  241. }
  242. }
  243. #[test]
  244. fn test_errors() {
  245. assert_fmt_err(c"%");
  246. assert_fmt_err(c"%1");
  247. }