1
0
mirror of https://github.com/godotengine/godot.git synced 2025-11-07 12:30:27 +00:00

Merge pull request #99490 from dalexeev/gds-tests-track-multiple-errors

GDScript: Support tracking multiple analyzer and runtime errors in tests
This commit is contained in:
Rémi Verschelde
2024-11-29 22:02:02 +01:00
294 changed files with 540 additions and 1084 deletions

View File

@@ -1,7 +0,0 @@
func test():
var state = PhysicsDirectBodyState3DExtension.new()
assign(state)
state.free()
func assign(state):
state.center_of_mass.x -= 1.0

View File

@@ -1,6 +0,0 @@
GDTEST_RUNTIME_ERROR
>> SCRIPT ERROR
>> on function: assign()
>> runtime/assign_to_read_only_property.gd
>> 7
>> Cannot set value into property "center_of_mass" (on base "PhysicsDirectBodyState3DExtension") because it is read-only.

View File

@@ -1,8 +0,0 @@
func test():
var state = PhysicsDirectBodyState3DExtension.new()
var prop = &"center_of_mass"
assign(state, prop)
state.free()
func assign(state, prop):
state[prop].x = 1.0

View File

@@ -1,6 +0,0 @@
GDTEST_RUNTIME_ERROR
>> SCRIPT ERROR
>> on function: assign()
>> runtime/assign_to_read_only_property_with_variable_index.gd
>> 8
>> Cannot set value into property "center_of_mass" (on base "PhysicsDirectBodyState3DExtension") because it is read-only.

View File

@@ -0,0 +1,22 @@
class A extends Node:
pass
func subtest_native():
var x = Node.new()
x.free()
var _ok = x
var _bad: Node = x
func subtest_script():
var x = A.new()
x.free()
var _ok = x
var _bad: A = x
func test():
subtest_native()
subtest_script()

View File

@@ -0,0 +1,3 @@
GDTEST_RUNTIME_ERROR
>> SCRIPT ERROR at runtime/errors/assign_freed_instance.gd:10 on subtest_native(): Trying to assign invalid previously freed instance.
>> SCRIPT ERROR at runtime/errors/assign_freed_instance.gd:18 on subtest_script(): Trying to assign invalid previously freed instance.

View File

@@ -0,0 +1,11 @@
func subtest_attribute(state):
state.center_of_mass.x -= 1.0
func subtest_variable_index(state, prop):
state[prop].x = 1.0
func test():
var state = PhysicsDirectBodyState3DExtension.new()
subtest_attribute(state)
subtest_variable_index(state, &"center_of_mass")
state.free()

View File

@@ -0,0 +1,6 @@
GDTEST_RUNTIME_ERROR
~~ WARNING at line 9: (UNSAFE_CALL_ARGUMENT) The argument 1 of the function "subtest_attribute()" requires the subtype "Variant" but the supertype "Variant" was provided.
~~ WARNING at line 10: (UNSAFE_CALL_ARGUMENT) The argument 1 of the function "subtest_variable_index()" requires the subtype "Variant" but the supertype "Variant" was provided.
>> ERROR: Required virtual method PhysicsDirectBodyState3DExtension::_get_center_of_mass must be overridden before calling.
>> SCRIPT ERROR at runtime/errors/assign_to_read_only_property.gd:2 on subtest_attribute(): Cannot set value into property "center_of_mass" (on base "PhysicsDirectBodyState3DExtension") because it is read-only.
>> SCRIPT ERROR at runtime/errors/assign_to_read_only_property.gd:5 on subtest_variable_index(): Cannot set value into property "center_of_mass" (on base "PhysicsDirectBodyState3DExtension") because it is read-only.

View File

@@ -1,8 +1,4 @@
GDTEST_RUNTIME_ERROR
>> SCRIPT ERROR
>> on function: weak()
>> runtime/errors/bad_conversion_for_default_parameter.gd
>> 2
>> Trying to assign value of type 'String' to a variable of type 'float'.
>> SCRIPT ERROR at runtime/errors/bad_conversion_for_default_parameter.gd:2 on weak(): Trying to assign value of type 'String' to a variable of type 'float'.
0
not ok

View File

@@ -1,6 +1,2 @@
GDTEST_RUNTIME_ERROR
>> SCRIPT ERROR
>> on function: test()
>> runtime/errors/callable_call_after_free_object.gd
>> 6
>> Attempt to call function 'null::is_inside_tree (Callable)' on a null instance.
>> SCRIPT ERROR at runtime/errors/callable_call_after_free_object.gd:6 on test(): Attempt to call function 'null::is_inside_tree (Callable)' on a null instance.

View File

@@ -1,6 +1,2 @@
GDTEST_RUNTIME_ERROR
>> SCRIPT ERROR
>> on function: test()
>> runtime/errors/cast_freed_object.gd
>> 4
>> Trying to cast a freed object.
>> SCRIPT ERROR at runtime/errors/cast_freed_object.gd:4 on test(): Trying to cast a freed object.

View File

@@ -1,6 +1,2 @@
GDTEST_RUNTIME_ERROR
>> SCRIPT ERROR
>> on function: test()
>> runtime/errors/cast_int_to_array.gd
>> 4
>> Invalid cast: could not convert value to 'Array'.
>> SCRIPT ERROR at runtime/errors/cast_int_to_array.gd:4 on test(): Invalid cast: could not convert value to 'Array'.

View File

@@ -1,6 +1,2 @@
GDTEST_RUNTIME_ERROR
>> SCRIPT ERROR
>> on function: test()
>> runtime/errors/cast_int_to_object.gd
>> 4
>> Invalid cast: can't convert a non-object value to an object type.
>> SCRIPT ERROR at runtime/errors/cast_int_to_object.gd:4 on test(): Invalid cast: can't convert a non-object value to an object type.

View File

@@ -1,6 +1,2 @@
GDTEST_RUNTIME_ERROR
>> SCRIPT ERROR
>> on function: test()
>> runtime/errors/cast_object_to_int.gd
>> 4
>> Invalid cast: could not convert value to 'int'.
>> SCRIPT ERROR at runtime/errors/cast_object_to_int.gd:4 on test(): Invalid cast: could not convert value to 'int'.

View File

@@ -1,6 +1,4 @@
GDTEST_RUNTIME_ERROR
>> SCRIPT ERROR
>> on function: test()
>> runtime/errors/constant_array_is_deep.gd
>> 6
>> Invalid assignment on read-only value (on base: 'Dictionary').
>> ERROR: Condition "_p->read_only" is true. Returning: false
>> Dictionary is in read-only state.
>> SCRIPT ERROR at runtime/errors/constant_array_is_deep.gd:6 on test(): Invalid assignment on read-only value (on base: 'Dictionary').

View File

@@ -1,6 +1,2 @@
GDTEST_RUNTIME_ERROR
>> SCRIPT ERROR
>> on function: test()
>> runtime/errors/constant_dictionary_is_deep.gd
>> 6
>> Invalid assignment on read-only value (on base: 'Array').
>> SCRIPT ERROR at runtime/errors/constant_dictionary_is_deep.gd:6 on test(): Invalid assignment on read-only value (on base: 'Array').

View File

@@ -1,6 +1,2 @@
GDTEST_RUNTIME_ERROR
>> SCRIPT ERROR
>> on function: test()
>> runtime/errors/for_loop_iterator_type_not_match_specified.gd
>> 3
>> Trying to assign value of type 'Resource' to a variable of type 'Node'.
>> SCRIPT ERROR at runtime/errors/for_loop_iterator_type_not_match_specified.gd:3 on test(): Trying to assign value of type 'Resource' to a variable of type 'Node'.

View File

@@ -1,6 +1,2 @@
GDTEST_RUNTIME_ERROR
>> SCRIPT ERROR
>> on function: test()
>> runtime/errors/gd_utility_function_wrong_arg.gd
>> 3
>> Error calling GDScript utility function "len()": Value of type 'Color' can't provide a length.
>> SCRIPT ERROR at runtime/errors/gd_utility_function_wrong_arg.gd:3 on test(): Error calling GDScript utility function "len()": Value of type 'Color' can't provide a length.

View File

@@ -1,6 +1,2 @@
GDTEST_RUNTIME_ERROR
>> SCRIPT ERROR
>> on function: test()
>> runtime/errors/invalid_property_assignment.gd
>> 9
>> Invalid assignment of property or key 'obj' with value of type 'RefCounted (MyObj)' on a base object of type 'RefCounted (MyObj)'.
>> SCRIPT ERROR at runtime/errors/invalid_property_assignment.gd:9 on test(): Invalid assignment of property or key 'obj' with value of type 'RefCounted (MyObj)' on a base object of type 'RefCounted (MyObj)'.

View File

@@ -1,6 +1,3 @@
GDTEST_RUNTIME_ERROR
>> SCRIPT ERROR
>> on function: example()
>> runtime/errors/non_static_method_call_on_native_class.gd
>> 6
>> Invalid call. Nonexistent function 'has_method' in base 'Node2D'.
~~ WARNING at line 6: (UNSAFE_METHOD_ACCESS) The method "has_method()" is not present on the inferred type "Variant" (but may be present on a subtype).
>> SCRIPT ERROR at runtime/errors/non_static_method_call_on_native_class.gd:6 on example(): Invalid call. Nonexistent function 'has_method' in base 'Node2D'.

View File

@@ -0,0 +1,28 @@
class Outer:
const OUTER_CONST := 0
class Inner:
pass
func subtest_type_hard():
var type := Outer.Inner
print(type.OUTER_CONST)
func subtest_type_weak():
var type := Outer.Inner
var type_v: Variant = type
print(type_v.OUTER_CONST)
func subtest_instance_hard():
var instance := Outer.Inner.new()
print(instance.OUTER_CONST)
func subtest_instance_weak():
var instance := Outer.Inner.new()
var instance_v: Variant = instance
print(instance_v.OUTER_CONST)
func test():
subtest_type_hard()
subtest_type_weak()
subtest_instance_hard()
subtest_instance_weak()

View File

@@ -0,0 +1,7 @@
GDTEST_RUNTIME_ERROR
~~ WARNING at line 8: (UNSAFE_PROPERTY_ACCESS) The property "OUTER_CONST" is not present on the inferred type "Inner" (but may be present on a subtype).
~~ WARNING at line 17: (UNSAFE_PROPERTY_ACCESS) The property "OUTER_CONST" is not present on the inferred type "Inner" (but may be present on a subtype).
>> SCRIPT ERROR at runtime/errors/outer_class_constants.gd:8 on subtest_type_hard(): Invalid access to property or key 'OUTER_CONST' on a base object of type 'GDScript'.
>> SCRIPT ERROR at runtime/errors/outer_class_constants.gd:13 on subtest_type_weak(): Invalid access to property or key 'OUTER_CONST' on a base object of type 'GDScript'.
>> SCRIPT ERROR at runtime/errors/outer_class_constants.gd:17 on subtest_instance_hard(): Invalid access to property or key 'OUTER_CONST' on a base object of type 'RefCounted (Inner)'.
>> SCRIPT ERROR at runtime/errors/outer_class_constants.gd:22 on subtest_instance_weak(): Invalid access to property or key 'OUTER_CONST' on a base object of type 'RefCounted (Inner)'.

View File

@@ -1,6 +1,4 @@
GDTEST_RUNTIME_ERROR
>> SCRIPT ERROR
>> on function: test()
>> runtime/errors/read_only_dictionary.gd
>> 4
>> Invalid assignment on read-only value (on base: 'Dictionary').
>> ERROR: Condition "_p->read_only" is true. Returning: false
>> Dictionary is in read-only state.
>> SCRIPT ERROR at runtime/errors/read_only_dictionary.gd:4 on test(): Invalid assignment on read-only value (on base: 'Dictionary').

View File

@@ -1,4 +1,4 @@
func test():
var basic := [1]
var typed: Array[int] = basic
var _typed: Array[int] = basic
print('not ok')

View File

@@ -1,6 +1,2 @@
GDTEST_RUNTIME_ERROR
>> SCRIPT ERROR
>> on function: test()
>> runtime/errors/typed_array_assign_basic_to_typed.gd
>> 3
>> Trying to assign an array of type "Array" to a variable of type "Array[int]".
>> SCRIPT ERROR at runtime/errors/typed_array_assign_basic_to_typed.gd:3 on test(): Trying to assign an array of type "Array" to a variable of type "Array[int]".

View File

@@ -1,4 +1,4 @@
func test():
var differently: Variant = [1.0] as Array[float]
var typed: Array[int] = differently
var _typed: Array[int] = differently
print('not ok')

View File

@@ -1,6 +1,2 @@
GDTEST_RUNTIME_ERROR
>> SCRIPT ERROR
>> on function: test()
>> runtime/errors/typed_array_assign_differently_typed.gd
>> 3
>> Trying to assign an array of type "Array[float]" to a variable of type "Array[int]".
>> SCRIPT ERROR at runtime/errors/typed_array_assign_differently_typed.gd:3 on test(): Trying to assign an array of type "Array[float]" to a variable of type "Array[int]".

View File

@@ -3,5 +3,5 @@ class Bar extends Foo: pass
class Baz extends Foo: pass
func test():
var typed: Array[Bar] = [Baz.new() as Foo]
var _typed: Array[Bar] = [Baz.new() as Foo]
print('not ok')

View File

@@ -1,5 +1,6 @@
GDTEST_RUNTIME_ERROR
>> ERROR
>> Method/function failed.
>> Unable to convert array index 0 from "Object" to "Object".
>> ERROR: Condition "!other_script->inherits_script(script)" is true. Returning: false
>> Attempted to assign an object into a TypedArray, that does not inherit from 'GDScript'.
>> ERROR: Method/function failed.
>> Unable to convert array index 0 from "Object" to "Object".
not ok

View File

@@ -1,6 +1,2 @@
GDTEST_RUNTIME_ERROR
>> SCRIPT ERROR
>> on function: test()
>> runtime/errors/typed_array_pass_basic_to_typed.gd
>> 6
>> Invalid type in function 'expect_typed' in base 'RefCounted (typed_array_pass_basic_to_typed.gd)'. The array of argument 1 (Array) does not have the same element type as the expected typed array argument.
>> SCRIPT ERROR at runtime/errors/typed_array_pass_basic_to_typed.gd:6 on test(): Invalid type in function 'expect_typed' in base 'RefCounted (typed_array_pass_basic_to_typed.gd)'. The array of argument 1 (Array) does not have the same element type as the expected typed array argument.

View File

@@ -1,6 +1,3 @@
GDTEST_RUNTIME_ERROR
>> SCRIPT ERROR
>> on function: test()
>> runtime/errors/typed_array_pass_differently_to_typed.gd
>> 6
>> Invalid type in function 'expect_typed' in base 'RefCounted (typed_array_pass_differently_to_typed.gd)'. The array of argument 1 (Array[float]) does not have the same element type as the expected typed array argument.
~~ WARNING at line 6: (UNSAFE_CALL_ARGUMENT) The argument 1 of the function "expect_typed()" requires the subtype "Array[int]" but the supertype "Variant" was provided.
>> SCRIPT ERROR at runtime/errors/typed_array_pass_differently_to_typed.gd:6 on test(): Invalid type in function 'expect_typed' in base 'RefCounted (typed_array_pass_differently_to_typed.gd)'. The array of argument 1 (Array[float]) does not have the same element type as the expected typed array argument.

View File

@@ -1,4 +1,4 @@
func test():
var basic := { 1: 1 }
var typed: Dictionary[int, int] = basic
var _typed: Dictionary[int, int] = basic
print('not ok')

View File

@@ -1,6 +1,2 @@
GDTEST_RUNTIME_ERROR
>> SCRIPT ERROR
>> on function: test()
>> runtime/errors/typed_dictionary_assign_basic_to_typed.gd
>> 3
>> Trying to assign a dictionary of type "Dictionary" to a variable of type "Dictionary[int, int]".
>> SCRIPT ERROR at runtime/errors/typed_dictionary_assign_basic_to_typed.gd:3 on test(): Trying to assign a dictionary of type "Dictionary" to a variable of type "Dictionary[int, int]".

View File

@@ -1,4 +1,4 @@
func test():
var differently: Variant = { 1.0: 0.0 } as Dictionary[float, float]
var typed: Dictionary[int, int] = differently
var _typed: Dictionary[int, int] = differently
print('not ok')

View File

@@ -1,6 +1,2 @@
GDTEST_RUNTIME_ERROR
>> SCRIPT ERROR
>> on function: test()
>> runtime/errors/typed_dictionary_assign_differently_typed.gd
>> 3
>> Trying to assign a dictionary of type "Dictionary[float, float]" to a variable of type "Dictionary[int, int]".
>> SCRIPT ERROR at runtime/errors/typed_dictionary_assign_differently_typed.gd:3 on test(): Trying to assign a dictionary of type "Dictionary[float, float]" to a variable of type "Dictionary[int, int]".

View File

@@ -1,6 +1,5 @@
GDTEST_RUNTIME_ERROR
>> SCRIPT ERROR
>> on function: test()
>> runtime/errors/typed_dictionary_assign_differently_typed_key.gd
>> 6
>> Invalid assignment of property or key 'key' with value of type 'int' on a base object of type 'Dictionary[int, int]'.
>> ERROR: Method/function failed. Returning: false
>> Attempted to set a variable of type 'String' into a TypedDictionary.Key of type 'int'.
>> ERROR: Condition "!_p->typed_key.validate(key, "set")" is true. Returning: false
>> SCRIPT ERROR at runtime/errors/typed_dictionary_assign_differently_typed_key.gd:6 on test(): Invalid assignment of property or key 'key' with value of type 'int' on a base object of type 'Dictionary[int, int]'.

View File

@@ -1,6 +1,5 @@
GDTEST_RUNTIME_ERROR
>> SCRIPT ERROR
>> on function: test()
>> runtime/errors/typed_dictionary_assign_differently_typed_value.gd
>> 6
>> Invalid assignment of property or key '0' with value of type 'String' on a base object of type 'Dictionary[int, int]'.
>> ERROR: Method/function failed. Returning: false
>> Attempted to set a variable of type 'String' into a TypedDictionary.Value of type 'int'.
>> ERROR: Condition "!_p->typed_value.validate(value, "set")" is true. Returning: false
>> SCRIPT ERROR at runtime/errors/typed_dictionary_assign_differently_typed_value.gd:6 on test(): Invalid assignment of property or key '0' with value of type 'String' on a base object of type 'Dictionary[int, int]'.

View File

@@ -3,5 +3,5 @@ class Bar extends Foo: pass
class Baz extends Foo: pass
func test():
var typed: Dictionary[Bar, Bar] = { Baz.new() as Foo: Baz.new() as Foo }
var _typed: Dictionary[Bar, Bar] = { Baz.new() as Foo: Baz.new() as Foo }
print('not ok')

View File

@@ -1,5 +1,6 @@
GDTEST_RUNTIME_ERROR
>> ERROR
>> Method/function failed.
>> Unable to convert key from "Object" to "Object".
>> ERROR: Condition "!other_script->inherits_script(script)" is true. Returning: false
>> Attempted to assign an object into a TypedDictionary.Key, that does not inherit from 'GDScript'.
>> ERROR: Method/function failed.
>> Unable to convert key from "Object" to "Object".
not ok

View File

@@ -1,6 +1,2 @@
GDTEST_RUNTIME_ERROR
>> SCRIPT ERROR
>> on function: test()
>> runtime/errors/typed_dictionary_pass_basic_to_typed.gd
>> 6
>> Invalid type in function 'expect_typed' in base 'RefCounted (typed_dictionary_pass_basic_to_typed.gd)'. The dictionary of argument 1 (Dictionary) does not have the same element type as the expected typed dictionary argument.
>> SCRIPT ERROR at runtime/errors/typed_dictionary_pass_basic_to_typed.gd:6 on test(): Invalid type in function 'expect_typed' in base 'RefCounted (typed_dictionary_pass_basic_to_typed.gd)'. The dictionary of argument 1 (Dictionary) does not have the same element type as the expected typed dictionary argument.

View File

@@ -1,6 +1,3 @@
GDTEST_RUNTIME_ERROR
>> SCRIPT ERROR
>> on function: test()
>> runtime/errors/typed_dictionary_pass_differently_to_typed.gd
>> 6
>> Invalid type in function 'expect_typed' in base 'RefCounted (typed_dictionary_pass_differently_to_typed.gd)'. The dictionary of argument 1 (Dictionary[float, float]) does not have the same element type as the expected typed dictionary argument.
~~ WARNING at line 6: (UNSAFE_CALL_ARGUMENT) The argument 1 of the function "expect_typed()" requires the subtype "Dictionary[int, int]" but the supertype "Variant" was provided.
>> SCRIPT ERROR at runtime/errors/typed_dictionary_pass_differently_to_typed.gd:6 on test(): Invalid type in function 'expect_typed' in base 'RefCounted (typed_dictionary_pass_differently_to_typed.gd)'. The dictionary of argument 1 (Dictionary[float, float]) does not have the same element type as the expected typed dictionary argument.

View File

@@ -1,6 +1,3 @@
GDTEST_RUNTIME_ERROR
>> SCRIPT ERROR
>> on function: test()
>> runtime/errors/use_return_value_of_free_call.gd
>> 4
>> Trying to get a return value of a method that returns "void"
~~ WARNING at line 4: (UNSAFE_METHOD_ACCESS) The method "free()" is not present on the inferred type "Variant" (but may be present on a subtype).
>> SCRIPT ERROR at runtime/errors/use_return_value_of_free_call.gd:4 on test(): Trying to get a return value of a method that returns "void"

View File

@@ -1,6 +1,3 @@
GDTEST_RUNTIME_ERROR
>> SCRIPT ERROR
>> on function: test()
>> runtime/errors/use_return_value_of_void_builtin_method_call.gd
>> 4
>> Trying to get a return value of a method that returns "void"
~~ WARNING at line 4: (UNSAFE_METHOD_ACCESS) The method "reverse()" is not present on the inferred type "Variant" (but may be present on a subtype).
>> SCRIPT ERROR at runtime/errors/use_return_value_of_void_builtin_method_call.gd:4 on test(): Trying to get a return value of a method that returns "void"

View File

@@ -1,6 +1,3 @@
GDTEST_RUNTIME_ERROR
>> SCRIPT ERROR
>> on function: test()
>> runtime/errors/use_return_value_of_void_native_method_call.gd
>> 4
>> Trying to get a return value of a method that returns "void"
~~ WARNING at line 4: (UNSAFE_METHOD_ACCESS) The method "notify_property_list_changed()" is not present on the inferred type "Variant" (but may be present on a subtype).
>> SCRIPT ERROR at runtime/errors/use_return_value_of_void_native_method_call.gd:4 on test(): Trying to get a return value of a method that returns "void"

View File

@@ -1,6 +1,2 @@
GDTEST_RUNTIME_ERROR
>> SCRIPT ERROR
>> on function: test()
>> runtime/errors/utility_function_wrong_arg.gd
>> 3
>> Error calling utility function "floor()": Argument "x" must be "int", "float", "Vector2", "Vector2i", "Vector3", "Vector3i", "Vector4", or "Vector4i".
>> SCRIPT ERROR at runtime/errors/utility_function_wrong_arg.gd:3 on test(): Error calling utility function "floor()": Argument "x" must be "int", "float", "Vector2", "Vector2i", "Vector3", "Vector3i", "Vector4", or "Vector4i".

View File

@@ -1,6 +1,3 @@
GDTEST_OK
>> WARNING
>> Line: 4
>> REDUNDANT_AWAIT
>> "await" keyword not needed in this case, because the expression isn't a coroutine nor a signal.
~~ WARNING at line 4: (REDUNDANT_AWAIT) "await" keyword not needed in this case, because the expression isn't a coroutine nor a signal.
awaited

View File

@@ -1,12 +1,6 @@
GDTEST_OK
>> WARNING
>> Line: 5
>> SHADOWED_VARIABLE
>> The local function parameter "a" is shadowing an already-declared variable at line 3 in the current class.
>> WARNING
>> Line: 15
>> SHADOWED_VARIABLE
>> The local function parameter "v" is shadowing an already-declared variable at line 13 in the current class.
~~ WARNING at line 5: (SHADOWED_VARIABLE) The local function parameter "a" is shadowing an already-declared variable at line 3 in the current class.
~~ WARNING at line 15: (SHADOWED_VARIABLE) The local function parameter "v" is shadowing an already-declared variable at line 13 in the current class.
a
1
b

View File

@@ -1,12 +1,6 @@
GDTEST_OK
>> WARNING
>> Line: 6
>> NARROWING_CONVERSION
>> Narrowing conversion (float is converted to int and loses precision).
>> WARNING
>> Line: 8
>> NARROWING_CONVERSION
>> Narrowing conversion (float is converted to int and loses precision).
~~ WARNING at line 6: (NARROWING_CONVERSION) Narrowing conversion (float is converted to int and loses precision).
~~ WARNING at line 8: (NARROWING_CONVERSION) Narrowing conversion (float is converted to int and loses precision).
2
2
2