UnitTestShaderCompilerServer.cpp 6.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205
  1. /*
  2. * Copyright (c) Contributors to the Open 3D Engine Project.
  3. * For complete copyright and license terms please see the LICENSE at the root of this distribution.
  4. *
  5. * SPDX-License-Identifier: Apache-2.0 OR MIT
  6. *
  7. */
  8. #include "native/utilities/UnitTestShaderCompilerServer.h"
  9. #include "native/assetprocessor.h"
  10. #include <QTcpServer>
  11. #include <QTcpSocket>
  12. UnitTestShaderCompilerServer::UnitTestShaderCompilerServer(QObject* parent)
  13. : QObject(parent)
  14. , m_incomingPayload("This is a test string")
  15. , m_outgoingPayload("Test string validated")
  16. , m_serverAddress(QString())
  17. , m_serverPort(0)
  18. , m_server(nullptr)
  19. , m_socket(nullptr)
  20. , m_isPayloadSizeKnown(false)
  21. , m_totalBytesReadInPayload(0)
  22. , m_bytesRemainingInPayload(0)
  23. , m_bytesRemainingInPayloadSize(0)
  24. , m_totalBytesReadInPayloadSize(0)
  25. , m_payloadSize(0)
  26. {
  27. }
  28. UnitTestShaderCompilerServer::~UnitTestShaderCompilerServer()
  29. {
  30. if (m_server != nullptr)
  31. {
  32. m_server->deleteLater();
  33. }
  34. }
  35. void UnitTestShaderCompilerServer::Init(QString serverAddress, int serverPort)
  36. {
  37. m_serverAddress = serverAddress;
  38. m_serverPort = serverPort;
  39. m_server = new QTcpServer(this);
  40. connect(m_server, SIGNAL(newConnection()), this, SLOT(newConnection()));
  41. startServer();
  42. }
  43. void UnitTestShaderCompilerServer::startServer()
  44. {
  45. if (!m_server->isListening())
  46. {
  47. if (!m_server->listen(QHostAddress(m_serverAddress), static_cast<quint16>(m_serverPort)))
  48. {
  49. AZ_TracePrintf(AssetProcessor::DebugChannel, "Server %s could not start.\n", m_serverAddress.toUtf8().data());
  50. emit errorMessage("Server could not start ");
  51. }
  52. }
  53. }
  54. void UnitTestShaderCompilerServer::closeSocket()
  55. {
  56. m_socket->close();
  57. }
  58. void UnitTestShaderCompilerServer::newConnection()
  59. {
  60. m_socket = m_server->nextPendingConnection();
  61. if (m_serverStatus == BadServer_DisconnectAfterConnect)
  62. {
  63. closeSocket();
  64. return;
  65. }
  66. connect(m_socket, SIGNAL(readyRead()), this, SLOT(incomingMessage()));
  67. connect(m_socket, SIGNAL(disconnected()), m_socket, SLOT(deleteLater()));
  68. m_isPayloadSizeKnown = false;
  69. m_totalBytesReadInPayload = 0;
  70. m_bytesRemainingInPayload = 0;
  71. m_totalBytesReadInPayloadSize = 0;
  72. m_bytesRemainingInPayloadSize = 0;
  73. m_payloadSize = 0;
  74. m_payload.clear();
  75. }
  76. void UnitTestShaderCompilerServer::incomingMessage()
  77. {
  78. if (m_serverStatus == BadServer_DisconnectAfterConnect || m_socket->bytesAvailable() == 0)
  79. {
  80. return;
  81. }
  82. if (!m_isPayloadSizeKnown)
  83. {
  84. //reading payload size
  85. m_bytesRemainingInPayloadSize = static_cast<qint64>(sizeof(qint64)) - m_totalBytesReadInPayloadSize;
  86. qint64 bytesAvailable = m_socket->bytesAvailable();
  87. qint64 bytesToread = qMin(bytesAvailable, m_bytesRemainingInPayloadSize);
  88. qint64 bytesRead = m_socket->read(reinterpret_cast<char*>(&m_payloadSize) + m_totalBytesReadInPayloadSize, bytesToread);
  89. if (bytesRead < 0)
  90. {
  91. AZ_TracePrintf(AssetProcessor::DebugChannel, "Connection Lost : Cannot read from socket.\n");
  92. emit errorMessage("Connection Lost:Cannot read from socket");
  93. return;
  94. }
  95. m_totalBytesReadInPayloadSize += bytesRead;
  96. if (m_totalBytesReadInPayloadSize == static_cast<qint64>(sizeof(qint64)))
  97. {
  98. m_isPayloadSizeKnown = true;
  99. m_payload.resize(aznumeric_cast<int>(m_payloadSize));
  100. }
  101. if (m_socket->bytesAvailable() > 0)
  102. {
  103. QMetaObject::invokeMethod(this, "incomingMessage", Qt::QueuedConnection);
  104. return;
  105. }
  106. }
  107. else
  108. {
  109. // payload size is known,read the payload
  110. m_bytesRemainingInPayload = m_payloadSize - m_totalBytesReadInPayload;
  111. qint64 bytesAvailable = m_socket->bytesAvailable();
  112. qint64 bytesToread = qMin(bytesAvailable, m_bytesRemainingInPayload);
  113. qint64 bytesRead = m_socket->read(m_payload.data() + m_totalBytesReadInPayload, bytesToread);
  114. if (bytesRead < 0)
  115. {
  116. AZ_TracePrintf(AssetProcessor::DebugChannel, "Connection Lost:Cannot read from socket.\n");
  117. emit errorMessage("Connection Lost:Cannot read from socket");
  118. return;
  119. }
  120. m_totalBytesReadInPayload += bytesRead;
  121. if (m_socket->bytesAvailable() > 0)
  122. {
  123. QMetaObject::invokeMethod(this, "incomingMessage", Qt::QueuedConnection);
  124. return;
  125. }
  126. if (m_totalBytesReadInPayload != m_payloadSize)
  127. {
  128. return;
  129. }
  130. if (m_serverStatus == BadServer_ReadsPayloadAndDisconnect)
  131. {
  132. closeSocket();
  133. return;
  134. }
  135. //we have the complete payload here
  136. //compare it with the expected payload
  137. if (QString::compare(QString(m_payload), m_incomingPayload) == 0)
  138. {
  139. QByteArray payload;
  140. qint64 messageSize;
  141. constructPayload(payload);
  142. messageSize = static_cast<qint64>(payload.size());
  143. if (m_serverStatus == BadServer_SendsIncompletePayload)
  144. {
  145. messageSize -= 5;
  146. }
  147. qint64 bytesWritten = 0;
  148. while (bytesWritten != messageSize)
  149. {
  150. qint64 currentWrite = m_socket->write(payload.data() + bytesWritten, messageSize - bytesWritten);
  151. if (currentWrite < 0)
  152. {
  153. AZ_TracePrintf(AssetProcessor::DebugChannel, "Connection Lost:Cannot write to socket.\n");
  154. emit errorMessage("Connection Lost:Cannot write to socket");
  155. return;
  156. }
  157. bytesWritten += currentWrite;
  158. }
  159. }
  160. else
  161. {
  162. AZ_TracePrintf(AssetProcessor::DebugChannel, "Server Payload is corrupt.\n");
  163. emit errorMessage("Server Payload is corrupt");
  164. return;
  165. }
  166. }
  167. }
  168. void UnitTestShaderCompilerServer::setServerStatus(const ServerStatus& serverStatus)
  169. {
  170. m_serverStatus = serverStatus;
  171. }
  172. void UnitTestShaderCompilerServer::constructPayload(QByteArray& payload)
  173. {
  174. //construct test response payload
  175. quint8 status = 1;
  176. unsigned int outgoingTextLength = static_cast<unsigned int>(m_outgoingPayload.size());
  177. payload.resize(outgoingTextLength + sizeof(unsigned int) + sizeof(quint8));
  178. memcpy(payload.data(), reinterpret_cast<char*>(&outgoingTextLength), sizeof(unsigned int));
  179. memcpy(payload.data() + sizeof(unsigned int), reinterpret_cast<char*>(&status), sizeof(quint8));
  180. memcpy(payload.data() + sizeof(unsigned int) + sizeof(quint8), m_outgoingPayload.toStdString().c_str(), outgoingTextLength);
  181. }