+++ /dev/null
-/*
- * PROJECT: ReactOS Automatic Testing Utility
- * LICENSE: GNU GPLv2 or any later version as published by the Free Software Foundation
- * PURPOSE: Submitting test results to the Web Service
- * COPYRIGHT: Copyright 2008-2009 Colin Finck <colin@reactos.org>
- */
-
-#include "precomp.h"
-
-static const CHAR ActionProp[] = "action=";
-static const CHAR TestIDProp[] = "&testid=";
-static const CHAR TestTypeProp[] = "&testtype=";
-static const CHAR WineTestType[] = "wine";
-
-/**
- * Sends data to the ReactOS Web Test Manager web service.
- *
- * @param Data
- * Pointer to a CHAR pointer, which contains the data to submit as HTTP POST data.
- * The buffer behind this pointer had to be allocated with HeapAlloc.
- * Returns the data received by the web service after the call.
- *
- * @param DataLength
- * Pointer to a DWORD, which contains the length of the data to submit (in bytes).
- * Returns the length of the data received by the web service after the call (in bytes).
- *
- * @return
- * TRUE if everything went well, FALSE if an error occured while submitting the request.
- * In case of an error, the function will output an appropriate error message through StringOut.
- */
-static BOOL
-IntDoRequest(char** Data, PDWORD DataLength)
-{
- const WCHAR Headers[] = L"Content-Type: application/x-www-form-urlencoded";
-
- BOOL ReturnValue = FALSE;
- HINTERNET hHTTP = NULL;
- HINTERNET hHTTPRequest = NULL;
- HINTERNET hInet = NULL;
-
- /* Establish an internet connection to the "testman" server */
- hInet = InternetOpenW(L"rosautotest", INTERNET_OPEN_TYPE_PRECONFIG, NULL, NULL, 0);
-
- if(!hInet)
- {
- StringOut("InternetOpenW failed\n");
- goto Cleanup;
- }
-
- hHTTP = InternetConnectW(hInet, SERVER_HOSTNAME, INTERNET_DEFAULT_HTTP_PORT, NULL, NULL, INTERNET_SERVICE_HTTP, 0, 0);
-
- if(!hHTTP)
- {
- StringOut("InternetConnectW failed\n");
- goto Cleanup;
- }
-
- /* Post our test results to the web service */
- hHTTPRequest = HttpOpenRequestW(hHTTP, L"POST", SERVER_FILE, NULL, NULL, NULL, INTERNET_FLAG_NO_COOKIES | INTERNET_FLAG_RELOAD | INTERNET_FLAG_NO_CACHE_WRITE, 0);
-
- if(!hHTTPRequest)
- {
- StringOut("HttpOpenRequestW failed\n");
- goto Cleanup;
- }
-
- if(!HttpSendRequestW(hHTTPRequest, Headers, wcslen(Headers), *Data, *DataLength))
- {
- StringOut("HttpSendRequestW failed\n");
- goto Cleanup;
- }
-
- HeapFree(hProcessHeap, 0, *Data);
- *Data = NULL;
-
- /* Get the response */
- if(!InternetQueryDataAvailable(hHTTPRequest, DataLength, 0, 0))
- {
- StringOut("InternetQueryDataAvailable failed\n");
- goto Cleanup;
- }
-
- *Data = HeapAlloc(hProcessHeap, 0, *DataLength + 1);
-
- if(!InternetReadFile(hHTTPRequest, *Data, *DataLength, DataLength))
- {
- StringOut("InternetReadFile failed\n");
- goto Cleanup;
- }
-
- (*Data)[*DataLength] = 0;
- ReturnValue = TRUE;
-
-Cleanup:
- if(hHTTPRequest)
- InternetCloseHandle(hHTTPRequest);
-
- if(hHTTP)
- InternetCloseHandle(hHTTP);
-
- if(hInet)
- InternetCloseHandle(hInet);
-
- return ReturnValue;
-}
-
-/**
- * Determines whether a string contains entirely numeric values.
- *
- * @param Input
- * The string to check.
- *
- * @return
- * TRUE if the string is entirely numeric, FALSE otherwise.
- */
-static BOOL
-IsNumber(PCHAR Input)
-{
- do
- {
- if(!isdigit(*Input))
- return FALSE;
-
- ++Input;
- }
- while(*Input);
-
- return TRUE;
-}
-
-/**
- * Requests a Test ID from the web service for our test run.
- *
- * @param TestType
- * Value from the TESTTYPES enum indicating the type of test we are about to submit.
- *
- * @return
- * Returns the Test ID as a CHAR array if successful or NULL otherwise.
- * The caller needs to HeapFree the returned pointer in case of success.
- */
-PCHAR
-GetTestID(TESTTYPES TestType)
-{
- const CHAR GetTestIDAction[] = "gettestid";
- const CHAR CommentProp[] = "&comment=";
-
- DWORD DataLength;
- PCHAR Data;
- PCHAR ReturnValue = NULL;
-
- /* Build the full request string */
- DataLength = sizeof(ActionProp) - 1 + sizeof(GetTestIDAction) - 1;
- DataLength += strlen(AuthenticationRequestString) + strlen(SystemInfoRequestString);
-
- if(AppOptions.Comment)
- DataLength += sizeof(CommentProp) - 1 + strlen(AppOptions.Comment);
-
- DataLength += sizeof(TestTypeProp) - 1;
-
- switch(TestType)
- {
- case WineTest:
- DataLength += sizeof(WineTestType) - 1;
- break;
- }
-
- Data = HeapAlloc(hProcessHeap, 0, DataLength + 1);
- strcpy(Data, ActionProp);
- strcat(Data, GetTestIDAction);
- strcat(Data, AuthenticationRequestString);
- strcat(Data, SystemInfoRequestString);
-
- if(AppOptions.Comment)
- {
- strcat(Data, CommentProp);
- strcat(Data, AppOptions.Comment);
- }
-
- strcat(Data, TestTypeProp);
-
- switch(TestType)
- {
- case WineTest:
- strcat(Data, WineTestType);
- break;
- }
-
- if(!IntDoRequest(&Data, &DataLength))
- goto Cleanup;
-
- /* Verify that this is really a number */
- if(!IsNumber(Data))
- {
- StringOut("Expected Test ID, but received:\n");
- StringOut(Data);
- StringOut("\n");
- goto Cleanup;
- }
-
- ReturnValue = Data;
-
-Cleanup:
- if(Data && ReturnValue != Data)
- HeapFree(hProcessHeap, 0, Data);
-
- return ReturnValue;
-}
-
-/**
- * Requests a Suite ID from the web service for our module/test combination.
- *
- * @param TestType
- * Value from the TESTTYPES enum indicating the type of test we are about to submit.
- *
- * @param TestData
- * Pointer to a *_GETSUITEID_DATA structure appropriate for our selected test type.
- * Contains other input information for this request.
- *
- * @return
- * Returns the Suite ID as a CHAR array if successful or NULL otherwise.
- * The caller needs to HeapFree the returned pointer in case of success.
- */
-PCHAR
-GetSuiteID(TESTTYPES TestType, const PVOID TestData)
-{
- const CHAR GetSuiteIDAction[] = "getsuiteid";
- const CHAR ModuleProp[] = "&module=";
- const CHAR TestProp[] = "&test=";
-
- DWORD DataLength;
- PCHAR Data;
- PCHAR ReturnValue = NULL;
- PWINE_GETSUITEID_DATA WineData;
-
- DataLength = sizeof(ActionProp) - 1 + sizeof(GetSuiteIDAction) - 1;
- DataLength += strlen(AuthenticationRequestString);
- DataLength += sizeof(TestTypeProp) - 1;
-
- switch(TestType)
- {
- case WineTest:
- DataLength += sizeof(WineTestType) - 1;
-
- WineData = (PWINE_GETSUITEID_DATA)TestData;
- DataLength += sizeof(ModuleProp) - 1;
- DataLength += strlen(WineData->Module);
- DataLength += sizeof(TestProp) - 1;
- DataLength += strlen(WineData->Test);
-
- break;
- }
-
- Data = HeapAlloc(hProcessHeap, 0, DataLength + 1);
- strcpy(Data, ActionProp);
- strcat(Data, GetSuiteIDAction);
- strcat(Data, AuthenticationRequestString);
- strcat(Data, TestTypeProp);
-
- switch(TestType)
- {
- case WineTest:
- strcat(Data, WineTestType);
-
- /* Stupid GCC and MSVC: WineData is already initialized above, still it's reported as a potentially uninitialized variable :-( */
- WineData = (PWINE_GETSUITEID_DATA)TestData;
- strcat(Data, ModuleProp);
- strcat(Data, WineData->Module);
- strcat(Data, TestProp);
- strcat(Data, WineData->Test);
-
- break;
- }
-
- if(!IntDoRequest(&Data, &DataLength))
- goto Cleanup;
-
- /* Verify that this is really a number */
- if(!IsNumber(Data))
- {
- StringOut("Expected Suite ID, but received:\n");
- StringOut(Data);
- StringOut("\n");
- goto Cleanup;
- }
-
- ReturnValue = Data;
-
-Cleanup:
- if(Data && ReturnValue != Data)
- HeapFree(hProcessHeap, 0, Data);
-
- return ReturnValue;
-}
-
-/**
- * Submits the result of one test call to the web service.
- *
- * @param TestType
- * Value from the TESTTYPES enum indicating the type of test we are about to submit.
- *
- * @param TestData
- * Pointer to a *_SUBMIT_DATA structure appropriate for our selected test type.
- * Contains other input information for this request.
- *
- * @return
- * TRUE if everything went well, FALSE otherwise.
- */
-BOOL
-Submit(TESTTYPES TestType, const PVOID TestData)
-{
- const CHAR SubmitAction[] = "submit";
- const CHAR SuiteIDProp[] = "&suiteid=";
- const CHAR LogProp[] = "&log=";
-
- BOOL ReturnValue = FALSE;
- DWORD DataLength;
- PCHAR Data;
- PCHAR pData;
- PGENERAL_SUBMIT_DATA GeneralData;
- PWINE_SUBMIT_DATA WineData;
-
- /* Compute the full length of the POST data */
- DataLength = sizeof(ActionProp) - 1 + sizeof(SubmitAction) - 1;
- DataLength += strlen(AuthenticationRequestString);
-
- GeneralData = (PGENERAL_SUBMIT_DATA)TestData;
- DataLength += sizeof(TestIDProp) - 1;
- DataLength += strlen(GeneralData->TestID);
- DataLength += sizeof(SuiteIDProp) - 1;
- DataLength += strlen(GeneralData->SuiteID);
-
- /* The rest of the POST data depends on the test type */
- DataLength += sizeof(TestTypeProp) - 1;
-
- switch(TestType)
- {
- case WineTest:
- DataLength += sizeof(WineTestType) - 1;
-
- WineData = (PWINE_SUBMIT_DATA)TestData;
- DataLength += sizeof(LogProp) - 1;
- DataLength += 3 * strlen(WineData->Log);
-
- break;
- }
-
- /* Now collect all the POST data */
- Data = HeapAlloc(hProcessHeap, 0, DataLength + 1);
- strcpy(Data, ActionProp);
- strcat(Data, SubmitAction);
- strcat(Data, AuthenticationRequestString);
-
- strcat(Data, TestIDProp);
- strcat(Data, GeneralData->TestID);
- strcat(Data, SuiteIDProp);
- strcat(Data, GeneralData->SuiteID);
-
- strcat(Data, TestTypeProp);
-
- switch(TestType)
- {
- case WineTest:
- strcat(Data, WineTestType);
-
- /* Stupid GCC and MSVC: WineData is already initialized above, still it's reported as a potentially uninitialized variable :-( */
- WineData = (PWINE_SUBMIT_DATA)TestData;
-
- strcat(Data, LogProp);
- pData = Data + strlen(Data);
- EscapeString(pData, WineData->Log);
-
- break;
- }
-
- /* DataLength still contains the maximum length of the buffer, but not the actual data length we need for the request.
- Determine that one now. */
- DataLength = strlen(Data);
-
- /* Send all the stuff */
- if(!IntDoRequest(&Data, &DataLength))
- goto Cleanup;
-
- /* Output the response */
- StringOut("The server responded:\n");
- StringOut(Data);
- StringOut("\n");
-
- if(!strcmp(Data, "OK"))
- ReturnValue = TRUE;
-
-Cleanup:
- if(Data)
- HeapFree(hProcessHeap, 0, Data);
-
- return ReturnValue;
-}
-
-/**
- * Finishes a test run for the web service.
- *
- * @param TestType
- * Value from the TESTTYPES enum indicating the type of test we are about to submit.
- *
- * @param TestData
- * Pointer to a *_FINISH_DATA structure appropriate for our selected test type.
- * Contains other input information for this request.
- *
- * @return
- * TRUE if everything went well, FALSE otherwise.
- */
-BOOL
-Finish(TESTTYPES TestType, const PVOID TestData)
-{
- const CHAR FinishAction[] = "finish";
-
- BOOL ReturnValue = FALSE;
- DWORD DataLength;
- PCHAR Data;
- PGENERAL_FINISH_DATA GeneralData;
-
- /* Build the full request string */
- DataLength = sizeof(ActionProp) - 1 + sizeof(FinishAction) - 1;
- DataLength += strlen(AuthenticationRequestString);
-
- GeneralData = (PGENERAL_FINISH_DATA)TestData;
- DataLength += sizeof(TestIDProp) - 1;
- DataLength += strlen(GeneralData->TestID);
-
- DataLength += sizeof(TestTypeProp) - 1;
-
- switch(TestType)
- {
- case WineTest:
- DataLength += sizeof(WineTestType) - 1;
- break;
- }
-
- Data = HeapAlloc(hProcessHeap, 0, DataLength + 1);
- strcpy(Data, ActionProp);
- strcat(Data, FinishAction);
- strcat(Data, AuthenticationRequestString);
- strcat(Data, TestIDProp);
- strcat(Data, GeneralData->TestID);
- strcat(Data, TestTypeProp);
-
- switch(TestType)
- {
- case WineTest:
- strcat(Data, WineTestType);
- break;
- }
-
- if(!IntDoRequest(&Data, &DataLength))
- goto Cleanup;
-
- if(!strcmp(Data, "OK"))
- ReturnValue = TRUE;
-
-Cleanup:
- if(Data)
- HeapFree(hProcessHeap, 0, Data);
-
- return ReturnValue;
-}