Add bluetooth plugin
authorHyunjee Kim <hj0426.kim@samsung.com>
Thu, 20 Jun 2019 05:57:31 +0000 (14:57 +0900)
committerYoungjae Shin <yj99.shin@samsung.com>
Thu, 19 Mar 2020 04:30:11 +0000 (13:30 +0900)
14 files changed:
CMakeLists.txt
bluetooth/BtAction.cpp [new file with mode: 0644]
bluetooth/BtAction.h [new file with mode: 0644]
bluetooth/BtActionAudioConnect.cpp [new file with mode: 0644]
bluetooth/BtActionAudioConnect.h [new file with mode: 0644]
bluetooth/BtActionPower.cpp [new file with mode: 0644]
bluetooth/BtActionPower.h [new file with mode: 0644]
bluetooth/BtFactory.cpp [new file with mode: 0644]
bluetooth/BtFactory.h [new file with mode: 0644]
bluetooth/BtPlugin.cpp [new file with mode: 0644]
bluetooth/CMakeLists.txt [new file with mode: 0644]
packaging/modes-plugins.spec
unittests/CMakeLists.txt
unittests/mdsp_bt_main.cpp [new file with mode: 0644]

index 7c5b362..706e695 100644 (file)
@@ -17,4 +17,5 @@ ENDIF(NOT DEFINED MODES_PLUGIN_DEFAULT_DIR)
 
 ADD_SUBDIRECTORY(wifi)
 ADD_SUBDIRECTORY(vconf)
+ADD_SUBDIRECTORY(bluetooth)
 ADD_SUBDIRECTORY(unittests)
diff --git a/bluetooth/BtAction.cpp b/bluetooth/BtAction.cpp
new file mode 100644 (file)
index 0000000..df2ecd1
--- /dev/null
@@ -0,0 +1,65 @@
+/*
+ * Copyright (c) 2019 Samsung Electronics Co., Ltd All Rights Reserved
+ *
+ * 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 "BtAction.h"
+#include <modes_errors.h>
+
+MODES_NAMESPACE_USE;
+
+BtAction::BtAction()
+{
+       int btRet = bt_initialize();
+       if (BT_ERROR_NONE != btRet) {
+               ERR("bt_initialize() Fail(%d)", btRet);
+       }
+
+       btAdapterStatus = getAdapterStatus();
+}
+
+BtAction::~BtAction()
+{
+       bt_deinitialize();
+}
+
+bt_adapter_state_e BtAction::getAdapterStatus()
+{
+       bt_adapter_state_e state;
+       int btRet = bt_adapter_get_state(&state);
+       if (BT_ERROR_NONE != btRet) {
+               ERR("bt_adapter_get_state() Fail(%d)", btRet);
+       }
+
+       return state;
+}
+
+int BtAction::set(bool val)
+{
+       return MODES_ERROR_NOT_SUPPORTED;
+}
+
+int BtAction::set(const std::string &val)
+{
+       return MODES_ERROR_NOT_SUPPORTED;
+}
+
+void BtAction::setName(std::string name)
+{
+       this->name = name;
+}
+
+std::string BtAction::getName()
+{
+       return name;
+}
diff --git a/bluetooth/BtAction.h b/bluetooth/BtAction.h
new file mode 100644 (file)
index 0000000..42a4a20
--- /dev/null
@@ -0,0 +1,43 @@
+/*
+ * Copyright (c) 2019 Samsung Electronics Co., Ltd All Rights Reserved
+ *
+ * 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.
+ */
+#pragma once
+
+#include <string>
+#include <bluetooth.h>
+#include "plugin-log.h"
+#include "plugin-def.h"
+
+MODES_NAMESPACE_BEGIN
+
+class BtAction {
+public:
+       BtAction();
+       virtual ~BtAction();
+
+       bt_adapter_state_e getAdapterStatus();
+       std::string getName();
+       virtual int set(bool val);
+       virtual int set(const std::string &val);
+
+protected:
+       void setName(std::string name);
+       bt_adapter_state_e btAdapterStatus;
+private:
+       std::string name;
+};
+
+MODES_NAMESPACE_END
+
diff --git a/bluetooth/BtActionAudioConnect.cpp b/bluetooth/BtActionAudioConnect.cpp
new file mode 100644 (file)
index 0000000..a17015b
--- /dev/null
@@ -0,0 +1,96 @@
+/*
+ * Copyright (c) 2019 Samsung Electronics Co., Ltd All Rights Reserved
+ *
+ * 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 "BtActionAudioConnect.h"
+
+#include <algorithm>
+#include <modes_errors.h>
+#include "plugin-log.h"
+
+MODES_NAMESPACE_USE;
+
+void BtActionAudioConnect::connection_state_changed_cb(int result, bool connected, const char *remote_address, bt_audio_profile_type_e type, void *user_data)
+{
+       INFO("remote_address: %s", remote_address);
+
+       if(BT_ERROR_NONE != result) {
+               ERR("Connection_state_changed_cb() Fail(%d)", result);
+       }
+}
+
+BtActionAudioConnect::BtActionAudioConnect()
+{
+       setName("audioConnect");
+
+       bt_audio_initialize();
+       int btRet = bt_audio_set_connection_state_changed_cb(connection_state_changed_cb, this);
+       if (BT_ERROR_NONE != btRet) {
+               ERR("bt_device_set_bond_created_cb failed[%d]", btRet);
+       }
+}
+
+int BtActionAudioConnect::set(const std::string &val)
+{
+       int btRet;
+       bt_device_info_s *deviceInfo = getBondedDeviceInfo(val.c_str());
+       if(!deviceInfo) {
+               btRet = bt_device_create_bond(val.c_str());
+               DBG("bt_device_create_bond() %d[%s]", btRet, val.c_str());
+               return MODES_ERROR_NONE;
+       }
+
+       if(deviceInfo->is_connected) {
+               DBG("Already connected[%s]", val.c_str());
+               return MODES_ERROR_NONE;
+       } else {
+               btRet = bt_audio_connect(val.c_str(), BT_AUDIO_PROFILE_TYPE_ALL);
+               DBG("bt_audio_connect() %d[%s]", btRet, val.c_str());
+               return MODES_ERROR_NONE;
+       }
+}
+
+bt_device_info_s *BtActionAudioConnect::getBondedDeviceInfo(const std::string &val)
+{
+       bt_device_info_s *deviceInfo = NULL;
+
+       int btRet = bt_adapter_get_bonded_device_info(val.c_str(), &deviceInfo);
+       if (btRet) {
+               ERR("bt_adapter_get_bonded_device_info() %d", btRet);
+               return NULL;
+       }
+
+       if (deviceInfo) {
+               INFO("address: %s", deviceInfo->remote_address);
+               INFO("name: %s", deviceInfo->remote_name);
+               INFO("is_bonded: %d", deviceInfo->is_bonded);
+               INFO("is_connected: %d", deviceInfo->is_connected);
+               INFO("is_authorized: %d", deviceInfo->is_authorized);
+               INFO("service_count: %d", deviceInfo->service_count);
+
+               char *str = NULL;
+               if (deviceInfo->service_uuid == NULL) {
+                       INFO("No uuids");
+               } else {
+                       for (int i = 0; i < deviceInfo->service_count; i++) {
+                               bt_get_uuid_name(deviceInfo->service_uuid[i], &str);
+                               INFO("[%d / %d] %s (%s)", i, deviceInfo->service_count,
+                                               str ? str : "Unknown", deviceInfo->service_uuid[i]);
+                               str = NULL;
+                       }
+               }
+       }
+
+       return deviceInfo;
+}
diff --git a/bluetooth/BtActionAudioConnect.h b/bluetooth/BtActionAudioConnect.h
new file mode 100644 (file)
index 0000000..85d6c84
--- /dev/null
@@ -0,0 +1,33 @@
+/*
+ * Copyright (c) 2019 Samsung Electronics Co., Ltd All Rights Reserved
+ *
+ * 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.
+ */
+#pragma once
+
+#include <string>
+#include "BtAction.h"
+
+MODES_NAMESPACE_BEGIN
+
+class BtActionAudioConnect : public BtAction {
+public:
+       BtActionAudioConnect();
+
+       int set(const std::string &val) override;
+private:
+       bt_device_info_s *getBondedDeviceInfo(const std::string &val);
+       static void connection_state_changed_cb(int result, bool connected, const char *remote_address, bt_audio_profile_type_e type, void *user_data);
+};
+
+MODES_NAMESPACE_END
diff --git a/bluetooth/BtActionPower.cpp b/bluetooth/BtActionPower.cpp
new file mode 100644 (file)
index 0000000..8a1318a
--- /dev/null
@@ -0,0 +1,48 @@
+/*
+ * Copyright (c) 2019 Samsung Electronics Co., Ltd All Rights Reserved
+ *
+ * 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 "BtActionPower.h"
+
+#include <algorithm>
+#include <modes_errors.h>
+#include "plugin-log.h"
+#include <bluetooth_internal.h>
+
+MODES_NAMESPACE_USE;
+
+BtActionPower::BtActionPower()
+{
+       setName("power");
+}
+
+int BtActionPower::set(bool val)
+{
+       if (val) {
+               int btRet = bt_adapter_enable();
+               if (BT_ERROR_NONE != btRet) {
+                       ERR("bt_adapter_enable() Fail(%d)", btRet);
+                       return MODES_ERROR_SYSTEM;
+               }
+       } else {
+               int btRet = bt_adapter_disable();
+               if (BT_ERROR_NONE != btRet) {
+                       ERR("bt_adapter_disable() Fail(%d)", btRet);
+                       return MODES_ERROR_SYSTEM;
+               }
+       }
+
+       INFO("Bluetooth power [%s]", val ? "On" : "Off");
+       return MODES_ERROR_NONE;
+}
diff --git a/bluetooth/BtActionPower.h b/bluetooth/BtActionPower.h
new file mode 100644 (file)
index 0000000..a412e44
--- /dev/null
@@ -0,0 +1,31 @@
+/*
+ * Copyright (c) 2019 Samsung Electronics Co., Ltd All Rights Reserved
+ *
+ * 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.
+ */
+#pragma once
+
+#include <string>
+#include "BtAction.h"
+
+MODES_NAMESPACE_BEGIN
+
+class BtActionPower : public BtAction {
+public:
+       BtActionPower();
+
+       int set(bool val) override;
+private:
+};
+
+MODES_NAMESPACE_END
diff --git a/bluetooth/BtFactory.cpp b/bluetooth/BtFactory.cpp
new file mode 100644 (file)
index 0000000..ba0278b
--- /dev/null
@@ -0,0 +1,65 @@
+/*
+ * Copyright (c) 2019 Samsung Electronics Co., Ltd All Rights Reserved
+ *
+ * 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 "BtFactory.h"
+
+#include "modes_errors.h"
+#include "plugin-log.h"
+#include "BtActionPower.h"
+#include "BtActionAudioConnect.h"
+
+
+MODES_NAMESPACE_USE;
+
+BtFactory::BtFactory()
+{
+       registerAction("power", BtActionEnum::POWER);
+       registerAction("audioConnect", BtActionEnum::AUDIO_CONNECT);
+}
+
+BtAction* BtFactory::createAction(const std::string &key)
+{
+       auto search = actionMap.find(key);
+       if (search == actionMap.end()) {
+               ERR("No BtAction(%s)", key.c_str());
+               return nullptr;
+       }
+
+       switch (search->second) {
+       case BtActionEnum::POWER: {
+               BtActionPower *btActionPower = new BtActionPower();
+               return btActionPower;
+               break;
+               }
+       case BtActionEnum::AUDIO_CONNECT: {
+               BtActionAudioConnect *btActionAudioConnect = new BtActionAudioConnect();
+               return btActionAudioConnect;
+               break;
+               }
+       }
+
+       return nullptr;
+}
+
+void BtFactory::destroyAction(BtAction *action)
+{
+       delete action;
+}
+
+void BtFactory::registerAction(std::string key, BtActionEnum action)
+{
+       DBG("Register Action key[%s]", key.c_str());
+       actionMap[key] = action;
+}
diff --git a/bluetooth/BtFactory.h b/bluetooth/BtFactory.h
new file mode 100644 (file)
index 0000000..e8b3f92
--- /dev/null
@@ -0,0 +1,41 @@
+/*
+ * Copyright (c) 2019 Samsung Electronics Co., Ltd All Rights Reserved
+ *
+ * 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.
+ */
+#pragma once
+
+#include <string>
+#include <map>
+#include "BtAction.h"
+
+MODES_NAMESPACE_BEGIN
+
+class BtFactory {
+public:
+       BtFactory();
+       ~BtFactory() = default;
+
+       BtAction *createAction(const std::string &key);
+       void destroyAction(BtAction *action);
+private:
+       enum class BtActionEnum {
+               POWER,
+               AUDIO_CONNECT
+       };
+
+       void registerAction(std::string key, BtActionEnum action);
+       std::map<std::string, BtActionEnum> actionMap;
+};
+
+MODES_NAMESPACE_END
diff --git a/bluetooth/BtPlugin.cpp b/bluetooth/BtPlugin.cpp
new file mode 100644 (file)
index 0000000..ac60e15
--- /dev/null
@@ -0,0 +1,106 @@
+/*
+ * Copyright (c) 2019 Samsung Electronics Co., Ltd All Rights Reserved
+ *
+ * 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 <string>
+#include <map>
+#include <utility>
+#include <modes_errors.h>
+#include <bluetooth.h>
+#include <Plugin.h>
+#include "plugin-log.h"
+#include "BtFactory.h"
+
+MODES_NAMESPACE_USE;
+
+class BtPlugin : public Plugin {
+public:
+       BtPlugin();
+       ~BtPlugin();
+
+       int set(const std::string &key, int val) override;
+       int set(const std::string &key, double val) override;
+       int set(const std::string &key, bool val) override;
+       int set(const std::string &key, const std::string &val) override;
+private:
+       BtFactory btFactory;
+};
+
+extern "C" API Plugin *objectCreate(void)
+{
+       return new BtPlugin;
+}
+
+extern "C" API void objectDelete(Plugin *plugin)
+{
+       delete plugin;
+}
+
+BtPlugin::BtPlugin()
+{
+       setName("bluetooth");
+}
+
+BtPlugin::~BtPlugin()
+{
+}
+
+int BtPlugin::set(const std::string &key, int val)
+{
+       BtAction *action = btFactory.createAction(key);
+       RETVM_IF(nullptr == action, MODES_ERROR_INVALID_PARAMETER, "action(%s) is null", key.c_str());
+
+       DBG("set [%s, %d]", key.c_str(), val);
+
+       int btRet = action->set(val);
+       btFactory.destroyAction(action);
+       return btRet;
+}
+
+int BtPlugin::set(const std::string &key, double val)
+{
+       BtAction *action = btFactory.createAction(key);
+       RETVM_IF(nullptr == action, MODES_ERROR_INVALID_PARAMETER, "action(%s) is null", key.c_str());
+
+       DBG("set [%s, %f]", key.c_str(), val);
+
+       int btRet = action->set(val);
+       btFactory.destroyAction(action);
+       return btRet;
+}
+
+int BtPlugin::set(const std::string &key, bool val)
+{
+       BtAction *action = btFactory.createAction(key);
+       RETVM_IF(nullptr == action, MODES_ERROR_INVALID_PARAMETER, "action(%s) is null", key.c_str());
+
+       DBG("set [%s, %s]", key.c_str(), (val ? "on" : "off"));
+
+       int btRet = action->set(val);
+       btFactory.destroyAction(action);
+       return btRet;
+}
+
+int BtPlugin::set(const std::string &key, const std::string &val)
+{
+       BtAction *action = btFactory.createAction(key);
+       RETVM_IF(nullptr == action, MODES_ERROR_INVALID_PARAMETER, "action(%s) is null", key.c_str());
+
+       DBG("set [%s, %s]", key.c_str(), val.c_str());
+
+       int btRet = action->set(val);
+       btFactory.destroyAction(action);
+       return btRet;
+}
+
diff --git a/bluetooth/CMakeLists.txt b/bluetooth/CMakeLists.txt
new file mode 100644 (file)
index 0000000..1866f61
--- /dev/null
@@ -0,0 +1,12 @@
+SET(BT_PLUGIN "modes-plugin-bluetooth")
+
+FILE(GLOB BT_SRCS *.cpp)
+
+pkg_check_modules(bluetooth_pkgs REQUIRED modes dlog capi-base-common capi-network-bluetooth)
+INCLUDE_DIRECTORIES(${bluetooth_pkgs_INCLUDE_DIRS})
+LINK_DIRECTORIES(${bluetooth_pkgs_LIBRARY_DIRS})
+
+ADD_LIBRARY(${BT_PLUGIN} SHARED ${BT_SRCS})
+TARGET_LINK_LIBRARIES(${BT_PLUGIN} ${bluetooth_pkgs_LIBRARIES})
+SET_TARGET_PROPERTIES(${BT_PLUGIN} PROPERTIES NO_SONAME 1 )
+INSTALL(TARGETS ${BT_PLUGIN} DESTINATION ${MODES_PLUGIN_DEFAULT_DIR})
index e82fbd2..4528bac 100644 (file)
@@ -15,6 +15,7 @@ BuildRequires: modes-plugin-devel
 BuildRequires: pkgconfig(dlog)
 BuildRequires: pkgconfig(capi-base-common)
 BuildRequires: pkgconfig(capi-network-wifi-manager)
+BuildRequires: pkgconfig(capi-network-bluetooth)
 BuildRequires: pkgconfig(vconf)
 BuildRequires: pkgconfig(gmock)
 
index 0721892..5586836 100644 (file)
@@ -2,15 +2,22 @@ SET(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -fPIE")
 SET(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -fPIE")
 ADD_DEFINITIONS("-DMDS_TEST")
 
-pkg_check_modules(test_pkgs REQUIRED modes dlog capi-network-wifi-manager gmock)
+pkg_check_modules(test_pkgs REQUIRED modes dlog capi-network-wifi-manager capi-network-bluetooth gmock)
 INCLUDE_DIRECTORIES(${test_pkgs_INCLUDE_DIRS})
 LINK_DIRECTORIES(${test_pkgs_LIBRARY_DIRS})
 
 SET(WIFI_SRC_DIR "${CMAKE_SOURCE_DIR}/wifi" )
-
 SET(WIFI_PLUGIN_TEST "modes-gtest-modemgr")
-SET(SRCS ${WIFI_SRC_DIR}/WifiAction.cpp "mdsp_wifi_main.cpp")
+SET(WIFI_SRCS ${WIFI_SRC_DIR}/WifiAction.cpp "mdsp_wifi_main.cpp")
 
-ADD_EXECUTABLE(${WIFI_PLUGIN_TEST} ${SRCS})
+ADD_EXECUTABLE(${WIFI_PLUGIN_TEST} ${WIFI_SRCS})
 TARGET_LINK_LIBRARIES(${WIFI_PLUGIN_TEST} ${test_pkgs_LIBRARIES} dl)
 INSTALL(TARGETS ${WIFI_PLUGIN_TEST} DESTINATION ${TEST_INSTALL_DIR})
+#===================================================================#
+SET(BT_SRC_DIR "${CMAKE_SOURCE_DIR}/bluetooth" )
+SET(BT_PLUGIN_TEST "modes-gtest-bt")
+SET(BT_SRCS ${BT_SRC_DIR}/BtAction.cpp "mdsp_bt_main.cpp")
+
+ADD_EXECUTABLE(${BT_PLUGIN_TEST} ${BT_SRCS})
+TARGET_LINK_LIBRARIES(${BT_PLUGIN_TEST} ${test_pkgs_LIBRARIES} dl)
+INSTALL(TARGETS ${BT_PLUGIN_TEST} DESTINATION ${TEST_INSTALL_DIR})
diff --git a/unittests/mdsp_bt_main.cpp b/unittests/mdsp_bt_main.cpp
new file mode 100644 (file)
index 0000000..e083c6b
--- /dev/null
@@ -0,0 +1,21 @@
+/*
+ * Copyright (c) 2019 Samsung Electronics Co., Ltd All Rights Reserved
+ *
+ * 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 <gtest/gtest.h>
+
+int main(int argc, char **argv) {
+       testing::InitGoogleTest(&argc, argv);
+       return RUN_ALL_TESTS();
+}