1# Write a Sanity Test 2 3Finally, to tie everything together, let's write a sanity test that round trips 4some text through compression and decompression, and then asserts that it came 5back out the same as it went in. This is a little wordy using the raw FFI 6bindings, but hopefully we wouldn't usually ask people to do this, we'd provide 7a nice Rust-y API on top of the raw FFI bindings for them. However, since this 8is for testing the bindings directly, our sanity test will use the bindings 9directly. 10 11The test data I'm round tripping are some Futurama quotes I got off the internet 12and put in the `futurama-quotes.txt` file, which is read into a `&'static str` 13at compile time via the `include_str!("../futurama-quotes.txt")` macro 14invocation. 15 16Without further ado, here is the test, which should be appended to the bottom of 17our `src/lib.rs` file: 18 19```rust 20#[cfg(test)] 21mod tests { 22 use super::*; 23 use std::mem; 24 25 #[test] 26 fn round_trip_compression_decompression() { 27 unsafe { 28 let input = include_str!("../futurama-quotes.txt").as_bytes(); 29 let mut compressed_output: Vec<u8> = vec![0; input.len()]; 30 let mut decompressed_output: Vec<u8> = vec![0; input.len()]; 31 32 // Construct a compression stream. 33 let mut stream: bz_stream = mem::zeroed(); 34 let result = BZ2_bzCompressInit(&mut stream as *mut _, 35 1, // 1 x 100000 block size 36 4, // verbosity (4 = most verbose) 37 0); // default work factor 38 match result { 39 r if r == (BZ_CONFIG_ERROR as _) => panic!("BZ_CONFIG_ERROR"), 40 r if r == (BZ_PARAM_ERROR as _) => panic!("BZ_PARAM_ERROR"), 41 r if r == (BZ_MEM_ERROR as _) => panic!("BZ_MEM_ERROR"), 42 r if r == (BZ_OK as _) => {}, 43 r => panic!("Unknown return value = {}", r), 44 } 45 46 // Compress `input` into `compressed_output`. 47 stream.next_in = input.as_ptr() as *mut _; 48 stream.avail_in = input.len() as _; 49 stream.next_out = compressed_output.as_mut_ptr() as *mut _; 50 stream.avail_out = compressed_output.len() as _; 51 let result = BZ2_bzCompress(&mut stream as *mut _, BZ_FINISH as _); 52 match result { 53 r if r == (BZ_RUN_OK as _) => panic!("BZ_RUN_OK"), 54 r if r == (BZ_FLUSH_OK as _) => panic!("BZ_FLUSH_OK"), 55 r if r == (BZ_FINISH_OK as _) => panic!("BZ_FINISH_OK"), 56 r if r == (BZ_SEQUENCE_ERROR as _) => panic!("BZ_SEQUENCE_ERROR"), 57 r if r == (BZ_STREAM_END as _) => {}, 58 r => panic!("Unknown return value = {}", r), 59 } 60 61 // Finish the compression stream. 62 let result = BZ2_bzCompressEnd(&mut stream as *mut _); 63 match result { 64 r if r == (BZ_PARAM_ERROR as _) => panic!("BZ_PARAM_ERROR"), 65 r if r == (BZ_OK as _) => {}, 66 r => panic!("Unknown return value = {}", r), 67 } 68 69 // Construct a decompression stream. 70 let mut stream: bz_stream = mem::zeroed(); 71 let result = BZ2_bzDecompressInit(&mut stream as *mut _, 72 4, // verbosity (4 = most verbose) 73 0); // default small factor 74 match result { 75 r if r == (BZ_CONFIG_ERROR as _) => panic!("BZ_CONFIG_ERROR"), 76 r if r == (BZ_PARAM_ERROR as _) => panic!("BZ_PARAM_ERROR"), 77 r if r == (BZ_MEM_ERROR as _) => panic!("BZ_MEM_ERROR"), 78 r if r == (BZ_OK as _) => {}, 79 r => panic!("Unknown return value = {}", r), 80 } 81 82 // Decompress `compressed_output` into `decompressed_output`. 83 stream.next_in = compressed_output.as_ptr() as *mut _; 84 stream.avail_in = compressed_output.len() as _; 85 stream.next_out = decompressed_output.as_mut_ptr() as *mut _; 86 stream.avail_out = decompressed_output.len() as _; 87 let result = BZ2_bzDecompress(&mut stream as *mut _); 88 match result { 89 r if r == (BZ_PARAM_ERROR as _) => panic!("BZ_PARAM_ERROR"), 90 r if r == (BZ_DATA_ERROR as _) => panic!("BZ_DATA_ERROR"), 91 r if r == (BZ_DATA_ERROR_MAGIC as _) => panic!("BZ_DATA_ERROR"), 92 r if r == (BZ_MEM_ERROR as _) => panic!("BZ_MEM_ERROR"), 93 r if r == (BZ_OK as _) => panic!("BZ_OK"), 94 r if r == (BZ_STREAM_END as _) => {}, 95 r => panic!("Unknown return value = {}", r), 96 } 97 98 // Close the decompression stream. 99 let result = BZ2_bzDecompressEnd(&mut stream as *mut _); 100 match result { 101 r if r == (BZ_PARAM_ERROR as _) => panic!("BZ_PARAM_ERROR"), 102 r if r == (BZ_OK as _) => {}, 103 r => panic!("Unknown return value = {}", r), 104 } 105 106 assert_eq!(input, &decompressed_output[..]); 107 } 108 } 109} 110``` 111 112Now let's run `cargo test` again and verify that everything is linking and binding 113properly! 114 115```bash 116$ cargo test 117 Compiling bindgen-tutorial-bzip2-sys v0.1.0 118 Finished debug [unoptimized + debuginfo] target(s) in 0.54 secs 119 Running target/debug/deps/bindgen_tutorial_bzip2_sys-1c5626bbc4401c3a 120 121running 15 tests 122test bindgen_test_layout___darwin_pthread_handler_rec ... ok 123test bindgen_test_layout___sFILE ... ok 124test bindgen_test_layout___sbuf ... ok 125test bindgen_test_layout__bindgen_ty_1 ... ok 126test bindgen_test_layout__bindgen_ty_2 ... ok 127test bindgen_test_layout__opaque_pthread_attr_t ... ok 128test bindgen_test_layout__opaque_pthread_cond_t ... ok 129test bindgen_test_layout__opaque_pthread_condattr_t ... ok 130test bindgen_test_layout__opaque_pthread_mutex_t ... ok 131test bindgen_test_layout__opaque_pthread_mutexattr_t ... ok 132test bindgen_test_layout__opaque_pthread_once_t ... ok 133test bindgen_test_layout__opaque_pthread_rwlock_t ... ok 134test bindgen_test_layout__opaque_pthread_rwlockattr_t ... ok 135test bindgen_test_layout__opaque_pthread_t ... ok 136 block 1: crc = 0x47bfca17, combined CRC = 0x47bfca17, size = 2857 137 bucket sorting ... 138 depth 1 has 2849 unresolved strings 139 depth 2 has 2702 unresolved strings 140 depth 4 has 1508 unresolved strings 141 depth 8 has 538 unresolved strings 142 depth 16 has 148 unresolved strings 143 depth 32 has 0 unresolved strings 144 reconstructing block ... 145 2857 in block, 2221 after MTF & 1-2 coding, 61+2 syms in use 146 initial group 5, [0 .. 1], has 570 syms (25.7%) 147 initial group 4, [2 .. 2], has 256 syms (11.5%) 148 initial group 3, [3 .. 6], has 554 syms (24.9%) 149 initial group 2, [7 .. 12], has 372 syms (16.7%) 150 initial group 1, [13 .. 62], has 469 syms (21.1%) 151 pass 1: size is 2743, grp uses are 13 6 15 0 11 152 pass 2: size is 1216, grp uses are 13 7 15 0 10 153 pass 3: size is 1214, grp uses are 13 8 14 0 10 154 pass 4: size is 1213, grp uses are 13 9 13 0 10 155 bytes: mapping 19, selectors 17, code lengths 79, codes 1213 156 final combined CRC = 0x47bfca17 157 158 [1: huff+mtf rt+rld {0x47bfca17, 0x47bfca17}] 159 combined CRCs: stored = 0x47bfca17, computed = 0x47bfca17 160test tests::round_trip_compression_decompression ... ok 161 162test result: ok. 15 passed; 0 failed; 0 ignored; 0 measured 163 164 Doc-tests bindgen-tutorial-bzip2-sys 165 166running 0 tests 167 168test result: ok. 0 passed; 0 failed; 0 ignored; 0 measured 169``` 170