112a9d9c8Sopenharmony_ci# Write a Sanity Test 212a9d9c8Sopenharmony_ci 312a9d9c8Sopenharmony_ciFinally, to tie everything together, let's write a sanity test that round trips 412a9d9c8Sopenharmony_cisome text through compression and decompression, and then asserts that it came 512a9d9c8Sopenharmony_ciback out the same as it went in. This is a little wordy using the raw FFI 612a9d9c8Sopenharmony_cibindings, but hopefully we wouldn't usually ask people to do this, we'd provide 712a9d9c8Sopenharmony_cia nice Rust-y API on top of the raw FFI bindings for them. However, since this 812a9d9c8Sopenharmony_ciis for testing the bindings directly, our sanity test will use the bindings 912a9d9c8Sopenharmony_cidirectly. 1012a9d9c8Sopenharmony_ci 1112a9d9c8Sopenharmony_ciThe test data I'm round tripping are some Futurama quotes I got off the internet 1212a9d9c8Sopenharmony_ciand put in the `futurama-quotes.txt` file, which is read into a `&'static str` 1312a9d9c8Sopenharmony_ciat compile time via the `include_str!("../futurama-quotes.txt")` macro 1412a9d9c8Sopenharmony_ciinvocation. 1512a9d9c8Sopenharmony_ci 1612a9d9c8Sopenharmony_ciWithout further ado, here is the test, which should be appended to the bottom of 1712a9d9c8Sopenharmony_ciour `src/lib.rs` file: 1812a9d9c8Sopenharmony_ci 1912a9d9c8Sopenharmony_ci```rust 2012a9d9c8Sopenharmony_ci#[cfg(test)] 2112a9d9c8Sopenharmony_cimod tests { 2212a9d9c8Sopenharmony_ci use super::*; 2312a9d9c8Sopenharmony_ci use std::mem; 2412a9d9c8Sopenharmony_ci 2512a9d9c8Sopenharmony_ci #[test] 2612a9d9c8Sopenharmony_ci fn round_trip_compression_decompression() { 2712a9d9c8Sopenharmony_ci unsafe { 2812a9d9c8Sopenharmony_ci let input = include_str!("../futurama-quotes.txt").as_bytes(); 2912a9d9c8Sopenharmony_ci let mut compressed_output: Vec<u8> = vec![0; input.len()]; 3012a9d9c8Sopenharmony_ci let mut decompressed_output: Vec<u8> = vec![0; input.len()]; 3112a9d9c8Sopenharmony_ci 3212a9d9c8Sopenharmony_ci // Construct a compression stream. 3312a9d9c8Sopenharmony_ci let mut stream: bz_stream = mem::zeroed(); 3412a9d9c8Sopenharmony_ci let result = BZ2_bzCompressInit(&mut stream as *mut _, 3512a9d9c8Sopenharmony_ci 1, // 1 x 100000 block size 3612a9d9c8Sopenharmony_ci 4, // verbosity (4 = most verbose) 3712a9d9c8Sopenharmony_ci 0); // default work factor 3812a9d9c8Sopenharmony_ci match result { 3912a9d9c8Sopenharmony_ci r if r == (BZ_CONFIG_ERROR as _) => panic!("BZ_CONFIG_ERROR"), 4012a9d9c8Sopenharmony_ci r if r == (BZ_PARAM_ERROR as _) => panic!("BZ_PARAM_ERROR"), 4112a9d9c8Sopenharmony_ci r if r == (BZ_MEM_ERROR as _) => panic!("BZ_MEM_ERROR"), 4212a9d9c8Sopenharmony_ci r if r == (BZ_OK as _) => {}, 4312a9d9c8Sopenharmony_ci r => panic!("Unknown return value = {}", r), 4412a9d9c8Sopenharmony_ci } 4512a9d9c8Sopenharmony_ci 4612a9d9c8Sopenharmony_ci // Compress `input` into `compressed_output`. 4712a9d9c8Sopenharmony_ci stream.next_in = input.as_ptr() as *mut _; 4812a9d9c8Sopenharmony_ci stream.avail_in = input.len() as _; 4912a9d9c8Sopenharmony_ci stream.next_out = compressed_output.as_mut_ptr() as *mut _; 5012a9d9c8Sopenharmony_ci stream.avail_out = compressed_output.len() as _; 5112a9d9c8Sopenharmony_ci let result = BZ2_bzCompress(&mut stream as *mut _, BZ_FINISH as _); 5212a9d9c8Sopenharmony_ci match result { 5312a9d9c8Sopenharmony_ci r if r == (BZ_RUN_OK as _) => panic!("BZ_RUN_OK"), 5412a9d9c8Sopenharmony_ci r if r == (BZ_FLUSH_OK as _) => panic!("BZ_FLUSH_OK"), 5512a9d9c8Sopenharmony_ci r if r == (BZ_FINISH_OK as _) => panic!("BZ_FINISH_OK"), 5612a9d9c8Sopenharmony_ci r if r == (BZ_SEQUENCE_ERROR as _) => panic!("BZ_SEQUENCE_ERROR"), 5712a9d9c8Sopenharmony_ci r if r == (BZ_STREAM_END as _) => {}, 5812a9d9c8Sopenharmony_ci r => panic!("Unknown return value = {}", r), 5912a9d9c8Sopenharmony_ci } 6012a9d9c8Sopenharmony_ci 6112a9d9c8Sopenharmony_ci // Finish the compression stream. 6212a9d9c8Sopenharmony_ci let result = BZ2_bzCompressEnd(&mut stream as *mut _); 6312a9d9c8Sopenharmony_ci match result { 6412a9d9c8Sopenharmony_ci r if r == (BZ_PARAM_ERROR as _) => panic!("BZ_PARAM_ERROR"), 6512a9d9c8Sopenharmony_ci r if r == (BZ_OK as _) => {}, 6612a9d9c8Sopenharmony_ci r => panic!("Unknown return value = {}", r), 6712a9d9c8Sopenharmony_ci } 6812a9d9c8Sopenharmony_ci 6912a9d9c8Sopenharmony_ci // Construct a decompression stream. 7012a9d9c8Sopenharmony_ci let mut stream: bz_stream = mem::zeroed(); 7112a9d9c8Sopenharmony_ci let result = BZ2_bzDecompressInit(&mut stream as *mut _, 7212a9d9c8Sopenharmony_ci 4, // verbosity (4 = most verbose) 7312a9d9c8Sopenharmony_ci 0); // default small factor 7412a9d9c8Sopenharmony_ci match result { 7512a9d9c8Sopenharmony_ci r if r == (BZ_CONFIG_ERROR as _) => panic!("BZ_CONFIG_ERROR"), 7612a9d9c8Sopenharmony_ci r if r == (BZ_PARAM_ERROR as _) => panic!("BZ_PARAM_ERROR"), 7712a9d9c8Sopenharmony_ci r if r == (BZ_MEM_ERROR as _) => panic!("BZ_MEM_ERROR"), 7812a9d9c8Sopenharmony_ci r if r == (BZ_OK as _) => {}, 7912a9d9c8Sopenharmony_ci r => panic!("Unknown return value = {}", r), 8012a9d9c8Sopenharmony_ci } 8112a9d9c8Sopenharmony_ci 8212a9d9c8Sopenharmony_ci // Decompress `compressed_output` into `decompressed_output`. 8312a9d9c8Sopenharmony_ci stream.next_in = compressed_output.as_ptr() as *mut _; 8412a9d9c8Sopenharmony_ci stream.avail_in = compressed_output.len() as _; 8512a9d9c8Sopenharmony_ci stream.next_out = decompressed_output.as_mut_ptr() as *mut _; 8612a9d9c8Sopenharmony_ci stream.avail_out = decompressed_output.len() as _; 8712a9d9c8Sopenharmony_ci let result = BZ2_bzDecompress(&mut stream as *mut _); 8812a9d9c8Sopenharmony_ci match result { 8912a9d9c8Sopenharmony_ci r if r == (BZ_PARAM_ERROR as _) => panic!("BZ_PARAM_ERROR"), 9012a9d9c8Sopenharmony_ci r if r == (BZ_DATA_ERROR as _) => panic!("BZ_DATA_ERROR"), 9112a9d9c8Sopenharmony_ci r if r == (BZ_DATA_ERROR_MAGIC as _) => panic!("BZ_DATA_ERROR"), 9212a9d9c8Sopenharmony_ci r if r == (BZ_MEM_ERROR as _) => panic!("BZ_MEM_ERROR"), 9312a9d9c8Sopenharmony_ci r if r == (BZ_OK as _) => panic!("BZ_OK"), 9412a9d9c8Sopenharmony_ci r if r == (BZ_STREAM_END as _) => {}, 9512a9d9c8Sopenharmony_ci r => panic!("Unknown return value = {}", r), 9612a9d9c8Sopenharmony_ci } 9712a9d9c8Sopenharmony_ci 9812a9d9c8Sopenharmony_ci // Close the decompression stream. 9912a9d9c8Sopenharmony_ci let result = BZ2_bzDecompressEnd(&mut stream as *mut _); 10012a9d9c8Sopenharmony_ci match result { 10112a9d9c8Sopenharmony_ci r if r == (BZ_PARAM_ERROR as _) => panic!("BZ_PARAM_ERROR"), 10212a9d9c8Sopenharmony_ci r if r == (BZ_OK as _) => {}, 10312a9d9c8Sopenharmony_ci r => panic!("Unknown return value = {}", r), 10412a9d9c8Sopenharmony_ci } 10512a9d9c8Sopenharmony_ci 10612a9d9c8Sopenharmony_ci assert_eq!(input, &decompressed_output[..]); 10712a9d9c8Sopenharmony_ci } 10812a9d9c8Sopenharmony_ci } 10912a9d9c8Sopenharmony_ci} 11012a9d9c8Sopenharmony_ci``` 11112a9d9c8Sopenharmony_ci 11212a9d9c8Sopenharmony_ciNow let's run `cargo test` again and verify that everything is linking and binding 11312a9d9c8Sopenharmony_ciproperly! 11412a9d9c8Sopenharmony_ci 11512a9d9c8Sopenharmony_ci```bash 11612a9d9c8Sopenharmony_ci$ cargo test 11712a9d9c8Sopenharmony_ci Compiling bindgen-tutorial-bzip2-sys v0.1.0 11812a9d9c8Sopenharmony_ci Finished debug [unoptimized + debuginfo] target(s) in 0.54 secs 11912a9d9c8Sopenharmony_ci Running target/debug/deps/bindgen_tutorial_bzip2_sys-1c5626bbc4401c3a 12012a9d9c8Sopenharmony_ci 12112a9d9c8Sopenharmony_cirunning 15 tests 12212a9d9c8Sopenharmony_citest bindgen_test_layout___darwin_pthread_handler_rec ... ok 12312a9d9c8Sopenharmony_citest bindgen_test_layout___sFILE ... ok 12412a9d9c8Sopenharmony_citest bindgen_test_layout___sbuf ... ok 12512a9d9c8Sopenharmony_citest bindgen_test_layout__bindgen_ty_1 ... ok 12612a9d9c8Sopenharmony_citest bindgen_test_layout__bindgen_ty_2 ... ok 12712a9d9c8Sopenharmony_citest bindgen_test_layout__opaque_pthread_attr_t ... ok 12812a9d9c8Sopenharmony_citest bindgen_test_layout__opaque_pthread_cond_t ... ok 12912a9d9c8Sopenharmony_citest bindgen_test_layout__opaque_pthread_condattr_t ... ok 13012a9d9c8Sopenharmony_citest bindgen_test_layout__opaque_pthread_mutex_t ... ok 13112a9d9c8Sopenharmony_citest bindgen_test_layout__opaque_pthread_mutexattr_t ... ok 13212a9d9c8Sopenharmony_citest bindgen_test_layout__opaque_pthread_once_t ... ok 13312a9d9c8Sopenharmony_citest bindgen_test_layout__opaque_pthread_rwlock_t ... ok 13412a9d9c8Sopenharmony_citest bindgen_test_layout__opaque_pthread_rwlockattr_t ... ok 13512a9d9c8Sopenharmony_citest bindgen_test_layout__opaque_pthread_t ... ok 13612a9d9c8Sopenharmony_ci block 1: crc = 0x47bfca17, combined CRC = 0x47bfca17, size = 2857 13712a9d9c8Sopenharmony_ci bucket sorting ... 13812a9d9c8Sopenharmony_ci depth 1 has 2849 unresolved strings 13912a9d9c8Sopenharmony_ci depth 2 has 2702 unresolved strings 14012a9d9c8Sopenharmony_ci depth 4 has 1508 unresolved strings 14112a9d9c8Sopenharmony_ci depth 8 has 538 unresolved strings 14212a9d9c8Sopenharmony_ci depth 16 has 148 unresolved strings 14312a9d9c8Sopenharmony_ci depth 32 has 0 unresolved strings 14412a9d9c8Sopenharmony_ci reconstructing block ... 14512a9d9c8Sopenharmony_ci 2857 in block, 2221 after MTF & 1-2 coding, 61+2 syms in use 14612a9d9c8Sopenharmony_ci initial group 5, [0 .. 1], has 570 syms (25.7%) 14712a9d9c8Sopenharmony_ci initial group 4, [2 .. 2], has 256 syms (11.5%) 14812a9d9c8Sopenharmony_ci initial group 3, [3 .. 6], has 554 syms (24.9%) 14912a9d9c8Sopenharmony_ci initial group 2, [7 .. 12], has 372 syms (16.7%) 15012a9d9c8Sopenharmony_ci initial group 1, [13 .. 62], has 469 syms (21.1%) 15112a9d9c8Sopenharmony_ci pass 1: size is 2743, grp uses are 13 6 15 0 11 15212a9d9c8Sopenharmony_ci pass 2: size is 1216, grp uses are 13 7 15 0 10 15312a9d9c8Sopenharmony_ci pass 3: size is 1214, grp uses are 13 8 14 0 10 15412a9d9c8Sopenharmony_ci pass 4: size is 1213, grp uses are 13 9 13 0 10 15512a9d9c8Sopenharmony_ci bytes: mapping 19, selectors 17, code lengths 79, codes 1213 15612a9d9c8Sopenharmony_ci final combined CRC = 0x47bfca17 15712a9d9c8Sopenharmony_ci 15812a9d9c8Sopenharmony_ci [1: huff+mtf rt+rld {0x47bfca17, 0x47bfca17}] 15912a9d9c8Sopenharmony_ci combined CRCs: stored = 0x47bfca17, computed = 0x47bfca17 16012a9d9c8Sopenharmony_citest tests::round_trip_compression_decompression ... ok 16112a9d9c8Sopenharmony_ci 16212a9d9c8Sopenharmony_citest result: ok. 15 passed; 0 failed; 0 ignored; 0 measured 16312a9d9c8Sopenharmony_ci 16412a9d9c8Sopenharmony_ci Doc-tests bindgen-tutorial-bzip2-sys 16512a9d9c8Sopenharmony_ci 16612a9d9c8Sopenharmony_cirunning 0 tests 16712a9d9c8Sopenharmony_ci 16812a9d9c8Sopenharmony_citest result: ok. 0 passed; 0 failed; 0 ignored; 0 measured 16912a9d9c8Sopenharmony_ci``` 170