Skip to content

Commit 2875896

Browse files
refactor autoencoder_hunyuan_video tests (#13835)
* refactor autoencoder_hunyuan_video tests * remove unused base_precision and test_outputs_equivalence skip --------- Co-authored-by: Sayak Paul <spsayakpaul@gmail.com>
1 parent 5385b2a commit 2875896

1 file changed

Lines changed: 62 additions & 57 deletions

File tree

tests/models/autoencoders/test_models_autoencoder_hunyuan_video.py

Lines changed: 62 additions & 57 deletions
Original file line numberDiff line numberDiff line change
@@ -13,27 +13,38 @@
1313
# See the License for the specific language governing permissions and
1414
# limitations under the License.
1515

16-
import unittest
17-
1816
import torch
1917

2018
from diffusers import AutoencoderKLHunyuanVideo
2119
from diffusers.models.autoencoders.autoencoder_kl_hunyuan_video import prepare_causal_attention_mask
20+
from diffusers.utils.torch_utils import randn_tensor
2221

23-
from ...testing_utils import enable_full_determinism, floats_tensor, torch_device
24-
from ..test_modeling_common import ModelTesterMixin
25-
from .testing_utils import AutoencoderTesterMixin
22+
from ...testing_utils import enable_full_determinism, torch_device
23+
from ..testing_utils import BaseModelTesterConfig, MemoryTesterMixin, ModelTesterMixin, TrainingTesterMixin
24+
from .testing_utils import NewAutoencoderTesterMixin
2625

2726

2827
enable_full_determinism()
2928

3029

31-
class AutoencoderKLHunyuanVideoTests(ModelTesterMixin, AutoencoderTesterMixin, unittest.TestCase):
32-
model_class = AutoencoderKLHunyuanVideo
33-
main_input_name = "sample"
34-
base_precision = 1e-2
30+
class AutoencoderKLHunyuanVideoTesterConfig(BaseModelTesterConfig):
31+
@property
32+
def model_class(self):
33+
return AutoencoderKLHunyuanVideo
34+
35+
@property
36+
def main_input_name(self) -> str:
37+
return "sample"
38+
39+
@property
40+
def output_shape(self) -> tuple:
41+
return (3, 9, 16, 16)
42+
43+
@property
44+
def generator(self):
45+
return torch.Generator("cpu").manual_seed(0)
3546

36-
def get_autoencoder_kl_hunyuan_video_config(self):
47+
def get_init_dict(self) -> dict:
3748
return {
3849
"in_channels": 3,
3950
"out_channels": 3,
@@ -60,29 +71,43 @@ def get_autoencoder_kl_hunyuan_video_config(self):
6071
"mid_block_add_attention": True,
6172
}
6273

63-
@property
64-
def dummy_input(self):
74+
def get_dummy_inputs(self) -> dict:
6575
batch_size = 2
6676
num_frames = 9
6777
num_channels = 3
6878
sizes = (16, 16)
79+
image = randn_tensor(
80+
(batch_size, num_channels, num_frames, *sizes), generator=self.generator, device=torch_device
81+
)
82+
return {"sample": image}
6983

70-
image = floats_tensor((batch_size, num_channels, num_frames) + sizes).to(torch_device)
7184

72-
return {"sample": image}
85+
class TestAutoencoderKLHunyuanVideo(AutoencoderKLHunyuanVideoTesterConfig, ModelTesterMixin):
86+
def test_prepare_causal_attention_mask(self):
87+
def prepare_causal_attention_mask_orig(
88+
num_frames: int, height_width: int, dtype: torch.dtype, device: torch.device, batch_size: int = None
89+
) -> torch.Tensor:
90+
seq_len = num_frames * height_width
91+
mask = torch.full((seq_len, seq_len), float("-inf"), dtype=dtype, device=device)
92+
for i in range(seq_len):
93+
i_frame = i // height_width
94+
mask[i, : (i_frame + 1) * height_width] = 0
95+
if batch_size is not None:
96+
mask = mask.unsqueeze(0).expand(batch_size, -1, -1)
97+
return mask
7398

74-
@property
75-
def input_shape(self):
76-
return (3, 9, 16, 16)
99+
# test with some odd shapes
100+
original_mask = prepare_causal_attention_mask_orig(
101+
num_frames=31, height_width=111, dtype=torch.float32, device=torch_device
102+
)
103+
new_mask = prepare_causal_attention_mask(
104+
num_frames=31, height_width=111, dtype=torch.float32, device=torch_device
105+
)
106+
assert torch.allclose(original_mask, new_mask), "Causal attention mask should be the same"
77107

78-
@property
79-
def output_shape(self):
80-
return (3, 9, 16, 16)
81108

82-
def prepare_init_args_and_inputs_for_common(self):
83-
init_dict = self.get_autoencoder_kl_hunyuan_video_config()
84-
inputs_dict = self.dummy_input
85-
return init_dict, inputs_dict
109+
class TestAutoencoderKLHunyuanVideoTraining(AutoencoderKLHunyuanVideoTesterConfig, TrainingTesterMixin):
110+
"""Training tests for AutoencoderKLHunyuanVideo."""
86111

87112
def test_gradient_checkpointing_is_applied(self):
88113
expected_set = {
@@ -94,9 +119,18 @@ def test_gradient_checkpointing_is_applied(self):
94119
}
95120
super().test_gradient_checkpointing_is_applied(expected_set=expected_set)
96121

97-
# We need to overwrite this test because the base test does not account length of down_block_types
122+
123+
class TestAutoencoderKLHunyuanVideoMemory(AutoencoderKLHunyuanVideoTesterConfig, MemoryTesterMixin):
124+
"""Memory optimization tests for AutoencoderKLHunyuanVideo."""
125+
126+
127+
class TestAutoencoderKLHunyuanVideoSlicingTiling(AutoencoderKLHunyuanVideoTesterConfig, NewAutoencoderTesterMixin):
128+
"""Slicing and tiling tests for AutoencoderKLHunyuanVideo."""
129+
130+
# Overwritten because the base test's block_out_channels doesn't account for the length of down_block_types.
98131
def test_forward_with_norm_groups(self):
99-
init_dict, inputs_dict = self.prepare_init_args_and_inputs_for_common()
132+
init_dict = self.get_init_dict()
133+
inputs_dict = self.get_dummy_inputs()
100134

101135
init_dict["norm_num_groups"] = 16
102136
init_dict["block_out_channels"] = (16, 16, 16, 16)
@@ -111,35 +145,6 @@ def test_forward_with_norm_groups(self):
111145
if isinstance(output, dict):
112146
output = output.to_tuple()[0]
113147

114-
self.assertIsNotNone(output)
148+
assert output is not None
115149
expected_shape = inputs_dict["sample"].shape
116-
self.assertEqual(output.shape, expected_shape, "Input and output shapes do not match")
117-
118-
@unittest.skip("Unsupported test.")
119-
def test_outputs_equivalence(self):
120-
pass
121-
122-
def test_prepare_causal_attention_mask(self):
123-
def prepare_causal_attention_mask_orig(
124-
num_frames: int, height_width: int, dtype: torch.dtype, device: torch.device, batch_size: int = None
125-
) -> torch.Tensor:
126-
seq_len = num_frames * height_width
127-
mask = torch.full((seq_len, seq_len), float("-inf"), dtype=dtype, device=device)
128-
for i in range(seq_len):
129-
i_frame = i // height_width
130-
mask[i, : (i_frame + 1) * height_width] = 0
131-
if batch_size is not None:
132-
mask = mask.unsqueeze(0).expand(batch_size, -1, -1)
133-
return mask
134-
135-
# test with some odd shapes
136-
original_mask = prepare_causal_attention_mask_orig(
137-
num_frames=31, height_width=111, dtype=torch.float32, device=torch_device
138-
)
139-
new_mask = prepare_causal_attention_mask(
140-
num_frames=31, height_width=111, dtype=torch.float32, device=torch_device
141-
)
142-
self.assertTrue(
143-
torch.allclose(original_mask, new_mask),
144-
"Causal attention mask should be the same",
145-
)
150+
assert output.shape == expected_shape, "Input and output shapes do not match"

0 commit comments

Comments
 (0)