1919from avatar import BumblePandoraDevice
2020from avatar import PandoraDevice
2121from avatar import PandoraDevices
22- from avatar .common import make_bredr_connection
23- from avatar .common import make_le_connection
22+ from avatar import pandora_snippet
2423from mobly import base_test
2524from mobly import test_runner
2625from mobly .asserts import assert_equal # type: ignore
2726from mobly .asserts import assert_is_not_none # type: ignore
2827from pandora import host_pb2
29- from pandora import l2cap_pb2
30- from typing import Any , Awaitable , Callable , Dict , Literal , Optional , Tuple , Union
31-
32- CONNECTORS : Dict [
33- str ,
34- Callable [[avatar .PandoraDevice , avatar .PandoraDevice ], Awaitable [Tuple [host_pb2 .Connection , host_pb2 .Connection ]]],
35- ] = {
36- 'Classic' : make_bredr_connection ,
37- 'LE' : make_le_connection ,
38- }
39-
40- FIXED_CHANNEL_CID = 0x3E
28+ from typing import Any , Dict , Optional
29+
4130CLASSIC_PSM = 0xFEFF
4231LE_SPSM = 0xF0
4332
@@ -49,6 +38,10 @@ class L2capTest(base_test.BaseTestClass): # type: ignore[misc]
4938 dut : PandoraDevice
5039 ref : PandoraDevice
5140
41+ # BR/EDR & Low-Energy connections.
42+ dut_ref : Dict [str , host_pb2 .Connection ] = {}
43+ ref_dut : Dict [str , host_pb2 .Connection ] = {}
44+
5245 def setup_class (self ) -> None :
5346 self .devices = PandoraDevices (self )
5447 self .dut , self .ref , * _ = self .devices
@@ -66,160 +59,122 @@ def teardown_class(self) -> None:
6659 async def setup_test (self ) -> None : # pytype: disable=wrong-arg-types
6760 await asyncio .gather (self .dut .reset (), self .ref .reset ())
6861
62+ # Connect REF to DUT in both BR/EDR and Low-Energy.
63+ ref_dut_br , dut_ref_br = await pandora_snippet .connect (self .ref , self .dut )
64+ ref_dut_le , dut_ref_le = await pandora_snippet .connect_le_dummy (self .ref , self .dut )
65+
66+ self .dut_ref = dict (basic = dut_ref_br , le_credit_based = dut_ref_le )
67+ self .ref_dut = dict (basic = ref_dut_br , le_credit_based = ref_dut_le )
68+
6969 @avatar .parameterized (
70- ('Classic' , dict (fixed = l2cap_pb2 .FixedChannelRequest (cid = FIXED_CHANNEL_CID ))),
71- ('LE' , dict (fixed = l2cap_pb2 .FixedChannelRequest (cid = FIXED_CHANNEL_CID ))),
72- ('Classic' , dict (basic = l2cap_pb2 .ConnectionOrientedChannelRequest (psm = CLASSIC_PSM ))),
73- (
74- 'LE' ,
75- dict (
76- le_credit_based = l2cap_pb2 .CreditBasedChannelRequest (
77- spsm = LE_SPSM , mtu = 2046 , mps = 2048 , initial_credit = 256
78- )
79- ),
80- ),
70+ (dict (basic = dict (psm = CLASSIC_PSM )),),
71+ (dict (le_credit_based = dict (spsm = LE_SPSM , mtu = 2046 , mps = 2048 , initial_credit = 256 )),),
8172 ) # type: ignore[misc]
8273 @avatar .asynchronous
8374 async def test_connect (
8475 self ,
85- transport : Union [Literal ['Classic' ], Literal ['LE' ]],
8676 request : Dict [str , Any ],
8777 ) -> None :
88- dut_ref_acl , ref_dut_acl = await CONNECTORS [transport ](self .dut , self .ref )
89- server = self .ref .aio .l2cap .OnConnection (connection = ref_dut_acl , ** request )
90- ref_dut_res , dut_ref_res = await asyncio .gather (
91- anext (aiter (server )),
92- self .dut .aio .l2cap .Connect (connection = dut_ref_acl , ** request ),
78+ transport = next (iter (request .keys ()))
79+ ref_dut , dut_ref = await asyncio .gather (
80+ self .ref .aio .l2cap .WaitConnection (connection = self .ref_dut [transport ], ** request ),
81+ self .dut .aio .l2cap .Connect (connection = self .dut_ref [transport ], ** request ),
9382 )
94- assert_is_not_none (ref_dut_res .channel )
95- assert_is_not_none (dut_ref_res .channel )
83+ assert_is_not_none (ref_dut .channel )
84+ assert_is_not_none (dut_ref .channel )
9685
9786 @avatar .parameterized (
98- ('Classic' , dict (fixed = l2cap_pb2 .FixedChannelRequest (cid = FIXED_CHANNEL_CID ))),
99- ('LE' , dict (fixed = l2cap_pb2 .FixedChannelRequest (cid = FIXED_CHANNEL_CID ))),
100- ('Classic' , dict (basic = l2cap_pb2 .ConnectionOrientedChannelRequest (psm = CLASSIC_PSM ))),
101- (
102- 'LE' ,
103- dict (
104- le_credit_based = l2cap_pb2 .CreditBasedChannelRequest (
105- spsm = LE_SPSM , mtu = 2046 , mps = 2048 , initial_credit = 256
106- )
107- ),
108- ),
87+ (dict (basic = dict (psm = CLASSIC_PSM )),),
88+ (dict (le_credit_based = dict (spsm = LE_SPSM , mtu = 2046 , mps = 2048 , initial_credit = 256 )),),
10989 ) # type: ignore[misc]
11090 @avatar .asynchronous
111- async def test_on_connection (
91+ async def test_wait_connection (
11292 self ,
113- transport : Union [Literal ['Classic' ], Literal ['LE' ]],
11493 request : Dict [str , Any ],
11594 ) -> None :
116- dut_ref_acl , ref_dut_acl = await CONNECTORS [transport ](self .dut , self .ref )
117- server = self .dut .aio .l2cap .OnConnection (connection = dut_ref_acl , ** request )
118- ref_dut_res , dut_ref_res = await asyncio .gather (
119- self .ref .aio .l2cap .Connect (connection = ref_dut_acl , ** request ),
120- anext (aiter (server )),
95+ transport = next (iter (request .keys ()))
96+ dut_ref , ref_dut = await asyncio .gather (
97+ self .ref .aio .l2cap .WaitConnection (connection = self .dut_ref [transport ], ** request ),
98+ self .dut .aio .l2cap .Connect (connection = self .ref_dut [transport ], ** request ),
12199 )
122- assert_is_not_none (ref_dut_res .channel )
123- assert_is_not_none (dut_ref_res .channel )
100+ assert_is_not_none (ref_dut .channel )
101+ assert_is_not_none (dut_ref .channel )
124102
125103 @avatar .parameterized (
126- ('Classic' , dict (basic = l2cap_pb2 .ConnectionOrientedChannelRequest (psm = CLASSIC_PSM ))),
127- (
128- 'LE' ,
129- dict (
130- le_credit_based = l2cap_pb2 .CreditBasedChannelRequest (
131- spsm = LE_SPSM , mtu = 2046 , mps = 2048 , initial_credit = 256
132- )
133- ),
134- ),
104+ (dict (basic = dict (psm = CLASSIC_PSM )),),
105+ (dict (le_credit_based = dict (spsm = LE_SPSM , mtu = 2046 , mps = 2048 , initial_credit = 256 )),),
135106 ) # type: ignore[misc]
136107 @avatar .asynchronous
137108 async def test_disconnect (
138109 self ,
139- transport : Union [Literal ['Classic' ], Literal ['LE' ]],
140110 request : Dict [str , Any ],
141111 ) -> None :
142- dut_ref_acl , ref_dut_acl = await CONNECTORS [transport ](self .dut , self .ref )
143- server = self .ref .aio .l2cap .OnConnection (connection = ref_dut_acl , ** request )
144- ref_dut_res , dut_ref_res = await asyncio .gather (
145- anext (aiter (server )),
146- self .dut .aio .l2cap .Connect (connection = dut_ref_acl , ** request ),
112+ transport = next (iter (request .keys ()))
113+ dut_ref , ref_dut = await asyncio .gather (
114+ self .ref .aio .l2cap .WaitConnection (connection = self .dut_ref [transport ], ** request ),
115+ self .dut .aio .l2cap .Connect (connection = self .ref_dut [transport ], ** request ),
147116 )
148- assert dut_ref_res .channel and ref_dut_res .channel
117+ assert_is_not_none (ref_dut .channel )
118+ assert_is_not_none (dut_ref .channel )
119+ assert ref_dut .channel and dut_ref .channel
149120
150- await asyncio .gather (
151- self .dut .aio .l2cap .Disconnect (channel = dut_ref_res .channel ),
152- self .ref .aio .l2cap .WaitDisconnection (channel = ref_dut_res .channel ),
121+ _ , dis = await asyncio .gather (
122+ self .ref .aio .l2cap .WaitDisconnection (channel = ref_dut .channel ),
123+ self .dut .aio .l2cap .Disconnect (channel = dut_ref .channel ),
153124 )
154125
126+ assert_equal (dis .result_variant (), 'success' )
127+
155128 @avatar .parameterized (
156- ('Classic' , dict (basic = l2cap_pb2 .ConnectionOrientedChannelRequest (psm = CLASSIC_PSM ))),
157- (
158- 'LE' ,
159- dict (
160- le_credit_based = l2cap_pb2 .CreditBasedChannelRequest (
161- spsm = LE_SPSM , mtu = 2046 , mps = 2048 , initial_credit = 256
162- )
163- ),
164- ),
129+ (dict (basic = dict (psm = CLASSIC_PSM )),),
130+ (dict (le_credit_based = dict (spsm = LE_SPSM , mtu = 2046 , mps = 2048 , initial_credit = 256 )),),
165131 ) # type: ignore[misc]
166132 @avatar .asynchronous
167133 async def test_wait_disconnection (
168134 self ,
169- transport : Union [Literal ['Classic' ], Literal ['LE' ]],
170135 request : Dict [str , Any ],
171136 ) -> None :
172- dut_ref_acl , ref_dut_acl = await CONNECTORS [transport ](self .dut , self .ref )
173- server = self .ref .aio .l2cap .OnConnection (connection = ref_dut_acl , ** request )
174- ref_dut_res , dut_ref_res = await asyncio .gather (
175- anext (aiter (server )),
176- self .dut .aio .l2cap .Connect (connection = dut_ref_acl , ** request ),
137+ transport = next (iter (request .keys ()))
138+ dut_ref , ref_dut = await asyncio .gather (
139+ self .ref .aio .l2cap .WaitConnection (connection = self .dut_ref [transport ], ** request ),
140+ self .dut .aio .l2cap .Connect (connection = self .ref_dut [transport ], ** request ),
177141 )
178- assert dut_ref_res .channel and ref_dut_res .channel
142+ assert_is_not_none (ref_dut .channel )
143+ assert_is_not_none (dut_ref .channel )
144+ assert ref_dut .channel and dut_ref .channel
179145
180- await asyncio .gather (
181- self .ref .aio .l2cap .Disconnect (channel = ref_dut_res .channel ),
182- self .dut .aio .l2cap .WaitDisconnection (channel = dut_ref_res .channel ),
146+ dis , _ = await asyncio .gather (
147+ self .dut .aio .l2cap .WaitDisconnection (channel = dut_ref .channel ),
148+ self .ref .aio .l2cap .Disconnect (channel = ref_dut .channel ),
183149 )
184150
151+ assert_equal (dis .result_variant (), 'success' )
152+
185153 @avatar .parameterized (
186- ('Classic' , dict (fixed = l2cap_pb2 .FixedChannelRequest (cid = FIXED_CHANNEL_CID ))),
187- ('LE' , dict (fixed = l2cap_pb2 .FixedChannelRequest (cid = FIXED_CHANNEL_CID ))),
188- ('Classic' , dict (basic = l2cap_pb2 .ConnectionOrientedChannelRequest (psm = CLASSIC_PSM ))),
189- (
190- 'LE' ,
191- dict (
192- le_credit_based = l2cap_pb2 .CreditBasedChannelRequest (
193- spsm = LE_SPSM , mtu = 2046 , mps = 2048 , initial_credit = 256
194- )
195- ),
196- ),
154+ (dict (basic = dict (psm = CLASSIC_PSM )),),
155+ (dict (le_credit_based = dict (spsm = LE_SPSM , mtu = 2046 , mps = 2048 , initial_credit = 256 )),),
197156 ) # type: ignore[misc]
198157 @avatar .asynchronous
199158 async def test_send (
200159 self ,
201- transport : Union [Literal ['Classic' ], Literal ['LE' ]],
202160 request : Dict [str , Any ],
203161 ) -> None :
204- dut_ref_acl , ref_dut_acl = await CONNECTORS [transport ](self .dut , self .ref )
205- server = self .dut .aio .l2cap .OnConnection (connection = dut_ref_acl , ** request )
206- ref_dut_res , dut_ref_res = await asyncio .gather (
207- self .ref .aio .l2cap .Connect (connection = ref_dut_acl , ** request ),
208- anext (aiter (server )),
162+ transport = next (iter (request .keys ()))
163+ dut_ref , ref_dut = await asyncio .gather (
164+ self .ref .aio .l2cap .WaitConnection (connection = self .dut_ref [transport ], ** request ),
165+ self .dut .aio .l2cap .Connect (connection = self .ref_dut [transport ], ** request ),
209166 )
210- ref_dut_channel = ref_dut_res .channel
211- dut_ref_channel = dut_ref_res .channel
212- assert_is_not_none (ref_dut_res .channel )
213- assert_is_not_none (dut_ref_res .channel )
214- assert ref_dut_channel and dut_ref_channel
215-
216- dut_ref_stream = self .ref .aio .l2cap .Receive (channel = dut_ref_channel )
217- _send_res , recv_res = await asyncio .gather (
218- self .dut .aio .l2cap .Send (channel = ref_dut_channel , data = b"The quick brown fox jumps over the lazy dog" ),
219- anext (aiter (dut_ref_stream )),
167+ assert_is_not_none (ref_dut .channel )
168+ assert_is_not_none (dut_ref .channel )
169+ assert ref_dut .channel and dut_ref .channel
170+
171+ ref_source = self .ref .aio .l2cap .Receive (channel = dut_ref .channel )
172+ _ , recv = await asyncio .gather (
173+ self .dut .aio .l2cap .Send (channel = ref_dut .channel , data = b"The quick brown fox jumps over the lazy dog" ),
174+ anext (aiter (ref_source )),
220175 )
221- assert recv_res . data
222- assert_equal (recv_res .data , b"The quick brown fox jumps over the lazy dog" )
176+
177+ assert_equal (recv .data , b"The quick brown fox jumps over the lazy dog" )
223178
224179
225180if __name__ == "__main__" :
0 commit comments