Godot: == returns false for references to the same object, sometimes.

Created on 28 Oct 2020  路  4Comments  路  Source: godotengine/godot

Godot version:
3.2.4 beta

OS/device including version:
macOS Catalina 10.15.6

Issue description:

When running the tests for the GUT framework using 3.2.4 beta I found some tests failing when checking to see if two references to an object were the same. When printed out though, the str of both objects shows the same object.

When run against earlier versions of Godot these tests pass. Some of the tests that are failing have been passing for a couple years now.

Steps to reproduce:
I have not been able to reproduce the issue outside of the GUT project. I've tried to create a standalone script that would replicate the issue but I've not been able to. If I put the same "failing" code from a test into a standalone script it works as expected.

Here is the simplest test case I was able to create. This tries to minimize the use of GUT. GUT should only be creating an instance of this script and running the test_using_local_copy_of_connection_check_logic method in this case. GUT does A LOT of other things though, so it's still feasible that GUT is doing something bad, but that seems unlikely given this code has worked for a long time now.

extends 'res://addons/gut/test.gd'

const SIGNAL_NAME = 'test_signal'
const METHOD_NAME = 'test_signal_connector'

class Signaler:
    signal test_signal

class ConnectTo:
    func test_signal_connector():
        pass

# Simulates the check used by assert_connected when a method name is
# not specified.  Checks for a connection between the two objects for
# the given signal without caring about what method it is connected to.
func _check_if_connected(signaler_obj, connect_to_obj, signal_name):
    var connections = signaler_obj.get_signal_connection_list(signal_name)
    for conn in connections:
        print('source/signaler:  ', conn.source, '==', signaler_obj, ' is ', conn.source == signaler_obj)
        print('target/connect_to:  ', conn.target, '==', connect_to_obj, ' is ', conn.target == connect_to_obj)
        if((conn.source == signaler_obj) and (conn.target == connect_to_obj)):
            return true
    return false

func test_using_local_copy_of_connection_check_logic():
    var s = Signaler.new()
    var c = ConnectTo.new()
    s.connect(SIGNAL_NAME, c, METHOD_NAME)
    print('check result = ', _check_if_connected(s, c, SIGNAL_NAME))

which generates the output:

res://test/integration/test_345_beta_issues_simple.gd
* test_using_local_copy_of_connection_check_logic
source/signaler:  [Reference:2619]==[Reference:2619] is False
target/connect_to:  [Reference:2620]==[Reference:2620] is False
check result = False

The print statements in _check_if_connected shows both references are the same in both cases (2619 = 2619 and 2620 = 2620) but the == check shows false.

Note This does not happen just when checking connections. This was just the simplest example I was able to come up with. Another area where tests were failing had to do with creating dynamic objects that have a dictionary of instances set using instance_from_id. I tried recreating the issue using dictionaries b/c that started to smell like the problem but was not able to recreate the issue in a standalone script.

Minimal reproduction project:

I'm happy to try to create a more simplified example if needed. After putting a couple hours into this I figured it was time to stop unless you need more information.

I created a branch that has some tests and examples in it.
https://github.com/bitwes/Gut/tree/godot_324_bugs

If you run this command after downloading the branch you'll see the failing tests:

<path-to-godot> -s res://addons/gut/gut_cmdln.gd  -d   -gselect=test_345_beta_issues_simple.gd

You can run all the tests with this command:

<path-to-godot> -s res://addons/gut/gut_cmdln.gd  -d

The related failing tests are (there are around 19 tests that are supposed to fail, the ones below should not):

  • test_when_target_connected_to_source_connected_passes_without_method_name
  • test_spy_is_set_in_metadata
  • test_doubled_have_ref_to_stubber
  • test_double_sets_stubber_for_doubled_class

Bug related files:

The test script shown above
https://github.com/bitwes/Gut/blob/godot_324_bugs/test/integration/test_345_beta_issues_simple.gd

Ported test code to a standalone script which acts as expected. This script also calls the test script code directly which also acts as expected.
https://github.com/bitwes/Gut/blob/godot_324_bugs/scratch/324_simple.gd
run with <path-to-godot> --path $PWD -s scratch/324_simple.gd

A mangled mess trying to replicate the issue in a standalone script. None of which worked.
https://github.com/bitwes/Gut/blob/godot_324_bugs/scratch/324_bugs.gd

bug regression core

Most helpful comment

43049 fixes this. It was again the case of Variant tracking a Reference in two different ways _simultaneously_.

This didn't happen in 3.2.3, because the change to stop decaying freed variables to null is new for 3.2.4. Without that change, the comparison could give a false positive.

All 4 comments

Verified issue exists on Windows 10 Pro version 1803 as well.

I confirm the difficult-to-reproduce issues with GUT testing, see my recent reports: #42305, #42339, #42465.

43049 fixes this. It was again the case of Variant tracking a Reference in two different ways _simultaneously_.

This didn't happen in 3.2.3, because the change to stop decaying freed variables to null is new for 3.2.4. Without that change, the comparison could give a false positive.

Fixed by #43049.

Was this page helpful?
0 / 5 - 0 ratings