feat: modules moved and engine moved to submodule

This commit is contained in:
Jan van der Weide 2025-04-12 18:40:44 +02:00
parent dfb5e645cd
commit c33d2130cc
5136 changed files with 225275 additions and 64485 deletions

View file

@ -28,8 +28,7 @@
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
/**************************************************************************/
#ifndef TEST_PROJECT_SETTINGS_H
#define TEST_PROJECT_SETTINGS_H
#pragma once
#include "core/config/project_settings.h"
#include "core/io/dir_access.h"
@ -113,7 +112,7 @@ TEST_CASE("[ProjectSettings] localize_path") {
TestProjectSettingsInternalsAccessor::resource_path() = DirAccess::create(DirAccess::ACCESS_FILESYSTEM)->get_current_dir();
String root_path = ProjectSettings::get_singleton()->get_resource_path();
#ifdef WINDOWS_ENABLED
String root_path_win = ProjectSettings::get_singleton()->get_resource_path().replace("/", "\\");
String root_path_win = ProjectSettings::get_singleton()->get_resource_path().replace_char('/', '\\');
#endif
CHECK_EQ(ProjectSettings::get_singleton()->localize_path("filename"), "res://filename");
@ -160,5 +159,3 @@ TEST_CASE("[ProjectSettings] localize_path") {
}
} // namespace TestProjectSettings
#endif // TEST_PROJECT_SETTINGS_H

View file

@ -28,8 +28,7 @@
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
/**************************************************************************/
#ifndef TEST_INPUT_EVENT_H
#define TEST_INPUT_EVENT_H
#pragma once
#include "core/input/input_event.h"
#include "core/math/rect2.h"
@ -44,10 +43,8 @@ TEST_CASE("[InputEvent] Signal is emitted when device is changed") {
input_event.instantiate();
SIGNAL_WATCH(*input_event, CoreStringName(changed));
Array args1;
Array empty_args;
empty_args.push_back(args1);
Array empty_args = { {} };
input_event->set_device(1);
SIGNAL_CHECK("changed", empty_args);
@ -111,5 +108,3 @@ TEST_CASE("[InputEvent] Test xformed_by") {
CHECK(iemm2->get_position().is_equal_approx(Vector2(2.0f, 3.0f)));
}
} // namespace TestInputEvent
#endif // TEST_INPUT_EVENT_H

View file

@ -28,8 +28,7 @@
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
/**************************************************************************/
#ifndef TEST_INPUT_EVENT_KEY_H
#define TEST_INPUT_EVENT_KEY_H
#pragma once
#include "core/input/input_event.h"
#include "core/os/keyboard.h"
@ -335,5 +334,3 @@ TEST_CASE("[IsMatch] Keys are correctly matched") {
CHECK(key3.is_match(loc_ref, false) == true);
}
} // namespace TestInputEventKey
#endif // TEST_INPUT_EVENT_KEY_H

View file

@ -28,8 +28,7 @@
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
/**************************************************************************/
#ifndef TEST_INPUT_EVENT_MOUSE_H
#define TEST_INPUT_EVENT_MOUSE_H
#pragma once
#include "core/input/input_event.h"
#include "tests/test_macros.h"
@ -77,5 +76,3 @@ TEST_CASE("[InputEventMouse] Setting the global mouse position works correctly")
CHECK(mousekey.get_global_position() != Vector2{ 1, 1 });
}
} // namespace TestInputEventMouse
#endif // TEST_INPUT_EVENT_MOUSE_H

View file

@ -28,8 +28,7 @@
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
/**************************************************************************/
#ifndef TEST_SHORTCUT_H
#define TEST_SHORTCUT_H
#pragma once
#include "core/input/input_event.h"
#include "core/input/shortcut.h"
@ -61,10 +60,7 @@ TEST_CASE("[Shortcut] Setting and getting an event should result in the same eve
// Cast to InputEvent so the internal code recognizes the objects.
Ref<InputEvent> e1 = k1;
Ref<InputEvent> e2 = k2;
Array input_array;
input_array.append(e1);
input_array.append(e2);
Array input_array = { e1, e2 };
Shortcut s;
s.set_events(input_array);
@ -132,8 +128,7 @@ TEST_CASE("[Shortcut] 'matches_event' should correctly match the same event") {
Ref<InputEvent> e_different = different;
Ref<InputEvent> e_copy = copy;
Array a;
a.append(e_original);
Array a = { e_original };
Shortcut s;
s.set_events(a);
@ -155,9 +150,7 @@ TEST_CASE("[Shortcut] 'get_as_text' text representation should be correct") {
different->set_keycode(Key::ESCAPE);
Ref<InputEvent> key_event1 = same;
Array a;
a.append(key_event1);
Array a = { key_event1 };
Shortcut s;
s.set_events(a);
@ -176,17 +169,14 @@ TEST_CASE("[Shortcut] Event validity should be correctly checked.") {
Ref<InputEvent> valid_event = valid;
Ref<InputEvent> invalid_event = invalid;
Array a;
a.append(invalid_event);
a.append(valid_event);
Array a = { invalid_event, valid_event };
Shortcut s;
s.set_events(a);
CHECK(s.has_valid_event() == true);
Array b;
b.append(invalid_event);
Array b = { invalid_event };
Shortcut shortcut_with_invalid_event;
shortcut_with_invalid_event.set_events(b);
@ -214,13 +204,8 @@ TEST_CASE("[Shortcut] Equal arrays should be recognized as such.") {
Array same_as_same;
same_as_same.append(key_event1);
Array different1;
different1.append(key_event2);
Array different2;
different2.append(key_event1);
different2.append(key_event2);
Array different1 = { key_event2 };
Array different2 = { key_event1, key_event2 };
Array different3;
Shortcut s;
@ -231,5 +216,3 @@ TEST_CASE("[Shortcut] Equal arrays should be recognized as such.") {
CHECK(s.is_event_array_equal(same, different3) == false);
}
} // namespace TestShortcut
#endif // TEST_SHORTCUT_H

View file

@ -28,8 +28,7 @@
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
/**************************************************************************/
#ifndef TEST_CONFIG_FILE_H
#define TEST_CONFIG_FILE_H
#pragma once
#include "core/io/config_file.h"
#include "core/os/os.h"
@ -160,5 +159,3 @@ antiAliasing=false
"The saved configuration file should match the expected format.");
}
} // namespace TestConfigFile
#endif // TEST_CONFIG_FILE_H

View file

@ -28,8 +28,7 @@
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
/**************************************************************************/
#ifndef TEST_FILE_ACCESS_H
#define TEST_FILE_ACCESS_H
#pragma once
#include "core/io/file_access.h"
#include "tests/test_macros.h"
@ -197,8 +196,28 @@ TEST_CASE("[FileAccess] Get/Store floating point half precision values") {
DirAccess::remove_file_or_error(file_path_new);
}
SUBCASE("4096 bytes fastlz compressed") {
const String file_path = TestUtils::get_data_path("exactly_4096_bytes_fastlz.bin");
Ref<FileAccess> f = FileAccess::open_compressed(file_path, FileAccess::READ, FileAccess::COMPRESSION_FASTLZ);
const Vector<uint8_t> full_data = f->get_buffer(4096 * 2);
CHECK(full_data.size() == 4096);
CHECK(f->eof_reached());
// Data should be empty.
PackedByteArray reference;
reference.resize_zeroed(4096);
CHECK(reference == full_data);
f->seek(0);
const Vector<uint8_t> partial_data = f->get_buffer(4095);
CHECK(partial_data.size() == 4095);
CHECK(!f->eof_reached());
reference.resize_zeroed(4095);
CHECK(reference == partial_data);
}
}
} // namespace TestFileAccess
#endif // TEST_FILE_ACCESS_H

View file

@ -28,8 +28,7 @@
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
/**************************************************************************/
#ifndef TEST_HTTP_CLIENT_H
#define TEST_HTTP_CLIENT_H
#pragma once
#include "core/io/http_client.h"
@ -59,10 +58,7 @@ TEST_CASE("[HTTPClient] query_string_from_dict") {
Dictionary dict2;
dict2["key1"] = "value";
dict2["key2"] = 123;
Array values;
values.push_back(1);
values.push_back(2);
values.push_back(3);
Array values = { 1, 2, 3 };
dict2["key3"] = values;
dict2["key4"] = Variant();
String multiple_keys = client->query_string_from_dict(dict2);
@ -106,5 +102,3 @@ TEST_CASE("[HTTPClient] connect_to_host") {
#endif // MODULE_MBEDTLS_ENABLED || WEB_ENABLED
} // namespace TestHTTPClient
#endif // TEST_HTTP_CLIENT_H

View file

@ -28,8 +28,7 @@
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
/**************************************************************************/
#ifndef TEST_IMAGE_H
#define TEST_IMAGE_H
#pragma once
#include "core/io/image.h"
#include "core/os/os.h"
@ -444,5 +443,3 @@ TEST_CASE("[Image] Convert image") {
}
} // namespace TestImage
#endif // TEST_IMAGE_H

View file

@ -28,8 +28,7 @@
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
/**************************************************************************/
#ifndef TEST_IP_H
#define TEST_IP_H
#pragma once
#include "core/io/ip.h"
@ -47,5 +46,3 @@ TEST_CASE("[IP] resolve_hostname") {
}
} // namespace TestIP
#endif // TEST_IP_H

View file

@ -28,8 +28,7 @@
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
/**************************************************************************/
#ifndef TEST_JSON_H
#define TEST_JSON_H
#pragma once
#include "core/io/json.h"
@ -153,21 +152,13 @@ TEST_CASE("[JSON] Parsing escape sequences") {
JSON json;
TypedArray<String> valid_escapes;
valid_escapes.push_back("\";\"");
valid_escapes.push_back("\\;\\");
valid_escapes.push_back("/;/");
valid_escapes.push_back("b;\b");
valid_escapes.push_back("f;\f");
valid_escapes.push_back("n;\n");
valid_escapes.push_back("r;\r");
valid_escapes.push_back("t;\t");
TypedArray<String> valid_escapes = { "\";\"", "\\;\\", "/;/", "b;\b", "f;\f", "n;\n", "r;\r", "t;\t" };
SUBCASE("Basic valid escape sequences") {
for (int i = 0; i < valid_escapes.size(); i++) {
String valid_escape = valid_escapes[i];
String valid_escape_string = valid_escape.get_slice(";", 0);
String valid_escape_value = valid_escape.get_slice(";", 1);
String valid_escape_string = valid_escape.get_slicec(';', 0);
String valid_escape_value = valid_escape.get_slicec(';', 1);
String json_string = "\"\\";
json_string += valid_escape_string;
@ -205,7 +196,7 @@ TEST_CASE("[JSON] Parsing escape sequences") {
bool skip = false;
for (int j = 0; j < valid_escapes.size(); j++) {
String valid_escape = valid_escapes[j];
String valid_escape_string = valid_escape.get_slice(";", 0);
String valid_escape_string = valid_escape.get_slicec(';', 0);
if (valid_escape_string[0] == i) {
skip = true;
break;
@ -318,5 +309,3 @@ TEST_CASE("[JSON] Serialization") {
}
}
} // namespace TestJSON
#endif // TEST_JSON_H

View file

@ -28,8 +28,7 @@
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
/**************************************************************************/
#ifndef TEST_JSON_NATIVE_H
#define TEST_JSON_NATIVE_H
#pragma once
#include "core/io/json.h"
@ -162,25 +161,13 @@ TEST_CASE("[JSON][Native] Conversion between native and JSON formats") {
// `Array`.
Array arr;
arr.push_back(true);
arr.push_back(1);
arr.push_back("abc");
Array arr = { true, 1, "abc" };
test(arr, R"([true,"i:1","s:abc"])");
TypedArray<int64_t> int_arr;
int_arr.push_back(1);
int_arr.push_back(2);
int_arr.push_back(3);
TypedArray<int64_t> int_arr = { 1, 2, 3 };
test(int_arr, R"({"type":"Array","elem_type":"int","args":["i:1","i:2","i:3"]})");
Array arr2;
arr2.push_back(1);
arr2.push_back(res);
arr2.push_back(9);
Array arr2 = { 1, res, 9 };
const String arr2_repr = vformat(R"(["i:1",%s,"i:9"])", res_repr);
test(arr2, arr2_repr, true);
@ -189,9 +176,7 @@ TEST_CASE("[JSON][Native] Conversion between native and JSON formats") {
CHECK(decode(arr2_repr).get_construct_string() == "[1, null, 9]");
ERR_PRINT_ON;
TypedArray<Resource> res_arr;
res_arr.push_back(res);
TypedArray<Resource> res_arr = { res };
const String res_arr_repr = vformat(R"({"type":"Array","elem_type":"Resource","args":[%s]})", res_repr);
test(res_arr, res_arr_repr, true);
@ -223,5 +208,3 @@ TEST_CASE("[JSON][Native] Conversion between native and JSON formats") {
}
} // namespace TestJSONNative
#endif // TEST_JSON_NATIVE_H

View file

@ -28,8 +28,7 @@
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
/**************************************************************************/
#ifndef TEST_LOGGER_H
#define TEST_LOGGER_H
#pragma once
#include "core/io/dir_access.h"
#include "core/io/logger.h"
@ -166,5 +165,3 @@ TEST_CASE("[Logger][CompositeLogger] Logs the same into multiple loggers") {
}
} // namespace TestLogger
#endif // TEST_LOGGER_H

View file

@ -28,8 +28,7 @@
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
/**************************************************************************/
#ifndef TEST_MARSHALLS_H
#define TEST_MARSHALLS_H
#pragma once
#include "core/io/marshalls.h"
@ -491,5 +490,3 @@ TEST_CASE("[Marshalls] Typed dictionary decoding") {
}
} // namespace TestMarshalls
#endif // TEST_MARSHALLS_H

View file

@ -28,8 +28,7 @@
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
/**************************************************************************/
#ifndef TEST_PACKET_PEER_H
#define TEST_PACKET_PEER_H
#pragma once
#include "core/io/packet_peer.h"
#include "tests/test_macros.h"
@ -200,5 +199,3 @@ TEST_CASE("[PacketPeer][PacketPeerStream] Put packet buffer when is empty") {
}
} // namespace TestPacketPeer
#endif // TEST_PACKET_PEER_H

View file

@ -28,8 +28,7 @@
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
/**************************************************************************/
#ifndef TEST_PCK_PACKER_H
#define TEST_PCK_PACKER_H
#pragma once
#include "core/io/file_access_pack.h"
#include "core/io/pck_packer.h"
@ -118,5 +117,3 @@ TEST_CASE("[PCKPacker] Pack a PCK file with some files and directories") {
"The generated non-empty PCK file shouldn't be too large.");
}
} // namespace TestPCKPacker
#endif // TEST_PCK_PACKER_H

View file

@ -28,8 +28,7 @@
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
/**************************************************************************/
#ifndef TEST_RESOURCE_H
#define TEST_RESOURCE_H
#pragma once
#include "core/io/resource.h"
#include "core/io/resource_loader.h"
@ -167,5 +166,3 @@ TEST_CASE("[Resource] Breaking circular references on save") {
resource_c->remove_meta("next");
}
} // namespace TestResource
#endif // TEST_RESOURCE_H

View file

@ -28,8 +28,7 @@
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
/**************************************************************************/
#ifndef TEST_RESOURCE_UID_H
#define TEST_RESOURCE_UID_H
#pragma once
#include "core/io/resource_uid.h"
@ -67,5 +66,3 @@ TEST_CASE("[ResourceUID] Must encode and decode various UIDs correctly") {
}
} // namespace TestResourceUID
#endif // TEST_RESOURCE_UID_H

View file

@ -28,8 +28,7 @@
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
/**************************************************************************/
#ifndef TEST_STREAM_PEER_H
#define TEST_STREAM_PEER_H
#pragma once
#include "core/io/stream_peer.h"
#include "tests/test_macros.h"
@ -307,5 +306,3 @@ TEST_CASE("[StreamPeer] Get UTF8 string when there is no string") {
}
} // namespace TestStreamPeer
#endif // TEST_STREAM_PEER_H

View file

@ -28,8 +28,7 @@
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
/**************************************************************************/
#ifndef TEST_STREAM_PEER_BUFFER_H
#define TEST_STREAM_PEER_BUFFER_H
#pragma once
#include "core/io/stream_peer.h"
#include "tests/test_macros.h"
@ -181,5 +180,3 @@ TEST_CASE("[StreamPeerBuffer] Get data with invalid size returns an error") {
}
} // namespace TestStreamPeerBuffer
#endif // TEST_STREAM_PEER_BUFFER_H

View file

@ -0,0 +1,195 @@
/**************************************************************************/
/* test_stream_peer_gzip.h */
/**************************************************************************/
/* This file is part of: */
/* GODOT ENGINE */
/* https://godotengine.org */
/**************************************************************************/
/* Copyright (c) 2014-present Godot Engine contributors (see AUTHORS.md). */
/* Copyright (c) 2007-2014 Juan Linietsky, Ariel Manzur. */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
/* "Software"), to deal in the Software without restriction, including */
/* without limitation the rights to use, copy, modify, merge, publish, */
/* distribute, sublicense, and/or sell copies of the Software, and to */
/* permit persons to whom the Software is furnished to do so, subject to */
/* the following conditions: */
/* */
/* The above copyright notice and this permission notice shall be */
/* included in all copies or substantial portions of the Software. */
/* */
/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. */
/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
/**************************************************************************/
#pragma once
#include "core/io/stream_peer_gzip.h"
#include "tests/test_macros.h"
namespace TestStreamPeerGZIP {
const String hello = "Hello World!!!";
TEST_CASE("[StreamPeerGZIP] Initialization") {
Ref<StreamPeerGZIP> spgz;
spgz.instantiate();
CHECK_EQ(spgz->get_available_bytes(), 0);
}
TEST_CASE("[StreamPeerGZIP] Compress/Decompress") {
Ref<StreamPeerGZIP> spgz;
spgz.instantiate();
bool is_deflate = false;
SUBCASE("GZIP") {
is_deflate = false;
}
SUBCASE("DEFLATE") {
is_deflate = true;
}
CHECK_EQ(spgz->start_compression(is_deflate), Error::OK);
CHECK_EQ(spgz->put_data(hello.to_ascii_buffer().ptr(), hello.to_ascii_buffer().size()), Error::OK);
CHECK_EQ(spgz->finish(), Error::OK);
Vector<uint8_t> hello_compressed;
int hello_compressed_size = spgz->get_available_bytes();
hello_compressed.resize(hello_compressed_size);
CHECK_EQ(spgz->get_data(hello_compressed.ptrw(), hello_compressed_size), Error::OK);
spgz->clear();
CHECK_EQ(spgz->start_decompression(is_deflate), Error::OK);
CHECK_EQ(spgz->put_data(hello_compressed.ptr(), hello_compressed.size()), Error::OK);
Vector<uint8_t> hello_decompressed;
int hello_decompressed_size = spgz->get_available_bytes();
hello_decompressed.resize(hello_decompressed_size);
CHECK_EQ(spgz->get_data(hello_decompressed.ptrw(), hello_decompressed_size), Error::OK);
CHECK_EQ(hello_decompressed, hello.to_ascii_buffer());
}
TEST_CASE("[StreamPeerGZIP] Compress/Decompress big chunks of data") { // GH-97201
Ref<StreamPeerGZIP> spgz;
spgz.instantiate();
CHECK_EQ(spgz->start_compression(false), Error::OK);
Vector<uint8_t> big_data;
big_data.resize(2500);
// Filling it with random data because the issue is related to the size of the data when it's compress.
// Random data results in bigger compressed data size.
for (int i = 0; i < big_data.size(); i++) {
big_data.write[i] = Math::random(48, 122);
}
CHECK_EQ(spgz->put_data(big_data.ptr(), big_data.size()), Error::OK);
CHECK_EQ(spgz->finish(), Error::OK);
Vector<uint8_t> big_data_compressed;
int big_data_compressed_size = spgz->get_available_bytes();
big_data_compressed.resize(big_data_compressed_size);
CHECK_EQ(spgz->get_data(big_data_compressed.ptrw(), big_data_compressed_size), Error::OK);
spgz->clear();
CHECK_EQ(spgz->start_decompression(false), Error::OK);
CHECK_EQ(spgz->put_data(big_data_compressed.ptr(), big_data_compressed.size()), Error::OK);
Vector<uint8_t> big_data_decompressed;
int big_data_decompressed_size = spgz->get_available_bytes();
big_data_decompressed.resize(big_data_decompressed_size);
CHECK_EQ(spgz->get_data(big_data_decompressed.ptrw(), big_data_decompressed_size), Error::OK);
CHECK_EQ(big_data_decompressed, big_data);
}
TEST_CASE("[StreamPeerGZIP] Can't start twice") {
Ref<StreamPeerGZIP> spgz;
spgz.instantiate();
CHECK_EQ(spgz->start_compression(false), Error::OK);
ERR_PRINT_OFF;
CHECK_EQ(spgz->start_compression(false), Error::ERR_ALREADY_IN_USE);
CHECK_EQ(spgz->start_decompression(false), Error::ERR_ALREADY_IN_USE);
ERR_PRINT_ON;
}
TEST_CASE("[StreamPeerGZIP] Can't start with a buffer size equal or less than zero") {
Ref<StreamPeerGZIP> spgz;
spgz.instantiate();
ERR_PRINT_OFF;
CHECK_EQ(spgz->start_compression(false, 0), Error::ERR_INVALID_PARAMETER);
CHECK_EQ(spgz->start_compression(false, -1), Error::ERR_INVALID_PARAMETER);
CHECK_EQ(spgz->start_decompression(false, 0), Error::ERR_INVALID_PARAMETER);
CHECK_EQ(spgz->start_decompression(false, -1), Error::ERR_INVALID_PARAMETER);
ERR_PRINT_ON;
}
TEST_CASE("[StreamPeerGZIP] Can't put/get data with a buffer size less than zero") {
Ref<StreamPeerGZIP> spgz;
spgz.instantiate();
CHECK_EQ(spgz->start_compression(false), Error::OK);
ERR_PRINT_OFF;
CHECK_EQ(spgz->put_data(hello.to_ascii_buffer().ptr(), -1), Error::ERR_INVALID_PARAMETER);
Vector<uint8_t> hello_compressed;
hello_compressed.resize(5);
CHECK_EQ(spgz->get_data(hello_compressed.ptrw(), -1), Error::ERR_INVALID_PARAMETER);
ERR_PRINT_ON;
}
TEST_CASE("[StreamPeerGZIP] Needs to be started before use") {
Ref<StreamPeerGZIP> spgz;
spgz.instantiate();
ERR_PRINT_OFF;
CHECK_EQ(spgz->put_data(hello.to_ascii_buffer().ptr(), hello.to_ascii_buffer().size()), Error::ERR_UNCONFIGURED);
ERR_PRINT_ON;
}
TEST_CASE("[StreamPeerGZIP] Can't be finished after clear or if it's decompressing") {
Ref<StreamPeerGZIP> spgz;
spgz.instantiate();
CHECK_EQ(spgz->start_compression(false), Error::OK);
spgz->clear();
ERR_PRINT_OFF;
CHECK_EQ(spgz->finish(), Error::ERR_UNAVAILABLE);
ERR_PRINT_ON;
spgz->clear();
CHECK_EQ(spgz->start_decompression(false), Error::OK);
ERR_PRINT_OFF;
CHECK_EQ(spgz->finish(), Error::ERR_UNAVAILABLE);
ERR_PRINT_ON;
}
TEST_CASE("[StreamPeerGZIP] Fails to get if nothing was compress/decompress") {
Ref<StreamPeerGZIP> spgz;
spgz.instantiate();
SUBCASE("Compression") {
CHECK_EQ(spgz->start_compression(false), Error::OK);
}
SUBCASE("Decompression") {
CHECK_EQ(spgz->start_decompression(false), Error::OK);
}
ERR_PRINT_OFF;
Vector<uint8_t> hello_compressed;
hello_compressed.resize(5);
CHECK_EQ(spgz->get_data(hello_compressed.ptrw(), hello_compressed.size()), Error::ERR_UNAVAILABLE);
ERR_PRINT_ON;
}
} // namespace TestStreamPeerGZIP

View file

@ -28,8 +28,7 @@
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
/**************************************************************************/
#ifndef TEST_TCP_SERVER_H
#define TEST_TCP_SERVER_H
#pragma once
#include "core/io/stream_peer_tcp.h"
#include "core/io/tcp_server.h"
@ -251,5 +250,3 @@ TEST_CASE("[TCPServer] Should disconnect client") {
}
} // namespace TestTCPServer
#endif // TEST_TCP_SERVER_H

View file

@ -28,8 +28,7 @@
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
/**************************************************************************/
#ifndef TEST_UDP_SERVER_H
#define TEST_UDP_SERVER_H
#pragma once
#include "core/io/packet_peer_udp.h"
#include "core/io/udp_server.h"
@ -215,5 +214,3 @@ TEST_CASE("[UDPServer] Should not accept new connections after stop") {
}
} // namespace TestUDPServer
#endif // TEST_UDP_SERVER_H

View file

@ -28,8 +28,7 @@
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
/**************************************************************************/
#ifndef TEST_XML_PARSER_H
#define TEST_XML_PARSER_H
#pragma once
#include "core/io/xml_parser.h"
@ -231,5 +230,3 @@ TEST_CASE("[XMLParser] CDATA") {
CHECK_EQ(parser.get_node_name(), "a");
}
} // namespace TestXMLParser
#endif // TEST_XML_PARSER_H

View file

@ -28,8 +28,7 @@
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
/**************************************************************************/
#ifndef TEST_AABB_H
#define TEST_AABB_H
#pragma once
#include "core/math/aabb.h"
@ -38,8 +37,8 @@
namespace TestAABB {
TEST_CASE("[AABB] Constructor methods") {
const AABB aabb = AABB(Vector3(-1.5, 2, -2.5), Vector3(4, 5, 6));
const AABB aabb_copy = AABB(aabb);
constexpr AABB aabb = AABB(Vector3(-1.5, 2, -2.5), Vector3(4, 5, 6));
constexpr AABB aabb_copy = AABB(aabb);
CHECK_MESSAGE(
aabb == aabb_copy,
@ -53,7 +52,7 @@ TEST_CASE("[AABB] String conversion") {
}
TEST_CASE("[AABB] Basic getters") {
const AABB aabb = AABB(Vector3(-1.5, 2, -2.5), Vector3(4, 5, 6));
constexpr AABB aabb = AABB(Vector3(-1.5, 2, -2.5), Vector3(4, 5, 6));
CHECK_MESSAGE(
aabb.get_position().is_equal_approx(Vector3(-1.5, 2, -2.5)),
"get_position() should return the expected value.");
@ -144,7 +143,7 @@ TEST_CASE("[AABB] Surface getters") {
}
TEST_CASE("[AABB] Intersection") {
const AABB aabb_big = AABB(Vector3(-1.5, 2, -2.5), Vector3(4, 5, 6));
constexpr AABB aabb_big = AABB(Vector3(-1.5, 2, -2.5), Vector3(4, 5, 6));
AABB aabb_small = AABB(Vector3(-1.5, 2, -2.5), Vector3(1, 1, 1));
CHECK_MESSAGE(
@ -230,7 +229,7 @@ TEST_CASE("[AABB] Intersection") {
"intersects_ray() should return false for being outside.");
// Finding ray intersections.
const AABB aabb_simple = AABB(Vector3(), Vector3(1, 1, 1));
constexpr AABB aabb_simple = AABB(Vector3(), Vector3(1, 1, 1));
bool inside = false;
Vector3 intersection_point;
Vector3 intersection_normal;
@ -252,7 +251,7 @@ TEST_CASE("[AABB] Intersection") {
CHECK_MESSAGE(intersection_normal.is_equal_approx(Vector3(0, -1, 0)), "find_intersects_ray() inside intersection normal incorrect.");
// Zero sized AABB.
const AABB aabb_zero = AABB(Vector3(), Vector3(1, 0, 1));
constexpr AABB aabb_zero = AABB(Vector3(), Vector3(1, 0, 1));
aabb_zero.find_intersects_ray(Vector3(0.5, 0, 0.5), Vector3(0, 1, 0), inside, &intersection_point, &intersection_normal);
CHECK_MESSAGE(inside == false, "find_intersects_ray() should return outside on borders of zero sized AABB.");
CHECK_MESSAGE(intersection_point.is_equal_approx(Vector3(0.5, 0, 0.5)), "find_intersects_ray() border intersection point incorrect for zero sized AABB.");
@ -268,7 +267,7 @@ TEST_CASE("[AABB] Intersection") {
}
TEST_CASE("[AABB] Merging") {
const AABB aabb_big = AABB(Vector3(-1.5, 2, -2.5), Vector3(4, 5, 6));
constexpr AABB aabb_big = AABB(Vector3(-1.5, 2, -2.5), Vector3(4, 5, 6));
AABB aabb_small = AABB(Vector3(-1.5, 2, -2.5), Vector3(1, 1, 1));
CHECK_MESSAGE(
@ -287,7 +286,7 @@ TEST_CASE("[AABB] Merging") {
}
TEST_CASE("[AABB] Encloses") {
const AABB aabb_big = AABB(Vector3(-1.5, 2, -2.5), Vector3(4, 5, 6));
constexpr AABB aabb_big = AABB(Vector3(-1.5, 2, -2.5), Vector3(4, 5, 6));
CHECK_MESSAGE(
aabb_big.encloses(aabb_big),
@ -315,7 +314,7 @@ TEST_CASE("[AABB] Encloses") {
}
TEST_CASE("[AABB] Get endpoints") {
const AABB aabb = AABB(Vector3(-1.5, 2, -2.5), Vector3(4, 5, 6));
constexpr AABB aabb = AABB(Vector3(-1.5, 2, -2.5), Vector3(4, 5, 6));
CHECK_MESSAGE(
aabb.get_endpoint(0).is_equal_approx(Vector3(-1.5, 2, -2.5)),
"The endpoint at index 0 should match the expected value.");
@ -352,7 +351,7 @@ TEST_CASE("[AABB] Get endpoints") {
}
TEST_CASE("[AABB] Get longest/shortest axis") {
const AABB aabb = AABB(Vector3(-1.5, 2, -2.5), Vector3(4, 5, 6));
constexpr AABB aabb = AABB(Vector3(-1.5, 2, -2.5), Vector3(4, 5, 6));
CHECK_MESSAGE(
aabb.get_longest_axis() == Vector3(0, 0, 1),
"get_longest_axis() should return the expected value.");
@ -375,7 +374,7 @@ TEST_CASE("[AABB] Get longest/shortest axis") {
}
TEST_CASE("[AABB] Get support") {
const AABB aabb = AABB(Vector3(-1.5, 2, -2.5), Vector3(4, 5, 6));
constexpr AABB aabb = AABB(Vector3(-1.5, 2, -2.5), Vector3(4, 5, 6));
CHECK_MESSAGE(
aabb.get_support(Vector3(1, 0, 0)) == Vector3(2.5, 2, -2.5),
"get_support() should return the expected value.");
@ -397,7 +396,7 @@ TEST_CASE("[AABB] Get support") {
}
TEST_CASE("[AABB] Grow") {
const AABB aabb = AABB(Vector3(-1.5, 2, -2.5), Vector3(4, 5, 6));
constexpr AABB aabb = AABB(Vector3(-1.5, 2, -2.5), Vector3(4, 5, 6));
CHECK_MESSAGE(
aabb.grow(0.25).is_equal_approx(AABB(Vector3(-1.75, 1.75, -2.75), Vector3(4.5, 5.5, 6.5))),
"grow() with positive value should return the expected AABB.");
@ -410,7 +409,7 @@ TEST_CASE("[AABB] Grow") {
}
TEST_CASE("[AABB] Has point") {
const AABB aabb = AABB(Vector3(-1.5, 2, -2.5), Vector3(4, 5, 6));
constexpr AABB aabb = AABB(Vector3(-1.5, 2, -2.5), Vector3(4, 5, 6));
CHECK_MESSAGE(
aabb.has_point(Vector3(-1, 3, 0)),
"has_point() with contained point should return the expected value.");
@ -442,7 +441,7 @@ TEST_CASE("[AABB] Has point") {
}
TEST_CASE("[AABB] Expanding") {
const AABB aabb = AABB(Vector3(-1.5, 2, -2.5), Vector3(4, 5, 6));
constexpr AABB aabb = AABB(Vector3(-1.5, 2, -2.5), Vector3(4, 5, 6));
CHECK_MESSAGE(
aabb.expand(Vector3(-1, 3, 0)).is_equal_approx(aabb),
"expand() with contained point should return the expected AABB.");
@ -461,8 +460,8 @@ TEST_CASE("[AABB] Expanding") {
}
TEST_CASE("[AABB] Finite number checks") {
const Vector3 x(0, 1, 2);
const Vector3 infinite(NAN, NAN, NAN);
constexpr Vector3 x(0, 1, 2);
constexpr Vector3 infinite(Math::NaN, Math::NaN, Math::NaN);
CHECK_MESSAGE(
AABB(x, x).is_finite(),
@ -481,5 +480,3 @@ TEST_CASE("[AABB] Finite number checks") {
}
} // namespace TestAABB
#endif // TEST_AABB_H

View file

@ -28,8 +28,7 @@
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
/**************************************************************************/
#ifndef TEST_ASTAR_H
#define TEST_ASTAR_H
#pragma once
#include "core/math/a_star.h"
@ -215,7 +214,7 @@ TEST_CASE("[AStar3D] Add/Remove") {
TEST_CASE("[Stress][AStar3D] Find paths") {
// Random stress tests with Floyd-Warshall.
const int N = 30;
constexpr int N = 30;
Math::seed(0);
for (int test = 0; test < 1000; test++) {
@ -281,7 +280,7 @@ TEST_CASE("[Stress][AStar3D] Find paths") {
float d[N][N];
for (int u = 0; u < N; u++) {
for (int v = 0; v < N; v++) {
d[u][v] = (u == v || adj[u][v]) ? p[u].distance_to(p[v]) : INFINITY;
d[u][v] = (u == v || adj[u][v]) ? p[u].distance_to(p[v]) : Math::INF;
}
}
for (int w = 0; w < N; w++) {
@ -358,5 +357,3 @@ TEST_CASE("[Stress][AStar3D] Find paths") {
}
}
} // namespace TestAStar
#endif // TEST_ASTAR_H

View file

@ -28,8 +28,7 @@
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
/**************************************************************************/
#ifndef TEST_BASIS_H
#define TEST_BASIS_H
#pragma once
#include "core/math/basis.h"
#include "core/math/random_number_generator.h"
@ -39,11 +38,11 @@
namespace TestBasis {
Vector3 deg_to_rad(const Vector3 &p_rotation) {
return p_rotation / 180.0 * Math_PI;
return p_rotation / 180.0 * Math::PI;
}
Vector3 rad2deg(const Vector3 &p_rotation) {
return p_rotation / Math_PI * 180.0;
return p_rotation / Math::PI * 180.0;
}
String get_rot_order_name(EulerOrder ro) {
@ -219,7 +218,7 @@ TEST_CASE("[Stress][Basis] Euler conversions") {
TEST_CASE("[Basis] Set axis angle") {
Vector3 axis;
real_t angle;
real_t pi = (real_t)Math_PI;
real_t pi = (real_t)Math::PI;
// Testing the singularity when the angle is 0°.
Basis identity(1, 0, 0, 0, 1, 0, 0, 0, 1);
@ -270,8 +269,8 @@ TEST_CASE("[Basis] Set axis angle") {
}
TEST_CASE("[Basis] Finite number checks") {
const Vector3 x(0, 1, 2);
const Vector3 infinite(NAN, NAN, NAN);
constexpr Vector3 x(0, 1, 2);
constexpr Vector3 infinite(Math::NaN, Math::NaN, Math::NaN);
CHECK_MESSAGE(
Basis(x, x, x).is_finite(),
@ -328,7 +327,7 @@ TEST_CASE("[Basis] Is conformal checks") {
"Basis with non-uniform scale should not be conformal.");
CHECK_FALSE_MESSAGE(
Basis(Vector3(Math_SQRT12, Math_SQRT12, 0), Vector3(0, 1, 0), Vector3(0, 0, 1)).is_conformal(),
Basis(Vector3(Math::SQRT12, Math::SQRT12, 0), Vector3(0, 1, 0), Vector3(0, 0, 1)).is_conformal(),
"Basis with the X axis skewed 45 degrees should not be conformal.");
CHECK_MESSAGE(
@ -358,7 +357,7 @@ TEST_CASE("[Basis] Is orthogonal checks") {
"Basis with a flip, rotation, and uniform scale should be orthogonal.");
CHECK_FALSE_MESSAGE(
Basis(Vector3(Math_SQRT12, Math_SQRT12, 0), Vector3(0, 1, 0), Vector3(0, 0, 1)).is_orthogonal(),
Basis(Vector3(Math::SQRT12, Math::SQRT12, 0), Vector3(0, 1, 0), Vector3(0, 0, 1)).is_orthogonal(),
"Basis with the X axis skewed 45 degrees should not be orthogonal.");
CHECK_MESSAGE(
@ -388,7 +387,7 @@ TEST_CASE("[Basis] Is orthonormal checks") {
"Basis with a flip, rotation, and uniform scale should not be orthonormal.");
CHECK_FALSE_MESSAGE(
Basis(Vector3(Math_SQRT12, Math_SQRT12, 0), Vector3(0, 1, 0), Vector3(0, 0, 1)).is_orthonormal(),
Basis(Vector3(Math::SQRT12, Math::SQRT12, 0), Vector3(0, 1, 0), Vector3(0, 0, 1)).is_orthonormal(),
"Basis with the X axis skewed 45 degrees should not be orthonormal.");
CHECK_FALSE_MESSAGE(
@ -418,7 +417,7 @@ TEST_CASE("[Basis] Is rotation checks") {
"Basis with a squeeze should not be a rotation.");
CHECK_FALSE_MESSAGE(
Basis(Vector3(Math_SQRT12, Math_SQRT12, 0), Vector3(0, 1, 0), Vector3(0, 0, 1)).is_rotation(),
Basis(Vector3(Math::SQRT12, Math::SQRT12, 0), Vector3(0, 1, 0), Vector3(0, 0, 1)).is_rotation(),
"Basis with the X axis skewed 45 degrees should not be a rotation.");
CHECK_FALSE_MESSAGE(
@ -427,5 +426,3 @@ TEST_CASE("[Basis] Is rotation checks") {
}
} // namespace TestBasis
#endif // TEST_BASIS_H

View file

@ -28,8 +28,7 @@
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
/**************************************************************************/
#ifndef TEST_COLOR_H
#define TEST_COLOR_H
#pragma once
#include "core/math/color.h"
@ -38,7 +37,7 @@
namespace TestColor {
TEST_CASE("[Color] Constructor methods") {
const Color blue_rgba = Color(0.25098, 0.376471, 1, 0.501961);
constexpr Color blue_rgba = Color(0.25098, 0.376471, 1, 0.501961);
const Color blue_html = Color::html("#4060ff80");
const Color blue_hex = Color::hex(0x4060ff80);
const Color blue_hex64 = Color::hex64(0x4040'6060'ffff'8080);
@ -61,7 +60,7 @@ TEST_CASE("[Color] Constructor methods") {
html_invalid.is_equal_approx(Color()),
"Creation with invalid HTML notation should result in a Color with the default values.");
const Color green_rgba = Color(0, 1, 0, 0.25);
constexpr Color green_rgba = Color(0, 1, 0, 0.25);
const Color green_hsva = Color(0, 0, 0).from_hsv(120 / 360.0, 1, 1, 0.25);
CHECK_MESSAGE(
@ -70,8 +69,8 @@ TEST_CASE("[Color] Constructor methods") {
}
TEST_CASE("[Color] Operators") {
const Color blue = Color(0.2, 0.2, 1);
const Color dark_red = Color(0.3, 0.1, 0.1);
constexpr Color blue = Color(0.2, 0.2, 1);
constexpr Color dark_red = Color(0.3, 0.1, 0.1);
// Color components may be negative. Also, the alpha component may be greater than 1.0.
CHECK_MESSAGE(
@ -98,7 +97,7 @@ TEST_CASE("[Color] Operators") {
}
TEST_CASE("[Color] Reading methods") {
const Color dark_blue = Color(0, 0, 0.5, 0.4);
constexpr Color dark_blue = Color(0, 0, 0.5, 0.4);
CHECK_MESSAGE(
dark_blue.get_h() == doctest::Approx(240.0f / 360.0f),
@ -112,8 +111,8 @@ TEST_CASE("[Color] Reading methods") {
}
TEST_CASE("[Color] Conversion methods") {
const Color cyan = Color(0, 1, 1);
const Color cyan_transparent = Color(0, 1, 1, 0);
constexpr Color cyan = Color(0, 1, 1);
constexpr Color cyan_transparent = Color(0, 1, 1, 0);
CHECK_MESSAGE(
cyan.to_html() == "00ffffff",
@ -145,7 +144,7 @@ TEST_CASE("[Color] Conversion methods") {
}
TEST_CASE("[Color] Linear <-> sRGB conversion") {
const Color color = Color(0.35, 0.5, 0.6, 0.7);
constexpr Color color = Color(0.35, 0.5, 0.6, 0.7);
const Color color_linear = color.srgb_to_linear();
const Color color_srgb = color.linear_to_srgb();
CHECK_MESSAGE(
@ -204,13 +203,13 @@ TEST_CASE("[Color] Validation methods") {
}
TEST_CASE("[Color] Manipulation methods") {
const Color blue = Color(0, 0, 1, 0.4);
constexpr Color blue = Color(0, 0, 1, 0.4);
CHECK_MESSAGE(
blue.inverted().is_equal_approx(Color(1, 1, 0, 0.4)),
"Inverted color should have its red, green and blue components inverted.");
const Color purple = Color(0.5, 0.2, 0.5, 0.25);
constexpr Color purple = Color(0.5, 0.2, 0.5, 0.25);
CHECK_MESSAGE(
purple.lightened(0.2).is_equal_approx(Color(0.6, 0.36, 0.6, 0.25)),
@ -219,13 +218,11 @@ TEST_CASE("[Color] Manipulation methods") {
purple.darkened(0.2).is_equal_approx(Color(0.4, 0.16, 0.4, 0.25)),
"Color should be darkened by the expected amount.");
const Color red = Color(1, 0, 0, 0.2);
const Color yellow = Color(1, 1, 0, 0.8);
constexpr Color red = Color(1, 0, 0, 0.2);
constexpr Color yellow = Color(1, 1, 0, 0.8);
CHECK_MESSAGE(
red.lerp(yellow, 0.5).is_equal_approx(Color(1, 0.5, 0, 0.5)),
"Red interpolated with yellow should be orange (with interpolated alpha).");
}
} // namespace TestColor
#endif // TEST_COLOR_H

View file

@ -28,8 +28,7 @@
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
/**************************************************************************/
#ifndef TEST_EXPRESSION_H
#define TEST_EXPRESSION_H
#pragma once
#include "core/math/expression.h"
@ -322,15 +321,11 @@ TEST_CASE("[Expression] Boolean expressions") {
TEST_CASE("[Expression] Expressions with variables") {
Expression expression;
PackedStringArray parameter_names;
parameter_names.push_back("foo");
parameter_names.push_back("bar");
PackedStringArray parameter_names = { "foo", "bar" };
CHECK_MESSAGE(
expression.parse("foo + bar + 50", parameter_names) == OK,
"The expression should parse successfully.");
Array values;
values.push_back(60);
values.push_back(20);
Array values = { 60, 20 };
CHECK_MESSAGE(
int(expression.execute(values)) == 130,
"The expression should return the expected value.");
@ -341,9 +336,7 @@ TEST_CASE("[Expression] Expressions with variables") {
CHECK_MESSAGE(
expression.parse("foo + bar + 50", parameter_names_invalid) == OK,
"The expression should parse successfully.");
Array values_invalid;
values_invalid.push_back(60);
values_invalid.push_back(20);
Array values_invalid = { 60, 20 };
// Invalid parameters will parse successfully but print an error message when executing.
ERR_PRINT_OFF;
CHECK_MESSAGE(
@ -352,31 +345,21 @@ TEST_CASE("[Expression] Expressions with variables") {
ERR_PRINT_ON;
// Mismatched argument count (more values than parameters).
PackedStringArray parameter_names_mismatch;
parameter_names_mismatch.push_back("foo");
parameter_names_mismatch.push_back("bar");
PackedStringArray parameter_names_mismatch = { "foo", "bar" };
CHECK_MESSAGE(
expression.parse("foo + bar + 50", parameter_names_mismatch) == OK,
"The expression should parse successfully.");
Array values_mismatch;
values_mismatch.push_back(60);
values_mismatch.push_back(20);
values_mismatch.push_back(110);
Array values_mismatch = { 60, 20, 110 };
CHECK_MESSAGE(
int(expression.execute(values_mismatch)) == 130,
"The expression should return the expected value.");
// Mismatched argument count (more parameters than values).
PackedStringArray parameter_names_mismatch2;
parameter_names_mismatch2.push_back("foo");
parameter_names_mismatch2.push_back("bar");
parameter_names_mismatch2.push_back("baz");
PackedStringArray parameter_names_mismatch2 = { "foo", "bar", "baz" };
CHECK_MESSAGE(
expression.parse("foo + bar + baz + 50", parameter_names_mismatch2) == OK,
"The expression should parse successfully.");
Array values_mismatch2;
values_mismatch2.push_back(60);
values_mismatch2.push_back(20);
Array values_mismatch2 = { 60, 20 };
// Having more parameters than values will parse successfully but print an
// error message when executing.
ERR_PRINT_OFF;
@ -505,5 +488,3 @@ TEST_CASE("[Expression] Unusual expressions") {
// "`(-9223372036854775807 - 1) / -1` should return the expected result.");
}
} // namespace TestExpression
#endif // TEST_EXPRESSION_H

View file

@ -28,8 +28,7 @@
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
/**************************************************************************/
#ifndef TEST_GEOMETRY_2D_H
#define TEST_GEOMETRY_2D_H
#pragma once
#include "core/math/geometry_2d.h"
@ -164,11 +163,11 @@ TEST_CASE("[Geometry2D] Segment intersection") {
}
TEST_CASE("[Geometry2D] Segment intersection with circle") {
real_t minus_one = -1.0;
real_t zero = 0.0;
real_t one_quarter = 0.25;
real_t three_quarters = 0.75;
real_t one = 1.0;
constexpr real_t minus_one = -1.0;
constexpr real_t zero = 0.0;
constexpr real_t one_quarter = 0.25;
constexpr real_t three_quarters = 0.75;
constexpr real_t one = 1.0;
CHECK_MESSAGE(
Geometry2D::segment_intersects_circle(Vector2(0, 0), Vector2(4, 0), Vector2(0, 0), 1.0) == doctest::Approx(one_quarter),
@ -262,22 +261,25 @@ TEST_CASE("[Geometry2D] Segment intersection with polygon") {
}
TEST_CASE("[Geometry2D] Closest point to segment") {
Vector2 s[] = { Vector2(-4, -4), Vector2(4, 4) };
CHECK(Geometry2D::get_closest_point_to_segment(Vector2(4.1, 4.1), s).is_equal_approx(Vector2(4, 4)));
CHECK(Geometry2D::get_closest_point_to_segment(Vector2(-4.1, -4.1), s).is_equal_approx(Vector2(-4, -4)));
CHECK(Geometry2D::get_closest_point_to_segment(Vector2(-1, 1), s).is_equal_approx(Vector2(0, 0)));
Vector2 a = Vector2(-4, -4);
Vector2 b = Vector2(4, 4);
CHECK(Geometry2D::get_closest_point_to_segment(Vector2(4.1, 4.1), a, b).is_equal_approx(Vector2(4, 4)));
CHECK(Geometry2D::get_closest_point_to_segment(Vector2(-4.1, -4.1), a, b).is_equal_approx(Vector2(-4, -4)));
CHECK(Geometry2D::get_closest_point_to_segment(Vector2(-1, 1), a, b).is_equal_approx(Vector2(0, 0)));
Vector2 t[] = { Vector2(1, -2), Vector2(1, -2) };
a = Vector2(1, -2);
b = Vector2(1, -2);
CHECK_MESSAGE(
Geometry2D::get_closest_point_to_segment(Vector2(-3, 4), t).is_equal_approx(Vector2(1, -2)),
Geometry2D::get_closest_point_to_segment(Vector2(-3, 4), a, b).is_equal_approx(Vector2(1, -2)),
"Line segment is only a single point. This point should be the closest.");
}
TEST_CASE("[Geometry2D] Closest point to uncapped segment") {
Vector2 s[] = { Vector2(-4, -4), Vector2(4, 4) };
CHECK(Geometry2D::get_closest_point_to_segment_uncapped(Vector2(-1, 1), s).is_equal_approx(Vector2(0, 0)));
CHECK(Geometry2D::get_closest_point_to_segment_uncapped(Vector2(-4, -6), s).is_equal_approx(Vector2(-5, -5)));
CHECK(Geometry2D::get_closest_point_to_segment_uncapped(Vector2(4, 6), s).is_equal_approx(Vector2(5, 5)));
constexpr Vector2 a = Vector2(-4, -4);
constexpr Vector2 b = Vector2(4, 4);
CHECK(Geometry2D::get_closest_point_to_segment_uncapped(Vector2(-1, 1), a, b).is_equal_approx(Vector2(0, 0)));
CHECK(Geometry2D::get_closest_point_to_segment_uncapped(Vector2(-4, -6), a, b).is_equal_approx(Vector2(-5, -5)));
CHECK(Geometry2D::get_closest_point_to_segment_uncapped(Vector2(4, 6), a, b).is_equal_approx(Vector2(5, 5)));
}
TEST_CASE("[Geometry2D] Closest points between segments") {
@ -888,5 +890,3 @@ TEST_CASE("[Geometry2D] Bresenham line") {
}
}
} // namespace TestGeometry2D
#endif // TEST_GEOMETRY_2D_H

View file

@ -28,8 +28,7 @@
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
/**************************************************************************/
#ifndef TEST_GEOMETRY_3D_H
#define TEST_GEOMETRY_3D_H
#pragma once
#include "core/math/geometry_3d.h"
#include "tests/test_macros.h"
@ -47,7 +46,7 @@ TEST_CASE("[Geometry3D] Closest Distance Between Segments") {
}
TEST_CASE("[Geometry3D] Build Box Planes") {
const Vector3 extents = Vector3(5, 5, 20);
constexpr Vector3 extents = Vector3(5, 5, 20);
Vector<Plane> box = Geometry3D::build_box_planes(extents);
CHECK(box.size() == 6);
CHECK(extents.x == box[0].d);
@ -130,8 +129,9 @@ TEST_CASE("[Geometry3D] Compute Convex Mesh Points") {
}
TEST_CASE("[Geometry3D] Get Closest Point To Segment") {
Vector3 segment[2] = { Vector3(1, 1, 1), Vector3(5, 5, 5) };
Vector3 output = Geometry3D::get_closest_point_to_segment(Vector3(2, 1, 4), segment);
constexpr Vector3 a = Vector3(1, 1, 1);
constexpr Vector3 b = Vector3(5, 5, 5);
Vector3 output = Geometry3D::get_closest_point_to_segment(Vector3(2, 1, 4), a, b);
CHECK(output.is_equal_approx(Vector3(2.33333, 2.33333, 2.33333)));
}
@ -183,22 +183,19 @@ TEST_CASE("[Geometry3D] Segment Intersects Triangle") {
}
TEST_CASE("[Geometry3D] Triangle and Box Overlap") {
Vector3 good_triangle[3] = { Vector3(3, 2, 3), Vector3(2, 2, 1), Vector3(2, 1, 1) };
constexpr Vector3 good_triangle[3] = { Vector3(3, 2, 3), Vector3(2, 2, 1), Vector3(2, 1, 1) };
CHECK(Geometry3D::triangle_box_overlap(Vector3(0, 0, 0), Vector3(5, 5, 5), good_triangle) == true);
Vector3 bad_triangle[3] = { Vector3(100, 100, 100), Vector3(-100, -100, -100), Vector3(10, 10, 10) };
constexpr Vector3 bad_triangle[3] = { Vector3(100, 100, 100), Vector3(-100, -100, -100), Vector3(10, 10, 10) };
CHECK(Geometry3D::triangle_box_overlap(Vector3(1000, 1000, 1000), Vector3(1, 1, 1), bad_triangle) == false);
}
TEST_CASE("[Geometry3D] Triangle and Sphere Intersect") {
Vector<Vector3> triangle;
triangle.push_back(Vector3(3, 0, 0));
triangle.push_back(Vector3(-3, 0, 0));
triangle.push_back(Vector3(0, 3, 0));
constexpr Vector3 triangle_a = Vector3(3, 0, 0);
constexpr Vector3 triangle_b = Vector3(-3, 0, 0);
constexpr Vector3 triangle_c = Vector3(0, 3, 0);
Vector3 triangle_contact, sphere_contact;
CHECK(Geometry3D::triangle_sphere_intersection_test(&triangle[0], Vector3(0, -1, 0), Vector3(0, 0, 0), 5, triangle_contact, sphere_contact) == true);
CHECK(Geometry3D::triangle_sphere_intersection_test(&triangle[0], Vector3(0, 1, 0), Vector3(0, 0, 0), 5, triangle_contact, sphere_contact) == true);
CHECK(Geometry3D::triangle_sphere_intersection_test(&triangle[0], Vector3(0, 1, 0), Vector3(20, 0, 0), 5, triangle_contact, sphere_contact) == false);
CHECK(Geometry3D::triangle_sphere_intersection_test(triangle_a, triangle_b, triangle_c, Vector3(0, -1, 0), Vector3(0, 0, 0), 5, triangle_contact, sphere_contact) == true);
CHECK(Geometry3D::triangle_sphere_intersection_test(triangle_a, triangle_b, triangle_c, Vector3(0, 1, 0), Vector3(0, 0, 0), 5, triangle_contact, sphere_contact) == true);
CHECK(Geometry3D::triangle_sphere_intersection_test(triangle_a, triangle_b, triangle_c, Vector3(0, 1, 0), Vector3(20, 0, 0), 5, triangle_contact, sphere_contact) == false);
}
} // namespace TestGeometry3D
#endif // TEST_GEOMETRY_3D_H

View file

@ -28,8 +28,7 @@
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
/**************************************************************************/
#ifndef TEST_MATH_FUNCS_H
#define TEST_MATH_FUNCS_H
#pragma once
#include "tests/test_macros.h"
@ -47,15 +46,15 @@ TEST_CASE("[Math] C++ macros") {
// `max` is lower than `min`.
CHECK(CLAMP(620, 600, 50) == 50);
CHECK(ABS(-5) == 5);
CHECK(ABS(0) == 0);
CHECK(ABS(5) == 5);
CHECK(Math::abs(-5) == 5);
CHECK(Math::abs(0) == 0);
CHECK(Math::abs(5) == 5);
CHECK(SIGN(-5) == -1.0);
CHECK(SIGN(0) == 0.0);
CHECK(SIGN(5) == 1.0);
// Check that SIGN(NAN) returns 0.0.
CHECK(SIGN(NAN) == 0.0);
// Check that SIGN(Math::NaN) returns 0.0.
CHECK(SIGN(Math::NaN) == 0.0);
}
TEST_CASE("[Math] Power of two functions") {
@ -190,7 +189,7 @@ TEST_CASE_TEMPLATE("[Math] asin/acos/atan", T, float, double) {
CHECK(Math::acos((T)0.5) == doctest::Approx((T)1.0471975512));
CHECK(Math::acos((T)1.0) == doctest::Approx((T)0.0));
CHECK(Math::acos((T)2.0) == doctest::Approx((T)0.0));
CHECK(Math::acos((T)-2.0) == doctest::Approx((T)Math_PI));
CHECK(Math::acos((T)-2.0) == doctest::Approx((T)Math::PI));
CHECK(Math::atan((T)-0.1) == doctest::Approx((T)-0.0996686525));
CHECK(Math::atan((T)0.1) == doctest::Approx((T)0.0996686525));
@ -292,10 +291,10 @@ TEST_CASE_TEMPLATE("[Math] pow/log/log2/exp/sqrt", T, float, double) {
TEST_CASE_TEMPLATE("[Math] is_nan/is_inf", T, float, double) {
CHECK(!Math::is_nan((T)0.0));
CHECK(Math::is_nan((T)NAN));
CHECK(Math::is_nan((T)Math::NaN));
CHECK(!Math::is_inf((T)0.0));
CHECK(Math::is_inf((T)INFINITY));
CHECK(Math::is_inf((T)Math::INF));
}
TEST_CASE_TEMPLATE("[Math] linear_to_db", T, float, double) {
@ -388,15 +387,15 @@ TEST_CASE_TEMPLATE("[Math] remap", T, float, double) {
TEST_CASE_TEMPLATE("[Math] angle_difference", T, float, double) {
// Loops around, should return 0.0.
CHECK(Math::angle_difference((T)0.0, (T)Math_TAU) == doctest::Approx((T)0.0));
CHECK(Math::angle_difference((T)Math_PI, (T)-Math_PI) == doctest::Approx((T)0.0));
CHECK(Math::angle_difference((T)0.0, (T)Math_TAU * (T)4.0) == doctest::Approx((T)0.0));
CHECK(Math::angle_difference((T)0.0, (T)Math::TAU) == doctest::Approx((T)0.0));
CHECK(Math::angle_difference((T)Math::PI, (T)-Math::PI) == doctest::Approx((T)0.0));
CHECK(Math::angle_difference((T)0.0, (T)Math::TAU * (T)4.0) == doctest::Approx((T)0.0));
// Rotation is clockwise, so it should return -PI.
CHECK(Math::angle_difference((T)0.0, (T)Math_PI) == doctest::Approx((T)-Math_PI));
CHECK(Math::angle_difference((T)0.0, (T)-Math_PI) == doctest::Approx((T)Math_PI));
CHECK(Math::angle_difference((T)Math_PI, (T)0.0) == doctest::Approx((T)Math_PI));
CHECK(Math::angle_difference((T)-Math_PI, (T)0.0) == doctest::Approx((T)-Math_PI));
CHECK(Math::angle_difference((T)0.0, (T)Math::PI) == doctest::Approx((T)-Math::PI));
CHECK(Math::angle_difference((T)0.0, (T)-Math::PI) == doctest::Approx((T)Math::PI));
CHECK(Math::angle_difference((T)Math::PI, (T)0.0) == doctest::Approx((T)Math::PI));
CHECK(Math::angle_difference((T)-Math::PI, (T)0.0) == doctest::Approx((T)-Math::PI));
CHECK(Math::angle_difference((T)0.0, (T)3.0) == doctest::Approx((T)3.0));
CHECK(Math::angle_difference((T)1.0, (T)-2.0) == doctest::Approx((T)-3.0));
@ -407,23 +406,23 @@ TEST_CASE_TEMPLATE("[Math] angle_difference", T, float, double) {
TEST_CASE_TEMPLATE("[Math] lerp_angle", T, float, double) {
// Counter-clockwise rotation.
CHECK(Math::lerp_angle((T)0.24 * Math_TAU, 0.75 * Math_TAU, 0.5) == doctest::Approx((T)-0.005 * Math_TAU));
CHECK(Math::lerp_angle((T)0.24 * Math::TAU, 0.75 * Math::TAU, 0.5) == doctest::Approx((T)-0.005 * Math::TAU));
// Counter-clockwise rotation.
CHECK(Math::lerp_angle((T)0.25 * Math_TAU, 0.75 * Math_TAU, 0.5) == doctest::Approx((T)0.0));
CHECK(Math::lerp_angle((T)0.25 * Math::TAU, 0.75 * Math::TAU, 0.5) == doctest::Approx((T)0.0));
// Clockwise rotation.
CHECK(Math::lerp_angle((T)0.26 * Math_TAU, 0.75 * Math_TAU, 0.5) == doctest::Approx((T)0.505 * Math_TAU));
CHECK(Math::lerp_angle((T)0.26 * Math::TAU, 0.75 * Math::TAU, 0.5) == doctest::Approx((T)0.505 * Math::TAU));
CHECK(Math::lerp_angle((T)-0.25 * Math_TAU, 1.25 * Math_TAU, 0.5) == doctest::Approx((T)-0.5 * Math_TAU));
CHECK(Math::lerp_angle((T)0.72 * Math_TAU, 1.44 * Math_TAU, 0.96) == doctest::Approx((T)0.4512 * Math_TAU));
CHECK(Math::lerp_angle((T)0.72 * Math_TAU, 1.44 * Math_TAU, 1.04) == doctest::Approx((T)0.4288 * Math_TAU));
CHECK(Math::lerp_angle((T)-0.25 * Math::TAU, 1.25 * Math::TAU, 0.5) == doctest::Approx((T)-0.5 * Math::TAU));
CHECK(Math::lerp_angle((T)0.72 * Math::TAU, 1.44 * Math::TAU, 0.96) == doctest::Approx((T)0.4512 * Math::TAU));
CHECK(Math::lerp_angle((T)0.72 * Math::TAU, 1.44 * Math::TAU, 1.04) == doctest::Approx((T)0.4288 * Math::TAU));
// Initial and final angles are effectively identical, so the value returned
// should always be the same regardless of the `weight` parameter.
CHECK(Math::lerp_angle((T)-4 * Math_TAU, 4 * Math_TAU, -1.0) == doctest::Approx((T)-4.0 * Math_TAU));
CHECK(Math::lerp_angle((T)-4 * Math_TAU, 4 * Math_TAU, 0.0) == doctest::Approx((T)-4.0 * Math_TAU));
CHECK(Math::lerp_angle((T)-4 * Math_TAU, 4 * Math_TAU, 0.5) == doctest::Approx((T)-4.0 * Math_TAU));
CHECK(Math::lerp_angle((T)-4 * Math_TAU, 4 * Math_TAU, 1.0) == doctest::Approx((T)-4.0 * Math_TAU));
CHECK(Math::lerp_angle((T)-4 * Math_TAU, 4 * Math_TAU, 500.0) == doctest::Approx((T)-4.0 * Math_TAU));
CHECK(Math::lerp_angle((T)-4 * Math::TAU, 4 * Math::TAU, -1.0) == doctest::Approx((T)-4.0 * Math::TAU));
CHECK(Math::lerp_angle((T)-4 * Math::TAU, 4 * Math::TAU, 0.0) == doctest::Approx((T)-4.0 * Math::TAU));
CHECK(Math::lerp_angle((T)-4 * Math::TAU, 4 * Math::TAU, 0.5) == doctest::Approx((T)-4.0 * Math::TAU));
CHECK(Math::lerp_angle((T)-4 * Math::TAU, 4 * Math::TAU, 1.0) == doctest::Approx((T)-4.0 * Math::TAU));
CHECK(Math::lerp_angle((T)-4 * Math::TAU, 4 * Math::TAU, 500.0) == doctest::Approx((T)-4.0 * Math::TAU));
}
TEST_CASE_TEMPLATE("[Math] move_toward", T, float, double) {
@ -437,16 +436,16 @@ TEST_CASE_TEMPLATE("[Math] move_toward", T, float, double) {
TEST_CASE_TEMPLATE("[Math] rotate_toward", T, float, double) {
// Rotate toward.
CHECK(Math::rotate_toward((T)0.0, (T)Math_PI * (T)0.75, (T)1.5) == doctest::Approx((T)1.5));
CHECK(Math::rotate_toward((T)0.0, (T)Math::PI * (T)0.75, (T)1.5) == doctest::Approx((T)1.5));
CHECK(Math::rotate_toward((T)-2.0, (T)1.0, (T)2.5) == doctest::Approx((T)0.5));
CHECK(Math::rotate_toward((T)-2.0, (T)Math_PI, (T)Math_PI) == doctest::Approx((T)-Math_PI));
CHECK(Math::rotate_toward((T)1.0, (T)Math_PI, (T)20.0) == doctest::Approx((T)Math_PI));
CHECK(Math::rotate_toward((T)-2.0, (T)Math::PI, (T)Math::PI) == doctest::Approx((T)-Math::PI));
CHECK(Math::rotate_toward((T)1.0, (T)Math::PI, (T)20.0) == doctest::Approx((T)Math::PI));
// Rotate away.
CHECK(Math::rotate_toward((T)0.0, (T)0.0, (T)-1.5) == doctest::Approx((T)-1.5));
CHECK(Math::rotate_toward((T)0.0, (T)0.0, (T)-Math_PI) == doctest::Approx((T)-Math_PI));
CHECK(Math::rotate_toward((T)3.0, (T)Math_PI, (T)-Math_PI) == doctest::Approx((T)0.0));
CHECK(Math::rotate_toward((T)2.0, (T)Math_PI, (T)-1.5) == doctest::Approx((T)0.5));
CHECK(Math::rotate_toward((T)0.0, (T)0.0, (T)-Math::PI) == doctest::Approx((T)-Math::PI));
CHECK(Math::rotate_toward((T)3.0, (T)Math::PI, (T)-Math::PI) == doctest::Approx((T)0.0));
CHECK(Math::rotate_toward((T)2.0, (T)Math::PI, (T)-1.5) == doctest::Approx((T)0.5));
CHECK(Math::rotate_toward((T)1.0, (T)2.0, (T)-0.5) == doctest::Approx((T)0.5));
CHECK(Math::rotate_toward((T)2.5, (T)2.0, (T)-0.5) == doctest::Approx((T)3.0));
CHECK(Math::rotate_toward((T)-1.0, (T)1.0, (T)-1.0) == doctest::Approx((T)-2.0));
@ -586,10 +585,10 @@ TEST_CASE_TEMPLATE("[Math] pingpong", T, float, double) {
}
TEST_CASE_TEMPLATE("[Math] deg_to_rad/rad_to_deg", T, float, double) {
CHECK(Math::deg_to_rad((T)180.0) == doctest::Approx((T)Math_PI));
CHECK(Math::deg_to_rad((T)180.0) == doctest::Approx((T)Math::PI));
CHECK(Math::deg_to_rad((T)-27.0) == doctest::Approx((T)-0.471239));
CHECK(Math::rad_to_deg((T)Math_PI) == doctest::Approx((T)180.0));
CHECK(Math::rad_to_deg((T)Math::PI) == doctest::Approx((T)180.0));
CHECK(Math::rad_to_deg((T)-1.5) == doctest::Approx((T)-85.94366927));
}
@ -608,11 +607,11 @@ TEST_CASE_TEMPLATE("[Math] cubic_interpolate", T, float, double) {
}
TEST_CASE_TEMPLATE("[Math] cubic_interpolate_angle", T, float, double) {
CHECK(Math::cubic_interpolate_angle((T)(Math_PI * (1.0 / 6.0)), (T)(Math_PI * (5.0 / 6.0)), (T)0.0, (T)Math_PI, (T)0.0) == doctest::Approx((T)Math_PI * (1.0 / 6.0)));
CHECK(Math::cubic_interpolate_angle((T)(Math_PI * (1.0 / 6.0)), (T)(Math_PI * (5.0 / 6.0)), (T)0.0, (T)Math_PI, (T)0.25) == doctest::Approx((T)0.973566));
CHECK(Math::cubic_interpolate_angle((T)(Math_PI * (1.0 / 6.0)), (T)(Math_PI * (5.0 / 6.0)), (T)0.0, (T)Math_PI, (T)0.5) == doctest::Approx((T)Math_PI / 2.0));
CHECK(Math::cubic_interpolate_angle((T)(Math_PI * (1.0 / 6.0)), (T)(Math_PI * (5.0 / 6.0)), (T)0.0, (T)Math_PI, (T)0.75) == doctest::Approx((T)2.16803));
CHECK(Math::cubic_interpolate_angle((T)(Math_PI * (1.0 / 6.0)), (T)(Math_PI * (5.0 / 6.0)), (T)0.0, (T)Math_PI, (T)1.0) == doctest::Approx((T)Math_PI * (5.0 / 6.0)));
CHECK(Math::cubic_interpolate_angle((T)(Math::PI * (1.0 / 6.0)), (T)(Math::PI * (5.0 / 6.0)), (T)0.0, (T)Math::PI, (T)0.0) == doctest::Approx((T)Math::PI * (1.0 / 6.0)));
CHECK(Math::cubic_interpolate_angle((T)(Math::PI * (1.0 / 6.0)), (T)(Math::PI * (5.0 / 6.0)), (T)0.0, (T)Math::PI, (T)0.25) == doctest::Approx((T)0.973566));
CHECK(Math::cubic_interpolate_angle((T)(Math::PI * (1.0 / 6.0)), (T)(Math::PI * (5.0 / 6.0)), (T)0.0, (T)Math::PI, (T)0.5) == doctest::Approx((T)Math::PI / 2.0));
CHECK(Math::cubic_interpolate_angle((T)(Math::PI * (1.0 / 6.0)), (T)(Math::PI * (5.0 / 6.0)), (T)0.0, (T)Math::PI, (T)0.75) == doctest::Approx((T)2.16803));
CHECK(Math::cubic_interpolate_angle((T)(Math::PI * (1.0 / 6.0)), (T)(Math::PI * (5.0 / 6.0)), (T)0.0, (T)Math::PI, (T)1.0) == doctest::Approx((T)Math::PI * (5.0 / 6.0)));
}
TEST_CASE_TEMPLATE("[Math] cubic_interpolate_in_time", T, float, double) {
@ -624,11 +623,11 @@ TEST_CASE_TEMPLATE("[Math] cubic_interpolate_in_time", T, float, double) {
}
TEST_CASE_TEMPLATE("[Math] cubic_interpolate_angle_in_time", T, float, double) {
CHECK(Math::cubic_interpolate_angle_in_time((T)(Math_PI * (1.0 / 6.0)), (T)(Math_PI * (5.0 / 6.0)), (T)0.0, (T)Math_PI, (T)0.0, (T)0.5, (T)0.0, (T)1.0) == doctest::Approx((T)0.0));
CHECK(Math::cubic_interpolate_angle_in_time((T)(Math_PI * (1.0 / 6.0)), (T)(Math_PI * (5.0 / 6.0)), (T)0.0, (T)Math_PI, (T)0.25, (T)0.5, (T)0.0, (T)1.0) == doctest::Approx((T)0.494964));
CHECK(Math::cubic_interpolate_angle_in_time((T)(Math_PI * (1.0 / 6.0)), (T)(Math_PI * (5.0 / 6.0)), (T)0.0, (T)Math_PI, (T)0.5, (T)0.5, (T)0.0, (T)1.0) == doctest::Approx((T)1.27627));
CHECK(Math::cubic_interpolate_angle_in_time((T)(Math_PI * (1.0 / 6.0)), (T)(Math_PI * (5.0 / 6.0)), (T)0.0, (T)Math_PI, (T)0.75, (T)0.5, (T)0.0, (T)1.0) == doctest::Approx((T)2.07394));
CHECK(Math::cubic_interpolate_angle_in_time((T)(Math_PI * (1.0 / 6.0)), (T)(Math_PI * (5.0 / 6.0)), (T)0.0, (T)Math_PI, (T)1.0, (T)0.5, (T)0.0, (T)1.0) == doctest::Approx((T)Math_PI * (5.0 / 6.0)));
CHECK(Math::cubic_interpolate_angle_in_time((T)(Math::PI * (1.0 / 6.0)), (T)(Math::PI * (5.0 / 6.0)), (T)0.0, (T)Math::PI, (T)0.0, (T)0.5, (T)0.0, (T)1.0) == doctest::Approx((T)0.0));
CHECK(Math::cubic_interpolate_angle_in_time((T)(Math::PI * (1.0 / 6.0)), (T)(Math::PI * (5.0 / 6.0)), (T)0.0, (T)Math::PI, (T)0.25, (T)0.5, (T)0.0, (T)1.0) == doctest::Approx((T)0.494964));
CHECK(Math::cubic_interpolate_angle_in_time((T)(Math::PI * (1.0 / 6.0)), (T)(Math::PI * (5.0 / 6.0)), (T)0.0, (T)Math::PI, (T)0.5, (T)0.5, (T)0.0, (T)1.0) == doctest::Approx((T)1.27627));
CHECK(Math::cubic_interpolate_angle_in_time((T)(Math::PI * (1.0 / 6.0)), (T)(Math::PI * (5.0 / 6.0)), (T)0.0, (T)Math::PI, (T)0.75, (T)0.5, (T)0.0, (T)1.0) == doctest::Approx((T)2.07394));
CHECK(Math::cubic_interpolate_angle_in_time((T)(Math::PI * (1.0 / 6.0)), (T)(Math::PI * (5.0 / 6.0)), (T)0.0, (T)Math::PI, (T)1.0, (T)0.5, (T)0.0, (T)1.0) == doctest::Approx((T)Math::PI * (5.0 / 6.0)));
}
TEST_CASE_TEMPLATE("[Math] bezier_interpolate", T, float, double) {
@ -640,5 +639,3 @@ TEST_CASE_TEMPLATE("[Math] bezier_interpolate", T, float, double) {
}
} // namespace TestMath
#endif // TEST_MATH_FUNCS_H

View file

@ -28,8 +28,7 @@
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
/**************************************************************************/
#ifndef TEST_PLANE_H
#define TEST_PLANE_H
#pragma once
#include "core/math/plane.h"
@ -40,22 +39,22 @@ namespace TestPlane {
// Plane
TEST_CASE("[Plane] Constructor methods") {
const Plane plane = Plane(32, 22, 16, 3);
const Plane plane_vector = Plane(Vector3(32, 22, 16), 3);
const Plane plane_copy_plane = Plane(plane);
constexpr Plane plane = Plane(32, 22, 16, 3);
constexpr Plane plane_vector = Plane(Vector3(32, 22, 16), 3);
constexpr Plane plane_copy_plane = Plane(plane);
CHECK_MESSAGE(
static_assert(
plane == plane_vector,
"Planes created with same values but different methods should be equal.");
CHECK_MESSAGE(
static_assert(
plane == plane_copy_plane,
"Planes created with same values but different methods should be equal.");
}
TEST_CASE("[Plane] Basic getters") {
const Plane plane = Plane(32, 22, 16, 3);
const Plane plane_normalized = Plane(32.0 / 42, 22.0 / 42, 16.0 / 42, 3.0 / 42);
constexpr Plane plane = Plane(32, 22, 16, 3);
constexpr Plane plane_normalized = Plane(32.0 / 42, 22.0 / 42, 16.0 / 42, 3.0 / 42);
CHECK_MESSAGE(
plane.get_normal().is_equal_approx(Vector3(32, 22, 16)),
@ -83,8 +82,8 @@ TEST_CASE("[Plane] Basic setters") {
}
TEST_CASE("[Plane] Plane-point operations") {
const Plane plane = Plane(32, 22, 16, 3);
const Plane y_facing_plane = Plane(0, 1, 0, 4);
constexpr Plane plane = Plane(32, 22, 16, 3);
constexpr Plane y_facing_plane = Plane(0, 1, 0, 4);
CHECK_MESSAGE(
plane.get_center().is_equal_approx(Vector3(32 * 3, 22 * 3, 16 * 3)),
@ -102,16 +101,16 @@ TEST_CASE("[Plane] Plane-point operations") {
}
TEST_CASE("[Plane] Has point") {
const Plane x_facing_plane = Plane(1, 0, 0, 0);
const Plane y_facing_plane = Plane(0, 1, 0, 0);
const Plane z_facing_plane = Plane(0, 0, 1, 0);
constexpr Plane x_facing_plane = Plane(1, 0, 0, 0);
constexpr Plane y_facing_plane = Plane(0, 1, 0, 0);
constexpr Plane z_facing_plane = Plane(0, 0, 1, 0);
const Vector3 x_axis_point = Vector3(10, 0, 0);
const Vector3 y_axis_point = Vector3(0, 10, 0);
const Vector3 z_axis_point = Vector3(0, 0, 10);
constexpr Vector3 x_axis_point = Vector3(10, 0, 0);
constexpr Vector3 y_axis_point = Vector3(0, 10, 0);
constexpr Vector3 z_axis_point = Vector3(0, 0, 10);
const Plane x_facing_plane_with_d_offset = Plane(1, 0, 0, 1);
const Vector3 y_axis_point_with_d_offset = Vector3(1, 10, 0);
constexpr Plane x_facing_plane_with_d_offset = Plane(1, 0, 0, 1);
constexpr Vector3 y_axis_point_with_d_offset = Vector3(1, 10, 0);
CHECK_MESSAGE(
x_facing_plane.has_point(y_axis_point),
@ -140,9 +139,9 @@ TEST_CASE("[Plane] Has point") {
}
TEST_CASE("[Plane] Intersection") {
const Plane x_facing_plane = Plane(1, 0, 0, 1);
const Plane y_facing_plane = Plane(0, 1, 0, 2);
const Plane z_facing_plane = Plane(0, 0, 1, 3);
constexpr Plane x_facing_plane = Plane(1, 0, 0, 1);
constexpr Plane y_facing_plane = Plane(0, 1, 0, 2);
constexpr Plane z_facing_plane = Plane(0, 0, 1, 3);
Vector3 vec_out;
@ -169,10 +168,10 @@ TEST_CASE("[Plane] Intersection") {
}
TEST_CASE("[Plane] Finite number checks") {
const Vector3 x(0, 1, 2);
const Vector3 infinite_vec(NAN, NAN, NAN);
const real_t y = 0;
const real_t infinite_y = NAN;
constexpr Vector3 x(0, 1, 2);
constexpr Vector3 infinite_vec(Math::NaN, Math::NaN, Math::NaN);
constexpr real_t y = 0;
constexpr real_t infinite_y = Math::NaN;
CHECK_MESSAGE(
Plane(x, y).is_finite(),
@ -191,5 +190,3 @@ TEST_CASE("[Plane] Finite number checks") {
}
} // namespace TestPlane
#endif // TEST_PLANE_H

View file

@ -28,8 +28,7 @@
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
/**************************************************************************/
#ifndef TEST_PROJECTION_H
#define TEST_PROJECTION_H
#pragma once
#include "core/math/aabb.h"
#include "core/math/plane.h"
@ -183,12 +182,6 @@ TEST_CASE("[Projection] Vector transformation") {
Vector4(4, 7, 11, 15),
Vector4(4, 8, 12, 16));
Projection inverse(
Vector4(-4.0 / 12, 0, 1, -8.0 / 12),
Vector4(8.0 / 12, -1, -1, 16.0 / 12),
Vector4(-20.0 / 12, 2, -1, 5.0 / 12),
Vector4(1, -1, 1, -0.75));
Vector4 vec4(1, 2, 3, 4);
CHECK(proj.xform(vec4).is_equal_approx(Vector4(33, 70, 112, 152)));
CHECK(proj.xform_inv(vec4).is_equal_approx(Vector4(90, 107, 111, 120)));
@ -449,6 +442,78 @@ TEST_CASE("[Projection] Perspective values extraction") {
CHECK(zfar == doctest::Approx(50));
CHECK(aspect == doctest::Approx(0.5));
CHECK(fov == doctest::Approx(90));
persp.set_perspective(38, 1.3, 0.2, 8, false);
znear = persp.get_z_near();
zfar = persp.get_z_far();
aspect = persp.get_aspect();
fov = persp.get_fov();
CHECK(znear == doctest::Approx(0.2));
CHECK(zfar == doctest::Approx(8));
CHECK(aspect == doctest::Approx(1.3));
CHECK(fov == doctest::Approx(Projection::get_fovy(38, 1.3)));
persp.set_perspective(47, 2.5, 0.9, 14, true);
znear = persp.get_z_near();
zfar = persp.get_z_far();
aspect = persp.get_aspect();
fov = persp.get_fov();
CHECK(znear == doctest::Approx(0.9));
CHECK(zfar == doctest::Approx(14));
CHECK(aspect == doctest::Approx(2.5));
CHECK(fov == doctest::Approx(47));
}
TEST_CASE("[Projection] Frustum values extraction") {
Projection frustum = Projection::create_frustum_aspect(1.0, 4.0 / 3.0, Vector2(0.5, -0.25), 0.5, 50, true);
double znear = frustum.get_z_near();
double zfar = frustum.get_z_far();
double aspect = frustum.get_aspect();
double fov = frustum.get_fov();
CHECK(znear == doctest::Approx(0.5));
CHECK(zfar == doctest::Approx(50));
CHECK(aspect == doctest::Approx(4.0 / 3.0));
CHECK(fov == doctest::Approx(Math::rad_to_deg(Math::atan(2.0))));
frustum.set_frustum(2.0, 1.5, Vector2(-0.5, 2), 2, 12, false);
znear = frustum.get_z_near();
zfar = frustum.get_z_far();
aspect = frustum.get_aspect();
fov = frustum.get_fov();
CHECK(znear == doctest::Approx(2));
CHECK(zfar == doctest::Approx(12));
CHECK(aspect == doctest::Approx(1.5));
CHECK(fov == doctest::Approx(Math::rad_to_deg(Math::atan(1.0) + Math::atan(0.5))));
}
TEST_CASE("[Projection] Orthographic values extraction") {
Projection ortho = Projection::create_orthogonal(-2, 3, -0.5, 1.5, 1.2, 15);
double znear = ortho.get_z_near();
double zfar = ortho.get_z_far();
double aspect = ortho.get_aspect();
CHECK(znear == doctest::Approx(1.2));
CHECK(zfar == doctest::Approx(15));
CHECK(aspect == doctest::Approx(2.5));
ortho.set_orthogonal(-7, 2, 2.5, 5.5, 0.5, 6);
znear = ortho.get_z_near();
zfar = ortho.get_z_far();
aspect = ortho.get_aspect();
CHECK(znear == doctest::Approx(0.5));
CHECK(zfar == doctest::Approx(6));
CHECK(aspect == doctest::Approx(3));
}
TEST_CASE("[Projection] Orthographic check") {
@ -487,16 +552,48 @@ TEST_CASE("[Projection] Planes extraction") {
CHECK(plane_array[Projection::PLANE_BOTTOM].normalized().is_equal_approx(planes[Projection::PLANE_BOTTOM].normalized()));
}
TEST_CASE("[Projection] Half extents") {
TEST_CASE("[Projection] Perspective Half extents") {
constexpr real_t sqrt3 = 1.7320508;
Projection persp = Projection::create_perspective(90, 1, 1, 40, false);
Vector2 ne = persp.get_viewport_half_extents();
Vector2 fe = persp.get_far_plane_half_extents();
CHECK(ne.is_equal_approx(Vector2(1, 1) * 1));
CHECK(fe.is_equal_approx(Vector2(1, 1) * 40));
persp.set_perspective(120, sqrt3, 0.8, 10, true);
ne = persp.get_viewport_half_extents();
fe = persp.get_far_plane_half_extents();
CHECK(ne.is_equal_approx(Vector2(sqrt3, 1.0) * 0.8));
CHECK(fe.is_equal_approx(Vector2(sqrt3, 1.0) * 10));
persp.set_perspective(60, 1.2, 0.5, 15, false);
ne = persp.get_viewport_half_extents();
fe = persp.get_far_plane_half_extents();
CHECK(ne.is_equal_approx(Vector2(sqrt3 / 3 * 1.2, sqrt3 / 3) * 0.5));
CHECK(fe.is_equal_approx(Vector2(sqrt3 / 3 * 1.2, sqrt3 / 3) * 15));
}
TEST_CASE("[Projection] Orthographic Half extents") {
Projection ortho = Projection::create_orthogonal(-3, 3, -1.5, 1.5, 1.2, 15);
Vector2 ne = ortho.get_viewport_half_extents();
Vector2 fe = ortho.get_far_plane_half_extents();
CHECK(ne.is_equal_approx(Vector2(3, 1.5)));
CHECK(fe.is_equal_approx(Vector2(3, 1.5)));
ortho.set_orthogonal(-7, 7, -2.5, 2.5, 0.5, 6);
ne = ortho.get_viewport_half_extents();
fe = ortho.get_far_plane_half_extents();
CHECK(ne.is_equal_approx(Vector2(7, 2.5)));
CHECK(fe.is_equal_approx(Vector2(7, 2.5)));
}
TEST_CASE("[Projection] Endpoints") {
constexpr real_t sqrt3 = 1.7320508;
Projection persp = Projection::create_perspective(90, 1, 1, 40, false);
Vector3 ep[8];
persp.get_endpoints(Transform3D(), ep);
@ -509,8 +606,89 @@ TEST_CASE("[Projection] Endpoints") {
CHECK(ep[5].is_equal_approx(Vector3(-1, -1, -1) * 1));
CHECK(ep[6].is_equal_approx(Vector3(1, 1, -1) * 1));
CHECK(ep[7].is_equal_approx(Vector3(1, -1, -1) * 1));
persp.set_perspective(120, sqrt3, 0.8, 10, true);
persp.get_endpoints(Transform3D(), ep);
CHECK(ep[0].is_equal_approx(Vector3(-sqrt3, 1, -1) * 10));
CHECK(ep[1].is_equal_approx(Vector3(-sqrt3, -1, -1) * 10));
CHECK(ep[2].is_equal_approx(Vector3(sqrt3, 1, -1) * 10));
CHECK(ep[3].is_equal_approx(Vector3(sqrt3, -1, -1) * 10));
CHECK(ep[4].is_equal_approx(Vector3(-sqrt3, 1, -1) * 0.8));
CHECK(ep[5].is_equal_approx(Vector3(-sqrt3, -1, -1) * 0.8));
CHECK(ep[6].is_equal_approx(Vector3(sqrt3, 1, -1) * 0.8));
CHECK(ep[7].is_equal_approx(Vector3(sqrt3, -1, -1) * 0.8));
persp.set_perspective(60, 1.2, 0.5, 15, false);
persp.get_endpoints(Transform3D(), ep);
CHECK(ep[0].is_equal_approx(Vector3(-sqrt3 / 3 * 1.2, sqrt3 / 3, -1) * 15));
CHECK(ep[1].is_equal_approx(Vector3(-sqrt3 / 3 * 1.2, -sqrt3 / 3, -1) * 15));
CHECK(ep[2].is_equal_approx(Vector3(sqrt3 / 3 * 1.2, sqrt3 / 3, -1) * 15));
CHECK(ep[3].is_equal_approx(Vector3(sqrt3 / 3 * 1.2, -sqrt3 / 3, -1) * 15));
CHECK(ep[4].is_equal_approx(Vector3(-sqrt3 / 3 * 1.2, sqrt3 / 3, -1) * 0.5));
CHECK(ep[5].is_equal_approx(Vector3(-sqrt3 / 3 * 1.2, -sqrt3 / 3, -1) * 0.5));
CHECK(ep[6].is_equal_approx(Vector3(sqrt3 / 3 * 1.2, sqrt3 / 3, -1) * 0.5));
CHECK(ep[7].is_equal_approx(Vector3(sqrt3 / 3 * 1.2, -sqrt3 / 3, -1) * 0.5));
}
} //namespace TestProjection
TEST_CASE("[Projection] LOD multiplier") {
constexpr real_t sqrt3 = 1.7320508;
Projection proj;
real_t multiplier;
#endif // TEST_PROJECTION_H
proj.set_perspective(60, 1, 1, 40, false);
multiplier = proj.get_lod_multiplier();
CHECK(multiplier == doctest::Approx(2 * sqrt3 / 3));
proj.set_perspective(120, 1.5, 0.5, 20, false);
multiplier = proj.get_lod_multiplier();
CHECK(multiplier == doctest::Approx(3 * sqrt3));
proj.set_orthogonal(15, 20, 10, 12, 5, 15);
multiplier = proj.get_lod_multiplier();
CHECK(multiplier == doctest::Approx(5));
proj.set_orthogonal(-5, 15, -8, 10, 1.5, 10);
multiplier = proj.get_lod_multiplier();
CHECK(multiplier == doctest::Approx(20));
proj.set_frustum(1.0, 4.0 / 3.0, Vector2(0.5, -0.25), 0.5, 50, false);
multiplier = proj.get_lod_multiplier();
CHECK(multiplier == doctest::Approx(8.0 / 3.0));
proj.set_frustum(2.0, 1.2, Vector2(-0.1, 0.8), 1, 10, true);
multiplier = proj.get_lod_multiplier();
CHECK(multiplier == doctest::Approx(2));
}
TEST_CASE("[Projection] Pixels per meter") {
constexpr real_t sqrt3 = 1.7320508;
Projection proj;
int ppm;
proj.set_perspective(60, 1, 1, 40, false);
ppm = proj.get_pixels_per_meter(1024);
CHECK(ppm == int(1536.0f / sqrt3));
proj.set_perspective(120, 1.5, 0.5, 20, false);
ppm = proj.get_pixels_per_meter(1200);
CHECK(ppm == int(800.0f / sqrt3));
proj.set_orthogonal(15, 20, 10, 12, 5, 15);
ppm = proj.get_pixels_per_meter(500);
CHECK(ppm == 100);
proj.set_orthogonal(-5, 15, -8, 10, 1.5, 10);
ppm = proj.get_pixels_per_meter(640);
CHECK(ppm == 32);
proj.set_frustum(1.0, 4.0 / 3.0, Vector2(0.5, -0.25), 0.5, 50, false);
ppm = proj.get_pixels_per_meter(2048);
CHECK(ppm == 1536);
proj.set_frustum(2.0, 1.2, Vector2(-0.1, 0.8), 1, 10, true);
ppm = proj.get_pixels_per_meter(800);
CHECK(ppm == 400);
}
} //namespace TestProjection

View file

@ -28,8 +28,7 @@
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
/**************************************************************************/
#ifndef TEST_QUATERNION_H
#define TEST_QUATERNION_H
#pragma once
#include "core/math/math_defs.h"
#include "core/math/math_funcs.h"
@ -57,7 +56,7 @@ Quaternion quat_euler_yxz_deg(Vector3 angle) {
}
TEST_CASE("[Quaternion] Default Construct") {
Quaternion q;
constexpr Quaternion q;
CHECK(q[0] == 0.0);
CHECK(q[1] == 0.0);
@ -67,7 +66,7 @@ TEST_CASE("[Quaternion] Default Construct") {
TEST_CASE("[Quaternion] Construct x,y,z,w") {
// Values are taken from actual use in another project & are valid (except roundoff error).
Quaternion q(0.2391, 0.099, 0.3696, 0.8924);
constexpr Quaternion q(0.2391, 0.099, 0.3696, 0.8924);
CHECK(q[0] == doctest::Approx(0.2391));
CHECK(q[1] == doctest::Approx(0.099));
@ -108,7 +107,7 @@ TEST_CASE("[Quaternion] Construct AxisAngle 3") {
TEST_CASE("[Quaternion] Construct AxisAngle 4") {
// More complex & hard to visualize, so test w/ data from online calculator.
Vector3 axis(1.0, 2.0, 0.5);
constexpr Vector3 axis(1.0, 2.0, 0.5);
Quaternion q(axis.normalized(), Math::deg_to_rad(35.0));
CHECK(q[0] == doctest::Approx(0.131239));
@ -118,7 +117,7 @@ TEST_CASE("[Quaternion] Construct AxisAngle 4") {
}
TEST_CASE("[Quaternion] Construct from Quaternion") {
Vector3 axis(1.0, 2.0, 0.5);
constexpr Vector3 axis(1.0, 2.0, 0.5);
Quaternion q_src(axis.normalized(), Math::deg_to_rad(35.0));
Quaternion q(q_src);
@ -199,17 +198,17 @@ TEST_CASE("[Quaternion] Construct Basis Euler") {
TEST_CASE("[Quaternion] Construct Basis Axes") {
// Arbitrary Euler angles.
Vector3 euler_yxz(Math::deg_to_rad(31.41), Math::deg_to_rad(-49.16), Math::deg_to_rad(12.34));
const Vector3 euler_yxz(Math::deg_to_rad(31.41), Math::deg_to_rad(-49.16), Math::deg_to_rad(12.34));
// Basis vectors from online calculation of rotation matrix.
Vector3 i_unit(0.5545787, 0.1823950, 0.8118957);
Vector3 j_unit(-0.5249245, 0.8337420, 0.1712555);
Vector3 k_unit(-0.6456754, -0.5211586, 0.5581192);
constexpr Vector3 i_unit(0.5545787, 0.1823950, 0.8118957);
constexpr Vector3 j_unit(-0.5249245, 0.8337420, 0.1712555);
constexpr Vector3 k_unit(-0.6456754, -0.5211586, 0.5581192);
// Quaternion from online calculation.
Quaternion q_calc(0.2016913, -0.4245716, 0.206033, 0.8582598);
constexpr Quaternion q_calc(0.2016913, -0.4245716, 0.206033, 0.8582598);
// Quaternion from local calculation.
Quaternion q_local = quat_euler_yxz_deg(Vector3(31.41, -49.16, 12.34));
const Quaternion q_local = quat_euler_yxz_deg(Vector3(31.41, -49.16, 12.34));
// Quaternion from Euler angles constructor.
Quaternion q_euler = Quaternion::from_euler(euler_yxz);
const Quaternion q_euler = Quaternion::from_euler(euler_yxz);
CHECK(q_calc.is_equal_approx(q_local));
CHECK(q_local.is_equal_approx(q_euler));
@ -287,10 +286,10 @@ TEST_CASE("[Quaternion] Get Euler Orders") {
TEST_CASE("[Quaternion] Product (book)") {
// Example from "Quaternions and Rotation Sequences" by Jack Kuipers, p. 108.
Quaternion p(1.0, -2.0, 1.0, 3.0);
Quaternion q(-1.0, 2.0, 3.0, 2.0);
constexpr Quaternion p(1.0, -2.0, 1.0, 3.0);
constexpr Quaternion q(-1.0, 2.0, 3.0, 2.0);
Quaternion pq = p * q;
constexpr Quaternion pq = p * q;
CHECK(pq[0] == doctest::Approx(-9.0));
CHECK(pq[1] == doctest::Approx(-2.0));
CHECK(pq[2] == doctest::Approx(11.0));
@ -383,13 +382,13 @@ TEST_CASE("[Quaternion] xform unit vectors") {
TEST_CASE("[Quaternion] xform vector") {
// Arbitrary quaternion rotates an arbitrary vector.
Vector3 euler_yzx(Math::deg_to_rad(31.41), Math::deg_to_rad(-49.16), Math::deg_to_rad(12.34));
Basis basis_axes = Basis::from_euler(euler_yzx);
Quaternion q(basis_axes);
const Vector3 euler_yzx(Math::deg_to_rad(31.41), Math::deg_to_rad(-49.16), Math::deg_to_rad(12.34));
const Basis basis_axes = Basis::from_euler(euler_yzx);
const Quaternion q(basis_axes);
Vector3 v_arb(3.0, 4.0, 5.0);
Vector3 v_rot = q.xform(v_arb);
Vector3 v_compare = basis_axes.xform(v_arb);
constexpr Vector3 v_arb(3.0, 4.0, 5.0);
const Vector3 v_rot = q.xform(v_arb);
const Vector3 v_compare = basis_axes.xform(v_arb);
CHECK(v_rot.length_squared() == doctest::Approx(v_arb.length_squared()));
CHECK(v_rot.is_equal_approx(v_compare));
@ -397,11 +396,11 @@ TEST_CASE("[Quaternion] xform vector") {
// Test vector xform for a single combination of Quaternion and Vector.
void test_quat_vec_rotate(Vector3 euler_yzx, Vector3 v_in) {
Basis basis_axes = Basis::from_euler(euler_yzx);
Quaternion q(basis_axes);
const Basis basis_axes = Basis::from_euler(euler_yzx);
const Quaternion q(basis_axes);
Vector3 v_rot = q.xform(v_in);
Vector3 v_compare = basis_axes.xform(v_in);
const Vector3 v_rot = q.xform(v_in);
const Vector3 v_compare = basis_axes.xform(v_in);
CHECK(v_rot.length_squared() == doctest::Approx(v_in.length_squared()));
CHECK(v_rot.is_equal_approx(v_compare));
@ -411,22 +410,22 @@ TEST_CASE("[Stress][Quaternion] Many vector xforms") {
// Many arbitrary quaternions rotate many arbitrary vectors.
// For each trial, check that rotation by Quaternion yields same result as
// rotation by Basis.
const int STEPS = 100; // Number of test steps in each dimension
const double delta = 2.0 * Math_PI / STEPS; // Angle increment per step
const double delta_vec = 20.0 / STEPS; // Vector increment per step
constexpr int STEPS = 100; // Number of test steps in each dimension
constexpr double delta = 2.0 * Math::PI / STEPS; // Angle increment per step
constexpr double delta_vec = 20.0 / STEPS; // Vector increment per step
Vector3 vec_arb(1.0, 1.0, 1.0);
double x_angle = -Math_PI;
double y_angle = -Math_PI;
double z_angle = -Math_PI;
double x_angle = -Math::PI;
double y_angle = -Math::PI;
double z_angle = -Math::PI;
for (double i = 0; i < STEPS; ++i) {
vec_arb[0] = -10.0 + i * delta_vec;
x_angle = i * delta - Math_PI;
x_angle = i * delta - Math::PI;
for (double j = 0; j < STEPS; ++j) {
vec_arb[1] = -10.0 + j * delta_vec;
y_angle = j * delta - Math_PI;
y_angle = j * delta - Math::PI;
for (double k = 0; k < STEPS; ++k) {
vec_arb[2] = -10.0 + k * delta_vec;
z_angle = k * delta - Math_PI;
z_angle = k * delta - Math::PI;
Vector3 euler_yzx(x_angle, y_angle, z_angle);
test_quat_vec_rotate(euler_yzx, vec_arb);
}
@ -435,7 +434,7 @@ TEST_CASE("[Stress][Quaternion] Many vector xforms") {
}
TEST_CASE("[Quaternion] Finite number checks") {
const real_t x = NAN;
constexpr real_t x = Math::NaN;
CHECK_MESSAGE(
Quaternion(0, 1, 2, 3).is_finite(),
@ -492,5 +491,3 @@ TEST_CASE("[Quaternion] Finite number checks") {
}
} // namespace TestQuaternion
#endif // TEST_QUATERNION_H

View file

@ -28,8 +28,7 @@
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
/**************************************************************************/
#ifndef TEST_RANDOM_NUMBER_GENERATOR_H
#define TEST_RANDOM_NUMBER_GENERATOR_H
#pragma once
#include "core/math/random_number_generator.h"
#include "tests/test_macros.h"
@ -271,5 +270,3 @@ TEST_CASE_MAY_FAIL("[RandomNumberGenerator] randi_range bias check") {
}
}
} // namespace TestRandomNumberGenerator
#endif // TEST_RANDOM_NUMBER_GENERATOR_H

View file

@ -28,8 +28,7 @@
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
/**************************************************************************/
#ifndef TEST_RECT2_H
#define TEST_RECT2_H
#pragma once
#include "core/math/rect2.h"
#include "core/math/rect2i.h"
@ -38,15 +37,15 @@
namespace TestRect2 {
TEST_CASE("[Rect2] Constructor methods") {
const Rect2 rect = Rect2(0, 100, 1280, 720);
const Rect2 rect_vector = Rect2(Vector2(0, 100), Vector2(1280, 720));
const Rect2 rect_copy_rect = Rect2(rect);
constexpr Rect2 rect = Rect2(0, 100, 1280, 720);
constexpr Rect2 rect_vector = Rect2(Vector2(0, 100), Vector2(1280, 720));
constexpr Rect2 rect_copy_rect = Rect2(rect);
const Rect2 rect_copy_recti = Rect2(Rect2i(0, 100, 1280, 720));
CHECK_MESSAGE(
static_assert(
rect == rect_vector,
"Rect2s created with the same dimensions but by different methods should be equal.");
CHECK_MESSAGE(
static_assert(
rect == rect_copy_rect,
"Rect2s created with the same dimensions but by different methods should be equal.");
CHECK_MESSAGE(
@ -62,7 +61,7 @@ TEST_CASE("[Rect2] String conversion") {
}
TEST_CASE("[Rect2] Basic getters") {
const Rect2 rect = Rect2(0, 100, 1280, 720);
constexpr Rect2 rect = Rect2(0, 100, 1280, 720);
CHECK_MESSAGE(
rect.get_position().is_equal_approx(Vector2(0, 100)),
"get_position() should return the expected value.");
@ -181,7 +180,7 @@ TEST_CASE("[Rect2] Expanding") {
}
TEST_CASE("[Rect2] Get support") {
const Rect2 rect = Rect2(Vector2(-1.5, 2), Vector2(4, 5));
constexpr Rect2 rect = Rect2(Vector2(-1.5, 2), Vector2(4, 5));
CHECK_MESSAGE(
rect.get_support(Vector2(1, 0)) == Vector2(2.5, 2),
"get_support() should return the expected value.");
@ -324,8 +323,8 @@ TEST_CASE("[Rect2] Merging") {
}
TEST_CASE("[Rect2] Finite number checks") {
const Vector2 x(0, 1);
const Vector2 infinite(NAN, NAN);
constexpr Vector2 x(0, 1);
constexpr Vector2 infinite(Math::NaN, Math::NaN);
CHECK_MESSAGE(
Rect2(x, x).is_finite(),
@ -344,5 +343,3 @@ TEST_CASE("[Rect2] Finite number checks") {
}
} // namespace TestRect2
#endif // TEST_RECT2_H

View file

@ -28,8 +28,7 @@
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
/**************************************************************************/
#ifndef TEST_RECT2I_H
#define TEST_RECT2I_H
#pragma once
#include "core/math/rect2.h"
#include "core/math/rect2i.h"
@ -38,15 +37,15 @@
namespace TestRect2i {
TEST_CASE("[Rect2i] Constructor methods") {
Rect2i recti = Rect2i(0, 100, 1280, 720);
Rect2i recti_vector = Rect2i(Vector2i(0, 100), Vector2i(1280, 720));
Rect2i recti_copy_recti = Rect2i(recti);
Rect2i recti_copy_rect = Rect2i(Rect2(0, 100, 1280, 720));
constexpr Rect2i recti = Rect2i(0, 100, 1280, 720);
constexpr Rect2i recti_vector = Rect2i(Vector2i(0, 100), Vector2i(1280, 720));
constexpr Rect2i recti_copy_recti = Rect2i(recti);
const Rect2i recti_copy_rect = Rect2i(Rect2(0, 100, 1280, 720));
CHECK_MESSAGE(
static_assert(
recti == recti_vector,
"Rect2is created with the same dimensions but by different methods should be equal.");
CHECK_MESSAGE(
static_assert(
recti == recti_copy_recti,
"Rect2is created with the same dimensions but by different methods should be equal.");
CHECK_MESSAGE(
@ -62,7 +61,7 @@ TEST_CASE("[Rect2i] String conversion") {
}
TEST_CASE("[Rect2i] Basic getters") {
const Rect2i rect = Rect2i(0, 100, 1280, 720);
constexpr Rect2i rect = Rect2i(0, 100, 1280, 720);
CHECK_MESSAGE(
rect.get_position() == Vector2i(0, 100),
"get_position() should return the expected value.");
@ -307,5 +306,3 @@ TEST_CASE("[Rect2i] Merging") {
"merge() with non-enclosed Rect2i should return the expected result.");
}
} // namespace TestRect2i
#endif // TEST_RECT2I_H

View file

@ -28,8 +28,7 @@
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
/**************************************************************************/
#ifndef TEST_TRANSFORM_2D_H
#define TEST_TRANSFORM_2D_H
#pragma once
#include "core/math/transform_2d.h"
@ -57,8 +56,8 @@ TEST_CASE("[Transform2D] Copy constructor") {
}
TEST_CASE("[Transform2D] Constructor from angle and position") {
constexpr float ROTATION = Math_PI / 4;
const Vector2 TRANSLATION = Vector2(20, -20);
constexpr float ROTATION = Math::PI / 4;
constexpr Vector2 TRANSLATION = Vector2(20, -20);
const Transform2D test = Transform2D(ROTATION, TRANSLATION);
const Transform2D expected = Transform2D().rotated(ROTATION).translated(TRANSLATION);
@ -66,10 +65,10 @@ TEST_CASE("[Transform2D] Constructor from angle and position") {
}
TEST_CASE("[Transform2D] Constructor from angle, scale, skew and position") {
constexpr float ROTATION = Math_PI / 2;
const Vector2 SCALE = Vector2(2, 0.5);
constexpr float SKEW = Math_PI / 4;
const Vector2 TRANSLATION = Vector2(30, 0);
constexpr float ROTATION = Math::PI / 2;
constexpr Vector2 SCALE = Vector2(2, 0.5);
constexpr float SKEW = Math::PI / 4;
constexpr Vector2 TRANSLATION = Vector2(30, 0);
const Transform2D test = Transform2D(ROTATION, SCALE, SKEW, TRANSLATION);
Transform2D expected = Transform2D().scaled(SCALE).rotated(ROTATION).translated(TRANSLATION);
@ -79,26 +78,26 @@ TEST_CASE("[Transform2D] Constructor from angle, scale, skew and position") {
}
TEST_CASE("[Transform2D] Constructor from raw values") {
const Transform2D test = Transform2D(1, 2, 3, 4, 5, 6);
const Transform2D expected = Transform2D(Vector2(1, 2), Vector2(3, 4), Vector2(5, 6));
CHECK(test == expected);
constexpr Transform2D test = Transform2D(1, 2, 3, 4, 5, 6);
constexpr Transform2D expected = Transform2D(Vector2(1, 2), Vector2(3, 4), Vector2(5, 6));
static_assert(test == expected);
}
TEST_CASE("[Transform2D] xform") {
const Vector2 v = Vector2(2, 3);
const Transform2D T = Transform2D(Vector2(1, 2), Vector2(3, 4), Vector2(5, 6));
const Vector2 expected = Vector2(1 * 2 + 3 * 3 + 5 * 1, 2 * 2 + 4 * 3 + 6 * 1);
constexpr Vector2 v = Vector2(2, 3);
constexpr Transform2D T = Transform2D(Vector2(1, 2), Vector2(3, 4), Vector2(5, 6));
constexpr Vector2 expected = Vector2(1 * 2 + 3 * 3 + 5 * 1, 2 * 2 + 4 * 3 + 6 * 1);
CHECK(T.xform(v) == expected);
}
TEST_CASE("[Transform2D] Basis xform") {
const Vector2 v = Vector2(2, 2);
const Transform2D T1 = Transform2D(Vector2(1, 2), Vector2(3, 4), Vector2(0, 0));
constexpr Vector2 v = Vector2(2, 2);
constexpr Transform2D T1 = Transform2D(Vector2(1, 2), Vector2(3, 4), Vector2(0, 0));
// Both versions should be the same when the origin is (0,0).
CHECK(T1.basis_xform(v) == T1.xform(v));
const Transform2D T2 = Transform2D(Vector2(1, 2), Vector2(3, 4), Vector2(5, 6));
constexpr Transform2D T2 = Transform2D(Vector2(1, 2), Vector2(3, 4), Vector2(5, 6));
// Each version should be different when the origin is not (0,0).
CHECK_FALSE(T2.basis_xform(v) == T2.xform(v));
@ -130,7 +129,7 @@ TEST_CASE("[Transform2D] Orthonormalized") {
}
TEST_CASE("[Transform2D] translation") {
const Vector2 offset = Vector2(1, 2);
constexpr Vector2 offset = Vector2(1, 2);
// Both versions should give the same result applied to identity.
CHECK(identity().translated(offset) == identity().translated_local(offset));
@ -143,7 +142,7 @@ TEST_CASE("[Transform2D] translation") {
}
TEST_CASE("[Transform2D] scaling") {
const Vector2 scaling = Vector2(1, 2);
constexpr Vector2 scaling = Vector2(1, 2);
// Both versions should give the same result applied to identity.
CHECK(identity().scaled(scaling) == identity().scaled_local(scaling));
@ -182,8 +181,8 @@ TEST_CASE("[Transform2D] Interpolation") {
}
TEST_CASE("[Transform2D] Finite number checks") {
const Vector2 x = Vector2(0, 1);
const Vector2 infinite = Vector2(NAN, NAN);
constexpr Vector2 x = Vector2(0, 1);
constexpr Vector2 infinite = Vector2(Math::NaN, Math::NaN);
CHECK_MESSAGE(
Transform2D(x, x, x).is_finite(),
@ -240,10 +239,8 @@ TEST_CASE("[Transform2D] Is conformal checks") {
"Transform2D with non-uniform scale should not be conformal.");
CHECK_FALSE_MESSAGE(
Transform2D(Vector2(Math_SQRT12, Math_SQRT12), Vector2(0, 1), Vector2()).is_conformal(),
Transform2D(Vector2(Math::SQRT12, Math::SQRT12), Vector2(0, 1), Vector2()).is_conformal(),
"Transform2D with the X axis skewed 45 degrees should not be conformal.");
}
} // namespace TestTransform2D
#endif // TEST_TRANSFORM_2D_H

View file

@ -28,8 +28,7 @@
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
/**************************************************************************/
#ifndef TEST_TRANSFORM_3D_H
#define TEST_TRANSFORM_3D_H
#pragma once
#include "core/math/transform_3d.h"
@ -46,7 +45,7 @@ Transform3D identity() {
}
TEST_CASE("[Transform3D] translation") {
Vector3 offset = Vector3(1, 2, 3);
constexpr Vector3 offset = Vector3(1, 2, 3);
// Both versions should give the same result applied to identity.
CHECK(identity().translated(offset) == identity().translated_local(offset));
@ -59,7 +58,7 @@ TEST_CASE("[Transform3D] translation") {
}
TEST_CASE("[Transform3D] scaling") {
Vector3 scaling = Vector3(1, 2, 3);
constexpr Vector3 scaling = Vector3(1, 2, 3);
// Both versions should give the same result applied to identity.
CHECK(identity().scaled(scaling) == identity().scaled_local(scaling));
@ -72,8 +71,8 @@ TEST_CASE("[Transform3D] scaling") {
}
TEST_CASE("[Transform3D] rotation") {
Vector3 axis = Vector3(1, 2, 3).normalized();
real_t phi = 1.0;
const Vector3 axis = Vector3(1, 2, 3).normalized();
constexpr real_t phi = 1.0;
// Both versions should give the same result applied to identity.
CHECK(identity().rotated(axis, phi) == identity().rotated_local(axis, phi));
@ -86,10 +85,10 @@ TEST_CASE("[Transform3D] rotation") {
}
TEST_CASE("[Transform3D] Finite number checks") {
const Vector3 y(0, 1, 2);
const Vector3 infinite_vec(NAN, NAN, NAN);
const Basis x(y, y, y);
const Basis infinite_basis(infinite_vec, infinite_vec, infinite_vec);
constexpr Vector3 y(0, 1, 2);
constexpr Vector3 infinite_vec(Math::NaN, Math::NaN, Math::NaN);
constexpr Basis x(y, y, y);
constexpr Basis infinite_basis(infinite_vec, infinite_vec, infinite_vec);
CHECK_MESSAGE(
Transform3D(x, y).is_finite(),
@ -118,7 +117,7 @@ TEST_CASE("[Transform3D] Rotate around global origin") {
expected.basis[0] = Vector3(-1, 0, 0);
expected.basis[2] = Vector3(0, 0, -1);
const Transform3D rotated_transform = transform.rotated(Vector3(0, 1, 0), Math_PI);
const Transform3D rotated_transform = transform.rotated(Vector3(0, 1, 0), Math::PI);
CHECK_MESSAGE(rotated_transform.is_equal_approx(expected), "The rotated transform should have a new orientation and basis.");
}
@ -133,9 +132,7 @@ TEST_CASE("[Transform3D] Rotate in-place (local rotation)") {
expected.basis[0] = Vector3(-1, 0, 0);
expected.basis[2] = Vector3(0, 0, -1);
const Transform3D rotated_transform = Transform3D(transform.rotated_local(Vector3(0, 1, 0), Math_PI));
const Transform3D rotated_transform = Transform3D(transform.rotated_local(Vector3(0, 1, 0), Math::PI));
CHECK_MESSAGE(rotated_transform.is_equal_approx(expected), "The rotated transform should have a new orientation but still be based on the same origin.");
}
} // namespace TestTransform3D
#endif // TEST_TRANSFORM_3D_H

View file

@ -0,0 +1,82 @@
/**************************************************************************/
/* test_triangle_mesh.h */
/**************************************************************************/
/* This file is part of: */
/* GODOT ENGINE */
/* https://godotengine.org */
/**************************************************************************/
/* Copyright (c) 2014-present Godot Engine contributors (see AUTHORS.md). */
/* Copyright (c) 2007-2014 Juan Linietsky, Ariel Manzur. */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
/* "Software"), to deal in the Software without restriction, including */
/* without limitation the rights to use, copy, modify, merge, publish, */
/* distribute, sublicense, and/or sell copies of the Software, and to */
/* permit persons to whom the Software is furnished to do so, subject to */
/* the following conditions: */
/* */
/* The above copyright notice and this permission notice shall be */
/* included in all copies or substantial portions of the Software. */
/* */
/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. */
/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
/**************************************************************************/
#pragma once
#include "core/math/triangle_mesh.h"
#include "scene/resources/3d/primitive_meshes.h"
#include "tests/test_macros.h"
namespace TestTriangleMesh {
TEST_CASE("[SceneTree][TriangleMesh] BVH creation and intersection") {
Ref<BoxMesh> box_mesh;
box_mesh.instantiate();
const Vector<Face3> faces = box_mesh->get_faces();
Ref<TriangleMesh> triangle_mesh;
triangle_mesh.instantiate();
CHECK(triangle_mesh->create_from_faces(Variant(faces)));
const Vector3 begin = Vector3(0.0, 2.0, 0.0);
const Vector3 end = Vector3(0.0, -2.0, 0.0);
{
Vector3 point;
Vector3 normal;
int32_t *surf_index = nullptr;
int32_t face_index = -1;
const bool has_result = triangle_mesh->intersect_segment(begin, end, point, normal, surf_index, &face_index);
CHECK(has_result);
CHECK(point.is_equal_approx(Vector3(0.0, 0.5, 0.0)));
CHECK(normal.is_equal_approx(Vector3(0.0, 1.0, 0.0)));
CHECK(surf_index == nullptr);
REQUIRE(face_index != -1);
CHECK(face_index == 8);
}
{
Vector3 dir = begin.direction_to(end);
Vector3 point;
Vector3 normal;
int32_t *surf_index = nullptr;
int32_t face_index = -1;
const bool has_result = triangle_mesh->intersect_ray(begin, dir, point, normal, surf_index, &face_index);
CHECK(has_result);
CHECK(point.is_equal_approx(Vector3(0.0, 0.5, 0.0)));
CHECK(normal.is_equal_approx(Vector3(0.0, 1.0, 0.0)));
CHECK(surf_index == nullptr);
REQUIRE(face_index != -1);
CHECK(face_index == 8);
}
}
} // namespace TestTriangleMesh

View file

@ -28,8 +28,7 @@
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
/**************************************************************************/
#ifndef TEST_VECTOR2_H
#define TEST_VECTOR2_H
#pragma once
#include "core/math/vector2.h"
#include "core/math/vector2i.h"
@ -38,27 +37,27 @@
namespace TestVector2 {
TEST_CASE("[Vector2] Constructor methods") {
const Vector2 vector_empty = Vector2();
const Vector2 vector_zero = Vector2(0.0, 0.0);
CHECK_MESSAGE(
constexpr Vector2 vector_empty = Vector2();
constexpr Vector2 vector_zero = Vector2(0.0, 0.0);
static_assert(
vector_empty == vector_zero,
"Vector2 Constructor with no inputs should return a zero Vector2.");
}
TEST_CASE("[Vector2] Angle methods") {
const Vector2 vector_x = Vector2(1, 0);
const Vector2 vector_y = Vector2(0, 1);
constexpr Vector2 vector_x = Vector2(1, 0);
constexpr Vector2 vector_y = Vector2(0, 1);
CHECK_MESSAGE(
vector_x.angle_to(vector_y) == doctest::Approx((real_t)Math_TAU / 4),
vector_x.angle_to(vector_y) == doctest::Approx((real_t)Math::TAU / 4),
"Vector2 angle_to should work as expected.");
CHECK_MESSAGE(
vector_y.angle_to(vector_x) == doctest::Approx((real_t)-Math_TAU / 4),
vector_y.angle_to(vector_x) == doctest::Approx((real_t)-Math::TAU / 4),
"Vector2 angle_to should work as expected.");
CHECK_MESSAGE(
vector_x.angle_to_point(vector_y) == doctest::Approx((real_t)Math_TAU * 3 / 8),
vector_x.angle_to_point(vector_y) == doctest::Approx((real_t)Math::TAU * 3 / 8),
"Vector2 angle_to_point should work as expected.");
CHECK_MESSAGE(
vector_y.angle_to_point(vector_x) == doctest::Approx((real_t)-Math_TAU / 8),
vector_y.angle_to_point(vector_x) == doctest::Approx((real_t)-Math::TAU / 8),
"Vector2 angle_to_point should work as expected.");
}
@ -80,8 +79,8 @@ TEST_CASE("[Vector2] Axis methods") {
}
TEST_CASE("[Vector2] Interpolation methods") {
const Vector2 vector1 = Vector2(1, 2);
const Vector2 vector2 = Vector2(4, 5);
constexpr Vector2 vector1 = Vector2(1, 2);
constexpr Vector2 vector2 = Vector2(4, 5);
CHECK_MESSAGE(
vector1.lerp(vector2, 0.5) == Vector2(2.5, 3.5),
"Vector2 lerp should work as expected.");
@ -95,7 +94,7 @@ TEST_CASE("[Vector2] Interpolation methods") {
vector1.normalized().slerp(vector2.normalized(), 1.0 / 3.0).is_equal_approx(Vector2(0.508990883827209473, 0.860771894454956055)),
"Vector2 slerp should work as expected.");
CHECK_MESSAGE(
Vector2(5, 0).slerp(Vector2(0, 5), 0.5).is_equal_approx(Vector2(5, 5) * Math_SQRT12),
Vector2(5, 0).slerp(Vector2(0, 5), 0.5).is_equal_approx(Vector2(5, 5) * Math::SQRT12),
"Vector2 slerp with non-normalized values should work as expected.");
CHECK_MESSAGE(
Vector2(1, 1).slerp(Vector2(2, 2), 0.5).is_equal_approx(Vector2(1.5, 1.5)),
@ -130,13 +129,13 @@ TEST_CASE("[Vector2] Interpolation methods") {
}
TEST_CASE("[Vector2] Length methods") {
const Vector2 vector1 = Vector2(10, 10);
const Vector2 vector2 = Vector2(20, 30);
constexpr Vector2 vector1 = Vector2(10, 10);
constexpr Vector2 vector2 = Vector2(20, 30);
CHECK_MESSAGE(
vector1.length_squared() == 200,
"Vector2 length_squared should work as expected and return exact result.");
CHECK_MESSAGE(
vector1.length() == doctest::Approx(10 * (real_t)Math_SQRT2),
vector1.length() == doctest::Approx(10 * (real_t)Math::SQRT2),
"Vector2 length should work as expected.");
CHECK_MESSAGE(
vector2.length_squared() == 1300,
@ -153,12 +152,12 @@ TEST_CASE("[Vector2] Length methods") {
}
TEST_CASE("[Vector2] Limiting methods") {
const Vector2 vector = Vector2(10, 10);
constexpr Vector2 vector = Vector2(10, 10);
CHECK_MESSAGE(
vector.limit_length().is_equal_approx(Vector2(Math_SQRT12, Math_SQRT12)),
vector.limit_length().is_equal_approx(Vector2(Math::SQRT12, Math::SQRT12)),
"Vector2 limit_length should work as expected.");
CHECK_MESSAGE(
vector.limit_length(5).is_equal_approx(5 * Vector2(Math_SQRT12, Math_SQRT12)),
vector.limit_length(5).is_equal_approx(5 * Vector2(Math::SQRT12, Math::SQRT12)),
"Vector2 limit_length should work as expected.");
CHECK_MESSAGE(
@ -180,7 +179,7 @@ TEST_CASE("[Vector2] Normalization methods") {
Vector2(1, 0).normalized() == Vector2(1, 0),
"Vector2 normalized should return the same vector for a normalized vector.");
CHECK_MESSAGE(
Vector2(1, 1).normalized().is_equal_approx(Vector2(Math_SQRT12, Math_SQRT12)),
Vector2(1, 1).normalized().is_equal_approx(Vector2(Math::SQRT12, Math::SQRT12)),
"Vector2 normalized should work as expected.");
Vector2 vector = Vector2(3.2, -5.4);
@ -194,70 +193,70 @@ TEST_CASE("[Vector2] Normalization methods") {
}
TEST_CASE("[Vector2] Operators") {
const Vector2 decimal1 = Vector2(2.3, 4.9);
const Vector2 decimal2 = Vector2(1.2, 3.4);
const Vector2 power1 = Vector2(0.75, 1.5);
const Vector2 power2 = Vector2(0.5, 0.125);
const Vector2 int1 = Vector2(4, 5);
const Vector2 int2 = Vector2(1, 2);
constexpr Vector2 decimal1 = Vector2(2.3, 4.9);
constexpr Vector2 decimal2 = Vector2(1.2, 3.4);
constexpr Vector2 power1 = Vector2(0.75, 1.5);
constexpr Vector2 power2 = Vector2(0.5, 0.125);
constexpr Vector2 int1 = Vector2(4, 5);
constexpr Vector2 int2 = Vector2(1, 2);
CHECK_MESSAGE(
(decimal1 + decimal2).is_equal_approx(Vector2(3.5, 8.3)),
"Vector2 addition should behave as expected.");
CHECK_MESSAGE(
static_assert(
(power1 + power2) == Vector2(1.25, 1.625),
"Vector2 addition with powers of two should give exact results.");
CHECK_MESSAGE(
static_assert(
(int1 + int2) == Vector2(5, 7),
"Vector2 addition with integers should give exact results.");
CHECK_MESSAGE(
(decimal1 - decimal2).is_equal_approx(Vector2(1.1, 1.5)),
"Vector2 subtraction should behave as expected.");
CHECK_MESSAGE(
static_assert(
(power1 - power2) == Vector2(0.25, 1.375),
"Vector2 subtraction with powers of two should give exact results.");
CHECK_MESSAGE(
static_assert(
(int1 - int2) == Vector2(3, 3),
"Vector2 subtraction with integers should give exact results.");
CHECK_MESSAGE(
(decimal1 * decimal2).is_equal_approx(Vector2(2.76, 16.66)),
"Vector2 multiplication should behave as expected.");
CHECK_MESSAGE(
static_assert(
(power1 * power2) == Vector2(0.375, 0.1875),
"Vector2 multiplication with powers of two should give exact results.");
CHECK_MESSAGE(
static_assert(
(int1 * int2) == Vector2(4, 10),
"Vector2 multiplication with integers should give exact results.");
CHECK_MESSAGE(
(decimal1 / decimal2).is_equal_approx(Vector2(1.91666666666666666, 1.44117647058823529)),
"Vector2 division should behave as expected.");
CHECK_MESSAGE(
static_assert(
(power1 / power2) == Vector2(1.5, 12.0),
"Vector2 division with powers of two should give exact results.");
CHECK_MESSAGE(
static_assert(
(int1 / int2) == Vector2(4, 2.5),
"Vector2 division with integers should give exact results.");
CHECK_MESSAGE(
(decimal1 * 2).is_equal_approx(Vector2(4.6, 9.8)),
"Vector2 multiplication should behave as expected.");
CHECK_MESSAGE(
static_assert(
(power1 * 2) == Vector2(1.5, 3),
"Vector2 multiplication with powers of two should give exact results.");
CHECK_MESSAGE(
static_assert(
(int1 * 2) == Vector2(8, 10),
"Vector2 multiplication with integers should give exact results.");
CHECK_MESSAGE(
(decimal1 / 2).is_equal_approx(Vector2(1.15, 2.45)),
"Vector2 division should behave as expected.");
CHECK_MESSAGE(
static_assert(
(power1 / 2) == Vector2(0.375, 0.75),
"Vector2 division with powers of two should give exact results.");
CHECK_MESSAGE(
static_assert(
(int1 / 2) == Vector2(2, 2.5),
"Vector2 division with integers should give exact results.");
@ -282,17 +281,17 @@ TEST_CASE("[Vector2] Operators") {
"Vector2 cast to String should work as expected.");
#ifdef REAL_T_IS_DOUBLE
CHECK_MESSAGE(
((String)Vector2(Math_PI, Math_TAU)) == "(3.14159265358979, 6.28318530717959)",
((String)Vector2(Math::PI, Math::TAU)) == "(3.14159265358979, 6.28318530717959)",
"Vector2 cast to String should print the correct amount of digits for real_t = double.");
#else
CHECK_MESSAGE(
((String)Vector2(Math_PI, Math_TAU)) == "(3.141593, 6.283185)",
((String)Vector2(Math::PI, Math::TAU)) == "(3.141593, 6.283185)",
"Vector2 cast to String should print the correct amount of digits for real_t = float.");
#endif // REAL_T_IS_DOUBLE
}
TEST_CASE("[Vector2] Other methods") {
const Vector2 vector = Vector2(1.2, 3.4);
constexpr Vector2 vector = Vector2(1.2, 3.4);
CHECK_MESSAGE(
vector.aspect() == doctest::Approx((real_t)1.2 / (real_t)3.4),
"Vector2 aspect should work as expected.");
@ -301,7 +300,7 @@ TEST_CASE("[Vector2] Other methods") {
vector.direction_to(Vector2()).is_equal_approx(-vector.normalized()),
"Vector2 direction_to should work as expected.");
CHECK_MESSAGE(
Vector2(1, 1).direction_to(Vector2(2, 2)).is_equal_approx(Vector2(Math_SQRT12, Math_SQRT12)),
Vector2(1, 1).direction_to(Vector2(2, 2)).is_equal_approx(Vector2(Math::SQRT12, Math::SQRT12)),
"Vector2 direction_to should work as expected.");
CHECK_MESSAGE(
@ -318,16 +317,16 @@ TEST_CASE("[Vector2] Other methods") {
"Vector2 posmodv should work as expected.");
CHECK_MESSAGE(
vector.rotated(Math_TAU).is_equal_approx(Vector2(1.2, 3.4)),
vector.rotated(Math::TAU).is_equal_approx(Vector2(1.2, 3.4)),
"Vector2 rotated should work as expected.");
CHECK_MESSAGE(
vector.rotated(Math_TAU / 4).is_equal_approx(Vector2(-3.4, 1.2)),
vector.rotated(Math::TAU / 4).is_equal_approx(Vector2(-3.4, 1.2)),
"Vector2 rotated should work as expected.");
CHECK_MESSAGE(
vector.rotated(Math_TAU / 3).is_equal_approx(Vector2(-3.544486372867091398996, -0.660769515458673623883)),
vector.rotated(Math::TAU / 3).is_equal_approx(Vector2(-3.544486372867091398996, -0.660769515458673623883)),
"Vector2 rotated should work as expected.");
CHECK_MESSAGE(
vector.rotated(Math_TAU / 2).is_equal_approx(vector.rotated(Math_TAU / -2)),
vector.rotated(Math::TAU / 2).is_equal_approx(vector.rotated(Math::TAU / -2)),
"Vector2 rotated should work as expected.");
CHECK_MESSAGE(
@ -350,10 +349,10 @@ TEST_CASE("[Vector2] Other methods") {
}
TEST_CASE("[Vector2] Plane methods") {
const Vector2 vector = Vector2(1.2, 3.4);
const Vector2 vector_y = Vector2(0, 1);
const Vector2 vector_normal = Vector2(0.95879811270838721622267, 0.2840883296913739899919);
const real_t p_d = 99.1;
constexpr Vector2 vector = Vector2(1.2, 3.4);
constexpr Vector2 vector_y = Vector2(0, 1);
constexpr Vector2 vector_normal = Vector2(0.95879811270838721622267, 0.2840883296913739899919);
constexpr real_t p_d = 99.1;
CHECK_MESSAGE(
vector.bounce(vector_y) == Vector2(1.2, -3.4),
"Vector2 bounce on a plane with normal of the Y axis should.");
@ -383,7 +382,7 @@ TEST_CASE("[Vector2] Plane methods") {
"Vector2 slide with normal should return expected value.");
// There's probably a better way to test these ones?
#ifdef MATH_CHECKS
const Vector2 vector_non_normal = Vector2(5.4, 1.6);
constexpr Vector2 vector_non_normal = Vector2(5.4, 1.6);
ERR_PRINT_OFF;
CHECK_MESSAGE(
vector.bounce(vector_non_normal).is_equal_approx(Vector2()),
@ -399,8 +398,8 @@ TEST_CASE("[Vector2] Plane methods") {
}
TEST_CASE("[Vector2] Rounding methods") {
const Vector2 vector1 = Vector2(1.2, 5.6);
const Vector2 vector2 = Vector2(1.2, -5.6);
constexpr Vector2 vector1 = Vector2(1.2, 5.6);
constexpr Vector2 vector2 = Vector2(1.2, -5.6);
CHECK_MESSAGE(
vector1.abs() == vector1,
"Vector2 abs should work as expected.");
@ -438,10 +437,10 @@ TEST_CASE("[Vector2] Rounding methods") {
}
TEST_CASE("[Vector2] Linear algebra methods") {
const Vector2 vector_x = Vector2(1, 0);
const Vector2 vector_y = Vector2(0, 1);
const Vector2 a = Vector2(3.5, 8.5);
const Vector2 b = Vector2(5.2, 4.6);
constexpr Vector2 vector_x = Vector2(1, 0);
constexpr Vector2 vector_y = Vector2(0, 1);
constexpr Vector2 a = Vector2(3.5, 8.5);
constexpr Vector2 b = Vector2(5.2, 4.6);
CHECK_MESSAGE(
vector_x.cross(vector_y) == 1,
"Vector2 cross product of X and Y should give 1.");
@ -473,7 +472,7 @@ TEST_CASE("[Vector2] Linear algebra methods") {
}
TEST_CASE("[Vector2] Finite number checks") {
const double infinite[] = { NAN, INFINITY, -INFINITY };
constexpr double infinite[] = { Math::NaN, Math::INF, -Math::INF };
CHECK_MESSAGE(
Vector2(0, 1).is_finite(),
@ -498,5 +497,3 @@ TEST_CASE("[Vector2] Finite number checks") {
}
} // namespace TestVector2
#endif // TEST_VECTOR2_H

View file

@ -28,8 +28,7 @@
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
/**************************************************************************/
#ifndef TEST_VECTOR2I_H
#define TEST_VECTOR2I_H
#pragma once
#include "core/math/vector2.h"
#include "core/math/vector2i.h"
@ -38,9 +37,9 @@
namespace TestVector2i {
TEST_CASE("[Vector2i] Constructor methods") {
const Vector2i vector_empty = Vector2i();
const Vector2i vector_zero = Vector2i(0, 0);
CHECK_MESSAGE(
constexpr Vector2i vector_empty = Vector2i();
constexpr Vector2i vector_zero = Vector2i(0, 0);
static_assert(
vector_empty == vector_zero,
"Vector2i Constructor with no inputs should return a zero Vector2i.");
}
@ -63,7 +62,7 @@ TEST_CASE("[Vector2i] Axis methods") {
}
TEST_CASE("[Vector2i] Clamp method") {
const Vector2i vector = Vector2i(10, 10);
constexpr Vector2i vector = Vector2i(10, 10);
CHECK_MESSAGE(
Vector2i(-5, 15).clamp(Vector2i(), vector) == Vector2i(0, 10),
"Vector2i clamp should work as expected.");
@ -73,13 +72,13 @@ TEST_CASE("[Vector2i] Clamp method") {
}
TEST_CASE("[Vector2i] Length methods") {
const Vector2i vector1 = Vector2i(10, 10);
const Vector2i vector2 = Vector2i(20, 30);
constexpr Vector2i vector1 = Vector2i(10, 10);
constexpr Vector2i vector2 = Vector2i(20, 30);
CHECK_MESSAGE(
vector1.length_squared() == 200,
"Vector2i length_squared should work as expected and return exact result.");
CHECK_MESSAGE(
vector1.length() == doctest::Approx(10 * Math_SQRT2),
vector1.length() == doctest::Approx(10 * Math::SQRT2),
"Vector2i length should work as expected.");
CHECK_MESSAGE(
vector2.length_squared() == 1300,
@ -96,26 +95,26 @@ TEST_CASE("[Vector2i] Length methods") {
}
TEST_CASE("[Vector2i] Operators") {
const Vector2i vector1 = Vector2i(5, 9);
const Vector2i vector2 = Vector2i(2, 3);
constexpr Vector2i vector1 = Vector2i(5, 9);
constexpr Vector2i vector2 = Vector2i(2, 3);
CHECK_MESSAGE(
static_assert(
(vector1 + vector2) == Vector2i(7, 12),
"Vector2i addition with integers should give exact results.");
CHECK_MESSAGE(
static_assert(
(vector1 - vector2) == Vector2i(3, 6),
"Vector2i subtraction with integers should give exact results.");
CHECK_MESSAGE(
static_assert(
(vector1 * vector2) == Vector2i(10, 27),
"Vector2i multiplication with integers should give exact results.");
CHECK_MESSAGE(
static_assert(
(vector1 / vector2) == Vector2i(2, 3),
"Vector2i division with integers should give exact results.");
CHECK_MESSAGE(
static_assert(
(vector1 * 2) == Vector2i(10, 18),
"Vector2i multiplication with integers should give exact results.");
CHECK_MESSAGE(
static_assert(
(vector1 / 2) == Vector2i(2, 4),
"Vector2i division with integers should give exact results.");
@ -131,7 +130,7 @@ TEST_CASE("[Vector2i] Operators") {
}
TEST_CASE("[Vector2i] Other methods") {
const Vector2i vector = Vector2i(1, 3);
constexpr Vector2i vector = Vector2i(1, 3);
CHECK_MESSAGE(
vector.aspect() == doctest::Approx((real_t)1.0 / (real_t)3.0),
"Vector2i aspect should work as expected.");
@ -150,8 +149,8 @@ TEST_CASE("[Vector2i] Other methods") {
}
TEST_CASE("[Vector2i] Abs and sign methods") {
const Vector2i vector1 = Vector2i(1, 3);
const Vector2i vector2 = Vector2i(1, -3);
constexpr Vector2i vector1 = Vector2i(1, 3);
constexpr Vector2i vector2 = Vector2i(1, -3);
CHECK_MESSAGE(
vector1.abs() == vector1,
"Vector2i abs should work as expected.");
@ -167,5 +166,3 @@ TEST_CASE("[Vector2i] Abs and sign methods") {
"Vector2i sign should work as expected.");
}
} // namespace TestVector2i
#endif // TEST_VECTOR2I_H

View file

@ -28,50 +28,46 @@
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
/**************************************************************************/
#ifndef TEST_VECTOR3_H
#define TEST_VECTOR3_H
#pragma once
#include "core/math/vector3.h"
#include "tests/test_macros.h"
#define Math_SQRT13 0.57735026918962576450914878050196
#define Math_SQRT3 1.7320508075688772935274463415059
namespace TestVector3 {
TEST_CASE("[Vector3] Constructor methods") {
const Vector3 vector_empty = Vector3();
const Vector3 vector_zero = Vector3(0.0, 0.0, 0.0);
CHECK_MESSAGE(
constexpr Vector3 vector_empty = Vector3();
constexpr Vector3 vector_zero = Vector3(0.0, 0.0, 0.0);
static_assert(
vector_empty == vector_zero,
"Vector3 Constructor with no inputs should return a zero Vector3.");
}
TEST_CASE("[Vector3] Angle methods") {
const Vector3 vector_x = Vector3(1, 0, 0);
const Vector3 vector_y = Vector3(0, 1, 0);
const Vector3 vector_yz = Vector3(0, 1, 1);
constexpr Vector3 vector_x = Vector3(1, 0, 0);
constexpr Vector3 vector_y = Vector3(0, 1, 0);
constexpr Vector3 vector_yz = Vector3(0, 1, 1);
CHECK_MESSAGE(
vector_x.angle_to(vector_y) == doctest::Approx((real_t)Math_TAU / 4),
vector_x.angle_to(vector_y) == doctest::Approx((real_t)Math::TAU / 4),
"Vector3 angle_to should work as expected.");
CHECK_MESSAGE(
vector_x.angle_to(vector_yz) == doctest::Approx((real_t)Math_TAU / 4),
vector_x.angle_to(vector_yz) == doctest::Approx((real_t)Math::TAU / 4),
"Vector3 angle_to should work as expected.");
CHECK_MESSAGE(
vector_yz.angle_to(vector_x) == doctest::Approx((real_t)Math_TAU / 4),
vector_yz.angle_to(vector_x) == doctest::Approx((real_t)Math::TAU / 4),
"Vector3 angle_to should work as expected.");
CHECK_MESSAGE(
vector_y.angle_to(vector_yz) == doctest::Approx((real_t)Math_TAU / 8),
vector_y.angle_to(vector_yz) == doctest::Approx((real_t)Math::TAU / 8),
"Vector3 angle_to should work as expected.");
CHECK_MESSAGE(
vector_x.signed_angle_to(vector_y, vector_y) == doctest::Approx((real_t)Math_TAU / 4),
vector_x.signed_angle_to(vector_y, vector_y) == doctest::Approx((real_t)Math::TAU / 4),
"Vector3 signed_angle_to edge case should be positive.");
CHECK_MESSAGE(
vector_x.signed_angle_to(vector_yz, vector_y) == doctest::Approx((real_t)Math_TAU / -4),
vector_x.signed_angle_to(vector_yz, vector_y) == doctest::Approx((real_t)Math::TAU / -4),
"Vector3 signed_angle_to should work as expected.");
CHECK_MESSAGE(
vector_yz.signed_angle_to(vector_x, vector_y) == doctest::Approx((real_t)Math_TAU / 4),
vector_yz.signed_angle_to(vector_x, vector_y) == doctest::Approx((real_t)Math::TAU / 4),
"Vector3 signed_angle_to should work as expected.");
}
@ -97,8 +93,8 @@ TEST_CASE("[Vector3] Axis methods") {
}
TEST_CASE("[Vector3] Interpolation methods") {
const Vector3 vector1 = Vector3(1, 2, 3);
const Vector3 vector2 = Vector3(4, 5, 6);
constexpr Vector3 vector1 = Vector3(1, 2, 3);
constexpr Vector3 vector2 = Vector3(4, 5, 6);
CHECK_MESSAGE(
vector1.lerp(vector2, 0.5) == Vector3(2.5, 3.5, 4.5),
"Vector3 lerp should work as expected.");
@ -147,13 +143,13 @@ TEST_CASE("[Vector3] Interpolation methods") {
}
TEST_CASE("[Vector3] Length methods") {
const Vector3 vector1 = Vector3(10, 10, 10);
const Vector3 vector2 = Vector3(20, 30, 40);
constexpr Vector3 vector1 = Vector3(10, 10, 10);
constexpr Vector3 vector2 = Vector3(20, 30, 40);
CHECK_MESSAGE(
vector1.length_squared() == 300,
"Vector3 length_squared should work as expected and return exact result.");
CHECK_MESSAGE(
vector1.length() == doctest::Approx(10 * (real_t)Math_SQRT3),
vector1.length() == doctest::Approx(10 * (real_t)Math::SQRT3),
"Vector3 length should work as expected.");
CHECK_MESSAGE(
vector2.length_squared() == 2900,
@ -170,12 +166,12 @@ TEST_CASE("[Vector3] Length methods") {
}
TEST_CASE("[Vector3] Limiting methods") {
const Vector3 vector = Vector3(10, 10, 10);
constexpr Vector3 vector = Vector3(10, 10, 10);
CHECK_MESSAGE(
vector.limit_length().is_equal_approx(Vector3(Math_SQRT13, Math_SQRT13, Math_SQRT13)),
vector.limit_length().is_equal_approx(Vector3(Math::SQRT13, Math::SQRT13, Math::SQRT13)),
"Vector3 limit_length should work as expected.");
CHECK_MESSAGE(
vector.limit_length(5).is_equal_approx(5 * Vector3(Math_SQRT13, Math_SQRT13, Math_SQRT13)),
vector.limit_length(5).is_equal_approx(5 * Vector3(Math::SQRT13, Math::SQRT13, Math::SQRT13)),
"Vector3 limit_length should work as expected.");
CHECK_MESSAGE(
@ -197,10 +193,10 @@ TEST_CASE("[Vector3] Normalization methods") {
Vector3(1, 0, 0).normalized() == Vector3(1, 0, 0),
"Vector3 normalized should return the same vector for a normalized vector.");
CHECK_MESSAGE(
Vector3(1, 1, 0).normalized().is_equal_approx(Vector3(Math_SQRT12, Math_SQRT12, 0)),
Vector3(1, 1, 0).normalized().is_equal_approx(Vector3(Math::SQRT12, Math::SQRT12, 0)),
"Vector3 normalized should work as expected.");
CHECK_MESSAGE(
Vector3(1, 1, 1).normalized().is_equal_approx(Vector3(Math_SQRT13, Math_SQRT13, Math_SQRT13)),
Vector3(1, 1, 1).normalized().is_equal_approx(Vector3(Math::SQRT13, Math::SQRT13, Math::SQRT13)),
"Vector3 normalized should work as expected.");
Vector3 vector = Vector3(3.2, -5.4, 6);
@ -214,70 +210,70 @@ TEST_CASE("[Vector3] Normalization methods") {
}
TEST_CASE("[Vector3] Operators") {
const Vector3 decimal1 = Vector3(2.3, 4.9, 7.8);
const Vector3 decimal2 = Vector3(1.2, 3.4, 5.6);
const Vector3 power1 = Vector3(0.75, 1.5, 0.625);
const Vector3 power2 = Vector3(0.5, 0.125, 0.25);
const Vector3 int1 = Vector3(4, 5, 9);
const Vector3 int2 = Vector3(1, 2, 3);
constexpr Vector3 decimal1 = Vector3(2.3, 4.9, 7.8);
constexpr Vector3 decimal2 = Vector3(1.2, 3.4, 5.6);
constexpr Vector3 power1 = Vector3(0.75, 1.5, 0.625);
constexpr Vector3 power2 = Vector3(0.5, 0.125, 0.25);
constexpr Vector3 int1 = Vector3(4, 5, 9);
constexpr Vector3 int2 = Vector3(1, 2, 3);
CHECK_MESSAGE(
(decimal1 + decimal2).is_equal_approx(Vector3(3.5, 8.3, 13.4)),
"Vector3 addition should behave as expected.");
CHECK_MESSAGE(
static_assert(
(power1 + power2) == Vector3(1.25, 1.625, 0.875),
"Vector3 addition with powers of two should give exact results.");
CHECK_MESSAGE(
static_assert(
(int1 + int2) == Vector3(5, 7, 12),
"Vector3 addition with integers should give exact results.");
CHECK_MESSAGE(
(decimal1 - decimal2).is_equal_approx(Vector3(1.1, 1.5, 2.2)),
"Vector3 subtraction should behave as expected.");
CHECK_MESSAGE(
static_assert(
(power1 - power2) == Vector3(0.25, 1.375, 0.375),
"Vector3 subtraction with powers of two should give exact results.");
CHECK_MESSAGE(
static_assert(
(int1 - int2) == Vector3(3, 3, 6),
"Vector3 subtraction with integers should give exact results.");
CHECK_MESSAGE(
(decimal1 * decimal2).is_equal_approx(Vector3(2.76, 16.66, 43.68)),
"Vector3 multiplication should behave as expected.");
CHECK_MESSAGE(
static_assert(
(power1 * power2) == Vector3(0.375, 0.1875, 0.15625),
"Vector3 multiplication with powers of two should give exact results.");
CHECK_MESSAGE(
static_assert(
(int1 * int2) == Vector3(4, 10, 27),
"Vector3 multiplication with integers should give exact results.");
CHECK_MESSAGE(
(decimal1 / decimal2).is_equal_approx(Vector3(1.91666666666666666, 1.44117647058823529, 1.39285714285714286)),
"Vector3 division should behave as expected.");
CHECK_MESSAGE(
static_assert(
(power1 / power2) == Vector3(1.5, 12.0, 2.5),
"Vector3 division with powers of two should give exact results.");
CHECK_MESSAGE(
static_assert(
(int1 / int2) == Vector3(4, 2.5, 3),
"Vector3 division with integers should give exact results.");
CHECK_MESSAGE(
(decimal1 * 2).is_equal_approx(Vector3(4.6, 9.8, 15.6)),
"Vector3 multiplication should behave as expected.");
CHECK_MESSAGE(
static_assert(
(power1 * 2) == Vector3(1.5, 3, 1.25),
"Vector3 multiplication with powers of two should give exact results.");
CHECK_MESSAGE(
static_assert(
(int1 * 2) == Vector3(8, 10, 18),
"Vector3 multiplication with integers should give exact results.");
CHECK_MESSAGE(
(decimal1 / 2).is_equal_approx(Vector3(1.15, 2.45, 3.9)),
"Vector3 division should behave as expected.");
CHECK_MESSAGE(
static_assert(
(power1 / 2) == Vector3(0.375, 0.75, 0.3125),
"Vector3 division with powers of two should give exact results.");
CHECK_MESSAGE(
static_assert(
(int1 / 2) == Vector3(2, 2.5, 4.5),
"Vector3 division with integers should give exact results.");
@ -302,22 +298,22 @@ TEST_CASE("[Vector3] Operators") {
"Vector3 cast to String should work as expected.");
#ifdef REAL_T_IS_DOUBLE
CHECK_MESSAGE(
((String)Vector3(Math_E, Math_SQRT2, Math_SQRT3)) == "(2.71828182845905, 1.4142135623731, 1.73205080756888)",
((String)Vector3(Math::E, Math::SQRT2, Math::SQRT3)) == "(2.71828182845905, 1.4142135623731, 1.73205080756888)",
"Vector3 cast to String should print the correct amount of digits for real_t = double.");
#else
CHECK_MESSAGE(
((String)Vector3(Math_E, Math_SQRT2, Math_SQRT3)) == "(2.718282, 1.414214, 1.732051)",
((String)Vector3(Math::E, Math::SQRT2, Math::SQRT3)) == "(2.718282, 1.414214, 1.732051)",
"Vector3 cast to String should print the correct amount of digits for real_t = float.");
#endif // REAL_T_IS_DOUBLE
}
TEST_CASE("[Vector3] Other methods") {
const Vector3 vector = Vector3(1.2, 3.4, 5.6);
constexpr Vector3 vector = Vector3(1.2, 3.4, 5.6);
CHECK_MESSAGE(
vector.direction_to(Vector3()).is_equal_approx(-vector.normalized()),
"Vector3 direction_to should work as expected.");
CHECK_MESSAGE(
Vector3(1, 1, 1).direction_to(Vector3(2, 2, 2)).is_equal_approx(Vector3(Math_SQRT13, Math_SQRT13, Math_SQRT13)),
Vector3(1, 1, 1).direction_to(Vector3(2, 2, 2)).is_equal_approx(Vector3(Math::SQRT13, Math::SQRT13, Math::SQRT13)),
"Vector3 direction_to should work as expected.");
CHECK_MESSAGE(
vector.inverse().is_equal_approx(Vector3(1 / 1.2, 1 / 3.4, 1 / 5.6)),
@ -336,16 +332,16 @@ TEST_CASE("[Vector3] Other methods") {
"Vector3 posmodv should work as expected.");
CHECK_MESSAGE(
vector.rotated(Vector3(0, 1, 0), Math_TAU).is_equal_approx(vector),
vector.rotated(Vector3(0, 1, 0), Math::TAU).is_equal_approx(vector),
"Vector3 rotated should work as expected.");
CHECK_MESSAGE(
vector.rotated(Vector3(0, 1, 0), Math_TAU / 4).is_equal_approx(Vector3(5.6, 3.4, -1.2)),
vector.rotated(Vector3(0, 1, 0), Math::TAU / 4).is_equal_approx(Vector3(5.6, 3.4, -1.2)),
"Vector3 rotated should work as expected.");
CHECK_MESSAGE(
vector.rotated(Vector3(1, 0, 0), Math_TAU / 3).is_equal_approx(Vector3(1.2, -6.54974226119285642, 0.1444863728670914)),
vector.rotated(Vector3(1, 0, 0), Math::TAU / 3).is_equal_approx(Vector3(1.2, -6.54974226119285642, 0.1444863728670914)),
"Vector3 rotated should work as expected.");
CHECK_MESSAGE(
vector.rotated(Vector3(0, 0, 1), Math_TAU / 2).is_equal_approx(vector.rotated(Vector3(0, 0, 1), Math_TAU / -2)),
vector.rotated(Vector3(0, 0, 1), Math::TAU / 2).is_equal_approx(vector.rotated(Vector3(0, 0, 1), Math::TAU / -2)),
"Vector3 rotated should work as expected.");
CHECK_MESSAGE(
@ -365,9 +361,9 @@ TEST_CASE("[Vector3] Other methods") {
}
TEST_CASE("[Vector3] Plane methods") {
const Vector3 vector = Vector3(1.2, 3.4, 5.6);
const Vector3 vector_y = Vector3(0, 1, 0);
const Vector3 vector_normal = Vector3(0.88763458893247992491, 0.26300284116517923701, 0.37806658417494515320);
constexpr Vector3 vector = Vector3(1.2, 3.4, 5.6);
constexpr Vector3 vector_y = Vector3(0, 1, 0);
constexpr Vector3 vector_normal = Vector3(0.88763458893247992491, 0.26300284116517923701, 0.37806658417494515320);
CHECK_MESSAGE(
vector.bounce(vector_y) == Vector3(1.2, -3.4, 5.6),
"Vector3 bounce on a plane with normal of the Y axis should.");
@ -394,7 +390,7 @@ TEST_CASE("[Vector3] Plane methods") {
"Vector3 slide with normal should return expected value.");
// There's probably a better way to test these ones?
#ifdef MATH_CHECKS
const Vector3 vector_non_normal = Vector3(5.4, 1.6, 2.3);
constexpr Vector3 vector_non_normal = Vector3(5.4, 1.6, 2.3);
ERR_PRINT_OFF;
CHECK_MESSAGE(
vector.bounce(vector_non_normal).is_equal_approx(Vector3()),
@ -410,8 +406,8 @@ TEST_CASE("[Vector3] Plane methods") {
}
TEST_CASE("[Vector3] Rounding methods") {
const Vector3 vector1 = Vector3(1.2, 3.4, 5.6);
const Vector3 vector2 = Vector3(1.2, -3.4, -5.6);
constexpr Vector3 vector1 = Vector3(1.2, 3.4, 5.6);
constexpr Vector3 vector2 = Vector3(1.2, -3.4, -5.6);
CHECK_MESSAGE(
vector1.abs() == vector1,
"Vector3 abs should work as expected.");
@ -449,11 +445,11 @@ TEST_CASE("[Vector3] Rounding methods") {
}
TEST_CASE("[Vector3] Linear algebra methods") {
const Vector3 vector_x = Vector3(1, 0, 0);
const Vector3 vector_y = Vector3(0, 1, 0);
const Vector3 vector_z = Vector3(0, 0, 1);
const Vector3 a = Vector3(3.5, 8.5, 2.3);
const Vector3 b = Vector3(5.2, 4.6, 7.8);
constexpr Vector3 vector_x = Vector3(1, 0, 0);
constexpr Vector3 vector_y = Vector3(0, 1, 0);
constexpr Vector3 vector_z = Vector3(0, 0, 1);
constexpr Vector3 a = Vector3(3.5, 8.5, 2.3);
constexpr Vector3 b = Vector3(5.2, 4.6, 7.8);
CHECK_MESSAGE(
vector_x.cross(vector_y) == vector_z,
"Vector3 cross product of X and Y should give Z.");
@ -491,7 +487,7 @@ TEST_CASE("[Vector3] Linear algebra methods") {
}
TEST_CASE("[Vector3] Finite number checks") {
const double infinite[] = { NAN, INFINITY, -INFINITY };
constexpr double infinite[] = { Math::NaN, Math::INF, -Math::INF };
CHECK_MESSAGE(
Vector3(0, 1, 2).is_finite(),
@ -535,5 +531,3 @@ TEST_CASE("[Vector3] Finite number checks") {
}
} // namespace TestVector3
#endif // TEST_VECTOR3_H

View file

@ -28,8 +28,7 @@
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
/**************************************************************************/
#ifndef TEST_VECTOR3I_H
#define TEST_VECTOR3I_H
#pragma once
#include "core/math/vector3i.h"
#include "tests/test_macros.h"
@ -37,9 +36,9 @@
namespace TestVector3i {
TEST_CASE("[Vector3i] Constructor methods") {
const Vector3i vector_empty = Vector3i();
const Vector3i vector_zero = Vector3i(0, 0, 0);
CHECK_MESSAGE(
constexpr Vector3i vector_empty = Vector3i();
constexpr Vector3i vector_zero = Vector3i(0, 0, 0);
static_assert(
vector_empty == vector_zero,
"Vector3i Constructor with no inputs should return a zero Vector3i.");
}
@ -66,7 +65,7 @@ TEST_CASE("[Vector3i] Axis methods") {
}
TEST_CASE("[Vector3i] Clamp method") {
const Vector3i vector = Vector3i(10, 10, 10);
constexpr Vector3i vector = Vector3i(10, 10, 10);
CHECK_MESSAGE(
Vector3i(-5, 5, 15).clamp(Vector3i(), vector) == Vector3i(0, 5, 10),
"Vector3i clamp should work as expected.");
@ -76,13 +75,13 @@ TEST_CASE("[Vector3i] Clamp method") {
}
TEST_CASE("[Vector3i] Length methods") {
const Vector3i vector1 = Vector3i(10, 10, 10);
const Vector3i vector2 = Vector3i(20, 30, 40);
constexpr Vector3i vector1 = Vector3i(10, 10, 10);
constexpr Vector3i vector2 = Vector3i(20, 30, 40);
CHECK_MESSAGE(
vector1.length_squared() == 300,
"Vector3i length_squared should work as expected and return exact result.");
CHECK_MESSAGE(
vector1.length() == doctest::Approx(10 * Math_SQRT3),
vector1.length() == doctest::Approx(10 * Math::SQRT3),
"Vector3i length should work as expected.");
CHECK_MESSAGE(
vector2.length_squared() == 2900,
@ -99,26 +98,26 @@ TEST_CASE("[Vector3i] Length methods") {
}
TEST_CASE("[Vector3i] Operators") {
const Vector3i vector1 = Vector3i(4, 5, 9);
const Vector3i vector2 = Vector3i(1, 2, 3);
constexpr Vector3i vector1 = Vector3i(4, 5, 9);
constexpr Vector3i vector2 = Vector3i(1, 2, 3);
CHECK_MESSAGE(
static_assert(
(vector1 + vector2) == Vector3i(5, 7, 12),
"Vector3i addition with integers should give exact results.");
CHECK_MESSAGE(
static_assert(
(vector1 - vector2) == Vector3i(3, 3, 6),
"Vector3i subtraction with integers should give exact results.");
CHECK_MESSAGE(
static_assert(
(vector1 * vector2) == Vector3i(4, 10, 27),
"Vector3i multiplication with integers should give exact results.");
CHECK_MESSAGE(
static_assert(
(vector1 / vector2) == Vector3i(4, 2, 3),
"Vector3i division with integers should give exact results.");
CHECK_MESSAGE(
static_assert(
(vector1 * 2) == Vector3i(8, 10, 18),
"Vector3i multiplication with integers should give exact results.");
CHECK_MESSAGE(
static_assert(
(vector1 / 2) == Vector3i(2, 2, 4),
"Vector3i division with integers should give exact results.");
@ -134,7 +133,7 @@ TEST_CASE("[Vector3i] Operators") {
}
TEST_CASE("[Vector3i] Other methods") {
const Vector3i vector = Vector3i(1, 3, -7);
constexpr Vector3i vector = Vector3i(1, 3, -7);
CHECK_MESSAGE(
vector.min(Vector3i(3, 2, 5)) == Vector3i(1, 2, -7),
@ -149,8 +148,8 @@ TEST_CASE("[Vector3i] Other methods") {
}
TEST_CASE("[Vector3i] Abs and sign methods") {
const Vector3i vector1 = Vector3i(1, 3, 5);
const Vector3i vector2 = Vector3i(1, -3, -5);
constexpr Vector3i vector1 = Vector3i(1, 3, 5);
constexpr Vector3i vector2 = Vector3i(1, -3, -5);
CHECK_MESSAGE(
vector1.abs() == vector1,
"Vector3i abs should work as expected.");
@ -166,5 +165,3 @@ TEST_CASE("[Vector3i] Abs and sign methods") {
"Vector3i sign should work as expected.");
}
} // namespace TestVector3i
#endif // TEST_VECTOR3I_H

View file

@ -28,20 +28,17 @@
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
/**************************************************************************/
#ifndef TEST_VECTOR4_H
#define TEST_VECTOR4_H
#pragma once
#include "core/math/vector4.h"
#include "tests/test_macros.h"
#define Math_SQRT3 1.7320508075688772935274463415059
namespace TestVector4 {
TEST_CASE("[Vector4] Constructor methods") {
const Vector4 vector_empty = Vector4();
const Vector4 vector_zero = Vector4(0.0, 0.0, 0.0, 0.0);
CHECK_MESSAGE(
constexpr Vector4 vector_empty = Vector4();
constexpr Vector4 vector_zero = Vector4(0.0, 0.0, 0.0, 0.0);
static_assert(
vector_empty == vector_zero,
"Vector4 Constructor with no inputs should return a zero Vector4.");
}
@ -68,8 +65,8 @@ TEST_CASE("[Vector4] Axis methods") {
}
TEST_CASE("[Vector4] Interpolation methods") {
const Vector4 vector1 = Vector4(1, 2, 3, 4);
const Vector4 vector2 = Vector4(4, 5, 6, 7);
constexpr Vector4 vector1 = Vector4(1, 2, 3, 4);
constexpr Vector4 vector2 = Vector4(4, 5, 6, 7);
CHECK_MESSAGE(
vector1.lerp(vector2, 0.5) == Vector4(2.5, 3.5, 4.5, 5.5),
"Vector4 lerp should work as expected.");
@ -85,8 +82,8 @@ TEST_CASE("[Vector4] Interpolation methods") {
}
TEST_CASE("[Vector4] Length methods") {
const Vector4 vector1 = Vector4(10, 10, 10, 10);
const Vector4 vector2 = Vector4(20, 30, 40, 50);
constexpr Vector4 vector1 = Vector4(10, 10, 10, 10);
constexpr Vector4 vector2 = Vector4(20, 30, 40, 50);
CHECK_MESSAGE(
vector1.length_squared() == 400,
"Vector4 length_squared should work as expected and return exact result.");
@ -108,7 +105,7 @@ TEST_CASE("[Vector4] Length methods") {
}
TEST_CASE("[Vector4] Limiting methods") {
const Vector4 vector = Vector4(10, 10, 10, 10);
constexpr Vector4 vector = Vector4(10, 10, 10, 10);
CHECK_MESSAGE(
Vector4(-5, 5, 15, -15).clamp(Vector4(), vector) == Vector4(0, 5, 10, 0),
"Vector4 clamp should work as expected.");
@ -128,7 +125,7 @@ TEST_CASE("[Vector4] Normalization methods") {
Vector4(1, 0, 0, 0).normalized() == Vector4(1, 0, 0, 0),
"Vector4 normalized should return the same vector for a normalized vector.");
CHECK_MESSAGE(
Vector4(1, 1, 0, 0).normalized().is_equal_approx(Vector4(Math_SQRT12, Math_SQRT12, 0, 0)),
Vector4(1, 1, 0, 0).normalized().is_equal_approx(Vector4(Math::SQRT12, Math::SQRT12, 0, 0)),
"Vector4 normalized should work as expected.");
CHECK_MESSAGE(
Vector4(1, 1, 1, 1).normalized().is_equal_approx(Vector4(0.5, 0.5, 0.5, 0.5)),
@ -136,73 +133,73 @@ TEST_CASE("[Vector4] Normalization methods") {
}
TEST_CASE("[Vector4] Operators") {
const Vector4 decimal1 = Vector4(2.3, 4.9, 7.8, 3.2);
const Vector4 decimal2 = Vector4(1.2, 3.4, 5.6, 1.7);
const Vector4 power1 = Vector4(0.75, 1.5, 0.625, 0.125);
const Vector4 power2 = Vector4(0.5, 0.125, 0.25, 0.75);
const Vector4 int1 = Vector4(4, 5, 9, 2);
const Vector4 int2 = Vector4(1, 2, 3, 1);
constexpr Vector4 decimal1 = Vector4(2.3, 4.9, 7.8, 3.2);
constexpr Vector4 decimal2 = Vector4(1.2, 3.4, 5.6, 1.7);
constexpr Vector4 power1 = Vector4(0.75, 1.5, 0.625, 0.125);
constexpr Vector4 power2 = Vector4(0.5, 0.125, 0.25, 0.75);
constexpr Vector4 int1 = Vector4(4, 5, 9, 2);
constexpr Vector4 int2 = Vector4(1, 2, 3, 1);
CHECK_MESSAGE(
static_assert(
-decimal1 == Vector4(-2.3, -4.9, -7.8, -3.2),
"Vector4 change of sign should work as expected.");
CHECK_MESSAGE(
(decimal1 + decimal2).is_equal_approx(Vector4(3.5, 8.3, 13.4, 4.9)),
"Vector4 addition should behave as expected.");
CHECK_MESSAGE(
static_assert(
(power1 + power2) == Vector4(1.25, 1.625, 0.875, 0.875),
"Vector4 addition with powers of two should give exact results.");
CHECK_MESSAGE(
static_assert(
(int1 + int2) == Vector4(5, 7, 12, 3),
"Vector4 addition with integers should give exact results.");
CHECK_MESSAGE(
(decimal1 - decimal2).is_equal_approx(Vector4(1.1, 1.5, 2.2, 1.5)),
"Vector4 subtraction should behave as expected.");
CHECK_MESSAGE(
static_assert(
(power1 - power2) == Vector4(0.25, 1.375, 0.375, -0.625),
"Vector4 subtraction with powers of two should give exact results.");
CHECK_MESSAGE(
static_assert(
(int1 - int2) == Vector4(3, 3, 6, 1),
"Vector4 subtraction with integers should give exact results.");
CHECK_MESSAGE(
(decimal1 * decimal2).is_equal_approx(Vector4(2.76, 16.66, 43.68, 5.44)),
"Vector4 multiplication should behave as expected.");
CHECK_MESSAGE(
static_assert(
(power1 * power2) == Vector4(0.375, 0.1875, 0.15625, 0.09375),
"Vector4 multiplication with powers of two should give exact results.");
CHECK_MESSAGE(
static_assert(
(int1 * int2) == Vector4(4, 10, 27, 2),
"Vector4 multiplication with integers should give exact results.");
CHECK_MESSAGE(
(decimal1 / decimal2).is_equal_approx(Vector4(1.91666666666666666, 1.44117647058823529, 1.39285714285714286, 1.88235294118)),
"Vector4 division should behave as expected.");
CHECK_MESSAGE(
static_assert(
(power1 / power2) == Vector4(1.5, 12.0, 2.5, 1.0 / 6.0),
"Vector4 division with powers of two should give exact results.");
CHECK_MESSAGE(
static_assert(
(int1 / int2) == Vector4(4, 2.5, 3, 2),
"Vector4 division with integers should give exact results.");
CHECK_MESSAGE(
(decimal1 * 2).is_equal_approx(Vector4(4.6, 9.8, 15.6, 6.4)),
"Vector4 multiplication should behave as expected.");
CHECK_MESSAGE(
static_assert(
(power1 * 2) == Vector4(1.5, 3, 1.25, 0.25),
"Vector4 multiplication with powers of two should give exact results.");
CHECK_MESSAGE(
static_assert(
(int1 * 2) == Vector4(8, 10, 18, 4),
"Vector4 multiplication with integers should give exact results.");
CHECK_MESSAGE(
(decimal1 / 2).is_equal_approx(Vector4(1.15, 2.45, 3.9, 1.6)),
"Vector4 division should behave as expected.");
CHECK_MESSAGE(
static_assert(
(power1 / 2) == Vector4(0.375, 0.75, 0.3125, 0.0625),
"Vector4 division with powers of two should give exact results.");
CHECK_MESSAGE(
static_assert(
(int1 / 2) == Vector4(2, 2.5, 4.5, 1),
"Vector4 division with integers should give exact results.");
@ -217,17 +214,17 @@ TEST_CASE("[Vector4] Operators") {
"Vector4 cast to String should work as expected.");
#ifdef REAL_T_IS_DOUBLE
CHECK_MESSAGE(
((String)Vector4(Math_E, Math_SQRT2, Math_SQRT3, Math_SQRT3)) == "(2.71828182845905, 1.4142135623731, 1.73205080756888, 1.73205080756888)",
((String)Vector4(Math::E, Math::SQRT2, Math::SQRT3, Math::SQRT3)) == "(2.71828182845905, 1.4142135623731, 1.73205080756888, 1.73205080756888)",
"Vector4 cast to String should print the correct amount of digits for real_t = double.");
#else
CHECK_MESSAGE(
((String)Vector4(Math_E, Math_SQRT2, Math_SQRT3, Math_SQRT3)) == "(2.718282, 1.414214, 1.732051, 1.732051)",
((String)Vector4(Math::E, Math::SQRT2, Math::SQRT3, Math::SQRT3)) == "(2.718282, 1.414214, 1.732051, 1.732051)",
"Vector4 cast to String should print the correct amount of digits for real_t = float.");
#endif // REAL_T_IS_DOUBLE
}
TEST_CASE("[Vector4] Other methods") {
const Vector4 vector = Vector4(1.2, 3.4, 5.6, 1.6);
constexpr Vector4 vector = Vector4(1.2, 3.4, 5.6, 1.6);
CHECK_MESSAGE(
vector.direction_to(Vector4()).is_equal_approx(-vector.normalized()),
"Vector4 direction_to should work as expected.");
@ -266,8 +263,8 @@ TEST_CASE("[Vector4] Other methods") {
}
TEST_CASE("[Vector4] Rounding methods") {
const Vector4 vector1 = Vector4(1.2, 3.4, 5.6, 1.6);
const Vector4 vector2 = Vector4(1.2, -3.4, -5.6, -1.6);
constexpr Vector4 vector1 = Vector4(1.2, 3.4, 5.6, 1.6);
constexpr Vector4 vector2 = Vector4(1.2, -3.4, -5.6, -1.6);
CHECK_MESSAGE(
vector1.abs() == vector1,
"Vector4 abs should work as expected.");
@ -304,10 +301,10 @@ TEST_CASE("[Vector4] Rounding methods") {
}
TEST_CASE("[Vector4] Linear algebra methods") {
const Vector4 vector_x = Vector4(1, 0, 0, 0);
const Vector4 vector_y = Vector4(0, 1, 0, 0);
const Vector4 vector1 = Vector4(1.7, 2.3, 1, 9.1);
const Vector4 vector2 = Vector4(-8.2, -16, 3, 2.4);
constexpr Vector4 vector_x = Vector4(1, 0, 0, 0);
constexpr Vector4 vector_y = Vector4(0, 1, 0, 0);
constexpr Vector4 vector1 = Vector4(1.7, 2.3, 1, 9.1);
constexpr Vector4 vector2 = Vector4(-8.2, -16, 3, 2.4);
CHECK_MESSAGE(
vector_x.dot(vector_y) == 0.0,
@ -324,7 +321,7 @@ TEST_CASE("[Vector4] Linear algebra methods") {
}
TEST_CASE("[Vector4] Finite number checks") {
const double infinite[] = { NAN, INFINITY, -INFINITY };
constexpr double infinite[] = { Math::NaN, Math::INF, -Math::INF };
CHECK_MESSAGE(
Vector4(0, 1, 2, 3).is_finite(),
@ -401,5 +398,3 @@ TEST_CASE("[Vector4] Finite number checks") {
}
} // namespace TestVector4
#endif // TEST_VECTOR4_H

View file

@ -28,8 +28,7 @@
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
/**************************************************************************/
#ifndef TEST_VECTOR4I_H
#define TEST_VECTOR4I_H
#pragma once
#include "core/math/vector4i.h"
#include "tests/test_macros.h"
@ -37,9 +36,9 @@
namespace TestVector4i {
TEST_CASE("[Vector4i] Constructor methods") {
const Vector4i vector_empty = Vector4i();
const Vector4i vector_zero = Vector4i(0, 0, 0, 0);
CHECK_MESSAGE(
constexpr Vector4i vector_empty = Vector4i();
constexpr Vector4i vector_zero = Vector4i(0, 0, 0, 0);
static_assert(
vector_empty == vector_zero,
"Vector4i Constructor with no inputs should return a zero Vector4i.");
}
@ -66,7 +65,7 @@ TEST_CASE("[Vector4i] Axis methods") {
}
TEST_CASE("[Vector4i] Clamp method") {
const Vector4i vector = Vector4i(10, 10, 10, 10);
constexpr Vector4i vector = Vector4i(10, 10, 10, 10);
CHECK_MESSAGE(
Vector4i(-5, 5, 15, INT_MAX).clamp(Vector4i(), vector) == Vector4i(0, 5, 10, 10),
"Vector4i clamp should work as expected.");
@ -76,8 +75,8 @@ TEST_CASE("[Vector4i] Clamp method") {
}
TEST_CASE("[Vector4i] Length methods") {
const Vector4i vector1 = Vector4i(10, 10, 10, 10);
const Vector4i vector2 = Vector4i(20, 30, 40, 50);
constexpr Vector4i vector1 = Vector4i(10, 10, 10, 10);
constexpr Vector4i vector2 = Vector4i(20, 30, 40, 50);
CHECK_MESSAGE(
vector1.length_squared() == 400,
"Vector4i length_squared should work as expected and return exact result.");
@ -99,29 +98,29 @@ TEST_CASE("[Vector4i] Length methods") {
}
TEST_CASE("[Vector4i] Operators") {
const Vector4i vector1 = Vector4i(4, 5, 9, 2);
const Vector4i vector2 = Vector4i(1, 2, 3, 4);
constexpr Vector4i vector1 = Vector4i(4, 5, 9, 2);
constexpr Vector4i vector2 = Vector4i(1, 2, 3, 4);
CHECK_MESSAGE(
static_assert(
-vector1 == Vector4i(-4, -5, -9, -2),
"Vector4i change of sign should work as expected.");
CHECK_MESSAGE(
static_assert(
(vector1 + vector2) == Vector4i(5, 7, 12, 6),
"Vector4i addition with integers should give exact results.");
CHECK_MESSAGE(
static_assert(
(vector1 - vector2) == Vector4i(3, 3, 6, -2),
"Vector4i subtraction with integers should give exact results.");
CHECK_MESSAGE(
static_assert(
(vector1 * vector2) == Vector4i(4, 10, 27, 8),
"Vector4i multiplication with integers should give exact results.");
CHECK_MESSAGE(
static_assert(
(vector1 / vector2) == Vector4i(4, 2, 3, 0),
"Vector4i division with integers should give exact results.");
CHECK_MESSAGE(
static_assert(
(vector1 * 2) == Vector4i(8, 10, 18, 4),
"Vector4i multiplication with integers should give exact results.");
CHECK_MESSAGE(
static_assert(
(vector1 / 2) == Vector4i(2, 2, 4, 1),
"Vector4i division with integers should give exact results.");
@ -137,7 +136,7 @@ TEST_CASE("[Vector4i] Operators") {
}
TEST_CASE("[Vector3i] Other methods") {
const Vector4i vector = Vector4i(1, 3, -7, 13);
constexpr Vector4i vector = Vector4i(1, 3, -7, 13);
CHECK_MESSAGE(
vector.min(Vector4i(3, 2, 5, 8)) == Vector4i(1, 2, -7, 8),
@ -153,8 +152,8 @@ TEST_CASE("[Vector3i] Other methods") {
}
TEST_CASE("[Vector4i] Abs and sign methods") {
const Vector4i vector1 = Vector4i(1, 3, 5, 7);
const Vector4i vector2 = Vector4i(1, -3, -5, 7);
constexpr Vector4i vector1 = Vector4i(1, 3, 5, 7);
constexpr Vector4i vector2 = Vector4i(1, -3, -5, 7);
CHECK_MESSAGE(
vector1.abs() == vector1,
"Vector4i abs should work as expected.");
@ -170,5 +169,3 @@ TEST_CASE("[Vector4i] Abs and sign methods") {
"Vector4i sign should work as expected.");
}
} // namespace TestVector4i
#endif // TEST_VECTOR4I_H

View file

@ -28,8 +28,7 @@
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
/**************************************************************************/
#ifndef TEST_CLASS_DB_H
#define TEST_CLASS_DB_H
#pragma once
#include "core/core_bind.h"
#include "core/core_constants.h"
@ -415,6 +414,9 @@ void validate_argument(const Context &p_context, const ExposedClass &p_class, co
#ifdef DEBUG_METHODS_ENABLED
TEST_COND((p_arg.name.is_empty() || p_arg.name.begins_with("_unnamed_arg")),
vformat("Unnamed argument in position %d of %s '%s.%s'.", p_arg.position, p_owner_type, p_class.name, p_owner_name));
TEST_FAIL_COND((p_arg.name != "@varargs@" && !p_arg.name.is_valid_ascii_identifier()),
vformat("Invalid argument name '%s' of %s '%s.%s'.", p_arg.name, p_owner_type, p_class.name, p_owner_name));
#endif // DEBUG_METHODS_ENABLED
const ExposedClass *arg_class = p_context.find_exposed_class(p_arg.type);
@ -658,9 +660,8 @@ void add_exposed_classes(Context &r_context) {
method.return_type.name = Variant::get_type_name(return_info.type);
}
int i = 0;
for (List<PropertyInfo>::ConstIterator itr = method_info.arguments.begin(); itr != method_info.arguments.end(); ++itr, ++i) {
const PropertyInfo &arg_info = *itr;
for (int64_t i = 0; i < method_info.arguments.size(); ++i) {
const PropertyInfo &arg_info = method_info.arguments[i];
String orig_arg_name = arg_info.name;
@ -732,9 +733,8 @@ void add_exposed_classes(Context &r_context) {
TEST_FAIL_COND(!String(signal.name).is_valid_ascii_identifier(),
"Signal name is not a valid identifier: '", exposed_class.name, ".", signal.name, "'.");
int i = 0;
for (List<PropertyInfo>::ConstIterator itr = method_info.arguments.begin(); itr != method_info.arguments.end(); ++itr, ++i) {
const PropertyInfo &arg_info = *itr;
for (int64_t i = 0; i < method_info.arguments.size(); ++i) {
const PropertyInfo &arg_info = method_info.arguments[i];
String orig_arg_name = arg_info.name;
@ -900,5 +900,3 @@ TEST_SUITE("[ClassDB]") {
}
}
} // namespace TestClassDB
#endif // TEST_CLASS_DB_H

View file

@ -28,8 +28,7 @@
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
/**************************************************************************/
#ifndef TEST_METHOD_BIND_H
#define TEST_METHOD_BIND_H
#pragma once
#include "core/object/class_db.h"
@ -56,6 +55,8 @@ public:
};
class ObjectSubclass : public Object {
GDSOFTCLASS(ObjectSubclass, Object);
public:
int value = 1;
};
@ -171,5 +172,3 @@ TEST_CASE("[MethodBind] check all method binds") {
memdelete(mbt);
}
} // namespace TestMethodBind
#endif // TEST_METHOD_BIND_H

View file

@ -28,8 +28,7 @@
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
/**************************************************************************/
#ifndef TEST_OBJECT_H
#define TEST_OBJECT_H
#pragma once
#include "core/object/class_db.h"
#include "core/object/object.h"
@ -144,15 +143,6 @@ TEST_CASE("[Object] Core getters") {
CHECK_MESSAGE(
object.get_save_class() == "Object",
"The returned save class should match the expected value.");
List<String> inheritance_list;
object.get_inheritance_list_static(&inheritance_list);
CHECK_MESSAGE(
inheritance_list.size() == 1,
"The inheritance list should consist of Object only");
CHECK_MESSAGE(
inheritance_list.front()->get() == "Object",
"The inheritance list should consist of Object only");
}
TEST_CASE("[Object] Metadata") {
@ -429,8 +419,7 @@ TEST_CASE("[Object] Signals") {
}
SUBCASE("Emitting an existing signal should call the connected method") {
Array empty_signal_args;
empty_signal_args.push_back(Array());
Array empty_signal_args = { {} };
SIGNAL_WATCH(&object, "my_custom_signal");
SIGNAL_CHECK_FALSE("my_custom_signal");
@ -466,72 +455,75 @@ TEST_CASE("[Object] Signals") {
}
}
class NotificationObject1 : public Object {
GDCLASS(NotificationObject1, Object);
class NotificationObjectSuperclass : public Object {
GDCLASS(NotificationObjectSuperclass, Object);
protected:
void _notification(int p_what) {
switch (p_what) {
case 12345: {
order_internal1 = order_global++;
} break;
}
order_superclass = ++order_global;
}
public:
static int order_global;
int order_internal1 = -1;
void reset_order() {
order_internal1 = -1;
order_global = 1;
}
static inline int order_global = 0;
int order_superclass = -1;
};
int NotificationObject1::order_global = 1;
class NotificationObject2 : public NotificationObject1 {
GDCLASS(NotificationObject2, NotificationObject1);
class NotificationObjectSubclass : public NotificationObjectSuperclass {
GDCLASS(NotificationObjectSubclass, NotificationObjectSuperclass);
protected:
void _notification(int p_what) {
switch (p_what) {
case 12345: {
order_internal2 = order_global++;
} break;
}
order_subclass = ++order_global;
}
public:
int order_internal2 = -1;
void reset_order() {
NotificationObject1::reset_order();
order_internal2 = -1;
int order_subclass = -1;
};
class NotificationScriptInstance : public _MockScriptInstance {
void notification(int p_notification, bool p_reversed) override {
order_script = ++NotificationObjectSuperclass::order_global;
}
public:
int order_script = -1;
};
TEST_CASE("[Object] Notification order") { // GH-52325
NotificationObject2 *test_notification_object = memnew(NotificationObject2);
NotificationObjectSubclass *object = memnew(NotificationObjectSubclass);
NotificationScriptInstance *script = memnew(NotificationScriptInstance);
object->set_script_instance(script);
SUBCASE("regular order") {
test_notification_object->notification(12345, false);
NotificationObjectSubclass::order_global = 0;
object->order_superclass = -1;
object->order_subclass = -1;
script->order_script = -1;
object->notification(12345, false);
CHECK_EQ(test_notification_object->order_internal1, 1);
CHECK_EQ(test_notification_object->order_internal2, 2);
test_notification_object->reset_order();
CHECK_EQ(object->order_superclass, 1);
CHECK_EQ(object->order_subclass, 2);
// TODO If an extension is attached, it should come here.
CHECK_EQ(script->order_script, 3);
CHECK_EQ(NotificationObjectSubclass::order_global, 3);
}
SUBCASE("reverse order") {
test_notification_object->notification(12345, true);
NotificationObjectSubclass::order_global = 0;
object->order_superclass = -1;
object->order_subclass = -1;
script->order_script = -1;
object->notification(12345, true);
CHECK_EQ(test_notification_object->order_internal1, 2);
CHECK_EQ(test_notification_object->order_internal2, 1);
test_notification_object->reset_order();
CHECK_EQ(script->order_script, 1);
// TODO If an extension is attached, it should come here.
CHECK_EQ(object->order_subclass, 2);
CHECK_EQ(object->order_superclass, 3);
CHECK_EQ(NotificationObjectSubclass::order_global, 3);
}
memdelete(test_notification_object);
memdelete(object);
}
TEST_CASE("[Object] Destruction at the end of the call chain is safe") {
@ -603,5 +595,3 @@ TEST_CASE("[Object] Destruction at the end of the call chain is safe") {
}
} // namespace TestObject
#endif // TEST_OBJECT_H

View file

@ -28,8 +28,7 @@
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
/**************************************************************************/
#ifndef TEST_UNDO_REDO_H
#define TEST_UNDO_REDO_H
#pragma once
#include "core/object/undo_redo.h"
#include "tests/test_macros.h"
@ -198,5 +197,3 @@ TEST_CASE("[UndoRedo] Merge Method UndoRedo") {
}
} //namespace TestUndoRedo
#endif // TEST_UNDO_REDO_H

View file

@ -28,8 +28,7 @@
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
/**************************************************************************/
#ifndef TEST_OS_H
#define TEST_OS_H
#pragma once
#include "core/os/os.h"
@ -202,5 +201,3 @@ TEST_CASE("[OS] Execute") {
}
} // namespace TestOS
#endif // TEST_OS_H

View file

@ -28,8 +28,7 @@
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
/**************************************************************************/
#ifndef TEST_FUZZY_SEARCH_H
#define TEST_FUZZY_SEARCH_H
#pragma once
#include "core/string/fuzzy_search.h"
#include "tests/test_macros.h"
@ -79,5 +78,3 @@ TEST_CASE("[FuzzySearch] Test fuzzy search results") {
}
} //namespace TestFuzzySearch
#endif // TEST_FUZZY_SEARCH_H

View file

@ -28,8 +28,7 @@
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
/**************************************************************************/
#ifndef TEST_NODE_PATH_H
#define TEST_NODE_PATH_H
#pragma once
#include "core/string/node_path.h"
@ -224,5 +223,3 @@ TEST_CASE("[NodePath] Slice") {
}
} // namespace TestNodePath
#endif // TEST_NODE_PATH_H

View file

@ -28,8 +28,7 @@
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
/**************************************************************************/
#ifndef TEST_STRING_H
#define TEST_STRING_H
#pragma once
#include "core/string/ustring.h"
@ -60,7 +59,7 @@ TEST_CASE("[String] Assign from Latin-1 char string (copycon)") {
const String &t1(s);
CHECK(u32scmp(t1.get_data(), U"Sheep") == 0);
String t2 = String("Sheep", 3);
String t2 = String::latin1(Span("Sheep", 3));
CHECK(u32scmp(t2.get_data(), U"She") == 0);
}
@ -88,34 +87,38 @@ TEST_CASE("[String] UTF8") {
/* how can i embed UTF in here? */
static const char32_t u32str[] = { 0x0045, 0x0020, 0x304A, 0x360F, 0x3088, 0x3046, 0x1F3A4, 0 };
static const uint8_t u8str[] = { 0x45, 0x20, 0xE3, 0x81, 0x8A, 0xE3, 0x98, 0x8F, 0xE3, 0x82, 0x88, 0xE3, 0x81, 0x86, 0xF0, 0x9F, 0x8E, 0xA4, 0 };
String s = u32str;
Error err = s.parse_utf8(s.utf8().get_data());
String expected = u32str;
String parsed;
Error err = parsed.append_utf8(expected.utf8().get_data());
CHECK(err == OK);
CHECK(s == u32str);
CHECK(parsed == u32str);
err = s.parse_utf8((const char *)u8str);
parsed.clear();
err = parsed.append_utf8((const char *)u8str);
CHECK(err == OK);
CHECK(s == u32str);
CHECK(parsed == u32str);
CharString cs = (const char *)u8str;
CHECK(String::utf8(cs) == s);
CHECK(String::utf8(cs) == parsed);
}
TEST_CASE("[String] UTF16") {
/* how can i embed UTF in here? */
static const char32_t u32str[] = { 0x0045, 0x0020, 0x304A, 0x360F, 0x3088, 0x3046, 0x1F3A4, 0 };
static const char16_t u16str[] = { 0x0045, 0x0020, 0x304A, 0x360F, 0x3088, 0x3046, 0xD83C, 0xDFA4, 0 };
String s = u32str;
Error err = s.parse_utf16(s.utf16().get_data());
String expected = u32str;
String parsed;
Error err = parsed.append_utf16(expected.utf16().get_data());
CHECK(err == OK);
CHECK(s == u32str);
CHECK(parsed == u32str);
err = s.parse_utf16(u16str);
parsed.clear();
err = parsed.append_utf16(u16str);
CHECK(err == OK);
CHECK(s == u32str);
CHECK(parsed == u32str);
Char16String cs = u16str;
CHECK(String::utf16(cs) == s);
CHECK(String::utf16(cs) == parsed);
}
TEST_CASE("[String] UTF8 with BOM") {
@ -123,7 +126,7 @@ TEST_CASE("[String] UTF8 with BOM") {
static const char32_t u32str[] = { 0x0045, 0x0020, 0x304A, 0x360F, 0x3088, 0x3046, 0x1F3A4, 0 };
static const uint8_t u8str[] = { 0xEF, 0xBB, 0xBF, 0x45, 0x20, 0xE3, 0x81, 0x8A, 0xE3, 0x98, 0x8F, 0xE3, 0x82, 0x88, 0xE3, 0x81, 0x86, 0xF0, 0x9F, 0x8E, 0xA4, 0 };
String s;
Error err = s.parse_utf8((const char *)u8str);
Error err = s.append_utf8((const char *)u8str);
CHECK(err == OK);
CHECK(s == u32str);
@ -137,11 +140,12 @@ TEST_CASE("[String] UTF16 with BOM") {
static const char16_t u16str[] = { 0xFEFF, 0x0020, 0x0045, 0x304A, 0x360F, 0x3088, 0x3046, 0xD83C, 0xDFA4, 0 };
static const char16_t u16str_swap[] = { 0xFFFE, 0x2000, 0x4500, 0x4A30, 0x0F36, 0x8830, 0x4630, 0x3CD8, 0xA4DF, 0 };
String s;
Error err = s.parse_utf16(u16str);
Error err = s.append_utf16(u16str);
CHECK(err == OK);
CHECK(s == u32str);
err = s.parse_utf16(u16str_swap);
s.clear();
err = s.append_utf16(u16str_swap);
CHECK(err == OK);
CHECK(s == u32str);
@ -156,23 +160,23 @@ TEST_CASE("[String] UTF8 with CR") {
const String base = U"Hello darkness\r\nMy old friend\nI've come to talk\rWith you again";
String keep_cr;
Error err = keep_cr.parse_utf8(base.utf8().get_data());
Error err = keep_cr.append_utf8(base.utf8().get_data());
CHECK(err == OK);
CHECK(keep_cr == base);
String no_cr;
err = no_cr.parse_utf8(base.utf8().get_data(), -1, true); // Skip CR.
err = no_cr.append_utf8(base.utf8().get_data(), -1, true); // Skip CR.
CHECK(err == OK);
CHECK(no_cr == base.replace("\r", ""));
}
TEST_CASE("[String] Invalid UTF8 (non-standard)") {
TEST_CASE("[String] Invalid UTF8 (non shortest form sequence)") {
ERR_PRINT_OFF
static const uint8_t u8str[] = { 0x45, 0xE3, 0x81, 0x8A, 0xE3, 0x82, 0x88, 0xE3, 0x81, 0x86, 0xF0, 0x9F, 0x8E, 0xA4, 0xF0, 0x82, 0x82, 0xAC, 0xED, 0xA0, 0x81, 0 };
// + +2 +2 +2 +3 overlong +3 unpaired +2
static const char32_t u32str[] = { 0x45, 0x304A, 0x3088, 0x3046, 0x1F3A4, 0x20AC, 0xFFFD, 0 };
// Examples from the unicode standard : 3.9 Unicode Encoding Forms - Table 3.8.
static const uint8_t u8str[] = { 0xC0, 0xAF, 0xE0, 0x80, 0xBF, 0xF0, 0x81, 0x82, 0x41, 0 };
static const char32_t u32str[] = { 0xFFFD, 0xFFFD, 0xFFFD, 0xFFFD, 0xFFFD, 0xFFFD, 0xFFFD, 0xFFFD, 0x41, 0 };
String s;
Error err = s.parse_utf8((const char *)u8str);
Error err = s.append_utf8((const char *)u8str);
CHECK(err == ERR_INVALID_DATA);
CHECK(s == u32str);
@ -181,13 +185,43 @@ TEST_CASE("[String] Invalid UTF8 (non-standard)") {
ERR_PRINT_ON
}
TEST_CASE("[String] Invalid UTF8 (unrecoverable)") {
TEST_CASE("[String] Invalid UTF8 (ill formed sequences for surrogates)") {
ERR_PRINT_OFF
static const uint8_t u8str[] = { 0x45, 0xE3, 0x81, 0x8A, 0x8F, 0xE3, 0xE3, 0x98, 0x8F, 0xE3, 0x82, 0x88, 0xE3, 0x81, 0x86, 0xC0, 0x80, 0xF0, 0x9F, 0x8E, 0xA4, 0xF0, 0x82, 0x82, 0xAC, 0xED, 0xA0, 0x81, 0 };
// + +2 inv +2 inv inv inv +2 +2 ovl NUL +1 +3 overlong +3 unpaired +2
static const char32_t u32str[] = { 0x45, 0x304A, 0xFFFD, 0xFFFD, 0xFFFD, 0xFFFD, 0x3088, 0x3046, 0xFFFD, 0x1F3A4, 0x20AC, 0xFFFD, 0 };
// Examples from the unicode standard : 3.9 Unicode Encoding Forms - Table 3.9.
static const uint8_t u8str[] = { 0xED, 0xA0, 0x80, 0xED, 0xBF, 0xBF, 0xED, 0xAF, 0x41, 0 };
static const char32_t u32str[] = { 0xFFFD, 0xFFFD, 0xFFFD, 0xFFFD, 0xFFFD, 0xFFFD, 0xFFFD, 0xFFFD, 0x41, 0 };
String s;
Error err = s.parse_utf8((const char *)u8str);
Error err = s.append_utf8((const char *)u8str);
CHECK(err == ERR_INVALID_DATA);
CHECK(s == u32str);
CharString cs = (const char *)u8str;
CHECK(String::utf8(cs) == s);
ERR_PRINT_ON
}
TEST_CASE("[String] Invalid UTF8 (other ill formed sequences)") {
ERR_PRINT_OFF
// Examples from the unicode standard : 3.9 Unicode Encoding Forms - Table 3.10.
static const uint8_t u8str[] = { 0xF4, 0x91, 0x92, 0x93, 0xFF, 0x41, 0x80, 0xBF, 0x42, 0 };
static const char32_t u32str[] = { 0xFFFD, 0xFFFD, 0xFFFD, 0xFFFD, 0xFFFD, 0x41, 0xFFFD, 0xFFFD, 0x42, 0 };
String s;
Error err = s.append_utf8((const char *)u8str);
CHECK(err == ERR_INVALID_DATA);
CHECK(s == u32str);
CharString cs = (const char *)u8str;
CHECK(String::utf8(cs) == s);
ERR_PRINT_ON
}
TEST_CASE("[String] Invalid UTF8 (truncated sequences)") {
ERR_PRINT_OFF
// Examples from the unicode standard : 3.9 Unicode Encoding Forms - Table 3.11.
static const uint8_t u8str[] = { 0xE1, 0x80, 0xE2, 0xF0, 0x91, 0x92, 0xF1, 0xBF, 0x41, 0 };
static const char32_t u32str[] = { 0xFFFD, 0xFFFD, 0xFFFD, 0xFFFD, 0x41, 0 };
String s;
Error err = s.append_utf8((const char *)u8str);
CHECK(err == ERR_INVALID_DATA);
CHECK(s == u32str);
@ -202,7 +236,7 @@ TEST_CASE("[String] Invalid UTF16 (non-standard)") {
// + + + + unpaired
static const char32_t u32str[] = { 0x0045, 0x304A, 0x3088, 0x3046, 0xDFA4, 0 };
String s;
Error err = s.parse_utf16(u16str);
Error err = s.append_utf16(u16str);
CHECK(err == ERR_PARSE_ERROR);
CHECK(s == u32str);
@ -442,6 +476,27 @@ TEST_CASE("[String] Find and replace") {
MULTICHECK_STRING_STRING_EQ(s, replacen, "Y", "Y", "HappY BirthdaY, Anna!");
}
TEST_CASE("[String] replace_char") {
String s = "Banana";
CHECK(s.replace_char('n', 'x') == "Baxaxa");
CHECK(s.replace_char('\0', 'x') == "Banana");
ERR_PRINT_OFF
CHECK(s.replace_char('n', '\0') == "Banana");
ERR_PRINT_ON
}
TEST_CASE("[String] replace_chars") {
String s = "Banana";
CHECK(s.replace_chars(String("Bn"), 'x') == "xaxaxa");
CHECK(s.replace_chars("Bn", 'x') == "xaxaxa");
CHECK(s.replace_chars(String(), 'x') == "Banana");
CHECK(s.replace_chars("", 'x') == "Banana");
ERR_PRINT_OFF
CHECK(s.replace_chars(String("Bn"), '\0') == "Banana");
CHECK(s.replace_chars("Bn", '\0') == "Banana");
ERR_PRINT_ON
}
TEST_CASE("[String] Insertion") {
String s = "Who is Frederic?";
s = s.insert(s.find("?"), " Chopin");
@ -467,6 +522,23 @@ TEST_CASE("[String] Erasing") {
CHECK(s == "Josephine is such a girl!");
}
TEST_CASE("[String] remove_char") {
String s = "Banana";
CHECK(s.remove_char('a') == "Bnn");
CHECK(s.remove_char('\0') == "Banana");
CHECK(s.remove_char('x') == "Banana");
}
TEST_CASE("[String] remove_chars") {
String s = "Banana";
CHECK(s.remove_chars("Ba") == "nn");
CHECK(s.remove_chars(String("Ba")) == "nn");
CHECK(s.remove_chars("") == "Banana");
CHECK(s.remove_chars(String()) == "Banana");
CHECK(s.remove_chars("xy") == "Banana");
CHECK(s.remove_chars(String("xy")) == "Banana");
}
TEST_CASE("[String] Number to string") {
CHECK(String::num(0) == "0.0"); // The method takes double, so always add zeros.
CHECK(String::num(0.0) == "0.0");
@ -507,12 +579,12 @@ TEST_CASE("[String] Number to string") {
#ifdef REAL_T_IS_DOUBLE
CHECK_MESSAGE(String::num_real(real_t(123.456789)) == "123.456789", "Prints the appropriate amount of digits for real_t = double.");
CHECK_MESSAGE(String::num_real(real_t(-123.456789)) == "-123.456789", "Prints the appropriate amount of digits for real_t = double.");
CHECK_MESSAGE(String::num_real(real_t(Math_PI)) == "3.14159265358979", "Prints the appropriate amount of digits for real_t = double.");
CHECK_MESSAGE(String::num_real(real_t(Math::PI)) == "3.14159265358979", "Prints the appropriate amount of digits for real_t = double.");
CHECK_MESSAGE(String::num_real(real_t(3.1415f)) == "3.1414999961853", "Prints more digits of 32-bit float when real_t = double (ones that would be reliable for double) and no trailing zero.");
#else
CHECK_MESSAGE(String::num_real(real_t(123.456789)) == "123.4568", "Prints the appropriate amount of digits for real_t = float.");
CHECK_MESSAGE(String::num_real(real_t(-123.456789)) == "-123.4568", "Prints the appropriate amount of digits for real_t = float.");
CHECK_MESSAGE(String::num_real(real_t(Math_PI)) == "3.141593", "Prints the appropriate amount of digits for real_t = float.");
CHECK_MESSAGE(String::num_real(real_t(Math::PI)) == "3.141593", "Prints the appropriate amount of digits for real_t = float.");
CHECK_MESSAGE(String::num_real(real_t(3.1415f)) == "3.1415", "Prints only reliable digits of 32-bit float when real_t = float.");
#endif // REAL_T_IS_DOUBLE
@ -603,7 +675,7 @@ TEST_CASE("[String] String to float") {
static const double num[12] = { -12348298412.2, 0.05, 2.0002, -0.0001, 0.0, 0.0, 123.0, 0.0, 0.0, 0.007, 234.0, 3.0 };
for (int i = 0; i < 12; i++) {
CHECK(!(ABS(String(nums[i]).to_float() - num[i]) > 0.00001));
CHECK(!(Math::abs(String(nums[i]).to_float() - num[i]) > 0.00001));
}
// Invalid float strings should return 0.
@ -618,15 +690,15 @@ TEST_CASE("[String] String to float") {
CHECK(String("-1e308").to_float() == -1e308);
// Exponent is so high that value is INFINITY/-INFINITY.
CHECK(String("1e309").to_float() == INFINITY);
CHECK(String("1e511").to_float() == INFINITY);
CHECK(String("-1e309").to_float() == -INFINITY);
CHECK(String("-1e511").to_float() == -INFINITY);
CHECK(String("1e309").to_float() == Math::INF);
CHECK(String("1e511").to_float() == Math::INF);
CHECK(String("-1e309").to_float() == -Math::INF);
CHECK(String("-1e511").to_float() == -Math::INF);
// Exponent is so high that a warning message is printed. Value is INFINITY/-INFINITY.
ERR_PRINT_OFF
CHECK(String("1e512").to_float() == INFINITY);
CHECK(String("-1e512").to_float() == -INFINITY);
CHECK(String("1e512").to_float() == Math::INF);
CHECK(String("-1e512").to_float() == -Math::INF);
ERR_PRINT_ON
}
@ -714,6 +786,14 @@ TEST_CASE("[String] Splitting") {
CHECK(l[i] == slices[i]);
}
}
{
const String s = "Mars Jupiter Saturn Uranus";
const char *slices[2] = { "Mars", "Jupiter Saturn Uranus" };
Vector<String> l = s.split_spaces(1);
for (int i = 0; i < l.size(); i++) {
CHECK(l[i] == slices[i]);
}
}
{
const String s = "1.2;2.3 4.5";
@ -722,14 +802,14 @@ TEST_CASE("[String] Splitting") {
const Vector<double> d_arr = s.split_floats(";");
CHECK(d_arr.size() == 2);
for (int i = 0; i < d_arr.size(); i++) {
CHECK(ABS(d_arr[i] - slices[i]) <= 0.00001);
CHECK(Math::abs(d_arr[i] - slices[i]) <= 0.00001);
}
const Vector<String> keys = { ";", " " };
const Vector<float> f_arr = s.split_floats_mk(keys);
CHECK(f_arr.size() == 3);
for (int i = 0; i < f_arr.size(); i++) {
CHECK(ABS(f_arr[i] - slices[i]) <= 0.00001);
CHECK(Math::abs(f_arr[i] - slices[i]) <= 0.00001);
}
}
@ -740,7 +820,7 @@ TEST_CASE("[String] Splitting") {
const Vector<double> arr = s.split_floats(" ");
CHECK(arr.size() == 10);
for (int i = 0; i < arr.size(); i++) {
CHECK(ABS(arr[i] - slices[i]) <= 0.00001);
CHECK(Math::abs(arr[i] - slices[i]) <= 0.00001);
}
const Vector<String> keys = { ";", " " };
@ -923,7 +1003,7 @@ TEST_CASE("[String] sprintf") {
// Real (infinity) left-padded
format = "fish %11f frog";
args.clear();
args.push_back(INFINITY);
args.push_back(Math::INF);
output = format.sprintf(args, &error);
REQUIRE(error == false);
CHECK(output == String("fish inf frog"));
@ -1047,7 +1127,7 @@ TEST_CASE("[String] sprintf") {
// Vector left-padded with inf/nan
format = "fish %11v frog";
args.clear();
args.push_back(Variant(Vector2(INFINITY, NAN)));
args.push_back(Variant(Vector2(Math::INF, Math::NaN)));
output = format.sprintf(args, &error);
REQUIRE(error == false);
CHECK(output == String("fish ( inf, nan) frog"));
@ -1371,6 +1451,14 @@ TEST_CASE("[String] Capitalize against many strings") {
output = "Snake Snake Case";
CHECK(input.capitalize() == output);
input = "kebab-case";
output = "Kebab Case";
CHECK(input.capitalize() == output);
input = "kebab-kebab-case";
output = "Kebab Kebab Case";
CHECK(input.capitalize() == output);
input = "sha256sum";
output = "Sha 256 Sum";
CHECK(input.capitalize() == output);
@ -1391,6 +1479,14 @@ TEST_CASE("[String] Capitalize against many strings") {
output = "Snake Case Function( Snake Case Arg )";
CHECK(input.capitalize() == output);
input = "kebab-case-function( kebab-case-arg )";
output = "Kebab Case Function( Kebab Case Arg )";
CHECK(input.capitalize() == output);
input = "kebab_case_function( kebab_case_arg )";
output = "Kebab Case Function( Kebab Case Arg )";
CHECK(input.capitalize() == output);
input = U"словоСлово_слово слово";
output = U"Слово Слово Слово Слово";
CHECK(input.capitalize() == output);
@ -1409,35 +1505,37 @@ struct StringCasesTestCase {
const char32_t *camel_case;
const char32_t *pascal_case;
const char32_t *snake_case;
const char32_t *kebab_case;
};
TEST_CASE("[String] Checking case conversion methods") {
StringCasesTestCase test_cases[] = {
/* clang-format off */
{ U"2D", U"2d", U"2d", U"2d" },
{ U"2d", U"2d", U"2d", U"2d" },
{ U"2db", U"2Db", U"2Db", U"2_db" },
{ U"Vector3", U"vector3", U"Vector3", U"vector_3" },
{ U"sha256", U"sha256", U"Sha256", U"sha_256" },
{ U"Node2D", U"node2d", U"Node2d", U"node_2d" },
{ U"RichTextLabel", U"richTextLabel", U"RichTextLabel", U"rich_text_label" },
{ U"HTML5", U"html5", U"Html5", U"html_5" },
{ U"Node2DPosition", U"node2dPosition", U"Node2dPosition", U"node_2d_position" },
{ U"Number2Digits", U"number2Digits", U"Number2Digits", U"number_2_digits" },
{ U"get_property_list", U"getPropertyList", U"GetPropertyList", U"get_property_list" },
{ U"get_camera_2d", U"getCamera2d", U"GetCamera2d", U"get_camera_2d" },
{ U"_physics_process", U"physicsProcess", U"PhysicsProcess", U"_physics_process" },
{ U"bytes2var", U"bytes2Var", U"Bytes2Var", U"bytes_2_var" },
{ U"linear2db", U"linear2Db", U"Linear2Db", U"linear_2_db" },
{ U"sha256sum", U"sha256Sum", U"Sha256Sum", U"sha_256_sum" },
{ U"camelCase", U"camelCase", U"CamelCase", U"camel_case" },
{ U"PascalCase", U"pascalCase", U"PascalCase", U"pascal_case" },
{ U"snake_case", U"snakeCase", U"SnakeCase", U"snake_case" },
{ U"Test TEST test", U"testTestTest", U"TestTestTest", U"test_test_test" },
{ U"словоСлово_слово слово", U"словоСловоСловоСлово", U"СловоСловоСловоСлово", U"слово_слово_слово_слово" },
{ U"λέξηΛέξη_λέξη λέξη", U"λέξηΛέξηΛέξηΛέξη", U"ΛέξηΛέξηΛέξηΛέξη", U"λέξη_λέξη_λέξη_λέξη" },
{ U"բառԲառառ բառ", U"բառԲառԲառԲառ", U"ԲառԲառԲառԲառ", U"բառառառառ" },
{ nullptr, nullptr, nullptr, nullptr },
{ U"2D", U"2d", U"2d", U"2d", U"2d" },
{ U"2d", U"2d", U"2d", U"2d", U"2d" },
{ U"2db", U"2Db", U"2Db", U"2_db", U"2-db" },
{ U"Vector3", U"vector3", U"Vector3", U"vector_3", U"vector-3" },
{ U"sha256", U"sha256", U"Sha256", U"sha_256", U"sha-256" },
{ U"Node2D", U"node2d", U"Node2d", U"node_2d", U"node-2d" },
{ U"RichTextLabel", U"richTextLabel", U"RichTextLabel", U"rich_text_label", U"rich-text-label" },
{ U"HTML5", U"html5", U"Html5", U"html_5", U"html-5" },
{ U"Node2DPosition", U"node2dPosition", U"Node2dPosition", U"node_2d_position", U"node-2d-position" },
{ U"Number2Digits", U"number2Digits", U"Number2Digits", U"number_2_digits", U"number-2-digits" },
{ U"get_property_list", U"getPropertyList", U"GetPropertyList", U"get_property_list", U"get-property-list" },
{ U"get_camera_2d", U"getCamera2d", U"GetCamera2d", U"get_camera_2d", U"get-camera-2d" },
{ U"_physics_process", U"physicsProcess", U"PhysicsProcess", U"_physics_process", U"-physics-process" },
{ U"bytes2var", U"bytes2Var", U"Bytes2Var", U"bytes_2_var", U"bytes-2-var" },
{ U"linear2db", U"linear2Db", U"Linear2Db", U"linear_2_db", U"linear-2-db" },
{ U"sha256sum", U"sha256Sum", U"Sha256Sum", U"sha_256_sum", U"sha-256-sum" },
{ U"camelCase", U"camelCase", U"CamelCase", U"camel_case", U"camel-case" },
{ U"PascalCase", U"pascalCase", U"PascalCase", U"pascal_case", U"pascal-case" },
{ U"snake_case", U"snakeCase", U"SnakeCase", U"snake_case", U"snake-case" },
{ U"kebab-case", U"kebabCase", U"KebabCase", U"kebab_case", U"kebab-case" },
{ U"Test TEST test", U"testTestTest", U"TestTestTest", U"test_test_test", U"test-test-test" },
{ U"словоСлово_слово слово", U"словоСловоСловоСлово", U"СловоСловоСловоСлово", U"слово_слово_слово_слово", U"слово-слово-слово-слово" },
{ U"λέξηΛέξη_λέξη λέξη", U"λέξηΛέξηΛέξηΛέξη", U"ΛέξηΛέξηΛέξηΛέξη", U"λέξη_λέξη_λέξη_λέξη", U"λέξη-λέξη-λέξη-λέξη" },
{ U"բառԲառառ բառ", U"բառԲառԲառԲառ", U"ԲառԲառԲառԲառ", U"բառառառառ", U"բառ-բառ-բառ-բառ" },
{ nullptr, nullptr, nullptr, nullptr, nullptr },
/* clang-format on */
};
@ -1447,6 +1545,7 @@ TEST_CASE("[String] Checking case conversion methods") {
CHECK(input.to_camel_case() == test_cases[idx].camel_case);
CHECK(input.to_pascal_case() == test_cases[idx].pascal_case);
CHECK(input.to_snake_case() == test_cases[idx].snake_case);
CHECK(input.to_kebab_case() == test_cases[idx].kebab_case);
idx++;
}
}
@ -1550,9 +1649,9 @@ TEST_CASE("[String] lstrip and rstrip") {
#undef STRIP_TEST
}
TEST_CASE("[String] Ensuring empty string into parse_utf8 passes empty string") {
TEST_CASE("[String] Ensuring empty string into extend_utf8 passes empty string") {
String empty;
CHECK(empty.parse_utf8(nullptr, -1) == ERR_INVALID_DATA);
CHECK(empty.append_utf8(nullptr, -1) == ERR_INVALID_DATA);
}
TEST_CASE("[String] Cyrillic to_lower()") {
@ -1715,6 +1814,7 @@ TEST_CASE("[String] uri_encode/unescape") {
static const uint8_t u8str[] = { 0x54, 0xC4, 0x93, 0xC5, 0xA1, 0x74, 0x00 };
String x2 = String::utf8((const char *)u8str);
String x3 = U"Tēšt";
String x4 = U"file+name";
CHECK(x1.uri_decode() == x2);
CHECK(x1.uri_decode() == x3);
@ -1724,6 +1824,8 @@ TEST_CASE("[String] uri_encode/unescape") {
CHECK(s.uri_encode() == t);
CHECK(t.uri_decode() == s);
CHECK(x4.uri_file_decode() == x4);
CHECK(x4.uri_decode() == U"file name");
}
TEST_CASE("[String] xml_escape/unescape") {
@ -1896,7 +1998,7 @@ TEST_CASE("[String] Is_*") {
static bool isflt[] = { true, true, true, false, true, true, false, false, false, false, false, false, false, true, true };
static bool isaid[] = { false, false, false, false, false, false, false, false, true, true, false, false, false, false, false };
static bool isuid[] = { false, false, false, false, false, false, false, false, true, true, false, false, true, false, false };
for (unsigned int i = 0; i < sizeof(data) / sizeof(data[0]); i++) {
for (unsigned int i = 0; i < std::size(data); i++) {
String s = String::utf8(data[i]);
CHECK(s.is_numeric() == isnum[i]);
CHECK(s.is_valid_int() == isint[i]);
@ -2103,5 +2205,3 @@ TEST_CASE("[Stress][String] Empty via `is_empty()`") {
}
}
} // namespace TestString
#endif // TEST_STRING_H

View file

@ -28,8 +28,7 @@
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
/**************************************************************************/
#ifndef TEST_TRANSLATION_H
#define TEST_TRANSLATION_H
#pragma once
#include "core/string/optimized_translation.h"
#include "core/string/translation.h"
@ -201,5 +200,3 @@ TEST_CASE("[TranslationCSV] CSV import") {
#endif // TOOLS_ENABLED
} // namespace TestTranslation
#endif // TEST_TRANSLATION_H

View file

@ -28,8 +28,7 @@
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
/**************************************************************************/
#ifndef TEST_TRANSLATION_SERVER_H
#define TEST_TRANSLATION_SERVER_H
#pragma once
#include "core/string/translation_server.h"
@ -222,5 +221,3 @@ TEST_CASE("[TranslationServer] Comparing locales") {
CHECK(res == 10);
}
} // namespace TestTranslationServer
#endif // TEST_TRANSLATION_SERVER_H

View file

@ -28,8 +28,7 @@
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
/**************************************************************************/
#ifndef TEST_A_HASH_MAP_H
#define TEST_A_HASH_MAP_H
#pragma once
#include "core/templates/a_hash_map.h"
@ -235,9 +234,13 @@ TEST_CASE("[AHashMap] Insert, iterate and remove many elements") {
TEST_CASE("[AHashMap] Insert, iterate and remove many strings") {
const int elem_max = 432;
AHashMap<String, String> map;
// To not print WARNING: Excessive collision count (NN), is the right hash function being used?
ERR_PRINT_OFF;
for (int i = 0; i < elem_max; i++) {
map.insert(itos(i), itos(i));
}
ERR_PRINT_ON;
//insert order should have been kept
int idx = 0;
@ -309,5 +312,3 @@ TEST_CASE("[AHashMap] Array methods") {
}
} // namespace TestAHashMap
#endif // TEST_A_HASH_MAP_H

View file

@ -28,8 +28,7 @@
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
/**************************************************************************/
#ifndef TEST_COMMAND_QUEUE_H
#define TEST_COMMAND_QUEUE_H
#pragma once
#include "core/config/project_settings.h"
#include "core/math/random_number_generator.h"
@ -562,5 +561,3 @@ TEST_CASE("[CommandQueue] Test Parameter Passing Semantics") {
sts.destroy_threads();
}
} // namespace TestCommandQueue
#endif // TEST_COMMAND_QUEUE_H

View file

@ -28,8 +28,7 @@
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
/**************************************************************************/
#ifndef TEST_HASH_MAP_H
#define TEST_HASH_MAP_H
#pragma once
#include "core/templates/hash_map.h"
@ -147,5 +146,3 @@ TEST_CASE("[HashMap] Const iteration") {
}
}
} // namespace TestHashMap
#endif // TEST_HASH_MAP_H

View file

@ -28,8 +28,7 @@
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
/**************************************************************************/
#ifndef TEST_HASH_SET_H
#define TEST_HASH_SET_H
#pragma once
#include "core/templates/hash_set.h"
@ -240,5 +239,3 @@ TEST_CASE("[HashSet] Copy") {
}
} // namespace TestHashSet
#endif // TEST_HASH_SET_H

View file

@ -28,8 +28,7 @@
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
/**************************************************************************/
#ifndef TEST_LIST_H
#define TEST_LIST_H
#pragma once
#include "core/templates/list.h"
@ -555,5 +554,3 @@ TEST_CASE("[Stress][List] Swap random 10 elements, 1000 iterations.") {
swap_random(list, n, 10, 1000);
}
} // namespace TestList
#endif // TEST_LIST_H

View file

@ -28,8 +28,7 @@
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
/**************************************************************************/
#ifndef TEST_LOCAL_VECTOR_H
#define TEST_LOCAL_VECTOR_H
#pragma once
#include "core/templates/local_vector.h"
@ -179,6 +178,23 @@ TEST_CASE("[LocalVector] Remove Unordered.") {
CHECK(vector.size() == 0);
}
TEST_CASE("[LocalVector] Erase Unordered.") {
LocalVector<int> vector;
vector.push_back(1);
vector.push_back(3);
vector.push_back(0);
vector.push_back(2);
vector.push_back(4);
CHECK(vector.find(1) == 0);
vector.erase_unordered(1);
CHECK(vector.find(1) == -1);
CHECK(vector.size() == 4);
CHECK(vector[0] == 4);
}
TEST_CASE("[LocalVector] Erase.") {
LocalVector<int> vector;
vector.push_back(1);
@ -245,5 +261,3 @@ TEST_CASE("[LocalVector] Size / Resize / Reserve.") {
CHECK(vector.get_capacity() >= 4);
}
} // namespace TestLocalVector
#endif // TEST_LOCAL_VECTOR_H

View file

@ -28,8 +28,7 @@
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
/**************************************************************************/
#ifndef TEST_LRU_H
#define TEST_LRU_H
#pragma once
#include "core/templates/lru.h"
@ -95,5 +94,3 @@ TEST_CASE("[LRU] Resize and clear") {
CHECK(!lru.has(4));
}
} // namespace TestLRU
#endif // TEST_LRU_H

View file

@ -28,8 +28,7 @@
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
/**************************************************************************/
#ifndef TEST_OA_HASH_MAP_H
#define TEST_OA_HASH_MAP_H
#pragma once
#include "core/templates/oa_hash_map.h"
#include "scene/resources/texture.h"
@ -247,5 +246,3 @@ TEST_CASE("[OAHashMap] Non-trivial types") {
}
} // namespace TestOAHashMap
#endif // TEST_OA_HASH_MAP_H

View file

@ -28,8 +28,7 @@
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
/**************************************************************************/
#ifndef TEST_PAGED_ARRAY_H
#define TEST_PAGED_ARRAY_H
#pragma once
#include "core/templates/paged_array.h"
@ -200,5 +199,3 @@ TEST_CASE("[PagedArray] Extensive merge_unordered() test") {
}
} // namespace TestPagedArray
#endif // TEST_PAGED_ARRAY_H

View file

@ -28,8 +28,7 @@
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
/**************************************************************************/
#ifndef TEST_RID_H
#define TEST_RID_H
#pragma once
#include "core/os/thread.h"
#include "core/templates/local_vector.h"
@ -38,6 +37,7 @@
#include "tests/test_macros.h"
#ifdef THREADS_ENABLED
#ifdef SANITIZERS_ENABLED
#ifdef __has_feature
#if __has_feature(thread_sanitizer)
@ -46,7 +46,8 @@
#elif defined(__SANITIZE_THREAD__)
#define TSAN_ENABLED
#endif
#endif
#endif // SANITIZERS_ENABLED
#endif // THREADS_ENABLED
#ifdef TSAN_ENABLED
#include <sanitizer/tsan_interface.h>
@ -114,6 +115,7 @@ TEST_CASE("[RID] 'get_local_index'") {
CHECK(RID::from_uint64(4'294'967'297).get_local_index() == 1);
}
#ifdef THREADS_ENABLED
// This case would let sanitizers realize data races.
// Additionally, on purely weakly ordered architectures, it would detect synchronization issues
// if RID_Alloc failed to impose proper memory ordering and the test's threads are distributed
@ -141,7 +143,7 @@ TEST_CASE("[RID_Owner] Thread safety") {
uint32_t target = (p_step / 2 + 1) * threads.size();
sync[buf_idx].fetch_add(1, std::memory_order_relaxed);
do {
std::this_thread::yield();
Thread::yield();
} while (sync[buf_idx].load(std::memory_order_relaxed) != target);
}
@ -249,6 +251,6 @@ TEST_CASE("[RID_Owner] Thread safety") {
tester.test();
}
}
} // namespace TestRID
#endif // THREADS_ENABLED
#endif // TEST_RID_H
} // namespace TestRID

View file

@ -0,0 +1,70 @@
/**************************************************************************/
/* test_span.h */
/**************************************************************************/
/* This file is part of: */
/* GODOT ENGINE */
/* https://godotengine.org */
/**************************************************************************/
/* Copyright (c) 2014-present Godot Engine contributors (see AUTHORS.md). */
/* Copyright (c) 2007-2014 Juan Linietsky, Ariel Manzur. */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
/* "Software"), to deal in the Software without restriction, including */
/* without limitation the rights to use, copy, modify, merge, publish, */
/* distribute, sublicense, and/or sell copies of the Software, and to */
/* permit persons to whom the Software is furnished to do so, subject to */
/* the following conditions: */
/* */
/* The above copyright notice and this permission notice shall be */
/* included in all copies or substantial portions of the Software. */
/* */
/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. */
/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
/**************************************************************************/
#pragma once
#include "core/templates/span.h"
#include "tests/test_macros.h"
namespace TestSpan {
TEST_CASE("[Span] Constexpr Validators") {
constexpr Span<uint16_t> span_empty;
static_assert(span_empty.ptr() == nullptr);
static_assert(span_empty.size() == 0);
static_assert(span_empty.is_empty());
constexpr static uint16_t value = 5;
constexpr Span<uint16_t> span_value(&value, 1);
static_assert(span_value.ptr() == &value);
static_assert(span_value.size() == 1);
static_assert(!span_value.is_empty());
static constexpr int ints[] = { 0, 1, 2, 3, 4, 5 };
constexpr Span<int> span_array = ints;
static_assert(span_array.size() == 6);
static_assert(!span_array.is_empty());
static_assert(span_array[0] == 0);
static_assert(span_array[span_array.size() - 1] == 5);
constexpr Span<char32_t> span_string = U"122345";
static_assert(span_string.size() == 6);
static_assert(!span_string.is_empty());
static_assert(span_string[0] == U'1');
static_assert(span_string[span_string.size() - 1] == U'5');
int idx = 0;
for (const char32_t &chr : span_string) {
CHECK_EQ(chr, span_string[idx++]);
}
}
} // namespace TestSpan

View file

@ -28,8 +28,7 @@
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
/**************************************************************************/
#ifndef TEST_VECTOR_H
#define TEST_VECTOR_H
#pragma once
#include "core/templates/vector.h"
@ -706,5 +705,3 @@ TEST_CASE("[Vector] Cyclic Reference") {
}
} // namespace TestVector
#endif // TEST_VECTOR_H

View file

@ -28,8 +28,7 @@
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
/**************************************************************************/
#ifndef TEST_CRYPTO_H
#define TEST_CRYPTO_H
#pragma once
#include "core/crypto/crypto.h"
#include "tests/test_macros.h"
@ -60,8 +59,8 @@ PackedByteArray raw_to_pba(const uint8_t *arr, size_t len) {
TEST_CASE("[Crypto] PackedByteArray constant time compare") {
const uint8_t hm1[] = { 144, 140, 176, 38, 88, 113, 101, 45, 71, 105, 10, 91, 248, 16, 117, 244, 189, 30, 238, 29, 219, 134, 82, 130, 212, 114, 161, 166, 188, 169, 200, 106 };
const uint8_t hm2[] = { 80, 30, 144, 228, 108, 38, 188, 125, 150, 64, 165, 127, 221, 118, 144, 232, 45, 100, 15, 248, 193, 244, 245, 34, 116, 147, 132, 200, 110, 27, 38, 75 };
PackedByteArray p1 = raw_to_pba(hm1, sizeof(hm1) / sizeof(hm1[0]));
PackedByteArray p2 = raw_to_pba(hm2, sizeof(hm2) / sizeof(hm2[0]));
PackedByteArray p1 = raw_to_pba(hm1, std::size(hm1));
PackedByteArray p2 = raw_to_pba(hm2, std::size(hm2));
_MockCrypto crypto;
bool equal = crypto.constant_time_compare(p1, p1);
CHECK(equal);
@ -69,5 +68,3 @@ TEST_CASE("[Crypto] PackedByteArray constant time compare") {
CHECK(!equal);
}
} // namespace TestCrypto
#endif // TEST_CRYPTO_H

View file

@ -28,8 +28,7 @@
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
/**************************************************************************/
#ifndef TEST_HASHING_CONTEXT_H
#define TEST_HASHING_CONTEXT_H
#pragma once
#include "core/crypto/hashing_context.h"
@ -161,5 +160,3 @@ TEST_CASE("[HashingContext] Invalid use of finish") {
ERR_PRINT_ON;
}
} // namespace TestHashingContext
#endif // TEST_HASHING_CONTEXT_H

View file

@ -28,8 +28,7 @@
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
/**************************************************************************/
#ifndef TEST_TIME_H
#define TEST_TIME_H
#pragma once
#include "core/os/time.h"
@ -144,5 +143,3 @@ TEST_CASE("[Time] System time methods") {
}
} // namespace TestTime
#endif // TEST_TIME_H

View file

@ -28,8 +28,7 @@
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
/**************************************************************************/
#ifndef TEST_WORKER_THREAD_POOL_H
#define TEST_WORKER_THREAD_POOL_H
#pragma once
#include "core/object/worker_thread_pool.h"
@ -174,5 +173,3 @@ TEST_CASE("[WorkerThreadPool] Run a yielding daemon as the only hope for other t
}
} // namespace TestWorkerThreadPool
#endif // TEST_WORKER_THREAD_POOL_H

View file

@ -28,8 +28,7 @@
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
/**************************************************************************/
#ifndef TEST_ARRAY_H
#define TEST_ARRAY_H
#pragma once
#include "core/variant/array.h"
#include "tests/test_macros.h"
@ -56,6 +55,26 @@ static inline Dictionary build_dictionary(Variant key, Variant item, Targs... Fa
return d;
}
TEST_CASE("[Array] initializer list") {
Array arr = { 0, 1, "test", true, { 0.0, 1.0 } };
CHECK(arr.size() == 5);
CHECK(arr[0] == Variant(0));
CHECK(arr[1] == Variant(1));
CHECK(arr[2] == Variant("test"));
CHECK(arr[3] == Variant(true));
CHECK(arr[4] == Variant({ 0.0, 1.0 }));
arr = { "reassign" };
CHECK(arr.size() == 1);
CHECK(arr[0] == Variant("reassign"));
TypedArray<int> typed_arr = { 0, 1, 2 };
CHECK(typed_arr.size() == 3);
CHECK(typed_arr[0] == Variant(0));
CHECK(typed_arr[1] == Variant(1));
CHECK(typed_arr[2] == Variant(2));
}
TEST_CASE("[Array] size(), clear(), and is_empty()") {
Array arr;
CHECK(arr.size() == 0);
@ -107,6 +126,12 @@ TEST_CASE("[Array] resize(), insert(), and erase()") {
CHECK(int(arr[0]) == 2);
arr.erase(2);
CHECK(int(arr[0]) == 1);
// Negative index on insert.
CHECK(arr.size() == 3);
arr.insert(-1, 3);
CHECK(int(arr[2]) == 3);
CHECK(arr.size() == 4);
}
TEST_CASE("[Array] front() and back()") {
@ -120,9 +145,7 @@ TEST_CASE("[Array] front() and back()") {
}
TEST_CASE("[Array] has() and count()") {
Array arr;
arr.push_back(1);
arr.push_back(1);
Array arr = { 1, 1 };
CHECK(arr.has(1));
CHECK(!arr.has(2));
CHECK(arr.count(1) == 2);
@ -130,15 +153,22 @@ TEST_CASE("[Array] has() and count()") {
}
TEST_CASE("[Array] remove_at()") {
Array arr;
arr.push_back(1);
arr.push_back(2);
Array arr = { 1, 2 };
arr.remove_at(0);
CHECK(arr.size() == 1);
CHECK(int(arr[0]) == 2);
arr.remove_at(0);
CHECK(arr.size() == 0);
// Negative index.
arr.push_back(3);
arr.push_back(4);
arr.remove_at(-1);
CHECK(arr.size() == 1);
CHECK(int(arr[0]) == 3);
arr.remove_at(-1);
CHECK(arr.size() == 0);
// The array is now empty; try to use `remove_at()` again.
// Normally, this prints an error message so we silence it.
ERR_PRINT_OFF;
@ -149,18 +179,12 @@ TEST_CASE("[Array] remove_at()") {
}
TEST_CASE("[Array] get()") {
Array arr;
arr.push_back(1);
Array arr = { 1 };
CHECK(int(arr.get(0)) == 1);
}
TEST_CASE("[Array] sort()") {
Array arr;
arr.push_back(3);
arr.push_back(4);
arr.push_back(2);
arr.push_back(1);
Array arr = { 3, 4, 2, 1 };
arr.sort();
int val = 1;
for (int i = 0; i < arr.size(); i++) {
@ -187,12 +211,7 @@ TEST_CASE("[Array] push_front(), pop_front(), pop_back()") {
TEST_CASE("[Array] pop_at()") {
ErrorDetector ed;
Array arr;
arr.push_back(2);
arr.push_back(4);
arr.push_back(6);
arr.push_back(8);
arr.push_back(10);
Array arr = { 2, 4, 6, 8, 10 };
REQUIRE(int(arr.pop_at(2)) == 6);
REQUIRE(arr.size() == 4);
@ -247,13 +266,7 @@ TEST_CASE("[Array] max() and min()") {
}
TEST_CASE("[Array] slice()") {
Array array;
array.push_back(0);
array.push_back(1);
array.push_back(2);
array.push_back(3);
array.push_back(4);
array.push_back(5);
Array array = { 0, 1, 2, 3, 4, 5 };
Array slice0 = array.slice(0, 0);
CHECK(slice0.size() == 0);
@ -598,11 +611,8 @@ TEST_CASE("[Array] Iteration and modification") {
}
TEST_CASE("[Array] Typed copying") {
TypedArray<int> a1;
a1.push_back(1);
TypedArray<double> a2;
a2.push_back(1.0);
TypedArray<int> a1 = { 1 };
TypedArray<double> a2 = { 1.0 };
Array a3 = a1;
TypedArray<int> a4 = a3;
@ -653,5 +663,3 @@ TEST_CASE("[Array] Test rfind_custom") {
}
} // namespace TestArray
#endif // TEST_ARRAY_H

View file

@ -28,8 +28,7 @@
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
/**************************************************************************/
#ifndef TEST_CALLABLE_H
#define TEST_CALLABLE_H
#pragma once
#include "core/object/class_db.h"
#include "core/object/object.h"
@ -155,11 +154,7 @@ public:
}
static String get_output(const Callable &p_callable) {
Array effective_args;
effective_args.push_back(7);
effective_args.push_back(8);
effective_args.push_back(9);
Array effective_args = { 7, 8, 9 };
effective_args.resize(3 - p_callable.get_unbound_arguments_count());
effective_args.append_array(p_callable.get_bound_arguments());
@ -200,5 +195,3 @@ TEST_CASE("[Callable] Bound and unbound argument count") {
}
} // namespace TestCallable
#endif // TEST_CALLABLE_H

View file

@ -28,8 +28,7 @@
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
/**************************************************************************/
#ifndef TEST_DICTIONARY_H
#define TEST_DICTIONARY_H
#pragma once
#include "core/variant/typed_dictionary.h"
#include "tests/test_macros.h"
@ -116,19 +115,18 @@ TEST_CASE("[Dictionary] List init") {
CHECK_EQ(tdict[5.0], Variant(2.0));
}
TEST_CASE("[Dictionary] get_key_lists()") {
TEST_CASE("[Dictionary] get_key_list()") {
Dictionary map;
List<Variant> keys;
List<Variant> *ptr = &keys;
map.get_key_list(ptr);
LocalVector<Variant> keys;
keys = map.get_key_list();
CHECK(keys.is_empty());
map[1] = 3;
map.get_key_list(ptr);
keys = map.get_key_list();
CHECK(keys.size() == 1);
CHECK(int(keys.front()->get()) == 1);
CHECK(int(keys[0]) == 1);
map[2] = 4;
map.get_key_list(ptr);
CHECK(keys.size() == 3);
keys = map.get_key_list();
CHECK(keys.size() == 2);
}
TEST_CASE("[Dictionary] get_key_at_index()") {
@ -546,11 +544,7 @@ TEST_CASE("[Dictionary] Order and find") {
d[12] = "twelve";
d["4"] = "four";
Array keys;
keys.append(4);
keys.append(8);
keys.append(12);
keys.append("4");
Array keys = { 4, 8, 12, "4" };
CHECK_EQ(d.keys(), keys);
CHECK_EQ(d.find_key("four"), Variant(4));
@ -594,6 +588,45 @@ TEST_CASE("[Dictionary] Typed copying") {
d6.clear();
}
} // namespace TestDictionary
TEST_CASE("[Dictionary] Iteration") {
Dictionary a1 = build_dictionary(1, 2, 3, 4, 5, 6);
Dictionary a2 = build_dictionary(1, 2, 3, 4, 5, 6);
#endif // TEST_DICTIONARY_H
int idx = 0;
for (const KeyValue<Variant, Variant> &kv : (const Dictionary &)a1) {
CHECK_EQ(int(a2[kv.key]), int(kv.value));
idx++;
}
CHECK_EQ(idx, a1.size());
a1.clear();
a2.clear();
}
TEST_CASE("[Dictionary] Object value init") {
Object *a = memnew(Object);
Object *b = memnew(Object);
TypedDictionary<double, Object *> tdict = {
{ 0.0, a },
{ 5.0, b },
};
CHECK_EQ(tdict[0.0], Variant(a));
CHECK_EQ(tdict[5.0], Variant(b));
memdelete(a);
memdelete(b);
}
TEST_CASE("[Dictionary] RefCounted value init") {
Ref<RefCounted> a = memnew(RefCounted);
Ref<RefCounted> b = memnew(RefCounted);
TypedDictionary<double, Ref<RefCounted>> tdict = {
{ 0.0, a },
{ 5.0, b },
};
CHECK_EQ(tdict[0.0], Variant(a));
CHECK_EQ(tdict[5.0], Variant(b));
}
} // namespace TestDictionary

View file

@ -28,8 +28,7 @@
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
/**************************************************************************/
#ifndef TEST_VARIANT_H
#define TEST_VARIANT_H
#pragma once
#include "core/variant/variant.h"
#include "core/variant/variant_parser.h"
@ -1737,6 +1736,24 @@ TEST_CASE("[Variant] Assignment To Color from Bool,Int,Float,String,Vec2,Vec2i,V
CHECK(object_v.get_type() == Variant::COLOR);
}
TEST_CASE("[Variant] array initializer list") {
Variant arr_v = { 0, 1, "test", true, { 0.0, 1.0 } };
CHECK(arr_v.get_type() == Variant::ARRAY);
Array arr = (Array)arr_v;
CHECK(arr.size() == 5);
CHECK(arr[0] == Variant(0));
CHECK(arr[1] == Variant(1));
CHECK(arr[2] == Variant("test"));
CHECK(arr[3] == Variant(true));
CHECK(arr[4] == Variant({ 0.0, 1.0 }));
PackedInt32Array packed_arr = { 2, 1, 0 };
CHECK(packed_arr.size() == 3);
CHECK(packed_arr[0] == 2);
CHECK(packed_arr[1] == 1);
CHECK(packed_arr[2] == 0);
}
TEST_CASE("[Variant] Writer and parser array") {
Array a = build_array(1, String("hello"), build_array(Variant()));
String a_str;
@ -2217,5 +2234,3 @@ TEST_CASE("[Variant] Operator NOT") {
}
} // namespace TestVariant
#endif // TEST_VARIANT_H

View file

@ -28,8 +28,7 @@
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
/**************************************************************************/
#ifndef TEST_VARIANT_UTILITY_H
#define TEST_VARIANT_UTILITY_H
#pragma once
#include "core/variant/variant_utility.h"
@ -93,15 +92,8 @@ TEST_CASE("[VariantUtility] Type conversion") {
}
{
Array arr;
arr.push_back(1.2);
arr.push_back(3.4);
arr.push_back(5.6);
PackedFloat64Array packed;
packed.push_back(1.2);
packed.push_back(3.4);
packed.push_back(5.6);
Array arr = { 1.2, 3.4, 5.6 };
PackedFloat64Array packed = { 1.2, 3.4, 5.6 };
converted = VariantUtilityFunctions::type_convert(arr, Variant::Type::PACKED_FLOAT64_ARRAY);
CHECK(converted.get_type() == Variant::Type::PACKED_FLOAT64_ARRAY);
@ -137,5 +129,3 @@ TEST_CASE("[VariantUtility] Type conversion") {
}
} // namespace TestVariantUtility
#endif // TEST_VARIANT_UTILITY_H