DryChem 1.0.0
A generic, compile-time C++ toolbox with no dependencies for the modern computational chemistry project.
Loading...
Searching...
No Matches
testVector3DFunctions.hpp
Go to the documentation of this file.
1// Copyright (c) 2020-2025 Cody R. Drisko. All rights reserved.
2// Licensed under the MIT License. See the LICENSE file in the project root for more information.
3//
4// Name: testVector3DFunctions.hpp
5// Author: crdrisko
6// Date: 04/09/2020-21:56:59
7// Description: Provides ~100% unit test coverage over all Vector3D functions
8
9#ifndef DRYCHEM_COMMON_UTILITIES_LIBS_MATH_TESTS_TESTCONTAINERS_TESTVECTOR3DFUNCTIONS_HPP
10#define DRYCHEM_COMMON_UTILITIES_LIBS_MATH_TESTS_TESTCONTAINERS_TESTVECTOR3DFUNCTIONS_HPP
11
12#include <algorithm>
13#include <array>
14#include <cstddef>
15#include <exception>
16#include <iostream>
17#include <stdexcept>
18#include <string>
19#include <utility>
20
22#include <common-utils/math.hpp>
23#include <common-utils/meta.hpp>
24#include <gtest/gtest.h>
25
26GTEST_TEST(testVector3DFunctions, typeWithNoDefaultConstructorGivesACompileTimeError)
27{
28 struct NoDefaultConstructor
29 {
30 // NoDefaultConstructor() = delete; // Uncomment for a compile-time error
31 };
32
33 DryChem::Vector3D<NoDefaultConstructor> test {};
34
35 static_assert(test.size() == 3UL, "size() of Vector 3D should always be 3.");
36}
37
38GTEST_TEST(testVector3DFunctions, memberTypesForAnExampleVector3DTypeAreCorrect)
39{
40 // clang-format off
41 static_assert((std::is_same_v<DryChem::Vector3D<double>::value_type, double>), "value_type is incorrect.");
42 static_assert((std::is_same_v<DryChem::Vector3D<double>::size_type, std::size_t>), "size_type is incorrect.");
43 static_assert((std::is_same_v<DryChem::Vector3D<double>::difference_type, std::ptrdiff_t>), "difference_type is incorrect.");
44 static_assert((std::is_same_v<DryChem::Vector3D<double>::reference, double&>), "reference is incorrect.");
45 static_assert((std::is_same_v<DryChem::Vector3D<double>::const_reference, const double&>), "const_reference is incorrect.");
46 static_assert((std::is_same_v<DryChem::Vector3D<double>::pointer, double*>), "pointer is incorrect.");
47 static_assert((std::is_same_v<DryChem::Vector3D<double>::const_pointer, const double*>), "const_pointer is incorrect.");
48 static_assert((std::is_same_v<DryChem::Vector3D<double>::iterator, std::array<double, 3>::iterator>), "iterator is incorrect.");
49 static_assert((std::is_same_v<DryChem::Vector3D<double>::const_iterator, std::array<double, 3>::const_iterator>), "const_iterator is incorrect.");
50 static_assert((std::is_same_v<DryChem::Vector3D<double>::container_type, std::array<double, 3>>), "const_iterator is incorrect.");
51 // clang-format on
52}
53
54GTEST_TEST(testVector3DFunctions, vector3DIsClassifiedLikeAStdArrayAndAContainerAdapter)
55{
56 ASSERT_FALSE((DryChem::is_allocator_aware_container_v<DryChem::Vector3D<int>>));
57 ASSERT_FALSE((DryChem::is_associative_container_v<DryChem::Vector3D<int>>));
58 ASSERT_TRUE((DryChem::is_container_v<DryChem::Vector3D<int>>));
59 ASSERT_TRUE((DryChem::is_container_adapter_v<DryChem::Vector3D<int>>));
60 ASSERT_FALSE((DryChem::is_reversible_container_v<DryChem::Vector3D<int>>));
61 ASSERT_TRUE((DryChem::is_sequence_container_v<DryChem::Vector3D<int>>));
62 ASSERT_FALSE((DryChem::is_unordered_associative_container_v<DryChem::Vector3D<int>>));
63}
64
65GTEST_TEST(testVector3DFunctions, differentConstructorsInitializeObjectsAsExpected)
66{
67 std::array<int, 3> sampleArray {1, 2, 3};
68
69 DryChem::Vector3D<long double> defaultInitialized {};
70 DryChem::Vector3D<int> arrayInitialized {sampleArray};
71 DryChem::Vector3D<float> valuesInitialized {1.0f, 3.0f, 5.0f};
72
73 for (std::size_t i {}; i < 3; ++i)
74 {
75 ASSERT_EQ(0.0, defaultInitialized[i]);
76 ASSERT_EQ(sampleArray[i], arrayInitialized[i]);
77 ASSERT_EQ(2 * sampleArray[i] - 1, valuesInitialized[i]);
78 }
79}
80
81GTEST_TEST(testVector3DFunctions, overloadedComparsionOperatorsPerformElementwiseComparisons)
82{
83 std::array<int, 3> valueArray {1, 2, 3};
84
85 DryChem::Vector3D<int> value1 {1, 2, 3};
86 DryChem::Vector3D<int> value2 {};
87 DryChem::Vector3D<int> value3 {valueArray};
88 DryChem::Vector3D<int> value4 {1, 0, 3};
89
90 ASSERT_TRUE(value1 == value3);
91 ASSERT_FALSE(value1 == value2);
92
93 ASSERT_TRUE(value2 < value1);
94 ASSERT_FALSE(value1 < value2);
95
96 ASSERT_TRUE(value3 != value2);
97 ASSERT_FALSE(value3 != value1);
98
99 ASSERT_TRUE(value1 <= value3);
100 ASSERT_FALSE(value3 <= value4);
101
102 ASSERT_TRUE(value1 > value4);
103 ASSERT_FALSE(value2 > value4);
104
105 ASSERT_TRUE(value3 >= value2);
106 ASSERT_FALSE(value2 >= value4);
107}
108
109GTEST_TEST(testVector3DFunctions, atFunctionOverloadsCanReturnAndSetTheInternalData)
110{
111 DryChem::Vector3D<long double> coordinates {1.0, -3.0, 5.0};
112
113 ASSERT_EQ(1.0, coordinates.at(0));
114 ASSERT_EQ(-3.0, coordinates.at(1));
115 ASSERT_EQ(5.0, coordinates.at(2));
116
117 coordinates.at(0) += 4.0;
118 coordinates.at(1) += 4.0;
119 coordinates.at(2) += 4.0;
120
121 ASSERT_EQ(5.0, coordinates.at(0));
122 ASSERT_EQ(1.0, coordinates.at(1));
123 ASSERT_EQ(9.0, coordinates.at(2));
124}
125
126GTEST_TEST(testVector3DFunctions, subscriptOperatorsCanReturnAndSetTheInternalData)
127{
128 DryChem::Vector3D<long double> coordinates {1.0, -3.0, 5.0};
129
130 ASSERT_EQ(1.0, coordinates[0]);
131 ASSERT_EQ(-3.0, coordinates[1]);
132 ASSERT_EQ(5.0, coordinates[2]);
133
134 coordinates[0] += 4.0;
135 coordinates[1] += 4.0;
136 coordinates[2] += 4.0;
137
138 ASSERT_EQ(5.0, coordinates[0]);
139 ASSERT_EQ(1.0, coordinates[1]);
140 ASSERT_EQ(9.0, coordinates[2]);
141}
142
143GTEST_TEST(testVector3DFunctions, atFunctionOverloadsWillThrowWhenIndexIsOutOfRange)
144{
145 std::stringstream deathRegex;
146
147 deathRegex << "Common-Utilities Fatal Error:\n Exception message: ";
148
149#if GTEST_USES_POSIX_RE
150 deathRegex << "array::at";
151#elif GTEST_USES_SIMPLE_RE
152 try
153 {
154 std::cout << std::array<int, 3>().at(3) << std::endl;
155 }
156 catch (const std::out_of_range& except)
157 {
158 deathRegex << except.what();
159 }
160#endif
161
162 ASSERT_DEATH(
163 {
164 try
165 {
166 try
167 {
168 DryChem::Vector3D<int>().at(3);
169 }
170 catch (const std::exception& except)
171 {
172 DryChem::ErrorMessage error;
173 error.programName = "Common-Utilities";
174 error.message = "Exception message: " + std::string {except.what()};
175
176 throw DryChem::FatalException(error);
177 }
178 }
179 catch (const DryChem::FatalException& except)
180 {
181 except.handleErrorWithMessage();
182 }
183 },
184 deathRegex.str());
185
186 ASSERT_DEATH(
187 {
188 try
189 {
190 try
191 {
192 DryChem::Vector3D<int>().at(3) = 2;
193 }
194 catch (const std::exception& except)
195 {
196 DryChem::ErrorMessage error;
197 error.programName = "Common-Utilities";
198 error.message = "Exception message: " + std::string {except.what()};
199
200 throw DryChem::FatalException(error);
201 }
202 }
203 catch (const DryChem::FatalException& except)
204 {
205 except.handleErrorWithMessage();
206 }
207 },
208 deathRegex.str());
209}
210
211GTEST_TEST(testVector3DFunctions, aVector3DCanBeUsedInStdAlgorithms)
212{
213 DryChem::Vector3D<long double> vec {2.0l, 3.5l, 0.1l};
214
215 ASSERT_FALSE(std::is_sorted(vec.cbegin(), vec.cend()));
216
217 std::sort(vec.begin(), vec.end());
218
219 ASSERT_TRUE(std::is_sorted(vec.begin(), vec.end()));
220}
221
222GTEST_TEST(testVector3DFunctions, aVector3DCanBeUsedInRangeBasedForLoops)
223{
224 testing::internal::CaptureStdout();
225
226 for (const auto& elem : DryChem::Vector3D<long double> {2.2l, 3.3l, 1.1l})
227 std::cout << elem << ' ';
228 std::cout << std::endl;
229
230 std::string output = testing::internal::GetCapturedStdout();
231 ASSERT_EQ(output, "2.2 3.3 1.1 \n");
232}
233
234GTEST_TEST(testVector3DFunctions, aVector3DIsNeverEmpty)
235{
236 DryChem::Vector3D<long> vec;
237
238 ASSERT_TRUE(!vec.empty());
239 ASSERT_FALSE(vec.empty());
240}
241
242GTEST_TEST(testVector3DFunctions, theSizeOfAVector3DIsAlways3)
243{
244 DryChem::Vector3D<long> vec;
245
246 ASSERT_EQ(vec.size(), 3UL);
247}
248
249GTEST_TEST(testVector3DFunctions, theMaxSizeOfAVector3DIsAlways3)
250{
251 DryChem::Vector3D<long> vec;
252
253 ASSERT_EQ(vec.max_size(), 3UL);
254}
255
256GTEST_TEST(testVector3DFunctions, theFillMemberFunctionSetsAllElementsToTheSameValue)
257{
258 DryChem::Vector3D<long double> vec {1.0l, 2.0l, 3.0l};
259
260 long double counter {};
261
262 for (const auto& elem : vec)
263 ASSERT_EQ(++counter, elem);
264
265 vec.fill(3.14l);
266
267 for (const auto& elem : vec)
268 ASSERT_EQ(3.14l, elem);
269}
270
271GTEST_TEST(testVector3DFunctions, theSwapMemberFunctionSwapsAllElementsOfTwoVector3Ds)
272{
273 DryChem::Vector3D<long double> vec1 {1.0l, 2.0l, 3.0l};
274 DryChem::Vector3D<long double> vec2 {6.0l, 4.0l, 2.0l};
275
276 DryChem::Vector3D<long double> copyVec1 {vec1};
277 DryChem::Vector3D<long double> copyVec2 {vec2};
278
279 vec1.swap(vec2);
280
281 for (std::size_t i {}; i < vec1.size(); ++i)
282 {
283 ASSERT_EQ(vec1[i], copyVec2[i]);
284 ASSERT_EQ(vec2[i], copyVec1[i]);
285 }
286}
287
288GTEST_TEST(testVector3DFunctions, ourTupleLikeAPIProvidesReadAccessToTheElementsViaStructuredBindings)
289{
290 DryChem::Vector3D<long double> vec {0.0l, 1.2l, 3.14l};
291 auto [x, y, z] = vec;
292
293 ASSERT_EQ(x, vec[0]);
294 ASSERT_EQ(y, vec[1]);
295 ASSERT_EQ(z, vec[2]);
296}
297
298GTEST_TEST(testVector3DFunctions, ourTupleLikeAPIProvidesReadAndWriteAccessToTheElementsViaStructuredBindings)
299{
300 DryChem::Vector3D<long double> vec {0.0l, 1.2l, 3.14l};
301
302 auto&& [x, y, z] = vec;
303
304 long double value {std::move(z)};
305
306 ASSERT_EQ(value, 3.14l);
307
308 z = 4.2l;
309 y += 3.8l;
310
311 ASSERT_EQ(x, 0.0l);
312 ASSERT_EQ(y, 5.0l);
313 ASSERT_EQ(z, 4.2l);
314}
315
316#endif
GTEST_TEST(testVector3DFunctions, typeWithNoDefaultConstructorGivesACompileTimeError)
Definition testVector3DFunctions.hpp:26