File: test_unit_serialization.py

package info (click to toggle)
python-azure 20251104%2Bgit-1
  • links: PTS, VCS
  • area: main
  • in suites: forky
  • size: 770,224 kB
  • sloc: python: 6,357,217; ansic: 804; javascript: 287; makefile: 198; sh: 193; xml: 109
file content (337 lines) | stat: -rw-r--r-- 12,737 bytes parent folder | download | duplicates (2)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
# coding=utf-8
# --------------------------------------------------------------------------
# Copyright (c) Microsoft Corporation. All rights reserved.
# Licensed under the MIT License.
# --------------------------------------------------------------------------

import pytest
from enum import Enum
from typing import cast

from azure.ai.voicelive._utils.serialization import Serializer, SerializationError
from azure.ai.voicelive.models import (
    AzureVoiceType,
    MessageRole,
    OpenAIVoiceName,
    InputAudioFormat,
    OutputAudioFormat,
    ItemParamStatus,
    ResponseStatus,
    Modality,
    InputTextContentPart,
    OutputTextContentPart,
    UserMessageItem,
    AssistantMessageItem,
    AzureStandardVoice,
    OpenAIVoice,
)


class EnumForTest(str, Enum):
    """Enum for serialization testing."""

    VALUE_A = "value_a"
    VALUE_B = "value_b"


class TestSerializerBasicTypes:
    """Test serializer with basic types."""

    def setUp(self):
        """Set up serializer for testing."""
        self.serializer = Serializer()

    def test_serialize_string(self):
        """Test string serialization."""
        serializer = Serializer()
        result = serializer.serialize_data("test_string", "str")
        assert result == "test_string"

    def test_serialize_int(self):
        """Test integer serialization."""
        serializer = Serializer()
        result = serializer.serialize_data(42, "int")
        assert result == 42

    def test_serialize_float(self):
        """Test float serialization."""
        serializer = Serializer()
        result = serializer.serialize_data(3.14, "float")
        assert result == 3.14

    def test_serialize_bool(self):
        """Test boolean serialization."""
        serializer = Serializer()
        result = serializer.serialize_data(True, "bool")
        assert result is True

        result = serializer.serialize_data(False, "bool")
        assert result is False

    def test_serialize_none(self):
        """Test None serialization."""
        serializer = Serializer()
        with pytest.raises(ValueError):
            serializer.serialize_data(None, "str")


class TestSerializerEnums:
    """Test serializer with enum types."""

    def test_serialize_azure_voice_type(self):
        """Test AzureVoiceType enum serialization."""
        serializer = Serializer()
        result = serializer.serialize_data(AzureVoiceType.AZURE_CUSTOM, "str")
        assert result == "azure-custom"

    def test_serialize_message_role(self):
        """Test MessageRole enum serialization."""
        serializer = Serializer()
        result = serializer.serialize_data(MessageRole.ASSISTANT, "str")
        assert result == "assistant"

    def test_serialize_oai_voice(self):
        """Test OpenAIVoiceName enum serialization."""
        serializer = Serializer()
        result = serializer.serialize_data(OpenAIVoiceName.ALLOY, "str")
        assert result == "alloy"

    def test_serialize_input_audio_format(self):
        """Test InputAudioFormat enum serialization."""
        serializer = Serializer()
        result = serializer.serialize_data(InputAudioFormat.PCM16, "str")
        assert result == "pcm16"

    def test_serialize_output_audio_format(self):
        """Test OutputAudioFormat enum serialization."""
        serializer = Serializer()
        result = serializer.serialize_data(OutputAudioFormat.G711_ULAW, "str")
        assert result == "g711_ulaw"

    def test_serialize_response_status(self):
        """Test ResponseStatus enum serialization."""
        serializer = Serializer()
        result = serializer.serialize_data(ResponseStatus.COMPLETED, "str")
        assert result == "completed"

    def test_serialize_custom_test_enum(self):
        """Test custom test enum serialization."""
        serializer = Serializer()
        result = serializer.serialize_data(EnumForTest.VALUE_A, "str")
        assert result == "value_a"


class TestSerializerEnumTypeCasting:
    """Test the specific enum type casting fix from the recent changes."""

    def test_enum_type_casting_fix(self):
        """Test that enum type casting works correctly.

        This tests the specific fix where data.__class__ is cast to type
        in the serialization utilities.
        """
        serializer = Serializer()

        # Test with various enum types to ensure the cast(type, data.__class__) fix works
        enums_to_test = [
            (AzureVoiceType.AZURE_CUSTOM, "azure-custom"),
            (MessageRole.USER, "user"),
            (OpenAIVoiceName.SHIMMER, "shimmer"),
            (InputAudioFormat.G711_ALAW, "g711_alaw"),
            (ItemParamStatus.COMPLETED, "completed"),
            (Modality.AUDIO, "audio"),
        ]

        for enum_value, expected_result in enums_to_test:
            result = serializer.serialize_data(enum_value, "str")
            assert result == expected_result, f"Failed for {enum_value}: expected {expected_result}, got {result}"

    def test_enum_class_attribute_casting(self):
        """Test that the enum class casting works with __class__ attribute."""
        serializer = Serializer()

        # Create enum instances and test that their __class__ can be cast to type
        voice_type = AzureVoiceType.AZURE_STANDARD
        role = MessageRole.ASSISTANT

        # These should not raise TypeError due to the cast(type, data.__class__) fix
        voice_result = serializer.serialize_data(voice_type, "str")
        role_result = serializer.serialize_data(role, "str")

        assert voice_result == "azure-standard"
        assert role_result == "assistant"

    def test_enum_inheritance_check(self):
        """Test that enum inheritance checking works correctly."""
        serializer = Serializer()

        # Test that issubclass works with the casted type
        voice_type = AzureVoiceType.AZURE_PERSONAL

        # This should work without TypeError
        result = serializer.serialize_data(voice_type, "str")
        assert result == "azure-personal"

        # Verify the enum is still recognized as an Enum subclass
        casted_type = cast(type, voice_type.__class__)
        assert issubclass(casted_type, Enum)


class TestSerializerCollections:
    """Test serializer with collections containing enums."""

    def test_serialize_list_of_enums(self):
        """Test serializing a list of enums."""
        serializer = Serializer()
        enum_list = [AzureVoiceType.AZURE_CUSTOM, AzureVoiceType.AZURE_STANDARD]

        result = serializer.serialize_data(enum_list, "[str]")
        assert result == ["azure-custom", "azure-standard"]

    def test_serialize_list_of_modalities(self):
        """Test serializing a list of modality enums."""
        serializer = Serializer()
        modalities = [Modality.TEXT, Modality.AUDIO, Modality.ANIMATION]

        result = serializer.serialize_data(modalities, "[str]")
        assert result == ["text", "audio", "animation"]

    def test_serialize_mixed_list(self):
        """Test serializing a list with mixed types."""
        serializer = Serializer()
        mixed_list = ["string", 42, True, MessageRole.SYSTEM]

        # Note: This might need adjustment based on actual serializer behavior
        # The test verifies that enums in mixed collections are handled correctly
        try:
            result = serializer.serialize_data(mixed_list, "[object]")
            # At minimum, ensure no exceptions are raised
            assert isinstance(result, list)
        except (SerializationError, NotImplementedError):
            # Some serializers may not support mixed types
            pytest.skip("Serializer doesn't support mixed type collections")


class TestSerializerModels:
    """Test serializer with model objects."""

    def test_serialize_content_part(self):
        """Test serializing content parts."""
        serializer = Serializer()
        content = InputTextContentPart(text="Hello, world!")

        # Test that model objects can be serialized
        # The exact behavior depends on the model's serialization implementation
        try:
            result = serializer.serialize_data(content, "object")
            assert isinstance(result, dict) or hasattr(content, "as_dict")
        except (SerializationError, AttributeError):
            # If direct serialization isn't supported, at least verify the object exists
            assert content.text == "Hello, world!"
            assert content.type == "input_text"

    def test_serialize_message_item(self):
        """Test serializing message items."""
        serializer = Serializer()
        content = [InputTextContentPart(text="Test message")]
        message = UserMessageItem(content=content)

        # Verify the message has the correct structure
        assert message.role == MessageRole.USER
        assert len(message.content) == 1
        assert message.content[0].text == "Test message"

    def test_serialize_voice_config(self):
        """Test serializing voice configurations."""
        serializer = Serializer()
        voice = AzureStandardVoice(name="test-voice", temperature=0.7)

        # Verify voice configuration structure
        assert voice.type == AzureVoiceType.AZURE_STANDARD
        assert voice.name == "test-voice"
        assert voice.temperature == 0.7


class TestSerializerErrorHandling:
    """Test serializer error handling."""

    def test_serialization_error_handling(self):
        """Test that serialization errors are properly handled."""
        serializer = Serializer()

        # Test with an object that can't be serialized
        class UnserializableObject:
            def __init__(self):
                self._private = "private"

        obj = UnserializableObject()

        # This should either serialize or raise a SerializationError
        try:
            result = serializer.serialize_data(obj, "object")
            # If serialization succeeds, verify it's reasonable
            assert isinstance(result, (dict, str)) or result is None
        except (SerializationError, TypeError):
            # Expected for truly unserializable objects
            pass

    def test_invalid_data_type_specification(self):
        """Test handling of invalid data type specifications."""
        serializer = Serializer()

        try:
            # Try with an invalid type specification
            result = serializer.serialize_data("test", "invalid_type")
            # If it doesn't raise an error, it should return something reasonable
            assert result is not None
        except (SerializationError, ValueError, TypeError):
            # Expected for invalid type specifications
            pass


class TestSerializerIntegration:
    """Integration tests for serializer functionality."""

    def test_complex_enum_scenarios(self):
        """Test complex scenarios with multiple enum types."""
        serializer = Serializer()

        # Create a complex scenario with nested enums
        voice_types = [AzureVoiceType.AZURE_CUSTOM, AzureVoiceType.AZURE_STANDARD, AzureVoiceType.AZURE_PERSONAL]

        roles = [MessageRole.SYSTEM, MessageRole.USER, MessageRole.ASSISTANT]

        # Test serializing multiple enum collections
        voice_result = serializer.serialize_data(voice_types, "[str]")
        roles_result = serializer.serialize_data(roles, "[str]")

        assert voice_result == ["azure-custom", "azure-standard", "azure-personal"]
        assert roles_result == ["system", "user", "assistant"]

    def test_enum_with_model_objects(self):
        """Test enums used within model objects."""
        content = [OutputTextContentPart(text="Assistant response")]
        message = AssistantMessageItem(content=content)

        # Verify that enums within models work correctly
        assert message.role == MessageRole.ASSISTANT
        assert message.content[0].type == "text"

        # Test that the discriminator enum values are properly set
        openai_voice = OpenAIVoice(name=OpenAIVoiceName.CORAL)
        assert openai_voice.type == "openai"
        assert openai_voice.name == OpenAIVoiceName.CORAL

    def test_serializer_with_real_world_data(self):
        """Test serializer with realistic data structures."""
        serializer = Serializer()

        # Create realistic data that might be serialized in the SDK
        modalities = [Modality.TEXT, Modality.AUDIO]
        audio_formats = [InputAudioFormat.PCM16, InputAudioFormat.G711_ULAW]

        modalities_result = serializer.serialize_data(modalities, "[str]")
        formats_result = serializer.serialize_data(audio_formats, "[str]")

        assert modalities_result == ["text", "audio"]
        assert formats_result == ["pcm16", "g711_ulaw"]