1/* 2 * Copyright (c) 2013 The WebRTC project authors. All Rights Reserved. 3 * 4 * Use of this source code is governed by a BSD-style license 5 * that can be found in the LICENSE file in the root of the source 6 * tree. An additional intellectual property rights grant can be found 7 * in the file PATENTS. All contributing project authors may 8 * be found in the AUTHORS file in the root of the source tree. 9 */ 10#include "dl/sp/src/test/test_util.h" 11 12#include "dl/sp/src/test/compare.h" 13 14/* 15 * Test results from running either forward or inverse FFT tests 16 */ 17struct TestResult { 18 /* Number of tests that failed */ 19 int failed_count_; 20 21 /* Number of tests run */ 22 int test_count_; 23 24 /* Number of tests that were expected to fail */ 25 int expected_failure_count_; 26 27 /* Number of tests that were expected to fail but didn't */ 28 int unexpected_pass_count_; 29 30 /* Number of tests that unexpectedly failed */ 31 int unexpected_failure_count_; 32 33 /* The minimum SNR found for all of the tests */ 34 float min_snr_; 35}; 36 37/* 38 * Run one FFT test 39 */ 40void TestOneFFT(int fft_log_size, 41 int signal_type, 42 float signal_value, 43 const struct TestInfo* info, 44 const char* message) { 45 struct SnrResult snr; 46 47 if (info->do_forward_tests_) { 48 RunOneForwardTest(fft_log_size, signal_type, signal_value, &snr); 49 printf("Forward %s\n", message); 50 printf("SNR: real part %10.3f dB\n", snr.real_snr_); 51 printf(" imag part %10.3f dB\n", snr.imag_snr_); 52 printf(" complex part %10.3f dB\n", snr.complex_snr_); 53 } 54 55 if (info->do_inverse_tests_) { 56 RunOneInverseTest(fft_log_size, signal_type, signal_value, &snr); 57 printf("Inverse %s\n", message); 58 if (info->real_only_) { 59 printf("SNR: real %10.3f dB\n", snr.real_snr_); 60 } else { 61 printf("SNR: real part %10.3f dB\n", snr.real_snr_); 62 printf(" imag part %10.3f dB\n", snr.imag_snr_); 63 printf(" complex part %10.3f dB\n", snr.complex_snr_); 64 } 65 } 66} 67 68/* 69 * Run a set of tests, printing out the result of each test. 70 */ 71void RunTests(struct TestResult* result, 72 float (*test_function)(int, int, float, struct SnrResult*), 73 const char* id, 74 int is_inverse_test, 75 const struct TestInfo* info, 76 float snr_threshold) { 77 int fft_order; 78 int signal_type; 79 float snr; 80 int tests = 0; 81 int failures = 0; 82 int expected_failures = 0; 83 int unexpected_failures = 0; 84 int unexpected_passes = 0; 85 float min_snr = 1e10; 86 struct SnrResult snrResults; 87 88 for (fft_order = info->min_fft_order_; fft_order <= info->max_fft_order_; 89 ++fft_order) { 90 for (signal_type = 0; signal_type < MaxSignalType(info->real_only_); 91 ++signal_type) { 92 int known_failure = 0; 93 int test_failed = 0; 94 ++tests; 95 snr = test_function(fft_order, signal_type, 1024.0, &snrResults); 96 if (snr < min_snr) 97 min_snr = snr; 98 known_failure = IsKnownFailure(fft_order, is_inverse_test, 99 signal_type, info->known_failures_); 100 if (snr < snr_threshold) { 101 ++failures; 102 test_failed = 1; 103 if (known_failure) { 104 ++expected_failures; 105 printf(" *FAILED: %s ", id); 106 } else { 107 ++unexpected_failures; 108 printf("**FAILED: %s ", id); 109 } 110 } else { 111 test_failed = 0; 112 printf(" PASSED: %s ", id); 113 } 114 printf("order %2d signal %d: SNR = %9.3f", 115 fft_order, signal_type, snr); 116 if (known_failure) { 117 if (test_failed) { 118 printf(" (expected failure)"); 119 } else { 120 ++unexpected_passes; 121 printf(" (**Expected to fail, but passed)"); 122 } 123 } 124 printf("\n"); 125 } 126 } 127 128 printf("%sSummary: %d %s tests failed out of %d tests. " 129 "(Success rate %.2f%%.)\n", 130 failures ? "**" : "", 131 failures, 132 id, 133 tests, 134 (100.0 * (tests - failures)) / tests); 135 if (expected_failures || unexpected_passes || unexpected_failures) { 136 printf(" (%d expected failures)\n", expected_failures); 137 printf(" (%d unexpected failures)\n", unexpected_failures); 138 printf(" (%d unexpected passes)\n", unexpected_passes); 139 } 140 141 printf(" (Minimum SNR = %.3f dB)\n", min_snr); 142 143 result->failed_count_ = failures; 144 result->test_count_ = tests; 145 result->expected_failure_count_ = expected_failures; 146 result->unexpected_pass_count_ = unexpected_passes; 147 result->unexpected_failure_count_ = unexpected_failures; 148 result->min_snr_ = min_snr; 149} 150 151/* 152 * For all FFT orders and signal types, run the forward FFT. 153 * runOneForwardTest must be defined to compute the forward FFT and 154 * return the SNR beween the actual and expected FFT. 155 * 156 * Also finds the minium SNR from all of the tests and returns the 157 * minimum SNR value. 158 */ 159void RunForwardTests(struct TestResult* result, const struct TestInfo* info, 160 float snr_threshold) { 161 RunTests(result, RunOneForwardTest, "FwdFFT", 0, info, snr_threshold); 162} 163 164void initializeTestResult(struct TestResult *result) { 165 result->failed_count_ = 0; 166 result->test_count_ = 0; 167 result->expected_failure_count_ = 0; 168 result->min_snr_ = 1000; 169} 170 171/* 172 * For all FFT orders and signal types, run the inverse FFT. 173 * runOneInverseTest must be defined to compute the forward FFT and 174 * return the SNR beween the actual and expected FFT. 175 * 176 * Also finds the minium SNR from all of the tests and returns the 177 * minimum SNR value. 178 */ 179void RunInverseTests(struct TestResult* result, const struct TestInfo* info, 180 float snr_threshold) { 181 RunTests(result, RunOneInverseTest, "InvFFT", 1, info, snr_threshold); 182} 183 184/* 185 * Run all forward and inverse FFT tests, printing a summary of the 186 * results. 187 */ 188int RunAllTests(const struct TestInfo* info) { 189 int failed; 190 int total; 191 float min_forward_snr; 192 float min_inverse_snr; 193 struct TestResult forward_results; 194 struct TestResult inverse_results; 195 196 initializeTestResult(&forward_results); 197 initializeTestResult(&inverse_results); 198 199 if (info->do_forward_tests_) 200 RunForwardTests(&forward_results, info, info->forward_threshold_); 201 if (info->do_inverse_tests_) 202 RunInverseTests(&inverse_results, info, info->inverse_threshold_); 203 204 failed = forward_results.failed_count_ + inverse_results.failed_count_; 205 total = forward_results.test_count_ + inverse_results.test_count_; 206 min_forward_snr = forward_results.min_snr_; 207 min_inverse_snr = inverse_results.min_snr_; 208 209 if (total) { 210 printf("%sTotal: %d tests failed out of %d tests. " 211 "(Success rate = %.2f%%.)\n", 212 failed ? "**" : "", 213 failed, 214 total, 215 (100.0 * (total - failed)) / total); 216 if (forward_results.expected_failure_count_ 217 + inverse_results.expected_failure_count_) { 218 printf(" (%d expected failures)\n", 219 forward_results.expected_failure_count_ 220 + inverse_results.expected_failure_count_); 221 printf(" (%d unexpected failures)\n", 222 forward_results.unexpected_failure_count_ 223 + inverse_results.unexpected_failure_count_); 224 printf(" (%d unexpected passes)\n", 225 forward_results.unexpected_pass_count_ 226 + inverse_results.unexpected_pass_count_); 227 } 228 printf(" Min forward SNR = %.3f dB, min inverse SNR = %.3f dB\n", 229 min_forward_snr, 230 min_inverse_snr); 231 } else { 232 printf("No tests run\n"); 233 } 234 235 return failed; 236} 237