diff options
Diffstat (limited to 'tests')
-rw-r--r-- | tests/SCsub | 3 | ||||
-rw-r--r-- | tests/core/io/test_packet_peer.h | 204 | ||||
-rw-r--r-- | tests/core/io/test_stream_peer.h | 289 | ||||
-rw-r--r-- | tests/core/io/test_stream_peer_buffer.h | 185 | ||||
-rw-r--r-- | tests/core/string/test_string.h | 71 | ||||
-rw-r--r-- | tests/scene/test_code_edit.h | 25 | ||||
-rw-r--r-- | tests/scene/test_physics_material.h | 107 | ||||
-rw-r--r-- | tests/scene/test_sky.h | 141 | ||||
-rw-r--r-- | tests/scene/test_text_edit.h | 48 | ||||
-rw-r--r-- | tests/scene/test_viewport.h | 7 | ||||
-rw-r--r-- | tests/test_main.cpp | 13 |
11 files changed, 1091 insertions, 2 deletions
diff --git a/tests/SCsub b/tests/SCsub index d96a1142e4..169c7c1efa 100644 --- a/tests/SCsub +++ b/tests/SCsub @@ -1,4 +1,5 @@ -#!/usr/bin/python +#!/usr/bin/env python +from misc.utility.scons_hints import * Import("env") diff --git a/tests/core/io/test_packet_peer.h b/tests/core/io/test_packet_peer.h new file mode 100644 index 0000000000..59c8dadad8 --- /dev/null +++ b/tests/core/io/test_packet_peer.h @@ -0,0 +1,204 @@ +/**************************************************************************/ +/* test_packet_peer.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. */ +/**************************************************************************/ + +#ifndef TEST_PACKET_PEER_H +#define TEST_PACKET_PEER_H + +#include "core/io/packet_peer.h" +#include "tests/test_macros.h" + +namespace TestPacketPeer { + +TEST_CASE("[PacketPeer][PacketPeerStream] Encode buffer max size") { + Ref<PacketPeerStream> pps; + pps.instantiate(); + + SUBCASE("Default value") { + CHECK_EQ(pps->get_encode_buffer_max_size(), 8 * 1024 * 1024); + } + + SUBCASE("Max encode buffer must be at least 1024 bytes") { + ERR_PRINT_OFF; + pps->set_encode_buffer_max_size(42); + ERR_PRINT_ON; + + CHECK_EQ(pps->get_encode_buffer_max_size(), 8 * 1024 * 1024); + } + + SUBCASE("Max encode buffer cannot exceed 256 MiB") { + ERR_PRINT_OFF; + pps->set_encode_buffer_max_size((256 * 1024 * 1024) + 42); + ERR_PRINT_ON; + + CHECK_EQ(pps->get_encode_buffer_max_size(), 8 * 1024 * 1024); + } + + SUBCASE("Should be next power of two") { + pps->set_encode_buffer_max_size(2000); + + CHECK_EQ(pps->get_encode_buffer_max_size(), 2048); + } +} + +TEST_CASE("[PacketPeer][PacketPeerStream] Read a variant from peer") { + String godot_rules = "Godot Rules!!!"; + + Ref<StreamPeerBuffer> spb; + spb.instantiate(); + spb->put_var(godot_rules); + spb->seek(0); + + Ref<PacketPeerStream> pps; + pps.instantiate(); + pps->set_stream_peer(spb); + + Variant value; + CHECK_EQ(pps->get_var(value), Error::OK); + CHECK_EQ(String(value), godot_rules); +} + +TEST_CASE("[PacketPeer][PacketPeerStream] Read a variant from peer fails") { + Ref<PacketPeerStream> pps; + pps.instantiate(); + + Variant value; + ERR_PRINT_OFF; + CHECK_EQ(pps->get_var(value), Error::ERR_UNCONFIGURED); + ERR_PRINT_ON; +} + +TEST_CASE("[PacketPeer][PacketPeerStream] Put a variant to peer") { + String godot_rules = "Godot Rules!!!"; + + Ref<StreamPeerBuffer> spb; + spb.instantiate(); + + Ref<PacketPeerStream> pps; + pps.instantiate(); + pps->set_stream_peer(spb); + + CHECK_EQ(pps->put_var(godot_rules), Error::OK); + + spb->seek(0); + CHECK_EQ(String(spb->get_var()), godot_rules); +} + +TEST_CASE("[PacketPeer][PacketPeerStream] Put a variant to peer out of memory failure") { + String more_than_1mb = String("*").repeat(1024 + 1); + + Ref<StreamPeerBuffer> spb; + spb.instantiate(); + + Ref<PacketPeerStream> pps; + pps.instantiate(); + pps->set_stream_peer(spb); + pps->set_encode_buffer_max_size(1024); + + ERR_PRINT_OFF; + CHECK_EQ(pps->put_var(more_than_1mb), Error::ERR_OUT_OF_MEMORY); + ERR_PRINT_ON; +} + +TEST_CASE("[PacketPeer][PacketPeerStream] Get packet buffer") { + String godot_rules = "Godot Rules!!!"; + + Ref<StreamPeerBuffer> spb; + spb.instantiate(); + // First 4 bytes are the length of the string. + CharString cs = godot_rules.ascii(); + Vector<uint8_t> buffer = { (uint8_t)(cs.length() + 1), 0, 0, 0 }; + buffer.resize_zeroed(4 + cs.length() + 1); + memcpy(buffer.ptrw() + 4, cs.get_data(), cs.length()); + spb->set_data_array(buffer); + + Ref<PacketPeerStream> pps; + pps.instantiate(); + pps->set_stream_peer(spb); + + buffer.clear(); + CHECK_EQ(pps->get_packet_buffer(buffer), Error::OK); + + CHECK_EQ(String(reinterpret_cast<const char *>(buffer.ptr())), godot_rules); +} + +TEST_CASE("[PacketPeer][PacketPeerStream] Get packet buffer from an empty peer") { + Ref<StreamPeerBuffer> spb; + spb.instantiate(); + + Ref<PacketPeerStream> pps; + pps.instantiate(); + pps->set_stream_peer(spb); + + Vector<uint8_t> buffer; + ERR_PRINT_OFF; + CHECK_EQ(pps->get_packet_buffer(buffer), Error::ERR_UNAVAILABLE); + ERR_PRINT_ON; + CHECK_EQ(buffer.size(), 0); +} + +TEST_CASE("[PacketPeer][PacketPeerStream] Put packet buffer") { + String godot_rules = "Godot Rules!!!"; + + Ref<StreamPeerBuffer> spb; + spb.instantiate(); + + Ref<PacketPeerStream> pps; + pps.instantiate(); + pps->set_stream_peer(spb); + + CHECK_EQ(pps->put_packet_buffer(godot_rules.to_ascii_buffer()), Error::OK); + + spb->seek(0); + CHECK_EQ(spb->get_string(), godot_rules); + // First 4 bytes are the length of the string. + CharString cs = godot_rules.ascii(); + Vector<uint8_t> buffer = { (uint8_t)cs.length(), 0, 0, 0 }; + buffer.resize(4 + cs.length()); + memcpy(buffer.ptrw() + 4, cs.get_data(), cs.length()); + CHECK_EQ(spb->get_data_array(), buffer); +} + +TEST_CASE("[PacketPeer][PacketPeerStream] Put packet buffer when is empty") { + Ref<StreamPeerBuffer> spb; + spb.instantiate(); + + Ref<PacketPeerStream> pps; + pps.instantiate(); + pps->set_stream_peer(spb); + + Vector<uint8_t> buffer; + CHECK_EQ(pps->put_packet_buffer(buffer), Error::OK); + + CHECK_EQ(spb->get_size(), 0); +} + +} // namespace TestPacketPeer + +#endif // TEST_PACKET_PEER_H diff --git a/tests/core/io/test_stream_peer.h b/tests/core/io/test_stream_peer.h new file mode 100644 index 0000000000..31bd69edd0 --- /dev/null +++ b/tests/core/io/test_stream_peer.h @@ -0,0 +1,289 @@ +/**************************************************************************/ +/* test_stream_peer.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. */ +/**************************************************************************/ + +#ifndef TEST_STREAM_PEER_H +#define TEST_STREAM_PEER_H + +#include "core/io/stream_peer.h" +#include "tests/test_macros.h" + +namespace TestStreamPeer { + +TEST_CASE("[StreamPeer] Initialization through StreamPeerBuffer") { + Ref<StreamPeerBuffer> spb; + spb.instantiate(); + + CHECK_EQ(spb->is_big_endian_enabled(), false); +} + +TEST_CASE("[StreamPeer] Get and sets through StreamPeerBuffer") { + Ref<StreamPeerBuffer> spb; + spb.instantiate(); + + SUBCASE("A int8_t value") { + int8_t value = 42; + + spb->clear(); + spb->put_8(value); + spb->seek(0); + + CHECK_EQ(spb->get_8(), value); + } + + SUBCASE("A uint8_t value") { + uint8_t value = 42; + + spb->clear(); + spb->put_u8(value); + spb->seek(0); + + CHECK_EQ(spb->get_u8(), value); + } + + SUBCASE("A int16_t value") { + int16_t value = 42; + + spb->clear(); + spb->put_16(value); + spb->seek(0); + + CHECK_EQ(spb->get_16(), value); + } + + SUBCASE("A uint16_t value") { + uint16_t value = 42; + + spb->clear(); + spb->put_u16(value); + spb->seek(0); + + CHECK_EQ(spb->get_u16(), value); + } + + SUBCASE("A int32_t value") { + int32_t value = 42; + + spb->clear(); + spb->put_32(value); + spb->seek(0); + + CHECK_EQ(spb->get_32(), value); + } + + SUBCASE("A uint32_t value") { + uint32_t value = 42; + + spb->clear(); + spb->put_u32(value); + spb->seek(0); + + CHECK_EQ(spb->get_u32(), value); + } + + SUBCASE("A int64_t value") { + int64_t value = 42; + + spb->clear(); + spb->put_64(value); + spb->seek(0); + + CHECK_EQ(spb->get_64(), value); + } + + SUBCASE("A int64_t value") { + uint64_t value = 42; + + spb->clear(); + spb->put_u64(value); + spb->seek(0); + + CHECK_EQ(spb->get_u64(), value); + } + + SUBCASE("A float value") { + float value = 42.0f; + + spb->clear(); + spb->put_float(value); + spb->seek(0); + + CHECK_EQ(spb->get_float(), value); + } + + SUBCASE("A double value") { + double value = 42.0; + + spb->clear(); + spb->put_double(value); + spb->seek(0); + + CHECK_EQ(spb->get_double(), value); + } + + SUBCASE("A string value") { + String value = "Hello, World!"; + + spb->clear(); + spb->put_string(value); + spb->seek(0); + + CHECK_EQ(spb->get_string(), value); + } + + SUBCASE("A utf8 string value") { + String value = String::utf8("Hello✩, World✩!"); + + spb->clear(); + spb->put_utf8_string(value); + spb->seek(0); + + CHECK_EQ(spb->get_utf8_string(), value); + } + + SUBCASE("A variant value") { + Array value; + value.push_front(42); + value.push_front("Hello, World!"); + + spb->clear(); + spb->put_var(value); + spb->seek(0); + + CHECK_EQ(spb->get_var(), value); + } +} + +TEST_CASE("[StreamPeer] Get and sets big endian through StreamPeerBuffer") { + Ref<StreamPeerBuffer> spb; + spb.instantiate(); + spb->set_big_endian(true); + + SUBCASE("A int16_t value") { + int16_t value = 42; + + spb->clear(); + spb->put_16(value); + spb->seek(0); + + CHECK_EQ(spb->get_16(), value); + } + + SUBCASE("A uint16_t value") { + uint16_t value = 42; + + spb->clear(); + spb->put_u16(value); + spb->seek(0); + + CHECK_EQ(spb->get_u16(), value); + } + + SUBCASE("A int32_t value") { + int32_t value = 42; + + spb->clear(); + spb->put_32(value); + spb->seek(0); + + CHECK_EQ(spb->get_32(), value); + } + + SUBCASE("A uint32_t value") { + uint32_t value = 42; + + spb->clear(); + spb->put_u32(value); + spb->seek(0); + + CHECK_EQ(spb->get_u32(), value); + } + + SUBCASE("A int64_t value") { + int64_t value = 42; + + spb->clear(); + spb->put_64(value); + spb->seek(0); + + CHECK_EQ(spb->get_64(), value); + } + + SUBCASE("A int64_t value") { + uint64_t value = 42; + + spb->clear(); + spb->put_u64(value); + spb->seek(0); + + CHECK_EQ(spb->get_u64(), value); + } + + SUBCASE("A float value") { + float value = 42.0f; + + spb->clear(); + spb->put_float(value); + spb->seek(0); + + CHECK_EQ(spb->get_float(), value); + } + + SUBCASE("A double value") { + double value = 42.0; + + spb->clear(); + spb->put_double(value); + spb->seek(0); + + CHECK_EQ(spb->get_double(), value); + } +} + +TEST_CASE("[StreamPeer] Get string when there is no string") { + Ref<StreamPeerBuffer> spb; + spb.instantiate(); + + ERR_PRINT_OFF; + CHECK_EQ(spb->get_string(), ""); + ERR_PRINT_ON; +} + +TEST_CASE("[StreamPeer] Get UTF8 string when there is no string") { + Ref<StreamPeerBuffer> spb; + spb.instantiate(); + + ERR_PRINT_OFF; + CHECK_EQ(spb->get_utf8_string(), ""); + ERR_PRINT_ON; +} + +} // namespace TestStreamPeer + +#endif // TEST_STREAM_PEER_H diff --git a/tests/core/io/test_stream_peer_buffer.h b/tests/core/io/test_stream_peer_buffer.h new file mode 100644 index 0000000000..8ba9c0a72c --- /dev/null +++ b/tests/core/io/test_stream_peer_buffer.h @@ -0,0 +1,185 @@ +/**************************************************************************/ +/* test_stream_peer_buffer.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. */ +/**************************************************************************/ + +#ifndef TEST_STREAM_PEER_BUFFER_H +#define TEST_STREAM_PEER_BUFFER_H + +#include "core/io/stream_peer.h" +#include "tests/test_macros.h" + +namespace TestStreamPeerBuffer { + +TEST_CASE("[StreamPeerBuffer] Initialization") { + Ref<StreamPeerBuffer> spb; + spb.instantiate(); + CHECK_EQ(spb->get_size(), 0); + CHECK_EQ(spb->get_position(), 0); + CHECK_EQ(spb->get_available_bytes(), 0); +} + +TEST_CASE("[StreamPeerBuffer] Seek") { + Ref<StreamPeerBuffer> spb; + spb.instantiate(); + uint8_t first = 5; + uint8_t second = 7; + uint8_t third = 11; + + spb->put_u8(first); + spb->put_u8(second); + spb->put_u8(third); + + spb->seek(0); + CHECK_EQ(spb->get_u8(), first); + CHECK_EQ(spb->get_u8(), second); + CHECK_EQ(spb->get_u8(), third); + + spb->seek(1); + CHECK_EQ(spb->get_position(), 1); + CHECK_EQ(spb->get_u8(), second); + + spb->seek(1); + ERR_PRINT_OFF; + spb->seek(-1); + ERR_PRINT_ON; + CHECK_EQ(spb->get_position(), 1); + ERR_PRINT_OFF; + spb->seek(5); + ERR_PRINT_ON; + CHECK_EQ(spb->get_position(), 1); +} + +TEST_CASE("[StreamPeerBuffer] Resize") { + Ref<StreamPeerBuffer> spb; + spb.instantiate(); + CHECK_EQ(spb->get_size(), 0); + CHECK_EQ(spb->get_position(), 0); + CHECK_EQ(spb->get_available_bytes(), 0); + + spb->resize(42); + CHECK_EQ(spb->get_size(), 42); + CHECK_EQ(spb->get_position(), 0); + CHECK_EQ(spb->get_available_bytes(), 42); + + spb->seek(21); + CHECK_EQ(spb->get_size(), 42); + CHECK_EQ(spb->get_position(), 21); + CHECK_EQ(spb->get_available_bytes(), 21); +} + +TEST_CASE("[StreamPeerBuffer] Get underlying data array") { + uint8_t first = 5; + uint8_t second = 7; + uint8_t third = 11; + + Ref<StreamPeerBuffer> spb; + spb.instantiate(); + spb->put_u8(first); + spb->put_u8(second); + spb->put_u8(third); + + Vector<uint8_t> data_array = spb->get_data_array(); + + CHECK_EQ(data_array[0], first); + CHECK_EQ(data_array[1], second); + CHECK_EQ(data_array[2], third); +} + +TEST_CASE("[StreamPeerBuffer] Set underlying data array") { + uint8_t first = 5; + uint8_t second = 7; + uint8_t third = 11; + + Ref<StreamPeerBuffer> spb; + spb.instantiate(); + spb->put_u8(1); + spb->put_u8(2); + spb->put_u8(3); + + Vector<uint8_t> new_data_array; + new_data_array.push_back(first); + new_data_array.push_back(second); + new_data_array.push_back(third); + + spb->set_data_array(new_data_array); + + CHECK_EQ(spb->get_u8(), first); + CHECK_EQ(spb->get_u8(), second); + CHECK_EQ(spb->get_u8(), third); +} + +TEST_CASE("[StreamPeerBuffer] Duplicate") { + uint8_t first = 5; + uint8_t second = 7; + uint8_t third = 11; + + Ref<StreamPeerBuffer> spb; + spb.instantiate(); + spb->put_u8(first); + spb->put_u8(second); + spb->put_u8(third); + + Ref<StreamPeerBuffer> spb2 = spb->duplicate(); + + CHECK_EQ(spb2->get_u8(), first); + CHECK_EQ(spb2->get_u8(), second); + CHECK_EQ(spb2->get_u8(), third); +} + +TEST_CASE("[StreamPeerBuffer] Put data with size equal to zero does nothing") { + Ref<StreamPeerBuffer> spb; + spb.instantiate(); + uint8_t data = 42; + + Error error = spb->put_data((const uint8_t *)&data, 0); + + CHECK_EQ(error, OK); + CHECK_EQ(spb->get_size(), 0); + CHECK_EQ(spb->get_position(), 0); + CHECK_EQ(spb->get_available_bytes(), 0); +} + +TEST_CASE("[StreamPeerBuffer] Get data with invalid size returns an error") { + Ref<StreamPeerBuffer> spb; + spb.instantiate(); + uint8_t data = 42; + spb->put_u8(data); + spb->seek(0); + + uint8_t data_out = 0; + Error error = spb->get_data(&data_out, 3); + + CHECK_EQ(error, ERR_INVALID_PARAMETER); + CHECK_EQ(spb->get_size(), 1); + CHECK_EQ(spb->get_position(), 1); +} + +} // namespace TestStreamPeerBuffer + +#endif // TEST_STREAM_PEER_BUFFER_H diff --git a/tests/core/string/test_string.h b/tests/core/string/test_string.h index a9f615af84..8559737e74 100644 --- a/tests/core/string/test_string.h +++ b/tests/core/string/test_string.h @@ -1888,7 +1888,7 @@ TEST_CASE("[String] validate_node_name") { CHECK(name_with_invalid_chars.validate_node_name() == "Name with invalid characters ____removed!"); } -TEST_CASE("[String] validate_identifier") { +TEST_CASE("[String] validate_ascii_identifier") { String empty_string; CHECK(empty_string.validate_ascii_identifier() == "_"); @@ -1902,6 +1902,20 @@ TEST_CASE("[String] validate_identifier") { CHECK(name_with_invalid_chars.validate_ascii_identifier() == "Invalid_characters_______"); } +TEST_CASE("[String] validate_unicode_identifier") { + String empty_string; + CHECK(empty_string.validate_unicode_identifier() == "_"); + + String numeric_only = "12345"; + CHECK(numeric_only.validate_unicode_identifier() == "_12345"); + + String name_with_spaces = "Name with spaces"; + CHECK(name_with_spaces.validate_unicode_identifier() == "Name_with_spaces"); + + String name_with_invalid_chars = U"Invalid characters:@*#&世界"; + CHECK(name_with_invalid_chars.validate_unicode_identifier() == U"Invalid_characters_____世界"); +} + TEST_CASE("[String] Variant indexed get") { Variant s = String("abcd"); bool valid = false; @@ -1974,6 +1988,61 @@ TEST_CASE("[String] Variant ptr indexed set") { CHECK_EQ(s, String("azcd")); } +TEST_CASE("[String][URL] Parse URL") { +#define CHECK_URL(m_url_to_parse, m_expected_schema, m_expected_host, m_expected_port, m_expected_path, m_expected_fragment, m_expected_error) \ + if (true) { \ + int port; \ + String url(m_url_to_parse), schema, host, path, fragment; \ + \ + CHECK_EQ(url.parse_url(schema, host, port, path, fragment), m_expected_error); \ + CHECK_EQ(schema, m_expected_schema); \ + CHECK_EQ(host, m_expected_host); \ + CHECK_EQ(path, m_expected_path); \ + CHECK_EQ(fragment, m_expected_fragment); \ + CHECK_EQ(port, m_expected_port); \ + } else \ + ((void)0) + + // All elements. + CHECK_URL("https://www.example.com:8080/path/to/file.html#fragment", "https://", "www.example.com", 8080, "/path/to/file.html", "fragment", Error::OK); + + // Valid URLs. + CHECK_URL("https://godotengine.org", "https://", "godotengine.org", 0, "", "", Error::OK); + CHECK_URL("https://godotengine.org/", "https://", "godotengine.org", 0, "/", "", Error::OK); + CHECK_URL("godotengine.org/", "", "godotengine.org", 0, "/", "", Error::OK); + CHECK_URL("HTTPS://godotengine.org/", "https://", "godotengine.org", 0, "/", "", Error::OK); + CHECK_URL("https://GODOTENGINE.ORG/", "https://", "godotengine.org", 0, "/", "", Error::OK); + CHECK_URL("http://godotengine.org", "http://", "godotengine.org", 0, "", "", Error::OK); + CHECK_URL("https://godotengine.org:8080", "https://", "godotengine.org", 8080, "", "", Error::OK); + CHECK_URL("https://godotengine.org/blog", "https://", "godotengine.org", 0, "/blog", "", Error::OK); + CHECK_URL("https://godotengine.org/blog/", "https://", "godotengine.org", 0, "/blog/", "", Error::OK); + CHECK_URL("https://docs.godotengine.org/en/stable", "https://", "docs.godotengine.org", 0, "/en/stable", "", Error::OK); + CHECK_URL("https://docs.godotengine.org/en/stable/", "https://", "docs.godotengine.org", 0, "/en/stable/", "", Error::OK); + CHECK_URL("https://me:secret@godotengine.org", "https://", "godotengine.org", 0, "", "", Error::OK); + CHECK_URL("https://[FEDC:BA98:7654:3210:FEDC:BA98:7654:3210]/ipv6", "https://", "fedc:ba98:7654:3210:fedc:ba98:7654:3210", 0, "/ipv6", "", Error::OK); + + // Scheme vs Fragment. + CHECK_URL("google.com/#goto=http://redirect_url/", "", "google.com", 0, "/", "goto=http://redirect_url/", Error::OK); + + // Invalid URLs. + + // Invalid Scheme. + CHECK_URL("https_://godotengine.org", "", "https_", 0, "//godotengine.org", "", Error::ERR_INVALID_PARAMETER); + + // Multiple ports. + CHECK_URL("https://godotengine.org:8080:433", "https://", "", 0, "", "", Error::ERR_INVALID_PARAMETER); + // Missing ] on literal IPv6. + CHECK_URL("https://[FEDC:BA98:7654:3210:FEDC:BA98:7654:3210/ipv6", "https://", "", 0, "/ipv6", "", Error::ERR_INVALID_PARAMETER); + // Missing host. + CHECK_URL("https:///blog", "https://", "", 0, "/blog", "", Error::ERR_INVALID_PARAMETER); + // Invalid ports. + CHECK_URL("https://godotengine.org:notaport", "https://", "godotengine.org", 0, "", "", Error::ERR_INVALID_PARAMETER); + CHECK_URL("https://godotengine.org:-8080", "https://", "godotengine.org", -8080, "", "", Error::ERR_INVALID_PARAMETER); + CHECK_URL("https://godotengine.org:88888", "https://", "godotengine.org", 88888, "", "", Error::ERR_INVALID_PARAMETER); + +#undef CHECK_URL +} + TEST_CASE("[Stress][String] Empty via ' == String()'") { for (int i = 0; i < 100000; ++i) { String str = "Hello World!"; diff --git a/tests/scene/test_code_edit.h b/tests/scene/test_code_edit.h index 9ec1b812df..ef630ad4f7 100644 --- a/tests/scene/test_code_edit.h +++ b/tests/scene/test_code_edit.h @@ -4779,6 +4779,31 @@ TEST_CASE("[SceneTree][CodeEdit] text manipulation") { CHECK(code_edit->get_caret_column(3) == 0); } + SUBCASE("[SceneTree][CodeEdit] cut when empty selection clipboard disabled") { + DisplayServerMock *DS = (DisplayServerMock *)(DisplayServer::get_singleton()); + code_edit->set_empty_selection_clipboard_enabled(false); + DS->clipboard_set(""); + + code_edit->set_text("this is\nsome\n"); + code_edit->set_caret_line(0); + code_edit->set_caret_column(6); + MessageQueue::get_singleton()->flush(); + SIGNAL_DISCARD("text_set"); + SIGNAL_DISCARD("text_changed"); + SIGNAL_DISCARD("lines_edited_from"); + SIGNAL_DISCARD("caret_changed"); + + code_edit->cut(); + MessageQueue::get_singleton()->flush(); + CHECK(DS->clipboard_get() == ""); + CHECK(code_edit->get_text() == "this is\nsome\n"); + CHECK(code_edit->get_caret_line() == 0); + CHECK(code_edit->get_caret_column() == 6); + SIGNAL_CHECK_FALSE("caret_changed"); + SIGNAL_CHECK_FALSE("text_changed"); + SIGNAL_CHECK_FALSE("lines_edited_from"); + } + SUBCASE("[SceneTree][CodeEdit] new line") { // Add a new line. code_edit->set_text("test new line"); diff --git a/tests/scene/test_physics_material.h b/tests/scene/test_physics_material.h new file mode 100644 index 0000000000..a078166f42 --- /dev/null +++ b/tests/scene/test_physics_material.h @@ -0,0 +1,107 @@ +/**************************************************************************/ +/* test_physics_material.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. */ +/**************************************************************************/ + +#ifndef TEST_PHYSICS_MATERIAL_H +#define TEST_PHYSICS_MATERIAL_H + +#include "scene/resources/physics_material.h" +#include "tests/test_macros.h" + +namespace TestPhysics_material { + +TEST_CASE("[Physics_material] Defaults") { + Ref<PhysicsMaterial> physics_material; + physics_material.instantiate(); + + CHECK(physics_material->get_friction() == 1.); + CHECK(physics_material->is_rough() == false); + CHECK(physics_material->get_bounce() == 0.); + CHECK(physics_material->is_absorbent() == false); +} + +TEST_CASE("[Physics_material] Friction") { + Ref<PhysicsMaterial> physics_material; + physics_material.instantiate(); + + real_t friction = 0.314; + physics_material->set_friction(friction); + CHECK(physics_material->get_friction() == friction); +} + +TEST_CASE("[Physics_material] Rough") { + Ref<PhysicsMaterial> physics_material; + physics_material.instantiate(); + + bool rough = true; + physics_material->set_rough(rough); + CHECK(physics_material->is_rough() == rough); + + real_t friction = 0.314; + physics_material->set_friction(friction); + CHECK(physics_material->computed_friction() == -friction); + + rough = false; + physics_material->set_rough(rough); + CHECK(physics_material->is_rough() == rough); + + CHECK(physics_material->computed_friction() == friction); +} + +TEST_CASE("[Physics_material] Bounce") { + Ref<PhysicsMaterial> physics_material; + physics_material.instantiate(); + + real_t bounce = 0.271; + physics_material->set_bounce(bounce); + CHECK(physics_material->get_bounce() == bounce); +} + +TEST_CASE("[Physics_material] Absorbent") { + Ref<PhysicsMaterial> physics_material; + physics_material.instantiate(); + + bool absorbent = true; + physics_material->set_absorbent(absorbent); + CHECK(physics_material->is_absorbent() == absorbent); + + real_t bounce = 0.271; + physics_material->set_bounce(bounce); + CHECK(physics_material->computed_bounce() == -bounce); + + absorbent = false; + physics_material->set_absorbent(absorbent); + CHECK(physics_material->is_absorbent() == absorbent); + + CHECK(physics_material->computed_bounce() == bounce); +} + +} // namespace TestPhysics_material + +#endif // TEST_PHYSICS_MATERIAL_H diff --git a/tests/scene/test_sky.h b/tests/scene/test_sky.h new file mode 100644 index 0000000000..812ea9b5ad --- /dev/null +++ b/tests/scene/test_sky.h @@ -0,0 +1,141 @@ +/**************************************************************************/ +/* test_sky.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. */ +/**************************************************************************/ + +#ifndef TEST_SKY_H +#define TEST_SKY_H + +#include "scene/resources/sky.h" + +#include "tests/test_macros.h" + +namespace TestSky { + +TEST_CASE("[SceneTree][Sky] Constructor") { + Sky *test_sky = memnew(Sky); + + CHECK(test_sky->get_process_mode() == Sky::PROCESS_MODE_AUTOMATIC); + CHECK(test_sky->get_radiance_size() == Sky::RADIANCE_SIZE_256); + CHECK(test_sky->get_material().is_null()); + memdelete(test_sky); +} + +TEST_CASE("[SceneTree][Sky] Radiance size setter and getter") { + Sky *test_sky = memnew(Sky); + + // Check default. + CHECK(test_sky->get_radiance_size() == Sky::RADIANCE_SIZE_256); + + test_sky->set_radiance_size(Sky::RADIANCE_SIZE_1024); + CHECK(test_sky->get_radiance_size() == Sky::RADIANCE_SIZE_1024); + + ERR_PRINT_OFF; + // Check setting invalid radiance size. + test_sky->set_radiance_size(Sky::RADIANCE_SIZE_MAX); + ERR_PRINT_ON; + + CHECK(test_sky->get_radiance_size() == Sky::RADIANCE_SIZE_1024); + + memdelete(test_sky); +} + +TEST_CASE("[SceneTree][Sky] Process mode setter and getter") { + Sky *test_sky = memnew(Sky); + + // Check default. + CHECK(test_sky->get_process_mode() == Sky::PROCESS_MODE_AUTOMATIC); + + test_sky->set_process_mode(Sky::PROCESS_MODE_INCREMENTAL); + CHECK(test_sky->get_process_mode() == Sky::PROCESS_MODE_INCREMENTAL); + + memdelete(test_sky); +} + +TEST_CASE("[SceneTree][Sky] Material setter and getter") { + Sky *test_sky = memnew(Sky); + Ref<Material> material = memnew(Material); + + SUBCASE("Material passed to the class should remain the same") { + test_sky->set_material(material); + CHECK(test_sky->get_material() == material); + } + SUBCASE("Material passed many times to the class should remain the same") { + test_sky->set_material(material); + test_sky->set_material(material); + test_sky->set_material(material); + CHECK(test_sky->get_material() == material); + } + SUBCASE("Material rewrite testing") { + Ref<Material> material1 = memnew(Material); + Ref<Material> material2 = memnew(Material); + + test_sky->set_material(material1); + test_sky->set_material(material2); + CHECK_MESSAGE(test_sky->get_material() != material1, + "After rewrite, second material should be in class."); + CHECK_MESSAGE(test_sky->get_material() == material2, + "After rewrite, second material should be in class."); + } + + SUBCASE("Assign same material to two skys") { + Sky *sky2 = memnew(Sky); + + test_sky->set_material(material); + sky2->set_material(material); + CHECK_MESSAGE(test_sky->get_material() == sky2->get_material(), + "Both skys should have the same material."); + memdelete(sky2); + } + + SUBCASE("Swapping materials between two skys") { + Sky *sky2 = memnew(Sky); + Ref<Material> material1 = memnew(Material); + Ref<Material> material2 = memnew(Material); + + test_sky->set_material(material1); + sky2->set_material(material2); + CHECK(test_sky->get_material() == material1); + CHECK(sky2->get_material() == material2); + + // Do the swap. + Ref<Material> temp = test_sky->get_material(); + test_sky->set_material(sky2->get_material()); + sky2->set_material(temp); + + CHECK(test_sky->get_material() == material2); + CHECK(sky2->get_material() == material1); + memdelete(sky2); + } + + memdelete(test_sky); +} + +} // namespace TestSky + +#endif // TEST_SKY_H diff --git a/tests/scene/test_text_edit.h b/tests/scene/test_text_edit.h index 46a5046b21..c41eebdf3a 100644 --- a/tests/scene/test_text_edit.h +++ b/tests/scene/test_text_edit.h @@ -3585,6 +3585,54 @@ TEST_CASE("[SceneTree][TextEdit] text entry") { SIGNAL_CHECK_FALSE("lines_edited_from"); } + SUBCASE("[TextEdit] cut when empty selection clipboard disabled") { + text_edit->set_empty_selection_clipboard_enabled(false); + DS->clipboard_set(""); + + text_edit->set_text("this is\nsome\n"); + text_edit->set_caret_line(0); + text_edit->set_caret_column(6); + MessageQueue::get_singleton()->flush(); + SIGNAL_DISCARD("text_set"); + SIGNAL_DISCARD("text_changed"); + SIGNAL_DISCARD("lines_edited_from"); + SIGNAL_DISCARD("caret_changed"); + + text_edit->cut(); + MessageQueue::get_singleton()->flush(); + CHECK(DS->clipboard_get() == ""); + CHECK(text_edit->get_text() == "this is\nsome\n"); + CHECK(text_edit->get_caret_line() == 0); + CHECK(text_edit->get_caret_column() == 6); + SIGNAL_CHECK_FALSE("caret_changed"); + SIGNAL_CHECK_FALSE("text_changed"); + SIGNAL_CHECK_FALSE("lines_edited_from"); + } + + SUBCASE("[TextEdit] copy when empty selection clipboard disabled") { + text_edit->set_empty_selection_clipboard_enabled(false); + DS->clipboard_set(""); + + text_edit->set_text("this is\nsome\n"); + text_edit->set_caret_line(0); + text_edit->set_caret_column(6); + MessageQueue::get_singleton()->flush(); + SIGNAL_DISCARD("text_set"); + SIGNAL_DISCARD("text_changed"); + SIGNAL_DISCARD("lines_edited_from"); + SIGNAL_DISCARD("caret_changed"); + + text_edit->copy(); + MessageQueue::get_singleton()->flush(); + CHECK(DS->clipboard_get() == ""); + CHECK(text_edit->get_text() == "this is\nsome\n"); + CHECK(text_edit->get_caret_line() == 0); + CHECK(text_edit->get_caret_column() == 6); + SIGNAL_CHECK_FALSE("caret_changed"); + SIGNAL_CHECK_FALSE("text_changed"); + SIGNAL_CHECK_FALSE("lines_edited_from"); + } + SIGNAL_UNWATCH(text_edit, "text_set"); SIGNAL_UNWATCH(text_edit, "text_changed"); SIGNAL_UNWATCH(text_edit, "lines_edited_from"); diff --git a/tests/scene/test_viewport.h b/tests/scene/test_viewport.h index 9d02c41719..dde37944ec 100644 --- a/tests/scene/test_viewport.h +++ b/tests/scene/test_viewport.h @@ -38,6 +38,7 @@ #include "scene/main/canvas_layer.h" #include "scene/main/window.h" #include "scene/resources/2d/rectangle_shape_2d.h" +#include "servers/physics_server_2d_dummy.h" #include "tests/test_macros.h" @@ -1550,6 +1551,12 @@ int TestArea2D::counter = 0; TEST_CASE("[SceneTree][Viewport] Physics Picking 2D") { // FIXME: MOUSE_MODE_CAPTURED if-conditions are not testable, because DisplayServerMock doesn't support it. + // NOTE: This test requires a real physics server. + PhysicsServer2DDummy *physics_server_2d_dummy = Object::cast_to<PhysicsServer2DDummy>(PhysicsServer2D::get_singleton()); + if (physics_server_2d_dummy) { + return; + } + struct PickingCollider { TestArea2D *a; CollisionShape2D *c; diff --git a/tests/test_main.cpp b/tests/test_main.cpp index 2721a4f710..465484d605 100644 --- a/tests/test_main.cpp +++ b/tests/test_main.cpp @@ -50,8 +50,11 @@ #include "tests/core/io/test_json.h" #include "tests/core/io/test_json_native.h" #include "tests/core/io/test_marshalls.h" +#include "tests/core/io/test_packet_peer.h" #include "tests/core/io/test_pck_packer.h" #include "tests/core/io/test_resource.h" +#include "tests/core/io/test_stream_peer.h" +#include "tests/core/io/test_stream_peer_buffer.h" #include "tests/core/io/test_xml_parser.h" #include "tests/core/math/test_aabb.h" #include "tests/core/math/test_astar.h" @@ -122,6 +125,7 @@ #include "tests/scene/test_parallax_2d.h" #include "tests/scene/test_path_2d.h" #include "tests/scene/test_path_follow_2d.h" +#include "tests/scene/test_physics_material.h" #include "tests/scene/test_sprite_frames.h" #include "tests/scene/test_style_box_texture.h" #include "tests/scene/test_theme.h" @@ -163,6 +167,7 @@ #include "tests/scene/test_path_follow_3d.h" #include "tests/scene/test_primitives.h" #include "tests/scene/test_skeleton_3d.h" +#include "tests/scene/test_sky.h" #endif // _3D_DISABLED #include "modules/modules_tests.gen.h" @@ -176,8 +181,10 @@ #include "servers/navigation_server_3d.h" #endif // _3D_DISABLED #include "servers/physics_server_2d.h" +#include "servers/physics_server_2d_dummy.h" #ifndef _3D_DISABLED #include "servers/physics_server_3d.h" +#include "servers/physics_server_3d_dummy.h" #endif // _3D_DISABLED #include "servers/rendering/rendering_server_default.h" @@ -292,10 +299,16 @@ struct GodotTestCaseListener : public doctest::IReporter { #ifndef _3D_DISABLED physics_server_3d = PhysicsServer3DManager::get_singleton()->new_default_server(); + if (!physics_server_3d) { + physics_server_3d = memnew(PhysicsServer3DDummy); + } physics_server_3d->init(); #endif // _3D_DISABLED physics_server_2d = PhysicsServer2DManager::get_singleton()->new_default_server(); + if (!physics_server_2d) { + physics_server_2d = memnew(PhysicsServer2DDummy); + } physics_server_2d->init(); #ifndef _3D_DISABLED |