File: testing_unit_tests_bitset.cpp

package info (click to toggle)
mrtrix3 3.0.8-1
  • links: PTS, VCS
  • area: main
  • in suites: forky, sid
  • size: 15,300 kB
  • sloc: cpp: 130,470; python: 9,603; sh: 597; makefile: 62; xml: 47
file content (127 lines) | stat: -rw-r--r-- 5,688 bytes parent folder | download
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
/* Copyright (c) 2008-2025 the MRtrix3 contributors.
 *
 * This Source Code Form is subject to the terms of the Mozilla Public
 * License, v. 2.0. If a copy of the MPL was not distributed with this
 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
 *
 * Covered Software is provided under this License on an "as is"
 * basis, without warranty of any kind, either expressed, implied, or
 * statutory, including, without limitation, warranties that the
 * Covered Software is free of defects, merchantable, fit for a
 * particular purpose or non-infringing.
 * See the Mozilla Public License v. 2.0 for more details.
 *
 * For more details, see http://www.mrtrix.org/.
 */


#include "command.h"
#include "exception.h"
#include "math/rng.h"
#include "misc/bitset.h"

using namespace MR;
using namespace App;

void usage ()
{
  AUTHOR = "Robert E. Smith (robert.smith@florey.edu.au)";
  SYNOPSIS = "Verify correct operation of the BitSet class";
  REQUIRES_AT_LEAST_ONE_ARGUMENT = false;
}


void run ()
{
  vector<std::string> failed_tests;
  auto test = [&] (const bool result, const std::string msg) {
    if (!result)
      failed_tests.push_back (msg);
  };
  auto identical = [] (const BitSet& a, const BitSet& b, const size_t bits) {
    for (size_t i = 0; i != bits; ++i) {
      if (a[i] != b[i])
        return false;
    }
    return true;
  };
  auto valid_last = [] (const BitSet& a, const size_t from_bit, const bool value) {
    for (size_t i = from_bit; i != a.size(); ++i) {
      if (a[i] != value)
        return false;
    }
    return true;
  };
  // Test up to two complete bytes; anything beyond that shouldn't be testing anything new
  for (size_t bits = 0; bits != 16; ++bits) {
    Math::RNG::Integer<size_t> rng (bits ? (bits-1) : 0);
    // Complete the sequence of tests twice:
    //   Once filling the bits with 0 and then setting specific bits to 1,
    //   then again filling them with 1 and then setting specific bits to 0
    for (size_t iter_fillvalue = 0; iter_fillvalue != 2; ++iter_fillvalue) {
      const bool fill_value = bool(iter_fillvalue);
      const bool set_value = !fill_value;
      BitSet data (bits, fill_value);
      switch (iter_fillvalue) {
        case 0: test (data.empty(), "Zero-filled set of size " + str(bits) + " reported non-empty"); break;
        case 1: test (data.full(), "One-filled set of size " + str(bits) + " reported non-full"); break;
        default: assert (0);
      }
      for (size_t i = 0; i != bits; ++i) {
        size_t index_to_toggle;
        do {
          index_to_toggle = rng();
        } while (data[index_to_toggle] != fill_value);
        switch (iter_fillvalue) {
          case 0: test (!data.full(), "Incompletely filled set of size " + str(bits) + " reported full"); break;
          case 1: test (!data.empty(), "Incompletely zeroed set of size " + str(bits) + " reported empty"); break;
          default: assert (0);
        }
        data[index_to_toggle] = set_value;
        const size_t target_count = iter_fillvalue ? (bits-(i+1)) : (i+1);
        test (data.count() == target_count, "Data " + str(data) + " (count " + str(target_count) + ") erroneously reported as count " + str(data.count()));
      }
      switch (iter_fillvalue) {
        case 0: test (data.full(), "Progressively filled set of size " + str(bits) + " reported non-full"); break;
        case 1: test (data.empty(), "Progressively zeroed set of size " + str(bits) + " reported non-empty"); break;
        default: assert (0);
      }
      // Duplicate
      BitSet duplicate (data);
      test (identical (data, duplicate, bits), "Duplicated sets pre-resize of size " + str(bits) + " did not lead to identical data: " + str(data) + " " + str(duplicate));
      // Change one bit within the final byte; make sure duplicate is no longer equivalent according to operator==()
      if (bits) {
        size_t index_to_toggle;
        do {
          index_to_toggle = rng();
        } while (index_to_toggle < 8*((bits-1)/8));
        duplicate[index_to_toggle] = fill_value;
        test (data != duplicate, "Change of one bit in size " + str(bits) + " not reported as inequal: " + str(data) + " " + str(duplicate));
        duplicate[index_to_toggle] = set_value;
        test (data == duplicate, "Reversion of one changed bit in size " + str(bits) + " not reported as equal: " + str(data) + " " + str(duplicate));
      }
      // Resize, make sure data are preserved and new items are set appropriately
      data.resize (bits+8, false);
      duplicate.resize (bits+8, true);
      test (identical (data, duplicate, bits), "Duplicated sets post-resize of size " + str(bits) + " did not lead to identical data: " + str(data) + " " + str(duplicate));
      switch (iter_fillvalue) {
        case 0:
          test (valid_last (data, bits, false), "Resized (0's) full set of size " + str(bits) + " contains invalid zeroed excess data: " + str(data));
          test (valid_last (duplicate, bits, true), "Resized (1's) full set of size " + str(bits) + " contains invalid filled excess data: " + str(duplicate));
          break;
        case 1:
          test (valid_last (data, bits, false), "Resized (0's) empty set of size " + str(bits) + " contains invalid zeroed excess data: " + str(data));
          test (valid_last (duplicate, bits, true), "Resized (1's) empty set of size " + str(bits) + " contains invalid filled excess data: " + str(duplicate));
          break;
        default: assert (0);
      }
    }
  }
  if (failed_tests.size()) {
    Exception e (str(failed_tests.size()) + " tests of BitSet class failed:");
    for (auto s : failed_tests)
      e.push_back (s);
    throw e;
  }
}