Clean up test infrastructure

o Update known failures for fft16 to match reality.
o Include info about tests that unexpectedly passed and tests that
  failed that weren't expected to fail.
o Add TestOneFFT to run one FFT test (forward, inverse, or both) and
  use it for all test programs instead of having one for each.

BUG=
R=andrew@webrtc.org

Review URL: https://webrtc-codereview.appspot.com/2929004

git-svn-id: http://webrtc.googlecode.com/svn/deps/third_party/openmax@5035 4adac7df-926f-26a2-2b94-8c16560cd09d
diff --git a/dl/sp/src/test/compare.c b/dl/sp/src/test/compare.c
index c2ed0c0..e369be4 100644
--- a/dl/sp/src/test/compare.c
+++ b/dl/sp/src/test/compare.c
@@ -25,8 +25,13 @@
 }
 
 /*
- * Compute the SNR of the actual signal, returning the SNR of the real
- * and imaginary parts separately, and also the overall (complex SNR)
+ * Each of the following functions computes the SNR of the actual
+ * signal, returning the SNR of the real and imaginary parts
+ * separately, and also the overall (complex SNR).
+ *
+ * For tests that compare real signals (CompareReal32, CompareReal16,
+ * CompareFloat), the real SNR is also copied to the overall (complex)
+ * SNR result.
  */
 
 void CompareComplex32(struct SnrResult* snr, OMX_SC32* actual,
@@ -108,10 +113,6 @@
     snr->complex_snr_ = CalculateSNR(complexSignalPower, complexNoisePower);
 }
 
-/*
- * Compute the SNR of the actual real signal, returning the SNR.
- */
-
 void CompareReal32(struct SnrResult* snr, OMX_S32* actual,
                    OMX_S32* expected, int size) {
   double real_signal_power = 0;
@@ -132,7 +133,7 @@
 
   snr->real_snr_ = CalculateSNR(real_signal_power, real_noise_power);
   snr->imag_snr_ = -10000;
-  snr->complex_snr_ = -10000;
+  snr->complex_snr_ = snr->real_snr_;
 }
 
 void CompareReal16(struct SnrResult* snr, OMX_S16* actual,
@@ -155,7 +156,7 @@
 
   snr->real_snr_ = CalculateSNR(real_signal_power, real_noise_power);
   snr->imag_snr_ = -10000;
-  snr->complex_snr_ = -10000;
+  snr->complex_snr_ = snr->real_snr_;
 }
 
 void CompareComplexFloat(struct SnrResult* snr, OMX_FC32* actual,
diff --git a/dl/sp/src/test/test_fft16.c b/dl/sp/src/test/test_fft16.c
index bedf278..05fc778 100644
--- a/dl/sp/src/test/test_fft16.c
+++ b/dl/sp/src/test/test_fft16.c
@@ -34,11 +34,10 @@
     {12, 0, 1},
     {12, 0, 2},
     {12, 0, 3},
-    { 6, 1, 3},
-    { 7, 1, 3},
-    { 8, 1, 3},
-    { 9, 1, 3},
-    {10, 1, 3},
+    { 9, 1, 1},
+    { 9, 1, 2},
+    {10, 1, 1},
+    {10, 1, 2},
     {11, 1, 1},
     {11, 1, 2},
     {11, 1, 3},
@@ -49,10 +48,9 @@
     {-1, 0, 0}
 };
 
-void TestFFT(int fftLogSize, int scale_factor, int signalType);
-
 void main(int argc, char* argv[]) {
   struct Options options;
+  struct TestInfo info;
 
   SetDefaultOptions(&options, 0, MAX_FFT_ORDER);
 
@@ -69,27 +67,27 @@
   if (verbose > 255)
     DumpOptions(stderr, &options);
 
+  info.real_only_ = options.real_only_;
+  info.max_fft_order_ = options.max_fft_order_;
+  info.min_fft_order_ = options.min_fft_order_;
+  info.do_forward_tests_ = options.do_forward_tests_;
+  info.do_inverse_tests_ = options.do_inverse_tests_;
+  info.known_failures_ = known_failures;
+  /*
+   * These SNR threshold values critically depend on the
+   * signal_value that is set for the tests!
+   */
+  info.forward_threshold_ = 33.01;
+  info.inverse_threshold_ = 35.59;
+
   if (options.test_mode_) {
-    struct TestInfo info;
-
-    info.real_only_ = options.real_only_;
-    info.max_fft_order_ = options.max_fft_order_;
-    info.min_fft_order_ = options.min_fft_order_;
-    info.do_forward_tests_ = options.do_forward_tests_;
-    info.do_inverse_tests_ = options.do_inverse_tests_;
-    info.known_failures_ = known_failures;
-    /*
-     * These SNR threshold values critically depend on the
-     * signal_value that is set for the tests!
-     */
-    info.forward_threshold_ = 33.01;
-    info.inverse_threshold_ = 35.59;
-
     RunAllTests(&info);
   } else {
-    TestFFT(options.fft_log_size_,
-            options.signal_type_,
-            options.scale_factor_);
+    TestOneFFT(options.fft_log_size_,
+               options.signal_type_,
+               options.signal_value_,
+               &info,
+               "16-bit FFT");
   }
 }
 
@@ -118,23 +116,6 @@
   printf(" pBuf     = %p\n", p->pBuf);
 }
 
-void TestFFT(int fft_log_size, int signal_type, int scale_factor) {
-  struct SnrResult snr;
-
-  RunOneForwardTest(fft_log_size, signal_type, signal_value, &snr);
-  printf("Forward float FFT\n");
-  printf("SNR:  real part    %f dB\n", snr.real_snr_);
-  printf("      imag part    %f dB\n", snr.imag_snr_);
-  printf("      complex part %f dB\n", snr.complex_snr_);
-
-  RunOneInverseTest(fft_log_size, signal_type, signal_value, &snr);
-  printf("Inverse float FFT\n");
-  printf("SNR:  real part    %f dB\n", snr.real_snr_);
-  printf("      imag part    %f dB\n", snr.imag_snr_);
-  printf("      complex part %f dB\n", snr.complex_snr_);
-}
-
-
 float RunOneForwardTest(int fft_log_size, int signal_type,
                         float unused_signal_value,
                         struct SnrResult* snr) {
diff --git a/dl/sp/src/test/test_fft32.c b/dl/sp/src/test/test_fft32.c
index 72ef96c..fe3c57a 100644
--- a/dl/sp/src/test/test_fft32.c
+++ b/dl/sp/src/test/test_fft32.c
@@ -26,10 +26,9 @@
 int verbose;
 int signal_value;
 
-void TestFFT(int fft_log_size, int sigtype, int scale_factor);
-
 void main(int argc, char* argv[]) {
   struct Options options;
+  struct TestInfo info;
 
   SetDefaultOptions(&options, 0, MAX_FFT_ORDER);
 
@@ -42,30 +41,31 @@
   if (verbose > 255)
     DumpOptions(stderr, &options);
 
+  info.real_only_ = options.real_only_;
+  info.max_fft_order_ = options.max_fft_order_;
+  info.min_fft_order_ = options.min_fft_order_;
+  info.do_forward_tests_ = options.do_forward_tests_;
+  info.do_inverse_tests_ = options.do_inverse_tests_;
+  info.known_failures_ = 0;
+  /*
+   * These threshold values assume that we're using the default
+   * signal_value set below.
+   */
+  info.forward_threshold_ = 107.33;
+  info.inverse_threshold_ = 79.02;
+
+  if (!options.signal_value_given_) {
+    signal_value = 262144;         /* 18 bits */
+  }
+
   if (options.test_mode_) {
-    struct TestInfo info;
-
-    info.real_only_ = options.real_only_;
-    info.max_fft_order_ = options.max_fft_order_;
-    info.min_fft_order_ = options.min_fft_order_;
-    info.do_forward_tests_ = options.do_forward_tests_;
-    info.do_inverse_tests_ = options.do_inverse_tests_;
-    info.known_failures_ = 0;
-    /*
-     * These threshold values assume that we're using the default
-     * signal_value set below.
-     */
-    info.forward_threshold_ = 107.33;
-    info.inverse_threshold_ = 79.02;
-
-    if (!options.signal_value_given_) {
-      signal_value = 262144;         /* 18 bits */
-    }
     RunAllTests(&info);
   } else {
-    TestFFT(options.fft_log_size_,
-            options.signal_type_,
-            options.scale_factor_);
+    TestOneFFT(options.fft_log_size_,
+               options.signal_type_,
+               options.signal_value_,
+               &info,
+               "32-bit FFT");
   }
 }
 
@@ -104,26 +104,6 @@
 }
 
 /*
- * Compute forward and inverse FFT for one test case and compare the
- * result with the expected result.
- */
-void TestFFT(int fft_log_size, int signal_type, int scale_factor) {
-  struct SnrResult snr;
-
-  RunOneForwardTest(fft_log_size, signal_type, signal_value, &snr);
-  printf("Forward float FFT\n");
-  printf("SNR:  real part    %f dB\n", snr.real_snr_);
-  printf("      imag part    %f dB\n", snr.imag_snr_);
-  printf("      complex part %f dB\n", snr.complex_snr_);
-
-  RunOneInverseTest(fft_log_size, signal_type, signal_value, &snr);
-  printf("Inverse float FFT\n");
-  printf("SNR:  real part    %f dB\n", snr.real_snr_);
-  printf("      imag part    %f dB\n", snr.imag_snr_);
-  printf("      complex part %f dB\n", snr.complex_snr_);
-}
-
-/*
  * Like TestFFT, but do just the forward FFT.
  */
 float RunOneForwardTest(int fft_log_size, int signal_type, float signal_value,
diff --git a/dl/sp/src/test/test_float_fft.c b/dl/sp/src/test/test_float_fft.c
index 397315f..925aee3 100644
--- a/dl/sp/src/test/test_float_fft.c
+++ b/dl/sp/src/test/test_float_fft.c
@@ -25,10 +25,9 @@
 
 int verbose;
 
-void TestFloatFFT(int fft_log_size, int sigtype, float signal_value);
-
 void main(int argc, char* argv[]) {
   struct Options options;
+  struct TestInfo info;
 
   SetDefaultOptions(&options, 0, MAX_FFT_ORDER);
 
@@ -40,24 +39,25 @@
   if (verbose > 255)
     DumpOptions(stderr, &options);
 
+  info.real_only_ = options.real_only_;
+  info.max_fft_order_ = options.max_fft_order_;
+  info.min_fft_order_ = options.min_fft_order_;
+  info.do_forward_tests_ = options.do_forward_tests_;
+  info.do_inverse_tests_ = options.do_inverse_tests_;
+  /* No known failures */
+  info.known_failures_ = 0;
+
+  info.forward_threshold_ = 138.81;
+  info.inverse_threshold_ = 138.81;
+
   if (options.test_mode_) {
-    struct TestInfo info;
-
-    info.real_only_ = options.real_only_;
-    info.max_fft_order_ = options.max_fft_order_;
-    info.min_fft_order_ = options.min_fft_order_;
-    info.do_forward_tests_ = options.do_forward_tests_;
-    info.do_inverse_tests_ = options.do_inverse_tests_;
-    /* No known failures */
-    info.known_failures_ = 0;
-
-    info.forward_threshold_ = 138.81;
-    info.inverse_threshold_ = 138.81;
     RunAllTests(&info);
   } else {
-    TestFloatFFT(options.fft_log_size_,
-                 options.signal_type_,
-                 options.signal_value_);
+    TestOneFFT(options.fft_log_size_,
+               options.signal_type_,
+               options.signal_value_,
+               &info,
+               "Float FFT");
   }
 }
 
@@ -79,22 +79,6 @@
                            0);
 }
 
-void TestFloatFFT(int fft_log_size, int signal_type, float signal_value) {
-  struct SnrResult snr;
-
-  RunOneForwardTest(fft_log_size, signal_type, signal_value, &snr);
-  printf("Forward float FFT\n");
-  printf("SNR:  real part    %f dB\n", snr.real_snr_);
-  printf("      imag part    %f dB\n", snr.imag_snr_);
-  printf("      complex part %f dB\n", snr.complex_snr_);
-
-  RunOneInverseTest(fft_log_size, signal_type, signal_value, &snr);
-  printf("Inverse float FFT\n");
-  printf("SNR:  real part    %f dB\n", snr.real_snr_);
-  printf("      imag part    %f dB\n", snr.imag_snr_);
-  printf("      complex part %f dB\n", snr.complex_snr_);
-}
-
 float RunOneForwardTest(int fft_log_size, int signal_type, float signal_value,
                         struct SnrResult* snr) {
   OMX_FC32* x;
diff --git a/dl/sp/src/test/test_float_rfft.c b/dl/sp/src/test/test_float_rfft.c
index 20b5e33..6414d21 100644
--- a/dl/sp/src/test/test_float_rfft.c
+++ b/dl/sp/src/test/test_float_rfft.c
@@ -29,10 +29,9 @@
  */
 int verbose;
 
-void TestFloatFFT(int fft_log_size, int sigtype, float signal_value);
-
 void main(int argc, char* argv[]) {
   struct Options options;
+  struct TestInfo info;
 
   SetDefaultOptions(&options, 1, MAX_FFT_ORDER);
 
@@ -44,28 +43,29 @@
   if (verbose > 255)
     DumpOptions(stderr, &options);
 
-  if (options.test_mode_) {
-    struct TestInfo info;
-
-    info.real_only_ = options.real_only_;
-    info.min_fft_order_ = options.min_fft_order_;
-    info.max_fft_order_ = options.max_fft_order_;
-    info.do_forward_tests_ = options.do_forward_tests_;
-    info.do_inverse_tests_ = options.do_inverse_tests_;
-    /* No known failures */
-    info.known_failures_ = 0;
+  info.real_only_ = options.real_only_;
+  info.min_fft_order_ = options.min_fft_order_;
+  info.max_fft_order_ = options.max_fft_order_;
+  info.do_forward_tests_ = options.do_forward_tests_;
+  info.do_inverse_tests_ = options.do_inverse_tests_;
+  /* No known failures */
+  info.known_failures_ = 0;
 #ifdef BIG_FFT_TABLE
-    info.forward_threshold_ = 136.07;
-    info.inverse_threshold_ = 140.76;
+  info.forward_threshold_ = 136.07;
+  info.inverse_threshold_ = 140.76;
 #else
-    info.forward_threshold_ = 136.07;
-    info.inverse_threshold_ = 142.41;
+  info.forward_threshold_ = 136.07;
+  info.inverse_threshold_ = 142.41;
 #endif
+
+  if (options.test_mode_) {
     RunAllTests(&info);
   } else {
-    TestFloatFFT(options.fft_log_size_,
-                 options.signal_type_,
-                 options.signal_value_);
+    TestOneFFT(options.fft_log_size_,
+               options.signal_type_,
+               options.signal_value_,
+               &info,
+               "Float Real FFT");
   }
 }
 
@@ -109,24 +109,6 @@
   free(true_fft);
 }
 
-/*
- * Run one test of the forward and inverse FFT for the specified FFT
- * size, signal type and amplitude
- */
-void TestFloatFFT(int fft_log_size, int signal_type, float signal_value) {
-  struct SnrResult snr;
-
-  RunOneForwardTest(fft_log_size, signal_type, signal_value, &snr);
-  printf("Forward float FFT\n");
-  printf("SNR:  real part    %f dB\n", snr.real_snr_);
-  printf("      imag part    %f dB\n", snr.imag_snr_);
-  printf("      complex part %f dB\n", snr.complex_snr_);
-
-  RunOneInverseTest(fft_log_size, signal_type, signal_value, &snr);
-  printf("Inverse float FFT\n");
-  printf("SNR:  %f dB\n", snr.real_snr_);
-}
-
 /* Run one forward FFT test in test mode */
 float RunOneForwardTest(int fft_log_size, int signal_type, float signal_value,
                         struct SnrResult* snr) {
diff --git a/dl/sp/src/test/test_rfft16_s16.c b/dl/sp/src/test/test_rfft16_s16.c
index c5520f8..33ca5b3 100644
--- a/dl/sp/src/test/test_rfft16_s16.c
+++ b/dl/sp/src/test/test_rfft16_s16.c
@@ -27,10 +27,9 @@
 int signal_value = 32767;
 int scale_factor = 0;
 
-void TestFFT(int fftLogSize, int scale_factor, int signalType);
-
 void main(int argc, char* argv[]) {
   struct Options options;
+  struct TestInfo info;
 
   SetDefaultOptions(&options, 1, MAX_FFT_ORDER);
 
@@ -47,24 +46,24 @@
   if (verbose > 255)
     DumpOptions(stderr, &options);
 
+  info.real_only_ = options.real_only_;
+  info.max_fft_order_ = options.max_fft_order_;
+  info.min_fft_order_ = options.min_fft_order_;
+  info.do_forward_tests_ = options.do_forward_tests_;
+  info.do_inverse_tests_ = options.do_inverse_tests_;
+  /* No known failures */
+  info.known_failures_ = 0;
+  info.forward_threshold_ = 45;
+  info.inverse_threshold_ = 14;
+
   if (options.test_mode_) {
-    struct TestInfo info;
-
-    info.real_only_ = options.real_only_;
-    info.max_fft_order_ = options.max_fft_order_;
-    info.min_fft_order_ = options.min_fft_order_;
-    info.do_forward_tests_ = options.do_forward_tests_;
-    info.do_inverse_tests_ = options.do_inverse_tests_;
-    /* No known failures */
-    info.known_failures_ = 0;
-    info.forward_threshold_ = 45;
-    info.inverse_threshold_ = 14;
-
     RunAllTests(&info);
   } else {
-    TestFFT(options.fft_log_size_,
-            options.signal_type_,
-            options.scale_factor_);
+    TestOneFFT(options.fft_log_size_,
+               options.signal_type_,
+               options.signal_value_,
+               &info,
+               "16-bit Real FFT using 16-bit complex FFT");
   }
 }
 
@@ -87,20 +86,6 @@
   free(test_signal);
 }
 
-void TestFFT(int fft_log_size, int signal_type, int scale_factor) {
-  struct SnrResult snr;
-
-  RunOneForwardTest(fft_log_size, signal_type, signal_value, &snr);
-  printf("Forward float FFT\n");
-  printf("SNR:  real part    %f dB\n", snr.real_snr_);
-  printf("      imag part    %f dB\n", snr.imag_snr_);
-  printf("      complex part %f dB\n", snr.complex_snr_);
-
-  RunOneInverseTest(fft_log_size, signal_type, signal_value, &snr);
-  printf("Inverse float FFT\n");
-  printf("SNR:  %f dB\n", snr.real_snr_);
-}
-
 float RunOneForwardTest(int fft_log_size, int signal_type,
                         float unused_signal_value,
                         struct SnrResult* snr) {
diff --git a/dl/sp/src/test/test_rfft16_s32.c b/dl/sp/src/test/test_rfft16_s32.c
index 2d825c6..a319984 100644
--- a/dl/sp/src/test/test_rfft16_s32.c
+++ b/dl/sp/src/test/test_rfft16_s32.c
@@ -26,10 +26,9 @@
 
 #define MAX_FFT_ORDER   12
 
-void TestFFT(int fft_log_size, int signal_type, int scale_factor);
-
 void main(int argc, char* argv[]) {
   struct Options options;
+  struct TestInfo info;
 
   SetDefaultOptions(&options, 1, MAX_FFT_ORDER);
 
@@ -42,23 +41,25 @@
   if (verbose > 255)
     DumpOptions(stderr, &options);
 
-  if (options.test_mode_) {
-    struct TestInfo info;
 
-    info.real_only_ = options.real_only_;
-    info.max_fft_order_ = options.max_fft_order_;
-    info.min_fft_order_ = options.min_fft_order_;
-    info.do_forward_tests_ = options.do_forward_tests_;
-    info.do_inverse_tests_ = options.do_inverse_tests_;
-    /* No known failures */
-    info.known_failures_ = 0;
-    info.forward_threshold_ = 90.12;
-    info.inverse_threshold_ = 89.28;
+  info.real_only_ = options.real_only_;
+  info.max_fft_order_ = options.max_fft_order_;
+  info.min_fft_order_ = options.min_fft_order_;
+  info.do_forward_tests_ = options.do_forward_tests_;
+  info.do_inverse_tests_ = options.do_inverse_tests_;
+  /* No known failures */
+  info.known_failures_ = 0;
+  info.forward_threshold_ = 90.12;
+  info.inverse_threshold_ = 89.28;
+
+  if (options.test_mode_) {
     RunAllTests(&info);
   } else {
-    TestFFT(options.fft_log_size_,
-            options.signal_type_,
-            options.scale_factor_);
+    TestOneFFT(options.fft_log_size_,
+               options.signal_type_,
+               options.signal_value_,
+               &info,
+               "16-bit Real FFT using 32-bit complex FFT");
   }
 }
 
@@ -89,20 +90,6 @@
   free(true_fft);
 }
 
-void TestFFT(int fft_log_size, int signal_type, int scale_factor) {
-  struct SnrResult snr;
-
-  RunOneForwardTest(fft_log_size, signal_type, signal_value, &snr);
-  printf("Forward float FFT\n");
-  printf("SNR:  real part    %f dB\n", snr.real_snr_);
-  printf("      imag part    %f dB\n", snr.imag_snr_);
-  printf("      complex part %f dB\n", snr.complex_snr_);
-
-  RunOneInverseTest(fft_log_size, signal_type, signal_value, &snr);
-  printf("Inverse float FFT\n");
-  printf("SNR:  %f dB\n", snr.real_snr_);
-}
-
 float RunOneForwardTest(int fft_log_size, int signal_type, float signal_value,
                         struct SnrResult* snr) {
   OMX_S16* x;
diff --git a/dl/sp/src/test/test_rfft32.c b/dl/sp/src/test/test_rfft32.c
index 544b29d..1b81d44 100644
--- a/dl/sp/src/test/test_rfft32.c
+++ b/dl/sp/src/test/test_rfft32.c
@@ -26,10 +26,9 @@
 
 #define MAX_FFT_ORDER   12
 
-void TestFFT(int fft_log_size, int signal_type, int scale_factor);
-
 void main(int argc, char* argv[]) {
   struct Options options;
+  struct TestInfo info;
 
   SetDefaultOptions(&options, 1, MAX_FFT_ORDER);
 
@@ -42,27 +41,29 @@
   if (verbose > 255)
     DumpOptions(stderr, &options);
 
-  if (options.test_mode_) {
-    struct TestInfo info;
+  info.real_only_ = options.real_only_;
+  info.min_fft_order_ = options.min_fft_order_;
+  info.max_fft_order_ = options.max_fft_order_;
+  info.do_forward_tests_ = options.do_forward_tests_;
+  info.do_inverse_tests_ = options.do_inverse_tests_;
+  /* No known failures */
+  info.known_failures_ = 0;
+  /* These thresholds are set for the default signal_value below */
+  info.forward_threshold_ = 105.94;
+  info.inverse_threshold_ = 104.62;
 
-    info.real_only_ = options.real_only_;
-    info.min_fft_order_ = options.min_fft_order_;
-    info.max_fft_order_ = options.max_fft_order_;
-    info.do_forward_tests_ = options.do_forward_tests_;
-    info.do_inverse_tests_ = options.do_inverse_tests_;
-    /* No known failures */
-    info.known_failures_ = 0;
-    /* These thresholds are set for the default signal_value below */
-    info.forward_threshold_ = 105.94;
-    info.inverse_threshold_ = 104.62;
-    if (!options.signal_value_given_) {
-      signal_value = 262144;
-    }
+  if (!options.signal_value_given_) {
+    signal_value = 262144;
+  }
+
+  if (options.test_mode_) {
     RunAllTests(&info);
   } else {
-    TestFFT(options.fft_log_size_,
-            options.signal_type_,
-            options.scale_factor_);
+    TestOneFFT(options.fft_log_size_,
+               options.signal_type_,
+               options.signal_value_,
+               &info,
+               "32-bit Real FFT");
   }
 }
 
@@ -93,20 +94,6 @@
   free(true_fft);
 }
 
-void TestFFT(int fft_log_size, int signal_type, int scale_factor) {
-  struct SnrResult snr;
-
-  RunOneForwardTest(fft_log_size, signal_type, signal_value, &snr);
-  printf("Forward float FFT\n");
-  printf("SNR:  real part    %f dB\n", snr.real_snr_);
-  printf("      imag part    %f dB\n", snr.imag_snr_);
-  printf("      complex part %f dB\n", snr.complex_snr_);
-
-  RunOneInverseTest(fft_log_size, signal_type, signal_value, &snr);
-  printf("Inverse float FFT\n");
-  printf("SNR:  %f dB\n", snr.real_snr_);
-}
-
 float RunOneForwardTest(int fft_log_size, int signal_type, float signal_value,
                         struct SnrResult* snr) {
   OMX_S32* x;
diff --git a/dl/sp/src/test/test_util.c b/dl/sp/src/test/test_util.c
index 8f0e3b7..63e2a6b 100644
--- a/dl/sp/src/test/test_util.c
+++ b/dl/sp/src/test/test_util.c
@@ -18,7 +18,7 @@
 #include "dl/sp/src/test/compare.h"
 
 /*
- * Test resuls from running either forward or inverse FFT tests
+ * Test results from running either forward or inverse FFT tests
  */
 struct TestResult {
   /* Number of tests that failed */
@@ -30,6 +30,12 @@
   /* Number of tests that were expected to fail */
   int expected_failure_count_;
 
+  /* Number of tests that were expected to fail but didn't */
+  int unexpected_pass_count_;
+
+  /* Number of tests that unexpectedly failed */
+  int unexpected_failure_count_;
+
   /* The minimum SNR found for all of the tests */
   float min_snr_;
 };
@@ -200,6 +206,37 @@
 }
 
 /*
+ * Run one FFT test
+ */
+void TestOneFFT(int fft_log_size,
+                int signal_type,
+                float signal_value,
+                const struct TestInfo* info,
+                const char* message) {
+  struct SnrResult snr;
+
+  if (info->do_forward_tests_) {
+    RunOneForwardTest(fft_log_size, signal_type, signal_value, &snr);
+    printf("Forward %s\n", message);
+    printf("SNR:  real part    %10.3f dB\n", snr.real_snr_);
+    printf("      imag part    %10.3f dB\n", snr.imag_snr_);
+    printf("      complex part %10.3f dB\n", snr.complex_snr_);
+  }
+
+  if (info->do_inverse_tests_) {
+    RunOneInverseTest(fft_log_size, signal_type, signal_value, &snr);
+    printf("Inverse %s\n", message);
+    if (info->real_only_) {
+      printf("SNR:  real         %10.3f dB\n", snr.real_snr_);
+    } else {
+      printf("SNR:  real part    %10.3f dB\n", snr.real_snr_);
+      printf("      imag part    %10.3f dB\n", snr.imag_snr_);
+      printf("      complex part %10.3f dB\n", snr.complex_snr_);
+    }
+  }
+}
+
+/*
  * Run a set of tests, printing out the result of each test.
  */
 void RunTests(struct TestResult* result,
@@ -214,6 +251,8 @@
   int tests = 0;
   int failures = 0;
   int expected_failures = 0;
+  int unexpected_failures = 0;
+  int unexpected_passes = 0;
   float min_snr = 1e10;
   struct SnrResult snrResults;
 
@@ -236,6 +275,7 @@
           ++expected_failures;
           printf(" *FAILED: %s ", id);
         } else {
+          ++unexpected_failures;
           printf("**FAILED: %s ", id);
         }
       } else {
@@ -248,6 +288,7 @@
         if (test_failed) {
           printf(" (expected failure)");
         } else {
+          ++unexpected_passes;
           printf(" (**Expected to fail, but passed)");
         }
       }
@@ -262,13 +303,19 @@
          id,
          tests,
          (100.0 * (tests - failures)) / tests);
-  if (expected_failures)
+  if (expected_failures || unexpected_passes || unexpected_failures) {
     printf("    (%d expected failures)\n", expected_failures);
+    printf("    (%d unexpected failures)\n", unexpected_failures);
+    printf("    (%d unexpected passes)\n", unexpected_passes);
+  }
+  
   printf("    (Minimum SNR = %.3f dB)\n", min_snr);
 
   result->failed_count_ = failures;
   result->test_count_ = tests;
   result->expected_failure_count_ = expected_failures;
+  result->unexpected_pass_count_ = unexpected_passes;
+  result->unexpected_failure_count_ = unexpected_failures;
   result->min_snr_ = min_snr;
 }
 
@@ -332,6 +379,12 @@
       printf("  (%d expected failures)\n",
              forward_results.expected_failure_count_
              + inverse_results.expected_failure_count_);
+      printf("  (%d unexpected failures)\n",
+             forward_results.unexpected_failure_count_
+             + inverse_results.unexpected_failure_count_);
+      printf("  (%d unexpected passes)\n",
+             forward_results.unexpected_pass_count_
+             + inverse_results.unexpected_pass_count_);
     }
     printf("  Min forward SNR = %.3f dB, min inverse SNR = %.3f dB\n",
            min_forward_snr,
diff --git a/dl/sp/src/test/test_util.h b/dl/sp/src/test/test_util.h
index 5851e12..482f742 100644
--- a/dl/sp/src/test/test_util.h
+++ b/dl/sp/src/test/test_util.h
@@ -120,6 +120,13 @@
 void DumpOptions(FILE*, const struct Options* options);
 
 /*
+ * Run FFT test for one case. May or may not include both forward and
+ * inverse tests.
+ */
+void TestOneFFT(int fft_log_size, int signal_type, float signal_value,
+                const struct TestInfo* info, const char* message);
+
+/*
  * Run one forward FFT test of the given size, signal type, and amplitude
  */
 float RunOneForwardTest(int fft_log_size, int signal_type,