@@ -88,41 +88,98 @@ public void ChatSegment_MemoryOwner_vs_ByteArray_Test()
88
88
[ Fact ]
89
89
public void ChatSegment_GetAudioSpan_SafetyBoundaryTest ( )
90
90
{
91
- // 경계 조건 테스트: AudioDataSize가 실제 메모리보다 큰 경우
91
+ // 경계 조건 테스트: 유효한 범위 내에서의 메모리 접근 안전성 검증
92
92
var testData = GenerateTestAudioData ( 1000 ) ;
93
93
using var memoryOwner = MemoryPool < byte > . Shared . Rent ( 500 ) ; // 더 작은 메모리 할당
94
94
var actualMemorySize = memoryOwner . Memory . Length ; // 실제 할당된 메모리 크기
95
95
var copySize = Math . Min ( 500 , actualMemorySize ) ;
96
96
testData . AsSpan ( 0 , copySize ) . CopyTo ( memoryOwner . Memory . Span ) ;
97
97
98
- // AudioDataSize를 실제 메모리보다 크게 설정 (위험한 상황 시뮬레이션 )
99
- var oversizedRequest = actualMemorySize + 100 ;
98
+ // 유효한 크기로 설정 (실제 메모리 크기 이하 )
99
+ var validSize = actualMemorySize - 10 ; // 안전한 크기
100
100
var segment = ChatSegment . CreateText ( "Test content" )
101
- . WithAudioMemory ( memoryOwner , oversizedRequest , "audio/wav" , 5.0f ) ; // oversizedRequest > actualMemorySize
101
+ . WithAudioMemory ( memoryOwner , validSize , "audio/wav" , 5.0f ) ;
102
102
103
- // GetAudioSpan이 예외 없이 안전하게 처리되어야 함
103
+ // GetAudioSpan이 정확한 크기를 반환해야 함
104
104
var span = segment . GetAudioSpan ( ) ;
105
105
106
- // 실제 메모리 크기만큼만 반환되어야 함 (Math.Min 적용됨)
107
- Assert . Equal ( actualMemorySize , span . Length ) ;
108
- _output . WriteLine ( $ "요청 크기: { oversizedRequest } , 실제 메모리: { actualMemorySize } , 반환된 span 크기: { span . Length } ") ;
106
+ // 요청한 크기만큼 반환되어야 함
107
+ Assert . Equal ( validSize , span . Length ) ;
108
+ _output . WriteLine ( $ "요청 크기: { validSize } , 실제 메모리: { actualMemorySize } , 반환된 span 크기: { span . Length } ") ;
109
109
}
110
110
111
111
[ Fact ]
112
112
public void ChatSegment_GetAudioSpan_EmptyAndNullSafetyTest ( )
113
113
{
114
- // null AudioMemoryOwner 테스트
115
- var segment1 = ChatSegment . CreateText ( "Test" ) . WithAudioMemory ( null ! , 100 , "audio/wav" , 1.0f ) ;
116
- var span1 = segment1 . GetAudioSpan ( ) ;
117
- Assert . True ( span1 . IsEmpty ) ;
114
+ // null AudioMemoryOwner는 이제 예외가 발생해야 함 (ArgumentNullException)
115
+ var nullException = Assert . Throws < ArgumentNullException > ( ( ) =>
116
+ ChatSegment . CreateText ( "Test" ) . WithAudioMemory ( null ! , 100 , "audio/wav" , 1.0f ) ) ;
117
+ Assert . Equal ( "audioMemoryOwner" , nullException . ParamName ) ;
118
118
119
- // AudioDataSize가 0인 경우
119
+ // AudioDataSize가 0인 경우는 여전히 정상 작동해야 함
120
120
using var memoryOwner = MemoryPool < byte > . Shared . Rent ( 100 ) ;
121
121
var segment2 = ChatSegment . CreateText ( "Test" ) . WithAudioMemory ( memoryOwner , 0 , "audio/wav" , 1.0f ) ;
122
122
var span2 = segment2 . GetAudioSpan ( ) ;
123
123
Assert . True ( span2 . IsEmpty ) ;
124
124
125
- _output . WriteLine ( "빈 케이스들이 모두 안전하게 처리됨" ) ;
125
+ // 기존 AudioData 방식 (null 허용)
126
+ var segment3 = ChatSegment . CreateText ( "Test" ) . WithAudioData ( null ! , "audio/wav" , 1.0f ) ;
127
+ var span3 = segment3 . GetAudioSpan ( ) ;
128
+ Assert . True ( span3 . IsEmpty ) ;
129
+
130
+ _output . WriteLine ( "null 검증과 빈 케이스가 모두 안전하게 처리됨" ) ;
131
+ }
132
+
133
+ [ Fact ]
134
+ public void ChatSegment_WithAudioMemory_ValidationTest ( )
135
+ {
136
+ var testData = GenerateTestAudioData ( 100 ) ;
137
+ using var memoryOwner = MemoryPool < byte > . Shared . Rent ( 100 ) ;
138
+ testData . CopyTo ( memoryOwner . Memory . Span ) ;
139
+
140
+ // 정상 케이스
141
+ var validSegment = ChatSegment . CreateText ( "Test" )
142
+ . WithAudioMemory ( memoryOwner , 50 , "audio/wav" , 1.0f ) ;
143
+ Assert . Equal ( 50 , validSegment . AudioDataSize ) ;
144
+
145
+ // null audioMemoryOwner 테스트
146
+ var nullException = Assert . Throws < ArgumentNullException > ( ( ) =>
147
+ ChatSegment . CreateText ( "Test" ) . WithAudioMemory ( null ! , 100 , "audio/wav" , 1.0f ) ) ;
148
+ Assert . Equal ( "audioMemoryOwner" , nullException . ParamName ) ;
149
+
150
+ // audioDataSize < 0 테스트
151
+ var negativeException = Assert . Throws < ArgumentOutOfRangeException > ( ( ) =>
152
+ ChatSegment . CreateText ( "Test" ) . WithAudioMemory ( memoryOwner , - 1 , "audio/wav" , 1.0f ) ) ;
153
+ Assert . Equal ( "audioDataSize" , negativeException . ParamName ) ;
154
+
155
+ // audioDataSize > memory.Length 테스트
156
+ var oversizeException = Assert . Throws < ArgumentOutOfRangeException > ( ( ) =>
157
+ ChatSegment . CreateText ( "Test" ) . WithAudioMemory ( memoryOwner , memoryOwner . Memory . Length + 1 , "audio/wav" , 1.0f ) ) ;
158
+ Assert . Equal ( "audioDataSize" , oversizeException . ParamName ) ;
159
+
160
+ _output . WriteLine ( "모든 소유권 이전 검증 테스트 통과" ) ;
161
+ }
162
+
163
+ [ Fact ]
164
+ public void ChatSegment_Dispose_MemoryOwnerReleaseTest ( )
165
+ {
166
+ var testData = GenerateTestAudioData ( 100 ) ;
167
+ using var memoryOwner = MemoryPool < byte > . Shared . Rent ( 100 ) ;
168
+ testData . CopyTo ( memoryOwner . Memory . Span ) ;
169
+
170
+ var segment = ChatSegment . CreateText ( "Test" )
171
+ . WithAudioMemory ( memoryOwner , 100 , "audio/wav" , 1.0f ) ;
172
+
173
+ // Dispose 호출 전에는 정상 접근 가능
174
+ Assert . True ( segment . HasAudio ) ;
175
+ Assert . Equal ( 100 , segment . GetAudioSpan ( ) . Length ) ;
176
+
177
+ // Dispose 호출
178
+ segment . Dispose ( ) ;
179
+
180
+ // 메모리가 해제되었으므로 ObjectDisposedException 발생할 수 있음
181
+ // (실제 구현에 따라 다를 수 있음)
182
+ _output . WriteLine ( "Dispose 호출 완료 - 메모리 소유자 해제됨" ) ;
126
183
}
127
184
128
185
private byte [ ] GenerateTestAudioData ( int size )
0 commit comments