pushnotificationstestutils.cpp 5.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209
  1. #include <QLoggingCategory>
  2. #include <QSignalSpy>
  3. #include <QTest>
  4. #include <functional>
  5. #include "pushnotificationstestutils.h"
  6. #include "pushnotifications.h"
  7. Q_LOGGING_CATEGORY(lcFakeWebSocketServer, "nextcloud.test.fakewebserver", QtInfoMsg)
  8. FakeWebSocketServer::FakeWebSocketServer(quint16 port, QObject *parent)
  9. : QObject(parent)
  10. , _webSocketServer(new QWebSocketServer(QStringLiteral("Fake Server"), QWebSocketServer::NonSecureMode, this))
  11. {
  12. if (!_webSocketServer->listen(QHostAddress::Any, port)) {
  13. Q_UNREACHABLE();
  14. }
  15. connect(_webSocketServer, &QWebSocketServer::newConnection, this, &FakeWebSocketServer::onNewConnection);
  16. connect(_webSocketServer, &QWebSocketServer::closed, this, &FakeWebSocketServer::closed);
  17. qCInfo(lcFakeWebSocketServer) << "Open fake websocket server on port:" << port;
  18. _processTextMessageSpy = std::make_unique<QSignalSpy>(this, &FakeWebSocketServer::processTextMessage);
  19. }
  20. FakeWebSocketServer::~FakeWebSocketServer()
  21. {
  22. close();
  23. }
  24. QWebSocket *FakeWebSocketServer::authenticateAccount(const OCC::AccountPtr account, std::function<void(OCC::PushNotifications *pushNotifications)> beforeAuthentication, std::function<void(void)> afterAuthentication)
  25. {
  26. const auto pushNotifications = account->pushNotifications();
  27. Q_ASSERT(pushNotifications);
  28. QSignalSpy readySpy(pushNotifications, &OCC::PushNotifications::ready);
  29. beforeAuthentication(pushNotifications);
  30. // Wait for authentication
  31. if (!waitForTextMessages()) {
  32. return nullptr;
  33. }
  34. // Right authentication data should be sent
  35. if (textMessagesCount() != 2) {
  36. return nullptr;
  37. }
  38. const auto socket = socketForTextMessage(0);
  39. const auto userSent = textMessage(0);
  40. const auto passwordSent = textMessage(1);
  41. if (userSent != account->credentials()->user() || passwordSent != account->credentials()->password()) {
  42. return nullptr;
  43. }
  44. // Sent authenticated
  45. socket->sendTextMessage("authenticated");
  46. // Wait for ready signal
  47. readySpy.wait();
  48. if (readySpy.count() != 1 || !account->pushNotifications()->isReady()) {
  49. return nullptr;
  50. }
  51. afterAuthentication();
  52. return socket;
  53. }
  54. void FakeWebSocketServer::close()
  55. {
  56. if (_webSocketServer->isListening()) {
  57. qCInfo(lcFakeWebSocketServer) << "Close fake websocket server";
  58. _webSocketServer->close();
  59. qDeleteAll(_clients.begin(), _clients.end());
  60. }
  61. }
  62. void FakeWebSocketServer::processTextMessageInternal(const QString &message)
  63. {
  64. auto client = qobject_cast<QWebSocket *>(sender());
  65. emit processTextMessage(client, message);
  66. }
  67. void FakeWebSocketServer::onNewConnection()
  68. {
  69. qCInfo(lcFakeWebSocketServer) << "New connection on fake websocket server";
  70. auto socket = _webSocketServer->nextPendingConnection();
  71. connect(socket, &QWebSocket::textMessageReceived, this, &FakeWebSocketServer::processTextMessageInternal);
  72. connect(socket, &QWebSocket::disconnected, this, &FakeWebSocketServer::socketDisconnected);
  73. _clients << socket;
  74. }
  75. void FakeWebSocketServer::socketDisconnected()
  76. {
  77. qCInfo(lcFakeWebSocketServer) << "Socket disconnected";
  78. auto client = qobject_cast<QWebSocket *>(sender());
  79. if (client) {
  80. _clients.removeAll(client);
  81. client->deleteLater();
  82. }
  83. }
  84. bool FakeWebSocketServer::waitForTextMessages() const
  85. {
  86. return _processTextMessageSpy->wait();
  87. }
  88. uint32_t FakeWebSocketServer::textMessagesCount() const
  89. {
  90. return _processTextMessageSpy->count();
  91. }
  92. QString FakeWebSocketServer::textMessage(uint32_t messageNumber) const
  93. {
  94. Q_ASSERT(messageNumber < _processTextMessageSpy->count());
  95. return _processTextMessageSpy->at(messageNumber).at(1).toString();
  96. }
  97. QWebSocket *FakeWebSocketServer::socketForTextMessage(uint32_t messageNumber) const
  98. {
  99. Q_ASSERT(messageNumber < _processTextMessageSpy->count());
  100. return _processTextMessageSpy->at(messageNumber).at(0).value<QWebSocket *>();
  101. }
  102. void FakeWebSocketServer::clearTextMessages()
  103. {
  104. _processTextMessageSpy->clear();
  105. }
  106. OCC::AccountPtr FakeWebSocketServer::createAccount(const QString &username, const QString &password)
  107. {
  108. auto account = OCC::Account::create();
  109. QStringList typeList;
  110. typeList.append("files");
  111. typeList.append("activities");
  112. typeList.append("notifications");
  113. QString websocketUrl("ws://localhost:12345");
  114. QVariantMap endpointsMap;
  115. endpointsMap["websocket"] = websocketUrl;
  116. QVariantMap notifyPushMap;
  117. notifyPushMap["type"] = typeList;
  118. notifyPushMap["endpoints"] = endpointsMap;
  119. QVariantMap capabilitiesMap;
  120. capabilitiesMap["notify_push"] = notifyPushMap;
  121. account->setCapabilities(capabilitiesMap);
  122. auto credentials = new CredentialsStub(username, password);
  123. account->setCredentials(credentials);
  124. return account;
  125. }
  126. CredentialsStub::CredentialsStub(const QString &user, const QString &password)
  127. : _user(user)
  128. , _password(password)
  129. {
  130. }
  131. QString CredentialsStub::authType() const
  132. {
  133. return "";
  134. }
  135. QString CredentialsStub::user() const
  136. {
  137. return _user;
  138. }
  139. QString CredentialsStub::password() const
  140. {
  141. return _password;
  142. }
  143. QNetworkAccessManager *CredentialsStub::createQNAM() const
  144. {
  145. return nullptr;
  146. }
  147. bool CredentialsStub::ready() const
  148. {
  149. return false;
  150. }
  151. void CredentialsStub::fetchFromKeychain() { }
  152. void CredentialsStub::askFromUser() { }
  153. bool CredentialsStub::stillValid(QNetworkReply * /*reply*/)
  154. {
  155. return false;
  156. }
  157. void CredentialsStub::persist() { }
  158. void CredentialsStub::invalidateToken() { }
  159. void CredentialsStub::forgetSensitiveData() { }