@@ -138,3 +138,149 @@ pub mod v11 {
138138 } )
139139 }
140140}
141+
142+ #[ cfg( all( test, any( feature = "osc10" , feature = "osc11" ) ) ) ]
143+ mod tests {
144+ use super :: * ;
145+
146+ #[ cfg( feature = "osc10" ) ]
147+ mod osc10 {
148+ use super :: * ;
149+ use alloc:: borrow:: ToOwned ;
150+
151+ #[ test]
152+ fn message_to_ir_encodes_metadata_and_args ( ) {
153+ use osc_types10 as osc;
154+
155+ let message = osc:: Message {
156+ address : "/basic" ,
157+ args : vec ! [
158+ osc:: OscType :: Int ( 42 ) ,
159+ osc:: OscType :: Float ( 0.5 ) ,
160+ osc:: OscType :: String ( "text" ) ,
161+ osc:: OscType :: Blob ( & [ 1 , 2 , 3 ] ) ,
162+ ] ,
163+ } ;
164+
165+ let ir = v10:: message_to_ir ( & message) ;
166+ let entries = match ir {
167+ IrValue :: Map ( entries) => entries,
168+ _ => panic ! ( "expected map" ) ,
169+ } ;
170+
171+ assert_eq ! ( entries. len( ) , 3 ) ;
172+
173+ let ty = entries. iter ( ) . find ( |( key, _) | key == "$type" ) . unwrap ( ) ;
174+ assert_eq ! ( ty. 1 , IrValue :: from( MESSAGE_TYPE_TAG ) ) ;
175+
176+ let address = entries. iter ( ) . find ( |( key, _) | key == "address" ) . unwrap ( ) ;
177+ assert_eq ! ( address. 1 , IrValue :: from( "/basic" ) ) ;
178+
179+ let args_entry = entries. iter ( ) . find ( |( key, _) | key == "args" ) . unwrap ( ) ;
180+ let args = match & args_entry. 1 {
181+ IrValue :: Array ( values) => values,
182+ _ => panic ! ( "expected args array" ) ,
183+ } ;
184+
185+ let expected = vec ! [
186+ IrValue :: Integer ( 42 ) ,
187+ IrValue :: Float ( 0.5 ) ,
188+ IrValue :: from( "text" ) ,
189+ IrValue :: Binary ( vec![ 1 , 2 , 3 ] ) ,
190+ ] ;
191+ assert_eq ! ( args, & expected) ;
192+ }
193+
194+ #[ test]
195+ fn ir_roundtrips_to_message ( ) {
196+ use osc_types10 as osc;
197+
198+ let ir = IrValue :: Map ( vec ! [
199+ ( "$type" . to_owned( ) , IrValue :: from( MESSAGE_TYPE_TAG ) ) ,
200+ ( "address" . to_owned( ) , IrValue :: from( "/roundtrip" ) ) ,
201+ (
202+ "args" . to_owned( ) ,
203+ IrValue :: Array ( vec![
204+ IrValue :: Integer ( 7 ) ,
205+ IrValue :: Float ( -1.25 ) ,
206+ IrValue :: from( "value" ) ,
207+ IrValue :: Binary ( vec![ 9 , 8 , 7 ] ) ,
208+ ] ) ,
209+ ) ,
210+ ] ) ;
211+
212+ let message = v10:: ir_to_message ( & ir) . expect ( "expected successful conversion" ) ;
213+ assert_eq ! ( message. address, "/roundtrip" ) ;
214+ assert ! ( matches!( message. args[ 0 ] , osc:: OscType :: Int ( 7 ) ) ) ;
215+ assert ! (
216+ matches!( message. args[ 1 ] , osc:: OscType :: Float ( f) if ( f + 1.25 ) . abs( ) < f32 :: EPSILON )
217+ ) ;
218+ assert ! ( matches!( message. args[ 2 ] , osc:: OscType :: String ( "value" ) ) ) ;
219+ assert ! ( matches!( message. args[ 3 ] , osc:: OscType :: Blob ( slice) if slice == & [ 9 , 8 , 7 ] ) ) ;
220+ }
221+
222+ #[ test]
223+ fn ir_to_message_rejects_unknown_arguments ( ) {
224+ let ir = IrValue :: Map ( vec ! [
225+ ( "address" . to_owned( ) , IrValue :: from( "/invalid" ) ) ,
226+ ( "args" . to_owned( ) , IrValue :: Array ( vec![ IrValue :: Bool ( true ) ] ) ) ,
227+ ] ) ;
228+
229+ assert ! ( v10:: ir_to_message( & ir) . is_none( ) ) ;
230+ }
231+ }
232+
233+ #[ test]
234+ fn mismatched_type_tag_is_rejected ( ) {
235+ let value = IrValue :: Map ( vec ! [
236+ ( "$type" . into( ) , IrValue :: from( "osc.bundle" ) ) ,
237+ ( "address" . into( ) , IrValue :: from( "/bad" ) ) ,
238+ ( "args" . into( ) , IrValue :: Array ( vec![ ] ) ) ,
239+ ] ) ;
240+
241+ assert ! ( try_extract_message( & value) . is_none( ) ) ;
242+ }
243+
244+ #[ test]
245+ fn missing_type_tag_defaults_to_message ( ) {
246+ let value = IrValue :: Map ( vec ! [
247+ ( "address" . into( ) , IrValue :: from( "/no-tag" ) ) ,
248+ ( "args" . into( ) , IrValue :: Array ( vec![ ] ) ) ,
249+ ] ) ;
250+
251+ let extracted = try_extract_message ( & value) . expect ( "expected message extraction" ) ;
252+ assert_eq ! ( extracted. 0 , "/no-tag" ) ;
253+ assert ! ( extracted. 1 . is_empty( ) ) ;
254+ }
255+
256+ #[ cfg( feature = "osc11" ) ]
257+ mod osc11 {
258+ use super :: * ;
259+
260+ #[ test]
261+ fn ir_to_message_rejects_color_and_midi ( ) {
262+ let ir = IrValue :: Map ( vec ! [
263+ ( "address" . into( ) , IrValue :: from( "/unsupported" ) ) ,
264+ (
265+ "args" . into( ) ,
266+ IrValue :: Array ( vec![
267+ IrValue :: Color {
268+ r: 0 ,
269+ g: 1 ,
270+ b: 2 ,
271+ a: 3 ,
272+ } ,
273+ IrValue :: Midi {
274+ port: 1 ,
275+ status: 2 ,
276+ data1: 3 ,
277+ data2: 4 ,
278+ } ,
279+ ] ) ,
280+ ) ,
281+ ] ) ;
282+
283+ assert ! ( v11:: ir_to_message( & ir) . is_none( ) ) ;
284+ }
285+ }
286+ }
0 commit comments