Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit d4a89d77 authored by Hansong Zhang's avatar Hansong Zhang
Browse files

LeL2capTest: Get incoming packet stream for each channel

Bug: 145707677
Test: cert/run --host
Change-Id: I5c0eea0de649609e0b431ef0d30c1e2570e51ab1
parent 611c9dfc
Loading
Loading
Loading
Loading
+5 −0
Original line number Diff line number Diff line
@@ -100,6 +100,11 @@ class L2capMatchers(object):
    def PacketPayloadRawData(payload):
        return lambda packet: payload in packet.payload

    # this is a hack - should be removed
    @staticmethod
    def PacketPayloadWithMatchingPsm(psm):
        return lambda packet: None if psm != packet.psm else packet

    @staticmethod
    def ExtractBasicFrame(scid):
        return lambda packet: L2capMatchers._basic_frame_for(packet, scid)
+19 −12
Original line number Diff line number Diff line
@@ -18,9 +18,11 @@ from l2cap.classic import facade_pb2 as l2cap_facade_pb2
from l2cap.le import facade_pb2 as l2cap_le_facade_pb2
from bluetooth_packets_python3 import l2cap_packets
from bluetooth_packets_python3.l2cap_packets import ConnectionResponseResult
from cert.event_stream import EventStream
from cert.event_stream import FilteringEventStream
from cert.event_stream import EventStream, IEventStream
from cert.closable import Closable, safeClose
from cert.truth import assertThat
from cert.matchers import L2capMatchers
from facade import common_pb2 as common
from google.protobuf import empty_pb2 as empty_proto

@@ -55,11 +57,18 @@ class PyL2cap(Closable):
        return PyL2capChannel(self._device, psm)


class PyLeL2capChannel(object):
class PyLeL2capChannel(IEventStream):

    def __init__(self, device, psm):
    def __init__(self, device, psm, l2cap_stream):
        self._device = device
        self._psm = psm
        self._le_l2cap_stream = l2cap_stream
        self._our_le_l2cap_view = FilteringEventStream(
            self._le_l2cap_stream,
            L2capMatchers.PacketPayloadWithMatchingPsm(self._psm))

    def get_event_queue(self):
        return self._our_le_l2cap_view.get_event_queue()

    def send(self, payload):
        self._device.l2cap_le.SendDynamicChannelPacket(
@@ -72,10 +81,11 @@ class CreditBasedConnectionResponseFutureWrapper(object):
    create the corresponding PyLeL2capChannel object later
    """

    def __init__(self, grpc_response_future, device, psm):
    def __init__(self, grpc_response_future, device, psm, le_l2cap_stream):
        self._grpc_response_future = grpc_response_future
        self._device = device
        self._psm = psm
        self._le_l2cap_stream = le_l2cap_stream

    def get_status(self):
        return l2cap_packets.LeCreditBasedConnectionResponseResult(
@@ -84,27 +94,24 @@ class CreditBasedConnectionResponseFutureWrapper(object):
    def get_channel(self):
        assertThat(self.get_status()).isEqualTo(
            l2cap_packets.LeCreditBasedConnectionResponseResult.SUCCESS)
        return PyLeL2capChannel(self._device, self._psm)
        return PyLeL2capChannel(self._device, self._psm, self._le_l2cap_stream)


class PyLeL2cap(Closable):

    def __init__(self, device):
        self._device = device
        self.le_l2cap_stream = EventStream(
        self._le_l2cap_stream = EventStream(
            self._device.l2cap_le.FetchL2capData(empty_proto.Empty()))

    def close(self):
        safeClose(self.le_l2cap_stream)

    def get_le_l2cap_stream(self):
        return self.le_l2cap_stream
        safeClose(self._le_l2cap_stream)

    def register_coc(self, psm=0x33):
        self._device.l2cap_le.SetDynamicChannel(
            l2cap_le_facade_pb2.SetEnableDynamicChannelRequest(
                psm=psm, enable=True))
        return PyLeL2capChannel(self._device, psm)
        return PyLeL2capChannel(self._device, psm, self._le_l2cap_stream)

    def connect_coc_to_cert(self, psm=0x33):
        """
@@ -120,4 +127,4 @@ class PyLeL2cap(Closable):
                        address=b"22:33:ff:ff:11:00"))))

        return CreditBasedConnectionResponseFutureWrapper(
            response_future, self._device, psm)
            response_future, self._device, psm, self._le_l2cap_stream)
+31 −3
Original line number Diff line number Diff line
@@ -144,7 +144,7 @@ class LeL2capTest(GdFacadeOnlyBaseTestClass):
        cert_channel.send_first_le_i_frame(sdu_size_for_two_sample_packet,
                                           SAMPLE_PACKET)
        cert_channel.send(SAMPLE_PACKET)
        assertThat(self.dut_l2cap.le_l2cap_stream).emits(
        assertThat(dut_channel).emits(
            L2capMatchers.PacketPayloadRawData(b'\x01\x01\x02\x00\x00\x00' * 2))

    def test_data_receiving(self):
@@ -154,7 +154,35 @@ class LeL2capTest(GdFacadeOnlyBaseTestClass):
        self._setup_link_from_cert()
        (dut_channel, cert_channel) = self._open_channel_from_cert()
        cert_channel.send_first_le_i_frame(6, SAMPLE_PACKET)
        assertThat(self.dut_l2cap.le_l2cap_stream).emits(
        assertThat(dut_channel).emits(
            L2capMatchers.PacketPayloadRawData(b'\x01\x01\x02\x00\x00\x00'))

    def test_multiple_channels_with_interleaved_data_streams(self):
        """
        L2CAP/COS/CFC/BV-05-C
        """
        self._setup_link_from_cert()
        (dut_channel_x, cert_channel_x) = self._open_channel_from_cert(
            signal_id=1, scid=0x0103, psm=0x33)
        (dut_channel_y, cert_channel_y) = self._open_channel_from_cert(
            signal_id=2, scid=0x0105, psm=0x35)
        (dut_channel_z, cert_channel_z) = self._open_channel_from_cert(
            signal_id=3, scid=0x0107, psm=0x37)
        cert_channel_y.send_first_le_i_frame(6, SAMPLE_PACKET)
        cert_channel_z.send_first_le_i_frame(6, SAMPLE_PACKET)
        cert_channel_y.send_first_le_i_frame(6, SAMPLE_PACKET)
        cert_channel_z.send_first_le_i_frame(6, SAMPLE_PACKET)
        cert_channel_y.send_first_le_i_frame(6, SAMPLE_PACKET)
        # TODO: We should assert two events in order, but it got stuck
        assertThat(dut_channel_y).emits(
            L2capMatchers.PacketPayloadRawData(b'\x01\x01\x02\x00\x00\x00'),
            at_least_times=3)
        assertThat(dut_channel_z).emits(
            L2capMatchers.PacketPayloadRawData(b'\x01\x01\x02\x00\x00\x00'),
            L2capMatchers.PacketPayloadRawData(
                b'\x01\x01\x02\x00\x00\x00')).inOrder()
        cert_channel_z.send_first_le_i_frame(6, SAMPLE_PACKET)
        assertThat(dut_channel_z).emits(
            L2capMatchers.PacketPayloadRawData(b'\x01\x01\x02\x00\x00\x00'))

    def test_reject_unknown_command_in_le_sigling_channel(self):
@@ -220,7 +248,7 @@ class LeL2capTest(GdFacadeOnlyBaseTestClass):
        self._setup_link_from_cert()
        (dut_channel, cert_channel) = self._open_channel_from_dut()
        cert_channel.send_first_le_i_frame(6, SAMPLE_PACKET)
        assertThat(self.dut_l2cap.le_l2cap_stream).emits(
        assertThat(dut_channel).emits(
            L2capMatchers.PacketPayloadRawData(b'\x01\x01\x02\x00\x00\x00'))

    def test_credit_based_connection_response_on_supported_le_psm(self):
+1 −1
Original line number Diff line number Diff line
@@ -182,6 +182,7 @@ class L2capLeModuleFacadeService : public L2capLeModuleFacade::Service {
      auto packet = channel_->GetQueueUpEnd()->TryDequeue();
      std::string data = std::string(packet->begin(), packet->end());
      L2capPacket l2cap_data;
      l2cap_data.set_psm(psm_);
      l2cap_data.set_payload(data);
      facade_service_->pending_l2cap_data_.OnIncomingEvent(l2cap_data);
    }
@@ -232,7 +233,6 @@ class L2capLeModuleFacadeService : public L2capLeModuleFacade::Service {
  os::Handler* facade_handler_;
  std::mutex channel_map_mutex_;
  std::map<Psm, std::unique_ptr<L2capDynamicChannelHelper>> dynamic_channel_helper_map_;
  bool fetch_l2cap_data_ = false;
  ::bluetooth::grpc::GrpcEventQueue<L2capPacket> pending_l2cap_data_{"FetchL2capData"};
};

+2 −3
Original line number Diff line number Diff line
@@ -16,9 +16,8 @@ service L2capLeModuleFacade {
}

message L2capPacket {
  facade.BluetoothAddressWithType remote = 1;
  uint32 channel = 2;
  bytes payload = 3;
  uint32 psm = 1;
  bytes payload = 2;
}

message DynamicChannelOpenEvent {