Add std/bzip2 mimic tests and benches
diff --git a/test/c/mimiclib/bzip2.c b/test/c/mimiclib/bzip2.c
new file mode 100644
index 0000000..211fb0b
--- /dev/null
+++ b/test/c/mimiclib/bzip2.c
@@ -0,0 +1,44 @@
+// Copyright 2022 The Wuffs Authors.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+//    https://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+#include "bzlib.h"
+
+const char*  //
+mimic_bzip2_decode(wuffs_base__io_buffer* dst,
+                   wuffs_base__io_buffer* src,
+                   uint32_t wuffs_initialize_flags,
+                   uint64_t wlimit,
+                   uint64_t rlimit) {
+  if (wuffs_base__io_buffer__writer_length(dst) > 0x7FFFFFFF) {
+    return "dst length is too large";
+  } else if (wuffs_base__io_buffer__reader_length(src) > 0x7FFFFFFF) {
+    return "src length is too large";
+  } else if ((wlimit < UINT64_MAX) || (rlimit < UINT64_MAX)) {
+    // Supporting this would probably mean using BZ2_bzDecompress instead of
+    // the simpler BZ2_bzBuffToBuffDecompress function.
+    return "unsupported I/O limit";
+  }
+  unsigned int dlen = wuffs_base__io_buffer__writer_length(dst);
+  unsigned int slen = wuffs_base__io_buffer__reader_length(src);
+  int err = BZ2_bzBuffToBuffDecompress(
+      ((char*)wuffs_base__io_buffer__writer_pointer(dst)), &dlen,
+      ((char*)wuffs_base__io_buffer__reader_pointer(src)), slen, 0, 0);
+  if (err != BZ_OK) {
+    return "libbz2: an error occurred";
+  } else if (dlen > wuffs_base__io_buffer__writer_length(dst)) {
+    return "libbz2: dst buffer overflow";
+  }
+  dst->meta.wi += dlen;
+  return NULL;
+}
diff --git a/test/c/std/bzip2.c b/test/c/std/bzip2.c
index 5de3bef..a772c44 100644
--- a/test/c/std/bzip2.c
+++ b/test/c/std/bzip2.c
@@ -37,7 +37,7 @@
 "wuffs mimic cflags" to run the mimic benchmarks.
 */
 
-// ¿ wuffs mimic cflags: -DWUFFS_MIMIC -ldeflate -lz
+// ¿ wuffs mimic cflags: -DWUFFS_MIMIC -lbz2
 
 // Wuffs ships as a "single file C library" or "header file library" as per
 // https://github.com/nothings/stb/blob/master/docs/stb_howto.txt
@@ -64,7 +64,7 @@
 #include "../../../release/c/wuffs-unsupported-snapshot.c"
 #include "../testlib/testlib.c"
 #ifdef WUFFS_MIMIC
-// No mimic library.
+#include "../mimiclib/bzip2.c"
 #endif
 
 // ---------------- Golden Tests
@@ -155,7 +155,26 @@
 
 #ifdef WUFFS_MIMIC
 
-// No mimic tests.
+const char*  //
+test_mimic_bzip2_decode_256_bytes() {
+  CHECK_FOCUS(__func__);
+  return do_test_io_buffers(mimic_bzip2_decode, &g_bzip2_256_bytes_gt,
+                            UINT64_MAX, UINT64_MAX);
+}
+
+const char*  //
+test_mimic_bzip2_decode_midsummer() {
+  CHECK_FOCUS(__func__);
+  return do_test_io_buffers(mimic_bzip2_decode, &g_bzip2_midsummer_gt,
+                            UINT64_MAX, UINT64_MAX);
+}
+
+const char*  //
+test_mimic_bzip2_decode_pi() {
+  CHECK_FOCUS(__func__);
+  return do_test_io_buffers(mimic_bzip2_decode, &g_bzip2_pi_gt, UINT64_MAX,
+                            UINT64_MAX);
+}
 
 #endif  // WUFFS_MIMIC
 
@@ -167,7 +186,7 @@
   return do_bench_io_buffers(
       wuffs_bzip2_decode,
       WUFFS_INITIALIZE__LEAVE_INTERNAL_BUFFERS_UNINITIALIZED, tcounter_dst,
-      &g_bzip2_midsummer_gt, UINT64_MAX, UINT64_MAX, 300);
+      &g_bzip2_midsummer_gt, UINT64_MAX, UINT64_MAX, 20);
 }
 
 const char*  //
@@ -176,14 +195,30 @@
   return do_bench_io_buffers(
       wuffs_bzip2_decode,
       WUFFS_INITIALIZE__LEAVE_INTERNAL_BUFFERS_UNINITIALIZED, tcounter_dst,
-      &g_bzip2_pi_gt, UINT64_MAX, UINT64_MAX, 30);
+      &g_bzip2_pi_gt, UINT64_MAX, UINT64_MAX, 2);
 }
 
 // ---------------- Mimic Benches
 
 #ifdef WUFFS_MIMIC
 
-// No mimic benches.
+const char*  //
+bench_mimic_bzip2_decode_10k() {
+  CHECK_FOCUS(__func__);
+  return do_bench_io_buffers(
+      mimic_bzip2_decode,
+      WUFFS_INITIALIZE__LEAVE_INTERNAL_BUFFERS_UNINITIALIZED, tcounter_dst,
+      &g_bzip2_midsummer_gt, UINT64_MAX, UINT64_MAX, 20);
+}
+
+const char*  //
+bench_mimic_bzip2_decode_100k() {
+  CHECK_FOCUS(__func__);
+  return do_bench_io_buffers(
+      mimic_bzip2_decode,
+      WUFFS_INITIALIZE__LEAVE_INTERNAL_BUFFERS_UNINITIALIZED, tcounter_dst,
+      &g_bzip2_pi_gt, UINT64_MAX, UINT64_MAX, 2);
+}
 
 #endif  // WUFFS_MIMIC
 
@@ -198,7 +233,9 @@
 
 #ifdef WUFFS_MIMIC
 
-// No mimic tests.
+    test_mimic_bzip2_decode_256_bytes,
+    test_mimic_bzip2_decode_midsummer,
+    test_mimic_bzip2_decode_pi,
 
 #endif  // WUFFS_MIMIC
 
@@ -212,7 +249,8 @@
 
 #ifdef WUFFS_MIMIC
 
-// No mimic benches.
+    bench_mimic_bzip2_decode_10k,
+    bench_mimic_bzip2_decode_100k,
 
 #endif  // WUFFS_MIMIC