pushnotificationstestutils.cpp 5.5 KB

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