File: itkCopyGTest.cxx

package info (click to toggle)
insighttoolkit5 5.4.3-5
  • links: PTS, VCS
  • area: main
  • in suites: forky, sid, trixie
  • size: 704,384 kB
  • sloc: cpp: 783,592; ansic: 628,724; xml: 44,704; fortran: 34,250; python: 22,874; sh: 4,078; pascal: 2,636; lisp: 2,158; makefile: 464; yacc: 328; asm: 205; perl: 203; lex: 146; tcl: 132; javascript: 98; csh: 81
file content (116 lines) | stat: -rw-r--r-- 4,491 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
/*=========================================================================
 *
 *  Copyright NumFOCUS
 *
 *  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.txt
 *
 *  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.
 *
 *=========================================================================*/

// First include the header file to be tested:
#include "itkCopy.h"
#include <gtest/gtest.h>

#include <array>
#include <cstdint> // For intmax_t.
#include <random>
#include <utility> // For pair.
#include <vector>


// Check compile-time evaluation:
static_assert(itk::Copy(0) == 0);
static_assert(itk::Copy(1) == 1);

namespace
{
// Returns a (const) reference to the specified argument.
template <typename T>
const T &
GetReference(const T & arg)
{
  return arg;
}
} // namespace


// Checks that an object returned by `itk::Copy(original)` compares equal to the original, even though it has a
// different address.
TEST(Copy, EqualToTheOriginalButHasDifferentAddress)
{
  const auto check = [](const auto & original) {
    auto && copy = itk::Copy(original);

    // The returned `copy` has an equal value...
    EXPECT_EQ(copy, original);

    // ... but a different address!
    EXPECT_NE(&copy, &original);
  };

  std::default_random_engine randomEngine{};
  const auto getRandomNumber = [&randomEngine] { return std::uniform_int_distribution<>{}(randomEngine); };

  check(getRandomNumber());
  check(std::vector<int>(3, getRandomNumber()));
  check(std::array<int, 3>{ getRandomNumber(), getRandomNumber(), getRandomNumber() });
}


// Tests that `itk::Copy` allows storing a copy of a value in a variable declared by `auto`, without a warning.
TEST(Copy, AllowsUsingAutoKeywordCopyingWithoutWarnings)
{
  std::vector<std::intmax_t> originalVector{ 1, 2, 3, 4 };

  // Without `itk::Copy`, the statement `const auto copyOfVector = GetReference(originalVector);` might trigger a
  // warning, saying something like "`auto` doesn't deduce references. A possibly unintended copy is being made" (MSVC
  // 2022 IntelliSense Code Linter).
  const auto copyOfVector = itk::Copy(GetReference(originalVector));

  // Clear the original (not the "copy").
  originalVector = {};

  // In this case, it is essential that the "copy" is not just a reference to the original, because the value of the
  // original object is modified after that copy took place. This modification should not affect the copy.
  ASSERT_NE(originalVector, copyOfVector);

  // A similar test for the equivalent `std::array`:
  std::array<std::intmax_t, 4> originalArray{ 1, 2, 3, 4 };

  // MSVC 2022 Warning C26820 ("This is a potentially expensive copy operation. Consider using a reference unless a copy
  // is required.") is not raised for types whose size isn't more than twice the platform-dependent pointer size,
  // according to https://learn.microsoft.com/en-us/cpp/code-quality/c26820?view=msvc-170
  static_assert(
    sizeof(originalArray) > 2 * sizeof(void *),
    "The array must be big enough to _possibly_ trigger compiler warnings about the expensiveness of copying!");

  const auto copyOfArray = itk::Copy(GetReference(originalArray));

  // Reset the elements of the original array (not the "copy").
  originalArray = {};

  // The original and the copy should be different now, because the copy is not reset.
  ASSERT_NE(originalArray, copyOfArray);

  // Sanity check: the copy of the vector and the copy of the array still have the same elements.
  EXPECT_TRUE(std::equal(copyOfVector.cbegin(), copyOfVector.cend(), copyOfArray.cbegin(), copyOfArray.cend()));

  // The following demonstates an `itk::Copy` use case when having structured bindings:
  auto originalPair =
    std::make_pair(std::vector<std::intmax_t>{ 1, 2, 3, 4 }, std::array<std::intmax_t, 4>{ 1, 2, 3, 4 });
  const auto [first, second] = itk::Copy(GetReference(originalPair));
  const auto copyOfPair = itk::Copy(GetReference(originalPair));
  originalPair = {};
  ASSERT_NE(originalPair, copyOfPair);

  EXPECT_EQ(copyOfPair, std::make_pair(first, second));
}