OSDN Git Service

net_test_bluetooth: GATT test refactor
authorAjay Panicker <apanicke@google.com>
Mon, 7 Dec 2015 22:15:33 +0000 (14:15 -0800)
committerAjay Panicker <apanicke@google.com>
Wed, 16 Dec 2015 00:31:32 +0000 (00:31 +0000)
Properly integrating the GATT tests in net_test_bluetooth to utilize GUnit
correctly. Contains all the GATT tests and the base class the GATT tests use.
Also reorganized the files.

Bug: 25793348
Change-Id: I5a547a2528c20d6baa9b1fb6d0b956f718d736cc

service/hal/bluetooth_gatt_interface.cpp
service/hal/bluetooth_gatt_interface.h
test/suite/Android.mk
test/suite/adapter/adapter_unittest.cpp [moved from test/suite/adapter_unittest.cpp with 99% similarity]
test/suite/adapter/bluetooth_test.cpp [moved from test/suite/bluetooth_test.cpp with 99% similarity]
test/suite/adapter/bluetooth_test.h [moved from test/suite/bluetooth_test.h with 100% similarity]
test/suite/gatt/gatt_test.cpp [new file with mode: 0644]
test/suite/gatt/gatt_test.h [new file with mode: 0644]
test/suite/gatt/gatt_unittest.cpp [new file with mode: 0644]

index a039841..4ad6304 100644 (file)
@@ -22,6 +22,7 @@
 #include <base/observer_list.h>
 
 #include "service/hal/bluetooth_interface.h"
+#include "service/logging_helpers.h"
 
 using std::lock_guard;
 using std::mutex;
@@ -70,6 +71,26 @@ void RegisterClientCallback(int status, int client_if, bt_uuid_t* app_uuid) {
       RegisterClientCallback(g_interface, status, client_if, *app_uuid));
 }
 
+void ScanResultCallback(bt_bdaddr_t* bda, int rssi, uint8_t* adv_data) {
+  lock_guard<mutex> lock(g_instance_lock);
+  VERIFY_INTERFACE_OR_RETURN();
+  CHECK(bda);
+  CHECK(adv_data);
+
+  VLOG(2) << __func__ << " - BD_ADDR: " << BtAddrString(bda)
+          << " RSSI: " << rssi;
+  FOR_EACH_CLIENT_OBSERVER(
+    ScanResultCallback(g_interface, *bda, rssi, adv_data));
+}
+
+void ListenCallback(int status, int client_if) {
+  lock_guard<mutex> lock(g_instance_lock);
+  VLOG(2) << __func__ << " - status: " << status << " client_if: " << client_if;
+  VERIFY_INTERFACE_OR_RETURN();
+
+  FOR_EACH_CLIENT_OBSERVER(ListenCallback(g_interface, status, client_if));
+}
+
 void MultiAdvEnableCallback(int client_if, int status) {
   lock_guard<mutex> lock(g_instance_lock);
   VLOG(2) << __func__ << " - status: " << status << " client_if: " << client_if;
@@ -193,6 +214,16 @@ void ServiceStoppedCallback(int status, int server_if, int srvc_handle) {
       g_interface, status, server_if, srvc_handle));
 }
 
+void ServiceDeletedCallback(int status, int server_if, int srvc_handle) {
+  lock_guard<mutex> lock(g_instance_lock);
+  VLOG(2) << __func__ << " - status: " << status << " server_if: " << server_if
+          << " handle: " << srvc_handle;
+  VERIFY_INTERFACE_OR_RETURN();
+
+  FOR_EACH_SERVER_OBSERVER(ServiceDeletedCallback(
+      g_interface, status, server_if, srvc_handle));
+}
+
 void RequestReadCallback(int conn_id, int trans_id, bt_bdaddr_t* bda,
                          int attr_handle, int offset, bool is_long) {
   lock_guard<mutex> lock(g_instance_lock);
@@ -248,7 +279,7 @@ void IndicationSentCallback(int conn_id, int status) {
 // GATT client-role and GAP events.
 const btgatt_client_callbacks_t gatt_client_callbacks = {
     RegisterClientCallback,
-    nullptr,  // scan_result_cb
+    ScanResultCallback,
     nullptr,  // open_cb
     nullptr,  // close_cb
     nullptr,  // search_complete_cb
@@ -264,7 +295,7 @@ const btgatt_client_callbacks_t gatt_client_callbacks = {
     nullptr,  // write_descriptor_cb
     nullptr,  // execute_write_cb
     nullptr,  // read_remote_rssi_cb
-    nullptr,  // listen_cb
+    ListenCallback,
     nullptr,  // configure_mtu_cb
     nullptr,  // scan_filter_cfg_cb
     nullptr,  // scan_filter_param_cb
@@ -286,16 +317,16 @@ const btgatt_server_callbacks_t gatt_server_callbacks = {
     RegisterServerCallback,
     ConnectionCallback,
     ServiceAddedCallback,
-    nullptr,  // included_service_added_cb,
+    nullptr,  // included_service_added_cb
     CharacteristicAddedCallback,
     DescriptorAddedCallback,
     ServiceStartedCallback,
     ServiceStoppedCallback,
-    nullptr,  // service_deleted_cb,
+    ServiceDeletedCallback,
     RequestReadCallback,
     RequestWriteCallback,
     RequestExecWriteCallback,
-    nullptr,  // response_confirmation_cb,
+    nullptr,  // response_confirmation_cb
     IndicationSentCallback,
     nullptr,  // congestion_cb
     nullptr,  // mtu_changed_cb
@@ -440,6 +471,19 @@ void BluetoothGattInterface::ClientObserver::RegisterClientCallback(
     const bt_uuid_t& /* app_uuid */) {
   // Do nothing.
 }
+void BluetoothGattInterface::ClientObserver::ScanResultCallback(
+    BluetoothGattInterface* /* gatt_iface */,
+    const bt_bdaddr_t& /* bda */,
+    int /* rssi */,
+    uint8_t* /* adv_data */) {
+  // Do Nothing.
+}
+void BluetoothGattInterface::ClientObserver::ListenCallback(
+    BluetoothGattInterface* /* gatt_iface */,
+    int /* status */,
+    int /* client_if */) {
+  // Do nothing.
+}
 void BluetoothGattInterface::ClientObserver::MultiAdvEnableCallback(
     BluetoothGattInterface* /* gatt_iface */,
     int /* status */,
@@ -527,6 +571,14 @@ void BluetoothGattInterface::ServerObserver::ServiceStoppedCallback(
   // Do nothing.
 }
 
+void BluetoothGattInterface::ServerObserver::ServiceDeletedCallback(
+    BluetoothGattInterface* /* gatt_iface */,
+    int /* status */,
+    int /* server_if */,
+    int /* srvc_handle */) {
+  // Do nothing.
+}
+
 void BluetoothGattInterface::ServerObserver::RequestReadCallback(
     BluetoothGattInterface* /* gatt_iface */,
     int /* conn_id */,
index ce781e5..e8d7561 100644 (file)
@@ -52,6 +52,15 @@ class BluetoothGattInterface {
         int status, int client_if,
         const bt_uuid_t& app_uuid);
 
+    virtual void ScanResultCallback(
+        BluetoothGattInterface* gatt_iface,
+        const bt_bdaddr_t& bda, int rssi,
+        uint8_t* adv_data);
+
+    virtual void ListenCallback(
+        BluetoothGattInterface* gatt_iface,
+        int status, int client_if);
+
     virtual void MultiAdvEnableCallback(
         BluetoothGattInterface* gatt_iface,
         int client_if, int status);
@@ -117,6 +126,11 @@ class BluetoothGattInterface {
         int status, int server_if,
         int srvc_handle);
 
+    virtual void ServiceDeletedCallback(
+        BluetoothGattInterface* gatt_iface,
+        int status, int server_if,
+        int srvc_handle);
+
     virtual void RequestReadCallback(
         BluetoothGattInterface* gatt_iface,
         int conn_id, int trans_id,
index 1a522a7..e7de1de 100644 (file)
@@ -25,6 +25,7 @@ LOCAL_MODULE := net_test_bluetooth
 # with the interface using C++
 # TODO: Make the bluetoothtbd HAL a static library
 bluetoothHalSrc := \
+  ../../service/hal/bluetooth_gatt_interface.cpp \
   ../../service/hal/bluetooth_interface.cpp \
   ../../service/logging_helpers.cpp
 
@@ -32,8 +33,10 @@ LOCAL_C_INCLUDES += \
     $(LOCAL_PATH)/../../
 
 LOCAL_SRC_FILES := \
-    adapter_unittest.cpp \
-    bluetooth_test.cpp \
+    adapter/adapter_unittest.cpp \
+    adapter/bluetooth_test.cpp \
+    gatt/gatt_test.cpp \
+    gatt/gatt_unittest.cpp \
     $(bluetoothHalSrc)
 
 LOCAL_SHARED_LIBRARIES += \
similarity index 99%
rename from test/suite/adapter_unittest.cpp
rename to test/suite/adapter/adapter_unittest.cpp
index 50c901c..e957fb4 100644 (file)
@@ -16,7 +16,7 @@
  *
  ******************************************************************************/
 
-#include "bluetooth_test.h"
+#include "adapter/bluetooth_test.h"
 
 extern "C" {
 #include "btcore/include/property.h"
similarity index 99%
rename from test/suite/bluetooth_test.cpp
rename to test/suite/adapter/bluetooth_test.cpp
index 7cf9da7..72d1943 100644 (file)
@@ -16,7 +16,7 @@
  *
  ******************************************************************************/
 
-#include "bluetooth_test.h"
+#include "adapter/bluetooth_test.h"
 
 #include <mutex>
 
diff --git a/test/suite/gatt/gatt_test.cpp b/test/suite/gatt/gatt_test.cpp
new file mode 100644 (file)
index 0000000..1506247
--- /dev/null
@@ -0,0 +1,190 @@
+/******************************************************************************
+ *
+ *  Copyright (C) 2015 Google, Inc.
+ *
+ *  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.
+ *
+ ******************************************************************************/
+
+#include "adapter/bluetooth_test.h"
+#include "gatt/gatt_test.h"
+
+extern "C" {
+#include "btcore/include/bdaddr.h"
+}
+
+namespace bttest {
+
+void GattTest::SetUp() {
+  gatt_client_interface_ = nullptr;
+  gatt_server_interface_ = nullptr;
+
+  client_interface_id_ = 0;
+  server_interface_id_ = 0;
+  service_handle_ = 0;
+  characteristic_handle_ = 0;
+  descriptor_handle_ = 0;
+  status_ = 0;
+
+  BluetoothTest::SetUp();
+  ASSERT_EQ(bt_interface()->enable(), BT_STATUS_SUCCESS);
+  semaphore_wait(adapter_state_changed_callback_sem_);
+  EXPECT_TRUE(GetState() == BT_STATE_ON);
+
+  register_client_callback_sem_ = semaphore_new(0);
+  scan_result_callback_sem_ = semaphore_new(0);
+  listen_callback_sem_ = semaphore_new(0);
+
+  register_server_callback_sem_ = semaphore_new(0);
+  service_added_callback_sem_ = semaphore_new(0);
+  characteristic_added_callback_sem_ = semaphore_new(0);
+  descriptor_added_callback_sem_ = semaphore_new(0);
+  service_started_callback_sem_ = semaphore_new(0);
+  service_stopped_callback_sem_ = semaphore_new(0);
+  service_deleted_callback_sem_ = semaphore_new(0);
+
+  bluetooth::hal::BluetoothGattInterface::Initialize();
+  ASSERT_TRUE(bluetooth::hal::BluetoothGattInterface::IsInitialized());
+  auto gatt_interface = bluetooth::hal::BluetoothGattInterface::Get();
+  gatt_interface->AddClientObserver(this);
+  gatt_interface->AddServerObserver(this);
+
+  gatt_client_interface_ = gatt_interface->GetClientHALInterface();
+  gatt_server_interface_ = gatt_interface->GetServerHALInterface();
+
+  ASSERT_NE(nullptr, gatt_client_interface_);
+  ASSERT_NE(nullptr, gatt_server_interface_);
+}
+
+void GattTest::TearDown() {
+  gatt_client_interface_ = nullptr;
+  gatt_server_interface_ = nullptr;
+
+  semaphore_free(register_client_callback_sem_);
+  semaphore_free(scan_result_callback_sem_);
+  semaphore_free(listen_callback_sem_);
+
+  semaphore_free(register_server_callback_sem_);
+  semaphore_free(service_added_callback_sem_);
+  semaphore_free(characteristic_added_callback_sem_);
+  semaphore_free(descriptor_added_callback_sem_);
+  semaphore_free(service_started_callback_sem_);
+  semaphore_free(service_stopped_callback_sem_);
+  semaphore_free(service_deleted_callback_sem_);
+
+  bluetooth::hal::BluetoothGattInterface::CleanUp();
+
+  ASSERT_EQ(bt_interface()->disable(), BT_STATUS_SUCCESS);
+  semaphore_wait(adapter_state_changed_callback_sem_);
+  BluetoothTest::TearDown();
+}
+
+const btgatt_client_interface_t* GattTest::gatt_client_interface() {
+  return gatt_client_interface_;
+}
+
+const btgatt_server_interface_t* GattTest::gatt_server_interface() {
+  return gatt_server_interface_;
+}
+
+void GattTest::RegisterClientCallback(
+    bluetooth::hal::BluetoothGattInterface* /* unused */,
+    int status, int clientIf, const bt_uuid_t& app_uuid) {
+  status_ = status;
+  client_interface_id_ = clientIf;
+  semaphore_post(register_client_callback_sem_);
+}
+
+void GattTest::ScanResultCallback(
+    bluetooth::hal::BluetoothGattInterface* /* unused */,
+    const bt_bdaddr_t& bda, int rssi, uint8_t* adv_data) {
+  semaphore_post(scan_result_callback_sem_);
+}
+
+void GattTest::ListenCallback(
+    bluetooth::hal::BluetoothGattInterface* /* unused */,
+    int status, int client_if) {
+  status_ = status;
+  client_interface_id_ = client_if;
+  semaphore_post(listen_callback_sem_);
+}
+
+// GATT server callbacks
+void GattTest::RegisterServerCallback(
+    bluetooth::hal::BluetoothGattInterface* /* unused */,
+    int status, int server_if, const bt_uuid_t& uuid) {
+  status_ = status;
+  server_interface_id_ = server_if;
+  semaphore_post(register_server_callback_sem_);
+}
+
+void GattTest::ServiceAddedCallback(
+    bluetooth::hal::BluetoothGattInterface* /* unused */,
+    int status, int server_if, const btgatt_srvc_id_t& srvc_id,
+    int srvc_handle) {
+  status_ = status;
+  server_interface_id_ = server_if;
+  service_handle_ = srvc_handle;
+  semaphore_post(service_added_callback_sem_);
+}
+
+void GattTest::CharacteristicAddedCallback(
+    bluetooth::hal::BluetoothGattInterface* /* unused */,
+    int status, int server_if, const bt_uuid_t& char_id,
+    int srvc_handle, int char_handle) {
+  status_ = status;
+  server_interface_id_ = server_if;
+  service_handle_ = srvc_handle;
+  characteristic_handle_ = char_handle;
+  semaphore_post(characteristic_added_callback_sem_);
+}
+
+void GattTest::DescriptorAddedCallback(
+    bluetooth::hal::BluetoothGattInterface* /* unused */,
+    int status, int server_if, const bt_uuid_t& descr_id,
+    int srvc_handle, int descr_handle) {
+  status_ = status;
+  server_interface_id_ = server_if;
+  service_handle_ = srvc_handle;
+  descriptor_handle_ = descr_handle;
+  semaphore_post(descriptor_added_callback_sem_);
+}
+
+void GattTest::ServiceStartedCallback(
+    bluetooth::hal::BluetoothGattInterface* /* unused */,
+    int status, int server_if, int srvc_handle) {
+  status_ = status;
+  server_interface_id_ = server_if;
+  service_handle_ = srvc_handle;
+  semaphore_post(service_started_callback_sem_);
+}
+
+void GattTest::ServiceStoppedCallback(
+    bluetooth::hal::BluetoothGattInterface* /* unused */,
+    int status, int server_if, int srvc_handle) {
+  status_ = status;
+  server_interface_id_ = server_if;
+  service_handle_ = srvc_handle;
+  semaphore_post(service_stopped_callback_sem_);
+}
+
+void GattTest::ServiceDeletedCallback(
+    bluetooth::hal::BluetoothGattInterface* /* unused */,
+    int status, int server_if, int srvc_handle) {
+  status_ = status;
+  server_interface_id_ = server_if;
+  service_handle_ = srvc_handle;
+  semaphore_post(service_deleted_callback_sem_);
+}
+
+}  // bttest
diff --git a/test/suite/gatt/gatt_test.h b/test/suite/gatt/gatt_test.h
new file mode 100644 (file)
index 0000000..f3525fe
--- /dev/null
@@ -0,0 +1,137 @@
+/******************************************************************************
+ *
+ *  Copyright (C) 2015 Google, Inc.
+ *
+ *  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.
+ *
+ ******************************************************************************/
+
+#include "adapter/bluetooth_test.h"
+#include "service/hal/bluetooth_gatt_interface.h"
+
+namespace bttest {
+
+// This class represents the Bluetooth GATT testing framework and provides
+// helpers and callbacks for GUnit to use for testing gatt.
+class GattTest : public BluetoothTest,
+                 public bluetooth::hal::BluetoothGattInterface::ClientObserver,
+                 public bluetooth::hal::BluetoothGattInterface::ServerObserver {
+ protected:
+  GattTest() = default;
+  virtual ~GattTest() = default;
+
+  // Gets the gatt_client_interface
+  const btgatt_client_interface_t* gatt_client_interface();
+
+  // Gets the gatt_server_interface
+  const btgatt_server_interface_t* gatt_server_interface();
+
+  // Getters for variables that track GATT-related state
+  int client_interface_id() const { return client_interface_id_; }
+  int server_interface_id() const { return server_interface_id_; }
+  int service_handle() const { return service_handle_; }
+  int characteristic_handle() const { return characteristic_handle_; }
+  int descriptor_handle() const { return descriptor_handle_; }
+  int status() const { return status_; }
+
+  // SetUp initializes the Bluetooth interfaces and the GATT Interface as well
+  // as registers the callbacks and initializes the semaphores before every test
+  virtual void SetUp();
+
+  // TearDown cleans up the Bluetooth and GATT interfaces and destroys the
+  // callback semaphores at the end of every test
+  virtual void TearDown();
+
+  // bluetooth::hal::BluetoothGattInterface::ClientObserver overrides
+  void RegisterClientCallback(
+      bluetooth::hal::BluetoothGattInterface* /* unused */,
+      int status, int clientIf, const bt_uuid_t& app_uuid) override;
+  void ScanResultCallback(
+      bluetooth::hal::BluetoothGattInterface* /* unused */,
+      const bt_bdaddr_t& bda, int rssi, uint8_t* adv_data) override;
+  void ListenCallback(
+      bluetooth::hal::BluetoothGattInterface* /* unused */,
+      int status, int client_if) override;
+
+  // bluetooth::hal::BluetoothGattInterface::ServerObserver overrides
+  void RegisterServerCallback(
+      bluetooth::hal::BluetoothGattInterface* /* unused */,
+      int status, int server_if, const bt_uuid_t& uuid) override;
+  void ServiceAddedCallback(
+      bluetooth::hal::BluetoothGattInterface* /* unused */,
+      int status, int server_if, const btgatt_srvc_id_t& srvc_id,
+      int srvc_handle) override;
+  void CharacteristicAddedCallback(
+      bluetooth::hal::BluetoothGattInterface* /* unused */,
+      int status, int server_if, const bt_uuid_t& char_id,
+      int srvc_handle, int char_handle) override;
+  void DescriptorAddedCallback(
+      bluetooth::hal::BluetoothGattInterface* /* unused */,
+      int status, int server_if, const bt_uuid_t& descr_id,
+      int srvc_handle, int descr_handle) override;
+  void ServiceStartedCallback(
+      bluetooth::hal::BluetoothGattInterface* /* unused */,
+      int status, int server_if, int srvc_handle) override;
+  void ServiceStoppedCallback(
+      bluetooth::hal::BluetoothGattInterface* /* unused */,
+      int status, int server_if, int srvc_handle) override;
+  void ServiceDeletedCallback(
+      bluetooth::hal::BluetoothGattInterface* /* unused */,
+      int status, int server_if, int srvc_handle) override;
+
+  // Semaphores used to wait for specific callback execution. Each callback
+  // has its own semaphore associated with it
+  semaphore_t* register_client_callback_sem_;
+  semaphore_t* scan_result_callback_sem_;
+  semaphore_t* listen_callback_sem_;
+
+  semaphore_t* register_server_callback_sem_;
+  semaphore_t* service_added_callback_sem_;
+  semaphore_t* characteristic_added_callback_sem_;
+  semaphore_t* descriptor_added_callback_sem_;
+  semaphore_t* service_started_callback_sem_;
+  semaphore_t* service_stopped_callback_sem_;
+  semaphore_t* service_deleted_callback_sem_;
+
+ private:
+  // The gatt_client_interface that all the tests use to interact with the HAL
+  const btgatt_client_interface_t* gatt_client_interface_;
+
+  // The gatt_server_interface that all the tests use to interact with the HAL
+  const btgatt_server_interface_t* gatt_server_interface_;
+
+  // No mutex needed for these as the semaphores should ensure
+  // synchronous access
+
+  // An ID that is used as a handle for each gatt client.
+  int client_interface_id_;
+
+  // An ID that is used as a handle for each gatt server.
+  int server_interface_id_;
+
+  // A handle to the last used service.
+  int service_handle_;
+
+  // A handle to the last characteristic added.
+  int characteristic_handle_;
+
+  // A handle to the last descriptor added.
+  int descriptor_handle_;
+
+  // The status of the last callback. Is BT_STATUS_SUCCESS if no issues.
+  int status_;
+
+  DISALLOW_COPY_AND_ASSIGN(GattTest);
+};
+
+}  // bttest
diff --git a/test/suite/gatt/gatt_unittest.cpp b/test/suite/gatt/gatt_unittest.cpp
new file mode 100644 (file)
index 0000000..e731634
--- /dev/null
@@ -0,0 +1,163 @@
+/******************************************************************************
+ *
+ *  Copyright (C) 2015 Google, Inc.
+ *
+ *  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.
+ *
+ ******************************************************************************/
+
+#include <stdlib.h>
+#include <time.h>
+#include <unistd.h>
+
+#include "gatt/gatt_test.h"
+
+#define DEFAULT_RANDOM_SEED 42
+
+namespace {
+
+static void create_random_uuid(bt_uuid_t *uuid, int seed) {
+  srand(seed < 0 ? time(NULL) : seed);
+  for (int i = 0; i < 16; ++i) {
+    uuid->uu[i] = (uint8_t) (rand() % 256);
+  }
+}
+
+}  // namespace
+
+namespace bttest {
+
+TEST_F(GattTest, GattClientRegister) {
+  // Registers gatt client.
+  bt_uuid_t gatt_client_uuid;
+  create_random_uuid(&gatt_client_uuid, DEFAULT_RANDOM_SEED);
+  gatt_client_interface()->register_client(&gatt_client_uuid);
+  semaphore_wait(register_client_callback_sem_);
+  EXPECT_TRUE(status() == BT_STATUS_SUCCESS)
+    << "Error registering GATT client app callback.";
+
+  // Unregisters gatt client. No callback is expected.
+  gatt_client_interface()->unregister_client(client_interface_id());
+}
+
+TEST_F(GattTest, GattClientScanRemoteDevice) {
+  // Starts BLE scan. NB: This test assumes there is a BLE beacon advertising nearby.
+  gatt_client_interface()->scan(true);
+  semaphore_wait(scan_result_callback_sem_);
+
+  // Ends BLE scan. No callback is expected.
+  gatt_client_interface()->scan(false);
+}
+
+TEST_F(GattTest, GattClientAdvertise) {
+  // Registers a new client app.
+  bt_uuid_t gatt_client_uuid;
+  create_random_uuid(&gatt_client_uuid, DEFAULT_RANDOM_SEED);
+  gatt_client_interface()->register_client(&gatt_client_uuid);
+  semaphore_wait(register_client_callback_sem_);
+  EXPECT_TRUE(status() == BT_STATUS_SUCCESS)
+    << "Error registering GATT client app callback.";
+
+  // Starts advertising.
+  gatt_client_interface()->listen(client_interface_id(), true);
+  semaphore_wait(listen_callback_sem_);
+  EXPECT_TRUE(status() == BT_STATUS_SUCCESS)
+    << "Error starting BLE advertisement.";
+
+  // Stops advertising.
+  gatt_client_interface()->listen(client_interface_id(), false);
+  semaphore_wait(listen_callback_sem_);
+  EXPECT_TRUE(status() == BT_STATUS_SUCCESS)
+    << "Error stopping BLE advertisement.";
+
+  // Unregisters gatt server. No callback is expected.
+  gatt_client_interface()->unregister_client(client_interface_id());
+}
+
+TEST_F(GattTest, GattServerRegister) {
+  // Registers gatt server.
+  bt_uuid_t gatt_server_uuid;
+  create_random_uuid(&gatt_server_uuid, DEFAULT_RANDOM_SEED);
+  gatt_server_interface()->register_server(&gatt_server_uuid);
+  semaphore_wait(register_server_callback_sem_);
+  EXPECT_TRUE(status() == BT_STATUS_SUCCESS)
+    << "Error registering GATT server app callback.";
+
+  // Unregisters gatt server. No callback is expected.
+  gatt_server_interface()->unregister_server(server_interface_id());
+}
+
+TEST_F(GattTest, GattServerBuild) {
+  // Registers gatt server.
+  bt_uuid_t gatt_server_uuid;
+  create_random_uuid(&gatt_server_uuid, DEFAULT_RANDOM_SEED);
+  gatt_server_interface()->register_server(&gatt_server_uuid);
+  semaphore_wait(register_server_callback_sem_);
+  EXPECT_TRUE(status() == BT_STATUS_SUCCESS)
+    << "Error registering GATT server app callback.";
+
+  // Service UUID.
+  btgatt_srvc_id_t srvc_id;
+  srvc_id.id.inst_id = 0;   // there is only one instance of this service.
+  srvc_id.is_primary = 1;   // this service is primary.
+  create_random_uuid(&srvc_id.id.uuid, -1);
+
+  // Characteristics UUID.
+  bt_uuid_t char_uuid;
+  create_random_uuid(&char_uuid, -1);
+
+  // Descriptor UUID.
+  bt_uuid_t desc_uuid;
+  create_random_uuid(&desc_uuid, -1);
+
+  // Adds service.
+  int server_if = server_interface_id();
+  gatt_server_interface()->add_service(server_if, &srvc_id, 4 /* # handles */);
+  semaphore_wait(service_added_callback_sem_);
+  EXPECT_TRUE(status() == BT_STATUS_SUCCESS) << "Error adding service.";
+
+  // Adds characteristics.
+  int srvc_handle = service_handle();
+  gatt_server_interface()->add_characteristic(server_if, srvc_handle,
+      &char_uuid, 0x10 /* notification */, 0x01 /* read only */);
+  semaphore_wait(characteristic_added_callback_sem_);
+  EXPECT_TRUE(status() == BT_STATUS_SUCCESS)
+      << "Error adding characteristics.";
+
+  // Adds descriptor.
+  gatt_server_interface()->add_descriptor(server_if, srvc_handle,
+                                          &desc_uuid, 0x01);
+  semaphore_wait(descriptor_added_callback_sem_);
+  EXPECT_TRUE(status() == BT_STATUS_SUCCESS)
+      << "Error adding descriptor.";
+
+  // Starts server.
+  gatt_server_interface()->start_service(server_if, srvc_handle, 2 /*BREDR/LE*/);
+  semaphore_wait(service_started_callback_sem_);
+  EXPECT_TRUE(status() == BT_STATUS_SUCCESS) << "Error starting server.";
+
+  // Stops server.
+  gatt_server_interface()->stop_service(server_if, srvc_handle);
+  semaphore_wait(service_stopped_callback_sem_);
+  EXPECT_TRUE(status() == BT_STATUS_SUCCESS) << "Error stopping server.";
+
+  // Deletes service.
+  gatt_server_interface()->delete_service(server_if, srvc_handle);
+  semaphore_wait(service_deleted_callback_sem_);
+  EXPECT_TRUE(status() == BT_STATUS_SUCCESS) << "Error deleting service.";
+
+  // Unregisters gatt server. No callback is expected.
+  gatt_server_interface()->unregister_server(server_if);
+}
+
+}  // bttest