From 2e2fef47f2ec91f7d15deb1bc593f2efb5e85a18 Mon Sep 17 00:00:00 2001 From: SubPointSupport Date: Sat, 1 Apr 2017 00:10:15 -0700 Subject: [PATCH 01/16] Regression testing fixes (o365) for the following issues: + Nested terms provisioning in Office 365 fails #995 + TermSet not found #994 --- SPMeta2.sln | 3 +- SPMeta2/Build/build.json | 115 +++++++++++++----- SPMeta2/Build/tools/packages.config.md5sum | 2 +- .../O365v16ProvisionRunner.cs | 1 - .../SPMeta2.Containers.O365v16.csproj | 20 +-- .../Base/SPMeta2RegresionTestBase.cs | 22 +++- .../SPMeta2.Containers.O365.dll.config | 65 ---------- .../SPMeta2.Regression.Tests.csproj | 18 +-- 8 files changed, 111 insertions(+), 135 deletions(-) delete mode 100644 SPMeta2/SPMeta2.Regression.Tests/SPMeta2.Containers.O365.dll.config diff --git a/SPMeta2.sln b/SPMeta2.sln index 24c200434..f26be87a4 100644 --- a/SPMeta2.sln +++ b/SPMeta2.sln @@ -1,7 +1,7 @@  Microsoft Visual Studio Solution File, Format Version 12.00 # Visual Studio 2013 -VisualStudioVersion = 12.0.30501.0 +VisualStudioVersion = 12.0.31101.0 MinimumVisualStudioVersion = 10.0.40219.1 Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Provision", "Provision", "{8A0307D3-5564-4034-9DB1-D13FEE1DADD9}" EndProject @@ -236,7 +236,6 @@ Global {04EF5903-B379-4404-8DBC-B21ABE0D1099}.Debug45|Any CPU.ActiveCfg = Debug45|Any CPU {04EF5903-B379-4404-8DBC-B21ABE0D1099}.Debug45|Any CPU.Build.0 = Debug45|Any CPU {E9274D1F-BF08-44CB-9162-35110379D5C0}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {E9274D1F-BF08-44CB-9162-35110379D5C0}.Debug|Any CPU.Build.0 = Debug|Any CPU {E9274D1F-BF08-44CB-9162-35110379D5C0}.Debug40|Any CPU.ActiveCfg = Debug40|Any CPU {E9274D1F-BF08-44CB-9162-35110379D5C0}.Debug40|Any CPU.Build.0 = Debug40|Any CPU {E9274D1F-BF08-44CB-9162-35110379D5C0}.Debug45|Any CPU.ActiveCfg = Debug45|Any CPU diff --git a/SPMeta2/Build/build.json b/SPMeta2/Build/build.json index c21e9ae41..e51b4a1ca 100644 --- a/SPMeta2/Build/build.json +++ b/SPMeta2/Build/build.json @@ -2,12 +2,12 @@ "defaultSolutionDirectory": "./../../", "defaultSolutionFilePath": "./../../SPMeta2.sln", - "defaultDocsBuildEnabled" : true, + "defaultDocsBuildEnabled": true, - "defaultDocsViewFolder" : "SPMeta2/SubPointSolutions.Docs/Views/SPMeta2", - "defaultDocsRepoFolder" : "m2-m2", - "defaultDocsBranch" : "wyam-dev", - "defaultDocsFileExtensions" : [ + "defaultDocsViewFolder": "SPMeta2/SubPointSolutions.Docs/Views/SPMeta2", + "defaultDocsRepoFolder": "m2-m2", + "defaultDocsBranch": "wyam-dev", + "defaultDocsFileExtensions": [ "*.md", "*.cs", "*.cshtml" @@ -15,11 +15,11 @@ "customProjectBuildProfiles": [ { - "ProfileName" : "SPMeta2: SP2010 + NET35", - "ProjectFiles" : [ + "ProfileName": "SPMeta2: SP2010 + NET35", + "ProjectFiles": [ "SPMeta2/SPMeta2/SPMeta2.csproj", "SPMeta2/SPMeta2.Standard/SPMeta2.Standard.csproj", - + "SPMeta2/SPMeta2.SSOM/SPMeta2.SSOM.csproj", "SPMeta2/SPMeta2.SSOM.Standard/SPMeta2.SSOM.Standard.csproj", @@ -41,11 +41,11 @@ }, { - "ProfileName" : "SPMeta2: SP2013 + NET40", - "ProjectFiles" : [ + "ProfileName": "SPMeta2: SP2013 + NET40", + "ProjectFiles": [ "SPMeta2/SPMeta2/SPMeta2.csproj", "SPMeta2/SPMeta2.Standard/SPMeta2.Standard.csproj", - + "SPMeta2/SPMeta2.SSOM/SPMeta2.SSOM.csproj", "SPMeta2/SPMeta2.SSOM.Standard/SPMeta2.SSOM.Standard.csproj", @@ -67,11 +67,11 @@ }, { - "ProfileName" : "SPMeta2: SP2013 + NET45", - "ProjectFiles" : [ + "ProfileName": "SPMeta2: SP2013 + NET45", + "ProjectFiles": [ "SPMeta2/SPMeta2/SPMeta2.csproj", "SPMeta2/SPMeta2.Standard/SPMeta2.Standard.csproj", - + "SPMeta2/SPMeta2.SSOM/SPMeta2.SSOM.csproj", "SPMeta2/SPMeta2.SSOM.Standard/SPMeta2.SSOM.Standard.csproj", @@ -93,11 +93,11 @@ }, { - "ProfileName" : "SPMeta2: SP2016 + NET45", - "ProjectFiles" : [ + "ProfileName": "SPMeta2: SP2016 + NET45", + "ProjectFiles": [ "SPMeta2/SPMeta2/SPMeta2.csproj", "SPMeta2/SPMeta2.Standard/SPMeta2.Standard.csproj", - + "SPMeta2/SPMeta2.SSOM/SPMeta2.SSOM.csproj", "SPMeta2/SPMeta2.SSOM.Standard/SPMeta2.SSOM.Standard.csproj", @@ -120,8 +120,8 @@ { - "ProfileName" : "SPMeta2: SharePoint Online (O365) + NET40", - "ProjectFiles" : [ + "ProfileName": "SPMeta2: SharePoint Online (O365) + NET40", + "ProjectFiles": [ "SPMeta2/SPMeta2/SPMeta2.csproj", "SPMeta2/SPMeta2.Standard/SPMeta2.Standard.csproj", @@ -142,9 +142,9 @@ ] }, - { - "ProfileName" : "SPMeta2: SharePoint Online (O365) + NET45", - "ProjectFiles" : [ + { + "ProfileName": "SPMeta2: SharePoint Online (O365) + NET45", + "ProjectFiles": [ "SPMeta2/SPMeta2/SPMeta2.csproj", "SPMeta2/SPMeta2.Standard/SPMeta2.Standard.csproj", @@ -166,11 +166,11 @@ }, { - "ProfileName" : "SPMeta2: Regression test containers NET45", - "ProjectFiles" : [ + "ProfileName": "SPMeta2: Regression test containers NET45", + "ProjectFiles": [ "SPMeta2/SPMeta2.Containers.CSOM/SPMeta2.Containers.CSOM.csproj", "SPMeta2/SPMeta2.Containers.SSOM/SPMeta2.Containers.SSOM.csproj", - "SPMeta2/SPMeta2.Containers.O365/SPMeta2.Containers.O365.csproj", + "SPMeta2/SPMeta2.Containers.O365/SPMeta2.Containers.O365.csproj", "SPMeta2/SPMeta2.Containers.O365v16/SPMeta2.Containers.O365v16.csproj" ], "BuildParameters": [ @@ -186,9 +186,67 @@ ] }, + { + "ProfileName": "SPMeta2: Regression CSOM", + "ProjectFiles": [ + "SPMeta2/SPMeta2.Regression.CSOM/SPMeta2.Regression.CSOM.csproj", + "SPMeta2/SPMeta2.Regression.CSOM.Standard/SPMeta2.Regression.CSOM.Standard.csproj" + ], + "BuildParameters": [ + "/p:Configuration=Debug", + "/p:DefineConstants=NET45", + + "/t:Build", + "/p:Platform=AnyCPU", + "/p:WarningLevel=0", + "/verbosity:quiet", + "/clp:ErrorsOnly", + "/nologo" + ] + }, + + { + "ProfileName": "SPMeta2: Regression CSOM NET45", + "ProjectFiles": [ + "SPMeta2/SPMeta2.Regression.CSOM/SPMeta2.Regression.CSOM.csproj", + "SPMeta2/SPMeta2.Regression.CSOM.Standard/SPMeta2.Regression.CSOM.Standard.csproj" + ], + "BuildParameters": [ + "/p:Configuration=Debug", + "/p:DefineConstants=NET45", + + "/t:Build", + "/p:Platform=AnyCPU", + "/p:WarningLevel=0", + "/verbosity:quiet", + "/clp:ErrorsOnly", + "/nologo" + ] + }, + { - "ProfileName" : "SPMeta2: Regression tests NET45", - "ProjectFiles" : [ + "ProfileName": "SPMeta2: Regression CSOM NET45 - v365", + "ProjectFiles": [ + "SPMeta2/SPMeta2.Regression.CSOM/SPMeta2.Regression.CSOM.csproj", + "SPMeta2/SPMeta2.Regression.CSOM.Standard/SPMeta2.Regression.CSOM.Standard.csproj" + ], + "BuildParameters": [ + "/p:spRuntime=365", + "/p:Configuration=Debug45", + "/p:DefineConstants=NET45", + + "/t:Build", + "/p:Platform=AnyCPU", + "/p:WarningLevel=0", + "/verbosity:quiet", + "/clp:ErrorsOnly", + "/nologo" + ] + }, + + { + "ProfileName": "SPMeta2: Regression tests NET45", + "ProjectFiles": [ "SPMeta2/SPMeta2.Regression.Tests/SPMeta2.Regression.Tests.csproj", "SPMeta2/SPMeta2.Regression.Impl.Tests/SPMeta2.Regression.Impl.Tests.csproj", ], @@ -204,8 +262,7 @@ "/nologo" ] } - ] - , + ], "defaultNuGetPackagesDirectory": "./build-artifact-nuget-packages", "defaultChocolateyPackagesDirectory": "./build-artifact-cli-packages", diff --git a/SPMeta2/Build/tools/packages.config.md5sum b/SPMeta2/Build/tools/packages.config.md5sum index 8b81cf99a..95db67f7c 100644 --- a/SPMeta2/Build/tools/packages.config.md5sum +++ b/SPMeta2/Build/tools/packages.config.md5sum @@ -1 +1 @@ -93-A8-F9-3B-FF-40-99-D5-E4-C1-E0-AF-32-14-3A-BB +38-0C-2E-66-B0-3C-49-7B-AD-15-87-FD-A7-2D-0C-44 diff --git a/SPMeta2/SPMeta2.Containers.O365v16/O365v16ProvisionRunner.cs b/SPMeta2/SPMeta2.Containers.O365v16/O365v16ProvisionRunner.cs index a9cdee267..0c55f241a 100644 --- a/SPMeta2/SPMeta2.Containers.O365v16/O365v16ProvisionRunner.cs +++ b/SPMeta2/SPMeta2.Containers.O365v16/O365v16ProvisionRunner.cs @@ -261,7 +261,6 @@ private void WithO365Context(string siteUrl, string userName, string userPasswor } } - #endregion } } diff --git a/SPMeta2/SPMeta2.Containers.O365v16/SPMeta2.Containers.O365v16.csproj b/SPMeta2/SPMeta2.Containers.O365v16/SPMeta2.Containers.O365v16.csproj index 09de2dc46..d68ed3707 100644 --- a/SPMeta2/SPMeta2.Containers.O365v16/SPMeta2.Containers.O365v16.csproj +++ b/SPMeta2/SPMeta2.Containers.O365v16/SPMeta2.Containers.O365v16.csproj @@ -119,28 +119,12 @@ False ..\SPMeta2.Dependencies\SharePoint\O365 - 16.1.5715.1200\NET45\Microsoft.SharePoint.Client.WorkflowServices.dll - - False + ..\SPMeta2.CSOM\bin\Debug45-365\SPMeta2.CSOM.dll - - False + ..\SPMeta2.CSOM.Standard\bin\Debug45-365\SPMeta2.CSOM.Standard.dll - - - True - ..\SPMeta2.CSOM\bin\Debug\SPMeta2.CSOM.dll - False - - - - True - ..\SPMeta2.CSOM\bin\Debug\SPMeta2.CSOM.Standard.dll - False - - - diff --git a/SPMeta2/SPMeta2.Regression.Tests/Base/SPMeta2RegresionTestBase.cs b/SPMeta2/SPMeta2.Regression.Tests/Base/SPMeta2RegresionTestBase.cs index 057fdfcaf..a8350c568 100644 --- a/SPMeta2/SPMeta2.Regression.Tests/Base/SPMeta2RegresionTestBase.cs +++ b/SPMeta2/SPMeta2.Regression.Tests/Base/SPMeta2RegresionTestBase.cs @@ -42,10 +42,15 @@ static SPMeta2RegresionTestCoreBase() AppDomain.CurrentDomain.AssemblyResolve += CurrentDomain_AssemblyResolve; } + private static string GetFullPath(string path) + { + return Path.GetFullPath(path); + } + static Assembly CurrentDomain_AssemblyResolve(object sender, ResolveEventArgs args) { var m2runner = Environment.GetEnvironmentVariable("SPMeta2_RunnerLibraries", EnvironmentVariableTarget.Machine); - var baseDir = AppDomain.CurrentDomain.BaseDirectory; + var baseDir = Path.GetFullPath(AppDomain.CurrentDomain.BaseDirectory); RegressionUtils.WriteLine(string.Format("Resolving custom assembly binding for m2 runner:[{0}]", m2runner)); @@ -81,11 +86,24 @@ static Assembly CurrentDomain_AssemblyResolve(object sender, ResolveEventArgs ar { assemblyDirs.Add(Path.Combine(baseDir, @"_Dependencies\spmeta2-csom-365")); assemblyDirs.Add(Path.Combine(baseDir, @"_Dependencies\spmeta2-csom-regression-365")); + + assemblyDirs.Add(Path.Combine(baseDir, @"_Dependencies\spmeta2-csom-regression-365")); + assemblyDirs.Add(Path.Combine(baseDir, @"_Dependencies\spmeta2-csom-regression-365")); + + // VS sometimes does not coipy these accorss + // referencing straight to the solution + assemblyDirs.Add(GetFullPath(Path.Combine(baseDir, @"..\..\..\SPMeta2.CSOM.Standard\bin\Debug45-365\"))); + assemblyDirs.Add(GetFullPath(Path.Combine(baseDir, @"..\..\..\SPMeta2.CSOM\bin\Debug45-365\"))); + + assemblyDirs.Add(GetFullPath(Path.Combine(baseDir, @"..\..\..\SPMeta2.Regression.CSOM\bin\Debug45-365\"))); + assemblyDirs.Add(GetFullPath(Path.Combine(baseDir, @"..\..\..\SPMeta2.Regression.CSOM.Standard\bin\Debug45-365\"))); } if (m2runner == "SPMeta2.Containers.O365.dll") + { assemblyDirs.Add(Path.Combine(baseDir, @"_Dependencies\spmeta2-csom-2013")); - assemblyDirs.Add(Path.Combine(baseDir, @"_Dependencies\spmeta2-csom-regression-2013")); + assemblyDirs.Add(Path.Combine(baseDir, @"_Dependencies\spmeta2-csom-regression-2013")); + } if (m2runner == "SPMeta2.Containers.CSOM.dll") { diff --git a/SPMeta2/SPMeta2.Regression.Tests/SPMeta2.Containers.O365.dll.config b/SPMeta2/SPMeta2.Regression.Tests/SPMeta2.Containers.O365.dll.config deleted file mode 100644 index 0a80f5c35..000000000 --- a/SPMeta2/SPMeta2.Regression.Tests/SPMeta2.Containers.O365.dll.config +++ /dev/null @@ -1,65 +0,0 @@ - - - - \ No newline at end of file diff --git a/SPMeta2/SPMeta2.Regression.Tests/SPMeta2.Regression.Tests.csproj b/SPMeta2/SPMeta2.Regression.Tests/SPMeta2.Regression.Tests.csproj index 423dd6f01..16d36594f 100644 --- a/SPMeta2/SPMeta2.Regression.Tests/SPMeta2.Regression.Tests.csproj +++ b/SPMeta2/SPMeta2.Regression.Tests/SPMeta2.Regression.Tests.csproj @@ -355,9 +355,8 @@ SPMeta2.Containers.CSOM.dll - Always - + SPMeta2.Containers.O365v16.dll Always @@ -541,18 +540,6 @@ _Dependencies\spmeta2-csom-regression-2013\SPMeta2.Regression.CSOM.dll Always - - SPMeta2.Regression.SSOM.Standard.dll - Always - - - SPMeta2.Regression.SSOM.dll - Always - - - SPMeta2.SSOM.Standard.dll - Always - SPMeta2.SSOM.dll Always @@ -589,9 +576,6 @@ - - Always - Always From cb25f4441eb07c91a6f408d3f8104ef644feb31f Mon Sep 17 00:00:00 2001 From: SubPointSupport Date: Sat, 8 Apr 2017 09:56:17 -0700 Subject: [PATCH 02/16] + O365 API regression - Nested terms provision fails #995 + O365 API regression - TermSet not found #994 + O365 API regression - Taxonomy Group provision fails #959 + Simplify SPMeta2 regression testing setup #800 --- SPMeta2.sln | 76 +++ SPMeta2/Regression/Properties/AssemblyInfo.cs | 36 ++ SPMeta2/Regression/Regression.csproj | 60 ++ SPMeta2/Regression/_helpers.ps1 | 147 +++++ SPMeta2/Regression/_ut_bootstrap_psmodule.ps1 | 6 + SPMeta2/Regression/_ut_grid_dsc_modules.ps1 | 44 ++ .../_ut_grid_dsc_spmeta2_webapp.ps1 | 117 ++++ .../_ut_grid_dsc_spmeta2_webapp_unittests.ps1 | 290 ++++++++++ SPMeta2/Regression/config.yaml | 65 +++ .../Taxonomy/TaxonomyGroupModelHandler.cs | 485 +++++++++------- .../Taxonomy/TaxonomyTermLabelModelHandler.cs | 250 ++++---- .../Taxonomy/TaxonomyTermModelHandler.cs | 125 +++- .../Taxonomy/TaxonomyTermSetModelHandler.cs | 495 +++++++++------- .../Taxonomy/TaxonomyTermStoreModelHandler.cs | 350 ++++++------ .../DefaultClientRuntimeContextService.cs | 8 + .../O365v16ProvisionRunner.cs | 8 + .../Services/RegressionTestService.cs | 4 + .../ClientTaxonomyGroupDefinitionValidator.cs | 130 ++--- .../ClientTaxonomyTermDefinitionValidator.cs | 364 ++++++------ ...entTaxonomyTermLabelDefinitionValidator.cs | 11 +- ...lientTaxonomyTermSetDefinitionValidator.cs | 8 +- .../SSOM/SSOMListViewLookupServiceTests.cs | 4 + .../Base/SPMeta2RegresionTestBase.cs | 22 +- .../Base/SPMeta2RegresionTestVeryBase.cs | 34 ++ .../Impl/Random/RandomDefinitionTest.cs | 2 +- .../Base/SPMeta2RegresionScenarioTestBase.cs | 2 +- .../Scenarios/FarmSolutionScenariosTest.cs | 2 +- .../Impl/Scenarios/TaxonomyScenariousTest.cs | 4 +- .../100 - Ensure M2 Web Application.ps1 | 13 - .../1000 - Internal.CheckContentTypeSetup.ps1 | 129 ----- .../200 - Configure M2 Test Environment.ps1 | 17 - .../PSScripts/300 - Configure M2 Grid.ps1 | 97 ---- .../PSScripts/_config.ps1 | 120 ---- .../PSScripts/_sys.common.ps1 | 535 ------------------ .../SPMeta2.Regression.Tests.csproj | 19 +- .../SPMeta2.Regression.Tests.dll.config | 6 +- .../SPMeta2/ModelHandlers/ModelHandlerBase.cs | 239 ++++---- SPMeta2/SPMeta2/SPMeta2.csproj | 2 + SPMeta2/SPMeta2/ServiceContainer.cs | 2 + .../Services/Impl/DefaultTryRetryService.cs | 75 +++ .../Services/Impl/TraceSourceService.cs | 10 +- .../SPMeta2/Services/TryRetryServiceBase.cs | 24 + 42 files changed, 2459 insertions(+), 1978 deletions(-) create mode 100644 SPMeta2/Regression/Properties/AssemblyInfo.cs create mode 100644 SPMeta2/Regression/Regression.csproj create mode 100644 SPMeta2/Regression/_helpers.ps1 create mode 100644 SPMeta2/Regression/_ut_bootstrap_psmodule.ps1 create mode 100644 SPMeta2/Regression/_ut_grid_dsc_modules.ps1 create mode 100644 SPMeta2/Regression/_ut_grid_dsc_spmeta2_webapp.ps1 create mode 100644 SPMeta2/Regression/_ut_grid_dsc_spmeta2_webapp_unittests.ps1 create mode 100644 SPMeta2/Regression/config.yaml create mode 100644 SPMeta2/SPMeta2.Regression.Tests/Base/SPMeta2RegresionTestVeryBase.cs delete mode 100644 SPMeta2/SPMeta2.Regression.Tests/PSScripts/100 - Ensure M2 Web Application.ps1 delete mode 100644 SPMeta2/SPMeta2.Regression.Tests/PSScripts/1000 - Internal.CheckContentTypeSetup.ps1 delete mode 100644 SPMeta2/SPMeta2.Regression.Tests/PSScripts/200 - Configure M2 Test Environment.ps1 delete mode 100644 SPMeta2/SPMeta2.Regression.Tests/PSScripts/300 - Configure M2 Grid.ps1 delete mode 100644 SPMeta2/SPMeta2.Regression.Tests/PSScripts/_config.ps1 delete mode 100644 SPMeta2/SPMeta2.Regression.Tests/PSScripts/_sys.common.ps1 create mode 100644 SPMeta2/SPMeta2/Services/Impl/DefaultTryRetryService.cs create mode 100644 SPMeta2/SPMeta2/Services/TryRetryServiceBase.cs diff --git a/SPMeta2.sln b/SPMeta2.sln index f26be87a4..cec2eae20 100644 --- a/SPMeta2.sln +++ b/SPMeta2.sln @@ -121,11 +121,14 @@ Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "SPMeta2.Nintex.CSOM", "SPMe EndProject Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "SPMeta2.Nintex.SSOM", "SPMeta2\SPMeta2.Nintex.SSOM\SPMeta2.Nintex.SSOM.csproj", "{788D7D6E-5347-4D09-BFF8-E83AD7CA1FD3}" EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Regression", "SPMeta2\Regression\Regression.csproj", "{593FFE45-EFCC-43DC-8AA2-27236DD6160D}" +EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution Debug|Any CPU = Debug|Any CPU Debug40|Any CPU = Debug40|Any CPU Debug45|Any CPU = Debug45|Any CPU + Release|Any CPU = Release|Any CPU EndGlobalSection GlobalSection(ProjectConfigurationPlatforms) = postSolution {A3A48F9F-1424-41CD-BF92-49D509C715CE}.Debug|Any CPU.ActiveCfg = Debug|Any CPU @@ -133,124 +136,166 @@ Global {A3A48F9F-1424-41CD-BF92-49D509C715CE}.Debug40|Any CPU.Build.0 = Debug40|Any CPU {A3A48F9F-1424-41CD-BF92-49D509C715CE}.Debug45|Any CPU.ActiveCfg = Debug45|Any CPU {A3A48F9F-1424-41CD-BF92-49D509C715CE}.Debug45|Any CPU.Build.0 = Debug45|Any CPU + {A3A48F9F-1424-41CD-BF92-49D509C715CE}.Release|Any CPU.ActiveCfg = Release|Any CPU + {A3A48F9F-1424-41CD-BF92-49D509C715CE}.Release|Any CPU.Build.0 = Release|Any CPU {EE49D3FD-6180-40E6-829F-6831FF89DAC6}.Debug|Any CPU.ActiveCfg = Debug|Any CPU {EE49D3FD-6180-40E6-829F-6831FF89DAC6}.Debug|Any CPU.Build.0 = Debug|Any CPU {EE49D3FD-6180-40E6-829F-6831FF89DAC6}.Debug40|Any CPU.ActiveCfg = Debug40|Any CPU {EE49D3FD-6180-40E6-829F-6831FF89DAC6}.Debug40|Any CPU.Build.0 = Debug40|Any CPU {EE49D3FD-6180-40E6-829F-6831FF89DAC6}.Debug45|Any CPU.ActiveCfg = Debug45|Any CPU {EE49D3FD-6180-40E6-829F-6831FF89DAC6}.Debug45|Any CPU.Build.0 = Debug45|Any CPU + {EE49D3FD-6180-40E6-829F-6831FF89DAC6}.Release|Any CPU.ActiveCfg = Debug35|Any CPU + {EE49D3FD-6180-40E6-829F-6831FF89DAC6}.Release|Any CPU.Build.0 = Debug35|Any CPU {6F7EBF0C-7124-44D6-B9EC-302A54A19FE4}.Debug|Any CPU.ActiveCfg = Debug|Any CPU {6F7EBF0C-7124-44D6-B9EC-302A54A19FE4}.Debug|Any CPU.Build.0 = Debug|Any CPU {6F7EBF0C-7124-44D6-B9EC-302A54A19FE4}.Debug40|Any CPU.ActiveCfg = Debug40|Any CPU {6F7EBF0C-7124-44D6-B9EC-302A54A19FE4}.Debug40|Any CPU.Build.0 = Debug40|Any CPU {6F7EBF0C-7124-44D6-B9EC-302A54A19FE4}.Debug45|Any CPU.ActiveCfg = Debug45|Any CPU {6F7EBF0C-7124-44D6-B9EC-302A54A19FE4}.Debug45|Any CPU.Build.0 = Debug45|Any CPU + {6F7EBF0C-7124-44D6-B9EC-302A54A19FE4}.Release|Any CPU.ActiveCfg = Debug35|Any CPU + {6F7EBF0C-7124-44D6-B9EC-302A54A19FE4}.Release|Any CPU.Build.0 = Debug35|Any CPU {5E592EAA-E21F-4BF4-8EDF-6F6452DC916A}.Debug|Any CPU.ActiveCfg = Debug|Any CPU {5E592EAA-E21F-4BF4-8EDF-6F6452DC916A}.Debug|Any CPU.Build.0 = Debug|Any CPU {5E592EAA-E21F-4BF4-8EDF-6F6452DC916A}.Debug40|Any CPU.ActiveCfg = Debug40|Any CPU {5E592EAA-E21F-4BF4-8EDF-6F6452DC916A}.Debug40|Any CPU.Build.0 = Debug40|Any CPU {5E592EAA-E21F-4BF4-8EDF-6F6452DC916A}.Debug45|Any CPU.ActiveCfg = Debug45|Any CPU {5E592EAA-E21F-4BF4-8EDF-6F6452DC916A}.Debug45|Any CPU.Build.0 = Debug45|Any CPU + {5E592EAA-E21F-4BF4-8EDF-6F6452DC916A}.Release|Any CPU.ActiveCfg = Debug35|Any CPU + {5E592EAA-E21F-4BF4-8EDF-6F6452DC916A}.Release|Any CPU.Build.0 = Debug35|Any CPU {4C4A0044-FBE1-46D8-B8DB-EB579831CDB6}.Debug|Any CPU.ActiveCfg = Debug|Any CPU {4C4A0044-FBE1-46D8-B8DB-EB579831CDB6}.Debug|Any CPU.Build.0 = Debug|Any CPU {4C4A0044-FBE1-46D8-B8DB-EB579831CDB6}.Debug40|Any CPU.ActiveCfg = Debug40|Any CPU {4C4A0044-FBE1-46D8-B8DB-EB579831CDB6}.Debug40|Any CPU.Build.0 = Debug40|Any CPU {4C4A0044-FBE1-46D8-B8DB-EB579831CDB6}.Debug45|Any CPU.ActiveCfg = Debug45|Any CPU {4C4A0044-FBE1-46D8-B8DB-EB579831CDB6}.Debug45|Any CPU.Build.0 = Debug45|Any CPU + {4C4A0044-FBE1-46D8-B8DB-EB579831CDB6}.Release|Any CPU.ActiveCfg = Release|Any CPU + {4C4A0044-FBE1-46D8-B8DB-EB579831CDB6}.Release|Any CPU.Build.0 = Release|Any CPU {FBD78AC1-B766-4332-A9B1-C73EE64FD5C6}.Debug|Any CPU.ActiveCfg = Debug|Any CPU {FBD78AC1-B766-4332-A9B1-C73EE64FD5C6}.Debug|Any CPU.Build.0 = Debug|Any CPU {FBD78AC1-B766-4332-A9B1-C73EE64FD5C6}.Debug40|Any CPU.ActiveCfg = Debug40|Any CPU {FBD78AC1-B766-4332-A9B1-C73EE64FD5C6}.Debug40|Any CPU.Build.0 = Debug40|Any CPU {FBD78AC1-B766-4332-A9B1-C73EE64FD5C6}.Debug45|Any CPU.ActiveCfg = Debug45|Any CPU {FBD78AC1-B766-4332-A9B1-C73EE64FD5C6}.Debug45|Any CPU.Build.0 = Debug45|Any CPU + {FBD78AC1-B766-4332-A9B1-C73EE64FD5C6}.Release|Any CPU.ActiveCfg = Debug35|Any CPU + {FBD78AC1-B766-4332-A9B1-C73EE64FD5C6}.Release|Any CPU.Build.0 = Debug35|Any CPU {2DA71A5B-C039-4A2E-9985-91D6501F293C}.Debug|Any CPU.ActiveCfg = Debug|Any CPU {2DA71A5B-C039-4A2E-9985-91D6501F293C}.Debug|Any CPU.Build.0 = Debug|Any CPU {2DA71A5B-C039-4A2E-9985-91D6501F293C}.Debug40|Any CPU.ActiveCfg = Debug40|Any CPU {2DA71A5B-C039-4A2E-9985-91D6501F293C}.Debug40|Any CPU.Build.0 = Debug40|Any CPU {2DA71A5B-C039-4A2E-9985-91D6501F293C}.Debug45|Any CPU.ActiveCfg = Debug45|Any CPU {2DA71A5B-C039-4A2E-9985-91D6501F293C}.Debug45|Any CPU.Build.0 = Debug45|Any CPU + {2DA71A5B-C039-4A2E-9985-91D6501F293C}.Release|Any CPU.ActiveCfg = Release|Any CPU + {2DA71A5B-C039-4A2E-9985-91D6501F293C}.Release|Any CPU.Build.0 = Release|Any CPU {5A1B98BF-4EA4-4DEE-988F-FA62EEFC9EB0}.Debug|Any CPU.ActiveCfg = Debug|Any CPU {5A1B98BF-4EA4-4DEE-988F-FA62EEFC9EB0}.Debug|Any CPU.Build.0 = Debug|Any CPU {5A1B98BF-4EA4-4DEE-988F-FA62EEFC9EB0}.Debug40|Any CPU.ActiveCfg = Debug45|Any CPU {5A1B98BF-4EA4-4DEE-988F-FA62EEFC9EB0}.Debug40|Any CPU.Build.0 = Debug45|Any CPU {5A1B98BF-4EA4-4DEE-988F-FA62EEFC9EB0}.Debug45|Any CPU.ActiveCfg = Debug45|Any CPU {5A1B98BF-4EA4-4DEE-988F-FA62EEFC9EB0}.Debug45|Any CPU.Build.0 = Debug45|Any CPU + {5A1B98BF-4EA4-4DEE-988F-FA62EEFC9EB0}.Release|Any CPU.ActiveCfg = Debug45|Any CPU + {5A1B98BF-4EA4-4DEE-988F-FA62EEFC9EB0}.Release|Any CPU.Build.0 = Debug45|Any CPU {00E1581F-31D9-493E-AD16-C188AE966458}.Debug|Any CPU.ActiveCfg = Debug|Any CPU {00E1581F-31D9-493E-AD16-C188AE966458}.Debug|Any CPU.Build.0 = Debug|Any CPU {00E1581F-31D9-493E-AD16-C188AE966458}.Debug40|Any CPU.ActiveCfg = Debug40|Any CPU {00E1581F-31D9-493E-AD16-C188AE966458}.Debug40|Any CPU.Build.0 = Debug40|Any CPU {00E1581F-31D9-493E-AD16-C188AE966458}.Debug45|Any CPU.ActiveCfg = Debug45|Any CPU {00E1581F-31D9-493E-AD16-C188AE966458}.Debug45|Any CPU.Build.0 = Debug45|Any CPU + {00E1581F-31D9-493E-AD16-C188AE966458}.Release|Any CPU.ActiveCfg = Release|Any CPU + {00E1581F-31D9-493E-AD16-C188AE966458}.Release|Any CPU.Build.0 = Release|Any CPU {7D095A0D-0BDE-446D-8093-13E5685F1D3C}.Debug|Any CPU.ActiveCfg = Debug|Any CPU {7D095A0D-0BDE-446D-8093-13E5685F1D3C}.Debug|Any CPU.Build.0 = Debug|Any CPU {7D095A0D-0BDE-446D-8093-13E5685F1D3C}.Debug40|Any CPU.ActiveCfg = Debug40|Any CPU {7D095A0D-0BDE-446D-8093-13E5685F1D3C}.Debug40|Any CPU.Build.0 = Debug40|Any CPU {7D095A0D-0BDE-446D-8093-13E5685F1D3C}.Debug45|Any CPU.ActiveCfg = Debug45|Any CPU {7D095A0D-0BDE-446D-8093-13E5685F1D3C}.Debug45|Any CPU.Build.0 = Debug45|Any CPU + {7D095A0D-0BDE-446D-8093-13E5685F1D3C}.Release|Any CPU.ActiveCfg = Debug35|Any CPU + {7D095A0D-0BDE-446D-8093-13E5685F1D3C}.Release|Any CPU.Build.0 = Debug35|Any CPU {D81AE83A-BEEF-4099-B354-0B88D7396B25}.Debug|Any CPU.ActiveCfg = Debug|Any CPU {D81AE83A-BEEF-4099-B354-0B88D7396B25}.Debug|Any CPU.Build.0 = Debug|Any CPU {D81AE83A-BEEF-4099-B354-0B88D7396B25}.Debug40|Any CPU.ActiveCfg = Debug40|Any CPU {D81AE83A-BEEF-4099-B354-0B88D7396B25}.Debug40|Any CPU.Build.0 = Debug40|Any CPU {D81AE83A-BEEF-4099-B354-0B88D7396B25}.Debug45|Any CPU.ActiveCfg = Debug45|Any CPU {D81AE83A-BEEF-4099-B354-0B88D7396B25}.Debug45|Any CPU.Build.0 = Debug45|Any CPU + {D81AE83A-BEEF-4099-B354-0B88D7396B25}.Release|Any CPU.ActiveCfg = Release|Any CPU + {D81AE83A-BEEF-4099-B354-0B88D7396B25}.Release|Any CPU.Build.0 = Release|Any CPU {33B40E92-C649-41FC-B774-53D259801B3B}.Debug|Any CPU.ActiveCfg = Debug|Any CPU {33B40E92-C649-41FC-B774-53D259801B3B}.Debug|Any CPU.Build.0 = Debug|Any CPU {33B40E92-C649-41FC-B774-53D259801B3B}.Debug40|Any CPU.ActiveCfg = Debug40|Any CPU {33B40E92-C649-41FC-B774-53D259801B3B}.Debug40|Any CPU.Build.0 = Debug40|Any CPU {33B40E92-C649-41FC-B774-53D259801B3B}.Debug45|Any CPU.ActiveCfg = Debug45|Any CPU {33B40E92-C649-41FC-B774-53D259801B3B}.Debug45|Any CPU.Build.0 = Debug45|Any CPU + {33B40E92-C649-41FC-B774-53D259801B3B}.Release|Any CPU.ActiveCfg = Release|Any CPU + {33B40E92-C649-41FC-B774-53D259801B3B}.Release|Any CPU.Build.0 = Release|Any CPU {091C48FB-27E3-4F84-897C-5DE7BB55A2D3}.Debug|Any CPU.ActiveCfg = Debug|Any CPU {091C48FB-27E3-4F84-897C-5DE7BB55A2D3}.Debug|Any CPU.Build.0 = Debug|Any CPU {091C48FB-27E3-4F84-897C-5DE7BB55A2D3}.Debug40|Any CPU.ActiveCfg = Debug40|Any CPU {091C48FB-27E3-4F84-897C-5DE7BB55A2D3}.Debug40|Any CPU.Build.0 = Debug40|Any CPU {091C48FB-27E3-4F84-897C-5DE7BB55A2D3}.Debug45|Any CPU.ActiveCfg = Debug45|Any CPU {091C48FB-27E3-4F84-897C-5DE7BB55A2D3}.Debug45|Any CPU.Build.0 = Debug45|Any CPU + {091C48FB-27E3-4F84-897C-5DE7BB55A2D3}.Release|Any CPU.ActiveCfg = Release|Any CPU + {091C48FB-27E3-4F84-897C-5DE7BB55A2D3}.Release|Any CPU.Build.0 = Release|Any CPU {5793019F-7514-4B1F-B31D-A5E472FD034D}.Debug|Any CPU.ActiveCfg = Debug|Any CPU {5793019F-7514-4B1F-B31D-A5E472FD034D}.Debug|Any CPU.Build.0 = Debug|Any CPU {5793019F-7514-4B1F-B31D-A5E472FD034D}.Debug40|Any CPU.ActiveCfg = Debug40|Any CPU {5793019F-7514-4B1F-B31D-A5E472FD034D}.Debug40|Any CPU.Build.0 = Debug40|Any CPU {5793019F-7514-4B1F-B31D-A5E472FD034D}.Debug45|Any CPU.ActiveCfg = Debug45|Any CPU {5793019F-7514-4B1F-B31D-A5E472FD034D}.Debug45|Any CPU.Build.0 = Debug45|Any CPU + {5793019F-7514-4B1F-B31D-A5E472FD034D}.Release|Any CPU.ActiveCfg = Release|Any CPU + {5793019F-7514-4B1F-B31D-A5E472FD034D}.Release|Any CPU.Build.0 = Release|Any CPU {F310878E-9B72-4C3C-AE5D-C60B3515E2FC}.Debug|Any CPU.ActiveCfg = Debug|Any CPU {F310878E-9B72-4C3C-AE5D-C60B3515E2FC}.Debug|Any CPU.Build.0 = Debug|Any CPU {F310878E-9B72-4C3C-AE5D-C60B3515E2FC}.Debug40|Any CPU.ActiveCfg = Debug40|Any CPU {F310878E-9B72-4C3C-AE5D-C60B3515E2FC}.Debug40|Any CPU.Build.0 = Debug40|Any CPU {F310878E-9B72-4C3C-AE5D-C60B3515E2FC}.Debug45|Any CPU.ActiveCfg = Debug45|Any CPU {F310878E-9B72-4C3C-AE5D-C60B3515E2FC}.Debug45|Any CPU.Build.0 = Debug45|Any CPU + {F310878E-9B72-4C3C-AE5D-C60B3515E2FC}.Release|Any CPU.ActiveCfg = Release|Any CPU + {F310878E-9B72-4C3C-AE5D-C60B3515E2FC}.Release|Any CPU.Build.0 = Release|Any CPU {2A8F08ED-E837-4E91-8E49-B5F30CF9EEF3}.Debug|Any CPU.ActiveCfg = Debug|Any CPU {2A8F08ED-E837-4E91-8E49-B5F30CF9EEF3}.Debug|Any CPU.Build.0 = Debug|Any CPU {2A8F08ED-E837-4E91-8E49-B5F30CF9EEF3}.Debug40|Any CPU.ActiveCfg = Debug40|Any CPU {2A8F08ED-E837-4E91-8E49-B5F30CF9EEF3}.Debug40|Any CPU.Build.0 = Debug40|Any CPU {2A8F08ED-E837-4E91-8E49-B5F30CF9EEF3}.Debug45|Any CPU.ActiveCfg = Debug45|Any CPU {2A8F08ED-E837-4E91-8E49-B5F30CF9EEF3}.Debug45|Any CPU.Build.0 = Debug45|Any CPU + {2A8F08ED-E837-4E91-8E49-B5F30CF9EEF3}.Release|Any CPU.ActiveCfg = Release|Any CPU + {2A8F08ED-E837-4E91-8E49-B5F30CF9EEF3}.Release|Any CPU.Build.0 = Release|Any CPU {8B199151-24BC-4C32-B69F-7371B37F33D4}.Debug|Any CPU.ActiveCfg = Debug|Any CPU {8B199151-24BC-4C32-B69F-7371B37F33D4}.Debug|Any CPU.Build.0 = Debug|Any CPU {8B199151-24BC-4C32-B69F-7371B37F33D4}.Debug40|Any CPU.ActiveCfg = Debug40|Any CPU {8B199151-24BC-4C32-B69F-7371B37F33D4}.Debug40|Any CPU.Build.0 = Debug40|Any CPU {8B199151-24BC-4C32-B69F-7371B37F33D4}.Debug45|Any CPU.ActiveCfg = Debug45|Any CPU {8B199151-24BC-4C32-B69F-7371B37F33D4}.Debug45|Any CPU.Build.0 = Debug45|Any CPU + {8B199151-24BC-4C32-B69F-7371B37F33D4}.Release|Any CPU.ActiveCfg = Release|Any CPU + {8B199151-24BC-4C32-B69F-7371B37F33D4}.Release|Any CPU.Build.0 = Release|Any CPU {04EF5903-B379-4404-8DBC-B21ABE0D1099}.Debug|Any CPU.ActiveCfg = Debug|Any CPU {04EF5903-B379-4404-8DBC-B21ABE0D1099}.Debug|Any CPU.Build.0 = Debug|Any CPU {04EF5903-B379-4404-8DBC-B21ABE0D1099}.Debug40|Any CPU.ActiveCfg = Debug40|Any CPU {04EF5903-B379-4404-8DBC-B21ABE0D1099}.Debug40|Any CPU.Build.0 = Debug40|Any CPU {04EF5903-B379-4404-8DBC-B21ABE0D1099}.Debug45|Any CPU.ActiveCfg = Debug45|Any CPU {04EF5903-B379-4404-8DBC-B21ABE0D1099}.Debug45|Any CPU.Build.0 = Debug45|Any CPU + {04EF5903-B379-4404-8DBC-B21ABE0D1099}.Release|Any CPU.ActiveCfg = Release|Any CPU + {04EF5903-B379-4404-8DBC-B21ABE0D1099}.Release|Any CPU.Build.0 = Release|Any CPU {E9274D1F-BF08-44CB-9162-35110379D5C0}.Debug|Any CPU.ActiveCfg = Debug|Any CPU {E9274D1F-BF08-44CB-9162-35110379D5C0}.Debug40|Any CPU.ActiveCfg = Debug40|Any CPU {E9274D1F-BF08-44CB-9162-35110379D5C0}.Debug40|Any CPU.Build.0 = Debug40|Any CPU {E9274D1F-BF08-44CB-9162-35110379D5C0}.Debug45|Any CPU.ActiveCfg = Debug45|Any CPU {E9274D1F-BF08-44CB-9162-35110379D5C0}.Debug45|Any CPU.Build.0 = Debug45|Any CPU + {E9274D1F-BF08-44CB-9162-35110379D5C0}.Release|Any CPU.ActiveCfg = Release|Any CPU + {E9274D1F-BF08-44CB-9162-35110379D5C0}.Release|Any CPU.Build.0 = Release|Any CPU {7B84193A-251E-47F1-BDD0-EDD85918D307}.Debug|Any CPU.ActiveCfg = Debug|Any CPU {7B84193A-251E-47F1-BDD0-EDD85918D307}.Debug40|Any CPU.ActiveCfg = Debug|Any CPU {7B84193A-251E-47F1-BDD0-EDD85918D307}.Debug40|Any CPU.Build.0 = Debug|Any CPU {7B84193A-251E-47F1-BDD0-EDD85918D307}.Debug45|Any CPU.ActiveCfg = Debug|Any CPU {7B84193A-251E-47F1-BDD0-EDD85918D307}.Debug45|Any CPU.Build.0 = Debug|Any CPU + {7B84193A-251E-47F1-BDD0-EDD85918D307}.Release|Any CPU.ActiveCfg = Release|Any CPU + {7B84193A-251E-47F1-BDD0-EDD85918D307}.Release|Any CPU.Build.0 = Release|Any CPU {B556A178-DA0A-4DA0-AF92-2D2504FBCDA9}.Debug|Any CPU.ActiveCfg = Debug|Any CPU {B556A178-DA0A-4DA0-AF92-2D2504FBCDA9}.Debug|Any CPU.Build.0 = Debug|Any CPU {B556A178-DA0A-4DA0-AF92-2D2504FBCDA9}.Debug40|Any CPU.ActiveCfg = Debug|Any CPU {B556A178-DA0A-4DA0-AF92-2D2504FBCDA9}.Debug40|Any CPU.Build.0 = Debug|Any CPU {B556A178-DA0A-4DA0-AF92-2D2504FBCDA9}.Debug45|Any CPU.ActiveCfg = Debug|Any CPU {B556A178-DA0A-4DA0-AF92-2D2504FBCDA9}.Debug45|Any CPU.Build.0 = Debug|Any CPU + {B556A178-DA0A-4DA0-AF92-2D2504FBCDA9}.Release|Any CPU.ActiveCfg = Release|Any CPU + {B556A178-DA0A-4DA0-AF92-2D2504FBCDA9}.Release|Any CPU.Build.0 = Release|Any CPU {A88390A8-20F2-4247-A9C3-28480FEAEFA6}.Debug|Any CPU.ActiveCfg = Debug|Any CPU {A88390A8-20F2-4247-A9C3-28480FEAEFA6}.Debug40|Any CPU.ActiveCfg = Debug|Any CPU {A88390A8-20F2-4247-A9C3-28480FEAEFA6}.Debug40|Any CPU.Build.0 = Debug|Any CPU @@ -258,6 +303,9 @@ Global {A88390A8-20F2-4247-A9C3-28480FEAEFA6}.Debug45|Any CPU.ActiveCfg = Debug|Any CPU {A88390A8-20F2-4247-A9C3-28480FEAEFA6}.Debug45|Any CPU.Build.0 = Debug|Any CPU {A88390A8-20F2-4247-A9C3-28480FEAEFA6}.Debug45|Any CPU.Deploy.0 = Debug|Any CPU + {A88390A8-20F2-4247-A9C3-28480FEAEFA6}.Release|Any CPU.ActiveCfg = Release|Any CPU + {A88390A8-20F2-4247-A9C3-28480FEAEFA6}.Release|Any CPU.Build.0 = Release|Any CPU + {A88390A8-20F2-4247-A9C3-28480FEAEFA6}.Release|Any CPU.Deploy.0 = Release|Any CPU {16A7F927-A570-4EB0-90E6-887E676AF42B}.Debug|Any CPU.ActiveCfg = Debug|Any CPU {16A7F927-A570-4EB0-90E6-887E676AF42B}.Debug40|Any CPU.ActiveCfg = Debug|Any CPU {16A7F927-A570-4EB0-90E6-887E676AF42B}.Debug40|Any CPU.Build.0 = Debug|Any CPU @@ -265,11 +313,16 @@ Global {16A7F927-A570-4EB0-90E6-887E676AF42B}.Debug45|Any CPU.ActiveCfg = Debug|Any CPU {16A7F927-A570-4EB0-90E6-887E676AF42B}.Debug45|Any CPU.Build.0 = Debug|Any CPU {16A7F927-A570-4EB0-90E6-887E676AF42B}.Debug45|Any CPU.Deploy.0 = Debug|Any CPU + {16A7F927-A570-4EB0-90E6-887E676AF42B}.Release|Any CPU.ActiveCfg = Release|Any CPU + {16A7F927-A570-4EB0-90E6-887E676AF42B}.Release|Any CPU.Build.0 = Release|Any CPU + {16A7F927-A570-4EB0-90E6-887E676AF42B}.Release|Any CPU.Deploy.0 = Release|Any CPU {16E57ADA-0D73-429E-96F7-87EAA03128D9}.Debug|Any CPU.ActiveCfg = Debug|Any CPU {16E57ADA-0D73-429E-96F7-87EAA03128D9}.Debug40|Any CPU.ActiveCfg = Debug|Any CPU {16E57ADA-0D73-429E-96F7-87EAA03128D9}.Debug40|Any CPU.Build.0 = Debug|Any CPU {16E57ADA-0D73-429E-96F7-87EAA03128D9}.Debug45|Any CPU.ActiveCfg = Debug|Any CPU {16E57ADA-0D73-429E-96F7-87EAA03128D9}.Debug45|Any CPU.Build.0 = Debug|Any CPU + {16E57ADA-0D73-429E-96F7-87EAA03128D9}.Release|Any CPU.ActiveCfg = Release|Any CPU + {16E57ADA-0D73-429E-96F7-87EAA03128D9}.Release|Any CPU.Build.0 = Release|Any CPU {2A290D6E-6AF3-4D17-975D-3C393700A0B1}.Debug|Any CPU.ActiveCfg = Debug|Any CPU {2A290D6E-6AF3-4D17-975D-3C393700A0B1}.Debug40|Any CPU.ActiveCfg = Debug|Any CPU {2A290D6E-6AF3-4D17-975D-3C393700A0B1}.Debug40|Any CPU.Build.0 = Debug|Any CPU @@ -277,40 +330,62 @@ Global {2A290D6E-6AF3-4D17-975D-3C393700A0B1}.Debug45|Any CPU.ActiveCfg = Debug|Any CPU {2A290D6E-6AF3-4D17-975D-3C393700A0B1}.Debug45|Any CPU.Build.0 = Debug|Any CPU {2A290D6E-6AF3-4D17-975D-3C393700A0B1}.Debug45|Any CPU.Deploy.0 = Debug|Any CPU + {2A290D6E-6AF3-4D17-975D-3C393700A0B1}.Release|Any CPU.ActiveCfg = Release|Any CPU + {2A290D6E-6AF3-4D17-975D-3C393700A0B1}.Release|Any CPU.Build.0 = Release|Any CPU + {2A290D6E-6AF3-4D17-975D-3C393700A0B1}.Release|Any CPU.Deploy.0 = Release|Any CPU {0DE538C9-1723-46B1-90F8-5DC67C56D7DD}.Debug|Any CPU.ActiveCfg = Debug|Any CPU {0DE538C9-1723-46B1-90F8-5DC67C56D7DD}.Debug|Any CPU.Build.0 = Debug|Any CPU {0DE538C9-1723-46B1-90F8-5DC67C56D7DD}.Debug40|Any CPU.ActiveCfg = Debug|Any CPU {0DE538C9-1723-46B1-90F8-5DC67C56D7DD}.Debug40|Any CPU.Build.0 = Debug|Any CPU {0DE538C9-1723-46B1-90F8-5DC67C56D7DD}.Debug45|Any CPU.ActiveCfg = Debug|Any CPU {0DE538C9-1723-46B1-90F8-5DC67C56D7DD}.Debug45|Any CPU.Build.0 = Debug|Any CPU + {0DE538C9-1723-46B1-90F8-5DC67C56D7DD}.Release|Any CPU.ActiveCfg = Release|Any CPU + {0DE538C9-1723-46B1-90F8-5DC67C56D7DD}.Release|Any CPU.Build.0 = Release|Any CPU {B30F6CA8-3E96-4734-B6B1-A61F201099E4}.Debug|Any CPU.ActiveCfg = Debug|Any CPU {B30F6CA8-3E96-4734-B6B1-A61F201099E4}.Debug40|Any CPU.ActiveCfg = Debug|Any CPU {B30F6CA8-3E96-4734-B6B1-A61F201099E4}.Debug40|Any CPU.Build.0 = Debug|Any CPU {B30F6CA8-3E96-4734-B6B1-A61F201099E4}.Debug45|Any CPU.ActiveCfg = Debug|Any CPU {B30F6CA8-3E96-4734-B6B1-A61F201099E4}.Debug45|Any CPU.Build.0 = Debug|Any CPU + {B30F6CA8-3E96-4734-B6B1-A61F201099E4}.Release|Any CPU.ActiveCfg = Release|Any CPU + {B30F6CA8-3E96-4734-B6B1-A61F201099E4}.Release|Any CPU.Build.0 = Release|Any CPU {B9AD05BB-B576-46B8-89A0-FBC70C438B64}.Debug|Any CPU.ActiveCfg = Debug|Any CPU {B9AD05BB-B576-46B8-89A0-FBC70C438B64}.Debug40|Any CPU.ActiveCfg = Debug|Any CPU {B9AD05BB-B576-46B8-89A0-FBC70C438B64}.Debug40|Any CPU.Build.0 = Debug|Any CPU {B9AD05BB-B576-46B8-89A0-FBC70C438B64}.Debug45|Any CPU.ActiveCfg = Debug|Any CPU {B9AD05BB-B576-46B8-89A0-FBC70C438B64}.Debug45|Any CPU.Build.0 = Debug|Any CPU + {B9AD05BB-B576-46B8-89A0-FBC70C438B64}.Release|Any CPU.ActiveCfg = Release|Any CPU + {B9AD05BB-B576-46B8-89A0-FBC70C438B64}.Release|Any CPU.Build.0 = Release|Any CPU {D19B0907-CED5-416A-9D45-0F112990C234}.Debug|Any CPU.ActiveCfg = Debug|Any CPU {D19B0907-CED5-416A-9D45-0F112990C234}.Debug|Any CPU.Build.0 = Debug|Any CPU {D19B0907-CED5-416A-9D45-0F112990C234}.Debug40|Any CPU.ActiveCfg = Debug|Any CPU {D19B0907-CED5-416A-9D45-0F112990C234}.Debug40|Any CPU.Build.0 = Debug|Any CPU {D19B0907-CED5-416A-9D45-0F112990C234}.Debug45|Any CPU.ActiveCfg = Debug|Any CPU {D19B0907-CED5-416A-9D45-0F112990C234}.Debug45|Any CPU.Build.0 = Debug|Any CPU + {D19B0907-CED5-416A-9D45-0F112990C234}.Release|Any CPU.ActiveCfg = Release|Any CPU + {D19B0907-CED5-416A-9D45-0F112990C234}.Release|Any CPU.Build.0 = Release|Any CPU {588FC30F-1C85-410E-AB20-C9741DB28857}.Debug|Any CPU.ActiveCfg = Debug|Any CPU {588FC30F-1C85-410E-AB20-C9741DB28857}.Debug|Any CPU.Build.0 = Debug|Any CPU {588FC30F-1C85-410E-AB20-C9741DB28857}.Debug40|Any CPU.ActiveCfg = Debug|Any CPU {588FC30F-1C85-410E-AB20-C9741DB28857}.Debug40|Any CPU.Build.0 = Debug|Any CPU {588FC30F-1C85-410E-AB20-C9741DB28857}.Debug45|Any CPU.ActiveCfg = Debug|Any CPU {588FC30F-1C85-410E-AB20-C9741DB28857}.Debug45|Any CPU.Build.0 = Debug|Any CPU + {588FC30F-1C85-410E-AB20-C9741DB28857}.Release|Any CPU.ActiveCfg = Release|Any CPU + {588FC30F-1C85-410E-AB20-C9741DB28857}.Release|Any CPU.Build.0 = Release|Any CPU {788D7D6E-5347-4D09-BFF8-E83AD7CA1FD3}.Debug|Any CPU.ActiveCfg = Debug|Any CPU {788D7D6E-5347-4D09-BFF8-E83AD7CA1FD3}.Debug|Any CPU.Build.0 = Debug|Any CPU {788D7D6E-5347-4D09-BFF8-E83AD7CA1FD3}.Debug40|Any CPU.ActiveCfg = Debug|Any CPU {788D7D6E-5347-4D09-BFF8-E83AD7CA1FD3}.Debug40|Any CPU.Build.0 = Debug|Any CPU {788D7D6E-5347-4D09-BFF8-E83AD7CA1FD3}.Debug45|Any CPU.ActiveCfg = Debug|Any CPU {788D7D6E-5347-4D09-BFF8-E83AD7CA1FD3}.Debug45|Any CPU.Build.0 = Debug|Any CPU + {788D7D6E-5347-4D09-BFF8-E83AD7CA1FD3}.Release|Any CPU.ActiveCfg = Release|Any CPU + {788D7D6E-5347-4D09-BFF8-E83AD7CA1FD3}.Release|Any CPU.Build.0 = Release|Any CPU + {593FFE45-EFCC-43DC-8AA2-27236DD6160D}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {593FFE45-EFCC-43DC-8AA2-27236DD6160D}.Debug40|Any CPU.ActiveCfg = Debug|Any CPU + {593FFE45-EFCC-43DC-8AA2-27236DD6160D}.Debug40|Any CPU.Build.0 = Debug|Any CPU + {593FFE45-EFCC-43DC-8AA2-27236DD6160D}.Debug45|Any CPU.ActiveCfg = Debug|Any CPU + {593FFE45-EFCC-43DC-8AA2-27236DD6160D}.Debug45|Any CPU.Build.0 = Debug|Any CPU + {593FFE45-EFCC-43DC-8AA2-27236DD6160D}.Release|Any CPU.ActiveCfg = Release|Any CPU + {593FFE45-EFCC-43DC-8AA2-27236DD6160D}.Release|Any CPU.Build.0 = Release|Any CPU EndGlobalSection GlobalSection(SolutionProperties) = preSolution HideSolutionNode = FALSE @@ -356,5 +431,6 @@ Global {D19B0907-CED5-416A-9D45-0F112990C234} = {543E02CC-AA4A-4B1F-ABBD-2C88CFAA463C} {588FC30F-1C85-410E-AB20-C9741DB28857} = {543E02CC-AA4A-4B1F-ABBD-2C88CFAA463C} {788D7D6E-5347-4D09-BFF8-E83AD7CA1FD3} = {543E02CC-AA4A-4B1F-ABBD-2C88CFAA463C} + {593FFE45-EFCC-43DC-8AA2-27236DD6160D} = {EE9BD842-2CA9-45B2-AB7C-A8EB0353AAB7} EndGlobalSection EndGlobal diff --git a/SPMeta2/Regression/Properties/AssemblyInfo.cs b/SPMeta2/Regression/Properties/AssemblyInfo.cs new file mode 100644 index 000000000..5e9584207 --- /dev/null +++ b/SPMeta2/Regression/Properties/AssemblyInfo.cs @@ -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("Regression")] +[assembly: AssemblyDescription("")] +[assembly: AssemblyConfiguration("")] +[assembly: AssemblyCompany("")] +[assembly: AssemblyProduct("Regression")] +[assembly: AssemblyCopyright("Copyright © 2017")] +[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("e91860b2-bf5a-4986-8624-4ee1057c7e43")] + +// 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")] diff --git a/SPMeta2/Regression/Regression.csproj b/SPMeta2/Regression/Regression.csproj new file mode 100644 index 000000000..4fc9d415d --- /dev/null +++ b/SPMeta2/Regression/Regression.csproj @@ -0,0 +1,60 @@ + + + + + Debug + AnyCPU + {593FFE45-EFCC-43DC-8AA2-27236DD6160D} + Library + Properties + Regression + Regression + v4.5 + 512 + + + true + full + false + bin\Debug\ + DEBUG;TRACE + prompt + 4 + + + pdbonly + true + bin\Release\ + TRACE + prompt + 4 + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/SPMeta2/Regression/_helpers.ps1 b/SPMeta2/Regression/_helpers.ps1 new file mode 100644 index 000000000..5cbcb1cc9 --- /dev/null +++ b/SPMeta2/Regression/_helpers.ps1 @@ -0,0 +1,147 @@ + + +function Get-RegressionConfig() { + + param ( + [Parameter(Mandatory=$true)] [ValidateNotNullorEmpty()] [string] $yamlFilePath + ) + + $yaml = (Get-Content $yamlFilePath -raw) + $config = ConvertFrom-Yaml $yaml + + return $config +} + +if($dsc_configFilePath -eq $null) { + $dsc_configFilePath = "config.yaml" +} + +$dsc_config = Get-RegressionConfig($dsc_configFilePath) +$env_config = $dsc_config.Configuration.Environment +$regression_config = $dsc_config.Configuration.RegressionTests + +$dsc_nodeNames = $dsc_config.Configuration.DSC.NodeNames + +$dsc_RunAsUserName = $dsc_config.Configuration.DSC.RunAs.UserName +$dsc_RunAsUserPassword = $dsc_config.Configuration.DSC.RunAs.UserPassword + +# from env variable? + + +$dsc_RunAsUserSecurePassword = ConvertTo-SecureString $dsc_RunAsUserPassword -AsPlainText -Force +$dsc_RunAsUserCredentials = New-Object System.Management.Automation.PSCredential ($dsc_RunAsUserName, $dsc_RunAsUserSecurePassword) + +$dsc_WebPoolManagedAccountUserName = $dsc_config.Configuration.DSC.WebPoolManagedAccount.UserName +$dsc_WebPoolManagedAccountUserPassword = $dsc_config.Configuration.DSC.WebPoolManagedAccount.UserPassword +$dsc_WebPoolManagedAccountSecurePassword = ConvertTo-SecureString $dsc_WebPoolManagedAccountUserPassword -AsPlainText -Force +$dsc_WebPoolManagedCredentials = New-Object System.Management.Automation.PSCredential ($dsc_WebPoolManagedAccountUserName, $dsc_WebPoolManagedAccountSecurePassword) + +$dsc_SPSetupAccountAccountUserName = $dsc_config.Configuration.DSC.SPSetupAccount.UserName +$dsc_SPSetupAccountAccountUserPassword = $dsc_config.Configuration.DSC.SPSetupAccount.UserPassword +$dsc_SPSetupAccountSecurePassword = ConvertTo-SecureString $dsc_SPSetupAccountAccountUserPassword -AsPlainText -Force +$dsc_SPSetupAccountCredentials = New-Object System.Management.Automation.PSCredential ($dsc_SPSetupAccountAccountUserName, $dsc_SPSetupAccountSecurePassword) + +function Ensure-PowerShellModule { + + foreach($nodeName in $dsc_nodeNames) { + + $moduleName = "PowerShellModule" + $moduleVersion = 0.3 + + Write-Host "Ensuring module [$moduleName] on node:[$nodeName]" -fore green + + Invoke-Command -ScriptBlock { + + function InstallModule($name, $version) { + + $module = Get-Module -ListAvailable | where-object { $_.Name -eq "PowerShellModule" } + + if($module -ne $null -and $module.Version -eq $version) { + + Write-Host "`tModule exists [$name] [$version]" -fore gray + } else { + + Write-Host "`tInstalling module [$name] [$version]" -fore gray + + Find-Module -Name $name -RequiredVersion $version -Repository PSGallery | Install-Module + Get-DscResource -Module $name + } + } + + InstallModule PowerShellModule 0.3 + + } -ComputerName $nodeName + } + +} + +function Apply-Dsc-Configuration { + + param ( + [Parameter(Mandatory=$true)] [ValidateNotNullorEmpty()] [string] $name, + [Parameter(Mandatory=$true)] [ValidateNotNullorEmpty()] [string[]] $nodeNames, + [Parameter(Mandatory=$false)][object] $config, + [Parameter(Mandatory=$false)][boolean] $isVerbose = $true + ) + + if($config -eq $null) { + $config = @{ + AllNodes = @() + } + } + + + $config.AllNodes[0].RecurseValue = $true + + $config.AllNodes[0].PsDscAllowPlainTextPassword = $true + $config.AllNodes[0].PSDscAllowDomainUser = $true + + Write-Host "Cleaning up DSC config [$name]..." -fore green + Remove-Item $name -Force -Recurse -Confirm:$false -ErrorAction:SilentlyContinue | out-null + + Write-Host "Compiling DSC config [$name] for [$($nodeNames.Count)] nodes..." -fore green + + foreach($nodeName in $nodeNames) { + + Write-Host "`tCompiling DSC config [$name] for node [$nodeName]" -fore Gray + + $config.AllNodes[0].NodeName = $nodeName + + . $name -NodeName $nodeName ` + -RunAsCredential $dsc_RunAsUserCredentials ` + -ConfigurationData $config | out-null + } + + Write-Host "Starting DSC config [$name]..." -fore Green + + if($isVerbose -eq $true) + { + Start-DscConfiguration $name -force ` + -Wait ` + -Verbose + } + else + { + Start-DscConfiguration $name -force ` + -Wait + } + + Write-Host "Testing DSC config [$name]..." -fore Green + $results = Test-DscConfiguration $name + + foreach($result in $results) { + + $node = $result.PSComputerName + $state = $result.InDesiredState + + $color = "Gray" + + if($result.InDesiredState) { + $color = "Gray" + } else { + $color = "Red" + } + + Write-Host "`tNode[$node]`tInDesiredState:[$state]" -fore $color + } +} \ No newline at end of file diff --git a/SPMeta2/Regression/_ut_bootstrap_psmodule.ps1 b/SPMeta2/Regression/_ut_bootstrap_psmodule.ps1 new file mode 100644 index 000000000..f15fcea82 --- /dev/null +++ b/SPMeta2/Regression/_ut_bootstrap_psmodule.ps1 @@ -0,0 +1,6 @@ +cls + +$ScriptDirectory = Split-Path -Path $MyInvocation.MyCommand.Definition -Parent +. "$ScriptDirectory/_helpers.ps1" + +Ensure-PowerShellModule \ No newline at end of file diff --git a/SPMeta2/Regression/_ut_grid_dsc_modules.ps1 b/SPMeta2/Regression/_ut_grid_dsc_modules.ps1 new file mode 100644 index 000000000..4dcd817bb --- /dev/null +++ b/SPMeta2/Regression/_ut_grid_dsc_modules.ps1 @@ -0,0 +1,44 @@ +cls + +$ScriptDirectory = Split-Path -Path $MyInvocation.MyCommand.Definition -Parent +. "$ScriptDirectory/_helpers.ps1" + +configuration SPMeta2_DSCModules { + + param ( + [Parameter(Mandatory=$true)] [ValidateNotNullorEmpty()] [string] $NodeName, + [Parameter(Mandatory=$true)] [ValidateNotNullorEmpty()] [PSCredential] $RunAsCredential + ) + + Import-DscResource -ModuleName PowerShellModule -ModuleVersion 0.3 + + Node $NodeName { + + PSModuleResource SharePointDSC { + + Module_Name = "SharePointDSC" + RequiredVersion = "1.6.0.0" + PsDscRunAsCredential = $RunAsCredential + } + + PSModuleResource PowershellYaml { + + Module_Name = "powershell-yaml" + RequiredVersion = "0.1" + PsDscRunAsCredential = $RunAsCredential + DependsOn = "[PSModuleResource]SharePointDSC" + } + + PSModuleResource PSParallel { + + Module_Name = "PSParallel" + RequiredVersion = "2.2.2" + PsDscRunAsCredential = $RunAsCredential + DependsOn = "[PSModuleResource]PowershellYaml" + } + } +} + +Apply-Dsc-Configuration -name SPMeta2_DSCModules ` + -nodeNames $dsc_nodeNames ` + -isVerbose $true \ No newline at end of file diff --git a/SPMeta2/Regression/_ut_grid_dsc_spmeta2_webapp.ps1 b/SPMeta2/Regression/_ut_grid_dsc_spmeta2_webapp.ps1 new file mode 100644 index 000000000..6a2aaf6f5 --- /dev/null +++ b/SPMeta2/Regression/_ut_grid_dsc_spmeta2_webapp.ps1 @@ -0,0 +1,117 @@ +cls + +$ScriptDirectory = Split-Path -Path $MyInvocation.MyCommand.Definition -Parent +. "$ScriptDirectory/_helpers.ps1" + +Configuration SPMeta2_WebApp +{ + param ( + [Parameter(Mandatory=$true)] [ValidateNotNullorEmpty()] [string] $NodeName, + [Parameter(Mandatory=$true)] [ValidateNotNullorEmpty()] [PSCredential] $RunAsCredential + ) + + Import-DscResource -ModuleName PSDesiredStateConfiguration + Import-DscResource -ModuleName SharePointDsc -ModuleVersion 1.6.0.0 + + $config = $ConfigurationData.AllNodes + + $webApp_Port = $config.WebAppPort + $webApp_isHttps = $config.IsHttps + + $machineName = $NodeName + + if($webApp_isHttps -eq $true) { + $webApp_Url = "https://" + $machineName + } else { + $webApp_Url = "http://" + $machineName + } + + $ensure = 'Present' + + $clean = $config.DeleteWebApplication + + if($clean -eq $true) { + $ensure = 'Absent' + } + + Node $NodeName { + + SPManagedAccount WebAppPoolManagedAccount + { + AccountName = $config.WebPoolManagedAccount.UserName + Account = $config.WebPoolManagedAccount + PsDscRunAsCredential = $config.SPSetupAccount + Ensure = 'Present' + } + + + SPWebApplication WebApp + { + Name = "SPMeta2 Regression Web App - $webApp_Port" + ApplicationPool = "SPMeta2 Regression Web App" + ApplicationPoolAccount = $config.WebPoolManagedAccount.UserName + AllowAnonymous = $false + AuthenticationMethod = "NTLM" + DatabaseName = "SPMeta2_Regression_Content" + Url = $webApp_Url + #HostHeader = "spmeta2.contoso.com" + Port = $webApp_Port + PsDscRunAsCredential = $config.SPSetupAccount + DependsOn = "[SPManagedAccount]WebAppPoolManagedAccount" + Ensure = $ensure + } + + if($ensure -eq 'Present') { + + SPSite RootSite + { + Url = $webApp_Url + ":" + $webApp_Port + OwnerAlias = $config.SPSetupAccount.UserName + Name = "SPMeta2 Regression Root Site" + Template = "STS#0" + PsDscRunAsCredential = $config.SPSetupAccount + DependsOn = "[SPWebApplication]WebApp" + } + + # other site collections + + foreach($url in $config.SiteCollectionUrls) { + + if($url -eq "/") { + continue; + } + + SPSite "SubSite$url" + { + Url = $webApp_Url + ":" + $webApp_Port + $url + OwnerAlias = $config.SPSetupAccount.UserName + Name = "SPMeta2 Regression $url" + Template = "STS#0" + PsDscRunAsCredential = $config.SPSetupAccount + DependsOn = "[SPWebApplication]WebApp" + } + } + } + } +} + +$config = @{ + AllNodes = @( + @{ + WebPoolManagedAccount = $dsc_WebPoolManagedCredentials + SPSetupAccount = $dsc_SPSetupAccountCredentials + + #DeleteWebApplication = $true + + WebAppPort = $env_config.SharePoint.WebApp.Port + + SiteCollectionUrls = $env_config.SharePoint.SiteCollection.Urls + WebUrls = $env_config.SharePoint.Web.Urls + } + ) + } + +Apply-Dsc-Configuration -name SPMeta2_WebApp ` + -nodeNames $dsc_nodeNames ` + -isVerbose $true ` + -config $config diff --git a/SPMeta2/Regression/_ut_grid_dsc_spmeta2_webapp_unittests.ps1 b/SPMeta2/Regression/_ut_grid_dsc_spmeta2_webapp_unittests.ps1 new file mode 100644 index 000000000..1515fe21a --- /dev/null +++ b/SPMeta2/Regression/_ut_grid_dsc_spmeta2_webapp_unittests.ps1 @@ -0,0 +1,290 @@ +cls + +$ScriptDirectory = Split-Path -Path $MyInvocation.MyCommand.Definition -Parent +. "$ScriptDirectory/_helpers.ps1" + +$o365RuntimePath = "$PSScriptRoot\..\..\SPMeta2.Dependencies\SharePoint\SP2013 - 15.0.4420.1017\CSOM" + Write-Host "Loading SharePoint CSOM API" -fore Green + + $files = [System.IO.Directory]::GetFiles($o365RuntimePath, "*.dll") + + foreach($filePath in $files) { + Write-Host "`tLoading assembly: [$filePath]" + $a = [System.Reflection.Assembly]::LoadFile($filePath) + } + +Configuration SPMeta2_UnitTestSettings_Clean +{ + param ( + [Parameter(Mandatory=$true)] [ValidateNotNullorEmpty()] [string] $NodeName, + [Parameter(Mandatory=$true)] [ValidateNotNullorEmpty()] [PSCredential] $RunAsCredential + ) + + $vars = @( + "SPMeta2_CSOM_SiteUrls" + "SPMeta2_CSOM_WebUrls" + + "SPMeta2_SSOM_WebApplicationUrls" + "SPMeta2_SSOM_SiteUrls" + "SPMeta2_SSOM_WebUrls" + + "SPMeta2_O365_SiteUrls" + "SPMeta2_O365_WebUrls" + "SPMeta2_O365_UserName" + "SPMeta2_O365_Password" + + "SPMeta2_DefaultSqlServerName" + + "SPMeta2_DefaultTaxonomyStoreId" + "SPMeta2_DefaultTaxonomyStoreName" + + "SPMeta2_DefaultTestUserLogins", + "SPMeta2_DefaultTestDomainUserEmails" + + "SPMeta2_DefaultTestADGroups" + + "SPMeta2_RunnerProvisionMode" + ); + + Node $NodeName { + + foreach($var in $vars) { + + $env_resource_name = $var.Replace(".", "_") + + Environment ($env_resource_name + "_Remove") { + Name = $env_resource_name + Ensure = 'Absent' + } + } + + } +} + + +Configuration SPMeta2_UnitTestSettings +{ + param ( + [Parameter(Mandatory=$true)] [ValidateNotNullorEmpty()] [string] $NodeName, + [Parameter(Mandatory=$true)] [ValidateNotNullorEmpty()] [PSCredential] $RunAsCredential + ) + + Import-DscResource -ModuleName SharePointDsc -ModuleVersion 1.6.0.0 + + $config = $ConfigurationData.AllNodes + $objectModels = $config.ObjectModels + + # SetEnvironmentVar "SPMeta2_RunnerLibraries" "SPMeta2.Containers.O365v16.dll" + + $r_runnerLibraries = @(); + + $onprem = $false + $online = $false + + foreach($objectModel in $objectModels) + { + if("SSOM" -eq $objectModel) { + $r_runnerLibraries += "SPMeta2.Containers.SSOM.dll"; + $onprem = $true + } + + if("CSOM" -eq $objectModel) { + $r_runnerLibraries += "SPMeta2.Containers.CSOM.dll"; + $onprem = $true + } + + if("O365" -eq $objectModel) { + $r_runnerLibraries += "SPMeta2.Containers.O365.dll"; + $online = $true + } + + if("O365v16" -eq $objectModel) { + $r_runnerLibraries += "SPMeta2.Containers.O365v16.dll"; + $online = $true + } + } + + + + $env_vars = @() + + $env_vars += @{ + Name = "SPMeta2_RunnerLibraries" + Value = [string]::Join(',', $r_runnerLibraries) + } + + $webApp_Url = "http://$NodeName" + ':' + $config.WebAppPort + + # onprem + + $taxonomyStoreName = ""; + $taxonomyStoreId = ""; + + if($onprem -eq $true) { + + $siteUrl = $webApp_Url.TrimEnd('/') + $config.SiteCollectionUrls + Write-Host "Fetching default taxoomy store for SharePoint:[$siteUrl]" -fore Green + + $o365_UserName = $config.OnlineUserName + $secO365_UserPassword = ConvertTo-SecureString $config.OnlineUserPassword -AsPlainText -Force + + $context = New-Object Microsoft.SharePoint.Client.ClientContext($siteUrl) + + $taxSession = [Microsoft.SharePoint.Client.Taxonomy.TaxonomySession]::GetTaxonomySession($context) + $store = $taxSession.GetDefaultSiteCollectionTermStore(); + + $context.Load($store) + $context.ExecuteQuery() + + Write-Host "Setting up taxonomy store vars" -fore Yellow + + $taxonomyStoreName = $store.Name + $taxonomyStoreId = $store.Id + + Write-Host "`tName:[$taxonomyStoreName]" -fore Gray + Write-Host "`tId:[$taxonomyStoreId]" -fore Gray + + $env_vars += @{ + Name = "SPMeta2_DefaultTaxonomyStoreId" + Value = $taxonomyStoreId + } + + $env_vars += @{ + Name = "SPMeta2_DefaultTaxonomyStoreName" + Value = $taxonomyStoreName + } + } + + if($online -eq $true) { + + $siteUrl = $config.OnlineSiteCollectionUrls; + + Write-Host "Fetching default taxoomy store for O365: [$siteUrl]" -fore Green + + $o365_UserName = $config.OnlineUserName + $secO365_UserPassword = ConvertTo-SecureString $config.OnlineUserPassword -AsPlainText -Force + + $context = New-Object Microsoft.SharePoint.Client.ClientContext($siteUrl) + $credentials = New-Object Microsoft.SharePoint.Client.SharePointOnlineCredentials($o365_UserName, $secO365_UserPassword) + + $context.Credentials = $credentials + + $taxSession = [Microsoft.SharePoint.Client.Taxonomy.TaxonomySession]::GetTaxonomySession($context) + $store = $taxSession.GetDefaultSiteCollectionTermStore(); + + $context.Load($store) + $context.ExecuteQuery() + + Write-Host "Setting up taxonomy store vars" -fore Yellow + + $taxonomyStoreName = $store.Name + $taxonomyStoreId = $store.Id + + Write-Host "`tName:[$taxonomyStoreName]" -fore Gray + Write-Host "`tId:[$taxonomyStoreId]" -fore Gray + + $env_vars += @{ + Name = "SPMeta2_DefaultTaxonomyStoreId" + Value = $taxonomyStoreId + } + + $env_vars += @{ + Name = "SPMeta2_DefaultTaxonomyStoreName" + Value = $taxonomyStoreName + } + } + + $env_vars += @{ + Name = "SPMeta2_SSOM_WebApplicationUrls" + Value = $webApp_Url + } + + $env_vars += @{ + Name = "SPMeta2_SSOM_SiteUrls" + Value = [string]::Join(",", ($config.SiteCollectionUrls | Foreach { [string]($webApp_Url.TrimEnd('/') + $_ ) } )) + } + + $env_vars += @{ + Name = "SPMeta2_SSOM_WebUrls" + Value = [string]::Join(",", ($config.WebUrls | Foreach { [string]($webApp_Url.TrimEnd('/') + $_ ) } )) + } + + $env_vars += @{ + Name = "SPMeta2_CSOM_SiteUrls" + Value = [string]::Join(",", ($config.SiteCollectionUrls | Foreach { [string]($webApp_Url.TrimEnd('/') + $_ ) } )) + } + + $env_vars += @{ + Name = "SPMeta2_CSOM_WebUrls" + Value = [string]::Join(",", ($config.WebUrls | Foreach { [string]($webApp_Url.TrimEnd('/') + $_ ) } )) + } + + # online + $env_vars += @{ + Name = "SPMeta2_O365_SiteUrls" + Value = [string]::Join(",", ($config.OnlineSiteCollectionUrls | Foreach { [string]$_ } ) ) + } + + $env_vars += @{ + Name = "SPMeta2_O365_WebUrls" + Value = [string]::Join(",", ($config.OnlineWebUrls | Foreach { [string]$_ } ) ) + } + + $env_vars += @{ + Name = "SPMeta2_O365_UserName" + Value = ($config.OnlineUserName) + } + + + $env_vars += @{ + Name = "SPMeta2_O365_Password" + Value = ($config.OnlineUserPassword) + } + + Node $NodeName { + + foreach($var in $env_vars) { + + $env_resource_name = $var.Name.Replace(".", "_") + + Environment ($env_resource_name) { + Name = $var.Name + Ensure = 'Present' + Value = $var.Value + } + } + } +} + +$config = @{ + AllNodes = @( + @{ + ObjectModels = $regression_config.ObjectModels + + WebAppPort = $env_config.SharePoint.WebApp.Port + + SiteCollectionUrls = $env_config.SharePoint.SiteCollection.Urls + WebUrls = $env_config.SharePoint.Web.Urls + + OnlineSiteCollectionUrls = $env_config.SharePointOnline.SiteCollection.Urls + OnlineWebUrls = $env_config.SharePointOnline.Web.Urls + OnlineUserName = $env_config.SharePointOnline.UserName + OnlineUserPassword = $env_config.SharePointOnline.UserPassword + } + ) + } + +#$dsc_nodeNames = @("dev13") + + +<# +Apply-Dsc-Configuration -name SPMeta2_UnitTestSettings_Clean ` + -nodeNames $dsc_nodeNames ` + -isVerbose $true ` + -config $config +#> + +Apply-Dsc-Configuration -name SPMeta2_UnitTestSettings ` + -nodeNames $dsc_nodeNames ` + -isVerbose $true ` + -config $config diff --git a/SPMeta2/Regression/config.yaml b/SPMeta2/Regression/config.yaml new file mode 100644 index 000000000..261b32709 --- /dev/null +++ b/SPMeta2/Regression/config.yaml @@ -0,0 +1,65 @@ +Configuration: + # describes DSC related settings + DSC: + # account used for DSC RunAs operations + RunAs: + UserName: "dev\\administrator" + UserPassword: "" + # account used SharePoint web app creation process + WebPoolManagedAccount: + UserName: "dev\\administrator" + UserPassword: "" + # account used SharePoint web app, site collection and web creation process + SPSetupAccount: + UserName: "dev\\administrator" + UserPassword: "" + # VM names to run DSC against + NodeNames: + - dev13 + - cloud20 + - cloud21 + - cloud22 + - cloud23 + - cloud24 + - cloud25 + - cloud26 + - cloud27 + + # describes regression environment settings + # SharePoint / SharePoint online web app, site collections and so on + Environment: + SharePoint: + WebApp: + Port: 31442 + IsHttps: false + SiteCollection: + Urls: + - / + #- /sites/spmeta2 + Web: + Urls: + - / + #- /sites/spmeta2 + SharePointOnline: + SiteCollection: + Urls: + - https://spmeta2-regression.sharepoint.com + #- https://spmeta2-regression.sharepoint.com + Web: + Urls: + - https://spmeta2-regression.sharepoint.com + #- https://spmeta2-regression.sharepoint.com + UserName: "ci@ci.com" + UserPassword: "" + + # describes unit tests settings + RegressionTests: + # which tests to run? + # SSOM, CSOM - these are run against SharePoint + # O365 - that's SP2013 CSOM run against SharePoint Online + # O365v16 - that's SharePoint Online packages run against SharePoint Online + ObjectModels: + - SSOM + #- CSOM + #- O365 + #- O365v16 \ No newline at end of file diff --git a/SPMeta2/SPMeta2.CSOM.Standard/ModelHandlers/Taxonomy/TaxonomyGroupModelHandler.cs b/SPMeta2/SPMeta2.CSOM.Standard/ModelHandlers/Taxonomy/TaxonomyGroupModelHandler.cs index d9586121c..3b96fca04 100644 --- a/SPMeta2/SPMeta2.CSOM.Standard/ModelHandlers/Taxonomy/TaxonomyGroupModelHandler.cs +++ b/SPMeta2/SPMeta2.CSOM.Standard/ModelHandlers/Taxonomy/TaxonomyGroupModelHandler.cs @@ -1,198 +1,287 @@ -using System; -using Microsoft.SharePoint.Client; -using Microsoft.SharePoint.Client.Taxonomy; -using SPMeta2.Common; -using SPMeta2.CSOM.Extensions; -using SPMeta2.CSOM.ModelHandlers; -using SPMeta2.CSOM.Standard.ModelHosts; -using SPMeta2.Definitions; -using SPMeta2.Services; -using SPMeta2.Standard.Definitions.Taxonomy; -using SPMeta2.Utils; - -namespace SPMeta2.CSOM.Standard.ModelHandlers.Taxonomy -{ - public class TaxonomyGroupModelHandler : CSOMModelHandlerBase - { - #region properties - - public override Type TargetType - { - get { return typeof(TaxonomyTermGroupDefinition); } - } - - #endregion - - #region methods - - public override void DeployModel(object modelHost, DefinitionBase model) - { - var siteModelHost = modelHost.WithAssertAndCast("modelHost", value => value.RequireNotNull()); - var groupModel = model.WithAssertAndCast("model", value => value.RequireNotNull()); - - DeployTaxonomyGroup(modelHost, siteModelHost, groupModel); - } - - public override void WithResolvingModelHost(ModelHostResolveContext modelHostContext) - { - var modelHost = modelHostContext.ModelHost; - var model = modelHostContext.Model; - var childModelType = modelHostContext.ChildModelType; - var action = modelHostContext.Action; - - - var storeModelHost = modelHost.WithAssertAndCast("modelHost", value => value.RequireNotNull()); - var groupModel = model.WithAssertAndCast("model", value => value.RequireNotNull()); - - var termStore = storeModelHost.HostTermStore; - var currentGroup = FindGroup(storeModelHost, groupModel); - - action(new TermGroupModelHost - { - HostTermStore = termStore, - HostGroup = currentGroup - }); - } - - protected TermGroup FindSiteCollectionGroup(TermStoreModelHost storeModelHost, TaxonomyTermGroupDefinition groupModel) - { - var termStore = storeModelHost.HostTermStore; - var site = storeModelHost.HostSite; - - var context = termStore.Context; - - TermGroup currentGroup = termStore.GetSiteCollectionGroup(site, true); - - context.Load(currentGroup); - context.ExecuteQueryWithTrace(); - return currentGroup; - } - - protected TermGroup FindGroup(TermStoreModelHost storeModelHost, TaxonomyTermGroupDefinition groupModel) - { - var termStore = storeModelHost.HostTermStore; - var context = termStore.Context; - - TermGroup currentGroup = null; - - if (groupModel.IsSiteCollectionGroup) - { - currentGroup = FindSiteCollectionGroup(storeModelHost, groupModel); - return currentGroup; - } - - if (groupModel.Id.HasValue) - { - var scope = new ExceptionHandlingScope(context); - using (scope.StartScope()) - { - using (scope.StartTry()) - { - currentGroup = termStore.Groups.GetById(groupModel.Id.Value); - context.Load(currentGroup); - } - - using (scope.StartCatch()) - { - - } - } - } - else if (!string.IsNullOrEmpty(groupModel.Name)) - { - var scope = new ExceptionHandlingScope(context); - using (scope.StartScope()) - { - using (scope.StartTry()) - { - currentGroup = termStore.Groups.GetByName(groupModel.Name); - context.Load(currentGroup); - } - - using (scope.StartCatch()) - { - - } - } - } - - context.ExecuteQueryWithTrace(); - - if (currentGroup != null && currentGroup.ServerObjectIsNull == false) - { - context.Load(currentGroup, g => g.Id); - context.Load(currentGroup, g => g.Name); - - context.ExecuteQueryWithTrace(); - - return currentGroup; - } - - return null; - } - - private void DeployTaxonomyGroup(object modelHost, TermStoreModelHost siteModelHost, TaxonomyTermGroupDefinition groupModel) - { - var termStore = siteModelHost.HostTermStore; - var currentGroup = FindGroup(siteModelHost, groupModel); - - InvokeOnModelEvent(this, new ModelEventArgs - { - CurrentModelNode = null, - Model = null, - EventType = ModelEventType.OnProvisioning, - Object = currentGroup, - ObjectType = typeof(TermGroup), - ObjectDefinition = groupModel, - ModelHost = modelHost - }); - - if (currentGroup == null) - { - TraceService.Information((int)LogEventId.ModelProvisionProcessingNewObject, "Processing new Term Group"); - - currentGroup = groupModel.Id.HasValue - ? termStore.CreateGroup(groupModel.Name, groupModel.Id.Value) - : termStore.CreateGroup(groupModel.Name, Guid.NewGuid()); - - if (!string.IsNullOrEmpty(groupModel.Description)) - currentGroup.Description = groupModel.Description; - - InvokeOnModelEvent(this, new ModelEventArgs - { - CurrentModelNode = null, - Model = null, - EventType = ModelEventType.OnProvisioned, - Object = currentGroup, - ObjectType = typeof(TermGroup), - ObjectDefinition = groupModel, - ModelHost = modelHost - }); - - } - else - { - TraceService.Information((int)LogEventId.ModelProvisionProcessingExistingObject, "Processing existing Term Group"); - - if (!string.IsNullOrEmpty(groupModel.Description)) - currentGroup.Description = groupModel.Description; - - InvokeOnModelEvent(this, new ModelEventArgs - { - CurrentModelNode = null, - Model = null, - EventType = ModelEventType.OnProvisioned, - Object = currentGroup, - ObjectType = typeof(TermGroup), - ObjectDefinition = groupModel, - ModelHost = modelHost - }); - } - - termStore.CommitAll(); - termStore.Context.ExecuteQueryWithTrace(); - } - - #endregion - } -} +using System; +using Microsoft.SharePoint.Client; +using Microsoft.SharePoint.Client.Taxonomy; +using SPMeta2.Common; +using SPMeta2.CSOM.Extensions; +using SPMeta2.CSOM.ModelHandlers; +using SPMeta2.CSOM.Standard.ModelHosts; +using SPMeta2.Definitions; +using SPMeta2.Services; +using SPMeta2.Standard.Definitions.Taxonomy; +using SPMeta2.Utils; +using SPMeta2.Exceptions; +using System.Threading; +using SPMeta2.ModelHosts; + +namespace SPMeta2.CSOM.Standard.ModelHandlers.Taxonomy +{ + public class TaxonomyGroupModelHandler : CSOMModelHandlerBase + { + #region properties + + public override Type TargetType + { + get { return typeof(TaxonomyTermGroupDefinition); } + } + + #endregion + + #region methods + + public override void DeployModel(object modelHost, DefinitionBase model) + { + var siteModelHost = modelHost.WithAssertAndCast("modelHost", value => value.RequireNotNull()); + var groupModel = model.WithAssertAndCast("model", value => value.RequireNotNull()); + + DeployTaxonomyGroup(modelHost, siteModelHost, groupModel); + SharePointOnlineWait(siteModelHost, groupModel); + } + + private void SharePointOnlineWait(TermStoreModelHost siteModelHost, TaxonomyTermGroupDefinition groupModel) + { + // wait until the group is there + // Nested terms provisioning in Office 365 fails #995 + // TermSet not found #994 + var context = siteModelHost.HostClientContext; + + if (context.Credentials is SharePointOnlineCredentials) + { + var currentGroup = FindGroup(siteModelHost, groupModel); + + if (currentGroup == null) + { + TryRetryService.TryWithRetry(() => + { + currentGroup = FindGroup(siteModelHost, groupModel); + return currentGroup != null; + }); + } + + if (currentGroup == null) + throw new SPMeta2Exception(string.Format("Cannot find a taxonomy group after provision")); + } + } + + public override void WithResolvingModelHost(ModelHostResolveContext modelHostContext) + { + var modelHost = modelHostContext.ModelHost; + var model = modelHostContext.Model; + var childModelType = modelHostContext.ChildModelType; + var action = modelHostContext.Action; + + var storeModelHost = modelHost.WithAssertAndCast("modelHost", value => value.RequireNotNull()); + var groupModel = model.WithAssertAndCast("model", value => value.RequireNotNull()); + + var termStore = storeModelHost.HostTermStore; + var currentGroup = FindGroup(storeModelHost, groupModel); + + if (currentGroup == null) + { + TryRetryService.TryWithRetry(() => + { + currentGroup = FindGroup(storeModelHost, groupModel); + return currentGroup != null; + }); + } + + if (currentGroup == null) + throw new SPMeta2Exception(string.Format("Cannot find a taxonomy group after provision")); + + action(ModelHostBase.Inherit(storeModelHost, host => + { + host.HostTermStore = termStore; + host.HostGroup = currentGroup; + })); + } + + protected TermGroup FindSiteCollectionGroup(TermStoreModelHost storeModelHost, TaxonomyTermGroupDefinition groupModel) + { + var termStore = storeModelHost.HostTermStore; + var site = storeModelHost.HostSite; + + var context = termStore.Context; + + TermGroup currentGroup = termStore.GetSiteCollectionGroup(site, true); + + context.Load(currentGroup); + context.ExecuteQueryWithTrace(); + return currentGroup; + } + + protected TermGroup FindGroup(TermStoreModelHost storeModelHost, TaxonomyTermGroupDefinition groupModel) + { + var termStore = storeModelHost.HostTermStore; + var context = termStore.Context; + + TermGroup currentGroup = null; + + if (groupModel.IsSiteCollectionGroup) + { + currentGroup = FindSiteCollectionGroup(storeModelHost, groupModel); + return currentGroup; + } + + if (groupModel.Id.HasValue) + { + var scope = new ExceptionHandlingScope(context); + using (scope.StartScope()) + { + using (scope.StartTry()) + { + currentGroup = termStore.Groups.GetById(groupModel.Id.Value); + context.Load(currentGroup); + } + + using (scope.StartCatch()) + { + + } + } + } + else if (!string.IsNullOrEmpty(groupModel.Name)) + { + var scope = new ExceptionHandlingScope(context); + using (scope.StartScope()) + { + using (scope.StartTry()) + { + currentGroup = termStore.Groups.GetByName(groupModel.Name); + context.Load(currentGroup); + } + + using (scope.StartCatch()) + { + + } + } + } + + context.ExecuteQueryWithTrace(); + + if (currentGroup != null + && currentGroup.ServerObjectIsNull.HasValue + && currentGroup.ServerObjectIsNull == false) + { + context.Load(currentGroup, g => g.Id); + context.Load(currentGroup, g => g.Name); + + context.ExecuteQueryWithTrace(); + + return currentGroup; + } + + return null; + } + + private void DeployTaxonomyGroup(object modelHost, TermStoreModelHost siteModelHost, TaxonomyTermGroupDefinition groupModel) + { + var termStore = siteModelHost.HostTermStore; + var currentGroup = FindGroup(siteModelHost, groupModel); + + InvokeOnModelEvent(this, new ModelEventArgs + { + CurrentModelNode = null, + Model = null, + EventType = ModelEventType.OnProvisioning, + Object = currentGroup, + ObjectType = typeof(TermGroup), + ObjectDefinition = groupModel, + ModelHost = modelHost + }); + + if (currentGroup == null) + { + TraceService.Information((int)LogEventId.ModelProvisionProcessingNewObject, "Processing new Term Group"); + + currentGroup = groupModel.Id.HasValue + ? termStore.CreateGroup(groupModel.Name, groupModel.Id.Value) + : termStore.CreateGroup(groupModel.Name, Guid.NewGuid()); + + if (!string.IsNullOrEmpty(groupModel.Description)) + currentGroup.Description = groupModel.Description; + + InvokeOnModelEvent(this, new ModelEventArgs + { + CurrentModelNode = null, + Model = null, + EventType = ModelEventType.OnProvisioned, + Object = currentGroup, + ObjectType = typeof(TermGroup), + ObjectDefinition = groupModel, + ModelHost = modelHost + }); + } + else + { + UpdateExistingTaxonomyGroup(modelHost, groupModel, currentGroup); + } + + termStore.CommitAll(); + + termStore.Groups.RefreshLoad(); + termStore.RefreshLoad(); + + try + { + termStore.Context.ExecuteQueryWithTrace(); + } + catch (Exception e) + { + // SPMeta2 Provisioning Taxonomy Group with CSOM Standard #959 + // https://github.com/SubPointSolutions/spmeta2/issues/959 + + // seems that newly created group might not be available for the time being + // handling that "Group names must be unique." exception + // trying to find the group and only update description + var serverException = e as ServerException; + + if (serverException != null + && serverException.ServerErrorCode == -2147024809) + { + currentGroup = FindGroup(siteModelHost, groupModel); + + if (currentGroup == null) + { + TryRetryService.TryWithRetry(() => + { + currentGroup = FindGroup(siteModelHost, groupModel); + return currentGroup != null; + }); + } + + UpdateExistingTaxonomyGroup(modelHost, groupModel, currentGroup); + + termStore.CommitAll(); + + termStore.Groups.RefreshLoad(); + termStore.RefreshLoad(); + + termStore.Context.ExecuteQueryWithTrace(); + } + } + + siteModelHost.ShouldUpdateHost = false; + } + + private void UpdateExistingTaxonomyGroup(object modelHost, TaxonomyTermGroupDefinition groupModel, TermGroup currentGroup) + { + TraceService.Information((int)LogEventId.ModelProvisionProcessingExistingObject, "Processing existing Term Group"); + + if (!string.IsNullOrEmpty(groupModel.Description)) + currentGroup.Description = groupModel.Description; + + InvokeOnModelEvent(this, new ModelEventArgs + { + CurrentModelNode = null, + Model = null, + EventType = ModelEventType.OnProvisioned, + Object = currentGroup, + ObjectType = typeof(TermGroup), + ObjectDefinition = groupModel, + ModelHost = modelHost + }); + } + + #endregion + } +} diff --git a/SPMeta2/SPMeta2.CSOM.Standard/ModelHandlers/Taxonomy/TaxonomyTermLabelModelHandler.cs b/SPMeta2/SPMeta2.CSOM.Standard/ModelHandlers/Taxonomy/TaxonomyTermLabelModelHandler.cs index 60ba28309..ff97b578c 100644 --- a/SPMeta2/SPMeta2.CSOM.Standard/ModelHandlers/Taxonomy/TaxonomyTermLabelModelHandler.cs +++ b/SPMeta2/SPMeta2.CSOM.Standard/ModelHandlers/Taxonomy/TaxonomyTermLabelModelHandler.cs @@ -1,104 +1,146 @@ -using System; -using System.Linq; -using Microsoft.SharePoint.Client.Taxonomy; -using SPMeta2.Common; -using SPMeta2.CSOM.Extensions; -using SPMeta2.CSOM.ModelHandlers; -using SPMeta2.CSOM.Standard.ModelHosts; -using SPMeta2.Definitions; -using SPMeta2.Services; -using SPMeta2.Standard.Definitions.Taxonomy; -using SPMeta2.Utils; - -namespace SPMeta2.CSOM.Standard.ModelHandlers.Taxonomy -{ - public class TaxonomyTermLabelModelHandler : CSOMModelHandlerBase - { - #region properties - - public override Type TargetType - { - get { return typeof(TaxonomyTermLabelDefinition); } - } - - #endregion - - #region methods - - public override void DeployModel(object modelHost, DefinitionBase model) - { - var termModelHost = modelHost.WithAssertAndCast("model", m => m.RequireNotNull()); - var definition = model.WithAssertAndCast("model", value => value.RequireNotNull()); - - DeployTermLabel(modelHost, termModelHost, definition); - } - private void DeployTermLabel(object modelHost, TermModelHost termModelHost, TaxonomyTermLabelDefinition labelModel) - { - var termStore = termModelHost.HostTermStore; - var context = termStore.Context; - - var term = termModelHost.HostTerm; - var currentLabel = FindLabelInTerm(term, labelModel); - - InvokeOnModelEvent(this, new ModelEventArgs - { - CurrentModelNode = null, - Model = null, - EventType = ModelEventType.OnProvisioning, - Object = currentLabel, - ObjectType = typeof(Label), - ObjectDefinition = labelModel, - ModelHost = modelHost - }); - - if (currentLabel == null) - { - TraceService.Verbose((int)LogEventId.ModelProvisionProcessingNewObject, "Processing new Label"); - - currentLabel = term.CreateLabel(labelModel.Name, labelModel.LCID, labelModel.IsDefault); - - InvokeOnModelEvent(this, new ModelEventArgs - { - CurrentModelNode = null, - Model = null, - EventType = ModelEventType.OnProvisioned, - Object = currentLabel, - ObjectType = typeof(Label), - ObjectDefinition = labelModel, - ModelHost = modelHost - }); - } - else - { - TraceService.Information((int)LogEventId.ModelProvisionProcessingExistingObject, "Processing existing Term"); - - InvokeOnModelEvent(this, new ModelEventArgs - { - CurrentModelNode = null, - Model = null, - EventType = ModelEventType.OnProvisioned, - Object = currentLabel, - ObjectType = typeof(Label), - ObjectDefinition = labelModel, - ModelHost = modelHost - }); - } - - termStore.CommitAll(); - context.ExecuteQueryWithTrace(); - } - - protected Label FindLabelInTerm(Term termSet, TaxonomyTermLabelDefinition labelModel) - { - var context = termSet.Context; - var labels = termSet.Labels; - - context.Load(labels); - context.ExecuteQueryWithTrace(); - - return termSet.Labels.ToList().FirstOrDefault(l => l.Value.ToUpper() == labelModel.Name.ToUpper()); - } - - #endregion - } -} +using System; +using System.Linq; +using Microsoft.SharePoint.Client.Taxonomy; +using SPMeta2.Common; +using SPMeta2.CSOM.Extensions; +using SPMeta2.CSOM.ModelHandlers; +using SPMeta2.CSOM.Standard.ModelHosts; +using SPMeta2.Definitions; +using SPMeta2.Services; +using SPMeta2.Standard.Definitions.Taxonomy; +using SPMeta2.Utils; +using Microsoft.SharePoint.Client; +using SPMeta2.Exceptions; + +namespace SPMeta2.CSOM.Standard.ModelHandlers.Taxonomy +{ + public class TaxonomyTermLabelModelHandler : CSOMModelHandlerBase + { + #region properties + + public override Type TargetType + { + get { return typeof(TaxonomyTermLabelDefinition); } + } + + #endregion + + #region methods + + public override void DeployModel(object modelHost, DefinitionBase model) + { + var termModelHost = modelHost.WithAssertAndCast("model", m => m.RequireNotNull()); + var definition = model.WithAssertAndCast("model", value => value.RequireNotNull()); + + DeployTermLabel(modelHost, termModelHost, definition); + SharePointOnlineWait(termModelHost, definition); + } + + private void SharePointOnlineWait(TermModelHost termModelHost, TaxonomyTermLabelDefinition definition) + { + // wait until the group is there + // Nested terms provisioning in Office 365 fails #995 + // TermSet not found #994 + var context = termModelHost.HostClientContext; + + if (context.Credentials is SharePointOnlineCredentials) + { + var term = termModelHost.HostTerm; + var currentLabel = FindLabelInTerm(term, definition); + + if (currentLabel == null) + { + TryRetryService.TryWithRetry(() => + { + currentLabel = FindLabelInTerm(term, definition); + return currentLabel != null; + }); + } + + if (currentLabel == null) + throw new SPMeta2Exception(string.Format("Cannot find a term label after provision")); + } + } + private void DeployTermLabel(object modelHost, TermModelHost termModelHost, TaxonomyTermLabelDefinition labelModel) + { + var termStore = termModelHost.HostTermStore; + var context = termStore.Context; + + var term = termModelHost.HostTerm; + var currentLabel = FindLabelInTerm(term, labelModel); + + var shouldCommitChanges = false; + + InvokeOnModelEvent(this, new ModelEventArgs + { + CurrentModelNode = null, + Model = null, + EventType = ModelEventType.OnProvisioning, + Object = currentLabel, + ObjectType = typeof(Label), + ObjectDefinition = labelModel, + ModelHost = modelHost + }); + + if (currentLabel == null) + { + TraceService.Verbose((int)LogEventId.ModelProvisionProcessingNewObject, "Processing new Label"); + + currentLabel = term.CreateLabel(labelModel.Name, labelModel.LCID, labelModel.IsDefault); + + InvokeOnModelEvent(this, new ModelEventArgs + { + CurrentModelNode = null, + Model = null, + EventType = ModelEventType.OnProvisioned, + Object = currentLabel, + ObjectType = typeof(Label), + ObjectDefinition = labelModel, + ModelHost = modelHost + }); + + shouldCommitChanges = true; + } + else + { + TraceService.Information((int)LogEventId.ModelProvisionProcessingExistingObject, "Processing existing Term"); + + InvokeOnModelEvent(this, new ModelEventArgs + { + CurrentModelNode = null, + Model = null, + EventType = ModelEventType.OnProvisioned, + Object = currentLabel, + ObjectType = typeof(Label), + ObjectDefinition = labelModel, + ModelHost = modelHost + }); + + shouldCommitChanges = false; + } + + if (shouldCommitChanges) + { + termStore.CommitAll(); + + currentLabel.RefreshLoad(); + term.RefreshLoad(); + + context.ExecuteQueryWithTrace(); + } + } + + protected Label FindLabelInTerm(Term termSet, TaxonomyTermLabelDefinition labelModel) + { + var context = termSet.Context; + var labels = termSet.Labels; + + context.Load(labels); + context.ExecuteQueryWithTrace(); + + return termSet.Labels.ToList().FirstOrDefault(l => l.Value.ToUpper() == labelModel.Name.ToUpper()); + } + + #endregion + } +} diff --git a/SPMeta2/SPMeta2.CSOM.Standard/ModelHandlers/Taxonomy/TaxonomyTermModelHandler.cs b/SPMeta2/SPMeta2.CSOM.Standard/ModelHandlers/Taxonomy/TaxonomyTermModelHandler.cs index 681dc19a7..d324103df 100644 --- a/SPMeta2/SPMeta2.CSOM.Standard/ModelHandlers/Taxonomy/TaxonomyTermModelHandler.cs +++ b/SPMeta2/SPMeta2.CSOM.Standard/ModelHandlers/Taxonomy/TaxonomyTermModelHandler.cs @@ -13,6 +13,7 @@ using SPMeta2.Standard.Definitions.Taxonomy; using SPMeta2.Standard.Utils; using SPMeta2.Utils; +using SPMeta2.ModelHosts; namespace SPMeta2.CSOM.Standard.ModelHandlers.Taxonomy { @@ -63,7 +64,6 @@ public override void WithResolvingModelHost(ModelHostResolveContext modelHostCon var childModelType = modelHostContext.ChildModelType; var action = modelHostContext.Action; - var definition = model.WithAssertAndCast("model", value => value.RequireNotNull()); Term currentTerm = null; @@ -71,7 +71,10 @@ public override void WithResolvingModelHost(ModelHostResolveContext modelHostCon TermSet termSet = null; TermStore termStore = null; - TermModelHost localModelHost = new TermModelHost(); + var localModelHost = ModelHostBase.Inherit(modelHost as ModelHostBase, host => + { + + }); if (modelHost is TermModelHost) { @@ -83,6 +86,15 @@ public override void WithResolvingModelHost(ModelHostResolveContext modelHostCon currentTerm = FindTermInTerm(h.HostTerm, definition); + if (currentTerm == null) + { + TryRetryService.TryWithRetry(() => + { + currentTerm = FindTermInTerm(h.HostTerm, definition); + return currentTerm != null; + }); + } + localModelHost.HostGroup = group; localModelHost.HostTermSet = termSet; localModelHost.HostTerm = currentTerm; @@ -98,6 +110,15 @@ public override void WithResolvingModelHost(ModelHostResolveContext modelHostCon currentTerm = FindTermInTermSet(h.HostTermSet, definition); + if (currentTerm == null) + { + TryRetryService.TryWithRetry(() => + { + currentTerm = FindTermInTermSet(h.HostTermSet, definition); + return currentTerm != null; + }); + } + localModelHost.HostGroup = group; localModelHost.HostTermSet = termSet; localModelHost.HostTerm = currentTerm; @@ -165,8 +186,51 @@ private void DeployTermUnderTermSet(object modelHost, TermSetModelHost groupMode }); } - termStore.CommitAll(); - termStore.Context.ExecuteQueryWithTrace(); + try + { + termStore.CommitAll(); + currentTerm.RefreshLoad(); + + termStore.Context.ExecuteQueryWithTrace(); + } + catch (Exception e) + { + var serverException = e as ServerException; + + if (serverException != null + && serverException.HResult == -2146233088 + && serverException.ServerErrorTypeName == "Microsoft.SharePoint.Taxonomy.TermStoreOperationException") + { + TraceService.Information((int)LogEventId.ModelProvisionProcessingExistingObject, "Processing existing Term"); + + currentTerm = FindTermInTermSet(termSet, termModel); + + if (currentTerm == null) + { + TryRetryService.TryWithRetry(() => + { + currentTerm = FindTermInTermSet(termSet, termModel); + return currentTerm != null; + }); + } + + MapTermProperties(currentTerm, termModel, false); + + InvokeOnModelEvent(this, new ModelEventArgs + { + CurrentModelNode = null, + Model = null, + EventType = ModelEventType.OnProvisioned, + Object = currentTerm, + ObjectType = typeof(Term), + ObjectDefinition = termModel, + ModelHost = modelHost + }); + + termStore.CommitAll(); + termStore.Context.ExecuteQueryWithTrace(); + } + } } private void MapTermProperties(Term currentTerm, TaxonomyTermDefinition termModel, bool isNewObject) @@ -219,7 +283,7 @@ private void UpdateTermProperties(Term currentTerm, TaxonomyTermDefinition termM { var propName = prop.Name; var propValue = prop.Value; - + var propExist = false; if (isNewObject) @@ -327,8 +391,51 @@ private void DeployTermUnderTerm(object modelHost, TermModelHost groupModelHost, }); } - termStore.CommitAll(); - termStore.Context.ExecuteQueryWithTrace(); + try + { + termStore.CommitAll(); + currentTerm.RefreshLoad(); + + termStore.Context.ExecuteQueryWithTrace(); + } + catch (Exception e) + { + var serverException = e as ServerException; + + if (serverException != null + && serverException.HResult == -2146233088 + && serverException.ServerErrorTypeName == "Microsoft.SharePoint.Taxonomy.TermStoreOperationException") + { + TraceService.Information((int)LogEventId.ModelProvisionProcessingExistingObject, "Processing existing Term"); + + currentTerm = FindTermInTerm(termSet, termModel); + + if (currentTerm == null) + { + TryRetryService.TryWithRetry(() => + { + currentTerm = FindTermInTerm(termSet, termModel); + return currentTerm != null; + }); + } + + MapTermProperties(currentTerm, termModel, false); + + InvokeOnModelEvent(this, new ModelEventArgs + { + CurrentModelNode = null, + Model = null, + EventType = ModelEventType.OnProvisioned, + Object = currentTerm, + ObjectType = typeof(Term), + ObjectDefinition = termModel, + ModelHost = modelHost + }); + + termStore.CommitAll(); + termStore.Context.ExecuteQueryWithTrace(); + } + } } @@ -411,7 +518,9 @@ protected Term FindTermInTermSet(TermSet termSet, TaxonomyTermDefinition termMod result = terms.FirstOrDefault(); } - if (result != null && result.ServerObjectIsNull == false) + if (result != null + && result.ServerObjectIsNull.HasValue + && result.ServerObjectIsNull == false) { context.Load(result); context.ExecuteQueryWithTrace(); diff --git a/SPMeta2/SPMeta2.CSOM.Standard/ModelHandlers/Taxonomy/TaxonomyTermSetModelHandler.cs b/SPMeta2/SPMeta2.CSOM.Standard/ModelHandlers/Taxonomy/TaxonomyTermSetModelHandler.cs index 7b809cfb2..7405e02b1 100644 --- a/SPMeta2/SPMeta2.CSOM.Standard/ModelHandlers/Taxonomy/TaxonomyTermSetModelHandler.cs +++ b/SPMeta2/SPMeta2.CSOM.Standard/ModelHandlers/Taxonomy/TaxonomyTermSetModelHandler.cs @@ -1,206 +1,289 @@ -using System; -using System.Linq; -using Microsoft.SharePoint.Client; -using Microsoft.SharePoint.Client.Taxonomy; -using SPMeta2.Common; -using SPMeta2.CSOM.Extensions; -using SPMeta2.CSOM.ModelHandlers; -using SPMeta2.CSOM.Standard.ModelHosts; -using SPMeta2.Definitions; -using SPMeta2.Services; -using SPMeta2.Standard.Definitions.Taxonomy; -using SPMeta2.Utils; - -namespace SPMeta2.CSOM.Standard.ModelHandlers.Taxonomy -{ - public class TaxonomyTermSetModelHandler : CSOMModelHandlerBase - { - #region properties - - public override Type TargetType - { - get { return typeof(TaxonomyTermSetDefinition); } - } - - #endregion - - #region methods - - public override void DeployModel(object modelHost, DefinitionBase model) - { - var groupModelHost = modelHost.WithAssertAndCast("modelHost", value => value.RequireNotNull()); - var groupModel = model.WithAssertAndCast("model", value => value.RequireNotNull()); - - DeployTaxonomyTermSet(modelHost, groupModelHost, groupModel); - - } - - public override void WithResolvingModelHost(ModelHostResolveContext modelHostContext) - { - var modelHost = modelHostContext.ModelHost; - var model = modelHostContext.Model; - var childModelType = modelHostContext.ChildModelType; - var action = modelHostContext.Action; - - - var groupModelHost = modelHost.WithAssertAndCast("modelHost", value => value.RequireNotNull()); - var termSetModel = model.WithAssertAndCast("model", value => value.RequireNotNull()); - - var currentTermSet = FindTermSet(groupModelHost.HostGroup, termSetModel); - - action(new TermSetModelHost - { - HostGroup = groupModelHost.HostGroup, - HostTermStore = groupModelHost.HostTermStore, - HostTermSet = currentTermSet - }); - } - - private void DeployTaxonomyTermSet(object modelHost, TermGroupModelHost groupModelHost, TaxonomyTermSetDefinition termSetModel) - { - var termStore = groupModelHost.HostTermStore; - var termGroup = groupModelHost.HostGroup; - - var currentTermSet = FindTermSet(termGroup, termSetModel); - - InvokeOnModelEvent(this, new ModelEventArgs - { - CurrentModelNode = null, - Model = null, - EventType = ModelEventType.OnProvisioning, - Object = currentTermSet, - ObjectType = typeof(TermSet), - ObjectDefinition = termSetModel, - ModelHost = modelHost - }); - - if (currentTermSet == null) - { - TraceService.Information((int)LogEventId.ModelProvisionProcessingNewObject, "Processing new Term Set"); - - currentTermSet = termSetModel.Id.HasValue - ? termGroup.CreateTermSet(termSetModel.Name, termSetModel.Id.Value, termSetModel.LCID) - : termGroup.CreateTermSet(termSetModel.Name, Guid.NewGuid(), termSetModel.LCID); - - MapTermSet(currentTermSet, termSetModel); - - InvokeOnModelEvent(this, new ModelEventArgs - { - CurrentModelNode = null, - Model = null, - EventType = ModelEventType.OnProvisioned, - Object = currentTermSet, - ObjectType = typeof(TermSet), - ObjectDefinition = termSetModel, - ModelHost = modelHost - }); - } - else - { - TraceService.Information((int)LogEventId.ModelProvisionProcessingExistingObject, "Processing existing Term Set"); - - MapTermSet(currentTermSet, termSetModel); - - InvokeOnModelEvent(this, new ModelEventArgs - { - CurrentModelNode = null, - Model = null, - EventType = ModelEventType.OnProvisioned, - Object = currentTermSet, - ObjectType = typeof(TermSet), - ObjectDefinition = termSetModel, - ModelHost = modelHost - }); - } - - termStore.CommitAll(); - termStore.Context.ExecuteQueryWithTrace(); - } - - private static void MapTermSet(TermSet currentTermSet, TaxonomyTermSetDefinition termSetModel) - { - if (!string.IsNullOrEmpty(termSetModel.Description)) - currentTermSet.Description = termSetModel.Description; - - if (!string.IsNullOrEmpty(termSetModel.Contact)) - currentTermSet.Contact = termSetModel.Contact; - - if (!string.IsNullOrEmpty(termSetModel.CustomSortOrder)) - currentTermSet.CustomSortOrder = termSetModel.CustomSortOrder; - - if (termSetModel.IsOpenForTermCreation.HasValue) - currentTermSet.IsOpenForTermCreation = termSetModel.IsOpenForTermCreation.Value; - - if (termSetModel.IsAvailableForTagging.HasValue) - currentTermSet.IsAvailableForTagging = termSetModel.IsAvailableForTagging.Value; - - - foreach (var customProp in termSetModel.CustomProperties.Where(p => p.Override)) - { - currentTermSet.SetCustomProperty(customProp.Name, customProp.Value); - } - } - - protected TermSet FindTermSet(TermGroup termGroup, TaxonomyTermSetDefinition termSetModel) - { - TermSet result = null; - - var context = termGroup.Context; - - context.Load(termGroup.TermSets); - context.ExecuteQueryWithTrace(); - - if (termSetModel.Id.HasValue) - { - var scope = new ExceptionHandlingScope(context); - using (scope.StartScope()) - { - using (scope.StartTry()) - { - result = termGroup.TermSets.GetById(termSetModel.Id.Value); - context.Load(result); - } - - using (scope.StartCatch()) - { - - } - } - } - else if (!string.IsNullOrEmpty(termSetModel.Name)) - { - var scope = new ExceptionHandlingScope(context); - using (scope.StartScope()) - { - using (scope.StartTry()) - { - result = termGroup.TermSets.GetByName(termSetModel.Name); - context.Load(result); - } - - using (scope.StartCatch()) - { - - } - } - } - - context.ExecuteQueryWithTrace(); - - if (result != null && result.ServerObjectIsNull == false) - { - context.Load(result); - //context.Load(result, g => g.Id); - //context.Load(result, g => g.Name); - - context.ExecuteQueryWithTrace(); - - return result; - } - - return null; - } - - #endregion - } -} +using System; +using System.Linq; +using Microsoft.SharePoint.Client; +using Microsoft.SharePoint.Client.Taxonomy; +using SPMeta2.Common; +using SPMeta2.CSOM.Extensions; +using SPMeta2.CSOM.ModelHandlers; +using SPMeta2.CSOM.Standard.ModelHosts; +using SPMeta2.Definitions; +using SPMeta2.Services; +using SPMeta2.Standard.Definitions.Taxonomy; +using SPMeta2.Utils; +using SPMeta2.Exceptions; +using SPMeta2.ModelHosts; + +namespace SPMeta2.CSOM.Standard.ModelHandlers.Taxonomy +{ + public class TaxonomyTermSetModelHandler : CSOMModelHandlerBase + { + #region properties + + public override Type TargetType + { + get { return typeof(TaxonomyTermSetDefinition); } + } + + #endregion + + #region methods + + public override void DeployModel(object modelHost, DefinitionBase model) + { + var groupModelHost = modelHost.WithAssertAndCast("modelHost", value => value.RequireNotNull()); + var termSetModel = model.WithAssertAndCast("model", value => value.RequireNotNull()); + + DeployTaxonomyTermSet(modelHost, groupModelHost, termSetModel); + SharePointOnlineWait(groupModelHost, termSetModel); + } + + private void SharePointOnlineWait(TermGroupModelHost groupModelHost, TaxonomyTermSetDefinition termSetModel) + { + // wait until the group is there + // Nested terms provisioning in Office 365 fails #995 + // TermSet not found #994 + var context = groupModelHost.HostClientContext; + + if (context.Credentials is SharePointOnlineCredentials) + { + var currentTermSet = FindTermSet(groupModelHost.HostGroup, termSetModel); + + if (currentTermSet == null) + { + TryRetryService.TryWithRetry(() => + { + currentTermSet = FindTermSet(groupModelHost.HostGroup, termSetModel); + return currentTermSet != null; + }); + } + + if (currentTermSet == null) + throw new SPMeta2Exception(string.Format("Cannot find a termset after provision")); + } + } + + public override void WithResolvingModelHost(ModelHostResolveContext modelHostContext) + { + var modelHost = modelHostContext.ModelHost; + var model = modelHostContext.Model; + var childModelType = modelHostContext.ChildModelType; + var action = modelHostContext.Action; + + var groupModelHost = modelHost.WithAssertAndCast("modelHost", value => value.RequireNotNull()); + var termSetModel = model.WithAssertAndCast("model", value => value.RequireNotNull()); + + var currentTermSet = FindTermSet(groupModelHost.HostGroup, termSetModel); + + if (currentTermSet == null) + { + TryRetryService.TryWithRetry(() => + { + currentTermSet = FindTermSet(groupModelHost.HostGroup, termSetModel); + return currentTermSet != null; + }); + } + + if (currentTermSet == null) + throw new SPMeta2Exception(string.Format("Cannot find a taxonomy term set after provision")); + + action(ModelHostBase.Inherit(groupModelHost, host => + { + host.HostGroup = groupModelHost.HostGroup; + host.HostTermStore = groupModelHost.HostTermStore; + host.HostTermSet = currentTermSet; + })); + } + + private void DeployTaxonomyTermSet(object modelHost, TermGroupModelHost groupModelHost, TaxonomyTermSetDefinition termSetModel) + { + var termStore = groupModelHost.HostTermStore; + var termGroup = groupModelHost.HostGroup; + + var currentTermSet = FindTermSet(termGroup, termSetModel); + + InvokeOnModelEvent(this, new ModelEventArgs + { + CurrentModelNode = null, + Model = null, + EventType = ModelEventType.OnProvisioning, + Object = currentTermSet, + ObjectType = typeof(TermSet), + ObjectDefinition = termSetModel, + ModelHost = modelHost + }); + + if (currentTermSet == null) + { + TraceService.Information((int)LogEventId.ModelProvisionProcessingNewObject, "Processing new Term Set"); + + currentTermSet = termSetModel.Id.HasValue + ? termGroup.CreateTermSet(termSetModel.Name, termSetModel.Id.Value, termSetModel.LCID) + : termGroup.CreateTermSet(termSetModel.Name, Guid.NewGuid(), termSetModel.LCID); + + MapTermSet(currentTermSet, termSetModel); + + InvokeOnModelEvent(this, new ModelEventArgs + { + CurrentModelNode = null, + Model = null, + EventType = ModelEventType.OnProvisioned, + Object = currentTermSet, + ObjectType = typeof(TermSet), + ObjectDefinition = termSetModel, + ModelHost = modelHost + }); + } + else + { + TraceService.Information((int)LogEventId.ModelProvisionProcessingExistingObject, "Processing existing Term Set"); + + UpdateExistingTaxonomyTermSet(modelHost, termSetModel, currentTermSet); + } + + termStore.CommitAll(); + + try + { + termStore.Context.ExecuteQueryWithTrace(); + } + catch (Exception e) + { + // SPMeta2 Provisioning Taxonomy Group with CSOM Standard #959 + // https://github.com/SubPointSolutions/spmeta2/issues/959 + + // seems that newly created group might not be available for the time being + // handling that "Group names must be unique." exception + // trying to find the group and only update description + var serverException = e as ServerException; + + if (serverException != null + && serverException.ServerErrorCode == -2146233088) + { + currentTermSet = FindTermSet(termGroup, termSetModel); + + if (currentTermSet == null) + { + TryRetryService.TryWithRetry(() => + { + currentTermSet = FindTermSet(termGroup, termSetModel); + return currentTermSet != null; + }); + } + + UpdateExistingTaxonomyTermSet(modelHost, termSetModel, currentTermSet); + + termStore.CommitAll(); + termStore.RefreshLoad(); + + termStore.Context.ExecuteQueryWithTrace(); + } + } + + groupModelHost.ShouldUpdateHost = false; + } + + private void UpdateExistingTaxonomyTermSet(object modelHost, TaxonomyTermSetDefinition termSetModel, TermSet currentTermSet) + { + MapTermSet(currentTermSet, termSetModel); + + InvokeOnModelEvent(this, new ModelEventArgs + { + CurrentModelNode = null, + Model = null, + EventType = ModelEventType.OnProvisioned, + Object = currentTermSet, + ObjectType = typeof(TermSet), + ObjectDefinition = termSetModel, + ModelHost = modelHost + }); + } + + private static void MapTermSet(TermSet currentTermSet, TaxonomyTermSetDefinition termSetModel) + { + if (!string.IsNullOrEmpty(termSetModel.Description)) + currentTermSet.Description = termSetModel.Description; + + if (!string.IsNullOrEmpty(termSetModel.Contact)) + currentTermSet.Contact = termSetModel.Contact; + + if (!string.IsNullOrEmpty(termSetModel.CustomSortOrder)) + currentTermSet.CustomSortOrder = termSetModel.CustomSortOrder; + + if (termSetModel.IsOpenForTermCreation.HasValue) + currentTermSet.IsOpenForTermCreation = termSetModel.IsOpenForTermCreation.Value; + + if (termSetModel.IsAvailableForTagging.HasValue) + currentTermSet.IsAvailableForTagging = termSetModel.IsAvailableForTagging.Value; + + + foreach (var customProp in termSetModel.CustomProperties.Where(p => p.Override)) + { + currentTermSet.SetCustomProperty(customProp.Name, customProp.Value); + } + } + + protected TermSet FindTermSet(TermGroup termGroup, TaxonomyTermSetDefinition termSetModel) + { + TermSet result = null; + + var context = termGroup.Context; + + context.Load(termGroup.TermSets); + context.ExecuteQueryWithTrace(); + + if (termSetModel.Id.HasValue) + { + var scope = new ExceptionHandlingScope(context); + using (scope.StartScope()) + { + using (scope.StartTry()) + { + result = termGroup.TermSets.GetById(termSetModel.Id.Value); + context.Load(result); + } + + using (scope.StartCatch()) + { + + } + } + } + else if (!string.IsNullOrEmpty(termSetModel.Name)) + { + var scope = new ExceptionHandlingScope(context); + using (scope.StartScope()) + { + using (scope.StartTry()) + { + result = termGroup.TermSets.GetByName(termSetModel.Name); + context.Load(result); + } + + using (scope.StartCatch()) + { + + } + } + } + + context.ExecuteQueryWithTrace(); + + if (result != null + && result.ServerObjectIsNull.HasValue + && result.ServerObjectIsNull == false) + { + context.Load(result); + //context.Load(result, g => g.Id); + //context.Load(result, g => g.Name); + + context.ExecuteQueryWithTrace(); + + return result; + } + + return null; + } + + #endregion + } +} diff --git a/SPMeta2/SPMeta2.CSOM.Standard/ModelHandlers/Taxonomy/TaxonomyTermStoreModelHandler.cs b/SPMeta2/SPMeta2.CSOM.Standard/ModelHandlers/Taxonomy/TaxonomyTermStoreModelHandler.cs index d3dcf5525..56e0e7278 100644 --- a/SPMeta2/SPMeta2.CSOM.Standard/ModelHandlers/Taxonomy/TaxonomyTermStoreModelHandler.cs +++ b/SPMeta2/SPMeta2.CSOM.Standard/ModelHandlers/Taxonomy/TaxonomyTermStoreModelHandler.cs @@ -1,174 +1,176 @@ -using System; -using System.Collections.Generic; -using Microsoft.SharePoint.Client; -using Microsoft.SharePoint.Client.Taxonomy; -using SPMeta2.Common; -using SPMeta2.CSOM.Extensions; -using SPMeta2.CSOM.ModelHandlers; -using SPMeta2.CSOM.ModelHosts; -using SPMeta2.CSOM.Standard.ModelHosts; -using SPMeta2.Definitions; -using SPMeta2.ModelHosts; -using SPMeta2.Services; -using SPMeta2.Standard.Definitions.Taxonomy; -using SPMeta2.Utils; - -namespace SPMeta2.CSOM.Standard.ModelHandlers.Taxonomy -{ - public class TaxonomyTermStoreModelHandler : CSOMModelHandlerBase - { - #region properties - - public override Type TargetType - { - get { return typeof(TaxonomyTermStoreDefinition); } - } - - #endregion - - #region methods - - protected TermStore FindTermStore(SiteModelHost siteModelHost, TaxonomyTermStoreDefinition termStoreModel) - { - return TaxonomyTermStoreModelHandler.FindTermStore(siteModelHost, - termStoreModel.Name, - termStoreModel.Id, - termStoreModel.UseDefaultSiteCollectionTermStore); - } - - public override void WithResolvingModelHost(ModelHostResolveContext modelHostContext) - { - var modelHost = modelHostContext.ModelHost; - var model = modelHostContext.Model; - var childModelType = modelHostContext.ChildModelType; - var action = modelHostContext.Action; - - - var siteModelHost = modelHost.WithAssertAndCast("model", value => value.RequireNotNull()); - var termStoreModel = model.WithAssertAndCast("model", value => value.RequireNotNull()); - - var termStore = FindTermStore(siteModelHost, termStoreModel); - - var termStoreModelHost = ModelHostBase.Inherit(siteModelHost, context => - { - context.HostTermStore = termStore; - }); - - action(termStoreModelHost); - - TraceService.Verbose((int)LogEventId.ModelProvisionCoreCall, "Calling termStore.CommitAll()"); - - termStore.CommitAll(); - termStore.Context.ExecuteQueryWithTrace(); - } - - private static Dictionary _storeCache = new Dictionary(); - private static readonly object _storeCacheLock = new object(); - - internal static TermStore FindTermStore(SiteModelHost siteModelHost, - string termStoreName, - Guid? termStoreId, - bool? useDefaultSiteCollectionTermStore) - { - return FindTermStore(siteModelHost.HostSite, termStoreName, termStoreId, useDefaultSiteCollectionTermStore); - } - - internal static TermStore FindTermStore(Site site, - string termStoreName, - Guid? termStoreId, - bool? useDefaultSiteCollectionTermStore) - { - var clientContext = site.Context; - TermStore termStore = null; - - lock (_storeCacheLock) - { - var key = string.Format("{0}-{1}-{2}", - clientContext.GetHashCode(), - clientContext.GetHashCode(), - string.Format("{0}-{1}-{2}", termStoreName, termStoreId, useDefaultSiteCollectionTermStore)) - .ToLower(); - - if (!_storeCache.ContainsKey(key)) - { - TraceService.VerboseFormat((int)LogEventId.ModelProvisionCoreCall, "First call to TermStore with cache key: [{0}]", key); - - var session = TaxonomySession.GetTaxonomySession(clientContext); - var client = clientContext; - - if (useDefaultSiteCollectionTermStore == true) - { - TraceService.Verbose((int)LogEventId.ModelProvisionCoreCall, "Resolving Term Store as useDefaultSiteCollectionTermStore"); - - termStore = session.GetDefaultSiteCollectionTermStore(); - } - else - { - if (termStoreId.HasValue && termStoreId != default(Guid)) - { - TraceService.VerboseFormat((int)LogEventId.ModelProvisionCoreCall, "Resolving Term Store by ID: [{0}]", termStoreId.Value); - termStore = session.TermStores.GetById(termStoreId.Value); - } - else if (!string.IsNullOrEmpty(termStoreName)) - { - TraceService.VerboseFormat((int)LogEventId.ModelProvisionCoreCall, "Resolving Term Store by Name: [{0}]", termStoreName); - termStore = session.TermStores.GetByName(termStoreName); - } - } - - if (termStore != null) - { - client.Load(termStore, s => s.Id); - client.Load(termStore, s => s.Name); - - client.ExecuteQueryWithTrace(); - } - - - _storeCache.Add(key, termStore); - } - else - { - TraceService.VerboseFormat((int)LogEventId.ModelProvisionCoreCall, "Resolving term store from internal cache with cache key: [{0}]", key); - } - - return _storeCache[key]; - } - } - - public override void DeployModel(object modelHost, DefinitionBase model) - { - var siteModelHost = modelHost.WithAssertAndCast("model", value => value.RequireNotNull()); - var termStoreModel = model.WithAssertAndCast("model", value => value.RequireNotNull()); - - var termStore = TaxonomyTermStoreModelHandler.FindTermStore(siteModelHost, - termStoreModel.Name, - termStoreModel.Id, - termStoreModel.UseDefaultSiteCollectionTermStore); - - InvokeOnModelEvent(this, new ModelEventArgs - { - CurrentModelNode = null, - Model = null, - EventType = ModelEventType.OnProvisioning, - Object = termStore, - ObjectType = typeof(TermStore), - ObjectDefinition = model, - ModelHost = modelHost - }); - - InvokeOnModelEvent(this, new ModelEventArgs - { - CurrentModelNode = null, - Model = null, - EventType = ModelEventType.OnProvisioned, - Object = termStore, - ObjectType = typeof(TermStore), - ObjectDefinition = model, - ModelHost = modelHost - }); - } - - #endregion - } -} +using System; +using System.Collections.Generic; +using Microsoft.SharePoint.Client; +using Microsoft.SharePoint.Client.Taxonomy; +using SPMeta2.Common; +using SPMeta2.CSOM.Extensions; +using SPMeta2.CSOM.ModelHandlers; +using SPMeta2.CSOM.ModelHosts; +using SPMeta2.CSOM.Standard.ModelHosts; +using SPMeta2.Definitions; +using SPMeta2.ModelHosts; +using SPMeta2.Services; +using SPMeta2.Standard.Definitions.Taxonomy; +using SPMeta2.Utils; + +namespace SPMeta2.CSOM.Standard.ModelHandlers.Taxonomy +{ + public class TaxonomyTermStoreModelHandler : CSOMModelHandlerBase + { + #region properties + + public override Type TargetType + { + get { return typeof(TaxonomyTermStoreDefinition); } + } + + #endregion + + #region methods + + protected TermStore FindTermStore(SiteModelHost siteModelHost, TaxonomyTermStoreDefinition termStoreModel) + { + return TaxonomyTermStoreModelHandler.FindTermStore(siteModelHost, + termStoreModel.Name, + termStoreModel.Id, + termStoreModel.UseDefaultSiteCollectionTermStore); + } + + public override void WithResolvingModelHost(ModelHostResolveContext modelHostContext) + { + var modelHost = modelHostContext.ModelHost; + var model = modelHostContext.Model; + var childModelType = modelHostContext.ChildModelType; + var action = modelHostContext.Action; + + var siteModelHost = modelHost.WithAssertAndCast("model", value => value.RequireNotNull()); + var termStoreModel = model.WithAssertAndCast("model", value => value.RequireNotNull()); + + var termStore = FindTermStore(siteModelHost, termStoreModel); + + var termStoreModelHost = ModelHostBase.Inherit(siteModelHost, context => + { + context.HostTermStore = termStore; + }); + + action(termStoreModelHost); + + TraceService.Verbose((int)LogEventId.ModelProvisionCoreCall, "Calling termStore.CommitAll()"); + + if (termStoreModelHost.ShouldUpdateHost) + { + termStore.CommitAll(); + termStore.Context.ExecuteQueryWithTrace(); + } + } + + private static Dictionary _storeCache = new Dictionary(); + private static readonly object _storeCacheLock = new object(); + + internal static TermStore FindTermStore(SiteModelHost siteModelHost, + string termStoreName, + Guid? termStoreId, + bool? useDefaultSiteCollectionTermStore) + { + return FindTermStore(siteModelHost.HostSite, termStoreName, termStoreId, useDefaultSiteCollectionTermStore); + } + + internal static TermStore FindTermStore(Site site, + string termStoreName, + Guid? termStoreId, + bool? useDefaultSiteCollectionTermStore) + { + var clientContext = site.Context; + TermStore termStore = null; + + lock (_storeCacheLock) + { + var key = string.Format("{0}-{1}-{2}", + clientContext.GetHashCode(), + clientContext.GetHashCode(), + string.Format("{0}-{1}-{2}", termStoreName, termStoreId, useDefaultSiteCollectionTermStore)) + .ToLower(); + + if (!_storeCache.ContainsKey(key)) + { + TraceService.VerboseFormat((int)LogEventId.ModelProvisionCoreCall, "First call to TermStore with cache key: [{0}]", key); + + var session = TaxonomySession.GetTaxonomySession(clientContext); + var client = clientContext; + + if (useDefaultSiteCollectionTermStore == true) + { + TraceService.Verbose((int)LogEventId.ModelProvisionCoreCall, "Resolving Term Store as useDefaultSiteCollectionTermStore"); + + termStore = session.GetDefaultSiteCollectionTermStore(); + } + else + { + if (termStoreId.HasValue && termStoreId != default(Guid)) + { + TraceService.VerboseFormat((int)LogEventId.ModelProvisionCoreCall, "Resolving Term Store by ID: [{0}]", termStoreId.Value); + termStore = session.TermStores.GetById(termStoreId.Value); + } + else if (!string.IsNullOrEmpty(termStoreName)) + { + TraceService.VerboseFormat((int)LogEventId.ModelProvisionCoreCall, "Resolving Term Store by Name: [{0}]", termStoreName); + termStore = session.TermStores.GetByName(termStoreName); + } + } + + if (termStore != null) + { + client.Load(termStore, s => s.Id); + client.Load(termStore, s => s.Name); + + client.ExecuteQueryWithTrace(); + } + + + _storeCache.Add(key, termStore); + } + else + { + TraceService.VerboseFormat((int)LogEventId.ModelProvisionCoreCall, "Resolving term store from internal cache with cache key: [{0}]", key); + } + + return _storeCache[key]; + } + } + + public override void DeployModel(object modelHost, DefinitionBase model) + { + var siteModelHost = modelHost.WithAssertAndCast("model", value => value.RequireNotNull()); + var termStoreModel = model.WithAssertAndCast("model", value => value.RequireNotNull()); + + var termStore = TaxonomyTermStoreModelHandler.FindTermStore(siteModelHost, + termStoreModel.Name, + termStoreModel.Id, + termStoreModel.UseDefaultSiteCollectionTermStore); + + InvokeOnModelEvent(this, new ModelEventArgs + { + CurrentModelNode = null, + Model = null, + EventType = ModelEventType.OnProvisioning, + Object = termStore, + ObjectType = typeof(TermStore), + ObjectDefinition = model, + ModelHost = modelHost + }); + + InvokeOnModelEvent(this, new ModelEventArgs + { + CurrentModelNode = null, + Model = null, + EventType = ModelEventType.OnProvisioned, + Object = termStore, + ObjectType = typeof(TermStore), + ObjectDefinition = model, + ModelHost = modelHost + }); + } + + #endregion + } +} diff --git a/SPMeta2/SPMeta2.CSOM/Services/Impl/DefaultClientRuntimeContextService.cs b/SPMeta2/SPMeta2.CSOM/Services/Impl/DefaultClientRuntimeContextService.cs index 008ad148b..26f2a8c06 100644 --- a/SPMeta2/SPMeta2.CSOM/Services/Impl/DefaultClientRuntimeContextService.cs +++ b/SPMeta2/SPMeta2.CSOM/Services/Impl/DefaultClientRuntimeContextService.cs @@ -134,6 +134,14 @@ protected virtual bool ShouldRetryExecuteQuery(Exception ex) //if (ex.HResult == -2146233088) // return true; + if (ex.Message.Contains("Failed to read from or write to database")) + { + // Nested terms provisioning in Office 365 fails #995 + // TermSet not found #994 + + return false; + } + // O365 related handling if (IsAllowedHttpWebResponseStatusCode(ex)) return true; diff --git a/SPMeta2/SPMeta2.Containers.O365v16/O365v16ProvisionRunner.cs b/SPMeta2/SPMeta2.Containers.O365v16/O365v16ProvisionRunner.cs index 0c55f241a..c0383a96e 100644 --- a/SPMeta2/SPMeta2.Containers.O365v16/O365v16ProvisionRunner.cs +++ b/SPMeta2/SPMeta2.Containers.O365v16/O365v16ProvisionRunner.cs @@ -1,4 +1,5 @@ using System; +using System.Linq; using System.Collections.Generic; using System.Diagnostics; using System.Security; @@ -19,6 +20,7 @@ using SPMeta2.Regression.CSOM.Standard.Validation.Fields; using SPMeta2.Services; using SPMeta2.Utils; +using SPMeta2.Exceptions; namespace SPMeta2.Containers.O365v16 { @@ -154,6 +156,9 @@ public override string ResolveFullTypeName(string typeName, string assemblyName) /// public override void DeploySiteModel(ModelNode model) { + if (!SiteUrls.Any()) + throw new SPMeta2Exception("SiteUrls is empty"); + foreach (var siteUrl in SiteUrls) { ContainerTraceUtils.WriteLine(string.Format("[INF] Running on site: [{0}]", siteUrl)); @@ -185,6 +190,9 @@ public override void DeploySiteModel(ModelNode model) /// public override void DeployWebModel(ModelNode model) { + if (!WebUrls.Any()) + throw new SPMeta2Exception("WebUrls is empty"); + foreach (var webUrl in WebUrls) { ContainerTraceUtils.WriteLine(string.Format("[INF] Running on web: [{0}]", webUrl)); diff --git a/SPMeta2/SPMeta2.Containers/Services/RegressionTestService.cs b/SPMeta2/SPMeta2.Containers/Services/RegressionTestService.cs index 5c59442d1..31d174353 100644 --- a/SPMeta2/SPMeta2.Containers/Services/RegressionTestService.cs +++ b/SPMeta2/SPMeta2.Containers/Services/RegressionTestService.cs @@ -124,12 +124,16 @@ protected virtual void InitConfig() private bool _hasInit = false; + public static string CurrentProvisionRunnerAsssmbly {get;set;} + protected virtual void InitRunnerImplementations() { if (_hasInit) return; foreach (var asmFileName in ProvisionRunnerAssemblies) { + CurrentProvisionRunnerAsssmbly = asmFileName; + var asmImpl = Assembly.LoadFrom(asmFileName); var types = ReflectionUtils.GetTypesFromAssembly(asmImpl); diff --git a/SPMeta2/SPMeta2.Regression.CSOM.Standard/Validation/Taxonomy/ClientTaxonomyGroupDefinitionValidator.cs b/SPMeta2/SPMeta2.Regression.CSOM.Standard/Validation/Taxonomy/ClientTaxonomyGroupDefinitionValidator.cs index dcf58dd53..64f897ce5 100644 --- a/SPMeta2/SPMeta2.Regression.CSOM.Standard/Validation/Taxonomy/ClientTaxonomyGroupDefinitionValidator.cs +++ b/SPMeta2/SPMeta2.Regression.CSOM.Standard/Validation/Taxonomy/ClientTaxonomyGroupDefinitionValidator.cs @@ -1,63 +1,67 @@ -using SPMeta2.Containers.Assertion; -using SPMeta2.CSOM.Standard.ModelHandlers.Taxonomy; -using SPMeta2.CSOM.Standard.ModelHosts; -using SPMeta2.Definitions; -using SPMeta2.Definitions.Base; -using SPMeta2.Standard.Definitions.Taxonomy; -using SPMeta2.Utils; - -namespace SPMeta2.Regression.CSOM.Standard.Validation.Taxonomy -{ - public class TaxonomyGroupDefinitionValidator : TaxonomyGroupModelHandler - { - public override void DeployModel(object modelHost, DefinitionBase model) - { - var termStoreModelHost = modelHost.WithAssertAndCast("modelHost", value => value.RequireNotNull()); - var definition = model.WithAssertAndCast("model", value => value.RequireNotNull()); - - var spObject = FindGroup(termStoreModelHost, definition); - - var assert = ServiceFactory.AssertService - .NewAssert(definition, spObject) - .ShouldNotBeNull(spObject); - - if (definition.IsSiteCollectionGroup) - { - assert.SkipProperty(m => m.Name, "IsSiteCollectionGroup is TRUE. Skipping Name property validation."); - - assert.ShouldBeEqual((p, s, d) => - { - var srcProp = s.GetExpressionValue(m => m.IsSiteCollectionGroup); - var group = FindSiteCollectionGroup(termStoreModelHost, definition); - - var isValid = group.IsSiteCollectionGroup; - - return new PropertyValidationResult - { - Tag = p.Tag, - Src = srcProp, - Dst = null, - IsValid = isValid - }; - }); - - - } - else - { - assert.SkipProperty(m => m.IsSiteCollectionGroup, "IsSiteCollectionGroup is false. Skipping property."); - assert.ShouldBeEqual(m => m.Name, o => o.Name); - } - - if (!string.IsNullOrEmpty(definition.Description)) - assert.ShouldBeEqual(m => m.Description, o => o.Description); - else - assert.SkipProperty(m => m.Description, "Description is null. Skipping property."); - - if (definition.Id.HasValue) - assert.ShouldBeEqual(m => m.Id, o => o.Id); - else - assert.SkipProperty(m => m.Id, "Id is null. Skipping property."); - } - } -} +using SPMeta2.Containers.Assertion; +using SPMeta2.CSOM.Standard.ModelHandlers.Taxonomy; +using SPMeta2.CSOM.Standard.ModelHosts; +using SPMeta2.Definitions; +using SPMeta2.Definitions.Base; +using SPMeta2.Standard.Definitions.Taxonomy; +using SPMeta2.Utils; + +namespace SPMeta2.Regression.CSOM.Standard.Validation.Taxonomy +{ + public class TaxonomyGroupDefinitionValidator : TaxonomyGroupModelHandler + { + public override void DeployModel(object modelHost, DefinitionBase model) + { + var termStoreModelHost = modelHost.WithAssertAndCast("modelHost", value => value.RequireNotNull()); + var definition = model.WithAssertAndCast("model", value => value.RequireNotNull()); + + var spObject = FindGroup(termStoreModelHost, definition); + + TryRetryService.TryWithRetry(() => + { + spObject = FindGroup(termStoreModelHost, definition); + return spObject != null; + }); + + var assert = ServiceFactory.AssertService + .NewAssert(definition, spObject) + .ShouldNotBeNull(spObject); + + if (definition.IsSiteCollectionGroup) + { + assert.SkipProperty(m => m.Name, "IsSiteCollectionGroup is TRUE. Skipping Name property validation."); + + assert.ShouldBeEqual((p, s, d) => + { + var srcProp = s.GetExpressionValue(m => m.IsSiteCollectionGroup); + var group = FindSiteCollectionGroup(termStoreModelHost, definition); + + var isValid = group.IsSiteCollectionGroup; + + return new PropertyValidationResult + { + Tag = p.Tag, + Src = srcProp, + Dst = null, + IsValid = isValid + }; + }); + } + else + { + assert.SkipProperty(m => m.IsSiteCollectionGroup, "IsSiteCollectionGroup is false. Skipping property."); + assert.ShouldBeEqual(m => m.Name, o => o.Name); + } + + if (!string.IsNullOrEmpty(definition.Description)) + assert.ShouldBeEqual(m => m.Description, o => o.Description); + else + assert.SkipProperty(m => m.Description, "Description is null. Skipping property."); + + if (definition.Id.HasValue) + assert.ShouldBeEqual(m => m.Id, o => o.Id); + else + assert.SkipProperty(m => m.Id, "Id is null. Skipping property."); + } + } +} diff --git a/SPMeta2/SPMeta2.Regression.CSOM.Standard/Validation/Taxonomy/ClientTaxonomyTermDefinitionValidator.cs b/SPMeta2/SPMeta2.Regression.CSOM.Standard/Validation/Taxonomy/ClientTaxonomyTermDefinitionValidator.cs index 06b3fe91c..c8c55a814 100644 --- a/SPMeta2/SPMeta2.Regression.CSOM.Standard/Validation/Taxonomy/ClientTaxonomyTermDefinitionValidator.cs +++ b/SPMeta2/SPMeta2.Regression.CSOM.Standard/Validation/Taxonomy/ClientTaxonomyTermDefinitionValidator.cs @@ -1,178 +1,186 @@ -using Microsoft.SharePoint.Client.Taxonomy; -using SPMeta2.Containers.Assertion; -using SPMeta2.CSOM.Extensions; -using SPMeta2.CSOM.Standard.ModelHandlers.Taxonomy; -using SPMeta2.CSOM.Standard.ModelHosts; -using SPMeta2.Definitions; -using SPMeta2.Definitions.Base; -using SPMeta2.Exceptions; -using SPMeta2.Standard.Definitions.Taxonomy; -using SPMeta2.Standard.Utils; -using SPMeta2.Utils; - -namespace SPMeta2.Regression.CSOM.Standard.Validation.Taxonomy -{ - public class TaxonomyTermDefinitionValidator : TaxonomyTermModelHandler - { - public override void DeployModel(object modelHost, DefinitionBase model) - { - var definition = model.WithAssertAndCast("model", value => value.RequireNotNull()); - - Term spObject = null; - - if (modelHost is TermModelHost) - spObject = FindTermInTerm((modelHost as TermModelHost).HostTerm, definition); - else if (modelHost is TermSetModelHost) - spObject = FindTermInTermSet((modelHost as TermSetModelHost).HostTermSet, definition); - else - { - throw new SPMeta2UnsupportedModelHostException(string.Format("Model host of type: [{0}] is not supported", modelHost.GetType())); - - } - - TermExtensions.CurrentLCID = definition.LCID; - - var assert = ServiceFactory.AssertService - .NewAssert(definition, spObject) - .ShouldNotBeNull(spObject) - //.ShouldBeEqual(m => m.Name, o => o.Name) - .ShouldBeEqual(m => m.Description, o => o.GetDefaultLCIDDescription()); - - assert.SkipProperty(m => m.LCID, "LCID is not accessible from OM. Should be alright while provision."); - - assert.ShouldBeEqual((p, s, d) => - { - var srcProp = s.GetExpressionValue(m => m.Name); - var dstProp = d.GetExpressionValue(m => m.Name); - - var isValid = NormalizeTermName(s.Name) == d.Name; - - return new PropertyValidationResult - { - Tag = p.Tag, - Src = srcProp, - Dst = dstProp, - IsValid = isValid - }; - }); - - - - - if (!string.IsNullOrEmpty(definition.CustomSortOrder)) - assert.ShouldBeEqual(m => m.CustomSortOrder, o => o.CustomSortOrder); - else - assert.SkipProperty(m => m.CustomSortOrder); - - if (definition.Id.HasValue) - { - assert.ShouldBeEqual(m => m.Id, o => o.Id); - } - else - { - assert.SkipProperty(m => m.Id, "Id is null. Skipping property."); - } - - if (definition.IsAvailableForTagging.HasValue) - { - assert.ShouldBeEqual(m => m.IsAvailableForTagging, o => o.IsAvailableForTagging); - } - else - { - assert.SkipProperty(m => m.IsAvailableForTagging, "IsAvailableForTagging is null. Skipping property."); - } - - assert.ShouldBeEqual((p, s, d) => - { - var srcProp = s.GetExpressionValue(m => m.CustomProperties); - - var isValid = true; - - // missed props, or too much - // should be equal on the first provision - if (s.CustomProperties.Count != d.CustomProperties.Count) - { - isValid = false; - } - - // per prop - foreach (var customProp in s.CustomProperties) - { - if (!d.CustomProperties.ContainsKey(customProp.Name)) - { - isValid = false; - break; - } - - if (d.CustomProperties[customProp.Name] != customProp.Value) - { - isValid = false; - break; - } - } - - return new PropertyValidationResult - { - Tag = p.Tag, - Src = srcProp, - // Dst = dstProp, - IsValid = isValid - }; - }); - - - assert.ShouldBeEqual((p, s, d) => - { - var srcProp = s.GetExpressionValue(m => m.LocalCustomProperties); - - var isValid = true; - - // missed props, or too much - // should be equal on the first provision - if (s.LocalCustomProperties.Count != d.LocalCustomProperties.Count) - { - isValid = false; - } - - // per prop - foreach (var customProp in s.LocalCustomProperties) - { - if (!d.LocalCustomProperties.ContainsKey(customProp.Name)) - { - isValid = false; - break; - } - - if (d.LocalCustomProperties[customProp.Name] != customProp.Value) - { - isValid = false; - break; - } - } - - return new PropertyValidationResult - { - Tag = p.Tag, - Src = srcProp, - // Dst = dstProp, - IsValid = isValid - }; - }); - } - } - - internal static class TermExtensions - { - public static int CurrentLCID { get; set; } - - public static string GetDefaultLCIDDescription(this Term term) - { - var context = term.Context; - - var resultValue = term.GetDescription(CurrentLCID); - context.ExecuteQueryWithTrace(); - - return resultValue.Value; - } - } -} +using Microsoft.SharePoint.Client.Taxonomy; +using SPMeta2.Containers.Assertion; +using SPMeta2.CSOM.Extensions; +using SPMeta2.CSOM.Standard.ModelHandlers.Taxonomy; +using SPMeta2.CSOM.Standard.ModelHosts; +using SPMeta2.Definitions; +using SPMeta2.Definitions.Base; +using SPMeta2.Exceptions; +using SPMeta2.Standard.Definitions.Taxonomy; +using SPMeta2.Standard.Utils; +using SPMeta2.Utils; + +namespace SPMeta2.Regression.CSOM.Standard.Validation.Taxonomy +{ + public class TaxonomyTermDefinitionValidator : TaxonomyTermModelHandler + { + public override void DeployModel(object modelHost, DefinitionBase model) + { + var definition = model.WithAssertAndCast("model", value => value.RequireNotNull()); + + Term spObject = null; + + if (modelHost is TermModelHost) + { + TryRetryService.TryWithRetry(() => + { + spObject = FindTermInTerm((modelHost as TermModelHost).HostTerm, definition); + return spObject != null; + }); + } + else if (modelHost is TermSetModelHost) + { + TryRetryService.TryWithRetry(() => + { + spObject = FindTermInTermSet((modelHost as TermSetModelHost).HostTermSet, definition); + return spObject != null; + }); + } + else + { + throw new SPMeta2UnsupportedModelHostException(string.Format("Model host of type: [{0}] is not supported", modelHost.GetType())); + } + + TermExtensions.CurrentLCID = definition.LCID; + + var assert = ServiceFactory.AssertService + .NewAssert(definition, spObject) + .ShouldNotBeNull(spObject) + //.ShouldBeEqual(m => m.Name, o => o.Name) + .ShouldBeEqual(m => m.Description, o => o.GetDefaultLCIDDescription()); + + assert.SkipProperty(m => m.LCID, "LCID is not accessible from OM. Should be alright while provision."); + + assert.ShouldBeEqual((p, s, d) => + { + var srcProp = s.GetExpressionValue(m => m.Name); + var dstProp = d.GetExpressionValue(m => m.Name); + + var isValid = NormalizeTermName(s.Name) == d.Name; + + return new PropertyValidationResult + { + Tag = p.Tag, + Src = srcProp, + Dst = dstProp, + IsValid = isValid + }; + }); + + if (!string.IsNullOrEmpty(definition.CustomSortOrder)) + assert.ShouldBeEqual(m => m.CustomSortOrder, o => o.CustomSortOrder); + else + assert.SkipProperty(m => m.CustomSortOrder); + + if (definition.Id.HasValue) + { + assert.ShouldBeEqual(m => m.Id, o => o.Id); + } + else + { + assert.SkipProperty(m => m.Id, "Id is null. Skipping property."); + } + + if (definition.IsAvailableForTagging.HasValue) + { + assert.ShouldBeEqual(m => m.IsAvailableForTagging, o => o.IsAvailableForTagging); + } + else + { + assert.SkipProperty(m => m.IsAvailableForTagging, "IsAvailableForTagging is null. Skipping property."); + } + + assert.ShouldBeEqual((p, s, d) => + { + var srcProp = s.GetExpressionValue(m => m.CustomProperties); + + var isValid = true; + + // missed props, or too much + // should be equal on the first provision + if (s.CustomProperties.Count != d.CustomProperties.Count) + { + isValid = false; + } + + // per prop + foreach (var customProp in s.CustomProperties) + { + if (!d.CustomProperties.ContainsKey(customProp.Name)) + { + isValid = false; + break; + } + + if (d.CustomProperties[customProp.Name] != customProp.Value) + { + isValid = false; + break; + } + } + + return new PropertyValidationResult + { + Tag = p.Tag, + Src = srcProp, + // Dst = dstProp, + IsValid = isValid + }; + }); + + + assert.ShouldBeEqual((p, s, d) => + { + var srcProp = s.GetExpressionValue(m => m.LocalCustomProperties); + + var isValid = true; + + // missed props, or too much + // should be equal on the first provision + if (s.LocalCustomProperties.Count != d.LocalCustomProperties.Count) + { + isValid = false; + } + + // per prop + foreach (var customProp in s.LocalCustomProperties) + { + if (!d.LocalCustomProperties.ContainsKey(customProp.Name)) + { + isValid = false; + break; + } + + if (d.LocalCustomProperties[customProp.Name] != customProp.Value) + { + isValid = false; + break; + } + } + + return new PropertyValidationResult + { + Tag = p.Tag, + Src = srcProp, + // Dst = dstProp, + IsValid = isValid + }; + }); + } + } + + internal static class TermExtensions + { + public static int CurrentLCID { get; set; } + + public static string GetDefaultLCIDDescription(this Term term) + { + var context = term.Context; + + var resultValue = term.GetDescription(CurrentLCID); + context.ExecuteQueryWithTrace(); + + return resultValue.Value; + } + } +} diff --git a/SPMeta2/SPMeta2.Regression.CSOM.Standard/Validation/Taxonomy/ClientTaxonomyTermLabelDefinitionValidator.cs b/SPMeta2/SPMeta2.Regression.CSOM.Standard/Validation/Taxonomy/ClientTaxonomyTermLabelDefinitionValidator.cs index 4b8b43749..08a16406a 100644 --- a/SPMeta2/SPMeta2.Regression.CSOM.Standard/Validation/Taxonomy/ClientTaxonomyTermLabelDefinitionValidator.cs +++ b/SPMeta2/SPMeta2.Regression.CSOM.Standard/Validation/Taxonomy/ClientTaxonomyTermLabelDefinitionValidator.cs @@ -13,7 +13,16 @@ public override void DeployModel(object modelHost, DefinitionBase model) var termModelHost = modelHost.WithAssertAndCast("modelHost", value => value.RequireNotNull()); var definition = model.WithAssertAndCast("model", value => value.RequireNotNull()); - var spObject = FindLabelInTerm(termModelHost.HostTerm, definition); + var spObject = FindLabelInTerm(termModelHost.HostTerm, definition); + + if (spObject == null) + { + TryRetryService.TryWithRetry(() => + { + spObject = FindLabelInTerm(termModelHost.HostTerm, definition); + return spObject != null; + }); + } var assert = ServiceFactory.AssertService .NewAssert(definition, spObject) diff --git a/SPMeta2/SPMeta2.Regression.CSOM.Standard/Validation/Taxonomy/ClientTaxonomyTermSetDefinitionValidator.cs b/SPMeta2/SPMeta2.Regression.CSOM.Standard/Validation/Taxonomy/ClientTaxonomyTermSetDefinitionValidator.cs index 4dd3eaa96..cbef364f8 100644 --- a/SPMeta2/SPMeta2.Regression.CSOM.Standard/Validation/Taxonomy/ClientTaxonomyTermSetDefinitionValidator.cs +++ b/SPMeta2/SPMeta2.Regression.CSOM.Standard/Validation/Taxonomy/ClientTaxonomyTermSetDefinitionValidator.cs @@ -15,7 +15,13 @@ public override void DeployModel(object modelHost, DefinitionBase model) var termGroupModelHost = modelHost.WithAssertAndCast("modelHost", value => value.RequireNotNull()); var definition = model.WithAssertAndCast("model", value => value.RequireNotNull()); - var spObject = FindTermSet(termGroupModelHost.HostGroup, definition); + var spObject = FindTermSet(termGroupModelHost.HostGroup, definition); + + TryRetryService.TryWithRetry(() => + { + spObject = FindTermSet(termGroupModelHost.HostGroup, definition); + return spObject != null; + }); var assert = ServiceFactory.AssertService .NewAssert(definition, spObject) diff --git a/SPMeta2/SPMeta2.Regression.Impl.Tests/Impl/LookupServices/SSOM/SSOMListViewLookupServiceTests.cs b/SPMeta2/SPMeta2.Regression.Impl.Tests/Impl/LookupServices/SSOM/SSOMListViewLookupServiceTests.cs index cec5758e8..77e8c139e 100644 --- a/SPMeta2/SPMeta2.Regression.Impl.Tests/Impl/LookupServices/SSOM/SSOMListViewLookupServiceTests.cs +++ b/SPMeta2/SPMeta2.Regression.Impl.Tests/Impl/LookupServices/SSOM/SSOMListViewLookupServiceTests.cs @@ -269,8 +269,12 @@ public void Can_Find_ListView_WithInList() var webModel = SPMeta2Model.NewWebModel(rootWeb => { + rootWeb.AddWebFeature(BuiltInWebFeatures.WikiPageHomePage.Inherit()); + rootWeb.AddWeb(webDef, web => { + web.AddWebFeature(BuiltInWebFeatures.WikiPageHomePage.Inherit()); + web .AddList(Lists.TestList1, list => { diff --git a/SPMeta2/SPMeta2.Regression.Tests/Base/SPMeta2RegresionTestBase.cs b/SPMeta2/SPMeta2.Regression.Tests/Base/SPMeta2RegresionTestBase.cs index a8350c568..6bab02951 100644 --- a/SPMeta2/SPMeta2.Regression.Tests/Base/SPMeta2RegresionTestBase.cs +++ b/SPMeta2/SPMeta2.Regression.Tests/Base/SPMeta2RegresionTestBase.cs @@ -35,7 +35,7 @@ namespace SPMeta2.Regression.Tests.Base { - public class SPMeta2RegresionTestCoreBase + public class SPMeta2RegresionTestCoreBase : SPMeta2RegresionTestVeryBase { static SPMeta2RegresionTestCoreBase() { @@ -49,7 +49,7 @@ private static string GetFullPath(string path) static Assembly CurrentDomain_AssemblyResolve(object sender, ResolveEventArgs args) { - var m2runner = Environment.GetEnvironmentVariable("SPMeta2_RunnerLibraries", EnvironmentVariableTarget.Machine); + var m2runner = RegressionTestService.CurrentProvisionRunnerAsssmbly; var baseDir = Path.GetFullPath(AppDomain.CurrentDomain.BaseDirectory); RegressionUtils.WriteLine(string.Format("Resolving custom assembly binding for m2 runner:[{0}]", m2runner)); @@ -103,12 +103,28 @@ static Assembly CurrentDomain_AssemblyResolve(object sender, ResolveEventArgs ar { assemblyDirs.Add(Path.Combine(baseDir, @"_Dependencies\spmeta2-csom-2013")); assemblyDirs.Add(Path.Combine(baseDir, @"_Dependencies\spmeta2-csom-regression-2013")); + + // VS sometimes does not coipy these accorss + // referencing straight to the solution + assemblyDirs.Add(GetFullPath(Path.Combine(baseDir, @"..\..\..\SPMeta2.CSOM.Standard\bin\Debug45\"))); + assemblyDirs.Add(GetFullPath(Path.Combine(baseDir, @"..\..\..\SPMeta2.CSOM\bin\Debug45\"))); + + assemblyDirs.Add(GetFullPath(Path.Combine(baseDir, @"..\..\..\SPMeta2.Regression.CSOM\bin\Debug45\"))); + assemblyDirs.Add(GetFullPath(Path.Combine(baseDir, @"..\..\..\SPMeta2.Regression.CSOM.Standard\bin\Debug45\"))); } if (m2runner == "SPMeta2.Containers.CSOM.dll") { assemblyDirs.Add(Path.Combine(baseDir, @"_Dependencies\spmeta2-csom-2013")); assemblyDirs.Add(Path.Combine(baseDir, @"_Dependencies\spmeta2-csom-regression-2013")); + + // VS sometimes does not coipy these accorss + // referencing straight to the solution + assemblyDirs.Add(GetFullPath(Path.Combine(baseDir, @"..\..\..\SPMeta2.CSOM.Standard\bin\Debug45\"))); + assemblyDirs.Add(GetFullPath(Path.Combine(baseDir, @"..\..\..\SPMeta2.CSOM\bin\Debug45\"))); + + assemblyDirs.Add(GetFullPath(Path.Combine(baseDir, @"..\..\..\SPMeta2.Regression.CSOM\bin\Debug45\"))); + assemblyDirs.Add(GetFullPath(Path.Combine(baseDir, @"..\..\..\SPMeta2.Regression.CSOM.Standard\bin\Debug45\"))); } foreach (var dir in assemblyDirs) @@ -122,7 +138,7 @@ static Assembly CurrentDomain_AssemblyResolve(object sender, ResolveEventArgs ar } } - throw new Exception(string.Format("Cannot load custom assembly:[{0}] for assembly:[{1}]", + throw new Exception(string.Format("Cannot load custom assembly:[{0}] for assembly:[{1}]. Rebuild solution via powershell .\build in 'Build' project and run regression again", args.Name, args.RequestingAssembly )); diff --git a/SPMeta2/SPMeta2.Regression.Tests/Base/SPMeta2RegresionTestVeryBase.cs b/SPMeta2/SPMeta2.Regression.Tests/Base/SPMeta2RegresionTestVeryBase.cs new file mode 100644 index 000000000..6a47eecd1 --- /dev/null +++ b/SPMeta2/SPMeta2.Regression.Tests/Base/SPMeta2RegresionTestVeryBase.cs @@ -0,0 +1,34 @@ +using SPMeta2.Services; +using SPMeta2.Services.Impl; +using System; +using System.Collections.Generic; +using System.Diagnostics; +using System.Linq; +using System.Text; + + +namespace SPMeta2.Regression.Tests.Base +{ + public class SPMeta2RegresionTestVeryBase + { + static SPMeta2RegresionTestVeryBase() + { + ServiceContainer.Instance.ReplaceService( + typeof(TraceServiceBase), + new TraceableTraceService()); + } + } + + + public class TraceableTraceService : TraceSourceService + { + protected override void TraceEvent(int id, System.Diagnostics.TraceEventType messageType, object message, Exception exception) + { + base.TraceEvent(id, messageType, message, exception); + + var traceString = GetTraceEventString(id, messageType, message, exception); + + Trace.WriteLine(traceString); + } + } +} diff --git a/SPMeta2/SPMeta2.Regression.Tests/Impl/Random/RandomDefinitionTest.cs b/SPMeta2/SPMeta2.Regression.Tests/Impl/Random/RandomDefinitionTest.cs index 2ad097068..bd9782694 100644 --- a/SPMeta2/SPMeta2.Regression.Tests/Impl/Random/RandomDefinitionTest.cs +++ b/SPMeta2/SPMeta2.Regression.Tests/Impl/Random/RandomDefinitionTest.cs @@ -98,7 +98,7 @@ public RandomDefinitionTest() EnablePropertyNullableValidation = true; PropertyNullableGenerationCount = 1; - RegressionService.ShowOnlyFalseResults = false; + RegressionService.ShowOnlyFalseResults = true; } #region common diff --git a/SPMeta2/SPMeta2.Regression.Tests/Impl/Scenarios/Base/SPMeta2RegresionScenarioTestBase.cs b/SPMeta2/SPMeta2.Regression.Tests/Impl/Scenarios/Base/SPMeta2RegresionScenarioTestBase.cs index b14f1bb14..81dfbf8ed 100644 --- a/SPMeta2/SPMeta2.Regression.Tests/Impl/Scenarios/Base/SPMeta2RegresionScenarioTestBase.cs +++ b/SPMeta2/SPMeta2.Regression.Tests/Impl/Scenarios/Base/SPMeta2RegresionScenarioTestBase.cs @@ -24,7 +24,7 @@ public class SPMeta2RegresionScenarioTestBase : SPMeta2ProvisionRegresionTestBas public SPMeta2RegresionScenarioTestBase() { RegressionService.ProvisionGenerationCount = 2; - RegressionService.ShowOnlyFalseResults = false; + RegressionService.ShowOnlyFalseResults = true; var isIncrementalProvisionEnabled = IsIncrementalProvisionMode; diff --git a/SPMeta2/SPMeta2.Regression.Tests/Impl/Scenarios/FarmSolutionScenariosTest.cs b/SPMeta2/SPMeta2.Regression.Tests/Impl/Scenarios/FarmSolutionScenariosTest.cs index a8ef17614..ae63b9162 100644 --- a/SPMeta2/SPMeta2.Regression.Tests/Impl/Scenarios/FarmSolutionScenariosTest.cs +++ b/SPMeta2/SPMeta2.Regression.Tests/Impl/Scenarios/FarmSolutionScenariosTest.cs @@ -26,7 +26,7 @@ public class FarmSolutionScenariosTest : SPMeta2RegresionScenarioTestBase public FarmSolutionScenariosTest() { RegressionService.ProvisionGenerationCount = 1; - RegressionService.ShowOnlyFalseResults = false; + RegressionService.ShowOnlyFalseResults = true; } #endregion diff --git a/SPMeta2/SPMeta2.Regression.Tests/Impl/Scenarios/TaxonomyScenariousTest.cs b/SPMeta2/SPMeta2.Regression.Tests/Impl/Scenarios/TaxonomyScenariousTest.cs index 6d80d61d2..71691627a 100644 --- a/SPMeta2/SPMeta2.Regression.Tests/Impl/Scenarios/TaxonomyScenariousTest.cs +++ b/SPMeta2/SPMeta2.Regression.Tests/Impl/Scenarios/TaxonomyScenariousTest.cs @@ -46,7 +46,7 @@ protected void GenerateTermsTree(ModelNode termSetOrTermNode, int deep, bool cle (termSetOrTermNode as TaxonomyTermModelNode).AddRandomTerm(term => { var termDef = term.Value as TaxonomyTermDefinition; - termDef.Name = string.Format("InvertedLevel_{0}_{1}", deep, termDef.Name); + termDef.Name = string.Format("il{0}_{1}", deep, termDef.Name); if (cleanGuid) termDef.Id = null; @@ -59,7 +59,7 @@ protected void GenerateTermsTree(ModelNode termSetOrTermNode, int deep, bool cle (termSetOrTermNode as TaxonomyTermSetModelNode).AddRandomTerm(term => { var termDef = term.Value as TaxonomyTermDefinition; - termDef.Name = string.Format("InvertedLevel_{0}_{1}", deep, termDef.Name); + termDef.Name = string.Format("il{0}_{1}", deep, termDef.Name); if (cleanGuid) termDef.Id = null; diff --git a/SPMeta2/SPMeta2.Regression.Tests/PSScripts/100 - Ensure M2 Web Application.ps1 b/SPMeta2/SPMeta2.Regression.Tests/PSScripts/100 - Ensure M2 Web Application.ps1 deleted file mode 100644 index 68c65af02..000000000 --- a/SPMeta2/SPMeta2.Regression.Tests/PSScripts/100 - Ensure M2 Web Application.ps1 +++ /dev/null @@ -1,13 +0,0 @@ -cls cd "$PSScriptRoot" . "$PSScriptRoot\_config.ps1" -. "$PSScriptRoot\_sys.common.ps1" - -Write-Host "Ensuring M2 test web application with the following settings:" -fore Green -M2ShowSettings $g_M2WebAppSettings - -Write-Host "Ensuring M2 test web application with the following settings:" -fore Green - -$g_M2WebAppSettings.ShouldRecreateWebApplicaiton = $true -$g_M2WebAppSettings.ShouldRecreateSiteCollection = $true - -EnsureSPMeta2SandboxWebApplication $g_M2WebAppSettings.ShouldRecreateWebApplicaiton -EnsureSPMeta2SandboxSiteCollections $g_M2WebAppSettings.ShouldRecreateSiteCollection \ No newline at end of file diff --git a/SPMeta2/SPMeta2.Regression.Tests/PSScripts/1000 - Internal.CheckContentTypeSetup.ps1 b/SPMeta2/SPMeta2.Regression.Tests/PSScripts/1000 - Internal.CheckContentTypeSetup.ps1 deleted file mode 100644 index fcac18fd2..000000000 --- a/SPMeta2/SPMeta2.Regression.Tests/PSScripts/1000 - Internal.CheckContentTypeSetup.ps1 +++ /dev/null @@ -1,129 +0,0 @@ -cls - -Write-Host "Loading SharePoint API" - -$ver = $host | select version -if ($ver.Version.Major -gt 1) {$host.Runspace.ThreadOptions = "ReuseThread"} -if ((Get-PSSnapin "Microsoft.SharePoint.PowerShell" -ErrorAction SilentlyContinue) -eq $null) { - Add-PSSnapin "Microsoft.SharePoint.PowerShell" -} - -# checks that Pages and Docs are configured correctly - -$rootWebUrl = "http://dev42:9299/sites/parliament-web-3" -$web = Get-SPWeb $rootWebUrl - -if($web -eq $null) { - return -} - -function isContentTypeHidden($list, $name) { - - $result = $true - - $cts = $list.RootFolder.ContentTypeOrder - foreach($ct in $cts) { - - if($ct.Name -eq $name) { - $result = $false - } - } - - return $result - -} - -function hasContentType($list, $name) { - - $result = $false - - $cts = $list.ContentTypes - - foreach($ct in $cts) { - - if($ct.Name -eq $name) { - $result = $true - } - } - - return $result - -} - -function CheckPagesLibraryContentTypes($web) { - - $isValid = $true - - $pages = $web.Lists["Pages"] - # should have 'Welcome Page' hidden - - - $isValid = $true - - $isValid = $isValid -and ((isContentTypeHidden $pages "Welcome Page") -eq $true) - $isValid = $isValid -and ((hasContentType $pages "Welcome Page") -eq $true) - $isValid = $isValid -and ((hasContentType $pages "Article Page") -eq $false) - $isValid = $isValid -and ((hasContentType $pages "Page") -eq $false) - - - - if($isValid -eq $true) { - Write-Host "`t`t[+] Page content types" -fore green - } else { - Write-Host "`t`t[-] Page content types " -fore red - } - #RETURN $isValid -} - - -function CheckDocumentaLibraryContentTypes($web) { - - $isValid = $true - - $pages = $web.Lists["Pages"] - # should have 'Welcome Page' hidden - - - $isValid = $true - - $isValid = $isValid -and ((hasContentType $pages "Document") -eq $false) - - - if($isValid -eq $true) { - Write-Host "`t`t[+] Document content types" -fore green - } else { - Write-Host "`t`t[-] Document content types" -fore red - $errors++ - #exit - } - - #RETURN $isValid -} - -function ProcessWeb($web) { - # Write-Host $web.ServerRelativeUrl - - - CheckPagesLibraryContentTypes $web - CheckDocumentaLibraryContentTypes $web -} - -function ProcessSPWebRecursively([Microsoft.SharePoint.SPWeb] $web) -{ - Write-Host "Processing web: [$($web.Url)]" -fore Gray - - ProcessWeb($web) - - $subwebs = $web.GetSubwebsForCurrentUser() - - foreach($subweb in $subwebs) - { - ProcessSPWebRecursively($subweb) - $subweb.Dispose() - } -} - -Write-Host "Processing web: [$webUrl] with all subwebs" -fore Green -ProcessSPWebRecursively $web - -Write-Host "Done" \ No newline at end of file diff --git a/SPMeta2/SPMeta2.Regression.Tests/PSScripts/200 - Configure M2 Test Environment.ps1 b/SPMeta2/SPMeta2.Regression.Tests/PSScripts/200 - Configure M2 Test Environment.ps1 deleted file mode 100644 index bfb0d0bc5..000000000 --- a/SPMeta2/SPMeta2.Regression.Tests/PSScripts/200 - Configure M2 Test Environment.ps1 +++ /dev/null @@ -1,17 +0,0 @@ -cls - -cd "$PSScriptRoot" - -$PSScriptRoot - -. "$PSScriptRoot\_config.ps1" -. "$PSScriptRoot\_sys.common.ps1" - -Write-Host "Configuring M2 test environment with the following settings:" -fore Green -M2ShowSettings $g_M2TestEnvironment - -# CSOM, SSOM, O365 -#SetupSPMeta2RegressionTestEnvironment "SSOM" -#SetupSPMeta2RegressionTestEnvironment "CSOM" -#SetupSPMeta2RegressionTestEnvironment "O365" -SetupSPMeta2RegressionTestEnvironment "O365v16" \ No newline at end of file diff --git a/SPMeta2/SPMeta2.Regression.Tests/PSScripts/300 - Configure M2 Grid.ps1 b/SPMeta2/SPMeta2.Regression.Tests/PSScripts/300 - Configure M2 Grid.ps1 deleted file mode 100644 index 11ebbb607..000000000 --- a/SPMeta2/SPMeta2.Regression.Tests/PSScripts/300 - Configure M2 Grid.ps1 +++ /dev/null @@ -1,97 +0,0 @@ -cls - -$s_runnerLibrary = "SPMeta2.Containers.CSOM.dll" -#$s_runnerLibrary = "SPMeta2.Containers.SSOM.dll" - -$s_username = [System.Environment]::GetEnvironmentVariable("SPMeta2_Grid_UserName", "Machine") -$s_password = [System.Environment]::GetEnvironmentVariable("SPMeta2_Grid_UserPassword", "Machine") -$s_nodeList = [System.Environment]::GetEnvironmentVariable("SPMeta2_Grid_Nodes", "Machine") - -$s_passwordSecure = $s_password | convertto-securestring -Force -AsPlainText - -$s_cred = new-object -typename System.Management.Automation.PSCredential ` - -argumentlist $s_username, $s_passwordSecure - -$s_nodes = $s_nodeList.Split(',') - -Configuration M2GridRunnerLibrariesClean { - - param( - $nodeName, - $runnerLibraries - ) - - Import-DscResource –ModuleName 'PSDesiredStateConfiguration' - - Node $nodeName { - - Environment RunnerLibraryRemove { - Name = "SPMeta2_RunnerLibraries" - Ensure = 'Absent' - } - } - - Node $nodeName { - - Environment SPMeta2_SSOM_WebApplicationUrlsRemove { - Name = "SPMeta2_SSOM_WebApplicationUrls" - Ensure = 'Absent' - } - } -} - -Configuration M2GridRunnerLibraries { - - param( - $nodeName, - $runnerLibraries, - $webAppUrls - ) - - Import-DscResource –ModuleName 'PSDesiredStateConfiguration' - - Node $nodeName { - - Environment RunnerLibrary { - Name = "SPMeta2_RunnerLibraries" - Ensure = 'Present' - Value = $runnerLibraries - } - } - - Node $nodeName { - - Environment SPMeta2_SSOM_WebApplicationUrls { - Name = "SPMeta2_SSOM_WebApplicationUrls" - Ensure = 'Present' - Value = $webAppUrls - } - } -} - -Remove-item M2GridRunnerLibrariesClean -Force -Recurse -Confirm:$false -Remove-item M2GridRunnerLibraries -Force -Recurse -Confirm:$false - -foreach($node in $s_nodes) { - - Write-Host "Compiling DSC for node [$node] and library:[$s_runnerLibrary]" -fore green - - M2GridRunnerLibrariesClean -nodeName $node ` - -runnerLibraries $s_runnerLibrary | out-null - - M2GridRunnerLibraries -nodeName $node ` - -webAppUrls ("http://" + $node + ":31417") ` - -runnerLibraries $s_runnerLibrary | out-null -} - -Write-Host "Applying DSC with library:[$s_runnerLibrary ]" -fore green - -Start-DscConfiguration M2GridRunnerLibrariesClean -Credential $s_cred ` - -Wait ` - -Verbose - -Start-DscConfiguration M2GridRunnerLibraries -Credential $s_cred ` - -Wait ` - -Verbose - - diff --git a/SPMeta2/SPMeta2.Regression.Tests/PSScripts/_config.ps1 b/SPMeta2/SPMeta2.Regression.Tests/PSScripts/_config.ps1 deleted file mode 100644 index 1b6b77efc..000000000 --- a/SPMeta2/SPMeta2.Regression.Tests/PSScripts/_config.ps1 +++ /dev/null @@ -1,120 +0,0 @@ -Add-Type -TypeDefinition @" - public enum EnvironmentType - { - SSOM, - CSOM, - O365, - O365v16 - } -"@ - -# defines configs for new 'sandbox' web application -$g_M2WebAppSettings = New-Object PSObject -Property @{ - - # -- GLOBAL SETTINGS -- - # current machine/domain name - MachineName = [Environment]::MachineName - DomainName = [Environment]::UserDomainName - - # sql server address - SqlServerMachineName = [Environment]::MachineName - - # -- WEB APP SETTINGS -- - # should web app or site be recreated - - ShouldRecreateWebApplicaiton = $true - - # port and ap account for the web app - WebApplicationPort = 31415 - WebApplicationPoolAccountName = "$([Environment]::UserDomainName)\sp_farm" - - - # -- SITE COLLECTION SETTINGS -- - # should site colleciton be recreated - - ShouldRecreateSiteCollection = $true - SiteCollectionTemplate = "BLANKINTERNET#0" - SiteCollectionLCID = 1033 - SiteCollectionOwner = "$([Environment]::UserDomainName)\$([Environment]::UserName)" - SiteCollectionAdministrators = @( - "$([Environment]::UserDomainName)\administrator", - "$([Environment]::UserDomainName)\sp_admin", - "$([Environment]::UserDomainName)\sp_farm" - ) -} - -# defines config for the regression test -$g_M2TestEnvironment = New-Object PSObject -Property @{ - - # -- GLOBAL SETTINGS -- - # current environment type - # CSOM, SSOM or O365 - EnvironmentType = "SSOM" - - #O365 specific settings - O365UserName = "support@subpointsolutions.com" - O365UserPassword = "su1sbhsbhu8wxvKQ" - - O365SiteUrls = @( - "https://subpointsolutions.sharepoint.com/sites/calc-col" - ) - - O365WebUrls = @( - "https://subpointsolutions.sharepoint.com/sites/calc-col" - ) - - RandomBalancedUrls = @( - -) - - O365DefaultTestUserLogins = @( - "" - ) - - - # CSOM specific settings - CSOMWebApplicationUrls = @( - "http://$([Environment]::MachineName):$($g_M2WebAppSettings.WebApplicationPort)" - #"http://$([Environment]::MachineName)" - #"http://portal" - ) - - CSOMSiteUrls = @( - "http://$([Environment]::MachineName):$($g_M2WebAppSettings.WebApplicationPort)" - #"http://$([Environment]::MachineName)" - #"http://portal" - ) - - CSOMWebUrls = @( - "http://$([Environment]::MachineName):$($g_M2WebAppSettings.WebApplicationPort)" - #"http://$([Environment]::MachineName)" - #"http://portal" - ) - - # SSOM specific settings - SSOMWebApplicationUrls = @( - "http://$([Environment]::MachineName):$($g_M2WebAppSettings.WebApplicationPort)" - ) - - SSOMSiteUrls = @( - "http://$([Environment]::MachineName):$($g_M2WebAppSettings.WebApplicationPort)" - ) - - SSOMWebUrls = @( - "http://$([Environment]::MachineName):$($g_M2WebAppSettings.WebApplicationPort)" - ) - - OO365TestLogins = @( - "" - ) - - OnPremTestActiveDirectoryLogins = @( - "$([Environment]::UserDomainName)\administrator", - "$([Environment]::UserDomainName)\sp_admin", - "$([Environment]::UserDomainName)\sp_farm" - ) - - OnPremTestActiveDirectoryGroups = @( - "$([Environment]::UserDomainName)\test-g1" - ) -} \ No newline at end of file diff --git a/SPMeta2/SPMeta2.Regression.Tests/PSScripts/_sys.common.ps1 b/SPMeta2/SPMeta2.Regression.Tests/PSScripts/_sys.common.ps1 deleted file mode 100644 index ae5897948..000000000 --- a/SPMeta2/SPMeta2.Regression.Tests/PSScripts/_sys.common.ps1 +++ /dev/null @@ -1,535 +0,0 @@ -. "$PSScriptRoot\_config.ps1" - -Write-Host "Loading SharePoint API" -fore Green -$ver = $host | select version -if ($ver.Version.Major -gt 1) {$host.Runspace.ThreadOptions = "ReuseThread"} -if ((Get-PSSnapin "Microsoft.SharePoint.PowerShell" -ErrorAction SilentlyContinue) -eq $null) { - Add-PSSnapin "Microsoft.SharePoint.PowerShell" -} - - -function M2ShowSettings($obj) { - - $props = $obj | Get-Member -type NoteProperty - - foreach($prop in $props) { - $value=$obj."$($prop.Name)" - Write-Host "`t[$($prop.Name)]:`t[$value]" -fore Gray - } -} - -#script setting -$g_script_RecreateWebApp = $g_M2WebAppSettings.ShouldRecreateWebApplicaiton -$g_script_RecreateSiteCollections = $g_M2WebAppSettings.ShouldRecreateSiteCollection - -#global settings -$g_port = $g_M2WebAppSettings.WebApplicationPort - -$g_machineName = $g_M2WebAppSettings.MachineName -$g_DomainName = $g_M2WebAppSettings.DomainName -$g_webAppDatabaseServerName = $g_M2WebAppSettings.SqlServerMachineName - -# web app settings - - $g_webAppUrl = $g_machineName + ":" + $g_port; - - $g_webAppName = "SPMeta2 Sandbox - $g_port" - $g_webAppPool = "$g_machineName - $g_port" - $g_webAppHostHeader = $g_machineName - $g_webAppPort = $g_port - - # should be managed account - $g_webAppAppPoolAccount = $g_M2WebAppSettings.WebApplicationPoolAccountName - - #$g_webAppDatabaseServerName = $g_machineName - $g_webAppDatabaseName = "WSS_Content_$g_port" - -# site settings - - $g_siteCollectionOwner = $g_M2WebAppSettings.SiteCollectionOwner - - $g_siteCollectionTemplate = $g_M2WebAppSettings.SiteCollectionTemplate - $g_siteCollectionLanguage = $g_M2WebAppSettings.SiteCollectionLCID - - $g_siteUrls = @() - $g_siteUrls += ("http://" + $g_machineName + ":" + $g_port); - $g_siteUrls += ("http://" + $g_machineName + ":" + $g_port + "/sites/m2"); - -# subweb settings - - $g_webTemplate = "STS#0" - - - $g_siteRelativeWebUrls = @() - $g_siteRelativeWebUrls += "/first" - $g_siteRelativeWebUrls += "/first/second" - $g_siteRelativeWebUrls += "/first/second/third" - - -# creates a new web app -function CreateWebApplication() -{ - $WebAppName = $g_webAppName - $WebAppAppPool = $g_webAppPool - - $WebAppHostHeader = $g_webAppHostHeader - $WebAppPort = $g_webAppPort - - $WebAppAppPoolAccount = $g_webAppAppPoolAccount - $WebAppDatabaseName = $g_webAppDatabaseName - $WebAppDatabaseServer = $g_webAppDatabaseServerName - - $WebAppName - $WebAppPort - $WebAppHostHeader - $WebAppAppPool - (Get-SPManagedAccount $WebAppAppPoolAccount) - $WebAppDatabaseName - $WebAppDatabaseServer - - New-SPWebApplication -Name $WebAppName -Port $WebAppPort -HostHeader $WebAppHostHeader -URL $WebAppHostHeader -ApplicationPool $WebAppAppPool -ApplicationPoolAccount (Get-SPManagedAccount $WebAppAppPoolAccount) -DatabaseName $WebAppDatabaseName -DatabaseServer $WebAppDatabaseServer -} - -# ensures security groups on the site -function EnsureSecurityGroup($web, $groupName) { - - $group = $web.SiteGroups[$groupName]; - - if($group -eq $null) { - $web.SiteGroups.Add($groupName, $web.Site.Owner, $web.Site.Owner, $groupName) - $group = $web.SiteGroups[$groupName]; - } - - return $group -} - -# ensures a web app -function EnsureSPMeta2SandboxWebApplication($recreate) { - - $webApp = GetSPMeta2SandboxWebApp $g_webAppUrl - - if($webApp -eq $null) { - - Write-Host "Cannot find web application. at URL:[$g_webAppUrl]. Creating one." -fore yellow - - CreateWebApplication - - } else { - - Write-Host "Web application at URL:[$g_webAppUrl] exists." -fore green - - if($recreate -eq $true) { - if($webApp -ne $null) { - - Write-Host "Deleting web application at URL:[$g_webAppUrl]." -fore yellow - Remove-SPWebApplication $webApp -Confirm:$false - - CreateWebApplication - } - } - - } -} - -function GetSPMeta2SandboxWebApp($url) { - return Get-SPWebApplication | Where-Object { $_.Url.ToUpper().Contains($url.ToUpper()) -eq $true } -} - -function LookupWebSite($url) -{ - $webApp = GetSPMeta2SandboxWebApp $g_webAppUrl - - return $webApp.Sites | Where-Object { $_.Url.ToUpper().EndsWith($url.ToUpper()) -eq $true } -} - -function LookupWeb($site, $url) { - - $web = $site.AllWebs | Where-Object { $_.Url.ToUpper().EndsWith($url.ToUpper()) -eq $true } - - return $web -} - -function CreateWeb( $url) { - - $web = New-SPWeb $url -Template $g_webTemplate - return $web -} - -function CreateSiteCollection($url) { - - $SiteCollectionName = "Root" - $SiteCollectionURL = $url - $SiteCollectionTemplate = $g_siteCollectionTemplate - $SiteCollectionLanguage = $g_siteCollectionLanguage - $SiteCollectionOwner = $g_siteCollectionOwner - - $site = New-SPSite -URL $SiteCollectionURL -OwnerAlias $SiteCollectionOwner -Language $SiteCollectionLanguage -Template $SiteCollectionTemplate -Name $SiteCollectionName - - return $site; -} - -function EnableFeature($web, $id) { - - $f = $web.Features[[guid]$id] - - if($f -eq $null) { - Enable-SPFeature -Identity $id -url $web.Url -Confirm:$false -force - } -} - -function DisableFeature($web, $id) { - - $f = $web.Features[[guid]$id] - - if($f -ne $null) { - Disable-SPFeature -Identity $id -url $web.Url -Confirm:$false -force - } -} - -function EnsureSiteCollectionAdministrators($site, $logins) { - - foreach($login in $logins) { - - Write-Host "`tEnsuring site admin: $login" -ForegroundColor Gray; - - $user = $site.RootWeb.EnsureUser($login); - if($user.IsSiteAdmin -ne $true) - { - $user.IsSiteAdmin = $true; - $user.Update(); - #Write-Host "User is now site collection admin for $site" -ForegroundColor Green; - } - else - { - #Write-Host "User is already site collection admin for $site" -ForegroundColor DarkYellow; - } - - #Write-Host "Current Site Collection Admins for site: " $site.Url " " $site.RootWeb.SiteAdministrators; - } - -} - -function EnsureSPMeta2SandboxSiteCollections($recreate) { - - Write-Host "" - Write-Host "Ensuring sandbox site collections" -fore Green - - $siteUrls = $g_siteUrls - - foreach($url in $siteUrls) { - - $site = LookupWebSite $url - - if($recreate -eq $true) { - - if( $site -ne $null) { - - Write-Host "Deleting site collection [$url]" -fore DarkYellow - - $siteId = $site.ID - - Remove-spsite $siteId -Confirm:$false - - $site = $null - } - } - - if($site -eq $null) { - - Write-Host "Site [$url] does not exist." -fore Gray - Write-Host "Creating site: [$url]" -fore DarkYellow - - $site = CreateSiteCollection $url - } else { - - Write-Host "Site [$url] exists." -fore Gray - - } - - EnsureSiteCollectionAdministrators $site $g_M2WebAppSettings.SiteCollectionAdministrators - EnsureAssociatedGroups $site.RootWeb - - $webUrls = $g_siteRelativeWebUrls - $rootWeb = $site.RootWeb - - # disabling MDS feature - DisableFeature $rootWeb "87294c72-f260-42f3-a41b-981a2ffce37a" - # eabling wiki page lib - EnableFeature $rootWeb "00bfea71-d8fe-4fec-8dad-01c19a6e4053" - - foreach($webUrl in $webUrls) { - - $fullwebUrl = $url + $webUrl - - $web = LookupWeb $site $fullwebUrl - - if($web -eq $null) { - - Write-Host "`tWeb [$fullwebUrl] does not exist." -fore Gray - Write-Host "`tCreating web: [$fullwebUrl]" -fore DarkYellow - - $web = CreateWeb $fullwebUrl - - } else { - - Write-Host "`tWeb [$fullwebUrl] exists." -fore Gray - - } - - Write-Host "Ensuring Associated groups..." - - if($web.HasUniqueRoleAssignments -eq $false) { - $web.RoleDefinitions.BreakInheritance($true,$true); - } - - EnsureAssociatedGroups $web - - DisableFeature $web "87294c72-f260-42f3-a41b-981a2ffce37a" - EnableFeature $web "00bfea71-d8fe-4fec-8dad-01c19a6e4053" - - } - - Write-Host "" - } -} - -function EnsureAssociatedGroups($web) { - - $assOwnerGroup = EnsureSecurityGroup $web "SPMeta2 AssociatedOwnerGroup" - $web.AssociatedOwnerGroup = $assOwnerGroup - - $assMemberGroup = EnsureSecurityGroup $web "SPMeta2 AssociatedMemberGroup" - $web.AssociatedMemberGroup = $assMemberGroup - - $assVisitorGroup = EnsureSecurityGroup $web "SPMeta2 AssociatedVisitorGroup" - $web.AssociatedVisitorGroup = $assVisitorGroup - - $web.Update() - -} - -# test environment settings - -$envType = $g_M2TestEnvironment.EnvironmentType -#$o365RuntimePath = "$PSScriptRoot\..\..\SPMeta2.Dependencies\SharePoint\O365 - 16.1.3912.1204" -$o365RuntimePath = "$PSScriptRoot\..\..\SPMeta2.Dependencies\SharePoint\O365 - 16.1.5715.1200\NET45" - -$o365_UserName = $g_M2TestEnvironment.O365UserName -$o365_UserPassword = $g_M2TestEnvironment.O365UserPassword - -$serverName = $g_M2WebAppSettings.MachineName -$sqlServerName = $g_M2WebAppSettings.SqlServerMachineName - -$serverName = [Environment]::MachineName - -function SetSqlServerName($name) -{ - SetEnvironmentVar "SPMeta2_DefaultSqlServerName" $name -} - -function SetTestOnPremTestLogins() -{ - $logins = $g_M2TestEnvironment.OnPremTestActiveDirectoryLogins - $loginsString = [string]::Join(",", $logins); - - SetEnvironmentVar "SPMeta2_DefaultTestUserLogins" $loginsString -} - -function SetTestO365Logins() { - - $logins = $g_M2TestEnvironment.O365DefaultTestUserLogins - $loginsString = [string]::Join(",", $logins); - - SetEnvironmentVar "SPMeta2_DefaultTestUserLogins" $loginsString - -} - -function SetTestOnPremTestADGroups() -{ - $groups = $g_M2TestEnvironment.OnPremTestActiveDirectoryGroups - $groupsString = [string]::Join(",", $groups); - - SetEnvironmentVar "SPMeta2_DefaultTestADGroups" $groupsString -} - -function SetEnvironmentVar($name, $value) { - - Write-Host "`tSetting [$name] - [$value]" -fore Gray - [Environment]::SetEnvironmentVariable($name, $value, "Machine") -} - -function SetSSOMManagedMetadataApplicationParams($siteUrl) { - - $session = Get-SPTaxonomySession -Site $siteUrl - $store = $session.DefaultSiteCollectionTermStore; - - Write-Host "Setting up taxonomy store vars" -fore Yellow - - SetEnvironmentVar "SPMeta2_DefaultTaxonomyStoreId" $store.Id - SetEnvironmentVar "SPMeta2_DefaultTaxonomyStoreName" $store.Name -} - -function SetupSSOMEnvironment() { - - Write-Host "Setting up SSOM environment" -fore Yellow - - - SetTestOnPremTestLogins - SetTestOnPremTestADGroups - - SetEnvironmentVar "SPMeta2_RunnerLibraries" "SPMeta2.Containers.SSOM.dll" - SetSqlServerName $sqlServerName - - $webAppUrls = $g_M2TestEnvironment.SSOMWebApplicationUrls - $siteUrls = $g_M2TestEnvironment.SSOMSiteUrls - $webUrls = $g_M2TestEnvironment.SSOMWebUrls - - SetSSOMManagedMetadataApplicationParams $siteUrls[0] - - $webAppUrlsValue = $webAppUrls -join ',' - $siteUrlsValue = $siteUrls -join ',' - $webUrlsValue = $webUrls -join ',' - - SetEnvironmentVar "SPMeta2_SSOM_WebApplicationUrls" $webAppUrlsValue - SetEnvironmentVar "SPMeta2_SSOM_SiteUrls" $siteUrlsValue - SetEnvironmentVar "SPMeta2_SSOM_WebUrls" $webUrlsValue -} - -function SetupCSOMEnvironment() { - - - Write-Host "Setting up CSOM environment" -fore Yellow - - SetTestOnPremTestLogins - SetTestOnPremTestADGroups - - SetEnvironmentVar "SPMeta2_RunnerLibraries" "SPMeta2.Containers.CSOM.dll" - SetSqlServerName $sqlServerName - - $webAppUrls = $g_M2TestEnvironment.CSOMWebApplicationUrls - $siteUrls = $g_M2TestEnvironment.CSOMSiteUrls - $webUrls = $g_M2TestEnvironment.CSOMWebUrls - - SetSSOMManagedMetadataApplicationParams $siteUrls[0] - - $webAppUrlsValue = $webAppUrls -join ',' - $siteUrlsValue = $siteUrls -join ',' - $webUrlsValue = $webUrls -join ',' - - SetEnvironmentVar "SPMeta2_CSOM_SiteUrls" $siteUrlsValue - SetEnvironmentVar "SPMeta2_CSOM_WebUrls" $webUrlsValue - SetEnvironmentVar "SPMeta2_CSOM_UserName" "" - SetEnvironmentVar "SPMeta2_CSOM_Password" "" -} - -function InitO365Runtime() { - $files = [System.IO.Directory]::GetFiles($o365RuntimePath, "*.dll") - - foreach($filePath in $files) { - Write-Host "`tLoading assembly: [$filePath]" - $a = [System.Reflection.Assembly]::LoadFile($filePath) - } -} - -function SetO365MManagedMetadataApplicationParams($siteUrl) { - - InitO365Runtime - - $secO365_UserPassword = ConvertTo-SecureString $o365_UserPassword -AsPlainText -Force - - $context = New-Object Microsoft.SharePoint.Client.ClientContext($siteUrl) - $credentials = New-Object Microsoft.SharePoint.Client.SharePointOnlineCredentials($o365_UserName, $secO365_UserPassword) - - $context.Credentials = $credentials - - $taxSession = [Microsoft.SharePoint.Client.Taxonomy.TaxonomySession]::GetTaxonomySession($context) - $store = $taxSession.GetDefaultSiteCollectionTermStore(); - - $context.Load($store) - $context.ExecuteQuery() - - Write-Host "Setting up taxonomy store vars" -fore Yellow - - SetEnvironmentVar "SPMeta2_DefaultTaxonomyStoreId" $store.Id - SetEnvironmentVar "SPMeta2_DefaultTaxonomyStoreName" $store.Name -} - -function SetO365RandomBalancedUrls() { - $urls = $g_M2TestEnvironment.RandomBalancedUrls -join ',' - - SetEnvironmentVar "SPMeta2_O365_RandomBalancedUrls" $urls -} - -function SetupO365v16Environment() { - - Write-Host "Setting up O365 environment" -fore Yellow - - SetEnvironmentVar "SPMeta2_RunnerLibraries" "SPMeta2.Containers.O365v16.dll" - - $o365_siteUrls = $g_M2TestEnvironment.O365SiteUrls - $o365_webUrls = $g_M2TestEnvironment.O365WebUrls - - SetO365MManagedMetadataApplicationParams $o365_siteUrls[0] - - $o365_siteUrlsValue = $o365_siteUrls -join ',' - $o365_webUrlsValue = $o365_webUrls -join ',' - - - SetEnvironmentVar "SPMeta2_O365_SiteUrls" $o365_siteUrlsValue - SetEnvironmentVar "SPMeta2_O365_WebUrls" $o365_webUrlsValue - SetEnvironmentVar "SPMeta2_O365_UserName" $g_M2TestEnvironment.O365UserName - SetEnvironmentVar "SPMeta2_O365_Password" $g_M2TestEnvironment.O365UserPassword -} - -function SetupO365Environment() { - - Write-Host "Setting up O365 environment" -fore Yellow - - SetTestO365Logins - SetO365RandomBalancedUrls - - SetEnvironmentVar "SPMeta2_RunnerLibraries" "SPMeta2.Containers.O365.dll" - - $o365_siteUrls = $g_M2TestEnvironment.O365SiteUrls - $o365_webUrls = $g_M2TestEnvironment.O365WebUrls - - SetO365MManagedMetadataApplicationParams $o365_siteUrls[0] - - $o365_siteUrlsValue = $o365_siteUrls -join ',' - $o365_webUrlsValue = $o365_webUrls -join ',' - - SetEnvironmentVar "SPMeta2_O365_SiteUrls" $o365_siteUrlsValue - SetEnvironmentVar "SPMeta2_O365_WebUrls" $o365_webUrlsValue - SetEnvironmentVar "SPMeta2_O365_UserName" $g_M2TestEnvironment.O365UserName - SetEnvironmentVar "SPMeta2_O365_Password" $g_M2TestEnvironment.O365UserPassword -} - -function SetupSPMeta2RegressionTestEnvironment($envType) { - - if($envType -eq $null) { - $envType = $g_M2TestEnvironment.EnvironmentType - } - - Write-Host "Setting up [$envType] environment." -fore Green - - switch($envType) - { - "SSOM" { - SetupSSOMEnvironment - } - - "CSOM" { - SetupCSOMEnvironment - } - - "O365" { - SetupO365Environment - } - - "O365v16" { - SetupO365v16Environment - } - } - - Write-Host "Setting up [$envType] environment completed." -fore Green -} diff --git a/SPMeta2/SPMeta2.Regression.Tests/SPMeta2.Regression.Tests.csproj b/SPMeta2/SPMeta2.Regression.Tests/SPMeta2.Regression.Tests.csproj index 16d36594f..f0d27d060 100644 --- a/SPMeta2/SPMeta2.Regression.Tests/SPMeta2.Regression.Tests.csproj +++ b/SPMeta2/SPMeta2.Regression.Tests/SPMeta2.Regression.Tests.csproj @@ -88,6 +88,7 @@ + @@ -355,6 +356,7 @@ SPMeta2.Containers.CSOM.dll + Always SPMeta2.Containers.O365v16.dll @@ -540,6 +542,18 @@ _Dependencies\spmeta2-csom-regression-2013\SPMeta2.Regression.CSOM.dll Always + + SPMeta2.Regression.SSOM.Standard.dll + Always + + + SPMeta2.Regression.SSOM.dll + Always + + + SPMeta2.SSOM.Standard.dll + Always + SPMeta2.SSOM.dll Always @@ -552,8 +566,6 @@ SPMeta2.dll Always - - @@ -573,9 +585,6 @@ - - - Always diff --git a/SPMeta2/SPMeta2.Regression.Tests/SPMeta2.Regression.Tests.dll.config b/SPMeta2/SPMeta2.Regression.Tests/SPMeta2.Regression.Tests.dll.config index f38f061fb..c55a301b3 100644 --- a/SPMeta2/SPMeta2.Regression.Tests/SPMeta2.Regression.Tests.dll.config +++ b/SPMeta2/SPMeta2.Regression.Tests/SPMeta2.Regression.Tests.dll.config @@ -31,6 +31,7 @@ switchName="sourceSwitch" switchType="System.Diagnostics.SourceSwitch"> + @@ -41,19 +42,22 @@ initializeData="spmeta2.log"> + diff --git a/SPMeta2/SPMeta2/ModelHandlers/ModelHandlerBase.cs b/SPMeta2/SPMeta2/ModelHandlers/ModelHandlerBase.cs index eae4c6e98..9363bc908 100644 --- a/SPMeta2/SPMeta2/ModelHandlers/ModelHandlerBase.cs +++ b/SPMeta2/SPMeta2/ModelHandlers/ModelHandlerBase.cs @@ -1,118 +1,121 @@ -using System; -using SPMeta2.Common; -using SPMeta2.Definitions; -using SPMeta2.Services; - -namespace SPMeta2.ModelHandlers -{ - /// - /// Base handler for model provision. - /// - public abstract class ModelHandlerBase - { - #region constructors - - public ModelHandlerBase() - { - TraceService = ServiceContainer.Instance.GetService(); - } - - #endregion - - #region properties - - protected static TraceServiceBase TraceService { get; set; } - - /// - /// Type of the definition which is handled by current model handler. - /// - public abstract Type TargetType { get; } - - #endregion - - #region events - - public EventHandler OnModelEvent; - - #endregion - - #region methods - - /// - /// Handles model provision under particular modelHost. - /// - /// - /// - public virtual void DeployModel(object modelHost, DefinitionBase model) - { - - } - - /// - /// Handles model retraction under particular model host. - /// - /// - /// - public virtual void RetractModel(object modelHost, DefinitionBase model) - { - - } - - /// - /// Resolves a new model host per particular child definition type. - /// - /// - public virtual void WithResolvingModelHost(ModelHostResolveContext context) - { - context.Action(context.ModelHost); - } - - /// - /// Promotes a model event outside of the model handler. - /// - /// - /// - protected void InvokeOnModelEvent(object sender, ModelEventArgs args) - { - TraceService.VerboseFormat((int)LogEventId.CoreCalls, "Entering InvokeOnModelEvent with sender: [{0}] and args: [{1}]", - new object[] { sender, args }); - - if (OnModelEvent != null) - { - TraceService.VerboseFormat((int)LogEventId.CoreCalls, - "OnModelEvent is not NULL. Calling OnModelEvent with sender: [{0}] and args: [{1}]", - new object[] { sender, args }); - - OnModelEvent.Invoke(this, args); - } - else - { - TraceService.Verbose((int)LogEventId.CoreCalls, "OnModelEvent is NULL. Skipping."); - } - - TraceService.VerboseFormat((int)LogEventId.CoreCalls, "Leaving InvokeOnModelEvent with sender: [{0}] and args: [{1}]", - new object[] { sender, args }); - } - - /// - /// Promotes a model event outside of the model handler. - /// - /// - /// - /// - /// - [Obsolete("Use InvokeOnModelEvents((object sender, ModelEventArgs args) with passing full ModelEventArgs")] - protected void InvokeOnModelEvent(TSPObject rawObject, ModelEventType eventType) - { - InvokeOnModelEvent(this, new ModelEventArgs - { - Object = rawObject, - EventType = eventType - }); - } - - #endregion - - - } -} +using System; +using SPMeta2.Common; +using SPMeta2.Definitions; +using SPMeta2.Services; +using SPMeta2.Services.Impl; + +namespace SPMeta2.ModelHandlers +{ + /// + /// Base handler for model provision. + /// + public abstract class ModelHandlerBase + { + #region constructors + + public ModelHandlerBase() + { + TraceService = ServiceContainer.Instance.GetService(); + TryRetryService = ServiceContainer.Instance.GetService() ?? new DefaultTryRetryService(); + } + + #endregion + + #region properties + + protected static TryRetryServiceBase TryRetryService { get; set; } + protected static TraceServiceBase TraceService { get; set; } + + /// + /// Type of the definition which is handled by current model handler. + /// + public abstract Type TargetType { get; } + + #endregion + + #region events + + public EventHandler OnModelEvent; + + #endregion + + #region methods + + /// + /// Handles model provision under particular modelHost. + /// + /// + /// + public virtual void DeployModel(object modelHost, DefinitionBase model) + { + + } + + /// + /// Handles model retraction under particular model host. + /// + /// + /// + public virtual void RetractModel(object modelHost, DefinitionBase model) + { + + } + + /// + /// Resolves a new model host per particular child definition type. + /// + /// + public virtual void WithResolvingModelHost(ModelHostResolveContext context) + { + context.Action(context.ModelHost); + } + + /// + /// Promotes a model event outside of the model handler. + /// + /// + /// + protected void InvokeOnModelEvent(object sender, ModelEventArgs args) + { + TraceService.VerboseFormat((int)LogEventId.CoreCalls, "Entering InvokeOnModelEvent with sender: [{0}] and args: [{1}]", + new object[] { sender, args }); + + if (OnModelEvent != null) + { + TraceService.VerboseFormat((int)LogEventId.CoreCalls, + "OnModelEvent is not NULL. Calling OnModelEvent with sender: [{0}] and args: [{1}]", + new object[] { sender, args }); + + OnModelEvent.Invoke(this, args); + } + else + { + TraceService.Verbose((int)LogEventId.CoreCalls, "OnModelEvent is NULL. Skipping."); + } + + TraceService.VerboseFormat((int)LogEventId.CoreCalls, "Leaving InvokeOnModelEvent with sender: [{0}] and args: [{1}]", + new object[] { sender, args }); + } + + /// + /// Promotes a model event outside of the model handler. + /// + /// + /// + /// + /// + [Obsolete("Use InvokeOnModelEvents((object sender, ModelEventArgs args) with passing full ModelEventArgs")] + protected void InvokeOnModelEvent(TSPObject rawObject, ModelEventType eventType) + { + InvokeOnModelEvent(this, new ModelEventArgs + { + Object = rawObject, + EventType = eventType + }); + } + + #endregion + + + } +} diff --git a/SPMeta2/SPMeta2/SPMeta2.csproj b/SPMeta2/SPMeta2/SPMeta2.csproj index 69e0f8216..f4388cb1f 100644 --- a/SPMeta2/SPMeta2/SPMeta2.csproj +++ b/SPMeta2/SPMeta2/SPMeta2.csproj @@ -372,6 +372,7 @@ + @@ -422,6 +423,7 @@ + diff --git a/SPMeta2/SPMeta2/ServiceContainer.cs b/SPMeta2/SPMeta2/ServiceContainer.cs index 2f5daf153..1488763c6 100644 --- a/SPMeta2/SPMeta2/ServiceContainer.cs +++ b/SPMeta2/SPMeta2/ServiceContainer.cs @@ -53,6 +53,8 @@ private void InitServices() RegisterService(typeof(FluentModelValidationServiceBase), new DefaultFluentModelValidationService()); RegisterService(typeof(ModelStatInfoServiceBase), new DefaultModelStatInfoService()); + + RegisterService(typeof(TryRetryServiceBase), new DefaultTryRetryService()); } #endregion diff --git a/SPMeta2/SPMeta2/Services/Impl/DefaultTryRetryService.cs b/SPMeta2/SPMeta2/Services/Impl/DefaultTryRetryService.cs new file mode 100644 index 000000000..b63799e35 --- /dev/null +++ b/SPMeta2/SPMeta2/Services/Impl/DefaultTryRetryService.cs @@ -0,0 +1,75 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading; + + +namespace SPMeta2.Services.Impl +{ + public class DefaultTryRetryService : TryRetryServiceBase + { + #region constructors + + public DefaultTryRetryService() + { + MaxRetryCount = 10; + RetryTimeoutInMilliseconds = 1000; + + DefaultRetryWaiter = (currentRetryIndex, maxRetryIndex, defaultTimeoutInMilliseconds) => + { + Thread.Sleep(defaultTimeoutInMilliseconds); + }; + } + + #endregion + + #region properties + + public int MaxRetryCount { get; set; } + public int RetryTimeoutInMilliseconds { get; set; } + + public Action DefaultRetryWaiter { get; set; } + protected TraceServiceBase TraceService + { + get + { + return ServiceContainer.Instance.GetService(); + } + } + + #endregion + + public override void TryWithRetry(Func action) + { + TryWithRetry(action, MaxRetryCount, RetryTimeoutInMilliseconds); + } + + public override void TryWithRetry(Func action, int maxTryCount, int retryTimeoutInMilliseconds) + { + TryWithRetry(action, maxTryCount, retryTimeoutInMilliseconds, this.DefaultRetryWaiter); + } + + public override void TryWithRetry(Func action, + int maxTryCount, int retryTimeoutInMilliseconds, + Action waiter) + { + var currentTryIndex = 0; + + while (action() != true) + { + TraceService.Warning((int)LogEventId.ModelProvision, + string.Format("Coudn't perform action. Waiting and retrying [{1}/{2}]", + RetryTimeoutInMilliseconds, + currentTryIndex, + MaxRetryCount)); + + if (currentTryIndex > retryTimeoutInMilliseconds) + break; + + waiter(currentTryIndex, maxTryCount, retryTimeoutInMilliseconds); + currentTryIndex++; + } + } + } +} diff --git a/SPMeta2/SPMeta2/Services/Impl/TraceSourceService.cs b/SPMeta2/SPMeta2/Services/Impl/TraceSourceService.cs index dcb685e9b..648334f4c 100644 --- a/SPMeta2/SPMeta2/Services/Impl/TraceSourceService.cs +++ b/SPMeta2/SPMeta2/Services/Impl/TraceSourceService.cs @@ -132,7 +132,7 @@ public override void Verbose(int id, object message, Exception exception) #region utils - protected virtual void TraceEvent(int id, TraceEventType messageType, object message, Exception exception) + protected virtual string GetTraceEventString(int id, TraceEventType messageType, object message, Exception exception) { var traceString = string.Empty; var messageString = message == null ? string.Empty : message.ToString(); @@ -156,8 +156,14 @@ protected virtual void TraceEvent(int id, TraceEventType messageType, object mes traceString = string.Format("{0}", subMessage); } - TraceSource.TraceEvent(messageType, id, traceString); + return traceString; + } + protected virtual void TraceEvent(int id, TraceEventType messageType, object message, Exception exception) + { + var traceString = GetTraceEventString(id, messageType, message, exception); + + TraceSource.TraceEvent(messageType, id, traceString); if (AutoFlush) { diff --git a/SPMeta2/SPMeta2/Services/TryRetryServiceBase.cs b/SPMeta2/SPMeta2/Services/TryRetryServiceBase.cs new file mode 100644 index 000000000..01119f91b --- /dev/null +++ b/SPMeta2/SPMeta2/Services/TryRetryServiceBase.cs @@ -0,0 +1,24 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading; + + +namespace SPMeta2.Services +{ + public abstract class TryRetryServiceBase + { + #region properties + + #endregion + + #region methods + + public abstract void TryWithRetry(Func action); + public abstract void TryWithRetry(Func action, int maxTryCount, int retryTimeoutInMilliseconds); + public abstract void TryWithRetry(Func action, int maxTryCount, int retryTimeoutInMilliseconds, Action waiter); + + #endregion + } +} From e9b6fa651b429bf03d8a24e076d8a07c62d4b68e Mon Sep 17 00:00:00 2001 From: SubPointSupport Date: Sat, 8 Apr 2017 10:08:53 -0700 Subject: [PATCH 03/16] + Simplify incremental provision usage #1005 --- .../SPMeta2/Extensions/ModelNodeExtensions.cs | 2 +- ...crementalProvisionServiceBaseExtensions.cs | 62 +++++++++++++++++++ 2 files changed, 63 insertions(+), 1 deletion(-) diff --git a/SPMeta2/SPMeta2/Extensions/ModelNodeExtensions.cs b/SPMeta2/SPMeta2/Extensions/ModelNodeExtensions.cs index 9dda48707..e9b978142 100644 --- a/SPMeta2/SPMeta2/Extensions/ModelNodeExtensions.cs +++ b/SPMeta2/SPMeta2/Extensions/ModelNodeExtensions.cs @@ -324,7 +324,7 @@ public static bool GetIncrementalRequireSelfProcessingValue(this TMo return false; } - private static TModelNode InternalSetIncrementalProvisionModelId(this TModelNode modelNode, string modelId) + internal static TModelNode InternalSetIncrementalProvisionModelId(this TModelNode modelNode, string modelId) where TModelNode : ModelNode { modelNode.SetPropertyBagValue(DefaultModelNodePropertyBagValue.Sys.IncrementalProvision.PersistenceStorageModelId, modelId); diff --git a/SPMeta2/SPMeta2/Services/IncrementalProvisionServiceBaseExtensions.cs b/SPMeta2/SPMeta2/Services/IncrementalProvisionServiceBaseExtensions.cs index 321aa9f68..328e6c857 100644 --- a/SPMeta2/SPMeta2/Services/IncrementalProvisionServiceBaseExtensions.cs +++ b/SPMeta2/SPMeta2/Services/IncrementalProvisionServiceBaseExtensions.cs @@ -7,6 +7,9 @@ using SPMeta2.Definitions; using SPMeta2.Common; using SPMeta2.Exceptions; +using SPMeta2.ModelHosts; +using SPMeta2.Models; +using SPMeta2.Extensions; namespace SPMeta2.Services { @@ -86,5 +89,64 @@ private static DefaultIncrementalModelTreeTraverseService GetIncrementalModelTra } #endregion + + #region deployment helpers + + /// + /// A shortcut for incremental provision + /// Sets incremental provision mode with AutoDetectSharePointPersistenceStorage = true + /// Once done, reverts back to default provision mode + /// + /// + /// + /// + /// + public static void DeployModelIncrementally(this ProvisionServiceBase provisionService, + ModelHostBase modelHost, + ModelNode model, + string incrementalModelId) + { + DeployModelIncrementally(provisionService, modelHost, model, incrementalModelId, null); + } + + /// + /// A shortcut for incremental provision + /// Sets incremental provision mode with IncrementalProvisionConfig.AutoDetectSharePointPersistenceStorage = true + /// Once done, reverts back to default provision mode + /// Callback on IncrementalProvisionConfig makes it easy to configure IncrementalProvisionConfig instance + /// + /// + /// + /// + /// + /// + public static void DeployModelIncrementally(this ProvisionServiceBase provisionService, + ModelHostBase modelHost, + ModelNode model, + string incrementalModelId, + Action config) + { + try + { + var incrementalProvisionConfig = new IncrementalProvisionConfig + { + AutoDetectSharePointPersistenceStorage = true + }; + + if (config != null) + config(incrementalProvisionConfig); + + provisionService.SetIncrementalProvisionMode(incrementalProvisionConfig); + model.InternalSetIncrementalProvisionModelId(incrementalModelId); + + provisionService.DeployModel(modelHost, model); + } + finally + { + provisionService.SetDefaultProvisionMode(); + } + } + + #endregion } } \ No newline at end of file From 17d81acdb4763ddce2d731ab699624661c785ba9 Mon Sep 17 00:00:00 2001 From: SubPointSupport Date: Sat, 8 Apr 2017 10:12:40 -0700 Subject: [PATCH 04/16] + NET35 build fix --- .../Taxonomy/TaxonomyTermModelHandler.cs | 12 ++++++++---- 1 file changed, 8 insertions(+), 4 deletions(-) diff --git a/SPMeta2/SPMeta2.CSOM.Standard/ModelHandlers/Taxonomy/TaxonomyTermModelHandler.cs b/SPMeta2/SPMeta2.CSOM.Standard/ModelHandlers/Taxonomy/TaxonomyTermModelHandler.cs index d324103df..99c6fdbb5 100644 --- a/SPMeta2/SPMeta2.CSOM.Standard/ModelHandlers/Taxonomy/TaxonomyTermModelHandler.cs +++ b/SPMeta2/SPMeta2.CSOM.Standard/ModelHandlers/Taxonomy/TaxonomyTermModelHandler.cs @@ -198,8 +198,10 @@ private void DeployTermUnderTermSet(object modelHost, TermSetModelHost groupMode var serverException = e as ServerException; if (serverException != null - && serverException.HResult == -2146233088 - && serverException.ServerErrorTypeName == "Microsoft.SharePoint.Taxonomy.TermStoreOperationException") +#if !NET35 + && serverException.HResult == -2146233088 +#endif + && serverException.ServerErrorTypeName == "Microsoft.SharePoint.Taxonomy.TermStoreOperationException") { TraceService.Information((int)LogEventId.ModelProvisionProcessingExistingObject, "Processing existing Term"); @@ -403,8 +405,10 @@ private void DeployTermUnderTerm(object modelHost, TermModelHost groupModelHost, var serverException = e as ServerException; if (serverException != null - && serverException.HResult == -2146233088 - && serverException.ServerErrorTypeName == "Microsoft.SharePoint.Taxonomy.TermStoreOperationException") +#if !NET35 + && serverException.HResult == -2146233088 +#endif + && serverException.ServerErrorTypeName == "Microsoft.SharePoint.Taxonomy.TermStoreOperationException") { TraceService.Information((int)LogEventId.ModelProvisionProcessingExistingObject, "Processing existing Term"); From 2a789fc264571233f5e4f2b7b4f5f73af65a5c2a Mon Sep 17 00:00:00 2001 From: SubPointSupport Date: Sat, 8 Apr 2017 10:25:22 -0700 Subject: [PATCH 05/16] .NET35 build fix --- .../Taxonomy/TaxonomyTermModelHandler.cs | 12 ++++------ SPMeta2/SPMeta2/Utils/ReflectionUtils.cs | 23 +++++++++++++++++++ 2 files changed, 27 insertions(+), 8 deletions(-) diff --git a/SPMeta2/SPMeta2.CSOM.Standard/ModelHandlers/Taxonomy/TaxonomyTermModelHandler.cs b/SPMeta2/SPMeta2.CSOM.Standard/ModelHandlers/Taxonomy/TaxonomyTermModelHandler.cs index 99c6fdbb5..8e79e5764 100644 --- a/SPMeta2/SPMeta2.CSOM.Standard/ModelHandlers/Taxonomy/TaxonomyTermModelHandler.cs +++ b/SPMeta2/SPMeta2.CSOM.Standard/ModelHandlers/Taxonomy/TaxonomyTermModelHandler.cs @@ -198,10 +198,8 @@ private void DeployTermUnderTermSet(object modelHost, TermSetModelHost groupMode var serverException = e as ServerException; if (serverException != null -#if !NET35 - && serverException.HResult == -2146233088 -#endif - && serverException.ServerErrorTypeName == "Microsoft.SharePoint.Taxonomy.TermStoreOperationException") + && ReflectionUtils.GetHResultValue(serverException).Value == -2146233088 + && serverException.ServerErrorTypeName == "Microsoft.SharePoint.Taxonomy.TermStoreOperationException") { TraceService.Information((int)LogEventId.ModelProvisionProcessingExistingObject, "Processing existing Term"); @@ -405,10 +403,8 @@ private void DeployTermUnderTerm(object modelHost, TermModelHost groupModelHost, var serverException = e as ServerException; if (serverException != null -#if !NET35 - && serverException.HResult == -2146233088 -#endif - && serverException.ServerErrorTypeName == "Microsoft.SharePoint.Taxonomy.TermStoreOperationException") + && ReflectionUtils.GetHResultValue(serverException).Value == -2146233088 + && serverException.ServerErrorTypeName == "Microsoft.SharePoint.Taxonomy.TermStoreOperationException") { TraceService.Information((int)LogEventId.ModelProvisionProcessingExistingObject, "Processing existing Term"); diff --git a/SPMeta2/SPMeta2/Utils/ReflectionUtils.cs b/SPMeta2/SPMeta2/Utils/ReflectionUtils.cs index 60ff6dbcc..8886d8651 100644 --- a/SPMeta2/SPMeta2/Utils/ReflectionUtils.cs +++ b/SPMeta2/SPMeta2/Utils/ReflectionUtils.cs @@ -303,6 +303,29 @@ public static bool HasPropertyPublicSetter(object obj, string propName) return false; } + public static int? GetHResultValue(Exception exception) + { + // .net 4 hack to get HResult + var hResultProp = exception.GetType() + .GetProperty("HResult", + BindingFlags.NonPublic + | BindingFlags.Public + | BindingFlags.Instance + | BindingFlags.Static); + + + if (hResultProp != null) + { + var hResultValue = hResultProp.GetValue(exception, null); + if (hResultValue is int) + { + return (int)hResultValue; + } + } + + return null; + } + #endregion } } From ed5afca68b25c186b389168dc4ac3999a4466902 Mon Sep 17 00:00:00 2001 From: SubPointSupport Date: Sat, 8 Apr 2017 23:15:11 -0700 Subject: [PATCH 06/16] + SSOM regression on content types + Broken field links operation in content types #1006 --- SPMeta2/Regression/Regression.csproj | 1 + .../Regression/_ut_grid_baseline_config.ps1 | 36 ++ SPMeta2/Regression/config.yaml | 15 +- ...ContentTypeFieldLinkDefinitionValidator.cs | 111 +++--- ...ontentTypeFieldLinksDefinitionValidator.cs | 50 +-- ...ontentTypeFieldLinksDefinitionValidator.cs | 6 +- ...ntentTypeFieldsOrderDefinitionValidator.cs | 6 +- .../SecurityGroupDefinitionValidator.cs | 22 +- .../ContentTypeLinkScenariousTest.cs | 334 +++++++++--------- .../Scenarios/DocumentSetScenariosTest.cs | 40 ++- .../Impl/Scenarios/SecurityScenariosTest.cs | 33 +- .../WorkflowAssociationScenariosTest.cs | 54 ++- .../ContentTypeFieldLinkModelHandler.cs | 11 +- .../ContentTypeLinkModelHandler.cs | 2 +- .../ModelHandlers/ContentTypeModelHandler.cs | 6 +- .../HideContentTypeFieldLinksModelHandler.cs | 23 +- ...RemoveContentTypeFieldLinksModelHandler.cs | 23 +- ...niqueContentTypeFieldsOrderModelHandler.cs | 22 +- .../ModelHandlers/ListModelHandler.cs | 7 +- .../WorkflowAssociationModelHandler.cs | 32 +- .../ModelHosts/ContentTypeLinkModelHost.cs | 29 ++ .../ModelHosts/ContentTypeModelHost.cs | 3 +- SPMeta2/SPMeta2.SSOM/SPMeta2.SSOM.csproj | 3 +- 23 files changed, 550 insertions(+), 319 deletions(-) create mode 100644 SPMeta2/Regression/_ut_grid_baseline_config.ps1 create mode 100644 SPMeta2/SPMeta2.SSOM/ModelHosts/ContentTypeLinkModelHost.cs diff --git a/SPMeta2/Regression/Regression.csproj b/SPMeta2/Regression/Regression.csproj index 4fc9d415d..0f78e5d1f 100644 --- a/SPMeta2/Regression/Regression.csproj +++ b/SPMeta2/Regression/Regression.csproj @@ -43,6 +43,7 @@ + diff --git a/SPMeta2/Regression/_ut_grid_baseline_config.ps1 b/SPMeta2/Regression/_ut_grid_baseline_config.ps1 new file mode 100644 index 000000000..a66393457 --- /dev/null +++ b/SPMeta2/Regression/_ut_grid_baseline_config.ps1 @@ -0,0 +1,36 @@ +cls + +$ScriptDirectory = Split-Path -Path $MyInvocation.MyCommand.Definition -Parent +. "$ScriptDirectory/_helpers.ps1" + +foreach($server in $dsc_nodeNames) { + + Write-Host "Configuring server [$server]" -fore Green + + Invoke-Command -ScriptBlock { + + + Write-Host "Updating SharePoint ULS settings..." + + add-pssnapin microsoft.sharepoint.powershell + Set-SPDiagnosticConfig -LogMaxDiskSpaceUsageEnabled + Set-SPDiagnosticConfig -LogDiskSpaceUsageGB 1 + + Write-Host "Updating SQL settings..." + + [System.Reflection.Assembly]::LoadWithPartialName("Microsoft.SqlServer.SMO") | out-null + $s = New-Object ("Microsoft.SqlServer.Management.Smo.Server") $server + + #$s.Configuration.MinServerMemory.ConfigValue = 3 * 1024 + $s.Configuration.MaxServerMemory.ConfigValue = 3 * 1024 + $s.Configuration.Alter() + + Write-Host "Restarting services..." + + Restart-Service MSSQLSERVER -Force + Restart-Service sptimerv4 -Force + + iisreset + + } -computer $server +} \ No newline at end of file diff --git a/SPMeta2/Regression/config.yaml b/SPMeta2/Regression/config.yaml index 261b32709..09d9c6568 100644 --- a/SPMeta2/Regression/config.yaml +++ b/SPMeta2/Regression/config.yaml @@ -62,4 +62,17 @@ - SSOM #- CSOM #- O365 - #- O365v16 \ No newline at end of file + #- O365v16 + TestData: + UserLogins: + # test user logins to be used with security related tests + # must not be same account under which tests are run + - dev\user1 + - dev\user2 + ActiveDirectoryGroups: + # test group user logins to be used with security related tests + - dev\group1 + - dev\group2 + DomainUserEmails: + - user1@dev.local + - user2@dev.local \ No newline at end of file diff --git a/SPMeta2/SPMeta2.Regression.SSOM/Validation/ContentTypeFieldLinkDefinitionValidator.cs b/SPMeta2/SPMeta2.Regression.SSOM/Validation/ContentTypeFieldLinkDefinitionValidator.cs index 528c2495a..348f5728f 100644 --- a/SPMeta2/SPMeta2.Regression.SSOM/Validation/ContentTypeFieldLinkDefinitionValidator.cs +++ b/SPMeta2/SPMeta2.Regression.SSOM/Validation/ContentTypeFieldLinkDefinitionValidator.cs @@ -1,54 +1,57 @@ -using System.Diagnostics; -using Microsoft.SharePoint; -using Microsoft.VisualStudio.TestTools.UnitTesting; -using SPMeta2.Definitions; -using SPMeta2.Definitions.Base; -using SPMeta2.SSOM.ModelHandlers; -using SPMeta2.Utils; - - -namespace SPMeta2.Regression.SSOM.Validation -{ - public class ContentTypeFieldLinkDefinitionValidator : ContentTypeFieldLinkModelHandler - { - public override void DeployModel(object modelHost, DefinitionBase model) - { - var spModel = modelHost.WithAssertAndCast("modelHost", value => value.RequireNotNull()); - var definition = model.WithAssertAndCast("model", value => value.RequireNotNull()); - - var spObject = FindExistingFieldLink(spModel, definition); - - var assert = ServiceFactory.AssertService - .NewAssert(definition, spObject) - .ShouldNotBeNull(spObject); - - //.ShouldBeEqual(m => m.FieldId, o => o.Id); - - if (!string.IsNullOrEmpty(definition.FieldInternalName)) - assert.ShouldBeEqual(m => m.FieldInternalName, o => o.Name); - else - assert.SkipProperty(m => m.FieldInternalName, "FieldInternalName is NULL or empty. Skipping."); - - if (definition.FieldId.HasGuidValue()) - assert.ShouldBeEqual(m => m.FieldId, o => o.Id); - else - assert.SkipProperty(m => m.FieldId, "FieldId is NULL. Skipping."); - - - if (!string.IsNullOrEmpty(definition.DisplayName)) - assert.ShouldBeEqual(m => m.DisplayName, o => o.DisplayName); - else - assert.SkipProperty(m => m.DisplayName, "DisplayName is NULL or empty. Skipping."); - - if (definition.Required.HasValue) - assert.ShouldBeEqual(m => m.Required, o => o.Required); - else - assert.SkipProperty(m => m.Required, "Required is NULL. Skipping."); - - if (definition.Hidden.HasValue) - assert.ShouldBeEqual(m => m.Hidden, o => o.Hidden); - else - assert.SkipProperty(m => m.Hidden, "Hidden is NULL. Skipping."); - } - } -} +using System.Diagnostics; +using Microsoft.SharePoint; +using Microsoft.VisualStudio.TestTools.UnitTesting; +using SPMeta2.Definitions; +using SPMeta2.Definitions.Base; +using SPMeta2.SSOM.ModelHandlers; +using SPMeta2.Utils; +using SPMeta2.SSOM.ModelHosts; + + +namespace SPMeta2.Regression.SSOM.Validation +{ + public class ContentTypeFieldLinkDefinitionValidator : ContentTypeFieldLinkModelHandler + { + public override void DeployModel(object modelHost, DefinitionBase model) + { + var typedModelhost = modelHost.WithAssertAndCast("model", value => value.RequireNotNull()); + var definition = model.WithAssertAndCast("model", value => value.RequireNotNull()); + + var spModel = typedModelhost.HostContentType; + + var spObject = FindExistingFieldLink(spModel, definition); + + var assert = ServiceFactory.AssertService + .NewAssert(definition, spObject) + .ShouldNotBeNull(spObject); + + //.ShouldBeEqual(m => m.FieldId, o => o.Id); + + if (!string.IsNullOrEmpty(definition.FieldInternalName)) + assert.ShouldBeEqual(m => m.FieldInternalName, o => o.Name); + else + assert.SkipProperty(m => m.FieldInternalName, "FieldInternalName is NULL or empty. Skipping."); + + if (definition.FieldId.HasGuidValue()) + assert.ShouldBeEqual(m => m.FieldId, o => o.Id); + else + assert.SkipProperty(m => m.FieldId, "FieldId is NULL. Skipping."); + + + if (!string.IsNullOrEmpty(definition.DisplayName)) + assert.ShouldBeEqual(m => m.DisplayName, o => o.DisplayName); + else + assert.SkipProperty(m => m.DisplayName, "DisplayName is NULL or empty. Skipping."); + + if (definition.Required.HasValue) + assert.ShouldBeEqual(m => m.Required, o => o.Required); + else + assert.SkipProperty(m => m.Required, "Required is NULL. Skipping."); + + if (definition.Hidden.HasValue) + assert.ShouldBeEqual(m => m.Hidden, o => o.Hidden); + else + assert.SkipProperty(m => m.Hidden, "Hidden is NULL. Skipping."); + } + } +} diff --git a/SPMeta2/SPMeta2.Regression.SSOM/Validation/ContentTypes/HideContentTypeFieldLinksDefinitionValidator.cs b/SPMeta2/SPMeta2.Regression.SSOM/Validation/ContentTypes/HideContentTypeFieldLinksDefinitionValidator.cs index 77dc6dda8..ebddd8d46 100644 --- a/SPMeta2/SPMeta2.Regression.SSOM/Validation/ContentTypes/HideContentTypeFieldLinksDefinitionValidator.cs +++ b/SPMeta2/SPMeta2.Regression.SSOM/Validation/ContentTypes/HideContentTypeFieldLinksDefinitionValidator.cs @@ -1,24 +1,26 @@ -using Microsoft.SharePoint; -using SPMeta2.Definitions; -using SPMeta2.Definitions.Base; -using SPMeta2.Definitions.ContentTypes; -using SPMeta2.SSOM.ModelHandlers; -using SPMeta2.SSOM.ModelHandlers.ContentTypes; -using SPMeta2.SSOM.ModelHosts; -using SPMeta2.Utils; - -namespace SPMeta2.Regression.SSOM.Validation.ContentTypes -{ - public class HideContentTypeFieldLinksDefinitionValidator : HideContentTypeFieldLinksModelHandler - { - public override void DeployModel(object modelHost, DefinitionBase model) - { - var definition = model.WithAssertAndCast("model", value => value.RequireNotNull()); - var spObject = modelHost as SPContentType; - - ServiceFactory.AssertService - .NewAssert(definition, spObject) - .ShouldNotBeNull(spObject); - } - } -} +using Microsoft.SharePoint; +using SPMeta2.Definitions; +using SPMeta2.Definitions.Base; +using SPMeta2.Definitions.ContentTypes; +using SPMeta2.SSOM.ModelHandlers; +using SPMeta2.SSOM.ModelHandlers.ContentTypes; +using SPMeta2.SSOM.ModelHosts; +using SPMeta2.Utils; + +namespace SPMeta2.Regression.SSOM.Validation.ContentTypes +{ + public class HideContentTypeFieldLinksDefinitionValidator : HideContentTypeFieldLinksModelHandler + { + public override void DeployModel(object modelHost, DefinitionBase model) + { + var definition = model.WithAssertAndCast("model", value => value.RequireNotNull()); + var typedModelhost = modelHost.WithAssertAndCast("model", value => value.RequireNotNull()); + + var spObject = typedModelhost.HostContentType; + + ServiceFactory.AssertService + .NewAssert(definition, spObject) + .ShouldNotBeNull(spObject); + } + } +} diff --git a/SPMeta2/SPMeta2.Regression.SSOM/Validation/ContentTypes/RemoveContentTypeFieldLinksDefinitionValidator.cs b/SPMeta2/SPMeta2.Regression.SSOM/Validation/ContentTypes/RemoveContentTypeFieldLinksDefinitionValidator.cs index 9018cf506..253238a2f 100644 --- a/SPMeta2/SPMeta2.Regression.SSOM/Validation/ContentTypes/RemoveContentTypeFieldLinksDefinitionValidator.cs +++ b/SPMeta2/SPMeta2.Regression.SSOM/Validation/ContentTypes/RemoveContentTypeFieldLinksDefinitionValidator.cs @@ -13,8 +13,10 @@ public class RemoveContentTypeFieldLinksDefinitionValidator : RemoveContentTypeF { public override void DeployModel(object modelHost, DefinitionBase model) { - var definition = model.WithAssertAndCast("model", value => value.RequireNotNull()); - var spObject = modelHost as SPContentType; + var definition = model.WithAssertAndCast("model", value => value.RequireNotNull()); + var typedModelhost = modelHost.WithAssertAndCast("model", value => value.RequireNotNull()); + + var spObject = typedModelhost.HostContentType; ServiceFactory.AssertService .NewAssert(definition, spObject) diff --git a/SPMeta2/SPMeta2.Regression.SSOM/Validation/ContentTypes/UniqueContentTypeFieldsOrderDefinitionValidator.cs b/SPMeta2/SPMeta2.Regression.SSOM/Validation/ContentTypes/UniqueContentTypeFieldsOrderDefinitionValidator.cs index 22ccc324c..50c761abd 100644 --- a/SPMeta2/SPMeta2.Regression.SSOM/Validation/ContentTypes/UniqueContentTypeFieldsOrderDefinitionValidator.cs +++ b/SPMeta2/SPMeta2.Regression.SSOM/Validation/ContentTypes/UniqueContentTypeFieldsOrderDefinitionValidator.cs @@ -16,8 +16,10 @@ public class UniqueContentTypeFieldsOrderDefinitionValidator : UniqueContentType { public override void DeployModel(object modelHost, DefinitionBase model) { - var definition = model.WithAssertAndCast("model", value => value.RequireNotNull()); - var spObject = modelHost as SPContentType; + var definition = model.WithAssertAndCast("model", value => value.RequireNotNull()); + var typedModelhost = modelHost.WithAssertAndCast("model", value => value.RequireNotNull()); + + var spObject = typedModelhost.HostContentType; var assert = ServiceFactory.AssertService .NewAssert(definition, spObject) diff --git a/SPMeta2/SPMeta2.Regression.SSOM/Validation/SecurityGroupDefinitionValidator.cs b/SPMeta2/SPMeta2.Regression.SSOM/Validation/SecurityGroupDefinitionValidator.cs index 53abbd9e1..7a875bd41 100644 --- a/SPMeta2/SPMeta2.Regression.SSOM/Validation/SecurityGroupDefinitionValidator.cs +++ b/SPMeta2/SPMeta2.Regression.SSOM/Validation/SecurityGroupDefinitionValidator.cs @@ -14,6 +14,16 @@ namespace SPMeta2.Regression.SSOM.Validation { public class SecurityGroupDefinitionValidator : SecurityGroupModelHandler { + protected string GetSafeUserLoging(string userLoginString) + { + var result = userLoginString.ToString().ToUpper().Replace("\\", "/"); + + if (result.Contains("|")) + result = result.Split('|')[1]; + + return result; + } + public override void DeployModel(object modelHost, DefinitionBase model) { if (modelHost is SiteModelHost) @@ -61,9 +71,10 @@ public override void DeployModel(object modelHost, DefinitionBase model) var srcProp = s.GetExpressionValue(def => def.Owner); var dstProp = d.GetExpressionValue(ct => ct.GetOwnerLogin()); - var isValid = srcProp.Value.ToString().ToUpper().Replace("\\", "/") == - dstProp.Value.ToString().ToUpper().Replace("\\", "/"); + var srcUserLogin = GetSafeUserLoging(srcProp.Value.ToString()); + var dstsUserLogin = GetSafeUserLoging(dstProp.Value.ToString()); + var isValid = srcUserLogin == dstsUserLogin; return new PropertyValidationResult { @@ -93,8 +104,11 @@ public override void DeployModel(object modelHost, DefinitionBase model) foreach (var userName in userNames) { - if (srcProp.Value.ToString().ToUpper().Replace("\\", "/") == - userName.ToString().ToUpper().Replace("\\", "/")) + + var srcUserLogin = GetSafeUserLoging(srcProp.Value.ToString()); + var dstsUserLogin = GetSafeUserLoging(userName); + + if (srcUserLogin == dstsUserLogin) { isValid = true; break; diff --git a/SPMeta2/SPMeta2.Regression.Tests/Impl/Scenarios/ContentTypeLinkScenariousTest.cs b/SPMeta2/SPMeta2.Regression.Tests/Impl/Scenarios/ContentTypeLinkScenariousTest.cs index 0d796c2ca..b02a60aae 100644 --- a/SPMeta2/SPMeta2.Regression.Tests/Impl/Scenarios/ContentTypeLinkScenariousTest.cs +++ b/SPMeta2/SPMeta2.Regression.Tests/Impl/Scenarios/ContentTypeLinkScenariousTest.cs @@ -1,162 +1,172 @@ -using Microsoft.VisualStudio.TestTools.UnitTesting; -using SPMeta2.Regression.Tests.Base; -using SPMeta2.Regression.Tests.Impl.Scenarios.Base; -using System; -using System.Collections.Generic; -using System.Linq; -using System.Text; -using SPMeta2.Containers; -using SPMeta2.Definitions; -using SPMeta2.Enumerations; -using SPMeta2.Syntax.Default; - - -namespace SPMeta2.Regression.Tests.Impl.Scenarios -{ - [TestClass] - public class ContentTypeLinkScenariousTest : SPMeta2RegresionScenarioTestBase - { - #region internal - - [ClassInitializeAttribute] - public static void Init(TestContext context) - { - InternalInit(); - } - - [ClassCleanupAttribute] - public static void Cleanup() - { - InternalCleanup(); - } - - #endregion - - #region default - - [TestMethod] - [TestCategory("Regression.Scenarios.ContentTypeLinks.Scopes")] - public void CanDeploy_ContentTypeLink_With_SiteAndWebContentTypes() - { - var siteContentType = ModelGeneratorService.GetRandomDefinition(); - var webContentType = ModelGeneratorService.GetRandomDefinition(); - - var webList = ModelGeneratorService.GetRandomDefinition(def => - { - def.ContentTypesEnabled = true; - }); - - var siteModel = SPMeta2Model.NewSiteModel(site => - { - site.AddContentType(siteContentType); - }); - - var webModel = SPMeta2Model.NewWebModel(web => - { - web.AddRandomWeb(subWeb => - { - subWeb.AddContentType(webContentType); - - subWeb.AddList(webList, list => - { - list.AddContentTypeLink(siteContentType); - list.AddContentTypeLink(webContentType); - }); - }); - }); - - TestModel(siteModel, webModel); - } - - #endregion - - #region read-only and sealed content types - - [TestMethod] - [TestCategory("Regression.Scenarios.ContentTypeLinks.CTH")] - public void CanDeploy_ContentTypeLink_As_CTH_Item_ContentType() - { - if (!TestOptions.EnableContentTypeHubTests) - return; - - WithDisabledPropertyUpdateValidation(() => - { - var listDef = ModelGeneratorService.GetRandomDefinition(def => - { - def.TemplateType = BuiltInListTemplateTypeId.GenericList; - def.ContentTypesEnabled = true; - }); - - var ctLinkDef1 = new ContentTypeLinkDefinition - { - ContentTypeName = "cth-item-1", - ContentTypeId = "0x01000FF176352927C44BB2DB4FBF2F30E88F" - }; - - var ctLinkDef2 = new ContentTypeLinkDefinition - { - ContentTypeName = "cth-item-2", - ContentTypeId = "0x010072398EFE7B102948B9BEE545225CA462" - }; - - var webModel = SPMeta2Model.NewWebModel(web => - { - web.AddList(listDef, list => - { - list.AddContentTypeLink(ctLinkDef1); - //list.AddContentTypeLink(ctLinkDef2); - }); - }); - - TestModel(webModel); - }); - } - - - [TestMethod] - [TestCategory("Regression.Scenarios.ContentTypeLinks.CTH")] - public void CanDeploy_ContentTypeLink_As_CTH_Document_ContentType() - { - if (!TestOptions.EnableContentTypeHubTests) - return; - - WithDisabledPropertyUpdateValidation(() => - { - var listDef = ModelGeneratorService.GetRandomDefinition(def => - { - def.TemplateType = BuiltInListTemplateTypeId.DocumentLibrary; - def.ContentTypesEnabled = true; - }); - - var ctLinkDef1 = new ContentTypeLinkDefinition - { - ContentTypeName = "cth-doc-1", - ContentTypeId = "0x01010021C1A5D40722E14591426E165F107547" - }; - - var ctLinkDef2 = new ContentTypeLinkDefinition - { - ContentTypeName = "cth-doc-2", - ContentTypeId = "0x010100429E2FB078A6984385E2531F073EA963" - }; - - var webModel = SPMeta2Model.NewWebModel(web => - { - web.AddList(listDef, list => - { - list.AddContentTypeLink(ctLinkDef1); - //list.AddContentTypeLink(ctLinkDef2); - }); - }); - - TestModel(webModel); - }); - } - - #endregion - - #region content type hub - - #endregion - } -} +using Microsoft.VisualStudio.TestTools.UnitTesting; +using SPMeta2.Regression.Tests.Base; +using SPMeta2.Regression.Tests.Impl.Scenarios.Base; +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using SPMeta2.Containers; +using SPMeta2.Definitions; +using SPMeta2.Enumerations; +using SPMeta2.Syntax.Default; + + +namespace SPMeta2.Regression.Tests.Impl.Scenarios +{ + [TestClass] + public class ContentTypeLinkScenariousTest : SPMeta2RegresionScenarioTestBase + { + #region internal + + [ClassInitializeAttribute] + public static void Init(TestContext context) + { + InternalInit(); + } + + [ClassCleanupAttribute] + public static void Cleanup() + { + InternalCleanup(); + } + + #endregion + + #region default + + [TestMethod] + [TestCategory("Regression.Scenarios.ContentTypeLinks.Scopes")] + public void CanDeploy_ContentTypeLink_With_SiteAndWebContentTypes() + { + var siteContentType = ModelGeneratorService.GetRandomDefinition(); + var webContentType = ModelGeneratorService.GetRandomDefinition(); + + var webList = ModelGeneratorService.GetRandomDefinition(def => + { + def.ContentTypesEnabled = true; + }); + + var siteModel = SPMeta2Model.NewSiteModel(site => + { + site.AddContentType(siteContentType); + }); + + var webModel = SPMeta2Model.NewWebModel(web => + { + web.AddWebFeature(BuiltInWebFeatures.WikiPageHomePage.Inherit(f => + { + f.Enable = true; + })); + + web.AddRandomWeb(subWeb => + { + subWeb.AddWebFeature(BuiltInWebFeatures.WikiPageHomePage.Inherit(f => + { + f.Enable = true; + })); + + subWeb.AddContentType(webContentType); + + subWeb.AddList(webList, list => + { + list.AddContentTypeLink(siteContentType); + list.AddContentTypeLink(webContentType); + }); + }); + }); + + TestModel(siteModel, webModel); + } + + #endregion + + #region read-only and sealed content types + + [TestMethod] + [TestCategory("Regression.Scenarios.ContentTypeLinks.CTH")] + public void CanDeploy_ContentTypeLink_As_CTH_Item_ContentType() + { + if (!TestOptions.EnableContentTypeHubTests) + return; + + WithDisabledPropertyUpdateValidation(() => + { + var listDef = ModelGeneratorService.GetRandomDefinition(def => + { + def.TemplateType = BuiltInListTemplateTypeId.GenericList; + def.ContentTypesEnabled = true; + }); + + var ctLinkDef1 = new ContentTypeLinkDefinition + { + ContentTypeName = "cth-item-1", + ContentTypeId = "0x01000FF176352927C44BB2DB4FBF2F30E88F" + }; + + var ctLinkDef2 = new ContentTypeLinkDefinition + { + ContentTypeName = "cth-item-2", + ContentTypeId = "0x010072398EFE7B102948B9BEE545225CA462" + }; + + var webModel = SPMeta2Model.NewWebModel(web => + { + web.AddList(listDef, list => + { + list.AddContentTypeLink(ctLinkDef1); + //list.AddContentTypeLink(ctLinkDef2); + }); + }); + + TestModel(webModel); + }); + } + + + [TestMethod] + [TestCategory("Regression.Scenarios.ContentTypeLinks.CTH")] + public void CanDeploy_ContentTypeLink_As_CTH_Document_ContentType() + { + if (!TestOptions.EnableContentTypeHubTests) + return; + + WithDisabledPropertyUpdateValidation(() => + { + var listDef = ModelGeneratorService.GetRandomDefinition(def => + { + def.TemplateType = BuiltInListTemplateTypeId.DocumentLibrary; + def.ContentTypesEnabled = true; + }); + + var ctLinkDef1 = new ContentTypeLinkDefinition + { + ContentTypeName = "cth-doc-1", + ContentTypeId = "0x01010021C1A5D40722E14591426E165F107547" + }; + + var ctLinkDef2 = new ContentTypeLinkDefinition + { + ContentTypeName = "cth-doc-2", + ContentTypeId = "0x010100429E2FB078A6984385E2531F073EA963" + }; + + var webModel = SPMeta2Model.NewWebModel(web => + { + web.AddList(listDef, list => + { + list.AddContentTypeLink(ctLinkDef1); + //list.AddContentTypeLink(ctLinkDef2); + }); + }); + + TestModel(webModel); + }); + } + + #endregion + + #region content type hub + + #endregion + } +} diff --git a/SPMeta2/SPMeta2.Regression.Tests/Impl/Scenarios/DocumentSetScenariosTest.cs b/SPMeta2/SPMeta2.Regression.Tests/Impl/Scenarios/DocumentSetScenariosTest.cs index fea1d87dc..e18a7ccf5 100644 --- a/SPMeta2/SPMeta2.Regression.Tests/Impl/Scenarios/DocumentSetScenariosTest.cs +++ b/SPMeta2/SPMeta2.Regression.Tests/Impl/Scenarios/DocumentSetScenariosTest.cs @@ -59,6 +59,14 @@ public void CanDeploy_DocumentSet_To_List_With_ContentTypeId() def.TemplateType = BuiltInListTemplateTypeId.DocumentLibrary; }); + var siteModel = SPMeta2Model.NewSiteModel(site => + { + site.AddSiteFeature(BuiltInSiteFeatures.DocumentSets.Inherit(f => + { + f.Enable = true; + })); + }); + var model = SPMeta2Model.NewWebModel(web => { web.AddList(listDef, list => @@ -68,7 +76,7 @@ public void CanDeploy_DocumentSet_To_List_With_ContentTypeId() }); }); - TestModel(model); + TestModel(siteModel, model); } [TestMethod] @@ -87,6 +95,14 @@ public void CanDeploy_DocumentSet_To_Folder_With_ContentTypeId() def.TemplateType = BuiltInListTemplateTypeId.DocumentLibrary; }); + var siteModel = SPMeta2Model.NewSiteModel(site => + { + site.AddSiteFeature(BuiltInSiteFeatures.DocumentSets.Inherit(f => + { + f.Enable = true; + })); + }); + var model = SPMeta2Model.NewWebModel(web => { web.AddList(listDef, list => @@ -100,7 +116,7 @@ public void CanDeploy_DocumentSet_To_Folder_With_ContentTypeId() }); }); - TestModel(model); + TestModel(siteModel, model); } [TestMethod] @@ -119,6 +135,14 @@ public void CanDeploy_DocumentSet_To_List_With_ContentTypeName() def.TemplateType = BuiltInListTemplateTypeId.DocumentLibrary; }); + var siteModel = SPMeta2Model.NewSiteModel(site => + { + site.AddSiteFeature(BuiltInSiteFeatures.DocumentSets.Inherit(f => + { + f.Enable = true; + })); + }); + var model = SPMeta2Model.NewWebModel(web => { web.AddList(listDef, list => @@ -129,7 +153,7 @@ public void CanDeploy_DocumentSet_To_List_With_ContentTypeName() }); }); - TestModel(model); + TestModel(siteModel, model); } [TestMethod] @@ -148,6 +172,14 @@ public void CanDeploy_DocumentSet_To_Folder_With_ContentTypeName() def.TemplateType = BuiltInListTemplateTypeId.DocumentLibrary; }); + var siteModel = SPMeta2Model.NewSiteModel(site => + { + site.AddSiteFeature(BuiltInSiteFeatures.DocumentSets.Inherit(f => + { + f.Enable = true; + })); + }); + var model = SPMeta2Model.NewWebModel(web => { web.AddList(listDef, list => @@ -161,7 +193,7 @@ public void CanDeploy_DocumentSet_To_Folder_With_ContentTypeName() }); }); - TestModel(model); + TestModel(siteModel, model); } #endregion diff --git a/SPMeta2/SPMeta2.Regression.Tests/Impl/Scenarios/SecurityScenariosTest.cs b/SPMeta2/SPMeta2.Regression.Tests/Impl/Scenarios/SecurityScenariosTest.cs index ffe602331..f277d0bac 100644 --- a/SPMeta2/SPMeta2.Regression.Tests/Impl/Scenarios/SecurityScenariosTest.cs +++ b/SPMeta2/SPMeta2.Regression.Tests/Impl/Scenarios/SecurityScenariosTest.cs @@ -1163,23 +1163,22 @@ public void CanDeploy_SecurityGroupLink_ByIsAssociatedMemberGroup() { var securityGroup = ModelGeneratorService.GetRandomDefinition(); - var webModel = SPMeta2Model - .NewWebModel(web => - { - web.AddRandomWeb(rndWeb => - { - rndWeb.AddRandomList(rndList => - { - rndList.AddRandomListItem(rndListItem => - { - rndListItem.AddSecurityGroupLink(new SecurityGroupLinkDefinition - { - IsAssociatedMemberGroup = true - }); - }); - }); - }); - }); + var webModel = SPMeta2Model.NewWebModel(web => + { + web.AddRandomWeb(rndWeb => + { + rndWeb.AddRandomList(rndList => + { + rndList.AddRandomListItem(rndListItem => + { + rndListItem.AddSecurityGroupLink(new SecurityGroupLinkDefinition + { + IsAssociatedMemberGroup = true + }); + }); + }); + }); + }); TestModels(new ModelNode[] { webModel }); diff --git a/SPMeta2/SPMeta2.Regression.Tests/Impl/Scenarios/WorkflowAssociationScenariosTest.cs b/SPMeta2/SPMeta2.Regression.Tests/Impl/Scenarios/WorkflowAssociationScenariosTest.cs index 25f0464b0..1355996e4 100644 --- a/SPMeta2/SPMeta2.Regression.Tests/Impl/Scenarios/WorkflowAssociationScenariosTest.cs +++ b/SPMeta2/SPMeta2.Regression.Tests/Impl/Scenarios/WorkflowAssociationScenariosTest.cs @@ -97,6 +97,11 @@ public void CanDeploy_WorkflowAssociation_UnderWeb() def.AssociationData = Rnd.String(); }); + var siteModel = SPMeta2Model.NewSiteModel(site => + { + AddDefaultWorkflowFeatures(site); + }); + var model = SPMeta2Model.NewWebModel(web => { web.AddList(taskList); @@ -106,7 +111,7 @@ public void CanDeploy_WorkflowAssociation_UnderWeb() web.AddWorkflowAssociation(workflowDefChanges); }); - TestModel(model); + TestModel(siteModel, model); } [TestMethod] @@ -144,6 +149,11 @@ public void CanDeploy_WorkflowAssociation_UnderList() def.AssociationData = Rnd.String(); }); + var siteModel = SPMeta2Model.NewSiteModel(site => + { + AddDefaultWorkflowFeatures(site); + }); + var model = SPMeta2Model.NewWebModel(web => { web.AddList(taskList); @@ -156,7 +166,7 @@ public void CanDeploy_WorkflowAssociation_UnderList() }); }); - TestModel(model); + TestModel(siteModel, model); } [TestMethod] @@ -203,6 +213,7 @@ public void CanDeploy_WorkflowAssociation_UnderContentTypeLink() var siteModel = SPMeta2Model.NewSiteModel(site => { site.AddContentType(contentTypeDef); + AddDefaultWorkflowFeatures(site); }); var model = SPMeta2Model.NewWebModel(web => @@ -223,6 +234,35 @@ public void CanDeploy_WorkflowAssociation_UnderContentTypeLink() TestModel(siteModel, model); } + private void AddDefaultWorkflowFeatures(SiteModelNode site) + { + site.AddSiteFeature(BuiltInSiteFeatures.Workflows.Inherit(f => + { + f.Enable = true; + })); + + site.AddSiteFeature(BuiltInSiteFeatures.SharePoint2007Workflows.Inherit(f => + { + f.Enable = true; + })); + + //site.AddSiteFeature(BuiltInSiteFeatures.DispositionApprovalWorkflow.Inherit(f => + //{ + // f.Enable = true; + //})); + + //site.AddSiteFeature(BuiltInSiteFeatures.PublishingApprovalWorkflow.Inherit(f => + //{ + // f.Enable = true; + //})); + + //site.AddSiteFeature(BuiltInSiteFeatures.ThreeStateWorkflow.Inherit(f => + //{ + // f.Enable = true; + //})); + } + + [TestMethod] [TestCategory("Regression.Scenarios.WorkflowAssociation")] @@ -249,6 +289,11 @@ public void CanDeploy_WorkflowAssociation_UnderContentType() def.HistoryListTitle = historyList.Title; }); + var initialSiteModel = SPMeta2Model.NewSiteModel(site => + { + AddDefaultWorkflowFeatures(site); + }); + // changability // deploy the same association with different props var workflowDefChanges = workflowDef.Inherit(def => @@ -279,7 +324,10 @@ public void CanDeploy_WorkflowAssociation_UnderContentType() }); }); - TestModel(webModel, siteModel); + TestModels(new ModelNode[] { + initialSiteModel, + webModel, + siteModel }); } } } diff --git a/SPMeta2/SPMeta2.SSOM/ModelHandlers/ContentTypeFieldLinkModelHandler.cs b/SPMeta2/SPMeta2.SSOM/ModelHandlers/ContentTypeFieldLinkModelHandler.cs index f8610ed30..adda91ff2 100644 --- a/SPMeta2/SPMeta2.SSOM/ModelHandlers/ContentTypeFieldLinkModelHandler.cs +++ b/SPMeta2/SPMeta2.SSOM/ModelHandlers/ContentTypeFieldLinkModelHandler.cs @@ -7,7 +7,8 @@ using SPMeta2.Definitions.Base; using SPMeta2.ModelHandlers; using SPMeta2.Services; -using SPMeta2.Utils; +using SPMeta2.Utils; +using SPMeta2.SSOM.ModelHosts; namespace SPMeta2.SSOM.ModelHandlers { @@ -66,9 +67,11 @@ protected SPField FindAvailableField(SPWeb web, ContentTypeFieldLinkDefinition l public override void DeployModel(object modelHost, DefinitionBase model) - { - var contentType = modelHost.WithAssertAndCast("modelHost", value => value.RequireNotNull()); - var contentTypeFieldLinkModel = model.WithAssertAndCast("model", value => value.RequireNotNull()); + { + var typedModelHost = modelHost.WithAssertAndCast("modelHost", value => value.RequireNotNull()); + var contentTypeFieldLinkModel = model.WithAssertAndCast("model", value => value.RequireNotNull()); + + var contentType = typedModelHost.HostContentType; var web = contentType.ParentWeb; diff --git a/SPMeta2/SPMeta2.SSOM/ModelHandlers/ContentTypeLinkModelHandler.cs b/SPMeta2/SPMeta2.SSOM/ModelHandlers/ContentTypeLinkModelHandler.cs index 0baa65d1e..0db546618 100644 --- a/SPMeta2/SPMeta2.SSOM/ModelHandlers/ContentTypeLinkModelHandler.cs +++ b/SPMeta2/SPMeta2.SSOM/ModelHandlers/ContentTypeLinkModelHandler.cs @@ -63,7 +63,7 @@ public override void WithResolvingModelHost(ModelHostResolveContext modelHostCon action(contentTypeLinkHost); - if (!contentTypeLinkHost.ShouldUpdateHost) + if (contentTypeLinkHost.ShouldUpdateHost) contentType.Update(false); } diff --git a/SPMeta2/SPMeta2.SSOM/ModelHandlers/ContentTypeModelHandler.cs b/SPMeta2/SPMeta2.SSOM/ModelHandlers/ContentTypeModelHandler.cs index 3b54023c4..39115acaa 100644 --- a/SPMeta2/SPMeta2.SSOM/ModelHandlers/ContentTypeModelHandler.cs +++ b/SPMeta2/SPMeta2.SSOM/ModelHandlers/ContentTypeModelHandler.cs @@ -10,6 +10,7 @@ using SPMeta2.SSOM.ModelHosts; using SPMeta2.Syntax.Default; using SPMeta2.Utils; +using SPMeta2.ModelHosts; namespace SPMeta2.SSOM.ModelHandlers { @@ -53,7 +54,10 @@ public override void WithResolvingModelHost(ModelHostResolveContext modelHostCon } else { - action(targetContentType); + action(ModelHostBase.Inherit(modelHost as ModelHostBase, host => + { + host.HostContentType = targetContentType; + })); } targetContentType.Update(true); diff --git a/SPMeta2/SPMeta2.SSOM/ModelHandlers/ContentTypes/HideContentTypeFieldLinksModelHandler.cs b/SPMeta2/SPMeta2.SSOM/ModelHandlers/ContentTypes/HideContentTypeFieldLinksModelHandler.cs index 2623211e0..b5c02d002 100644 --- a/SPMeta2/SPMeta2.SSOM/ModelHandlers/ContentTypes/HideContentTypeFieldLinksModelHandler.cs +++ b/SPMeta2/SPMeta2.SSOM/ModelHandlers/ContentTypes/HideContentTypeFieldLinksModelHandler.cs @@ -26,15 +26,16 @@ public override Type TargetType #region methods public override void DeployModel(object modelHost, DefinitionBase model) - { - var contentType = modelHost.WithAssertAndCast("model", value => value.RequireNotNull()); - var hideContentTypeFieldLinksDefinition = model.WithAssertAndCast("model", value => value.RequireNotNull()); - - DeployHideContentTypeLinks(modelHost, contentType, hideContentTypeFieldLinksDefinition); - } - - private void DeployHideContentTypeLinks(object modelHost, SPContentType contentType, HideContentTypeFieldLinksDefinition hideFieldLinksModel) - { + { + var typedModelHost = modelHost.WithAssertAndCast("model", value => value.RequireNotNull()); + var hideContentTypeFieldLinksDefinition = model.WithAssertAndCast("model", value => value.RequireNotNull()); + + DeployHideContentTypeLinks(modelHost, typedModelHost, hideContentTypeFieldLinksDefinition); + } + + private void DeployHideContentTypeLinks(object modelHost, ContentTypeModelHost contentTypeModelHost, HideContentTypeFieldLinksDefinition hideFieldLinksModel) + { + var contentType = contentTypeModelHost.HostContentType; var fieldLinks = contentType.FieldLinks.OfType().ToList(); InvokeOnModelEvent(this, new ModelEventArgs @@ -76,7 +77,9 @@ private void DeployHideContentTypeLinks(object modelHost, SPContentType contentT ObjectType = typeof(SPContentType), ObjectDefinition = hideFieldLinksModel, ModelHost = modelHost - }); + }); + + contentTypeModelHost.ShouldUpdateHost = true; } #endregion diff --git a/SPMeta2/SPMeta2.SSOM/ModelHandlers/ContentTypes/RemoveContentTypeFieldLinksModelHandler.cs b/SPMeta2/SPMeta2.SSOM/ModelHandlers/ContentTypes/RemoveContentTypeFieldLinksModelHandler.cs index cc41fd811..4e45548e0 100644 --- a/SPMeta2/SPMeta2.SSOM/ModelHandlers/ContentTypes/RemoveContentTypeFieldLinksModelHandler.cs +++ b/SPMeta2/SPMeta2.SSOM/ModelHandlers/ContentTypes/RemoveContentTypeFieldLinksModelHandler.cs @@ -26,15 +26,16 @@ public override Type TargetType #region methods public override void DeployModel(object modelHost, DefinitionBase model) - { - var contentType = modelHost.WithAssertAndCast("model", value => value.RequireNotNull()); - var hideContentTypeFieldLinksDefinition = model.WithAssertAndCast("model", value => value.RequireNotNull()); - - DeployHideContentTypeLinks(modelHost, contentType, hideContentTypeFieldLinksDefinition); - } - - private void DeployHideContentTypeLinks(object modelHost, SPContentType contentType, RemoveContentTypeFieldLinksDefinition hideFieldLinksModel) - { + { + var typedModelHost = modelHost.WithAssertAndCast("model", value => value.RequireNotNull()); + var hideContentTypeFieldLinksDefinition = model.WithAssertAndCast("model", value => value.RequireNotNull()); + + DeployHideContentTypeLinks(modelHost, typedModelHost, hideContentTypeFieldLinksDefinition); + } + + private void DeployHideContentTypeLinks(object modelHost, ContentTypeModelHost contentTypeModelHost, RemoveContentTypeFieldLinksDefinition hideFieldLinksModel) + { + var contentType = contentTypeModelHost.HostContentType; var fieldLinks = contentType.FieldLinks.OfType().ToList(); InvokeOnModelEvent(this, new ModelEventArgs @@ -74,7 +75,9 @@ private void DeployHideContentTypeLinks(object modelHost, SPContentType contentT ObjectType = typeof(SPContentType), ObjectDefinition = hideFieldLinksModel, ModelHost = modelHost - }); + }); + + contentTypeModelHost.ShouldUpdateHost = true; } #endregion diff --git a/SPMeta2/SPMeta2.SSOM/ModelHandlers/ContentTypes/UniqueContentTypeFieldsOrderModelHandler.cs b/SPMeta2/SPMeta2.SSOM/ModelHandlers/ContentTypes/UniqueContentTypeFieldsOrderModelHandler.cs index 3e2bb948c..cf759bfc6 100644 --- a/SPMeta2/SPMeta2.SSOM/ModelHandlers/ContentTypes/UniqueContentTypeFieldsOrderModelHandler.cs +++ b/SPMeta2/SPMeta2.SSOM/ModelHandlers/ContentTypes/UniqueContentTypeFieldsOrderModelHandler.cs @@ -26,15 +26,17 @@ public override Type TargetType #region methods public override void DeployModel(object modelHost, DefinitionBase model) - { - var contentType = modelHost.WithAssertAndCast("modelHost", value => value.RequireNotNull()); ; - var contentTypeOrderDefinition = model.WithAssertAndCast("model", value => value.RequireNotNull()); - - DeployContentTypeOrder(modelHost, contentType, contentTypeOrderDefinition); - } + { + var typedModelHost = modelHost.WithAssertAndCast("modelHost", value => value.RequireNotNull()); ; + var contentTypeOrderDefinition = model.WithAssertAndCast("model", value => value.RequireNotNull()); + + DeployContentTypeOrder(modelHost, typedModelHost, contentTypeOrderDefinition); + } + + private void DeployContentTypeOrder(object modelHost, ContentTypeModelHost contentTypeModellHost, UniqueContentTypeFieldsOrderDefinition reorderFieldLinksModel) + { + var contentType = contentTypeModellHost.HostContentType; - private void DeployContentTypeOrder(object modelHost, SPContentType contentType, UniqueContentTypeFieldsOrderDefinition reorderFieldLinksModel) - { var fieldLinks = contentType.FieldLinks.OfType().ToList(); var fields = contentType.Fields.OfType().ToList(); @@ -84,7 +86,9 @@ private void DeployContentTypeOrder(object modelHost, SPContentType contentType, ObjectType = typeof(SPContentType), ObjectDefinition = reorderFieldLinksModel, ModelHost = modelHost - }); + }); + + contentTypeModellHost.ShouldUpdateHost = true; } #endregion diff --git a/SPMeta2/SPMeta2.SSOM/ModelHandlers/ListModelHandler.cs b/SPMeta2/SPMeta2.SSOM/ModelHandlers/ListModelHandler.cs index 8ff788e7e..326b066cc 100644 --- a/SPMeta2/SPMeta2.SSOM/ModelHandlers/ListModelHandler.cs +++ b/SPMeta2/SPMeta2.SSOM/ModelHandlers/ListModelHandler.cs @@ -12,6 +12,7 @@ using SPMeta2.SSOM.ModelHandlers.Base; using SPMeta2.SSOM.ModelHosts; using SPMeta2.Utils; +using SPMeta2.ModelHosts; namespace SPMeta2.SSOM.ModelHandlers { @@ -314,10 +315,10 @@ public override void WithResolvingModelHost(ModelHostResolveContext modelHostCon var list = hostList ?? web.GetList(SPUtility.ConcatUrls(web.ServerRelativeUrl, listDefinition.GetListUrl())); #pragma warning restore 618 - var listModelHost = new ListModelHost + var listModelHost = ModelHostBase.Inherit(modelHost as ModelHostBase, host => { - HostList = list - }; + host.HostList = list; + }); if (childModelType == typeof(ModuleFileDefinition)) { diff --git a/SPMeta2/SPMeta2.SSOM/ModelHandlers/WorkflowAssociationModelHandler.cs b/SPMeta2/SPMeta2.SSOM/ModelHandlers/WorkflowAssociationModelHandler.cs index f82daef77..f1d7db862 100644 --- a/SPMeta2/SPMeta2.SSOM/ModelHandlers/WorkflowAssociationModelHandler.cs +++ b/SPMeta2/SPMeta2.SSOM/ModelHandlers/WorkflowAssociationModelHandler.cs @@ -51,11 +51,19 @@ public override void DeployModel(object modelHost, DefinitionBase model) } else if (modelHost is ContentTypeLinkModelHost) { - var contentType = (modelHost as ContentTypeLinkModelHost).HostContentType; + var contentTypeLinkMpodelHost = (modelHost as ContentTypeLinkModelHost); + var contentType = contentTypeLinkMpodelHost.HostContentType; DeployContentTypeWorkflowAssociationDefinition(contentType, contentType, workflowAssociationModel); + + contentTypeLinkMpodelHost.ShouldUpdateHost = false; } + else if (modelHost is ContentTypeModelHost) + { + var contentType = (modelHost as ContentTypeModelHost).HostContentType; + DeployContentTypeWorkflowAssociationDefinition(contentType, contentType, workflowAssociationModel); + } else { throw new SPMeta2NotSupportedException("model host should be of type ListModelHost or WebModelHost"); @@ -80,6 +88,12 @@ private SPWeb GetWebFromModelHost(object modelHost) return (modelHost as SPContentType).ParentWeb; } + + if (modelHost is ContentTypeModelHost) + { + return (modelHost as ContentTypeModelHost).HostWeb; + } + if (modelHost is ContentTypeLinkModelHost) { return (modelHost as ContentTypeLinkModelHost).HostWeb; @@ -97,22 +111,22 @@ protected SPWorkflowAssociation FindExistringWorkflowAssotiation(object modelHos return list.WorkflowAssociations .GetAssociationByName(def.Name, list.ParentWeb.UICulture); } - if (modelHost is WebModelHost) + else if (modelHost is WebModelHost) { var web = (modelHost as WebModelHost).HostWeb; return web.WorkflowAssociations .GetAssociationByName(def.Name, web.UICulture); } - if (modelHost is SPContentType) + else if (modelHost is SPContentType) { var contentType = (modelHost as SPContentType); var web = contentType.ParentWeb; return contentType.WorkflowAssociations - .GetAssociationByName(def.Name, web.UICulture); + .GetAssociationByName(def.Name, web.UICulture); } - if (modelHost is ContentTypeLinkModelHost) + else if (modelHost is ContentTypeLinkModelHost) { var listContentTypeHost = (modelHost as ContentTypeLinkModelHost); @@ -126,6 +140,14 @@ protected SPWorkflowAssociation FindExistringWorkflowAssotiation(object modelHos return contentType.WorkflowAssociations .GetAssociationByName(def.Name, web.UICulture); } + else if (modelHost is ContentTypeModelHost) + { + var contentType = (modelHost as ContentTypeModelHost).HostContentType; + var web = contentType.ParentWeb; + + return contentType.WorkflowAssociations + .GetAssociationByName(def.Name, web.UICulture); + } else { throw new SPMeta2NotImplementedException( diff --git a/SPMeta2/SPMeta2.SSOM/ModelHosts/ContentTypeLinkModelHost.cs b/SPMeta2/SPMeta2.SSOM/ModelHosts/ContentTypeLinkModelHost.cs new file mode 100644 index 000000000..cf2013f17 --- /dev/null +++ b/SPMeta2/SPMeta2.SSOM/ModelHosts/ContentTypeLinkModelHost.cs @@ -0,0 +1,29 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; + +using Microsoft.SharePoint; + +namespace SPMeta2.SSOM.ModelHosts +{ + + public class ContentTypeLinkModelHost : ContentTypeModelHost + { + #region constructors + + + #endregion + + #region properties + + + + #endregion + + + + public SPList HostList { get; set; } + + } +} diff --git a/SPMeta2/SPMeta2.SSOM/ModelHosts/ContentTypeModelHost.cs b/SPMeta2/SPMeta2.SSOM/ModelHosts/ContentTypeModelHost.cs index 1acfc55fb..8265c5b21 100644 --- a/SPMeta2/SPMeta2.SSOM/ModelHosts/ContentTypeModelHost.cs +++ b/SPMeta2/SPMeta2.SSOM/ModelHosts/ContentTypeModelHost.cs @@ -7,7 +7,7 @@ namespace SPMeta2.SSOM.ModelHosts { - public class ContentTypeLinkModelHost : SSOMModelHostBase + public class ContentTypeModelHost : SSOMModelHostBase { #region constructors @@ -22,7 +22,6 @@ public class ContentTypeLinkModelHost : SSOMModelHostBase - public SPList HostList { get; set; } public SPWeb HostWeb { get; set; } } } diff --git a/SPMeta2/SPMeta2.SSOM/SPMeta2.SSOM.csproj b/SPMeta2/SPMeta2.SSOM/SPMeta2.SSOM.csproj index f45593402..8b1438855 100644 --- a/SPMeta2/SPMeta2.SSOM/SPMeta2.SSOM.csproj +++ b/SPMeta2/SPMeta2.SSOM/SPMeta2.SSOM.csproj @@ -325,6 +325,7 @@ + @@ -335,7 +336,7 @@ - + From 5116b68a73d686afd21e0d2ea91dbbf386916a32 Mon Sep 17 00:00:00 2001 From: SubPointSupport Date: Sun, 9 Apr 2017 07:24:21 -0700 Subject: [PATCH 07/16] + CSOM regression on content types + Broken field links operation in content types #1006 --- .../ContentTypeFieldLinkModelHandler.cs | 7 +- .../ContentTypeLinkModelHandler.cs | 381 +++++++++--------- .../ModelHandlers/ContentTypeModelHandler.cs | 8 +- .../ContentTypeFieldLinksModelHandlerBase.cs | 106 ++--- .../HideContentTypeFieldLinksModelHandler.cs | 7 +- ...RemoveContentTypeFieldLinksModelHandler.cs | 7 +- ...niqueContentTypeFieldsOrderModelHandler.cs | 7 +- .../ModelHandlers/FieldModelHandler.cs | 23 +- .../ModelHosts/ContentTypeLinkModelHost.cs | 6 +- .../ModelHosts/ContentTypeModelHost.cs | 18 + SPMeta2/SPMeta2.CSOM/SPMeta2.CSOM.csproj | 1 + ...ContentTypeFieldLinkDefinitionValidator.cs | 9 +- 12 files changed, 313 insertions(+), 267 deletions(-) create mode 100644 SPMeta2/SPMeta2.CSOM/ModelHosts/ContentTypeModelHost.cs diff --git a/SPMeta2/SPMeta2.CSOM/ModelHandlers/ContentTypeFieldLinkModelHandler.cs b/SPMeta2/SPMeta2.CSOM/ModelHandlers/ContentTypeFieldLinkModelHandler.cs index 8a64490d6..b74bdce1f 100644 --- a/SPMeta2/SPMeta2.CSOM/ModelHandlers/ContentTypeFieldLinkModelHandler.cs +++ b/SPMeta2/SPMeta2.CSOM/ModelHandlers/ContentTypeFieldLinkModelHandler.cs @@ -9,6 +9,7 @@ using SPMeta2.ModelHandlers; using SPMeta2.Services; using SPMeta2.Utils; +using SPMeta2.CSOM.ModelHosts; namespace SPMeta2.CSOM.ModelHandlers { @@ -121,12 +122,12 @@ protected FieldLink FindExistingFieldLink(ContentType contentType, ContentTypeFi public override void DeployModel(object modelHost, DefinitionBase model) { - var modelHostWrapper = modelHost.WithAssertAndCast("modelHost", value => value.RequireNotNull()); + var modelHostWrapper = modelHost.WithAssertAndCast("modelHost", value => value.RequireNotNull()); var contentTypeFieldLinkModel = model.WithAssertAndCast("model", value => value.RequireNotNull()); //var site = modelHostWrapper.Site; - var web = modelHostWrapper.Web; - var contentType = modelHostWrapper.ContentType; + var web = modelHostWrapper.HostWeb; + var contentType = modelHostWrapper.HostContentType; var context = contentType.Context; diff --git a/SPMeta2/SPMeta2.CSOM/ModelHandlers/ContentTypeLinkModelHandler.cs b/SPMeta2/SPMeta2.CSOM/ModelHandlers/ContentTypeLinkModelHandler.cs index 1983ec965..e980b76f0 100644 --- a/SPMeta2/SPMeta2.CSOM/ModelHandlers/ContentTypeLinkModelHandler.cs +++ b/SPMeta2/SPMeta2.CSOM/ModelHandlers/ContentTypeLinkModelHandler.cs @@ -1,39 +1,39 @@ -using System; -using Microsoft.SharePoint.Client; -using SPMeta2.Common; -using SPMeta2.CSOM.Common; -using SPMeta2.CSOM.Extensions; -using SPMeta2.Definitions; -using SPMeta2.Definitions.Base; -using SPMeta2.ModelHandlers; -using SPMeta2.Services; -using SPMeta2.Utils; +using System; +using Microsoft.SharePoint.Client; +using SPMeta2.Common; +using SPMeta2.CSOM.Common; +using SPMeta2.CSOM.Extensions; +using SPMeta2.Definitions; +using SPMeta2.Definitions.Base; +using SPMeta2.ModelHandlers; +using SPMeta2.Services; +using SPMeta2.Utils; using SPMeta2.CSOM.ModelHosts; -using SPMeta2.ModelHosts; - -namespace SPMeta2.CSOM.ModelHandlers -{ - public class ContentTypeLinkModelHandler : CSOMModelHandlerBase - { - public override Type TargetType - { - get { return typeof(ContentTypeLinkDefinition); } - } - - public override void WithResolvingModelHost(ModelHostResolveContext modelHostContext) +using SPMeta2.ModelHosts; + +namespace SPMeta2.CSOM.ModelHandlers +{ + public class ContentTypeLinkModelHandler : CSOMModelHandlerBase + { + public override Type TargetType + { + get { return typeof(ContentTypeLinkDefinition); } + } + + public override void WithResolvingModelHost(ModelHostResolveContext modelHostContext) { - var modelHost = modelHostContext.ModelHost as CSOMModelHostBase; - var model = modelHostContext.Model; - var childModelType = modelHostContext.ChildModelType; - var action = modelHostContext.Action; - - var listModelHost = modelHost.WithAssertAndCast("modelHost", value => value.RequireNotNull()); - var contentTypeLinkModel = model.WithAssertAndCast("model", value => value.RequireNotNull()); - - var list = listModelHost.HostList; - var context = list.Context; - - context.Load(list, l => l.ContentTypes); + var modelHost = modelHostContext.ModelHost as CSOMModelHostBase; + var model = modelHostContext.Model; + var childModelType = modelHostContext.ChildModelType; + var action = modelHostContext.Action; + + var listModelHost = modelHost.WithAssertAndCast("modelHost", value => value.RequireNotNull()); + var contentTypeLinkModel = model.WithAssertAndCast("model", value => value.RequireNotNull()); + + var list = listModelHost.HostList; + var context = list.Context; + + context.Load(list, l => l.ContentTypes); context.ExecuteQueryWithTrace(); var contentType = FindListContentType(list, contentTypeLinkModel); @@ -42,163 +42,164 @@ public override void WithResolvingModelHost(ModelHostResolveContext modelHostCon { host.HostContentType = contentType; host.HostList = list; + host.ShouldUpdateHost = true; }); action(contentTypeLinkHost); - if (!contentTypeLinkHost.ShouldUpdateHost) - contentType.Update(false); - - context.ExecuteQueryWithTrace(); - } - - public override void DeployModel(object modelHost, DefinitionBase model) - { - var listModelHost = modelHost.WithAssertAndCast("modelHost", value => value.RequireNotNull()); - var contentTypeLinkModel = model.WithAssertAndCast("model", value => value.RequireNotNull()); - - var list = listModelHost.HostList; - - var context = list.Context; - - context.Load(list, l => l.ContentTypesEnabled); - context.ExecuteQueryWithTrace(); - - if (list.ContentTypesEnabled) - { - TraceService.Information((int)LogEventId.ModelProvisionCoreCall, "ContentTypesEnabled is TRUE. Processing content type link"); - - var web = list.ParentWeb; - - // context.Load(web, w => w.AvailableContentTypes); - context.Load(list, l => l.ContentTypes); - - context.ExecuteQueryWithTrace(); - - var targetContentType = web.AvailableContentTypes.GetById(contentTypeLinkModel.ContentTypeId); - var listContentType = FindListContentType(list, contentTypeLinkModel); - - context.Load(targetContentType); - context.ExecuteQueryWithTrace(); - - InvokeOnModelEvent(this, new ModelEventArgs - { - CurrentModelNode = null, - Model = null, - EventType = ModelEventType.OnProvisioning, - Object = listContentType, - ObjectType = typeof(ContentType), - ObjectDefinition = model, - ModelHost = modelHost - }); - - if (targetContentType != null && listContentType == null) - { - TraceService.Information((int)LogEventId.ModelProvisionProcessingNewObject, "Processing new list content type link"); - - var ct = list.ContentTypes.Add(new ContentTypeCreationInformation - { - Description = targetContentType.Description, - Group = targetContentType.Group, - Name = targetContentType.Name, - ParentContentType = targetContentType, - }); - - InvokeOnModelEvent(this, new ModelEventArgs - { - CurrentModelNode = null, - Model = null, - EventType = ModelEventType.OnProvisioned, - Object = ct, - ObjectType = typeof(ContentType), - ObjectDefinition = model, - ModelHost = modelHost - }); - - TraceService.Verbose((int)LogEventId.ModelProvisionCoreCall, "list.Update()"); - list.Update(); - - context.ExecuteQueryWithTrace(); - } - else - { - TraceService.Information((int)LogEventId.ModelProvisionProcessingExistingObject, "Processing existing list content type link"); - - InvokeOnModelEvent(this, new ModelEventArgs - { - CurrentModelNode = null, - Model = null, - EventType = ModelEventType.OnProvisioned, - Object = listContentType, - ObjectType = typeof(ContentType), - ObjectDefinition = model, - ModelHost = modelHost - }); - - TraceService.Verbose((int)LogEventId.ModelProvisionCoreCall, "listContentType.Update(false)"); - - // no update is required for content type link - // besides, CTH wouldn't work - - // .AddContentTypeLink() should work well with the read-only content types (Content Type Hub) - // https://github.com/SubPointSolutions/spmeta2/issues/745 - - // listContentType.Update(false); - // context.ExecuteQueryWithTrace(); - } - } - else - { - TraceService.Information((int)LogEventId.ModelProvisionCoreCall, "ContentTypesEnabled is FALSE. Provision might break."); - } - } - - protected ContentType FindListContentType(List list, ContentTypeLinkDefinition contentTypeLinkModel) - { - ContentType result = null; - - // TODO - // https://github.com/SubPointSolutions/spmeta2/issues/68 - - // if content type name was not provided, this fails - // should be re-done by ID and Name - // OOTB content types could be binded by ID, and custom content types might be binded by name - - - // trying to find by name - if (!string.IsNullOrEmpty(contentTypeLinkModel.ContentTypeName)) - { - TraceService.InformationFormat((int)LogEventId.ModelProvisionCoreCall, - "ContentTypeName is not NULL. Trying to find list content type by ContentTypeName: [{0}]", contentTypeLinkModel.ContentTypeName); - - result = list.ContentTypes.FindByName(contentTypeLinkModel.ContentTypeName); - } - - // trying to find by content type id - // will never be resolved, actually - // list content types have different ID - - //if (result == null && !string.IsNullOrEmpty(contentTypeLinkModel.ContentTypeId)) - // result = list.ContentTypes.GetById(contentTypeLinkModel.ContentTypeId); - - // trying to find by beat match - if (result == null) - { - TraceService.InformationFormat((int)LogEventId.ModelProvisionCoreCall, - "Trying to find list content type by ContentTypeId: [{0}]", contentTypeLinkModel.ContentTypeId); - - // No SPContentTypeCollection.BestMatch() method avialable. - // http://officespdev.uservoice.com/forums/224641-general/suggestions/6356289-expose-spcontenttypecollection-bestmatch-for-csom - - // TODO, correct best match impl - foreach (var contentType in list.ContentTypes) - { - if (contentType.Id.ToString().ToUpper().StartsWith(contentTypeLinkModel.ContentTypeId.ToUpper())) - result = contentType; - } - } - - return result; - } - } -} + if (contentTypeLinkHost.ShouldUpdateHost) + contentType.Update(false); + + context.ExecuteQueryWithTrace(); + } + + public override void DeployModel(object modelHost, DefinitionBase model) + { + var listModelHost = modelHost.WithAssertAndCast("modelHost", value => value.RequireNotNull()); + var contentTypeLinkModel = model.WithAssertAndCast("model", value => value.RequireNotNull()); + + var list = listModelHost.HostList; + + var context = list.Context; + + context.Load(list, l => l.ContentTypesEnabled); + context.ExecuteQueryWithTrace(); + + if (list.ContentTypesEnabled) + { + TraceService.Information((int)LogEventId.ModelProvisionCoreCall, "ContentTypesEnabled is TRUE. Processing content type link"); + + var web = list.ParentWeb; + + // context.Load(web, w => w.AvailableContentTypes); + context.Load(list, l => l.ContentTypes); + + context.ExecuteQueryWithTrace(); + + var targetContentType = web.AvailableContentTypes.GetById(contentTypeLinkModel.ContentTypeId); + var listContentType = FindListContentType(list, contentTypeLinkModel); + + context.Load(targetContentType); + context.ExecuteQueryWithTrace(); + + InvokeOnModelEvent(this, new ModelEventArgs + { + CurrentModelNode = null, + Model = null, + EventType = ModelEventType.OnProvisioning, + Object = listContentType, + ObjectType = typeof(ContentType), + ObjectDefinition = model, + ModelHost = modelHost + }); + + if (targetContentType != null && listContentType == null) + { + TraceService.Information((int)LogEventId.ModelProvisionProcessingNewObject, "Processing new list content type link"); + + var ct = list.ContentTypes.Add(new ContentTypeCreationInformation + { + Description = targetContentType.Description, + Group = targetContentType.Group, + Name = targetContentType.Name, + ParentContentType = targetContentType, + }); + + InvokeOnModelEvent(this, new ModelEventArgs + { + CurrentModelNode = null, + Model = null, + EventType = ModelEventType.OnProvisioned, + Object = ct, + ObjectType = typeof(ContentType), + ObjectDefinition = model, + ModelHost = modelHost + }); + + TraceService.Verbose((int)LogEventId.ModelProvisionCoreCall, "list.Update()"); + list.Update(); + + context.ExecuteQueryWithTrace(); + } + else + { + TraceService.Information((int)LogEventId.ModelProvisionProcessingExistingObject, "Processing existing list content type link"); + + InvokeOnModelEvent(this, new ModelEventArgs + { + CurrentModelNode = null, + Model = null, + EventType = ModelEventType.OnProvisioned, + Object = listContentType, + ObjectType = typeof(ContentType), + ObjectDefinition = model, + ModelHost = modelHost + }); + + TraceService.Verbose((int)LogEventId.ModelProvisionCoreCall, "listContentType.Update(false)"); + + // no update is required for content type link + // besides, CTH wouldn't work + + // .AddContentTypeLink() should work well with the read-only content types (Content Type Hub) + // https://github.com/SubPointSolutions/spmeta2/issues/745 + + // listContentType.Update(false); + // context.ExecuteQueryWithTrace(); + } + } + else + { + TraceService.Information((int)LogEventId.ModelProvisionCoreCall, "ContentTypesEnabled is FALSE. Provision might break."); + } + } + + protected ContentType FindListContentType(List list, ContentTypeLinkDefinition contentTypeLinkModel) + { + ContentType result = null; + + // TODO + // https://github.com/SubPointSolutions/spmeta2/issues/68 + + // if content type name was not provided, this fails + // should be re-done by ID and Name + // OOTB content types could be binded by ID, and custom content types might be binded by name + + + // trying to find by name + if (!string.IsNullOrEmpty(contentTypeLinkModel.ContentTypeName)) + { + TraceService.InformationFormat((int)LogEventId.ModelProvisionCoreCall, + "ContentTypeName is not NULL. Trying to find list content type by ContentTypeName: [{0}]", contentTypeLinkModel.ContentTypeName); + + result = list.ContentTypes.FindByName(contentTypeLinkModel.ContentTypeName); + } + + // trying to find by content type id + // will never be resolved, actually + // list content types have different ID + + //if (result == null && !string.IsNullOrEmpty(contentTypeLinkModel.ContentTypeId)) + // result = list.ContentTypes.GetById(contentTypeLinkModel.ContentTypeId); + + // trying to find by beat match + if (result == null) + { + TraceService.InformationFormat((int)LogEventId.ModelProvisionCoreCall, + "Trying to find list content type by ContentTypeId: [{0}]", contentTypeLinkModel.ContentTypeId); + + // No SPContentTypeCollection.BestMatch() method avialable. + // http://officespdev.uservoice.com/forums/224641-general/suggestions/6356289-expose-spcontenttypecollection-bestmatch-for-csom + + // TODO, correct best match impl + foreach (var contentType in list.ContentTypes) + { + if (contentType.Id.ToString().ToUpper().StartsWith(contentTypeLinkModel.ContentTypeId.ToUpper())) + result = contentType; + } + } + + return result; + } + } +} diff --git a/SPMeta2/SPMeta2.CSOM/ModelHandlers/ContentTypeModelHandler.cs b/SPMeta2/SPMeta2.CSOM/ModelHandlers/ContentTypeModelHandler.cs index 529eea0d6..935fd45dc 100644 --- a/SPMeta2/SPMeta2.CSOM/ModelHandlers/ContentTypeModelHandler.cs +++ b/SPMeta2/SPMeta2.CSOM/ModelHandlers/ContentTypeModelHandler.cs @@ -117,12 +117,10 @@ public override void WithResolvingModelHost(ModelHostResolveContext modelHostCon } else { - action(new ModelHostContext + action(ModelHostBase.Inherit(mdHHost, host => { - Site = site, - Web = web, - ContentType = currentContentType - }); + host.HostContentType = currentContentType; + })); } TraceService.Information((int)LogEventId.ModelProvisionCoreCall, "Calling currentContentType.Update(true)"); diff --git a/SPMeta2/SPMeta2.CSOM/ModelHandlers/ContentTypes/Base/ContentTypeFieldLinksModelHandlerBase.cs b/SPMeta2/SPMeta2.CSOM/ModelHandlers/ContentTypes/Base/ContentTypeFieldLinksModelHandlerBase.cs index c551cad91..9262f2e29 100644 --- a/SPMeta2/SPMeta2.CSOM/ModelHandlers/ContentTypes/Base/ContentTypeFieldLinksModelHandlerBase.cs +++ b/SPMeta2/SPMeta2.CSOM/ModelHandlers/ContentTypes/Base/ContentTypeFieldLinksModelHandlerBase.cs @@ -1,45 +1,61 @@ -using System; -using Microsoft.SharePoint.Client; -using SPMeta2.CSOM.Common; -using SPMeta2.CSOM.ModelHosts; - -namespace SPMeta2.CSOM.ModelHandlers.ContentTypes.Base -{ - public abstract class ContentTypeFieldLinksModelHandlerBase : CSOMModelHandlerBase - { - #region methods - - protected ContentType ExtractContentTypeFromHost(object host) - { - return (host as ModelHostContext).ContentType; - } - - protected Folder ExtractFolderFromHost(object modelHost) - { - if (modelHost is ListModelHost) - return (modelHost as ListModelHost).HostList.RootFolder; - - if (modelHost is FolderModelHost) - return (modelHost as FolderModelHost).CurrentListFolder; - - throw new ArgumentException("modelHost needs to be ListModelHost or FolderModelHost"); - } - - protected List ExtractListFromHost(object modelHost) - { - if (modelHost is ListModelHost) - return (modelHost as ListModelHost).HostList; - - if (modelHost is FolderModelHost) - { - var host = modelHost as FolderModelHost; - - return host.CurrentList; - } - - throw new ArgumentException("modelHost needs to be ListModelHost or FolderModelHost"); - } - - #endregion - } -} +using System; +using Microsoft.SharePoint.Client; +using SPMeta2.CSOM.Common; +using SPMeta2.CSOM.ModelHosts; +using SPMeta2.Exceptions; + +namespace SPMeta2.CSOM.ModelHandlers.ContentTypes.Base +{ + public abstract class ContentTypeFieldLinksModelHandlerBase : CSOMModelHandlerBase + { + #region methods + + protected ContentType ExtractContentTypeFromHost(object host) + { + if (host is ContentTypeModelHost) + { + return (host as ContentTypeModelHost).HostContentType; + } + else if (host is ContentTypeLinkModelHost) + { + return (host as ContentTypeLinkModelHost).HostContentType; + } + else if (host is ModelHostContext) + { + return (host as ModelHostContext).ContentType; + } + + throw new SPMeta2Exception( + string.Format("Unsupported model host type:[{0}]", + host.GetType())); + } + + protected Folder ExtractFolderFromHost(object modelHost) + { + if (modelHost is ListModelHost) + return (modelHost as ListModelHost).HostList.RootFolder; + + if (modelHost is FolderModelHost) + return (modelHost as FolderModelHost).CurrentListFolder; + + throw new ArgumentException("modelHost needs to be ListModelHost or FolderModelHost"); + } + + protected List ExtractListFromHost(object modelHost) + { + if (modelHost is ListModelHost) + return (modelHost as ListModelHost).HostList; + + if (modelHost is FolderModelHost) + { + var host = modelHost as FolderModelHost; + + return host.CurrentList; + } + + throw new ArgumentException("modelHost needs to be ListModelHost or FolderModelHost"); + } + + #endregion + } +} diff --git a/SPMeta2/SPMeta2.CSOM/ModelHandlers/ContentTypes/HideContentTypeFieldLinksModelHandler.cs b/SPMeta2/SPMeta2.CSOM/ModelHandlers/ContentTypes/HideContentTypeFieldLinksModelHandler.cs index 67bc9a18a..8a04717fe 100644 --- a/SPMeta2/SPMeta2.CSOM/ModelHandlers/ContentTypes/HideContentTypeFieldLinksModelHandler.cs +++ b/SPMeta2/SPMeta2.CSOM/ModelHandlers/ContentTypes/HideContentTypeFieldLinksModelHandler.cs @@ -8,7 +8,8 @@ using SPMeta2.Definitions; using SPMeta2.Definitions.Base; using SPMeta2.Definitions.ContentTypes; -using SPMeta2.Utils; +using SPMeta2.Utils; +using SPMeta2.CSOM.ModelHosts; namespace SPMeta2.CSOM.ModelHandlers.ContentTypes { @@ -26,8 +27,8 @@ public override Type TargetType #region methods public override void DeployModel(object modelHost, DefinitionBase model) - { - var contentTypeHost = modelHost.WithAssertAndCast("model", value => value.RequireNotNull()); + { + var contentTypeHost = modelHost.WithAssertAndCast("model", value => value.RequireNotNull()); var hideContentTypeFieldLinksDefinition = model.WithAssertAndCast("model", value => value.RequireNotNull()); var contentType = ExtractContentTypeFromHost(contentTypeHost); diff --git a/SPMeta2/SPMeta2.CSOM/ModelHandlers/ContentTypes/RemoveContentTypeFieldLinksModelHandler.cs b/SPMeta2/SPMeta2.CSOM/ModelHandlers/ContentTypes/RemoveContentTypeFieldLinksModelHandler.cs index 74c92c932..d227db80a 100644 --- a/SPMeta2/SPMeta2.CSOM/ModelHandlers/ContentTypes/RemoveContentTypeFieldLinksModelHandler.cs +++ b/SPMeta2/SPMeta2.CSOM/ModelHandlers/ContentTypes/RemoveContentTypeFieldLinksModelHandler.cs @@ -8,7 +8,8 @@ using SPMeta2.Definitions; using SPMeta2.Definitions.Base; using SPMeta2.Definitions.ContentTypes; -using SPMeta2.Utils; +using SPMeta2.Utils; +using SPMeta2.CSOM.ModelHosts; namespace SPMeta2.CSOM.ModelHandlers.ContentTypes { @@ -26,8 +27,8 @@ public override Type TargetType #region methods public override void DeployModel(object modelHost, DefinitionBase model) - { - var contentTypeHost = modelHost.WithAssertAndCast("model", value => value.RequireNotNull()); + { + var contentTypeHost = modelHost.WithAssertAndCast("model", value => value.RequireNotNull()); var hideContentTypeFieldLinksDefinition = model.WithAssertAndCast("model", value => value.RequireNotNull()); var contentType = ExtractContentTypeFromHost(contentTypeHost); diff --git a/SPMeta2/SPMeta2.CSOM/ModelHandlers/ContentTypes/UniqueContentTypeFieldsOrderModelHandler.cs b/SPMeta2/SPMeta2.CSOM/ModelHandlers/ContentTypes/UniqueContentTypeFieldsOrderModelHandler.cs index f983a1e79..33820c5d8 100644 --- a/SPMeta2/SPMeta2.CSOM/ModelHandlers/ContentTypes/UniqueContentTypeFieldsOrderModelHandler.cs +++ b/SPMeta2/SPMeta2.CSOM/ModelHandlers/ContentTypes/UniqueContentTypeFieldsOrderModelHandler.cs @@ -9,7 +9,8 @@ using SPMeta2.Definitions; using SPMeta2.Definitions.Base; using SPMeta2.Definitions.ContentTypes; -using SPMeta2.Utils; +using SPMeta2.Utils; +using SPMeta2.CSOM.ModelHosts; namespace SPMeta2.CSOM.ModelHandlers.ContentTypes { @@ -27,8 +28,8 @@ public override Type TargetType #region methods public override void DeployModel(object modelHost, DefinitionBase model) - { - var contentTypeHost = modelHost.WithAssertAndCast("model", value => value.RequireNotNull()); + { + var contentTypeHost = modelHost.WithAssertAndCast("model", value => value.RequireNotNull()); var contentTypeOrderDefinition = model.WithAssertAndCast("model", value => value.RequireNotNull()); var contentType = ExtractContentTypeFromHost(modelHost); diff --git a/SPMeta2/SPMeta2.CSOM/ModelHandlers/FieldModelHandler.cs b/SPMeta2/SPMeta2.CSOM/ModelHandlers/FieldModelHandler.cs index 03bc1550d..b3c87f8d8 100644 --- a/SPMeta2/SPMeta2.CSOM/ModelHandlers/FieldModelHandler.cs +++ b/SPMeta2/SPMeta2.CSOM/ModelHandlers/FieldModelHandler.cs @@ -144,26 +144,31 @@ public override void DeployModel(object modelHost, DefinitionBase model) ModelHost = modelHost }); - if (modelHost is SiteModelHost) + if (modelHost is ListModelHost) { - var siteHost = modelHost as SiteModelHost; - context = siteHost.HostSite.Context; + var listHost = modelHost as ListModelHost; + context = listHost.HostList.Context; - currentField = DeploySiteField(siteHost as SiteModelHost, fieldModel); + currentField = DeployListField(modelHost as ListModelHost, fieldModel); } - if (modelHost is WebModelHost) + else if (modelHost is WebModelHost) { var webHost = modelHost as WebModelHost; context = webHost.HostWeb.Context; currentField = DeployWebField(webHost as WebModelHost, fieldModel); } - else if (modelHost is ListModelHost) + + else if (modelHost is SiteModelHost) { - var listHost = modelHost as ListModelHost; - context = listHost.HostList.Context; + var siteHost = modelHost as SiteModelHost; + context = siteHost.HostSite.Context; - currentField = DeployListField(modelHost as ListModelHost, fieldModel); + currentField = DeploySiteField(siteHost as SiteModelHost, fieldModel); + } + else + { + throw new ArgumentException("modelHost needs to be SiteModelHost/WebModelHost/ListModelHost instance."); } object typedField = null; diff --git a/SPMeta2/SPMeta2.CSOM/ModelHosts/ContentTypeLinkModelHost.cs b/SPMeta2/SPMeta2.CSOM/ModelHosts/ContentTypeLinkModelHost.cs index e2cea1c1f..db650dbcf 100644 --- a/SPMeta2/SPMeta2.CSOM/ModelHosts/ContentTypeLinkModelHost.cs +++ b/SPMeta2/SPMeta2.CSOM/ModelHosts/ContentTypeLinkModelHost.cs @@ -8,7 +8,9 @@ namespace SPMeta2.CSOM.ModelHosts { - public class ContentTypeLinkModelHost : ListModelHost + + + public class ContentTypeLinkModelHost : ContentTypeModelHost { #region constructors @@ -17,7 +19,7 @@ public class ContentTypeLinkModelHost : ListModelHost #region properties - public ContentType HostContentType { get; set; } + public List HostList { get; set; } #endregion } diff --git a/SPMeta2/SPMeta2.CSOM/ModelHosts/ContentTypeModelHost.cs b/SPMeta2/SPMeta2.CSOM/ModelHosts/ContentTypeModelHost.cs new file mode 100644 index 000000000..2de92ef89 --- /dev/null +++ b/SPMeta2/SPMeta2.CSOM/ModelHosts/ContentTypeModelHost.cs @@ -0,0 +1,18 @@ +using Microsoft.SharePoint.Client; +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace SPMeta2.CSOM.ModelHosts +{ + public class ContentTypeModelHost : WebModelHost + { + #region properties + + public ContentType HostContentType { get; set; } + + #endregion + } +} diff --git a/SPMeta2/SPMeta2.CSOM/SPMeta2.CSOM.csproj b/SPMeta2/SPMeta2.CSOM/SPMeta2.CSOM.csproj index 08389eca2..60b42d11b 100644 --- a/SPMeta2/SPMeta2.CSOM/SPMeta2.CSOM.csproj +++ b/SPMeta2/SPMeta2.CSOM/SPMeta2.CSOM.csproj @@ -258,6 +258,7 @@ + diff --git a/SPMeta2/SPMeta2.Regression.CSOM/Validation/ClientContentTypeFieldLinkDefinitionValidator.cs b/SPMeta2/SPMeta2.Regression.CSOM/Validation/ClientContentTypeFieldLinkDefinitionValidator.cs index 04e7d6cfc..7b70d79ac 100644 --- a/SPMeta2/SPMeta2.Regression.CSOM/Validation/ClientContentTypeFieldLinkDefinitionValidator.cs +++ b/SPMeta2/SPMeta2.Regression.CSOM/Validation/ClientContentTypeFieldLinkDefinitionValidator.cs @@ -3,7 +3,8 @@ using SPMeta2.CSOM.Common; using SPMeta2.CSOM.ModelHandlers; using SPMeta2.Definitions; -using SPMeta2.Utils; +using SPMeta2.Utils; +using SPMeta2.CSOM.ModelHosts; namespace SPMeta2.Regression.CSOM.Validation { @@ -11,11 +12,11 @@ public class ClientContentTypeFieldLinkDefinitionValidator : ContentTypeFieldLin { public override void DeployModel(object modelHost, DefinitionBase model) { - var modelHostContext = modelHost.WithAssertAndCast("modelHost", value => value.RequireNotNull()); + var modelHostContext = modelHost.WithAssertAndCast("modelHost", value => value.RequireNotNull()); var definition = model.WithAssertAndCast("model", value => value.RequireNotNull()); - var site = modelHostContext.Site; - var contentType = modelHostContext.ContentType; + var site = modelHostContext.HostSite; + var contentType = modelHostContext.HostContentType; var context = site.Context; From a842b9a768194b806fbdda6d664a238d3b6c2340 Mon Sep 17 00:00:00 2001 From: SubPointSupport Date: Tue, 11 Apr 2017 00:49:16 -0700 Subject: [PATCH 08/16] + CSOM 2013 full regression + CSOM regression on content types + Broken field links operation in content types #1006 --- .../Regression/_ut_grid_baseline_config.ps1 | 112 +++- .../_ut_grid_dsc_spmeta2_webapp.ps1 | 4 +- .../_ut_grid_dsc_spmeta2_webapp_unittests.ps1 | 2 +- .../Taxonomy/TaxonomyGroupModelHandler.cs | 11 +- .../Taxonomy/TaxonomyTermLabelModelHandler.cs | 2 +- .../Taxonomy/TaxonomyTermModelHandler.cs | 20 +- .../Taxonomy/TaxonomyTermSetModelHandler.cs | 10 +- .../BreakRoleInheritanceModelHandler.cs | 14 +- .../ModelHandlers/CSOMModelHandlerBase.cs | 5 + .../ModelHandlers/ListModelHandler.cs | 8 +- .../ModelHosts/ContentTypeModelHost.cs | 2 +- .../Services/CSOMFieldLookupService.cs | 8 +- ...ebNavigationSettingsDefinitionGenerator.cs | 97 ++- .../ClientTaxonomyGroupDefinitionValidator.cs | 12 +- .../ClientTaxonomyTermDefinitionValidator.cs | 28 +- ...entTaxonomyTermLabelDefinitionValidator.cs | 3 +- ...lientTaxonomyTermSetDefinitionValidator.cs | 12 +- ...WorkflowSubscriptionDefinitionValidator.cs | 345 ++++++----- ...ientUserCustomActionDefinitionValidator.cs | 512 ++++++++-------- .../Impl/ModelAPI/SPMeta2ModelTests.cs | 26 +- .../Impl/Scenarios/FieldScenariosTest.cs | 15 +- .../QuickLaunchNavigationNodeScenariosTest.cs | 11 +- .../Scenarios/ReusableItemScenariosTest.cs | 194 +++--- .../Scenarios/SP2013WorkflowScenariosTest.cs | 453 +++++++------- .../Impl/Scenarios/WebpartScenariosTest.cs | 551 ++++++++++-------- .../Services/Impl/DefaultTryRetryService.cs | 4 +- 26 files changed, 1351 insertions(+), 1110 deletions(-) diff --git a/SPMeta2/Regression/_ut_grid_baseline_config.ps1 b/SPMeta2/Regression/_ut_grid_baseline_config.ps1 index a66393457..1b489294a 100644 --- a/SPMeta2/Regression/_ut_grid_baseline_config.ps1 +++ b/SPMeta2/Regression/_ut_grid_baseline_config.ps1 @@ -7,30 +7,114 @@ foreach($server in $dsc_nodeNames) { Write-Host "Configuring server [$server]" -fore Green + $isOnline = Test-Connection -Computername $server -BufferSize 16 -Count 1 -Quiet + + if($isOnline -eq $true) + { + Write-Host "Server [$server] online. Processing..." -fore Green + Invoke-Command -ScriptBlock { - Write-Host "Updating SharePoint ULS settings..." + function Ensure-ISS-AppPools() { + + Import-Module WebAdministration + + $pools = Get-ChildItem –Path IIS:\AppPools + + foreach($pool in $pools) { + + $name = $pool.Name + $state = $pool.State + + if($state -ne "Started") { + Write-Host "`tStarting [$name] - [$state]" -fore Yellow + Start-WebAppPool -Name $name + } else { + Write-Host "`tStarted [$name] - [$state]" -fore Gray + } + } + + } + + function Restart-SharePoint { + + Write-Host "Restarting services..." + + Restart-Service MSSQLSERVER -Force + Restart-Service sptimerv4 -Force + + iisreset + } + + function Update-SharePoint-ULS() { + Write-Host "Updating SharePoint ULS settings..." - add-pssnapin microsoft.sharepoint.powershell - Set-SPDiagnosticConfig -LogMaxDiskSpaceUsageEnabled - Set-SPDiagnosticConfig -LogDiskSpaceUsageGB 1 + add-pssnapin microsoft.sharepoint.powershell + Set-SPDiagnosticConfig -LogMaxDiskSpaceUsageEnabled + Set-SPDiagnosticConfig -LogDiskSpaceUsageGB 1 + } - Write-Host "Updating SQL settings..." + function Set-MSSQL-Ram($ramInMb) { + Write-Host "Updating SQL settings..." - [System.Reflection.Assembly]::LoadWithPartialName("Microsoft.SqlServer.SMO") | out-null - $s = New-Object ("Microsoft.SqlServer.Management.Smo.Server") $server + [System.Reflection.Assembly]::LoadWithPartialName("Microsoft.SqlServer.SMO") | out-null + $s = New-Object ("Microsoft.SqlServer.Management.Smo.Server") $server - #$s.Configuration.MinServerMemory.ConfigValue = 3 * 1024 - $s.Configuration.MaxServerMemory.ConfigValue = 3 * 1024 - $s.Configuration.Alter() + #$s.Configuration.MinServerMemory.ConfigValue = 3 * 1024 + $s.Configuration.MaxServerMemory.ConfigValue = $ramInMb + $s.Configuration.Alter() + } - Write-Host "Restarting services..." + function Ensure-AssociatedGroups() { - Restart-Service MSSQLSERVER -Force - Restart-Service sptimerv4 -Force + Add-PSSnapin Microsoft.SharePoint.PowerShell - iisreset + + $computerName = [environment]::MachineName + + # TODO + + $web = Get-SPWeb ("http://" + $computerName + ":31449") + if ($web.AssociatedVisitorGroup -eq $null) { + Write-Host 'The Visitor Group does not exist. It will be created...' -ForegroundColor DarkYellow + $currentLogin = $web.CurrentUser.LoginName + + if ($web.CurrentUser.IsSiteAdmin -eq $false){ + Write-Host ('The user '+$currentLogin+' needs to be a SiteCollection administrator, to create the default groups.') -ForegroundColor Red + return + } + + $web.CreateDefaultAssociatedGroups($currentLogin, $currentLogin, [System.String].Empty) + Write-Host 'The default Groups have been created.' -ForegroundColor Green + } else { + Write-Host 'The Visitor Group already exists.' -ForegroundColor Green + } + + } + + function Limit-SharePoint-Search() { + Add-PSSnapin Microsoft.SharePoint.PowerShell + + set-SPEnterpriseSearchService -PerformanceLevel Reduced + } + + Ensure-AssociatedGroups + + Update-SharePoint-ULS + Limit-SharePoint-Search + + Set-MSSQL-Ram (6 * 1024) + + Restart-SharePoint + + Ensure-ISS-AppPools + Ensure-ISS-AppPools } -computer $server + } + else + { + Write-Host "Server [$server] is OFFLINE. Skipping Processing..." -fore Yellow + } } \ No newline at end of file diff --git a/SPMeta2/Regression/_ut_grid_dsc_spmeta2_webapp.ps1 b/SPMeta2/Regression/_ut_grid_dsc_spmeta2_webapp.ps1 index 6a2aaf6f5..78f4ffe43 100644 --- a/SPMeta2/Regression/_ut_grid_dsc_spmeta2_webapp.ps1 +++ b/SPMeta2/Regression/_ut_grid_dsc_spmeta2_webapp.ps1 @@ -52,7 +52,7 @@ Configuration SPMeta2_WebApp ApplicationPoolAccount = $config.WebPoolManagedAccount.UserName AllowAnonymous = $false AuthenticationMethod = "NTLM" - DatabaseName = "SPMeta2_Regression_Content" + DatabaseName = "SPMeta2_Regression_Content_$webApp_Port" Url = $webApp_Url #HostHeader = "spmeta2.contoso.com" Port = $webApp_Port @@ -101,7 +101,7 @@ $config = @{ WebPoolManagedAccount = $dsc_WebPoolManagedCredentials SPSetupAccount = $dsc_SPSetupAccountCredentials - #DeleteWebApplication = $true + DeleteWebApplication = $false WebAppPort = $env_config.SharePoint.WebApp.Port diff --git a/SPMeta2/Regression/_ut_grid_dsc_spmeta2_webapp_unittests.ps1 b/SPMeta2/Regression/_ut_grid_dsc_spmeta2_webapp_unittests.ps1 index 1515fe21a..5f3be1791 100644 --- a/SPMeta2/Regression/_ut_grid_dsc_spmeta2_webapp_unittests.ps1 +++ b/SPMeta2/Regression/_ut_grid_dsc_spmeta2_webapp_unittests.ps1 @@ -3,7 +3,7 @@ $ScriptDirectory = Split-Path -Path $MyInvocation.MyCommand.Definition -Parent . "$ScriptDirectory/_helpers.ps1" -$o365RuntimePath = "$PSScriptRoot\..\..\SPMeta2.Dependencies\SharePoint\SP2013 - 15.0.4420.1017\CSOM" +$o365RuntimePath = "$PSScriptRoot\..\SPMeta2.Dependencies\SharePoint\SP2013 - 15.0.4420.1017\CSOM" Write-Host "Loading SharePoint CSOM API" -fore Green $files = [System.IO.Directory]::GetFiles($o365RuntimePath, "*.dll") diff --git a/SPMeta2/SPMeta2.CSOM.Standard/ModelHandlers/Taxonomy/TaxonomyGroupModelHandler.cs b/SPMeta2/SPMeta2.CSOM.Standard/ModelHandlers/Taxonomy/TaxonomyGroupModelHandler.cs index 3b96fca04..971dcd3d8 100644 --- a/SPMeta2/SPMeta2.CSOM.Standard/ModelHandlers/Taxonomy/TaxonomyGroupModelHandler.cs +++ b/SPMeta2/SPMeta2.CSOM.Standard/ModelHandlers/Taxonomy/TaxonomyGroupModelHandler.cs @@ -44,7 +44,7 @@ private void SharePointOnlineWait(TermStoreModelHost siteModelHost, TaxonomyTerm // TermSet not found #994 var context = siteModelHost.HostClientContext; - if (context.Credentials is SharePointOnlineCredentials) + if (IsSharePointOnlineContext(context)) { var currentGroup = FindGroup(siteModelHost, groupModel); @@ -72,10 +72,12 @@ public override void WithResolvingModelHost(ModelHostResolveContext modelHostCon var storeModelHost = modelHost.WithAssertAndCast("modelHost", value => value.RequireNotNull()); var groupModel = model.WithAssertAndCast("model", value => value.RequireNotNull()); + var context = storeModelHost.HostClientContext; + var termStore = storeModelHost.HostTermStore; var currentGroup = FindGroup(storeModelHost, groupModel); - if (currentGroup == null) + if (currentGroup == null && IsSharePointOnlineContext(context)) { TryRetryService.TryWithRetry(() => { @@ -227,6 +229,11 @@ private void DeployTaxonomyGroup(object modelHost, TermStoreModelHost siteModelH } catch (Exception e) { + var context = siteModelHost.HostClientContext; + + if (!IsSharePointOnlineContext(context)) + throw; + // SPMeta2 Provisioning Taxonomy Group with CSOM Standard #959 // https://github.com/SubPointSolutions/spmeta2/issues/959 diff --git a/SPMeta2/SPMeta2.CSOM.Standard/ModelHandlers/Taxonomy/TaxonomyTermLabelModelHandler.cs b/SPMeta2/SPMeta2.CSOM.Standard/ModelHandlers/Taxonomy/TaxonomyTermLabelModelHandler.cs index ff97b578c..537cff465 100644 --- a/SPMeta2/SPMeta2.CSOM.Standard/ModelHandlers/Taxonomy/TaxonomyTermLabelModelHandler.cs +++ b/SPMeta2/SPMeta2.CSOM.Standard/ModelHandlers/Taxonomy/TaxonomyTermLabelModelHandler.cs @@ -43,7 +43,7 @@ private void SharePointOnlineWait(TermModelHost termModelHost, TaxonomyTermLabel // TermSet not found #994 var context = termModelHost.HostClientContext; - if (context.Credentials is SharePointOnlineCredentials) + if (IsSharePointOnlineContext(context)) { var term = termModelHost.HostTerm; var currentLabel = FindLabelInTerm(term, definition); diff --git a/SPMeta2/SPMeta2.CSOM.Standard/ModelHandlers/Taxonomy/TaxonomyTermModelHandler.cs b/SPMeta2/SPMeta2.CSOM.Standard/ModelHandlers/Taxonomy/TaxonomyTermModelHandler.cs index 8e79e5764..025db6f8c 100644 --- a/SPMeta2/SPMeta2.CSOM.Standard/ModelHandlers/Taxonomy/TaxonomyTermModelHandler.cs +++ b/SPMeta2/SPMeta2.CSOM.Standard/ModelHandlers/Taxonomy/TaxonomyTermModelHandler.cs @@ -86,7 +86,9 @@ public override void WithResolvingModelHost(ModelHostResolveContext modelHostCon currentTerm = FindTermInTerm(h.HostTerm, definition); - if (currentTerm == null) + var context = h.HostClientContext; + + if (currentTerm == null && IsSharePointOnlineContext(context)) { TryRetryService.TryWithRetry(() => { @@ -110,7 +112,9 @@ public override void WithResolvingModelHost(ModelHostResolveContext modelHostCon currentTerm = FindTermInTermSet(h.HostTermSet, definition); - if (currentTerm == null) + var context = h.HostClientContext; + + if (currentTerm == null && IsSharePointOnlineContext(context)) { TryRetryService.TryWithRetry(() => { @@ -136,6 +140,8 @@ private void DeployTermUnderTermSet(object modelHost, TermSetModelHost groupMode var currentTerm = FindTermInTermSet(termSet, termModel); var termName = NormalizeTermName(termModel.Name); + + InvokeOnModelEvent(this, new ModelEventArgs { CurrentModelNode = null, @@ -195,6 +201,11 @@ private void DeployTermUnderTermSet(object modelHost, TermSetModelHost groupMode } catch (Exception e) { + var context = groupModelHost.HostClientContext; + + if (!IsSharePointOnlineContext(context)) + throw; + var serverException = e as ServerException; if (serverException != null @@ -400,6 +411,11 @@ private void DeployTermUnderTerm(object modelHost, TermModelHost groupModelHost, } catch (Exception e) { + var context = groupModelHost.HostClientContext; + + if (!IsSharePointOnlineContext(context)) + throw; + var serverException = e as ServerException; if (serverException != null diff --git a/SPMeta2/SPMeta2.CSOM.Standard/ModelHandlers/Taxonomy/TaxonomyTermSetModelHandler.cs b/SPMeta2/SPMeta2.CSOM.Standard/ModelHandlers/Taxonomy/TaxonomyTermSetModelHandler.cs index 7405e02b1..ab828d87e 100644 --- a/SPMeta2/SPMeta2.CSOM.Standard/ModelHandlers/Taxonomy/TaxonomyTermSetModelHandler.cs +++ b/SPMeta2/SPMeta2.CSOM.Standard/ModelHandlers/Taxonomy/TaxonomyTermSetModelHandler.cs @@ -44,7 +44,7 @@ private void SharePointOnlineWait(TermGroupModelHost groupModelHost, TaxonomyTer // TermSet not found #994 var context = groupModelHost.HostClientContext; - if (context.Credentials is SharePointOnlineCredentials) + if (IsSharePointOnlineContext(context)) { var currentTermSet = FindTermSet(groupModelHost.HostGroup, termSetModel); @@ -72,9 +72,10 @@ public override void WithResolvingModelHost(ModelHostResolveContext modelHostCon var groupModelHost = modelHost.WithAssertAndCast("modelHost", value => value.RequireNotNull()); var termSetModel = model.WithAssertAndCast("model", value => value.RequireNotNull()); + var context = groupModelHost.HostClientContext; var currentTermSet = FindTermSet(groupModelHost.HostGroup, termSetModel); - if (currentTermSet == null) + if (currentTermSet == null && IsSharePointOnlineContext(context)) { TryRetryService.TryWithRetry(() => { @@ -148,6 +149,11 @@ private void DeployTaxonomyTermSet(object modelHost, TermGroupModelHost groupMod } catch (Exception e) { + var context = groupModelHost.HostClientContext; + + if (!IsSharePointOnlineContext(context)) + throw; + // SPMeta2 Provisioning Taxonomy Group with CSOM Standard #959 // https://github.com/SubPointSolutions/spmeta2/issues/959 diff --git a/SPMeta2/SPMeta2.CSOM/ModelHandlers/BreakRoleInheritanceModelHandler.cs b/SPMeta2/SPMeta2.CSOM/ModelHandlers/BreakRoleInheritanceModelHandler.cs index 4a876db4c..ad53dfc59 100644 --- a/SPMeta2/SPMeta2.CSOM/ModelHandlers/BreakRoleInheritanceModelHandler.cs +++ b/SPMeta2/SPMeta2.CSOM/ModelHandlers/BreakRoleInheritanceModelHandler.cs @@ -20,17 +20,17 @@ internal static class SecurableHelper public static SecurableObject ExtractSecurableObject(object modelHost) { if (modelHost is SecurableObject) - return modelHost as SecurableObject; + return modelHost as SecurableObject; + + if (modelHost is ListModelHost) + return (modelHost as ListModelHost).HostList; + + if (modelHost is WebModelHost) + return (modelHost as WebModelHost).HostWeb; if (modelHost is SiteModelHost) return (modelHost as SiteModelHost).HostSite.RootWeb; - if (modelHost is WebModelHost) - return (modelHost as WebModelHost).HostWeb; - - if (modelHost is ListModelHost) - return (modelHost as ListModelHost).HostList; - if (modelHost is File) return (modelHost as File).ListItemAllFields; diff --git a/SPMeta2/SPMeta2.CSOM/ModelHandlers/CSOMModelHandlerBase.cs b/SPMeta2/SPMeta2.CSOM/ModelHandlers/CSOMModelHandlerBase.cs index fc0635dd1..1bde33022 100644 --- a/SPMeta2/SPMeta2.CSOM/ModelHandlers/CSOMModelHandlerBase.cs +++ b/SPMeta2/SPMeta2.CSOM/ModelHandlers/CSOMModelHandlerBase.cs @@ -52,6 +52,11 @@ protected virtual object GetPropertyValue(object obj, string propName) return ReflectionUtils.GetPropertyValue(obj, propName); } + protected virtual bool IsSharePointOnlineContext(ClientContext context) + { + return context.Credentials is SharePointOnlineCredentials; + } + #endregion #region localization diff --git a/SPMeta2/SPMeta2.CSOM/ModelHandlers/ListModelHandler.cs b/SPMeta2/SPMeta2.CSOM/ModelHandlers/ListModelHandler.cs index 455980e34..31b974e58 100644 --- a/SPMeta2/SPMeta2.CSOM/ModelHandlers/ListModelHandler.cs +++ b/SPMeta2/SPMeta2.CSOM/ModelHandlers/ListModelHandler.cs @@ -38,13 +38,15 @@ public override void WithResolvingModelHost(ModelHostResolveContext modelHostCon Web web = null; List hostList = null; - if (modelHost is WebModelHost) - web = (modelHost as WebModelHost).HostWeb; - else if (modelHost is ListModelHost) + if (modelHost is ListModelHost) { web = (modelHost as ListModelHost).HostList.ParentWeb; hostList = (modelHost as ListModelHost).HostList; } + else if (modelHost is WebModelHost) + { + web = (modelHost as WebModelHost).HostWeb; + } else { throw new SPMeta2UnsupportedModelHostException( diff --git a/SPMeta2/SPMeta2.CSOM/ModelHosts/ContentTypeModelHost.cs b/SPMeta2/SPMeta2.CSOM/ModelHosts/ContentTypeModelHost.cs index 2de92ef89..b64dc791b 100644 --- a/SPMeta2/SPMeta2.CSOM/ModelHosts/ContentTypeModelHost.cs +++ b/SPMeta2/SPMeta2.CSOM/ModelHosts/ContentTypeModelHost.cs @@ -3,7 +3,7 @@ using System.Collections.Generic; using System.Linq; using System.Text; -using System.Threading.Tasks; + namespace SPMeta2.CSOM.ModelHosts { diff --git a/SPMeta2/SPMeta2.CSOM/Services/CSOMFieldLookupService.cs b/SPMeta2/SPMeta2.CSOM/Services/CSOMFieldLookupService.cs index f884391c0..e922d9b82 100644 --- a/SPMeta2/SPMeta2.CSOM/Services/CSOMFieldLookupService.cs +++ b/SPMeta2/SPMeta2.CSOM/Services/CSOMFieldLookupService.cs @@ -14,12 +14,12 @@ public class CSOMFieldLookupService { public virtual FieldCollection GetFieldCollection(object modelHost) { - if (modelHost is SiteModelHost) - return (modelHost as SiteModelHost).HostSite.RootWeb.Fields; + if (modelHost is ListModelHost) + return (modelHost as ListModelHost).HostList.Fields; else if (modelHost is WebModelHost) return (modelHost as WebModelHost).HostWeb.Fields; - else if (modelHost is ListModelHost) - return (modelHost as ListModelHost).HostList.Fields; + if (modelHost is SiteModelHost) + return (modelHost as SiteModelHost).HostSite.RootWeb.Fields; throw new SPMeta2Exception("Unsupported model host"); } diff --git a/SPMeta2/SPMeta2.Containers.Standard/DefinitionGenerators/WebNavigationSettingsDefinitionGenerator.cs b/SPMeta2/SPMeta2.Containers.Standard/DefinitionGenerators/WebNavigationSettingsDefinitionGenerator.cs index ae4be2f51..2128a08c9 100644 --- a/SPMeta2/SPMeta2.Containers.Standard/DefinitionGenerators/WebNavigationSettingsDefinitionGenerator.cs +++ b/SPMeta2/SPMeta2.Containers.Standard/DefinitionGenerators/WebNavigationSettingsDefinitionGenerator.cs @@ -1,49 +1,48 @@ -using System; -using System.Collections.Generic; -using SPMeta2.Containers.Services.Base; -using SPMeta2.Definitions; -using SPMeta2.Definitions.Base; -using SPMeta2.Enumerations; -using SPMeta2.Standard.Definitions; -using SPMeta2.Syntax.Default; - -namespace SPMeta2.Containers.Standard.DefinitionGenerators -{ - public class WebNavigationSettingsDefinitionGenerator : TypedDefinitionGeneratorServiceBase - { - public override DefinitionBase GenerateRandomDefinition(Action action) - { - return WithEmptyDefinition(def => - { - def.CurrentNavigationSource = BuiltInStandardNavigationSources.PortalProvider; - - def.CurrentNavigationMaximumNumberOfDynamicItems = Rnd.Int(15) + 1; - def.CurrentNavigationShowPages = Rnd.Bool(); - def.CurrentNavigationShowSubsites = Rnd.Bool(); - - def.GlobalNavigationSource = BuiltInStandardNavigationSources.PortalProvider; - - def.GlobalNavigationMaximumNumberOfDynamicItems = Rnd.Int(15) + 1; - def.GlobalNavigationShowPages = Rnd.Bool(); - def.GlobalNavigationShowSubsites = Rnd.Bool(); - }); - } - - public override IEnumerable GetAdditionalArtifacts() - { - var sitePublishing = BuiltInSiteFeatures.SharePointServerPublishingInfrastructure - .Inherit(f => - { - f.Enable = true; - }); - - var webPublishing = BuiltInWebFeatures.SharePointServerPublishing - .Inherit(f => - { - f.Enable = true; - }); - - return new[] { sitePublishing, webPublishing }; - } - } -} +using System; +using System.Collections.Generic; +using SPMeta2.Containers.Services.Base; +using SPMeta2.Definitions; +using SPMeta2.Definitions.Base; +using SPMeta2.Enumerations; +using SPMeta2.Standard.Definitions; +using SPMeta2.Syntax.Default; + +namespace SPMeta2.Containers.Standard.DefinitionGenerators +{ + public class WebNavigationSettingsDefinitionGenerator : TypedDefinitionGeneratorServiceBase + { + public override DefinitionBase GenerateRandomDefinition(Action action) + { + return WithEmptyDefinition(def => + { + def.CurrentNavigationSource = BuiltInStandardNavigationSources.PortalProvider; + + def.CurrentNavigationMaximumNumberOfDynamicItems = Rnd.Int(15) + 1; + def.CurrentNavigationShowPages = Rnd.Bool(); + def.CurrentNavigationShowSubsites = Rnd.Bool(); + + def.GlobalNavigationSource = BuiltInStandardNavigationSources.PortalProvider; + + def.GlobalNavigationMaximumNumberOfDynamicItems = Rnd.Int(15) + 1; + def.GlobalNavigationShowPages = Rnd.Bool(); + def.GlobalNavigationShowSubsites = Rnd.Bool(); + }); + } + + public override IEnumerable GetAdditionalArtifacts() + { + var sitePublishing = BuiltInSiteFeatures.SharePointServerPublishingInfrastructure.Inherit(f => + { + f.Enable = true; + }); + + var webPublishing = BuiltInWebFeatures.SharePointServerPublishing.Inherit(f => + { + f.Enable = true; + f.ForceActivate = true; + }); + + return new[] { sitePublishing, webPublishing }; + } + } +} diff --git a/SPMeta2/SPMeta2.Regression.CSOM.Standard/Validation/Taxonomy/ClientTaxonomyGroupDefinitionValidator.cs b/SPMeta2/SPMeta2.Regression.CSOM.Standard/Validation/Taxonomy/ClientTaxonomyGroupDefinitionValidator.cs index 64f897ce5..87690e5d5 100644 --- a/SPMeta2/SPMeta2.Regression.CSOM.Standard/Validation/Taxonomy/ClientTaxonomyGroupDefinitionValidator.cs +++ b/SPMeta2/SPMeta2.Regression.CSOM.Standard/Validation/Taxonomy/ClientTaxonomyGroupDefinitionValidator.cs @@ -15,13 +15,17 @@ public override void DeployModel(object modelHost, DefinitionBase model) var termStoreModelHost = modelHost.WithAssertAndCast("modelHost", value => value.RequireNotNull()); var definition = model.WithAssertAndCast("model", value => value.RequireNotNull()); + var context = termStoreModelHost.HostClientContext; var spObject = FindGroup(termStoreModelHost, definition); - TryRetryService.TryWithRetry(() => + if (spObject == null && IsSharePointOnlineContext(context)) { - spObject = FindGroup(termStoreModelHost, definition); - return spObject != null; - }); + TryRetryService.TryWithRetry(() => + { + spObject = FindGroup(termStoreModelHost, definition); + return spObject != null; + }); + } var assert = ServiceFactory.AssertService .NewAssert(definition, spObject) diff --git a/SPMeta2/SPMeta2.Regression.CSOM.Standard/Validation/Taxonomy/ClientTaxonomyTermDefinitionValidator.cs b/SPMeta2/SPMeta2.Regression.CSOM.Standard/Validation/Taxonomy/ClientTaxonomyTermDefinitionValidator.cs index c8c55a814..2c9035c5d 100644 --- a/SPMeta2/SPMeta2.Regression.CSOM.Standard/Validation/Taxonomy/ClientTaxonomyTermDefinitionValidator.cs +++ b/SPMeta2/SPMeta2.Regression.CSOM.Standard/Validation/Taxonomy/ClientTaxonomyTermDefinitionValidator.cs @@ -22,19 +22,31 @@ public override void DeployModel(object modelHost, DefinitionBase model) if (modelHost is TermModelHost) { - TryRetryService.TryWithRetry(() => + var context = (modelHost as TermModelHost).HostClientContext; + spObject = FindTermInTerm((modelHost as TermModelHost).HostTerm, definition); + + if (spObject == null && IsSharePointOnlineContext(context)) { - spObject = FindTermInTerm((modelHost as TermModelHost).HostTerm, definition); - return spObject != null; - }); + TryRetryService.TryWithRetry(() => + { + spObject = FindTermInTerm((modelHost as TermModelHost).HostTerm, definition); + return spObject != null; + }); + } } else if (modelHost is TermSetModelHost) { - TryRetryService.TryWithRetry(() => + var context = (modelHost as TermSetModelHost).HostClientContext; + spObject = FindTermInTermSet((modelHost as TermSetModelHost).HostTermSet, definition); + + if (spObject == null && IsSharePointOnlineContext(context)) { - spObject = FindTermInTermSet((modelHost as TermSetModelHost).HostTermSet, definition); - return spObject != null; - }); + TryRetryService.TryWithRetry(() => + { + spObject = FindTermInTermSet((modelHost as TermSetModelHost).HostTermSet, definition); + return spObject != null; + }); + } } else { diff --git a/SPMeta2/SPMeta2.Regression.CSOM.Standard/Validation/Taxonomy/ClientTaxonomyTermLabelDefinitionValidator.cs b/SPMeta2/SPMeta2.Regression.CSOM.Standard/Validation/Taxonomy/ClientTaxonomyTermLabelDefinitionValidator.cs index 08a16406a..6235a92f9 100644 --- a/SPMeta2/SPMeta2.Regression.CSOM.Standard/Validation/Taxonomy/ClientTaxonomyTermLabelDefinitionValidator.cs +++ b/SPMeta2/SPMeta2.Regression.CSOM.Standard/Validation/Taxonomy/ClientTaxonomyTermLabelDefinitionValidator.cs @@ -14,8 +14,9 @@ public override void DeployModel(object modelHost, DefinitionBase model) var definition = model.WithAssertAndCast("model", value => value.RequireNotNull()); var spObject = FindLabelInTerm(termModelHost.HostTerm, definition); + var context = termModelHost.HostClientContext; - if (spObject == null) + if (spObject == null && IsSharePointOnlineContext(context)) { TryRetryService.TryWithRetry(() => { diff --git a/SPMeta2/SPMeta2.Regression.CSOM.Standard/Validation/Taxonomy/ClientTaxonomyTermSetDefinitionValidator.cs b/SPMeta2/SPMeta2.Regression.CSOM.Standard/Validation/Taxonomy/ClientTaxonomyTermSetDefinitionValidator.cs index cbef364f8..08922822b 100644 --- a/SPMeta2/SPMeta2.Regression.CSOM.Standard/Validation/Taxonomy/ClientTaxonomyTermSetDefinitionValidator.cs +++ b/SPMeta2/SPMeta2.Regression.CSOM.Standard/Validation/Taxonomy/ClientTaxonomyTermSetDefinitionValidator.cs @@ -16,12 +16,16 @@ public override void DeployModel(object modelHost, DefinitionBase model) var definition = model.WithAssertAndCast("model", value => value.RequireNotNull()); var spObject = FindTermSet(termGroupModelHost.HostGroup, definition); + var context = termGroupModelHost.HostClientContext; - TryRetryService.TryWithRetry(() => + if (spObject == null && IsSharePointOnlineContext(context)) { - spObject = FindTermSet(termGroupModelHost.HostGroup, definition); - return spObject != null; - }); + TryRetryService.TryWithRetry(() => + { + spObject = FindTermSet(termGroupModelHost.HostGroup, definition); + return spObject != null; + }); + } var assert = ServiceFactory.AssertService .NewAssert(definition, spObject) diff --git a/SPMeta2/SPMeta2.Regression.CSOM/Validation/ClientSP2013WorkflowSubscriptionDefinitionValidator.cs b/SPMeta2/SPMeta2.Regression.CSOM/Validation/ClientSP2013WorkflowSubscriptionDefinitionValidator.cs index b3c60ac9e..f85dfd974 100644 --- a/SPMeta2/SPMeta2.Regression.CSOM/Validation/ClientSP2013WorkflowSubscriptionDefinitionValidator.cs +++ b/SPMeta2/SPMeta2.Regression.CSOM/Validation/ClientSP2013WorkflowSubscriptionDefinitionValidator.cs @@ -1,172 +1,171 @@ -using System; -using System.Collections.Generic; -using System.Linq; -using System.Text; - -using Microsoft.SharePoint.Client.WorkflowServices; -using SPMeta2.Containers.Assertion; -using SPMeta2.CSOM.ModelHandlers; -using SPMeta2.CSOM.ModelHosts; -using SPMeta2.Definitions; -using SPMeta2.Definitions.Base; -using SPMeta2.Utils; -using Microsoft.SharePoint.Client; -using SPMeta2.CSOM.Extensions; - -namespace SPMeta2.Regression.CSOM.Validation -{ - public class ClientSP2013WorkflowSubscriptionDefinitionValidator : SP2013WorkflowSubscriptionDefinitionModelHandler - { - public override void DeployModel(object modelHost, DefinitionBase model) - { - if (modelHost is WebModelHost) - { - var workflowWebSubscriptionModelHost = modelHost.WithAssertAndCast("modelHost", value => value.RequireNotNull()); - var definition = model.WithAssertAndCast("model", value => value.RequireNotNull()); - - var web = workflowWebSubscriptionModelHost.HostWeb; - - var spObject = GetCurrentWebWorkflowSubscriptioBySourceId(workflowWebSubscriptionModelHost, - workflowWebSubscriptionModelHost.HostClientContext, - web, - web.Id, - definition); - - ValidateWorkflowSubscription(modelHost, workflowWebSubscriptionModelHost.HostClientContext, workflowWebSubscriptionModelHost.HostWeb, spObject, definition); - } - - if (modelHost is ListModelHost) - { - var workflowSubscriptionModelHost = modelHost.WithAssertAndCast("modelHost", value => value.RequireNotNull()); - var definition = model.WithAssertAndCast("model", value => value.RequireNotNull()); - - var web = workflowSubscriptionModelHost.HostWeb; - var list = workflowSubscriptionModelHost.HostList; - - var spObject = GetCurrentWebWorkflowSubscriptioBySourceId(workflowSubscriptionModelHost, - workflowSubscriptionModelHost.HostClientContext, - list.ParentWeb, - list.Id, - definition); - - ValidateWorkflowSubscription(modelHost, workflowSubscriptionModelHost.HostClientContext, web, spObject, definition); - } - } - - private void ValidateWorkflowSubscription(object modelHost, - ClientContext clientContext, - Web web, - WorkflowSubscription spObject, - SP2013WorkflowSubscriptionDefinition definition) - { - - var spObjectContext = spObject.Context; - - //spObjectContext.Load(spObject); - //spObjectContext.Load(spObject, o => o.PropertyDefinitions); - //spObjectContext.Load(spObject, o => o.EventSourceId); - //spObjectContext.Load(spObject, o => o.EventTypes); - - //spObjectContext.ExecuteQueryWithTrace(); - - #region list accos - - var webContext = web.Context; - - var assert = ServiceFactory.AssertService - .NewAssert(definition, spObject) - .ShouldNotBeNull(spObject) - .ShouldBeEqual(m => m.Name, o => o.Name); - - // [FALSE] - [WorkflowDisplayName] - { - var srcProp = s.GetExpressionValue(m => m.EventTypes); - - var hasAllEventTypes = true; - - foreach (var srcEventType in s.EventTypes) - if (!d.EventTypes.Contains(srcEventType)) - hasAllEventTypes = false; - - return new PropertyValidationResult - { - Tag = p.Tag, - Src = srcProp, - IsValid = hasAllEventTypes - }; - }); - - #endregion - - #region validate DefinitionId - - var workflowDefinition = GetWorkflowDefinition(modelHost, - clientContext, - web, - definition); - - assert.ShouldBeEqual((p, s, d) => - { - var srcProp = s.GetExpressionValue(m => m.WorkflowDisplayName); - - return new PropertyValidationResult - { - Tag = p.Tag, - Src = srcProp, - IsValid = d.DefinitionId == workflowDefinition.Id - }; - }); - - #endregion - - #region validate task and history list - - var taskListId = new Guid(spObject.PropertyDefinitions["TaskListId"]); - var historyListId = new Guid(spObject.PropertyDefinitions["HistoryListId"]); - - var lists = webContext.LoadQuery(web.Lists.Include(l => l.DefaultViewUrl, l => l.Id)); - webContext.ExecuteQueryWithTrace(); - - var srcTaskList = lists.FirstOrDefault(l => l.Id == taskListId); - var srcHistoryList = lists.FirstOrDefault(l => l.Id == historyListId); - - var dstTaskList = GetTaskList(web, definition); - var dstHistoryList = GetHistoryList(web, definition); - - assert.ShouldBeEqual((p, s, d) => - { - var srcProp = s.GetExpressionValue(m => m.TaskListUrl); - - return new PropertyValidationResult - { - Tag = p.Tag, - Src = srcProp, - IsValid = srcTaskList.Id == dstTaskList.Id - }; - }); - - assert.ShouldBeEqual((p, s, d) => - { - var srcProp = s.GetExpressionValue(m => m.HistoryListUrl); - - return new PropertyValidationResult - { - Tag = p.Tag, - Src = srcProp, - IsValid = srcHistoryList.Id == dstHistoryList.Id - }; - }); - - #endregion - +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; + +using Microsoft.SharePoint.Client.WorkflowServices; +using SPMeta2.Containers.Assertion; +using SPMeta2.CSOM.ModelHandlers; +using SPMeta2.CSOM.ModelHosts; +using SPMeta2.Definitions; +using SPMeta2.Definitions.Base; +using SPMeta2.Utils; +using Microsoft.SharePoint.Client; +using SPMeta2.CSOM.Extensions; + +namespace SPMeta2.Regression.CSOM.Validation +{ + public class ClientSP2013WorkflowSubscriptionDefinitionValidator : SP2013WorkflowSubscriptionDefinitionModelHandler + { + public override void DeployModel(object modelHost, DefinitionBase model) + { + if (modelHost is ListModelHost) + { + var workflowSubscriptionModelHost = modelHost.WithAssertAndCast("modelHost", value => value.RequireNotNull()); + var definition = model.WithAssertAndCast("model", value => value.RequireNotNull()); + + var web = workflowSubscriptionModelHost.HostWeb; + var list = workflowSubscriptionModelHost.HostList; + + var spObject = GetCurrentWebWorkflowSubscriptioBySourceId(workflowSubscriptionModelHost, + workflowSubscriptionModelHost.HostClientContext, + list.ParentWeb, + list.Id, + definition); + + ValidateWorkflowSubscription(modelHost, workflowSubscriptionModelHost.HostClientContext, web, spObject, definition); + } + else if (modelHost is WebModelHost) + { + var workflowWebSubscriptionModelHost = modelHost.WithAssertAndCast("modelHost", value => value.RequireNotNull()); + var definition = model.WithAssertAndCast("model", value => value.RequireNotNull()); + + var web = workflowWebSubscriptionModelHost.HostWeb; + + var spObject = GetCurrentWebWorkflowSubscriptioBySourceId(workflowWebSubscriptionModelHost, + workflowWebSubscriptionModelHost.HostClientContext, + web, + web.Id, + definition); + + ValidateWorkflowSubscription(modelHost, workflowWebSubscriptionModelHost.HostClientContext, workflowWebSubscriptionModelHost.HostWeb, spObject, definition); + } + } + + private void ValidateWorkflowSubscription(object modelHost, + ClientContext clientContext, + Web web, + WorkflowSubscription spObject, + SP2013WorkflowSubscriptionDefinition definition) + { + + var spObjectContext = spObject.Context; + + //spObjectContext.Load(spObject); + //spObjectContext.Load(spObject, o => o.PropertyDefinitions); + //spObjectContext.Load(spObject, o => o.EventSourceId); + //spObjectContext.Load(spObject, o => o.EventTypes); + + //spObjectContext.ExecuteQueryWithTrace(); + + #region list accos + + var webContext = web.Context; + + var assert = ServiceFactory.AssertService + .NewAssert(definition, spObject) + .ShouldNotBeNull(spObject) + .ShouldBeEqual(m => m.Name, o => o.Name); + + // [FALSE] - [WorkflowDisplayName] + { + var srcProp = s.GetExpressionValue(m => m.EventTypes); + + var hasAllEventTypes = true; + + foreach (var srcEventType in s.EventTypes) + if (!d.EventTypes.Contains(srcEventType)) + hasAllEventTypes = false; + + return new PropertyValidationResult + { + Tag = p.Tag, + Src = srcProp, + IsValid = hasAllEventTypes + }; + }); + + #endregion + + #region validate DefinitionId + + var workflowDefinition = GetWorkflowDefinition(modelHost, + clientContext, + web, + definition); + + assert.ShouldBeEqual((p, s, d) => + { + var srcProp = s.GetExpressionValue(m => m.WorkflowDisplayName); + + return new PropertyValidationResult + { + Tag = p.Tag, + Src = srcProp, + IsValid = d.DefinitionId == workflowDefinition.Id + }; + }); + + #endregion + + #region validate task and history list + + var taskListId = new Guid(spObject.PropertyDefinitions["TaskListId"]); + var historyListId = new Guid(spObject.PropertyDefinitions["HistoryListId"]); + + var lists = webContext.LoadQuery(web.Lists.Include(l => l.DefaultViewUrl, l => l.Id)); + webContext.ExecuteQueryWithTrace(); + + var srcTaskList = lists.FirstOrDefault(l => l.Id == taskListId); + var srcHistoryList = lists.FirstOrDefault(l => l.Id == historyListId); + + var dstTaskList = GetTaskList(web, definition); + var dstHistoryList = GetHistoryList(web, definition); + + assert.ShouldBeEqual((p, s, d) => + { + var srcProp = s.GetExpressionValue(m => m.TaskListUrl); + + return new PropertyValidationResult + { + Tag = p.Tag, + Src = srcProp, + IsValid = srcTaskList.Id == dstTaskList.Id + }; + }); + + assert.ShouldBeEqual((p, s, d) => + { + var srcProp = s.GetExpressionValue(m => m.HistoryListUrl); + + return new PropertyValidationResult + { + Tag = p.Tag, + Src = srcProp, + IsValid = srcHistoryList.Id == dstHistoryList.Id + }; + }); + + #endregion + #endregion if (definition.Properties.Count() > 0) @@ -206,7 +205,7 @@ private void ValidateWorkflowSubscription(object modelHost, else { assert.SkipProperty(p => p.Properties, ".Properties.Count() = 0. Skipping"); - } - } - } -} + } + } + } +} diff --git a/SPMeta2/SPMeta2.Regression.CSOM/Validation/ClientUserCustomActionDefinitionValidator.cs b/SPMeta2/SPMeta2.Regression.CSOM/Validation/ClientUserCustomActionDefinitionValidator.cs index 85479abc2..832bb1a25 100644 --- a/SPMeta2/SPMeta2.Regression.CSOM/Validation/ClientUserCustomActionDefinitionValidator.cs +++ b/SPMeta2/SPMeta2.Regression.CSOM/Validation/ClientUserCustomActionDefinitionValidator.cs @@ -1,252 +1,266 @@ -using System; -using System.Collections.Generic; -using System.Linq; -using System.Text; - -using Microsoft.SharePoint.Client; -using SPMeta2.Containers.Assertion; -using SPMeta2.CSOM.ModelHandlers; -using SPMeta2.CSOM.ModelHosts; -using SPMeta2.Definitions; -using SPMeta2.Definitions.Base; -using SPMeta2.Services; -using SPMeta2.Utils; - - -namespace SPMeta2.Regression.CSOM.Validation -{ - public class ClientUserCustomActionDefinitionValidator : UserCustomActionModelHandler - { - public override void DeployModel(object modelHost, DefinitionBase model) - { - var definition = model.WithAssertAndCast("model", value => value.RequireNotNull()); - var spObject = GetCurrentCustomUserAction(modelHost, definition); - - var assert = ServiceFactory.AssertService - .NewAssert(definition, definition, spObject) - .ShouldBeEqual(m => m.Name, o => o.Name) - .ShouldBeEqual(m => m.Title, o => o.Title) - .ShouldBeEqual(m => m.Description, o => o.Description) - .ShouldBeEqual(m => m.Group, o => o.Group) - .ShouldBeEqual(m => m.Location, o => o.Location) - .ShouldBeEqual(m => m.ScriptSrc, o => o.ScriptSrc) - .ShouldBeEqual(m => m.ScriptBlock, o => o.ScriptBlock) - .ShouldBeEqual(m => m.Sequence, o => o.Sequence) - .ShouldBeEqual(m => m.Url, o => o.Url) - //.ShouldBeEqual(m => m.RegistrationId, o => o.RegistrationId) - .ShouldBeEqual(m => m.RegistrationType, o => o.GetRegistrationType()); - - var context = spObject.Context; - - var registrationIdIsGuid = ConvertUtils.ToGuid(spObject.RegistrationId); - - if (registrationIdIsGuid.HasValue) - { - // this is list scoped user custom action reg - // skipping validation - assert.SkipProperty(m => m.RegistrationId, "RegistrationId is GUID. List scope user custom action. Skipping validation."); - } - else - { - assert.ShouldBeEqual(m => m.RegistrationId, o => o.RegistrationId); - } - - if (!string.IsNullOrEmpty(definition.CommandUIExtension)) - { - assert.ShouldBeEqual((p, s, d) => - { - var srcProp = s.GetExpressionValue(def => def.CommandUIExtension); - var dstProp = d.GetExpressionValue(ct => ct.CommandUIExtension); - - var isValid = GetCommandUIString(srcProp.Value.ToString()) == - GetCommandUIString(dstProp.Value.ToString()); - - return new PropertyValidationResult - { - Tag = p.Tag, - Src = srcProp, - Dst = dstProp, - IsValid = isValid - }; - }); - } - else - { - assert.SkipProperty(m => m.CommandUIExtension, "CommandUIExtension is null or empty. Skipping."); - } - - assert - .ShouldBeEqual((p, s, d) => - { - var srcProp = s.GetExpressionValue(def => def.Rights); - var dstProp = d.GetExpressionValue(ct => ct.Rights); - - var hasCorrectRights = true; - - foreach (var srcRight in s.Rights) - { - var srcPermission = (PermissionKind)Enum.Parse(typeof(PermissionKind), srcRight); - - var tmpRight = d.Rights.Has(srcPermission); - - if (tmpRight == false) - hasCorrectRights = false; - } - - return new PropertyValidationResult - { - Tag = p.Tag, - Src = srcProp, - Dst = dstProp, - IsValid = hasCorrectRights - }; - }); - - - +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; + +using Microsoft.SharePoint.Client; +using SPMeta2.Containers.Assertion; +using SPMeta2.CSOM.ModelHandlers; +using SPMeta2.CSOM.ModelHosts; +using SPMeta2.Definitions; +using SPMeta2.Definitions.Base; +using SPMeta2.Services; +using SPMeta2.Utils; + + +namespace SPMeta2.Regression.CSOM.Validation +{ + public class ClientUserCustomActionDefinitionValidator : UserCustomActionModelHandler + { + public override void DeployModel(object modelHost, DefinitionBase model) + { + var definition = model.WithAssertAndCast("model", value => value.RequireNotNull()); + var spObject = GetCurrentCustomUserAction(modelHost, definition); + + var shouldCheckRegistrationType = true; + + if (modelHost is ListModelHost) + { + //// skipping setup for List script + //// System.NotSupportedException: Setting this property is not supported. A value of List has already been set and cannot be changed. + shouldCheckRegistrationType = false; + } + + var assert = ServiceFactory.AssertService + .NewAssert(definition, definition, spObject) + .ShouldBeEqual(m => m.Name, o => o.Name) + .ShouldBeEqual(m => m.Title, o => o.Title) + .ShouldBeEqual(m => m.Description, o => o.Description) + .ShouldBeEqual(m => m.Group, o => o.Group) + .ShouldBeEqual(m => m.Location, o => o.Location) + .ShouldBeEqual(m => m.ScriptSrc, o => o.ScriptSrc) + .ShouldBeEqual(m => m.ScriptBlock, o => o.ScriptBlock) + .ShouldBeEqual(m => m.Sequence, o => o.Sequence) + .ShouldBeEqual(m => m.Url, o => o.Url); + //.ShouldBeEqual(m => m.RegistrationId, o => o.RegistrationId) + //.ShouldBeEqual(m => m.RegistrationType, o => o.GetRegistrationType()); + + if (shouldCheckRegistrationType) + assert.ShouldBeEqual(m => m.RegistrationType, o => o.GetRegistrationType()); + else + assert.SkipProperty(m => m.RegistrationType, "Skipping validation"); + + var context = spObject.Context; + + var registrationIdIsGuid = ConvertUtils.ToGuid(spObject.RegistrationId); + + if (registrationIdIsGuid.HasValue) + { + // this is list scoped user custom action reg + // skipping validation + assert.SkipProperty(m => m.RegistrationId, "RegistrationId is GUID. List scope user custom action. Skipping validation."); + } + else + { + assert.ShouldBeEqual(m => m.RegistrationId, o => o.RegistrationId); + } + + if (!string.IsNullOrEmpty(definition.CommandUIExtension)) + { + assert.ShouldBeEqual((p, s, d) => + { + var srcProp = s.GetExpressionValue(def => def.CommandUIExtension); + var dstProp = d.GetExpressionValue(ct => ct.CommandUIExtension); + + var isValid = GetCommandUIString(srcProp.Value.ToString()) == + GetCommandUIString(dstProp.Value.ToString()); + + return new PropertyValidationResult + { + Tag = p.Tag, + Src = srcProp, + Dst = dstProp, + IsValid = isValid + }; + }); + } + else + { + assert.SkipProperty(m => m.CommandUIExtension, "CommandUIExtension is null or empty. Skipping."); + } + + assert + .ShouldBeEqual((p, s, d) => + { + var srcProp = s.GetExpressionValue(def => def.Rights); + var dstProp = d.GetExpressionValue(ct => ct.Rights); + + var hasCorrectRights = true; + + foreach (var srcRight in s.Rights) + { + var srcPermission = (PermissionKind)Enum.Parse(typeof(PermissionKind), srcRight); + + var tmpRight = d.Rights.Has(srcPermission); + + if (tmpRight == false) + hasCorrectRights = false; + } + + return new PropertyValidationResult + { + Tag = p.Tag, + Src = srcProp, + Dst = dstProp, + IsValid = hasCorrectRights + }; + }); + + + var supportsLocalization = ReflectionUtils.HasProperties(spObject, new[] { "TitleResource", "DescriptionResource", "CommandUIExtensionResource" - }); - - if (supportsLocalization) - { - if (definition.TitleResource.Any()) - { - assert.ShouldBeEqual((p, s, d) => - { - var srcProp = s.GetExpressionValue(def => def.TitleResource); - var isValid = true; - - foreach (var userResource in s.TitleResource) - { - var culture = LocalizationService.GetUserResourceCultureInfo(userResource); - var resourceObject = ReflectionUtils.GetPropertyValue(spObject, "TitleResource"); - - var value = ReflectionUtils.GetMethod(resourceObject, "GetValueForUICulture") - .Invoke(resourceObject, new[] { culture.Name }) as ClientResult; - - context.ExecuteQuery(); - - isValid = userResource.Value == value.Value; - - if (!isValid) - break; - } - - return new PropertyValidationResult - { - Tag = p.Tag, - Src = srcProp, - Dst = null, - IsValid = isValid - }; - }); - } - else - { - assert.SkipProperty(m => m.TitleResource, "TitleResource is NULL or empty. Skipping."); - } - - if (definition.DescriptionResource.Any()) - { - assert.ShouldBeEqual((p, s, d) => - { - var srcProp = s.GetExpressionValue(def => def.DescriptionResource); - var isValid = true; - - foreach (var userResource in s.DescriptionResource) - { - var culture = LocalizationService.GetUserResourceCultureInfo(userResource); - var resourceObject = ReflectionUtils.GetPropertyValue(spObject, "DescriptionResource"); - - var value = ReflectionUtils.GetMethod(resourceObject, "GetValueForUICulture") - .Invoke(resourceObject, new[] { culture.Name }) as ClientResult; - - context.ExecuteQuery(); - - isValid = userResource.Value == value.Value; - - if (!isValid) - break; - } - - return new PropertyValidationResult - { - Tag = p.Tag, - Src = srcProp, - Dst = null, - IsValid = isValid - }; - }); - } - else - { - assert.SkipProperty(m => m.DescriptionResource, "DescriptionResource is NULL or empty. Skipping."); - } - - if (definition.CommandUIExtensionResource.Any()) - { - assert.ShouldBeEqual((p, s, d) => - { - var srcProp = s.GetExpressionValue(def => def.CommandUIExtensionResource); - var isValid = true; - - foreach (var userResource in s.CommandUIExtensionResource) - { - var culture = LocalizationService.GetUserResourceCultureInfo(userResource); - var resourceObject = ReflectionUtils.GetPropertyValue(spObject, "CommandUIExtensionResource"); - - var value = ReflectionUtils.GetMethod(resourceObject, "GetValueForUICulture") - .Invoke(resourceObject, new[] { culture.Name }) as ClientResult; - - context.ExecuteQuery(); - - isValid = GetCommandUIString(userResource.Value) == GetCommandUIString(value.Value); - - if (!isValid) - break; - } - - return new PropertyValidationResult - { - Tag = p.Tag, - Src = srcProp, - Dst = null, - IsValid = isValid - }; - }); - } - else - { - assert.SkipProperty(m => m.CommandUIExtensionResource, "DescriptionResource is NULL or empty. Skipping."); - } - - } - else - { - TraceService.Critical((int)LogEventId.ModelProvisionCoreCall, - "CSOM runtime doesn't have Web.TitleResource and Web.DescriptionResource() methods support. Skipping validation."); - - assert.SkipProperty(m => m.TitleResource, "TitleResource is null or empty. Skipping."); - assert.SkipProperty(m => m.DescriptionResource, "DescriptionResource is null or empty. Skipping."); - assert.SkipProperty(m => m.CommandUIExtensionResource, "CommandUIExtensionResource is null or empty. Skipping."); - } - } - - protected string GetCommandUIString(string value) - { - return value.Replace(" ", "") - .Replace(Environment.NewLine, "") - .Replace("\n", ""); - } - } - - internal static class SPUserActionHelpers - { - public static string GetRegistrationType(this UserCustomAction action) - { - return action.RegistrationType.ToString(); - } - } -} + }); + + if (supportsLocalization) + { + if (definition.TitleResource.Any()) + { + assert.ShouldBeEqual((p, s, d) => + { + var srcProp = s.GetExpressionValue(def => def.TitleResource); + var isValid = true; + + foreach (var userResource in s.TitleResource) + { + var culture = LocalizationService.GetUserResourceCultureInfo(userResource); + var resourceObject = ReflectionUtils.GetPropertyValue(spObject, "TitleResource"); + + var value = ReflectionUtils.GetMethod(resourceObject, "GetValueForUICulture") + .Invoke(resourceObject, new[] { culture.Name }) as ClientResult; + + context.ExecuteQuery(); + + isValid = userResource.Value == value.Value; + + if (!isValid) + break; + } + + return new PropertyValidationResult + { + Tag = p.Tag, + Src = srcProp, + Dst = null, + IsValid = isValid + }; + }); + } + else + { + assert.SkipProperty(m => m.TitleResource, "TitleResource is NULL or empty. Skipping."); + } + + if (definition.DescriptionResource.Any()) + { + assert.ShouldBeEqual((p, s, d) => + { + var srcProp = s.GetExpressionValue(def => def.DescriptionResource); + var isValid = true; + + foreach (var userResource in s.DescriptionResource) + { + var culture = LocalizationService.GetUserResourceCultureInfo(userResource); + var resourceObject = ReflectionUtils.GetPropertyValue(spObject, "DescriptionResource"); + + var value = ReflectionUtils.GetMethod(resourceObject, "GetValueForUICulture") + .Invoke(resourceObject, new[] { culture.Name }) as ClientResult; + + context.ExecuteQuery(); + + isValid = userResource.Value == value.Value; + + if (!isValid) + break; + } + + return new PropertyValidationResult + { + Tag = p.Tag, + Src = srcProp, + Dst = null, + IsValid = isValid + }; + }); + } + else + { + assert.SkipProperty(m => m.DescriptionResource, "DescriptionResource is NULL or empty. Skipping."); + } + + if (definition.CommandUIExtensionResource.Any()) + { + assert.ShouldBeEqual((p, s, d) => + { + var srcProp = s.GetExpressionValue(def => def.CommandUIExtensionResource); + var isValid = true; + + foreach (var userResource in s.CommandUIExtensionResource) + { + var culture = LocalizationService.GetUserResourceCultureInfo(userResource); + var resourceObject = ReflectionUtils.GetPropertyValue(spObject, "CommandUIExtensionResource"); + + var value = ReflectionUtils.GetMethod(resourceObject, "GetValueForUICulture") + .Invoke(resourceObject, new[] { culture.Name }) as ClientResult; + + context.ExecuteQuery(); + + isValid = GetCommandUIString(userResource.Value) == GetCommandUIString(value.Value); + + if (!isValid) + break; + } + + return new PropertyValidationResult + { + Tag = p.Tag, + Src = srcProp, + Dst = null, + IsValid = isValid + }; + }); + } + else + { + assert.SkipProperty(m => m.CommandUIExtensionResource, "DescriptionResource is NULL or empty. Skipping."); + } + + } + else + { + TraceService.Critical((int)LogEventId.ModelProvisionCoreCall, + "CSOM runtime doesn't have Web.TitleResource and Web.DescriptionResource() methods support. Skipping validation."); + + assert.SkipProperty(m => m.TitleResource, "TitleResource is null or empty. Skipping."); + assert.SkipProperty(m => m.DescriptionResource, "DescriptionResource is null or empty. Skipping."); + assert.SkipProperty(m => m.CommandUIExtensionResource, "CommandUIExtensionResource is null or empty. Skipping."); + } + } + + protected string GetCommandUIString(string value) + { + return value.Replace(" ", "") + .Replace(Environment.NewLine, "") + .Replace("\n", ""); + } + } + + internal static class SPUserActionHelpers + { + public static string GetRegistrationType(this UserCustomAction action) + { + return action.RegistrationType.ToString(); + } + } +} diff --git a/SPMeta2/SPMeta2.Regression.Tests/Impl/ModelAPI/SPMeta2ModelTests.cs b/SPMeta2/SPMeta2.Regression.Tests/Impl/ModelAPI/SPMeta2ModelTests.cs index d644950a0..4fe4ce32d 100644 --- a/SPMeta2/SPMeta2.Regression.Tests/Impl/ModelAPI/SPMeta2ModelTests.cs +++ b/SPMeta2/SPMeta2.Regression.Tests/Impl/ModelAPI/SPMeta2ModelTests.cs @@ -11,6 +11,8 @@ using SPMeta2.Utils; using SPMeta2.Syntax.Default; using SPMeta2.Containers.Utils; +using SPMeta2.Enumerations; +using SPMeta2.Models; namespace SPMeta2.Regression.Tests.Impl.ModelAPI { @@ -91,6 +93,22 @@ public void CanDeploy_ListModel() [TestCategory("Regression.SPMeta2Model")] public void CanDeploy_ListModel_WithFolders() { + var siteModel = SPMeta2Model.NewSiteModel(site => + { + site.AddSiteFeature(BuiltInSiteFeatures.SharePointServerPublishingInfrastructure.Inherit(def => + { + def.Enable = true; + })); + }); + + var webModel = SPMeta2Model.NewWebModel(web => + { + web.AddWebFeature(BuiltInWebFeatures.SharePointServerPublishing.Inherit(def => + { + def.Enable = true; + })); + }); + var model = SPMeta2Model.NewListModel(list => { list.AddFolder(ModelGeneratorService.GetRandomDefinition()); @@ -98,7 +116,11 @@ public void CanDeploy_ListModel_WithFolders() list.AddFolder(ModelGeneratorService.GetRandomDefinition()); }); - TestModel(model); + TestModels(new ModelNode[]{ + siteModel, + webModel, + model + }); } #endregion @@ -272,7 +294,7 @@ public void SPMeta2Model_NewSiteModel_Contract() Assert.IsTrue(SPMeta2Model.NewSiteModel(newDefinition).GetType() == expectedType); // new definition with callback - Assert.IsTrue(SPMeta2Model.NewSiteModel(newDefinition, node => { }).GetType() == expectedType); + Assert.IsTrue(SPMeta2Model.NewSiteModel(newDefinition, node => { }).GetType() == expectedType); } diff --git a/SPMeta2/SPMeta2.Regression.Tests/Impl/Scenarios/FieldScenariosTest.cs b/SPMeta2/SPMeta2.Regression.Tests/Impl/Scenarios/FieldScenariosTest.cs index fb1acc5f9..86dcb06f4 100644 --- a/SPMeta2/SPMeta2.Regression.Tests/Impl/Scenarios/FieldScenariosTest.cs +++ b/SPMeta2/SPMeta2.Regression.Tests/Impl/Scenarios/FieldScenariosTest.cs @@ -440,14 +440,13 @@ public void CanDeploy_ListScoped_Field() { var field = ModelGeneratorService.GetRandomDefinition(); - var model = SPMeta2Model - .NewWebModel(web => - { - web.AddRandomList(list => - { - list.AddField(field); - }); - }); + var model = SPMeta2Model.NewWebModel(web => + { + web.AddRandomList(list => + { + list.AddField(field); + }); + }); TestModel(model); } diff --git a/SPMeta2/SPMeta2.Regression.Tests/Impl/Scenarios/QuickLaunchNavigationNodeScenariosTest.cs b/SPMeta2/SPMeta2.Regression.Tests/Impl/Scenarios/QuickLaunchNavigationNodeScenariosTest.cs index c1bb1bc64..0945379ca 100644 --- a/SPMeta2/SPMeta2.Regression.Tests/Impl/Scenarios/QuickLaunchNavigationNodeScenariosTest.cs +++ b/SPMeta2/SPMeta2.Regression.Tests/Impl/Scenarios/QuickLaunchNavigationNodeScenariosTest.cs @@ -259,14 +259,13 @@ public void CanDeploy_QuickLaunchNavigationNode_WithSiteCollectionToken() n.Url = string.Format("~sitecollection/{0}.html", Rnd.String()); }); - var model = SPMeta2Model - .NewWebModel(web => + var model = SPMeta2Model.NewWebModel(web => + { + web.AddRandomWeb(rndWeb => { - web.AddRandomWeb(rndWeb => - { - rndWeb.AddQuickLaunchNavigationNode(nav1Node); - }); + rndWeb.AddQuickLaunchNavigationNode(nav1Node); }); + }); TestModel(model); } diff --git a/SPMeta2/SPMeta2.Regression.Tests/Impl/Scenarios/ReusableItemScenariosTest.cs b/SPMeta2/SPMeta2.Regression.Tests/Impl/Scenarios/ReusableItemScenariosTest.cs index d2b374e38..913e1b764 100644 --- a/SPMeta2/SPMeta2.Regression.Tests/Impl/Scenarios/ReusableItemScenariosTest.cs +++ b/SPMeta2/SPMeta2.Regression.Tests/Impl/Scenarios/ReusableItemScenariosTest.cs @@ -1,84 +1,110 @@ -using System; -using System.Collections.Generic; -using System.Linq; -using System.Text; - -using Microsoft.VisualStudio.TestTools.UnitTesting; -using SPMeta2.BuiltInDefinitions; -using SPMeta2.Containers; -using SPMeta2.Definitions; -using SPMeta2.Definitions.ContentTypes; -using SPMeta2.Enumerations; -using SPMeta2.Regression.Tests.Impl.Scenarios.Base; -using SPMeta2.Standard.Definitions; -using SPMeta2.Standard.Syntax; -using SPMeta2.Syntax.Default; - -namespace SPMeta2.Regression.Tests.Impl.Scenarios -{ - [TestClass] - public class ReusableItemScenariosTest : SPMeta2RegresionScenarioTestBase - { - #region internal - - [ClassInitializeAttribute] - public static void Init(TestContext context) - { - InternalInit(); - } - - [ClassCleanup] - public static void Cleanup() - { - InternalCleanup(); - } - - #endregion - - #region tests - - [TestMethod] - [TestCategory("Regression.Scenarios.ReusableItems")] - public void CanDeploy_ReusableItemsToList() - { - var reusableHtml = ModelGeneratorService.GetRandomDefinition(); - var reusableText = ModelGeneratorService.GetRandomDefinition(); - - var model = SPMeta2Model.NewWebModel(web => - { - web.AddHostList(BuiltInListDefinitions.ReusableContent, list => - { - list.AddReusableHTMLItem(reusableHtml); - list.AddReusableTextItem(reusableText); - }); - }); - - TestModel(model); - } - - [TestMethod] - [TestCategory("Regression.Scenarios.ReusableItems")] - public void CanDeploy_ReusableItemsToFolder() - { - var reusableHtml = ModelGeneratorService.GetRandomDefinition(); - var reusableText = ModelGeneratorService.GetRandomDefinition(); - - var model = SPMeta2Model.NewWebModel(web => - { - web.AddHostList(BuiltInListDefinitions.ReusableContent, list => - { - list.AddRandomFolder(folder => - { - folder.AddReusableHTMLItem(reusableHtml); - folder.AddReusableTextItem(reusableText); - }); - }); - }); - - TestModel(model); - } - - #endregion - - } -} +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; + +using Microsoft.VisualStudio.TestTools.UnitTesting; +using SPMeta2.BuiltInDefinitions; +using SPMeta2.Containers; +using SPMeta2.Definitions; +using SPMeta2.Definitions.ContentTypes; +using SPMeta2.Enumerations; +using SPMeta2.Regression.Tests.Impl.Scenarios.Base; +using SPMeta2.Standard.Definitions; +using SPMeta2.Standard.Syntax; +using SPMeta2.Syntax.Default; + +namespace SPMeta2.Regression.Tests.Impl.Scenarios +{ + [TestClass] + public class ReusableItemScenariosTest : SPMeta2RegresionScenarioTestBase + { + #region internal + + [ClassInitializeAttribute] + public static void Init(TestContext context) + { + InternalInit(); + } + + [ClassCleanup] + public static void Cleanup() + { + InternalCleanup(); + } + + #endregion + + #region tests + + [TestMethod] + [TestCategory("Regression.Scenarios.ReusableItems")] + public void CanDeploy_ReusableItemsToList() + { + var siteModel = SPMeta2Model.NewSiteModel(site => + { + site.AddSiteFeature(BuiltInSiteFeatures.SharePointServerPublishingInfrastructure.Inherit(def => + { + def.Enable = true; + })); + }); + + var reusableHtml = ModelGeneratorService.GetRandomDefinition(); + var reusableText = ModelGeneratorService.GetRandomDefinition(); + + var model = SPMeta2Model.NewWebModel(web => + { + web.AddWebFeature(BuiltInWebFeatures.SharePointServerPublishing.Inherit(def => + { + def.Enable = true; + })); + + web.AddHostList(BuiltInListDefinitions.ReusableContent, list => + { + list.AddReusableHTMLItem(reusableHtml); + list.AddReusableTextItem(reusableText); + }); + }); + + TestModel(siteModel, model); + } + + [TestMethod] + [TestCategory("Regression.Scenarios.ReusableItems")] + public void CanDeploy_ReusableItemsToFolder() + { + var siteModel = SPMeta2Model.NewSiteModel(site => + { + site.AddSiteFeature(BuiltInSiteFeatures.SharePointServerPublishingInfrastructure.Inherit(def => + { + def.Enable = true; + })); + }); + + var reusableHtml = ModelGeneratorService.GetRandomDefinition(); + var reusableText = ModelGeneratorService.GetRandomDefinition(); + + var model = SPMeta2Model.NewWebModel(web => + { + web.AddWebFeature(BuiltInWebFeatures.SharePointServerPublishing.Inherit(def => + { + def.Enable = true; + })); + + web.AddHostList(BuiltInListDefinitions.ReusableContent, list => + { + list.AddRandomFolder(folder => + { + folder.AddReusableHTMLItem(reusableHtml); + folder.AddReusableTextItem(reusableText); + }); + }); + }); + + TestModel(siteModel, model); + } + + #endregion + + } +} diff --git a/SPMeta2/SPMeta2.Regression.Tests/Impl/Scenarios/SP2013WorkflowScenariosTest.cs b/SPMeta2/SPMeta2.Regression.Tests/Impl/Scenarios/SP2013WorkflowScenariosTest.cs index 06b7615e0..d104ce7a3 100644 --- a/SPMeta2/SPMeta2.Regression.Tests/Impl/Scenarios/SP2013WorkflowScenariosTest.cs +++ b/SPMeta2/SPMeta2.Regression.Tests/Impl/Scenarios/SP2013WorkflowScenariosTest.cs @@ -1,229 +1,228 @@ -using System; -using System.Collections.Generic; -using System.Linq; -using System.Text; - -using Microsoft.VisualStudio.TestTools.UnitTesting; -using SPMeta2.BuiltInDefinitions; -using SPMeta2.Containers; -using SPMeta2.Containers.Standard; - -using SPMeta2.Definitions; -using SPMeta2.Enumerations; -using SPMeta2.Models; -using SPMeta2.Regression.Tests.Definitions; -using SPMeta2.Regression.Tests.Impl.Scenarios.Base; -using SPMeta2.Standard.Definitions; -using SPMeta2.Syntax.Default; +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; + +using Microsoft.VisualStudio.TestTools.UnitTesting; +using SPMeta2.BuiltInDefinitions; +using SPMeta2.Containers; +using SPMeta2.Containers.Standard; + +using SPMeta2.Definitions; +using SPMeta2.Enumerations; +using SPMeta2.Models; +using SPMeta2.Regression.Tests.Definitions; +using SPMeta2.Regression.Tests.Impl.Scenarios.Base; +using SPMeta2.Standard.Definitions; +using SPMeta2.Syntax.Default; using SPMeta2.Validation.Validators.Relationships; -using SPMeta2.Regression.Tests.Extensions; - -namespace SPMeta2.Regression.Tests.Impl.Scenarios -{ - [TestClass] - public class SP2013WorkflowScenariosTest : SPMeta2RegresionScenarioTestBase - { - #region internal - - [ClassInitializeAttribute] - public static void Init(TestContext context) - { - InternalInit(); - } - - [ClassCleanupAttribute] - public static void Cleanup() - { - InternalCleanup(); - } - - #endregion - - #region default - - [TestMethod] - [TestCategory("Regression.Scenarios.SP2013Workflow")] - public void CanDeploy_SP2013WebWorkflowAccosiation() - { - var model = SPMeta2Model - .NewWebModel(web => - { - AddWebWorkflow(web); - }); - - TestModel(model); - } - - [TestMethod] - [TestCategory("Regression.Scenarios.SP2013Workflow")] - public void CanDeploy_SP2013ListWorkflowAccosiation() - { - var model = SPMeta2Model - .NewWebModel(web => - { - AddListWorkflow(web); - }); - - TestModel(model); - } - - #endregion - - #region list workflow on sub webs - - [TestMethod] - [TestCategory("Regression.Scenarios.SP2013Workflow")] - public void CanDeploy_SP2013ListWorkflowAccosiation_OnHierarchicalWebs() - { - var level1Web = ModelGeneratorService.GetRandomDefinition(w => - { - w.Url = string.Format("l1{0}", Rnd.String()); - }); - - var level2Web = ModelGeneratorService.GetRandomDefinition(w => - { - w.Url = string.Format("l2{0}", Rnd.String()); - }); - - var model = SPMeta2Model - .NewWebModel(web => - { - web - .AddWeb(level1Web, l1w => - { - AddListWorkflow(l1w); - - l1w.AddWeb(level2Web, l2web => - { - AddListWorkflow(l2web); - }); - - }); - - AddListWorkflow(web); - }); - - TestModel(model); - } - - #endregion - - #region web workflow on sub webs - - [TestMethod] - [TestCategory("Regression.Scenarios.SP2013Workflow")] - public void CanDeploy_SP2013WebWorkflowAccosiation_OnHierarchicalWebs() - { - var level1Web = ModelGeneratorService.GetRandomDefinition(w => - { - w.Url = string.Format("l1{0}", Rnd.String()); - }); - - var level2Web = ModelGeneratorService.GetRandomDefinition(w => - { - w.Url = string.Format("l2{0}", Rnd.String()); - }); - - var model = SPMeta2Model - .NewWebModel(web => - { - web - .AddWeb(level1Web, l1w => - { - AddWebWorkflow(l1w); - - l1w.AddWeb(level2Web, l2web => - { - AddWebWorkflow(l2web); - }); - }); - - AddWebWorkflow(web); - }); - - TestModel(model); - - } - - #endregion - - #region utils - - protected ListDefinition GetTaskList() - { - return new ListDefinition - { - Title = Rnd.String(), - TemplateType = BuiltInListTemplateTypeId.Tasks, -#pragma warning disable 618 - Url = Rnd.String() -#pragma warning restore 618 - }; - } - - protected ListDefinition GetHistoryList() - { - return new ListDefinition - { - Title = Rnd.String(), - TemplateType = BuiltInListTemplateTypeId.WorkflowHistory, -#pragma warning disable 618 - Url = Rnd.String() -#pragma warning restore 618 - }; - } - - protected void AddWebWorkflow(WebModelNode web) - { - var workflow = ModelGeneratorService.GetRandomDefinition(); - - var historyList = GetHistoryList(); - var taskList = GetTaskList(); - - web - .AddList(historyList) - .AddList(taskList) - .AddSP2013Workflow(workflow) - .AddSP2013WorkflowSubscription(new SP2013WorkflowSubscriptionDefinition - { - Name = Rnd.String(), - WorkflowDisplayName = workflow.DisplayName, -#pragma warning disable 618 - HistoryListUrl = historyList.GetListUrl(), - TaskListUrl = taskList.GetListUrl() -#pragma warning restore 618 - }); - } - - protected void AddListWorkflow(WebModelNode web) - { - var workflow = ModelGeneratorService.GetRandomDefinition(); - var workflowEnableList = ModelGeneratorService.GetRandomDefinition(); - - var historyList = GetHistoryList(); - var taskList = GetTaskList(); - - web - - .AddList(historyList) - .AddList(taskList) - .AddList(workflowEnableList, list => - { - list.AddSP2013WorkflowSubscription(new SP2013WorkflowSubscriptionDefinition - { - Name = Rnd.String(), - WorkflowDisplayName = workflow.DisplayName, -#pragma warning disable 618 - HistoryListUrl = historyList.GetListUrl(), - TaskListUrl = taskList.GetListUrl() -#pragma warning restore 618 - }); - }) - .AddSP2013Workflow(workflow); - } - - #endregion - } - -} +using SPMeta2.Regression.Tests.Extensions; + +namespace SPMeta2.Regression.Tests.Impl.Scenarios +{ + [TestClass] + public class SP2013WorkflowScenariosTest : SPMeta2RegresionScenarioTestBase + { + #region internal + + [ClassInitializeAttribute] + public static void Init(TestContext context) + { + InternalInit(); + } + + [ClassCleanupAttribute] + public static void Cleanup() + { + InternalCleanup(); + } + + #endregion + + #region default + + [TestMethod] + [TestCategory("Regression.Scenarios.SP2013Workflow")] + public void CanDeploy_SP2013WebWorkflowAccosiation() + { + var model = SPMeta2Model + .NewWebModel(web => + { + AddWebWorkflow(web); + }); + + TestModel(model); + } + + [TestMethod] + [TestCategory("Regression.Scenarios.SP2013Workflow")] + public void CanDeploy_SP2013ListWorkflowAccosiation() + { + var model = SPMeta2Model.NewWebModel(web => + { + AddListWorkflow(web); + }); + + TestModel(model); + } + + #endregion + + #region list workflow on sub webs + + [TestMethod] + [TestCategory("Regression.Scenarios.SP2013Workflow")] + public void CanDeploy_SP2013ListWorkflowAccosiation_OnHierarchicalWebs() + { + var level1Web = ModelGeneratorService.GetRandomDefinition(w => + { + w.Url = string.Format("l1{0}", Rnd.String()); + }); + + var level2Web = ModelGeneratorService.GetRandomDefinition(w => + { + w.Url = string.Format("l2{0}", Rnd.String()); + }); + + var model = SPMeta2Model + .NewWebModel(web => + { + web + .AddWeb(level1Web, l1w => + { + AddListWorkflow(l1w); + + l1w.AddWeb(level2Web, l2web => + { + AddListWorkflow(l2web); + }); + + }); + + AddListWorkflow(web); + }); + + TestModel(model); + } + + #endregion + + #region web workflow on sub webs + + [TestMethod] + [TestCategory("Regression.Scenarios.SP2013Workflow")] + public void CanDeploy_SP2013WebWorkflowAccosiation_OnHierarchicalWebs() + { + var level1Web = ModelGeneratorService.GetRandomDefinition(w => + { + w.Url = string.Format("l1{0}", Rnd.String()); + }); + + var level2Web = ModelGeneratorService.GetRandomDefinition(w => + { + w.Url = string.Format("l2{0}", Rnd.String()); + }); + + var model = SPMeta2Model + .NewWebModel(web => + { + web + .AddWeb(level1Web, l1w => + { + AddWebWorkflow(l1w); + + l1w.AddWeb(level2Web, l2web => + { + AddWebWorkflow(l2web); + }); + }); + + AddWebWorkflow(web); + }); + + TestModel(model); + + } + + #endregion + + #region utils + + protected ListDefinition GetTaskList() + { + return new ListDefinition + { + Title = Rnd.String(), + TemplateType = BuiltInListTemplateTypeId.Tasks, +#pragma warning disable 618 + Url = Rnd.String() +#pragma warning restore 618 + }; + } + + protected ListDefinition GetHistoryList() + { + return new ListDefinition + { + Title = Rnd.String(), + TemplateType = BuiltInListTemplateTypeId.WorkflowHistory, +#pragma warning disable 618 + Url = Rnd.String() +#pragma warning restore 618 + }; + } + + protected void AddWebWorkflow(WebModelNode web) + { + var workflow = ModelGeneratorService.GetRandomDefinition(); + + var historyList = GetHistoryList(); + var taskList = GetTaskList(); + + web + .AddList(historyList) + .AddList(taskList) + .AddSP2013Workflow(workflow) + .AddSP2013WorkflowSubscription(new SP2013WorkflowSubscriptionDefinition + { + Name = Rnd.String(), + WorkflowDisplayName = workflow.DisplayName, +#pragma warning disable 618 + HistoryListUrl = historyList.GetListUrl(), + TaskListUrl = taskList.GetListUrl() +#pragma warning restore 618 + }); + } + + protected void AddListWorkflow(WebModelNode web) + { + var workflow = ModelGeneratorService.GetRandomDefinition(); + var workflowEnableList = ModelGeneratorService.GetRandomDefinition(); + + var historyList = GetHistoryList(); + var taskList = GetTaskList(); + + web + + .AddList(historyList) + .AddList(taskList) + .AddList(workflowEnableList, list => + { + list.AddSP2013WorkflowSubscription(new SP2013WorkflowSubscriptionDefinition + { + Name = Rnd.String(), + WorkflowDisplayName = workflow.DisplayName, +#pragma warning disable 618 + HistoryListUrl = historyList.GetListUrl(), + TaskListUrl = taskList.GetListUrl() +#pragma warning restore 618 + }); + }) + .AddSP2013Workflow(workflow); + } + + #endregion + } + +} diff --git a/SPMeta2/SPMeta2.Regression.Tests/Impl/Scenarios/WebpartScenariosTest.cs b/SPMeta2/SPMeta2.Regression.Tests/Impl/Scenarios/WebpartScenariosTest.cs index 0a1288e2d..b9b1a1a66 100644 --- a/SPMeta2/SPMeta2.Regression.Tests/Impl/Scenarios/WebpartScenariosTest.cs +++ b/SPMeta2/SPMeta2.Regression.Tests/Impl/Scenarios/WebpartScenariosTest.cs @@ -418,18 +418,22 @@ public void CanDeploy_Webpart_With_AuthorizationFilter() var webModel = SPMeta2Model.NewWebModel(web => { - web - .AddHostList(BuiltInListDefinitions.SitePages, list => + web.AddWebFeature(BuiltInWebFeatures.WikiPageHomePage.Inherit(def => + { + def.Enable = true; + })); + + web.AddHostList(BuiltInListDefinitions.SitePages, list => + { + list.AddRandomWebPartPage(page => { - list.AddRandomWebPartPage(page => + page.AddRandomWebpart(webPart => { - page.AddRandomWebpart(webPart => - { - var wpDef = webPart.Value as WebPartDefinition; - wpDef.AuthorizationFilter = string.Format(";;;;{0}", securityGroupDef.Name); - }); + var wpDef = webPart.Value as WebPartDefinition; + wpDef.AuthorizationFilter = string.Format(";;;;{0}", securityGroupDef.Name); }); }); + }); }); @@ -441,29 +445,32 @@ public void CanDeploy_Webpart_With_AuthorizationFilter() [TestCategory("Regression.Scenarios.Webparts.Hosts")] public void CanDeploy_WebpartTo_WebpartPage() { - var model = SPMeta2Model - .NewWebModel(web => + var model = SPMeta2Model.NewWebModel(web => + { + web.AddWebFeature(BuiltInWebFeatures.WikiPageHomePage.Inherit(def => { - web - .AddHostList(BuiltInListDefinitions.SitePages, list => + def.Enable = true; + })); + + web.AddHostList(BuiltInListDefinitions.SitePages, list => + { + list + .AddRandomWebPartPage(page => { - list - .AddRandomWebPartPage(page => - { - page - .AddRandomWebpart() - .AddRandomWebpart(); - }) - .AddRandomWebPartPage(page => - { - page - .AddRandomWebpart() - .AddRandomWebpart(); - }); + page + .AddRandomWebpart() + .AddRandomWebpart(); + }) + .AddRandomWebPartPage(page => + { + page + .AddRandomWebpart() + .AddRandomWebpart(); }); - }); + }); + TestModel(model); } @@ -484,6 +491,11 @@ public void CanDeploy_WebpartTo_WebpartPage_WithCustomPageLayout() var model = SPMeta2Model.NewWebModel(web => { + web.AddWebFeature(BuiltInWebFeatures.WikiPageHomePage.Inherit(def => + { + def.Enable = true; + })); + web.AddHostList(BuiltInListDefinitions.SitePages, list => { list @@ -516,32 +528,35 @@ public void CanDeploy_WebpartTo_WebpartPage_WithCustomPageLayout() [TestCategory("Regression.Scenarios.Webparts")] public void CanDeploy_Webpart_WithTitleUrl_WithTokens() { - var model = SPMeta2Model - .NewWebModel(web => + var model = SPMeta2Model.NewWebModel(web => + { + web.AddWebFeature(BuiltInWebFeatures.WikiPageHomePage.Inherit(def => { - web - .AddHostList(BuiltInListDefinitions.SitePages, list => + def.Enable = true; + })); + + web.AddHostList(BuiltInListDefinitions.SitePages, list => + { + list + .AddRandomWebPartPage(page => { - list - .AddRandomWebPartPage(page => + page + .AddRandomWebpart(w => { - page - .AddRandomWebpart(w => - { - (w.Value as WebPartDefinition).TitleUrl = - string.Format("~sitecollection/{0}.html", Rnd.String()); - }) - .AddRandomWebpart(w => - { - (w.Value as WebPartDefinition).TitleUrl = - string.Format("~site/{0}.html", Rnd.String()); - - }); + (w.Value as WebPartDefinition).TitleUrl = + string.Format("~sitecollection/{0}.html", Rnd.String()); + }) + .AddRandomWebpart(w => + { + (w.Value as WebPartDefinition).TitleUrl = + string.Format("~site/{0}.html", Rnd.String()); + }); }); - }); + }); + TestModel(model); } @@ -621,24 +636,27 @@ public void CanDeploy_WebpartTo_PublishingPageWebPartZone() var webModel = SPMeta2Model.NewWebModel(web => { - web - .AddWebFeature(RegWebFeatures.Publishing) - .AddHostList(BuiltInListDefinitions.Pages, list => - { - list - .AddRandomPublishingPage(page => - { - page - .AddRandomWebpart() - .AddRandomWebpart(); - }) - .AddRandomPublishingPage(page => - { - page - .AddRandomWebpart() - .AddRandomWebpart(); - }); - }); + web.AddWebFeature(BuiltInWebFeatures.SharePointServerPublishing.Inherit(def => + { + def.Enable = true; + })); + + web.AddHostList(BuiltInListDefinitions.Pages, list => + { + list + .AddRandomPublishingPage(page => + { + page + .AddRandomWebpart() + .AddRandomWebpart(); + }) + .AddRandomPublishingPage(page => + { + page + .AddRandomWebpart() + .AddRandomWebpart(); + }); + }); }); @@ -651,77 +669,89 @@ public void CanDeploy_WebpartTo_PublishingPageWebPartZone() [TestCategory("Regression.Scenarios.Webparts.Hosts")] public void CanDeploy_WebpartTo_PublishingPageContent() { - var webModel = SPMeta2Model - .NewWebModel(web => - { - web - .AddHostList(BuiltInListDefinitions.Pages, list => - { - list - .AddRandomPublishingPage(page => - { - var id_1 = "g_" + Guid.NewGuid().ToString("D").Replace('-', '_'); - var id_2 = "g_" + Guid.NewGuid().ToString("D").Replace('-', '_'); + var siteModel = SPMeta2Model.NewSiteModel(site => + { + site.AddSiteFeature(BuiltInSiteFeatures.SharePointServerPublishingInfrastructure.Inherit(def => + { + def.Enable = true; + })); + }); - var id_3 = "g_" + Guid.NewGuid().ToString("D").Replace('-', '_'); + var webModel = SPMeta2Model.NewWebModel(web => + { + web.AddWebFeature(BuiltInWebFeatures.SharePointServerPublishing.Inherit(def => + { + def.Enable = true; + })); - var wpId11 = id_1 - .Replace("g_", string.Empty) - .Replace("_", "-"); + web + .AddHostList(BuiltInListDefinitions.Pages, list => + { + list + .AddRandomPublishingPage(page => + { + var id_1 = "g_" + Guid.NewGuid().ToString("D").Replace('-', '_'); + var id_2 = "g_" + Guid.NewGuid().ToString("D").Replace('-', '_'); - var wpId22 = id_2 - .Replace("g_", string.Empty) - .Replace("_", "-"); + var id_3 = "g_" + Guid.NewGuid().ToString("D").Replace('-', '_'); - var pageTemplate = new StringBuilder(); + var wpId11 = id_1 + .Replace("g_", string.Empty) + .Replace("_", "-"); - pageTemplate.AppendFormat("​​​​​​​​​​​​​​​​​​​​​​
"); - pageTemplate.AppendFormat("
", wpId11); - pageTemplate.AppendFormat("
"); - pageTemplate.AppendFormat("
"); + var wpId22 = id_2 + .Replace("g_", string.Empty) + .Replace("_", "-"); - pageTemplate.AppendFormat("
"); - pageTemplate.AppendFormat(" SPMeta2 publishing page."); - pageTemplate.AppendFormat("
"); + var pageTemplate = new StringBuilder(); - pageTemplate.AppendFormat("​​​​​​​​​​​​​​​​​​​​​​
"); - pageTemplate.AppendFormat("
", wpId22); - pageTemplate.AppendFormat("
"); - pageTemplate.AppendFormat("
"); + pageTemplate.AppendFormat("​​​​​​​​​​​​​​​​​​​​​​
"); + pageTemplate.AppendFormat("
", wpId11); + pageTemplate.AppendFormat("
"); + pageTemplate.AppendFormat("
"); - (page.Value as PublishingPageDefinition).Content = pageTemplate.ToString(); + pageTemplate.AppendFormat("
"); + pageTemplate.AppendFormat(" SPMeta2 publishing page."); + pageTemplate.AppendFormat("
"); - page - .AddRandomWebpart(wpNode => - { - var wp = wpNode.Value as WebPartDefinition; - - wp.ZoneId = "wpz"; - wp.Id = id_1; - wp.AddToPageContent = true; - }) - .AddRandomWebpart(wpNode => - { - var wp = wpNode.Value as WebPartDefinition; - - wp.ZoneId = "wpz"; - wp.Id = id_2; - wp.AddToPageContent = true; - }) - .AddRandomWebpart(wpNode => - { - var wp = wpNode.Value as WebPartDefinition; - - wp.ZoneId = "wpz"; - wp.Id = id_3; - wp.AddToPageContent = true; - }); - }); - }); + pageTemplate.AppendFormat("​​​​​​​​​​​​​​​​​​​​​​
"); + pageTemplate.AppendFormat("
", wpId22); + pageTemplate.AppendFormat("
"); + pageTemplate.AppendFormat("
"); - }); + (page.Value as PublishingPageDefinition).Content = pageTemplate.ToString(); - TestModel(webModel); + page + .AddRandomWebpart(wpNode => + { + var wp = wpNode.Value as WebPartDefinition; + + wp.ZoneId = "wpz"; + wp.Id = id_1; + wp.AddToPageContent = true; + }) + .AddRandomWebpart(wpNode => + { + var wp = wpNode.Value as WebPartDefinition; + + wp.ZoneId = "wpz"; + wp.Id = id_2; + wp.AddToPageContent = true; + }) + .AddRandomWebpart(wpNode => + { + var wp = wpNode.Value as WebPartDefinition; + + wp.ZoneId = "wpz"; + wp.Id = id_3; + wp.AddToPageContent = true; + }); + }); + }); + + }); + + TestModel(siteModel, webModel); } [TestMethod] @@ -732,22 +762,25 @@ public void CanDeploy_WebpartTo_WikiPageContent_AsItIs() // Some web part provision on wiki page give empty markup // https://github.com/SubPointSolutions/spmeta2/issues/693 - var webModel = SPMeta2Model - .NewWebModel(web => - { - web - .AddHostList(BuiltInListDefinitions.SitePages, list => - { - list - .AddRandomWikiPage(page => - { - page - .AddRandomWebpart() - .AddRandomWebpart() - .AddRandomWebpart(); - }); - }); - }); + var webModel = SPMeta2Model.NewWebModel(web => + { + web.AddWebFeature(BuiltInWebFeatures.WikiPageHomePage.Inherit(def => + { + def.Enable = true; + })); + + web.AddHostList(BuiltInListDefinitions.SitePages, list => + { + list + .AddRandomWikiPage(page => + { + page + .AddRandomWebpart() + .AddRandomWebpart() + .AddRandomWebpart(); + }); + }); + }); TestModel(webModel); } @@ -784,22 +817,26 @@ public void CanDeploy_ScriptEditorTo_WikiPageContent_As_AddToPageContent() Rnd.String()) }; - var webModel = SPMeta2Model - .NewWebModel(web => - { - web - .AddHostList(BuiltInListDefinitions.SitePages, list => - { - list - .AddRandomWikiPage(page => - { - page.RegExcludeFromValidation(); + var webModel = SPMeta2Model.NewWebModel(web => + { + web.AddWebFeature(BuiltInWebFeatures.WikiPageHomePage.Inherit(def => + { + def.Enable = true; + })); - page.AddScriptEditorWebPart(scriptEditor1); - page.AddScriptEditorWebPart(scriptEditor2); - }); - }); - }); + web + .AddHostList(BuiltInListDefinitions.SitePages, list => + { + list + .AddRandomWikiPage(page => + { + page.RegExcludeFromValidation(); + + page.AddScriptEditorWebPart(scriptEditor1); + page.AddScriptEditorWebPart(scriptEditor2); + }); + }); + }); TestModel(webModel); } @@ -825,47 +862,50 @@ public void CanDeploy_WebpartTo_WikiPageContent_As_AddToPageContent() ListUrl = BuiltInListDefinitions.SitePages.CustomUrl }; - var webModel = SPMeta2Model - .NewWebModel(web => - { - web - .AddHostList(BuiltInListDefinitions.SitePages, list => - { - list - .AddRandomWikiPage(page => - { - page.RegExcludeFromValidation(); + var webModel = SPMeta2Model.NewWebModel(web => + { + web.AddWebFeature(BuiltInWebFeatures.WikiPageHomePage.Inherit(def => + { + def.Enable = true; + })); - page - .AddListViewWebPart(listViewWebPartDef) - .AddRandomWebpart(wpNode => - { - var wp = wpNode.Value as WebPartDefinition; - - wp.Id = "g_" + Guid.NewGuid().ToString("D").Replace('-', '_'); - wp.ZoneId = "wpz"; - wp.AddToPageContent = true; - }) - .AddRandomWebpart(wpNode => - { - var wp = wpNode.Value as WebPartDefinition; - - wp.Id = "g_" + Guid.NewGuid().ToString("D").Replace('-', '_'); - wp.ZoneId = "wpz"; - wp.AddToPageContent = true; - }) - .AddRandomWebpart(wpNode => - { - var wp = wpNode.Value as WebPartDefinition; - - wp.Id = "g_" + Guid.NewGuid().ToString("D").Replace('-', '_'); - wp.ZoneId = "wpz"; - wp.AddToPageContent = true; - }) - ; - }); - }); - }); + web.AddHostList(BuiltInListDefinitions.SitePages, list => + { + list + .AddRandomWikiPage(page => + { + page.RegExcludeFromValidation(); + + page + .AddListViewWebPart(listViewWebPartDef) + .AddRandomWebpart(wpNode => + { + var wp = wpNode.Value as WebPartDefinition; + + wp.Id = "g_" + Guid.NewGuid().ToString("D").Replace('-', '_'); + wp.ZoneId = "wpz"; + wp.AddToPageContent = true; + }) + .AddRandomWebpart(wpNode => + { + var wp = wpNode.Value as WebPartDefinition; + + wp.Id = "g_" + Guid.NewGuid().ToString("D").Replace('-', '_'); + wp.ZoneId = "wpz"; + wp.AddToPageContent = true; + }) + .AddRandomWebpart(wpNode => + { + var wp = wpNode.Value as WebPartDefinition; + + wp.Id = "g_" + Guid.NewGuid().ToString("D").Replace('-', '_'); + wp.ZoneId = "wpz"; + wp.AddToPageContent = true; + }) + ; + }); + }); + }); TestModel(webModel); } @@ -875,77 +915,80 @@ public void CanDeploy_WebpartTo_WikiPageContent_As_AddToPageContent() [TestCategory("Regression.Scenarios.Webparts.Hosts")] public void CanDeploy_WebpartTo_WikiPageContent() { - var webModel = SPMeta2Model - .NewWebModel(web => - { - web - .AddHostList(BuiltInListDefinitions.SitePages, list => - { - list - .AddRandomWikiPage(page => - { - page.RegExcludeFromValidation(); + var webModel = SPMeta2Model.NewWebModel(web => + { + web.AddWebFeature(BuiltInWebFeatures.WikiPageHomePage.Inherit(def => + { + def.Enable = true; + })); - var id_1 = "g_" + Guid.NewGuid().ToString("D").Replace('-', '_'); - var id_2 = "g_" + Guid.NewGuid().ToString("D").Replace('-', '_'); + web.AddHostList(BuiltInListDefinitions.SitePages, list => + { + list + .AddRandomWikiPage(page => + { + page.RegExcludeFromValidation(); - var id_3 = "g_" + Guid.NewGuid().ToString("D").Replace('-', '_'); + var id_1 = "g_" + Guid.NewGuid().ToString("D").Replace('-', '_'); + var id_2 = "g_" + Guid.NewGuid().ToString("D").Replace('-', '_'); - var wpId11 = id_1 - .Replace("g_", string.Empty) - .Replace("_", "-"); + var id_3 = "g_" + Guid.NewGuid().ToString("D").Replace('-', '_'); - var wpId22 = id_2 - .Replace("g_", string.Empty) - .Replace("_", "-"); + var wpId11 = id_1 + .Replace("g_", string.Empty) + .Replace("_", "-"); - var pageTemplate = new StringBuilder(); + var wpId22 = id_2 + .Replace("g_", string.Empty) + .Replace("_", "-"); - pageTemplate.AppendFormat("​​​​​​​​​​​​​​​​​​​​​​
"); - pageTemplate.AppendFormat("
", wpId11); - pageTemplate.AppendFormat("
"); - pageTemplate.AppendFormat("
"); + var pageTemplate = new StringBuilder(); - pageTemplate.AppendFormat("
"); - pageTemplate.AppendFormat(" SPMeta2 wiki page."); - pageTemplate.AppendFormat("
"); + pageTemplate.AppendFormat("​​​​​​​​​​​​​​​​​​​​​​
"); + pageTemplate.AppendFormat("
", wpId11); + pageTemplate.AppendFormat("
"); + pageTemplate.AppendFormat("
"); - pageTemplate.AppendFormat("​​​​​​​​​​​​​​​​​​​​​​
"); - pageTemplate.AppendFormat("
", wpId22); - pageTemplate.AppendFormat("
"); - pageTemplate.AppendFormat("
"); + pageTemplate.AppendFormat("
"); + pageTemplate.AppendFormat(" SPMeta2 wiki page."); + pageTemplate.AppendFormat("
"); - (page.Value as WikiPageDefinition).Content = pageTemplate.ToString(); + pageTemplate.AppendFormat("​​​​​​​​​​​​​​​​​​​​​​
"); + pageTemplate.AppendFormat("
", wpId22); + pageTemplate.AppendFormat("
"); + pageTemplate.AppendFormat("
"); - page - .AddRandomWebpart(wpNode => - { - var wp = wpNode.Value as WebPartDefinition; - - wp.ZoneId = "wpz"; - wp.Id = id_1; - wp.AddToPageContent = true; - }) - .AddRandomWebpart(wpNode => - { - var wp = wpNode.Value as WebPartDefinition; - - wp.ZoneId = "wpz"; - wp.Id = id_2; - wp.AddToPageContent = true; - }) - .AddRandomWebpart(wpNode => - { - var wp = wpNode.Value as WebPartDefinition; - - wp.ZoneId = "wpz"; - wp.Id = id_3; - wp.AddToPageContent = true; - }); - }); - }); + (page.Value as WikiPageDefinition).Content = pageTemplate.ToString(); - }); + page + .AddRandomWebpart(wpNode => + { + var wp = wpNode.Value as WebPartDefinition; + + wp.ZoneId = "wpz"; + wp.Id = id_1; + wp.AddToPageContent = true; + }) + .AddRandomWebpart(wpNode => + { + var wp = wpNode.Value as WebPartDefinition; + + wp.ZoneId = "wpz"; + wp.Id = id_2; + wp.AddToPageContent = true; + }) + .AddRandomWebpart(wpNode => + { + var wp = wpNode.Value as WebPartDefinition; + + wp.ZoneId = "wpz"; + wp.Id = id_3; + wp.AddToPageContent = true; + }); + }); + }); + + }); TestModel(webModel); } diff --git a/SPMeta2/SPMeta2/Services/Impl/DefaultTryRetryService.cs b/SPMeta2/SPMeta2/Services/Impl/DefaultTryRetryService.cs index b63799e35..ab2ec83a0 100644 --- a/SPMeta2/SPMeta2/Services/Impl/DefaultTryRetryService.cs +++ b/SPMeta2/SPMeta2/Services/Impl/DefaultTryRetryService.cs @@ -60,11 +60,11 @@ public override void TryWithRetry(Func action, { TraceService.Warning((int)LogEventId.ModelProvision, string.Format("Coudn't perform action. Waiting and retrying [{1}/{2}]", - RetryTimeoutInMilliseconds, + retryTimeoutInMilliseconds, currentTryIndex, MaxRetryCount)); - if (currentTryIndex > retryTimeoutInMilliseconds) + if (currentTryIndex > maxTryCount) break; waiter(currentTryIndex, maxTryCount, retryTimeoutInMilliseconds); From 6532589bb7d52381f0095240556366c491b1f349 Mon Sep 17 00:00:00 2001 From: SubPointSupport Date: Tue, 11 Apr 2017 03:49:25 -0700 Subject: [PATCH 09/16] + SSOM 2013 full regression + Broken field links operation in content types #1006 --- SPMeta2/Regression/_helpers.ps1 | 36 ++++++ .../Regression/_ut_grid_baseline_config.ps1 | 104 ++++++++++++++++-- .../_ut_grid_dsc_spmeta2_webapp_unittests.ps1 | 89 ++++++++------- .../ModelHandlers/CSOMModelHandlerBase.cs | 6 + .../Definitions/ContentDatabaseDefinition.cs | 1 + 5 files changed, 182 insertions(+), 54 deletions(-) diff --git a/SPMeta2/Regression/_helpers.ps1 b/SPMeta2/Regression/_helpers.ps1 index 5cbcb1cc9..841319972 100644 --- a/SPMeta2/Regression/_helpers.ps1 +++ b/SPMeta2/Regression/_helpers.ps1 @@ -12,10 +12,46 @@ function Get-RegressionConfig() { return $config } +function Get-EnvironmentVariable($name) { + + $result = [System.Environment]::GetEnvironmentVariable($name) + if($result -ne $null) { return $result; } + + $result = [System.Environment]::GetEnvironmentVariable($name, "Machine") + if($result -ne $null) { return $result; } + + $result = [System.Environment]::GetEnvironmentVariable($name, "Process") + if($result -ne $null) { return $result; } + + $result = [System.Environment]::GetEnvironmentVariable($name, "User") + if($result -ne $null) { return $result; } + + return $null +} + if($dsc_configFilePath -eq $null) { + $dsc_configFilePath = "config.yaml" + + # environment specific? + $environmentSpecificConfigPath = Get-EnvironmentVariable "SPMeta2.Regression.Config.FilePath" + + if( [System.IO.File]::Exists($environmentSpecificConfigPath) -eq $true) { + $dsc_configFilePath = $environmentSpecificConfigPath + Write-Host "Using environment specific config file:[$dsc_configFilePath]" -ForegroundColor Green + } + else { + $dsc_configFilePath = "config.yaml" + Write-Host "Using default config file:[$dsc_configFilePath]" -ForegroundColor Green + + } } +if( [System.IO.File]::Exists($dsc_configFilePath) -eq $false) { + throw "Config file [$dsc_configFilePath] does not exist" +} + + $dsc_config = Get-RegressionConfig($dsc_configFilePath) $env_config = $dsc_config.Configuration.Environment $regression_config = $dsc_config.Configuration.RegressionTests diff --git a/SPMeta2/Regression/_ut_grid_baseline_config.ps1 b/SPMeta2/Regression/_ut_grid_baseline_config.ps1 index 1b489294a..3015fa376 100644 --- a/SPMeta2/Regression/_ut_grid_baseline_config.ps1 +++ b/SPMeta2/Regression/_ut_grid_baseline_config.ps1 @@ -3,18 +3,9 @@ $ScriptDirectory = Split-Path -Path $MyInvocation.MyCommand.Definition -Parent . "$ScriptDirectory/_helpers.ps1" -foreach($server in $dsc_nodeNames) { - - Write-Host "Configuring server [$server]" -fore Green - - $isOnline = Test-Connection -Computername $server -BufferSize 16 -Count 1 -Quiet - - if($isOnline -eq $true) - { - Write-Host "Server [$server] online. Processing..." -fore Green - - Invoke-Command -ScriptBlock { +$isParallerRun = $true +$configScript = { function Ensure-ISS-AppPools() { @@ -98,6 +89,45 @@ foreach($server in $dsc_nodeNames) { set-SPEnterpriseSearchService -PerformanceLevel Reduced } + + function Ensure-SecureStoreApplicationKey() + { + param ( + [Parameter(Mandatory=$true)] [ValidateNotNullorEmpty()] [string] $passPhrase, + [Parameter(Mandatory=$false)] [ValidateNotNullorEmpty()] [boolean] $force + ) + + Write-Host "Loading SharePoint API..." + Add-PSSnapin Microsoft.SharePoint.PowerShell + + $service = Get-SPserviceApplicationProxy | Where-Object { $_.TypeName -eq "Secure Store Service Application Proxy" } + + + if(($service.Properties["spmeta2.regression"] -eq $null) -or ($force -eq $true) ) + { + Write-Host "Creating new master key with password:[$passPhrase]" -fore Green + + Update-SPSecureStoreMasterKey -ServiceApplicationProxy $service -Passphrase $passPhrase > $null + Start-Sleep 5 + + Update-SPSecureStoreApplicationServerKey -ServiceApplicationProxy $service -Passphrase $passPhrase > $null + Start-Sleep 5 + + $service.Properties["spmeta2.regression"] = 1; + $service.Update() + + Write-Host "Master ket was created." -fore Green + } + else + { + Write-Host "Master key exists." -fore Green + } + } + + $computerName = [environment]::MachineName + + Write-Host "Runing on [$computerName]" + #return Ensure-AssociatedGroups @@ -106,15 +136,65 @@ foreach($server in $dsc_nodeNames) { Set-MSSQL-Ram (6 * 1024) + Ensure-SecureStoreApplicationKey "pass@word1" + Restart-SharePoint Ensure-ISS-AppPools Ensure-ISS-AppPools - } -computer $server +} + +$invokeParallelCmd = get-command -Name "Invoke-Parallel" -ErrorAction SilentlyContinue + +if($isParallerRun -eq $false) { + $invokeParallelCmd = $null +} + +if($invokeParallelCmd -eq $null) { + + Write-Host "Configuring servers [$dsc_nodeNames] sequentially" -fore Green + + foreach($server in $dsc_nodeNames) { + + Write-Host "Configuring server [$server]" -fore Green + + $isOnline = Test-Connection -Computername $server -BufferSize 16 -Count 1 -Quiet + + if($isOnline -eq $true) + { + Write-Host "Server [$server] online. Processing..." -fore Green + + Invoke-Command -ScriptBlock $configScript -computer $server } else { Write-Host "Server [$server] is OFFLINE. Skipping Processing..." -fore Yellow } +} + +} else { + + Write-Host "Configuring servers [$dsc_nodeNames] in parallel" -fore Green + + $dsc_nodeNames | Invoke-Parallel -ScriptBlock { + + $server = $_ + + Write-Host "Configuring server [$server]" -fore Green + + $isOnline = Test-Connection -Computername $server -BufferSize 16 -Count 1 -Quiet + + if($isOnline -eq $true) + { + Write-Host "Server [$server] online. Processing..." -fore Green + + Invoke-Command -ScriptBlock $configScript -computer $server + } + else + { + Write-Host "Server [$server] is OFFLINE. Skipping Processing..." -fore Yellow + } + + } } \ No newline at end of file diff --git a/SPMeta2/Regression/_ut_grid_dsc_spmeta2_webapp_unittests.ps1 b/SPMeta2/Regression/_ut_grid_dsc_spmeta2_webapp_unittests.ps1 index 5f3be1791..b788b0b45 100644 --- a/SPMeta2/Regression/_ut_grid_dsc_spmeta2_webapp_unittests.ps1 +++ b/SPMeta2/Regression/_ut_grid_dsc_spmeta2_webapp_unittests.ps1 @@ -6,11 +6,11 @@ $ScriptDirectory = Split-Path -Path $MyInvocation.MyCommand.Definition -Parent $o365RuntimePath = "$PSScriptRoot\..\SPMeta2.Dependencies\SharePoint\SP2013 - 15.0.4420.1017\CSOM" Write-Host "Loading SharePoint CSOM API" -fore Green - $files = [System.IO.Directory]::GetFiles($o365RuntimePath, "*.dll") - - foreach($filePath in $files) { - Write-Host "`tLoading assembly: [$filePath]" - $a = [System.Reflection.Assembly]::LoadFile($filePath) + $files = [System.IO.Directory]::GetFiles($o365RuntimePath, "*.dll") + + foreach($filePath in $files) { + Write-Host "`tLoading assembly: [$filePath]" + $a = [System.Reflection.Assembly]::LoadFile($filePath) } Configuration SPMeta2_UnitTestSettings_Clean @@ -126,23 +126,23 @@ Configuration SPMeta2_UnitTestSettings Write-Host "Fetching default taxoomy store for SharePoint:[$siteUrl]" -fore Green $o365_UserName = $config.OnlineUserName - $secO365_UserPassword = ConvertTo-SecureString $config.OnlineUserPassword -AsPlainText -Force - - $context = New-Object Microsoft.SharePoint.Client.ClientContext($siteUrl) - - $taxSession = [Microsoft.SharePoint.Client.Taxonomy.TaxonomySession]::GetTaxonomySession($context) - $store = $taxSession.GetDefaultSiteCollectionTermStore(); - - $context.Load($store) - $context.ExecuteQuery() - - Write-Host "Setting up taxonomy store vars" -fore Yellow - - $taxonomyStoreName = $store.Name - $taxonomyStoreId = $store.Id - - Write-Host "`tName:[$taxonomyStoreName]" -fore Gray - Write-Host "`tId:[$taxonomyStoreId]" -fore Gray + $secO365_UserPassword = ConvertTo-SecureString $config.OnlineUserPassword -AsPlainText -Force + + $context = New-Object Microsoft.SharePoint.Client.ClientContext($siteUrl) + + $taxSession = [Microsoft.SharePoint.Client.Taxonomy.TaxonomySession]::GetTaxonomySession($context) + $store = $taxSession.GetDefaultSiteCollectionTermStore(); + + $context.Load($store) + $context.ExecuteQuery() + + Write-Host "Setting up taxonomy store vars" -fore Yellow + + $taxonomyStoreName = $store.Name + $taxonomyStoreId = $store.Id + + Write-Host "`tName:[$taxonomyStoreName]" -fore Gray + Write-Host "`tId:[$taxonomyStoreId]" -fore Gray $env_vars += @{ Name = "SPMeta2_DefaultTaxonomyStoreId" @@ -162,26 +162,26 @@ Configuration SPMeta2_UnitTestSettings Write-Host "Fetching default taxoomy store for O365: [$siteUrl]" -fore Green $o365_UserName = $config.OnlineUserName - $secO365_UserPassword = ConvertTo-SecureString $config.OnlineUserPassword -AsPlainText -Force - - $context = New-Object Microsoft.SharePoint.Client.ClientContext($siteUrl) - $credentials = New-Object Microsoft.SharePoint.Client.SharePointOnlineCredentials($o365_UserName, $secO365_UserPassword) - - $context.Credentials = $credentials - - $taxSession = [Microsoft.SharePoint.Client.Taxonomy.TaxonomySession]::GetTaxonomySession($context) - $store = $taxSession.GetDefaultSiteCollectionTermStore(); - - $context.Load($store) - $context.ExecuteQuery() - - Write-Host "Setting up taxonomy store vars" -fore Yellow - - $taxonomyStoreName = $store.Name - $taxonomyStoreId = $store.Id - - Write-Host "`tName:[$taxonomyStoreName]" -fore Gray - Write-Host "`tId:[$taxonomyStoreId]" -fore Gray + $secO365_UserPassword = ConvertTo-SecureString $config.OnlineUserPassword -AsPlainText -Force + + $context = New-Object Microsoft.SharePoint.Client.ClientContext($siteUrl) + $credentials = New-Object Microsoft.SharePoint.Client.SharePointOnlineCredentials($o365_UserName, $secO365_UserPassword) + + $context.Credentials = $credentials + + $taxSession = [Microsoft.SharePoint.Client.Taxonomy.TaxonomySession]::GetTaxonomySession($context) + $store = $taxSession.GetDefaultSiteCollectionTermStore(); + + $context.Load($store) + $context.ExecuteQuery() + + Write-Host "Setting up taxonomy store vars" -fore Yellow + + $taxonomyStoreName = $store.Name + $taxonomyStoreId = $store.Id + + Write-Host "`tName:[$taxonomyStoreName]" -fore Gray + Write-Host "`tId:[$taxonomyStoreId]" -fore Gray $env_vars += @{ Name = "SPMeta2_DefaultTaxonomyStoreId" @@ -241,6 +241,11 @@ Configuration SPMeta2_UnitTestSettings Value = ($config.OnlineUserPassword) } + $env_vars += @{ + Name = "SPMeta2_DefaultSqlServerName" + Value = $NodeName + } + Node $NodeName { foreach($var in $env_vars) { diff --git a/SPMeta2/SPMeta2.CSOM/ModelHandlers/CSOMModelHandlerBase.cs b/SPMeta2/SPMeta2.CSOM/ModelHandlers/CSOMModelHandlerBase.cs index 1bde33022..7b4f0738f 100644 --- a/SPMeta2/SPMeta2.CSOM/ModelHandlers/CSOMModelHandlerBase.cs +++ b/SPMeta2/SPMeta2.CSOM/ModelHandlers/CSOMModelHandlerBase.cs @@ -54,7 +54,13 @@ protected virtual object GetPropertyValue(object obj, string propName) protected virtual bool IsSharePointOnlineContext(ClientContext context) { +#if NET35 + return false; +#endif + +#if !NET35 return context.Credentials is SharePointOnlineCredentials; +#endif } #endregion diff --git a/SPMeta2/SPMeta2/Definitions/ContentDatabaseDefinition.cs b/SPMeta2/SPMeta2/Definitions/ContentDatabaseDefinition.cs index fcf5779fd..eb4328f11 100644 --- a/SPMeta2/SPMeta2/Definitions/ContentDatabaseDefinition.cs +++ b/SPMeta2/SPMeta2/Definitions/ContentDatabaseDefinition.cs @@ -42,6 +42,7 @@ public ContentDatabaseDefinition() [ExpectValidation] [DataMember] [IdentityKey] + [ExpectRequired] public string ServerName { get; set; } [ExpectValidation] From b838e0b29fc9c0d749baea091354a83154fba1c3 Mon Sep 17 00:00:00 2001 From: SubPointSupport Date: Tue, 11 Apr 2017 19:33:09 -0700 Subject: [PATCH 10/16] + O365 full regression + CanDeploy_ListModel_WithFolders fix under CSOM API --- .../_ut_grid_dsc_spmeta2_webapp_unittests.ps1 | 108 +++++++++++------- .../O365ProvisionRunner.cs | 68 +++++++++-- .../O365v16ProvisionRunner.cs | 67 +++++++++++ ...ntSetContentsWebPartDefinitionGenerator.cs | Bin 1520 -> 2352 bytes .../ClientSecurityGroupDefinitionValidator.cs | 12 +- .../Scenarios/SecurityGroupScenariosTest.cs | 19 +-- .../DocumentSetContentsWebPartDefinition.cs | Bin 2870 -> 2872 bytes 7 files changed, 213 insertions(+), 61 deletions(-) diff --git a/SPMeta2/Regression/_ut_grid_dsc_spmeta2_webapp_unittests.ps1 b/SPMeta2/Regression/_ut_grid_dsc_spmeta2_webapp_unittests.ps1 index b788b0b45..22d0001ee 100644 --- a/SPMeta2/Regression/_ut_grid_dsc_spmeta2_webapp_unittests.ps1 +++ b/SPMeta2/Regression/_ut_grid_dsc_spmeta2_webapp_unittests.ps1 @@ -6,11 +6,11 @@ $ScriptDirectory = Split-Path -Path $MyInvocation.MyCommand.Definition -Parent $o365RuntimePath = "$PSScriptRoot\..\SPMeta2.Dependencies\SharePoint\SP2013 - 15.0.4420.1017\CSOM" Write-Host "Loading SharePoint CSOM API" -fore Green - $files = [System.IO.Directory]::GetFiles($o365RuntimePath, "*.dll") - - foreach($filePath in $files) { - Write-Host "`tLoading assembly: [$filePath]" - $a = [System.Reflection.Assembly]::LoadFile($filePath) + $files = [System.IO.Directory]::GetFiles($o365RuntimePath, "*.dll") + + foreach($filePath in $files) { + Write-Host "`tLoading assembly: [$filePath]" + $a = [System.Reflection.Assembly]::LoadFile($filePath) } Configuration SPMeta2_UnitTestSettings_Clean @@ -126,23 +126,23 @@ Configuration SPMeta2_UnitTestSettings Write-Host "Fetching default taxoomy store for SharePoint:[$siteUrl]" -fore Green $o365_UserName = $config.OnlineUserName - $secO365_UserPassword = ConvertTo-SecureString $config.OnlineUserPassword -AsPlainText -Force - - $context = New-Object Microsoft.SharePoint.Client.ClientContext($siteUrl) - - $taxSession = [Microsoft.SharePoint.Client.Taxonomy.TaxonomySession]::GetTaxonomySession($context) - $store = $taxSession.GetDefaultSiteCollectionTermStore(); - - $context.Load($store) - $context.ExecuteQuery() - - Write-Host "Setting up taxonomy store vars" -fore Yellow - - $taxonomyStoreName = $store.Name - $taxonomyStoreId = $store.Id - - Write-Host "`tName:[$taxonomyStoreName]" -fore Gray - Write-Host "`tId:[$taxonomyStoreId]" -fore Gray + $secO365_UserPassword = ConvertTo-SecureString $config.OnlineUserPassword -AsPlainText -Force + + $context = New-Object Microsoft.SharePoint.Client.ClientContext($siteUrl) + + $taxSession = [Microsoft.SharePoint.Client.Taxonomy.TaxonomySession]::GetTaxonomySession($context) + $store = $taxSession.GetDefaultSiteCollectionTermStore(); + + $context.Load($store) + $context.ExecuteQuery() + + Write-Host "Setting up taxonomy store vars" -fore Yellow + + $taxonomyStoreName = $store.Name + $taxonomyStoreId = $store.Id + + Write-Host "`tName:[$taxonomyStoreName]" -fore Gray + Write-Host "`tId:[$taxonomyStoreId]" -fore Gray $env_vars += @{ Name = "SPMeta2_DefaultTaxonomyStoreId" @@ -162,26 +162,26 @@ Configuration SPMeta2_UnitTestSettings Write-Host "Fetching default taxoomy store for O365: [$siteUrl]" -fore Green $o365_UserName = $config.OnlineUserName - $secO365_UserPassword = ConvertTo-SecureString $config.OnlineUserPassword -AsPlainText -Force - - $context = New-Object Microsoft.SharePoint.Client.ClientContext($siteUrl) - $credentials = New-Object Microsoft.SharePoint.Client.SharePointOnlineCredentials($o365_UserName, $secO365_UserPassword) - - $context.Credentials = $credentials - - $taxSession = [Microsoft.SharePoint.Client.Taxonomy.TaxonomySession]::GetTaxonomySession($context) - $store = $taxSession.GetDefaultSiteCollectionTermStore(); - - $context.Load($store) - $context.ExecuteQuery() - - Write-Host "Setting up taxonomy store vars" -fore Yellow - - $taxonomyStoreName = $store.Name - $taxonomyStoreId = $store.Id - - Write-Host "`tName:[$taxonomyStoreName]" -fore Gray - Write-Host "`tId:[$taxonomyStoreId]" -fore Gray + $secO365_UserPassword = ConvertTo-SecureString $config.OnlineUserPassword -AsPlainText -Force + + $context = New-Object Microsoft.SharePoint.Client.ClientContext($siteUrl) + $credentials = New-Object Microsoft.SharePoint.Client.SharePointOnlineCredentials($o365_UserName, $secO365_UserPassword) + + $context.Credentials = $credentials + + $taxSession = [Microsoft.SharePoint.Client.Taxonomy.TaxonomySession]::GetTaxonomySession($context) + $store = $taxSession.GetDefaultSiteCollectionTermStore(); + + $context.Load($store) + $context.ExecuteQuery() + + Write-Host "Setting up taxonomy store vars" -fore Yellow + + $taxonomyStoreName = $store.Name + $taxonomyStoreId = $store.Id + + Write-Host "`tName:[$taxonomyStoreName]" -fore Gray + Write-Host "`tId:[$taxonomyStoreId]" -fore Gray $env_vars += @{ Name = "SPMeta2_DefaultTaxonomyStoreId" @@ -246,6 +246,26 @@ Configuration SPMeta2_UnitTestSettings Value = $NodeName } + $env_vars += @{ + Name = "SPMeta2_O365_DefaultTestUserLogins" + Value = [string]::Join(",", ($config.TestUserLogins | Foreach { [string]$_ } ) ) + } + + $env_vars += @{ + Name = "SPMeta2_DefaultTestUserLogins" + Value = [string]::Join(",", ($config.TestUserLogins | Foreach { [string]$_ } ) ) + } + + $env_vars += @{ + Name = "SPMeta2_DefaultTestDomainUserEmails" + Value = [string]::Join(",", ($config.TestDomainUserEmails | Foreach { [string]$_ } ) ) + } + + $env_vars += @{ + Name = "SPMeta2_DefaultTestADGroups" + Value = [string]::Join(",", ($config.TestActiveDirectoryGroups | Foreach { [string]$_ } ) ) + } + Node $NodeName { foreach($var in $env_vars) { @@ -266,6 +286,10 @@ $config = @{ @{ ObjectModels = $regression_config.ObjectModels + TestUserLogins = $regression_config.TestData.UserLogins + TestActiveDirectoryGroups = $regression_config.TestData.ActiveDirectoryGroups + TestDomainUserEmails = $regression_config.TestData.DomainUserEmails + WebAppPort = $env_config.SharePoint.WebApp.Port SiteCollectionUrls = $env_config.SharePoint.SiteCollection.Urls diff --git a/SPMeta2/SPMeta2.Containers.O365/O365ProvisionRunner.cs b/SPMeta2/SPMeta2.Containers.O365/O365ProvisionRunner.cs index 2f2e6a5d2..11c227277 100644 --- a/SPMeta2/SPMeta2.Containers.O365/O365ProvisionRunner.cs +++ b/SPMeta2/SPMeta2.Containers.O365/O365ProvisionRunner.cs @@ -21,6 +21,9 @@ using SPMeta2.Utils; using SPMeta2.CSOM.Standard.Services; using SPMeta2.Services; +using SPMeta2.CSOM.Extensions; +using SPMeta2.Exceptions; +using SPMeta2.ModelHosts; namespace SPMeta2.Containers.O365 { @@ -221,20 +224,67 @@ private void SiteOnUrl(ModelNode model, string siteUrl) public override void DeployListModel(ModelNode model) { - - if (RandomBalancedUrls.Count > 0) + foreach (var webUrl in WebUrls) { - var url = RandomBalancedUrls[rnd.Next(0, RandomBalancedUrls.Count)]; - WebOnUrl(model, url); + ListOnUrl(model, webUrl); } - else - { + } - foreach (var webUrl in WebUrls) + private void ListOnUrl(ModelNode model, string webUrl) + { + ContainerTraceUtils.WriteLine(string.Format("[INF] Running on web: [{0}]", webUrl)); + + WithO365Context(webUrl, context => + { + for (var provisionGeneration = 0; + provisionGeneration < ProvisionGenerationCount; + provisionGeneration++) { - WebOnUrl(model, webUrl); + if (EnableDefinitionProvision) + { + if (OnBeforeDeployModel != null) + OnBeforeDeployModel(_provisionService, model); + + var web = context.Web; + var list = web.QueryAndGetListByTitle("Site Pages"); + + if (list == null) + list = web.QueryAndGetListByTitle("Pages"); + + if (list == null) + throw new SPMeta2Exception("Cannot find host list"); + + var listHost = ModelHostBase.Inherit(WebModelHost.FromClientContext(context), h => + { + h.HostList = list; + }); + + _provisionService.DeployModel(listHost, model); + + if (OnAfterDeployModel != null) + OnAfterDeployModel(_provisionService, model); + } + + if (EnableDefinitionValidation) + { + var web = context.Web; + var list = web.QueryAndGetListByTitle("Site Pages"); + + if (list == null) + list = web.QueryAndGetListByTitle("Pages"); + + if (list == null) + throw new SPMeta2Exception("Cannot find host list"); + + var listHost = ModelHostBase.Inherit(WebModelHost.FromClientContext(context), h => + { + h.HostList = list; + }); + + _validationService.DeployModel(listHost, model); + } } - } + }); } private void WebOnUrl(ModelNode model, string webUrl) diff --git a/SPMeta2/SPMeta2.Containers.O365v16/O365v16ProvisionRunner.cs b/SPMeta2/SPMeta2.Containers.O365v16/O365v16ProvisionRunner.cs index c0383a96e..6fbc43d90 100644 --- a/SPMeta2/SPMeta2.Containers.O365v16/O365v16ProvisionRunner.cs +++ b/SPMeta2/SPMeta2.Containers.O365v16/O365v16ProvisionRunner.cs @@ -21,6 +21,8 @@ using SPMeta2.Services; using SPMeta2.Utils; using SPMeta2.Exceptions; +using SPMeta2.ModelHosts; +using SPMeta2.CSOM.Extensions; namespace SPMeta2.Containers.O365v16 { @@ -218,6 +220,71 @@ public override void DeployWebModel(ModelNode model) } } + public override void DeployListModel(ModelNode model) + { + foreach (var webUrl in WebUrls) + { + ListOnUrl(model, webUrl); + } + } + + private void ListOnUrl(ModelNode model, string webUrl) + { + ContainerTraceUtils.WriteLine(string.Format("[INF] Running on web: [{0}]", webUrl)); + + WithO365Context(webUrl, context => + { + for (var provisionGeneration = 0; + provisionGeneration < ProvisionGenerationCount; + provisionGeneration++) + { + if (EnableDefinitionProvision) + { + if (OnBeforeDeployModel != null) + OnBeforeDeployModel(_provisionService, model); + + var web = context.Web; + var list = web.QueryAndGetListByTitle("Site Pages"); + + if (list == null) + list = web.QueryAndGetListByTitle("Pages"); + + if (list == null) + throw new SPMeta2Exception("Cannot find host list"); + + var listHost = ModelHostBase.Inherit(WebModelHost.FromClientContext(context), h => + { + h.HostList = list; + }); + + _provisionService.DeployModel(listHost, model); + + if (OnAfterDeployModel != null) + OnAfterDeployModel(_provisionService, model); + } + + if (EnableDefinitionValidation) + { + var web = context.Web; + var list = web.QueryAndGetListByTitle("Site Pages"); + + if (list == null) + list = web.QueryAndGetListByTitle("Pages"); + + if (list == null) + throw new SPMeta2Exception("Cannot find host list"); + + var listHost = ModelHostBase.Inherit(WebModelHost.FromClientContext(context), h => + { + h.HostList = list; + }); + + _validationService.DeployModel(listHost, model); + } + } + }); + } + #endregion #region utils diff --git a/SPMeta2/SPMeta2.Containers.Standard/DefinitionGenerators/Webparts/DocumentSetContentsWebPartDefinitionGenerator.cs b/SPMeta2/SPMeta2.Containers.Standard/DefinitionGenerators/Webparts/DocumentSetContentsWebPartDefinitionGenerator.cs index fb7dc80b2ec2b1b6892cda4616d9aa3244c20808..96ab3ada573f6740fd6263da5935d73ff864389b 100644 GIT binary patch delta 477 zcma)&%}T>i5QUHV5mD?y6c@H8;HGW@rAxI?txDHfii?=07_<@6L@h;p1>;@$3NEDX zTnN5`FW@7HzJZ>(7C}Lf%O!Va&Ybxs?=z#h(d0yNTb|uUf*d_WND&k_PHlibGKM{P z*un{pc_M_&#f%bGJ?t`*=$05^akR4JW57g)0Ou^XSnBefvo*W_c(K&AIj^1#cd?Bh z^KhWe*VUU*sW;$i;|xu7c;fGo0aZ=%34-_vOdnOOs={1QSLX8NDYGg2J46h}`v{Lu z64CDP8}OA=6;ZdryU8dPLbS>5>v_>Hr7YX}!_(7!hxAKJy17a?v2GBnB3R0`rkpM< wWa(hM?AP#&AURvtwD!@SRu5KL-I*m@{_B}~HJth$_USj|{qI^A>dCHs0$$Q* { var srcProp = s.GetExpressionValue(def => def.Owner); - var dstProp = d.GetExpressionValue(ct => ct.GetOwnerLogin()); + var dstProp = d.GetExpressionValue(ct => ct.GetOwnerLogin()); + + var srcOwner = dstProp.Value.ToString().ToUpper().Replace("\\", "/"); + var dstOwner = dstProp.Value.ToString().ToUpper().Replace("\\", "/"); var isValid = dstProp.Value.ToString().ToUpper().Replace("\\", "/").EndsWith( - srcProp.Value.ToString().ToUpper().Replace("\\", "/")); + srcProp.Value.ToString().ToUpper().Replace("\\", "/")); + + if (!isValid) + { + isValid = dstOwner.Contains(srcOwner); + } return new PropertyValidationResult { diff --git a/SPMeta2/SPMeta2.Regression.Tests/Impl/Scenarios/SecurityGroupScenariosTest.cs b/SPMeta2/SPMeta2.Regression.Tests/Impl/Scenarios/SecurityGroupScenariosTest.cs index 0a26be533..21cdb3957 100644 --- a/SPMeta2/SPMeta2.Regression.Tests/Impl/Scenarios/SecurityGroupScenariosTest.cs +++ b/SPMeta2/SPMeta2.Regression.Tests/Impl/Scenarios/SecurityGroupScenariosTest.cs @@ -45,6 +45,10 @@ public static void Cleanup() [TestCategory("Regression.Scenarios.SecurityGroup")] public void CanDeploy_SecurityGroup_Under_SecurityGroup() { + // TODO, handle O365 failure + // this ine would fail in O365, that's fine + // must only work onprem with 'AD' groups + var activeDirectoryOrGlobalO365Groups = RunnerEnvironmentUtils.GetEnvironmentVariables(EnvironmentConsts.DefaultTestADGroups); if (activeDirectoryOrGlobalO365Groups.Count() == 0) @@ -58,14 +62,13 @@ public void CanDeploy_SecurityGroup_Under_SecurityGroup() def.Name = randomNestedGroup; }); - var siteModel = SPMeta2Model - .NewSiteModel(site => - { - site.AddSecurityGroup(spGroup, group => - { - group.AddSecurityGroup(domainGroup); - }); - }); + var siteModel = SPMeta2Model.NewSiteModel(site => + { + site.AddSecurityGroup(spGroup, group => + { + group.AddSecurityGroup(domainGroup); + }); + }); TestModels(new ModelNode[] { siteModel }); } diff --git a/SPMeta2/SPMeta2.Standard/Definitions/Webparts/DocumentSetContentsWebPartDefinition.cs b/SPMeta2/SPMeta2.Standard/Definitions/Webparts/DocumentSetContentsWebPartDefinition.cs index 72ebc7824269230cd5d9973859521d2326fd708e..56f86f2e58a42f1d22b6d4194be8b0115e5f195b 100644 GIT binary patch delta 20 bcmdlcwnJ>g7Z&zlhD?SMhSbeJS!~$=P96r* delta 18 ZcmdlXwoPoq7Z%oVhE#^6&A(Y}*#JUb23r6C From d9e8ef2df9fe6aea62340cd8fb6c9f4966972f7e Mon Sep 17 00:00:00 2001 From: SubPointSupport Date: Tue, 11 Apr 2017 19:49:36 -0700 Subject: [PATCH 11/16] + O365 full regression + TokenReplacementServiceTests fixes --- .../Impl/Services/TokenReplacementServiceTests.cs | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/SPMeta2/SPMeta2.Regression.Tests/Impl/Services/TokenReplacementServiceTests.cs b/SPMeta2/SPMeta2.Regression.Tests/Impl/Services/TokenReplacementServiceTests.cs index 7bbfee9b6..1ad53d901 100644 --- a/SPMeta2/SPMeta2.Regression.Tests/Impl/Services/TokenReplacementServiceTests.cs +++ b/SPMeta2/SPMeta2.Regression.Tests/Impl/Services/TokenReplacementServiceTests.cs @@ -197,10 +197,14 @@ protected void TestModelAndUrl(ModelNode model, string expectedEndWithUrl) { hasHit = true; - if (e.Result.Value == expectedEndWithUrl) + if (e.Result.Value.EndsWith(expectedEndWithUrl)) { hasCorrectUrl = true; } + else + { + hasCorrectUrl = false; + } }; TestModel(model); From b212f95b7749d78fc2415f15f6fa6d9db159492f Mon Sep 17 00:00:00 2001 From: SubPointSupport Date: Tue, 11 Apr 2017 20:00:57 -0700 Subject: [PATCH 12/16] + O365 full regression + MasterPageSettingsDefinitionScenariosTest fix --- .../Validation/ClientMasterPageSettingsDefinitionValidator.cs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/SPMeta2/SPMeta2.Regression.CSOM/Validation/ClientMasterPageSettingsDefinitionValidator.cs b/SPMeta2/SPMeta2.Regression.CSOM/Validation/ClientMasterPageSettingsDefinitionValidator.cs index e48412b76..4243772b5 100644 --- a/SPMeta2/SPMeta2.Regression.CSOM/Validation/ClientMasterPageSettingsDefinitionValidator.cs +++ b/SPMeta2/SPMeta2.Regression.CSOM/Validation/ClientMasterPageSettingsDefinitionValidator.cs @@ -42,7 +42,7 @@ public override void DeployModel(object modelHost, DefinitionBase model) var srcProp = s.GetExpressionValue(def => def.SiteMasterPageUrl); var dstProp = d.GetExpressionValue(def => def.CustomMasterUrl); - var isValid = url == (string)dstProp.Value; + var isValid = ((string)dstProp.Value).EndsWith((string)url); return new PropertyValidationResult { @@ -75,7 +75,7 @@ public override void DeployModel(object modelHost, DefinitionBase model) var srcProp = s.GetExpressionValue(def => def.SystemMasterPageUrl); var dstProp = d.GetExpressionValue(def => def.MasterUrl); - var isValid = (string)url == (string)dstProp.Value; + var isValid = ((string)dstProp.Value).EndsWith((string)url); return new PropertyValidationResult { From 756a032dfff17dabfd76db99f0dfcd6bbaa5cc01 Mon Sep 17 00:00:00 2001 From: SubPointSupport Date: Wed, 12 Apr 2017 19:55:44 -0700 Subject: [PATCH 13/16] + O365 regression + CanDeploy_DocumentLibrary_With_Custom_DocumentTemplateUrl fix --- .../Impl/Scenarios/ListScenariosTest.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/SPMeta2/SPMeta2.Regression.Tests/Impl/Scenarios/ListScenariosTest.cs b/SPMeta2/SPMeta2.Regression.Tests/Impl/Scenarios/ListScenariosTest.cs index 2c2996739..5937f3582 100644 --- a/SPMeta2/SPMeta2.Regression.Tests/Impl/Scenarios/ListScenariosTest.cs +++ b/SPMeta2/SPMeta2.Regression.Tests/Impl/Scenarios/ListScenariosTest.cs @@ -669,7 +669,7 @@ public void CanDeploy_DocumentLibrary_With_Custom_DocumentTemplateUrl() // add a clone second time with the template var listWithDocumentTemplate = randomList.Inherit(); #pragma warning disable 618 - listWithDocumentTemplate.DocumentTemplateUrl = string.Format("/" + randomList.GetListUrl() + "/Forms/" + templateFileName); + listWithDocumentTemplate.DocumentTemplateUrl = string.Format("~sitecollection/" + randomList.GetListUrl() + "/Forms/" + templateFileName); #pragma warning restore 618 web.AddList(listWithDocumentTemplate); From c92c5044c9819c0eb751edd29e4b7ec8811d976e Mon Sep 17 00:00:00 2001 From: SubPointSupport Date: Thu, 13 Apr 2017 18:50:08 -0700 Subject: [PATCH 14/16] + Add TryRetryService to implement try-retry logic #1010 + Added Regression.Services.DefaultTryRetryService tests + Green O365 regression testing for taxonomy related operations --- .../Services/DefaultTryRetryServiceTests.cs | 185 ++++++++++++++++++ .../Impl/Services/ServiceContainerTests.cs | 4 +- .../SPMeta2.Regression.Tests.csproj | 1 + .../Services/Impl/DefaultTryRetryService.cs | 41 +++- .../SPMeta2/Services/TryRetryServiceBase.cs | 1 + 5 files changed, 227 insertions(+), 5 deletions(-) create mode 100644 SPMeta2/SPMeta2.Regression.Tests/Impl/Services/DefaultTryRetryServiceTests.cs diff --git a/SPMeta2/SPMeta2.Regression.Tests/Impl/Services/DefaultTryRetryServiceTests.cs b/SPMeta2/SPMeta2.Regression.Tests/Impl/Services/DefaultTryRetryServiceTests.cs new file mode 100644 index 000000000..ed5438414 --- /dev/null +++ b/SPMeta2/SPMeta2.Regression.Tests/Impl/Services/DefaultTryRetryServiceTests.cs @@ -0,0 +1,185 @@ +using Microsoft.VisualStudio.TestTools.UnitTesting; +using SPMeta2.Containers.Services; +using SPMeta2.Containers.Services.Rnd; +using SPMeta2.Definitions; +using SPMeta2.Exceptions; +using SPMeta2.Services.Impl; +using System; + +namespace SPMeta2.Regression.Tests.Impl.Services +{ + [TestClass] + public class DefaultTryRetryServiceTests + { + #region constructors + + public DefaultTryRetryServiceTests() + { + Rnd = new DefaultRandomService(); + } + + #endregion + + #region properties + + public RandomService Rnd { get; set; } + + #endregion + + #region tests + + [TestMethod] + [TestCategory("Regression.Services.DefaultTryRetryService")] + [TestCategory("CI.Core")] + public void CanCreate_DefaultTryRetryService() + { + var service = new DefaultTryRetryService(); + + Assert.IsNotNull(service); + } + + [TestMethod] + [TestCategory("Regression.Services.DefaultTryRetryService")] + [TestCategory("CI.Core")] + public void ShouldFail_OnMoreAttempts() + { + var service = new DefaultTryRetryService(); + var currentTryCount = 0; + + ExpectException(() => + { + service.TryWithRetry(() => + { + currentTryCount++; + return false; + }); + }); + + Assert.AreEqual(service.MaxRetryCount, currentTryCount); + } + + [TestMethod] + [TestCategory("Regression.Services.DefaultTryRetryService")] + [TestCategory("CI.Core")] + public void ShouldWork_On_FirstAttempt() + { + var service = new DefaultTryRetryService(); + + var currentTryCount = 0; + var maxTryCount = Rnd.Int(5) + 1; + + service.TryWithRetry(() => + { + currentTryCount++; + return true; + }, maxTryCount, 50); + + Assert.AreEqual(1, currentTryCount); + } + + [TestMethod] + [TestCategory("Regression.Services.DefaultTryRetryService")] + [TestCategory("CI.Core")] + public void ShouldWork_On_RandomAttempt() + { + var service = new DefaultTryRetryService(); + + var currentTryCount = 0; + + var maxTryCount = Rnd.Int(5) + 2; + var positiveTryCount = maxTryCount / 2 + 1; + + service.TryWithRetry(() => + { + currentTryCount++; + + if (positiveTryCount == currentTryCount) + return true; + + return false; + + }, maxTryCount, 50); + + Assert.AreEqual(positiveTryCount, currentTryCount); + } + + [TestMethod] + [TestCategory("Regression.Services.DefaultTryRetryService")] + [TestCategory("CI.Core")] + public void CanOverride_MaxTryAttempts() + { + var service = new DefaultTryRetryService(); + + var currentTryCount = 0; + var maxTryCount = Rnd.Int(5) + 1; + + ExpectException(() => + { + service.TryWithRetry(() => + { + currentTryCount++; + return false; + }, maxTryCount, 50); + }); + + Assert.AreEqual(maxTryCount, currentTryCount); + } + + [TestMethod] + [TestCategory("Regression.Services.DefaultTryRetryService")] + [TestCategory("CI.Core")] + public void ShouldFail_OnWrongParameters() + { + var service = new DefaultTryRetryService(); + + ExpectException(() => + { + service.TryWithRetry(null, 1, 50); + }); + + ExpectException(() => + { + service.TryWithRetry(() => + { + return true; + }, 1, 50, null); + }); + + ExpectException(() => + { + service.TryWithRetry(() => + { + return false; + }, -1, 50); + }); + + ExpectException(() => + { + service.TryWithRetry(() => + { + return false; + }, 1, -50); + }); + } + + protected void ExpectException(Action action) + where TException : Exception + { + var hasValidException = false; + var expectedExceptionType = typeof(TException); + + try + { + action(); + } + catch (Exception e) + { + hasValidException = e.GetType() == expectedExceptionType; + } + + Assert.IsTrue(hasValidException); + } + + #endregion + } +} diff --git a/SPMeta2/SPMeta2.Regression.Tests/Impl/Services/ServiceContainerTests.cs b/SPMeta2/SPMeta2.Regression.Tests/Impl/Services/ServiceContainerTests.cs index ed28551c9..3b234b6e7 100644 --- a/SPMeta2/SPMeta2.Regression.Tests/Impl/Services/ServiceContainerTests.cs +++ b/SPMeta2/SPMeta2.Regression.Tests/Impl/Services/ServiceContainerTests.cs @@ -38,7 +38,9 @@ public void ServiceContainer_Should_Have_DefaultServices() typeof(DefaultDiagnosticInfoService), typeof(ModelPrettyPrintServiceBase), - typeof(ModelDotGraphPrintServiceBase) + typeof(ModelDotGraphPrintServiceBase), + + typeof(TryRetryServiceBase) }; foreach (var serviceType in serviceTypes) diff --git a/SPMeta2/SPMeta2.Regression.Tests/SPMeta2.Regression.Tests.csproj b/SPMeta2/SPMeta2.Regression.Tests/SPMeta2.Regression.Tests.csproj index f0d27d060..f2fd22710 100644 --- a/SPMeta2/SPMeta2.Regression.Tests/SPMeta2.Regression.Tests.csproj +++ b/SPMeta2/SPMeta2.Regression.Tests/SPMeta2.Regression.Tests.csproj @@ -258,6 +258,7 @@ + diff --git a/SPMeta2/SPMeta2/Services/Impl/DefaultTryRetryService.cs b/SPMeta2/SPMeta2/Services/Impl/DefaultTryRetryService.cs index ab2ec83a0..7b5107214 100644 --- a/SPMeta2/SPMeta2/Services/Impl/DefaultTryRetryService.cs +++ b/SPMeta2/SPMeta2/Services/Impl/DefaultTryRetryService.cs @@ -1,4 +1,5 @@ -using System; +using SPMeta2.Exceptions; +using System; using System.Collections.Generic; using System.Linq; using System.Text; @@ -41,6 +42,11 @@ protected TraceServiceBase TraceService #endregion public override void TryWithRetry(Func action) + { + TryWithRetry(action, MaxRetryCount); + } + + public override void TryWithRetry(Func action, int maxTryCount) { TryWithRetry(action, MaxRetryCount, RetryTimeoutInMilliseconds); } @@ -54,9 +60,12 @@ public override void TryWithRetry(Func action, int maxTryCount, int retryTimeoutInMilliseconds, Action waiter) { - var currentTryIndex = 0; + ValidateParameters(action, maxTryCount, retryTimeoutInMilliseconds, waiter); + + var currentTryIndex = 1; + var actionResult = action(); - while (action() != true) + while (actionResult != true) { TraceService.Warning((int)LogEventId.ModelProvision, string.Format("Coudn't perform action. Waiting and retrying [{1}/{2}]", @@ -64,12 +73,36 @@ public override void TryWithRetry(Func action, currentTryIndex, MaxRetryCount)); - if (currentTryIndex > maxTryCount) + if (currentTryIndex >= maxTryCount) break; waiter(currentTryIndex, maxTryCount, retryTimeoutInMilliseconds); currentTryIndex++; + + actionResult = action(); + } + + if (actionResult != true) + { + throw new SPMeta2Exception(string.Format( + "Error while performing requested action. Tried [{0}] out of [{1}], raising exception", + currentTryIndex, maxTryCount)); } } + + private static void ValidateParameters(Func action, int maxTryCount, int retryTimeoutInMilliseconds, Action waiter) + { + if (action == null) + throw new ArgumentNullException("action"); + + if (waiter == null) + throw new ArgumentNullException("waiter"); + + if (maxTryCount <= 0) + throw new ArgumentOutOfRangeException("maxTryCount must be greater than 0"); + + if (retryTimeoutInMilliseconds <= 0) + throw new ArgumentOutOfRangeException("retryTimeoutInMilliseconds must be greater than 0"); + } } } diff --git a/SPMeta2/SPMeta2/Services/TryRetryServiceBase.cs b/SPMeta2/SPMeta2/Services/TryRetryServiceBase.cs index 01119f91b..bb92fa9b4 100644 --- a/SPMeta2/SPMeta2/Services/TryRetryServiceBase.cs +++ b/SPMeta2/SPMeta2/Services/TryRetryServiceBase.cs @@ -16,6 +16,7 @@ public abstract class TryRetryServiceBase #region methods public abstract void TryWithRetry(Func action); + public abstract void TryWithRetry(Func action, int maxTryCount); public abstract void TryWithRetry(Func action, int maxTryCount, int retryTimeoutInMilliseconds); public abstract void TryWithRetry(Func action, int maxTryCount, int retryTimeoutInMilliseconds, Action waiter); From 4180f8008470e0811a6400ca9cad9ab2fae2ef34 Mon Sep 17 00:00:00 2001 From: SubPointSupport Date: Thu, 13 Apr 2017 21:17:25 -0700 Subject: [PATCH 15/16] SPMeta2 1.2.120, April 2017 --- SPMeta2/Build/build.json | 56 ++++++++++++++++++++-------------------- 1 file changed, 28 insertions(+), 28 deletions(-) diff --git a/SPMeta2/Build/build.json b/SPMeta2/Build/build.json index e51b4a1ca..5cf940e86 100644 --- a/SPMeta2/Build/build.json +++ b/SPMeta2/Build/build.json @@ -284,7 +284,7 @@ { "CustomProjectFolder" : "SPMeta2/SPMeta2", "Id": "SPMeta2.Core", - "Version": "1.2.120-beta5", + "Version": "1.2.120", "Dependencies": [ ], "LicenseUrl": "http://docs.subpointsolutions.com/spmeta2/license", "ProjectUrl": "https://github.com/SubPointSolutions/spmeta2", @@ -323,11 +323,11 @@ { "CustomProjectFolder" : "SPMeta2/SPMeta2.Standard", "Id": "SPMeta2.Core.Standard", - "Version": "1.2.120-beta5", + "Version": "1.2.120", "Dependencies": [ { "Id": "SPMeta2.Core", - "Version": "1.2.120-beta5" + "Version": "1.2.120" } ], "LicenseUrl": "http://docs.subpointsolutions.com/spmeta2/license", @@ -368,11 +368,11 @@ { "CustomProjectFolder" : "SPMeta2/SPMeta2.CSOM", "Id": "SPMeta2.CSOM.Foundation", - "Version": "1.2.120-beta5", + "Version": "1.2.120", "Dependencies": [ { "Id": "SPMeta2.Core", - "Version": "1.2.120-beta5" + "Version": "1.2.120" } ], "LicenseUrl": "http://docs.subpointsolutions.com/spmeta2/license", @@ -405,15 +405,15 @@ { "CustomProjectFolder" : "SPMeta2/SPMeta2.CSOM.Standard", "Id": "SPMeta2.CSOM.Standard", - "Version": "1.2.120-beta5", + "Version": "1.2.120", "Dependencies": [ { "Id": "SPMeta2.CSOM.Foundation", - "Version": "1.2.120-beta5" + "Version": "1.2.120" }, { "Id": "SPMeta2.Core.Standard", - "Version": "1.2.120-beta5" + "Version": "1.2.120" } ], "LicenseUrl": "http://docs.subpointsolutions.com/spmeta2/license", @@ -446,11 +446,11 @@ { "CustomProjectFolder" : "SPMeta2/SPMeta2.SSOM", "Id": "SPMeta2.SSOM.Foundation", - "Version": "1.2.120-beta5", + "Version": "1.2.120", "Dependencies": [ { "Id": "SPMeta2.Core", - "Version": "1.2.120-beta5" + "Version": "1.2.120" } ], "LicenseUrl": "http://docs.subpointsolutions.com/spmeta2/license", @@ -483,15 +483,15 @@ { "CustomProjectFolder" : "SPMeta2/SPMeta2.SSOM.Standard", "Id": "SPMeta2.SSOM.Standard", - "Version": "1.2.120-beta5", + "Version": "1.2.120", "Dependencies": [ { "Id": "SPMeta2.SSOM.Foundation", - "Version": "1.2.120-beta5" + "Version": "1.2.120" }, { "Id": "SPMeta2.Core.Standard", - "Version": "1.2.120-beta5" + "Version": "1.2.120" } ], "LicenseUrl": "http://docs.subpointsolutions.com/spmeta2/license", @@ -525,11 +525,11 @@ { "CustomProjectFolder" : "SPMeta2/SPMeta2.CSOM", "Id": "SPMeta2.CSOM.Foundation-v14", - "Version": "1.2.120-beta5", + "Version": "1.2.120", "Dependencies": [ { "Id": "SPMeta2.Core", - "Version": "1.2.120-beta5" + "Version": "1.2.120" } ], "LicenseUrl": "http://docs.subpointsolutions.com/spmeta2/license", @@ -555,15 +555,15 @@ { "CustomProjectFolder" : "SPMeta2/SPMeta2.CSOM.Standard", "Id": "SPMeta2.CSOM.Standard-v14", - "Version": "1.2.120-beta5", + "Version": "1.2.120", "Dependencies": [ { "Id": "SPMeta2.CSOM.Foundation-v14", - "Version": "1.2.120-beta5" + "Version": "1.2.120" }, { "Id": "SPMeta2.Core.Standard", - "Version": "1.2.120-beta5" + "Version": "1.2.120" } ], "LicenseUrl": "http://docs.subpointsolutions.com/spmeta2/license", @@ -589,11 +589,11 @@ { "CustomProjectFolder" : "SPMeta2/SPMeta2.SSOM", "Id": "SPMeta2.SSOM.Foundation-v14", - "Version": "1.2.120-beta5", + "Version": "1.2.120", "Dependencies": [ { "Id": "SPMeta2.Core", - "Version": "1.2.120-beta5" + "Version": "1.2.120" } ], "LicenseUrl": "http://docs.subpointsolutions.com/spmeta2/license", @@ -619,15 +619,15 @@ { "CustomProjectFolder" : "SPMeta2/SPMeta2.SSOM.Standard", "Id": "SPMeta2.SSOM.Standard-v14", - "Version": "1.2.120-beta5", + "Version": "1.2.120", "Dependencies": [ { "Id": "SPMeta2.SSOM.Foundation-v14", - "Version": "1.2.120-beta5" + "Version": "1.2.120" }, { "Id": "SPMeta2.Core.Standard", - "Version": "1.2.120-beta5" + "Version": "1.2.120" } ], "LicenseUrl": "http://docs.subpointsolutions.com/spmeta2/license", @@ -653,11 +653,11 @@ { "CustomProjectFolder" : "SPMeta2/SPMeta2.CSOM", "Id": "SPMeta2.CSOM.Foundation-v16", - "Version": "1.2.120-beta5", + "Version": "1.2.120", "Dependencies": [ { "Id": "SPMeta2.Core", - "Version": "1.2.120-beta5" + "Version": "1.2.120" }, { "Id": "Microsoft.SharePointOnline.CSOM", @@ -694,15 +694,15 @@ { "CustomProjectFolder" : "SPMeta2/SPMeta2.CSOM.Standard", "Id": "SPMeta2.CSOM.Standard-v16", - "Version": "1.2.120-beta5", + "Version": "1.2.120", "Dependencies": [ { "Id": "SPMeta2.CSOM.Foundation-v16", - "Version": "1.2.120-beta5" + "Version": "1.2.120" }, { "Id": "SPMeta2.Core.Standard", - "Version": "1.2.120-beta5" + "Version": "1.2.120" }, { "Id": "Microsoft.SharePointOnline.CSOM", From 9a0d2cf452a8c200158321b2bd7ac64d579cc7c5 Mon Sep 17 00:00:00 2001 From: SubPointSupport Date: Thu, 13 Apr 2017 21:21:29 -0700 Subject: [PATCH 16/16] + SPMeta2 1.2.120, April 2017 + assembly version 1.2.17104.0417 --- SPMeta2/SPMeta2.CSOM.Standard/Properties/AssemblyInfo.cs | 2 +- SPMeta2/SPMeta2.CSOM/Properties/AssemblyInfo.cs | 2 +- SPMeta2/SPMeta2.Containers.CSOM/Properties/AssemblyInfo.cs | 2 +- SPMeta2/SPMeta2.Containers.O365/Properties/AssemblyInfo.cs | 2 +- SPMeta2/SPMeta2.Containers.SSOM/Properties/AssemblyInfo.cs | 2 +- SPMeta2/SPMeta2.Containers.Standard/Properties/AssemblyInfo.cs | 2 +- SPMeta2/SPMeta2.Containers/Properties/AssemblyInfo.cs | 2 +- SPMeta2/SPMeta2.Nintex.CSOM/Properties/AssemblyInfo.cs | 2 +- SPMeta2/SPMeta2.Nintex.SSOM/Properties/AssemblyInfo.cs | 2 +- SPMeta2/SPMeta2.Nintex/Properties/AssemblyInfo.cs | 2 +- SPMeta2/SPMeta2.O365/Properties/AssemblyInfo.cs | 2 +- .../SPMeta2.Regression.CSOM.Standard/Properties/AssemblyInfo.cs | 2 +- SPMeta2/SPMeta2.Regression.CSOM/Properties/AssemblyInfo.cs | 2 +- .../SPMeta2.Regression.Impl.Tests/Properties/AssemblyInfo.cs | 2 +- .../SPMeta2.Regression.SSOM.Standard/Properties/AssemblyInfo.cs | 2 +- SPMeta2/SPMeta2.Regression.SSOM/Properties/AssemblyInfo.cs | 2 +- SPMeta2/SPMeta2.Regression.Tests/Properties/AssemblyInfo.cs | 2 +- SPMeta2/SPMeta2.Regression/Properties/AssemblyInfo.cs | 2 +- SPMeta2/SPMeta2.SSOM.Standard/Properties/AssemblyInfo.cs | 2 +- SPMeta2/SPMeta2.SSOM/Properties/AssemblyInfo.cs | 2 +- SPMeta2/SPMeta2.Standard/Properties/AssemblyInfo.cs | 2 +- SPMeta2/SPMeta2/Properties/AssemblyInfo.cs | 2 +- 22 files changed, 22 insertions(+), 22 deletions(-) diff --git a/SPMeta2/SPMeta2.CSOM.Standard/Properties/AssemblyInfo.cs b/SPMeta2/SPMeta2.CSOM.Standard/Properties/AssemblyInfo.cs index d415ea936..49e68f197 100644 --- a/SPMeta2/SPMeta2.CSOM.Standard/Properties/AssemblyInfo.cs +++ b/SPMeta2/SPMeta2.CSOM.Standard/Properties/AssemblyInfo.cs @@ -32,4 +32,4 @@ // by using the '*' as shown below: // [assembly: AssemblyVersion("1.0.*")] [assembly: AssemblyVersion("1.0.0.0")] -[assembly: AssemblyFileVersion("1.2.17079.1227")] +[assembly: AssemblyFileVersion("1.2.17104.0417")] diff --git a/SPMeta2/SPMeta2.CSOM/Properties/AssemblyInfo.cs b/SPMeta2/SPMeta2.CSOM/Properties/AssemblyInfo.cs index 0555bbd09..46e9cd6f9 100644 --- a/SPMeta2/SPMeta2.CSOM/Properties/AssemblyInfo.cs +++ b/SPMeta2/SPMeta2.CSOM/Properties/AssemblyInfo.cs @@ -33,4 +33,4 @@ // by using the '*' as shown below: // [assembly: AssemblyVersion("1.0.*")] [assembly: AssemblyVersion("1.0.0.0")] -[assembly: AssemblyFileVersion("1.2.17079.1227")] +[assembly: AssemblyFileVersion("1.2.17104.0417")] diff --git a/SPMeta2/SPMeta2.Containers.CSOM/Properties/AssemblyInfo.cs b/SPMeta2/SPMeta2.Containers.CSOM/Properties/AssemblyInfo.cs index 36e1f3717..11f033529 100644 --- a/SPMeta2/SPMeta2.Containers.CSOM/Properties/AssemblyInfo.cs +++ b/SPMeta2/SPMeta2.Containers.CSOM/Properties/AssemblyInfo.cs @@ -33,4 +33,4 @@ // by using the '*' as shown below: // [assembly: AssemblyVersion("1.0.*")] [assembly: AssemblyVersion("1.0.0.0")] -[assembly: AssemblyFileVersion("1.2.17079.1227")] \ No newline at end of file +[assembly: AssemblyFileVersion("1.2.17104.0417")] \ No newline at end of file diff --git a/SPMeta2/SPMeta2.Containers.O365/Properties/AssemblyInfo.cs b/SPMeta2/SPMeta2.Containers.O365/Properties/AssemblyInfo.cs index d6078c9b0..231fa7c70 100644 --- a/SPMeta2/SPMeta2.Containers.O365/Properties/AssemblyInfo.cs +++ b/SPMeta2/SPMeta2.Containers.O365/Properties/AssemblyInfo.cs @@ -33,4 +33,4 @@ // by using the '*' as shown below: // [assembly: AssemblyVersion("1.0.*")] [assembly: AssemblyVersion("1.0.0.0")] -[assembly: AssemblyFileVersion("1.2.17079.1227")] +[assembly: AssemblyFileVersion("1.2.17104.0417")] diff --git a/SPMeta2/SPMeta2.Containers.SSOM/Properties/AssemblyInfo.cs b/SPMeta2/SPMeta2.Containers.SSOM/Properties/AssemblyInfo.cs index e77fe9e57..15deea26d 100644 --- a/SPMeta2/SPMeta2.Containers.SSOM/Properties/AssemblyInfo.cs +++ b/SPMeta2/SPMeta2.Containers.SSOM/Properties/AssemblyInfo.cs @@ -33,4 +33,4 @@ // by using the '*' as shown below: // [assembly: AssemblyVersion("1.0.*")] [assembly: AssemblyVersion("1.0.0.0")] -[assembly: AssemblyFileVersion("1.2.17079.1254")] +[assembly: AssemblyFileVersion("1.2.17104.0417")] diff --git a/SPMeta2/SPMeta2.Containers.Standard/Properties/AssemblyInfo.cs b/SPMeta2/SPMeta2.Containers.Standard/Properties/AssemblyInfo.cs index d37656b35..8c2a30d4f 100644 --- a/SPMeta2/SPMeta2.Containers.Standard/Properties/AssemblyInfo.cs +++ b/SPMeta2/SPMeta2.Containers.Standard/Properties/AssemblyInfo.cs @@ -33,4 +33,4 @@ // by using the '*' as shown below: // [assembly: AssemblyVersion("1.0.*")] [assembly: AssemblyVersion("1.0.0.0")] -[assembly: AssemblyFileVersion("1.2.17079.1227")] +[assembly: AssemblyFileVersion("1.2.17104.0417")] diff --git a/SPMeta2/SPMeta2.Containers/Properties/AssemblyInfo.cs b/SPMeta2/SPMeta2.Containers/Properties/AssemblyInfo.cs index 4d6b34d08..c21723570 100644 --- a/SPMeta2/SPMeta2.Containers/Properties/AssemblyInfo.cs +++ b/SPMeta2/SPMeta2.Containers/Properties/AssemblyInfo.cs @@ -33,4 +33,4 @@ // by using the '*' as shown below: // [assembly: AssemblyVersion("1.0.*")] [assembly: AssemblyVersion("1.0.0.0")] -[assembly: AssemblyFileVersion("1.2.17079.1227")] +[assembly: AssemblyFileVersion("1.2.17104.0417")] diff --git a/SPMeta2/SPMeta2.Nintex.CSOM/Properties/AssemblyInfo.cs b/SPMeta2/SPMeta2.Nintex.CSOM/Properties/AssemblyInfo.cs index 495e20ae1..66c39bb42 100644 --- a/SPMeta2/SPMeta2.Nintex.CSOM/Properties/AssemblyInfo.cs +++ b/SPMeta2/SPMeta2.Nintex.CSOM/Properties/AssemblyInfo.cs @@ -33,4 +33,4 @@ // by using the '*' as shown below: // [assembly: AssemblyVersion("1.0.*")] [assembly: AssemblyVersion("1.0.0.0")] -[assembly: AssemblyFileVersion("1.0.17079.1227")] +[assembly: AssemblyFileVersion("1.0.17104.0417")] diff --git a/SPMeta2/SPMeta2.Nintex.SSOM/Properties/AssemblyInfo.cs b/SPMeta2/SPMeta2.Nintex.SSOM/Properties/AssemblyInfo.cs index b87c409f7..1ca1da521 100644 --- a/SPMeta2/SPMeta2.Nintex.SSOM/Properties/AssemblyInfo.cs +++ b/SPMeta2/SPMeta2.Nintex.SSOM/Properties/AssemblyInfo.cs @@ -33,4 +33,4 @@ // by using the '*' as shown below: // [assembly: AssemblyVersion("1.0.*")] [assembly: AssemblyVersion("1.0.0.0")] -[assembly: AssemblyFileVersion("1.0.17079.1227")] +[assembly: AssemblyFileVersion("1.0.17104.0417")] diff --git a/SPMeta2/SPMeta2.Nintex/Properties/AssemblyInfo.cs b/SPMeta2/SPMeta2.Nintex/Properties/AssemblyInfo.cs index 983fb0fe4..f6ac5aa03 100644 --- a/SPMeta2/SPMeta2.Nintex/Properties/AssemblyInfo.cs +++ b/SPMeta2/SPMeta2.Nintex/Properties/AssemblyInfo.cs @@ -33,4 +33,4 @@ // by using the '*' as shown below: // [assembly: AssemblyVersion("1.0.*")] [assembly: AssemblyVersion("1.0.0.0")] -[assembly: AssemblyFileVersion("1.0.17079.1227")] +[assembly: AssemblyFileVersion("1.0.17104.0417")] diff --git a/SPMeta2/SPMeta2.O365/Properties/AssemblyInfo.cs b/SPMeta2/SPMeta2.O365/Properties/AssemblyInfo.cs index 48bb2f621..afd37ea9e 100644 --- a/SPMeta2/SPMeta2.O365/Properties/AssemblyInfo.cs +++ b/SPMeta2/SPMeta2.O365/Properties/AssemblyInfo.cs @@ -33,4 +33,4 @@ // by using the '*' as shown below: // [assembly: AssemblyVersion("1.0.*")] [assembly: AssemblyVersion("1.0.0.0")] -[assembly: AssemblyFileVersion("1.2.17079.1227")] +[assembly: AssemblyFileVersion("1.2.17104.0417")] diff --git a/SPMeta2/SPMeta2.Regression.CSOM.Standard/Properties/AssemblyInfo.cs b/SPMeta2/SPMeta2.Regression.CSOM.Standard/Properties/AssemblyInfo.cs index 44a71f312..bc7d8d532 100644 --- a/SPMeta2/SPMeta2.Regression.CSOM.Standard/Properties/AssemblyInfo.cs +++ b/SPMeta2/SPMeta2.Regression.CSOM.Standard/Properties/AssemblyInfo.cs @@ -33,4 +33,4 @@ // by using the '*' as shown below: // [assembly: AssemblyVersion("1.0.*")] [assembly: AssemblyVersion("1.0.0.0")] -[assembly: AssemblyFileVersion("1.2.17079.1227")] +[assembly: AssemblyFileVersion("1.2.17104.0417")] diff --git a/SPMeta2/SPMeta2.Regression.CSOM/Properties/AssemblyInfo.cs b/SPMeta2/SPMeta2.Regression.CSOM/Properties/AssemblyInfo.cs index 1db99efab..f8c7b3998 100644 --- a/SPMeta2/SPMeta2.Regression.CSOM/Properties/AssemblyInfo.cs +++ b/SPMeta2/SPMeta2.Regression.CSOM/Properties/AssemblyInfo.cs @@ -33,4 +33,4 @@ // by using the '*' as shown below: // [assembly: AssemblyVersion("1.0.*")] [assembly: AssemblyVersion("1.0.0.0")] -[assembly: AssemblyFileVersion("1.2.17079.1227")] +[assembly: AssemblyFileVersion("1.2.17104.0417")] diff --git a/SPMeta2/SPMeta2.Regression.Impl.Tests/Properties/AssemblyInfo.cs b/SPMeta2/SPMeta2.Regression.Impl.Tests/Properties/AssemblyInfo.cs index 146bd5ffb..fe8ed4165 100644 --- a/SPMeta2/SPMeta2.Regression.Impl.Tests/Properties/AssemblyInfo.cs +++ b/SPMeta2/SPMeta2.Regression.Impl.Tests/Properties/AssemblyInfo.cs @@ -33,4 +33,4 @@ // by using the '*' as shown below: // [assembly: AssemblyVersion("1.0.*")] [assembly: AssemblyVersion("1.0.0.0")] -[assembly: AssemblyFileVersion("1.2.17079.1246")] +[assembly: AssemblyFileVersion("1.2.17104.0417")] diff --git a/SPMeta2/SPMeta2.Regression.SSOM.Standard/Properties/AssemblyInfo.cs b/SPMeta2/SPMeta2.Regression.SSOM.Standard/Properties/AssemblyInfo.cs index ab4173853..143ef9adf 100644 --- a/SPMeta2/SPMeta2.Regression.SSOM.Standard/Properties/AssemblyInfo.cs +++ b/SPMeta2/SPMeta2.Regression.SSOM.Standard/Properties/AssemblyInfo.cs @@ -33,4 +33,4 @@ // by using the '*' as shown below: // [assembly: AssemblyVersion("1.0.*")] [assembly: AssemblyVersion("1.0.0.0")] -[assembly: AssemblyFileVersion("1.2.17079.1254")] +[assembly: AssemblyFileVersion("1.2.17104.0417")] diff --git a/SPMeta2/SPMeta2.Regression.SSOM/Properties/AssemblyInfo.cs b/SPMeta2/SPMeta2.Regression.SSOM/Properties/AssemblyInfo.cs index 853435573..c2c5a9ff4 100644 --- a/SPMeta2/SPMeta2.Regression.SSOM/Properties/AssemblyInfo.cs +++ b/SPMeta2/SPMeta2.Regression.SSOM/Properties/AssemblyInfo.cs @@ -33,4 +33,4 @@ // by using the '*' as shown below: // [assembly: AssemblyVersion("1.0.*")] [assembly: AssemblyVersion("1.0.0.0")] -[assembly: AssemblyFileVersion("1.2.17079.1254")] +[assembly: AssemblyFileVersion("1.2.17104.0417")] diff --git a/SPMeta2/SPMeta2.Regression.Tests/Properties/AssemblyInfo.cs b/SPMeta2/SPMeta2.Regression.Tests/Properties/AssemblyInfo.cs index a59cad00f..9b5cf2a5c 100644 --- a/SPMeta2/SPMeta2.Regression.Tests/Properties/AssemblyInfo.cs +++ b/SPMeta2/SPMeta2.Regression.Tests/Properties/AssemblyInfo.cs @@ -33,4 +33,4 @@ // by using the '*' as shown below: // [assembly: AssemblyVersion("1.0.*")] [assembly: AssemblyVersion("1.0.0.0")] -[assembly: AssemblyFileVersion("1.2.17079.1254")] +[assembly: AssemblyFileVersion("1.2.17104.0417")] diff --git a/SPMeta2/SPMeta2.Regression/Properties/AssemblyInfo.cs b/SPMeta2/SPMeta2.Regression/Properties/AssemblyInfo.cs index 6ab6dd9fd..91e1ca507 100644 --- a/SPMeta2/SPMeta2.Regression/Properties/AssemblyInfo.cs +++ b/SPMeta2/SPMeta2.Regression/Properties/AssemblyInfo.cs @@ -33,4 +33,4 @@ // by using the '*' as shown below: // [assembly: AssemblyVersion("1.0.*")] [assembly: AssemblyVersion("1.0.0.0")] -[assembly: AssemblyFileVersion("1.0.17079.1227")] +[assembly: AssemblyFileVersion("1.0.17104.0417")] diff --git a/SPMeta2/SPMeta2.SSOM.Standard/Properties/AssemblyInfo.cs b/SPMeta2/SPMeta2.SSOM.Standard/Properties/AssemblyInfo.cs index 4e3c96605..bf184884d 100644 --- a/SPMeta2/SPMeta2.SSOM.Standard/Properties/AssemblyInfo.cs +++ b/SPMeta2/SPMeta2.SSOM.Standard/Properties/AssemblyInfo.cs @@ -33,4 +33,4 @@ // by using the '*' as shown below: // [assembly: AssemblyVersion("1.0.*")] [assembly: AssemblyVersion("1.0.0.0")] -[assembly: AssemblyFileVersion("1.2.17079.1254")] +[assembly: AssemblyFileVersion("1.2.17104.0417")] diff --git a/SPMeta2/SPMeta2.SSOM/Properties/AssemblyInfo.cs b/SPMeta2/SPMeta2.SSOM/Properties/AssemblyInfo.cs index 54ab8e737..0d47e1bc1 100644 --- a/SPMeta2/SPMeta2.SSOM/Properties/AssemblyInfo.cs +++ b/SPMeta2/SPMeta2.SSOM/Properties/AssemblyInfo.cs @@ -33,4 +33,4 @@ // by using the '*' as shown below: // [assembly: AssemblyVersion("1.0.*")] [assembly: AssemblyVersion("1.0.0.0")] -[assembly: AssemblyFileVersion("1.2.17079.1254")] +[assembly: AssemblyFileVersion("1.2.17104.0417")] diff --git a/SPMeta2/SPMeta2.Standard/Properties/AssemblyInfo.cs b/SPMeta2/SPMeta2.Standard/Properties/AssemblyInfo.cs index 2a62bdd07..d8c8808a9 100644 --- a/SPMeta2/SPMeta2.Standard/Properties/AssemblyInfo.cs +++ b/SPMeta2/SPMeta2.Standard/Properties/AssemblyInfo.cs @@ -33,4 +33,4 @@ // by using the '*' as shown below: // [assembly: AssemblyVersion("1.0.*")] [assembly: AssemblyVersion("1.0.0.0")] -[assembly: AssemblyFileVersion("1.2.17079.1227")] +[assembly: AssemblyFileVersion("1.2.17104.0417")] diff --git a/SPMeta2/SPMeta2/Properties/AssemblyInfo.cs b/SPMeta2/SPMeta2/Properties/AssemblyInfo.cs index 904477cce..2e0b5dbfd 100644 --- a/SPMeta2/SPMeta2/Properties/AssemblyInfo.cs +++ b/SPMeta2/SPMeta2/Properties/AssemblyInfo.cs @@ -32,4 +32,4 @@ // by using the '*' as shown below: // [assembly: AssemblyVersion("1.0.*")] [assembly: AssemblyVersion("1.0.0.0")] -[assembly: AssemblyFileVersion("1.2.17079.1227")] +[assembly: AssemblyFileVersion("1.2.17104.0417")]