[KMTESTS:CC]
[reactos.git] / rostests / rosautotest / CWebService.cpp
1 /*
2 * PROJECT: ReactOS Automatic Testing Utility
3 * LICENSE: GNU GPLv2 or any later version as published by the Free Software Foundation
4 * PURPOSE: Class implementing the interface to the "testman" Web Service
5 * COPYRIGHT: Copyright 2009-2015 Colin Finck <colin@reactos.org>
6 */
7
8 #include "precomp.h"
9
10 static const WCHAR szHostname[] = L"reactos.org";
11 static const WCHAR szServerFile[] = L"testman/webservice/";
12
13 /**
14 * Constructs a CWebService object and immediately establishes a connection to the "testman" Web Service.
15 */
16 CWebService::CWebService()
17 {
18 /* Zero-initialize variables */
19 m_hHTTP = NULL;
20 m_hHTTPRequest = NULL;
21 m_TestID = NULL;
22
23 /* Establish an internet connection to the "testman" server */
24 m_hInet = InternetOpenW(L"rosautotest", INTERNET_OPEN_TYPE_PRECONFIG, NULL, NULL, 0);
25
26 if(!m_hInet)
27 FATAL("InternetOpenW failed\n");
28
29 m_hHTTP = InternetConnectW(m_hInet, szHostname, INTERNET_DEFAULT_HTTP_PORT, NULL, NULL, INTERNET_SERVICE_HTTP, 0, 0);
30
31 if(!m_hHTTP)
32 FATAL("InternetConnectW failed\n");
33 }
34
35 /**
36 * Destructs a CWebService object and closes all connections to the Web Service.
37 */
38 CWebService::~CWebService()
39 {
40 if(m_hInet)
41 InternetCloseHandle(m_hInet);
42
43 if(m_hHTTP)
44 InternetCloseHandle(m_hHTTP);
45
46 if(m_hHTTPRequest)
47 InternetCloseHandle(m_hHTTPRequest);
48
49 if(m_TestID)
50 delete m_TestID;
51 }
52
53 /**
54 * Sends data to the Web Service.
55 *
56 * @param InputData
57 * A std::string containing all the data, which is going to be submitted as HTTP POST data.
58 *
59 * @return
60 * Returns a pointer to a char array containing the data received from the Web Service.
61 * The caller needs to free that pointer.
62 */
63 PCHAR
64 CWebService::DoRequest(const string& InputData)
65 {
66 const WCHAR szHeaders[] = L"Content-Type: application/x-www-form-urlencoded";
67
68 auto_array_ptr<char> Data;
69 DWORD DataLength;
70
71 /* Post our test results to the web service */
72 m_hHTTPRequest = HttpOpenRequestW(m_hHTTP, L"POST", szServerFile, NULL, NULL, NULL, INTERNET_FLAG_NO_COOKIES | INTERNET_FLAG_RELOAD | INTERNET_FLAG_NO_CACHE_WRITE, 0);
73
74 if(!m_hHTTPRequest)
75 FATAL("HttpOpenRequestW failed\n");
76
77 Data.reset(new char[InputData.size() + 1]);
78 strcpy(Data, InputData.c_str());
79
80 if(!HttpSendRequestW(m_hHTTPRequest, szHeaders, wcslen(szHeaders), Data, InputData.size()))
81 FATAL("HttpSendRequestW failed\n");
82
83 /* Get the response */
84 if(!InternetQueryDataAvailable(m_hHTTPRequest, &DataLength, 0, 0))
85 FATAL("InternetQueryDataAvailable failed\n");
86
87 Data.reset(new char[DataLength + 1]);
88
89 if(!InternetReadFile(m_hHTTPRequest, Data, DataLength, &DataLength))
90 FATAL("InternetReadFile failed\n");
91
92 Data[DataLength] = 0;
93
94 return Data.release();
95 }
96
97 /**
98 * Interface to other classes for finishing this test run
99 *
100 * @param TestType
101 * Constant pointer to a char array containing the test type to be run (i.e. "wine")
102 */
103 void
104 CWebService::Finish(const char* TestType)
105 {
106 auto_array_ptr<char> Response;
107 string Data;
108 stringstream ss;
109
110 if (!m_TestID)
111 EXCEPTION("CWebService::Finish was called, but not a single result had been submitted!");
112
113 Data = "action=finish";
114 Data += Configuration.GetAuthenticationRequestString();
115 Data += "&testtype=";
116 Data += TestType;
117 Data += "&testid=";
118 Data += m_TestID;
119
120 Response.reset(DoRequest(Data));
121
122 if (strcmp(Response, "OK"))
123 {
124 ss << "When finishing the test run, the server responded:" << endl << Response << endl;
125 SSEXCEPTION;
126 }
127 }
128
129 /**
130 * Requests a Test ID from the Web Service for our test run.
131 *
132 * @param TestType
133 * Constant pointer to a char array containing the test type to be run (i.e. "wine")
134 */
135 void
136 CWebService::GetTestID(const char* TestType)
137 {
138 string Data;
139
140 Data = "action=gettestid";
141 Data += Configuration.GetAuthenticationRequestString();
142 Data += Configuration.GetSystemInfoRequestString();
143 Data += "&testtype=";
144 Data += TestType;
145
146 if(!Configuration.GetComment().empty())
147 {
148 Data += "&comment=";
149 Data += Configuration.GetComment();
150 }
151
152 m_TestID = DoRequest(Data);
153
154 /* Verify that this is really a number */
155 if(!IsNumber(m_TestID))
156 {
157 stringstream ss;
158
159 ss << "Expected Test ID, but received:" << endl << m_TestID << endl;
160 SSEXCEPTION;
161 }
162 }
163
164 /**
165 * Gets a Suite ID from the Web Service for this module/test combination.
166 *
167 * @param TestType
168 * Constant pointer to a char array containing the test type to be run (i.e. "wine")
169 *
170 * @param TestInfo
171 * Pointer to a CTestInfo object containing information about the test
172 *
173 * @return
174 * Returns a pointer to a char array containing the Suite ID received from the Web Service.
175 * The caller needs to free that pointer.
176 */
177 PCHAR
178 CWebService::GetSuiteID(const char* TestType, CTestInfo* TestInfo)
179 {
180 auto_array_ptr<char> SuiteID;
181 string Data;
182
183 Data = "action=getsuiteid";
184 Data += Configuration.GetAuthenticationRequestString();
185 Data += "&testtype=";
186 Data += TestType;
187 Data += "&module=";
188 Data += TestInfo->Module;
189 Data += "&test=";
190 Data += TestInfo->Test;
191
192 SuiteID.reset(DoRequest(Data));
193
194 /* Verify that this is really a number */
195 if(!IsNumber(SuiteID))
196 {
197 stringstream ss;
198
199 ss << "Expected Suite ID, but received:" << endl << SuiteID << endl;
200 SSEXCEPTION;
201 }
202
203 return SuiteID.release();
204 }
205
206 /**
207 * Interface to other classes for submitting a result of one test
208 *
209 * @param TestType
210 * Constant pointer to a char array containing the test type to be run (i.e. "wine")
211 *
212 * @param TestInfo
213 * Pointer to a CTestInfo object containing information about the test
214 */
215 void
216 CWebService::Submit(const char* TestType, CTestInfo* TestInfo)
217 {
218 auto_array_ptr<char> Response;
219 auto_array_ptr<char> SuiteID;
220 string Data;
221 stringstream ss;
222
223 if(!m_TestID)
224 GetTestID(TestType);
225
226 SuiteID.reset(GetSuiteID(TestType, TestInfo));
227
228 Data = "action=submit";
229 Data += Configuration.GetAuthenticationRequestString();
230 Data += "&testtype=";
231 Data += TestType;
232 Data += "&testid=";
233 Data += m_TestID;
234 Data += "&suiteid=";
235 Data += SuiteID;
236 Data += "&log=";
237 Data += EscapeString(TestInfo->Log);
238
239 Response.reset(DoRequest(Data));
240
241 if (strcmp(Response, "OK"))
242 {
243 ss << "When submitting the result, the server responded:" << endl << Response << endl;
244 SSEXCEPTION;
245 }
246 }