Track bundled vendor runtime sources
This commit is contained in:
0
vendor/ComfyUI/tests-unit/comfy_extras_test/__init__.py
vendored
Normal file
0
vendor/ComfyUI/tests-unit/comfy_extras_test/__init__.py
vendored
Normal file
243
vendor/ComfyUI/tests-unit/comfy_extras_test/image_stitch_test.py
vendored
Normal file
243
vendor/ComfyUI/tests-unit/comfy_extras_test/image_stitch_test.py
vendored
Normal file
@@ -0,0 +1,243 @@
|
||||
import torch
|
||||
from unittest.mock import patch, MagicMock
|
||||
|
||||
# Mock nodes module to prevent CUDA initialization during import
|
||||
mock_nodes = MagicMock()
|
||||
mock_nodes.MAX_RESOLUTION = 16384
|
||||
|
||||
# Mock server module for PromptServer
|
||||
mock_server = MagicMock()
|
||||
|
||||
with patch.dict('sys.modules', {'nodes': mock_nodes, 'server': mock_server}):
|
||||
from comfy_extras.nodes_images import ImageStitch
|
||||
|
||||
|
||||
class TestImageStitch:
|
||||
|
||||
def create_test_image(self, batch_size=1, height=64, width=64, channels=3):
|
||||
"""Helper to create test images with specific dimensions"""
|
||||
return torch.rand(batch_size, height, width, channels)
|
||||
|
||||
def test_no_image2_passthrough(self):
|
||||
"""Test that when image2 is None, image1 is returned unchanged"""
|
||||
node = ImageStitch()
|
||||
image1 = self.create_test_image()
|
||||
|
||||
result = node.stitch(image1, "right", True, 0, "white", image2=None)
|
||||
|
||||
assert len(result.result) == 1
|
||||
assert torch.equal(result[0], image1)
|
||||
|
||||
def test_basic_horizontal_stitch_right(self):
|
||||
"""Test basic horizontal stitching to the right"""
|
||||
node = ImageStitch()
|
||||
image1 = self.create_test_image(height=32, width=32)
|
||||
image2 = self.create_test_image(height=32, width=24)
|
||||
|
||||
result = node.stitch(image1, "right", False, 0, "white", image2)
|
||||
|
||||
assert result[0].shape == (1, 32, 56, 3) # 32 + 24 width
|
||||
|
||||
def test_basic_horizontal_stitch_left(self):
|
||||
"""Test basic horizontal stitching to the left"""
|
||||
node = ImageStitch()
|
||||
image1 = self.create_test_image(height=32, width=32)
|
||||
image2 = self.create_test_image(height=32, width=24)
|
||||
|
||||
result = node.stitch(image1, "left", False, 0, "white", image2)
|
||||
|
||||
assert result[0].shape == (1, 32, 56, 3) # 24 + 32 width
|
||||
|
||||
def test_basic_vertical_stitch_down(self):
|
||||
"""Test basic vertical stitching downward"""
|
||||
node = ImageStitch()
|
||||
image1 = self.create_test_image(height=32, width=32)
|
||||
image2 = self.create_test_image(height=24, width=32)
|
||||
|
||||
result = node.stitch(image1, "down", False, 0, "white", image2)
|
||||
|
||||
assert result[0].shape == (1, 56, 32, 3) # 32 + 24 height
|
||||
|
||||
def test_basic_vertical_stitch_up(self):
|
||||
"""Test basic vertical stitching upward"""
|
||||
node = ImageStitch()
|
||||
image1 = self.create_test_image(height=32, width=32)
|
||||
image2 = self.create_test_image(height=24, width=32)
|
||||
|
||||
result = node.stitch(image1, "up", False, 0, "white", image2)
|
||||
|
||||
assert result[0].shape == (1, 56, 32, 3) # 24 + 32 height
|
||||
|
||||
def test_size_matching_horizontal(self):
|
||||
"""Test size matching for horizontal concatenation"""
|
||||
node = ImageStitch()
|
||||
image1 = self.create_test_image(height=64, width=64)
|
||||
image2 = self.create_test_image(height=32, width=32) # Different aspect ratio
|
||||
|
||||
result = node.stitch(image1, "right", True, 0, "white", image2)
|
||||
|
||||
# image2 should be resized to match image1's height (64) with preserved aspect ratio
|
||||
expected_width = 64 + 64 # original + resized (32*64/32 = 64)
|
||||
assert result[0].shape == (1, 64, expected_width, 3)
|
||||
|
||||
def test_size_matching_vertical(self):
|
||||
"""Test size matching for vertical concatenation"""
|
||||
node = ImageStitch()
|
||||
image1 = self.create_test_image(height=64, width=64)
|
||||
image2 = self.create_test_image(height=32, width=32)
|
||||
|
||||
result = node.stitch(image1, "down", True, 0, "white", image2)
|
||||
|
||||
# image2 should be resized to match image1's width (64) with preserved aspect ratio
|
||||
expected_height = 64 + 64 # original + resized (32*64/32 = 64)
|
||||
assert result[0].shape == (1, expected_height, 64, 3)
|
||||
|
||||
def test_padding_for_mismatched_heights_horizontal(self):
|
||||
"""Test padding when heights don't match in horizontal concatenation"""
|
||||
node = ImageStitch()
|
||||
image1 = self.create_test_image(height=64, width=32)
|
||||
image2 = self.create_test_image(height=48, width=24) # Shorter height
|
||||
|
||||
result = node.stitch(image1, "right", False, 0, "white", image2)
|
||||
|
||||
# Both images should be padded to height 64
|
||||
assert result[0].shape == (1, 64, 56, 3) # 32 + 24 width, max(64,48) height
|
||||
|
||||
def test_padding_for_mismatched_widths_vertical(self):
|
||||
"""Test padding when widths don't match in vertical concatenation"""
|
||||
node = ImageStitch()
|
||||
image1 = self.create_test_image(height=32, width=64)
|
||||
image2 = self.create_test_image(height=24, width=48) # Narrower width
|
||||
|
||||
result = node.stitch(image1, "down", False, 0, "white", image2)
|
||||
|
||||
# Both images should be padded to width 64
|
||||
assert result[0].shape == (1, 56, 64, 3) # 32 + 24 height, max(64,48) width
|
||||
|
||||
def test_spacing_horizontal(self):
|
||||
"""Test spacing addition in horizontal concatenation"""
|
||||
node = ImageStitch()
|
||||
image1 = self.create_test_image(height=32, width=32)
|
||||
image2 = self.create_test_image(height=32, width=24)
|
||||
spacing_width = 16
|
||||
|
||||
result = node.stitch(image1, "right", False, spacing_width, "white", image2)
|
||||
|
||||
# Expected width: 32 + 16 (spacing) + 24 = 72
|
||||
assert result[0].shape == (1, 32, 72, 3)
|
||||
|
||||
def test_spacing_vertical(self):
|
||||
"""Test spacing addition in vertical concatenation"""
|
||||
node = ImageStitch()
|
||||
image1 = self.create_test_image(height=32, width=32)
|
||||
image2 = self.create_test_image(height=24, width=32)
|
||||
spacing_width = 16
|
||||
|
||||
result = node.stitch(image1, "down", False, spacing_width, "white", image2)
|
||||
|
||||
# Expected height: 32 + 16 (spacing) + 24 = 72
|
||||
assert result[0].shape == (1, 72, 32, 3)
|
||||
|
||||
def test_spacing_color_values(self):
|
||||
"""Test that spacing colors are applied correctly"""
|
||||
node = ImageStitch()
|
||||
image1 = self.create_test_image(height=32, width=32)
|
||||
image2 = self.create_test_image(height=32, width=32)
|
||||
|
||||
# Test white spacing
|
||||
result_white = node.stitch(image1, "right", False, 16, "white", image2)
|
||||
# Check that spacing region contains white values (close to 1.0)
|
||||
spacing_region = result_white[0][:, :, 32:48, :] # Middle 16 pixels
|
||||
assert torch.all(spacing_region >= 0.9) # Should be close to white
|
||||
|
||||
# Test black spacing
|
||||
result_black = node.stitch(image1, "right", False, 16, "black", image2)
|
||||
spacing_region = result_black[0][:, :, 32:48, :]
|
||||
assert torch.all(spacing_region <= 0.1) # Should be close to black
|
||||
|
||||
def test_odd_spacing_width_made_even(self):
|
||||
"""Test that odd spacing widths are made even"""
|
||||
node = ImageStitch()
|
||||
image1 = self.create_test_image(height=32, width=32)
|
||||
image2 = self.create_test_image(height=32, width=32)
|
||||
|
||||
# Use odd spacing width
|
||||
result = node.stitch(image1, "right", False, 15, "white", image2)
|
||||
|
||||
# Should be made even (16), so total width = 32 + 16 + 32 = 80
|
||||
assert result[0].shape == (1, 32, 80, 3)
|
||||
|
||||
def test_batch_size_matching(self):
|
||||
"""Test that different batch sizes are handled correctly"""
|
||||
node = ImageStitch()
|
||||
image1 = self.create_test_image(batch_size=2, height=32, width=32)
|
||||
image2 = self.create_test_image(batch_size=1, height=32, width=32)
|
||||
|
||||
result = node.stitch(image1, "right", False, 0, "white", image2)
|
||||
|
||||
# Should match larger batch size
|
||||
assert result[0].shape == (2, 32, 64, 3)
|
||||
|
||||
def test_channel_matching_rgb_to_rgba(self):
|
||||
"""Test that channel differences are handled (RGB + alpha)"""
|
||||
node = ImageStitch()
|
||||
image1 = self.create_test_image(channels=3) # RGB
|
||||
image2 = self.create_test_image(channels=4) # RGBA
|
||||
|
||||
result = node.stitch(image1, "right", False, 0, "white", image2)
|
||||
|
||||
# Should have 4 channels (RGBA)
|
||||
assert result[0].shape[-1] == 4
|
||||
|
||||
def test_channel_matching_rgba_to_rgb(self):
|
||||
"""Test that channel differences are handled (RGBA + RGB)"""
|
||||
node = ImageStitch()
|
||||
image1 = self.create_test_image(channels=4) # RGBA
|
||||
image2 = self.create_test_image(channels=3) # RGB
|
||||
|
||||
result = node.stitch(image1, "right", False, 0, "white", image2)
|
||||
|
||||
# Should have 4 channels (RGBA)
|
||||
assert result[0].shape[-1] == 4
|
||||
|
||||
def test_all_color_options(self):
|
||||
"""Test all available color options"""
|
||||
node = ImageStitch()
|
||||
image1 = self.create_test_image(height=32, width=32)
|
||||
image2 = self.create_test_image(height=32, width=32)
|
||||
|
||||
colors = ["white", "black", "red", "green", "blue"]
|
||||
|
||||
for color in colors:
|
||||
result = node.stitch(image1, "right", False, 16, color, image2)
|
||||
assert result[0].shape == (1, 32, 80, 3) # Basic shape check
|
||||
|
||||
def test_all_directions(self):
|
||||
"""Test all direction options"""
|
||||
node = ImageStitch()
|
||||
image1 = self.create_test_image(height=32, width=32)
|
||||
image2 = self.create_test_image(height=32, width=32)
|
||||
|
||||
directions = ["right", "left", "up", "down"]
|
||||
|
||||
for direction in directions:
|
||||
result = node.stitch(image1, direction, False, 0, "white", image2)
|
||||
assert result[0].shape == (1, 32, 64, 3) if direction in ["right", "left"] else (1, 64, 32, 3)
|
||||
|
||||
def test_batch_size_channel_spacing_integration(self):
|
||||
"""Test integration of batch matching, channel matching, size matching, and spacings"""
|
||||
node = ImageStitch()
|
||||
image1 = self.create_test_image(batch_size=2, height=64, width=48, channels=3)
|
||||
image2 = self.create_test_image(batch_size=1, height=32, width=32, channels=4)
|
||||
|
||||
result = node.stitch(image1, "right", True, 8, "red", image2)
|
||||
|
||||
# Should handle: batch matching, size matching, channel matching, spacing
|
||||
assert result[0].shape[0] == 2 # Batch size matched
|
||||
assert result[0].shape[-1] == 4 # Channels matched to max
|
||||
assert result[0].shape[1] == 64 # Height from image1 (size matching)
|
||||
# Width should be: 48 + 8 (spacing) + resized_image2_width
|
||||
expected_image2_width = int(64 * (32/32)) # Resized to height 64
|
||||
expected_total_width = 48 + 8 + expected_image2_width
|
||||
assert result[0].shape[2] == expected_total_width
|
||||
|
||||
206
vendor/ComfyUI/tests-unit/comfy_extras_test/nodes_math_test.py
vendored
Normal file
206
vendor/ComfyUI/tests-unit/comfy_extras_test/nodes_math_test.py
vendored
Normal file
@@ -0,0 +1,206 @@
|
||||
import math
|
||||
|
||||
import pytest
|
||||
from collections import OrderedDict
|
||||
from unittest.mock import patch, MagicMock
|
||||
|
||||
mock_nodes = MagicMock()
|
||||
mock_nodes.MAX_RESOLUTION = 16384
|
||||
mock_server = MagicMock()
|
||||
|
||||
with patch.dict("sys.modules", {"nodes": mock_nodes, "server": mock_server}):
|
||||
from comfy_extras.nodes_math import MathExpressionNode
|
||||
|
||||
|
||||
class TestMathExpressionExecute:
|
||||
@staticmethod
|
||||
def _exec(expression: str, **kwargs) -> object:
|
||||
values = OrderedDict(kwargs)
|
||||
return MathExpressionNode.execute(expression, values)
|
||||
|
||||
def test_addition(self):
|
||||
result = self._exec("a + b", a=3, b=4)
|
||||
assert result[0] == 7.0
|
||||
assert result[1] == 7
|
||||
|
||||
def test_subtraction(self):
|
||||
result = self._exec("a - b", a=10, b=3)
|
||||
assert result[0] == 7.0
|
||||
assert result[1] == 7
|
||||
|
||||
def test_multiplication(self):
|
||||
result = self._exec("a * b", a=3, b=5)
|
||||
assert result[0] == 15.0
|
||||
assert result[1] == 15
|
||||
|
||||
def test_division(self):
|
||||
result = self._exec("a / b", a=10, b=4)
|
||||
assert result[0] == 2.5
|
||||
assert result[1] == 2
|
||||
|
||||
def test_single_input(self):
|
||||
result = self._exec("a * 2", a=5)
|
||||
assert result[0] == 10.0
|
||||
assert result[1] == 10
|
||||
|
||||
def test_three_inputs(self):
|
||||
result = self._exec("a + b + c", a=1, b=2, c=3)
|
||||
assert result[0] == 6.0
|
||||
assert result[1] == 6
|
||||
|
||||
def test_float_inputs(self):
|
||||
result = self._exec("a + b", a=1.5, b=2.5)
|
||||
assert result[0] == 4.0
|
||||
assert result[1] == 4
|
||||
|
||||
def test_mixed_int_float_inputs(self):
|
||||
result = self._exec("a * b", a=1024, b=1.5)
|
||||
assert result[0] == 1536.0
|
||||
assert result[1] == 1536
|
||||
|
||||
def test_mixed_resolution_scale(self):
|
||||
result = self._exec("a * b", a=512, b=0.75)
|
||||
assert result[0] == 384.0
|
||||
assert result[1] == 384
|
||||
|
||||
def test_sum_values_array(self):
|
||||
result = self._exec("sum(values)", a=1, b=2, c=3)
|
||||
assert result[0] == 6.0
|
||||
|
||||
def test_sum_variadic(self):
|
||||
result = self._exec("sum(a, b, c)", a=1, b=2, c=3)
|
||||
assert result[0] == 6.0
|
||||
|
||||
def test_min_values(self):
|
||||
result = self._exec("min(values)", a=5, b=2, c=8)
|
||||
assert result[0] == 2.0
|
||||
|
||||
def test_max_values(self):
|
||||
result = self._exec("max(values)", a=5, b=2, c=8)
|
||||
assert result[0] == 8.0
|
||||
|
||||
def test_abs_function(self):
|
||||
result = self._exec("abs(a)", a=-7)
|
||||
assert result[0] == 7.0
|
||||
assert result[1] == 7
|
||||
|
||||
def test_sqrt(self):
|
||||
result = self._exec("sqrt(a)", a=16)
|
||||
assert result[0] == 4.0
|
||||
assert result[1] == 4
|
||||
|
||||
def test_ceil(self):
|
||||
result = self._exec("ceil(a)", a=2.3)
|
||||
assert result[0] == 3.0
|
||||
assert result[1] == 3
|
||||
|
||||
def test_floor(self):
|
||||
result = self._exec("floor(a)", a=2.7)
|
||||
assert result[0] == 2.0
|
||||
assert result[1] == 2
|
||||
|
||||
def test_sin(self):
|
||||
result = self._exec("sin(a)", a=0)
|
||||
assert result[0] == 0.0
|
||||
|
||||
def test_log10(self):
|
||||
result = self._exec("log10(a)", a=100)
|
||||
assert result[0] == 2.0
|
||||
assert result[1] == 2
|
||||
|
||||
def test_float_output_type(self):
|
||||
result = self._exec("a + b", a=1, b=2)
|
||||
assert isinstance(result[0], float)
|
||||
|
||||
def test_int_output_type(self):
|
||||
result = self._exec("a + b", a=1, b=2)
|
||||
assert isinstance(result[1], int)
|
||||
|
||||
def test_non_numeric_result_raises(self):
|
||||
with pytest.raises(ValueError, match="must evaluate to a numeric result"):
|
||||
self._exec("'hello'", a=42)
|
||||
|
||||
def test_undefined_function_raises(self):
|
||||
with pytest.raises(Exception, match="not defined"):
|
||||
self._exec("str(a)", a=42)
|
||||
|
||||
def test_boolean_result(self):
|
||||
result = self._exec("a > b", a=5, b=3)
|
||||
assert result[2] is True
|
||||
result = self._exec("a > b", a=3, b=5)
|
||||
assert result[2] is False
|
||||
|
||||
def test_empty_expression_raises(self):
|
||||
with pytest.raises(ValueError, match="Expression cannot be empty"):
|
||||
self._exec("", a=1)
|
||||
|
||||
def test_whitespace_only_expression_raises(self):
|
||||
with pytest.raises(ValueError, match="Expression cannot be empty"):
|
||||
self._exec(" ", a=1)
|
||||
|
||||
# --- Missing function coverage (round, pow, log, log2, cos, tan) ---
|
||||
|
||||
def test_round(self):
|
||||
result = self._exec("round(a)", a=2.7)
|
||||
assert result[0] == 3.0
|
||||
assert result[1] == 3
|
||||
|
||||
def test_round_with_ndigits(self):
|
||||
result = self._exec("round(a, 2)", a=3.14159)
|
||||
assert result[0] == pytest.approx(3.14)
|
||||
|
||||
def test_pow(self):
|
||||
result = self._exec("pow(a, b)", a=2, b=10)
|
||||
assert result[0] == 1024.0
|
||||
assert result[1] == 1024
|
||||
|
||||
def test_log(self):
|
||||
result = self._exec("log(a)", a=math.e)
|
||||
assert result[0] == pytest.approx(1.0)
|
||||
|
||||
def test_log2(self):
|
||||
result = self._exec("log2(a)", a=8)
|
||||
assert result[0] == pytest.approx(3.0)
|
||||
|
||||
def test_cos(self):
|
||||
result = self._exec("cos(a)", a=0)
|
||||
assert result[0] == 1.0
|
||||
|
||||
def test_tan(self):
|
||||
result = self._exec("tan(a)", a=0)
|
||||
assert result[0] == 0.0
|
||||
|
||||
# --- int/float converter functions ---
|
||||
|
||||
def test_int_converter(self):
|
||||
result = self._exec("int(a / b)", a=7, b=2)
|
||||
assert result[1] == 3
|
||||
|
||||
def test_float_converter(self):
|
||||
result = self._exec("float(a)", a=5)
|
||||
assert result[0] == 5.0
|
||||
|
||||
# --- Error path tests ---
|
||||
|
||||
def test_division_by_zero_raises(self):
|
||||
with pytest.raises(ZeroDivisionError):
|
||||
self._exec("a / b", a=1, b=0)
|
||||
|
||||
def test_sqrt_negative_raises(self):
|
||||
with pytest.raises(ValueError, match="math domain error"):
|
||||
self._exec("sqrt(a)", a=-1)
|
||||
|
||||
def test_overflow_inf_raises(self):
|
||||
with pytest.raises(ValueError, match="non-finite result"):
|
||||
self._exec("a * b", a=1e308, b=10)
|
||||
|
||||
def test_pow_huge_exponent_raises(self):
|
||||
with pytest.raises(ValueError, match="Exponent .* exceeds maximum"):
|
||||
self._exec("pow(a, b)", a=10, b=10000000)
|
||||
|
||||
def test_huge_int_result_raises_value_error(self):
|
||||
# Exponent is within the allowed MAX_EXPONENT range, so the result is a
|
||||
# finite Python int that is nonetheless too large to convert to float.
|
||||
# This must raise a clean ValueError, not an uncaught OverflowError.
|
||||
with pytest.raises(ValueError, match="too large to represent as a float"):
|
||||
self._exec("2 ** 3999")
|
||||
180
vendor/ComfyUI/tests-unit/comfy_extras_test/nodes_number_convert_test.py
vendored
Normal file
180
vendor/ComfyUI/tests-unit/comfy_extras_test/nodes_number_convert_test.py
vendored
Normal file
@@ -0,0 +1,180 @@
|
||||
import pytest
|
||||
from unittest.mock import patch, MagicMock
|
||||
|
||||
mock_nodes = MagicMock()
|
||||
mock_nodes.MAX_RESOLUTION = 16384
|
||||
mock_server = MagicMock()
|
||||
|
||||
with patch.dict("sys.modules", {"nodes": mock_nodes, "server": mock_server}):
|
||||
from comfy_extras.nodes_number_convert import NumberConvertNode
|
||||
|
||||
|
||||
class TestNumberConvertExecute:
|
||||
@staticmethod
|
||||
def _exec(value) -> object:
|
||||
return NumberConvertNode.execute(value)
|
||||
|
||||
# --- INT input ---
|
||||
|
||||
def test_int_input(self):
|
||||
result = self._exec(42)
|
||||
assert result[0] == 42.0
|
||||
assert result[1] == 42
|
||||
|
||||
def test_int_zero(self):
|
||||
result = self._exec(0)
|
||||
assert result[0] == 0.0
|
||||
assert result[1] == 0
|
||||
|
||||
def test_int_negative(self):
|
||||
result = self._exec(-7)
|
||||
assert result[0] == -7.0
|
||||
assert result[1] == -7
|
||||
|
||||
# --- FLOAT input ---
|
||||
|
||||
def test_float_input(self):
|
||||
result = self._exec(3.14)
|
||||
assert result[0] == 3.14
|
||||
assert result[1] == 3
|
||||
|
||||
def test_float_truncation_toward_zero(self):
|
||||
result = self._exec(-2.9)
|
||||
assert result[0] == -2.9
|
||||
assert result[1] == -2 # int() truncates toward zero, not floor
|
||||
|
||||
def test_float_output_type(self):
|
||||
result = self._exec(5)
|
||||
assert isinstance(result[0], float)
|
||||
|
||||
def test_int_output_type(self):
|
||||
result = self._exec(5.7)
|
||||
assert isinstance(result[1], int)
|
||||
|
||||
# --- BOOL input ---
|
||||
|
||||
def test_bool_true(self):
|
||||
result = self._exec(True)
|
||||
assert result[0] == 1.0
|
||||
assert result[1] == 1
|
||||
|
||||
def test_bool_false(self):
|
||||
result = self._exec(False)
|
||||
assert result[0] == 0.0
|
||||
assert result[1] == 0
|
||||
|
||||
# --- STRING input ---
|
||||
|
||||
def test_string_integer(self):
|
||||
result = self._exec("42")
|
||||
assert result[0] == 42.0
|
||||
assert result[1] == 42
|
||||
|
||||
def test_string_float(self):
|
||||
result = self._exec("3.14")
|
||||
assert result[0] == 3.14
|
||||
assert result[1] == 3
|
||||
|
||||
def test_string_negative(self):
|
||||
result = self._exec("-5.5")
|
||||
assert result[0] == -5.5
|
||||
assert result[1] == -5
|
||||
|
||||
def test_string_with_whitespace(self):
|
||||
result = self._exec(" 7.0 ")
|
||||
assert result[0] == 7.0
|
||||
assert result[1] == 7
|
||||
|
||||
def test_string_scientific_notation(self):
|
||||
result = self._exec("1e3")
|
||||
assert result[0] == 1000.0
|
||||
assert result[1] == 1000
|
||||
|
||||
# --- Large number precision (string input) ---
|
||||
|
||||
def test_string_large_int_above_2_53(self):
|
||||
"""Text-to-int must not lose precision for integers beyond 2^53."""
|
||||
big = 2**53 + 1 # 9007199254740993
|
||||
result = self._exec(str(big))
|
||||
assert result[1] == big
|
||||
|
||||
def test_string_large_negative_int_above_2_53(self):
|
||||
big = -(2**53 + 1)
|
||||
result = self._exec(str(big))
|
||||
assert result[1] == big
|
||||
|
||||
def test_string_very_large_int(self):
|
||||
big = 2**63 + 42
|
||||
result = self._exec(str(big))
|
||||
assert result[1] == big
|
||||
|
||||
def test_string_large_int_float_output_is_float(self):
|
||||
"""FLOAT output is still a float (may lose precision, but must be float type)."""
|
||||
result = self._exec(str(2**53 + 1))
|
||||
assert isinstance(result[0], float)
|
||||
|
||||
# --- Large number precision (int input) ---
|
||||
|
||||
def test_int_large_above_2_53(self):
|
||||
"""Native int input must preserve its value in the INT output."""
|
||||
big = 2**53 + 1
|
||||
result = self._exec(big)
|
||||
assert result[1] == big
|
||||
|
||||
def test_int_large_negative_above_2_53(self):
|
||||
big = -(2**53 + 1)
|
||||
result = self._exec(big)
|
||||
assert result[1] == big
|
||||
|
||||
def test_int_very_large(self):
|
||||
big = 2**100
|
||||
result = self._exec(big)
|
||||
assert result[1] == big
|
||||
|
||||
# --- String decimal / scientific notation fallback ---
|
||||
|
||||
def test_string_decimal_still_truncates(self):
|
||||
"""Strings with decimal points fall back to int(float(...)) truncation."""
|
||||
result = self._exec("3.7")
|
||||
assert result[1] == 3
|
||||
|
||||
def test_string_negative_decimal_truncates(self):
|
||||
result = self._exec("-2.9")
|
||||
assert result[1] == -2
|
||||
|
||||
def test_string_scientific_large(self):
|
||||
result = self._exec("1e18")
|
||||
assert result[0] == 1e18
|
||||
assert result[1] == 10**18
|
||||
|
||||
# --- STRING error paths ---
|
||||
|
||||
def test_empty_string_raises(self):
|
||||
with pytest.raises(ValueError, match="Cannot convert empty string"):
|
||||
self._exec("")
|
||||
|
||||
def test_whitespace_only_string_raises(self):
|
||||
with pytest.raises(ValueError, match="Cannot convert empty string"):
|
||||
self._exec(" ")
|
||||
|
||||
def test_non_numeric_string_raises(self):
|
||||
with pytest.raises(ValueError, match="Cannot convert string to number"):
|
||||
self._exec("abc")
|
||||
|
||||
def test_string_inf_raises(self):
|
||||
with pytest.raises(ValueError, match="non-finite"):
|
||||
self._exec("inf")
|
||||
|
||||
def test_string_nan_raises(self):
|
||||
with pytest.raises(ValueError, match="non-finite"):
|
||||
self._exec("nan")
|
||||
|
||||
def test_string_negative_inf_raises(self):
|
||||
with pytest.raises(ValueError, match="non-finite"):
|
||||
self._exec("-inf")
|
||||
|
||||
# --- Unsupported type ---
|
||||
|
||||
def test_unsupported_type_raises(self):
|
||||
with pytest.raises(TypeError, match="Unsupported input type"):
|
||||
self._exec([1, 2, 3])
|
||||
Reference in New Issue
Block a user