loolwsd/Admin.cpp           |   79 +------
 loolwsd/Admin.hpp           |    3 
 loolwsd/AdminModel.cpp      |    2 
 loolwsd/Unit.hpp            |    6 
 loolwsd/test/Makefile.am    |    9 
 loolwsd/test/UnitAdmin.cpp  |  451 ++++++++++++++++++++++++++++++++++++++++++++
 loolwsd/test/run_unit.sh.in |    2 
 7 files changed, 486 insertions(+), 66 deletions(-)

New commits:
commit 3e93a212f09e51577bb787093643a0d998b20b61
Author: Pranav Kant <pran...@collabora.com>
Date:   Mon Apr 18 18:59:17 2016 +0530

    loolwsd: Admin console unit tests
    
    Change-Id: Id0baa51c2adb14b77080b5acd2abf0658ee54b2b

diff --git a/loolwsd/Admin.cpp b/loolwsd/Admin.cpp
index a350ba9..e246495 100644
--- a/loolwsd/Admin.cpp
+++ b/loolwsd/Admin.cpp
@@ -35,6 +35,7 @@
 #include "LOOLProtocol.hpp"
 #include "LOOLWSD.hpp"
 #include "IoUtil.hpp"
+#include "Unit.hpp"
 #include "Util.hpp"
 
 using namespace LOOLProtocol;
@@ -272,6 +273,7 @@ AdminRequestHandler::AdminRequestHandler(Admin* 
adminManager)
 
 void AdminRequestHandler::sendTextFrame(std::shared_ptr<Poco::Net::WebSocket>& 
socket, const std::string& message)
 {
+    UnitWSD::get().onAdminQueryMessage(message);
     socket->sendFrame(message.data(), message.size());
 }
 
diff --git a/loolwsd/AdminModel.cpp b/loolwsd/AdminModel.cpp
index ccc342f..d9f10a0 100644
--- a/loolwsd/AdminModel.cpp
+++ b/loolwsd/AdminModel.cpp
@@ -17,6 +17,7 @@
 #include <Poco/StringTokenizer.h>
 
 #include "AdminModel.hpp"
+#include "Unit.hpp"
 #include "Util.hpp"
 
 using Poco::StringTokenizer;
@@ -65,6 +66,7 @@ bool Subscriber::notify(const std::string& message)
     auto webSocket = _ws.lock();
     if (webSocket)
     {
+        UnitWSD::get().onAdminNotifyMessage(message);
         webSocket->sendFrame(message.data(), message.length());
         return true;
     }
diff --git a/loolwsd/Unit.hpp b/loolwsd/Unit.hpp
index c9a7a6d..05d5696 100644
--- a/loolwsd/Unit.hpp
+++ b/loolwsd/Unit.hpp
@@ -14,6 +14,8 @@
 #include <atomic>
 #include <assert.h>
 
+#include <Poco/Net/WebSocket.h>
+
 class UnitBase;
 class UnitWSD;
 class UnitKit;
@@ -133,6 +135,10 @@ public:
 
     // ---------------- WSD events ----------------
     virtual void onChildConnected(const int /* pid */, const std::string& /* 
sessionId */) {}
+    /// When admin notify message is sent
+    virtual void onAdminNotifyMessage(const std::string& /* message */) {}
+    /// When admin message is sent in response to a query
+    virtual void onAdminQueryMessage(const std::string& /* message */) {}
 };
 
 /// Derive your Kit unit test / hooks from me.
diff --git a/loolwsd/test/Makefile.am b/loolwsd/test/Makefile.am
index 0a40ef3..98d3f3f 100644
--- a/loolwsd/test/Makefile.am
+++ b/loolwsd/test/Makefile.am
@@ -5,8 +5,9 @@ check_PROGRAMS = test
 AM_CXXFLAGS = $(CPPUNIT_CFLAGS)
 
 noinst_LTLIBRARIES = \
-       unit-timeout.la unit-prefork.la \
-        unit-storage.la unit-fonts.la
+        unit-timeout.la unit-prefork.la \
+        unit-storage.la unit-fonts.la \
+        unit-admin.la
 
 MAGIC_TO_FORCE_SHLIB_CREATION = -rpath /dummy
 AM_LDFLAGS = -module $(MAGIC_TO_FORCE_SHLIB_CREATION)
@@ -17,6 +18,8 @@ test_SOURCES = WhiteBoxTests.cpp httpposttest.cpp 
httpwstest.cpp test.cpp ../LOO
 test_LDADD = $(CPPUNIT_LIBS)
 
 # unit test modules:
+unit_admin_la_SOURCES = UnitAdmin.cpp
+unit_admin_la_CPPFLAGS = -DTDOC=\"$(top_srcdir)/test/data\"
 unit_fonts_la_SOURCES = UnitFonts.cpp
 unit_timeout_la_SOURCES = UnitTimeout.cpp
 unit_prefork_la_SOURCES = UnitPrefork.cpp
@@ -29,7 +32,7 @@ SYSTEM_STAMP =
 endif
 
 if HAVE_LO_PATH
-TESTS = unit-timeout.la unit-fonts.la unit-storage.la unit-prefork.la 
run_test.sh
+TESTS = unit-admin.la unit-timeout.la unit-fonts.la unit-storage.la 
unit-prefork.la run_test.sh
 else
 TESTS = ${top_builddir}/test/test
 endif
diff --git a/loolwsd/test/UnitAdmin.cpp b/loolwsd/test/UnitAdmin.cpp
new file mode 100644
index 0000000..e4b2bb6
--- /dev/null
+++ b/loolwsd/test/UnitAdmin.cpp
@@ -0,0 +1,451 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4; 
fill-column: 100 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ */
+
+#include "config.h"
+
+#include <cassert>
+#include <condition_variable>
+#include <mutex>
+
+#include "Common.hpp"
+#include "Unit.hpp"
+#include "Util.hpp"
+#include "Log.hpp"
+
+#include <Poco/StringTokenizer.h>
+#include <Poco/Net/HTTPBasicCredentials.h>
+#include <Poco/Net/HTTPCookie.h>
+#include <Poco/Net/HTTPResponse.h>
+#include <Poco/Net/HTTPClientSession.h>
+#include <Poco/Net/HTTPSClientSession.h>
+#include <Poco/Net/HTTPServerRequest.h>
+#include <Poco/Net/NameValueCollection.h>
+#include <Poco/Net/NetException.h>
+#include <Poco/Net/WebSocket.h>
+#include <Poco/StringTokenizer.h>
+#include <Poco/URI.h>
+
+#define UNIT_URI "/loolwsd/unit-admin"
+
+using Poco::Net::HTTPBasicCredentials;
+using Poco::Net::HTTPCookie;
+using Poco::Net::HTTPRequest;
+using Poco::Net::HTTPResponse;
+using Poco::Net::HTTPSClientSession;
+using Poco::StringTokenizer;
+
+// Inside the WSD process
+class UnitAdmin : public UnitWSD
+{
+private:
+    unsigned _testCounter = 0;
+    std::string _jwtCookie;
+    bool _isTestRunning = false;
+    const Poco::URI _uri;
+    std::shared_ptr<Poco::Net::WebSocket> _adminWs;
+
+    typedef TestResult (UnitAdmin::*AdminTest)(void);
+    std::vector<AdminTest> _tests;
+
+    std::shared_ptr<Poco::Net::WebSocket> _docWs1;
+    std::shared_ptr<Poco::Net::WebSocket> _docWs2;
+    std::shared_ptr<Poco::Net::WebSocket> _docWs3;
+    int _docPid1;
+    int _docPid2;
+    int _docPid3;
+    int _usersCount = 0;
+    int _docsCount = 0;
+
+    int  _messageTimeoutMilliSeconds = 5000;
+    std::condition_variable _messageReceivedCV;
+    std::mutex _messageReceivedMutex;
+    std::string _messageReceived;
+
+// Tests
+private:
+    TestResult testIncorrectPassword()
+    {
+        HTTPResponse response;
+        std::string path(_uri.getPathAndQuery());
+        HTTPRequest request(HTTPRequest::HTTP_GET, path);
+        HTTPSClientSession session(_uri.getHost(), _uri.getPort());
+
+        session.sendRequest(request);
+        session.receiveResponse(response);
+        TestResult res = TestResult::TEST_FAILED;
+        if (response.getStatus() == HTTPResponse::HTTP_UNAUTHORIZED)
+            res = TestResult::TEST_OK;
+
+        Log::info("testIncorrectPassword: " + (res == TestResult::TEST_OK) ? 
"OK" : "FAIL");
+        return res;
+    }
+
+    TestResult testCorrectPassword()
+    {
+        HTTPResponse response;
+        std::string path(_uri.getPathAndQuery());
+        HTTPRequest request(HTTPRequest::HTTP_GET, path);
+        HTTPSClientSession session(_uri.getHost(), _uri.getPort());
+        HTTPBasicCredentials credentials("admin", "admin");
+        credentials.authenticate(request);
+
+        session.sendRequest(request);
+        session.receiveResponse(response);
+        std::vector<HTTPCookie> cookies;
+        response.getCookies(cookies);
+
+        // For now we only set one cookie
+        assert(cookies.size() == 1);
+        // and it is jwt=
+        assert(cookies[0].getName() == "jwt");
+
+        // Check cookie properties
+        std::string cookiePath = cookies[0].getPath();
+        bool secure = cookies[0].getSecure();
+        bool httpOnly = cookies[0].getHttpOnly();
+        std::string value = cookies[0].getValue();
+        TestResult res = TestResult::TEST_FAILED;
+        if (cookiePath.find_first_of("/adminws/") == 0 &&
+            secure &&
+            httpOnly &&
+            value != "")
+        {
+            // Set JWT cookie to be used for subsequent tests
+            _jwtCookie = value;
+            res = TestResult::TEST_OK;
+        }
+
+        Log::info("testCorrectPassword: " + (res == TestResult::TEST_OK) ? 
"OK" : "FAIL");
+        return res;
+    }
+
+    TestResult testWebSocketWithoutCookie()
+    {
+        // try connecting without cookie; should result in exception
+        HTTPResponse response;
+        HTTPRequest request(HTTPRequest::HTTP_GET, "/adminws/");
+        HTTPSClientSession session(_uri.getHost(), _uri.getPort());
+        bool authorized = true;
+        try
+        {
+            _adminWs = std::make_shared<Poco::Net::WebSocket>(session, 
request, response);
+        }
+        catch (const Poco::Net::WebSocketException& exc)
+        {
+            Log::info() << "Admin websocket: Not authorized " << Log::end;
+            authorized = false;
+        }
+
+        // no cookie -> should result in not authorized exception
+        TestResult res = TestResult::TEST_FAILED;
+        if (!authorized)
+            res = TestResult::TEST_OK;
+
+        Log::info("testWebSocketWithoutCookie: " + (res == 
TestResult::TEST_OK) ? "OK" : "FAIL");
+        return res;
+    }
+
+    TestResult testWebSocketWithCookie()
+    {
+        HTTPResponse response;
+        HTTPRequest request(HTTPRequest::HTTP_GET, "/adminws/");
+        HTTPSClientSession session(_uri.getHost(), _uri.getPort());
+
+        // set cookie
+        assert(_jwtCookie != "");
+        HTTPCookie cookie("jwt", _jwtCookie);
+        Poco::Net::NameValueCollection nvc;
+        nvc.add("jwt", _jwtCookie);
+        request.setCookies(nvc);
+
+        bool authorized = true;
+        try
+        {
+            _adminWs = std::make_shared<Poco::Net::WebSocket>(session, 
request, response);
+        }
+        catch (const Poco::Net::WebSocketException& exc)
+        {
+            Log::info() << "Admin websocket: Not authorized " << Log::end;
+            authorized = false;
+        }
+
+        TestResult res = TestResult::TEST_FAILED;
+        if (authorized)
+            res = TestResult::TEST_OK;
+
+        Log::info("testWebSocketWithCookie: " + (res == TestResult::TEST_OK) ? 
"OK" : "FAIL");
+        return res;
+    }
+
+    TestResult testAddDocNotify()
+    {
+        // subscribe notification on admin websocket
+        const std::string subscribeMessage = "subscribe adddoc";
+        _adminWs->sendFrame(subscribeMessage.data(), subscribeMessage.size());
+
+        const std::string documentPath1 = Util::getTempFilePath(TDOC, 
"hello.odt");
+        const std::string documentURL1 = "file://" + 
Poco::Path(documentPath1).makeAbsolute().toString();
+        HTTPRequest request1(HTTPRequest::HTTP_GET, documentURL1);
+        HTTPResponse response1;
+        const Poco::URI docUri1("https://127.0.0.1:"; + 
std::to_string(DEFAULT_CLIENT_PORT_NUMBER));
+        const std::string loadMessage1 = "load url=" + documentURL1;
+        HTTPSClientSession session1(docUri1.getHost(), docUri1.getPort());
+        HTTPSClientSession session2(docUri1.getHost(), docUri1.getPort());
+        _docWs1 = std::make_shared<Poco::Net::WebSocket>(session1, request1, 
response1);
+        _docWs2 = std::make_shared<Poco::Net::WebSocket>(session2, request1, 
response1);
+
+        {
+            _messageReceived.clear();
+            _docWs1->sendFrame(loadMessage1.data(), loadMessage1.size());
+
+            std::unique_lock<std::mutex> lock(_messageReceivedMutex);
+            if (_messageReceived.empty() &&
+                _messageReceivedCV.wait_for(lock, 
std::chrono::milliseconds(_messageTimeoutMilliSeconds)) == 
std::cv_status::timeout)
+            {
+                Log::info("testAddDocNotify: Timed out waiting for admin 
console message");
+                return TestResult::TEST_TIMED_OUT;
+            }
+            lock.unlock();
+
+            StringTokenizer tokens(_messageReceived, " ", 
StringTokenizer::TOK_IGNORE_EMPTY | StringTokenizer::TOK_TRIM);
+            if (tokens.count() != 5 ||
+                tokens[0] != "adddoc" ||
+                tokens[2] != 
documentPath1.substr(documentPath1.find_last_of("/") + 1) )
+            {
+                Log::info("testAddDocNotify: Unrecognized message format");
+                return TestResult::TEST_FAILED;
+            }
+
+            // store document pid
+            _docPid1 = std::stoi(tokens[1]);
+            _usersCount++;
+        }
+        _docsCount++;
+
+
+        // Open another view of same document
+        {
+            // Send another load request for same document
+            _messageReceived.clear();
+            _docWs2->sendFrame(loadMessage1.data(), loadMessage1.size());
+
+            std::unique_lock<std::mutex> lock(_messageReceivedMutex);
+            if (_messageReceived.empty() &&
+                _messageReceivedCV.wait_for(lock, 
std::chrono::milliseconds(_messageTimeoutMilliSeconds)) == 
std::cv_status::timeout)
+            {
+                Log::info("testAddDocNotify: Timed out waiting for admin 
console message");
+                return TestResult::TEST_TIMED_OUT;
+            }
+            lock.unlock();
+
+            StringTokenizer tokens(_messageReceived, " ", 
StringTokenizer::TOK_IGNORE_EMPTY | StringTokenizer::TOK_TRIM);
+            if (tokens.count() != 5 ||
+                tokens[0] != "adddoc" ||
+                tokens[2] != 
documentPath1.substr(documentPath1.find_last_of("/") + 1) )
+            {
+                Log::info("testAddDocNotify: Unrecognized message format");
+                return TestResult::TEST_FAILED;
+            }
+
+            // store document pid
+            _docPid2 = std::stoi(tokens[1]);
+            _usersCount++;
+        }
+
+        // Open another document (different)
+        const std::string documentPath2 = Util::getTempFilePath(TDOC, 
"insert-delete.odp");
+        const std::string documentURL2 = "file://" + 
Poco::Path(documentPath2).makeAbsolute().toString();
+        HTTPRequest request2(HTTPRequest::HTTP_GET, documentURL2);
+        HTTPResponse response2;
+        const Poco::URI docUri2("https://127.0.0.1:"; + 
std::to_string(DEFAULT_CLIENT_PORT_NUMBER));
+        const std::string loadMessage2 = "load url=" + documentURL2;
+        HTTPSClientSession session3(docUri2.getHost(), docUri2.getPort());
+        _docWs3 = std::make_shared<Poco::Net::WebSocket>(session3, request2, 
response2);
+
+        {
+            _messageReceived.clear();
+            _docWs3->sendFrame(loadMessage2.data(), loadMessage2.size());
+
+            std::unique_lock<std::mutex> lock(_messageReceivedMutex);
+            if (_messageReceived.empty() &&
+                _messageReceivedCV.wait_for(lock, 
std::chrono::milliseconds(_messageTimeoutMilliSeconds)) == 
std::cv_status::timeout)
+            {
+                Log::info("testAddDocNotify: Timed out waiting for admin 
console message");
+                return TestResult::TEST_TIMED_OUT;
+            }
+            lock.unlock();
+
+            StringTokenizer tokens(_messageReceived, " ", 
StringTokenizer::TOK_IGNORE_EMPTY | StringTokenizer::TOK_TRIM);
+            if (tokens.count() != 5 ||
+                tokens[0] != "adddoc" ||
+                tokens[2] != 
documentPath2.substr(documentPath2.find_last_of("/") + 1) )
+            {
+                Log::info("testAddDocNotify: Unrecognized message format");
+                return TestResult::TEST_FAILED;
+            }
+
+            // store document pid
+            _docPid3 = std::stoi(tokens[1]);
+            _usersCount++;
+        }
+        _docsCount++;
+
+        return TestResult::TEST_OK;
+    }
+
+    TestResult testUsersCount()
+    {
+        _messageReceived.clear();
+
+        // We should have 3 users by now; lets verify
+        const std::string queryMessage = "active_users_count";
+        _adminWs->sendFrame(queryMessage.data(), queryMessage.size());
+
+        std::unique_lock<std::mutex> lock(_messageReceivedMutex);
+        if (_messageReceived.empty() &&
+            _messageReceivedCV.wait_for(lock, 
std::chrono::milliseconds(_messageTimeoutMilliSeconds)) == 
std::cv_status::timeout)
+        {
+            Log::info("testAddDocNotify: Timed out waiting for admin console 
message");
+            return TestResult::TEST_TIMED_OUT;
+        }
+        lock.unlock();
+
+        StringTokenizer tokens(_messageReceived, " ", 
StringTokenizer::TOK_IGNORE_EMPTY | StringTokenizer::TOK_TRIM);
+        if (tokens.count() != 2 ||
+            tokens[0] != "active_users_count" ||
+            std::stoi(tokens[1]) != _usersCount)
+        {
+            Log::info("testAddDocNotify: Unrecognized message format");
+            return TestResult::TEST_FAILED;
+        }
+
+        return TestResult::TEST_OK;
+    }
+
+    TestResult testDocCount()
+    {
+        _messageReceived.clear();
+
+        // We should have 2 total docs open by now; lets verify
+        const std::string queryMessage = "active_docs_count";
+        _adminWs->sendFrame(queryMessage.data(), queryMessage.size());
+
+        std::unique_lock<std::mutex> lock(_messageReceivedMutex);
+        if (_messageReceived.empty() &&
+            _messageReceivedCV.wait_for(lock, 
std::chrono::milliseconds(_messageTimeoutMilliSeconds)) == 
std::cv_status::timeout)
+        {
+            Log::info("testAddDocNotify: Timed out waiting for admin console 
message");
+            return TestResult::TEST_TIMED_OUT;
+        }
+        lock.unlock();
+
+        StringTokenizer tokens(_messageReceived, " ", 
StringTokenizer::TOK_IGNORE_EMPTY | StringTokenizer::TOK_TRIM);
+        if (tokens.count() != 2 ||
+            tokens[0] != "active_docs_count" ||
+            std::stoi(tokens[1]) != _docsCount)
+        {
+            Log::info("testAddDocNotify: Unrecognized message format");
+            return TestResult::TEST_FAILED;
+        }
+
+        return TestResult::TEST_OK;
+    }
+
+    TestResult testRmDocNotify()
+    {
+        _messageReceived.clear();
+
+        // subscribe to rmdoc notification on admin websocket
+        const std::string subscribeMessage = "subscribe rmdoc";
+        _adminWs->sendFrame(subscribeMessage.data(), subscribeMessage.size());
+
+        _docWs1->close();
+        std::unique_lock<std::mutex> lock(_messageReceivedMutex);
+        if (_messageReceived.empty() &&
+            _messageReceivedCV.wait_for(lock, 
std::chrono::milliseconds(_messageTimeoutMilliSeconds)) == 
std::cv_status::timeout)
+        {
+            Log::info("testRmDocNotify: Timed out waiting for admin console 
message");
+            return TestResult::TEST_TIMED_OUT;
+        }
+        lock.unlock();
+
+        StringTokenizer tokens(_messageReceived, " ", 
StringTokenizer::TOK_IGNORE_EMPTY | StringTokenizer::TOK_TRIM);
+        if (tokens.count() != 3 ||
+            tokens[0] != "rmdoc" ||
+            stoi(tokens[1]) != _docPid1)
+        {
+            Log::info("testRmDocNotify: Invalid message format");
+            return TestResult::TEST_FAILED;
+        }
+        _usersCount--;
+
+        return TestResult::TEST_OK;
+    }
+
+
+public:
+    UnitAdmin()
+        : _uri("https://127.0.0.1:"; + 
std::to_string(DEFAULT_CLIENT_PORT_NUMBER) + "/loleaflet/dist/admin/admin.html")
+    {
+        // Register tests here.
+        _tests.push_back(&UnitAdmin::testIncorrectPassword);
+        _tests.push_back(&UnitAdmin::testCorrectPassword);
+        _tests.push_back(&UnitAdmin::testWebSocketWithoutCookie);
+        _tests.push_back(&UnitAdmin::testWebSocketWithCookie);
+        _tests.push_back(&UnitAdmin::testAddDocNotify);
+        _tests.push_back(&UnitAdmin::testUsersCount);
+        _tests.push_back(&UnitAdmin::testDocCount);
+        _tests.push_back(&UnitAdmin::testRmDocNotify);
+        _tests.push_back(&UnitAdmin::testUsersCount);
+        _tests.push_back(&UnitAdmin::testDocCount);
+    }
+
+    // Runs tests sequentially in _tests
+    virtual void invokeTest()
+    {
+        if (!_isTestRunning)
+        {
+            _isTestRunning = true;
+            AdminTest test = _tests[_testCounter++];
+            TestResult res = ((*this).*(test))();
+            if (res != TestResult::TEST_OK)
+            {
+                exitTest(res);
+                return;
+            }
+
+            // End this when all tests are finished
+            if (_tests.size() == _testCounter)
+                exitTest(TestResult::TEST_OK);
+
+            _isTestRunning = false;
+        }
+    }
+
+    virtual void onAdminNotifyMessage(const std::string& message)
+    {
+        std::unique_lock<std::mutex> lock(_messageReceivedMutex);
+        _messageReceivedCV.notify_all();
+        _messageReceived = message;
+    }
+
+    virtual void onAdminQueryMessage(const std::string& message)
+    {
+        std::unique_lock<std::mutex> lock(_messageReceivedMutex);
+        _messageReceivedCV.notify_all();
+        _messageReceived = message;
+    }
+};
+
+UnitBase *unit_create_wsd(void)
+{
+    return new UnitAdmin();
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/loolwsd/test/run_unit.sh.in b/loolwsd/test/run_unit.sh.in
index 1af8b86..acfac8e 100755
--- a/loolwsd/test/run_unit.sh.in
+++ b/loolwsd/test/run_unit.sh.in
@@ -76,6 +76,8 @@ else # newer unit tests.
     if ${abs_top_builddir}/loolwsd --systemplate="$systemplate_path" \
                                    --lotemplate="$lo_path" \
                                    --childroot="$jails_path" \
+                                   --allowlocalstorage \
+                                   --admincreds=admin/admin \
                                    --unitlib=".libs/$tst.so" 2> "$tst_log"; 
then
         echo "Test $tst passed."
         echo ":test-result: PASS $tst" >> $test_output
commit 3111c5c6d162cffa1df86b642891eb840e086ea6
Author: Pranav Kant <pran...@collabora.com>
Date:   Tue Apr 19 12:57:28 2016 +0530

    loolwsd: Use common method to send websocket messages
    
    Will help in placing unit test hooks to better test the admin
    console
    
    Change-Id: Ic4daae685a8fe493a0395d94e40112bf119c93e3

diff --git a/loolwsd/Admin.cpp b/loolwsd/Admin.cpp
index b1a4fc7..a350ba9 100644
--- a/loolwsd/Admin.cpp
+++ b/loolwsd/Admin.cpp
@@ -117,7 +117,16 @@ void 
AdminRequestHandler::handleWSRequests(HTTPServerRequest& request, HTTPServe
                     std::unique_lock<std::mutex> modelLock(_admin->getLock());
                     AdminModel& model = _admin->getModel();
 
-                    if (tokens[0] == "subscribe" && tokens.count() > 1)
+                    if (tokens[0] == "documents" ||
+                        tokens[0] == "active_users_count" ||
+                        tokens[0] == "active_docs_count" ||
+                        tokens[0] == "mem_stats" ||
+                        tokens[0] == "cpu_stats" )
+                    {
+                        const std::string responseFrame = tokens[0] + " " + 
model.query(tokens[0]);
+                        sendTextFrame(ws, responseFrame);
+                    }
+                    else if (tokens[0] == "subscribe" && tokens.count() > 1)
                     {
                         for (unsigned i = 0; i < tokens.count() - 1; i++)
                         {
@@ -131,26 +140,11 @@ void 
AdminRequestHandler::handleWSRequests(HTTPServerRequest& request, HTTPServe
                             model.unsubscribe(nSessionId, tokens[i + 1]);
                         }
                     }
-                    else if (tokens[0] == "documents")
-                    {
-                        std::string responseString = "documents " + 
model.query("documents");
-                        ws->sendFrame(responseString.data(), 
responseString.size());
-                    }
                     else if (tokens[0] == "total_mem")
                     {
                         unsigned totalMem = _admin->getTotalMemoryUsage(model);
                         std::string responseFrame = "total_mem " + 
std::to_string(totalMem);
-                        ws->sendFrame(responseFrame.data(), 
responseFrame.size());
-                    }
-                    else if (tokens[0] == "active_users_count")
-                    {
-                        std::string responseFrame = tokens[0] + " " + 
model.query(tokens[0]);
-                        ws->sendFrame(responseFrame.data(), 
responseFrame.size());
-                    }
-                    else if (tokens[0] == "active_docs_count")
-                    {
-                        std::string responseFrame = tokens[0] + " " + 
model.query(tokens[0]);
-                        ws->sendFrame(responseFrame.data(), 
responseFrame.size());
+                        sendTextFrame(ws, responseFrame);
                     }
                     else if (tokens[0] == "kill" && tokens.count() == 2)
                     {
@@ -167,24 +161,6 @@ void 
AdminRequestHandler::handleWSRequests(HTTPServerRequest& request, HTTPServe
                             Log::warn() << "Invalid PID to kill: " << 
tokens[0] << Log::end;
                         }
                     }
-                    else if (tokens[0] == "mem_stats")
-                    {
-                        std::ostringstream oss;
-                        oss << tokens[0] << " "
-                            << model.query(tokens[0]);
-
-                        std::string responseFrame = oss.str();
-                        ws->sendFrame(responseFrame.data(), 
responseFrame.size());
-                    }
-                    else if (tokens[0] == "cpu_stats")
-                    {
-                        std::ostringstream oss;
-                        oss << tokens[0] << " "
-                            << model.query(tokens[0]);
-
-                        std::string responseFrame = oss.str();
-                        ws->sendFrame(responseFrame.data(), 
responseFrame.size());
-                    }
                     else if (tokens[0] == "settings")
                     {
                         // for now, we have only these settings
@@ -196,7 +172,7 @@ void 
AdminRequestHandler::handleWSRequests(HTTPServerRequest& request, HTTPServe
                             << "cpu_stats_interval=" << 
std::to_string(_admin->getCpuStatsInterval());
 
                         std::string responseFrame = oss.str();
-                        ws->sendFrame(responseFrame.data(), 
responseFrame.size());
+                        sendTextFrame(ws, responseFrame);
                     }
                     else if (tokens[0] == "set" && tokens.count() > 1)
                     {
@@ -294,6 +270,11 @@ AdminRequestHandler::AdminRequestHandler(Admin* 
adminManager)
     : _admin(adminManager)
 {    }
 
+void AdminRequestHandler::sendTextFrame(std::shared_ptr<Poco::Net::WebSocket>& 
socket, const std::string& message)
+{
+    socket->sendFrame(message.data(), message.size());
+}
+
 void AdminRequestHandler::handleRequest(HTTPServerRequest& request, 
HTTPServerResponse& response)
 {
     // Different session id pool for admin sessions (?)
diff --git a/loolwsd/Admin.hpp b/loolwsd/Admin.hpp
index 3e66b17..f315efa 100644
--- a/loolwsd/Admin.hpp
+++ b/loolwsd/Admin.hpp
@@ -13,6 +13,7 @@
 #include <Poco/Net/HTTPRequest.h>
 #include <Poco/Net/HTTPRequestHandler.h>
 #include <Poco/Net/HTTPServer.h>
+#include <Poco/Net/WebSocket.h>
 #include <Poco/Runnable.h>
 #include <Poco/Types.h>
 #include <Poco/Util/Timer.h>
@@ -32,6 +33,8 @@ public:
 private:
     void handleWSRequests(Poco::Net::HTTPServerRequest& request, 
Poco::Net::HTTPServerResponse& response, int nSessionId);
 
+    void sendTextFrame(std::shared_ptr<Poco::Net::WebSocket>& socket, const 
std::string& message);
+
 private:
     Admin* _admin;
 };
commit 56d18909d531f7c819954e503b71911349f4eab7
Author: Pranav Kant <pran...@collabora.com>
Date:   Tue Apr 19 12:37:07 2016 +0530

    loolwsd: Remove unused code
    
    Change-Id: I7edf6b8d4f83f2cf9f85a2075d1dca216cda3d34

diff --git a/loolwsd/Admin.cpp b/loolwsd/Admin.cpp
index dcd9ad4..b1a4fc7 100644
--- a/loolwsd/Admin.cpp
+++ b/loolwsd/Admin.cpp
@@ -117,36 +117,7 @@ void 
AdminRequestHandler::handleWSRequests(HTTPServerRequest& request, HTTPServe
                     std::unique_lock<std::mutex> modelLock(_admin->getLock());
                     AdminModel& model = _admin->getModel();
 
-                    if (tokens[0] == "stats")
-                    {
-                        //TODO: Collect stats and reply back to admin.
-                        // We need to ask ForKit to give us some numbers on 
docs/clients/etc.
-                        // But we can also collect some memory info using 
system calls.
-
-                        std::string statsResponse;
-
-                        const auto cmd = "pstree -a -c -h -A -p " + 
std::to_string(getpid());
-                        FILE* fp = popen(cmd.c_str(), "r");
-                        if (fp == nullptr)
-                        {
-                            statsResponse = "error: failed to collect stats.";
-                            ws->sendFrame(statsResponse.data(), 
statsResponse.size());
-                            continue;
-                        }
-
-                        char treeBuffer[1024];
-                        while (fgets(treeBuffer, sizeof(treeBuffer)-1, fp) != 
nullptr &&
-                               !TerminationFlag)
-                        {
-                            statsResponse += treeBuffer;
-                            statsResponse += "</ BR>\n";
-                        }
-
-                        pclose(fp);
-
-                        ws->sendFrame(statsResponse.data(), 
statsResponse.size());
-                    }
-                    else if (tokens[0] == "subscribe" && tokens.count() > 1)
+                    if (tokens[0] == "subscribe" && tokens.count() > 1)
                     {
                         for (unsigned i = 0; i < tokens.count() - 1; i++)
                         {
@@ -162,7 +133,6 @@ void 
AdminRequestHandler::handleWSRequests(HTTPServerRequest& request, HTTPServe
                     }
                     else if (tokens[0] == "documents")
                     {
-
                         std::string responseString = "documents " + 
model.query("documents");
                         ws->sendFrame(responseString.data(), 
responseString.size());
                     }
_______________________________________________
Libreoffice-commits mailing list
libreoffice-comm...@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/libreoffice-commits

Reply via email to