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

Commit e642e500 authored by David Duarte's avatar David Duarte
Browse files

BumbleBluetoothTests: Introduce a PandoraDevice junit Rule

This manages the lifecycle of the PandoraDevice to factor
some boilerplate used in each test.

This also has the advantage of not running the after function if
the before one threw an Exception.

Bug: 266884665
Test: atest BumbleBluetoothTests
Change-Id: I69d0d9ed7482083ee1008ecb90fbee548e3774b6
parent 87db92d3
Loading
Loading
Loading
Loading
+3 −30
Original line number Diff line number Diff line
@@ -16,7 +16,6 @@

package android.bluetooth;

import static android.bluetooth.Utils.factoryResetAndCreateNewChannel;
import static com.google.common.truth.Truth.assertThat;

import android.bluetooth.le.AdvertiseData;
@@ -31,39 +30,29 @@ import androidx.test.core.app.ApplicationProvider;
import androidx.test.platform.app.InstrumentationRegistry;
import androidx.test.runner.AndroidJUnit4;

import com.google.protobuf.Empty;

import io.grpc.Context.CancellableContext;
import io.grpc.Deadline;
import io.grpc.ManagedChannel;
import io.grpc.stub.StreamObserver;

import org.junit.After;
import org.junit.Before;
import org.junit.BeforeClass;
import org.junit.Rule;
import org.junit.Test;
import org.junit.runner.RunWith;

import java.util.concurrent.CompletableFuture;
import java.util.concurrent.TimeUnit;

import pandora.HostGrpc;
import pandora.HostProto.ScanRequest;
import pandora.HostProto.ScanningResponse;

/** Test cases for {@link AdvertiseManager}. */
@RunWith(AndroidJUnit4.class)
public class LeAdvertisingTest {

    private static final String TAG = "LeAdvertisingTest";

    private static final int TIMEOUT_ADVERTISING_MS = 1000;

    private static ManagedChannel mChannel;

    private static HostGrpc.HostBlockingStub mHostBlockingStub;

    private static HostGrpc.HostStub mHostStub;
    @Rule public final PandoraDevice mBumble = new PandoraDevice();

    @BeforeClass
    public static void setUpClass() throws Exception {
@@ -72,22 +61,6 @@ public class LeAdvertisingTest {
                .adoptShellPermissionIdentity();
    }

    @Before
    public void setUp() throws Exception {
        // Cleanup previous channels and create a new channel for all successive grpc calls
        mChannel = factoryResetAndCreateNewChannel();

        mHostBlockingStub = HostGrpc.newBlockingStub(mChannel);
        mHostStub = HostGrpc.newStub(mChannel);
        mHostBlockingStub.withWaitForReady().readLocalAddress(Empty.getDefaultInstance());
    }

    @After
    public void tearDown() throws Exception {
        // terminate the channel
        mChannel.shutdown().awaitTermination(1, TimeUnit.SECONDS);
    }

    @Test
    public void advertisingSet() throws Exception {
        ScanningResponse response =
@@ -202,7 +175,7 @@ public class LeAdvertisingTest {

        Deadline initialDeadline = Deadline.after(TIMEOUT_ADVERTISING_MS, TimeUnit.MILLISECONDS);
        withCancellation.run(
                () -> mHostStub.withDeadline(initialDeadline).scan(request, responseObserver));
                () -> mBumble.host().withDeadline(initialDeadline).scan(request, responseObserver));

        return future.whenComplete(
                (input, exception) -> {
+3 −29
Original line number Diff line number Diff line
@@ -16,7 +16,6 @@

package android.bluetooth;

import static android.bluetooth.Utils.factoryResetAndCreateNewChannel;
import static com.google.common.truth.Truth.assertThat;

import android.bluetooth.le.BluetoothLeScanner;
@@ -31,15 +30,11 @@ import androidx.test.core.app.ApplicationProvider;
import androidx.test.platform.app.InstrumentationRegistry;
import androidx.test.runner.AndroidJUnit4;

import com.google.protobuf.Empty;

import io.grpc.ManagedChannel;
import io.grpc.stub.StreamObserver;

import org.junit.After;
import org.junit.AfterClass;
import org.junit.Before;
import org.junit.BeforeClass;
import org.junit.Rule;
import org.junit.Test;
import org.junit.runner.RunWith;

@@ -48,7 +43,6 @@ import java.util.List;
import java.util.concurrent.CompletableFuture;
import java.util.concurrent.TimeUnit;

import pandora.HostGrpc;
import pandora.HostProto;
import pandora.HostProto.AdvertiseRequest;
import pandora.HostProto.AdvertiseResponse;
@@ -58,11 +52,7 @@ public class LeScanningTest {
    private static final String TAG = "LeScanningTest";
    private static final int TIMEOUT_SCANNING_MS = 2000;

    private static ManagedChannel mChannel;

    private static HostGrpc.HostBlockingStub mHostBlockingStub;

    private static HostGrpc.HostStub mHostStub;
    @Rule public final PandoraDevice mBumble = new PandoraDevice();

    private final String TEST_UUID_STRING = "00001805-0000-1000-8000-00805f9b34fb";

@@ -73,22 +63,6 @@ public class LeScanningTest {
                .adoptShellPermissionIdentity();
    }

    @Before
    public void setUp() throws Exception {
        // Cleanup previous channels and create a new channel for all successive grpc calls
        mChannel = factoryResetAndCreateNewChannel();

        mHostBlockingStub = HostGrpc.newBlockingStub(mChannel);
        mHostStub = HostGrpc.newStub(mChannel);
        mHostBlockingStub.withWaitForReady().readLocalAddress(Empty.getDefaultInstance());
    }

    @After
    public void tearDown() throws Exception {
        // terminate the channel
        mChannel.shutdown().awaitTermination(1, TimeUnit.SECONDS);
    }

    @AfterClass
    public static void tearDownClass() throws Exception {
        InstrumentationRegistry.getInstrumentation()
@@ -190,6 +164,6 @@ public class LeScanningTest {
                    }
                };

        mHostStub.advertise(request, responseObserver);
        mBumble.host().advertise(request, responseObserver);
    }
}
+89 −0
Original line number Diff line number Diff line
/*
 * Copyright (C) 2023 The Android Open Source Project
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package android.bluetooth;

import android.util.Log;

import com.google.protobuf.Empty;

import io.grpc.ManagedChannel;
import io.grpc.okhttp.OkHttpChannelBuilder;

import org.junit.rules.ExternalResource;

import java.util.concurrent.TimeUnit;

import pandora.HostGrpc;

public final class PandoraDevice extends ExternalResource {
    private static final String TAG = PandoraDevice.class.getSimpleName();

    private final String mAddress;
    private final int mPort;

    private ManagedChannel mChannel;

    public PandoraDevice(String address, int port) {
        mAddress = address;
        mPort = port;
    }

    public PandoraDevice() {
        this("localhost", 7999);
    }

    @Override
    protected void before() {
        Log.i(TAG, "factoryReset");
        // FactoryReset is killing the server and restarting all channels created before the server
        // restarted that cannot be reused
        ManagedChannel channel =
                OkHttpChannelBuilder.forAddress(mAddress, mPort).usePlaintext().build();

        HostGrpc.HostBlockingStub stub = HostGrpc.newBlockingStub(channel);
        stub.factoryReset(Empty.getDefaultInstance());

        try {
            // terminate the channel
            channel.shutdown().awaitTermination(1, TimeUnit.SECONDS);
        } catch (InterruptedException e) {
            throw new RuntimeException(e);
        }

        mChannel = OkHttpChannelBuilder.forAddress(mAddress, mPort).usePlaintext().build();
        stub = HostGrpc.newBlockingStub(mChannel);

        stub.withWaitForReady().readLocalAddress(Empty.getDefaultInstance());
    }

    @Override
    protected void after() {
        Log.i(TAG, "shutdown");
        try {
            // terminate the channel
            mChannel.shutdown().awaitTermination(1, TimeUnit.SECONDS);
            mChannel = null;
        } catch (InterruptedException e) {
            throw new RuntimeException(e);
        }
    }

    /** Get Pandora Host service */
    public HostGrpc.HostStub host() {
        return HostGrpc.newStub(mChannel);
    }
}
+0 −24
Original line number Diff line number Diff line
@@ -17,14 +17,6 @@
package android.bluetooth;

import com.google.protobuf.ByteString;
import com.google.protobuf.Empty;

import io.grpc.ManagedChannel;
import io.grpc.okhttp.OkHttpChannelBuilder;

import java.util.concurrent.TimeUnit;

import pandora.HostGrpc;

public final class Utils {
    public static String addressStringFromByteString(ByteString bs) {
@@ -37,20 +29,4 @@ public final class Utils {
        }
        return refAddrBuilder.toString();
    }

    public static ManagedChannel factoryResetAndCreateNewChannel() throws InterruptedException {
        // FactoryReset is killing the server and restarting all channels created before the server
        // restarted that cannot be reused
        ManagedChannel channel =
                OkHttpChannelBuilder.forAddress("localhost", 7999).usePlaintext().build();

        HostGrpc.HostBlockingStub stub = HostGrpc.newBlockingStub(channel);
        stub.factoryReset(Empty.getDefaultInstance());

        // terminate the channel
        channel.shutdown().awaitTermination(1, TimeUnit.SECONDS);

        // return new channel for future use
        return OkHttpChannelBuilder.forAddress("localhost", 7999).usePlaintext().build();
    }
}