Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add Object support for compare_deep() #662

Open
neth392 opened this issue Sep 13, 2024 · 3 comments
Open

Add Object support for compare_deep() #662

neth392 opened this issue Sep 13, 2024 · 3 comments

Comments

@neth392
Copy link

neth392 commented Sep 13, 2024

Versions

What versions of Godot do you want to use this feature in?
Latest

The Feature

I am writing tests for a serialization library. The tests involve comparing original object instances to their deserialized counterparts. Godot's == does not work with this as the objects are two different instances, but I need to test to see if their property values match. If compare_deep supported objects this would be great, as right now I have to write some really hacky code to make these tests work & be verbose enough to isolate which properties do not match. Recursive support would be needed too as objects can have properties whose values are other objects

@bitwes
Copy link
Owner

bitwes commented Sep 16, 2024

This seems out of scope for compare_deep, even though it feels very similar. If you have a dictionary or array of of things to compare then maybe GUT could get a compare_deep_custom that would allow you to specify a Callable to compare two elements.

If you only have two objects you want to compare you might be able to use compare_deep with the results of inst_to_dict. I'm not sure if inst_to_dict handles sub-objects but it shouldn't be too difficult to add that. You can also use get_property_list and get to go through each property.

If I'm misunderstanding the request, add some sample code.

@neth392
Copy link
Author

neth392 commented Sep 16, 2024

That's a good point. I didn't think of trying inst_to_dict, maybe it could've worked. A compare_deep_custom(callable) could work but it'd have to account for properties that are other objects and so on, and be able to isolate at what level there was an issue, say if "MyObject.other_object_property.another_object_property" didn't match.

I wrote some functions to use in a GutTest (link below) where I needed to compare objects & arrays/dictionaries possibly containing objects, so that'd be a good sample of why I needed it. The initial code I had written didn't really isolate what failed the comparison so that's why I recursively return a string, and concatenate it back up that recursive chain until it's printed as 1 string containing all the info I need to see what failed. May be something to consider if it's decided to implement this

https://github.com/neth392/godot-improved-json/blob/main/tests/test_custom_objects.gd#L160

@christo8989
Copy link

christo8989 commented Nov 25, 2024

There are problems with this implementation but if anyone wants a quick and dirty approach:

USE WITH CAUTION!!!! (I haven't tested)

func deep(v1, v2):
	var result =  null

	if(GutUtils.are_datatypes_same(v1, v2)):
		if(typeof(v1) in [TYPE_ARRAY, TYPE_DICTIONARY]):
			result = GutUtils.DiffTool.new(v1, v2, GutUtils.DIFF.DEEP)
		elif (
			typeof(v1) == TYPE_OBJECT and 
			typeof(v2) == TYPE_OBJECT and 
			v1.get_class() == v2.get_class()
		):
			if v1.has_method('equal'):
				result = simple(v1.equal(v2), true)
			else:
				for property in v1.get_property_list():
					if property.usage != PROPERTY_USAGE_SCRIPT_VARIABLE:
						continue
					result = deep(v1[property.name], v2[property.name])
		else:
			result = simple(v1, v2)
	else:
		result = simple(v1, v2)

	return result

Maybe it'd be best to first check for an .equal function on the object, and if it's not found, perform the following. So, they can override this default behavior that is somewhat arbitrary.

Also, I haven't tested this too deeply. So, I don't know how well the recursiveness works.

EDIT:

I cleaned up the code a bit and added the .equal part.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

3 participants