annotate base/test/TestMovingMedian.h @ 1671:82d03c9661f9 single-point

Rework isReady()/getCompletion() on models. Previously the new overhauled models were implementing getCompletion() but inheriting a version of isReady() (from the Model base) that didn't call it, referring only to isOK(). So they were reporting completion as soon as they had begun. Instead hoist getCompletion() to abstract base and call it from Model::isReady().
author Chris Cannam
date Wed, 27 Mar 2019 13:15:16 +0000
parents cfcfec216c21
children
rev   line source
Chris@1573 1 /* -*- c-basic-offset: 4 indent-tabs-mode: nil -*- vi:set ts=8 sts=4 sw=4: */
Chris@1573 2
Chris@1573 3 /*
Chris@1573 4 Sonic Visualiser
Chris@1573 5 An audio file viewer and annotation editor.
Chris@1573 6 Centre for Digital Music, Queen Mary, University of London.
Chris@1573 7
Chris@1573 8 This program is free software; you can redistribute it and/or
Chris@1573 9 modify it under the terms of the GNU General Public License as
Chris@1573 10 published by the Free Software Foundation; either version 2 of the
Chris@1573 11 License, or (at your option) any later version. See the file
Chris@1573 12 COPYING included with this distribution for more information.
Chris@1573 13 */
Chris@1573 14
Chris@1573 15 #ifndef TEST_MOVING_MEDIAN_H
Chris@1573 16 #define TEST_MOVING_MEDIAN_H
Chris@1573 17
Chris@1573 18 #include "../MovingMedian.h"
Chris@1573 19
Chris@1573 20 #include <QObject>
Chris@1573 21 #include <QtTest>
Chris@1573 22 #include <QDir>
Chris@1573 23
Chris@1573 24 #include <iostream>
Chris@1573 25
Chris@1573 26 using namespace std;
Chris@1573 27
Chris@1573 28 class TestMovingMedian : public QObject
Chris@1573 29 {
Chris@1573 30 Q_OBJECT
Chris@1573 31
Chris@1573 32 template <typename T>
Chris@1573 33 void checkExpected(const vector<T> &output,
Chris@1573 34 const vector<T> &expected) {
Chris@1573 35 if (output.size() != expected.size()) {
Chris@1574 36 std::cerr << "ERROR: output array size " << output.size()
Chris@1574 37 << " differs from expected size " << expected.size()
Chris@1574 38 << std::endl;
Chris@1573 39 }
Chris@1573 40 for (int i = 0; i < int(output.size()); ++i) {
Chris@1573 41 if (output[i] != expected[i]) {
Chris@1574 42 std::cerr << "ERROR: Value at index " << i
Chris@1574 43 << " in output array differs from expected"
Chris@1574 44 << std::endl;
Chris@1574 45 std::cerr << "Output: ";
Chris@1574 46 for (auto v: output) std::cerr << v << " ";
Chris@1574 47 std::cerr << "\nExpected: ";
Chris@1574 48 for (auto v: expected) std::cerr << v << " ";
Chris@1574 49 std::cerr << std::endl;
Chris@1573 50 break;
Chris@1573 51 }
Chris@1573 52 }
Chris@1573 53 QCOMPARE(output, expected);
Chris@1573 54 }
Chris@1573 55
Chris@1573 56 template <typename T>
Chris@1573 57 void testFixed(int n,
Chris@1573 58 const vector<T> &input,
Chris@1573 59 const vector<T> &expected,
Chris@1573 60 double percentile = 50.0) {
Chris@1573 61 vector<T> output;
Chris@1573 62 MovingMedian<T> mm(n, percentile);
Chris@1573 63 for (auto v: input) {
Chris@1573 64 mm.push(v);
Chris@1573 65 mm.checkIntegrity();
Chris@1573 66 output.push_back(mm.get());
Chris@1573 67 }
Chris@1573 68 mm.checkIntegrity();
Chris@1573 69 checkExpected<T>(output, expected);
Chris@1573 70 }
Chris@1573 71
Chris@1573 72 private slots:
Chris@1573 73
Chris@1573 74 void empty() {
Chris@1573 75 MovingMedian<double> mm(3);
Chris@1573 76 QCOMPARE(mm.get(), 0.0);
Chris@1573 77 }
Chris@1573 78
Chris@1573 79 void zeros() {
Chris@1573 80 vector<double> input { 0.0, 0.0, 0.0, 0.0, 0.0 };
Chris@1573 81 vector<double> expected { 0.0, 0.0, 0.0, 0.0, 0.0 };
Chris@1573 82 testFixed<double>(3, input, expected);
Chris@1573 83 }
Chris@1573 84
Chris@1573 85 void ascending() {
Chris@1573 86 vector<double> input { 1.0, 2.0, 3.0, 4.0, 5.0 };
Chris@1573 87 vector<double> expected { 0.0, 1.0, 2.0, 3.0, 4.0 };
Chris@1573 88 testFixed<double>(3, input, expected);
Chris@1573 89 }
Chris@1573 90
Chris@1573 91 void ascendingInt() {
Chris@1573 92 vector<int> input { 1, 2, 3, 4, 5 };
Chris@1573 93 vector<int> expected { 0, 1, 2, 3, 4 };
Chris@1573 94 testFixed<int>(3, input, expected);
Chris@1573 95 }
Chris@1573 96
Chris@1573 97 void descending() {
Chris@1573 98 vector<double> input { 5.0, 4.0, 3.0, 2.0, 1.0 };
Chris@1573 99 vector<double> expected { 0.0, 4.0, 4.0, 3.0, 2.0 };
Chris@1573 100 testFixed<double>(3, input, expected);
Chris@1573 101 }
Chris@1573 102
Chris@1573 103 void descendingInt() {
Chris@1573 104 vector<int> input { 5, 4, 3, 2, 1 };
Chris@1573 105 vector<int> expected { 0, 4, 4, 3, 2 };
Chris@1573 106 testFixed<int>(3, input, expected);
Chris@1573 107 }
Chris@1573 108
Chris@1573 109 void duplicates() {
Chris@1573 110 vector<double> input { 2.0, 2.0, 3.0, 4.0, 3.0 };
Chris@1573 111 vector<double> expected { 0.0, 2.0, 2.0, 3.0, 3.0 };
Chris@1573 112 testFixed<double>(3, input, expected);
Chris@1573 113 }
Chris@1573 114
Chris@1573 115 void percentile10() {
Chris@1573 116 vector<double> input { 1.0, 2.0, 3.0, 4.0, 5.0 };
Chris@1573 117 vector<double> expected { 0.0, 0.0, 1.0, 2.0, 3.0 };
Chris@1573 118 testFixed<double>(3, input, expected, 10);
Chris@1573 119 }
Chris@1573 120
Chris@1573 121 void percentile90() {
Chris@1573 122 vector<double> input { 1.0, 2.0, 3.0, 4.0, 5.0 };
Chris@1573 123 vector<double> expected { 1.0, 2.0, 3.0, 4.0, 5.0 };
Chris@1573 124 testFixed<double>(3, input, expected, 90);
Chris@1573 125 }
Chris@1573 126
Chris@1573 127 void even() {
Chris@1573 128 vector<double> input { 5.0, 4.0, 3.0, 2.0, 1.0 };
Chris@1573 129 vector<double> expected { 0.0, 4.0, 4.0, 4.0, 3.0 };
Chris@1573 130 testFixed<double>(4, input, expected);
Chris@1573 131 }
Chris@1573 132
Chris@1573 133 void growing() {
Chris@1573 134 vector<double> input { 2.0, 4.0, 3.0, 2.5, 2.5, 3.0, 1.0, 2.0, 1.0, 0.0 };
Chris@1573 135 vector<double> expected { 2.0, 4.0, 4.0, 3.0, 2.5, 2.5, 2.5, 2.5, 2.0, 1.0 };
Chris@1573 136 vector<double> output;
Chris@1573 137 MovingMedian<double> mm(1);
Chris@1573 138 for (int i = 0; i < int(input.size()); ++i) {
Chris@1573 139 // sizes 1, 1, 2, 2, 3, 3, 4, 4, 5, 5
Chris@1573 140 int sz = i/2 + 1;
Chris@1573 141 mm.resize(sz);
Chris@1573 142 QCOMPARE(mm.size(), sz);
Chris@1573 143 mm.push(input[i]);
Chris@1573 144 mm.checkIntegrity();
Chris@1573 145 output.push_back(mm.get());
Chris@1573 146 }
Chris@1573 147 mm.checkIntegrity();
Chris@1573 148 checkExpected<double>(output, expected);
Chris@1573 149 }
Chris@1573 150
Chris@1573 151 void shrinking() {
Chris@1573 152 vector<double> input { 2.0, 4.0, 3.0, 2.5, 2.5, 3.0, 1.0, 2.0, 1.0, 0.0 };
Chris@1573 153 vector<double> expected { 0.0, 0.0, 3.0, 3.0, 2.5, 2.5, 3.0, 2.0, 1.0, 0.0 };
Chris@1573 154 vector<double> output;
Chris@1573 155 MovingMedian<double> mm(99);
Chris@1573 156 for (int i = 0; i < int(input.size()); ++i) {
Chris@1573 157 // sizes 5, 5, 4, 4, 3, 3, 2, 2, 1, 1
Chris@1573 158 int sz = 5 - i/2;
Chris@1573 159 mm.resize(sz);
Chris@1573 160 QCOMPARE(mm.size(), sz);
Chris@1573 161 mm.push(input[i]);
Chris@1573 162 mm.checkIntegrity();
Chris@1573 163 output.push_back(mm.get());
Chris@1573 164 }
Chris@1573 165 mm.checkIntegrity();
Chris@1573 166 checkExpected<double>(output, expected);
Chris@1573 167 }
Chris@1573 168 };
Chris@1573 169
Chris@1573 170 #endif