Coverage for tests/test_wrapper_hunyuanframepackf1.py: 100%

95 statements  

« prev     ^ index     » next       coverage.py v7.15.4, created at 2026-08-09 04:47 +0000

1#!/usr/bin/env python3 

2 

3import sys 

4import pytest 

5 

6from unittest.mock import patch 

7from unittest.mock import MagicMock 

8from tests.torch_mock import TorchMock 

9from tests.diffusers_mock import DiffusersMock 

10 

11from PIL import Image 

12 

13mock_torch = TorchMock() 

14mock_diffusers = DiffusersMock() 

15 

16sys.path.append("wrapper") 

17sys.path.append("wrapper/hunyuanframepackf1") 

18sys.path.append("wrapper/hunyuanframepack") 

19 

20mock_modules = { 

21 'nvidia_smi': MagicMock(), 

22 'imageio': MagicMock(), 

23 'cv2': MagicMock(), 

24 'torch': mock_torch, 

25 'torchvision': MagicMock(), 

26 'torchvision.transforms': MagicMock(), 

27 'torchvision.transforms.functional': MagicMock(), 

28 'xfuser': MagicMock(), 

29 'xfuser.envs': MagicMock(), 

30 'xfuser.config': MagicMock(), 

31 'xfuser.core': MagicMock(), 

32 'xfuser.core.distributed': MagicMock(), 

33 'xfuser.core.cache_manager': MagicMock(), 

34 'xfuser.core.cache_manager.cache_manager': MagicMock(), 

35 'xfuser.core.long_ctx_attention': MagicMock(), 

36 'xfuser.model_executor': MagicMock(), 

37 'xfuser.model_executor.layers': MagicMock(), 

38 'xfuser.model_executor.layers.attention_processor': MagicMock(), 

39 'transformers': MagicMock(), 

40 'einops': MagicMock(), 

41 'flash_attn': MagicMock(), 

42 'diffusers_helper': MagicMock(), 

43 'diffusers_helper.hunyuan': MagicMock(), 

44 'diffusers_helper.utils': MagicMock(), 

45 'diffusers_helper.clip_vision': MagicMock(), 

46 'diffusers_helper.models': MagicMock(), 

47 'diffusers_helper.models.hunyuan_video_packed': MagicMock(), 

48 'diffusers_helper.pipelines': MagicMock(), 

49 'diffusers_helper.pipelines.k_diffusion_hunyuan': MagicMock(), 

50 'diffusers_helper.k_diffusion': MagicMock(), 

51 'diffusers_helper.k_diffusion.uni_pc_fm': MagicMock(), 

52 'diffusers_helper.k_diffusion.wrapper': MagicMock(), 

53} 

54mock_modules.update(mock_torch.get_sub_modules()) 

55mock_modules.update(mock_diffusers.get_sub_modules()) 

56 

57with patch.dict(sys.modules, mock_modules): 

58 from image_utils import img_to_base64 

59 from hunyuanframepackf1.wrapper_hunyuanframepackf1 import HunyuanFramepackF1Generation 

60 

61 

62@pytest.mark.asyncio 

63async def test_hunyuanframepackf1() -> None: 

64 model = HunyuanFramepackF1Generation() 

65 assert model is not None 

66 assert model.model_name == "hunyuanframepackf1" 

67 assert model.status == "initializing" 

68 

69 model.init() 

70 assert model.status == "ok" 

71 health = model.get_health() 

72 assert health is not None 

73 timestamps = model.get_timestamps() 

74 assert timestamps is not None 

75 

76 with pytest.raises(ValueError): 

77 await model.get_rest_args(None) 

78 with pytest.raises(ValueError): 

79 await model.get_rest_args({}) 

80 img = Image.new("RGB", (40, 30)) 

81 img_base64 = img_to_base64(img) 

82 await model.get_rest_args({ 

83 "img": img_base64, 

84 "prompt": "test prompt", 

85 }) 

86 

87 with pytest.raises(ValueError): 

88 # TODO implement fixtures for diffusers_helper 

89 await model.warmup() 

90 

91 with pytest.raises(ValueError): 

92 # TODO implement fixtures for diffusers_helper 

93 await model.generate( 

94 img=img, 

95 prompt="test prompt", 

96 output_type="video_frames") 

97 

98 del model 

99 

100 

101@pytest.mark.asyncio 

102async def test_hunyuanframepackf1_get_rest_args_negative_values() -> None: 

103 """get_rest_args raises ValueError for non-positive numeric parameters.""" 

104 model = HunyuanFramepackF1Generation() 

105 model.init() 

106 

107 img = Image.new("RGB", (40, 30)) 

108 img_base64 = img_to_base64(img) 

109 base = {"img": img_base64, "prompt": "test prompt"} 

110 

111 with pytest.raises(ValueError, match="num_frames"): 

112 await model.get_rest_args({**base, "num_frames": -3}) 

113 

114 with pytest.raises(ValueError, match="num_frames"): 

115 await model.get_rest_args({**base, "num_frames": 0}) 

116 

117 with pytest.raises(ValueError, match="height"): 

118 await model.get_rest_args({**base, "height": -480}) 

119 

120 with pytest.raises(ValueError, match="height"): 

121 await model.get_rest_args({**base, "height": 0}) 

122 

123 with pytest.raises(ValueError, match="width"): 

124 await model.get_rest_args({**base, "width": -640}) 

125 

126 with pytest.raises(ValueError, match="width"): 

127 await model.get_rest_args({**base, "width": 0}) 

128 

129 with pytest.raises(ValueError, match="sampling_steps"): 

130 await model.get_rest_args({**base, "sampling_steps": -10}) 

131 

132 with pytest.raises(ValueError, match="sampling_steps"): 

133 await model.get_rest_args({**base, "sampling_steps": 0}) 

134 

135 with pytest.raises(ValueError, match="latent_window_size"): 

136 await model.get_rest_args({**base, "latent_window_size": -1}) 

137 

138 with pytest.raises(ValueError, match="latent_window_size"): 

139 await model.get_rest_args({**base, "latent_window_size": 0}) 

140 

141 with pytest.raises(ValueError, match="video_seconds"): 

142 await model.get_rest_args({**base, "video_seconds": -1.0}) 

143 

144 with pytest.raises(ValueError, match="video_seconds"): 

145 await model.get_rest_args({**base, "video_seconds": 0.0}) 

146 

147 del model 

148 

149 

150@pytest.mark.asyncio 

151async def test_hunyuanframepackf1_assert_args() -> None: 

152 """_assert_args raises for image sizes not divisible by vae_stride.""" 

153 model = HunyuanFramepackF1Generation() 

154 model.init() 

155 assert model.vae_stride == (4, 8, 8) 

156 

157 # Valid size: both height and width divisible by 8 

158 model._assert_args(height=512, width=768) 

159 

160 # Height not divisible by 8 

161 with pytest.raises(ValueError, match="Height"): 

162 model._assert_args(height=513, width=768) 

163 

164 # Width not divisible by 8 

165 with pytest.raises(ValueError, match="Width"): 

166 model._assert_args(height=512, width=769) 

167 

168 del model 

169 

170 

171@pytest.mark.asyncio 

172async def test_hunyuanframepackf1_generate_proceeds_past_text_encoding() -> None: 

173 """generate() proceeds past _encode_text when it is patched to return mock values.""" 

174 model = HunyuanFramepackF1Generation() 

175 model.init() 

176 

177 img = Image.new("RGB", (768, 512)) 

178 six_mocks = tuple(MagicMock() for _ in range(6)) 

179 

180 with patch.object(model, "_encode_text", return_value=six_mocks): 

181 with pytest.raises(ValueError): 

182 await model.generate( 

183 img=img, 

184 prompt="test prompt", 

185 height=512, 

186 width=768, 

187 ) 

188 

189 del model