[mapguide-commits] r7655 - in trunk/MgDev/UnitTest/WebTier: . DotNet DotNet/MgTestRunner DotNet/MgTestRunner/Properties DotNet/TestCommon DotNet/TestCommon/FeatureService DotNet/TestCommon/MapLayer DotNet/TestCommon/Properties DotNet/TestCommon/ResourceService DotNet/TestMapGuideApi DotNet/TestMapGuideApi/DrawingService DotNet/TestMapGuideApi/MappingService DotNet/TestMapGuideApi/Properties DotNet/TestMapGuideApi/RenderingService DotNet/TestMapGuideApi/ServerAdmin DotNet/TestMapGuideApi/SiteService DotNet/TestMapGuideApi/WebLayout

svn_mapguide at osgeo.org svn_mapguide at osgeo.org
Tue Jul 2 08:49:52 PDT 2013


Author: jng
Date: 2013-07-02 08:49:52 -0700 (Tue, 02 Jul 2013)
New Revision: 7655

Added:
   trunk/MgDev/UnitTest/WebTier/DotNet/
   trunk/MgDev/UnitTest/WebTier/DotNet/DotNet.sln
   trunk/MgDev/UnitTest/WebTier/DotNet/MgTestRunner/
   trunk/MgDev/UnitTest/WebTier/DotNet/MgTestRunner/App.config
   trunk/MgDev/UnitTest/WebTier/DotNet/MgTestRunner/MgTestRunner.csproj
   trunk/MgDev/UnitTest/WebTier/DotNet/MgTestRunner/MgTestRunner.csproj.user
   trunk/MgDev/UnitTest/WebTier/DotNet/MgTestRunner/Program.cs
   trunk/MgDev/UnitTest/WebTier/DotNet/MgTestRunner/Properties/
   trunk/MgDev/UnitTest/WebTier/DotNet/MgTestRunner/Properties/AssemblyInfo.cs
   trunk/MgDev/UnitTest/WebTier/DotNet/TestCommon/
   trunk/MgDev/UnitTest/WebTier/DotNet/TestCommon/ApiTypes.cs
   trunk/MgDev/UnitTest/WebTier/DotNet/TestCommon/CommonUtility.cs
   trunk/MgDev/UnitTest/WebTier/DotNet/TestCommon/FeatureService/
   trunk/MgDev/UnitTest/WebTier/DotNet/TestCommon/FeatureService/FeatureServiceOperationExecutor.cs
   trunk/MgDev/UnitTest/WebTier/DotNet/TestCommon/FeatureService/Operations.cs
   trunk/MgDev/UnitTest/WebTier/DotNet/TestCommon/ITestExecutor.cs
   trunk/MgDev/UnitTest/WebTier/DotNet/TestCommon/ITestExecutorCollection.cs
   trunk/MgDev/UnitTest/WebTier/DotNet/TestCommon/ITestLogger.cs
   trunk/MgDev/UnitTest/WebTier/DotNet/TestCommon/MapLayer/
   trunk/MgDev/UnitTest/WebTier/DotNet/TestCommon/MapLayer/MapLayerOperationExecutor.cs
   trunk/MgDev/UnitTest/WebTier/DotNet/TestCommon/MapLayer/Operations.cs
   trunk/MgDev/UnitTest/WebTier/DotNet/TestCommon/PlatformApiTestExecutor.cs
   trunk/MgDev/UnitTest/WebTier/DotNet/TestCommon/Properties/
   trunk/MgDev/UnitTest/WebTier/DotNet/TestCommon/Properties/AssemblyInfo.cs
   trunk/MgDev/UnitTest/WebTier/DotNet/TestCommon/ResourceService/
   trunk/MgDev/UnitTest/WebTier/DotNet/TestCommon/ResourceService/Operations.cs
   trunk/MgDev/UnitTest/WebTier/DotNet/TestCommon/ResourceService/ResourceServiceOperationExecutor.cs
   trunk/MgDev/UnitTest/WebTier/DotNet/TestCommon/SqliteException.cs
   trunk/MgDev/UnitTest/WebTier/DotNet/TestCommon/TestCommon.csproj
   trunk/MgDev/UnitTest/WebTier/DotNet/TestCommon/TestExecutionRun.cs
   trunk/MgDev/UnitTest/WebTier/DotNet/TestCommon/TestExecutorBase.cs
   trunk/MgDev/UnitTest/WebTier/DotNet/TestCommon/TestResult.cs
   trunk/MgDev/UnitTest/WebTier/DotNet/TestCommon/UnitTestException.cs
   trunk/MgDev/UnitTest/WebTier/DotNet/TestMapGuideApi/
   trunk/MgDev/UnitTest/WebTier/DotNet/TestMapGuideApi/DrawingService/
   trunk/MgDev/UnitTest/WebTier/DotNet/TestMapGuideApi/DrawingService/DrawingServiceOperationExecutor.cs
   trunk/MgDev/UnitTest/WebTier/DotNet/TestMapGuideApi/DrawingService/Operations.cs
   trunk/MgDev/UnitTest/WebTier/DotNet/TestMapGuideApi/MapGuideTestExecutorCollection.cs
   trunk/MgDev/UnitTest/WebTier/DotNet/TestMapGuideApi/MappingService/
   trunk/MgDev/UnitTest/WebTier/DotNet/TestMapGuideApi/MappingService/MappingServiceOperationExecutor.cs
   trunk/MgDev/UnitTest/WebTier/DotNet/TestMapGuideApi/Properties/
   trunk/MgDev/UnitTest/WebTier/DotNet/TestMapGuideApi/Properties/AssemblyInfo.cs
   trunk/MgDev/UnitTest/WebTier/DotNet/TestMapGuideApi/RenderingService/
   trunk/MgDev/UnitTest/WebTier/DotNet/TestMapGuideApi/RenderingService/RenderingServiceOperationExecutor.cs
   trunk/MgDev/UnitTest/WebTier/DotNet/TestMapGuideApi/ServerAdmin/
   trunk/MgDev/UnitTest/WebTier/DotNet/TestMapGuideApi/ServerAdmin/ServerAdminOperationExecutor.cs
   trunk/MgDev/UnitTest/WebTier/DotNet/TestMapGuideApi/SiteService/
   trunk/MgDev/UnitTest/WebTier/DotNet/TestMapGuideApi/SiteService/SiteServiceOperationExecutor.cs
   trunk/MgDev/UnitTest/WebTier/DotNet/TestMapGuideApi/TestMapGuideApi.csproj
   trunk/MgDev/UnitTest/WebTier/DotNet/TestMapGuideApi/WebLayout/
   trunk/MgDev/UnitTest/WebTier/DotNet/TestMapGuideApi/WebLayout/WebLayoutOperationExecutor.cs
   trunk/MgDev/UnitTest/WebTier/DotNet/readme.txt
Log:
#2307: Check in a work in progress of the .net MapGuide Web API test runner. This works off of the same dump files as the PHP one, but differs from the PHP one in the following ways:

 * We're using SqliteDotNet in Oem, which was already 90% there (made 100% by r7654) so we don't have to make a fresh SWIG binding to this library like the PHP one
 * This does not support test updating/generation. The PHP one can be used for this purpose.
 * This does not support or run the HTTP tests. The PHP one already covers this. Duplicating it here is redundant.
 * This runs strictly from the command line

This runner contains 2/3 of the Web API test suite. Some tests are currently failing on this one.


Property changes on: trunk/MgDev/UnitTest/WebTier/DotNet
___________________________________________________________________
Added: svn:ignore
   + Libs

Added: bugtraq:number
   + true

Added: trunk/MgDev/UnitTest/WebTier/DotNet/DotNet.sln
===================================================================
--- trunk/MgDev/UnitTest/WebTier/DotNet/DotNet.sln	                        (rev 0)
+++ trunk/MgDev/UnitTest/WebTier/DotNet/DotNet.sln	2013-07-02 15:49:52 UTC (rev 7655)
@@ -0,0 +1,46 @@
+
+Microsoft Visual Studio Solution File, Format Version 12.00
+# Visual Studio Express 2012 for Windows Desktop
+Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "TestCommon", "TestCommon\TestCommon.csproj", "{80EAA5CB-E709-485A-86AC-DE9B5236EAB9}"
+EndProject
+Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "TestMapGuideApi", "TestMapGuideApi\TestMapGuideApi.csproj", "{54A7F4EE-D977-4DFB-9922-C46C5FFB6822}"
+EndProject
+Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "MgTestRunner", "MgTestRunner\MgTestRunner.csproj", "{C920EC51-255B-4257-81AA-8D984B5B5A48}"
+EndProject
+Global
+	GlobalSection(SolutionConfigurationPlatforms) = preSolution
+		Debug|x64 = Debug|x64
+		Debug|x86 = Debug|x86
+		Release|x64 = Release|x64
+		Release|x86 = Release|x86
+	EndGlobalSection
+	GlobalSection(ProjectConfigurationPlatforms) = postSolution
+		{80EAA5CB-E709-485A-86AC-DE9B5236EAB9}.Debug|x64.ActiveCfg = Debug|x64
+		{80EAA5CB-E709-485A-86AC-DE9B5236EAB9}.Debug|x64.Build.0 = Debug|x64
+		{80EAA5CB-E709-485A-86AC-DE9B5236EAB9}.Debug|x86.ActiveCfg = Debug|x86
+		{80EAA5CB-E709-485A-86AC-DE9B5236EAB9}.Debug|x86.Build.0 = Debug|x86
+		{80EAA5CB-E709-485A-86AC-DE9B5236EAB9}.Release|x64.ActiveCfg = Release|x64
+		{80EAA5CB-E709-485A-86AC-DE9B5236EAB9}.Release|x64.Build.0 = Release|x64
+		{80EAA5CB-E709-485A-86AC-DE9B5236EAB9}.Release|x86.ActiveCfg = Release|x86
+		{80EAA5CB-E709-485A-86AC-DE9B5236EAB9}.Release|x86.Build.0 = Release|x86
+		{54A7F4EE-D977-4DFB-9922-C46C5FFB6822}.Debug|x64.ActiveCfg = Debug|x64
+		{54A7F4EE-D977-4DFB-9922-C46C5FFB6822}.Debug|x64.Build.0 = Debug|x64
+		{54A7F4EE-D977-4DFB-9922-C46C5FFB6822}.Debug|x86.ActiveCfg = Debug|x86
+		{54A7F4EE-D977-4DFB-9922-C46C5FFB6822}.Debug|x86.Build.0 = Debug|x86
+		{54A7F4EE-D977-4DFB-9922-C46C5FFB6822}.Release|x64.ActiveCfg = Release|x64
+		{54A7F4EE-D977-4DFB-9922-C46C5FFB6822}.Release|x64.Build.0 = Release|x64
+		{54A7F4EE-D977-4DFB-9922-C46C5FFB6822}.Release|x86.ActiveCfg = Release|x86
+		{54A7F4EE-D977-4DFB-9922-C46C5FFB6822}.Release|x86.Build.0 = Release|x86
+		{C920EC51-255B-4257-81AA-8D984B5B5A48}.Debug|x64.ActiveCfg = Debug|x64
+		{C920EC51-255B-4257-81AA-8D984B5B5A48}.Debug|x64.Build.0 = Debug|x64
+		{C920EC51-255B-4257-81AA-8D984B5B5A48}.Debug|x86.ActiveCfg = Debug|x86
+		{C920EC51-255B-4257-81AA-8D984B5B5A48}.Debug|x86.Build.0 = Debug|x86
+		{C920EC51-255B-4257-81AA-8D984B5B5A48}.Release|x64.ActiveCfg = Release|x64
+		{C920EC51-255B-4257-81AA-8D984B5B5A48}.Release|x64.Build.0 = Release|x64
+		{C920EC51-255B-4257-81AA-8D984B5B5A48}.Release|x86.ActiveCfg = Release|x86
+		{C920EC51-255B-4257-81AA-8D984B5B5A48}.Release|x86.Build.0 = Release|x86
+	EndGlobalSection
+	GlobalSection(SolutionProperties) = preSolution
+		HideSolutionNode = FALSE
+	EndGlobalSection
+EndGlobal


Property changes on: trunk/MgDev/UnitTest/WebTier/DotNet/MgTestRunner
___________________________________________________________________
Added: bugtraq:number
   + true

Added: trunk/MgDev/UnitTest/WebTier/DotNet/MgTestRunner/App.config
===================================================================
--- trunk/MgDev/UnitTest/WebTier/DotNet/MgTestRunner/App.config	                        (rev 0)
+++ trunk/MgDev/UnitTest/WebTier/DotNet/MgTestRunner/App.config	2013-07-02 15:49:52 UTC (rev 7655)
@@ -0,0 +1,6 @@
+<?xml version="1.0" encoding="utf-8" ?>
+<configuration>
+    <startup> 
+        <supportedRuntime version="v4.0" sku=".NETFramework,Version=v4.5" />
+    </startup>
+</configuration>
\ No newline at end of file

Added: trunk/MgDev/UnitTest/WebTier/DotNet/MgTestRunner/MgTestRunner.csproj
===================================================================
--- trunk/MgDev/UnitTest/WebTier/DotNet/MgTestRunner/MgTestRunner.csproj	                        (rev 0)
+++ trunk/MgDev/UnitTest/WebTier/DotNet/MgTestRunner/MgTestRunner.csproj	2013-07-02 15:49:52 UTC (rev 7655)
@@ -0,0 +1,110 @@
+<?xml version="1.0" encoding="utf-8"?>
+<Project ToolsVersion="4.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
+  <Import Project="$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props" Condition="Exists('$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props')" />
+  <PropertyGroup>
+    <Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
+    <Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform>
+    <ProjectGuid>{C920EC51-255B-4257-81AA-8D984B5B5A48}</ProjectGuid>
+    <OutputType>Exe</OutputType>
+    <AppDesignerFolder>Properties</AppDesignerFolder>
+    <RootNamespace>MgTestRunner</RootNamespace>
+    <AssemblyName>MgTestRunner</AssemblyName>
+    <TargetFrameworkVersion>v4.5</TargetFrameworkVersion>
+    <FileAlignment>512</FileAlignment>
+  </PropertyGroup>
+  <PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'Debug|x64'">
+    <DebugSymbols>true</DebugSymbols>
+    <OutputPath>..\..\DotNet_x64\</OutputPath>
+    <DefineConstants>DEBUG;TRACE</DefineConstants>
+    <DebugType>full</DebugType>
+    <PlatformTarget>x64</PlatformTarget>
+    <ErrorReport>prompt</ErrorReport>
+    <CodeAnalysisRuleSet>ManagedMinimumRules.ruleset</CodeAnalysisRuleSet>
+    <Prefer32Bit>true</Prefer32Bit>
+  </PropertyGroup>
+  <PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'Release|x64'">
+    <OutputPath>bin\x64\Release\</OutputPath>
+    <DefineConstants>TRACE</DefineConstants>
+    <Optimize>true</Optimize>
+    <DebugType>pdbonly</DebugType>
+    <PlatformTarget>x64</PlatformTarget>
+    <ErrorReport>prompt</ErrorReport>
+    <CodeAnalysisRuleSet>ManagedMinimumRules.ruleset</CodeAnalysisRuleSet>
+    <Prefer32Bit>true</Prefer32Bit>
+  </PropertyGroup>
+  <PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'Debug|x86'">
+    <DebugSymbols>true</DebugSymbols>
+    <OutputPath>..\..\DotNet_x86\</OutputPath>
+    <DefineConstants>DEBUG;TRACE</DefineConstants>
+    <DebugType>full</DebugType>
+    <PlatformTarget>x86</PlatformTarget>
+    <ErrorReport>prompt</ErrorReport>
+    <CodeAnalysisRuleSet>ManagedMinimumRules.ruleset</CodeAnalysisRuleSet>
+    <Prefer32Bit>true</Prefer32Bit>
+    <WarningLevel>0</WarningLevel>
+    <UseVSHostingProcess>false</UseVSHostingProcess>
+  </PropertyGroup>
+  <PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'Release|x86'">
+    <OutputPath>bin\x86\Release\</OutputPath>
+    <DefineConstants>TRACE</DefineConstants>
+    <Optimize>true</Optimize>
+    <DebugType>pdbonly</DebugType>
+    <PlatformTarget>x86</PlatformTarget>
+    <ErrorReport>prompt</ErrorReport>
+    <CodeAnalysisRuleSet>ManagedMinimumRules.ruleset</CodeAnalysisRuleSet>
+    <Prefer32Bit>true</Prefer32Bit>
+  </PropertyGroup>
+  <ItemGroup>
+    <Reference Include="OSGeo.MapGuide.Foundation">
+      <HintPath>..\Libs\OSGeo.MapGuide.Foundation.dll</HintPath>
+    </Reference>
+    <Reference Include="OSGeo.MapGuide.Geometry">
+      <HintPath>..\Libs\OSGeo.MapGuide.Geometry.dll</HintPath>
+    </Reference>
+    <Reference Include="OSGeo.MapGuide.MapGuideCommon">
+      <HintPath>..\Libs\OSGeo.MapGuide.MapGuideCommon.dll</HintPath>
+    </Reference>
+    <Reference Include="OSGeo.MapGuide.PlatformBase">
+      <HintPath>..\Libs\OSGeo.MapGuide.PlatformBase.dll</HintPath>
+    </Reference>
+    <Reference Include="OSGeo.MapGuide.Web">
+      <HintPath>..\Libs\OSGeo.MapGuide.Web.dll</HintPath>
+    </Reference>
+    <Reference Include="System" />
+    <Reference Include="System.Core" />
+    <Reference Include="System.Xml.Linq" />
+    <Reference Include="System.Data.DataSetExtensions" />
+    <Reference Include="Microsoft.CSharp" />
+    <Reference Include="System.Data" />
+    <Reference Include="System.Xml" />
+  </ItemGroup>
+  <ItemGroup>
+    <Compile Include="Program.cs" />
+    <Compile Include="Properties\AssemblyInfo.cs" />
+  </ItemGroup>
+  <ItemGroup>
+    <None Include="App.config" />
+  </ItemGroup>
+  <ItemGroup>
+    <ProjectReference Include="..\TestCommon\TestCommon.csproj">
+      <Project>{80eaa5cb-e709-485a-86ac-de9b5236eab9}</Project>
+      <Name>TestCommon</Name>
+    </ProjectReference>
+    <ProjectReference Include="..\TestMapGuideApi\TestMapGuideApi.csproj">
+      <Project>{54a7f4ee-d977-4dfb-9922-c46c5ffb6822}</Project>
+      <Name>TestMapGuideApi</Name>
+    </ProjectReference>
+  </ItemGroup>
+  <Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
+  <PropertyGroup>
+    <PostBuildEvent>copy /Y "$(SolutionDir)Libs\*.*" "$(TargetDir)"
+xcopy /S /Y /I ..\..\..\Web\src\mapagent\Resources "$(TargetDir)\Resources"</PostBuildEvent>
+  </PropertyGroup>
+  <!-- To modify your build process, add your task inside one of the targets below and uncomment it. 
+       Other similar extension points exist, see Microsoft.Common.targets.
+  <Target Name="BeforeBuild">
+  </Target>
+  <Target Name="AfterBuild">
+  </Target>
+  -->
+</Project>
\ No newline at end of file

Added: trunk/MgDev/UnitTest/WebTier/DotNet/MgTestRunner/MgTestRunner.csproj.user
===================================================================
--- trunk/MgDev/UnitTest/WebTier/DotNet/MgTestRunner/MgTestRunner.csproj.user	                        (rev 0)
+++ trunk/MgDev/UnitTest/WebTier/DotNet/MgTestRunner/MgTestRunner.csproj.user	2013-07-02 15:49:52 UTC (rev 7655)
@@ -0,0 +1,10 @@
+<?xml version="1.0" encoding="utf-8"?>
+<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
+  <PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'Debug|x64'">
+    <StartArguments>webconfig.ini</StartArguments>
+  </PropertyGroup>
+  <PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'Debug|x86'">
+    <StartArguments>"../../../web/src/webconfig.ini" "../../../Oem/CsMap/Dictionaries"</StartArguments>
+    <EnableUnmanagedDebugging>true</EnableUnmanagedDebugging>
+  </PropertyGroup>
+</Project>
\ No newline at end of file

Added: trunk/MgDev/UnitTest/WebTier/DotNet/MgTestRunner/Program.cs
===================================================================
--- trunk/MgDev/UnitTest/WebTier/DotNet/MgTestRunner/Program.cs	                        (rev 0)
+++ trunk/MgDev/UnitTest/WebTier/DotNet/MgTestRunner/Program.cs	2013-07-02 15:49:52 UTC (rev 7655)
@@ -0,0 +1,80 @@
+using OSGeo.MapGuide;
+using OSGeo.MapGuide.Test.Common;
+using OSGeo.MapGuide.Test.Web;
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+
+namespace MgTestRunner
+{
+    //TODO: This test runner does not support generation/update mode yet. Please use the existing PHP test runner for doing this.
+
+    class Program
+    {
+        static MgUserInformation userInfo;
+        static MgSiteConnection siteConn;
+
+        //Usage: MgTestRunner.exe <webconfig.ini path> <MENTOR_DICTIONARY_PATH> [test log path]
+        static void Main(string[] args)
+        {
+            if (args.Length >= 2 && args.Length <= 3)
+            {
+                string webconfig = args[0];
+                string logFile = "UnitTests.log";
+                if (args.Length == 3)
+                    logFile = args[2];
+
+                int failures = 0;
+                using (var logger = new TestLoggerFile(logFile, false))
+                {
+                    logger.Write("Run started: {0}\n\n", DateTime.Now.ToString());
+
+                    Environment.SetEnvironmentVariable("MENTOR_DICTIONARY_PATH", args[1], EnvironmentVariableTarget.Process);
+
+                    MapGuideApi.MgInitializeWebTier(args[0]);
+                    userInfo = new MgUserInformation("Administrator", "admin");
+                    siteConn = new MgSiteConnection();
+                    siteConn.Open(userInfo);
+
+                    int testsRun = 0;
+                    bool isEnterprise = false;
+                    failures += ExecuteTest(ApiTypes.Platform, "../../TestData/ResourceService/ResourceServiceTest.dump", ref testsRun, logger, isEnterprise);
+                    failures += ExecuteTest(ApiTypes.Platform, "../../TestData/FeatureService/FeatureServiceTest.dump", ref testsRun, logger, isEnterprise);
+                    failures += ExecuteTest(ApiTypes.Platform, "../../TestData/MapLayer/MapLayerTest.dump", ref testsRun, logger, isEnterprise);
+                    failures += ExecuteTest(ApiTypes.Platform, "../../TestData/DrawingService/DrawingServiceTest.dump", ref testsRun, logger, isEnterprise);
+                    failures += ExecuteTest(ApiTypes.Platform, "../../TestData/MappingService/MappingServiceTest.dump", ref testsRun, logger, isEnterprise);
+                    //failures += ExecuteTest(ApiTypes.Platform, "../../TestData/SiteService/SiteServiceTest.dump", ref testsRun, logger, isEnterprise);
+                    //failures += ExecuteTest(ApiTypes.Platform, "../../TestData/ServerAdmin/ServerAdminTest.dump", ref testsRun, logger, isEnterprise);
+                    //failures += ExecuteTest(ApiTypes.Platform, "../../TestData/WebLayout/WebLayoutTest.dump", ref testsRun, logger, isEnterprise);
+                    failures += ExecuteTest(ApiTypes.Platform, "../../TestData/Unicode/UnicodeTest.dump", ref testsRun, logger, isEnterprise);
+                    logger.Write("\n\nTests failed/run: {0}/{1}\n", failures, testsRun);
+                    Console.Write("\n\nTests failed/run: {0}/{1}\n", failures, testsRun);
+                    logger.Write("Run ended: {0}\n\n", DateTime.Now.ToString());
+                }
+                Environment.ExitCode = failures;
+            }
+            else
+            {
+                Console.WriteLine("Usage: MgTestRunner.exe <webconfig.ini path> <MENTOR_DICTIONARY_PATH> [test log path]");
+                Environment.ExitCode = 1;
+            }
+        }
+
+        private static int ExecuteTest(string apiType, string dumpFile, ref int testsRun, TestLoggerFile logger, bool isEnterprise)
+        {
+            ITestExecutorCollection exec = null;
+            if (apiType == ApiTypes.Platform)
+                exec = new MapGuideTestExecutorCollection(userInfo, siteConn);
+
+            int ret = 0;
+            if (exec != null)
+            {
+                exec.Initialize("validate", dumpFile);
+                ret += exec.Execute(ref testsRun, logger, isEnterprise);
+            }
+            return ret;
+        }
+    }
+}


Property changes on: trunk/MgDev/UnitTest/WebTier/DotNet/MgTestRunner/Properties
___________________________________________________________________
Added: bugtraq:number
   + true

Added: trunk/MgDev/UnitTest/WebTier/DotNet/MgTestRunner/Properties/AssemblyInfo.cs
===================================================================
--- trunk/MgDev/UnitTest/WebTier/DotNet/MgTestRunner/Properties/AssemblyInfo.cs	                        (rev 0)
+++ trunk/MgDev/UnitTest/WebTier/DotNet/MgTestRunner/Properties/AssemblyInfo.cs	2013-07-02 15:49:52 UTC (rev 7655)
@@ -0,0 +1,36 @@
+using System.Reflection;
+using System.Runtime.CompilerServices;
+using System.Runtime.InteropServices;
+
+// General Information about an assembly is controlled through the following 
+// set of attributes. Change these attribute values to modify the information
+// associated with an assembly.
+[assembly: AssemblyTitle("MgTestRunner")]
+[assembly: AssemblyDescription("")]
+[assembly: AssemblyConfiguration("")]
+[assembly: AssemblyCompany("")]
+[assembly: AssemblyProduct("MgTestRunner")]
+[assembly: AssemblyCopyright("Copyright ©  2013")]
+[assembly: AssemblyTrademark("")]
+[assembly: AssemblyCulture("")]
+
+// Setting ComVisible to false makes the types in this assembly not visible 
+// to COM components.  If you need to access a type in this assembly from 
+// COM, set the ComVisible attribute to true on that type.
+[assembly: ComVisible(false)]
+
+// The following GUID is for the ID of the typelib if this project is exposed to COM
+[assembly: Guid("931557e7-5baa-4066-b770-886d5e746161")]
+
+// Version information for an assembly consists of the following four values:
+//
+//      Major Version
+//      Minor Version 
+//      Build Number
+//      Revision
+//
+// You can specify all the values or you can default the Build and Revision Numbers 
+// by using the '*' as shown below:
+// [assembly: AssemblyVersion("1.0.*")]
+[assembly: AssemblyVersion("1.0.0.0")]
+[assembly: AssemblyFileVersion("1.0.0.0")]


Property changes on: trunk/MgDev/UnitTest/WebTier/DotNet/TestCommon
___________________________________________________________________
Added: bugtraq:number
   + true

Added: trunk/MgDev/UnitTest/WebTier/DotNet/TestCommon/ApiTypes.cs
===================================================================
--- trunk/MgDev/UnitTest/WebTier/DotNet/TestCommon/ApiTypes.cs	                        (rev 0)
+++ trunk/MgDev/UnitTest/WebTier/DotNet/TestCommon/ApiTypes.cs	2013-07-02 15:49:52 UTC (rev 7655)
@@ -0,0 +1,14 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+
+namespace OSGeo.MapGuide.Test.Common
+{
+    public static class ApiTypes
+    {
+        public const string Platform = "Api";
+        public const string Http = "Http";
+    }
+}

Added: trunk/MgDev/UnitTest/WebTier/DotNet/TestCommon/CommonUtility.cs
===================================================================
--- trunk/MgDev/UnitTest/WebTier/DotNet/TestCommon/CommonUtility.cs	                        (rev 0)
+++ trunk/MgDev/UnitTest/WebTier/DotNet/TestCommon/CommonUtility.cs	2013-07-02 15:49:52 UTC (rev 7655)
@@ -0,0 +1,484 @@
+using SqliteDotNet;
+using System;
+using System.Collections.Generic;
+using System.Collections.Specialized;
+using System.Globalization;
+using System.IO;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+using System.Xml;
+
+namespace OSGeo.MapGuide.Test.Common
+{
+    /// <summary>
+    /// Extension methods for SqliteVm
+    /// </summary>
+    public static class SqliteDbExtensions
+    {
+        public static int Prepare(this SqliteVm vm, string sql, params object[] args)
+        {
+            string formattedSql = string.Format(sql, args);
+            return vm.Prepare(formattedSql);
+        }
+
+        public static int Execute(this SqliteVm vm, string sql, params object[] args)
+        {
+            string formattedSql = string.Format(sql, args);
+            return vm.Execute(formattedSql);
+        }
+
+        public static bool ReadParameterValue(this SqliteVm vm, int paramSetId, string paramName, NameValueCollection result, bool bIsPath = false)
+        {
+            int stat = vm.Execute("Select ParamValue from Params WHERE ParamSet={0} AND ParamName=\"{1}\"", paramSetId, paramName);
+            if (stat == Sqlite.Row)
+            {
+                string str = vm.GetString("ParamValue");
+                if (bIsPath)
+                {
+                    str = CommonUtility.GetPath(str);
+                }
+                result.Add(paramName, str);
+                return true;
+            }
+            return false;
+        }
+
+        public static bool ReadParameterValue(this SqliteVm vm, string paramName, NameValueCollection result)
+        {
+            int stat = vm.Execute("Select ParamValue from Params WHERE ParamName=\"{0}\"", paramName);
+            if (stat == Sqlite.Row)
+            {
+                result.Add(paramName, vm.GetString("ParamValue"));
+                return true;
+            }
+            return false;
+        }
+
+        public static bool ReadCommonParameterValue(this SqliteVm vm, string paramName, NameValueCollection result)
+        {
+            int stat = vm.Execute("Select ParamValue from CommonParams WHERE ParamName=\"{0}\"", paramName);
+            if (stat == Sqlite.Row)
+            {
+                result.Add(paramName, vm.GetString("ParamValue"));
+                return true;
+            }
+            return false;
+        }
+    }
+
+    /// <summary>
+    /// Common utility methods
+    /// </summary>
+    public class CommonUtility
+    {
+        public static NameValueCollection SetCommonParams(int paramSet, SqliteDb db)
+        {
+            NameValueCollection result = null;
+            var vm = new SqliteVm(db, false);
+            try
+            {
+                result = new NameValueCollection();
+
+                vm.ReadParameterValue(paramSet, "OPERATION", result);
+                vm.ReadCommonParameterValue("VERSION", result);
+                vm.ReadCommonParameterValue("CREDENTIALS", result);
+                vm.ReadCommonParameterValue("LOCALE", result);
+
+                vm = null;
+            }
+            catch (MgException ex)
+            {
+                throw new UnitTestException(string.Format("Exception from MapGuide:\n{0}", ex.GetDetails()));
+            }
+            catch (Exception ex)
+            {
+                try
+                {
+                    vm = null;
+                    vm = new SqliteVm(db, true);
+                    vm.ReadParameterValue("VERSION", result);
+                    vm.ReadParameterValue("CREDENTIALS", result);
+                    vm.ReadParameterValue("LOCALE", result);
+                }
+                catch (Exception ex2)
+                {
+
+                }
+            }
+            return result;
+        }
+
+        public static MgByteReader GetByteReaderFromPath(string path, bool bCheck = true)
+        {
+            if (bCheck)
+            {
+                if (File.Exists(path))
+                {
+                    MgByteSource source = new MgByteSource(path);
+                    MgByteReader reader = source.GetReader();
+                    return reader;
+                }
+                return null;
+            }
+            else
+            {
+                MgByteSource source = new MgByteSource(path);
+                MgByteReader reader = source.GetReader();
+                return reader;
+            }
+        }
+
+        public static string GetDbPath(string dumpFileName)
+        {
+            var db = new SqliteDb();
+            var dbPath = dumpFileName.Replace(".dump", ".db");
+            var dbName = CommonUtility.GetPath(dbPath);
+
+            if (!File.Exists(dumpFileName) && !File.Exists(dbName))
+            {
+                throw new UnitTestException(string.Format("Error: Dump file {0} not found. Unable to create database file", dumpFileName));
+            }
+            else if (!File.Exists(dbName))
+            {
+                db.GenerateDatabase(dumpFileName, dbName);
+            }
+            else if (File.Exists(dumpFileName) && File.GetLastWriteTimeUtc(dumpFileName) > File.GetLastWriteTimeUtc(dbName))
+            {
+                try
+                {
+                    File.Delete(dbName);
+                    db.GenerateDatabase(dumpFileName, dbName);
+                }
+                catch
+                {
+                    throw new UnitTestException(string.Format("Unable to delete database file {0}. The file is either in use or is read-only. The database has not been updated", dbName));
+                }
+            }
+
+            return dbPath;
+        }
+
+        public static string GetPath(string dbPath)
+        {
+            return dbPath.Replace("\\", "/");
+        }
+
+        public static MgStringCollection StringToMgStringCollection(string str)
+        {
+            try
+            {
+                MgStringCollection coll = new MgStringCollection();
+                string[] tokens = str.Split(',');
+                foreach (var token in tokens)
+                {
+                    coll.Add(token);
+                }
+                return coll;
+            }
+            catch (MgException ex)
+            {
+                throw new UnitTestException(string.Format("Exception from MapGuide:\n{0}", ex.GetDetails()));
+            }
+        }
+
+        public static string MgStringCollectionToString(MgStringCollection coll)
+        {
+            try
+            {
+                List<string> items = new List<string>();
+                for (int i = 0; i < coll.GetCount(); i++)
+                {
+                    items.Add(coll.GetItem(i));
+                }
+                return string.Join(",", items.ToArray());
+            }
+            catch (MgException ex)
+            {
+                throw new UnitTestException(string.Format("Exception from MapGuide:\n{0}", ex.GetDetails()));
+            }
+        }
+
+        public static string BooleanToString(bool b)
+        {
+            return b ? "True" : "False";
+        }
+
+        public static string MgEnvelopeToString(MgEnvelope env)
+        {
+            try
+            {
+                var ll = env.GetLowerLeftCoordinate();
+                var ur = env.GetUpperRightCoordinate();
+                return string.Format(CultureInfo.InvariantCulture,
+                    "({0}:{1})-({2}:{3})", 
+                    ll.GetX(), 
+                    ll.GetY(), 
+                    ur.GetX(), 
+                    ur.GetY());
+            }
+            catch (MgException ex)
+            {
+                throw new UnitTestException(string.Format("Exception from MapGuide:\n{0}", ex.GetDetails()));
+            }
+        }
+
+        public static string MgPointToString(MgPoint pt)
+        {
+            try
+            {
+                var coord = pt.GetCoordinate();
+                return string.Format(CultureInfo.InvariantCulture,
+                    "({0}:{1})",
+                    coord.GetX(),
+                    coord.GetY());
+            }
+            catch (MgException ex)
+            {
+                throw new UnitTestException(string.Format("Exception from MapGuide:\n{0}", ex.GetDetails()));
+            }
+        }
+
+        public static string GetExtension(string name)
+        {
+            if (name.LastIndexOf(".") >= 0)
+            {
+                return name.Substring(name.LastIndexOf(".") + 1);
+            }
+            else
+            {
+                if (name == "MG_USER_CREDENTIALS")
+                    return "txt";
+                else
+                    return "bin";
+            }
+        }
+
+        public static string GetMimeType(string extension)
+        {
+            switch (extension)
+            {
+                case "agf":
+                    return "application/agf";
+                case "bin":
+                    return "application/octet-stream";
+                case "dwf":
+                    return "model/vnd.dwf";
+                case "jpg":
+                case "jpeg":
+                    return "image/jpeg";
+                case "png":
+                    return "image/png";
+                case "tif":
+                case "tiff":
+                    return "image/tiff";
+                case "html":
+                    return "text/html";
+                case "txt":
+                    return "text/plain";
+                case "xml":
+                    return "text/xml";
+                default:
+                    return "application/octet-stream";
+            }
+        }
+
+        public static string SpecialDataHandling(string operation, string resultData, string mimeType)
+        {
+            string res = resultData;
+            switch (operation)
+            {
+                case "ENUMERATERESOURCES":
+                    res = RemoveTimeStamp(resultData);
+                    break;
+                case "GETDRAWINGLAYER":
+                    res = RemoveDwfSectionName(resultData);
+                    break;
+                case "GETDRAWINGSECTION":
+                    res = RemoveDwfSectionName(resultData);
+                    break;
+                case "GETLOG":
+                    res = RemoveLogEntryTimeStamp(resultData);
+                    break;
+                case "GETMAP":
+                    res = GetMapHeader(resultData);
+                    break;
+                case "GETLONGTRANSACTIONS":
+                    res = RemoveCreationDate(resultData);
+                    break;
+            }
+
+            if (res != null && mimeType == "text/xml")
+            {
+                var doc = new XmlDocument();
+                doc.LoadXml(res);
+                res = SortElement(doc, "");
+            }
+            return res;
+        }
+
+        private static string SortElement(XmlNode elem, string preText)
+        {
+            var elemArray = new List<string>();
+            string elemString = "";
+            if (elem.ChildNodes.Count > 0)
+            {
+                foreach (XmlNode child in elem.ChildNodes)
+                {
+                    if (child.NodeType == XmlNodeType.Element)
+                    {
+                        var elemValue = SortElement(child, preText + "  ");
+                        if (!string.IsNullOrEmpty(elemValue))
+                            elemArray.Add(elemValue);
+                    }
+                    else if (child.NodeType == XmlNodeType.Text)
+                    {
+                        string content = child.InnerText.Trim();
+                        if (!string.IsNullOrEmpty(content))
+                            elemArray.Add(content);
+                    }
+                }
+                elemArray.Sort();
+                foreach (string str in elemArray)
+                {
+                    elemString += str;
+                }
+            }
+
+            string endTag = "";
+            if (elemArray.Count > 1 && elemString.Length > 0)
+            {
+                endTag = "\n" + preText;
+            }
+            string tagName = "";
+            if (!(elem is XmlDocument))
+            {
+                tagName = elem.Name;
+            }
+            endTag += "</" + tagName + ">";
+
+            if ("" != tagName)
+            {
+                elemString = "\n" + preText + "<" + tagName + ">" + elemString + endTag;
+            }
+
+            return elemString;
+        }
+
+        private static string RemoveTimeStamp(string resultData)
+        {
+            string result = resultData;
+            string newResult = result;
+            while (result.IndexOf("<CreatedDate>") >= 0)
+            {
+                newResult = result.Substring(0, result.IndexOf("<CreatedDate>"));
+                newResult += result.Substring(result.IndexOf("</ModifiedDate>") + "</ModifiedDate>".Length);
+                result = newResult;
+            }
+            return newResult;
+        }
+
+        private static string RemoveDwfSectionName(string resultData)
+        {
+            string newResult = resultData.Substring(resultData.IndexOf(".w2d"));
+            if (0 != newResult.IndexOf("EndOfDWF"))
+            {
+                newResult = newResult.Substring(0, newResult.IndexOf("EndOfDWF"));
+            }
+            return newResult;
+        }
+
+        private static string RemoveLogEntryTimeStamp(string resultData)
+        {
+            string result = resultData;
+            string newResult = result;
+            while (result.IndexOf("<") >= 0)
+            {
+                newResult = result.Substring(0, result.IndexOf("<"));
+                newResult += result.Substring(result.IndexOf(">") + 1);
+                result = newResult;
+            }
+            return newResult;
+        }
+
+        private static string GetMapHeader(string resultData)
+        {
+            if (resultData.IndexOf("(DWF V06.01)") >= 0)
+                resultData = "(DWF V06.01)";
+            return resultData;
+        }
+
+        private static string RemoveCreationDate(string resultData)
+        {
+            string newResult = resultData;
+            while (resultData.IndexOf("<CreationDate>") >= 0)
+            {
+                newResult = resultData.Substring(0, resultData.IndexOf("<CreationDate>"));
+                newResult += resultData.Substring(resultData.IndexOf("</CreationDate>") + "</CreationDate>".Length);
+                resultData = newResult;
+            }
+            return newResult;
+        }
+
+        public static string ProcessExceptionMessage(string resultData)
+        {
+            string text = "exception occurred";
+            if (resultData.Contains(text))
+            {
+                resultData = resultData.Substring(0, resultData.IndexOf(text) + text.Length); 
+            }
+            return resultData;
+        }
+
+        public static bool SpecialValidation(string operation, string resultData, string expectedResult)
+        {
+            if (operation == "GETFEATUREPROVIDERS")
+            {
+                return GetFeatureProvidersValidation(resultData, expectedResult);
+            }
+            return false;
+        }
+
+        private static bool GetFeatureProvidersValidation(string resultData, string expectedResult)
+        {
+            throw new NotImplementedException();
+        }
+
+        public static string RemoveStackTraceFromResult(string result)
+        {
+            //TODO: Clean out stack trace
+            return result;
+        }
+
+        public static string GetExtensionFromMimeType(string mimeType)
+        {
+            string extension = "xml";
+            if (mimeType.Contains("ePlot"))
+                return "dwf";
+            if (mimeType.Contains("text/plain"))
+                return "txt";
+            if (mimeType.Contains("text/html"))
+                return "html";
+
+            switch (mimeType)
+            { 
+                case "application/agf":
+                    return "agf";
+                case "application/octet-stream":
+                    return "bin";
+                case "model/vnd.dwf":
+                    return "dwf";
+                case "image/jpeg":
+                    return "jpg";
+                case "image/png":
+                    return "png";
+                case "image/tiff":
+                    return "tiff";
+                case "application/x-w2d":
+                    return "dwf";
+            }
+
+            return extension;
+        }
+    }
+}


Property changes on: trunk/MgDev/UnitTest/WebTier/DotNet/TestCommon/FeatureService
___________________________________________________________________
Added: bugtraq:number
   + true

Added: trunk/MgDev/UnitTest/WebTier/DotNet/TestCommon/FeatureService/FeatureServiceOperationExecutor.cs
===================================================================
--- trunk/MgDev/UnitTest/WebTier/DotNet/TestCommon/FeatureService/FeatureServiceOperationExecutor.cs	                        (rev 0)
+++ trunk/MgDev/UnitTest/WebTier/DotNet/TestCommon/FeatureService/FeatureServiceOperationExecutor.cs	2013-07-02 15:49:52 UTC (rev 7655)
@@ -0,0 +1,25 @@
+using OSGeo.MapGuide.Test.Common;
+using SqliteDotNet;
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+
+namespace OSGeo.MapGuide.Test.Operations
+{
+    /// <summary>
+    /// The base class of all test executors using the MgFeatureService
+    /// </summary>
+    /// <typeparam name="T">The test executor subclass type</typeparam>
+    public abstract class FeatureServiceOperationExecutor<T> : PlatformApiTestExecutor
+    {
+        protected MgFeatureService _featureService;
+
+        protected FeatureServiceOperationExecutor(MgFeatureService featSvc, string unitTestVm)
+            : base(typeof(T).Name.ToUpper(), ApiTypes.Platform, unitTestVm)
+        {
+            _featureService = featSvc;
+        }
+    }
+}

Added: trunk/MgDev/UnitTest/WebTier/DotNet/TestCommon/FeatureService/Operations.cs
===================================================================
--- trunk/MgDev/UnitTest/WebTier/DotNet/TestCommon/FeatureService/Operations.cs	                        (rev 0)
+++ trunk/MgDev/UnitTest/WebTier/DotNet/TestCommon/FeatureService/Operations.cs	2013-07-02 15:49:52 UTC (rev 7655)
@@ -0,0 +1,535 @@
+using OSGeo.MapGuide.Test.Common;
+using SqliteDotNet;
+using System;
+using System.Collections.Generic;
+using System.Collections.Specialized;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+
+namespace OSGeo.MapGuide.Test.Operations
+{
+    public class GetFeatureProviders : FeatureServiceOperationExecutor<GetFeatureProviders>
+    {
+        public GetFeatureProviders(MgFeatureService featSvc, string unitTestVm)
+            : base(featSvc, unitTestVm)
+        {
+
+        }
+
+        public override TestResult Execute(int paramSetId)
+        {
+            try
+            {
+                MgByteReader reader = _featureService.GetFeatureProviders();
+                return TestResult.FromByteReader(null);
+            }
+            catch (MgException ex)
+            {
+                return TestResult.FromMgException(ex);
+            }
+            catch (Exception ex)
+            {
+                return TestResult.FromException(ex);
+            }
+        }
+    }
+
+    public class GetProviderCapabilities : FeatureServiceOperationExecutor<GetProviderCapabilities>
+    {
+        public GetProviderCapabilities(MgFeatureService featSvc, string unitTestVm)
+            : base(featSvc, unitTestVm)
+        {
+
+        }
+
+        public override TestResult Execute(int paramSetId)
+        {
+            try
+            {
+                NameValueCollection param = new NameValueCollection();
+                _unitTestVm.ReadParameterValue(paramSetId, "PROVIDER", param);
+
+                MgByteReader reader = _featureService.GetCapabilities(param["PROVIDER"] ?? "");
+                return TestResult.FromByteReader(reader);
+            }
+            catch (MgException ex)
+            {
+                return TestResult.FromMgException(ex);
+            }
+            catch (Exception ex)
+            {
+                return TestResult.FromException(ex);
+            }
+        }
+    }
+
+    public class GetConnectionPropertyValues : FeatureServiceOperationExecutor<GetConnectionPropertyValues>
+    {
+        public GetConnectionPropertyValues(MgFeatureService featSvc, string unitTestVm)
+            : base(featSvc, unitTestVm)
+        {
+
+        }
+
+        public override TestResult Execute(int paramSetId)
+        {
+            try
+            {
+                NameValueCollection param = new NameValueCollection();
+                _unitTestVm.ReadParameterValue(paramSetId, "PROVIDER", param);
+                _unitTestVm.ReadParameterValue(paramSetId, "PROPERTY", param);
+                _unitTestVm.ReadParameterValue(paramSetId, "CONNECTIONSTRING", param);
+
+                MgStringCollection result = _featureService.GetConnectionPropertyValues(param["PROVIDER"], param["PROPERTY"], param["CONNECTIONSTRING"]);
+                return new TestResult(CommonUtility.MgStringCollectionToString(result), "text/plain");
+            }
+            catch (MgException ex)
+            {
+                return TestResult.FromMgException(ex);
+            }
+            catch (Exception ex)
+            {
+                return TestResult.FromException(ex);
+            }
+        }
+    }
+
+    public class DescribeFeatureSchema : FeatureServiceOperationExecutor<DescribeFeatureSchema>
+    {
+        public DescribeFeatureSchema(MgFeatureService featSvc, string unitTestVm)
+            : base(featSvc, unitTestVm)
+        {
+
+        }
+
+        public override TestResult Execute(int paramSetId)
+        {
+            try
+            {
+                NameValueCollection param = new NameValueCollection();
+                _unitTestVm.ReadParameterValue(paramSetId, "RESOURCEID", param);
+                _unitTestVm.ReadParameterValue(paramSetId, "SCHEMA", param);
+
+                MgResourceIdentifier resId = null;
+                if (param["RESOURCEID"] != null)
+                {
+                    resId = new MgResourceIdentifier(param["RESOURCEID"]);
+                }
+
+                string result = _featureService.DescribeSchemaAsXml(resId, param["SCHEMA"]);
+
+                return new TestResult(result, "text/xml");
+            }
+            catch (MgException ex)
+            {
+                return TestResult.FromMgException(ex);
+            }
+            catch (Exception ex)
+            {
+                return TestResult.FromException(ex);
+            }
+        }
+    }
+
+    public class SelectFeatures : FeatureServiceOperationExecutor<SelectFeatures>
+    {
+        public SelectFeatures(MgFeatureService featSvc, string unitTestVm)
+            : base(featSvc, unitTestVm)
+        {
+
+        }
+
+        public override TestResult Execute(int paramSetId)
+        {
+            try
+            {
+                NameValueCollection param = new NameValueCollection();
+                _unitTestVm.ReadParameterValue(paramSetId, "RESOURCEID", param);
+                _unitTestVm.ReadParameterValue(paramSetId, "CLASSNAME", param);
+                _unitTestVm.ReadParameterValue(paramSetId, "PROPERTIES", param);
+                _unitTestVm.ReadParameterValue(paramSetId, "FILTER", param);
+
+                MgResourceIdentifier resId = null;
+                if (param["RESOURCEID"] != null)
+                {
+                    resId = new MgResourceIdentifier(param["RESOURCEID"]);
+                }
+
+                MgFeatureQueryOptions query = new MgFeatureQueryOptions();
+                //TODO: Set query options
+                if (param["FILTER"] != null)
+                {
+                    query.SetFilter(param["FILTER"]);
+                }
+
+                //PROPERTIES should be stored in the database as comma separated string without spaces
+                if (param["PROPERTIES"] != null)
+                {
+                    string [] props = param["PROPERTIES"].Split(',');
+                    foreach(var p in props)
+                    {
+                        query.AddFeatureProperty(p);
+                    }
+                }
+
+                MgFeatureReader reader = _featureService.SelectFeatures(resId, param["CLASSNAME"], query);
+                MgByteReader byteReader = reader.ToXml();
+                reader.Close();
+                return TestResult.FromByteReader(byteReader);
+            }
+            catch (MgException ex)
+            {
+                return TestResult.FromMgException(ex);
+            }
+            catch (Exception ex)
+            {
+                return TestResult.FromException(ex);
+            }
+        }
+    }
+
+    public class SelectAggregates : FeatureServiceOperationExecutor<SelectAggregates>
+    {
+        public SelectAggregates(MgFeatureService featSvc, string unitTestVm)
+            : base(featSvc, unitTestVm)
+        {
+
+        }
+
+        public override TestResult Execute(int paramSetId)
+        {
+            try
+            {
+                NameValueCollection param = new NameValueCollection();
+                _unitTestVm.ReadParameterValue(paramSetId, "RESOURCEID", param);
+                _unitTestVm.ReadParameterValue(paramSetId, "CLASSNAME", param);
+                //_unitTestVm.ReadParameterValue(paramSetId, "PROPERTIES", param);
+                //_unitTestVm.ReadParameterValue(paramSetId, "FILTER", param);
+
+                MgResourceIdentifier resId = null;
+                if (param["RESOURCEID"] != null)
+                {
+                    resId = new MgResourceIdentifier(param["RESOURCEID"]);
+                }
+
+                MgFeatureAggregateOptions query = new MgFeatureAggregateOptions();
+                //TODO: Set query options
+                /*
+                if (param["FILTER"] != null)
+                {
+                    query.SetFilter(param["FILTER"]);
+                }
+                */
+                //PROPERTIES should be stored in the database as comma separated string without spaces
+                /*
+                if (param["PROPERTIES"] != null)
+                {
+                    string[] props = param["PROPERTIES"].Split(',');
+                    foreach (var p in props)
+                    {
+                        query.AddFeatureProperty(p);
+                    }
+                }*/
+
+                MgDataReader reader = _featureService.SelectAggregate(resId, param["CLASSNAME"], query);
+                MgByteReader byteReader = reader.ToXml();
+                reader.Close();
+                return TestResult.FromByteReader(byteReader);
+            }
+            catch (MgException ex)
+            {
+                return TestResult.FromMgException(ex);
+            }
+            catch (Exception ex)
+            {
+                return TestResult.FromException(ex);
+            }
+        }
+    }
+
+    public class ExecuteSqlQuery : FeatureServiceOperationExecutor<ExecuteSqlQuery>
+    {
+        public ExecuteSqlQuery(MgFeatureService featSvc, string unitTestVm)
+            : base(featSvc, unitTestVm)
+        {
+
+        }
+
+        public override TestResult Execute(int paramSetId)
+        {
+            try
+            {
+                NameValueCollection param = new NameValueCollection();
+                _unitTestVm.ReadParameterValue(paramSetId, "RESOURCEID", param);
+                _unitTestVm.ReadParameterValue(paramSetId, "SQL", param);
+
+                MgResourceIdentifier resId = null;
+                if (param["RESOURCEID"] != null)
+                {
+                    resId = new MgResourceIdentifier(param["RESOURCEID"]);
+                }
+
+                MgSqlDataReader reader = _featureService.ExecuteSqlQuery(resId, param["SQL"]);
+                MgByteReader byteReader = reader.ToXml();
+                reader.Close();
+                return TestResult.FromByteReader(byteReader);
+            }
+            catch (MgException ex)
+            {
+                return TestResult.FromMgException(ex);
+            }
+            catch (Exception ex)
+            {
+                return TestResult.FromException(ex);
+            }
+        }
+    }
+
+    public class GetSpatialContexts : FeatureServiceOperationExecutor<GetSpatialContexts>
+    {
+        public GetSpatialContexts(MgFeatureService featSvc, string unitTestVm)
+            : base(featSvc, unitTestVm)
+        {
+
+        }
+
+        public override TestResult Execute(int paramSetId)
+        {
+            try
+            {
+                NameValueCollection param = new NameValueCollection();
+                _unitTestVm.ReadParameterValue(paramSetId, "RESOURCEID", param);
+                _unitTestVm.ReadParameterValue(paramSetId, "ACTIVEONLY", param);
+
+                MgResourceIdentifier resId = null;
+                if (param["RESOURCEID"] != null)
+                {
+                    resId = new MgResourceIdentifier(param["RESOURCEID"]);
+                }
+
+                MgSpatialContextReader reader = _featureService.GetSpatialContexts(resId, (param["ACTIVEONLY"] == "1"));
+                MgByteReader byteReader = reader.ToXml();
+                reader.Close();
+                return TestResult.FromByteReader(byteReader);
+            }
+            catch (MgException ex)
+            {
+                return TestResult.FromMgException(ex);
+            }
+            catch (Exception ex)
+            {
+                return TestResult.FromException(ex);
+            }
+        }
+    }
+
+    public class GetLongTransactions : FeatureServiceOperationExecutor<GetLongTransactions>
+    {
+        public GetLongTransactions(MgFeatureService featSvc, string unitTestVm)
+            : base(featSvc, unitTestVm)
+        {
+
+        }
+
+        public override TestResult Execute(int paramSetId)
+        {
+            try
+            {
+                NameValueCollection param = new NameValueCollection();
+                _unitTestVm.ReadParameterValue(paramSetId, "RESOURCEID", param);
+                _unitTestVm.ReadParameterValue(paramSetId, "ACTIVEONLY", param);
+
+                MgResourceIdentifier resId = null;
+                if (param["RESOURCEID"] != null)
+                {
+                    resId = new MgResourceIdentifier(param["RESOURCEID"]);
+                }
+
+                MgLongTransactionReader reader = _featureService.GetLongTransactions(resId, (param["ACTIVEONLY"] == "1"));
+                MgByteReader byteReader = reader.ToXml();
+                reader.Close();
+                return TestResult.FromByteReader(byteReader);
+            }
+            catch (MgException ex)
+            {
+                return TestResult.FromMgException(ex);
+            }
+            catch (Exception ex)
+            {
+                return TestResult.FromException(ex);
+            }
+        }
+    }
+
+    public interface ISessionCreator
+    {
+        string CreateSession();
+    }
+
+    public interface IApplySession
+    {
+        void SetSessionId(string sessionId);
+    }
+
+    public class SetLongTransaction : FeatureServiceOperationExecutor<SetLongTransaction>
+    {
+        private ISessionCreator _creator;
+        private IApplySession _apply;
+
+        public SetLongTransaction(MgFeatureService featSvc, string unitTestVm, ISessionCreator creator, IApplySession apply)
+            : base(featSvc, unitTestVm)
+        {
+            _creator = creator;
+            _apply = apply;
+        }
+
+        public override TestResult Execute(int paramSetId)
+        {
+            try
+            {
+                NameValueCollection param = new NameValueCollection();
+                _unitTestVm.ReadParameterValue(paramSetId, "RESOURCEID", param);
+                _unitTestVm.ReadParameterValue(paramSetId, "LONGTRANSACTIONNAME", param);
+                _unitTestVm.ReadParameterValue(paramSetId, "CREATESESSION", param);
+
+                MgResourceIdentifier resId = null;
+                if (param["RESOURCEID"] != null)
+                {
+                    resId = new MgResourceIdentifier(param["RESOURCEID"]);
+                }
+
+                if (param["CREATESESSION"] == "TRUE")
+                {
+                    string sessionId = _creator.CreateSession();
+                    _apply.SetSessionId(sessionId);
+                }
+
+                bool bRes = _featureService.SetLongTransaction(resId, param["LONGTRANSACTIONNAME"]);
+
+                return new TestResult(CommonUtility.BooleanToString(bRes), "text/plain");
+            }
+            catch (MgException ex)
+            {
+                return TestResult.FromMgException(ex);
+            }
+            catch (Exception ex)
+            {
+                return TestResult.FromException(ex);
+            }
+        }
+    }
+
+    public class TestConnection : FeatureServiceOperationExecutor<TestConnection>
+    {
+        public TestConnection(MgFeatureService featSvc, string unitTestVm)
+            : base(featSvc, unitTestVm)
+        {
+
+        }
+
+        public override TestResult Execute(int paramSetId)
+        {
+            try
+            {
+                NameValueCollection param = new NameValueCollection();
+                _unitTestVm.ReadParameterValue(paramSetId, "RESOURCEID", param);
+
+                bool bRes = false;
+                MgResourceIdentifier resId = null;
+                if (!string.IsNullOrEmpty(param["RESOURCEID"]))
+                {
+                    resId = new MgResourceIdentifier(param["RESOURCEID"]);
+                    bRes = _featureService.TestConnection(resId);
+                }
+                else
+                {
+                    _unitTestVm.ReadParameterValue(paramSetId, "PROVIDER", param);
+                    _unitTestVm.ReadParameterValue(paramSetId, "CONNECTIONSTRING", param);
+                    bRes = _featureService.TestConnection(param["PROVIDER"] ?? "", param["CONNECTIONSTRING"] ?? "");
+                }
+
+                return new TestResult(CommonUtility.BooleanToString(bRes), "text/plain");
+            }
+            catch (MgException ex)
+            {
+                return TestResult.FromMgException(ex);
+            }
+            catch (Exception ex)
+            {
+                return TestResult.FromException(ex);
+            }
+        }
+    }
+
+    public class GetSchemas : FeatureServiceOperationExecutor<GetSchemas>
+    {
+        public GetSchemas(MgFeatureService featSvc, string unitTestVm)
+            : base(featSvc, unitTestVm)
+        {
+
+        }
+
+        public override TestResult Execute(int paramSetId)
+        {
+            try
+            {
+                NameValueCollection param = new NameValueCollection();
+                _unitTestVm.ReadParameterValue(paramSetId, "RESOURCEID", param);
+                
+                MgResourceIdentifier resId = null;
+                if (param["RESOURCEID"] != null)
+                {
+                    resId = new MgResourceIdentifier(param["RESOURCEID"]);
+                }
+
+                MgStringCollection result = _featureService.GetSchemas(resId);
+                return new TestResult(CommonUtility.MgStringCollectionToString(result), "text/plain");
+            }
+            catch (MgException ex)
+            {
+                return TestResult.FromMgException(ex);
+            }
+            catch (Exception ex)
+            {
+                return TestResult.FromException(ex);
+            }
+        }
+    }
+
+    public class GetClasses : FeatureServiceOperationExecutor<GetClasses>
+    {
+        public GetClasses(MgFeatureService featSvc, string unitTestVm)
+            : base(featSvc, unitTestVm)
+        {
+
+        }
+
+        public override TestResult Execute(int paramSetId)
+        {
+            try
+            {
+                NameValueCollection param = new NameValueCollection();
+                _unitTestVm.ReadParameterValue(paramSetId, "RESOURCEID", param);
+                _unitTestVm.ReadParameterValue(paramSetId, "SCHEMANAME", param);
+
+                MgResourceIdentifier resId = null;
+                if (param["RESOURCEID"] != null)
+                {
+                    resId = new MgResourceIdentifier(param["RESOURCEID"]);
+                }
+
+                MgStringCollection result = _featureService.GetClasses(resId, param["SCHEMANAME"]);
+                return new TestResult(CommonUtility.MgStringCollectionToString(result), "text/plain");
+            }
+            catch (MgException ex)
+            {
+                return TestResult.FromMgException(ex);
+            }
+            catch (Exception ex)
+            {
+                return TestResult.FromException(ex);
+            }
+        }
+    }
+}

Added: trunk/MgDev/UnitTest/WebTier/DotNet/TestCommon/ITestExecutor.cs
===================================================================
--- trunk/MgDev/UnitTest/WebTier/DotNet/TestCommon/ITestExecutor.cs	                        (rev 0)
+++ trunk/MgDev/UnitTest/WebTier/DotNet/TestCommon/ITestExecutor.cs	2013-07-02 15:49:52 UTC (rev 7655)
@@ -0,0 +1,31 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+
+namespace OSGeo.MapGuide.Test.Common
+{
+    /// <summary>
+    /// Executes a particular MapGuide API
+    /// </summary>
+    public interface ITestExecutor : IDisposable
+    {
+        /// <summary>
+        /// The API flavour we're executing. See <see cref="OSGeo.MapGuide.Test.Common.ApiTypes"/>
+        /// </summary>
+        string Api { get; }
+
+        /// <summary>
+        /// The name of the operation
+        /// </summary>
+        string OperationName { get; }
+
+        /// <summary>
+        /// Executes the API with the particular parameter set
+        /// </summary>
+        /// <param name="paramSetId"></param>
+        /// <returns></returns>
+        TestResult Execute(int paramSetId);
+    }
+}

Added: trunk/MgDev/UnitTest/WebTier/DotNet/TestCommon/ITestExecutorCollection.cs
===================================================================
--- trunk/MgDev/UnitTest/WebTier/DotNet/TestCommon/ITestExecutorCollection.cs	                        (rev 0)
+++ trunk/MgDev/UnitTest/WebTier/DotNet/TestCommon/ITestExecutorCollection.cs	2013-07-02 15:49:52 UTC (rev 7655)
@@ -0,0 +1,139 @@
+using SqliteDotNet;
+using System;
+using System.Collections.Generic;
+using System.IO;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+
+namespace OSGeo.MapGuide.Test.Common
+{
+    /// <summary>
+    /// A collection of test executors
+    /// </summary>
+    public interface ITestExecutorCollection
+    {
+        /// <summary>
+        /// Initializes this collection of test executors
+        /// </summary>
+        /// <param name="testExecutionMode"></param>
+        /// <param name="dumpFile"></param>
+        void Initialize(string testExecutionMode, string dumpFile);
+
+        /// <summary>
+        /// Gets the dump file path
+        /// </summary>
+        string DumpFile { get; }
+
+        /// <summary>
+        /// Gets the test execution mode
+        /// </summary>
+        string TestExecutionMode { get; }
+
+        /// <summary>
+        /// Gets the test executor of the specified operation name
+        /// </summary>
+        /// <param name="opName"></param>
+        /// <returns></returns>
+        ITestExecutor GetTestExecutor(string opName);
+
+        /// <summary>
+        /// Executes the test suite as defined in the dump file
+        /// </summary>
+        /// <param name="testsRun"></param>
+        /// <param name="logger"></param>
+        /// <param name="isEnterprise"></param>
+        /// <returns></returns>
+        int Execute(ref int testsRun, ITestLogger logger, bool isEnterprise);
+
+        /// <summary>
+        /// Validates a test execution result
+        /// </summary>
+        /// <param name="db"></param>
+        /// <param name="testName"></param>
+        /// <param name="paramSetId"></param>
+        /// <param name="operation"></param>
+        /// <param name="actualResult"></param>
+        /// <param name="logger"></param>
+        /// <returns></returns>
+        int ValidateRequest(SqliteDb db, string testName, int paramSetId, string operation, TestResult actualResult, ITestLogger logger);
+
+        /// <summary>
+        /// Performs necessary cleanup
+        /// </summary>
+        void Cleanup();
+    }
+
+    public abstract class TestExecutorCollectionBase : ITestExecutorCollection
+    {
+        public string TestExecutionMode { get; protected set; }
+
+        public string DumpFile { get; protected set; }
+
+        public abstract string ApiType { get; }
+
+        public void Initialize(string testExecutionMode, string dumpFile)
+        {
+            this.TestExecutionMode = testExecutionMode;
+            this.DumpFile = dumpFile;
+        }
+
+        protected abstract void SetupExecutors(string dbPath);
+
+        public int Execute(ref int testsRun, ITestLogger logger, bool isEnterprise)
+        {
+            int exitStatus = 0;
+            try
+            {
+                string dbPath = CommonUtility.GetDbPath(this.DumpFile);
+                string dbName = CommonUtility.GetPath(dbPath);
+
+                if (File.Exists(dbName))
+                {
+                    var db = new SqliteDb();
+                    db.Open(dbName);
+
+                    var vm = new SqliteVm(db, true);
+
+                    int status = vm.Execute("Select TestName, TestType from TestCase where TestType=\"{0}\" order by ExecuteSequence", this.ApiType);
+
+                    //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
+                    SetupExecutors(dbName);
+
+                    while (status == Sqlite.Row)
+                    {
+                        string testName = vm.GetString("TestName");
+                        string testType = vm.GetString("TestType");
+
+                        Console.WriteLine("Executing {0} test: {1}", testType, testName);
+                        using (var run = new TestExecutionRun(dbPath, this))
+                        {
+                            exitStatus += run.RunTests(testName, logger, ref testsRun);
+                        }
+                        status = vm.NextRow();
+                    }
+                    vm.SqlFinalize();
+                    vm = null;
+                    db = null;
+                }
+                return exitStatus;
+            }
+            catch (UnitTestException ex)
+            {
+                throw;
+            }
+            catch (Exception ex)
+            {
+                Console.WriteLine(ex.Message);
+                return 1;
+            }
+        }
+
+        public abstract ITestExecutor GetTestExecutor(string opName);
+
+        public abstract int ValidateRequest(SqliteDb db, string testName, int paramSetId, string operation, TestResult actualResult, ITestLogger logger);
+        
+        public abstract void Cleanup();
+    }
+}

Added: trunk/MgDev/UnitTest/WebTier/DotNet/TestCommon/ITestLogger.cs
===================================================================
--- trunk/MgDev/UnitTest/WebTier/DotNet/TestCommon/ITestLogger.cs	                        (rev 0)
+++ trunk/MgDev/UnitTest/WebTier/DotNet/TestCommon/ITestLogger.cs	2013-07-02 15:49:52 UTC (rev 7655)
@@ -0,0 +1,71 @@
+using System;
+using System.Collections.Generic;
+using System.IO;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+
+namespace OSGeo.MapGuide.Test.Common
+{
+    /// <summary>
+    /// A simple logger interface
+    /// </summary>
+    public interface ITestLogger : IDisposable
+    {
+        void Write(string format, params object[] args);
+        void WriteLine(string format, params object[] args);
+    }
+
+    /// <summary>
+    /// A logger for command line output
+    /// </summary>
+    public class TestLoggerConsole : ITestLogger
+    {
+        public void Write(string format, params object[] args)
+        {
+            Console.Write(format, args);
+        }
+
+        public void WriteLine(string format, params object[] args)
+        {
+            Console.WriteLine(format, args);
+        }
+
+        public void Dispose()
+        {
+            
+        }
+    }
+
+    /// <summary>
+    /// A logger for file output
+    /// </summary>
+    public class TestLoggerFile : ITestLogger
+    {
+        private StreamWriter sw;
+
+        public TestLoggerFile(string file, bool append)
+        {
+            sw = new StreamWriter(file, append);
+        }
+
+        public void Write(string format, params object[] args)
+        {
+            sw.Write(format, args);
+        }
+
+        public void WriteLine(string format, params object[] args)
+        {
+            sw.WriteLine(format, args);
+        }
+
+        public void Dispose()
+        {
+            if (sw != null)
+            {
+                sw.Close();
+                sw = null;
+            }
+        }
+    }
+}


Property changes on: trunk/MgDev/UnitTest/WebTier/DotNet/TestCommon/MapLayer
___________________________________________________________________
Added: bugtraq:number
   + true

Added: trunk/MgDev/UnitTest/WebTier/DotNet/TestCommon/MapLayer/MapLayerOperationExecutor.cs
===================================================================
--- trunk/MgDev/UnitTest/WebTier/DotNet/TestCommon/MapLayer/MapLayerOperationExecutor.cs	                        (rev 0)
+++ trunk/MgDev/UnitTest/WebTier/DotNet/TestCommon/MapLayer/MapLayerOperationExecutor.cs	2013-07-02 15:49:52 UTC (rev 7655)
@@ -0,0 +1,62 @@
+using OSGeo.MapGuide.Test.Common;
+using SqliteDotNet;
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+
+namespace OSGeo.MapGuide.Test.Operations
+{
+    public interface IMapCreator
+    {
+        MgMapBase CreateMap(MgResourceIdentifier resId);
+        MgLayerBase CreateLayer(MgResourceIdentifier resId);
+    }
+
+    /// <summary>
+    /// The base class of all test executors operating with the runtime map
+    /// </summary>
+    /// <typeparam name="T">The test executor subclass type</typeparam>
+    public abstract class MapLayerOperationExecutor<T> : PlatformApiTestExecutor
+    {
+        protected MgMapBase _map;
+        protected MgResourceService _resourceService;
+        protected IMapCreator _creator;
+
+        protected MapLayerOperationExecutor(MgResourceService resSvc, string unitTestVm, IMapCreator creator)
+            : base(typeof(T).Name.ToUpper(), ApiTypes.Platform, unitTestVm)
+        {
+            _resourceService = resSvc;
+            _creator = creator;
+        }
+
+        protected void CreateMapFromResource(int paramSetId)
+        {
+            if (_map != null)
+                return;
+
+            _unitTestVm.Execute("Select ParamValue from Params WHERE ParamSet={0} AND ParamName=\"MAPDEFINITION\"", paramSetId);
+            string mapName = _unitTestVm.GetString("ParamValue");
+            if (string.IsNullOrEmpty(mapName))
+            {
+                mapName = "Library://maplayertest/World.MapDefinition";
+            }
+
+            MgResourceIdentifier mdfId = new MgResourceIdentifier(mapName);
+            _map = _creator.CreateMap(mdfId);
+        }
+
+        protected MgLayerBase FindLayer(string name)
+        {
+            if (_map != null)
+            {
+                var layers = _map.GetLayers();
+                var lidx = layers.IndexOf(name);
+                if (lidx >= 0)
+                    return layers.GetItem(lidx);
+            }
+            return null;
+        }
+    }
+}

Added: trunk/MgDev/UnitTest/WebTier/DotNet/TestCommon/MapLayer/Operations.cs
===================================================================
--- trunk/MgDev/UnitTest/WebTier/DotNet/TestCommon/MapLayer/Operations.cs	                        (rev 0)
+++ trunk/MgDev/UnitTest/WebTier/DotNet/TestCommon/MapLayer/Operations.cs	2013-07-02 15:49:52 UTC (rev 7655)
@@ -0,0 +1,587 @@
+using OSGeo.MapGuide.Test.Common;
+using SqliteDotNet;
+using System;
+using System.Collections.Generic;
+using System.Globalization;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+
+namespace OSGeo.MapGuide.Test.Operations
+{
+    public class GetMapExtent : MapLayerOperationExecutor<GetMapExtent>
+    {
+        public GetMapExtent(MgResourceService resSvc, string vm, IMapCreator creator)
+            : base(resSvc, vm, creator)
+        {
+        }
+
+        public override TestResult Execute(int paramSetId)
+        {
+            try
+            {
+                this.CreateMapFromResource(paramSetId);
+                var extent = _map.GetMapExtent();
+                return new TestResult(CommonUtility.MgEnvelopeToString(extent), "text/plain");
+            }
+            catch (MgException ex)
+            {
+                return TestResult.FromMgException(ex);
+            }
+        }
+    }
+
+    public class GetCoordinateSystem : MapLayerOperationExecutor<GetCoordinateSystem>
+    {
+        public GetCoordinateSystem(MgResourceService resSvc, string vm, IMapCreator creator)
+            : base(resSvc, vm, creator)
+        {
+        }
+
+        public override TestResult Execute(int paramSetId)
+        {
+            try
+            {
+                this.CreateMapFromResource(paramSetId);
+                return new TestResult(_map.GetMapSRS(), "text/plain");
+            }
+            catch (MgException ex)
+            {
+                return TestResult.FromMgException(ex);
+            }
+        }
+    }
+
+    public class GetMapName : MapLayerOperationExecutor<GetMapName>
+    {
+        public GetMapName(MgResourceService resSvc, string vm, IMapCreator creator)
+            : base(resSvc, vm, creator)
+        {
+        }
+
+        public override TestResult Execute(int paramSetId)
+        {
+            try
+            {
+                this.CreateMapFromResource(paramSetId);
+                return new TestResult(_map.GetName(), "text/plain");
+            }
+            catch (MgException ex)
+            {
+                return TestResult.FromMgException(ex);
+            }
+        }
+    }
+
+    public class GetLayers : MapLayerOperationExecutor<GetLayers>
+    {
+        public GetLayers(MgResourceService resSvc, string vm, IMapCreator creator)
+            : base(resSvc, vm, creator)
+        {
+        }
+
+        public override TestResult Execute(int paramSetId)
+        {
+            try
+            {
+                this.CreateMapFromResource(paramSetId);
+                var layers = _map.GetLayers();
+                var names = new List<string>();
+                for (int i = 0; i < layers.GetCount(); i++)
+                {
+                    var layer = layers.GetItem(i);
+                    names.Add(layer.GetName());
+                }
+
+                return new TestResult(string.Join("/", names.ToArray()), "text/plain");
+            }
+            catch (MgException ex)
+            {
+                return TestResult.FromMgException(ex);
+            }
+        }
+    }
+
+    public class GetGroups : MapLayerOperationExecutor<GetGroups>
+    {
+        public GetGroups(MgResourceService resSvc, string vm, IMapCreator creator)
+            : base(resSvc, vm, creator)
+        {
+        }
+
+        public override TestResult Execute(int paramSetId)
+        {
+            try
+            {
+                this.CreateMapFromResource(paramSetId);
+                var groups = _map.GetLayerGroups();
+                var names = new List<string>();
+                for (int i = 0; i < groups.GetCount(); i++)
+                {
+                    var group = groups.GetItem(i);
+                    names.Add(group.GetName());
+                }
+
+                return new TestResult(string.Join("/", names.ToArray()), "text/plain");
+            }
+            catch (MgException ex)
+            {
+                return TestResult.FromMgException(ex);
+            }
+        }
+    }
+
+    public class GetLayerVisibility : MapLayerOperationExecutor<GetLayerVisibility>
+    {
+        public GetLayerVisibility(MgResourceService resSvc, string vm, IMapCreator creator)
+            : base(resSvc, vm, creator)
+        {
+        }
+
+        public override TestResult Execute(int paramSetId)
+        {
+            try
+            {
+                this.CreateMapFromResource(paramSetId);
+
+                _unitTestVm.Execute("Select ParamValue from Params WHERE ParamSet={0} AND ParamName=\"LAYERNAME\"", paramSetId);
+                string layerName = _unitTestVm.GetString("ParamValue");
+
+                var layer = this.FindLayer(layerName);
+                if (layer == null)
+                    return new TestResult("***Unknown Layer***", "text/plain");
+                return new TestResult(CommonUtility.BooleanToString(layer.GetVisible()), "text/plain");
+            }
+            catch (MgException ex)
+            {
+                return TestResult.FromMgException(ex);
+            }
+        }
+    }
+
+    public class GetDisplayInLegend : MapLayerOperationExecutor<GetDisplayInLegend>
+    {
+        public GetDisplayInLegend(MgResourceService resSvc, string vm, IMapCreator creator)
+            : base(resSvc, vm, creator)
+        {
+        }
+
+        public override TestResult Execute(int paramSetId)
+        {
+            try
+            {
+                this.CreateMapFromResource(paramSetId);
+
+                _unitTestVm.Execute("Select ParamValue from Params WHERE ParamSet={0} AND ParamName=\"LAYERNAME\"", paramSetId);
+                string layerName = _unitTestVm.GetString("ParamValue");
+
+                var layer = this.FindLayer(layerName);
+                if (layer == null)
+                    return new TestResult("***Unknown Layer***", "text/plain");
+                return new TestResult(CommonUtility.BooleanToString(layer.GetDisplayInLegend()), "text/plain");
+            }
+            catch (MgException ex)
+            {
+                return TestResult.FromMgException(ex);
+            }
+        }
+    }
+
+    public class GetLegendLabel : MapLayerOperationExecutor<GetLegendLabel>
+    {
+        public GetLegendLabel(MgResourceService resSvc, string vm, IMapCreator creator)
+            : base(resSvc, vm, creator)
+        {
+        }
+
+        public override TestResult Execute(int paramSetId)
+        {
+            try
+            {
+                this.CreateMapFromResource(paramSetId);
+
+                _unitTestVm.Execute("Select ParamValue from Params WHERE ParamSet={0} AND ParamName=\"LAYERNAME\"", paramSetId);
+                string layerName = _unitTestVm.GetString("ParamValue");
+
+                var layer = this.FindLayer(layerName);
+                if (layer == null)
+                    return new TestResult("***Unknown Layer***", "text/plain");
+                return new TestResult(layer.GetLegendLabel(), "text/plain");
+            }
+            catch (MgException ex)
+            {
+                return TestResult.FromMgException(ex);
+            }
+        }
+    }
+
+    public class GetLayerDefinition : MapLayerOperationExecutor<GetLayerDefinition>
+    {
+        public GetLayerDefinition(MgResourceService resSvc, string vm, IMapCreator creator)
+            : base(resSvc, vm, creator)
+        {
+        }
+
+        public override TestResult Execute(int paramSetId)
+        {
+            try
+            {
+                this.CreateMapFromResource(paramSetId);
+
+                _unitTestVm.Execute("Select ParamValue from Params WHERE ParamSet={0} AND ParamName=\"LAYERNAME\"", paramSetId);
+                string layerName = _unitTestVm.GetString("ParamValue");
+
+                var layer = this.FindLayer(layerName);
+                if (layer == null)
+                    return new TestResult("***Unknown Layer***", "text/plain");
+                var ldfId = layer.GetLayerDefinition();
+                return new TestResult(ldfId.ToString(), "text/plain");
+            }
+            catch (MgException ex)
+            {
+                return TestResult.FromMgException(ex);
+            }
+        }
+    }
+
+    public class IsLayerVisible : MapLayerOperationExecutor<IsLayerVisible>
+    {
+        public IsLayerVisible(MgResourceService resSvc, string vm, IMapCreator creator)
+            : base(resSvc, vm, creator)
+        {
+        }
+
+        public override TestResult Execute(int paramSetId)
+        {
+            try
+            {
+                this.CreateMapFromResource(paramSetId);
+
+                _unitTestVm.Execute("Select ParamValue from Params WHERE ParamSet={0} AND ParamName=\"LAYERNAME\"", paramSetId);
+                string layerName = _unitTestVm.GetString("ParamValue");
+
+                var layer = this.FindLayer(layerName);
+                if (layer == null)
+                    return new TestResult("***Unknown Layer***", "text/plain");
+                return new TestResult(CommonUtility.BooleanToString(layer.IsVisible()), "text/plain");
+            }
+            catch (MgException ex)
+            {
+                return TestResult.FromMgException(ex);
+            }
+        }
+    }
+
+    public class AddLayerGroup : MapLayerOperationExecutor<AddLayerGroup>
+    {
+        public AddLayerGroup(MgResourceService resSvc, string vm, IMapCreator creator)
+            : base(resSvc, vm, creator)
+        {
+        }
+
+        public override TestResult Execute(int paramSetId)
+        {
+            try
+            {
+                this.CreateMapFromResource(paramSetId);
+
+                _unitTestVm.Execute("Select ParamValue from Params WHERE ParamSet={0} AND ParamName=\"GROUPNAME\"", paramSetId);
+                string groupName = _unitTestVm.GetString("ParamValue");
+
+                _unitTestVm.Execute("Select ParamValue from Params WHERE ParamSet={0} AND ParamName=\"PARENTGROUPNAME\"", paramSetId);
+                string parentGroupName = _unitTestVm.GetString("ParamValue");
+
+                var groups = _map.GetLayerGroups();
+                var group = new MgLayerGroup(groupName);
+                if (!string.IsNullOrEmpty(parentGroupName))
+                {
+                    var parentGroup = groups.GetItem(parentGroupName);
+                    group.SetGroup(parentGroup);
+                }
+                groups.Add(group);
+
+                return new TestResult(groups.GetCount().ToString(), "text/plain");
+            }
+            catch (MgException ex)
+            {
+                return TestResult.FromMgException(ex);
+            }
+        }
+    }
+
+    public class AddLayer : MapLayerOperationExecutor<AddLayer>
+    {
+        public AddLayer(MgResourceService resSvc, string vm, IMapCreator creator)
+            : base(resSvc, vm, creator)
+        {
+        }
+
+        public override TestResult Execute(int paramSetId)
+        {
+            try
+            {
+                this.CreateMapFromResource(paramSetId);
+
+                _unitTestVm.Execute("Select ParamValue from Params WHERE ParamSet={0} AND ParamName=\"LAYERDEFINITION\"", paramSetId);
+                string layerDefinition = _unitTestVm.GetString("ParamValue");
+
+                _unitTestVm.Execute("Select ParamValue from Params WHERE ParamSet={0} AND ParamName=\"GROUPNAME\"", paramSetId);
+                string groupName = _unitTestVm.GetString("ParamValue");
+
+                var ldfId = new MgResourceIdentifier(layerDefinition);
+                var layer = _creator.CreateLayer(ldfId);
+
+                if (!string.IsNullOrEmpty(groupName))
+                {
+                    var groups = _map.GetLayerGroups();
+                    var gidx = groups.IndexOf(groupName);
+                    if (gidx >= 0)
+                        layer.SetGroup(groups.GetItem(gidx));
+                }
+
+                var layers = _map.GetLayers();
+                layers.Add(layer);
+
+                return new TestResult(layers.GetCount().ToString(), "text/plain");
+            }
+            catch (MgException ex)
+            {
+                return TestResult.FromMgException(ex);
+            }
+        }
+    }
+
+    public class HideGroup : MapLayerOperationExecutor<HideGroup>
+    {
+        public HideGroup(MgResourceService resSvc, string vm, IMapCreator creator)
+            : base(resSvc, vm, creator)
+        {
+        }
+
+        public override TestResult Execute(int paramSetId)
+        {
+            try
+            {
+                this.CreateMapFromResource(paramSetId);
+
+                _unitTestVm.Execute("Select ParamValue from Params WHERE ParamSet={0} AND ParamName=\"GROUPNAME\"", paramSetId);
+                string groupName = _unitTestVm.GetString("ParamValue");
+
+                var groups = _map.GetLayerGroups();
+                var group = groups.GetItem(groupName);
+
+                group.SetVisible(false);
+                return new TestResult(CommonUtility.BooleanToString(group.GetVisible()), "text/plain");
+            }
+            catch (MgException ex)
+            {
+                return TestResult.FromMgException(ex);
+            }
+        }
+    }
+
+    public class ShowGroup : MapLayerOperationExecutor<ShowGroup>
+    {
+        public ShowGroup(MgResourceService resSvc, string vm, IMapCreator creator)
+            : base(resSvc, vm, creator)
+        {
+        }
+
+        public override TestResult Execute(int paramSetId)
+        {
+            try
+            {
+                this.CreateMapFromResource(paramSetId);
+
+                _unitTestVm.Execute("Select ParamValue from Params WHERE ParamSet={0} AND ParamName=\"GROUPNAME\"", paramSetId);
+                string groupName = _unitTestVm.GetString("ParamValue");
+
+                var groups = _map.GetLayerGroups();
+                var group = groups.GetItem(groupName);
+
+                group.SetVisible(true);
+                return new TestResult(CommonUtility.BooleanToString(group.GetVisible()), "text/plain");
+            }
+            catch (MgException ex)
+            {
+                return TestResult.FromMgException(ex);
+            }
+        }
+    }
+
+    public class GetViewCenter : MapLayerOperationExecutor<GetViewCenter>
+    {
+        public GetViewCenter(MgResourceService resSvc, string vm, IMapCreator creator)
+            : base(resSvc, vm, creator)
+        {
+        }
+
+        public override TestResult Execute(int paramSetId)
+        {
+            try
+            {
+                this.CreateMapFromResource(paramSetId);
+                return new TestResult(CommonUtility.MgPointToString(_map.GetViewCenter()), "text/plain");
+            }
+            catch (MgException ex)
+            {
+                return TestResult.FromMgException(ex);
+            }
+        }
+    }
+
+    public class GetViewScale : MapLayerOperationExecutor<GetViewScale>
+    {
+        public GetViewScale(MgResourceService resSvc, string vm, IMapCreator creator)
+            : base(resSvc, vm, creator)
+        {
+        }
+
+        public override TestResult Execute(int paramSetId)
+        {
+            try
+            {
+                this.CreateMapFromResource(paramSetId);
+                return new TestResult(_map.GetViewScale().ToString(CultureInfo.InvariantCulture), "text/plain");
+            }
+            catch (MgException ex)
+            {
+                return TestResult.FromMgException(ex);
+            }
+        }
+    }
+
+    public class GetDataExtent : MapLayerOperationExecutor<GetDataExtent>
+    {
+        public GetDataExtent(MgResourceService resSvc, string vm, IMapCreator creator)
+            : base(resSvc, vm, creator)
+        {
+        }
+
+        public override TestResult Execute(int paramSetId)
+        {
+            try
+            {
+                this.CreateMapFromResource(paramSetId);
+
+                var extent = _map.GetDataExtent();
+                return new TestResult(CommonUtility.MgEnvelopeToString(extent), "text/plain");
+            }
+            catch (MgException ex)
+            {
+                return TestResult.FromMgException(ex);
+            }
+        }
+    }
+
+    public class RemoveGroup : MapLayerOperationExecutor<RemoveGroup>
+    {
+        public RemoveGroup(MgResourceService resSvc, string vm, IMapCreator creator)
+            : base(resSvc, vm, creator)
+        {
+        }
+
+        public override TestResult Execute(int paramSetId)
+        {
+            try
+            {
+                this.CreateMapFromResource(paramSetId);
+
+                _unitTestVm.Execute("Select ParamValue from Params WHERE ParamSet={0} AND ParamName=\"GROUPNAME\"", paramSetId);
+                string groupName = _unitTestVm.GetString("ParamValue");
+
+                var groups = _map.GetLayerGroups();
+                var group = groups.GetItem(groupName);
+
+                groups.Remove(group);
+
+                return new TestResult("", "text/plain");
+            }
+            catch (MgException ex)
+            {
+                return TestResult.FromMgException(ex);
+            }
+        }
+    }
+
+    public class LayerExists : MapLayerOperationExecutor<LayerExists>
+    {
+        public LayerExists(MgResourceService resSvc, string vm, IMapCreator creator)
+            : base(resSvc, vm, creator)
+        {
+        }
+
+        public override TestResult Execute(int paramSetId)
+        {
+            try
+            {
+                this.CreateMapFromResource(paramSetId);
+
+                _unitTestVm.Execute("Select ParamValue from Params WHERE ParamSet={0} AND ParamName=\"LAYERNAME\"", paramSetId);
+                string layerName = _unitTestVm.GetString("ParamValue");
+
+                var layer = this.FindLayer(layerName);
+
+                return new TestResult(CommonUtility.BooleanToString(layer != null), "text/plain");
+            }
+            catch (MgException ex)
+            {
+                return TestResult.FromMgException(ex);
+            }
+        }
+    }
+
+    public class GetLayerFeatureSource : MapLayerOperationExecutor<GetLayerFeatureSource>
+    {
+        public GetLayerFeatureSource(MgResourceService resSvc, string vm, IMapCreator creator)
+            : base(resSvc, vm, creator)
+        {
+        }
+
+        public override TestResult Execute(int paramSetId)
+        {
+            try
+            {
+                this.CreateMapFromResource(paramSetId);
+
+                _unitTestVm.Execute("Select ParamValue from Params WHERE ParamSet={0} AND ParamName=\"LAYERNAME\"", paramSetId);
+                string layerName = _unitTestVm.GetString("ParamValue");
+
+                var layer = this.FindLayer(layerName);
+                if (layer == null)
+                    return new TestResult("***Unknown Layer***", "text/plain");
+                return new TestResult(layer.GetFeatureSourceId(), "text/plain");
+            }
+            catch (MgException ex)
+            {
+                return TestResult.FromMgException(ex);
+            }
+        }
+    }
+
+    public class GetLayerFeatureClass : MapLayerOperationExecutor<GetLayerFeatureClass>
+    {
+        public GetLayerFeatureClass(MgResourceService resSvc, string vm, IMapCreator creator)
+            : base(resSvc, vm, creator)
+        {
+        }
+
+        public override TestResult Execute(int paramSetId)
+        {
+            try
+            {
+                this.CreateMapFromResource(paramSetId);
+
+                _unitTestVm.Execute("Select ParamValue from Params WHERE ParamSet={0} AND ParamName=\"LAYERNAME\"", paramSetId);
+                string layerName = _unitTestVm.GetString("ParamValue");
+
+                var layer = this.FindLayer(layerName);
+                return new TestResult(layer.GetFeatureClassName(), "text/plain");
+            }
+            catch (MgException ex)
+            {
+                return TestResult.FromMgException(ex);
+            }
+        }
+    }
+}

Added: trunk/MgDev/UnitTest/WebTier/DotNet/TestCommon/PlatformApiTestExecutor.cs
===================================================================
--- trunk/MgDev/UnitTest/WebTier/DotNet/TestCommon/PlatformApiTestExecutor.cs	                        (rev 0)
+++ trunk/MgDev/UnitTest/WebTier/DotNet/TestCommon/PlatformApiTestExecutor.cs	2013-07-02 15:49:52 UTC (rev 7655)
@@ -0,0 +1,57 @@
+using SqliteDotNet;
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+
+namespace OSGeo.MapGuide.Test.Common
+{
+    /// <summary>
+    /// The base class of all MapGuide API test executors
+    /// </summary>
+    public abstract class PlatformApiTestExecutor : TestExecutorBase
+    {
+        protected string _unitTestVmPath;
+        private SqliteDb _unitTestDb;
+        protected SqliteVm _unitTestVm;
+
+        protected PlatformApiTestExecutor(string opName, string apiType, string unitTestVm)
+        {
+            _opName = opName;
+            _apiType = apiType;
+            _unitTestVmPath = unitTestVm;
+
+            _unitTestDb = new SqliteDb();
+            _unitTestDb.Open(_unitTestVmPath);
+
+            _unitTestVm = new SqliteVm(_unitTestDb, true);
+        }
+
+        public override void Dispose()
+        {
+            _unitTestVm.SqlFinalize();
+            _unitTestVm = null;
+            try
+            {
+                _unitTestDb.Close();
+            }
+            catch { }
+            _unitTestDb = null;
+        }
+
+        private string _apiType;
+
+        public override string Api
+        {
+            get { return _apiType; }
+        }
+
+        private string _opName;
+
+        public override string OperationName
+        {
+            get { return _opName; }
+        }
+    }
+}


Property changes on: trunk/MgDev/UnitTest/WebTier/DotNet/TestCommon/Properties
___________________________________________________________________
Added: bugtraq:number
   + true

Added: trunk/MgDev/UnitTest/WebTier/DotNet/TestCommon/Properties/AssemblyInfo.cs
===================================================================
--- trunk/MgDev/UnitTest/WebTier/DotNet/TestCommon/Properties/AssemblyInfo.cs	                        (rev 0)
+++ trunk/MgDev/UnitTest/WebTier/DotNet/TestCommon/Properties/AssemblyInfo.cs	2013-07-02 15:49:52 UTC (rev 7655)
@@ -0,0 +1,36 @@
+using System.Reflection;
+using System.Runtime.CompilerServices;
+using System.Runtime.InteropServices;
+
+// General Information about an assembly is controlled through the following 
+// set of attributes. Change these attribute values to modify the information
+// associated with an assembly.
+[assembly: AssemblyTitle("TestCommon")]
+[assembly: AssemblyDescription("")]
+[assembly: AssemblyConfiguration("")]
+[assembly: AssemblyCompany("")]
+[assembly: AssemblyProduct("TestCommon")]
+[assembly: AssemblyCopyright("Copyright ©  2013")]
+[assembly: AssemblyTrademark("")]
+[assembly: AssemblyCulture("")]
+
+// Setting ComVisible to false makes the types in this assembly not visible 
+// to COM components.  If you need to access a type in this assembly from 
+// COM, set the ComVisible attribute to true on that type.
+[assembly: ComVisible(false)]
+
+// The following GUID is for the ID of the typelib if this project is exposed to COM
+[assembly: Guid("f2cd2fd2-ec02-4886-bfe2-ba2755b47726")]
+
+// Version information for an assembly consists of the following four values:
+//
+//      Major Version
+//      Minor Version 
+//      Build Number
+//      Revision
+//
+// You can specify all the values or you can default the Build and Revision Numbers 
+// by using the '*' as shown below:
+// [assembly: AssemblyVersion("1.0.*")]
+[assembly: AssemblyVersion("1.0.0.0")]
+[assembly: AssemblyFileVersion("1.0.0.0")]


Property changes on: trunk/MgDev/UnitTest/WebTier/DotNet/TestCommon/ResourceService
___________________________________________________________________
Added: bugtraq:number
   + true

Added: trunk/MgDev/UnitTest/WebTier/DotNet/TestCommon/ResourceService/Operations.cs
===================================================================
--- trunk/MgDev/UnitTest/WebTier/DotNet/TestCommon/ResourceService/Operations.cs	                        (rev 0)
+++ trunk/MgDev/UnitTest/WebTier/DotNet/TestCommon/ResourceService/Operations.cs	2013-07-02 15:49:52 UTC (rev 7655)
@@ -0,0 +1,735 @@
+using OSGeo.MapGuide.Test.Common;
+using SqliteDotNet;
+using System;
+using System.Collections.Generic;
+using System.Collections.Specialized;
+using System.IO;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+
+namespace OSGeo.MapGuide.Test.Operations
+{
+    public class EnumerateResources : ResourceServiceOperationExecutor<EnumerateResources>
+    {
+        public EnumerateResources(MgResourceService resSvc, string unitTestVm)
+            : base(resSvc, unitTestVm)
+        {
+
+        }
+
+        public override TestResult Execute(int paramSetId)
+        {
+            try
+            {
+                var param = new NameValueCollection();
+                
+                _unitTestVm.ReadParameterValue(paramSetId, "RESOURCEID", param);
+                _unitTestVm.ReadParameterValue(paramSetId, "TYPE", param);
+                _unitTestVm.ReadParameterValue(paramSetId, "DEPTH", param);
+
+                MgResourceIdentifier resId = null;
+                if (param["RESOURCEID"] != null)
+                {
+                    resId = new MgResourceIdentifier(param["RESOURCEID"]);
+                }
+                MgByteReader byteReader = _resourceService.EnumerateResources(resId, Convert.ToInt32(param["DEPTH"]), param["TYPE"] ?? "");
+
+                return TestResult.FromByteReader(byteReader);
+            }
+            catch (MgException ex)
+            {
+                return TestResult.FromMgException(ex);
+            }
+            catch (Exception ex)
+            {
+                return TestResult.FromException(ex);
+            }
+        }
+    }
+
+    public class SetResource : ResourceServiceOperationExecutor<SetResource>
+    {
+        public SetResource(MgResourceService resSvc, string unitTestVm)
+            : base(resSvc, unitTestVm)
+        {
+
+        }
+
+        public override TestResult Execute(int paramSetId)
+        {
+            try
+            {
+                var param = new NameValueCollection();
+                _unitTestVm.ReadParameterValue(paramSetId, "RESOURCEID", param);
+                _unitTestVm.ReadParameterValue(paramSetId, "CONTENT", param, true);
+                _unitTestVm.ReadParameterValue(paramSetId, "HEADER", param, true);
+
+                MgResourceIdentifier resId = null;
+                if (param["RESOURCEID"] != null)
+                {
+                    resId = new MgResourceIdentifier(param["RESOURCEID"]);
+                }
+
+                MgByteReader content = CommonUtility.GetByteReaderFromPath(param["CONTENT"]);
+                MgByteReader header = CommonUtility.GetByteReaderFromPath(param["HEADER"]);
+
+                _resourceService.SetResource(resId, content, header);
+
+                return TestResult.FromByteReader(null);
+            }
+            catch (MgException ex)
+            {
+                return TestResult.FromMgException(ex);
+            }
+            catch (Exception ex)
+            {
+                return TestResult.FromException(ex);
+            }
+        }
+    }
+
+    public class DeleteResource : ResourceServiceOperationExecutor<DeleteResource>
+    {
+        public DeleteResource(MgResourceService resSvc, string unitTestVm)
+            : base(resSvc, unitTestVm)
+        {
+
+        }
+
+        public override TestResult Execute(int paramSetId)
+        {
+            try
+            {
+                var param = new NameValueCollection();
+                _unitTestVm.ReadParameterValue(paramSetId, "RESOURCEID", param);
+
+                MgResourceIdentifier resId = null;
+                if (param["RESOURCEID"] != null)
+                {
+                    resId = new MgResourceIdentifier(param["RESOURCEID"]);
+                }
+
+                _resourceService.DeleteResource(resId);
+
+                return TestResult.FromByteReader(null);
+            }
+            catch (MgException ex)
+            {
+                return TestResult.FromMgException(ex);
+            }
+            catch (Exception ex)
+            {
+                return TestResult.FromException(ex);
+            }
+        }
+    }
+
+    public class GetResourceContent : ResourceServiceOperationExecutor<GetResourceContent>
+    {
+        public GetResourceContent(MgResourceService resSvc, string unitTestVm)
+            : base(resSvc, unitTestVm)
+        {
+
+        }
+
+        public override TestResult Execute(int paramSetId)
+        {
+            try
+            {
+                var param = new NameValueCollection();
+                _unitTestVm.ReadParameterValue(paramSetId, "RESOURCEID", param);
+                _unitTestVm.ReadParameterValue(paramSetId, "PREPROCESS", param);
+
+                MgResourceIdentifier resId = null;
+                if (param["RESOURCEID"] != null)
+                {
+                    resId = new MgResourceIdentifier(param["RESOURCEID"]);
+                }
+
+                MgByteReader reader = _resourceService.GetResourceContent(resId);
+
+                return TestResult.FromByteReader(reader);
+            }
+            catch (MgException ex)
+            {
+                return TestResult.FromMgException(ex);
+            }
+            catch (Exception ex)
+            {
+                return TestResult.FromException(ex);
+            }
+        }
+    }
+
+    public class GetResourceHeader : ResourceServiceOperationExecutor<GetResourceHeader>
+    {
+        public GetResourceHeader(MgResourceService resSvc, string unitTestVm)
+            : base(resSvc, unitTestVm)
+        {
+
+        }
+
+        public override TestResult Execute(int paramSetId)
+        {
+            try
+            {
+                var param = new NameValueCollection();
+                _unitTestVm.ReadParameterValue(paramSetId, "RESOURCEID", param);
+
+                MgResourceIdentifier resId = null;
+                if (param["RESOURCEID"] != null)
+                {
+                    resId = new MgResourceIdentifier(param["RESOURCEID"]);
+                }
+
+                MgByteReader reader = _resourceService.GetResourceHeader(resId);
+
+                return TestResult.FromByteReader(reader);
+            }
+            catch (MgException ex)
+            {
+                return TestResult.FromMgException(ex);
+            }
+            catch (Exception ex)
+            {
+                return TestResult.FromException(ex);
+            }
+        }
+    }
+
+    public class EnumerateResourceData : ResourceServiceOperationExecutor<EnumerateResourceData>
+    {
+        public EnumerateResourceData(MgResourceService resSvc, string unitTestVm)
+            : base(resSvc, unitTestVm)
+        {
+
+        }
+
+        public override TestResult Execute(int paramSetId)
+        {
+            try
+            {
+                var param = new NameValueCollection();
+                _unitTestVm.ReadParameterValue(paramSetId, "RESOURCEID", param);
+
+                MgResourceIdentifier resId = null;
+                if (param["RESOURCEID"] != null)
+                {
+                    resId = new MgResourceIdentifier(param["RESOURCEID"]);
+                }
+
+                MgByteReader reader = _resourceService.EnumerateResourceData(resId);
+
+                return TestResult.FromByteReader(reader);
+            }
+            catch (MgException ex)
+            {
+                return TestResult.FromMgException(ex);
+            }
+            catch (Exception ex)
+            {
+                return TestResult.FromException(ex);
+            }
+        }
+    }
+
+    public class GetResourceData : ResourceServiceOperationExecutor<GetResourceData>
+    {
+        public GetResourceData(MgResourceService resSvc, string unitTestVm)
+            : base(resSvc, unitTestVm)
+        {
+
+        }
+
+        public override TestResult Execute(int paramSetId)
+        {
+            try
+            {
+                var param = new NameValueCollection();
+                _unitTestVm.ReadParameterValue(paramSetId, "RESOURCEID", param);
+                _unitTestVm.ReadParameterValue(paramSetId, "DATANAME", param);
+
+                MgResourceIdentifier resId = null;
+                if (param["RESOURCEID"] != null)
+                {
+                    resId = new MgResourceIdentifier(param["RESOURCEID"]);
+                }
+
+                MgByteReader reader = _resourceService.GetResourceData(resId, param["DATANAME"]);
+
+                return TestResult.FromByteReader(reader);
+            }
+            catch (MgException ex)
+            {
+                Console.WriteLine(ex.GetDetails());
+                return TestResult.FromMgException(ex);
+            }
+            catch (Exception ex)
+            {
+                return TestResult.FromException(ex);
+            }
+        }
+    }
+
+    public class SetResourceData : ResourceServiceOperationExecutor<SetResourceData>
+    {
+        public SetResourceData(MgResourceService resSvc, string unitTestVm)
+            : base(resSvc, unitTestVm)
+        {
+
+        }
+
+        public override TestResult Execute(int paramSetId)
+        {
+            try
+            {
+                var param = new NameValueCollection();
+                _unitTestVm.ReadParameterValue(paramSetId, "RESOURCEID", param);
+                _unitTestVm.ReadParameterValue(paramSetId, "DATANAME", param);
+                _unitTestVm.ReadParameterValue(paramSetId, "DATATYPE", param);
+                _unitTestVm.ReadParameterValue(paramSetId, "DATA", param, true);
+
+                MgResourceIdentifier resId = null;
+                if (param["RESOURCEID"] != null)
+                {
+                    resId = new MgResourceIdentifier(param["RESOURCEID"]);
+                }
+
+                string extension = CommonUtility.GetExtension(param["DATANAME"]);
+                string mimeType = CommonUtility.GetMimeType(extension);
+                MgByteSource dataSource = new MgByteSource(param["DATA"]);
+                dataSource.SetMimeType(mimeType);
+                MgByteReader dataReader = dataSource.GetReader();
+
+                _resourceService.SetResourceData(resId, param["DATANAME"], param["DATATYPE"], dataReader);
+
+                return TestResult.FromByteReader(null);
+            }
+            catch (MgException ex)
+            {
+                return TestResult.FromMgException(ex);
+            }
+            catch (Exception ex)
+            {
+                return TestResult.FromException(ex);
+            }
+        }
+    }
+
+    public class RenameResourceData : ResourceServiceOperationExecutor<RenameResourceData>
+    {
+        public RenameResourceData(MgResourceService resSvc, string unitTestVm)
+            : base(resSvc, unitTestVm)
+        {
+
+        }
+
+        public override TestResult Execute(int paramSetId)
+        {
+            try
+            {
+                var param = new NameValueCollection();
+                _unitTestVm.ReadParameterValue(paramSetId, "RESOURCEID", param);
+                _unitTestVm.ReadParameterValue(paramSetId, "OLDDATANAME", param);
+                _unitTestVm.ReadParameterValue(paramSetId, "NEWDATANAME", param);
+
+                MgResourceIdentifier resId = null;
+                if (param["RESOURCEID"] != null)
+                {
+                    resId = new MgResourceIdentifier(param["RESOURCEID"]);
+                }
+
+                _resourceService.RenameResourceData(resId, param["OLDDATANAME"], param["NEWDATANAME"], false);
+
+                return TestResult.FromByteReader(null);
+            }
+            catch (MgException ex)
+            {
+                return TestResult.FromMgException(ex);
+            }
+            catch (Exception ex)
+            {
+                return TestResult.FromException(ex);
+            }
+        }
+    }
+
+    public class DeleteResourceData : ResourceServiceOperationExecutor<DeleteResourceData>
+    {
+        public DeleteResourceData(MgResourceService resSvc, string unitTestVm)
+            : base(resSvc, unitTestVm)
+        {
+
+        }
+
+        public override TestResult Execute(int paramSetId)
+        {
+            try
+            {
+                var param = new NameValueCollection();
+                _unitTestVm.ReadParameterValue(paramSetId, "RESOURCEID", param);
+                _unitTestVm.ReadParameterValue(paramSetId, "DATANAME", param);
+
+                MgResourceIdentifier resId = null;
+                if (param["RESOURCEID"] != null)
+                {
+                    resId = new MgResourceIdentifier(param["RESOURCEID"]);
+                }
+
+                _resourceService.DeleteResourceData(resId, param["DATANAME"] ?? "");
+
+                return TestResult.FromByteReader(null);
+            }
+            catch (MgException ex)
+            {
+                return TestResult.FromMgException(ex);
+            }
+            catch (Exception ex)
+            {
+                return TestResult.FromException(ex);
+            }
+        }
+    }
+
+    public class GetRepositoryContent : ResourceServiceOperationExecutor<GetRepositoryContent>
+    {
+        public GetRepositoryContent(MgResourceService resSvc, string unitTestVm)
+            : base(resSvc, unitTestVm)
+        {
+
+        }
+
+        public override TestResult Execute(int paramSetId)
+        {
+            try
+            {
+                var param = new NameValueCollection();
+                _unitTestVm.ReadParameterValue(paramSetId, "RESOURCEID", param);
+
+                MgResourceIdentifier resId = null;
+                if (param["RESOURCEID"] != null)
+                {
+                    resId = new MgResourceIdentifier(param["RESOURCEID"]);
+                }
+
+                MgByteReader result = _resourceService.GetRepositoryContent(resId);
+
+                return TestResult.FromByteReader(result);
+            }
+            catch (MgException ex)
+            {
+                return TestResult.FromMgException(ex);
+            }
+            catch (Exception ex)
+            {
+                return TestResult.FromException(ex);
+            }
+        }
+    }
+
+    public class GetRepositoryHeader : ResourceServiceOperationExecutor<GetRepositoryHeader>
+    {
+        public GetRepositoryHeader(MgResourceService resSvc, string unitTestVm)
+            : base(resSvc, unitTestVm)
+        {
+
+        }
+
+        public override TestResult Execute(int paramSetId)
+        {
+            try
+            {
+                var param = new NameValueCollection();
+                _unitTestVm.ReadParameterValue(paramSetId, "RESOURCEID", param);
+
+                MgResourceIdentifier resId = null;
+                if (param["RESOURCEID"] != null)
+                {
+                    resId = new MgResourceIdentifier(param["RESOURCEID"]);
+                }
+
+                MgByteReader result = _resourceService.GetRepositoryHeader(resId);
+
+                return TestResult.FromByteReader(result);
+            }
+            catch (MgException ex)
+            {
+                return TestResult.FromMgException(ex);
+            }
+            catch (Exception ex)
+            {
+                return TestResult.FromException(ex);
+            }
+        }
+    }
+
+    public class UpdateRepository : ResourceServiceOperationExecutor<UpdateRepository>
+    {
+        public UpdateRepository(MgResourceService resSvc, string unitTestVm)
+            : base(resSvc, unitTestVm)
+        {
+
+        }
+
+        public override TestResult Execute(int paramSetId)
+        {
+            try
+            {
+                var param = new NameValueCollection();
+                _unitTestVm.ReadParameterValue(paramSetId, "RESOURCEID", param);
+                _unitTestVm.ReadParameterValue(paramSetId, "CONTENT", param, true);
+                _unitTestVm.ReadParameterValue(paramSetId, "HEADER", param, true);
+
+                MgResourceIdentifier resId = null;
+                if (param["RESOURCEID"] != null)
+                {
+                    resId = new MgResourceIdentifier(param["RESOURCEID"]);
+                }
+
+                MgByteReader content = CommonUtility.GetByteReaderFromPath(param["CONTENT"]);
+                MgByteReader header = CommonUtility.GetByteReaderFromPath(param["HEADER"]);
+
+                _resourceService.UpdateRepository(resId, content, header);
+
+                return TestResult.FromByteReader(null);
+            }
+            catch (MgException ex)
+            {
+                return TestResult.FromMgException(ex);
+            }
+            catch (Exception ex)
+            {
+                return TestResult.FromException(ex);
+            }
+        }
+    }
+
+    public class EnumerateResourceReferences : ResourceServiceOperationExecutor<EnumerateResourceReferences>
+    {
+        public EnumerateResourceReferences(MgResourceService resSvc, string unitTestVm)
+            : base(resSvc, unitTestVm)
+        {
+
+        }
+
+        public override TestResult Execute(int paramSetId)
+        {
+            try
+            {
+                var param = new NameValueCollection();
+                _unitTestVm.ReadParameterValue(paramSetId, "RESOURCEID", param);
+
+                MgResourceIdentifier resId = null;
+                if (param["RESOURCEID"] != null)
+                {
+                    resId = new MgResourceIdentifier(param["RESOURCEID"]);
+                }
+
+                MgByteReader reader = _resourceService.EnumerateReferences(resId);
+
+                return TestResult.FromByteReader(reader);
+            }
+            catch (MgException ex)
+            {
+                return TestResult.FromMgException(ex);
+            }
+            catch (Exception ex)
+            {
+                return TestResult.FromException(ex);
+            }
+        }
+    }
+
+    public class MoveResource : ResourceServiceOperationExecutor<MoveResource>
+    {
+        public MoveResource(MgResourceService resSvc, string unitTestVm)
+            : base(resSvc, unitTestVm)
+        {
+
+        }
+
+        public override TestResult Execute(int paramSetId)
+        {
+            try
+            {
+                var param = new NameValueCollection();
+                _unitTestVm.ReadParameterValue(paramSetId, "SOURCE", param);
+                _unitTestVm.ReadParameterValue(paramSetId, "DESTINATION", param);
+
+                MgResourceIdentifier srcId = null;
+                if (param["SOURCE"] != null)
+                {
+                    srcId = new MgResourceIdentifier(param["SOURCE"]);
+                }
+
+                MgResourceIdentifier dstId = null;
+                if (param["DESTINATION"] != null)
+                {
+                    dstId = new MgResourceIdentifier(param["DESTINATION"]);
+                }
+
+                _resourceService.MoveResource(srcId, dstId, false);
+
+                return TestResult.FromByteReader(null);
+            }
+            catch (MgException ex)
+            {
+                return TestResult.FromMgException(ex);
+            }
+            catch (Exception ex)
+            {
+                return TestResult.FromException(ex);
+            }
+        }
+    }
+
+    public class CopyResource : ResourceServiceOperationExecutor<CopyResource>
+    {
+        public CopyResource(MgResourceService resSvc, string unitTestVm)
+            : base(resSvc, unitTestVm)
+        {
+
+        }
+
+        public override TestResult Execute(int paramSetId)
+        {
+            try
+            {
+                var param = new NameValueCollection();
+                _unitTestVm.ReadParameterValue(paramSetId, "SOURCE", param);
+                _unitTestVm.ReadParameterValue(paramSetId, "DESTINATION", param);
+
+                MgResourceIdentifier srcId = null;
+                if (param["SOURCE"] != null)
+                {
+                    srcId = new MgResourceIdentifier(param["SOURCE"]);
+                }
+
+                MgResourceIdentifier dstId = null;
+                if (param["DESTINATION"] != null)
+                {
+                    dstId = new MgResourceIdentifier(param["DESTINATION"]);
+                }
+
+                _resourceService.CopyResource(srcId, dstId, false);
+
+                return TestResult.FromByteReader(null);
+            }
+            catch (MgException ex)
+            {
+                return TestResult.FromMgException(ex);
+            }
+            catch (Exception ex)
+            {
+                return TestResult.FromException(ex);
+            }
+        }
+    }
+
+    public class ChangeResourceOwner : ResourceServiceOperationExecutor<ChangeResourceOwner>
+    {
+        public ChangeResourceOwner(MgResourceService resSvc, string unitTestVm)
+            : base(resSvc, unitTestVm)
+        {
+
+        }
+
+        public override TestResult Execute(int paramSetId)
+        {
+            try
+            {
+                var param = new NameValueCollection();
+                _unitTestVm.ReadParameterValue(paramSetId, "RESOURCEID", param);
+                _unitTestVm.ReadParameterValue(paramSetId, "OWNER", param);
+                _unitTestVm.ReadParameterValue(paramSetId, "INCLUDEDESCENDANTS", param);
+
+                MgResourceIdentifier resId = null;
+                if (param["RESOURCEID"] != null)
+                {
+                    resId = new MgResourceIdentifier(param["RESOURCEID"]);
+                }
+
+                _resourceService.ChangeResourceOwner(resId, param["OWNER"], (param["INCLUDEDESCENDANTS"] == "1"));
+
+                return TestResult.FromByteReader(null);
+            }
+            catch (MgException ex)
+            {
+                return TestResult.FromMgException(ex);
+            }
+            catch (Exception ex)
+            {
+                return TestResult.FromException(ex);
+            }
+        }
+    }
+
+    public class InheritPermissionsFrom : ResourceServiceOperationExecutor<InheritPermissionsFrom>
+    {
+        public InheritPermissionsFrom(MgResourceService resSvc, string unitTestVm)
+            : base(resSvc, unitTestVm)
+        {
+
+        }
+
+        public override TestResult Execute(int paramSetId)
+        {
+            try
+            {
+                var param = new NameValueCollection();
+                _unitTestVm.ReadParameterValue(paramSetId, "RESOURCEID", param);
+
+                MgResourceIdentifier resId = null;
+                if (param["RESOURCEID"] != null)
+                {
+                    resId = new MgResourceIdentifier(param["RESOURCEID"]);
+                }
+
+                _resourceService.InheritPermissionsFrom(resId);
+
+                return TestResult.FromByteReader(null);
+            }
+            catch (MgException ex)
+            {
+                return TestResult.FromMgException(ex);
+            }
+            catch (Exception ex)
+            {
+                return TestResult.FromException(ex);
+            }
+        }
+    }
+
+    public class ApplyResourcePackage : ResourceServiceOperationExecutor<ApplyResourcePackage>
+    {
+        public ApplyResourcePackage(MgResourceService resSvc, string unitTestVm)
+            : base(resSvc, unitTestVm)
+        {
+
+        }
+
+        public override TestResult Execute(int paramSetId)
+        {
+            try
+            {
+                var param = new NameValueCollection();
+                _unitTestVm.ReadParameterValue(paramSetId, "PACKAGE", param, true);
+
+                MgByteReader reader = CommonUtility.GetByteReaderFromPath(param["PACKAGE"] ?? "", false);
+
+                _resourceService.ApplyResourcePackage(reader);
+
+                return TestResult.FromByteReader(null);
+            }
+            catch (MgException ex)
+            {
+                return TestResult.FromMgException(ex);
+            }
+            catch (Exception ex)
+            {
+                return TestResult.FromException(ex);
+            }
+        }
+    }
+}

Added: trunk/MgDev/UnitTest/WebTier/DotNet/TestCommon/ResourceService/ResourceServiceOperationExecutor.cs
===================================================================
--- trunk/MgDev/UnitTest/WebTier/DotNet/TestCommon/ResourceService/ResourceServiceOperationExecutor.cs	                        (rev 0)
+++ trunk/MgDev/UnitTest/WebTier/DotNet/TestCommon/ResourceService/ResourceServiceOperationExecutor.cs	2013-07-02 15:49:52 UTC (rev 7655)
@@ -0,0 +1,25 @@
+using OSGeo.MapGuide.Test.Common;
+using SqliteDotNet;
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+
+namespace OSGeo.MapGuide.Test.Operations
+{
+    /// <summary>
+    /// The base class of all test executors using the MgResourceService
+    /// </summary>
+    /// <typeparam name="T">The test executor subclass type</typeparam>
+    public abstract class ResourceServiceOperationExecutor<T> : PlatformApiTestExecutor
+    {
+        protected MgResourceService _resourceService;
+
+        protected ResourceServiceOperationExecutor(MgResourceService resSvc, string unitTestVm)
+            : base(typeof(T).Name.ToUpper(), ApiTypes.Platform, unitTestVm)
+        {
+            _resourceService = resSvc;
+        }
+    }
+}

Added: trunk/MgDev/UnitTest/WebTier/DotNet/TestCommon/SqliteException.cs
===================================================================
(Binary files differ)


Property changes on: trunk/MgDev/UnitTest/WebTier/DotNet/TestCommon/SqliteException.cs
___________________________________________________________________
Added: svn:mime-type
   + application/octet-stream

Added: trunk/MgDev/UnitTest/WebTier/DotNet/TestCommon/TestCommon.csproj
===================================================================
--- trunk/MgDev/UnitTest/WebTier/DotNet/TestCommon/TestCommon.csproj	                        (rev 0)
+++ trunk/MgDev/UnitTest/WebTier/DotNet/TestCommon/TestCommon.csproj	2013-07-02 15:49:52 UTC (rev 7655)
@@ -0,0 +1,101 @@
+<?xml version="1.0" encoding="utf-8"?>
+<Project ToolsVersion="4.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
+  <Import Project="$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props" Condition="Exists('$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props')" />
+  <PropertyGroup>
+    <Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
+    <Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform>
+    <ProjectGuid>{80EAA5CB-E709-485A-86AC-DE9B5236EAB9}</ProjectGuid>
+    <OutputType>Library</OutputType>
+    <AppDesignerFolder>Properties</AppDesignerFolder>
+    <RootNamespace>OSGeo.MapGuide.Test.Common</RootNamespace>
+    <AssemblyName>OSGeo.MapGuide.Test.Common</AssemblyName>
+    <TargetFrameworkVersion>v4.5</TargetFrameworkVersion>
+    <FileAlignment>512</FileAlignment>
+  </PropertyGroup>
+  <PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'Debug|x64'">
+    <DebugSymbols>true</DebugSymbols>
+    <OutputPath>bin\x64\Debug\</OutputPath>
+    <DefineConstants>DEBUG;TRACE</DefineConstants>
+    <DebugType>full</DebugType>
+    <PlatformTarget>x64</PlatformTarget>
+    <ErrorReport>prompt</ErrorReport>
+    <CodeAnalysisRuleSet>ManagedMinimumRules.ruleset</CodeAnalysisRuleSet>
+  </PropertyGroup>
+  <PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'Release|x64'">
+    <OutputPath>bin\x64\Release\</OutputPath>
+    <DefineConstants>TRACE</DefineConstants>
+    <Optimize>true</Optimize>
+    <DebugType>pdbonly</DebugType>
+    <PlatformTarget>x64</PlatformTarget>
+    <ErrorReport>prompt</ErrorReport>
+    <CodeAnalysisRuleSet>ManagedMinimumRules.ruleset</CodeAnalysisRuleSet>
+  </PropertyGroup>
+  <PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'Debug|x86'">
+    <DebugSymbols>true</DebugSymbols>
+    <OutputPath>bin\x86\Debug\</OutputPath>
+    <DefineConstants>DEBUG;TRACE</DefineConstants>
+    <DebugType>full</DebugType>
+    <PlatformTarget>x86</PlatformTarget>
+    <ErrorReport>prompt</ErrorReport>
+    <CodeAnalysisRuleSet>ManagedMinimumRules.ruleset</CodeAnalysisRuleSet>
+  </PropertyGroup>
+  <PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'Release|x86'">
+    <OutputPath>bin\x86\Release\</OutputPath>
+    <DefineConstants>TRACE</DefineConstants>
+    <Optimize>true</Optimize>
+    <DebugType>pdbonly</DebugType>
+    <PlatformTarget>x86</PlatformTarget>
+    <ErrorReport>prompt</ErrorReport>
+    <CodeAnalysisRuleSet>ManagedMinimumRules.ruleset</CodeAnalysisRuleSet>
+  </PropertyGroup>
+  <ItemGroup>
+    <Reference Include="OSGeo.MapGuide.Foundation">
+      <HintPath>..\Libs\OSGeo.MapGuide.Foundation.dll</HintPath>
+    </Reference>
+    <Reference Include="OSGeo.MapGuide.Geometry">
+      <HintPath>..\Libs\OSGeo.MapGuide.Geometry.dll</HintPath>
+    </Reference>
+    <Reference Include="OSGeo.MapGuide.PlatformBase">
+      <HintPath>..\Libs\OSGeo.MapGuide.PlatformBase.dll</HintPath>
+    </Reference>
+    <Reference Include="SqliteDotNet">
+      <HintPath>..\Libs\SqliteDotNet.dll</HintPath>
+    </Reference>
+    <Reference Include="System" />
+    <Reference Include="System.Core" />
+    <Reference Include="System.Xml.Linq" />
+    <Reference Include="System.Data.DataSetExtensions" />
+    <Reference Include="Microsoft.CSharp" />
+    <Reference Include="System.Data" />
+    <Reference Include="System.Xml" />
+  </ItemGroup>
+  <ItemGroup>
+    <Compile Include="ApiTypes.cs" />
+    <Compile Include="FeatureService\Operations.cs" />
+    <Compile Include="ITestExecutor.cs" />
+    <Compile Include="ITestExecutorCollection.cs" />
+    <Compile Include="ITestLogger.cs" />
+    <Compile Include="MapLayer\MapLayerOperationExecutor.cs" />
+    <Compile Include="MapLayer\Operations.cs" />
+    <Compile Include="PlatformApiTestExecutor.cs" />
+    <Compile Include="Properties\AssemblyInfo.cs" />
+    <Compile Include="FeatureService\FeatureServiceOperationExecutor.cs" />
+    <Compile Include="ResourceService\ResourceServiceOperationExecutor.cs" />
+    <Compile Include="ResourceService\Operations.cs" />
+    <Compile Include="SqliteException.cs" />
+    <Compile Include="TestExecutionRun.cs" />
+    <Compile Include="TestExecutorBase.cs" />
+    <Compile Include="TestResult.cs" />
+    <Compile Include="UnitTestException.cs" />
+    <Compile Include="CommonUtility.cs" />
+  </ItemGroup>
+  <ItemGroup />
+  <Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
+  <!-- To modify your build process, add your task inside one of the targets below and uncomment it. 
+       Other similar extension points exist, see Microsoft.Common.targets.
+  <Target Name="BeforeBuild">
+  </Target>
+  <Target Name="AfterBuild">
+  </Target>
+  -->
+</Project>
\ No newline at end of file

Added: trunk/MgDev/UnitTest/WebTier/DotNet/TestCommon/TestExecutionRun.cs
===================================================================
--- trunk/MgDev/UnitTest/WebTier/DotNet/TestCommon/TestExecutionRun.cs	                        (rev 0)
+++ trunk/MgDev/UnitTest/WebTier/DotNet/TestCommon/TestExecutionRun.cs	2013-07-02 15:49:52 UTC (rev 7655)
@@ -0,0 +1,113 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+using SqliteDotNet;
+
+namespace OSGeo.MapGuide.Test.Common
+{
+    /// <summary>
+    /// Executes a <see cref="T:OSGeo.MapGuide.Test.Common.ITestExecutorCollection"/> instance
+    /// </summary>
+    public class TestExecutionRun : IDisposable
+    {
+        private ITestExecutorCollection _executors;
+        private SqliteDb _unitTestDb;
+        private SqliteVm _unitTestVm;
+        private SqliteVm _unitTestResultVm;
+        private bool _generateDump;
+
+        public TestExecutionRun(string dbPath, ITestExecutorCollection exec, bool generateDump = false)
+        {
+            _executors = exec;
+            _generateDump = generateDump;
+            _unitTestDb = new SqliteDb();
+            _unitTestDb.Open(dbPath);
+
+            _unitTestVm = new SqliteVm(_unitTestDb, false);
+            _unitTestResultVm = new SqliteVm(_unitTestDb, false);
+        }
+
+        public void Dispose()
+        {
+            _unitTestResultVm.SqlFinalize();
+            _unitTestResultVm = null;
+            _unitTestVm.SqlFinalize();
+            _unitTestVm = null;
+            try
+            {
+                _unitTestDb.Close();
+            }
+            catch { }
+            _unitTestDb = null;
+        }
+
+        public int RunTests(string testName, ITestLogger logger, ref int testsRun)
+        {
+            TestResult actualResult = null;
+            int exitStatus = 0;
+            try
+            {
+                //Add the test in the log file
+                string msg = "\n\n************************************************************\n" +
+                             string.Format("Executing {0}\n", testName) +
+                             "************************************************************\n\n";
+
+                logger.Write(msg);
+
+                //Get the list of operations to be executed for this test. This list should comma separated, no spaces.
+                _unitTestVm.Execute("Select ParamSets from TestCase where TestName=\"{0}\"", testName);
+                string sets = _unitTestVm.GetString("ParamSets");
+
+                //Extract the paramset ids
+                int[] paramSet = sets.Split(',').Where(x => !string.IsNullOrEmpty(x)).Select(x => Convert.ToInt32(x)).ToArray();
+                foreach (int paramSetId in paramSet)
+                {
+                    _unitTestVm.Execute("Select ParamValue from Params where ParamSet={0} AND ParamName=\"OPERATION\"", paramSetId);
+                    string paramValue = _unitTestVm.GetString("ParamValue");
+
+                    testsRun++;
+
+                    //Add the operation to the log file
+                    AddLogFileEntry(logger, paramValue, paramSetId, _unitTestResultVm);
+
+                    var exec = _executors.GetTestExecutor(paramValue);
+                    actualResult = exec.Execute(paramSetId);
+
+                    exitStatus += _executors.ValidateRequest(_unitTestDb, testName, paramSetId, paramValue, actualResult, logger);
+                }
+
+                return exitStatus;
+            }
+            catch (MgException ex)
+            {
+                throw new UnitTestException(string.Format("Exception from MapGuide:\n{0}", ex.GetDetails()));
+            }
+        }
+
+        private static void AddLogFileEntry(ITestLogger logger, string operation, int paramSetId, SqliteVm vm)
+        {
+            logger.Write("\nParamSet: {0}\n", paramSetId);
+            int status = vm.Execute("Select * from Params where ParamSet={0}", paramSetId);
+
+            while (status == Sqlite.Row)
+            {
+                string paramName = vm.GetString("ParamName");
+                string paramValue = vm.GetString("ParamValue");
+
+                logger.Write("{0}: {1}\n", paramName, paramValue);
+                status = vm.NextRow();
+            }
+        }
+
+        public void Cleanup()
+        {
+            if (_executors != null)
+            {
+                _executors.Cleanup();
+                _executors = null;
+            }
+        }
+    }
+}

Added: trunk/MgDev/UnitTest/WebTier/DotNet/TestCommon/TestExecutorBase.cs
===================================================================
--- trunk/MgDev/UnitTest/WebTier/DotNet/TestCommon/TestExecutorBase.cs	                        (rev 0)
+++ trunk/MgDev/UnitTest/WebTier/DotNet/TestCommon/TestExecutorBase.cs	2013-07-02 15:49:52 UTC (rev 7655)
@@ -0,0 +1,25 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+
+namespace OSGeo.MapGuide.Test.Common
+{
+    public abstract class TestExecutorBase : ITestExecutor
+    {
+        public abstract string Api
+        {
+            get;
+        }
+
+        public abstract string OperationName
+        {
+            get;
+        }
+
+        public abstract TestResult Execute(int paramSetId);
+
+        public abstract void Dispose();
+    }
+}

Added: trunk/MgDev/UnitTest/WebTier/DotNet/TestCommon/TestResult.cs
===================================================================
--- trunk/MgDev/UnitTest/WebTier/DotNet/TestCommon/TestResult.cs	                        (rev 0)
+++ trunk/MgDev/UnitTest/WebTier/DotNet/TestCommon/TestResult.cs	2013-07-02 15:49:52 UTC (rev 7655)
@@ -0,0 +1,67 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+
+namespace OSGeo.MapGuide.Test.Common
+{
+    /// <summary>
+    /// Encapsulates a unit test result
+    /// </summary>
+    public class TestResult
+    {
+        public string ResultData
+        {
+            get;
+            private set;
+        }
+
+        public string ContentType
+        {
+            get;
+            private set;
+        }
+
+        public string HttpStatusCode
+        {
+            get;
+            private set;
+        }
+
+        public TestResult(string resultData = "", string contentType = "", string statusCode = "")
+        {
+            this.ResultData = resultData;
+            this.ContentType = contentType;
+            this.HttpStatusCode = statusCode;
+        }
+
+        public static TestResult FromByteReader(MgByteReader byteReader)
+        {
+            try
+            {
+                TestResult res = new TestResult();
+                if (byteReader != null)
+                {
+                    res.ContentType = byteReader.GetMimeType();
+                    res.ResultData = byteReader.ToString();
+                }
+                return res;
+            }
+            catch (MgException ex)
+            {
+                return FromMgException(ex);
+            }
+        }
+
+        public static TestResult FromMgException(MgException ex)
+        {
+            return new TestResult(ex.GetType().Name, "text/plain");
+        }
+
+        public static TestResult FromException(Exception ex)
+        {
+            return new TestResult(ex.Message, "text/plain");
+        }
+    }
+}

Added: trunk/MgDev/UnitTest/WebTier/DotNet/TestCommon/UnitTestException.cs
===================================================================
--- trunk/MgDev/UnitTest/WebTier/DotNet/TestCommon/UnitTestException.cs	                        (rev 0)
+++ trunk/MgDev/UnitTest/WebTier/DotNet/TestCommon/UnitTestException.cs	2013-07-02 15:49:52 UTC (rev 7655)
@@ -0,0 +1,20 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+
+namespace OSGeo.MapGuide.Test.Common
+{
+    [Serializable]
+    public class UnitTestException : Exception
+    {
+        public UnitTestException() { }
+        public UnitTestException(string message) : base(message) { }
+        public UnitTestException(string message, Exception inner) : base(message, inner) { }
+        protected UnitTestException(
+          System.Runtime.Serialization.SerializationInfo info,
+          System.Runtime.Serialization.StreamingContext context)
+            : base(info, context) { }
+    }
+}


Property changes on: trunk/MgDev/UnitTest/WebTier/DotNet/TestMapGuideApi
___________________________________________________________________
Added: bugtraq:number
   + true


Property changes on: trunk/MgDev/UnitTest/WebTier/DotNet/TestMapGuideApi/DrawingService
___________________________________________________________________
Added: bugtraq:number
   + true

Added: trunk/MgDev/UnitTest/WebTier/DotNet/TestMapGuideApi/DrawingService/DrawingServiceOperationExecutor.cs
===================================================================
--- trunk/MgDev/UnitTest/WebTier/DotNet/TestMapGuideApi/DrawingService/DrawingServiceOperationExecutor.cs	                        (rev 0)
+++ trunk/MgDev/UnitTest/WebTier/DotNet/TestMapGuideApi/DrawingService/DrawingServiceOperationExecutor.cs	2013-07-02 15:49:52 UTC (rev 7655)
@@ -0,0 +1,25 @@
+using OSGeo.MapGuide.Test.Common;
+using SqliteDotNet;
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+
+namespace OSGeo.MapGuide.Test.Operations
+{
+    /// <summary>
+    /// The base class of all test executors using the MgDrawingService
+    /// </summary>
+    /// <typeparam name="T">The test executor subclass type</typeparam>
+    public abstract class DrawingServiceOperationExecutor<T> : PlatformApiTestExecutor
+    {
+        protected MgDrawingService _drawingService;
+
+        protected DrawingServiceOperationExecutor(MgDrawingService drawSvc, string unitTestVm)
+            : base(typeof(T).Name.ToUpper(), ApiTypes.Platform, unitTestVm)
+        {
+            _drawingService = drawSvc;
+        }
+    }
+}
\ No newline at end of file

Added: trunk/MgDev/UnitTest/WebTier/DotNet/TestMapGuideApi/DrawingService/Operations.cs
===================================================================
--- trunk/MgDev/UnitTest/WebTier/DotNet/TestMapGuideApi/DrawingService/Operations.cs	                        (rev 0)
+++ trunk/MgDev/UnitTest/WebTier/DotNet/TestMapGuideApi/DrawingService/Operations.cs	2013-07-02 15:49:52 UTC (rev 7655)
@@ -0,0 +1,258 @@
+using OSGeo.MapGuide.Test.Common;
+using SqliteDotNet;
+using System;
+using System.Collections.Generic;
+using System.Collections.Specialized;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+
+namespace OSGeo.MapGuide.Test.Operations
+{
+    public class DescribeDrawing : DrawingServiceOperationExecutor<DescribeDrawing>
+    {
+        public DescribeDrawing(MgDrawingService drawSvc, string vm)
+            : base(drawSvc, vm)
+        {
+        }
+
+        public override TestResult Execute(int paramSetId)
+        {
+            try
+            {
+                var param = new NameValueCollection();
+                _unitTestVm.ReadParameterValue(paramSetId, "RESOURCEID", param);
+
+                MgResourceIdentifier resId = null;
+                if (param["RESOURCEID"] != null)
+                {
+                    resId = new MgResourceIdentifier(param["RESOURCEID"]);
+                }
+
+                MgByteReader reader = _drawingService.DescribeDrawing(resId);
+                return TestResult.FromByteReader(reader);
+            }
+            catch (MgException ex)
+            {
+                return TestResult.FromMgException(ex);
+            }
+        }
+    }
+
+    public class GetDrawing : DrawingServiceOperationExecutor<GetDrawing>
+    {
+        public GetDrawing(MgDrawingService drawSvc, string vm)
+            : base(drawSvc, vm)
+        {
+        }
+
+        public override TestResult Execute(int paramSetId)
+        {
+            try
+            {
+                var param = new NameValueCollection();
+                _unitTestVm.ReadParameterValue(paramSetId, "RESOURCEID", param);
+
+                MgResourceIdentifier resId = null;
+                if (param["RESOURCEID"] != null)
+                {
+                    resId = new MgResourceIdentifier(param["RESOURCEID"]);
+                }
+
+                MgByteReader reader = _drawingService.GetDrawing(resId);
+                return TestResult.FromByteReader(reader);
+            }
+            catch (MgException ex)
+            {
+                return TestResult.FromMgException(ex);
+            }
+        }
+    }
+
+    public class EnumerateDrawingLayers : DrawingServiceOperationExecutor<EnumerateDrawingLayers>
+    {
+        public EnumerateDrawingLayers(MgDrawingService drawSvc, string vm)
+            : base(drawSvc, vm)
+        {
+        }
+
+        public override TestResult Execute(int paramSetId)
+        {
+            try
+            {
+                var param = new NameValueCollection();
+                _unitTestVm.ReadParameterValue(paramSetId, "RESOURCEID", param);
+                _unitTestVm.ReadParameterValue(paramSetId, "SECTION", param);
+
+                MgResourceIdentifier resId = null;
+                if (param["RESOURCEID"] != null)
+                {
+                    resId = new MgResourceIdentifier(param["RESOURCEID"]);
+                }
+
+                MgStringCollection coll = _drawingService.EnumerateLayers(resId, param["SECTION"]);
+                MgByteReader reader = coll.ToXml();
+                return TestResult.FromByteReader(reader);
+            }
+            catch (MgException ex)
+            {
+                return TestResult.FromMgException(ex);
+            }
+        }
+    }
+
+    public class GetDrawingLayer : DrawingServiceOperationExecutor<GetDrawingLayer>
+    {
+        public GetDrawingLayer(MgDrawingService drawSvc, string vm)
+            : base(drawSvc, vm)
+        {
+        }
+
+        public override TestResult Execute(int paramSetId)
+        {
+            try
+            {
+                var param = new NameValueCollection();
+                _unitTestVm.ReadParameterValue(paramSetId, "RESOURCEID", param);
+                _unitTestVm.ReadParameterValue(paramSetId, "SECTION", param);
+                _unitTestVm.ReadParameterValue(paramSetId, "LAYER", param);
+
+                MgResourceIdentifier resId = null;
+                if (param["RESOURCEID"] != null)
+                {
+                    resId = new MgResourceIdentifier(param["RESOURCEID"]);
+                }
+
+                MgByteReader reader = _drawingService.GetLayer(resId, param["SECTION"], param["LAYER"]);
+                return TestResult.FromByteReader(reader);
+            }
+            catch (MgException ex)
+            {
+                return TestResult.FromMgException(ex);
+            }
+        }
+    }
+
+    public class GetDrawingSection : DrawingServiceOperationExecutor<GetDrawingSection>
+    {
+        public GetDrawingSection(MgDrawingService drawSvc, string vm)
+            : base(drawSvc, vm)
+        {
+        }
+
+        public override TestResult Execute(int paramSetId)
+        {
+            try
+            {
+                var param = new NameValueCollection();
+                _unitTestVm.ReadParameterValue(paramSetId, "RESOURCEID", param);
+                _unitTestVm.ReadParameterValue(paramSetId, "SECTION", param);
+
+                MgResourceIdentifier resId = null;
+                if (param["RESOURCEID"] != null)
+                {
+                    resId = new MgResourceIdentifier(param["RESOURCEID"]);
+                }
+
+                MgByteReader reader = _drawingService.GetSection(resId, param["SECTION"]);
+                return TestResult.FromByteReader(reader);
+            }
+            catch (MgException ex)
+            {
+                return TestResult.FromMgException(ex);
+            }
+        }
+    }
+
+    public class EnumerateDrawingSections : DrawingServiceOperationExecutor<EnumerateDrawingSections>
+    {
+        public EnumerateDrawingSections(MgDrawingService drawSvc, string vm)
+            : base(drawSvc, vm)
+        {
+        }
+
+        public override TestResult Execute(int paramSetId)
+        {
+            try
+            {
+                var param = new NameValueCollection();
+                _unitTestVm.ReadParameterValue(paramSetId, "RESOURCEID", param);
+
+                MgResourceIdentifier resId = null;
+                if (param["RESOURCEID"] != null)
+                {
+                    resId = new MgResourceIdentifier(param["RESOURCEID"]);
+                }
+
+                MgByteReader reader = _drawingService.EnumerateSections(resId);
+                return TestResult.FromByteReader(reader);
+            }
+            catch (MgException ex)
+            {
+                return TestResult.FromMgException(ex);
+            }
+        }
+    }
+
+    public class EnumerateDrawingSectionResources : DrawingServiceOperationExecutor<EnumerateDrawingSectionResources>
+    {
+        public EnumerateDrawingSectionResources(MgDrawingService drawSvc, string vm)
+            : base(drawSvc, vm)
+        {
+        }
+
+        public override TestResult Execute(int paramSetId)
+        {
+            try
+            {
+                var param = new NameValueCollection();
+                _unitTestVm.ReadParameterValue(paramSetId, "RESOURCEID", param);
+                _unitTestVm.ReadParameterValue(paramSetId, "SECTION", param);
+
+                MgResourceIdentifier resId = null;
+                if (param["RESOURCEID"] != null)
+                {
+                    resId = new MgResourceIdentifier(param["RESOURCEID"]);
+                }
+
+                MgByteReader reader = _drawingService.EnumerateSectionResources(resId, param["SECTION"]);
+                return TestResult.FromByteReader(reader);
+            }
+            catch (MgException ex)
+            {
+                return TestResult.FromMgException(ex);
+            }
+        }
+    }
+
+    public class GetDrawingSectionResource : DrawingServiceOperationExecutor<GetDrawingSectionResource>
+    {
+        public GetDrawingSectionResource(MgDrawingService drawSvc, string vm)
+            : base(drawSvc, vm)
+        {
+        }
+
+        public override TestResult Execute(int paramSetId)
+        {
+            try
+            {
+                var param = new NameValueCollection();
+                _unitTestVm.ReadParameterValue(paramSetId, "RESOURCEID", param);
+                _unitTestVm.ReadParameterValue(paramSetId, "RESOURCENAME", param);
+
+                MgResourceIdentifier resId = null;
+                if (param["RESOURCEID"] != null)
+                {
+                    resId = new MgResourceIdentifier(param["RESOURCEID"]);
+                }
+
+                MgByteReader reader = _drawingService.GetSectionResource(resId, param["RESOURCENAME"]);
+                return TestResult.FromByteReader(reader);
+            }
+            catch (MgException ex)
+            {
+                return TestResult.FromMgException(ex);
+            }
+        }
+    }
+}

Added: trunk/MgDev/UnitTest/WebTier/DotNet/TestMapGuideApi/MapGuideTestExecutorCollection.cs
===================================================================
--- trunk/MgDev/UnitTest/WebTier/DotNet/TestMapGuideApi/MapGuideTestExecutorCollection.cs	                        (rev 0)
+++ trunk/MgDev/UnitTest/WebTier/DotNet/TestMapGuideApi/MapGuideTestExecutorCollection.cs	2013-07-02 15:49:52 UTC (rev 7655)
@@ -0,0 +1,342 @@
+using OSGeo.MapGuide;
+using OSGeo.MapGuide.Test.Common;
+using SqliteDotNet;
+using System;
+using System.Collections.Generic;
+using System.IO;
+using System.Linq;
+using System.Reflection;
+using System.Text;
+using System.Threading.Tasks;
+using System.Xml;
+
+namespace OSGeo.MapGuide.Test.Web
+{
+    public class MapGuideTestExecutorCollection : TestExecutorCollectionBase
+    {
+        private Dictionary<string, ITestExecutor> _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<string, ITestExecutor>();
+
+            MgResourceService resSvc = (MgResourceService)_conn.CreateService(MgServiceType.ResourceService);
+            MgFeatureService featSvc = (MgFeatureService)_conn.CreateService(MgServiceType.FeatureService);
+            MgDrawingService drawSvc = (MgDrawingService)_conn.CreateService(MgServiceType.DrawingService);
+
+            var creator = new MgMapCreator(resSvc);
+            var sessionCreator = new MgSessionCreator(_conn);
+            var sessionApply = new MgApplySession(_userInfo);
+
+            //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
+
+            //Site Service
+
+            //Web Layout
+        }
+
+        class MgMapCreator : Operations.IMapCreator
+        {
+            private MgResourceService _resSvc;
+            private MgMap _map;
+
+            public MgMapCreator(MgResourceService resSvc)
+            {
+                _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();
+                _map.Create(_resSvc, 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);
+            }
+        }
+
+        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);
+
+            string expectedResult = "";
+
+            //If we have an exception we need to remove the stack trace because different line numbers will fail the test
+            string 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);
+                }
+                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");
+                        /*
+                        //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)
+                            expectedResult = Encoding.UTF8.GetString(b);
+
+                        //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 (expectedResult.StartsWith("@@"))
+                        {
+                            string sampleDataFile = expectedResult.Substring(2);
+                            sampleDataFile = CommonUtility.GetPath(sampleDataFile);
+                            expectedResult = File.ReadAllText(sampleDataFile);
+                        }
+
+                        if (this.TestExecutionMode == "validate")
+                        {
+                            //If the results are different and special validation fails then the operation failed ->mark it red
+                            if (!resultData.Equals(expectedResult, StringComparison.InvariantCultureIgnoreCase) && !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
+                        {
+                            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);
+                logger.Write(str);
+            }
+
+            vm.SqlFinalize();
+            vm = null;
+
+            return exitStatus;
+        }
+
+        public override void Cleanup()
+        {
+            
+        }
+
+        public override string ApiType
+        {
+            get { return ApiTypes.Platform; }
+        }
+    }
+}


Property changes on: trunk/MgDev/UnitTest/WebTier/DotNet/TestMapGuideApi/MappingService
___________________________________________________________________
Added: bugtraq:number
   + true

Added: trunk/MgDev/UnitTest/WebTier/DotNet/TestMapGuideApi/MappingService/MappingServiceOperationExecutor.cs
===================================================================
--- trunk/MgDev/UnitTest/WebTier/DotNet/TestMapGuideApi/MappingService/MappingServiceOperationExecutor.cs	                        (rev 0)
+++ trunk/MgDev/UnitTest/WebTier/DotNet/TestMapGuideApi/MappingService/MappingServiceOperationExecutor.cs	2013-07-02 15:49:52 UTC (rev 7655)
@@ -0,0 +1,25 @@
+using OSGeo.MapGuide.Test.Common;
+using SqliteDotNet;
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+
+namespace OSGeo.MapGuide.Test.Operations
+{
+    /// <summary>
+    /// The base class of all test executors using the MgMappingService
+    /// </summary>
+    /// <typeparam name="T">The test executor subclass type</typeparam>
+    public abstract class MappingServiceOperationExecutor<T> : PlatformApiTestExecutor
+    {
+        protected MgMappingService _mappingService;
+
+        protected MappingServiceOperationExecutor(MgMappingService mappingSvc, string unitTestVm)
+            : base(typeof(T).Name.ToUpper(), ApiTypes.Platform, unitTestVm)
+        {
+            _mappingService = mappingSvc;
+        }
+    }
+}
\ No newline at end of file


Property changes on: trunk/MgDev/UnitTest/WebTier/DotNet/TestMapGuideApi/Properties
___________________________________________________________________
Added: bugtraq:number
   + true

Added: trunk/MgDev/UnitTest/WebTier/DotNet/TestMapGuideApi/Properties/AssemblyInfo.cs
===================================================================
--- trunk/MgDev/UnitTest/WebTier/DotNet/TestMapGuideApi/Properties/AssemblyInfo.cs	                        (rev 0)
+++ trunk/MgDev/UnitTest/WebTier/DotNet/TestMapGuideApi/Properties/AssemblyInfo.cs	2013-07-02 15:49:52 UTC (rev 7655)
@@ -0,0 +1,36 @@
+using System.Reflection;
+using System.Runtime.CompilerServices;
+using System.Runtime.InteropServices;
+
+// General Information about an assembly is controlled through the following 
+// set of attributes. Change these attribute values to modify the information
+// associated with an assembly.
+[assembly: AssemblyTitle("TestMapGuideApi")]
+[assembly: AssemblyDescription("")]
+[assembly: AssemblyConfiguration("")]
+[assembly: AssemblyCompany("")]
+[assembly: AssemblyProduct("TestMapGuideApi")]
+[assembly: AssemblyCopyright("Copyright ©  2013")]
+[assembly: AssemblyTrademark("")]
+[assembly: AssemblyCulture("")]
+
+// Setting ComVisible to false makes the types in this assembly not visible 
+// to COM components.  If you need to access a type in this assembly from 
+// COM, set the ComVisible attribute to true on that type.
+[assembly: ComVisible(false)]
+
+// The following GUID is for the ID of the typelib if this project is exposed to COM
+[assembly: Guid("5378c42b-69aa-42e2-bd4f-7e4e53e41bda")]
+
+// Version information for an assembly consists of the following four values:
+//
+//      Major Version
+//      Minor Version 
+//      Build Number
+//      Revision
+//
+// You can specify all the values or you can default the Build and Revision Numbers 
+// by using the '*' as shown below:
+// [assembly: AssemblyVersion("1.0.*")]
+[assembly: AssemblyVersion("1.0.0.0")]
+[assembly: AssemblyFileVersion("1.0.0.0")]


Property changes on: trunk/MgDev/UnitTest/WebTier/DotNet/TestMapGuideApi/RenderingService
___________________________________________________________________
Added: bugtraq:number
   + true

Added: trunk/MgDev/UnitTest/WebTier/DotNet/TestMapGuideApi/RenderingService/RenderingServiceOperationExecutor.cs
===================================================================
--- trunk/MgDev/UnitTest/WebTier/DotNet/TestMapGuideApi/RenderingService/RenderingServiceOperationExecutor.cs	                        (rev 0)
+++ trunk/MgDev/UnitTest/WebTier/DotNet/TestMapGuideApi/RenderingService/RenderingServiceOperationExecutor.cs	2013-07-02 15:49:52 UTC (rev 7655)
@@ -0,0 +1,25 @@
+using OSGeo.MapGuide.Test.Common;
+using SqliteDotNet;
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+
+namespace OSGeo.MapGuide.Test.Operations
+{
+    /// <summary>
+    /// The base class of all test executors using the MgRenderingService
+    /// </summary>
+    /// <typeparam name="T">The test executor subclass type</typeparam>
+    public abstract class RenderingServiceOperationExecutor<T> : PlatformApiTestExecutor
+    {
+        protected MgRenderingService _renderingService;
+
+        protected RenderingServiceOperationExecutor(MgRenderingService renderSvc, string unitTestVm)
+            : base(typeof(T).Name.ToUpper(), ApiTypes.Platform, unitTestVm)
+        {
+            _renderingService = renderSvc;
+        }
+    }
+}
\ No newline at end of file


Property changes on: trunk/MgDev/UnitTest/WebTier/DotNet/TestMapGuideApi/ServerAdmin
___________________________________________________________________
Added: bugtraq:number
   + true

Added: trunk/MgDev/UnitTest/WebTier/DotNet/TestMapGuideApi/ServerAdmin/ServerAdminOperationExecutor.cs
===================================================================
--- trunk/MgDev/UnitTest/WebTier/DotNet/TestMapGuideApi/ServerAdmin/ServerAdminOperationExecutor.cs	                        (rev 0)
+++ trunk/MgDev/UnitTest/WebTier/DotNet/TestMapGuideApi/ServerAdmin/ServerAdminOperationExecutor.cs	2013-07-02 15:49:52 UTC (rev 7655)
@@ -0,0 +1,25 @@
+using OSGeo.MapGuide.Test.Common;
+using SqliteDotNet;
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+
+namespace OSGeo.MapGuide.Test.Operations
+{
+    /// <summary>
+    /// The base class of all test executors using the MgServerAdmin
+    /// </summary>
+    /// <typeparam name="T">The test executor subclass type</typeparam>
+    public abstract class ServerAdminOperationExecutor<T> : PlatformApiTestExecutor
+    {
+        protected MgServerAdmin _serverAdmin;
+
+        protected ServerAdminOperationExecutor(MgServerAdmin serverAdmin, string unitTestVm)
+            : base(typeof(T).Name.ToUpper(), ApiTypes.Platform, unitTestVm)
+        {
+            _serverAdmin = serverAdmin;
+        }
+    }
+}
\ No newline at end of file


Property changes on: trunk/MgDev/UnitTest/WebTier/DotNet/TestMapGuideApi/SiteService
___________________________________________________________________
Added: bugtraq:number
   + true

Added: trunk/MgDev/UnitTest/WebTier/DotNet/TestMapGuideApi/SiteService/SiteServiceOperationExecutor.cs
===================================================================
--- trunk/MgDev/UnitTest/WebTier/DotNet/TestMapGuideApi/SiteService/SiteServiceOperationExecutor.cs	                        (rev 0)
+++ trunk/MgDev/UnitTest/WebTier/DotNet/TestMapGuideApi/SiteService/SiteServiceOperationExecutor.cs	2013-07-02 15:49:52 UTC (rev 7655)
@@ -0,0 +1,25 @@
+using OSGeo.MapGuide.Test.Common;
+using SqliteDotNet;
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+
+namespace OSGeo.MapGuide.Test.Operations
+{
+    /// <summary>
+    /// The base class of all test executors using the MgSite
+    /// </summary>
+    /// <typeparam name="T">The test executor subclass type</typeparam>
+    public abstract class SiteServiceOperationExecutor<T> : PlatformApiTestExecutor
+    {
+        protected MgSite _site;
+
+        protected SiteServiceOperationExecutor(MgSite site, string unitTestVm)
+            : base(typeof(T).Name.ToUpper(), ApiTypes.Platform, unitTestVm)
+        {
+            _site = site;
+        }
+    }
+}
\ No newline at end of file

Added: trunk/MgDev/UnitTest/WebTier/DotNet/TestMapGuideApi/TestMapGuideApi.csproj
===================================================================
--- trunk/MgDev/UnitTest/WebTier/DotNet/TestMapGuideApi/TestMapGuideApi.csproj	                        (rev 0)
+++ trunk/MgDev/UnitTest/WebTier/DotNet/TestMapGuideApi/TestMapGuideApi.csproj	2013-07-02 15:49:52 UTC (rev 7655)
@@ -0,0 +1,104 @@
+<?xml version="1.0" encoding="utf-8"?>
+<Project ToolsVersion="4.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
+  <Import Project="$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props" Condition="Exists('$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props')" />
+  <PropertyGroup>
+    <Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
+    <Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform>
+    <ProjectGuid>{54A7F4EE-D977-4DFB-9922-C46C5FFB6822}</ProjectGuid>
+    <OutputType>Library</OutputType>
+    <AppDesignerFolder>Properties</AppDesignerFolder>
+    <RootNamespace>OSGeo.MapGuide.Test.Web</RootNamespace>
+    <AssemblyName>OSGeo.MapGuide.Test.Web</AssemblyName>
+    <TargetFrameworkVersion>v4.5</TargetFrameworkVersion>
+    <FileAlignment>512</FileAlignment>
+  </PropertyGroup>
+  <PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'Debug|x64'">
+    <DebugSymbols>true</DebugSymbols>
+    <OutputPath>bin\x64\Debug\</OutputPath>
+    <DefineConstants>DEBUG;TRACE</DefineConstants>
+    <DebugType>full</DebugType>
+    <PlatformTarget>x64</PlatformTarget>
+    <ErrorReport>prompt</ErrorReport>
+    <CodeAnalysisRuleSet>ManagedMinimumRules.ruleset</CodeAnalysisRuleSet>
+  </PropertyGroup>
+  <PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'Release|x64'">
+    <OutputPath>bin\x64\Release\</OutputPath>
+    <DefineConstants>TRACE</DefineConstants>
+    <Optimize>true</Optimize>
+    <DebugType>pdbonly</DebugType>
+    <PlatformTarget>x64</PlatformTarget>
+    <ErrorReport>prompt</ErrorReport>
+    <CodeAnalysisRuleSet>ManagedMinimumRules.ruleset</CodeAnalysisRuleSet>
+  </PropertyGroup>
+  <PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'Debug|x86'">
+    <DebugSymbols>true</DebugSymbols>
+    <OutputPath>bin\x86\Debug\</OutputPath>
+    <DefineConstants>DEBUG;TRACE</DefineConstants>
+    <DebugType>full</DebugType>
+    <PlatformTarget>x86</PlatformTarget>
+    <ErrorReport>prompt</ErrorReport>
+    <CodeAnalysisRuleSet>ManagedMinimumRules.ruleset</CodeAnalysisRuleSet>
+  </PropertyGroup>
+  <PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'Release|x86'">
+    <OutputPath>bin\x86\Release\</OutputPath>
+    <DefineConstants>TRACE</DefineConstants>
+    <Optimize>true</Optimize>
+    <DebugType>pdbonly</DebugType>
+    <PlatformTarget>x86</PlatformTarget>
+    <ErrorReport>prompt</ErrorReport>
+    <CodeAnalysisRuleSet>ManagedMinimumRules.ruleset</CodeAnalysisRuleSet>
+  </PropertyGroup>
+  <ItemGroup>
+    <Reference Include="OSGeo.MapGuide.Foundation">
+      <HintPath>..\Libs\OSGeo.MapGuide.Foundation.dll</HintPath>
+    </Reference>
+    <Reference Include="OSGeo.MapGuide.Geometry">
+      <HintPath>..\Libs\OSGeo.MapGuide.Geometry.dll</HintPath>
+    </Reference>
+    <Reference Include="OSGeo.MapGuide.MapGuideCommon">
+      <HintPath>..\Libs\OSGeo.MapGuide.MapGuideCommon.dll</HintPath>
+    </Reference>
+    <Reference Include="OSGeo.MapGuide.PlatformBase">
+      <HintPath>..\Libs\OSGeo.MapGuide.PlatformBase.dll</HintPath>
+    </Reference>
+    <Reference Include="OSGeo.MapGuide.Web">
+      <HintPath>..\Libs\OSGeo.MapGuide.Web.dll</HintPath>
+    </Reference>
+    <Reference Include="SqliteDotNet">
+      <HintPath>..\Libs\SqliteDotNet.dll</HintPath>
+    </Reference>
+    <Reference Include="System" />
+    <Reference Include="System.Core" />
+    <Reference Include="System.Xml.Linq" />
+    <Reference Include="System.Data.DataSetExtensions" />
+    <Reference Include="Microsoft.CSharp" />
+    <Reference Include="System.Data" />
+    <Reference Include="System.Xml" />
+  </ItemGroup>
+  <ItemGroup>
+    <Compile Include="DrawingService\DrawingServiceOperationExecutor.cs" />
+    <Compile Include="DrawingService\Operations.cs" />
+    <Compile Include="MappingService\MappingServiceOperationExecutor.cs" />
+    <Compile Include="Properties\AssemblyInfo.cs" />
+    <Compile Include="MapGuideTestExecutorCollection.cs" />
+    <Compile Include="RenderingService\RenderingServiceOperationExecutor.cs" />
+    <Compile Include="ServerAdmin\ServerAdminOperationExecutor.cs" />
+    <Compile Include="SiteService\SiteServiceOperationExecutor.cs" />
+    <Compile Include="WebLayout\WebLayoutOperationExecutor.cs" />
+  </ItemGroup>
+  <ItemGroup>
+    <ProjectReference Include="..\TestCommon\TestCommon.csproj">
+      <Project>{80eaa5cb-e709-485a-86ac-de9b5236eab9}</Project>
+      <Name>TestCommon</Name>
+    </ProjectReference>
+  </ItemGroup>
+  <ItemGroup />
+  <Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
+  <!-- To modify your build process, add your task inside one of the targets below and uncomment it. 
+       Other similar extension points exist, see Microsoft.Common.targets.
+  <Target Name="BeforeBuild">
+  </Target>
+  <Target Name="AfterBuild">
+  </Target>
+  -->
+</Project>
\ No newline at end of file


Property changes on: trunk/MgDev/UnitTest/WebTier/DotNet/TestMapGuideApi/WebLayout
___________________________________________________________________
Added: bugtraq:number
   + true

Added: trunk/MgDev/UnitTest/WebTier/DotNet/TestMapGuideApi/WebLayout/WebLayoutOperationExecutor.cs
===================================================================
--- trunk/MgDev/UnitTest/WebTier/DotNet/TestMapGuideApi/WebLayout/WebLayoutOperationExecutor.cs	                        (rev 0)
+++ trunk/MgDev/UnitTest/WebTier/DotNet/TestMapGuideApi/WebLayout/WebLayoutOperationExecutor.cs	2013-07-02 15:49:52 UTC (rev 7655)
@@ -0,0 +1,25 @@
+using OSGeo.MapGuide.Test.Common;
+using SqliteDotNet;
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+
+namespace OSGeo.MapGuide.Test.Operations
+{
+    /// <summary>
+    /// The base class of all test executors using the MgWebLayout
+    /// </summary>
+    /// <typeparam name="T">The test executor subclass type</typeparam>
+    public abstract class WebLayoutOperationExecutor<T> : PlatformApiTestExecutor
+    {
+        protected MgWebLayout _wl;
+
+        protected WebLayoutOperationExecutor(MgWebLayout wl, string unitTestVm)
+            : base(typeof(T).Name.ToUpper(), ApiTypes.Platform, unitTestVm)
+        {
+            _wl = wl;
+        }
+    }
+}
\ No newline at end of file

Added: trunk/MgDev/UnitTest/WebTier/DotNet/readme.txt
===================================================================
--- trunk/MgDev/UnitTest/WebTier/DotNet/readme.txt	                        (rev 0)
+++ trunk/MgDev/UnitTest/WebTier/DotNet/readme.txt	2013-07-02 15:49:52 UTC (rev 7655)
@@ -0,0 +1,7 @@
+This is the .net port of the PHP test runner for unit testing the language bindings to the MapGuide Web API.
+
+This test runner differs from the PHP one in the following ways:
+
+ - It does not support test update/generation. Use the existing PHP runner to do that.
+ - Does not support the HTTP API tests. The PHP test runner already covers this and duplicating it in .net serves no real purpose.
+ - It is strictly for running from the command-line and not within a web browser.
\ No newline at end of file



More information about the mapguide-commits mailing list