using OSGeo.MapGuide; using OSGeo.MapGuide.Test.Common; using SqliteDotNet; using System; using System.Collections.Generic; using System.Data.SqlTypes; using System.IO; using System.Linq; using System.Reflection; using System.Runtime.InteropServices; using System.Text; using System.Threading.Tasks; using System.Xml; using System.Xml.Linq; namespace OSGeo.MapGuide.Test.Web { public class MapGuideTestExecutorCollection : TestExecutorCollectionBase { private Dictionary _executors; private MgUserInformation _userInfo; private MgSiteConnection _conn; public MapGuideTestExecutorCollection(MgUserInformation userInfo, MgSiteConnection conn) { _userInfo = userInfo; _conn = conn; } protected override void SetupExecutors(string dbPath) { //NOTE: We can't share the SqliteVm instance among our executor objects as this messes up query results //we must be able to re-create a new SqliteVm for each executor, so we pass down the db path _executors = new Dictionary(); MgResourceService resSvc = (MgResourceService)_conn.CreateService(MgServiceType.ResourceService); MgFeatureService featSvc = (MgFeatureService)_conn.CreateService(MgServiceType.FeatureService); MgDrawingService drawSvc = (MgDrawingService)_conn.CreateService(MgServiceType.DrawingService); var site = _conn.GetSite(); var admin = new MgServerAdmin(); admin.Open(_userInfo); var wlCreator = new MgWebLayoutCreator(resSvc); var creator = new MgMapCreator(_conn, resSvc); var sessionCreator = new MgSessionCreator(_conn); var sessionApply = new MgApplySession(_userInfo); var session = new MgSession(); //Resource Service _executors[typeof(Operations.ApplyResourcePackage).Name.ToUpper()] = new Operations.ApplyResourcePackage(resSvc, dbPath); _executors[typeof(Operations.ChangeResourceOwner).Name.ToUpper()] = new Operations.ChangeResourceOwner(resSvc, dbPath); _executors[typeof(Operations.CopyResource).Name.ToUpper()] = new Operations.CopyResource(resSvc, dbPath); _executors[typeof(Operations.DeleteResource).Name.ToUpper()] = new Operations.DeleteResource(resSvc, dbPath); _executors[typeof(Operations.DeleteResourceData).Name.ToUpper()] = new Operations.DeleteResourceData(resSvc, dbPath); _executors[typeof(Operations.EnumerateResourceData).Name.ToUpper()] = new Operations.EnumerateResourceData(resSvc, dbPath); _executors[typeof(Operations.EnumerateResourceReferences).Name.ToUpper()] = new Operations.EnumerateResourceReferences(resSvc, dbPath); _executors[typeof(Operations.EnumerateResources).Name.ToUpper()] = new Operations.EnumerateResources(resSvc, dbPath); _executors[typeof(Operations.GetRepositoryContent).Name.ToUpper()] = new Operations.GetRepositoryContent(resSvc, dbPath); _executors[typeof(Operations.GetRepositoryHeader).Name.ToUpper()] = new Operations.GetRepositoryHeader(resSvc, dbPath); _executors[typeof(Operations.GetResourceContent).Name.ToUpper()] = new Operations.GetResourceContent(resSvc, dbPath); _executors[typeof(Operations.GetResourceData).Name.ToUpper()] = new Operations.GetResourceData(resSvc, dbPath); _executors[typeof(Operations.GetResourceHeader).Name.ToUpper()] = new Operations.GetResourceHeader(resSvc, dbPath); _executors[typeof(Operations.InheritPermissionsFrom).Name.ToUpper()] = new Operations.InheritPermissionsFrom(resSvc, dbPath); _executors[typeof(Operations.MoveResource).Name.ToUpper()] = new Operations.MoveResource(resSvc, dbPath); _executors[typeof(Operations.RenameResourceData).Name.ToUpper()] = new Operations.RenameResourceData(resSvc, dbPath); _executors[typeof(Operations.SetResource).Name.ToUpper()] = new Operations.SetResource(resSvc, dbPath); _executors[typeof(Operations.SetResourceData).Name.ToUpper()] = new Operations.SetResourceData(resSvc, dbPath); _executors[typeof(Operations.UpdateRepository).Name.ToUpper()] = new Operations.UpdateRepository(resSvc, dbPath); //Feature Service _executors[typeof(Operations.DescribeFeatureSchema).Name.ToUpper()] = new Operations.DescribeFeatureSchema(featSvc, dbPath); _executors[typeof(Operations.ExecuteSqlQuery).Name.ToUpper()] = new Operations.ExecuteSqlQuery(featSvc, dbPath); _executors[typeof(Operations.GetClasses).Name.ToUpper()] = new Operations.GetClasses(featSvc, dbPath); _executors[typeof(Operations.GetConnectionPropertyValues).Name.ToUpper()] = new Operations.GetConnectionPropertyValues(featSvc, dbPath); _executors[typeof(Operations.GetFeatureProviders).Name.ToUpper()] = new Operations.GetFeatureProviders(featSvc, dbPath); _executors[typeof(Operations.GetLongTransactions).Name.ToUpper()] = new Operations.GetLongTransactions(featSvc, dbPath); _executors[typeof(Operations.GetProviderCapabilities).Name.ToUpper()] = new Operations.GetProviderCapabilities(featSvc, dbPath); _executors[typeof(Operations.GetSchemas).Name.ToUpper()] = new Operations.GetSchemas(featSvc, dbPath); _executors[typeof(Operations.GetSpatialContexts).Name.ToUpper()] = new Operations.GetSpatialContexts(featSvc, dbPath); _executors[typeof(Operations.SelectAggregates).Name.ToUpper()] = new Operations.SelectAggregates(featSvc, dbPath); _executors[typeof(Operations.SelectFeatures).Name.ToUpper()] = new Operations.SelectFeatures(featSvc, dbPath); _executors[typeof(Operations.SetLongTransaction).Name.ToUpper()] = new Operations.SetLongTransaction(featSvc, dbPath, sessionCreator, sessionApply); _executors[typeof(Operations.TestConnection).Name.ToUpper()] = new Operations.TestConnection(featSvc, dbPath); //Map and Layers _executors[typeof(Operations.AddLayerGroup).Name.ToUpper()] = new Operations.AddLayerGroup(resSvc, dbPath, creator); _executors[typeof(Operations.AddLayer).Name.ToUpper()] = new Operations.AddLayer(resSvc, dbPath, creator); _executors[typeof(Operations.GetCoordinateSystem).Name.ToUpper()] = new Operations.GetCoordinateSystem(resSvc, dbPath, creator); _executors[typeof(Operations.GetDataExtent).Name.ToUpper()] = new Operations.GetDataExtent(resSvc, dbPath, creator); _executors[typeof(Operations.GetDisplayInLegend).Name.ToUpper()] = new Operations.GetDisplayInLegend(resSvc, dbPath, creator); _executors[typeof(Operations.GetLayerFeatureClass).Name.ToUpper()] = new Operations.GetLayerFeatureClass(resSvc, dbPath, creator); _executors[typeof(Operations.GetLayerFeatureSource).Name.ToUpper()] = new Operations.GetLayerFeatureSource(resSvc, dbPath, creator); _executors[typeof(Operations.GetLayerDefinition).Name.ToUpper()] = new Operations.GetLayerDefinition(resSvc, dbPath, creator); _executors[typeof(Operations.GetGroups).Name.ToUpper()] = new Operations.GetGroups(resSvc, dbPath, creator); _executors[typeof(Operations.GetLayers).Name.ToUpper()] = new Operations.GetLayers(resSvc, dbPath, creator); _executors[typeof(Operations.GetLayerVisibility).Name.ToUpper()] = new Operations.GetLayerVisibility(resSvc, dbPath, creator); _executors[typeof(Operations.GetLegendLabel).Name.ToUpper()] = new Operations.GetLegendLabel(resSvc, dbPath, creator); _executors[typeof(Operations.GetMapExtent).Name.ToUpper()] = new Operations.GetMapExtent(resSvc, dbPath, creator); _executors[typeof(Operations.GetMapName).Name.ToUpper()] = new Operations.GetMapName(resSvc, dbPath, creator); _executors[typeof(Operations.GetViewCenter).Name.ToUpper()] = new Operations.GetViewCenter(resSvc, dbPath, creator); _executors[typeof(Operations.GetViewScale).Name.ToUpper()] = new Operations.GetViewScale(resSvc, dbPath, creator); _executors[typeof(Operations.HideGroup).Name.ToUpper()] = new Operations.HideGroup(resSvc, dbPath, creator); _executors[typeof(Operations.IsLayerVisible).Name.ToUpper()] = new Operations.IsLayerVisible(resSvc, dbPath, creator); _executors[typeof(Operations.LayerExists).Name.ToUpper()] = new Operations.LayerExists(resSvc, dbPath, creator); _executors[typeof(Operations.RemoveGroup).Name.ToUpper()] = new Operations.RemoveGroup(resSvc, dbPath, creator); _executors[typeof(Operations.ShowGroup).Name.ToUpper()] = new Operations.ShowGroup(resSvc, dbPath, creator); //Drawing Service _executors[typeof(Operations.DescribeDrawing).Name.ToUpper()] = new Operations.DescribeDrawing(drawSvc, dbPath); _executors[typeof(Operations.GetDrawing).Name.ToUpper()] = new Operations.GetDrawing(drawSvc, dbPath); _executors[typeof(Operations.EnumerateDrawingLayers).Name.ToUpper()] = new Operations.EnumerateDrawingLayers(drawSvc, dbPath); _executors[typeof(Operations.GetDrawingLayer).Name.ToUpper()] = new Operations.GetDrawingLayer(drawSvc, dbPath); _executors[typeof(Operations.GetDrawingSection).Name.ToUpper()] = new Operations.GetDrawingSection(drawSvc, dbPath); _executors[typeof(Operations.EnumerateDrawingSections).Name.ToUpper()] = new Operations.EnumerateDrawingSections(drawSvc, dbPath); _executors[typeof(Operations.EnumerateDrawingSectionResources).Name.ToUpper()] = new Operations.EnumerateDrawingSectionResources(drawSvc, dbPath); _executors[typeof(Operations.GetDrawingSectionResource).Name.ToUpper()] = new Operations.GetDrawingSectionResource(drawSvc, dbPath); //Mapping Service //Rendering Service //Server Admin _executors[typeof(Operations.Offline).Name.ToUpper()] = new Operations.Offline(admin, dbPath); _executors[typeof(Operations.Online).Name.ToUpper()] = new Operations.Online(admin, dbPath); _executors[typeof(Operations.GetLog).Name.ToUpper()] = new Operations.GetLog(admin, dbPath); _executors[typeof(Operations.GetLogByDate).Name.ToUpper()] = new Operations.GetLogByDate(admin, dbPath); _executors[typeof(Operations.ClearLog).Name.ToUpper()] = new Operations.ClearLog(admin, dbPath); _executors[typeof(Operations.DeleteLog).Name.ToUpper()] = new Operations.DeleteLog(admin, dbPath); _executors[typeof(Operations.RenameLog).Name.ToUpper()] = new Operations.RenameLog(admin, dbPath); _executors[typeof(Operations.EnumeratePackages).Name.ToUpper()] = new Operations.EnumeratePackages(admin, dbPath); _executors[typeof(Operations.DeletePackage).Name.ToUpper()] = new Operations.DeletePackage(admin, dbPath); _executors[typeof(Operations.LoadPackage).Name.ToUpper()] = new Operations.LoadPackage(admin, dbPath); _executors[typeof(Operations.GetPackageStatus).Name.ToUpper()] = new Operations.GetPackageStatus(admin, dbPath); _executors[typeof(Operations.GetPackageLog).Name.ToUpper()] = new Operations.GetPackageLog(admin, dbPath); //Site Service _executors[typeof(Operations.CreateSession).Name.ToUpper()] = new Operations.CreateSession(site, dbPath, session); _executors[typeof(Operations.DestroySession).Name.ToUpper()] = new Operations.DestroySession(site, dbPath); _executors[typeof(Operations.GetUserForSession).Name.ToUpper()] = new Operations.GetUserForSession(site, dbPath, session); _executors[typeof(Operations.EnumerateUsers).Name.ToUpper()] = new Operations.EnumerateUsers(site, dbPath); _executors[typeof(Operations.AddUser).Name.ToUpper()] = new Operations.AddUser(site, dbPath); _executors[typeof(Operations.UpdateUser).Name.ToUpper()] = new Operations.UpdateUser(site, dbPath); _executors[typeof(Operations.DeleteUsers).Name.ToUpper()] = new Operations.DeleteUsers(site, dbPath); _executors[typeof(Operations.GrantRoleMembershipsToUsers).Name.ToUpper()] = new Operations.GrantRoleMembershipsToUsers(site, dbPath); _executors[typeof(Operations.RevokeRoleMembershipsFromUsers).Name.ToUpper()] = new Operations.RevokeRoleMembershipsFromUsers(site, dbPath); _executors[typeof(Operations.GrantGroupMembershipsToUsers).Name.ToUpper()] = new Operations.GrantGroupMembershipsToUsers(site, dbPath); _executors[typeof(Operations.RevokeGroupMembershipsFromUsers).Name.ToUpper()] = new Operations.RevokeGroupMembershipsFromUsers(site, dbPath); _executors[typeof(Operations.EnumerateGroups).Name.ToUpper()] = new Operations.EnumerateGroups(site, dbPath); _executors[typeof(Operations.EnumerateGroups2).Name.ToUpper()] = new Operations.EnumerateGroups2(site, dbPath); _executors[typeof(Operations.EnumerateRoles2).Name.ToUpper()] = new Operations.EnumerateRoles2(site, dbPath); _executors[typeof(Operations.AddGroup).Name.ToUpper()] = new Operations.AddGroup(site, dbPath); _executors[typeof(Operations.UpdateGroup).Name.ToUpper()] = new Operations.UpdateGroup(site, dbPath); _executors[typeof(Operations.DeleteGroups).Name.ToUpper()] = new Operations.DeleteGroups(site, dbPath); _executors[typeof(Operations.GrantRoleMembershipsToGroups).Name.ToUpper()] = new Operations.GrantRoleMembershipsToGroups(site, dbPath); _executors[typeof(Operations.RevokeRoleMembershipsFromGroups).Name.ToUpper()] = new Operations.RevokeRoleMembershipsFromGroups(site, dbPath); _executors[typeof(Operations.EnumerateRoles).Name.ToUpper()] = new Operations.EnumerateRoles(site, dbPath); _executors[typeof(Operations.EnumerateServers).Name.ToUpper()] = new Operations.EnumerateServers(site, dbPath); _executors[typeof(Operations.AddServer).Name.ToUpper()] = new Operations.AddServer(site, dbPath); _executors[typeof(Operations.UpdateServer).Name.ToUpper()] = new Operations.UpdateServer(site, dbPath); _executors[typeof(Operations.RemoveServer).Name.ToUpper()] = new Operations.RemoveServer(site, dbPath); //Web Layout _executors[typeof(Operations.WL_GetTitle).Name.ToUpper()] = new Operations.WL_GetTitle(wlCreator, dbPath); _executors[typeof(Operations.WL_GetMapDefinition).Name.ToUpper()] = new Operations.WL_GetMapDefinition(wlCreator, dbPath); _executors[typeof(Operations.WL_GetScale).Name.ToUpper()] = new Operations.WL_GetScale(wlCreator, dbPath); _executors[typeof(Operations.WL_GetCenter).Name.ToUpper()] = new Operations.WL_GetCenter(wlCreator, dbPath); _executors[typeof(Operations.WL_ShowToolbar).Name.ToUpper()] = new Operations.WL_ShowToolbar(wlCreator, dbPath); _executors[typeof(Operations.WL_ShowStatusbar).Name.ToUpper()] = new Operations.WL_ShowStatusbar(wlCreator, dbPath); _executors[typeof(Operations.WL_ShowTaskpane).Name.ToUpper()] = new Operations.WL_ShowTaskpane(wlCreator, dbPath); _executors[typeof(Operations.WL_ShowTaskbar).Name.ToUpper()] = new Operations.WL_ShowTaskbar(wlCreator, dbPath); _executors[typeof(Operations.WL_ShowLegend).Name.ToUpper()] = new Operations.WL_ShowLegend(wlCreator, dbPath); _executors[typeof(Operations.WL_ShowProperties).Name.ToUpper()] = new Operations.WL_ShowProperties(wlCreator, dbPath); _executors[typeof(Operations.WL_GetTaskPaneWidth).Name.ToUpper()] = new Operations.WL_GetTaskPaneWidth(wlCreator, dbPath); _executors[typeof(Operations.WL_GetInformationPaneWidth).Name.ToUpper()] = new Operations.WL_GetInformationPaneWidth(wlCreator, dbPath); _executors[typeof(Operations.WL_GetInitialTaskUrl).Name.ToUpper()] = new Operations.WL_GetInitialTaskUrl(wlCreator, dbPath); _executors[typeof(Operations.WL_ShowContextMenu).Name.ToUpper()] = new Operations.WL_ShowContextMenu(wlCreator, dbPath); _executors[typeof(Operations.WL_TestUiItem).Name.ToUpper()] = new Operations.WL_TestUiItem(wlCreator, dbPath); _executors[typeof(Operations.WL_HomeTooltip).Name.ToUpper()] = new Operations.WL_HomeTooltip(wlCreator, dbPath); _executors[typeof(Operations.WL_HomeDescription).Name.ToUpper()] = new Operations.WL_HomeDescription(wlCreator, dbPath); _executors[typeof(Operations.WL_BackTooltip).Name.ToUpper()] = new Operations.WL_BackTooltip(wlCreator, dbPath); _executors[typeof(Operations.WL_BackDescription).Name.ToUpper()] = new Operations.WL_BackDescription(wlCreator, dbPath); _executors[typeof(Operations.WL_ForwardTooltip).Name.ToUpper()] = new Operations.WL_ForwardTooltip(wlCreator, dbPath); _executors[typeof(Operations.WL_ForwardDescription).Name.ToUpper()] = new Operations.WL_ForwardDescription(wlCreator, dbPath); _executors[typeof(Operations.WL_TasksName).Name.ToUpper()] = new Operations.WL_TasksName(wlCreator, dbPath); _executors[typeof(Operations.WL_TasksTooltip).Name.ToUpper()] = new Operations.WL_TasksTooltip(wlCreator, dbPath); _executors[typeof(Operations.WL_TasksDescription).Name.ToUpper()] = new Operations.WL_TasksDescription(wlCreator, dbPath); } class MgWebLayoutCreator : Operations.IWebLayoutCreator { private MgResourceService _resSvc; private MgWebLayout _wl; public MgWebLayoutCreator(MgResourceService resSvc) { _resSvc = resSvc; } public MgWebLayout CreateWebLayout(MgResourceIdentifier resId) { if (_wl != null) return _wl; _wl = new MgWebLayout(_resSvc, resId); return _wl; } } class MgMapCreator : Operations.IMapCreator { private MgSiteConnection _siteConn; private MgMap _map; private MgResourceService _resSvc; public MgMapCreator(MgSiteConnection siteConn, MgResourceService resSvc) { _siteConn = siteConn; _resSvc = resSvc; } public MgMapBase CreateMap(MgResourceIdentifier resId) { //The test suite relies on the same map and not a new one //re-created on each test of that particular test suite if (_map != null) return _map; _map = new MgMap(_siteConn); _map.Create(resId, resId.GetName()); return _map; } public MgLayerBase CreateLayer(MgResourceIdentifier resId) { return new MgLayer(resId, _resSvc); } } class MgSessionCreator : Operations.ISessionCreator { private MgSiteConnection _siteConn; public MgSessionCreator(MgSiteConnection siteConn) { _siteConn = siteConn; } public string CreateSession() { var site = _siteConn.GetSite(); return site.CreateSession(); } } class MgApplySession : Operations.IApplySession { private MgUserInformation _userInfo; public MgApplySession(MgUserInformation userInfo) { _userInfo = userInfo; } public void SetSessionId(string sessionId) { _userInfo.SetMgSessionId(sessionId); } } class MgSession : Operations.IMapGuideSession { public string SessionID { get; set; } } public override ITestExecutor GetTestExecutor(string opName) { if (_executors.ContainsKey(opName)) return _executors[opName]; throw new Exception("Executor for " + opName + " not found"); } public override int ValidateRequest(SqliteDotNet.SqliteDb db, string testName, int paramSetId, string operation, TestResult actualResult, ITestLogger logger) { int exitStatus = 0; string outcome = "pass"; SqliteVm vm = new SqliteVm(db, false); object expectedResult = null; //If we have an exception we need to remove the stack trace because different line numbers will fail the test object resultData = CommonUtility.RemoveStackTraceFromResult(actualResult.ResultData); //Get the mime type based on the content type in the result string mimeType = actualResult.ContentType; //If we have exception message we need to remove any parts that may contain system dependent information //Ex. file paths resultData = CommonUtility.ProcessExceptionMessage(resultData); //Get the file extension that will be used for a dump string actualExtension = CommonUtility.GetExtensionFromMimeType(mimeType); //If we have an ALWAYSPASS parameter defined for the operation then skip the whole validation process //This parameter should only be used for clean up operations that are no related with the tests if (vm.Execute("Select ParamValue from Params where ParamName=\"ALWAYSPASS\" and ParamSet={0}", paramSetId) != Sqlite.Row) { //TestName is Test_[ServiceType] string type = testName.Substring(testName.IndexOf("_") + 1); string filePath = CommonUtility.GetPath(string.Format("../../TestData/{0}/DumpFiles/{0}ApiTest", type)); string fileName = string.Format("{0}_{1}.{2}", filePath, paramSetId, actualExtension); if (this.TestExecutionMode == "dump") { //File.WriteAllText(fileName, resultData); throw new NotImplementedException("The .net test runner does not support dumping of test results. Please use the PHP test runner for this purpose"); } else { //This section is special case handling for the operations that return different data after each call resultData = CommonUtility.SpecialDataHandling(operation, resultData, mimeType); if (this.TestExecutionMode == "generate") { throw new NotImplementedException("The .net test runner does not support test update/generation. Please use the PHP test runner for this purpose"); /* //Get the sample result that is stored in the database. If we are using file on disk for validation //then do not overwrite the filename in the database //To distinguish between sample data and filename all filenames should be prefixed with "@@" int status = vm.Execute("Select Result from ApiTestResults where ParamSet={0}", paramSetId); string sampleResult = vm.GetString("Result"); if (!sampleResult.StartsWith("@@")) { //Insert the sample data as a BLOB //Update the row for that param set or create a new row if we do not have it yet string responseBody = ""; if (status == Sqlite.Row) { vm.Prepare("update ApiTestResults set Result = :blob where ParamSet={0}", paramSetId); } else { Console.WriteLine("A new row has been created in ApiTestResults table to store the result for operation {0}", paramSetId); Console.WriteLine("Please update the description field for that row later"); vm.Prepare("INSERT INTO ApiTestResults(ParamSet, Result) VALUES({0}, :blob)", paramSetId); } byte[] bytes = Encoding.UTF8.GetBytes(resultData); vm.BindBlob(":blob", bytes); vm.Execute(); if (mimeType != null) { vm.Execute("UPDATE ApiTestResults SET ContentType=\"{0}\" WHERE ParamSet={1}", mimeType, paramSetId); } File.WriteAllText(fileName, resultData); } */ } else if (this.TestExecutionMode == "validate" || this.TestExecutionMode == "show") { string resultContent = ""; //Get the sample result and the expected content type from the database int status = vm.Execute("Select Result, ContentType from ApiTestResults where ParamSet={0}", paramSetId); string expectedContentType = vm.GetString("ContentType"); string expectedExtension = CommonUtility.GetExtensionFromMimeType(expectedContentType); SqliteGcBlob blob = vm.GetBlob("Result"); byte[] b = blob.Read(); if (b != null) { if (expectedExtension == "xml" || expectedExtension == "txt" || expectedExtension == "html") expectedResult = Encoding.UTF8.GetString(b); else expectedResult = b; } else { if (expectedExtension == "xml" || expectedExtension == "txt" || expectedExtension == "html") expectedResult = string.Empty; else expectedResult = null; } string strExpectedResult = expectedResult as string; //If we are validating from a file then get the contents of that file //File names should be prefixed with "@@" to distinguish them from BLOB data if (strExpectedResult != null && strExpectedResult.StartsWith("@@")) { string sampleDataFile = strExpectedResult.Substring(2); sampleDataFile = CommonUtility.GetPath(sampleDataFile); expectedResult = File.ReadAllText(sampleDataFile); } if (this.TestExecutionMode == "validate") { bool bEqual = false; byte[] bExpected = expectedResult as byte[]; byte[] bActual = resultData as byte[]; string strResultData = resultData as string; //FIXME: We're not processing DWF content properly to do this check properly. So just //pass these for now if (operation == "GETDRAWINGLAYER" || operation == "GETDRAWINGSECTION") { bEqual = true; } else { if (strExpectedResult != null && strResultData != null) { //Normalize line endings on LF before comparsion (in case the SQLite GUI recorded CRLFs) string normStrResultData = strResultData.Replace("\r\n", "\n"); string normStrExpectedResult = strExpectedResult.Replace("\r\n", "\n"); bEqual = normStrResultData.Equals(normStrExpectedResult, StringComparison.InvariantCultureIgnoreCase); } else if (bExpected != null && bActual != null) { bEqual = CommonUtility.ByteArraysEqual(bExpected, bActual, operation, testName); } else { System.Diagnostics.Debug.WriteLine(string.Format("[MgTestRunner]: {0} - {1} - Encountered disparate data types between expected and actual results. Expecting test failure :(", testName, operation)); } } //If the results are different and special validation fails then the operation failed ->mark it red if (!bEqual && !CommonUtility.SpecialValidation(operation, resultData, expectedResult)) { outcome = "fail"; exitStatus = 1; if (expectedExtension != "xml" && expectedExtension != "html" && expectedExtension != "txt") { expectedResult = "Unable to display binary data"; } if (actualExtension != "xml" && actualExtension != "html" && actualExtension != "txt") { resultData = "Unable to display binary data"; } } } else { throw new NotImplementedException("The .net test runner does not support the given test execution mode (" + this.TestExecutionMode + "). Please use the PHP test runner for this purpose"); /* type = testName.Substring(testName.IndexOf("_") + 1); string showPath = CommonUtility.GetPath(string.Format("../../TestData/{0}/ShowFiles/{0}ApiTest", type)); string showName = string.Format("{0}_{1}.{2}", showPath, paramSetId, actualExtension); File.WriteAllText(showName, expectedResult); */ } } } } if (outcome == "fail") { Console.WriteLine("****{0} {1} {2} failed.\n", testName, paramSetId, operation); string str = string.Format("\n****ACTUAL RESULT****\n{0}\n****EXPECTED RESULT****\n{1}\n********\n\n\n", resultData, expectedResult); //Console.WriteLine(str); //Console.WriteLine(""); logger.Write(str); } vm.SqlFinalize(); vm = null; return exitStatus; } public override void Cleanup() { foreach (var exec in _executors.Values) { exec.Dispose(); } _executors.Clear(); } public override string ApiType { get { return ApiTypes.Platform; } } } }