From d8ef8e68805ab7f53258427c79ee5aaafec916ba Mon Sep 17 00:00:00 2001 From: Charles Kerr Date: Thu, 10 Mar 2016 17:09:59 -0600 Subject: add UsbManager --- tests/integration/usb-manager-test.cpp | 186 +++++++++++++++++++++++++++++++++ 1 file changed, 186 insertions(+) create mode 100644 tests/integration/usb-manager-test.cpp (limited to 'tests/integration/usb-manager-test.cpp') diff --git a/tests/integration/usb-manager-test.cpp b/tests/integration/usb-manager-test.cpp new file mode 100644 index 0000000..aca5325 --- /dev/null +++ b/tests/integration/usb-manager-test.cpp @@ -0,0 +1,186 @@ +/* + * Copyright 2016 Canonical Ltd. + * + * This program is free software: you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 3, as published + * by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranties of + * MERCHANTABILITY, SATISFACTORY QUALITY, or FITNESS FOR A PARTICULAR + * PURPOSE. See the GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program. If not, see . + * + * Authors: + * Charles Kerr + */ + +#define QT_NO_KEYWORDS + +#include +#include +#include +#include + +#include + +#include +#include +#include + +#include + +#include + +#include + +#include +#include +#include + +/*** +**** +***/ + +#define WAIT_FOR_SIGNALS(signalSpy, signalsExpected)\ +{\ + while (signalSpy.size() < signalsExpected)\ + {\ + ASSERT_TRUE(signalSpy.wait());\ + }\ + ASSERT_EQ(signalsExpected, signalSpy.size());\ +} + +class UsbManagerFixture: public GlibFixture +{ + using super = GlibFixture; + +public: + + UsbManagerFixture(): + dbusMock{dbusTestRunner} + { + DBusTypes::registerMetaTypes(); + + dbusTestRunner.startServices(); + } + + ~UsbManagerFixture() =default; + +protected: + + static void file_deleter (std::string* s) + { + fprintf(stderr, "remove \"%s\"\n", s->c_str()); + remove(s->c_str()); + delete s; + } + + bool qDBusArgumentToMap(QVariant const& variant, QVariantMap& map) + { + if (variant.canConvert()) + { + QDBusArgument value(variant.value()); + if (value.currentType() == QDBusArgument::MapType) + { + value >> map; + return true; + } + } + return false; + } + + void SetUp() override + { + super::SetUp(); + + char tmpl[] = {"usb-manager-test-XXXXXX"}; + m_tmpdir.reset(new std::string{g_mkdtemp(tmpl)}, file_deleter); + g_message("using tmpdir '%s'", m_tmpdir->c_str()); + + dbusMock.registerNotificationDaemon(); + dbusTestRunner.startServices(); + } + + OrgFreedesktopDBusMockInterface& notificationsMockInterface() + { + return dbusMock.mockInterface("org.freedesktop.Notifications", + "/org/freedesktop/Notifications", + "org.freedesktop.Notifications", + QDBusConnection::SessionBus); + } + + QtDBusTest::DBusTestRunner dbusTestRunner; + QtDBusMock::DBusMock dbusMock; + QtDBusTest::DBusServicePtr indicator; + std::shared_ptr m_tmpdir; +}; + +TEST_F(UsbManagerFixture, Allow) +{ + const std::shared_ptr socket_path {new std::string{*m_tmpdir+"/socket"}, file_deleter}; + const std::shared_ptr public_keys_path {new std::string{*m_tmpdir+"/adb_keys"}, file_deleter}; + + // add a signal spy to listen to the notification daemon + QSignalSpy notificationsSpy( + ¬ificationsMockInterface(), + SIGNAL(MethodCalled(const QString &, const QVariantList &)) + ); + + // start a mock AdbdServer ready to submit a request + const std::string public_key {"qAAAALUHllFjEZjl5jbS9ivjpQpaTNpibl28Re71D/S8sV3usNJTkbpvZYoVPfxtmHSNdCgLkWN6qcDZsHZqE/4myzmx/8Y/RqBy1oirudugi3YUUcJh7aWkY8lKQe9shCLTcrT7cFLZIJIidTvfmWTm0UcU+xmdPALze11I3lGo1Ty5KpCe9oP+qYM8suHbxhm78LKLlo0QJ2QqM8T5isr1pvoPHDgRb+mSESElG+xDIfPWA2BTu77/xk4EnXmOYfcuCr5akF3N4fRo/ACnYgXWDZFX2XdklBXyDj78lVlinF37xdMk7BMQh166X7UNkpH1uG2y5F6lUzyLg8SsFtRnJkw7eVe/gnJj3feQaFQbF5oVDhWhLMtWLtejhX6umvroVBVA4rynG4xEgs00K4u4ly8DUIIJYDO22Ml4myFR5CUm3lOlyitNdzYGh0utLXPq9oc8EbMVxM3i+O7PRxQw5Ul04X6K8GLiGUDV98DB+xYUqfEveq1BRnXi/ZrdPDhQ8Lfkg5xnLccPTFamAqutPtZXV6s7dXJInBTZf0NtBaWL0RdR2cOJBrpeBYkrc9yIyeqFLFdxr66rjaehjaa4pS4S+CD6PkGiIpPWSQtwNC4RlT10qTQ0/K9lRux2p0D8Z8ubUTFuh4kBScGUkN1OV3Z+7d7B+ghmBtZrrgleXsbehjRuKgEAAQA= foo@bar"}; + const std::string fingerprint {"12:23:5f:2d:8c:40:ae:1d:05:7b:ae:bd:88:8a:f0:80"}; + auto adbd_server = std::make_shared(*socket_path, std::vector{"PK"+public_key}); + + // set up a UsbManager to process the request + auto usb_manager = std::make_shared(*socket_path, *public_keys_path); + + // wait for the notification to show up, confirm it looks right + WAIT_FOR_SIGNALS(notificationsSpy, 1); + { + QVariantList const& call(notificationsSpy.at(0)); + EXPECT_EQ("Notify", call.at(0)); + + QVariantList const& args(call.at(1).toList()); + ASSERT_EQ(8, args.size()); + EXPECT_EQ("", args.at(0)); // app name + EXPECT_EQ(0, args.at(1)); // replaces-id + EXPECT_EQ("computer-symbolic", args.at(2)); // icon name + EXPECT_EQ("Allow USB Debugging?", args.at(3)); // summary + EXPECT_EQ(QString::fromUtf8("The computer's RSA key fingerprint is: ") + QString::fromUtf8(fingerprint.c_str()), args.at(4)); // body + EXPECT_EQ(QStringList({"allow", "Allow", "deny", "Deny"}), args.at(5)); // actions + EXPECT_EQ(-1, args.at(7)); + + QVariantMap hints; + ASSERT_TRUE(qDBusArgumentToMap(args.at(6), hints)); + ASSERT_EQ(3, hints.size()); + ASSERT_TRUE(hints.contains("x-canonical-private-affirmative-tint")); + ASSERT_TRUE(hints.contains("x-canonical-non-shaped-icon")); + ASSERT_TRUE(hints.contains("x-canonical-snap-decisions")); + } + notificationsSpy.clear(); + + // click on allow in the notification + notificationsMockInterface().EmitSignal( + DBusTypes::NOTIFY_DBUS_INTERFACE, + "ActionInvoked", + "us", + QVariantList() << uint32_t(1) << "allow" + ); + + // confirm that the AdbdServer got the right response + wait_for([adbd_server](){return !adbd_server->m_responses.empty();}, 2000); + ASSERT_EQ(1, adbd_server->m_responses.size()); + EXPECT_EQ("OK", adbd_server->m_responses.front()); + + // confirm that the public_keys file got the public key appended to it + std::ifstream ifkeys {*public_keys_path}; + std::vector lines; + std::string line; + while(getline(ifkeys, line)) + lines.emplace_back(std::move(line)); + ASSERT_EQ(1, lines.size()); + EXPECT_EQ(public_key, lines[0]); +} -- cgit v1.2.3 From 65eba5e107b0499aec4bed55be202bf1df6710bb Mon Sep 17 00:00:00 2001 From: Charles Kerr Date: Thu, 17 Mar 2016 09:25:23 -0500 Subject: add tests/utils/qdbus-helpers.h so that we only define qDBusArgumentToMap() in one place --- tests/integration/usb-manager-test.cpp | 17 ++--------------- tests/unit/usb-snap-test.cpp | 15 +-------------- tests/utils/qdbus-helpers.h | 21 +++++++++++++++++++++ 3 files changed, 24 insertions(+), 29 deletions(-) create mode 100644 tests/utils/qdbus-helpers.h (limited to 'tests/integration/usb-manager-test.cpp') diff --git a/tests/integration/usb-manager-test.cpp b/tests/integration/usb-manager-test.cpp index aca5325..5e3377d 100644 --- a/tests/integration/usb-manager-test.cpp +++ b/tests/integration/usb-manager-test.cpp @@ -20,9 +20,10 @@ #define QT_NO_KEYWORDS #include -#include #include +#include #include +#include #include @@ -78,20 +79,6 @@ protected: delete s; } - bool qDBusArgumentToMap(QVariant const& variant, QVariantMap& map) - { - if (variant.canConvert()) - { - QDBusArgument value(variant.value()); - if (value.currentType() == QDBusArgument::MapType) - { - value >> map; - return true; - } - } - return false; - } - void SetUp() override { super::SetUp(); diff --git a/tests/unit/usb-snap-test.cpp b/tests/unit/usb-snap-test.cpp index 84555cc..e8f8bb2 100644 --- a/tests/unit/usb-snap-test.cpp +++ b/tests/unit/usb-snap-test.cpp @@ -19,6 +19,7 @@ #define QT_NO_KEYWORDS #include +#include #include #include @@ -64,20 +65,6 @@ public: protected: - bool qDBusArgumentToMap(QVariant const& variant, QVariantMap& map) - { - if (variant.canConvert()) - { - QDBusArgument value(variant.value()); - if (value.currentType() == QDBusArgument::MapType) - { - value >> map; - return true; - } - } - return false; - } - void SetUp() override { super::SetUp(); diff --git a/tests/utils/qdbus-helpers.h b/tests/utils/qdbus-helpers.h new file mode 100644 index 0000000..f873e23 --- /dev/null +++ b/tests/utils/qdbus-helpers.h @@ -0,0 +1,21 @@ +#pragma once + +#define QT_NO_KEYWORDS +#include +#include + +bool qDBusArgumentToMap(QVariant const& variant, QVariantMap& map) +{ + if (variant.canConvert()) + { + QDBusArgument value(variant.value()); + if (value.currentType() == QDBusArgument::MapType) + { + value >> map; + return true; + } + } + + return false; +} + -- cgit v1.2.3 From c63d90da0f1d9cbd1eee5dd66a9828c51cc8dcc9 Mon Sep 17 00:00:00 2001 From: Charles Kerr Date: Thu, 17 Mar 2016 09:59:32 -0500 Subject: de-dupe use of dbus names --- src/dbus-names.h | 42 ++++++++++++++++++++++++++++++++++ src/usb-snap.cpp | 34 ++++++++++++--------------- tests/integration/usb-manager-test.cpp | 13 ++++++----- tests/unit/usb-snap-test.cpp | 13 ++++++----- tests/utils/dbus-types.h | 5 ---- 5 files changed, 71 insertions(+), 36 deletions(-) create mode 100644 src/dbus-names.h (limited to 'tests/integration/usb-manager-test.cpp') diff --git a/src/dbus-names.h b/src/dbus-names.h new file mode 100644 index 0000000..753b8c8 --- /dev/null +++ b/src/dbus-names.h @@ -0,0 +1,42 @@ +/* + * Copyright 2016 Canonical Ltd. + * + * This program is free software: you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 3, as published + * by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranties of + * MERCHANTABILITY, SATISFACTORY QUALITY, or FITNESS FOR A PARTICULAR + * PURPOSE. See the GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program. If not, see . + * + * Authors: + * Charles Kerr + */ + +#pragma once + +namespace DBusNames +{ + namespace Notify + { + static constexpr char const * NAME = "org.freedesktop.Notifications"; + static constexpr char const * PATH = "/org/freedesktop/Notifications"; + static constexpr char const * INTERFACE = "org.freedesktop.Notifications"; + + namespace ActionInvoked + { + static constexpr char const * NAME = "ActionInvoked"; + } + + namespace NotificationClosed + { + static constexpr char const * NAME = "NotificationClosed"; + enum Reason { EXPIRED=1, DISMISSED=2, API=3, UNDEFINED=4 }; + } + } +} + diff --git a/src/usb-snap.cpp b/src/usb-snap.cpp index c42f9f0..41c78c6 100644 --- a/src/usb-snap.cpp +++ b/src/usb-snap.cpp @@ -17,6 +17,7 @@ * Charles Kerr */ +#include #include #include @@ -48,9 +49,9 @@ public: if (m_notification_id != 0) { GError* error {}; g_dbus_connection_call_sync(m_bus, - BUS_NAME, - OBJECT_PATH, - IFACE_NAME, + DBusNames::Notify::NAME, + DBusNames::Notify::PATH, + DBusNames::Notify::INTERFACE, "CloseNotification", g_variant_new("(u)", m_notification_id), nullptr, @@ -93,10 +94,10 @@ private: m_bus = G_DBUS_CONNECTION(g_object_ref(G_OBJECT(bus))); m_subscription_id = g_dbus_connection_signal_subscribe(m_bus, - BUS_NAME, - IFACE_NAME, + DBusNames::Notify::NAME, + DBusNames::Notify::INTERFACE, nullptr, - OBJECT_PATH, + DBusNames::Notify::PATH, nullptr, G_DBUS_SIGNAL_FLAGS_NONE, on_notification_signal_static, @@ -128,9 +129,9 @@ private: &hints_builder, -1); g_dbus_connection_call(m_bus, - BUS_NAME, - OBJECT_PATH, - IFACE_NAME, + DBusNames::Notify::NAME, + DBusNames::Notify::PATH, + DBusNames::Notify::INTERFACE, "Notify", args, G_VARIANT_TYPE("(u)"), @@ -172,12 +173,12 @@ private: GVariant* parameters, gpointer gself) { - g_return_if_fail(!g_strcmp0(object_path, OBJECT_PATH)); - g_return_if_fail(!g_strcmp0(interface_name, IFACE_NAME)); + g_return_if_fail(!g_strcmp0(object_path, DBusNames::Notify::PATH)); + g_return_if_fail(!g_strcmp0(interface_name, DBusNames::Notify::INTERFACE)); auto self = static_cast(gself); - if (!g_strcmp0(signal_name, "ActionInvoked")) + if (!g_strcmp0(signal_name, DBusNames::Notify::ActionInvoked::NAME)) { uint32_t id {}; const char* action_name {}; @@ -185,7 +186,7 @@ private: if (id == self->m_notification_id) self->on_action_invoked(action_name); } - else if (!g_strcmp0(signal_name, "NotificationClosed")) + else if (!g_strcmp0(signal_name, DBusNames::Notify::NotificationClosed::NAME)) { uint32_t id {}; uint32_t close_reason {}; @@ -211,7 +212,7 @@ private: void on_notification_closed(uint32_t close_reason) { - if (close_reason == CloseReason::EXPIRED) + if (close_reason == DBusNames::Notify::NotificationClosed::Reason::EXPIRED) m_on_user_response(AdbdClient::PKResponse::DENY, false); m_notification_id = 0; @@ -220,11 +221,6 @@ private: static constexpr char const * ACTION_ALLOW {"allow"}; static constexpr char const * ACTION_DENY {"deny"}; - static constexpr char const * BUS_NAME {"org.freedesktop.Notifications" }; - static constexpr char const * IFACE_NAME {"org.freedesktop.Notifications" }; - static constexpr char const * OBJECT_PATH {"/org/freedesktop/Notifications" }; - enum CloseReason { EXPIRED=1, DISMISSED=2, API=3, UNDEFINED=4 }; - const std::string m_fingerprint; core::Signal m_on_user_response; GCancellable* m_cancellable {}; diff --git a/tests/integration/usb-manager-test.cpp b/tests/integration/usb-manager-test.cpp index 5e3377d..82c170e 100644 --- a/tests/integration/usb-manager-test.cpp +++ b/tests/integration/usb-manager-test.cpp @@ -25,6 +25,7 @@ #include #include +#include #include #include @@ -93,10 +94,10 @@ protected: OrgFreedesktopDBusMockInterface& notificationsMockInterface() { - return dbusMock.mockInterface("org.freedesktop.Notifications", - "/org/freedesktop/Notifications", - "org.freedesktop.Notifications", - QDBusConnection::SessionBus); + return dbusMock.mockInterface(DBusNames::Notify::NAME, + DBusNames::Notify::PATH, + DBusNames::Notify::INTERFACE, + QDBusConnection::SessionBus); } QtDBusTest::DBusTestRunner dbusTestRunner; @@ -151,8 +152,8 @@ TEST_F(UsbManagerFixture, Allow) // click on allow in the notification notificationsMockInterface().EmitSignal( - DBusTypes::NOTIFY_DBUS_INTERFACE, - "ActionInvoked", + DBusNames::Notify::INTERFACE, + DBusNames::Notify::ActionInvoked::NAME, "us", QVariantList() << uint32_t(1) << "allow" ); diff --git a/tests/unit/usb-snap-test.cpp b/tests/unit/usb-snap-test.cpp index e8f8bb2..dc17696 100644 --- a/tests/unit/usb-snap-test.cpp +++ b/tests/unit/usb-snap-test.cpp @@ -23,6 +23,7 @@ #include #include +#include #include #include @@ -75,10 +76,10 @@ protected: OrgFreedesktopDBusMockInterface& notificationsMockInterface() { - return dbusMock.mockInterface("org.freedesktop.Notifications", - "/org/freedesktop/Notifications", - "org.freedesktop.Notifications", - QDBusConnection::SessionBus); + return dbusMock.mockInterface(DBusNames::Notify::NAME, + DBusNames::Notify::PATH, + DBusNames::Notify::INTERFACE, + QDBusConnection::SessionBus); } QtDBusTest::DBusTestRunner dbusTestRunner; @@ -144,8 +145,8 @@ TEST_F(UsbSnapFixture, TestRoundTrip) // fake a user interaction with the fdo notification notificationsMockInterface().EmitSignal( - DBusTypes::NOTIFY_DBUS_INTERFACE, - "ActionInvoked", + DBusNames::Notify::INTERFACE, + DBusNames::Notify::ActionInvoked::NAME, "us", QVariantList() << id << test.action_to_invoke); diff --git a/tests/utils/dbus-types.h b/tests/utils/dbus-types.h index c2dfb81..3b3a02d 100644 --- a/tests/utils/dbus-types.h +++ b/tests/utils/dbus-types.h @@ -39,9 +39,4 @@ namespace DBusTypes qDBusRegisterMetaType(); qDBusRegisterMetaType(); } - static constexpr char const* NOTIFY_DBUS_NAME = "org.freedesktop.Notifications"; - - static constexpr char const* NOTIFY_DBUS_INTERFACE = "org.freedesktop.Notifications"; - - static constexpr char const* NOTIFY_DBUS_PATH = "/org/freedesktop/Notifications"; } -- cgit v1.2.3 From 5b6008fa3b5a9b0373b2f03791140ca1fa8dc8de Mon Sep 17 00:00:00 2001 From: Charles Kerr Date: Thu, 17 Mar 2016 10:24:41 -0500 Subject: introduce a QtFixture gtest base class to reduce redundancy in test fixtures' helper/util code --- tests/integration/usb-manager-test.cpp | 31 +++--------------- tests/unit/adbd-client-test.cpp | 2 +- tests/unit/usb-snap-test.cpp | 34 +++----------------- tests/utils/qt-fixture.h | 58 ++++++++++++++++++++++++++++++++++ 4 files changed, 69 insertions(+), 56 deletions(-) create mode 100644 tests/utils/qt-fixture.h (limited to 'tests/integration/usb-manager-test.cpp') diff --git a/tests/integration/usb-manager-test.cpp b/tests/integration/usb-manager-test.cpp index 82c170e..21fdc97 100644 --- a/tests/integration/usb-manager-test.cpp +++ b/tests/integration/usb-manager-test.cpp @@ -20,10 +20,7 @@ #define QT_NO_KEYWORDS #include -#include -#include -#include -#include +#include #include #include @@ -32,12 +29,6 @@ #include #include -#include - -#include - -#include - #include #include #include @@ -46,26 +37,15 @@ **** ***/ -#define WAIT_FOR_SIGNALS(signalSpy, signalsExpected)\ -{\ - while (signalSpy.size() < signalsExpected)\ - {\ - ASSERT_TRUE(signalSpy.wait());\ - }\ - ASSERT_EQ(signalsExpected, signalSpy.size());\ -} - -class UsbManagerFixture: public GlibFixture +class UsbManagerFixture: public QtFixture { - using super = GlibFixture; + using super = QtFixture; public: UsbManagerFixture(): dbusMock{dbusTestRunner} { - DBusTypes::registerMetaTypes(); - dbusTestRunner.startServices(); } @@ -76,7 +56,7 @@ protected: static void file_deleter (std::string* s) { fprintf(stderr, "remove \"%s\"\n", s->c_str()); - remove(s->c_str()); + g_remove(s->c_str()); delete s; } @@ -102,7 +82,6 @@ protected: QtDBusTest::DBusTestRunner dbusTestRunner; QtDBusMock::DBusMock dbusMock; - QtDBusTest::DBusServicePtr indicator; std::shared_ptr m_tmpdir; }; @@ -126,7 +105,7 @@ TEST_F(UsbManagerFixture, Allow) auto usb_manager = std::make_shared(*socket_path, *public_keys_path); // wait for the notification to show up, confirm it looks right - WAIT_FOR_SIGNALS(notificationsSpy, 1); + wait_for_signals(notificationsSpy, 1); { QVariantList const& call(notificationsSpy.at(0)); EXPECT_EQ("Notify", call.at(0)); diff --git a/tests/unit/adbd-client-test.cpp b/tests/unit/adbd-client-test.cpp index c00c07a..754f76c 100644 --- a/tests/unit/adbd-client-test.cpp +++ b/tests/unit/adbd-client-test.cpp @@ -32,7 +32,7 @@ protected: static void file_deleter (std::string* s) { fprintf(stderr, "remove \"%s\"\n", s->c_str()); - remove(s->c_str()); + g_remove(s->c_str()); delete s; } diff --git a/tests/unit/usb-snap-test.cpp b/tests/unit/usb-snap-test.cpp index dc17696..663f9e6 100644 --- a/tests/unit/usb-snap-test.cpp +++ b/tests/unit/usb-snap-test.cpp @@ -18,47 +18,24 @@ */ #define QT_NO_KEYWORDS -#include -#include -#include -#include +#include #include #include -#include - #include #include #include -#include - -#include - -using namespace QtDBusTest; -using namespace QtDBusMock; - -#define WAIT_FOR_SIGNALS(signalSpy, signalsExpected)\ -{\ - while (signalSpy.size() < signalsExpected)\ - {\ - ASSERT_TRUE(signalSpy.wait());\ - }\ - ASSERT_EQ(signalsExpected, signalSpy.size());\ -} - -class UsbSnapFixture: public GlibFixture +class UsbSnapFixture: public QtFixture { - using super = GlibFixture; + using super = QtFixture; public: UsbSnapFixture(): dbusMock{dbusTestRunner} { - DBusTypes::registerMetaTypes(); - dbusTestRunner.startServices(); } @@ -84,7 +61,6 @@ protected: QtDBusTest::DBusTestRunner dbusTestRunner; QtDBusMock::DBusMock dbusMock; - QtDBusTest::DBusServicePtr indicator; }; TEST_F(UsbSnapFixture, TestRoundTrip) @@ -119,7 +95,7 @@ TEST_F(UsbSnapFixture, TestRoundTrip) }); // test that UsbSnap creates a fdo notification - WAIT_FOR_SIGNALS(notificationsSpy, 1); + wait_for_signals(notificationsSpy, 1); { QVariantList const& call(notificationsSpy.at(0)); EXPECT_EQ("Notify", call.at(0)); @@ -157,7 +133,7 @@ TEST_F(UsbSnapFixture, TestRoundTrip) // confirm that the snap dtor cleans up the notification snap.reset(); - WAIT_FOR_SIGNALS(notificationsSpy, 1); + wait_for_signals(notificationsSpy, 1); { QVariantList const& call(notificationsSpy.at(0)); EXPECT_EQ("CloseNotification", call.at(0)); diff --git a/tests/utils/qt-fixture.h b/tests/utils/qt-fixture.h new file mode 100644 index 0000000..321d56e --- /dev/null +++ b/tests/utils/qt-fixture.h @@ -0,0 +1,58 @@ +/* + * Copyright 2016 Canonical Ltd. + * + * This program is free software: you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 3, as published + * by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranties of + * MERCHANTABILITY, SATISFACTORY QUALITY, or FITNESS FOR A PARTICULAR + * PURPOSE. See the GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program. If not, see . + * + * Authors: + * Charles Kerr + */ + +#pragma once + +#define QT_NO_KEYWORDS + +#include +#include +#include +#include + +#include + +#include + +class QtFixture: public GlibFixture +{ + using super = GlibFixture; + +public: + + QtFixture() + { + DBusTypes::registerMetaTypes(); + } + + ~QtFixture() =default; + +protected: + + void wait_for_signals(QSignalSpy& signalSpy, int signalsExpected) + { + while (signalSpy.size() < signalsExpected) + { + ASSERT_TRUE(signalSpy.wait()); + } + + ASSERT_EQ(signalsExpected, signalSpy.size()); + } +}; + -- cgit v1.2.3 From 7a25132c125f6e5e413ad26ea950ae22bee982f5 Mon Sep 17 00:00:00 2001 From: Charles Kerr Date: Mon, 21 Mar 2016 13:40:11 -0500 Subject: if our USB device is disconnected while prompting the user for ADBD, cancel the prompt. --- CMakeLists.txt | 1 + debian/control | 1 + src/CMakeLists.txt | 1 + src/adbd-client.cpp | 1 + src/main.cpp | 4 +- src/usb-manager.cpp | 63 +++++++++++++++++--------- src/usb-manager.h | 11 ++++- src/usb-monitor.cpp | 81 ++++++++++++++++++++++++++++++++++ src/usb-monitor.h | 52 ++++++++++++++++++++++ src/usb-snap.cpp | 1 + tests/integration/usb-manager-test.cpp | 44 ++++++++++++++++-- tests/unit/usb-snap-test.cpp | 1 - tests/utils/mock-usb-monitor.h | 32 ++++++++++++++ tests/utils/qdbus-helpers.h | 21 --------- tests/utils/qt-fixture.h | 18 +++++++- 15 files changed, 284 insertions(+), 48 deletions(-) create mode 100644 src/usb-monitor.cpp create mode 100644 src/usb-monitor.h create mode 100644 tests/utils/mock-usb-monitor.h delete mode 100644 tests/utils/qdbus-helpers.h (limited to 'tests/integration/usb-manager-test.cpp') diff --git a/CMakeLists.txt b/CMakeLists.txt index bb7568e..8a1a6aa 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -48,6 +48,7 @@ set(GLIB_MINIMUM 2.36) pkg_check_modules(SERVICE_DEPS REQUIRED gio-unix-2.0>=${GLIB_MINIMUM} glib-2.0>=${GLIB_MINIMUM} + gudev-1.0 ) include_directories (SYSTEM ${SERVICE_DEPS_INCLUDE_DIRS} diff --git a/debian/control b/debian/control index 529fa37..90e2590 100644 --- a/debian/control +++ b/debian/control @@ -7,6 +7,7 @@ Build-Depends: cmake, cmake-extras (>= 0.4), dbus, libglib2.0-dev (>= 2.36), + libgudev-1.0-dev, libproperties-cpp-dev, # for coverage reports lcov, diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index d3a021b..cdd2384 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -13,6 +13,7 @@ add_library( indicator.cpp rotation-lock.cpp usb-manager.cpp + usb-monitor.cpp usb-snap.cpp ) diff --git a/src/adbd-client.cpp b/src/adbd-client.cpp index 4f7d28f..937215e 100644 --- a/src/adbd-client.cpp +++ b/src/adbd-client.cpp @@ -45,6 +45,7 @@ public: { // tell the worker thread to stop whatever it's doing and exit. g_cancellable_cancel(m_cancellable); + m_pkresponse_cv.notify_one(); m_sleep_cv.notify_one(); m_worker_thread.join(); g_clear_object(&m_cancellable); diff --git a/src/main.cpp b/src/main.cpp index 7d6eb5f..27e6bcc 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -20,6 +20,7 @@ #include #include #include +#include #include // bindtextdomain() #include @@ -59,7 +60,8 @@ main(int /*argc*/, char** /*argv*/) // even though it doesn't have an indicator component yet static constexpr char const * ADB_SOCKET_PATH {"/dev/socket/adbd"}; static constexpr char const * PUBLIC_KEYS_FILENAME {"/data/misc/adb/adb_keys"}; - UsbManager usb_manager {ADB_SOCKET_PATH, PUBLIC_KEYS_FILENAME}; + auto usb_monitor = std::make_shared(); + UsbManager usb_manager {ADB_SOCKET_PATH, PUBLIC_KEYS_FILENAME, usb_monitor}; // let's go! g_main_loop_run(loop); diff --git a/src/usb-manager.cpp b/src/usb-manager.cpp index 7f43520..840a04b 100644 --- a/src/usb-manager.cpp +++ b/src/usb-manager.cpp @@ -28,39 +28,57 @@ #include #include +#include + class UsbManager::Impl { public: explicit Impl( const std::string& socket_path, - const std::string& public_keys_filename + const std::string& public_keys_filename, + const std::shared_ptr& usb_monitor ): m_adbd_client{std::make_shared(socket_path)}, - m_public_keys_filename{public_keys_filename} + m_public_keys_filename{public_keys_filename}, + m_usb_monitor{usb_monitor} { - m_adbd_client->on_pk_request().connect([this](const AdbdClient::PKRequest& req){ - auto snap = new UsbSnap(req.fingerprint); - snap->on_user_response().connect([this,req,snap](AdbdClient::PKResponse response, bool remember_choice){ - g_debug("%s user responded! response %d, remember %d", G_STRLOC, int(response), int(remember_choice)); - req.respond(response); - if (remember_choice && (response == AdbdClient::PKResponse::ALLOW)) - write_public_key(req.public_key); - // delete_later - g_idle_add([](gpointer gsnap){delete static_cast(gsnap); return G_SOURCE_REMOVE;}, snap); - }); + m_usb_monitor->on_usb_disconnected().connect([this](const std::string& /*usb_name*/) { + m_snap.reset(); }); - } - ~Impl() - { + m_adbd_client->on_pk_request().connect( + [this](const AdbdClient::PKRequest& req){ + + m_snap.reset(new UsbSnap(req.fingerprint), + [this](UsbSnap* snap){ + m_snap_connections.clear(); + delete snap; + } + ); + + m_snap_connections.insert((*m_snap).on_user_response().connect( + [this,req](AdbdClient::PKResponse response, bool remember_choice){ + g_message("%s user responded! response %d, remember %d", G_STRLOC, int(response), int(remember_choice)); + req.respond(response); + g_message("%s", G_STRLOC); + if (remember_choice && (response == AdbdClient::PKResponse::ALLOW)) + write_public_key(req.public_key); + g_idle_add([](gpointer gself){static_cast(gself)->m_snap.reset(); return G_SOURCE_REMOVE;}, this); + } + )); + } + ); + } + ~Impl() =default; + private: void write_public_key(const std::string& public_key) { - g_debug("writing public key '%s' to '%s'", public_key.c_str(), m_public_keys_filename.c_str()); + g_message("%s writing public key '%s' to '%s'", G_STRLOC, public_key.c_str(), m_public_keys_filename.c_str()); // confirm the directory exists auto dirname = g_path_get_dirname(m_public_keys_filename.c_str()); @@ -78,12 +96,12 @@ private: S_IRUSR|S_IWUSR|S_IRGRP ); if (fd == -1) { - g_warning("Error opening ADB datafile '%s': %s", m_public_keys_filename.c_str(), g_strerror(errno)); + g_warning("Error opening ADB datafile: %s", g_strerror(errno)); return; } // write the new public key on its own line - const std::string buf {public_key + '\n'}; + std::string buf {public_key + '\n'}; if (write(fd, buf.c_str(), buf.size()) == -1) g_warning("Error writing ADB datafile: %d %s", errno, g_strerror(errno)); close(fd); @@ -91,6 +109,10 @@ private: std::shared_ptr m_adbd_client; const std::string m_public_keys_filename; + std::shared_ptr m_usb_monitor; + + std::shared_ptr m_snap; + std::set m_snap_connections; }; /*** @@ -99,9 +121,10 @@ private: UsbManager::UsbManager( const std::string& socket_path, - const std::string& public_keys_filename + const std::string& public_keys_filename, + const std::shared_ptr& usb_monitor ): - impl{new Impl{socket_path, public_keys_filename}} + impl{new Impl{socket_path, public_keys_filename, usb_monitor}} { } diff --git a/src/usb-manager.h b/src/usb-manager.h index ec405c0..960d634 100644 --- a/src/usb-manager.h +++ b/src/usb-manager.h @@ -19,6 +19,8 @@ #pragma once +#include + #include #include @@ -28,10 +30,17 @@ class UsbManager { public: - UsbManager(const std::string& socket_path, const std::string& public_key_filename); + + UsbManager( + const std::string& socket_path, + const std::string& public_key_filename, + const std::shared_ptr& + ); + ~UsbManager(); protected: + class Impl; std::unique_ptr impl; }; diff --git a/src/usb-monitor.cpp b/src/usb-monitor.cpp new file mode 100644 index 0000000..5fc5a6d --- /dev/null +++ b/src/usb-monitor.cpp @@ -0,0 +1,81 @@ +/* + * Copyright 2016 Canonical Ltd. + * + * This program is free software: you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 3, as published + * by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranties of + * MERCHANTABILITY, SATISFACTORY QUALITY, or FITNESS FOR A PARTICULAR + * PURPOSE. See the GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program. If not, see . + * + * Authors: + * Charles Kerr + */ + +#include + +#include +#include + +class GUDevUsbMonitor::Impl +{ +public: + + Impl() + { + const char* subsystems[] = {"android_usb", nullptr}; + m_udev_client = g_udev_client_new(subsystems); + g_signal_connect(m_udev_client, "uevent", G_CALLBACK(on_android_usb_event), this); + } + + ~Impl() + { + g_signal_handlers_disconnect_by_data(m_udev_client, this); + g_clear_object(&m_udev_client); + } + + core::Signal& on_usb_disconnected() + { + return m_on_usb_disconnected; + } + +private: + + static void on_android_usb_event(GUdevClient*, gchar* action, GUdevDevice* device, gpointer gself) + { + if (!g_strcmp0(action, "change")) + if (!g_strcmp0(g_udev_device_get_property(device, "USB_STATE"), "DISCONNECTED")) + static_cast(gself)->m_on_usb_disconnected(g_udev_device_get_name(device)); + } + + core::Signal m_on_usb_disconnected; + + GUdevClient* m_udev_client = nullptr; +}; + +/*** +**** +***/ + +UsbMonitor::UsbMonitor() =default; + +UsbMonitor::~UsbMonitor() =default; + +GUDevUsbMonitor::GUDevUsbMonitor(): + impl{new Impl{}} +{ +} + +GUDevUsbMonitor::~GUDevUsbMonitor() =default; + +core::Signal& +GUDevUsbMonitor::on_usb_disconnected() +{ + return impl->on_usb_disconnected(); +} + diff --git a/src/usb-monitor.h b/src/usb-monitor.h new file mode 100644 index 0000000..d9be539 --- /dev/null +++ b/src/usb-monitor.h @@ -0,0 +1,52 @@ +/* + * Copyright 2016 Canonical Ltd. + * + * This program is free software: you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 3, as published + * by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranties of + * MERCHANTABILITY, SATISFACTORY QUALITY, or FITNESS FOR A PARTICULAR + * PURPOSE. See the GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program. If not, see . + * + * Authors: + * Charles Kerr + */ + +#pragma once + +#include + +#include +#include + +/** + * Simple interface that emits signals on USB device state changes + */ +class UsbMonitor +{ +public: + UsbMonitor(); + virtual ~UsbMonitor(); + virtual core::Signal& on_usb_disconnected() =0; +}; + +/** + * Simple GUDev wrapper that notifies on android_usb device state changes + */ +class GUDevUsbMonitor: public UsbMonitor +{ +public: + GUDevUsbMonitor(); + virtual ~GUDevUsbMonitor(); + core::Signal& on_usb_disconnected() override; + +protected: + class Impl; + std::unique_ptr impl; +}; + diff --git a/src/usb-snap.cpp b/src/usb-snap.cpp index 41c78c6..349d80e 100644 --- a/src/usb-snap.cpp +++ b/src/usb-snap.cpp @@ -148,6 +148,7 @@ private: { GError* error {}; auto reply = g_dbus_connection_call_finish (G_DBUS_CONNECTION(obus), res, &error); +g_message("%s got notify response %s", G_STRLOC, g_variant_print(reply, true)); if (error != nullptr) { if (!g_error_matches(error, G_IO_ERROR, G_IO_ERROR_CANCELLED)) g_warning("UsbSnap: Error calling Notify: %s", error->message); diff --git a/tests/integration/usb-manager-test.cpp b/tests/integration/usb-manager-test.cpp index 21fdc97..19c0401 100644 --- a/tests/integration/usb-manager-test.cpp +++ b/tests/integration/usb-manager-test.cpp @@ -17,10 +17,9 @@ * Charles Kerr */ -#define QT_NO_KEYWORDS - #include #include +#include #include #include @@ -64,6 +63,8 @@ protected: { super::SetUp(); + m_usb_monitor.reset(new MockUsbMonitor{}); + char tmpl[] = {"usb-manager-test-XXXXXX"}; m_tmpdir.reset(new std::string{g_mkdtemp(tmpl)}, file_deleter); g_message("using tmpdir '%s'", m_tmpdir->c_str()); @@ -83,6 +84,7 @@ protected: QtDBusTest::DBusTestRunner dbusTestRunner; QtDBusMock::DBusMock dbusMock; std::shared_ptr m_tmpdir; + std::shared_ptr m_usb_monitor; }; TEST_F(UsbManagerFixture, Allow) @@ -102,7 +104,7 @@ TEST_F(UsbManagerFixture, Allow) auto adbd_server = std::make_shared(*socket_path, std::vector{"PK"+public_key}); // set up a UsbManager to process the request - auto usb_manager = std::make_shared(*socket_path, *public_keys_path); + auto usb_manager = std::make_shared(*socket_path, *public_keys_path, m_usb_monitor); // wait for the notification to show up, confirm it looks right wait_for_signals(notificationsSpy, 1); @@ -151,3 +153,39 @@ TEST_F(UsbManagerFixture, Allow) ASSERT_EQ(1, lines.size()); EXPECT_EQ(public_key, lines[0]); } + +TEST_F(UsbManagerFixture, Cancel) +{ + const std::shared_ptr socket_path {new std::string{*m_tmpdir+"/socket"}, file_deleter}; + const std::shared_ptr public_keys_path {new std::string{*m_tmpdir+"/adb_keys"}, file_deleter}; + + // add a signal spy to listen to the notification daemon + QSignalSpy notificationsSpy( + ¬ificationsMockInterface(), + SIGNAL(MethodCalled(const QString &, const QVariantList &)) + ); + + // start a mock AdbdServer ready to submit a request + const std::string public_key {"public_key"}; + auto adbd_server = std::make_shared(*socket_path, std::vector{"PK"+public_key}); + + // set up a UsbManager to process the request + auto usb_manager = std::make_shared(*socket_path, *public_keys_path, m_usb_monitor); + + // wait for a notification to show up + wait_for_signals(notificationsSpy, 1); + EXPECT_EQ("Notify", notificationsSpy.at(0).at(0)); + notificationsSpy.clear(); + + // wait for UsbSnap to receive dbusmock's response to the Notify request. + // there's no event to key off of for this, so just wait for a moment + wait_msec(); + + // disconnect the USB before the user has a chance to allow/deny + m_usb_monitor->m_on_usb_disconnected("android0"); + + // confirm that we requested the notification to be pulled down + wait_for_signals(notificationsSpy, 1); + EXPECT_EQ("CloseNotification", notificationsSpy.at(0).at(0)); + notificationsSpy.clear(); +} diff --git a/tests/unit/usb-snap-test.cpp b/tests/unit/usb-snap-test.cpp index 663f9e6..40de94a 100644 --- a/tests/unit/usb-snap-test.cpp +++ b/tests/unit/usb-snap-test.cpp @@ -17,7 +17,6 @@ * Charles Kerr */ -#define QT_NO_KEYWORDS #include #include diff --git a/tests/utils/mock-usb-monitor.h b/tests/utils/mock-usb-monitor.h new file mode 100644 index 0000000..92b89db --- /dev/null +++ b/tests/utils/mock-usb-monitor.h @@ -0,0 +1,32 @@ +/* + * Copyright 2016 Canonical Ltd. + * + * This program is free software: you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 3, as published + * by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranties of + * MERCHANTABILITY, SATISFACTORY QUALITY, or FITNESS FOR A PARTICULAR + * PURPOSE. See the GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program. If not, see . + * + * Authors: + * Charles Kerr + */ + +#pragma once + +#include + +class MockUsbMonitor: public UsbMonitor +{ +public: + MockUsbMonitor() =default; + virtual ~MockUsbMonitor() =default; + core::Signal& on_usb_disconnected() override {return m_on_usb_disconnected;} + core::Signal m_on_usb_disconnected; +}; + diff --git a/tests/utils/qdbus-helpers.h b/tests/utils/qdbus-helpers.h deleted file mode 100644 index f873e23..0000000 --- a/tests/utils/qdbus-helpers.h +++ /dev/null @@ -1,21 +0,0 @@ -#pragma once - -#define QT_NO_KEYWORDS -#include -#include - -bool qDBusArgumentToMap(QVariant const& variant, QVariantMap& map) -{ - if (variant.canConvert()) - { - QDBusArgument value(variant.value()); - if (value.currentType() == QDBusArgument::MapType) - { - value >> map; - return true; - } - } - - return false; -} - diff --git a/tests/utils/qt-fixture.h b/tests/utils/qt-fixture.h index 321d56e..0f5722b 100644 --- a/tests/utils/qt-fixture.h +++ b/tests/utils/qt-fixture.h @@ -22,12 +22,13 @@ #define QT_NO_KEYWORDS #include -#include #include #include #include +#include +#include #include class QtFixture: public GlibFixture @@ -54,5 +55,20 @@ protected: ASSERT_EQ(signalsExpected, signalSpy.size()); } + + bool qDBusArgumentToMap(QVariant const& variant, QVariantMap& map) + { + if (variant.canConvert()) + { + QDBusArgument value(variant.value()); + if (value.currentType() == QDBusArgument::MapType) + { + value >> map; + return true; + } + } + + return false; + } }; -- cgit v1.2.3 From 952552b8a92cdec3c03fec81711211d8c82c984f Mon Sep 17 00:00:00 2001 From: Charles Kerr Date: Tue, 22 Mar 2016 15:39:19 -0500 Subject: add multiple usb requests + disconnects to confirm the notification appears on subsequent requests --- tests/integration/usb-manager-test.cpp | 57 +++++++++++++++++++--------------- 1 file changed, 32 insertions(+), 25 deletions(-) (limited to 'tests/integration/usb-manager-test.cpp') diff --git a/tests/integration/usb-manager-test.cpp b/tests/integration/usb-manager-test.cpp index 19c0401..3ce79d0 100644 --- a/tests/integration/usb-manager-test.cpp +++ b/tests/integration/usb-manager-test.cpp @@ -19,6 +19,7 @@ #include #include +#include #include #include @@ -64,6 +65,7 @@ protected: super::SetUp(); m_usb_monitor.reset(new MockUsbMonitor{}); + m_greeter.reset(new MockGreeter{}); char tmpl[] = {"usb-manager-test-XXXXXX"}; m_tmpdir.reset(new std::string{g_mkdtemp(tmpl)}, file_deleter); @@ -85,6 +87,7 @@ protected: QtDBusMock::DBusMock dbusMock; std::shared_ptr m_tmpdir; std::shared_ptr m_usb_monitor; + std::shared_ptr m_greeter; }; TEST_F(UsbManagerFixture, Allow) @@ -104,7 +107,7 @@ TEST_F(UsbManagerFixture, Allow) auto adbd_server = std::make_shared(*socket_path, std::vector{"PK"+public_key}); // set up a UsbManager to process the request - auto usb_manager = std::make_shared(*socket_path, *public_keys_path, m_usb_monitor); + auto usb_manager = std::make_shared(*socket_path, *public_keys_path, m_usb_monitor, m_greeter); // wait for the notification to show up, confirm it looks right wait_for_signals(notificationsSpy, 1); @@ -154,38 +157,42 @@ TEST_F(UsbManagerFixture, Allow) EXPECT_EQ(public_key, lines[0]); } -TEST_F(UsbManagerFixture, Cancel) +TEST_F(UsbManagerFixture, AndroidInterruptus) { const std::shared_ptr socket_path {new std::string{*m_tmpdir+"/socket"}, file_deleter}; const std::shared_ptr public_keys_path {new std::string{*m_tmpdir+"/adb_keys"}, file_deleter}; - // add a signal spy to listen to the notification daemon - QSignalSpy notificationsSpy( - ¬ificationsMockInterface(), - SIGNAL(MethodCalled(const QString &, const QVariantList &)) - ); - // start a mock AdbdServer ready to submit a request const std::string public_key {"public_key"}; auto adbd_server = std::make_shared(*socket_path, std::vector{"PK"+public_key}); // set up a UsbManager to process the request - auto usb_manager = std::make_shared(*socket_path, *public_keys_path, m_usb_monitor); + auto usb_manager = std::make_shared(*socket_path, *public_keys_path, m_usb_monitor, m_greeter); - // wait for a notification to show up - wait_for_signals(notificationsSpy, 1); - EXPECT_EQ("Notify", notificationsSpy.at(0).at(0)); - notificationsSpy.clear(); - - // wait for UsbSnap to receive dbusmock's response to the Notify request. - // there's no event to key off of for this, so just wait for a moment - wait_msec(); - - // disconnect the USB before the user has a chance to allow/deny - m_usb_monitor->m_on_usb_disconnected("android0"); - - // confirm that we requested the notification to be pulled down - wait_for_signals(notificationsSpy, 1); - EXPECT_EQ("CloseNotification", notificationsSpy.at(0).at(0)); - notificationsSpy.clear(); + for (int i=0; i<3; i++) + { +g_message("i %d", i); + // add a signal spy to listen to the notification daemon + QSignalSpy notificationsSpy( + ¬ificationsMockInterface(), + SIGNAL(MethodCalled(const QString &, const QVariantList &)) + ); + + // wait for a notification to show up + wait_for_signals(notificationsSpy, 1); + EXPECT_EQ("Notify", notificationsSpy.at(0).at(0)); + notificationsSpy.clear(); + + // wait for UsbSnap to receive dbusmock's response to the Notify request. + // there's no event to key off of for this, so just wait for a moment + wait_msec(); + + // disconnect the USB before the user has a chance to allow/deny + m_usb_monitor->m_on_usb_disconnected("android0"); + + // confirm that we requested the notification to be pulled down + wait_for_signals(notificationsSpy, 1); + EXPECT_EQ("CloseNotification", notificationsSpy.at(0).at(0)); + notificationsSpy.clear(); + } } -- cgit v1.2.3 From 4f8a17f23a0bba7da7654c147ca377e271abe0db Mon Sep 17 00:00:00 2001 From: Charles Kerr Date: Tue, 22 Mar 2016 16:01:47 -0500 Subject: add tests for not showing snap decisions in greeter mode --- src/usb-manager.cpp | 48 ++++++++++++---------------------- tests/integration/usb-manager-test.cpp | 34 +++++++++++++++++++++--- tests/utils/adbd-server.h | 8 +++--- 3 files changed, 51 insertions(+), 39 deletions(-) (limited to 'tests/integration/usb-manager-test.cpp') diff --git a/src/usb-manager.cpp b/src/usb-manager.cpp index 0e59ca2..4fdfdc1 100644 --- a/src/usb-manager.cpp +++ b/src/usb-manager.cpp @@ -50,7 +50,7 @@ public: }); m_greeter->is_active().changed().connect([this](bool /*is_active*/) { - maybe_snap_now(); + restart(); }); restart(); @@ -68,7 +68,6 @@ private: // clear out old state m_snap_connections.clear(); m_snap.reset(); - m_req = AdbdClient::PKRequest{}; m_adbd_client.reset(); } @@ -76,44 +75,30 @@ private: { clear(); + // don't prompt in the greeter! + if (m_greeter->is_active().get()) + return; + // set a new client +g_message("creating a new adbd client"); m_adbd_client.reset(new GAdbdClient{m_socket_path}); m_adbd_client->on_pk_request().connect( [this](const AdbdClient::PKRequest& req) { g_debug("%s got pk request", G_STRLOC); - m_req = req; - maybe_snap_now(); + m_snap = std::make_shared(req.fingerprint); + m_snap_connections.insert((*m_snap).on_user_response().connect( + [this,req](AdbdClient::PKResponse response, bool remember_choice){ + g_debug("%s user responded! response %d, remember %d", G_STRLOC, int(response), int(remember_choice)); + req.respond(response); + if (remember_choice && (response == AdbdClient::PKResponse::ALLOW)) + write_public_key(req.public_key); + g_idle_add([](gpointer gself){static_cast(gself)->restart(); return G_SOURCE_REMOVE;}, this); + } + )); } ); } - bool ready_to_snap() - { - return !m_greeter->is_active().get() && !m_req.public_key.empty(); - } - - void maybe_snap_now() - { - if (ready_to_snap()) - snap_now(); - } - - void snap_now() - { - g_return_if_fail(ready_to_snap()); - - m_snap = std::make_shared(m_req.fingerprint); - m_snap_connections.insert((*m_snap).on_user_response().connect( - [this](AdbdClient::PKResponse response, bool remember_choice){ - g_debug("%s user responded! response %d, remember %d", G_STRLOC, int(response), int(remember_choice)); - m_req.respond(response); - if (remember_choice && (response == AdbdClient::PKResponse::ALLOW)) - write_public_key(m_req.public_key); - g_idle_add([](gpointer gself){static_cast(gself)->restart(); return G_SOURCE_REMOVE;}, this); - } - )); - } - void write_public_key(const std::string& public_key) { g_debug("%s writing public key '%s' to '%s'", G_STRLOC, public_key.c_str(), m_public_keys_filename.c_str()); @@ -151,7 +136,6 @@ private: const std::shared_ptr m_greeter; std::shared_ptr m_adbd_client; - AdbdClient::PKRequest m_req; std::shared_ptr m_snap; std::set m_snap_connections; }; diff --git a/tests/integration/usb-manager-test.cpp b/tests/integration/usb-manager-test.cpp index 3ce79d0..03c80c7 100644 --- a/tests/integration/usb-manager-test.cpp +++ b/tests/integration/usb-manager-test.cpp @@ -87,7 +87,7 @@ protected: QtDBusMock::DBusMock dbusMock; std::shared_ptr m_tmpdir; std::shared_ptr m_usb_monitor; - std::shared_ptr m_greeter; + std::shared_ptr m_greeter; }; TEST_F(UsbManagerFixture, Allow) @@ -157,7 +157,7 @@ TEST_F(UsbManagerFixture, Allow) EXPECT_EQ(public_key, lines[0]); } -TEST_F(UsbManagerFixture, AndroidInterruptus) +TEST_F(UsbManagerFixture, USBDisconnectedDuringPrompt) { const std::shared_ptr socket_path {new std::string{*m_tmpdir+"/socket"}, file_deleter}; const std::shared_ptr public_keys_path {new std::string{*m_tmpdir+"/adb_keys"}, file_deleter}; @@ -171,7 +171,6 @@ TEST_F(UsbManagerFixture, AndroidInterruptus) for (int i=0; i<3; i++) { -g_message("i %d", i); // add a signal spy to listen to the notification daemon QSignalSpy notificationsSpy( ¬ificationsMockInterface(), @@ -196,3 +195,32 @@ g_message("i %d", i); notificationsSpy.clear(); } } + +TEST_F(UsbManagerFixture, Greeter) +{ + const std::shared_ptr socket_path {new std::string{*m_tmpdir+"/socket"}, file_deleter}; + const std::shared_ptr public_keys_path {new std::string{*m_tmpdir+"/adb_keys"}, file_deleter}; + + // start a mock AdbdServer ready to submit a request + const std::string public_key {"public_key"}; + auto adbd_server = std::make_shared(*socket_path, std::vector{"PK"+public_key}); + + // set up a UsbManager to process the request + m_greeter->m_is_active.set(true); + auto usb_manager = std::make_shared(*socket_path, *public_keys_path, m_usb_monitor, m_greeter); + + // add a signal spy to listen to the notification daemon + QSignalSpy notificationsSpy( + ¬ificationsMockInterface(), + SIGNAL(MethodCalled(const QString &, const QVariantList &)) + ); + + // the greeter is active, so the notification should not appear + EXPECT_FALSE(notificationsSpy.wait(2000)); + + // disable the greeter, the notification should appear + m_greeter->m_is_active.set(false); + wait_for_signals(notificationsSpy, 1); + EXPECT_EQ("Notify", notificationsSpy.at(0).at(0)); + notificationsSpy.clear(); +} diff --git a/tests/utils/adbd-server.h b/tests/utils/adbd-server.h index 968c1f0..5e66379 100644 --- a/tests/utils/adbd-server.h +++ b/tests/utils/adbd-server.h @@ -73,7 +73,7 @@ private: auto client_socket = g_socket_accept(server_socket, m_cancellable, &error); if (error != nullptr) { if (!g_error_matches(error, G_IO_ERROR, G_IO_ERROR_CANCELLED)) - g_warning("GAdbdServer: Error accepting socket connection: %s", error->message); + g_message("GAdbdServer: Error accepting socket connection: %s", error->message); g_clear_error(&error); break; } @@ -90,7 +90,7 @@ private: &error); if (error != nullptr) { if (!g_error_matches(error, G_IO_ERROR, G_IO_ERROR_CANCELLED)) - g_warning("GAdbdServer: Error sending request: %s", error->message); + g_message("GAdbdServer: Error sending request: %s", error->message); g_clear_error(&error); g_clear_object(&client_socket); break; @@ -106,10 +106,10 @@ private: &error); if (error != nullptr) { if (!g_error_matches(error, G_IO_ERROR, G_IO_ERROR_CANCELLED)) - g_warning("GAdbdServer: Error reading response: %s", error->message); + g_message("GAdbdServer: Error reading response: %s", error->message); g_clear_error(&error); g_clear_object(&client_socket); - break; + continue; } const std::string response(buf, std::string::size_type(n_bytes)); g_message("server got response: %s", response.c_str()); -- cgit v1.2.3 From 82588108a40fb50b2bbd3c7b89b990f76f488edc Mon Sep 17 00:00:00 2001 From: Charles Kerr Date: Wed, 23 Mar 2016 12:16:06 -0500 Subject: replace text 'Deny' with 'Don't Allow' for consistency with other permission prompts --- src/usb-snap.cpp | 2 +- tests/integration/usb-manager-test.cpp | 2 +- tests/unit/usb-snap-test.cpp | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) (limited to 'tests/integration/usb-manager-test.cpp') diff --git a/src/usb-snap.cpp b/src/usb-snap.cpp index 41c78c6..ba964fb 100644 --- a/src/usb-snap.cpp +++ b/src/usb-snap.cpp @@ -111,7 +111,7 @@ private: g_variant_builder_add(&actions_builder, "s", ACTION_ALLOW); g_variant_builder_add(&actions_builder, "s", _("Allow")); g_variant_builder_add(&actions_builder, "s", ACTION_DENY); - g_variant_builder_add(&actions_builder, "s", _("Deny")); + g_variant_builder_add(&actions_builder, "s", _("Don't Allow")); GVariantBuilder hints_builder; g_variant_builder_init(&hints_builder, G_VARIANT_TYPE_VARDICT); diff --git a/tests/integration/usb-manager-test.cpp b/tests/integration/usb-manager-test.cpp index 03c80c7..d62756f 100644 --- a/tests/integration/usb-manager-test.cpp +++ b/tests/integration/usb-manager-test.cpp @@ -122,7 +122,7 @@ TEST_F(UsbManagerFixture, Allow) EXPECT_EQ("computer-symbolic", args.at(2)); // icon name EXPECT_EQ("Allow USB Debugging?", args.at(3)); // summary EXPECT_EQ(QString::fromUtf8("The computer's RSA key fingerprint is: ") + QString::fromUtf8(fingerprint.c_str()), args.at(4)); // body - EXPECT_EQ(QStringList({"allow", "Allow", "deny", "Deny"}), args.at(5)); // actions + EXPECT_EQ(QStringList({"allow", "Allow", "deny", "Don't Allow"}), args.at(5)); // actions EXPECT_EQ(-1, args.at(7)); QVariantMap hints; diff --git a/tests/unit/usb-snap-test.cpp b/tests/unit/usb-snap-test.cpp index 40de94a..3b778dd 100644 --- a/tests/unit/usb-snap-test.cpp +++ b/tests/unit/usb-snap-test.cpp @@ -106,7 +106,7 @@ TEST_F(UsbSnapFixture, TestRoundTrip) EXPECT_EQ("computer-symbolic", args.at(2)); // icon name EXPECT_EQ("Allow USB Debugging?", args.at(3)); // summary EXPECT_EQ(QString::fromUtf8("The computer's RSA key fingerprint is: ") + test.fingerprint, args.at(4)); // body - EXPECT_EQ(QStringList({"allow", "Allow", "deny", "Deny"}), args.at(5)); // actions + EXPECT_EQ(QStringList({"allow", "Allow", "deny", "Don't Allow"}), args.at(5)); // actions EXPECT_EQ(-1, args.at(7)); QVariantMap hints; -- cgit v1.2.3