[MSCTF]
[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-2011 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 * Requests a Test ID from the Web Service for our 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::GetTestID(const char* TestType)
105 {
106 string Data;
107
108 Data = "action=gettestid";
109 Data += Configuration.GetAuthenticationRequestString();
110 Data += Configuration.GetSystemInfoRequestString();
111 Data += "&testtype=";
112 Data += TestType;
113
114 if(!Configuration.GetComment().empty())
115 {
116 Data += "&comment=";
117 Data += Configuration.GetComment();
118 }
119
120 m_TestID = DoRequest(Data);
121
122 /* Verify that this is really a number */
123 if(!IsNumber(m_TestID))
124 {
125 stringstream ss;
126
127 ss << "Expected Test ID, but received:" << endl << m_TestID << endl;
128 SSEXCEPTION;
129 }
130 }
131
132 /**
133 * Gets a Suite ID from the Web Service for this module/test combination.
134 *
135 * @param TestType
136 * Constant pointer to a char array containing the test type to be run (i.e. "wine")
137 *
138 * @param TestInfo
139 * Pointer to a CTestInfo object containing information about the test
140 *
141 * @return
142 * Returns a pointer to a char array containing the Suite ID received from the Web Service.
143 * The caller needs to free that pointer.
144 */
145 PCHAR
146 CWebService::GetSuiteID(const char* TestType, CTestInfo* TestInfo)
147 {
148 auto_array_ptr<char> SuiteID;
149 string Data;
150
151 Data = "action=getsuiteid";
152 Data += Configuration.GetAuthenticationRequestString();
153 Data += "&testtype=";
154 Data += TestType;
155 Data += "&module=";
156 Data += TestInfo->Module;
157 Data += "&test=";
158 Data += TestInfo->Test;
159
160 SuiteID.reset(DoRequest(Data));
161
162 /* Verify that this is really a number */
163 if(!IsNumber(SuiteID))
164 {
165 stringstream ss;
166
167 ss << "Expected Suite ID, but received:" << endl << SuiteID << endl;
168 SSEXCEPTION;
169 }
170
171 return SuiteID.release();
172 }
173
174 /**
175 * Interface to other classes for submitting a result of one test
176 *
177 * @param TestType
178 * Constant pointer to a char array containing the test type to be run (i.e. "wine")
179 *
180 * @param TestInfo
181 * Pointer to a CTestInfo object containing information about the test
182 */
183 void
184 CWebService::Submit(const char* TestType, CTestInfo* TestInfo)
185 {
186 auto_array_ptr<char> Response;
187 auto_array_ptr<char> SuiteID;
188 string Data;
189 stringstream ss;
190
191 if(!m_TestID)
192 GetTestID(TestType);
193
194 SuiteID.reset(GetSuiteID(TestType, TestInfo));
195
196 Data = "action=submit";
197 Data += Configuration.GetAuthenticationRequestString();
198 Data += "&testtype=";
199 Data += TestType;
200 Data += "&testid=";
201 Data += m_TestID;
202 Data += "&suiteid=";
203 Data += SuiteID;
204 Data += "&log=";
205 Data += TestInfo->Log;
206
207 Response.reset(DoRequest(Data));
208
209 ss << "The server responded:" << endl << Response << endl;
210 StringOut(ss.str());
211
212 if(strcmp(Response, "OK"))
213 EXCEPTION("Aborted!\n");
214 }